{"id":15142114,"url":"https://github.com/gdsports/usbhostcopro","last_synced_at":"2025-10-23T19:31:11.989Z","repository":{"id":55128859,"uuid":"169833482","full_name":"gdsports/usbhostcopro","owner":"gdsports","description":"USB Host Co-processor","archived":false,"fork":false,"pushed_at":"2021-01-08T00:42:42.000Z","size":1843,"stargazers_count":77,"open_issues_count":5,"forks_count":10,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-09-27T09:22:49.281Z","etag":null,"topics":["arduino","circuitpython","esp32","espruino","keyboard","micropython","midi","pass-th","trinket-m0","usb-host"],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gdsports.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-02-09T04:59:40.000Z","updated_at":"2024-09-05T11:06:45.000Z","dependencies_parsed_at":"2022-08-14T12:50:47.108Z","dependency_job_id":null,"html_url":"https://github.com/gdsports/usbhostcopro","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gdsports%2Fusbhostcopro","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gdsports%2Fusbhostcopro/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gdsports%2Fusbhostcopro/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gdsports%2Fusbhostcopro/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gdsports","download_url":"https://codeload.github.com/gdsports/usbhostcopro/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219867955,"owners_count":16555810,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arduino","circuitpython","esp32","espruino","keyboard","micropython","midi","pass-th","trinket-m0","usb-host"],"created_at":"2024-09-26T09:23:03.817Z","updated_at":"2025-10-23T19:31:11.162Z","avatar_url":"https://github.com/gdsports.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# USB Host Co-Processor\n\n![Metro M4 Express and USB MIDI controller](images/cpmidiled.jpg)\n\nThe USB Host co-processor connects USB devices such as USB keyboards to\ndevolpment boards without USB host ports or without USB host software. The\nconnection is made via UART.  Device specific firmware is programmed into the\nUSB Host co-processor by dragging and dropping a firmware file.\n\nThe USB Host co-processor handles the complexities of USB host protocol and\ncommunicates the raw data via UART. For example, the USB MIDI firmware sends\nand receives MIDI messages at 115,200 bits/sec via UART. It is bi-directional\nand can handle System Exclusive messages up to 1024 bytes.\n\nThis open source project is based on the [USB Host Library for\nSAMD](https://github.com/gdsports/USB_Host_Library_SAMD) which is a port of the\n[USB Host Shield Library 2.0](https://github.com/felis/USB_Host_Shield_2.0).\n\nThe hardware is an Adafruit Trinket M0 with a USB OTG to host cable or adapter.\nThe Trinket M0 has a UF2 bootloader which means it appears as a USB drive.\nFirmware is burned into the device by dragging and dropping a firmware file\non to the USB drive. There is no need to install USB serial drivers, IDEs, or\nsource code unless you want to change the source code.\n\nSee the [firmware](./firmware) directory for the latest releases.\n\nUsing a UART interface makes it much easier to develop software since all of\nthe USB complexities are hidden in the co-processor. For example, the following\nCircuitPython code shows data arriving on the UART from the USB host\nco-processor. It is no more complicated than receiving data from any other\nserial device.\n\n```\nimport board\nimport busio\n\nuart = busio.UART(board.TX, board.RX, baudrate=115200)\n\nwhile True:\n    data = uart.read(1)\n\n    if data is not None:\n        # Show the byte as 2 hex digits then in the default way\n        print(\"%02x \" % (data[0]), end='')\n        print(data)\n```\n\n## Related Projects\n\n* [Convert USB keyboard to Bluetooth LE](https://github.com/gdsports/usbkbdble)\n* [USB Host MIDI for Two](https://github.com/gdsports/usbhostmidix2)\n\n## USB Host MIDI to UART\n\nMIDIUARTUSBH is a bi-directional converter for USB host MIDI and UART MIDI. The\nUART speed is 115,200 bits/sec. Modify the code if MIDI standard 31,250\nbits/sec is required. Not all MIDI gear is MIDI class compliant. Also gear with\ninternal USB hubs is not supported.\n\nThis is an example of [Controlling the RGB colors of a NeoPixel using a MIDI\ncontroller](https://github.com/gdsports/circuitpython_usb_host_midi).\n\n## USB Host keyboard to ASCII UART\n\nKBDUARTUSBH when used with a USB keyboard outputs ASCII on the UART. UART input\nis ignored. Many keys on a USB keyboard do not have an ASCII code so nothing\nwill be produced. For example, F1-F12 keys and any combination using the ALT or Win\nLogo key do not produce any output.\n\nSome other USB devices emulate USB keyboards such as barcode and RFID readers.\nSome barcode readers default to USB keyboard mode but others use USB serial or\nUSB Point of Sale. Some readers can be configured so consult the reader manual.\n\nUSB RFID readers (at least, the cheap ones) can only read the card unique\nserial number.\n\n## USB Host keyboard advanced\n\nKBDADVUARTUSBH when used with a USB keyboard outputs USB keyboard HID reports\non the UART. UART input is ignored. All USB keyboard keycodes are supported.\nFor example, Ctrl-ALT-Shift-F12 is a valid keystroke as well as Ctrl-ALT-DEL.\nThe CircuitPython program kbdhid.py receives the HID report and sends it\nout. Two Trinket M0 cross connected via UART Tx and Rx, one running KBDADVUARTUSBH\nand the other running kbdhid.py, act as a USB keyboard pass through. Either\nprogram can be modified to swap keys, expand macros, etc.\n\n```\nUSB keyboard \u003e USB OTG to host \u003e Trinket M0-A \u003e UART TX/RX \u003e Trinket M0-B \u003e computer\n                                 KBDADVUARTUSBH              kbdhid.py\n```\n\n![USB Keyboard pass through](./images/usb_keyboard_passthru.jpg)\n\nTrinket M0-A keyboard\t|Trinket M0-B computer\n------------------------|-------------\nGND\t\t\t\t\t\t|GND\nUSB (5V in)\t\t\t\t|USB (5V out)\nUART Tx(4)\t\t\t\t|UART Rx(3)\nUART Rx(3)\t\t\t\t|UART Rx(4)\n\n## USB Host mouse advanced\n\nMSEADVUARTUSBH when used with a USB mouse outputs USB mouse HID reports on the\nUART. UART input is ignored. The UART runs as 921,600 bits/sec (8\\*115200).\n\nEach mouse HID report appears on the UART TX in the following format.\n\nuint8_t mouseHID[7];\n\nmouseHID[0] = 0x02;  // (STX)\nmouseHID[1] = 0x24;  // Mouse report 4 bytes follow\nmouseHID[2] = 0xhh;  // Mouse button bitmap, 1=button pressed\nmouseHID[3] = 0xhh;  // int8_t X-axis relative movement\nmouseHID[4] = 0xhh;  // int8_t Y-axis relative movement\nmouseHID[5] = 0x00;  // int8_t scroll wheel movement (not used)\nmouseHID[6] = 0x03;  // (ETX)\n\nSee https://github.com/gdsports/usbmseble for a sketch that parses the UART\nstream and extracts the HID report.\n\n```\nUSB mouse \u003e USB OTG to host \u003e Trinket M0    \u003e UART TX\n                              MSEADVUARTUSBH\n```\n\n![USB Keyboard pass through](./images/usb_keyboard_passthru.jpg)\n\nTrinket M0-A keyboard\t|Trinket M0-B computer\n------------------------|-------------\nGND\t\t\t\t\t\t|GND\nUSB (5V in)\t\t\t\t|USB (5V out)\nUART Tx(4)\t\t\t\t|UART Rx(3)\nUART Rx(3)\t\t\t\t|UART Rx(4)\n\n## USB Host CDC ACM to UART\n\nCDCACMUSBH bi-directionally transfers data between a USB device with CDC ACM\nUSB serial to a UART port runnning at 115,200. This provides access to data\nfrom a USB CDC ACM device such as an Arduino board to another device with a\nUART but no USB hardware. For example, connect an ESP32 to a Pro Micro board.\nThe Pro Micro has a USB native hardware port and lots of 5V digital and analog\nI/O, PWM, etc. Firmata might work here.\n\n```\nUSB CDC ACM -\u003e USB OTG host cable -\u003e Trinket M0 -\u003e UART Tx/Rx -\u003e ESP32\nPro Micro                            CDCACMUSBH\n```\n\n## Logitech Extreme 3D Pro USB Joystick\n\nLE3DPUSBH takes input from the Logitech joystick and outputs JSON on the\nTrinket M0 UART Tx pin at 921,600 bits/sec. This high speed is used because\nJSON is verbose.\n\n![Logitech joystick with Trinket M0 and ESP32](./images/logitechjoy.jpg)\n\nThis was tested with a SparkFun ESP32 Thing running MicroPython.\n\n```\nLogitech joystick -\u003e USB OTG host cable -\u003e Trinket M0 -\u003e ESP32 -\u003e Computer\n                                           LE3DPUSBH     uPython\n```\n\nTrinket M0\t|ESP32\n------------|-------------\nGND         |GND\nUSB (5V in) |VUSB (5V out)\nUART Tx(4)  |16 (UART2 Rx)\nUART Rx(3)  |17 (UART2 Tx)\n\nJoystick        |Range\n----------------|-----\njstype          |0\nX and Y axes    |0..1023\ntwist           |0..255\nthrottle        |0..255\nhat             |0..8\nbuttons_a       |0..255\nbuttons_b       |0..255\n\nHat     |Direction\n--------|---------\n0|North, Forward\n1|North East\n2|East, Right\n3|South East\n4|South, Back\n5|South West\n6|West, Left\n7|North West\n8|no direction\n\nThe buttons are labelled but the numbers in a hard read gray-on-black and using\nan odd looking typeface.\n\nbuttons_a\n\nBit|Value|Button\n---|-----|------\n0  | 1   |Front Trigger\n1  | 2   |Side Trigger\n2  | 4   |Button 3\n3  | 8   |Button 4\n4  | 16  |Button 5\n5  | 32  |Button 6\n6  | 64  |Button 7\n7  |128  |Button 8\n\nbuttons_b\n\nBit|Value|Button\n---|-----|------\n0  | 1   |Button 9\n1  | 2   |Button 10\n2  | 4   |Button 11\n3  | 8   |Button 12\n\n\nSee the [firmware](./firmware) directory for the latest binary releases.\n\nSample minimum MicroPython code for ESP32.\n\n```\nfrom machine import UART\nimport ujson\n\nuart = UART(2, tx=17, rx=16)\nuart.init(8*115200, bits=8, parity=None, stop=1)\n\nwhile True:\n    # Read line of JSON from Trinket M0 connected to the joystick\n    data = uart.readline()\n    if data is not None:\n        try:\n            # Convert JSON string to Python dictionary\n            joy = ujson.loads(data)\n            print(joy)\n            print(joy['X'])\n            # Insert code to change motor or servo direction and speed based\n            # on joy['X'], joy['Y'], joy['hat'], etc.\n        except:\n            print(\"json error\")\n```\n\n### Thrustmaster T.16000M USB Joystick\n\nExperimental support for the Thrustmaster T.16000M joystick has been added. It\nis automatically detected.\n\nJoystick        |Range\n----------------|-----\njstype          |1\nX and Y axes    |0..16383\ntwist           |0..255\nthrottle        |0..255\nhat             |0..7,63\nbuttons         |0..65535\n\nHat     |Direction\n--------|---------\n0|North, Forward\n1|North East\n2|East, Right\n3|South East\n4|South, Back\n5|South West\n6|West, Left\n7|North West\n63|no direction\n\nbuttons\n\nBit|Value|Button\n---|-----|------\n0  | 1   |Front Trigger\n1  | 2   |Top middle\n2  | 4   |Top left\n3  | 8   |Top right\n4  | 16  |Base left front low\n5  | 32  |Base left front middle\n6  | 64  |Base left front high\n7  |128  |Base left back high\n8  |256  |Base left back middle\n9  |512  |Base left back low\n10 |1024 |Base right front low\n11 |2048 |Base right front middle\n12 |4096 |Base right front high\n13 |8192 |Base right back high\n14 |16384|Base right back middle\n15 |32768|Base right back low\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgdsports%2Fusbhostcopro","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgdsports%2Fusbhostcopro","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgdsports%2Fusbhostcopro/lists"}