class XFunction(fnfs.Function): def __init__(self, path, args): # TODO: endpoints aren't unique to interfaces (each ep shouldn't require a unique address) # TODO: functionfs doesn't support interfaces with 0 endpoints (required to function? unknown) self.max_packet_size = 0x0020 # 32 bytes iface0 = self.describe( fnfs.Descriptor.Interface, bInterfaceNumber=0, bAlternateSetting=0, bNumEndpoints=2, bInterfaceClass=fnfs.Descriptor.Class.vendor_spec, bInterfaceSubClass=93, bInterfaceProtocol=1, iInterface=0, ) if0ep1 = self.describe( fnfs.Descriptor.Endpoint, bEndpointAddress=1|fnfs.USB.Dir.IN, bmAttributes=fnfs.USB.Endpoint.Xfer.int, wMaxPacketSize=self.max_packet_size, bInterval=4, ) if0ep2 = self.describe( fnfs.Descriptor.Endpoint, bEndpointAddress=2|fnfs.USB.Dir.OUT, bmAttributes=fnfs.USB.Endpoint.Xfer.int, wMaxPacketSize=self.max_packet_size, bInterval=8, ) ifaces = [self.Interface(iface0, [if0ep1,if0ep2])] iface1 = self.describe( fnfs.Descriptor.Interface, bInterfaceNumber=1, bAlternateSetting=0, bNumEndpoints=4, bInterfaceClass=fnfs.Descriptor.Class.vendor_spec, bInterfaceSubClass=93, bInterfaceProtocol=3, iInterface=0, ) if1ep1 = self.describe( fnfs.Descriptor.Endpoint, bEndpointAddress=3|fnfs.USB.Dir.IN, bmAttributes=fnfs.USB.Endpoint.Xfer.int, wMaxPacketSize=self.max_packet_size, bInterval=2, ) if1ep2 = self.describe( fnfs.Descriptor.Endpoint, bEndpointAddress=4|fnfs.USB.Dir.OUT, bmAttributes=fnfs.USB.Endpoint.Xfer.int, wMaxPacketSize=self.max_packet_size, bInterval=4, ) if1ep3 = self.describe( fnfs.Descriptor.Endpoint, bEndpointAddress=5|fnfs.USB.Dir.IN, bmAttributes=fnfs.USB.Endpoint.Xfer.int, wMaxPacketSize=self.max_packet_size, bInterval=64, ) if1ep4 = self.describe( fnfs.Descriptor.Endpoint, bEndpointAddress=6|fnfs.USB.Dir.OUT, bmAttributes=fnfs.USB.Endpoint.Xfer.int, wMaxPacketSize=self.max_packet_size, bInterval=16, ) ifaces.append(self.Interface(iface1, [if1ep1, if1ep2, if1ep3, if1ep4])) iface2 = self.describe( fnfs.Descriptor.Interface, bInterfaceNumber=2, bAlternateSetting=0, bNumEndpoints=1, bInterfaceClass=fnfs.Descriptor.Class.vendor_spec, bInterfaceSubClass=93, bInterfaceProtocol=2, iInterface=0, ) if2ep1 = self.describe( fnfs.Descriptor.Endpoint, bEndpointAddress=7|fnfs.USB.Dir.IN, bmAttributes=fnfs.USB.Endpoint.Xfer.int, wMaxPacketSize=self.max_packet_size, bInterval=16, ) ifaces.append(self.Interface(iface2, [if2ep1])) iface3 = self.describe( fnfs.Descriptor.Interface, bInterfaceNumber=3, bAlternateSetting=0, bNumEndpoints=0, bInterfaceClass=fnfs.Descriptor.Class.vendor_spec, bInterfaceSubClass=93, bInterfaceProtocol=19, iInterface=4, # UNRECOGNIZED: 06 41 00 01 01 03 ) # TODO: this fails #ifaces.append(self.Interface(iface3)) self.loop = asyncio.get_event_loop() self.loop.set_exception_handler(self.exception) try: # If anything goes wrong from here on we MUST not # hold any file descriptors open, else there is a # good chance the kernel will deadlock. super(XFunction, self).__init__( path, ifaces, langs={ 0x0409: [ u'X Input', ], }, ) self.loop.add_reader(self.e0, self.process) # assert len(self._ep_list) == 4 self.inep = self._eps[1] self.outep = KAIOReader(self._eps[2]) self.outep.maxpkt = 512 self.inep.maxpkt = 512 self.responder = XResponder( outep=self.outep, inep=self.inep, loop=self.loop, ) except: # Catch ANY exception, close all file descriptors # and then re-raise. self.close() raise def exception(self, loop, context): loop.stop() raise context['exception'] def close(self): self.outep.close() super().close() def process(self): import time from random import randint while True: self.inep.write(struct.pack(msgfmt,*msg)) time.sleep(1) msg[1] = randint(0, 255) # randomly hit buttons msg[2] = randint(0, 255) # randomly hit more buttons if limit is None: self.outep.submit() # prime the first async read self.loop.run_forever() def run(self): self.outep.submit() # prime the first async read self.loop.run_forever()
class XFunction(functionfs.Function): def onEnable(self): print('functionfs: ENABLE') print('Real interface 0:', self.ep0.getRealInterfaceNumber(0)) import time cmds = [ [0x01, 0x03, 0x0e], [0x02, 0x03, 0x00], [0x03, 0x03, 0x03], [0x08, 0x03, 0x00], [ 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x69, 0xed, 0x23, 0xff, 0x6b, 0x00, 0x15, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ], [ 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xec, 0x23, 0xff, 0x6b, 0x00, 0x15, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ], ] neutral = [ 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xec, 0x23, 0xff, 0x6b, 0x00, 0x15, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ] press_a = [ 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0xfc, 0xec, 0x23, 0xff, 0x6b, 0x00, 0x15, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ] print('processing...') self.outep.submit() # prime the first async read for c in cmds: print('cmd: %s' % c) self.write(c) def onSetup(self, request_type, request, value, index, length): print('setup %s' % request_type) request_type_type = request_type & functionfs.ch9.USB_TYPE_MASK if request_type_type == functionfs.ch9.USB_TYPE_VENDOR: if request == common.REQUEST_ECHO: if (request_type & functionfs.ch9.USB_DIR_IN ) == functionfs.ch9.USB_DIR_IN: self.ep0.write(self.__echo_payload[:length]) elif length: self.__echo_payload = self.ep0.read(length) else: print('functionfs: onSetup: halt') self.ep0.halt(request_type) else: super(XFunction, self).onSetup( request_type, request, value, index, length, ) def __init__(self, path, args): # TODO: endpoints aren't unique to interfaces (each ep shouldn't require a unique address) # TODO: functionfs doesn't support interfaces with 0 endpoints (required to function? unknown) self.max_packet_size = 0x0020 # 32 bytes iface0 = functionfs.getDescriptor( functionfs.USBInterfaceDescriptor, bInterfaceNumber=0, bAlternateSetting=0, bNumEndpoints=2, bInterfaceClass=255, #functionfs.ch9.USB_CLASS_VENDOR_SPEC, bInterfaceSubClass=93, #functionfs.ch9.USB_SUBCLASS_VENDOR_SPEC, bInterfaceProtocol=1, iInterface=0, ) fs_list = [iface0] hs_list = [iface0] if0ep1 = functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=1 | functionfs.ch9.USB_DIR_IN, bmAttributes=3, #functionfs.ch9.USB_ENDPOINT_XFER_BULK, wMaxPacketSize=self.max_packet_size, bInterval=4, ) if0ep2 = functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=2 | functionfs.ch9.USB_DIR_OUT, bmAttributes=3, #functionfs.ch9.USB_ENDPOINT_XFER_BULK, wMaxPacketSize=self.max_packet_size, bInterval=8, ) fs_list += [if0ep1, if0ep2] hs_list += [if0ep1, if0ep2] iface1 = functionfs.getDescriptor( functionfs.USBInterfaceDescriptor, bInterfaceNumber=1, bAlternateSetting=0, bNumEndpoints=4, bInterfaceClass=255, #functionfs.ch9.USB_CLASS_VENDOR_SPEC, bInterfaceSubClass=93, #functionfs.ch9.USB_SUBCLASS_VENDOR_SPEC, bInterfaceProtocol=3, iInterface=0, ) if1ep1 = functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=3 | functionfs.ch9.USB_DIR_IN, bmAttributes=3, #functionfs.ch9.USB_ENDPOINT_XFER_BULK, wMaxPacketSize=self.max_packet_size, bInterval=2, ) if1ep2 = functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=4 | functionfs.ch9.USB_DIR_OUT, bmAttributes=3, #functionfs.ch9.USB_ENDPOINT_XFER_BULK, wMaxPacketSize=self.max_packet_size, bInterval=4, ) if1ep3 = functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=5 | functionfs.ch9.USB_DIR_IN, bmAttributes=3, #functionfs.ch9.USB_ENDPOINT_XFER_BULK, wMaxPacketSize=self.max_packet_size, bInterval=64, ) if1ep4 = functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=6 | functionfs.ch9.USB_DIR_OUT, bmAttributes=3, #functionfs.ch9.USB_ENDPOINT_XFER_BULK, wMaxPacketSize=self.max_packet_size, bInterval=16, ) fs_list += [iface1, if1ep1, if1ep2, if1ep3, if1ep4] hs_list += [iface1, if1ep1, if1ep2, if1ep3, if1ep4] iface2 = functionfs.getDescriptor( functionfs.USBInterfaceDescriptor, bInterfaceNumber=2, bAlternateSetting=0, bNumEndpoints=1, bInterfaceClass=255, #functionfs.ch9.USB_CLASS_VENDOR_SPEC, bInterfaceSubClass=93, #functionfs.ch9.USB_SUBCLASS_VENDOR_SPEC, bInterfaceProtocol=2, iInterface=0, ) if2ep1 = functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=7 | functionfs.ch9.USB_DIR_IN, bmAttributes=3, #functionfs.ch9.USB_ENDPOINT_XFER_BULK, wMaxPacketSize=self.max_packet_size, bInterval=16, ) fs_list += [iface2, if2ep1] hs_list += [iface2, if2ep1] iface3 = functionfs.getDescriptor( functionfs.USBInterfaceDescriptor, bInterfaceNumber=3, bAlternateSetting=0, bNumEndpoints=0, bInterfaceClass=255, #functionfs.ch9.USB_CLASS_VENDOR_SPEC, bInterfaceSubClass=253, #functionfs.ch9.USB_SUBCLASS_VENDOR_SPEC, bInterfaceProtocol=19, iInterface=4, # UNRECOGNIZED: 06 41 00 01 01 03 ) #INT_DESCRIPTOR = functionfs.getDescriptor( #functionfs.USBEndpointDescriptorNoAudio, #bEndpointAddress=2|functionfs.ch9.USB_DIR_IN, #bmAttributes=functionfs.ch9.USB_ENDPOINT_XFER_INT, #wMaxPacketSize=28, #bInterval=6, #) #hs_list.append(iface3) #fs_list.append(iface3) self.loop = asyncio.get_event_loop() self.loop.set_exception_handler(self.exception) try: # If anything goes wrong from here on we MUST not # hold any file descriptors open, else there is a # good chance the kernel will deadlock. super(XFunction, self).__init__( path, fs_list=fs_list, hs_list=hs_list, lang_dict={ 0x0409: [ u'MTP', ], }, ) self.loop.add_reader(self.ep0, self.processEvents) print(len(self._ep_list)) # assert len(self._ep_list) == 4 print(self._ep_list) self.cmdep = KAIOWriter(self._ep_list[1]) #self.inep = self._ep_list[1] self.outep = KAIOReader(self._ep_list[2]) #self.intep = KAIOWriter(self._ep_list[3]) self.outep.maxpkt = 512 #self.inep.maxpkt = 512 #self.responder = MTPResponder( #outep=self.outep, #inep=self.inep, #intep=self.intep, #loop=self.loop, #args=args #) except: # Catch ANY exception, close all file descriptors # and then re-raise. self.close() raise def write(self, value): """ Queue write in kernel. value (bytes) Value to send. """ ep = self.getEndpoint(1) ep.write(bytes(value)) #self.cmdep.write(bytes(value)) return aio_block = libaio.AIOBlock( libaio.AIOBLOCK_MODE_WRITE, self.getEndpoint(1), [bytearray(value)], 0, self.eventfd, self._onCanSend, ) self._aio_send_block_list.append(aio_block) self._aio_context.submit([aio_block]) if len(self._aio_send_block_list) == MAX_PENDING_WRITE_COUNT: self._onCannotSend() def exception(self, loop, context): loop.stop() raise context['exception'] def close(self): self.outep.close() #self.intep.close() super().close() def processEventsForever(self): import time cmds = [ [0x01, 0x03, 0x0e], [0x02, 0x03, 0x00], [0x03, 0x03, 0x03], [0x08, 0x03, 0x00], [ 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x69, 0xed, 0x23, 0xff, 0x6b, 0x00, 0x15, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ], [ 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xec, 0x23, 0xff, 0x6b, 0x00, 0x15, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ], ] neutral = [ 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xec, 0x23, 0xff, 0x6b, 0x00, 0x15, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ] press_a = [ 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0xfc, 0xec, 0x23, 0xff, 0x6b, 0x00, 0x15, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ] print('processing...') self.outep.submit() # prime the first async read for c in cmds: print('cmd: %s' % c) self.write(c) self.loop.run_forever() print('press a') for x in range(0, 60): time.sleep(0.01) self.write(neutral) for x in range(0, 60): time.sleep(0.01) self.write(press_a)
class XFunction(functionfs.Function): def onSetup(self, *args, **kwargs): print('setup') super(XFunction, self).setup(*args, **kwargs) def __init__(self, path, args): # TODO: endpoints aren't unique to interfaces (each ep shouldn't require a unique address) # TODO: functionfs doesn't support interfaces with 0 endpoints (required to function? unknown) self.max_packet_size = 0x0020 # 32 bytes iface0 = functionfs.getDescriptor( functionfs.USBInterfaceDescriptor, bInterfaceNumber=0, bAlternateSetting=0, bNumEndpoints=2, bInterfaceClass=255, #functionfs.ch9.USB_CLASS_VENDOR_SPEC, bInterfaceSubClass=93, #functionfs.ch9.USB_SUBCLASS_VENDOR_SPEC, bInterfaceProtocol=1, iInterface=0, ) fs_list = [iface0] hs_list = [iface0] if0ep1 = functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=1|functionfs.ch9.USB_DIR_IN, bmAttributes=3,#functionfs.ch9.USB_ENDPOINT_XFER_BULK, wMaxPacketSize=self.max_packet_size, bInterval=4, ) if0ep2 = functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=2|functionfs.ch9.USB_DIR_OUT, bmAttributes=3,#functionfs.ch9.USB_ENDPOINT_XFER_BULK, wMaxPacketSize=self.max_packet_size, bInterval=8, ) fs_list += [if0ep1,if0ep2] hs_list += [if0ep1,if0ep2] iface1 = functionfs.getDescriptor( functionfs.USBInterfaceDescriptor, bInterfaceNumber=1, bAlternateSetting=0, bNumEndpoints=4, bInterfaceClass=255, #functionfs.ch9.USB_CLASS_VENDOR_SPEC, bInterfaceSubClass=93, #functionfs.ch9.USB_SUBCLASS_VENDOR_SPEC, bInterfaceProtocol=3, iInterface=0, ) if1ep1 = functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=3|functionfs.ch9.USB_DIR_IN, bmAttributes=3,#functionfs.ch9.USB_ENDPOINT_XFER_BULK, wMaxPacketSize=self.max_packet_size, bInterval=2, ) if1ep2 = functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=4|functionfs.ch9.USB_DIR_OUT, bmAttributes=3,#functionfs.ch9.USB_ENDPOINT_XFER_BULK, wMaxPacketSize=self.max_packet_size, bInterval=4, ) if1ep3 = functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=5|functionfs.ch9.USB_DIR_IN, bmAttributes=3,#functionfs.ch9.USB_ENDPOINT_XFER_BULK, wMaxPacketSize=self.max_packet_size, bInterval=64, ) if1ep4 = functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=6|functionfs.ch9.USB_DIR_OUT, bmAttributes=3,#functionfs.ch9.USB_ENDPOINT_XFER_BULK, wMaxPacketSize=self.max_packet_size, bInterval=16, ) fs_list += [iface1,if1ep1,if1ep2,if1ep3,if1ep4] hs_list += [iface1,if1ep1,if1ep2,if1ep3,if1ep4] iface2 = functionfs.getDescriptor( functionfs.USBInterfaceDescriptor, bInterfaceNumber=2, bAlternateSetting=0, bNumEndpoints=1, bInterfaceClass=255, #functionfs.ch9.USB_CLASS_VENDOR_SPEC, bInterfaceSubClass=93, #functionfs.ch9.USB_SUBCLASS_VENDOR_SPEC, bInterfaceProtocol=2, iInterface=0, ) if2ep1 = functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=7|functionfs.ch9.USB_DIR_IN, bmAttributes=3,#functionfs.ch9.USB_ENDPOINT_XFER_BULK, wMaxPacketSize=self.max_packet_size, bInterval=16, ) fs_list += [iface2,if2ep1] hs_list += [iface2,if2ep1] iface3 = functionfs.getDescriptor( functionfs.USBInterfaceDescriptor, bInterfaceNumber=3, bAlternateSetting=0, bNumEndpoints=0, bInterfaceClass=255, #functionfs.ch9.USB_CLASS_VENDOR_SPEC, bInterfaceSubClass=253, #functionfs.ch9.USB_SUBCLASS_VENDOR_SPEC, bInterfaceProtocol=19, iInterface=4, # UNRECOGNIZED: 06 41 00 01 01 03 ) import ctypes def barray(data): BArray = ctypes.c_ubyte*(len(data)) return BArray(*data) osc = functionfs.OSExtCompatDesc( # hid interface bFirstInterfaceNumber=0, Reserved1=1, CompatibleID=barray([0,0,0,0,0,0,0,0]), SubCompatibleID=barray([0,0,0,0,0,0,0,0]), Reserved2=barray([0,0,0,0,0,0]) ) osp1 = functionfs.getOSExtPropDesc( 0x00000002, #unicode str w/ env variables 'Icons'.encode('utf8'), '%SystemRoot%\system32\shell32.dll,-233'.encode('utf8'), ) osp2 = functionfs.getOSExtPropDesc( 0x00000001, # unicode str 'Label'.encode('utf8'), 'XYZ Device'.encode('utf8'), ) ospd1 = functionfs.getOSDesc(1, [osp1]) ospd2 = functionfs.getOSDesc(1, [osp2]) oscd = functionfs.getOSDesc(1, [osc]) os_list = [oscd,ospd1,ospd2] #INT_DESCRIPTOR = functionfs.getDescriptor( #functionfs.USBEndpointDescriptorNoAudio, #bEndpointAddress=2|functionfs.ch9.USB_DIR_IN, #bmAttributes=functionfs.ch9.USB_ENDPOINT_XFER_INT, #wMaxPacketSize=28, #bInterval=6, #) #hs_list.append(iface3) #fs_list.append(iface3) print('building') self.loop = asyncio.get_event_loop() self.loop.set_exception_handler(self.exception) try: # If anything goes wrong from here on we MUST not # hold any file descriptors open, else there is a # good chance the kernel will deadlock. super(XFunction, self).__init__( path, fs_list=fs_list, hs_list=hs_list, os_list=os_list, lang_dict={ 0x0409: [ u'MTP', ], }, ) self.loop.add_reader(self.ep0, self.processEvents) print(len(self._ep_list)) # assert len(self._ep_list) == 4 self.inep = self._ep_list[1] self.outep = KAIOReader(self._ep_list[2]) self.intep = KAIOWriter(self._ep_list[3]) self.outep.maxpkt = 512 self.inep.maxpkt = 512 self.responder = MTPResponder( outep=self.outep, inep=self.inep, intep=self.intep, loop=self.loop, args=args ) except: # Catch ANY exception, close all file descriptors # and then re-raise. self.close() raise def exception(self, loop, context): loop.stop() raise context['exception'] def close(self): self.outep.close() self.intep.close() super().close() def processEventsForever(self): print('processing') self.outep.submit() # prime the first async read self.loop.run_forever()
class XFunction(functionfs.Function): def __init__(self, path, args): # TODO: endpoints aren't unique to interfaces (each ep shouldn't require a unique address) # TODO: functionfs doesn't support interfaces with 0 endpoints (required to function? unknown) self.max_packet_size = 0x0040 # 64 bytes #self._aio_context = libaio.AIOContext( # PENDING_READ_COUNT + MAX_PENDING_WRITE_COUNT, #) #self.eventfd = eventfd = libaio.EventFD() iface0 = functionfs.getDescriptor( functionfs.USBInterfaceDescriptor, bInterfaceNumber=0, bAlternateSetting=0, bNumEndpoints=2, bInterfaceClass=255, #functionfs.ch9.USB_CLASS_VENDOR_SPEC, bInterfaceSubClass=93, #functionfs.ch9.USB_SUBCLASS_VENDOR_SPEC, bInterfaceProtocol=1, iInterface=0, ) fs_list = [iface0] hs_list = [iface0] if0ep1 = functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=1 | functionfs.ch9.USB_DIR_IN, bmAttributes=3, #functionfs.ch9.USB_ENDPOINT_XFER_BULK, wMaxPacketSize=self.max_packet_size, bInterval=4, ) if0ep2 = functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=2 | functionfs.ch9.USB_DIR_OUT, bmAttributes=3, #functionfs.ch9.USB_ENDPOINT_XFER_BULK, wMaxPacketSize=self.max_packet_size, bInterval=8, ) import ctypes def barray(data): BArray = ctypes.c_ubyte * (len(data)) return BArray(*data) osc = functionfs.OSExtCompatDesc( # hid interface bFirstInterfaceNumber=0, Reserved1=1, CompatibleID=barray('XUSB10'.encode('utf8') + bytes([0, 0])), SubCompatibleID=barray([0, 0, 0, 0, 0, 0, 0, 0]), Reserved2=barray([0, 0, 0, 0, 0, 0])) osp1 = functionfs.getOSExtPropDesc( 0x00000002, #unicode str w/ env variables 'Icons'.encode('utf8'), '%SystemRoot%\system32\shell32.dll,-233'.encode('utf8'), ) osp2 = functionfs.getOSExtPropDesc( 0x00000001, # unicode str 'Label'.encode('utf8'), 'XYZ Device'.encode('utf8'), ) ospd1 = functionfs.getOSDesc(0, [osp1]) ospd2 = functionfs.getOSDesc(0, [osp2]) oscd = functionfs.getOSDesc(0, [osc]) os_list = [oscd] #,ospd1,ospd2] fs_list += [if0ep1, if0ep2] hs_list += [if0ep1, if0ep2] self.loop = asyncio.get_event_loop() self.loop.set_exception_handler(self.exception) try: # If anything goes wrong from here on we MUST not # hold any file descriptors open, else there is a # good chance the kernel will deadlock. super(XFunction, self).__init__( path, fs_list=fs_list, hs_list=hs_list, os_list=os_list, lang_dict={ 0x0409: [ u'English', ], }, ) self.loop.add_reader(self.ep0, self.processEventsForever) print(len(self._ep_list)) # assert len(self._ep_list) == 4 self.inep = self._ep_list[1] self.cmdep = KAIOWriter(self._ep_list[1]) self.outep = KAIOReader(self._ep_list[2]) self.intep = KAIOWriter(self._ep_list[2]) self.outep.maxpkt = 512 self.inep.maxpkt = 512 self.responder = MTPResponder(outep=self.outep, inep=self.inep, intep=self.intep, loop=self.loop, args=args) except: # Catch ANY exception, close all file descriptors # and then re-raise. self.close() raise def onEnable(self): print('functionfs: ENABLE') print('Real interface 0:', self.ep0.getRealInterfaceNumber(0)) def write(self, value): """ Queue write in kernel. value (bytes) Value to send. """ #print('reading') #ep2 = self.getEndpoint(2) #ep2.read(64) #print('writing') #ep1 = self.getEndpoint(1) self.cmdep.write(bytes(value)) return aio_block = libaio.AIOBlock( libaio.AIOBLOCK_MODE_WRITE, self.getEndpoint(1), [bytearray(value)], 0, self.eventfd, self._onCanSend, ) self._aio_send_block_list.append(aio_block) self._aio_context.submit([aio_block]) if len(self._aio_send_block_list) == MAX_PENDING_WRITE_COUNT: self._onCannotSend() def exception(self, loop, context): loop.stop() raise context['exception'] def close(self): #self.outep.close() #self.intep.close() super().close() def __process(self, iterator): print('processing...') readinto = self.ep0.readinto # FunctionFS can queue up to 4 events, so let's read that much. event_len = ctypes.sizeof(Event) array_type = Event * 4 buf = bytearray(ctypes.sizeof(array_type)) print(phexlify(buf)) event_list = array_type.from_buffer(buf) event_dict = self.__event_dict for _ in iterator: if self._closed: break try: length = readinto(buf) except IOError as exc: if exc.errno == errno.EINTR: continue raise if not length: # Note: also catches None, returned when ep0 is non-blocking break # TODO: test if this happens when ep0 gets closed # (by FunctionFS or in another thread or in a handler) count, remainder = divmod(length, event_len) assert remainder == 0, (length, event_len) for index in range(count): event = event_list[index] event_type = event.type if event_type == SETUP: setup = event.u.setup try: self.onSetup( setup.bRequestType, setup.bRequest, setup.wValue, setup.wIndex, setup.wLength, ) except BaseException: # On *ANY* exception, halt endpoint self.ep0.halt(setup.bRequestType) raise else: getattr(self, event_dict[event.type])() def processEventsForever(self): import time cmds = [ [0x01, 0x03, 0x0e], [0x02, 0x03, 0x00], [0x03, 0x03, 0x03], [0x08, 0x03, 0x00], [ 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x69, 0xed, 0x23, 0xff, 0x6b, 0x00, 0x15, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ], [ 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xec, 0x23, 0xff, 0x6b, 0x00, 0x15, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ], ] neutral = [ 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xec, 0x23, 0xff, 0x6b, 0x00, 0x15, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ] press_a = [ 0x00, 0x14, 0x00, 0x08, 0x00, 0x00, 0xfc, 0xec, 0x23, 0xff, 0x6b, 0x00, 0x15, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ] #for c in cmds: # self.write(c) #while True: # for x in range(0,60): # time.sleep(0.01) # self.write(neutral) # for x in range(0,60): # time.sleep(0.01) # self.write(press_a) self.outep.submit() # prime the first async read self.loop.run_forever()
class XFunction(functionfs.Function): def __init__(self, path, args): # TODO: endpoints aren't unique to interfaces (each ep shouldn't require a unique address) # TODO: functionfs doesn't support interfaces with 0 endpoints (required to function? unknown) self.max_packet_size = 0x0020 # 32 bytes iface0 = functionfs.getDescriptor( functionfs.USBInterfaceDescriptor, bInterfaceNumber=0, bAlternateSetting=0, bNumEndpoints=2, bInterfaceClass=255, #functionfs.ch9.USB_CLASS_VENDOR_SPEC, bInterfaceSubClass=93, #functionfs.ch9.USB_SUBCLASS_VENDOR_SPEC, bInterfaceProtocol=1, iInterface=0, ) fs_list = [iface0] hs_list = [iface0] if0ep1 = functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=1 | functionfs.ch9.USB_DIR_IN, bmAttributes=3, #functionfs.ch9.USB_ENDPOINT_XFER_BULK, wMaxPacketSize=self.max_packet_size, bInterval=4, ) if0ep2 = functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=2 | functionfs.ch9.USB_DIR_OUT, bmAttributes=3, #functionfs.ch9.USB_ENDPOINT_XFER_BULK, wMaxPacketSize=self.max_packet_size, bInterval=8, ) fs_list += [if0ep1, if0ep2] hs_list += [if0ep1, if0ep2] iface1 = functionfs.getDescriptor( functionfs.USBInterfaceDescriptor, bInterfaceNumber=1, bAlternateSetting=0, bNumEndpoints=4, bInterfaceClass=255, #functionfs.ch9.USB_CLASS_VENDOR_SPEC, bInterfaceSubClass=93, #functionfs.ch9.USB_SUBCLASS_VENDOR_SPEC, bInterfaceProtocol=3, iInterface=0, ) if1ep1 = functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=3 | functionfs.ch9.USB_DIR_IN, bmAttributes=3, #functionfs.ch9.USB_ENDPOINT_XFER_BULK, wMaxPacketSize=self.max_packet_size, bInterval=2, ) if1ep2 = functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=4 | functionfs.ch9.USB_DIR_OUT, bmAttributes=3, #functionfs.ch9.USB_ENDPOINT_XFER_BULK, wMaxPacketSize=self.max_packet_size, bInterval=4, ) if1ep3 = functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=5 | functionfs.ch9.USB_DIR_IN, bmAttributes=3, #functionfs.ch9.USB_ENDPOINT_XFER_BULK, wMaxPacketSize=self.max_packet_size, bInterval=64, ) if1ep4 = functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=6 | functionfs.ch9.USB_DIR_OUT, bmAttributes=3, #functionfs.ch9.USB_ENDPOINT_XFER_BULK, wMaxPacketSize=self.max_packet_size, bInterval=16, ) fs_list += [iface1, if1ep1, if1ep2, if1ep3, if1ep4] hs_list += [iface1, if1ep1, if1ep2, if1ep3, if1ep4] iface2 = functionfs.getDescriptor( functionfs.USBInterfaceDescriptor, bInterfaceNumber=2, bAlternateSetting=0, bNumEndpoints=1, bInterfaceClass=255, #functionfs.ch9.USB_CLASS_VENDOR_SPEC, bInterfaceSubClass=93, #functionfs.ch9.USB_SUBCLASS_VENDOR_SPEC, bInterfaceProtocol=2, iInterface=0, ) if2ep1 = functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=7 | functionfs.ch9.USB_DIR_IN, bmAttributes=3, #functionfs.ch9.USB_ENDPOINT_XFER_BULK, wMaxPacketSize=self.max_packet_size, bInterval=16, ) fs_list += [iface2, if2ep1] hs_list += [iface2, if2ep1] iface3 = functionfs.getDescriptor( functionfs.USBInterfaceDescriptor, bInterfaceNumber=3, bAlternateSetting=0, bNumEndpoints=0, bInterfaceClass=255, #functionfs.ch9.USB_CLASS_VENDOR_SPEC, bInterfaceSubClass=253, #functionfs.ch9.USB_SUBCLASS_VENDOR_SPEC, bInterfaceProtocol=19, iInterface=4, # UNRECOGNIZED: 06 41 00 01 01 03 ) #INT_DESCRIPTOR = functionfs.getDescriptor( #functionfs.USBEndpointDescriptorNoAudio, #bEndpointAddress=2|functionfs.ch9.USB_DIR_IN, #bmAttributes=functionfs.ch9.USB_ENDPOINT_XFER_INT, #wMaxPacketSize=28, #bInterval=6, #) #hs_list.append(iface3) #fs_list.append(iface3) self.loop = asyncio.get_event_loop() self.loop.set_exception_handler(self.exception) try: # If anything goes wrong from here on we MUST not # hold any file descriptors open, else there is a # good chance the kernel will deadlock. super(XFunction, self).__init__( path, fs_list=fs_list, hs_list=hs_list, lang_dict={ 0x0409: [ u'MTP', ], }, ) self.loop.add_reader(self.ep0, self.processEvents) print(len(self._ep_list)) # assert len(self._ep_list) == 4 self.inep = self._ep_list[1] self.outep = KAIOReader(self._ep_list[2]) self.intep = KAIOWriter(self._ep_list[3]) self.outep.maxpkt = 512 self.inep.maxpkt = 512 self.responder = MTPResponder(outep=self.outep, inep=self.inep, intep=self.intep, loop=self.loop, args=args) except: # Catch ANY exception, close all file descriptors # and then re-raise. self.close() raise def exception(self, loop, context): loop.stop() raise context['exception'] def close(self): self.outep.close() self.intep.close() super().close() def processEventsForever(self): self.outep.submit() # prime the first async read self.loop.run_forever()
class MTPFunction(functionfs.Function): def __init__(self, path, args): INTERFACE_DESCRIPTOR = functionfs.getDescriptor( functionfs.USBInterfaceDescriptor, bInterfaceNumber=0, bAlternateSetting=0, bNumEndpoints=3, bInterfaceClass=functionfs.ch9.USB_CLASS_VENDOR_SPEC, bInterfaceSubClass=functionfs.ch9.USB_SUBCLASS_VENDOR_SPEC, bInterfaceProtocol=0, iInterface=1, ) fs_list = [INTERFACE_DESCRIPTOR] hs_list = [INTERFACE_DESCRIPTOR] fs_list.append( functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=1 | functionfs.ch9.USB_DIR_IN, bmAttributes=functionfs.ch9.USB_ENDPOINT_XFER_BULK, wMaxPacketSize=FS_BULK_MAX_PACKET_SIZE, bInterval=0, )) fs_list.append( functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=2 | functionfs.ch9.USB_DIR_OUT, bmAttributes=functionfs.ch9.USB_ENDPOINT_XFER_BULK, wMaxPacketSize=FS_BULK_MAX_PACKET_SIZE, bInterval=0, )) hs_list.append( functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=1 | functionfs.ch9.USB_DIR_IN, bmAttributes=functionfs.ch9.USB_ENDPOINT_XFER_BULK, wMaxPacketSize=HS_BULK_MAX_PACKET_SIZE, bInterval=0, )) hs_list.append( functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=2 | functionfs.ch9.USB_DIR_OUT, bmAttributes=functionfs.ch9.USB_ENDPOINT_XFER_BULK, wMaxPacketSize=HS_BULK_MAX_PACKET_SIZE, bInterval=0, )) INT_DESCRIPTOR = functionfs.getDescriptor( functionfs.USBEndpointDescriptorNoAudio, bEndpointAddress=2 | functionfs.ch9.USB_DIR_IN, bmAttributes=functionfs.ch9.USB_ENDPOINT_XFER_INT, wMaxPacketSize=28, bInterval=6, ) hs_list.append(INT_DESCRIPTOR) fs_list.append(INT_DESCRIPTOR) self.loop = asyncio.get_event_loop() self.loop.set_exception_handler(self.exception) try: # If anything goes wrong from here on we MUST not # hold any file descriptors open, else there is a # good chance the kernel will deadlock. super(MTPFunction, self).__init__( path, fs_list=fs_list, hs_list=hs_list, lang_dict={ 0x0409: [ u'MTP', ], }, ) self.loop.add_reader(self.ep0, self.processEvents) assert len(self._ep_list) == 4 self.inep = self._ep_list[1] self.outep = KAIOReader(self._ep_list[2]) self.intep = KAIOWriter(self._ep_list[3]) self.outep.maxpkt = 512 self.inep.maxpkt = 512 self.responder = MTPResponder(outep=self.outep, inep=self.inep, intep=self.intep, loop=self.loop, args=args) except: # Catch ANY exception, close all file descriptors # and then re-raise. self.close() raise def exception(self, loop, context): loop.stop() raise context['exception'] def close(self): self.outep.close() self.intep.close() super().close() def processEventsForever(self): self.outep.submit() # prime the first async read self.loop.run_forever()