Flow control code added for FTDI driver.
pull/6/head
Quan Lin 2019-01-23 15:36:41 +11:00
rodzic c0f45b73f2
commit 066901d5bb
4 zmienionych plików z 379 dodań i 94 usunięć

Wyświetl plik

@ -90,6 +90,7 @@ class MainApp(App):
self.device_name_list = [] self.device_name_list = []
self.serial_port = None self.serial_port = None
self.read_thread = None self.read_thread = None
self.port_thread_lock = threading.Lock()
super(MainApp, self).__init__(*args, **kwargs) super(MainApp, self).__init__(*args, **kwargs)
def build(self): def build(self):
@ -97,7 +98,8 @@ class MainApp(App):
def on_stop(self): def on_stop(self):
if self.serial_port: if self.serial_port:
self.serial_port.close() with self.port_thread_lock:
self.serial_port.close()
def on_btn_scan_release(self): def on_btn_scan_release(self):
self.uiDict['box_list'].clear_widgets() self.uiDict['box_list'].clear_widgets()
@ -106,7 +108,8 @@ class MainApp(App):
if platform == 'android': if platform == 'android':
usb_device_list = usb.get_usb_device_list() usb_device_list = usb.get_usb_device_list()
self.device_name_list = [ self.device_name_list = [
device.getDeviceName() for device in usb_device_list] device.getDeviceName() for device in usb_device_list
]
else: else:
usb_device_list = list_ports.comports() usb_device_list = list_ports.comports()
self.device_name_list = [port.device for port in usb_device_list] self.device_name_list = [port.device for port in usb_device_list]
@ -124,7 +127,8 @@ class MainApp(App):
device = usb.get_usb_device(device_name) device = usb.get_usb_device(device_name)
if not device: if not device:
raise SerialException( raise SerialException(
"Device {} not present!".format(device_name)) "Device {} not present!".format(device_name)
)
if not usb.has_usb_permission(device): if not usb.has_usb_permission(device):
usb.request_usb_permission(device) usb.request_usb_permission(device)
return return
@ -134,7 +138,8 @@ class MainApp(App):
8, 8,
'N', 'N',
1, 1,
timeout=1) timeout=1
)
else: else:
self.serial_port = Serial( self.serial_port = Serial(
device_name, device_name,
@ -142,7 +147,8 @@ class MainApp(App):
8, 8,
'N', 'N',
1, 1,
timeout=1) timeout=1
)
if self.serial_port.is_open and not self.read_thread: if self.serial_port.is_open and not self.read_thread:
self.read_thread = threading.Thread(target = self.read_msg_thread) self.read_thread = threading.Thread(target = self.read_msg_thread)
@ -156,24 +162,30 @@ class MainApp(App):
data = bytes(self.uiDict['txtInput_write'].text + '\n') data = bytes(self.uiDict['txtInput_write'].text + '\n')
else: else:
data = bytes( data = bytes(
(self.uiDict['txtInput_write'].text + '\n'), 'utf8') (self.uiDict['txtInput_write'].text + '\n'),
'utf8'
)
self.serial_port.write(data) self.serial_port.write(data)
self.uiDict['txtInput_read'].text += '[Sent]{}\n'.format( self.uiDict['txtInput_read'].text += '[Sent]{}\n'.format(
self.uiDict['txtInput_write'].text) self.uiDict['txtInput_write'].text
)
self.uiDict['txtInput_write'].text = '' self.uiDict['txtInput_write'].text = ''
def read_msg_thread(self): def read_msg_thread(self):
while True: while True:
if not self.serial_port.is_open:
break
try: try:
received_msg = self.serial_port.read() with self.port_thread_lock:
if not self.serial_port.is_open:
break
received_msg = self.serial_port.read(
self.serial_port.in_waiting
)
if received_msg: if received_msg:
msg = bytes(received_msg).decode('utf8') msg = bytes(received_msg).decode('utf8')
self.display_received_msg(msg) self.display_received_msg(msg)
except Exception as ex: except Exception as ex:
raise ex raise ex
@mainthread @mainthread
def display_received_msg(self, msg): def display_received_msg(self, msg):
self.uiDict['txtInput_read'].text += msg self.uiDict['txtInput_read'].text += msg

