Permalink
Cannot retrieve contributors at this time
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?
micropython/examples/usb/usb_simple_device.py
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
144 lines (131 sloc)
4.12 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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) |