| 262 | } |
| 263 | |
| 264 | void fxRegisterSerial(void *refcon, io_iterator_t iterator) |
| 265 | { |
| 266 | txSerialTool self = refcon; |
| 267 | io_service_t usbDevice; |
| 268 | while ((usbDevice = IOIteratorNext(iterator))) { |
| 269 | CFTypeRef typeRef, vendorRef, productRef; |
| 270 | int vendorID = 0, productID = 0; |
| 271 | int match = 0; |
| 272 | |
| 273 | vendorRef = IORegistryEntrySearchCFProperty(usbDevice, kIOServicePlane, CFSTR("idVendor"), |
| 274 | kCFAllocatorDefault, kIORegistryIterateRecursively | kIORegistryIterateParents); |
| 275 | if (vendorRef) |
| 276 | CFNumberGetValue(vendorRef , kCFNumberIntType, &vendorID); |
| 277 | |
| 278 | productRef = IORegistryEntrySearchCFProperty(usbDevice, kIOServicePlane, CFSTR("idProduct"), |
| 279 | kCFAllocatorDefault, kIORegistryIterateRecursively | kIORegistryIterateParents); |
| 280 | if (productRef) |
| 281 | CFNumberGetValue(productRef , kCFNumberIntType, &productID); |
| 282 | |
| 283 | //fprintf(stderr, "checking productID %04x:%04x\n", vendorID, productID); |
| 284 | match = (!self->productID || (productID == self->productID)) && |
| 285 | (!self->vendorID || (vendorID == self->vendorID)); |
| 286 | |
| 287 | if ((typeRef = IORegistryEntryCreateCFProperty(usbDevice, CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0))) { |
| 288 | CFIndex length = CFStringGetLength(typeRef); |
| 289 | CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8); |
| 290 | txSerialDescription description = malloc(sizeof(txSerialDescriptionRecord) + maxSize); |
| 291 | if (description) { |
| 292 | description->tool = self; |
| 293 | CFStringGetCString(typeRef, &description->path[0], maxSize + 1, kCFStringEncodingUTF8); |
| 294 | if (!strcmp(self->path, "") && match) { |
| 295 | self->path = malloc(strlen(description->path) + 1); |
| 296 | strcpy(self->path, description->path); |
| 297 | |
| 298 | if (self->showPath) { |
| 299 | printf("%s\n", description->path); |
| 300 | exit(0); |
| 301 | } |
| 302 | else { |
| 303 | // fprintf(stderr, "product/vendor match: %s\n", description->path); |
| 304 | fxOpenSerial(self); |
| 305 | } |
| 306 | } |
| 307 | else |
| 308 | if (!strcmp(self->path, description->path) |
| 309 | && IOServiceAddInterestNotification(self->notificationPort, usbDevice, kIOGeneralInterest, fxUnregisterSerial, description, &description->notification) == KERN_SUCCESS) { |
| 310 | fxOpenSerial(self); |
| 311 | } |
| 312 | else |
| 313 | free(description); |
| 314 | } |
| 315 | } |
| 316 | |
| 317 | IOObjectRelease(usbDevice); |
| 318 | } |
| 319 | } |
| 320 | |
| 321 | void fxRestartSerial(txSerialTool self) |