Chapman Flack
2015-04-19 00:53:17 UTC
Hi, I'm new to pyusb, thinking I have an idea to propose for how
uniformly serial and usb support in Python could be handled ... it
started with this sort of dream vision:
1. I have this gizmo that once upon a time had an old-fashioned 232
serial interface to the computer. I can talk to it in Python:
import serial
giz = serial.serial_for_url(sys.argv[1]) # caller passes /dev/ttyS0
2. But that was then. These days it's the same gizmo with a
USB-to-serial chip glued on the front. I'd like that to change my
code as little as possible - maybe even not at all except for what
the caller sends as argv[1].
Under the hood a few different things could be going on:
2a. My kernel has a driver for that USB-to-serial chip, and makes a
native device node.
import serial
giz = serial.serial_for_url(sys.argv[1])
# caller passes /dev/serial/by-id/usb-0683_1550-if01-port0
2b. Maybe the kernel doesn't have a specific driver for that chip, but
the chip has the right communications USB class and the kernel's
usbserial generic driver might work with it. Same native device node
gets created, so nothing changes in Python code, not even the device
name.
2c. Instead of using an in-kernel driver, maybe pyusb is around and the
chip is from FTDI...
import serial
import ftdi.serialext # ?? see more dream below
giz = serial.serial_for_url(sys.argv[1])
# caller passes ftdi://0x0683:0x1550/2
2d. Maybe the chip's an MCT instead? (caution, science fiction ahead)
import serial
giz = serial.serial_for_url(sys.argv[1])
# caller passes mct://0x0711:0x0210/1
2e. Could there be a generic communications-USB-class driver, like the
one the linux kernel has? (Also science fiction at the moment.)
import serial
giz = serial.serial_for_url(sys.argv[1])
# caller passes usb://0x0683:0x1550/2
Ok, waking up from the dream ....
The current state of things is almost where it could allow all the above
to work.
- pyserial already provides serial_for_url() that can open a native
serial device node or a "url" with extensible schemes via
protocol_handler_packages. It already provides a SerialBase class and
several implementations.
- There's already a UsbSerial base class that extends SerialBase and is
used as a mixin for the pyftdi driver allowing it to be used as a
pyserial driver. This should work for other USB-to-serial drivers
(prolific, mct, whatever) too, or a generic communications-USB-class
driver.
- That UsbSerial class, and the rest of the 'serialext' package, was
contributed to pyftdi by Emmanuel Blot, but maybe pyftdi isn't the
best place for it, because it could be a base mixin for many different
USB-serial driver protocols and ftdi is just one specific one.
- Maybe it would make sense if pyftdi.serialext became pyusb.serialext
instead? It is BSD-licensed (unlike the rest of the code in pyftdi,
which carries LGPL headers) so that much should be a comfortable fit
with pyusb.
- That way, any Python driver for a USB-serial chip would probably
import pyusb (as it likely would anyway) and extend UsbSerial.
- Moving serialext would require Emmanuel Blot's agreement for pyftdi,
and for a while pyftdi would probably have to do try: import
pyusb.serialext; except ImportError: import pyftdi.serialext; to work
in old and new cases.
- UsbSerial does import some UsbTools code from pyftdi proper (LGPL),
most significantly parse_url, which is useful. It would be good to
have one url-parsing scheme applicable across any USB-serial drivers,
not just as part of pyftdi. Maybe Emmanuel could be approached about
allowing BSD licensing for usbtools.py?
- At the moment there isn't a generic,
don't-care-what-the-chip-is-as-long-as-I-can-bulk-read-write-it
pure-pyusb driver like the usbserial generic one in the linux kernel.
I might be interested enough to try writing one at some point. Maybe
such a generic usb-serial driver would also be at home within pyusb?
I realize both of these proposals turn pyusb into something slightly
more than a ctypes wrapper on libusb. Maybe that's not desired, and
there should just be a package usbserial in its own right, with
relationships like
pyserial pyusb
| |
+--------------+-------------+
|
serialusb
(UsbSerial base class,
generic USB-class-based driver)
|
+-------+-------+------------------...
| |
pyftdi other specific USB-serial chip drivers...
On the other hand, if there is no objection to growing pyusb a little
bit beyond wrapping libusb, that would save creating another separate
package.
Reactions? Does my dream make sense to other pyusb-users readers?
Thanks,
Chapman Flack
uniformly serial and usb support in Python could be handled ... it
started with this sort of dream vision:
1. I have this gizmo that once upon a time had an old-fashioned 232
serial interface to the computer. I can talk to it in Python:
import serial
giz = serial.serial_for_url(sys.argv[1]) # caller passes /dev/ttyS0
2. But that was then. These days it's the same gizmo with a
USB-to-serial chip glued on the front. I'd like that to change my
code as little as possible - maybe even not at all except for what
the caller sends as argv[1].
Under the hood a few different things could be going on:
2a. My kernel has a driver for that USB-to-serial chip, and makes a
native device node.
import serial
giz = serial.serial_for_url(sys.argv[1])
# caller passes /dev/serial/by-id/usb-0683_1550-if01-port0
2b. Maybe the kernel doesn't have a specific driver for that chip, but
the chip has the right communications USB class and the kernel's
usbserial generic driver might work with it. Same native device node
gets created, so nothing changes in Python code, not even the device
name.
2c. Instead of using an in-kernel driver, maybe pyusb is around and the
chip is from FTDI...
import serial
import ftdi.serialext # ?? see more dream below
giz = serial.serial_for_url(sys.argv[1])
# caller passes ftdi://0x0683:0x1550/2
2d. Maybe the chip's an MCT instead? (caution, science fiction ahead)
import serial
giz = serial.serial_for_url(sys.argv[1])
# caller passes mct://0x0711:0x0210/1
2e. Could there be a generic communications-USB-class driver, like the
one the linux kernel has? (Also science fiction at the moment.)
import serial
giz = serial.serial_for_url(sys.argv[1])
# caller passes usb://0x0683:0x1550/2
Ok, waking up from the dream ....
The current state of things is almost where it could allow all the above
to work.
- pyserial already provides serial_for_url() that can open a native
serial device node or a "url" with extensible schemes via
protocol_handler_packages. It already provides a SerialBase class and
several implementations.
- There's already a UsbSerial base class that extends SerialBase and is
used as a mixin for the pyftdi driver allowing it to be used as a
pyserial driver. This should work for other USB-to-serial drivers
(prolific, mct, whatever) too, or a generic communications-USB-class
driver.
- That UsbSerial class, and the rest of the 'serialext' package, was
contributed to pyftdi by Emmanuel Blot, but maybe pyftdi isn't the
best place for it, because it could be a base mixin for many different
USB-serial driver protocols and ftdi is just one specific one.
- Maybe it would make sense if pyftdi.serialext became pyusb.serialext
instead? It is BSD-licensed (unlike the rest of the code in pyftdi,
which carries LGPL headers) so that much should be a comfortable fit
with pyusb.
- That way, any Python driver for a USB-serial chip would probably
import pyusb (as it likely would anyway) and extend UsbSerial.
- Moving serialext would require Emmanuel Blot's agreement for pyftdi,
and for a while pyftdi would probably have to do try: import
pyusb.serialext; except ImportError: import pyftdi.serialext; to work
in old and new cases.
- UsbSerial does import some UsbTools code from pyftdi proper (LGPL),
most significantly parse_url, which is useful. It would be good to
have one url-parsing scheme applicable across any USB-serial drivers,
not just as part of pyftdi. Maybe Emmanuel could be approached about
allowing BSD licensing for usbtools.py?
- At the moment there isn't a generic,
don't-care-what-the-chip-is-as-long-as-I-can-bulk-read-write-it
pure-pyusb driver like the usbserial generic one in the linux kernel.
I might be interested enough to try writing one at some point. Maybe
such a generic usb-serial driver would also be at home within pyusb?
I realize both of these proposals turn pyusb into something slightly
more than a ctypes wrapper on libusb. Maybe that's not desired, and
there should just be a package usbserial in its own right, with
relationships like
pyserial pyusb
| |
+--------------+-------------+
|
serialusb
(UsbSerial base class,
generic USB-class-based driver)
|
+-------+-------+------------------...
| |
pyftdi other specific USB-serial chip drivers...
On the other hand, if there is no objection to growing pyusb a little
bit beyond wrapping libusb, that would save creating another separate
package.
Reactions? Does my dream make sense to other pyusb-users readers?
Thanks,
Chapman Flack