|
| 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 | +/* This example demonstrate HID Generic raw Input & Output. |
| 13 | + * It will receive data from Host (In endpoint) and echo back (Out endpoint). |
| 14 | + * HID Report descriptor use vendor for usage page (using template TUD_HID_REPORT_DESC_GENERIC_INOUT) |
| 15 | + * |
| 16 | + * There are 2 ways to test the sketch |
| 17 | + * 1. Using nodejs |
| 18 | + * - Install nodejs and nmp to your PC |
| 19 | + * - Install execellent node-hid (https://github.com/node-hid/node-hid) by |
| 20 | + * $ npm install node-hid |
| 21 | + * - Run provided hid test script |
| 22 | + * $ node hid_test.js |
| 23 | + * |
| 24 | + * 2. Using python hidRun |
| 25 | + * - Python and `hid` package is required, for installation please follow https://pypi.org/project/hid/ |
| 26 | + * - Run provided hid test script to send and receive data to this device. |
| 27 | + * $ python3 hid_test.py |
| 28 | + */ |
| 29 | + |
| 30 | +#include "Adafruit_TinyUSB.h" |
| 31 | + |
| 32 | +// 8KB is the smallest size that windows allow to mount |
| 33 | +#define DISK_BLOCK_NUM 16 |
| 34 | +#define DISK_BLOCK_SIZE 512 |
| 35 | +#include "ramdisk.h" |
| 36 | + |
| 37 | +// HID report descriptor using TinyUSB's template |
| 38 | +// Generic In Out with 64 bytes report (max) |
| 39 | +uint8_t const desc_hid_report[] = |
| 40 | +{ |
| 41 | + TUD_HID_REPORT_DESC_GENERIC_INOUT(64) |
| 42 | +}; |
| 43 | + |
| 44 | +Adafruit_USBD_HID usb_hid; |
| 45 | +Adafruit_USBD_MSC usb_msc; |
| 46 | + |
| 47 | +// the setup function runs once when you press reset or power the board |
| 48 | +void setup() |
| 49 | +{ |
| 50 | + usb_msc.setID("Adafruit", "Mass Storage", "1.0"); |
| 51 | + |
| 52 | + // Set disk size |
| 53 | + usb_msc.setCapacity(DISK_BLOCK_NUM, DISK_BLOCK_SIZE); |
| 54 | + |
| 55 | + // Set callback |
| 56 | + usb_msc.setReadWriteCallback(msc_read_cb, msc_write_cb, msc_flush_cb); |
| 57 | + |
| 58 | + // Set Lun ready (RAM disk is always ready) |
| 59 | + usb_msc.setUnitReady(true); |
| 60 | + |
| 61 | + usb_msc.begin(); |
| 62 | + |
| 63 | + usb_hid.enableOutEndpoint(true); |
| 64 | + usb_hid.setPollInterval(2); |
| 65 | + usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report)); |
| 66 | + usb_hid.setReportCallback(get_report_callback, set_report_callback); |
| 67 | + |
| 68 | + usb_hid.begin(); |
| 69 | + |
| 70 | + Serial.begin(115200); |
| 71 | + Serial.println("Waiting for USBDevice mount"); |
| 72 | + // wait until device mounted |
| 73 | + while( !USBDevice.mounted() ) delay(1); |
| 74 | + |
| 75 | + Serial.println("Adafruit TinyUSB HID Generic In Out example"); |
| 76 | +} |
| 77 | + |
| 78 | +void loop() |
| 79 | +{ |
| 80 | + // nothing to do |
| 81 | +} |
| 82 | + |
| 83 | +// Invoked when received GET_REPORT control request |
| 84 | +// Application must fill buffer report's content and return its length. |
| 85 | +// Return zero will cause the stack to STALL request |
| 86 | +uint16_t get_report_callback (uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) |
| 87 | +{ |
| 88 | + // not used in this example |
| 89 | + return 0; |
| 90 | +} |
| 91 | + |
| 92 | +// Invoked when received SET_REPORT control request or |
| 93 | +// received data on OUT endpoint ( Report ID = 0, Type = 0 ) |
| 94 | +void set_report_callback(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) |
| 95 | +{ |
| 96 | + // This example doesn't use multiple report and report ID |
| 97 | + (void) report_id; |
| 98 | + (void) report_type; |
| 99 | + |
| 100 | + // echo back anything we received from host |
| 101 | + usb_hid.sendReport(0, buffer, bufsize); |
| 102 | +} |
| 103 | + |
| 104 | +// Callback invoked when received READ10 command. |
| 105 | +// Copy disk's data to buffer (up to bufsize) and |
| 106 | +// return number of copied bytes (must be multiple of block size) |
| 107 | +int32_t msc_read_cb (uint32_t lba, void* buffer, uint32_t bufsize) |
| 108 | +{ |
| 109 | + uint8_t const* addr = msc_disk[lba]; |
| 110 | + memcpy(buffer, addr, bufsize); |
| 111 | + |
| 112 | + return bufsize; |
| 113 | +} |
| 114 | + |
| 115 | +// Callback invoked when received WRITE10 command. |
| 116 | +// Process data in buffer to disk's storage and |
| 117 | +// return number of written bytes (must be multiple of block size) |
| 118 | +int32_t msc_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize) |
| 119 | +{ |
| 120 | + uint8_t* addr = msc_disk[lba]; |
| 121 | + memcpy(addr, buffer, bufsize); |
| 122 | + |
| 123 | + return bufsize; |
| 124 | +} |
| 125 | + |
| 126 | +// Callback invoked when WRITE10 command is completed (status received and accepted by host). |
| 127 | +// used to flush any pending cache. |
| 128 | +void msc_flush_cb (void) |
| 129 | +{ |
| 130 | + // nothing to do |
| 131 | +} |
0 commit comments