def OPEN_SESSION(self, p): if self.session_id is not None: raise MTPError('SESSION_ALREADY_OPEN', (self.session_id, )) else: self.session_id = p.p1 logger.info('Session opened.') return (self.session_id, )
def receivedata(self, p): if self.session_id is None: raise MTPError('SESSION_NOT_OPEN') else: bio = io.BytesIO() outdata(self.outep, p.code, p.tx_id, bio) return fn(self, p, bytes(bio.getbuffer()))
def GET_OBJECT_HANDLES(self, p): if p.p2 != 0: raise MTPError('SPECIFICATION_BY_FORMAT_UNSUPPORTED') else: data = DataFormats['AUINT32'].build(list(self.sm.handles(p.p1, p.p3))) logger.debug(' '.join(str(x) for x in ('Data:', *DataFormats['AUINT32'].parse(data)))) return (io.BytesIO(data), ())
def senddata(self, p): if self.session_id is None: raise MTPError('SESSION_NOT_OPEN') else: try: (data, params) = fn(self, p) except MTPError as e: indata(self.inep, p.code, p.tx_id, io.BytesIO(b'')) raise e else: indata(self.inep, p.code, p.tx_id, data) return params
def outdata(outep, code, tx_id, f): buf = outep.read() mtpdata = MTPData.parse(buf) length = mtpdata.length - 12 if length == 0: return while length >= outep.maxpkt: # TODO: this should be connection max packet size rather than 512 buf = outep.read() f.write(buf) if len(buf) != outep.maxpkt: raise MTPError('INCOMPLETE_TRANSFER') length -= outep.maxpkt if length >= 0: # geq because we need to send null sentinal packet iff len(data) is a multiple of 512 buf = outep.read() if len(buf) != length: raise MTPError('INCOMPLETE_TRANSFER') f.write(buf) if mtpdata.code != code: raise MTPError('INVALID_DATASET') if mtpdata.tx_id != tx_id: raise MTPError('INVALID_TRANSACTION_ID')
def SEND_OBJECT(self, p): if self.object_info is None: raise MTPError('NO_VALID_OBJECT_INFO') (parent, info, handle) = self.object_info if (info.format == 'ASSOCIATION' and info.association_type == 'GENERIC_FOLDER') or info.compressed_size == 0: f = open('/dev/null', 'wb') else: p = parent.path() / info.filename f = p.open('wb') parent.add_child(p, handle) self.object_info = None return (f, ())
def receivefile(self, p): if self.session_id is None: raise MTPError('SESSION_NOT_OPEN') else: try: (dest, params) = fn(self, p) except MTPError as e: outdata(self.outep, p.code, p.tx_id, open('/dev/null', 'wb')) raise e else: outdata(self.outep, p.code, p.tx_id, dest) return params
def check_session(self, *args): if self.session_id is None: raise MTPError('SESSION_NOT_OPEN') else: return fn(self, *args)
def __getitem__(self, name): try: return self.operations[name] except KeyError: raise MTPError('OPERATION_NOT_SUPPORTED')
def GET_NUM_OBJECTS(self, p): if p.p2 != 0: raise MTPError('SPECIFICATION_BY_FORMAT_UNSUPPORTED') else: num = len(self.sm.handles(p.p1, p.p3)) return (num, )
def parse(self, value): if not self.__writable: raise MTPError('ACCESS_DENIED') self.__current = DevicePropertyFormats[self.__code].parse(value)
def truncate(self, offset): raise MTPError( 'INVALID_OBJECT_HANDLE') # TODO: is this the right error?
def __getitem__(self, item): obj = self.hm[item] if obj.storage != self: raise MTPError('INVALID_OBJECT_HANDLE') else: return obj
def __getitem__(self, key): try: return self.stores[key] except KeyError: raise MTPError('STORE_NOT_AVAILABLE')
def handles(self, recurse): raise MTPError('INVALID_PARENT_HANDLE')
def create_or_reserve(self, info): raise MTPError('INVALID_PARENT_HANDLE')
def partial_file(self, offset, length): raise MTPError( 'INVALID_OBJECT_HANDLE') # TODO: is this the right error?
def reset(self, force=False): if not force and not self.__writable: raise MTPError('ACCESS_DENIED') self.__current = self.__default
def __getitem__(self, handle): try: return self.objects[handle] except KeyError: raise MTPError('INVALID_OBJECT_HANDLE')
def __getitem__(self, item): raise MTPError('INVALID_OBJECT_HANDLE')
def __getitem__(self, key): try: return self.__props[key] except KeyError: raise MTPError('DEVICE_PROP_NOT_SUPPORTED')