def find_usb_devices(device_key, vendor_id_key, product_id_key, device_class): ''' query the host computer for all available USB devices and returns a list of any found ''' devices = [] matchDictionary = IOServiceMatching(device_key) objectIterator = io_iterator_t() result = IOServiceGetMatchingServices( kIOMasterPortDefault, matchDictionary, byref(objectIterator)) if result != kIOReturnSuccess or not objectIterator: raise RuntimeError("Can't obtain an IO iterator") try: while True: device = IOIteratorNext(objectIterator) if not device: break dev = device_class(device, 0, 0) properties = CFMutableDictionaryRef() result = IORegistryEntryCreateCFProperties( device, byref(properties), kCFAllocatorDefault, kNilOptions) if result == KERN_SUCCESS and properties: vendor, product = 0, 0 vendorRef = CFDictionaryGetValue(properties, CFSTR(vendor_id_key)) productRef = CFDictionaryGetValue(properties, CFSTR(product_id_key)) if vendorRef: vendor = c_int() CFNumberGetValue( parse('CFNumberRef').cast(vendorRef), kCFNumberIntType, byref(vendor)) CFRelease(vendorRef) vendor = vendor.value if productRef: product = c_int() CFNumberGetValue( parse('CFNumberRef').cast(productRef), kCFNumberIntType, byref(product)) CFRelease(productRef) product = product.value dev.vendor = vendor dev.product = product logging.info( "find_usb_devices: found device vendor=0x%04x product=0x%04x", dev.vendor, dev.product) devices.append(dev) finally: IOObjectRelease(objectIterator) return devices
class IOUSBFindInterfaceRequest(Structure): _fields_ = [ parse('UInt16 bInterfaceClass').cstruct, parse('UInt16 bInterfaceSubClass').cstruct, parse('UInt16 bInterfaceProtocol').cstruct, parse('UInt16 bAlternateSetting').cstruct, ]
def find_usb_devices(device_key,vendor_id_key,product_id_key,device_class): ''' query the host computer for all available USB devices and returns a list of any found ''' devices=[] matchDictionary = IOServiceMatching(device_key); objectIterator=io_iterator_t() result=IOServiceGetMatchingServices(kIOMasterPortDefault,matchDictionary,byref(objectIterator)) if result != kIOReturnSuccess or not objectIterator: raise RuntimeError("Can't obtain an IO iterator") try: while True: device = IOIteratorNext(objectIterator) if not device: break dev=device_class(device,0,0) properties=CFMutableDictionaryRef() result = IORegistryEntryCreateCFProperties(device,byref(properties),kCFAllocatorDefault,kNilOptions) if result == KERN_SUCCESS and properties: vendor,product=0,0 vendorRef = CFDictionaryGetValue(properties, CFSTR(vendor_id_key)); productRef = CFDictionaryGetValue(properties, CFSTR(product_id_key)); if vendorRef: vendor=c_int() CFNumberGetValue(parse('CFNumberRef').cast(vendorRef),kCFNumberIntType,byref(vendor)) CFRelease(vendorRef) vendor=vendor.value if productRef: product=c_int() CFNumberGetValue(parse('CFNumberRef').cast(productRef),kCFNumberIntType,byref(product)) CFRelease(productRef) product=product.value dev.vendor=vendor dev.product=product logging.info("find_usb_devices: found device vendor=0x%04x product=0x%04x",dev.vendor,dev.product) devices.append(dev) finally: IOObjectRelease(objectIterator) return devices
class IOUSBDevRequestTO(Structure): _fields_ = [ parse('UInt8 bmRequestType').cstruct, parse('UInt8 bRequest').cstruct, parse('UInt16 wValue').cstruct, parse('UInt16 wIndex').cstruct, parse('UInt16 wLength').cstruct, parse('void *pData').cstruct, parse('UInt32 wLenDone').cstruct, parse('UInt32 noDataTimeout').cstruct, parse('UInt32 completionTimeout').cstruct, ]
def open(self): ''' open the HID device - must be called prior to registering callbacks or setting reports ''' if not self.is_open(): logging.info("opening hid device") # plugInInterface initialised to NULL plugInInterface = COMObjectRef( POINTER(POINTER(IOCFPlugInInterfaceStruct))()) score = SInt32() IOCreatePlugInInterfaceForService(self._hidDevice, kIOHIDDeviceUserClientTypeID, kIOCFPlugInInterfaceID, byref(plugInInterface.ref), byref(score)) # query to get the HID interface hidInterface = POINTER(POINTER(IOHIDDeviceInterface122))() plugInInterface.QueryInterface( CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), parse('LPVOID*').cast(byref(hidInterface))) self._hidInterface = COMObjectRef(hidInterface) # open the HID device self._hidInterface.open(0) else: loggging.info("device already open")
def _open_interface(self, interface): plugInInterface = COMObjectRef( POINTER(POINTER(IOCFPlugInInterfaceStruct))()) score = SInt32() err = IOCreatePlugInInterfaceForService( interface, kIOUSBInterfaceUserClientTypeID, kIOCFPlugInInterfaceID, byref(plugInInterface.ref), byref(score)) devInterface = POINTER(POINTER(IOUSBInterfaceInterface182))() err = plugInInterface.QueryInterface( CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), parse('LPVOID*').cast(byref(devInterface))) if err: raise RuntimeError( "Failed to QueryInterface for USB Interface Interface") self._devInterface = COMObjectRef(devInterface) err = self._devInterface.USBInterfaceOpen() if err: raise RuntimeError("Error opening USB interface") numPipes = UInt8() err = self._devInterface.GetNumEndpoints(byref(numPipes)) if err: raise RuntimeError("Error calling GetNumEndpoints")
def _open_interface(self, interface): plugInInterface = COMObjectRef(POINTER(POINTER(IOCFPlugInInterfaceStruct))()) score = SInt32() err = IOCreatePlugInInterfaceForService( interface, kIOUSBInterfaceUserClientTypeID, kIOCFPlugInInterfaceID, byref(plugInInterface.ref), byref(score) ) devInterface = POINTER(POINTER(IOUSBInterfaceInterface182))() err = plugInInterface.QueryInterface( CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), parse("LPVOID*").cast(byref(devInterface)) ) if err: raise RuntimeError("Failed to QueryInterface for USB Interface Interface") self._devInterface = COMObjectRef(devInterface) err = self._devInterface.USBInterfaceOpen() if err: raise RuntimeError("Error opening USB interface") numPipes = UInt8() err = self._devInterface.GetNumEndpoints(byref(numPipes)) if err: raise RuntimeError("Error calling GetNumEndpoints")
class IOUSBConfigurationDescriptor(Structure): _fields_ = [ parse('UInt8 bLength').cstruct, parse('UInt8 bDescriptorType').cstruct, parse('UInt16 wTotalLength').cstruct, parse('UInt8 bNumInterfaces').cstruct, parse('UInt8 bConfigurationValue').cstruct, parse('UInt8 iConfiguration').cstruct, parse('UInt8 bmAttributes').cstruct, parse('UInt8 MaxPower').cstruct, ]
class IOHIDEventStruct(Structure): _fields_ = [ parse('IOHIDElementType type').cstruct, parse('IOHIDElementCookie elementCookie').cstruct, parse('SInt32 value').cstruct, parse('AbsoluteTime timestamp').cstruct, parse('UInt32 longValueSize').cstruct, parse('void * longValue').cstruct, ]
class IOUSBIsocFrame(Structure): _fields_ = [ parse('IOReturn frStatus').cstruct, parse('UInt16 frReqCount').cstruct, parse('UInt16 frActCount').cstruct, ]
def open(self): logging.info("opening hid device via usb") # plugInInterface initialised to NULL plugInInterface = COMObjectRef( POINTER(POINTER(IOCFPlugInInterfaceStruct))()) score = SInt32() err = IOCreatePlugInInterfaceForService(self._usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, byref(plugInInterface.ref), byref(score)) # query to get the USB interface usbDevInterface = POINTER(POINTER(IOUSBDeviceInterface))() err = plugInInterface.QueryInterface( CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), parse('LPVOID*').cast(byref(usbDevInterface))) if err: raise RuntimeError( "Failed to QueryInterface for USB Device Interface") usbDevInterface = COMObjectRef(usbDevInterface) # open USB device err = usbDevInterface.USBDeviceOpen() if err: if err == kIOReturnExclusiveAccess: raise RuntimeError("Device already open") raise RuntimeError("Could not open device") numConf = UInt8() err = usbDevInterface.GetNumberOfConfigurations(byref(numConf)) if err: raise RuntimeError("Error calling GetNumberOfConfigurations") logging.info("Found %d Interface(s)" % numConf.value) configDesc = IOUSBConfigurationDescriptorPtr() # get first (and only) config err = usbDevInterface.GetConfigurationDescriptorPtr( 0, byref(configDesc)) if err: raise RuntimeError("Error calling GetConfigurationDescriptorPtr") err = usbDevInterface.SetConfiguration( configDesc.contents.bConfigurationValue) if err: raise RuntimeError("Error calling SetConfiguration") interfaceRequest = IOUSBFindInterfaceRequest() interfaceRequest.bInterfaceClass = kIOUSBFindInterfaceDontCare interfaceRequest.bInterfaceSubClass = kIOUSBFindInterfaceDontCare interfaceRequest.bInterfaceProtocol = kIOUSBFindInterfaceDontCare interfaceRequest.bAlternateSetting = kIOUSBFindInterfaceDontCare interfaceIterator = io_iterator_t() err = usbDevInterface.CreateInterfaceIterator(byref(interfaceRequest), byref(interfaceIterator)) if err: raise RuntimeError("Error calling CreateInterfaceIterator") err = usbDevInterface.USBDeviceClose() if err: raise RuntimeError("Error calling USBDeviceClose") while True: interface = IOIteratorNext(interfaceIterator) if not interface: break self._open_interface(interface) IOObjectRelease(interfaceIterator)
class IOUSBInterfaceInterface182(Structure): _fields_ = IUNKNOWN_C_GUTS + \ [ parse('IOReturn (*CreateInterfaceAsyncEventSource)(void *self, CFRunLoopSourceRef *source)').cstruct, parse('CFRunLoopSourceRef (*GetInterfaceAsyncEventSource)(void *self)').cstruct, parse('IOReturn (*CreateInterfaceAsyncPort)(void *self, mach_port_t *port)').cstruct, parse('mach_port_t (*GetInterfaceAsyncPort)(void *self)').cstruct, parse('IOReturn (*USBInterfaceOpen)(void *self)').cstruct, parse('IOReturn (*USBInterfaceClose)(void *self)').cstruct, parse('IOReturn (*GetInterfaceClass)(void *self, UInt8 *intfClass)').cstruct, parse('IOReturn (*GetInterfaceSubClass)(void *self, UInt8 *intfSubClass)').cstruct, parse('IOReturn (*GetInterfaceProtocol)(void *self, UInt8 *intfProtocol)').cstruct, parse('IOReturn (*GetDeviceVendor)(void *self, UInt16 *devVendor)').cstruct, parse('IOReturn (*GetDeviceProduct)(void *self, UInt16 *devProduct)').cstruct, parse('IOReturn (*GetDeviceReleaseNumber)(void *self, UInt16 *devRelNum)').cstruct, parse('IOReturn (*GetConfigurationValue)(void *self, UInt8 *configVal)').cstruct, parse('IOReturn (*GetInterfaceNumber)(void *self, UInt8 *intfNumber)').cstruct, parse('IOReturn (*GetAlternateSetting)(void *self, UInt8 *intfAltSetting)').cstruct, parse('IOReturn (*GetNumEndpoints)(void *self, UInt8 *intfNumEndpoints)').cstruct, parse('IOReturn (*GetLocationID)(void *self, UInt32 *locationID)').cstruct, parse('IOReturn (*GetDevice)(void *self, io_service_t *device)').cstruct, parse('IOReturn (*SetAlternateInterface)(void *self, UInt8 alternateSetting)').cstruct, parse('IOReturn (*GetBusFrameNumber)(void *self, UInt64 *frame, AbsoluteTime *atTime)').cstruct, parse('IOReturn (*ControlRequest)(void *self, UInt8 pipeRef, IOUSBDevRequest *req)').cstruct, parse('IOReturn (*ControlRequestAsync)(void *self, UInt8 pipeRef, IOUSBDevRequest *req, IOAsyncCallback1 callback, void *refCon)').cstruct, parse('IOReturn (*GetPipeProperties)(void *self, UInt8 pipeRef, UInt8 *direction, UInt8 *number, UInt8 *transferType, UInt16 *maxPacketSize, UInt8 *interval)').cstruct, parse('IOReturn (*GetPipeStatus)(void *self, UInt8 pipeRef)').cstruct, parse('IOReturn (*AbortPipe)(void *self, UInt8 pipeRef)').cstruct, parse('IOReturn (*ResetPipe)(void *self, UInt8 pipeRef)').cstruct, parse('IOReturn (*ClearPipeStall)(void *self, UInt8 pipeRef)').cstruct, parse('IOReturn (*ReadPipe)(void *self, UInt8 pipeRef, void *buf, UInt32 *size)').cstruct, parse('IOReturn (*WritePipe)(void *self, UInt8 pipeRef, void *buf, UInt32 size)').cstruct, parse('IOReturn (*ReadPipeAsync)(void *self, UInt8 pipeRef, void *buf, UInt32 size, IOAsyncCallback1 callback, void *refcon)').cstruct, parse('IOReturn (*WritePipeAsync)(void *self, UInt8 pipeRef, void *buf, UInt32 size, IOAsyncCallback1 callback, void *refcon)').cstruct, parse('IOReturn (*ReadIsochPipeAsync)(void *self, UInt8 pipeRef, void *buf, UInt64 frameStart, UInt32 numFrames, IOUSBIsocFrame *frameList,' 'IOAsyncCallback1 callback, void *refcon)').cstruct, parse('IOReturn (*WriteIsochPipeAsync)(void *self, UInt8 pipeRef, void *buf, UInt64 frameStart, UInt32 numFrames, IOUSBIsocFrame *frameList,' 'IOAsyncCallback1 callback, void *refcon)').cstruct, parse('IOReturn (*ControlRequestTO)(void *self, UInt8 pipeRef, IOUSBDevRequestTO *req)').cstruct, parse('IOReturn (*ControlRequestAsyncTO)(void *self, UInt8 pipeRef, IOUSBDevRequestTO *req, IOAsyncCallback1 callback, void *refCon)').cstruct, parse('IOReturn (*ReadPipeTO)(void *self, UInt8 pipeRef, void *buf, UInt32 *size, UInt32 noDataTimeout, UInt32 completionTimeout)').cstruct, parse('IOReturn (*WritePipeTO)(void *self, UInt8 pipeRef, void *buf, UInt32 size, UInt32 noDataTimeout, UInt32 completionTimeout)').cstruct, parse('IOReturn (*ReadPipeAsyncTO)(void *self, UInt8 pipeRef, void *buf, UInt32 size, UInt32 noDataTimeout, UInt32 completionTimeout, IOAsyncCallback1 callback, void *refcon)').cstruct, parse('IOReturn (*WritePipeAsyncTO)(void *self, UInt8 pipeRef, void *buf, UInt32 size, UInt32 noDataTimeout, UInt32 completionTimeout, IOAsyncCallback1 callback, void *refcon)').cstruct, parse('IOReturn (*USBInterfaceGetStringIndex)(void *self, UInt8 *si)').cstruct, ]
class IOUSBDeviceInterface(Structure): _fields_= IUNKNOWN_C_GUTS + \ [ parse('IOReturn (*CreateDeviceAsyncEventSource)(void *self, CFRunLoopSourceRef *source)').cstruct, parse('CFRunLoopSourceRef (*GetDeviceAsyncEventSource)(void *self)').cstruct, parse('IOReturn (*CreateDeviceAsyncPort)(void *self, mach_port_t *port)').cstruct, parse('mach_port_t (*GetDeviceAsyncPort)(void *self)').cstruct, parse('IOReturn (*USBDeviceOpen)(void *self)').cstruct, parse('IOReturn (*USBDeviceClose)(void *self)').cstruct, parse('IOReturn (*GetDeviceClass)(void *self, UInt8 *devClass)').cstruct, parse('IOReturn (*GetDeviceSubClass)(void *self, UInt8 *devSubClass)').cstruct, parse('IOReturn (*GetDeviceProtocol)(void *self, UInt8 *devProtocol)').cstruct, parse('IOReturn (*GetDeviceVendor)(void *self, UInt16 *devVendor)').cstruct, parse('IOReturn (*GetDeviceProduct)(void *self, UInt16 *devProduct)').cstruct, parse('IOReturn (*GetDeviceReleaseNumber)(void *self, UInt16 *devRelNum)').cstruct, parse('IOReturn (*GetDeviceAddress)(void *self, USBDeviceAddress *addr)').cstruct, parse('IOReturn (*GetDeviceBusPowerAvailable)(void *self, UInt32 *powerAvailable)').cstruct, parse('IOReturn (*GetDeviceSpeed)(void *self, UInt8 *devSpeed)').cstruct, parse('IOReturn (*GetNumberOfConfigurations)(void *self, UInt8 *numConfig)').cstruct, parse('IOReturn (*GetLocationID)(void *self, UInt32 *locationID)').cstruct, parse('IOReturn (*GetConfigurationDescriptorPtr)(void *self, UInt8 configIndex, IOUSBConfigurationDescriptorPtr *desc)').cstruct, parse('IOReturn (*GetConfiguration)(void *self, UInt8 *configNum)').cstruct, parse('IOReturn (*SetConfiguration)(void *self, UInt8 configNum)').cstruct, parse('IOReturn (*GetBusFrameNumber)(void *self, UInt64 *frame, AbsoluteTime *atTime)').cstruct, parse('IOReturn (*ResetDevice)(void *self)').cstruct, parse('IOReturn (*DeviceRequest)(void *self, IOUSBDevRequest *req)').cstruct, parse('IOReturn (*DeviceRequestAsync)(void *self, IOUSBDevRequest *req, IOAsyncCallback1 callback, void *refCon)').cstruct, parse('IOReturn (*CreateInterfaceIterator)(void *self, IOUSBFindInterfaceRequest *req, io_iterator_t *iter)').cstruct, ]
define('CFUUIDBytes', CFUUIDBytes) REFIID = define('REFIID', 'CFUUIDBytes') IOHIDElementCookie = define('IOHIDElementCookie', 'void*') IOHIDElementType = define('IOHIDElementType', c_int) # enum IOHIDQueueInterface = define('IOHIDQueueInterface', 'void*') IOHIDOutputTransactionInterface = define('IOHIDOutputTransactionInterface', 'void*') IOHIDReportType = define('IOHIDReportType', c_int) # enum HRESULT = define('HRESULT', 'SInt32') IOHIDCallbackFunction = parse( 'void (*IOHIDCallbackFunction)(void *target, IOReturn result, void *refcon, void *sender)' ).ctype define('IOHIDCallbackFunction', IOHIDCallbackFunction) IOHIDElementCallbackFunction = parse( 'void (*IOHIDElementCallbackFunction)(void *target, IOReturn result, void *refcon, void *sender, IOHIDElementCookie elementCookie)' ).ctype define('IOHIDElementCallbackFunction', IOHIDElementCallbackFunction) IOHIDReportCallbackFunction = parse( 'void ( *IOHIDReportCallbackFunction) ( void *target, IOReturn result, void *refcon, void *sender, uint32_t bufferSize)' ).ctype define('IOHIDReportCallbackFunction', IOHIDReportCallbackFunction) class IOHIDEventStruct(Structure):
class IOUSBDevRequest(Structure): _fields_ = [ parse('UInt8 bmRequestType').cstruct, parse('UInt8 bRequest').cstruct, parse('UInt16 wValue').cstruct, parse('UInt16 wIndex').cstruct, parse('UInt16 wLength').cstruct, parse('void *pData').cstruct, parse('UInt32 wLenDone').cstruct, ] define('IOUSBDevRequest', IOUSBDevRequest) IOAsyncCallback1 = parse( 'void ( *IOAsyncCallback1)(void *refcon,IOReturn result,void *arg0)' ).ctype define('IOAsyncCallback1', IOAsyncCallback1) class IOUSBIsocFrame(Structure): _fields_ = [ parse('IOReturn frStatus').cstruct, parse('UInt16 frReqCount').cstruct, parse('UInt16 frActCount').cstruct, ] define('IOUSBIsocFrame', IOUSBIsocFrame) class IOUSBDevRequestTO(Structure): _fields_ = [ parse('UInt8 bmRequestType').cstruct,
USBDeviceAddress=define('USBDeviceAddress','UInt16') class IOUSBDevRequest(Structure): _fields_=[ parse('UInt8 bmRequestType').cstruct, parse('UInt8 bRequest').cstruct, parse('UInt16 wValue').cstruct, parse('UInt16 wIndex').cstruct, parse('UInt16 wLength').cstruct, parse('void *pData').cstruct, parse('UInt32 wLenDone').cstruct, ] define('IOUSBDevRequest',IOUSBDevRequest) IOAsyncCallback1=parse('void ( *IOAsyncCallback1)(void *refcon,IOReturn result,void *arg0)').ctype define('IOAsyncCallback1',IOAsyncCallback1) class IOUSBIsocFrame(Structure): _fields_=[ parse('IOReturn frStatus').cstruct, parse('UInt16 frReqCount').cstruct, parse('UInt16 frActCount').cstruct, ] define('IOUSBIsocFrame',IOUSBIsocFrame) class IOUSBDevRequestTO(Structure): _fields_=[ parse('UInt8 bmRequestType').cstruct, parse('UInt8 bRequest').cstruct,
def open(self): logging.info("opening hid device via usb") # plugInInterface initialised to NULL plugInInterface=COMObjectRef(POINTER(POINTER(IOCFPlugInInterfaceStruct))()) score=SInt32() err=IOCreatePlugInInterfaceForService(self._usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, byref(plugInInterface.ref), byref(score)); # query to get the USB interface usbDevInterface=POINTER(POINTER(IOUSBDeviceInterface))() err=plugInInterface.QueryInterface(CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),parse('LPVOID*').cast(byref(usbDevInterface))) if err: raise RuntimeError("Failed to QueryInterface for USB Device Interface") usbDevInterface=COMObjectRef(usbDevInterface) # open USB device err=usbDevInterface.USBDeviceOpen() if err: if err == kIOReturnExclusiveAccess: raise RuntimeError("Device already open") raise RuntimeError("Could not open device") numConf=UInt8() err=usbDevInterface.GetNumberOfConfigurations(byref(numConf)) if err: raise RuntimeError("Error calling GetNumberOfConfigurations") logging.info("Found %d Interface(s)" % numConf.value) configDesc=IOUSBConfigurationDescriptorPtr() # get first (and only) config err = usbDevInterface.GetConfigurationDescriptorPtr(0, byref(configDesc)) if err: raise RuntimeError("Error calling GetConfigurationDescriptorPtr") err = usbDevInterface.SetConfiguration(configDesc.contents.bConfigurationValue) if err: raise RuntimeError("Error calling SetConfiguration") interfaceRequest=IOUSBFindInterfaceRequest() interfaceRequest.bInterfaceClass = kIOUSBFindInterfaceDontCare interfaceRequest.bInterfaceSubClass = kIOUSBFindInterfaceDontCare interfaceRequest.bInterfaceProtocol = kIOUSBFindInterfaceDontCare interfaceRequest.bAlternateSetting = kIOUSBFindInterfaceDontCare interfaceIterator=io_iterator_t() err = usbDevInterface.CreateInterfaceIterator(byref(interfaceRequest), byref(interfaceIterator)) if err: raise RuntimeError("Error calling CreateInterfaceIterator") err = usbDevInterface.USBDeviceClose() if err: raise RuntimeError("Error calling USBDeviceClose") while True: interface = IOIteratorNext(interfaceIterator) if not interface: break self._open_interface(interface) IOObjectRelease(interfaceIterator)