Home > front end >  how to setup IOServiceAddMatching for different product identifications
how to setup IOServiceAddMatching for different product identifications

Time:02-04

need to use IOServiceAddMatchingNotification routine for supporing multiple product identifications. To show the concept, I got part of this code from a site and revised it.Kept it short.

// Set up matching dictionary.  
NSMutableDictionary* matchingDictionary;

for (int n = 0; n < numberOfDevices; n  )
{
matchingDictionary = (NSMutableDictionary*)IOServiceMatching(kIOUSBDeviceClassName);  

[matchingDictionary setObject:[NSNumber numberWithLong:myVid[n]] forKey:[NSString stringWithUTF8String:kUSBVendorID]];  
[matchingDictionary setObject:[NSNumber numberWithLong:myPid[n]] forKey:[NSString stringWithUTF8String:kUSBProductID]];  

// Set up a notification callback for device addition on first match.  
IOServiceAddMatchingNotification(g_notificationPort, kIOFirstMatchNotification, (CFMutableDictionaryRef)matchingDictionary, deviceAddedCallback, (void*)self, &g_iteratorAdded);  
}

I am not sure if it really is correct?. I did not see complains from the xcode and it works.

CodePudding user response:

This requires a nuanced answer - there are three things to note here:

  1. In principle, yes, you need to create distinct matching notifications for each independent match dictionary.
  2. However, it looks like you're expecting only one io_iterator_t to be created and updated with each matching dictionary, as you only have a single variable to store it, g_iteratorAdded. This is not the case. The code shown suffers from a resource leak. Each successful call to IOServiceAddMatchingNotification will create a new iterator, so you will need to retain all of them in an array or so. And then, when you no longer need the notifications (at the latest, when self is dealloc'd, or you'll get callbacks on a freed object!), you need to release all of the iterators.
  3. For matching multiple different USB product IDs but identical vendor IDs, you actually don't need to create multiple match dictionaries and notifications. Instead of kUSBProductID with a single NSNumber/CFNumber, provide a kUSBProductIdsArrayName (aka kUSBHostMatchingPropertyProductIDArray) and specify an array of numbers. (NSArray/CFArray containing a NSNumber/CFNumber for every product ID.)
    Alternatively, if your product IDs match some hex pattern, you can also use kUSBProductIDMask in conjunction with kUSBProductID: in this case, candidate devices' product IDs will be bitwise masked (&) with the number provided for kUSBProductIDMask before comparing to the kUSBProductID.
    If you need to match multiple vendor IDs, you will still need to create a matching notification for each vendor ID, and provide the list of product IDs in the kUSBProductIdsArrayName value for each.

Update: Sample code for array PID match dictionaries

Some rough untested code for dealing with kUSBProductIdsArrayName, assuming your VIDs/PIDs are laid out like this:

static const uint16_t myVid[] = { 0x1234, 0x5555 };
static const size_t numberOfVids = sizeof(myVid) / sizeof(myVid[0]);
static const uint16_t myPid[] = {
   // for VID 0x1234
   0x1, 0x2, 0x3, 0x1001, 0x1002,
   // for VID 0x555
   0x100, 0x101,
};
static const unsigned pidsForVid[] = { 5, 2 };

Setting up the matching dictionaries would then look something like this:

unsigned next_pid_index = 0;
for (int n = 0; n < numberOfVids; n  )
{
  NSMutableDictionary* matchingDictionary =
    (__bridge_transfer NSMutableDictionary*)IOServiceMatching(kIOUSBDeviceClassName);  

  [matchingDictionary setObject:@(myVid[n]) forKey:@kUSBVendorID];  
  NSMutableArray* pid_array = [NSMutableArray arrayWithCapacity:pidsForVid[n]];
  for (unsigned i = 0; i < pidsForVid[n];   i)
  {
    [pid_array addObject:@(myPid[next_pid_index])];
      next_pid_index;
  }
  [matchingDictionary setObject:pid_array forKey:@kUSBProductIdsArrayName];  

  // Set up a notification callback for device addition on first match.  
  IOReturn result = IOServiceAddMatchingNotification(
    g_notificationPort,
    kIOFirstMatchNotification,
    (__bridge_retained CFMutableDictionaryRef)matchingDictionary,
    deviceAddedCallback,
    (__bridge void*)self,
    &g_iteratorAdded[n]);  
  assert(result == kIOReturnSuccess);
}
  • Related