class MtpApiTest(BaseTestCase): ''' Currently, all tests here are with buffers, as the API of MtpApi ''' def setUp(self): super(MtpApiTest, self).setUp() self.object = MtpObject.from_fs_recursive('.') self.storage_info = MtpStorageInfo( st_type=0, fs_type=0, access=0, max_cap=150000, free_bytes=0, free_objs=0, desc='MyStorage', vol_id='Python MTP Device Stack', ) self.storage = MtpStorage(self.storage_info) self.storage.add_object(self.object) self.dev_info = MtpDeviceInfo( std_version=0x0102, mtp_vendor_ext_id=0x03040506, mtp_version=0x0708, mtp_extensions='Some Extension', functional_mode=0x0000, capture_formats=[], playback_formats=[], manufacturer='BinyaminSharet', model='Role', device_version='1.2.3', serial_number='0123456789abcdef', ) properties = [ MtpDeviceProperty(MtpDevicePropertyCode.BatteryLevel, 0, UInt8(50), UInt8(0)) ] self.dev = MtpDevice(self.dev_info, properties) self.dev.add_storage(self.storage) self.api = MtpApi(self.dev) def testApiOpenSession(self): command = pack('<IHHII', 0x10, ContainerTypes.Command, OperationDataCodes.OpenSession, 1, 1) excepted_response = pack('<IHHI', 0xc, ContainerTypes.Response, ResponseCodes.OK, 1) resps = self.api.handle_payload(command) self.assertEqual(len(resps), 1) self.assertEqual(resps[0], excepted_response) def testApiGetDeviceInfo(self): command = pack('<IHHI', 0x0c, ContainerTypes.Command, OperationDataCodes.GetDeviceInfo, 1) excepted_response = pack('<IHHI', 0xc, ContainerTypes.Response, ResponseCodes.OK, 1) resps = self.api.handle_payload(command) self.assertEqual(len(resps), 2) self.assertEqual(resps[1], excepted_response) def testApiUnsupportedOperation(self): command = pack('<IHHI', 0xc, ContainerTypes.Command, 0, 1) excepted_response = pack('<IHHI', 0xc, ContainerTypes.Response, ResponseCodes.OPERATION_NOT_SUPPORTED, 1) resps = self.api.handle_payload(command) self.assertEqual(len(resps), 1) self.assertEqual(resps[0], excepted_response) def testApiSendObjectOperation(self): obj_data = b'1234' # open session self.testApiOpenSession() # send object info send_obj_info_cmd = pack('<IHHII', 0x10, ContainerTypes.Command, OperationDataCodes.SendObjectInfo, 1, self.storage.get_uid()) send_obj_info_cmd_resp = self.api.handle_payload(send_obj_info_cmd) self.assertEqual(send_obj_info_cmd_resp, []) obj_info_dataset = unhexlify('0100010001380000040000000000000000000000000000000000000000000000000000000000060000000000000000000000000011770061006c006c00700061007000650072005f0031002e006a007000650067000000000000') send_obj_info_data = pack('<IHHI', len(obj_info_dataset) + 0xc, ContainerTypes.Data, OperationDataCodes.SendObjectInfo, 1) + obj_info_dataset send_obj_info_data_resp = self.api.handle_payload(send_obj_info_data) self.assertEqual(len(send_obj_info_data_resp), 1) response_status = unpack('<H', send_obj_info_data_resp[0][6:8])[0] self.assertEqual(response_status, ResponseCodes.OK) # send object send_obj_cmd = pack('<IHHI', 0xc, ContainerTypes.Command, OperationDataCodes.SendObject, 2) send_obj_cmd_resp = self.api.handle_payload(send_obj_cmd) self.assertEqual(send_obj_cmd_resp, []) send_obj_data = pack('<IHHI', len(obj_data) + 0xc, ContainerTypes.Data, OperationDataCodes.SendObject, 2) + obj_data send_obj_data_resp = self.api.handle_payload(send_obj_data) self.assertEqual(len(send_obj_data_resp), 1) response_status = unpack('<H', send_obj_info_data_resp[0][6:8])[0] self.assertEqual(response_status, ResponseCodes.OK) # read object info # read object ? def testApiLongSendObjectOperation(self): obj_data = b'1234' # open session self.testApiOpenSession() # send object info send_obj_info_cmd = pack('<IHHII', 0x10, ContainerTypes.Command, OperationDataCodes.SendObjectInfo, 1, self.storage.get_uid()) send_obj_info_cmd_resp = self.api.handle_payload(send_obj_info_cmd) self.assertEqual(send_obj_info_cmd_resp, []) obj_info_dataset = unhexlify('0100010001380000040000000000000000000000000000000000000000000000000000000000060000000000000000000000000011770061006c006c00700061007000650072005f0031002e006a007000650067000000000000') send_obj_info_data = pack('<IHHI', len(obj_info_dataset) + 0xc, ContainerTypes.Data, OperationDataCodes.SendObjectInfo, 1) + obj_info_dataset send_obj_info_data_resp = self.api.handle_payload(send_obj_info_data) self.assertEqual(len(send_obj_info_data_resp), 1) response_status = unpack('<H', send_obj_info_data_resp[0][6:8])[0] self.assertEqual(response_status, ResponseCodes.OK) # send object send_obj_cmd = pack('<IHHI', 0xc, ContainerTypes.Command, OperationDataCodes.SendObject, 2) send_obj_cmd_resp = self.api.handle_payload(send_obj_cmd) self.assertEqual(send_obj_cmd_resp, []) send_obj_data = pack('<IHHI', len(obj_data) + 0xc, ContainerTypes.Data, OperationDataCodes.SendObject, 2) + obj_data[:2] send_obj_data_resp = self.api.handle_payload(send_obj_data) self.assertEqual(send_obj_data_resp, []) send_obj_data = obj_data[2:3] send_obj_data_resp = self.api.handle_payload(send_obj_data) self.assertEqual(send_obj_data_resp, []) send_obj_data = obj_data[3:4] send_obj_data_resp = self.api.handle_payload(send_obj_data) self.assertEqual(len(send_obj_data_resp), 1) response_status = unpack('<H', send_obj_info_data_resp[0][6:8])[0] self.assertEqual(response_status, ResponseCodes.OK)
class USBMtpInterface(USBInterface): name = 'MtpInterface' def __init__(self, app, phy): if not mtpdeviceloaded: raise Exception('You cannot use USBMtp until you install pymtpdevice') # TODO: un-hardcode string index (last arg before 'verbose') super(USBMtpInterface, self).__init__( app=app, phy=phy, interface_number=0, interface_alternate=0, interface_class=USBClass.VendorSpecific, interface_subclass=0xff, interface_protocol=0, interface_string_index=0, endpoints=[ USBEndpoint( app=app, phy=phy, number=1, direction=USBEndpoint.direction_out, transfer_type=USBEndpoint.transfer_type_bulk, sync_type=USBEndpoint.sync_type_none, usage_type=USBEndpoint.usage_type_data, max_packet_size=64, interval=0, handler=self.handle_ep1_data_available ), USBEndpoint( app=app, phy=phy, number=2, direction=USBEndpoint.direction_in, transfer_type=USBEndpoint.transfer_type_bulk, sync_type=USBEndpoint.sync_type_none, usage_type=USBEndpoint.usage_type_data, max_packet_size=64, interval=0, handler=None ), USBEndpoint( app=app, phy=phy, number=3, direction=USBEndpoint.direction_in, transfer_type=USBEndpoint.transfer_type_interrupt, sync_type=USBEndpoint.sync_type_none, usage_type=USBEndpoint.usage_type_data, max_packet_size=64, interval=32, handler=None ), ], ) self.object = MtpObject.from_fs_recursive('mtp_fs') # self.object = MtpObject.from_fs_recursive('mtp_fs/eits.mp3') self.storage_info = MtpStorageInfo( st_type=1, fs_type=2, access=0, max_cap=150000, free_bytes=0, free_objs=0, desc='MyStorage', vol_id='Python MTP Device Stack', ) self.storage = MtpStorage(self.storage_info) self.storage.add_object(self.object) self.dev_info = MtpDeviceInfo( std_version=0x0064, mtp_vendor_ext_id=0x00000006, mtp_version=0x0064, mtp_extensions='microsoft.com: 1.0;', functional_mode=0x0000, capture_formats=[], playback_formats=[], manufacturer='BinyaminSharet', model='Role', device_version='1.2', serial_number='3031323334353637', ) properties = [ MtpDeviceProperty(MtpDevicePropertyCode.MTP_DeviceFriendlyName, 0, MStr('UmapMtpDevice'), MStr('')), MtpDeviceProperty(MtpDevicePropertyCode.BatteryLevel, 0, UInt8(100), UInt8(0)) ] self.dev = MtpDevice(self.dev_info, properties, self.logger) self.dev.add_storage(self.storage) self.dev.set_fuzzer(app.fuzzer) self.api = MtpApi(self.dev) # OS String descriptor # self.add_string_with_id(50, 'MTP'.encode('utf-16') + b'\x00\x00') self.add_string_with_id(0xee, 'MSFT100'.encode('utf-16') + b'\x00\x00') def handle_ep1_data_available(self, data): resps = self.api.handle_payload(data) if resps: for resp in resps: self.send_on_endpoint(2, resp) self.usb_function_supported()
class USBMtpInterface(USBInterface): name = 'MtpInterface' def __init__(self, app, phy): if not mtpdeviceloaded: raise Exception('You cannot use USBMtp until you install pymtpdevice') # TODO: un-hardcode string index (last arg before 'verbose') super(USBMtpInterface, self).__init__( app=app, phy=phy, interface_number=0, interface_alternate=0, interface_class=USBClass.VendorSpecific, interface_subclass=0xff, interface_protocol=0, interface_string_index=0, endpoints=[ USBEndpoint( app=app, phy=phy, number=1, direction=USBEndpoint.direction_out, transfer_type=USBEndpoint.transfer_type_bulk, sync_type=USBEndpoint.sync_type_none, usage_type=USBEndpoint.usage_type_data, max_packet_size=64, interval=0, handler=self.handle_ep1_data_available ), USBEndpoint( app=app, phy=phy, number=2, direction=USBEndpoint.direction_in, transfer_type=USBEndpoint.transfer_type_bulk, sync_type=USBEndpoint.sync_type_none, usage_type=USBEndpoint.usage_type_data, max_packet_size=64, interval=0, handler=None ), USBEndpoint( app=app, phy=phy, number=3, direction=USBEndpoint.direction_in, transfer_type=USBEndpoint.transfer_type_interrupt, sync_type=USBEndpoint.sync_type_none, usage_type=USBEndpoint.usage_type_data, max_packet_size=64, interval=32, handler=None ), ], ) self.object = MtpObject.from_fs_recursive('mtp_fs') # self.object = MtpObject.from_fs_recursive('mtp_fs/eits.mp3') self.storage_info = MtpStorageInfo( st_type=1, fs_type=2, access=0, max_cap=150000, free_bytes=0, free_objs=0, desc='MyStorage', vol_id='Python MTP Device Stack', ) self.storage = MtpStorage(self.storage_info) self.storage.add_object(self.object) self.dev_info = MtpDeviceInfo( std_version=0x0064, mtp_vendor_ext_id=0x00000006, mtp_version=0x0064, mtp_extensions='microsoft.com: 1.0;', functional_mode=0x0000, capture_formats=[], playback_formats=[], manufacturer='UMAP2', model='Role', device_version='1.2', serial_number='3031323334353637', ) properties = [ MtpDeviceProperty(MtpDevicePropertyCode.MTP_DeviceFriendlyName, 0, MStr('UmapMtpDevice'), MStr('')), MtpDeviceProperty(MtpDevicePropertyCode.BatteryLevel, 0, UInt8(100), UInt8(0)) ] self.dev = MtpDevice(self.dev_info, properties, self.logger) self.dev.add_storage(self.storage) self.dev.set_fuzzer(app.fuzzer) self.api = MtpApi(self.dev) # OS String descriptor # self.add_string_with_id(50, 'MTP'.encode('utf-16') + b'\x00\x00') self.add_string_with_id(0xee, 'MSFT100'.encode('utf-16') + b'\x00\x00') def handle_ep1_data_available(self, data): resps = self.api.handle_payload(data) if resps: for resp in resps: self.send_on_endpoint(2, resp)
class MtpApiTest(BaseTestCase): ''' Currently, all tests here are with buffers, as the API of MtpApi ''' def setUp(self): super(MtpApiTest, self).setUp() self.object = MtpObject.from_fs_recursive('.') self.storage_info = MtpStorageInfo( st_type=0, fs_type=0, access=0, max_cap=150000, free_bytes=0, free_objs=0, desc='MyStorage', vol_id='Python MTP Device Stack', ) self.storage = MtpStorage(self.storage_info) self.storage.add_object(self.object) self.dev_info = MtpDeviceInfo( std_version=0x0102, mtp_vendor_ext_id=0x03040506, mtp_version=0x0708, mtp_extensions='Some Extension', functional_mode=0x0000, capture_formats=[], playback_formats=[], manufacturer='BinyaminSharet', model='Role', device_version='1.2.3', serial_number='0123456789abcdef', ) properties = [ MtpDeviceProperty(MtpDevicePropertyCode.BatteryLevel, 0, UInt8(50), UInt8(0)) ] self.dev = MtpDevice(self.dev_info, properties) self.dev.add_storage(self.storage) self.api = MtpApi(self.dev) def testApiOpenSession(self): command = pack('<IHHII', 0x10, ContainerTypes.Command, OperationDataCodes.OpenSession, 1, 1) excepted_response = pack('<IHHI', 0xc, ContainerTypes.Response, ResponseCodes.OK, 1) resps = self.api.handle_payload(command) self.assertEqual(len(resps), 1) self.assertEqual(resps[0], excepted_response) def testApiGetDeviceInfo(self): command = pack('<IHHI', 0x0c, ContainerTypes.Command, OperationDataCodes.GetDeviceInfo, 1) excepted_response = pack('<IHHI', 0xc, ContainerTypes.Response, ResponseCodes.OK, 1) resps = self.api.handle_payload(command) self.assertEqual(len(resps), 2) self.assertEqual(resps[1], excepted_response) def testApiUnsupportedOperation(self): command = pack('<IHHI', 0xc, ContainerTypes.Command, 0, 1) excepted_response = pack('<IHHI', 0xc, ContainerTypes.Response, ResponseCodes.OPERATION_NOT_SUPPORTED, 1) resps = self.api.handle_payload(command) self.assertEqual(len(resps), 1) self.assertEqual(resps[0], excepted_response) def testApiSendObjectOperation(self): obj_data = b'1234' # open session self.testApiOpenSession() # send object info send_obj_info_cmd = pack('<IHHII', 0x10, ContainerTypes.Command, OperationDataCodes.SendObjectInfo, 1, self.storage.get_uid()) send_obj_info_cmd_resp = self.api.handle_payload(send_obj_info_cmd) self.assertEqual(send_obj_info_cmd_resp, []) obj_info_dataset = unhexlify( '0100010001380000040000000000000000000000000000000000000000000000000000000000060000000000000000000000000011770061006c006c00700061007000650072005f0031002e006a007000650067000000000000' ) send_obj_info_data = pack( '<IHHI', len(obj_info_dataset) + 0xc, ContainerTypes.Data, OperationDataCodes.SendObjectInfo, 1) + obj_info_dataset send_obj_info_data_resp = self.api.handle_payload(send_obj_info_data) self.assertEqual(len(send_obj_info_data_resp), 1) response_status = unpack('<H', send_obj_info_data_resp[0][6:8])[0] self.assertEqual(response_status, ResponseCodes.OK) # send object send_obj_cmd = pack('<IHHI', 0xc, ContainerTypes.Command, OperationDataCodes.SendObject, 2) send_obj_cmd_resp = self.api.handle_payload(send_obj_cmd) self.assertEqual(send_obj_cmd_resp, []) send_obj_data = pack('<IHHI', len(obj_data) + 0xc, ContainerTypes.Data, OperationDataCodes.SendObject, 2) + obj_data send_obj_data_resp = self.api.handle_payload(send_obj_data) self.assertEqual(len(send_obj_data_resp), 1) response_status = unpack('<H', send_obj_info_data_resp[0][6:8])[0] self.assertEqual(response_status, ResponseCodes.OK) # read object info # read object ? def testApiLongSendObjectOperation(self): obj_data = b'1234' # open session self.testApiOpenSession() # send object info send_obj_info_cmd = pack('<IHHII', 0x10, ContainerTypes.Command, OperationDataCodes.SendObjectInfo, 1, self.storage.get_uid()) send_obj_info_cmd_resp = self.api.handle_payload(send_obj_info_cmd) self.assertEqual(send_obj_info_cmd_resp, []) obj_info_dataset = unhexlify( '0100010001380000040000000000000000000000000000000000000000000000000000000000060000000000000000000000000011770061006c006c00700061007000650072005f0031002e006a007000650067000000000000' ) send_obj_info_data = pack( '<IHHI', len(obj_info_dataset) + 0xc, ContainerTypes.Data, OperationDataCodes.SendObjectInfo, 1) + obj_info_dataset send_obj_info_data_resp = self.api.handle_payload(send_obj_info_data) self.assertEqual(len(send_obj_info_data_resp), 1) response_status = unpack('<H', send_obj_info_data_resp[0][6:8])[0] self.assertEqual(response_status, ResponseCodes.OK) # send object send_obj_cmd = pack('<IHHI', 0xc, ContainerTypes.Command, OperationDataCodes.SendObject, 2) send_obj_cmd_resp = self.api.handle_payload(send_obj_cmd) self.assertEqual(send_obj_cmd_resp, []) send_obj_data = pack('<IHHI', len(obj_data) + 0xc, ContainerTypes.Data, OperationDataCodes.SendObject, 2) + obj_data[:2] send_obj_data_resp = self.api.handle_payload(send_obj_data) self.assertEqual(send_obj_data_resp, []) send_obj_data = obj_data[2:3] send_obj_data_resp = self.api.handle_payload(send_obj_data) self.assertEqual(send_obj_data_resp, []) send_obj_data = obj_data[3:4] send_obj_data_resp = self.api.handle_payload(send_obj_data) self.assertEqual(len(send_obj_data_resp), 1) response_status = unpack('<H', send_obj_info_data_resp[0][6:8])[0] self.assertEqual(response_status, ResponseCodes.OK)