def _get_string_descriptor(device, index): request_type = usb_core.RequestType(direction='in', type_='standard', recipient='device').u8 byte_buffer = bytearray(STRING_LENGTH_MAX) buffer_type = c_uint8 * STRING_LENGTH_MAX buffer = buffer_type.from_buffer(byte_buffer) # determine default language rv = _lib.libusb_control_transfer(device, request_type, usb_core.Request.GET_DESCRIPTOR, (DescriptorType.STRING << 8), 0, buffer, STRING_LENGTH_MAX, 1000) if rv < 0: raise RuntimeError('control_transfer could not get language: %d' % (rv, )) langid = int(byte_buffer[2]) | (int(byte_buffer[3]) << 8) rv = _lib.libusb_control_transfer( device, request_type, usb_core.Request.GET_DESCRIPTOR, (DescriptorType.STRING << 8) | (index & 0xff), langid, buffer, STRING_LENGTH_MAX, 1000) if rv < 0: raise RuntimeError( 'control transfer could not get string descriptor: %d' % (rv, )) buffer_len = min(rv, byte_buffer[0]) # byte 0 is length, byte 1 is string identifier return byte_buffer[2:buffer_len].decode('UTF-16-LE')
def _finish(self, command, do_wait=True): buffer = None cbk_fn, setup_packet, _ = command length_transferred = c_ulong() rc = WinUsb_GetOverlappedResult(self._winusb, self._overlapped.ptr, byref(length_transferred), do_wait) if rc == 0: # failed (any value other than 0 is success) rc = kernel32.GetLastError() if rc not in [ kernel32.ERROR_IO_INCOMPLETE, kernel32.ERROR_IO_PENDING ]: kernel32.ResetEvent(self._event) log.warning('ControlTransferAsync._finish result: %s', kernel32.get_error_str(rc)) else: kernel32.ResetEvent(self._event) rc = 0 pkt = usb_core.RequestType(value=setup_packet.request_type) duration = time.time() - self._time_start if pkt.direction == 'in' and setup_packet.length: log.debug( 'ControlTransferAsync._finish duration=%.6f s, length: %s, %s', duration, setup_packet.length, length_transferred.value) buffer = bytes( self._overlapped.data[:length_transferred.value]) else: log.debug('ControlTransferAsync._finish duration=%.6f s', duration) response = usb_core.ControlTransferResponse(setup_packet, rc, buffer) cbk_fn(response)
def _issue(self): if not self._commands: return True cbk_fn, setup_packet, buffer = self._commands[0] pkt = usb_core.RequestType(value=setup_packet.request_type) self._overlapped.reset() if pkt.direction == 'out': if setup_packet.length > 0: log.debug('ControlTransferAsync._issue buffer type: %s', type(buffer)) self._overlapped.data[:setup_packet.length] = np.frombuffer( buffer, dtype=np.uint8) result = WinUsb_ControlTransfer(self._winusb, setup_packet, self._overlapped.b, setup_packet.length, None, self._overlapped.ptr) result = sanitize_boolean_return_code(result) self._time_start = time.time() if result != kernel32.ERROR_IO_PENDING: if self.stop_code is None: self.stop_code = DeviceEvent.COMMUNICATION_ERROR log.warning('ControlTransferAsync._issue %s', kernel32.get_error_str(result)) response = usb_core.ControlTransferResponse( setup_packet, result, None) cbk_fn(response) return False return True
def control_transfer_in(self, cbk_fn, recipient, type_, request, value, index, length) -> ControlTransferResponse: if cbk_fn is None: run_until_done = RunUntilDone(1.0, 'control_transfer_in') self.control_transfer_in(run_until_done.cbk_fn, recipient, type_, request, value, index, length) while not run_until_done.is_done(): self.process(0.01) return run_until_done.value_args0 request_type = usb_core.RequestType(direction='in', type_=type_, recipient=recipient).u8 setup_packet = usb_core.SetupPacket(request_type, request, value, index, length) return self._control_transfer.pend(cbk_fn, setup_packet, None)
def control_transfer_out(self, cbk_fn, recipient, type_, request, value=0, index=0, data=None): if cbk_fn is None: run_until_done = RunUntilDone(1.0, 'control_transfer_out') self.control_transfer_out(run_until_done.cbk_fn, recipient, type_, request, value, index, data) while not run_until_done.is_done(): self.process(0.01) return run_until_done.value_args0 request_type = usb_core.RequestType(direction='out', type_=type_, recipient=recipient).u8 length = 0 if data is None else len(data) setup_packet = usb_core.SetupPacket(request_type, request, value, index, length) return self._control_transfer.pend(cbk_fn, setup_packet, data)
def _finish(self, command, transfer): buffer = None rc = transfer.transfer[0].status cbk_fn, setup_packet, _ = command pkt = usb_core.RequestType(value=setup_packet.request_type) duration = time.time() - self._time_start if rc == TransferStatus.NO_DEVICE: log.warning('device_removed') if self.stop_code is None: self.stop_code = DeviceEvent.COMMUNICATION_ERROR if pkt.direction == 'out': log.debug('ControlTransferAsync._finish rc=%d, duration=%.6f s', rc, duration) else: actual_length = transfer.transfer[0].actual_length log.debug('ControlTransferAsync._finish rc=%d, duration=%.6f s, length: %s, %s', rc, duration, setup_packet.length, actual_length) buffer = bytes(transfer.buffer[8:(actual_length+8)]) response = usb_core.ControlTransferResponse(setup_packet, rc, buffer) cbk_fn(response)