Search code examples
swiftobjective-cusbnfc

Sending commands to ACR122U with Swift or Objective-C


I’m in the process of writing a macOS application that will provide features to read and write data to nfc tags using the ACR122u usb reader. I’m having a difficult time finding examples of how to send commands to the device in this environment. I came across this question but can’t seem to adapt it to Swift or Objective C. Any help would be greatly appreciated.

Here's what I have so far but I can't seem to wrap my head around how to send an array of bytes.

func _getSerialNumber(device: USBDevice) throws -> String {
    
    // get device interface from our pointer
    guard let deviceInterface = device.deviceInterfacePtrPtr?.pointee?.pointee else {
        throw NSError(domain: domain, code: 404, userInfo: [NSLocalizedDescriptionKey: "device not found"])
    }
    
    // create usb device request
    let length: Int = 5
    var requestPtr: [UInt8] = [UInt8](repeating: 0, count: Int(length))
    let type = USBmakebmRequestType(direction: kUSBIn, type: kUSBStandard, recipient: kUSBDevice)
    var request = IOUSBDevRequest(bmRequestType: type,
                                      bRequest: UInt8(kUSBRqGetDescriptor),
                                      wValue: 0,
                                      wIndex: 0,
                                      wLength: UInt16(length),
                                      pData: &requestPtr,
                                      wLenDone: 255)
    
    let kr: Int32 = deviceInterface.DeviceRequest(device.deviceInterfacePtrPtr, &request)
    if kr == -536870163 {
        throw NSError(domain: domain, code: Int(kr), userInfo: [NSLocalizedDescriptionKey: "unable to send request"])
    }
    if kr != kIOReturnSuccess {
        throw NSError(domain: domain, code: Int(kr), userInfo: [NSLocalizedDescriptionKey: "unknown error occurred"])
    }
    
    guard let string = String(bytes: requestPtr, encoding: .utf8) else {
        throw NSError(domain: domain, code: 500, userInfo: [NSLocalizedDescriptionKey: "unable to decode device response"])
    }
    return string
}

Solution

  • It turns out that using CryptoTokenKit was a better fit than what I had previously found. You init the reader as a TKSmartCardSlot and the card as a TKSmartCard. You then transmit the byte array to the TKSmartCard through the transmit function. Please send a dm if anyone needs additional information about this workflow.

    https://developer.apple.com/documentation/cryptotokenkit/tksmartcardslot