Plug Any USB Device on an ESP8266
Did you know you could plug USB devices on an Arduino or ESP? Keyboard, mouse, game controller, Midi controller, you name it!
Components and supplies
1
USB Host Mini
1
Wemos D1 Mini
Apps and platforms
1
Arduino IDE
Project description
Code
Simple USBMidi code
arduino
1#include <usbh_midi.h> 2#include <usbhub.h> 3#include <SPI.h> 4 5USB Usb; 6USBH_MIDI Midi(&Usb); 7 8void MIDI_poll(); 9uint16_t pid, vid; 10 11void setup() 12{ 13 vid = pid = 0; 14 Serial.begin(115200); 15 16 if (Usb.Init() == -1) { 17 while (1); //halt 18 }//if (Usb.Init() == -1... 19 delay( 200 ); 20} 21 22void loop() 23{ 24 Usb.Task(); 25 //uint32_t t1 = (uint32_t)micros(); 26 if ( Midi ) { 27 MIDI_poll(); 28 } 29} 30 31// Poll USB MIDI Controler and send to serial MIDI 32void MIDI_poll() 33{ 34 char buf[20]; 35 uint8_t bufMidi[64]; 36 uint16_t rcvd; 37 38 if (Midi.idVendor() != vid || Midi.idProduct() != pid) { 39 vid = Midi.idVendor(); 40 pid = Midi.idProduct(); 41 sprintf(buf, "VID:%04X, PID:%04X", vid, pid); 42 Serial.println(buf); 43 } 44 if (Midi.RecvData( &rcvd, bufMidi) == 0 ) { 45 uint32_t time = (uint32_t)millis(); 46 if (bufMidi[0] == 9) { 47 Serial.print("Note on -- "); 48 } 49 50 if (bufMidi[0] == 8) { 51 Serial.print("Note off -- "); 52 } 53 54 Serial.print("Note: "); 55 Serial.print(bufMidi[2]); 56 Serial.print(" Velocity: "); 57 Serial.print(bufMidi[3]); 58 Serial.println(""); 59 } 60}
Simple USBMidi code
arduino
1#include <usbh_midi.h> 2#include <usbhub.h> 3#include <SPI.h> 4 5USB Usb; 6USBH_MIDI Midi(&Usb); 7 8void MIDI_poll(); 9uint16_t pid, vid; 10 11void setup() 12{ 13 vid = pid = 0; 14 Serial.begin(115200); 15 16 if (Usb.Init() == -1) { 17 while (1); //halt 18 }//if (Usb.Init() == -1... 19 delay( 200 ); 20} 21 22void loop() 23{ 24 Usb.Task(); 25 //uint32_t t1 = (uint32_t)micros(); 26 if ( Midi ) { 27 MIDI_poll(); 28 } 29} 30 31// Poll USB MIDI Controler and send to serial MIDI 32void MIDI_poll() 33{ 34 char buf[20]; 35 uint8_t bufMidi[64]; 36 uint16_t rcvd; 37 38 if (Midi.idVendor() != vid || Midi.idProduct() != pid) { 39 vid = Midi.idVendor(); 40 pid = Midi.idProduct(); 41 sprintf(buf, "VID:%04X, PID:%04X", vid, pid); 42 Serial.println(buf); 43 } 44 if (Midi.RecvData( &rcvd, bufMidi) == 0 ) { 45 uint32_t time = (uint32_t)millis(); 46 if (bufMidi[0] == 9) { 47 Serial.print("Note on -- "); 48 } 49 50 if (bufMidi[0] == 8) { 51 Serial.print("Note off -- "); 52 } 53 54 Serial.print("Note: "); 55 Serial.print(bufMidi[2]); 56 Serial.print(" Velocity: "); 57 Serial.print(bufMidi[3]); 58 Serial.println(""); 59 } 60}
USBHost test (with baudrate for ESP8266)
arduino
1#include <usbhub.h> 2 3#include "pgmstrings.h" 4 5// Satisfy the IDE, which needs to see the include statment in the ino too. 6#ifdef dobogusinclude 7#include <spi4teensy3.h> 8#endif 9#include <SPI.h> 10 11USB Usb; 12//USBHub Hub1(&Usb); 13//USBHub Hub2(&Usb); 14//USBHub Hub3(&Usb); 15//USBHub Hub4(&Usb); 16//USBHub Hub5(&Usb); 17//USBHub Hub6(&Usb); 18//USBHub Hub7(&Usb); 19 20void PrintAllAddresses(UsbDevice *pdev) 21{ 22 UsbDeviceAddress adr; 23 adr.devAddress = pdev->address.devAddress; 24 Serial.print("\ \ 25Addr:"); 26 Serial.print(adr.devAddress, HEX); 27 Serial.print("("); 28 Serial.print(adr.bmHub, HEX); 29 Serial.print("."); 30 Serial.print(adr.bmParent, HEX); 31 Serial.print("."); 32 Serial.print(adr.bmAddress, HEX); 33 Serial.println(")"); 34} 35 36void PrintAddress(uint8_t addr) 37{ 38 UsbDeviceAddress adr; 39 adr.devAddress = addr; 40 Serial.print("\ \ 41ADDR:\ "); 42 Serial.println(adr.devAddress, HEX); 43 Serial.print("DEV:\ "); 44 Serial.println(adr.bmAddress, HEX); 45 Serial.print("PRNT:\ "); 46 Serial.println(adr.bmParent, HEX); 47 Serial.print("HUB:\ "); 48 Serial.println(adr.bmHub, HEX); 49} 50 51void setup() 52{ 53 Serial.begin( 74880 ); 54#if !defined(__MIPSEL__) 55 while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection 56#endif 57 Serial.println("Start"); 58 59 if (Usb.Init() == -1) 60 Serial.println("OSC did not start."); 61 62 delay( 200 ); 63} 64 65uint8_t getdevdescr( uint8_t addr, uint8_t &num_conf ); 66 67void PrintDescriptors(uint8_t addr) 68{ 69 uint8_t rcode = 0; 70 uint8_t num_conf = 0; 71 72 rcode = getdevdescr( (uint8_t)addr, num_conf ); 73 if ( rcode ) 74 { 75 printProgStr(Gen_Error_str); 76 print_hex( rcode, 8 ); 77 } 78 Serial.print("\ \ 79"); 80 81 for (int i = 0; i < num_conf; i++) 82 { 83 rcode = getconfdescr( addr, i ); // get configuration descriptor 84 if ( rcode ) 85 { 86 printProgStr(Gen_Error_str); 87 print_hex(rcode, 8); 88 } 89 Serial.println("\ \ 90"); 91 } 92} 93 94void PrintAllDescriptors(UsbDevice *pdev) 95{ 96 Serial.println("\ \ 97"); 98 print_hex(pdev->address.devAddress, 8); 99 Serial.println("\ \ 100--"); 101 PrintDescriptors( pdev->address.devAddress ); 102} 103 104void loop() 105{ 106 Usb.Task(); 107 108 if ( Usb.getUsbTaskState() == USB_STATE_RUNNING ) 109 { 110 Usb.ForEachUsbDevice(&PrintAllDescriptors); 111 Usb.ForEachUsbDevice(&PrintAllAddresses); 112 113 while ( 1 ) { // stop 114#ifdef ESP8266 115 yield(); // needed in order to reset the watchdog timer on the ESP8266 116#endif 117 } 118 } 119} 120 121uint8_t getdevdescr( uint8_t addr, uint8_t &num_conf ) 122{ 123 USB_DEVICE_DESCRIPTOR buf; 124 uint8_t rcode; 125 rcode = Usb.getDevDescr( addr, 0, 0x12, ( uint8_t *)&buf ); 126 if ( rcode ) { 127 return ( rcode ); 128 } 129 printProgStr(Dev_Header_str); 130 printProgStr(Dev_Length_str); 131 print_hex( buf.bLength, 8 ); 132 printProgStr(Dev_Type_str); 133 print_hex( buf.bDescriptorType, 8 ); 134 printProgStr(Dev_Version_str); 135 print_hex( buf.bcdUSB, 16 ); 136 printProgStr(Dev_Class_str); 137 print_hex( buf.bDeviceClass, 8 ); 138 printProgStr(Dev_Subclass_str); 139 print_hex( buf.bDeviceSubClass, 8 ); 140 printProgStr(Dev_Protocol_str); 141 print_hex( buf.bDeviceProtocol, 8 ); 142 printProgStr(Dev_Pktsize_str); 143 print_hex( buf.bMaxPacketSize0, 8 ); 144 printProgStr(Dev_Vendor_str); 145 print_hex( buf.idVendor, 16 ); 146 printProgStr(Dev_Product_str); 147 print_hex( buf.idProduct, 16 ); 148 printProgStr(Dev_Revision_str); 149 print_hex( buf.bcdDevice, 16 ); 150 printProgStr(Dev_Mfg_str); 151 print_hex( buf.iManufacturer, 8 ); 152 printProgStr(Dev_Prod_str); 153 print_hex( buf.iProduct, 8 ); 154 printProgStr(Dev_Serial_str); 155 print_hex( buf.iSerialNumber, 8 ); 156 printProgStr(Dev_Nconf_str); 157 print_hex( buf.bNumConfigurations, 8 ); 158 num_conf = buf.bNumConfigurations; 159 return ( 0 ); 160} 161 162void printhubdescr(uint8_t *descrptr, uint8_t addr) 163{ 164 HubDescriptor *pHub = (HubDescriptor*) descrptr; 165 uint8_t len = *((uint8_t*)descrptr); 166 167 printProgStr(PSTR("\ \ 168\ \ 169Hub Descriptor:\ \ 170")); 171 printProgStr(PSTR("bDescLength:\ \ ")); 172 Serial.println(pHub->bDescLength, HEX); 173 174 printProgStr(PSTR("bDescriptorType:\ ")); 175 Serial.println(pHub->bDescriptorType, HEX); 176 177 printProgStr(PSTR("bNbrPorts:\ \ ")); 178 Serial.println(pHub->bNbrPorts, HEX); 179 180 printProgStr(PSTR("LogPwrSwitchMode:\ ")); 181 Serial.println(pHub->LogPwrSwitchMode, BIN); 182 183 printProgStr(PSTR("CompoundDevice:\ \ ")); 184 Serial.println(pHub->CompoundDevice, BIN); 185 186 printProgStr(PSTR("OverCurrentProtectMode:\ ")); 187 Serial.println(pHub->OverCurrentProtectMode, BIN); 188 189 printProgStr(PSTR("TTThinkTime:\ \ ")); 190 Serial.println(pHub->TTThinkTime, BIN); 191 192 printProgStr(PSTR("PortIndicatorsSupported:")); 193 Serial.println(pHub->PortIndicatorsSupported, BIN); 194 195 printProgStr(PSTR("Reserved:\ \ ")); 196 Serial.println(pHub->Reserved, HEX); 197 198 printProgStr(PSTR("bPwrOn2PwrGood:\ \ ")); 199 Serial.println(pHub->bPwrOn2PwrGood, HEX); 200 201 printProgStr(PSTR("bHubContrCurrent:\ ")); 202 Serial.println(pHub->bHubContrCurrent, HEX); 203 204 for (uint8_t i = 7; i < len; i++) 205 print_hex(descrptr[i], 8); 206 207 //for (uint8_t i=1; i<=pHub->bNbrPorts; i++) 208 // PrintHubPortStatus(&Usb, addr, i, 1); 209} 210 211uint8_t getconfdescr( uint8_t addr, uint8_t conf ) 212{ 213 uint8_t buf[ BUFSIZE ]; 214 uint8_t* buf_ptr = buf; 215 uint8_t rcode; 216 uint8_t descr_length; 217 uint8_t descr_type; 218 uint16_t total_length; 219 rcode = Usb.getConfDescr( addr, 0, 4, conf, buf ); //get total length 220 LOBYTE( total_length ) = buf[ 2 ]; 221 HIBYTE( total_length ) = buf[ 3 ]; 222 if ( total_length > 256 ) { //check if total length is larger than buffer 223 printProgStr(Conf_Trunc_str); 224 total_length = 256; 225 } 226 rcode = Usb.getConfDescr( addr, 0, total_length, conf, buf ); //get the whole descriptor 227 while ( buf_ptr < buf + total_length ) { //parsing descriptors 228 descr_length = *( buf_ptr ); 229 descr_type = *( buf_ptr + 1 ); 230 switch ( descr_type ) { 231 case ( USB_DESCRIPTOR_CONFIGURATION ): 232 printconfdescr( buf_ptr ); 233 break; 234 case ( USB_DESCRIPTOR_INTERFACE ): 235 printintfdescr( buf_ptr ); 236 break; 237 case ( USB_DESCRIPTOR_ENDPOINT ): 238 printepdescr( buf_ptr ); 239 break; 240 case 0x29: 241 printhubdescr( buf_ptr, addr ); 242 break; 243 default: 244 printunkdescr( buf_ptr ); 245 break; 246 }//switch( descr_type 247 buf_ptr = ( buf_ptr + descr_length ); //advance buffer pointer 248 }//while( buf_ptr <=... 249 return ( rcode ); 250} 251/* prints hex numbers with leading zeroes */ 252// copyright, Peter H Anderson, Baltimore, MD, Nov, '07 253// source: http://www.phanderson.com/arduino/arduino_display.html 254void print_hex(int v, int num_places) 255{ 256 int mask = 0, n, num_nibbles, digit; 257 258 for (n = 1; n <= num_places; n++) { 259 mask = (mask << 1) | 0x0001; 260 } 261 v = v & mask; // truncate v to specified number of places 262 263 num_nibbles = num_places / 4; 264 if ((num_places % 4) != 0) { 265 ++num_nibbles; 266 } 267 do { 268 digit = ((v >> (num_nibbles - 1) * 4)) & 0x0f; 269 Serial.print(digit, HEX); 270 } 271 while (--num_nibbles); 272} 273/* function to print configuration descriptor */ 274void printconfdescr( uint8_t* descr_ptr ) 275{ 276 USB_CONFIGURATION_DESCRIPTOR* conf_ptr = ( USB_CONFIGURATION_DESCRIPTOR* )descr_ptr; 277 printProgStr(Conf_Header_str); 278 printProgStr(Conf_Totlen_str); 279 print_hex( conf_ptr->wTotalLength, 16 ); 280 printProgStr(Conf_Nint_str); 281 print_hex( conf_ptr->bNumInterfaces, 8 ); 282 printProgStr(Conf_Value_str); 283 print_hex( conf_ptr->bConfigurationValue, 8 ); 284 printProgStr(Conf_String_str); 285 print_hex( conf_ptr->iConfiguration, 8 ); 286 printProgStr(Conf_Attr_str); 287 print_hex( conf_ptr->bmAttributes, 8 ); 288 printProgStr(Conf_Pwr_str); 289 print_hex( conf_ptr->bMaxPower, 8 ); 290 return; 291} 292/* function to print interface descriptor */ 293void printintfdescr( uint8_t* descr_ptr ) 294{ 295 USB_INTERFACE_DESCRIPTOR* intf_ptr = ( USB_INTERFACE_DESCRIPTOR* )descr_ptr; 296 printProgStr(Int_Header_str); 297 printProgStr(Int_Number_str); 298 print_hex( intf_ptr->bInterfaceNumber, 8 ); 299 printProgStr(Int_Alt_str); 300 print_hex( intf_ptr->bAlternateSetting, 8 ); 301 printProgStr(Int_Endpoints_str); 302 print_hex( intf_ptr->bNumEndpoints, 8 ); 303 printProgStr(Int_Class_str); 304 print_hex( intf_ptr->bInterfaceClass, 8 ); 305 printProgStr(Int_Subclass_str); 306 print_hex( intf_ptr->bInterfaceSubClass, 8 ); 307 printProgStr(Int_Protocol_str); 308 print_hex( intf_ptr->bInterfaceProtocol, 8 ); 309 printProgStr(Int_String_str); 310 print_hex( intf_ptr->iInterface, 8 ); 311 return; 312} 313/* function to print endpoint descriptor */ 314void printepdescr( uint8_t* descr_ptr ) 315{ 316 USB_ENDPOINT_DESCRIPTOR* ep_ptr = ( USB_ENDPOINT_DESCRIPTOR* )descr_ptr; 317 printProgStr(End_Header_str); 318 printProgStr(End_Address_str); 319 print_hex( ep_ptr->bEndpointAddress, 8 ); 320 printProgStr(End_Attr_str); 321 print_hex( ep_ptr->bmAttributes, 8 ); 322 printProgStr(End_Pktsize_str); 323 print_hex( ep_ptr->wMaxPacketSize, 16 ); 324 printProgStr(End_Interval_str); 325 print_hex( ep_ptr->bInterval, 8 ); 326 327 return; 328} 329/*function to print unknown descriptor */ 330void printunkdescr( uint8_t* descr_ptr ) 331{ 332 uint8_t length = *descr_ptr; 333 uint8_t i; 334 printProgStr(Unk_Header_str); 335 printProgStr(Unk_Length_str); 336 print_hex( *descr_ptr, 8 ); 337 printProgStr(Unk_Type_str); 338 print_hex( *(descr_ptr + 1 ), 8 ); 339 printProgStr(Unk_Contents_str); 340 descr_ptr += 2; 341 for ( i = 0; i < length; i++ ) { 342 print_hex( *descr_ptr, 8 ); 343 descr_ptr++; 344 } 345} 346 347 348/* Print a string from Program Memory directly to save RAM */ 349void printProgStr(const char* str) 350{ 351 char c; 352 if (!str) return; 353 while ((c = pgm_read_byte(str++))) 354 Serial.print(c); 355}
UsbCore.h Fix for Wemos Mini D1
arduino
1/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. 2 3This software may be distributed and modified under the terms of the GNU 4General Public License version 2 (GPL2) as published by the Free Software 5Foundation and appearing in the file GPL2.TXT included in the packaging of 6this file. Please note that GPL2 Section 2[b] requires that all works based 7on this software must also be made publicly available under the terms of 8the GPL2 ("Copyleft"). 9 10Contact information 11------------------- 12 13Circuits At Home, LTD 14Web : http://www.circuitsathome.com 15e-mail : support@circuitsathome.com 16 */ 17 18#if !defined(_usb_h_) || defined(USBCORE_H) 19#error "Never include UsbCore.h directly; include Usb.h instead" 20#else 21#define USBCORE_H 22 23// Not used anymore? If anyone uses this, please let us know so that this may be 24// moved to the proper place, settings.h. 25//#define USB_METHODS_INLINE 26 27/* shield pins. First parameter - SS pin, second parameter - INT pin */ 28#ifdef BOARD_BLACK_WIDDOW 29typedef MAX3421e<P6, P3> MAX3421E; // Black Widow 30#elif defined(CORE_TEENSY) && (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)) 31#if EXT_RAM 32typedef MAX3421e<P20, P7> MAX3421E; // Teensy++ 2.0 with XMEM2 33#else 34typedef MAX3421e<P9, P8> MAX3421E; // Teensy++ 1.0 and 2.0 35#endif 36#elif defined(BOARD_MEGA_ADK) 37typedef MAX3421e<P53, P54> MAX3421E; // Arduino Mega ADK 38#elif defined(ARDUINO_AVR_BALANDUINO) 39typedef MAX3421e<P20, P19> MAX3421E; // Balanduino 40#elif defined(__ARDUINO_X86__) && PLATFORM_ID == 0x06 41typedef MAX3421e<P3, P2> MAX3421E; // The Intel Galileo supports much faster read and write speed at pin 2 and 3 42#elif defined(ESP8266) 43typedef MAX3421e<P0, P5> MAX3421E; // ESP8266 boards 44#elif defined(ESP32) 45typedef MAX3421e<P5, P17> MAX3421E; // ESP32 boards 46#else 47typedef MAX3421e<P10, P9> MAX3421E; // Official Arduinos (UNO, Duemilanove, Mega, 2560, Leonardo, Due etc.), Intel Edison, Intel Galileo 2 or Teensy 2.0 and 3.x 48#endif 49 50/* Common setup data constant combinations */ 51#define bmREQ_GET_DESCR USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE //get descriptor request type 52#define bmREQ_SET USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE //set request type for all but 'set feature' and 'set interface' 53#define bmREQ_CL_GET_INTF USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE //get interface request type 54 55// D7 data transfer direction (0 - host-to-device, 1 - device-to-host) 56// D6-5 Type (0- standard, 1 - class, 2 - vendor, 3 - reserved) 57// D4-0 Recipient (0 - device, 1 - interface, 2 - endpoint, 3 - other, 4..31 - reserved) 58 59// USB Device Classes 60#define USB_CLASS_USE_CLASS_INFO 0x00 // Use Class Info in the Interface Descriptors 61#define USB_CLASS_AUDIO 0x01 // Audio 62#define USB_CLASS_COM_AND_CDC_CTRL 0x02 // Communications and CDC Control 63#define USB_CLASS_HID 0x03 // HID 64#define USB_CLASS_PHYSICAL 0x05 // Physical 65#define USB_CLASS_IMAGE 0x06 // Image 66#define USB_CLASS_PRINTER 0x07 // Printer 67#define USB_CLASS_MASS_STORAGE 0x08 // Mass Storage 68#define USB_CLASS_HUB 0x09 // Hub 69#define USB_CLASS_CDC_DATA 0x0a // CDC-Data 70#define USB_CLASS_SMART_CARD 0x0b // Smart-Card 71#define USB_CLASS_CONTENT_SECURITY 0x0d // Content Security 72#define USB_CLASS_VIDEO 0x0e // Video 73#define USB_CLASS_PERSONAL_HEALTH 0x0f // Personal Healthcare 74#define USB_CLASS_DIAGNOSTIC_DEVICE 0xdc // Diagnostic Device 75#define USB_CLASS_WIRELESS_CTRL 0xe0 // Wireless Controller 76#define USB_CLASS_MISC 0xef // Miscellaneous 77#define USB_CLASS_APP_SPECIFIC 0xfe // Application Specific 78#define USB_CLASS_VENDOR_SPECIFIC 0xff // Vendor Specific 79 80// Additional Error Codes 81#define USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED 0xD1 82#define USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE 0xD2 83#define USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS 0xD3 84#define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL 0xD4 85#define USB_ERROR_HUB_ADDRESS_OVERFLOW 0xD5 86#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL 0xD6 87#define USB_ERROR_EPINFO_IS_NULL 0xD7 88#define USB_ERROR_INVALID_ARGUMENT 0xD8 89#define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE 0xD9 90#define USB_ERROR_INVALID_MAX_PKT_SIZE 0xDA 91#define USB_ERROR_EP_NOT_FOUND_IN_TBL 0xDB 92#define USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET 0xE0 93#define USB_ERROR_FailGetDevDescr 0xE1 94#define USB_ERROR_FailSetDevTblEntry 0xE2 95#define USB_ERROR_FailGetConfDescr 0xE3 96#define USB_ERROR_TRANSFER_TIMEOUT 0xFF 97 98#define USB_XFER_TIMEOUT 5000 // (5000) USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec 99//#define USB_NAK_LIMIT 32000 // NAK limit for a transfer. 0 means NAKs are not counted 100#define USB_RETRY_LIMIT 3 // 3 retry limit for a transfer 101#define USB_SETTLE_DELAY 200 // settle delay in milliseconds 102 103#define USB_NUMDEVICES 16 //number of USB devices 104//#define HUB_MAX_HUBS 7 // maximum number of hubs that can be attached to the host controller 105#define HUB_PORT_RESET_DELAY 20 // hub port reset delay 10 ms recomended, can be up to 20 ms 106 107/* USB state machine states */ 108#define USB_STATE_MASK 0xf0 109 110#define USB_STATE_DETACHED 0x10 111#define USB_DETACHED_SUBSTATE_INITIALIZE 0x11 112#define USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE 0x12 113#define USB_DETACHED_SUBSTATE_ILLEGAL 0x13 114#define USB_ATTACHED_SUBSTATE_SETTLE 0x20 115#define USB_ATTACHED_SUBSTATE_RESET_DEVICE 0x30 116#define USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE 0x40 117#define USB_ATTACHED_SUBSTATE_WAIT_SOF 0x50 118#define USB_ATTACHED_SUBSTATE_WAIT_RESET 0x51 119#define USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE 0x60 120#define USB_STATE_ADDRESSING 0x70 121#define USB_STATE_CONFIGURING 0x80 122#define USB_STATE_RUNNING 0x90 123#define USB_STATE_ERROR 0xa0 124 125class USBDeviceConfig { 126public: 127 128 virtual uint8_t Init(uint8_t parent __attribute__((unused)), uint8_t port __attribute__((unused)), bool lowspeed __attribute__((unused))) { 129 return 0; 130 } 131 132 virtual uint8_t ConfigureDevice(uint8_t parent __attribute__((unused)), uint8_t port __attribute__((unused)), bool lowspeed __attribute__((unused))) { 133 return 0; 134 } 135 136 virtual uint8_t Release() { 137 return 0; 138 } 139 140 virtual uint8_t Poll() { 141 return 0; 142 } 143 144 virtual uint8_t GetAddress() { 145 return 0; 146 } 147 148 virtual void ResetHubPort(uint8_t port __attribute__((unused))) { 149 return; 150 } // Note used for hubs only! 151 152 virtual bool VIDPIDOK(uint16_t vid __attribute__((unused)), uint16_t pid __attribute__((unused))) { 153 return false; 154 } 155 156 virtual bool DEVCLASSOK(uint8_t klass __attribute__((unused))) { 157 return false; 158 } 159 160 virtual bool DEVSUBCLASSOK(uint8_t subklass __attribute__((unused))) { 161 return true; 162 } 163 164}; 165 166/* USB Setup Packet Structure */ 167typedef struct { 168 169 union { // offset description 170 uint8_t bmRequestType; // 0 Bit-map of request type 171 172 struct { 173 uint8_t recipient : 5; // Recipient of the request 174 uint8_t type : 2; // Type of request 175 uint8_t direction : 1; // Direction of data X-fer 176 } __attribute__((packed)); 177 } ReqType_u; 178 uint8_t bRequest; // 1 Request 179 180 union { 181 uint16_t wValue; // 2 Depends on bRequest 182 183 struct { 184 uint8_t wValueLo; 185 uint8_t wValueHi; 186 } __attribute__((packed)); 187 } wVal_u; 188 uint16_t wIndex; // 4 Depends on bRequest 189 uint16_t wLength; // 6 Depends on bRequest 190} __attribute__((packed)) SETUP_PKT, *PSETUP_PKT; 191 192 193 194// Base class for incoming data parser 195 196class USBReadParser { 197public: 198 virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) = 0; 199}; 200 201class USB : public MAX3421E { 202 AddressPoolImpl<USB_NUMDEVICES> addrPool; 203 USBDeviceConfig* devConfig[USB_NUMDEVICES]; 204 uint8_t bmHubPre; 205 206public: 207 USB(void); 208 209 void SetHubPreMask() { 210 bmHubPre |= bmHUBPRE; 211 }; 212 213 void ResetHubPreMask() { 214 bmHubPre &= (~bmHUBPRE); 215 }; 216 217 AddressPool& GetAddressPool() { 218 return (AddressPool&)addrPool; 219 }; 220 221 uint8_t RegisterDeviceClass(USBDeviceConfig *pdev) { 222 for(uint8_t i = 0; i < USB_NUMDEVICES; i++) { 223 if(!devConfig[i]) { 224 devConfig[i] = pdev; 225 return 0; 226 } 227 } 228 return USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS; 229 }; 230 231 void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) { 232 addrPool.ForEachUsbDevice(pfunc); 233 }; 234 uint8_t getUsbTaskState(void); 235 void setUsbTaskState(uint8_t state); 236 237 EpInfo* getEpInfoEntry(uint8_t addr, uint8_t ep); 238 uint8_t setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr); 239 240 /* Control requests */ 241 uint8_t getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr); 242 uint8_t getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr); 243 244 uint8_t getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p); 245 246 uint8_t getStrDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t index, uint16_t langid, uint8_t* dataptr); 247 uint8_t setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr); 248 uint8_t setConf(uint8_t addr, uint8_t ep, uint8_t conf_value); 249 /**/ 250 uint8_t ctrlData(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr, bool direction); 251 uint8_t ctrlStatus(uint8_t ep, bool direction, uint16_t nak_limit); 252 uint8_t inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* data, uint8_t bInterval = 0); 253 uint8_t outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data); 254 uint8_t dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit); 255 256 void Task(void); 257 258 uint8_t DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed); 259 uint8_t Configuring(uint8_t parent, uint8_t port, bool lowspeed); 260 uint8_t ReleaseDevice(uint8_t addr); 261 262 uint8_t ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, 263 uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBReadParser *p); 264 265private: 266 void init(); 267 uint8_t SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t *nak_limit); 268 uint8_t OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data); 269 uint8_t InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t *data, uint8_t bInterval = 0); 270 uint8_t AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed); 271}; 272 273#if 0 //defined(USB_METHODS_INLINE) 274//get device descriptor 275 276inline uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr) { 277 return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr)); 278} 279//get configuration descriptor 280 281inline uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) { 282 return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr)); 283} 284//get string descriptor 285 286inline uint8_t USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t nuint8_ts, uint8_t index, uint16_t langid, uint8_t* dataptr) { 287 return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nuint8_ts, dataptr)); 288} 289//set address 290 291inline uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) { 292 return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, NULL)); 293} 294//set configuration 295 296inline uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) { 297 return ( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL)); 298} 299 300#endif // defined(USB_METHODS_INLINE) 301 302#endif /* USBCORE_H */ 303
USBHost test (with baudrate for ESP8266)
arduino
1#include <usbhub.h> 2 3#include "pgmstrings.h" 4 5// Satisfy 6 the IDE, which needs to see the include statment in the ino too. 7#ifdef dobogusinclude 8#include 9 <spi4teensy3.h> 10#endif 11#include <SPI.h> 12 13USB Usb; 14//USBHub Hub1(&Usb); 15//USBHub 16 Hub2(&Usb); 17//USBHub Hub3(&Usb); 18//USBHub Hub4(&Usb); 19//USBHub Hub5(&Usb); 20//USBHub 21 Hub6(&Usb); 22//USBHub Hub7(&Usb); 23 24void PrintAllAddresses(UsbDevice *pdev) 25{ 26 27 UsbDeviceAddress adr; 28 adr.devAddress = pdev->address.devAddress; 29 Serial.print("\ \ 30Addr:"); 31 32 Serial.print(adr.devAddress, HEX); 33 Serial.print("("); 34 Serial.print(adr.bmHub, 35 HEX); 36 Serial.print("."); 37 Serial.print(adr.bmParent, HEX); 38 Serial.print("."); 39 40 Serial.print(adr.bmAddress, HEX); 41 Serial.println(")"); 42} 43 44void 45 PrintAddress(uint8_t addr) 46{ 47 UsbDeviceAddress adr; 48 adr.devAddress = 49 addr; 50 Serial.print("\ \ 51ADDR:\ "); 52 Serial.println(adr.devAddress, 53 HEX); 54 Serial.print("DEV:\ "); 55 Serial.println(adr.bmAddress, HEX); 56 57 Serial.print("PRNT:\ "); 58 Serial.println(adr.bmParent, HEX); 59 Serial.print("HUB:\ "); 60 61 Serial.println(adr.bmHub, HEX); 62} 63 64void setup() 65{ 66 Serial.begin( 67 74880 ); 68#if !defined(__MIPSEL__) 69 while (!Serial); // Wait for serial port 70 to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial 71 connection 72#endif 73 Serial.println("Start"); 74 75 if (Usb.Init() == 76 -1) 77 Serial.println("OSC did not start."); 78 79 delay( 200 ); 80} 81 82uint8_t 83 getdevdescr( uint8_t addr, uint8_t &num_conf ); 84 85void PrintDescriptors(uint8_t 86 addr) 87{ 88 uint8_t rcode = 0; 89 uint8_t num_conf = 0; 90 91 rcode = getdevdescr( 92 (uint8_t)addr, num_conf ); 93 if ( rcode ) 94 { 95 printProgStr(Gen_Error_str); 96 97 print_hex( rcode, 8 ); 98 } 99 Serial.print("\ \ 100"); 101 102 for (int 103 i = 0; i < num_conf; i++) 104 { 105 rcode = getconfdescr( addr, i ); // 106 get configuration descriptor 107 if ( rcode ) 108 { 109 printProgStr(Gen_Error_str); 110 111 print_hex(rcode, 8); 112 } 113 Serial.println("\ \ 114"); 115 } 116} 117 118void 119 PrintAllDescriptors(UsbDevice *pdev) 120{ 121 Serial.println("\ \ 122"); 123 print_hex(pdev->address.devAddress, 124 8); 125 Serial.println("\ \ 126--"); 127 PrintDescriptors( pdev->address.devAddress 128 ); 129} 130 131void loop() 132{ 133 Usb.Task(); 134 135 if ( Usb.getUsbTaskState() 136 == USB_STATE_RUNNING ) 137 { 138 Usb.ForEachUsbDevice(&PrintAllDescriptors); 139 140 Usb.ForEachUsbDevice(&PrintAllAddresses); 141 142 while ( 1 ) { // stop 143#ifdef 144 ESP8266 145 yield(); // needed in order to reset the watchdog timer on the 146 ESP8266 147#endif 148 } 149 } 150} 151 152uint8_t getdevdescr( uint8_t addr, 153 uint8_t &num_conf ) 154{ 155 USB_DEVICE_DESCRIPTOR buf; 156 uint8_t rcode; 157 158 rcode = Usb.getDevDescr( addr, 0, 0x12, ( uint8_t *)&buf ); 159 if ( rcode ) 160 { 161 return ( rcode ); 162 } 163 printProgStr(Dev_Header_str); 164 printProgStr(Dev_Length_str); 165 166 print_hex( buf.bLength, 8 ); 167 printProgStr(Dev_Type_str); 168 print_hex( 169 buf.bDescriptorType, 8 ); 170 printProgStr(Dev_Version_str); 171 print_hex( buf.bcdUSB, 172 16 ); 173 printProgStr(Dev_Class_str); 174 print_hex( buf.bDeviceClass, 8 ); 175 176 printProgStr(Dev_Subclass_str); 177 print_hex( buf.bDeviceSubClass, 8 ); 178 179 printProgStr(Dev_Protocol_str); 180 print_hex( buf.bDeviceProtocol, 8 ); 181 182 printProgStr(Dev_Pktsize_str); 183 print_hex( buf.bMaxPacketSize0, 8 ); 184 printProgStr(Dev_Vendor_str); 185 186 print_hex( buf.idVendor, 16 ); 187 printProgStr(Dev_Product_str); 188 print_hex( 189 buf.idProduct, 16 ); 190 printProgStr(Dev_Revision_str); 191 print_hex( buf.bcdDevice, 192 16 ); 193 printProgStr(Dev_Mfg_str); 194 print_hex( buf.iManufacturer, 8 ); 195 196 printProgStr(Dev_Prod_str); 197 print_hex( buf.iProduct, 8 ); 198 printProgStr(Dev_Serial_str); 199 200 print_hex( buf.iSerialNumber, 8 ); 201 printProgStr(Dev_Nconf_str); 202 print_hex( 203 buf.bNumConfigurations, 8 ); 204 num_conf = buf.bNumConfigurations; 205 return 206 ( 0 ); 207} 208 209void printhubdescr(uint8_t *descrptr, uint8_t addr) 210{ 211 212 HubDescriptor *pHub = (HubDescriptor*) descrptr; 213 uint8_t len = *((uint8_t*)descrptr); 214 215 216 printProgStr(PSTR("\ \ 217\ \ 218Hub Descriptor:\ \ 219")); 220 printProgStr(PSTR("bDescLength:\ \ ")); 221 222 Serial.println(pHub->bDescLength, HEX); 223 224 printProgStr(PSTR("bDescriptorType:\ ")); 225 226 Serial.println(pHub->bDescriptorType, HEX); 227 228 printProgStr(PSTR("bNbrPorts:\ \ ")); 229 230 Serial.println(pHub->bNbrPorts, HEX); 231 232 printProgStr(PSTR("LogPwrSwitchMode:\ ")); 233 234 Serial.println(pHub->LogPwrSwitchMode, BIN); 235 236 printProgStr(PSTR("CompoundDevice:\ \ ")); 237 238 Serial.println(pHub->CompoundDevice, BIN); 239 240 printProgStr(PSTR("OverCurrentProtectMode:\ ")); 241 242 Serial.println(pHub->OverCurrentProtectMode, BIN); 243 244 printProgStr(PSTR("TTThinkTime:\ \ ")); 245 246 Serial.println(pHub->TTThinkTime, BIN); 247 248 printProgStr(PSTR("PortIndicatorsSupported:")); 249 250 Serial.println(pHub->PortIndicatorsSupported, BIN); 251 252 printProgStr(PSTR("Reserved:\ \ ")); 253 254 Serial.println(pHub->Reserved, HEX); 255 256 printProgStr(PSTR("bPwrOn2PwrGood:\ \ ")); 257 258 Serial.println(pHub->bPwrOn2PwrGood, HEX); 259 260 printProgStr(PSTR("bHubContrCurrent:\ ")); 261 262 Serial.println(pHub->bHubContrCurrent, HEX); 263 264 for (uint8_t i = 7; i < 265 len; i++) 266 print_hex(descrptr[i], 8); 267 268 //for (uint8_t i=1; i<=pHub->bNbrPorts; 269 i++) 270 // PrintHubPortStatus(&Usb, addr, i, 1); 271} 272 273uint8_t getconfdescr( 274 uint8_t addr, uint8_t conf ) 275{ 276 uint8_t buf[ BUFSIZE ]; 277 uint8_t* buf_ptr 278 = buf; 279 uint8_t rcode; 280 uint8_t descr_length; 281 uint8_t descr_type; 282 283 uint16_t total_length; 284 rcode = Usb.getConfDescr( addr, 0, 4, conf, buf ); 285 //get total length 286 LOBYTE( total_length ) = buf[ 2 ]; 287 HIBYTE( total_length 288 ) = buf[ 3 ]; 289 if ( total_length > 256 ) { //check if total length is larger 290 than buffer 291 printProgStr(Conf_Trunc_str); 292 total_length = 256; 293 294 } 295 rcode = Usb.getConfDescr( addr, 0, total_length, conf, buf ); //get the 296 whole descriptor 297 while ( buf_ptr < buf + total_length ) { //parsing descriptors 298 299 descr_length = *( buf_ptr ); 300 descr_type = *( buf_ptr + 1 ); 301 switch 302 ( descr_type ) { 303 case ( USB_DESCRIPTOR_CONFIGURATION ): 304 printconfdescr( 305 buf_ptr ); 306 break; 307 case ( USB_DESCRIPTOR_INTERFACE ): 308 printintfdescr( 309 buf_ptr ); 310 break; 311 case ( USB_DESCRIPTOR_ENDPOINT ): 312 printepdescr( 313 buf_ptr ); 314 break; 315 case 0x29: 316 printhubdescr( buf_ptr, 317 addr ); 318 break; 319 default: 320 printunkdescr( buf_ptr ); 321 322 break; 323 }//switch( descr_type 324 buf_ptr = ( buf_ptr + descr_length 325 ); //advance buffer pointer 326 }//while( buf_ptr <=... 327 return ( rcode 328 ); 329} 330/* prints hex numbers with leading zeroes */ 331// copyright, Peter H 332 Anderson, Baltimore, MD, Nov, '07 333// source: http://www.phanderson.com/arduino/arduino_display.html 334void 335 print_hex(int v, int num_places) 336{ 337 int mask = 0, n, num_nibbles, digit; 338 339 340 for (n = 1; n <= num_places; n++) { 341 mask = (mask << 1) | 0x0001; 342 } 343 344 v = v & mask; // truncate v to specified number of places 345 346 num_nibbles 347 = num_places / 4; 348 if ((num_places % 4) != 0) { 349 ++num_nibbles; 350 } 351 352 do { 353 digit = ((v >> (num_nibbles - 1) * 4)) & 0x0f; 354 Serial.print(digit, 355 HEX); 356 } 357 while (--num_nibbles); 358} 359/* function to print configuration 360 descriptor */ 361void printconfdescr( uint8_t* descr_ptr ) 362{ 363 USB_CONFIGURATION_DESCRIPTOR* 364 conf_ptr = ( USB_CONFIGURATION_DESCRIPTOR* )descr_ptr; 365 printProgStr(Conf_Header_str); 366 367 printProgStr(Conf_Totlen_str); 368 print_hex( conf_ptr->wTotalLength, 16 ); 369 370 printProgStr(Conf_Nint_str); 371 print_hex( conf_ptr->bNumInterfaces, 8 ); 372 373 printProgStr(Conf_Value_str); 374 print_hex( conf_ptr->bConfigurationValue, 8 375 ); 376 printProgStr(Conf_String_str); 377 print_hex( conf_ptr->iConfiguration, 378 8 ); 379 printProgStr(Conf_Attr_str); 380 print_hex( conf_ptr->bmAttributes, 8 381 ); 382 printProgStr(Conf_Pwr_str); 383 print_hex( conf_ptr->bMaxPower, 8 ); 384 385 return; 386} 387/* function to print interface descriptor */ 388void printintfdescr( 389 uint8_t* descr_ptr ) 390{ 391 USB_INTERFACE_DESCRIPTOR* intf_ptr = ( USB_INTERFACE_DESCRIPTOR* 392 )descr_ptr; 393 printProgStr(Int_Header_str); 394 printProgStr(Int_Number_str); 395 396 print_hex( intf_ptr->bInterfaceNumber, 8 ); 397 printProgStr(Int_Alt_str); 398 399 print_hex( intf_ptr->bAlternateSetting, 8 ); 400 printProgStr(Int_Endpoints_str); 401 402 print_hex( intf_ptr->bNumEndpoints, 8 ); 403 printProgStr(Int_Class_str); 404 405 print_hex( intf_ptr->bInterfaceClass, 8 ); 406 printProgStr(Int_Subclass_str); 407 408 print_hex( intf_ptr->bInterfaceSubClass, 8 ); 409 printProgStr(Int_Protocol_str); 410 411 print_hex( intf_ptr->bInterfaceProtocol, 8 ); 412 printProgStr(Int_String_str); 413 414 print_hex( intf_ptr->iInterface, 8 ); 415 return; 416} 417/* function to print 418 endpoint descriptor */ 419void printepdescr( uint8_t* descr_ptr ) 420{ 421 USB_ENDPOINT_DESCRIPTOR* 422 ep_ptr = ( USB_ENDPOINT_DESCRIPTOR* )descr_ptr; 423 printProgStr(End_Header_str); 424 425 printProgStr(End_Address_str); 426 print_hex( ep_ptr->bEndpointAddress, 8 ); 427 428 printProgStr(End_Attr_str); 429 print_hex( ep_ptr->bmAttributes, 8 ); 430 printProgStr(End_Pktsize_str); 431 432 print_hex( ep_ptr->wMaxPacketSize, 16 ); 433 printProgStr(End_Interval_str); 434 435 print_hex( ep_ptr->bInterval, 8 ); 436 437 return; 438} 439/*function to print 440 unknown descriptor */ 441void printunkdescr( uint8_t* descr_ptr ) 442{ 443 uint8_t 444 length = *descr_ptr; 445 uint8_t i; 446 printProgStr(Unk_Header_str); 447 printProgStr(Unk_Length_str); 448 449 print_hex( *descr_ptr, 8 ); 450 printProgStr(Unk_Type_str); 451 print_hex( *(descr_ptr 452 + 1 ), 8 ); 453 printProgStr(Unk_Contents_str); 454 descr_ptr += 2; 455 for ( 456 i = 0; i < length; i++ ) { 457 print_hex( *descr_ptr, 8 ); 458 descr_ptr++; 459 460 } 461} 462 463 464/* Print a string from Program Memory directly to save RAM */ 465void 466 printProgStr(const char* str) 467{ 468 char c; 469 if (!str) return; 470 while 471 ((c = pgm_read_byte(str++))) 472 Serial.print(c); 473}
UsbCore.h Fix for Wemos Mini D1
arduino
1/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. 2 3This 4 software may be distributed and modified under the terms of the GNU 5General Public 6 License version 2 (GPL2) as published by the Free Software 7Foundation and appearing 8 in the file GPL2.TXT included in the packaging of 9this file. Please note that 10 GPL2 Section 2[b] requires that all works based 11on this software must also be 12 made publicly available under the terms of 13the GPL2 ("Copyleft"). 14 15Contact 16 information 17------------------- 18 19Circuits At Home, LTD 20Web : http://www.circuitsathome.com 21e-mail 22 : support@circuitsathome.com 23 */ 24 25#if !defined(_usb_h_) || defined(USBCORE_H) 26#error 27 "Never include UsbCore.h directly; include Usb.h instead" 28#else 29#define 30 USBCORE_H 31 32// Not used anymore? If anyone uses this, please let us know so 33 that this may be 34// moved to the proper place, settings.h. 35//#define USB_METHODS_INLINE 36 37/* 38 shield pins. First parameter - SS pin, second parameter - INT pin */ 39#ifdef BOARD_BLACK_WIDDOW 40typedef 41 MAX3421e<P6, P3> MAX3421E; // Black Widow 42#elif defined(CORE_TEENSY) && (defined(__AVR_AT90USB646__) 43 || defined(__AVR_AT90USB1286__)) 44#if EXT_RAM 45typedef MAX3421e<P20, P7> MAX3421E; 46 // Teensy++ 2.0 with XMEM2 47#else 48typedef MAX3421e<P9, P8> MAX3421E; // Teensy++ 49 1.0 and 2.0 50#endif 51#elif defined(BOARD_MEGA_ADK) 52typedef MAX3421e<P53, 53 P54> MAX3421E; // Arduino Mega ADK 54#elif defined(ARDUINO_AVR_BALANDUINO) 55typedef 56 MAX3421e<P20, P19> MAX3421E; // Balanduino 57#elif defined(__ARDUINO_X86__) && 58 PLATFORM_ID == 0x06 59typedef MAX3421e<P3, P2> MAX3421E; // The Intel Galileo supports 60 much faster read and write speed at pin 2 and 3 61#elif defined(ESP8266) 62typedef 63 MAX3421e<P0, P5> MAX3421E; // ESP8266 boards 64#elif defined(ESP32) 65typedef 66 MAX3421e<P5, P17> MAX3421E; // ESP32 boards 67#else 68typedef MAX3421e<P10, P9> 69 MAX3421E; // Official Arduinos (UNO, Duemilanove, Mega, 2560, Leonardo, Due etc.), 70 Intel Edison, Intel Galileo 2 or Teensy 2.0 and 3.x 71#endif 72 73/* Common setup 74 data constant combinations */ 75#define bmREQ_GET_DESCR USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE 76 //get descriptor request type 77#define bmREQ_SET USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE 78 //set request type for all but 'set feature' and 'set interface' 79#define 80 bmREQ_CL_GET_INTF USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE 81 //get interface request type 82 83// D7 data transfer direction 84 (0 - host-to-device, 1 - device-to-host) 85// D6-5 Type (0- standard, 1 86 - class, 2 - vendor, 3 - reserved) 87// D4-0 Recipient (0 - device, 1 - 88 interface, 2 - endpoint, 3 - other, 4..31 - reserved) 89 90// USB Device Classes 91#define 92 USB_CLASS_USE_CLASS_INFO 0x00 // Use Class Info in the Interface Descriptors 93#define 94 USB_CLASS_AUDIO 0x01 // Audio 95#define USB_CLASS_COM_AND_CDC_CTRL 96 0x02 // Communications and CDC Control 97#define USB_CLASS_HID 0x03 98 // HID 99#define USB_CLASS_PHYSICAL 0x05 // Physical 100#define 101 USB_CLASS_IMAGE 0x06 // Image 102#define USB_CLASS_PRINTER 0x07 103 // Printer 104#define USB_CLASS_MASS_STORAGE 0x08 // Mass Storage 105#define 106 USB_CLASS_HUB 0x09 // Hub 107#define USB_CLASS_CDC_DATA 0x0a 108 // CDC-Data 109#define USB_CLASS_SMART_CARD 0x0b // Smart-Card 110#define 111 USB_CLASS_CONTENT_SECURITY 0x0d // Content Security 112#define USB_CLASS_VIDEO 113 0x0e // Video 114#define USB_CLASS_PERSONAL_HEALTH 0x0f 115 // Personal Healthcare 116#define USB_CLASS_DIAGNOSTIC_DEVICE 0xdc // 117 Diagnostic Device 118#define USB_CLASS_WIRELESS_CTRL 0xe0 // Wireless 119 Controller 120#define USB_CLASS_MISC 0xef // Miscellaneous 121#define 122 USB_CLASS_APP_SPECIFIC 0xfe // Application Specific 123#define USB_CLASS_VENDOR_SPECIFIC 124 0xff // Vendor Specific 125 126// Additional Error Codes 127#define USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED 128 0xD1 129#define USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE 0xD2 130#define 131 USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS 0xD3 132#define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL 133 0xD4 134#define USB_ERROR_HUB_ADDRESS_OVERFLOW 0xD5 135#define 136 USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL 0xD6 137#define USB_ERROR_EPINFO_IS_NULL 138 0xD7 139#define USB_ERROR_INVALID_ARGUMENT 0xD8 140#define 141 USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE 0xD9 142#define USB_ERROR_INVALID_MAX_PKT_SIZE 143 0xDA 144#define USB_ERROR_EP_NOT_FOUND_IN_TBL 0xDB 145#define 146 USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET 0xE0 147#define USB_ERROR_FailGetDevDescr 148 0xE1 149#define USB_ERROR_FailSetDevTblEntry 0xE2 150#define 151 USB_ERROR_FailGetConfDescr 0xE3 152#define USB_ERROR_TRANSFER_TIMEOUT 153 0xFF 154 155#define USB_XFER_TIMEOUT 5000 // (5000) 156 USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec 157//#define 158 USB_NAK_LIMIT 32000 // NAK limit for a transfer. 0 means NAKs are not 159 counted 160#define USB_RETRY_LIMIT 3 // 3 retry limit for a transfer 161#define 162 USB_SETTLE_DELAY 200 // settle delay in milliseconds 163 164#define USB_NUMDEVICES 165 16 //number of USB devices 166//#define HUB_MAX_HUBS 7 // 167 maximum number of hubs that can be attached to the host controller 168#define HUB_PORT_RESET_DELAY 169 20 // hub port reset delay 10 ms recomended, can be up to 20 ms 170 171/* 172 USB state machine states */ 173#define USB_STATE_MASK 0xf0 174 175#define 176 USB_STATE_DETACHED 0x10 177#define USB_DETACHED_SUBSTATE_INITIALIZE 178 0x11 179#define USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE 0x12 180#define 181 USB_DETACHED_SUBSTATE_ILLEGAL 0x13 182#define USB_ATTACHED_SUBSTATE_SETTLE 183 0x20 184#define USB_ATTACHED_SUBSTATE_RESET_DEVICE 0x30 185#define 186 USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE 0x40 187#define USB_ATTACHED_SUBSTATE_WAIT_SOF 188 0x50 189#define USB_ATTACHED_SUBSTATE_WAIT_RESET 0x51 190#define 191 USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE 0x60 192#define USB_STATE_ADDRESSING 193 0x70 194#define USB_STATE_CONFIGURING 0x80 195#define 196 USB_STATE_RUNNING 0x90 197#define USB_STATE_ERROR 198 0xa0 199 200class USBDeviceConfig { 201public: 202 203 204 virtual uint8_t Init(uint8_t parent __attribute__((unused)), uint8_t port 205 __attribute__((unused)), bool lowspeed __attribute__((unused))) { 206 return 207 0; 208 } 209 210 virtual uint8_t ConfigureDevice(uint8_t parent __attribute__((unused)), 211 uint8_t port __attribute__((unused)), bool lowspeed __attribute__((unused))) { 212 213 return 0; 214 } 215 216 virtual uint8_t Release() 217 { 218 return 0; 219 } 220 221 virtual uint8_t Poll() 222 { 223 return 0; 224 } 225 226 virtual uint8_t GetAddress() 227 { 228 return 0; 229 } 230 231 virtual void ResetHubPort(uint8_t 232 port __attribute__((unused))) { 233 return; 234 } // Note 235 used for hubs only! 236 237 virtual bool VIDPIDOK(uint16_t vid __attribute__((unused)), 238 uint16_t pid __attribute__((unused))) { 239 return false; 240 } 241 242 243 virtual bool DEVCLASSOK(uint8_t klass __attribute__((unused))) { 244 return 245 false; 246 } 247 248 virtual bool DEVSUBCLASSOK(uint8_t subklass __attribute__((unused))) 249 { 250 return true; 251 } 252 253}; 254 255/* USB Setup Packet 256 Structure */ 257typedef struct { 258 259 union { // offset description 260 261 uint8_t bmRequestType; // 0 Bit-map of request type 262 263 264 struct { 265 uint8_t recipient : 5; // Recipient 266 of the request 267 uint8_t type : 2; // Type of 268 request 269 uint8_t direction : 1; // Direction 270 of data X-fer 271 } __attribute__((packed)); 272 } ReqType_u; 273 274 uint8_t bRequest; // 1 Request 275 276 union { 277 uint16_t 278 wValue; // 2 Depends on bRequest 279 280 struct { 281 uint8_t 282 wValueLo; 283 uint8_t wValueHi; 284 } __attribute__((packed)); 285 286 } wVal_u; 287 uint16_t wIndex; // 4 Depends on bRequest 288 289 uint16_t wLength; // 6 Depends on bRequest 290} __attribute__((packed)) 291 SETUP_PKT, *PSETUP_PKT; 292 293 294 295// Base class for incoming data parser 296 297class 298 USBReadParser { 299public: 300 virtual void Parse(const uint16_t len, const 301 uint8_t *pbuf, const uint16_t &offset) = 0; 302}; 303 304class USB : public MAX3421E 305 { 306 AddressPoolImpl<USB_NUMDEVICES> addrPool; 307 USBDeviceConfig* 308 devConfig[USB_NUMDEVICES]; 309 uint8_t bmHubPre; 310 311public: 312 USB(void); 313 314 315 void SetHubPreMask() { 316 bmHubPre |= bmHUBPRE; 317 }; 318 319 320 void ResetHubPreMask() { 321 bmHubPre &= (~bmHUBPRE); 322 323 }; 324 325 AddressPool& GetAddressPool() { 326 return 327 (AddressPool&)addrPool; 328 }; 329 330 uint8_t RegisterDeviceClass(USBDeviceConfig 331 *pdev) { 332 for(uint8_t i = 0; i < USB_NUMDEVICES; i++) { 333 if(!devConfig[i]) 334 { 335 devConfig[i] = pdev; 336 return 337 0; 338 } 339 } 340 return USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS; 341 342 }; 343 344 void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) { 345 346 addrPool.ForEachUsbDevice(pfunc); 347 }; 348 uint8_t 349 getUsbTaskState(void); 350 void setUsbTaskState(uint8_t state); 351 352 EpInfo* 353 getEpInfoEntry(uint8_t addr, uint8_t ep); 354 uint8_t setEpInfoEntry(uint8_t 355 addr, uint8_t epcount, EpInfo* eprecord_ptr); 356 357 /* Control requests 358 */ 359 uint8_t getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* 360 dataptr); 361 uint8_t getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, 362 uint8_t conf, uint8_t* dataptr); 363 364 uint8_t getConfDescr(uint8_t addr, 365 uint8_t ep, uint8_t conf, USBReadParser *p); 366 367 uint8_t getStrDescr(uint8_t 368 addr, uint8_t ep, uint16_t nbytes, uint8_t index, uint16_t langid, uint8_t* dataptr); 369 370 uint8_t setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr); 371 uint8_t 372 setConf(uint8_t addr, uint8_t ep, uint8_t conf_value); 373 /**/ 374 uint8_t 375 ctrlData(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr, bool direction); 376 377 uint8_t ctrlStatus(uint8_t ep, bool direction, uint16_t nak_limit); 378 379 uint8_t inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* 380 data, uint8_t bInterval = 0); 381 uint8_t outTransfer(uint8_t addr, uint8_t 382 ep, uint16_t nbytes, uint8_t* data); 383 uint8_t dispatchPkt(uint8_t token, 384 uint8_t ep, uint16_t nak_limit); 385 386 void Task(void); 387 388 uint8_t 389 DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed); 390 uint8_t 391 Configuring(uint8_t parent, uint8_t port, bool lowspeed); 392 uint8_t ReleaseDevice(uint8_t 393 addr); 394 395 uint8_t ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, 396 uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, 397 uint16_t wInd, 398 uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBReadParser *p); 399 400private: 401 402 void init(); 403 uint8_t SetAddress(uint8_t addr, uint8_t ep, EpInfo 404 **ppep, uint16_t *nak_limit); 405 uint8_t OutTransfer(EpInfo *pep, uint16_t 406 nak_limit, uint16_t nbytes, uint8_t *data); 407 uint8_t InTransfer(EpInfo 408 *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t *data, uint8_t bInterval 409 = 0); 410 uint8_t AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, 411 bool lowspeed); 412}; 413 414#if 0 //defined(USB_METHODS_INLINE) 415//get device 416 descriptor 417 418inline uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t 419 nbytes, uint8_t* dataptr) { 420 return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, 421 USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr)); 422} 423//get 424 configuration descriptor 425 426inline uint8_t USB::getConfDescr(uint8_t addr, uint8_t 427 ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) { 428 return ( ctrlReq(addr, 429 ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 430 0x0000, nbytes, dataptr)); 431} 432//get string descriptor 433 434inline uint8_t 435 USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t nuint8_ts, uint8_t index, uint16_t 436 langid, uint8_t* dataptr) { 437 return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, 438 USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nuint8_ts, dataptr)); 439} 440//set 441 address 442 443inline uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t 444 newaddr) { 445 return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, 446 newaddr, 0x00, 0x0000, 0x0000, NULL)); 447} 448//set configuration 449 450inline 451 uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) { 452 return 453 ( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 454 0x0000, 0x0000, NULL)); 455} 456 457#endif // defined(USB_METHODS_INLINE) 458 459#endif 460 /* USBCORE_H */ 461
Downloadable files
Arduino Micro 3V Wiring
Arduino Micro 3V Wiring

Arduino Mini 3V Wiring
Arduino Mini 3V Wiring

ESP32 Wiring
ESP32 Wiring

USB Host Mini Pins
USB Host Mini Pins

Arduino Mini 3V Wiring
Arduino Mini 3V Wiring

USB Host Mini Pins
USB Host Mini Pins

ESP8266 Wiring
ESP8266 Wiring

ESP32 Wiring
ESP32 Wiring

Arduino Micro 3V Wiring
Arduino Micro 3V Wiring

Comments
Only logged in users can leave comments