Skip to content
Permalink
Machine-UART
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
# Implementation of a very simple, custom USB device in Python. The device has an
# IN and OUT endpoint, accepts up to 64 bytes of data on the OUT endpoint, and echos
# that data back to the IN endpoint.
#
# To run, just execute this file on a device with machine.USBDevice support. The device
# will then change to the custom USB device.
#
# For example, use `mpremote` (the `--no-follow` option starts the script running
# without waiting for a response, because there won't be a response after the device
# changes its USB mode):
#
# $ mpremote run --no-follow usb_simple_device.py
#
# Then, run the host side of the example on your PC using:
#
# $ sudo python usb_simple_host_pyusb.py
#
# You'll need to have `pyusb` installed via `pip install pyusb` to run the host PC code.
# And `sudo` is most likely needed to access the custom USB device.
#
# Once you have finished running the code, you will need to reset or unplug the USB
# device to stop it.
import machine
# VID and PID of the USB device.
VID = 0xF055
PID = 0x9999
# USB endpoints used by the device.
EP_OUT = 0x01
EP_IN = 0x81
# USB device descriptor.
_desc_dev = bytes(
[
0x12, # bLength
0x01, # bDescriptorType: Device
0x00,
0x02, # USB version: 2.00
0xFF, # bDeviceClass: vendor
0x00, # bDeviceSubClass
0x01, # bDeviceProtocol
0x40, # bMaxPacketSize
VID & 0xFF,
VID >> 8 & 0xFF, # VID
PID & 0xFF,
PID >> 8 & 0xFF, # PID
0x00,
0x01, # bcdDevice: 1.00
0x11, # iManufacturer
0x12, # iProduct
0x13, # iSerialNumber
0x01, # bNumConfigurations: 1
]
)
# USB configuration descriptor.
_desc_cfg = bytes(
[
# Configuration Descriptor.
0x09, # bLength
0x02, # bDescriptorType: configuration
0x20,
0x00, # wTotalLength: 32
0x01, # bNumInterfaces
0x01, # bConfigurationValue
0x14, # iConfiguration
0xA0, # bmAttributes
0x96, # bMaxPower
# Interface Descriptor.
0x09, # bLength
0x04, # bDescriptorType: interface
0x00, # bInterfaceNumber
0x00, # bAlternateSetting
0x02, # bNumEndpoints
0xFF, # bInterfaceClass
0x03, # bInterfaceSubClass
0x00, # bInterfaceProtocol
0x15, # iInterface
# Endpoint IN1.
0x07, # bLength
0x05, # bDescriptorType: endpoint
EP_IN, # bEndpointAddress
0x03, # bmAttributes: interrupt
0x40,
0x00, # wMaxPacketSize
0x0A, # bInterval
# Endpoint OUT1.
0x07, # bLength
0x05, # bDescriptorType: endpoint
EP_OUT, # bEndpointAddress
0x02, # bmAttributes: bulk
0x40,
0x00, # wMaxPacketSize
0x00, # bInterval
]
)
# USB strings.
_desc_strs = {
0x11: b"iManufacturer",
0x12: b"iProduct",
0x13: b"iSerial",
0x14: b"iInterface",
0x15: b"iInterface",
0x16: b"Extra information",
}
# USB callback for when our custom USB interface is opened by the host.
def _open_itf_cb(interface_desc_view):
print("_open_itf_cb", bytes(interface_desc_view))
# Prepare to receive first data packet on the OUT endpoint.
usbd.submit_xfer(EP_OUT, usbd_buf)
# USB callback for when a data transfer (IN or OUT) has completed.
def _xfer_cb(ep_addr, result, xferred_bytes):
print("_xfer_cb", ep_addr, result, xferred_bytes)
if ep_addr == EP_OUT:
# Received data packet from the host, print it out.
print(usbd_buf)
# And then echo the data back to the host.
usbd.submit_xfer(EP_IN, memoryview(usbd_buf)[:xferred_bytes])
elif ep_addr == EP_IN:
# Host got our data, prepare to receive the next data packet.
usbd.submit_xfer(EP_OUT, usbd_buf)
# USB data buffer, for IN and OUT transfers.
usbd_buf = bytearray(64)
# Switch the USB device to our custom USB driver.
usbd = machine.USBDevice()
usbd.builtin_driver = usbd.BUILTIN_NONE
usbd.config(
desc_dev=_desc_dev,
desc_cfg=_desc_cfg,
desc_strs=_desc_strs,
open_itf_cb=_open_itf_cb,
xfer_cb=_xfer_cb,
)
usbd.active(1)