|
| 1 | +/********************************************************************* |
| 2 | + Adafruit invests time and resources providing this open source code, |
| 3 | + please support Adafruit and open-source hardware by purchasing |
| 4 | + products from Adafruit! |
| 5 | +
|
| 6 | + MIT license, check LICENSE for more information |
| 7 | + Copyright (c) 2019 Ha Thach for Adafruit Industries |
| 8 | + All text above, and the splash screen below must be included in |
| 9 | + any redistribution |
| 10 | +*********************************************************************/ |
| 11 | + |
| 12 | + |
| 13 | +/* This example demonstrates use of both device and host, where |
| 14 | + * - Device run on native usb controller (controller0) |
| 15 | + * - Host run on bit-banging 2 GPIOs with the help of Pico-PIO-USB library (controller1) |
| 16 | + * |
| 17 | + * Requirements: |
| 18 | + * - [Pico-PIO-USB](https://github.com/sekigon-gonnoc/Pico-PIO-USB) library |
| 19 | + * - 2 consecutive GPIOs: D+ is defined by HOST_PIN_DP (gpio2), D- = D+ +1 (gpio3) |
| 20 | + * - Provide VBus (5v) and GND for peripheral |
| 21 | + * - CPU Speed must be either 120 or 240 Mhz. Selected via "Menu -> CPU Speed" |
| 22 | + * |
| 23 | + * RP2040 host stack will get device descriptors of attached devices and print it out via |
| 24 | + * device cdc (Serial) as follows: |
| 25 | + * Device 1: ID 046d:c52f |
| 26 | + Device Descriptor: |
| 27 | + bLength 18 |
| 28 | + bDescriptorType 1 |
| 29 | + bcdUSB 0200 |
| 30 | + bDeviceClass 0 |
| 31 | + bDeviceSubClass 0 |
| 32 | + bDeviceProtocol 0 |
| 33 | + bMaxPacketSize0 8 |
| 34 | + idVendor 0x046d |
| 35 | + idProduct 0xc52f |
| 36 | + bcdDevice 2200 |
| 37 | + iManufacturer 1 Logitech |
| 38 | + iProduct 2 USB Receiver |
| 39 | + iSerialNumber 0 |
| 40 | + bNumConfigurations 1 |
| 41 | + * |
| 42 | + */ |
| 43 | + |
| 44 | +// pio-usb is required for rp2040 host |
| 45 | +#include "pio_usb.h" |
| 46 | +#define HOST_PIN_DP 2 // Pin used as D+ for host, D- = D+ + 1 |
| 47 | + |
| 48 | +#include "Adafruit_TinyUSB.h" |
| 49 | + |
| 50 | +#define LANGUAGE_ID 0x0409 // English |
| 51 | + |
| 52 | +// USB Host object |
| 53 | +Adafruit_USBH_Host USBHost; |
| 54 | + |
| 55 | +// holding device descriptor |
| 56 | +tusb_desc_device_t desc_device; |
| 57 | + |
| 58 | +// the setup function runs once when you press reset or power the board |
| 59 | +void setup() |
| 60 | +{ |
| 61 | + Serial1.begin(115200); |
| 62 | + |
| 63 | + Serial.begin(115200); |
| 64 | + //while ( !Serial ) delay(10); // wait for native usb |
| 65 | + |
| 66 | + Serial.println("TinyUSB Dual Device Info Example"); |
| 67 | +} |
| 68 | + |
| 69 | +void loop() |
| 70 | +{ |
| 71 | +} |
| 72 | + |
| 73 | +// core1's setup |
| 74 | +void setup1() { |
| 75 | + //while ( !Serial ) delay(10); // wait for native usb |
| 76 | + Serial.println("Core1 setup to run TinyUSB host with pio-usb"); |
| 77 | + |
| 78 | + // Check for CPU frequency, must be multiple of 120Mhz for bit-banging USB |
| 79 | + uint32_t cpu_hz = clock_get_hz(clk_sys); |
| 80 | + if ( cpu_hz != 120000000UL && cpu_hz != 240000000UL ) { |
| 81 | + while ( !Serial ) delay(10); // wait for native usb |
| 82 | + Serial.printf("Error: CPU Clock = %u, PIO USB require CPU clock must be multiple of 120 Mhz\r\n", cpu_hz); |
| 83 | + Serial.printf("Change your CPU Clock to either 120 or 240 Mhz in Menu->CPU Speed \r\n", cpu_hz); |
| 84 | + while(1) delay(1); |
| 85 | + } |
| 86 | + |
| 87 | + pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG; |
| 88 | + pio_cfg.pin_dp = HOST_PIN_DP; |
| 89 | + USBHost.configure_pio_usb(1, &pio_cfg); |
| 90 | + |
| 91 | + // run host stack on controller (rhport) 1 |
| 92 | + // Note: For rp2040 pico-pio-usb, calling USBHost.begin() on core1 will have most of the |
| 93 | + // host bit-banging processing works done in core1 to free up core0 for other works |
| 94 | + USBHost.begin(1); |
| 95 | +} |
| 96 | + |
| 97 | +// core1's loop |
| 98 | +void loop1() |
| 99 | +{ |
| 100 | + USBHost.task(); |
| 101 | +} |
| 102 | + |
| 103 | +// Invoked when device with hid interface is mounted |
| 104 | +// Report descriptor is also available for use. |
| 105 | +// tuh_hid_parse_report_descriptor() can be used to parse common/simple enough |
| 106 | +// descriptor. Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, |
| 107 | +// it will be skipped therefore report_desc = NULL, desc_len = 0 |
| 108 | +void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_report, uint16_t desc_len) { |
| 109 | + (void)desc_report; |
| 110 | + (void)desc_len; |
| 111 | + uint16_t vid, pid; |
| 112 | + tuh_vid_pid_get(dev_addr, &vid, &pid); |
| 113 | + |
| 114 | + Serial.printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); |
| 115 | + Serial.printf("VID = %04x, PID = %04x\r\n", vid, pid); |
| 116 | + if (!tuh_hid_receive_report(dev_addr, instance)) { |
| 117 | + Serial.printf("Error: cannot request to receive report\r\n"); |
| 118 | + } |
| 119 | +} |
| 120 | + |
| 121 | +// Invoked when device with hid interface is un-mounted |
| 122 | +void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) { |
| 123 | + Serial.printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); |
| 124 | +} |
| 125 | + |
| 126 | +// Invoked when received report from device via interrupt endpoint |
| 127 | +void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) { |
| 128 | + Serial.printf("HIDreport : "); |
| 129 | + for (uint16_t i = 0; i < len; i++) { |
| 130 | + Serial.printf("0x%02X ", report[i]); |
| 131 | + } |
| 132 | + Serial.println(); |
| 133 | + // continue to request to receive report |
| 134 | + if (!tuh_hid_receive_report(dev_addr, instance)) { |
| 135 | + Serial.printf("Error: cannot request to receive report\r\n"); |
| 136 | + } |
| 137 | +} |
0 commit comments