scarer
scarer

Reputation: 101

Get serial number from usb device in xcode at application level

I am just starting out at hardware programming and have been trying to get the serial number from a USB device. I am implementing everything at the application level rather than the kernel level.

I have a dictionary already that matches to the usb device so I know I have the correct device. What I am not sure about is the data that I'm getting back and how to interpret it and whether or not I'm going about this correctly.

So here's some code I have that I've been trying to work with to get the serial number from the device.

IOReturn retSerialIndex;
UInt8 snsi;
retSerialIndex = (*usbDevice)->USBGetSerialNumberStringIndex(usbDevice, &snsi);
if (retSerialIndex != kIOReturnSuccess)
{
    printf("Could not get serial number string index (error: %x)\n", retSerialIndex);
}
printf("Serial string index is %x\n", retSerialIndex);
IOReturn retSerial;
IOUSBConfigurationDescriptorPtr *desc;
if (retSerialIndex)
{
    retSerial = (*usbDevice)->GetConfigurationDescriptorPtr(usbDevice,
                                                            retSerialIndex,
                                                            desc);
    if (retSerial != kIOReturnSuccess)
    {
        printf("Could not get serial number using string index (error: %x)\n", retSerial);
    }
}
printf("Serial number is %x\n", retSerial);
char serialString;
serialString = getUSBStringDescriptor(usbDevice, retSerial);
printf("Serial string is %c\n", serialString);

And here is my getUSBStringDescriptor implementation:

char MyClass::getUSBStringDescriptor( IOUSBDeviceInterface300** usbDevice, int idx )
{
   assert( usbDevice );
   UInt32 buffer[32];
   IOUSBDevRequest request;
   request.bmRequestType = USBmakebmRequestType(
                                             kUSBIn,
                                             kUSBStandard,
                                             kUSBDevice );
   request.bRequest = kUSBRqGetDescriptor;
   request.wValue = (3 << 8) | idx;
   request.wIndex = 0x0904; // english
   request.wLength = sizeof( buffer );
   request.pData = buffer;
   kern_return_t err = (*usbDevice)->DeviceRequest( usbDevice, &request );
   if ( err != 0 )
   {
       // the request failed.
       return NULL;
   }
   static char charstring[33];
   int count = ( request.wLenDone - 1 ) / 2;
   int i;
   for ( i = 0; i < count; i++ )
        charstring[i] = buffer[i+1];
    charstring[i] = '\0';
    return charstring[33 - 1];
}

Any help would be greatly appreciated. Thanks!

Upvotes: 2

Views: 1266

Answers (1)

scarer
scarer

Reputation: 101

So I figured it out. I was getting the wrong information at the wrong places and not paying enough attention to where the values were being stored. Here is the amended code that returns the serial number for the selected device.

//My call to get serial number
NSString * serialString;
serialString = getUSBStringDescriptor(usbDevice);
printf("Serial string is %s\n", [serialString UTF8String]);

//My function that gets the serial number for me
NSString * MyUSBClass::getUSBStringDescriptor( IOUSBDeviceInterface300** usbDevice)
{
    UInt8 snsi;
    UInt8 buffer[256];
    IOUSBDevRequest request;
    IOReturn err;
    err = (*usbDevice)->USBGetSerialNumberStringIndex(usbDevice, &snsi);
    if (err != kIOReturnSuccess)
    {
        printf("Could not get serial number string index (error: %x)\n", err);
        return 0;
    }
    request.bmRequestType = USBmakebmRequestType(
                                             kUSBIn,
                                             kUSBStandard,
                                             kUSBDevice );
    request.bRequest = kUSBRqGetDescriptor;
    request.wValue = (kUSBStringDesc << 8) | snsi;
    request.wIndex = 0x409; // english
    request.wLength = sizeof( buffer );
    request.pData = &buffer[0];
    bzero(&buffer[0], sizeof(buffer));
    err = (*usbDevice)->DeviceRequest( usbDevice, &request );
    if ( err != kIOReturnSuccess )
    {
        printf("Could not get serial number string using index\n");
        // the request failed.
        return 0;
    }
    int strLength;
    CFStringRef serialNumberString;
    strLength = buffer[0] -2;
    serialNumberString = CFStringCreateWithBytes(kCFAllocatorDefault, &buffer[2], strLength, kCFStringEncodingUTF16LE, FALSE);
    CFShow(serialNumberString);
    NSString *stringBuffer = (__bridge NSString *)serialNumberString;
    return stringBuffer;
}

I hope this saves someone lots of time! I wish I had this answer when I started trying to figure this out.

Upvotes: 5

Related Questions