Wyświetl plik

@ -2,7 +2,7 @@ from setuptools import setup
setup( setup(
name="usbserial4a", name="usbserial4a",
version="0.1.6", version="0.1.7",
description="Python package for Kivy Android USB serial port.", description="Python package for Kivy Android USB serial port.",
long_description="https://github.com/jacklinquan/usbserial4a", long_description="https://github.com/jacklinquan/usbserial4a",
long_description_content_type="text/markdown", long_description_content_type="text/markdown",

Wyświetl plik

@ -9,4 +9,4 @@ Requires: kivy, pyjnius, pyserial, usb4a
''' '''
# Project version # Project version
__version__ = '0.1.6' __version__ = '0.1.7'

Wyświetl plik

@ -4,6 +4,8 @@ Classes:
FtdiSerial(serial.serialutil.SerialBase) FtdiSerial(serial.serialutil.SerialBase)
''' '''
from struct import unpack
import time
from serial.serialutil import SerialBase, SerialException, to_bytes, \ from serial.serialutil import SerialBase, SerialException, to_bytes, \
portNotOpenError, writeTimeoutError, Timeout portNotOpenError, writeTimeoutError, Timeout
from usb4a import usb from usb4a import usb
@ -14,6 +16,19 @@ class FtdiSerial(SerialBase):
FtdiSerial extends serial.serialutil.SerialBase. FtdiSerial extends serial.serialutil.SerialBase.
It can be used in a similar way to serial.Serial from pyserial. It can be used in a similar way to serial.Serial from pyserial.
''' '''
# Modem status
MODEM_CTS = (1 << 4) # Clear to send
MODEM_DSR = (1 << 5) # Data set ready
MODEM_RI = (1 << 6) # Ring indicator
MODEM_RLSD = (1 << 7) # Carrier detect
MODEM_DR = (1 << 8) # Data ready
MODEM_OE = (1 << 9) # Overrun error
MODEM_PE = (1 << 10) # Parity error
MODEM_FE = (1 << 11) # Framing error
MODEM_BI = (1 << 12) # Break interrupt
MODEM_THRE = (1 << 13) # Transmitter holding register
MODEM_TEMT = (1 << 14) # Transmitter empty
MODEM_RCVE = (1 << 15) # Error in RCVR FIFO
# Requests # Requests
SIO_RESET = 0 # Reset the port SIO_RESET = 0 # Reset the port
@ -52,6 +67,28 @@ class FtdiSerial(SerialBase):
SIO_SET_RTS_HIGH = (SIO_SET_RTS_MASK | (SIO_SET_RTS_MASK << 8)) SIO_SET_RTS_HIGH = (SIO_SET_RTS_MASK | (SIO_SET_RTS_MASK << 8))
SIO_SET_RTS_LOW = (0x0 | (SIO_SET_RTS_MASK << 8)) SIO_SET_RTS_LOW = (0x0 | (SIO_SET_RTS_MASK << 8))
# Break type
BREAK_OFF, BREAK_ON = range(2)
# cts: Clear to send
# dsr: Data set ready
# ri: Ring indicator
# dcd: Data carrier detect
# dr: Data ready
# oe: Overrun error
# pe: Parity error
# fe: Framing error
# bi: Break interrupt
# thre: Transmitter holding register
# temt: Transmitter empty
# err: Error in RCVR FIFO
MODEM_STATUS = [
('', '', '', '', 'cts', 'dsr', 'ri', 'dcd'),
('dr', 'overrun', 'parity', 'framing', 'break', 'thre', 'txe', 'rcvr')
]
ERROR_BITS = (0x00, 0x8E)
# Clocks and baudrates # Clocks and baudrates
BUS_CLOCK_BASE = 6.0E6 # 6 MHz BUS_CLOCK_BASE = 6.0E6 # 6 MHz
BUS_CLOCK_HIGH = 30.0E6 # 30 MHz BUS_CLOCK_HIGH = 30.0E6 # 30 MHz
@ -64,11 +101,13 @@ class FtdiSerial(SerialBase):
FTDI_DEVICE_OUT_REQTYPE = usb.build_usb_control_request_type( FTDI_DEVICE_OUT_REQTYPE = usb.build_usb_control_request_type(
usb.UsbConstants.USB_DIR_OUT, usb.UsbConstants.USB_DIR_OUT,
usb.UsbConstants.USB_TYPE_VENDOR, usb.UsbConstants.USB_TYPE_VENDOR,
usb.USB_RECIPIENT_DEVICE) usb.USB_RECIPIENT_DEVICE
)
FTDI_DEVICE_IN_REQTYPE = usb.build_usb_control_request_type( FTDI_DEVICE_IN_REQTYPE = usb.build_usb_control_request_type(
usb.UsbConstants.USB_DIR_IN, usb.UsbConstants.USB_DIR_IN,
usb.UsbConstants.USB_TYPE_VENDOR, usb.UsbConstants.USB_TYPE_VENDOR,
usb.USB_RECIPIENT_DEVICE) usb.USB_RECIPIENT_DEVICE
)
DEFAULT_READ_BUFFER_SIZE = 1024 DEFAULT_READ_BUFFER_SIZE = 1024
DEFAULT_WRITE_BUFFER_SIZE = 16 * 1024 DEFAULT_WRITE_BUFFER_SIZE = 16 * 1024
@ -88,6 +127,7 @@ class FtdiSerial(SerialBase):
self._control_endpoint = None self._control_endpoint = None
self._read_endpoint = None self._read_endpoint = None
self._write_endpoint = None self._write_endpoint = None
self._lineprop = 0
self._read_buffer = bytearray() self._read_buffer = bytearray()
super(FtdiSerial, self).__init__(*args, **kwargs) super(FtdiSerial, self).__init__(*args, **kwargs)
@ -121,21 +161,28 @@ class FtdiSerial(SerialBase):
self._interface = self._device.getInterface(i) self._interface = self._device.getInterface(i)
if not self._connection.claimInterface( if not self._connection.claimInterface(
self._device.getInterface(i), self._device.getInterface(i),
True): True
):
raise SerialException("Could not claim interface {}.".format(i)) raise SerialException("Could not claim interface {}.".format(i))
self._index = self._interface.getId() + 1 self._index = self._interface.getId() + 1
for i in range(self._interface.getEndpointCount()): for i in range(self._interface.getEndpointCount()):
ep = self._interface.getEndpoint(i) ep = self._interface.getEndpoint(i)
if ((ep.getDirection() == usb.UsbConstants.USB_DIR_IN) and if (
(ep.getType() == usb.UsbConstants.USB_ENDPOINT_XFER_INT)): (ep.getDirection() == usb.UsbConstants.USB_DIR_IN) \
and (ep.getType() == usb.UsbConstants.USB_ENDPOINT_XFER_INT)
):
self._control_endpoint = ep self._control_endpoint = ep
elif ((ep.getDirection() == usb.UsbConstants.USB_DIR_IN) and elif (
(ep.getType() == usb.UsbConstants.USB_ENDPOINT_XFER_BULK)): (ep.getDirection() == usb.UsbConstants.USB_DIR_IN) \
and (ep.getType() == usb.UsbConstants.USB_ENDPOINT_XFER_BULK)
):
self._read_endpoint = ep self._read_endpoint = ep
elif ((ep.getDirection() == usb.UsbConstants.USB_DIR_OUT) and elif (
(ep.getType() == usb.UsbConstants.USB_ENDPOINT_XFER_BULK)): (ep.getDirection() == usb.UsbConstants.USB_DIR_OUT) \
and (ep.getType() == usb.UsbConstants.USB_ENDPOINT_XFER_BULK)
):
self._write_endpoint = ep self._write_endpoint = ep
# Check that all endpoints are good # Check that all endpoints are good
@ -145,6 +192,22 @@ class FtdiSerial(SerialBase):
self.is_open = True self.is_open = True
self._reconfigure_port() self._reconfigure_port()
def _reconfigure_port(self):
'''Reconfigure serial port parameters.'''
self._setParameters(
self.baudrate,
self.bytesize,
self.parity,
self.stopbits
)
if self._rtscts:
self._set_flowctrl('hw')
elif self._xonxoff:
self._set_flowctrl('sw')
else:
self._set_flowctrl('')
def close(self): def close(self):
'''Close the serial port.''' '''Close the serial port.'''
if self._connection: if self._connection:
@ -158,10 +221,13 @@ class FtdiSerial(SerialBase):
result = self._ctrl_transfer_out( result = self._ctrl_transfer_out(
self.SIO_RESET, self.SIO_RESET,
self.SIO_RESET_SIO, self.SIO_RESET_SIO,
0) self._index
)
if result != 0: if result != 0:
raise SerialException("Reset failed: result={}".format(result)) raise SerialException("Reset failed: result={}".format(result))
# - - - - - - - - - - - - - - - - - - - - - - - -
@property @property
def in_waiting(self): def in_waiting(self):
'''Return the number of bytes currently in the input buffer. '''Return the number of bytes currently in the input buffer.
@ -173,6 +239,14 @@ class FtdiSerial(SerialBase):
self._read_buffer.extend(self._read()) self._read_buffer.extend(self._read())
return len(self._read_buffer) 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): def read(self, size=1):
'''Read data from the serial port. '''Read data from the serial port.
@ -212,18 +286,21 @@ class FtdiSerial(SerialBase):
offset = 0 offset = 0
timeout = int( timeout = int(
self._write_timeout * 1000 if self._write_timeout \ self._write_timeout * 1000 if self._write_timeout \
else self.USB_WRITE_TIMEOUT_MILLIS) else self.USB_WRITE_TIMEOUT_MILLIS
)
wrote = 0 wrote = 0
while offset < len(data): while offset < len(data):
data_length = min( data_length = min(
len(data) - offset, len(data) - offset,
self.DEFAULT_WRITE_BUFFER_SIZE) self.DEFAULT_WRITE_BUFFER_SIZE
)
buf = data[offset:offset + data_length] buf = data[offset:offset + data_length]
i = self._connection.bulkTransfer( i = self._connection.bulkTransfer(
self._write_endpoint, self._write_endpoint,
buf, buf,
data_length, data_length,
timeout) timeout
)
if i <= 0: if i <= 0:
raise SerialException("Failed to write {}: {}".format(buf, i)) raise SerialException("Failed to write {}: {}".format(buf, i))
offset += data_length offset += data_length
@ -234,7 +311,151 @@ class FtdiSerial(SerialBase):
'''Simply wait some time to allow all data to be written.''' '''Simply wait some time to allow all data to be written.'''
pass pass
def purgeHwBuffers(self, purgeReadBuffers, purgeWriteBuffers): 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.MODEM_CTS)
@property
def dsr(self):
'''Read terminal status line: Data Set Ready.'''
status = self._poll_modem_status()
return bool(status & self.MODEM_DSR)
@property
def ri(self):
'''Read terminal status line: Ring Indicator.'''
status = self._poll_modem_status()
return bool(status & self.MODEM_RI)
@property
def cd(self):
'''Read terminal status line: Carrier Detect.'''
status = self._poll_modem_status()
return bool(status & self.MODEM_RLSD)
# - - - - - - - - - - - - - - - - - - - - - - - -
def _ctrl_transfer_out(self, request, value, index):
'''USB control transfer out.
This function does the USB configuration job.
'''
return self._connection.controlTransfer(
self.FTDI_DEVICE_OUT_REQTYPE,
request,
value,
index,
None,
0,
self.USB_WRITE_TIMEOUT_MILLIS
)
def _ctrl_transfer_in(self, request, buf, length):
'''USB control transfer in.
Request for a control message from the device.
'''
return self._connection.controlTransfer(
self.FTDI_DEVICE_IN_REQTYPE,
request,
0,
self._index,
buf,
length,
self.USB_READ_TIMEOUT_MILLIS
)
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.
'''
if break_:
value = self._lineprop | (0x01 << 14)
if self._ctrl_transfer_out(self.SIO_SET_DATA, value, self._index):
raise SerialException('Unable to start break sequence')
else:
value = self._lineprop & ~(0x01 << 14)
if self._ctrl_transfer_out(self.SIO_SET_DATA, value, self._index):
raise SerialException('Unable to stop break sequence')
self._lineprop = value
def _set_dtr(self, state):
'''Set dtr line.
Parameters:
state (bool): new DTR logical level.
'''
value = state and self.SIO_SET_DTR_HIGH or self.SIO_SET_DTR_LOW
if self._ctrl_transfer_out(self.SIO_SET_MODEM_CTRL, value, self._index):
raise SerialException('Unable to set DTR line')
def _set_rts(self, state):
'''Set rts line.
Parameters:
state (bool): new RTS logical level.
'''
value = state and self.SIO_SET_RTS_HIGH or self.SIO_SET_RTS_LOW
if self._ctrl_transfer_out(self.SIO_SET_MODEM_CTRL, value, self._index):
raise SerialException('Unable to set RTS line')
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
value |= dtr and self.SIO_SET_DTR_HIGH or self.SIO_SET_DTR_LOW
value |= rts and self.SIO_SET_RTS_HIGH or self.SIO_SET_RTS_LOW
if self._ctrl_transfer_out(self.SIO_SET_FLOW_CTRL, value, self._index):
raise SerialException('Unable to set DTR/RTS lines')
def _purgeHwBuffers(self, purgeReadBuffers, purgeWriteBuffers):
'''Set serial port parameters. '''Set serial port parameters.
Parameters: Parameters:
@ -247,19 +468,22 @@ class FtdiSerial(SerialBase):
result = self._ctrl_transfer_out( result = self._ctrl_transfer_out(
self.SIO_RESET, self.SIO_RESET,
self.SIO_RESET_PURGE_RX, self.SIO_RESET_PURGE_RX,
0) self._index
)
if result != 0: if result != 0:
raise SerialException( raise SerialException(
"Flushing RX failed: result={}".format(result)) "Flushing RX failed: result={}".format(result)
)
if purgeWriteBuffers: if purgeWriteBuffers:
result = self._ctrl_transfer_out( result = self._ctrl_transfer_out(
self.SIO_RESET, self.SIO_RESET,
self.SIO_RESET_PURGE_TX, self.SIO_RESET_PURGE_TX,
0) self._index)
if result != 0: if result != 0:
raise SerialException( raise SerialException(
"Flushing TX failed: result={}".format(result)) "Flushing TX failed: result={}".format(result)
)
return True return True
@ -280,11 +504,14 @@ class FtdiSerial(SerialBase):
self._read_endpoint, self._read_endpoint,
buf, buf,
self.DEFAULT_READ_BUFFER_SIZE, self.DEFAULT_READ_BUFFER_SIZE,
self.USB_READ_TIMEOUT_MILLIS) self.USB_READ_TIMEOUT_MILLIS
)
if totalBytesRead < self.MODEM_STATUS_HEADER_LENGTH: if totalBytesRead < self.MODEM_STATUS_HEADER_LENGTH:
raise SerialException( raise SerialException(
"Expected at least {} bytes".format( "Expected at least {} bytes".format(
self.MODEM_STATUS_HEADER_LENGTH)) self.MODEM_STATUS_HEADER_LENGTH
)
)
# Translate raw data into serial port data. # Translate raw data into serial port data.
read = bytearray() read = bytearray()
@ -292,7 +519,8 @@ class FtdiSerial(SerialBase):
buf, buf,
read, read,
totalBytesRead, totalBytesRead,
self._read_endpoint.getMaxPacketSize()) self._read_endpoint.getMaxPacketSize()
)
return bytes(read) return bytes(read)
@ -315,13 +543,59 @@ class FtdiSerial(SerialBase):
actual, value, index = self._convert_baudrate(baudrate) actual, value, index = self._convert_baudrate(baudrate)
delta = 100*abs(float(actual-baudrate))/baudrate delta = 100*abs(float(actual-baudrate))/baudrate
if delta > self.BAUDRATE_TOLERANCE: if delta > self.BAUDRATE_TOLERANCE:
raise ValueError('Baudrate tolerance exceeded: %.02f%% ' raise ValueError(
'(wanted %d, achievable %d)' % 'Baudrate tolerance exceeded: %.02f%% '
(delta, baudrate, actual)) '(wanted %d, achievable %d)' %
(delta, baudrate, actual)
)
result = self._ctrl_transfer_out(self.SIO_SET_BAUDRATE, value, index) result = self._ctrl_transfer_out(self.SIO_SET_BAUDRATE, value, index)
if result != 0: if result != 0:
raise SerialException('Unable to set baudrate') raise SerialException('Unable to set baudrate.')
def _set_line_property(self, bits, stopbits, parity, break_=0):
'''Set serial port line property.
Parameters:
bits (int): number of bits in data(5, 6, 7 or 8).
stopbits (float): number of stop bits(1, 1.5, 2).
parity (str): 'N', 'E', 'O', 'M' or 'S'.
break_ (int): 0 for break off or 1 for break on.
'''
value = bits & 0x0F
if parity == 'N':
value |= (0x00 << 8)
elif parity == 'O':
value |= (0x01 << 8)
elif parity == 'E':
value |= (0x02 << 8)
elif parity == 'M':
value |= (0x03 << 8)
elif parity == 'S':
value |= (0x04 << 8)
else:
raise ValueError('Unknown parity value: {}'.format(parity))
if stopbits == 1:
value |= (0x00 << 11)
elif stopbits == 1.5:
value |= (0x01 << 11)
elif stopbits == 2:
value |= (0x02 << 11)
else:
raise ValueError("Unknown stopbits value: {}".format(stopbits))
if break_ == self.BREAK_ON:
value |= 0x01 << 14
result = self._ctrl_transfer_out(self.SIO_SET_DATA, value, self._index)
if result != 0:
raise SerialException(
'Setting line property failed: result={}'.format(result)
)
self._lineprop = value
def _setParameters(self, baudrate, databits, parity, stopbits): def _setParameters(self, baudrate, databits, parity, stopbits):
'''Set serial port parameters. '''Set serial port parameters.
@ -333,57 +607,54 @@ class FtdiSerial(SerialBase):
''' '''
self._set_baudrate(baudrate) self._set_baudrate(baudrate)
self._set_line_property(databits, stopbits, parity)
config = databits def _poll_modem_status(self):
'''Poll modem status information.
if parity == 'N': This function allows the retrieve the two status bytes of the
config |= (0x00 << 8) device, useful in UART mode.
elif parity == 'O': FTDI device does not have a so-called USB "interrupt" end-point,
config |= (0x01 << 8) event polling on the UART interface is done through the regular
elif parity == 'E': control endpoint.
config |= (0x02 << 8) Returns:
elif parity == 'M': status (int): modem status, as a proprietary bitfield
config |= (0x03 << 8) '''
elif parity == 'S': buf = bytearray(self.DEFAULT_READ_BUFFER_SIZE)
config |= (0x04 << 8) result = self._ctrl_transfer_in(self.SIO_POLL_MODEM_STATUS, buf, 2)
else: if result != 2:
raise ValueError("Unknown parity value: {}".format(parity)) raise SerialException('Unable to get modem status.')
buf = buf[:2]
status, = unpack('<H', bytes(buf))
return status
def _set_flowctrl(self, flowctrl):
'''Select flowcontrol in UART mode.
if stopbits == 1: Either hardware flow control through RTS/CTS UART lines,
config |= (0x00 << 11) software or no flow control.
elif stopbits == 1.5: Parameters:
config |= (0x01 << 11) flowctrl (str): 'hw', 'sw' or ''
elif stopbits == 2: '''
config |= (0x02 << 11) ctrl = {
else: 'hw': self.SIO_RTS_CTS_HS,
raise ValueError("Unknown stopbits value: {}".format(stopbits)) 'sw': self.SIO_XON_XOFF_HS,
'': self.SIO_DISABLE_FLOW_CTRL
}
try:
value = ctrl[flowctrl] | self._index
except KeyError:
raise ValueError('Unknown flow control: {}'.format(flowctrl))
result = self._ctrl_transfer_out(self.SIO_SET_DATA, config, 0) result = self._ctrl_transfer_out(
self.SIO_SET_FLOW_CTRL,
0,
value
)
if result != 0: if result != 0:
raise SerialException( raise SerialException(
"Setting parameters failed: result={}".format(result)) "Setting flow control failed: result={}".format(result)
)
def _reconfigure_port(self):
'''Reconfigure serial port parameters.'''
self._setParameters(
self.baudrate,
self.bytesize,
self.parity,
self.stopbits)
def _ctrl_transfer_out(self, request, value, index):
'''USB control transfer.
This function does the USB configuration job.
'''
return self._connection.controlTransfer(
self.FTDI_DEVICE_OUT_REQTYPE,
request,
value,
index,
None,
0,
self.USB_WRITE_TIMEOUT_MILLIS)
def _has_mpsse(self): def _has_mpsse(self):
'''Tell whether the device supports MPSSE (I2C, SPI, JTAG, ...). '''Tell whether the device supports MPSSE (I2C, SPI, JTAG, ...).
@ -500,8 +771,8 @@ class FtdiSerial(SerialBase):
if baud_diff == 0: if baud_diff == 0:
break break
# Encode the best divisor value # Encode the best divisor value
encoded_divisor = (best_divisor >> 3) | \ encoded_divisor = (best_divisor >> 3) \
(frac_code[best_divisor & 7] << 14) | (frac_code[best_divisor & 7] << 14)
# Deal with special cases for encoded value # Deal with special cases for encoded value
if encoded_divisor == 1: if encoded_divisor == 1:
encoded_divisor = 0 # 3000000 baud encoded_divisor = 0 # 3000000 baud
@ -531,21 +802,23 @@ class FtdiSerial(SerialBase):
Returns: Returns:
result (int): the number of payload bytes. result (int): the number of payload bytes.
''' '''
packetsCount = totalBytesRead // maxPacketSize + ( packetsCount = totalBytesRead // maxPacketSize + \
0 if totalBytesRead % maxPacketSize == 0 else 1) (0 if totalBytesRead % maxPacketSize == 0 else 1)
for packetIdx in range(packetsCount): for packetIdx in range(packetsCount):
count = ((totalBytesRead % maxPacketSize) - count = (
self.MODEM_STATUS_HEADER_LENGTH) if ( (totalBytesRead % maxPacketSize) \
packetIdx == (packetsCount - 1)) else ( - self.MODEM_STATUS_HEADER_LENGTH
maxPacketSize - self.MODEM_STATUS_HEADER_LENGTH) ) if (packetIdx == (packetsCount - 1)) else \
(maxPacketSize - self.MODEM_STATUS_HEADER_LENGTH)
if count > 0: if count > 0:
usb.arraycopy( usb.arraycopy(
src, src,
packetIdx * maxPacketSize + self.MODEM_STATUS_HEADER_LENGTH, packetIdx * maxPacketSize + self.MODEM_STATUS_HEADER_LENGTH,
dest, dest,
packetIdx * ( packetIdx \
maxPacketSize - self.MODEM_STATUS_HEADER_LENGTH), * (maxPacketSize - self.MODEM_STATUS_HEADER_LENGTH),
count) count
)
return totalBytesRead - (packetsCount * 2) return totalBytesRead - (packetsCount * 2)