def bulk_read(self, size, timeout=None): start = time.time() data = self.ep_in.read(size, timeout) end = time.time() data_size = len(data) if not data_size == size: _log.warn( "bulk_read: WRONG SIZE: 0x{:x} bytes instead of 0x{:x}".format( data_size, size)) _log.debug('\n' + hexdump(data)) raise CanonError( "unexpected data length ({} instead of {})".format( len(data), size)) _log.info("bulk_read got {} (0x{:x}) b in {:.6f} sec".format( len(data), len(data), end - start)) _log.debug("\n" + hexdump(data)) return data
def __repr__(self): if self.is_rc: name = (commands.lookup_rc(self.payload[0x00]) or '-RC 0x{:x}-'.format(self.payload[0x00])) else: name = commands.lookup(self.cmd1, self.cmd2, self.cmd3) or '-unknown-' name += ' ' + hexdump( self.payload[:0x10], with_ascii=False, with_offset=False) return "<CMD 0x{:02x} 0x{:02x} 0x{:03x} (0x{:02x}) (0x{:03x}) {}>".format( self.cmd1, self.cmd2, self.cmd3, len(self.payload), len(self.response), name)
def control_write(self, wValue, data='', timeout=None): # bRequest is 0x4 if length of data is >1, 0x0c otherwise (length >1 ? 0x04 : 0x0C) bRequest = 0x04 if len(data) > 1 else 0x0c _log.info( "control_write (rt: 0x{:x}, req: 0x{:x}, wValue: 0x{:x}) 0x{:x} bytes" .format(0x40, bRequest, wValue, len(data))) _log.debug("\n" + hexdump(data)) # bmRequestType is 0xC0 during read and 0x40 during write. i = self.device.ctrl_transfer(0x40, bRequest, wValue=wValue, wIndex=0, data_or_wLength=data, timeout=timeout) if i != len(data): raise CanonError("control write was incomplete") return i
def control_read(self, wValue, data_length=0, timeout=None): """Read from the control pipe. ``bRequest`` is 0x4 if length of data is >1, 0x0c otherwise (length >1 ? 0x04 : 0x0C) ``bmRequestType`` is 0xC0 during read and 0x40 during write. """ # bRequest = 0x04 if data_length > 1 else 0x0c _log.info( "control_read (req: 0x{:x} wValue: 0x{:x}) reading 0x{:x} bytes". format(bRequest, wValue, data_length)) response = self.device.ctrl_transfer(0xc0, bRequest, wValue=wValue, wIndex=0, data_or_wLength=data_length, timeout=timeout) if len(response) != data_length: raise CanonError("incorrect response length form camera") _log.debug('\n' + hexdump(response)) return response
return all( (is_transfer_bulk(data), is_direction_in(data), is_urb_complete(data))) def get_commands(fname): cmds = [] r = reader(fname) cmd = None for data in r: if is_cmd_start_packet(data): cmd = CanonUSBCommand.from_out_packet(data[0x40:]) cmds.append(cmd) if is_cmd_response_packet(data): cmd.response.extend(data[0x40:]) return cmds if __name__ == '__main__': import sys fname = '/home/kiril/Desktop/G3/win_bootstrap.pcap' if len(sys.argv) > 1: fname = sys.argv[1] cmds = get_commands(fname) for i, c in enumerate(cmds): print "{:04d} {}".format(i, c) print " payload:" print hexdump(c.payload) print " response:" print hexdump(c.response[0x50:]) print
class CanonUSB(object): """USB Link to the camera. """ def __init__(self, device): self.max_chunk_size = MAX_CHUNK_SIZE self.device = device self.device.default_timeout = 500 self.iface = iface = device[0][0, 0] # Other models may have different endpoint addresses self.ep_in = usb.util.find_descriptor(iface, bEndpointAddress=0x81) self.ep_out = usb.util.find_descriptor(iface, bEndpointAddress=0x02) self.ep_int = usb.util.find_descriptor(iface, bEndpointAddress=0x83) self._cmd_serial = 0 self._poller = None @contextmanager def timeout_ctx(self, new): old = self.device.default_timeout self.device.default_timeout = new _log.info("timeout_ctx: {} ms -> {} ms".format(old, new)) now = time.time() try: yield finally: _log.info("timeout_ctx: {} ms <- {} ms; back in {:.3f} ms".format( old, new, (time.time() - now) * 1000)) self.device.default_timeout = old def start_poller(self, size=None, timeout=None): if self._poller and self._poller.isAlive(): raise CanonError("Poller already started.") self._poller = InterruptPoller(self, size, timeout=timeout) self._poller.start() def stop_poller(self): if not self._poller: raise CanonError("There's no poller to stop.") if self._poller.isAlive(): self._poller.stop() self._poller = None @property def is_polling(self): return bool(self._poller and self._poller.isAlive()) @property def poller(self): return self._poller @contextmanager def poller_ctx(self, size=None, timeout=None): if self.is_polling: _log.warn("poller_ctx: -> entered while poller was active!") yield self._poller _log.warn("poller_ctx: <- pretending this isn't real") else: started = time.time() _log.info("poller_ctx: -> ({}, {})".format(size, timeout)) self.start_poller(size, timeout) yield self._poller if self.is_polling: self.stop_poller() _log.info("poller_ctx: <- back in {:.3} ms".format( (time.time() - started) * 1000)) def control_read(self, wValue, data_length=0, timeout=None): """Read from the control pipe. ``bRequest`` is 0x4 if length of data is >1, 0x0c otherwise (length >1 ? 0x04 : 0x0C) ``bmRequestType`` is 0xC0 during read and 0x40 during write. """ # bRequest = 0x04 if data_length > 1 else 0x0c _log.info( "control_read (req: 0x{:x} wValue: 0x{:x}) reading 0x{:x} bytes". format(bRequest, wValue, data_length)) response = self.device.ctrl_transfer(0xc0, bRequest, wValue=wValue, wIndex=0, data_or_wLength=data_length, timeout=timeout) if len(response) != data_length: raise CanonError("incorrect response length form camera") _log.debug('\n' + hexdump(response)) return response def control_write(self, wValue, data='', timeout=None): # bRequest is 0x4 if length of data is >1, 0x0c otherwise (length >1 ? 0x04 : 0x0C) bRequest = 0x04 if len(data) > 1 else 0x0c _log.info( "control_write (rt: 0x{:x}, req: 0x{:x}, wValue: 0x{:x}) 0x{:x} bytes" .format(0x40, bRequest, wValue, len(data))) _log.debug("\n" + hexdump(data)) # bmRequestType is 0xC0 during read and 0x40 during write. i = self.device.ctrl_transfer(0x40, bRequest, wValue=wValue, wIndex=0, data_or_wLength=data, timeout=timeout) if i != len(data): raise CanonError("control write was incomplete") return i def bulk_read(self, size, timeout=None): start = time.time() data = self.ep_in.read(size, timeout) end = time.time() data_size = len(data) if not data_size == size: _log.warn( "bulk_read: WRONG SIZE: 0x{:x} bytes instead of 0x{:x}".format( data_size, size)) _log.debug('\n' + hexdump(data)) raise CanonError( "unexpected data length ({} instead of {})".format( len(data), size)) _log.info("bulk_read got {} (0x{:x}) b in {:.6f} sec".format( len(data), len(data), end - start)) _log.debug("\n" + hexdump(data)) return data def interrupt_read(self, size, timeout=100, ignore_timeouts=False): try: data = self.ep_int.read(size, timeout) except USBError, e: if ignore_timeouts and e.errno == 110: return array('B') raise if data is not None and len(data): dlen = len(data) _log.info("interrupt_read: got 0x{:x} bytes".format(dlen)) _log.debug("\n" + hexdump(data)) return data return array('B')