diff --git a/README.md b/README.md index 2b4e4dd..c402be9 100644 --- a/README.md +++ b/README.md @@ -3,12 +3,12 @@ Python package for Kivy Android USB serial port. -Drivers in roadmap are listed below: +Implemented drivers are listed below: * FTDI serial driver - done and tested with FT230X. * CDC ACM serial driver - done and tested with MCP2200. * CP210x serial driver - done and tested with CP2102. * CH34x serial driver - done and tested with CH340. -* PL2303 serial driver - todo. +* PL2303 serial driver - done and tested with PL2303. Please consider [![Paypal Donate](https://github.com/jacklinquan/images/blob/master/paypal_donate_button_200x80.png)](https://www.paypal.me/jacklinquan) to support me. diff --git a/setup.py b/setup.py index 05620cf..28a8b61 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup setup( name="usbserial4a", - version="0.1.9", + version="0.1.10", description="Python package for Kivy Android USB serial port.", long_description="https://github.com/jacklinquan/usbserial4a", long_description_content_type="text/markdown", diff --git a/usbserial4a/__init__.py b/usbserial4a/__init__.py index 8895bfd..02ed8a8 100644 --- a/usbserial4a/__init__.py +++ b/usbserial4a/__init__.py @@ -9,4 +9,4 @@ Requires: kivy, pyjnius, pyserial, usb4a ''' # Project version -__version__ = '0.1.9' +__version__ = '0.1.10' diff --git a/usbserial4a/pl2303serial4a.py b/usbserial4a/pl2303serial4a.py new file mode 100644 index 0000000..8d91d47 --- /dev/null +++ b/usbserial4a/pl2303serial4a.py @@ -0,0 +1,586 @@ +'''Android USB serial PL2303 driver. + +Classes: +Pl2303Serial(serial.serialutil.SerialBase) +''' + +from struct import pack, unpack +import time +from serial.serialutil import SerialBase, SerialException, to_bytes, \ + portNotOpenError, writeTimeoutError, Timeout +from usb4a import usb + +class Pl2303Serial(SerialBase): + '''PL2303 serial port class. + + Pl2303Serial extends serial.serialutil.SerialBase. + It can be used in a similar way to serial.Serial from pyserial. + ''' + # Default baudrate + DEFAULT_BAUDRATE = 9600 + + USB_RECIP_INTERFACE = 0x01 + + PROLIFIC_VENDOR_READ_REQUEST = 0x01 + PROLIFIC_VENDOR_WRITE_REQUEST = 0x01 + + # 0x21 + PROLIFIC_CTRL_OUT_REQTYPE = usb.UsbConstants.USB_DIR_OUT | \ + usb.UsbConstants.USB_TYPE_CLASS | USB_RECIP_INTERFACE + + # 0xa1 + PROLIFIC_CTRL_IN_REQTYPE = usb.UsbConstants.USB_DIR_IN | \ + usb.UsbConstants.USB_TYPE_CLASS | USB_RECIP_INTERFACE + + # 0x40 + PROLIFIC_VENDOR_OUT_REQTYPE = usb.UsbConstants.USB_DIR_OUT | \ + usb.UsbConstants.USB_TYPE_VENDOR + + # 0xC0 + PROLIFIC_VENDOR_IN_REQTYPE = usb.UsbConstants.USB_DIR_IN | \ + usb.UsbConstants.USB_TYPE_VENDOR + + WRITE_ENDPOINT = 0x02 + READ_ENDPOINT = 0x83 + INTERRUPT_ENDPOINT = 0x81 + + FLUSH_RX_REQUEST = 0x08 + FLUSH_TX_REQUEST = 0x09 + + SET_LINE_REQUEST = 0x20 + SET_CONTROL_REQUEST = 0x22 + + CONTROL_DTR = 0x01 + CONTROL_RTS = 0x02 + + BREAK_REQUEST = 0x23 + BREAK_ON = 0xffff + BREAK_OFF = 0x0000 + + GET_LINE_REQUEST = 0x21 + + STATUS_FLAG_CD = 0x01 + STATUS_FLAG_DSR = 0x02 + STATUS_FLAG_RI = 0x08 + STATUS_FLAG_CTS = 0x80 + + STATUS_BUFFER_SIZE = 10 + STATUS_BYTE_IDX = 8 + + DEVICE_TYPE_HX = 0 + DEVICE_TYPE_0 = 1 + DEVICE_TYPE_1 = 2 + + # Buffer + DEFAULT_READ_BUFFER_SIZE = 16 * 1024 + DEFAULT_WRITE_BUFFER_SIZE = 16 * 1024 + + # Timeout + USB_READ_TIMEOUT_MILLIS = 5000 + USB_WRITE_TIMEOUT_MILLIS = 5000 + + def __init__(self, *args, **kwargs): + self._device = None + self._connection = None + self._interface = None + self._control_endpoint = None + self._read_endpoint = None + self._write_endpoint = None + self._read_buffer = bytearray() + self._device_type = self.DEVICE_TYPE_HX + super(Pl2303Serial, self).__init__(*args, **kwargs) + + def open(self): + '''Open the serial port. + + When the serial port is instantiated, it will try to open automatically. + ''' + self.close() + + device = usb.get_usb_device(self.portstr) + if not device: + raise SerialException("Device not present {}".format(self.portstr)) + + if not usb.has_usb_permission(device): + usb.request_usb_permission(device) + return + + connection = usb.get_usb_manager().openDevice(device) + if not connection: + raise SerialException("Failed to open device!") + + self._device = device + self._connection = connection + + for i in range(self._device.getInterfaceCount()): + if not self._connection.claimInterface( + self._device.getInterface(i), + True + ): + raise SerialException("Could not claim interface {}.".format(i)) + + self._interface = self._device.getInterface( + self._device.getInterfaceCount() - 1 + ) + + for i in range(self._interface.getEndpointCount()): + ep = self._interface.getEndpoint(i) + if ( + (ep.getDirection() == usb.UsbConstants.USB_DIR_IN) \ + and (ep.getType() == usb.UsbConstants.USB_ENDPOINT_XFER_INT) + ): + self._control_endpoint = ep + elif ( + (ep.getDirection() == usb.UsbConstants.USB_DIR_IN) \ + and (ep.getType() == usb.UsbConstants.USB_ENDPOINT_XFER_BULK) + ): + self._read_endpoint = ep + elif ( + (ep.getDirection() == usb.UsbConstants.USB_DIR_OUT) \ + and (ep.getType() == usb.UsbConstants.USB_ENDPOINT_XFER_BULK) + ): + self._write_endpoint = ep + + # Check that all endpoints are good + if None in [ + self._control_endpoint, + self._read_endpoint, + self._write_endpoint + ]: + raise SerialException("Could not establish all endpoints!") + + if self._device.getDeviceClass() == usb.UsbConstants.USB_CLASS_COMM: + self._device_type = self.DEVICE_TYPE_0 + else: + raw_descriptors = self._connection.getRawDescriptors() + max_packet_size_0 = raw_descriptors[7] + if max_packet_size_0 == 64: + self._device_type = self.DEVICE_TYPE_HX + elif ( + self._device.getDeviceClass() == \ + usb.UsbConstants.USB_CLASS_PER_INTERFACE + or self._device.getDeviceClass() == \ + usb.UsbConstants.USB_CLASS_VENDOR_SPEC + ): + self._device_type = self.DEVICE_TYPE_1 + else: + # Unknown device sub type, assume DEVICE_TYPE_HX. + self._device_type = self.DEVICE_TYPE_HX + + self._init_device() + self.is_open = True + self._set_dtr_rts(self._dtr_state, self._rts_state) + self._reconfigure_port() + + def _reconfigure_port(self): + '''Reconfigure serial port parameters.''' + self._set_parameters( + self.baudrate, + self.bytesize, + self.parity, + self.stopbits + ) + + def close(self): + '''Close the serial port.''' + if self._connection: + self._connection.close() + self._connection = None + self.is_open = False + + # - - - - - - - - - - - - - - - - - - - - - - - - + + @property + def in_waiting(self): + '''Return the number of bytes currently in the input buffer. + + Returns: + Length (int): number of data bytes in the input buffer. + ''' + # Read from serial port hardware and put the data into read buffer. + self._read_buffer.extend(self._read()) + return len(self._read_buffer) + + @property + def out_waiting(self): + '''Return the number of bytes currently in the output buffer. + + Always return 0. + ''' + return 0 + + def read(self, size=1): + '''Read data from the serial port. + + Parameters: + size (int): the number of data bytes to read. + + Returns: + read (bytes): data bytes read from the serial port. + ''' + read = bytearray() + timeout = Timeout(self.timeout) + + # If there is enough data in the buffer, do not bother to read. + if len(self._read_buffer) < size: + # Keep reading until there is enough data or timeout. + while self.in_waiting < size: + if timeout.expired(): + break + + # Get data from read buffer. + read = self._read_buffer[:size] + self._read_buffer = self._read_buffer[size:] + + return bytes(read) + + def write(self, data): + '''Write data to the serial port. + + Parameters: + data (bytearray): data written to the serial port. + + Returns: + wrote (int): the number of data bytes written. + ''' + if not self.is_open: + return None + offset = 0 + timeout = int( + self._write_timeout * 1000 if self._write_timeout \ + else self.USB_WRITE_TIMEOUT_MILLIS + ) + wrote = 0 + while offset < len(data): + data_length = min( + len(data) - offset, + self.DEFAULT_WRITE_BUFFER_SIZE + ) + buf = data[offset:offset + data_length] + i = self._connection.bulkTransfer( + self._write_endpoint, + buf, + data_length, + timeout + ) + if i <= 0: + raise SerialException("Failed to write {}: {}".format(buf, i)) + offset += data_length + wrote += i + return wrote + + def flush(self): + '''Simply wait some time to allow all data to be written.''' + pass + + def reset_input_buffer(self): + '''Clear input buffer, discarding all that is in the buffer.''' + if not self.is_open: + raise portNotOpenError + self._purgeHwBuffers(True, False) + + def reset_output_buffer(self): + '''\ + Clear output buffer, aborting the current output and discarding all + that is in the buffer. + ''' + if not self.is_open: + raise portNotOpenError + self._purgeHwBuffers(False, True) + + def send_break(self, duration=0.25): + '''Send break condition. + + Parameters: + duration (float): break time in seconds. + ''' + if not self.is_open: + raise portNotOpenError + self._set_break(True) + time.sleep(duration) + self._set_break(False) + + def _update_break_state(self): + '''Send break condition.''' + self._set_break(self._break_state) + + def _update_rts_state(self): + '''Set terminal status line: Request To Send.''' + self._set_rts(self._rts_state) + + def _update_dtr_state(self): + '''Set terminal status line: Data Terminal Ready.''' + self._set_dtr(self._dtr_state) + + @property + def cts(self): + '''Read terminal status line: Clear To Send.''' + status = self._poll_modem_status() + return bool(status & self.STATUS_FLAG_CTS) + + @property + def dsr(self): + '''Read terminal status line: Data Set Ready.''' + status = self._poll_modem_status() + return bool(status & self.STATUS_FLAG_DSR) + + @property + def ri(self): + '''Read terminal status line: Ring Indicator.''' + status = self._poll_modem_status() + return bool(status & self.STATUS_FLAG_RI) + + @property + def cd(self): + '''Read terminal status line: Carrier Detect.''' + status = self._poll_modem_status() + return bool(status & self.STATUS_FLAG_CD) + + # - - - - - - - - - - - - - - - - - - - - - - - - + + def _ctrl_out(self, request, value, index, buf=None): + '''USB control transfer out. + + This function does the USB configuration job. + ''' + result = self._connection.controlTransfer( + self.PROLIFIC_CTRL_OUT_REQTYPE, + request, + value, + index, + buf, + (0 if buf is None else len(buf)), + self.USB_WRITE_TIMEOUT_MILLIS + ) + + return result + + def _ctrl_in(self, request, value, index, buf=None): + '''USB control transfer in. + + Request for a control message from the device. + ''' + result = self._connection.controlTransfer( + self.PROLIFIC_CTRL_IN_REQTYPE, + request, + value, + index, + buf, + (0 if buf is None else len(buf)), + self.USB_READ_TIMEOUT_MILLIS + ) + + return result + + def _vendor_out(self, value, index, buf=None): + '''USB vendor transfer out. + + This function does the USB configuration job. + ''' + result = self._connection.controlTransfer( + self.PROLIFIC_VENDOR_OUT_REQTYPE, + self.PROLIFIC_VENDOR_WRITE_REQUEST, + value, + index, + buf, + (0 if buf is None else len(buf)), + self.USB_WRITE_TIMEOUT_MILLIS + ) + + return result + + def _vendor_in(self, value, index, buf=None): + '''USB vendor transfer in. + + Request for a control message from the device. + ''' + result = self._connection.controlTransfer( + self.PROLIFIC_VENDOR_IN_REQTYPE, + self.PROLIFIC_VENDOR_READ_REQUEST, + value, + index, + buf, + (0 if buf is None else len(buf)), + self.USB_READ_TIMEOUT_MILLIS + ) + + return result + + def _init_device(self): + buf = bytearray(1) + + self._vendor_in(0x8484, 0, buf) + self._vendor_out(0x0404, 0) + self._vendor_in(0x8484, 0, buf) + self._vendor_in(0x8383, 0, buf) + self._vendor_in(0x8484, 0, buf) + self._vendor_out(0x0404, 1) + self._vendor_in(0x8484, 0, buf) + self._vendor_in(0x8383, 0, buf) + self._vendor_out(0, 1) + self._vendor_out(1, 0) + self._vendor_out( + 2, + (0x44 if self._device_type == self.DEVICE_TYPE_HX else 0x24) + ) + + def _set_break(self, break_): + '''Start or stop a break exception event on the serial line. + + Parameters: + break_ (bool): either start or stop break event. + ''' + result = self._ctrl_out( + self.BREAK_REQUEST, + self.BREAK_ON if break_ else self.BREAK_OFF, + 0 + ) + if result != 0: + raise SerialException('Unable to set break state!') + + def _set_dtr(self, state): + '''Set dtr line. + + Parameters: + state (bool): new DTR logical level. + ''' + self._set_dtr_rts(state, self._rts_state) + + def _set_rts(self, state): + '''Set rts line. + + Parameters: + state (bool): new RTS logical level. + ''' + self._set_dtr_rts(self._dtr_state, state) + + def _set_dtr_rts(self, dtr, rts): + '''Set dtr and rts lines at once. + + Parameters: + dtr (bool): new DTR logical level. + rts (bool): new RTS logical level. + ''' + value = 0 + if dtr: + value |= self.CONTROL_DTR + if rts: + value |= self.CONTROL_RTS + + result = self._ctrl_out( + self.SET_CONTROL_REQUEST, + value, + 0 + ) + if result != 0: + raise SerialException('Unable to set DTR/RTS lines!') + + def _purgeHwBuffers(self, purgeReadBuffers, purgeWriteBuffers): + '''Set serial port parameters. + + Parameters: + purgeReadBuffers (bool): need to purge read buffer or not. + purgeWriteBuffers (bool): need to purge write buffer or not. + Returns: + result (bool): successful or not. + ''' + if purgeReadBuffers: + self._vendor_out(self.FLUSH_RX_REQUEST, 0) + + if purgeWriteBuffers: + self._vendor_out(self.FLUSH_TX_REQUEST, 0) + + return True + + def _read(self): + '''Hardware dependent read function. + + Returns: + read (bytes): data bytes read from the serial port. + ''' + if not self.is_open: + raise portNotOpenError + if not self._read_endpoint: + raise SerialException("Read endpoint does not exist!") + + # Get raw data from hardware. + buf = bytearray(self.DEFAULT_READ_BUFFER_SIZE) + totalBytesRead = self._connection.bulkTransfer( + self._read_endpoint, + buf, + self.DEFAULT_READ_BUFFER_SIZE, + self.USB_READ_TIMEOUT_MILLIS + ) + if totalBytesRead < 0: + # Read timeout. Set totalBytesRead to 0. + totalBytesRead = 0 + + read = buf[:totalBytesRead] + return bytes(read) + + def _set_parameters(self, baudrate, databits, parity, stopbits): + '''Set serial port parameters. + + Parameters: + baudrate (int): the new baudrate for the UART(eg 9600). + databits (int): number of bits in data(5, 6, 7 or 8). + parity (str): 'N', 'E', 'O', 'M' or 'S'. + stopbits (float): number of stop bits(1, 1.5, 2). + ''' + buf = bytearray(7) + + buf[0] = baudrate & 0xff + buf[1] = (baudrate >> 8) & 0xff + buf[2] = (baudrate >> 16) & 0xff + buf[3] = (baudrate >> 24) & 0xff + + if stopbits == 1: + buf[4] = 0 + elif stopbits == 1.5: + buf[4] = 1 + elif stopbits == 2: + buf[4] = 2 + else: + buf[4] = 0 + + if parity == 'N': + buf[5] = 0 + elif parity == 'O': + buf[5] = 1 + elif parity == 'E': + buf[5] = 2 + elif parity == 'M': + buf[5] = 3 + elif parity == 'S': + buf[5] = 4 + else: + buf[5] = 0 + + buf[6] = databits & 0xff + + self._ctrl_out(self.SET_LINE_REQUEST, 0, 0, buf) + + def _poll_modem_status(self): + '''Poll modem status information. + + This function allows the retrieve the one status byte of the + device, useful in UART mode. + + Returns: + status (int): modem status, as a proprietary bitfield + ''' + buf = bytearray(self.STATUS_BUFFER_SIZE) + read_bytes_count = self._connection.bulkTransfer( + self._control_endpoint, + buf, + len(buf), + self.USB_READ_TIMEOUT_MILLIS + ) + + if read_bytes_count != self.STATUS_BUFFER_SIZE: + raise SerialException('Unable to get modem status!') + + status = buf[self.STATUS_BYTE_IDX] & 0xff + return status + + \ No newline at end of file diff --git a/usbserial4a/serial4a.py b/usbserial4a/serial4a.py index 185b6f0..b45ff30 100644 --- a/usbserial4a/serial4a.py +++ b/usbserial4a/serial4a.py @@ -5,421 +5,14 @@ get_serial_port ''' from usb4a import usb +from .vidpid4a import FTDI_VENDOR_ID, SILABS_VENDOR_ID, QINHENG_VENDOR_ID, \ + PROLIFIC_VENDOR_ID, FTDI_VID_PID_GROUP, SILABS_VID_PID_GROUP, \ + QINHENG_VID_PID_GROUP, PROLIFIC_VID_PID_GROUP from .ftdiserial4a import FtdiSerial from .cdcacmserial4a import CdcAcmSerial from .cp210xserial4a import Cp210xSerial from .ch34xserial4a import Ch34xSerial -#from .pl2303serial4a import Pl2303Serial - -FTDI_VENDOR_ID = 0x0403 -SILABS_VENDOR_ID = 0x10C4 -QINHENG_VENDOR_ID = 0x1A86 -PROLIFIC_VENDOR_ID = 0x067B - -FTDI_VID_PID_GROUP = [ - (0x03eb, 0x2109), - (0x0456, 0xf000), - (0x0456, 0xf001), - (0x04d8, 0x000a), - (0x0584, 0xb020), - (0x0647, 0x0100), - (0x06CE, 0x8311), - (0x06D3, 0x0284), - (0x0856, 0xac01), - (0x0856, 0xac02), - (0x0856, 0xac03), - (0x0856, 0xac11), - (0x0856, 0xac12), - (0x0856, 0xac16), - (0x0856, 0xac17), - (0x0856, 0xac18), - (0x0856, 0xac19), - (0x0856, 0xac25), - (0x0856, 0xac26), - (0x0856, 0xac27), - (0x0856, 0xac33), - (0x0856, 0xac34), - (0x0856, 0xac49), - (0x0856, 0xac50), - (0x0856, 0xba02), - (0x093c, 0x0601), - (0x093c, 0x0701), - (0x0acd, 0x0300), - (0x0b39, 0x0103), - (0x0b39, 0x0421), - (0x0c26, 0x0004), - (0x0c26, 0x0018), - (0x0c26, 0x0009), - (0x0c26, 0x000a), - (0x0c26, 0x000b), - (0x0c26, 0x000c), - (0x0c26, 0x000d), - (0x0c26, 0x0010), - (0x0c26, 0x0011), - (0x0c26, 0x0012), - (0x0c26, 0x0013), - (0x0c33, 0x0010), - (0x0c52, 0x2101), - (0x0c52, 0x2101), - (0x0c52, 0x2102), - (0x0c52, 0x2103), - (0x0c52, 0x2104), - (0x0c52, 0x9020), - (0x0c52, 0x2211), - (0x0c52, 0x2221), - (0x0c52, 0x2212), - (0x0c52, 0x2222), - (0x0c52, 0x2213), - (0x0c52, 0x2223), - (0x0c52, 0x2411), - (0x0c52, 0x2421), - (0x0c52, 0x2431), - (0x0c52, 0x2441), - (0x0c52, 0x2412), - (0x0c52, 0x2422), - (0x0c52, 0x2432), - (0x0c52, 0x2442), - (0x0c52, 0x2413), - (0x0c52, 0x2423), - (0x0c52, 0x2433), - (0x0c52, 0x2443), - (0x0c52, 0x2811), - (0x0c52, 0x2821), - (0x0c52, 0x2831), - (0x0c52, 0x2841), - (0x0c52, 0x2851), - (0x0c52, 0x2861), - (0x0c52, 0x2871), - (0x0c52, 0x2881), - (0x0c52, 0x2812), - (0x0c52, 0x2822), - (0x0c52, 0x2832), - (0x0c52, 0x2842), - (0x0c52, 0x2852), - (0x0c52, 0x2862), - (0x0c52, 0x2872), - (0x0c52, 0x2882), - (0x0c52, 0x2813), - (0x0c52, 0x2823), - (0x0c52, 0x2833), - (0x0c52, 0x2843), - (0x0c52, 0x2853), - (0x0c52, 0x2863), - (0x0c52, 0x2873), - (0x0c52, 0x2883), - (0x0c52, 0xa02a), - (0x0c52, 0xa02b), - (0x0c52, 0xa02c), - (0x0c52, 0xa02d), - (0x0c6c, 0x04b2), - (0x0c7d, 0x0005), - (0x0d3a, 0x0300), - (0x0d46, 0x2020), - (0x0d46, 0x2021), - (0x0dcd, 0x0001), - (0x0f94, 0x0001), - (0x0f94, 0x0005), - (0x0fd8, 0x0001), - (0x103e, 0x03e8), - (0x104d, 0x3000), - (0x104d, 0x3002), - (0x104d, 0x3006), - (0x1209, 0x1002), - (0x1209, 0x1006), - (0x128d, 0x0001), - (0x1342, 0x0202), - (0x1457, 0x5118), - (0x15ba, 0x0003), - (0x15ba, 0x002b), - (0x1781, 0x0c30), - (0x2100, 0x9001), - (0x2100, 0x9e50), - (0x2100, 0x9e51), - (0x2100, 0x9e52), - (0x2100, 0x9e53), - (0x2100, 0x9e54), - (0x2100, 0x9e55), - (0x2100, 0x9e56), - (0x2100, 0x9e57), - (0x2100, 0x9e58), - (0x2100, 0x9e59), - (0x2100, 0x9e5a), - (0x2100, 0x9e5b), - (0x2100, 0x9e5c), - (0x2100, 0x9e5d), - (0x2100, 0x9e5e), - (0x2100, 0x9e5f), - (0x2100, 0x9e60), - (0x2100, 0x9e61), - (0x2100, 0x9e62), - (0x2100, 0x9e63), - (0x2100, 0x9e64), - (0x2100, 0x9e65), - (0x2100, 0x9e65), - (0x2100, 0x9e66), - (0x2100, 0x9e67), - (0x2100, 0x9e68), - (0x2100, 0x9e69), - (0x2100, 0x9e6a), - (0x1a72, 0x1000), - (0x1a72, 0x1001), - (0x1a72, 0x1002), - (0x1a72, 0x1005), - (0x1a72, 0x1007), - (0x1a72, 0x1008), - (0x1a72, 0x1009), - (0x1a72, 0x100d), - (0x1a72, 0x100e), - (0x1a72, 0x100f), - (0x1a72, 0x1011), - (0x1a72, 0x1012), - (0x1a72, 0x1013), - (0x1a72, 0x1014), - (0x1a72, 0x1015), - (0x1a72, 0x1016), - (0x165c, 0x0002), - (0x1a79, 0x6001), - (0x1b3d, 0x0100), - (0x1b3d, 0x0101), - (0x1b3d, 0x0102), - (0x1b3d, 0x0103), - (0x1b3d, 0x0104), - (0x1b3d, 0x0105), - (0x1b3d, 0x0106), - (0x1b3d, 0x0107), - (0x1b3d, 0x0108), - (0x1b3d, 0x0109), - (0x1b3d, 0x010a), - (0x1b3d, 0x010b), - (0x1b3d, 0x010c), - (0x1b3d, 0x010d), - (0x1b3d, 0x010e), - (0x1b3d, 0x010f), - (0x1b3d, 0x0110), - (0x1b3d, 0x0111), - (0x1b3d, 0x0112), - (0x1b3d, 0x0113), - (0x1b3d, 0x0114), - (0x1b3d, 0x0115), - (0x1b3d, 0x0116), - (0x1b3d, 0x0117), - (0x1b3d, 0x0118), - (0x1b3d, 0x0119), - (0x1b3d, 0x011a), - (0x1b3d, 0x011b), - (0x1b3d, 0x011c), - (0x1b3d, 0x011d), - (0x1b3d, 0x011e), - (0x1b3d, 0x011f), - (0x1b3d, 0x0120), - (0x1b3d, 0x0121), - (0x1b3d, 0x0122), - (0x1b3d, 0x0123), - (0x1b3d, 0x0124), - (0x1b3d, 0x0125), - (0x1b3d, 0x0126), - (0x1b3d, 0x0127), - (0x1b3d, 0x0128), - (0x1b3d, 0x0129), - (0x1b3d, 0x012a), - (0x1b3d, 0x012b), - (0x1b3d, 0x012c), - (0x1b3d, 0x012e), - (0x1b3d, 0x012f), - (0x1b3d, 0x0130), - (0x1b91, 0x0064), - (0x1bc9, 0x6001), - (0x1c0c, 0x0102), - (0x1cf1, 0x0001), - (0x1cf1, 0x0041), - (0x0483, 0x3746), - (0x0483, 0x3747), - (0x5050, 0x0100), - (0x5050, 0x0101), - (0x5050, 0x0102), - (0x5050, 0x0103), - (0x5050, 0x0104), - (0x5050, 0x0105), - (0x5050, 0x0106), - (0x5050, 0x0107), - (0x5050, 0x0300), - (0x5050, 0x0301), - (0x5050, 0x0400), - (0x5050, 0x0500), - (0x5050, 0x0700), - (0x5050, 0x0800), - (0x5050, 0x0900), - (0x5050, 0x0a00), - (0x5050, 0x0b00), - (0x5050, 0x0c00), - (0x5050, 0x0d00), - (0x5050, 0x0e00), - (0x5050, 0x0f00), - (0x5050, 0x1000), - (0x5050, 0x8000), - (0x5050, 0x8001), - (0x5050, 0x8002), - (0x5050, 0x8003), - (0x5050, 0x8004), - (0x5050, 0x8005), - (0x9e88, 0x9e8f), - (0xdeee, 0x0300), - (0xdeee, 0x02ff), - (0xdeee, 0x0302), - (0xdeee, 0x0303), - (0x05d1, 0x1001), - (0x05d1, 0x1002), - (0x05d1, 0x1003), - (0x05d1, 0x1004), - (0x05d1, 0x1011), - (0x05d1, 0x1013), - (0x05d1, 0x2001), - (0x05d1, 0x2002), - (0x05d1, 0x2003), - (0x05d1, 0x2011), - (0x05d1, 0x2012), - (0x05d1, 0x2021), - (0x05d1, 0x2022), - (0x05d1, 0x2023), - (0x05d1, 0x2024), - (0x05d1, 0x3011), - (0x05d1, 0x3012), - (0x05d1, 0x5001), - (0x05d1, 0x6001), - (0x05d1, 0x7001), - (0x05d1, 0x8001), - (0x05d1, 0x8002), - (0x05d1, 0x8003), - (0x05d1, 0x8004), - (0x05d1, 0x9001), - (0x05d1, 0x9002), - (0x05d1, 0x9003), - (0x05d1, 0x9004), - (0x05d1, 0x9005), - (0x05d1, 0x9006), - (0x05d1, 0x9007), - (0x05d1, 0x9008) -] -SILABS_VID_PID_GROUP = [ - (0x045B, 0x0053), - (0x0471, 0x066A), - (0x0489, 0xE000), - (0x0489, 0xE003), - (0x0745, 0x1000), - (0x0846, 0x1100), - (0x08e6, 0x5501), - (0x08FD, 0x000A), - (0x0BED, 0x1100), - (0x0BED, 0x1101), - (0x0FCF, 0x1003), - (0x0FCF, 0x1004), - (0x0FCF, 0x1006), - (0x0FDE, 0xCA05), - (0x10A6, 0xAA26), - (0x10AB, 0x10C5), - (0x10B5, 0xAC70), - (0x2405, 0x0003), - (0x10C5, 0xEA61), - (0x10CE, 0xEA6A), - (0x13AD, 0x9999), - (0x1555, 0x0004), - (0x166A, 0x0201), - (0x166A, 0x0301), - (0x166A, 0x0303), - (0x166A, 0x0304), - (0x166A, 0x0305), - (0x166A, 0x0401), - (0x166A, 0x0101), - (0x16D6, 0x0001), - (0x16DC, 0x0010), - (0x16DC, 0x0011), - (0x16DC, 0x0012), - (0x16DC, 0x0015), - (0x17A8, 0x0001), - (0x17A8, 0x0005), - (0x17F4, 0xAAAA), - (0x1843, 0x0200), - (0x18EF, 0xE00F), - (0x1ADB, 0x0001), - (0x1BE3, 0x07A6), - (0x1E29, 0x0102), - (0x1E29, 0x0501), - (0x1FB9, 0x0100), - (0x1FB9, 0x0200), - (0x1FB9, 0x0201), - (0x1FB9, 0x0202), - (0x1FB9, 0x0203), - (0x1FB9, 0x0300), - (0x1FB9, 0x0301), - (0x1FB9, 0x0302), - (0x1FB9, 0x0303), - (0x1FB9, 0x0400), - (0x1FB9, 0x0401), - (0x1FB9, 0x0402), - (0x1FB9, 0x0403), - (0x1FB9, 0x0404), - (0x1FB9, 0x0600), - (0x1FB9, 0x0601), - (0x1FB9, 0x0602), - (0x1FB9, 0x0700), - (0x1FB9, 0x0701), - (0x3195, 0xF190), - (0x3195, 0xF280), - (0x3195, 0xF281), - (0x413C, 0x9500), - (0x1908, 0x2311) -] -QINHENG_VID_PID_GROUP = [ - (0x4348, 0x5523) -] -PROLIFIC_VID_PID_GROUP = [ - (0x04a5, 0x4027), - (0x0557, 0x2008), - (0x0547, 0x2008), - (0x04bb, 0x0a03), - (0x04bb, 0x0a0e), - (0x056e, 0x5003), - (0x056e, 0x5004), - (0x0eba, 0x1080), - (0x0eba, 0x2080), - (0x0df7, 0x0620), - (0x0584, 0xb000), - (0x2478, 0x2008), - (0x1453, 0x4026), - (0x0731, 0x0528), - (0x6189, 0x2068), - (0x11f7, 0x02df), - (0x04e8, 0x8001), - (0x11f5, 0x0001), - (0x11f5, 0x0003), - (0x11f5, 0x0004), - (0x11f5, 0x0005), - (0x0745, 0x0001), - (0x078b, 0x1234), - (0x10b5, 0xac70), - (0x079b, 0x0027), - (0x0413, 0x2101), - (0x0e55, 0x110b), - (0x0731, 0x2003), - (0x050d, 0x0257), - (0x058f, 0x9720), - (0x11f6, 0x2001), - (0x07aa, 0x002a), - (0x05ad, 0x0fba), - (0x5372, 0x2303), - (0x03f0, 0x0b39), - (0x03f0, 0x3139), - (0x03f0, 0x3239), - (0x03f0, 0x3524), - (0x04b8, 0x0521), - (0x04b8, 0x0522), - (0x054c, 0x0437), - (0x11ad, 0x0001), - (0x0b63, 0x6530), - (0x0b8c, 0x2303), - (0x110a, 0x1150), - (0x0557, 0x2008) -] +from .pl2303serial4a import Pl2303Serial def get_serial_port(device_name, *args, **kwargs): '''Get a USB serial port from the system. @@ -456,8 +49,7 @@ def get_serial_port(device_name, *args, **kwargs): device_vid == PROLIFIC_VENDOR_ID \ or (device_vid, device_pid) in PROLIFIC_VID_PID_GROUP ): - #return Pl2303Serial(device_name, *args, **kwargs) - raise Exception('PL2303 serial driver is not implemented yet!') + return Pl2303Serial(device_name, *args, **kwargs) else: return CdcAcmSerial(device_name, *args, **kwargs) else: diff --git a/usbserial4a/vidpid4a.py b/usbserial4a/vidpid4a.py new file mode 100644 index 0000000..b8ed78d --- /dev/null +++ b/usbserial4a/vidpid4a.py @@ -0,0 +1,423 @@ +'''Android USB host serial vendor ids and product ids. + +FTDI_VENDOR_ID +SILABS_VENDOR_ID +QINHENG_VENDOR_ID +PROLIFIC_VENDOR_ID + +FTDI_VID_PID_GROUP +SILABS_VID_PID_GROUP +QINHENG_VID_PID_GROUP +PROLIFIC_VID_PID_GROUP +''' + +FTDI_VENDOR_ID = 0x0403 +SILABS_VENDOR_ID = 0x10C4 +QINHENG_VENDOR_ID = 0x1A86 +PROLIFIC_VENDOR_ID = 0x067B + +FTDI_VID_PID_GROUP = [ + (0x03eb, 0x2109), + (0x0456, 0xf000), + (0x0456, 0xf001), + (0x04d8, 0x000a), + (0x0584, 0xb020), + (0x0647, 0x0100), + (0x06CE, 0x8311), + (0x06D3, 0x0284), + (0x0856, 0xac01), + (0x0856, 0xac02), + (0x0856, 0xac03), + (0x0856, 0xac11), + (0x0856, 0xac12), + (0x0856, 0xac16), + (0x0856, 0xac17), + (0x0856, 0xac18), + (0x0856, 0xac19), + (0x0856, 0xac25), + (0x0856, 0xac26), + (0x0856, 0xac27), + (0x0856, 0xac33), + (0x0856, 0xac34), + (0x0856, 0xac49), + (0x0856, 0xac50), + (0x0856, 0xba02), + (0x093c, 0x0601), + (0x093c, 0x0701), + (0x0acd, 0x0300), + (0x0b39, 0x0103), + (0x0b39, 0x0421), + (0x0c26, 0x0004), + (0x0c26, 0x0018), + (0x0c26, 0x0009), + (0x0c26, 0x000a), + (0x0c26, 0x000b), + (0x0c26, 0x000c), + (0x0c26, 0x000d), + (0x0c26, 0x0010), + (0x0c26, 0x0011), + (0x0c26, 0x0012), + (0x0c26, 0x0013), + (0x0c33, 0x0010), + (0x0c52, 0x2101), + (0x0c52, 0x2101), + (0x0c52, 0x2102), + (0x0c52, 0x2103), + (0x0c52, 0x2104), + (0x0c52, 0x9020), + (0x0c52, 0x2211), + (0x0c52, 0x2221), + (0x0c52, 0x2212), + (0x0c52, 0x2222), + (0x0c52, 0x2213), + (0x0c52, 0x2223), + (0x0c52, 0x2411), + (0x0c52, 0x2421), + (0x0c52, 0x2431), + (0x0c52, 0x2441), + (0x0c52, 0x2412), + (0x0c52, 0x2422), + (0x0c52, 0x2432), + (0x0c52, 0x2442), + (0x0c52, 0x2413), + (0x0c52, 0x2423), + (0x0c52, 0x2433), + (0x0c52, 0x2443), + (0x0c52, 0x2811), + (0x0c52, 0x2821), + (0x0c52, 0x2831), + (0x0c52, 0x2841), + (0x0c52, 0x2851), + (0x0c52, 0x2861), + (0x0c52, 0x2871), + (0x0c52, 0x2881), + (0x0c52, 0x2812), + (0x0c52, 0x2822), + (0x0c52, 0x2832), + (0x0c52, 0x2842), + (0x0c52, 0x2852), + (0x0c52, 0x2862), + (0x0c52, 0x2872), + (0x0c52, 0x2882), + (0x0c52, 0x2813), + (0x0c52, 0x2823), + (0x0c52, 0x2833), + (0x0c52, 0x2843), + (0x0c52, 0x2853), + (0x0c52, 0x2863), + (0x0c52, 0x2873), + (0x0c52, 0x2883), + (0x0c52, 0xa02a), + (0x0c52, 0xa02b), + (0x0c52, 0xa02c), + (0x0c52, 0xa02d), + (0x0c6c, 0x04b2), + (0x0c7d, 0x0005), + (0x0d3a, 0x0300), + (0x0d46, 0x2020), + (0x0d46, 0x2021), + (0x0dcd, 0x0001), + (0x0f94, 0x0001), + (0x0f94, 0x0005), + (0x0fd8, 0x0001), + (0x103e, 0x03e8), + (0x104d, 0x3000), + (0x104d, 0x3002), + (0x104d, 0x3006), + (0x1209, 0x1002), + (0x1209, 0x1006), + (0x128d, 0x0001), + (0x1342, 0x0202), + (0x1457, 0x5118), + (0x15ba, 0x0003), + (0x15ba, 0x002b), + (0x1781, 0x0c30), + (0x2100, 0x9001), + (0x2100, 0x9e50), + (0x2100, 0x9e51), + (0x2100, 0x9e52), + (0x2100, 0x9e53), + (0x2100, 0x9e54), + (0x2100, 0x9e55), + (0x2100, 0x9e56), + (0x2100, 0x9e57), + (0x2100, 0x9e58), + (0x2100, 0x9e59), + (0x2100, 0x9e5a), + (0x2100, 0x9e5b), + (0x2100, 0x9e5c), + (0x2100, 0x9e5d), + (0x2100, 0x9e5e), + (0x2100, 0x9e5f), + (0x2100, 0x9e60), + (0x2100, 0x9e61), + (0x2100, 0x9e62), + (0x2100, 0x9e63), + (0x2100, 0x9e64), + (0x2100, 0x9e65), + (0x2100, 0x9e65), + (0x2100, 0x9e66), + (0x2100, 0x9e67), + (0x2100, 0x9e68), + (0x2100, 0x9e69), + (0x2100, 0x9e6a), + (0x1a72, 0x1000), + (0x1a72, 0x1001), + (0x1a72, 0x1002), + (0x1a72, 0x1005), + (0x1a72, 0x1007), + (0x1a72, 0x1008), + (0x1a72, 0x1009), + (0x1a72, 0x100d), + (0x1a72, 0x100e), + (0x1a72, 0x100f), + (0x1a72, 0x1011), + (0x1a72, 0x1012), + (0x1a72, 0x1013), + (0x1a72, 0x1014), + (0x1a72, 0x1015), + (0x1a72, 0x1016), + (0x165c, 0x0002), + (0x1a79, 0x6001), + (0x1b3d, 0x0100), + (0x1b3d, 0x0101), + (0x1b3d, 0x0102), + (0x1b3d, 0x0103), + (0x1b3d, 0x0104), + (0x1b3d, 0x0105), + (0x1b3d, 0x0106), + (0x1b3d, 0x0107), + (0x1b3d, 0x0108), + (0x1b3d, 0x0109), + (0x1b3d, 0x010a), + (0x1b3d, 0x010b), + (0x1b3d, 0x010c), + (0x1b3d, 0x010d), + (0x1b3d, 0x010e), + (0x1b3d, 0x010f), + (0x1b3d, 0x0110), + (0x1b3d, 0x0111), + (0x1b3d, 0x0112), + (0x1b3d, 0x0113), + (0x1b3d, 0x0114), + (0x1b3d, 0x0115), + (0x1b3d, 0x0116), + (0x1b3d, 0x0117), + (0x1b3d, 0x0118), + (0x1b3d, 0x0119), + (0x1b3d, 0x011a), + (0x1b3d, 0x011b), + (0x1b3d, 0x011c), + (0x1b3d, 0x011d), + (0x1b3d, 0x011e), + (0x1b3d, 0x011f), + (0x1b3d, 0x0120), + (0x1b3d, 0x0121), + (0x1b3d, 0x0122), + (0x1b3d, 0x0123), + (0x1b3d, 0x0124), + (0x1b3d, 0x0125), + (0x1b3d, 0x0126), + (0x1b3d, 0x0127), + (0x1b3d, 0x0128), + (0x1b3d, 0x0129), + (0x1b3d, 0x012a), + (0x1b3d, 0x012b), + (0x1b3d, 0x012c), + (0x1b3d, 0x012e), + (0x1b3d, 0x012f), + (0x1b3d, 0x0130), + (0x1b91, 0x0064), + (0x1bc9, 0x6001), + (0x1c0c, 0x0102), + (0x1cf1, 0x0001), + (0x1cf1, 0x0041), + (0x0483, 0x3746), + (0x0483, 0x3747), + (0x5050, 0x0100), + (0x5050, 0x0101), + (0x5050, 0x0102), + (0x5050, 0x0103), + (0x5050, 0x0104), + (0x5050, 0x0105), + (0x5050, 0x0106), + (0x5050, 0x0107), + (0x5050, 0x0300), + (0x5050, 0x0301), + (0x5050, 0x0400), + (0x5050, 0x0500), + (0x5050, 0x0700), + (0x5050, 0x0800), + (0x5050, 0x0900), + (0x5050, 0x0a00), + (0x5050, 0x0b00), + (0x5050, 0x0c00), + (0x5050, 0x0d00), + (0x5050, 0x0e00), + (0x5050, 0x0f00), + (0x5050, 0x1000), + (0x5050, 0x8000), + (0x5050, 0x8001), + (0x5050, 0x8002), + (0x5050, 0x8003), + (0x5050, 0x8004), + (0x5050, 0x8005), + (0x9e88, 0x9e8f), + (0xdeee, 0x0300), + (0xdeee, 0x02ff), + (0xdeee, 0x0302), + (0xdeee, 0x0303), + (0x05d1, 0x1001), + (0x05d1, 0x1002), + (0x05d1, 0x1003), + (0x05d1, 0x1004), + (0x05d1, 0x1011), + (0x05d1, 0x1013), + (0x05d1, 0x2001), + (0x05d1, 0x2002), + (0x05d1, 0x2003), + (0x05d1, 0x2011), + (0x05d1, 0x2012), + (0x05d1, 0x2021), + (0x05d1, 0x2022), + (0x05d1, 0x2023), + (0x05d1, 0x2024), + (0x05d1, 0x3011), + (0x05d1, 0x3012), + (0x05d1, 0x5001), + (0x05d1, 0x6001), + (0x05d1, 0x7001), + (0x05d1, 0x8001), + (0x05d1, 0x8002), + (0x05d1, 0x8003), + (0x05d1, 0x8004), + (0x05d1, 0x9001), + (0x05d1, 0x9002), + (0x05d1, 0x9003), + (0x05d1, 0x9004), + (0x05d1, 0x9005), + (0x05d1, 0x9006), + (0x05d1, 0x9007), + (0x05d1, 0x9008) +] +SILABS_VID_PID_GROUP = [ + (0x045B, 0x0053), + (0x0471, 0x066A), + (0x0489, 0xE000), + (0x0489, 0xE003), + (0x0745, 0x1000), + (0x0846, 0x1100), + (0x08e6, 0x5501), + (0x08FD, 0x000A), + (0x0BED, 0x1100), + (0x0BED, 0x1101), + (0x0FCF, 0x1003), + (0x0FCF, 0x1004), + (0x0FCF, 0x1006), + (0x0FDE, 0xCA05), + (0x10A6, 0xAA26), + (0x10AB, 0x10C5), + (0x10B5, 0xAC70), + (0x2405, 0x0003), + (0x10C5, 0xEA61), + (0x10CE, 0xEA6A), + (0x13AD, 0x9999), + (0x1555, 0x0004), + (0x166A, 0x0201), + (0x166A, 0x0301), + (0x166A, 0x0303), + (0x166A, 0x0304), + (0x166A, 0x0305), + (0x166A, 0x0401), + (0x166A, 0x0101), + (0x16D6, 0x0001), + (0x16DC, 0x0010), + (0x16DC, 0x0011), + (0x16DC, 0x0012), + (0x16DC, 0x0015), + (0x17A8, 0x0001), + (0x17A8, 0x0005), + (0x17F4, 0xAAAA), + (0x1843, 0x0200), + (0x18EF, 0xE00F), + (0x1ADB, 0x0001), + (0x1BE3, 0x07A6), + (0x1E29, 0x0102), + (0x1E29, 0x0501), + (0x1FB9, 0x0100), + (0x1FB9, 0x0200), + (0x1FB9, 0x0201), + (0x1FB9, 0x0202), + (0x1FB9, 0x0203), + (0x1FB9, 0x0300), + (0x1FB9, 0x0301), + (0x1FB9, 0x0302), + (0x1FB9, 0x0303), + (0x1FB9, 0x0400), + (0x1FB9, 0x0401), + (0x1FB9, 0x0402), + (0x1FB9, 0x0403), + (0x1FB9, 0x0404), + (0x1FB9, 0x0600), + (0x1FB9, 0x0601), + (0x1FB9, 0x0602), + (0x1FB9, 0x0700), + (0x1FB9, 0x0701), + (0x3195, 0xF190), + (0x3195, 0xF280), + (0x3195, 0xF281), + (0x413C, 0x9500), + (0x1908, 0x2311) +] +QINHENG_VID_PID_GROUP = [ + (0x4348, 0x5523) +] +PROLIFIC_VID_PID_GROUP = [ + (0x04a5, 0x4027), + (0x0557, 0x2008), + (0x0547, 0x2008), + (0x04bb, 0x0a03), + (0x04bb, 0x0a0e), + (0x056e, 0x5003), + (0x056e, 0x5004), + (0x0eba, 0x1080), + (0x0eba, 0x2080), + (0x0df7, 0x0620), + (0x0584, 0xb000), + (0x2478, 0x2008), + (0x1453, 0x4026), + (0x0731, 0x0528), + (0x6189, 0x2068), + (0x11f7, 0x02df), + (0x04e8, 0x8001), + (0x11f5, 0x0001), + (0x11f5, 0x0003), + (0x11f5, 0x0004), + (0x11f5, 0x0005), + (0x0745, 0x0001), + (0x078b, 0x1234), + (0x10b5, 0xac70), + (0x079b, 0x0027), + (0x0413, 0x2101), + (0x0e55, 0x110b), + (0x0731, 0x2003), + (0x050d, 0x0257), + (0x058f, 0x9720), + (0x11f6, 0x2001), + (0x07aa, 0x002a), + (0x05ad, 0x0fba), + (0x5372, 0x2303), + (0x03f0, 0x0b39), + (0x03f0, 0x3139), + (0x03f0, 0x3239), + (0x03f0, 0x3524), + (0x04b8, 0x0521), + (0x04b8, 0x0522), + (0x054c, 0x0437), + (0x11ad, 0x0001), + (0x0b63, 0x6530), + (0x0b8c, 0x2303), + (0x110a, 0x1150), + (0x0557, 0x2008) +] +