From c1aaef21e1b0f8a01f47dc113ab5233635af24fa Mon Sep 17 00:00:00 2001 From: Thibault RICHARD Date: Tue, 12 Jun 2012 14:43:52 +0200 Subject: [PATCH] [sam] USBHost HID Mouse example is working --- .../validation_usb_host/descriptor_parser.h | 288 ------ .../validation_usb_host/test_usb_host.cpp | 822 ++------------- hardware/arduino/sam/system/USBHost/Usb.cpp | 756 +++++++------- hardware/arduino/sam/system/USBHost/Usb.h | 268 ++--- hardware/arduino/sam/system/USBHost/address.h | 293 ++++++ .../sam/system/USBHost/confdescparser.h | 213 ++++ .../examples/USB_desc/descriptor_strings.h | 50 + .../examples/USB_desc/test_usb_host.cpp | 281 +++++ .../USBHost/examples/board_test/board_test.h | 21 - .../examples/board_test/board_test.ino | 296 ------ .../conf_descr_dump/conf_descr_dump.ino | 181 ---- .../descriptor_parser/descriptor_parser.h | 284 ----- .../descriptor_parser/descriptor_parser.ino | 720 ------------- hardware/arduino/sam/system/USBHost/hid.h | 188 ++++ hardware/arduino/sam/system/USBHost/hid2.cpp | 101 ++ .../arduino/sam/system/USBHost/hidboot.cpp | 158 +++ hardware/arduino/sam/system/USBHost/hidboot.h | 478 +++++++++ .../arduino/sam/system/USBHost/hidusagestr.h | 976 ++++++++++++++++++ .../arduino/sam/system/USBHost/parsetools.cpp | 73 ++ .../arduino/sam/system/USBHost/parsetools.h | 143 +++ .../sam/system/USBHost/{ch9.h => usb_ch9.h} | 349 +++---- .../sam/system/libsam/include/USB_host.h | 1 + .../sam/system/libsam/include/uotghs_host.h | 8 +- .../sam/system/libsam/source/uotghs_host.c | 58 +- .../arduino_due_x/libsam_sam3x8e_gcc_rel.a | Bin 81262 -> 81662 bytes .../libsam_sam3x8e_gcc_rel.a.txt | 55 +- 26 files changed, 3810 insertions(+), 3251 deletions(-) delete mode 100644 hardware/arduino/sam/cores/arduino/validation_usb_host/descriptor_parser.h create mode 100644 hardware/arduino/sam/system/USBHost/address.h create mode 100644 hardware/arduino/sam/system/USBHost/confdescparser.h create mode 100644 hardware/arduino/sam/system/USBHost/examples/USB_desc/descriptor_strings.h create mode 100644 hardware/arduino/sam/system/USBHost/examples/USB_desc/test_usb_host.cpp delete mode 100644 hardware/arduino/sam/system/USBHost/examples/board_test/board_test.h delete mode 100644 hardware/arduino/sam/system/USBHost/examples/board_test/board_test.ino delete mode 100644 hardware/arduino/sam/system/USBHost/examples/conf_descr_dump/conf_descr_dump.ino delete mode 100644 hardware/arduino/sam/system/USBHost/examples/descriptor_parser/descriptor_parser.h delete mode 100644 hardware/arduino/sam/system/USBHost/examples/descriptor_parser/descriptor_parser.ino create mode 100644 hardware/arduino/sam/system/USBHost/hid.h create mode 100644 hardware/arduino/sam/system/USBHost/hid2.cpp create mode 100644 hardware/arduino/sam/system/USBHost/hidboot.cpp create mode 100644 hardware/arduino/sam/system/USBHost/hidboot.h create mode 100644 hardware/arduino/sam/system/USBHost/hidusagestr.h create mode 100644 hardware/arduino/sam/system/USBHost/parsetools.cpp create mode 100644 hardware/arduino/sam/system/USBHost/parsetools.h rename hardware/arduino/sam/system/USBHost/{ch9.h => usb_ch9.h} (73%) diff --git a/hardware/arduino/sam/cores/arduino/validation_usb_host/descriptor_parser.h b/hardware/arduino/sam/cores/arduino/validation_usb_host/descriptor_parser.h deleted file mode 100644 index 02df7d116..000000000 --- a/hardware/arduino/sam/cores/arduino/validation_usb_host/descriptor_parser.h +++ /dev/null @@ -1,288 +0,0 @@ -#ifndef _DESCRIPTOR_PARSER_ -#define _DESCRIPTOR_PARSER_ - -typedef void (*PARSE)( uint8_t* buffer, uint8_t pkt_size ); - -/* Common Messages */ -const char descr_len[] = "Descriptor Length:\t"; -const char descr_type[] = "Descriptor type:\t"; -const char class_str[] = "Class:\t\t\t"; -const char subclass_str[] = "Subclass:\t\t"; -const char protocol_str[] = "Protocol:\t\t"; -const char maxpktsize_str[] = "Max.packet size:\t"; -const char unk_msg[] = " Unknown"; -const char reserved_msg[] = "Reserved"; -const char rcode_error_msg[] = "\r\nRequest error. Return code: "; - -/* Endpoint attributes */ -const char control_tr[] = "Control"; -const char iso_tr[] = "Isochronous"; -const char bulk_tr[] = "Bulk"; -const char int_tr[] = "Interrupt"; - -const char* transfer_types[] = -{ - control_tr, - iso_tr, - bulk_tr, - int_tr -}; - -const char nosync_type[] = "No Synchronization"; -const char async_type[] = "Asynchronous"; -const char adaptive_type[] = "Adaptive"; -const char sync_type[] = "Synchronous"; - -const char* sync_types[] = -{ - nosync_type, - async_type, - adaptive_type, - sync_type -}; - -const char data_usage[] = "Data"; -const char feedback_usage[] = "Feedback"; -const char implicit_usage[] = "Implicit Feedback Data"; -const char reserved_usage[] = "Reserved"; - -const char* usage_types[] = -{ - data_usage, - feedback_usage, - implicit_usage, - reserved_usage -}; - -/* HID Country Codes */ -const char notsupported_cc[] = "Not Supported"; -const char arabic_cc[] = "Arabic"; -const char belgian_cc[] = "Belgian"; -const char canadianbi_cc[] = "Canadian-Bilingual"; -const char canadianfr_cc[] = "Canadian-French"; -const char czech_cc[] = "Czech Republic"; -const char danish_cc[] = "Danish"; -const char finnish_cc[] = "Finnish"; -const char french_cc[] = "French"; -const char german_cc[] = "German"; -const char greek_cc[] = "Greek"; -const char hebrew_cc[] = "Hebrew"; -const char hungary_cc[] = "Hungary"; -const char intl_cc[] = "International (ISO)"; -const char italian_cc[] = "Italian"; -const char japan_cc[] = "Japan (Katakana)"; -const char korean_cc[] = "Korean"; -const char latam_cc[] = "Latin American"; -const char dutch_cc[] = "Netherlands/Dutch"; -const char norwegian_cc[] = "Norwegian"; -const char persian_cc[] = "Persian (Farsi)"; -const char poland_cc[] = "Poland"; -const char portuguese_cc[] = "Portuguese"; -const char russia_cc[] = "Russia"; -const char slovakia_cc[] = "Slovakia"; -const char spanish_cc[] = "Spanish"; -const char swedish_cc[] = "Swedish"; -const char swiss_fr_cc[] = "Swiss/French"; -const char swiss_ger_cc[] = "Swiss/German"; -const char swiss_cc[] = "Switzerland"; -const char taiwan_cc[] = "Taiwan"; -const char turkish_q_cc[] = "Turkish-Q"; -const char uk_cc[] = "UK"; -const char us_cc[] = "US"; -const char yugo_cc[] = "Yugoslavia"; -const char turkish_f_cc[] = "Turkish-F"; - -const char* HID_Country_Codes[] = -{ - notsupported_cc, - arabic_cc, - belgian_cc, - canadianbi_cc, - canadianfr_cc, - czech_cc, - danish_cc, - finnish_cc, - french_cc, - german_cc, - greek_cc, - hebrew_cc, - hungary_cc, - intl_cc, - italian_cc, - japan_cc, - korean_cc, - latam_cc, - dutch_cc, - norwegian_cc, - persian_cc, - poland_cc, - portuguese_cc, - russia_cc, - slovakia_cc, - spanish_cc, - swedish_cc, - swiss_fr_cc, - swiss_ger_cc, - swiss_cc, - taiwan_cc, - turkish_q_cc, - uk_cc, - us_cc, - yugo_cc, - turkish_f_cc -}; - -/* HID report descriptor parser string definitions */ -/* Item type strings */ -const char btype_main[] = "Main"; -const char btype_global[] = "Global"; -const char btype_local[] = "Local"; -const char btype_reserved[] = "Reserved"; - -/* Item types strings array. Array index corresponds to bType */ -const char* btypes[] = -{ - btype_main, - btype_global, - btype_local, - btype_reserved -}; - -/* Main Item Tag Strings */ -const char main_tag_input[] = "Input "; -const char main_tag_output[] = "Output "; -const char main_tag_collection[] = "Collection "; -const char main_tag_feature[] = "Feature "; -const char main_tag_endcoll[] = "End Collection\r\n"; - -/* Main Item Tags Strings Array */ -const char* maintags[] = -{ - main_tag_input, - main_tag_output, - main_tag_collection, - main_tag_feature, - main_tag_endcoll -}; - -/* Global Item Tag Strings */ -const char global_tag_usagepage[] = "Usage Page "; -const char global_tag_logmin[] = "Logical Minimum "; -const char global_tag_logmax[] = "Logical Maximum "; -const char global_tag_physmin[] = "Physical Minimum "; -const char global_tag_physmax[] = "Physical Maximum "; -const char global_tag_unitexp[] = "Unit Exponent "; -const char global_tag_unit[] = "Unit "; -const char global_tag_repsize[] = "Report Size "; -const char global_tag_repid[] = "Report ID "; -const char global_tag_repcount[] = "Report Count "; -const char global_tag_push[] = "Push"; -const char global_tag_pop[] = "Pop"; - -/* Global Item Tag Strings Array */ -const char* globaltags[] = -{ - global_tag_usagepage, - global_tag_logmin, - global_tag_logmax, - global_tag_physmin, - global_tag_physmax, - global_tag_unitexp, - global_tag_unit, - global_tag_repsize, - global_tag_repid, - global_tag_repcount, - global_tag_push, - global_tag_pop -}; - -/* Local Item Tag Strings */ -const char local_tag_usage[] = "Usage "; -const char local_tag_usagemin[] = "Usage Minimum "; -const char local_tag_usagemax[] = "Usage Maximum "; -const char local_tag_desidx[] = "Designator Index "; -const char local_tag_desmin[] = "Designator Minimum "; -const char local_tag_desmax[] = "Designator Maximum "; -const char local_tag_stridx[] = "String Index "; -const char local_tag_strmin[] = "String Minimum "; -const char local_tag_strmax[] = "String Maximum "; -const char local_tag_delimiter[] = "Delimiter "; - -/* Local Item Tag Strings Array */ -const char* localtags[] = -{ - local_tag_usage, - local_tag_usagemin, - local_tag_usagemax, - local_tag_desidx, - local_tag_desmin, - local_tag_desmax, - local_tag_stridx, - local_tag_strmin, - local_tag_strmax, - local_tag_delimiter -}; - -/* Collection Types Strings */ -const char coll_phy[] = "Physical (group of axes)"; -const char coll_app[] = "Application (mouse, keyboard)"; -const char coll_log[] = "Logical (interrelated data)"; -const char coll_rep[] = "Report"; -const char coll_arr[] = "Named Array"; -const char coll_usw[] = "Usage Switch"; -const char coll_umod[] = "Usage Modifier"; - -/* Collection Types Strings Array */ -const char* collections[] = -{ - coll_phy, - coll_app, - coll_log, - coll_rep, - coll_arr, - coll_usw, - coll_umod -}; - -/* Usage Pages Strings */ -const char up_undef[] = "Undefined"; -const char up_gendesk[] = "Generic Desktop Controls"; -const char up_sim[] = "Simulation Controls"; -const char up_vr[] = "VR Controls"; -const char up_sport[] = "Sport Controls"; -const char up_game[] = "Game Controls"; -const char up_gendev[] = "Generic Device Controls"; -const char up_kbd[] = "Keyboard/Keypad"; -const char up_led[] = "LEDs"; -const char up_button[] = "Button"; -const char up_ord[] = "Ordinal"; -const char up_tele[] = "Telephony"; -const char up_cons[] = "Consumer"; -const char up_dig[] = "Digitizer"; -//const char up_res[] = "Reserved"; -const char up_pid[] = "PID Page"; -const char up_uni[] = "Unicode"; - -/* Usage Pages Strings Array */ -const char * usage_pages[] = -{ - up_undef, - up_gendesk, - up_sim, - up_vr, - up_sport, - up_game, - up_gendev, - up_kbd, - up_led, - up_button, - up_ord, - up_tele, - up_cons, - up_dig, - reserved_msg, - up_pid, - up_uni -}; - -#endif //_DESCRIPTOR_PARSER_ diff --git a/hardware/arduino/sam/cores/arduino/validation_usb_host/test_usb_host.cpp b/hardware/arduino/sam/cores/arduino/validation_usb_host/test_usb_host.cpp index 5ea2fbc7e..5bff4afc6 100644 --- a/hardware/arduino/sam/cores/arduino/validation_usb_host/test_usb_host.cpp +++ b/hardware/arduino/sam/cores/arduino/validation_usb_host/test_usb_host.cpp @@ -1,780 +1,78 @@ -/* - Copyright (c) 2012 Arduino. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - #include "variant.h" #include -#include "descriptor_parser.h" +#include -#define LOBYTE(x) ((char*)(&(x)))[0] -#define HIBYTE(x) ((char*)(&(x)))[1] -#define BUFSIZE 256 -#define DEVADDR 1 +/* -#define getReportDescr(addr, ep, nbytes, buf) Usb.ctrlReq(addr, ep, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, HID_DESCRIPTOR_REPORT, 0x0000, nbytes, buf) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +*/ +class MouseRptParser : public MouseReportParser +{ +protected: + virtual void OnMouseMove (MOUSEINFO *mi); + virtual void OnLeftButtonUp (MOUSEINFO *mi); + virtual void OnLeftButtonDown (MOUSEINFO *mi); + virtual void OnRightButtonUp (MOUSEINFO *mi); + virtual void OnRightButtonDown (MOUSEINFO *mi); + virtual void OnMiddleButtonUp (MOUSEINFO *mi); + virtual void OnMiddleButtonDown (MOUSEINFO *mi); +}; +void MouseRptParser::OnMouseMove(MOUSEINFO *mi) +{ + printf("Pos={%d,%d}\r\n", mi->dX, mi->dY); +}; +void MouseRptParser::OnLeftButtonUp (MOUSEINFO *mi) +{ + printf("L Butt Up\r\n"); +}; +void MouseRptParser::OnLeftButtonDown (MOUSEINFO *mi) +{ + printf("L Butt Dn\r\n"); +}; +void MouseRptParser::OnRightButtonUp (MOUSEINFO *mi) +{ + printf("R Butt Up\r\n"); +}; +void MouseRptParser::OnRightButtonDown (MOUSEINFO *mi) +{ + printf("R Butt Dn\r\n"); +}; +void MouseRptParser::OnMiddleButtonUp (MOUSEINFO *mi) +{ + printf("M Butt Up\r\n"); +}; +void MouseRptParser::OnMiddleButtonDown (MOUSEINFO *mi) +{ + printf("M Butt Dn\r\n"); +}; USBHost Usb; - -/* Forward declarations */ -void HIDreport_parse(uint8_t* buffer, uint8_t pkt_size); -void print_mainbitfield(uint8_t byte_toparse); -void printunkdescr(uint8_t* descr_ptr); -void printhid_descr(uint8_t* descr_ptr); -void printepdescr(uint8_t* descr_ptr); -void printintfdescr(uint8_t* descr_ptr); -void printconfdescr(uint8_t* descr_ptr); -uint32_t getconfdescr(uint32_t addr, uint32_t conf); -void classname_parse(byte class_number); -uint32_t getstrdescr(uint32_t addr, uint32_t idx); -uint32_t getdevdescr(uint32_t addr); - -_Pragma("pack(1)") - -typedef struct -{ - uint8_t bDescriptorType; - uint16_t wDescriptorLength; -} HID_CLASS_DESCRIPTOR; - -_Pragma("pack()") +HIDBoot HostMouse(&Usb); +MouseRptParser Prs; void setup() { cpu_irq_enable(); printf("\r\nProgram started:\r\n"); delay(200); + + HostMouse.SetReportParser(0,(HIDReportParser*)&Prs); } void loop() { - uint8_t tmpbyte = 0; - Usb.Task(); - - // If state configuring or higher - if (Usb.getUsbTaskState() >= USB_STATE_CONFIGURING) - { - // Printing device descriptor - printf("\r\nDevice addressed...\r\n"); - printf("Requesting device descriptor.\r\n"); - - // Number of configurations, 0 if error - tmpbyte = getdevdescr(DEVADDR); - if (tmpbyte == 0) - { - printf("\r\nDevice descriptor cannot be retrieved. Program Halted!\r\n"); - while (1) - ; - } - - // Print configuration descriptors for all configurations - for (uint8_t i = 0; i < tmpbyte; i++) - { - getconfdescr(DEVADDR, i); - } - - while (1) - ; - } -} - -/** - * Get device descriptor. - * Return number of configurations or zero on error. - */ -uint32_t getdevdescr(uint32_t addr) -{ - USB_DEVICE_DESCRIPTOR buf; - uint32_t rcode; - - rcode = Usb.getDevDescr(addr, 0, 0x12, (uint8_t*)&buf); - if (rcode) - { - printf("\r\n%s %lu\r\n", rcode_error_msg, rcode); - return 0; - } - printf("\r\nDevice descriptor: \r\n"); - - // Descriptor length - printf("%s0x%x\r\n", descr_len, buf.bLength); - - // Descriptor type - printf("%s0x%x\r\n", descr_type, buf.bDescriptorType); - - // USB Version - printf("USB version:\t\t0x%x\r\n", buf.bcdUSB); - - // Device class - printf("%s0x%x", class_str, buf.bDeviceClass); - classname_parse(buf.bDeviceClass); - printf("\r\n"); - - // Device Subclass - printf("%s0x%x\r\n", subclass_str, buf.bDeviceSubClass); - - // Device Protocol - printf("%s0x%x\r\n", protocol_str, buf.bDeviceProtocol); - - // Max.packet size - printf("%s0x%x\r\n", maxpktsize_str, buf.bMaxPacketSize0); - - // VID - printf("Vendor ID:\t\t0x%x\r\n", buf.idVendor); - - // PID - printf("Product ID:\t\t0x%x\r\n", buf.idProduct); - - // Revision - printf("Revision ID:\t\t0x%x\r\n", buf.bcdDevice); - - // Mfg.string - printf("Mfg.string index:\t0x%x", buf.iManufacturer); - getstrdescr(addr, buf.iManufacturer); - - // Prod.string - printf("Prod.string index:\t0x%x", buf.iProduct); - getstrdescr(addr, buf.iProduct); - - // Serial number string - printf("Serial number index:\t0x%x", buf.iSerialNumber); - getstrdescr(addr, buf.iSerialNumber); - - // Number of configurations - printf("Number of conf.:\t0x%x\r\n", buf.bNumConfigurations); - - return buf.bNumConfigurations; -} - -/** - * Get string descriptor. - * Takes device address and string index. - */ -uint32_t getstrdescr(uint32_t addr, uint32_t idx) -{ - uint8_t buf[BUFSIZE]; - uint32_t rcode; - uint32_t length; - uint32_t i; - uint16_t langid; - - if (idx == 0) - { - // Don't try to get index zero - printf("\r\n"); - return 0; - } - - rcode = Usb.getStrDescr(addr, 0, 1, 0, 0, buf); - // Get language table length - if (rcode) - { - printf("\r\nError retrieving LangID table length!\r\n"); - return rcode; - } - - // Length is the first byte - length = buf[0]; - // Get language table - rcode = Usb.getStrDescr(addr, 0, length, 0, 0, buf); - if (rcode) - { - printf("\r\nError retrieving LangID table!\r\n"); - return rcode; - } - - // Get first langid - langid = buf[3] << 8; - // Bytes are swapped to account for endiannes - langid |= (buf[2] & 0xff); - - rcode = Usb.getStrDescr(addr, 0, 1, idx, langid, buf); - if (rcode) - { - printf("\r\nError retrieving string length!\r\n"); - return rcode; - } - - length = (buf[0] < 254 ? buf[0] : 254); - printf(" Length: %lu", length); - rcode = Usb.getStrDescr(addr, 0, length, idx, langid, buf); - if (rcode) - { - printf("\r\nError retrieving string!\r\n"); - return rcode; - } - - printf(" Contents: "); - for (i = 2; i < length; i += 2) - { - printf("%c", buf[i]); - } - printf("\r\n"); - - return idx; -} - - -/** - * Returns string to class name - */ -void classname_parse(uint8_t class_number) -{ - switch(class_number) { - case 0x00: - printf(" Use class information in the Interface Descriptor"); - break; - case 0x01: - printf(" Audio"); - break; - case 0x02: - printf(" Communications and CDC Control"); - break; - case 0x03: - printf(" HID (Human Interface Device)"); - break; - case 0x05: - printf(" Physical"); - break; - case 0x06: - printf(" Image"); - break; - case 0x07: - printf(" Printer"); - break; - case 0x08: - printf(" Mass Storage"); - break; - case 0x09: - printf(" Hub"); - break; - case 0x0a: - printf(" CDC-Data"); - break; - case 0x0b: - printf(" Smart Card"); - break; - case 0x0d: - printf(" Content Security"); - break; - case 0x0e: - printf(" Video"); - break; - case 0x0f: - printf(" Personal Healthcare"); - break; - case 0xdc: - printf("Diagnostic Device"); - break; - case 0xe0: - printf(" Wireless Controller"); - break; - case 0xef: - printf(" Miscellaneous"); - break; - case 0xfe: - printf(" Application Specific"); - break; - case 0xff: - printf(" Vendor Specific"); - break; - default: - break; - } -} - - -/** - * Print configuration descriptor. - */ -uint32_t getconfdescr(uint32_t addr, uint32_t conf) -{ - uint8_t buf[BUFSIZE]; - uint8_t* buf_ptr = buf; - uint32_t rcode = 0; - uint8_t confdescr_length = 0; - uint8_t confdescr_type = 0; - uint32_t total_length = 0; - - printf("\r\nConfiguration number %lu:\r\n", conf); - - rcode = Usb.getConfDescr(addr, 0, 4, conf, buf); //get total length - if (rcode) - { - printf("\r\nError retrieving configuration length. Error code %lu\r\n", rcode); - return(0); - } - - total_length = buf[3] << 8; - total_length |= (buf[2] & 0xff); - - if (total_length > BUFSIZE) - { - // Check if total length is larger than buffer - printf("Total length truncated to %d bytes\r\n", BUFSIZE); - total_length = BUFSIZE; - } - - // Get the whole descriptor - rcode = Usb.getConfDescr(addr, 0, total_length, conf, buf); - - while (buf_ptr < buf + total_length) - { - // Parsing descriptors - confdescr_length = *(buf_ptr); - confdescr_type = *(buf_ptr + 1); - switch (confdescr_type) - { - case(USB_DESCRIPTOR_CONFIGURATION): - printconfdescr(buf_ptr); - break; - case(USB_DESCRIPTOR_INTERFACE): - printintfdescr(buf_ptr); - break; - case(USB_DESCRIPTOR_ENDPOINT): - printepdescr(buf_ptr); - break; - case(HID_DESCRIPTOR_HID): - printhid_descr(buf_ptr); - break; - default: - printunkdescr(buf_ptr); - break; - } - - // Advance buffer pointer - buf_ptr = (buf_ptr + confdescr_length); - } - - return 0; -} - -/** - * Print configuration descriptor. - */ -void printconfdescr(uint8_t* descr_ptr) -{ - USB_CONFIGURATION_DESCRIPTOR* conf_ptr = (USB_CONFIGURATION_DESCRIPTOR*)descr_ptr; - uint8_t tmpbyte = 0; - - printf("\r\n\nConfiguration descriptor:\r\n"); - printf("Total length:\t\t%d\r\n", conf_ptr->wTotalLength); - - printf("\r\nNumber of interfaces:\t%d\r\n", conf_ptr->bNumInterfaces); - - printf("Configuration value:\t%d\r\n", conf_ptr->bConfigurationValue); - - printf("Configuration string:\t"); - tmpbyte = conf_ptr->iConfiguration; - printf("0x%x", tmpbyte); - getstrdescr(DEVADDR, tmpbyte); - printf("Attributes:\t\t"); - tmpbyte = conf_ptr->bmAttributes; - printf("0x%x", tmpbyte); - - if (tmpbyte & 0x40) - { - // D6 - printf(" Self-powered\r\n"); - } - - if (tmpbyte & 0x20) - { - // D5 - printf(" Remote Wakeup\r\n"); - } - - printf("Max.power:\t\t"); - tmpbyte = conf_ptr->bMaxPower; - printf("0x%x", tmpbyte); - printf(" "); - printf("%d", (tmpbyte * 2)); - printf("ma\r\n"); -} - -/** - * Print interface descriptor. - */ -void printintfdescr(uint8_t* descr_ptr) -{ - USB_INTERFACE_DESCRIPTOR* intf_ptr = (USB_INTERFACE_DESCRIPTOR*)descr_ptr; - uint8_t tmpbyte = 0; - - printf("\r\nInterface descriptor:\r\n"); - printf("Interface number:\t%d\r\n", intf_ptr->bInterfaceNumber); - printf("Alternate setting:\t%d\r\n", intf_ptr->bAlternateSetting); - printf("Endpoints:\t\t%d\r\n", intf_ptr->bNumEndpoints); - - printf("%s", class_str); - tmpbyte = intf_ptr->bInterfaceClass; - printf("0x%x", tmpbyte); - classname_parse(tmpbyte); - printf("\r\n"); - - printf("%s%d\r\n", subclass_str, intf_ptr->bInterfaceSubClass); - printf("%s%d\r\n", protocol_str, intf_ptr->bInterfaceProtocol); - - printf("Interface string:\t"); - tmpbyte = intf_ptr->iInterface; - printf("0x%x", tmpbyte); - getstrdescr(DEVADDR, tmpbyte); -} - -/** - * Print endpoint descriptor. - */ -void printepdescr(uint8_t* descr_ptr) -{ - USB_ENDPOINT_DESCRIPTOR* ep_ptr = (USB_ENDPOINT_DESCRIPTOR*)descr_ptr; - uint8_t tmpbyte = 0; - - printf("\r\nEndpoint descriptor:\r\n"); - printf("Endpoint address:\t"); - tmpbyte = ep_ptr->bEndpointAddress; - printf("0x%x", tmpbyte & 0x0f); - printf(" Direction: "); - (tmpbyte & 0x80) ? printf("IN\r\n") : printf("OUT\r\n"); - - printf("Attributes:\t\t"); - tmpbyte = ep_ptr->bmAttributes; - printf("0x%x", tmpbyte); - printf(" Transfer type: %s", transfer_types[(tmpbyte & 0x03)]); - - if ((tmpbyte & 0x03) == 1) - { - // Isochronous Transfer - printf(", Sync Type: "); - printf("%s", sync_types[(tmpbyte & 0x0c)]); - printf(", Usage Type: "); - printf("%s", usage_types[(tmpbyte & 0x30)]); - } - printf("\r\n"); - printf("%s%d\r\n", maxpktsize_str, ep_ptr->wMaxPacketSize); - - printf("Polling interval:\t"); - tmpbyte = ep_ptr->bInterval; - printf("0x%x", tmpbyte); - printf(" "); - printf("%d", tmpbyte); - printf(" ms\r\n"); -} - -/** - * Print HID descriptor. - */ -void printhid_descr(uint8_t* descr_ptr) -{ - //PARSE pf = HIDreport_parse; - USB_HID_DESCRIPTOR* hid_ptr = (USB_HID_DESCRIPTOR*)descr_ptr; - uint8_t tmpbyte = 0; - - printf("\r\nHID descriptor:\r\n"); - printf("Descriptor length:\t"); - tmpbyte = hid_ptr->bLength; - printf("0x%x %d bytes\r\n", tmpbyte, tmpbyte); - printf("HID version:\t\t0x%x\r\n", hid_ptr->bcdHID); - tmpbyte = hid_ptr->bCountryCode; - printf("Country Code:\t\t%d ", tmpbyte); - (tmpbyte > 35) ? printf("Reserved\r\n") : printf("%s\r\n", HID_Country_Codes[tmpbyte]); - tmpbyte = hid_ptr->bNumDescriptors; - printf("Class Descriptors:\t%d\r\n", tmpbyte); - - // Printing class descriptors - // Advance buffer pointer - descr_ptr += 6; - for (uint8_t i = 0; i < tmpbyte; i++) - { - uint8_t tmpdata = 0; - HID_CLASS_DESCRIPTOR* hidclass_ptr = (HID_CLASS_DESCRIPTOR*)descr_ptr; - tmpdata = hidclass_ptr->bDescriptorType; - printf("Class Descriptor Type:\t0x%x", tmpdata); - - if ((tmpdata < 0x21) || (tmpdata > 0x2f)) - { - printf(" Invalid"); - } - - switch(tmpdata) - { - case 0x21: - printf(" HID\r\n"); - break; - case 0x22: - printf(" Report\r\n"); - break; - case 0x23: - printf(" Physical\r\n"); - break; - default: - printf(" Reserved\r\n"); - break; - } - - printf("Class Descriptor Size: %d bytes\r\n", hidclass_ptr->wDescriptorLength); - - printf("\r\nHID report descriptor:\r\n"); - uint8_t buf[hidclass_ptr->wDescriptorLength]; - getReportDescr(DEVADDR, 0 , hidclass_ptr->wDescriptorLength, (uint8_t*)&buf); - HIDreport_parse(buf, hidclass_ptr->wDescriptorLength); - - // Advance to the next record - descr_ptr += 3; - } - printf("\r\n"); -} - -/** - * Print unknown descriptor. - */ -void printunkdescr(uint8_t* descr_ptr) -{ - uint8_t length = *descr_ptr; - uint32_t i = 0; - - printf("\r\nUnknown descriptor:\r\n"); - printf("Length:\t\t%d\r\n", *descr_ptr); - printf("Type:\t\t %d\r\n", *(descr_ptr + 1)); - printf("Contents:\t"); - descr_ptr += 2; - - for (i = 0; i < length; i++) - { - printf("%d", *descr_ptr); - descr_ptr++; - } - - printf("\r\n"); -} - -/** - * Print bitfields in main items. - */ -void print_mainbitfield(uint8_t byte_toparse) -{ - (byte_toparse & 0x01) ? printf("Constant,") : printf("Data,"); //bit 0 - (byte_toparse & 0x02) ? printf("Variable,") : printf("Array,"); //bit 1 - (byte_toparse & 0x04) ? printf("Relative,") : printf("Absolute,"); //... - (byte_toparse & 0x08) ? printf("Wrap,") : printf("No Wrap,"); - (byte_toparse & 0x10) ? printf("Non Linear,") : printf("Linear,"); - (byte_toparse & 0x20) ? printf("No preferred,") : printf("Preferred State,"); - (byte_toparse & 0x40) ? printf("Null State,") : printf("No Null Position,"); //bit 6 - (byte_toparse & 0x40) ? printf("Volatile(ignore for Input),") : printf("Non-volatile(Ignore for Input),"); //bit 7 -} - -/** - * HID Report Desriptor Parser Callback. - * Called repeatedly from Control transfer function. - */ -void HIDreport_parse(uint8_t* buffer, uint8_t pkt_size) -{ -#define B_SIZE 0x03 //bSize bitmask -#define B_TYPE 0x0c //bType bitmask -#define B_TAG 0xf0 //bTag bitmask - - // Parser states - enum STATE { ITEM_START, DATA_PARSE }; - static STATE state = ITEM_START; - static uint8_t databytes_left = 0; - static uint8_t databytes_left2 = 0; - static uint8_t prefix; //item prefix - type and tag - uint8_t byte_toparse; - uint8_t bType; - uint8_t tmpbyte; - uint32_t i = 0, j = 0; - - while (1) - { - if (i < pkt_size) - { - i = i + 1; - byte_toparse = buffer[i]; - } - else - { - return; - } - - switch(state) - { - // Start of the record - case ITEM_START: - // Store prefix for databyte parsing - prefix = byte_toparse >> 2; - tmpbyte = byte_toparse & B_SIZE; - - // Get item length - (tmpbyte == 0x03) ? databytes_left = 4 : databytes_left = tmpbyte; - if (databytes_left) - { - // Read bytes after prefix - state = DATA_PARSE; - } - printf("bSize: %d", databytes_left); - databytes_left2 = databytes_left; - - // Get item type - bType = (byte_toparse & B_TYPE) >> 2; - printf(" bType: %s", btypes[bType]); - - // Get item tag - printf("\t\tbTag: "); - tmpbyte = (byte_toparse & B_TAG) >> 4 ; - switch(bType) - { - case 0: // Main - if (tmpbyte < 0x08) - { - printf("Invalid Tag"); - } - else if (tmpbyte > 0x0c) - { - printf("%s", reserved_msg); - } - else - { - printf("%s", maintags[tmpbyte - 8]); - } - break; - - case 1: // Global - (tmpbyte > 0x0b) ? printf("%s", reserved_msg) : printf("%s", globaltags[tmpbyte]); - break; - - case 2: // Local - (tmpbyte > 0x0a) ? printf("%s", reserved_msg) : printf("%s", localtags[tmpbyte]); - break; - - default: - break; - } - break; - - case DATA_PARSE: - switch(prefix) - { - case 0x20: // Main Input - case 0x24: // Main Output - case 0x2c: // Main Feature - // TODO: add parsing 8th bit - print_mainbitfield(byte_toparse); - break; - - case 0x28: //Main Collection - if ((byte_toparse > 0x06) && (byte_toparse < 0x80)) - { - printf("%s", reserved_msg); - } - else if ((byte_toparse > 0x7f) && (byte_toparse <= 0xff)) - { - printf("Vendor-defined"); - } - else - { - printf("%s", collections[byte_toparse]); - } - break; - - //case 0x30: //Main End Collection - case 0x01: //Global Usage Page - switch(byte_toparse) - { - // See HID Usage Tables doc v.1.12 page 14 - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x08: - case 0x09: - case 0x0a: - case 0x0b: - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: - case 0x10: - printf("%s", usage_pages[byte_toparse]); - break; - - case 0x14: - printf("Alphanumeric Display"); - break; - - case 0x40: - printf("Medical Instruments"); - break; - - case 0x80: - case 0x81: - case 0x82: - case 0x83: - printf("Monitor page"); - break; - - case 0x84: - case 0x85: - case 0x86: - case 0x87: - printf("Power page"); - break; - - case 0x8c: - printf("Bar Code Scanner page"); - break; - - case 0x8d: - printf("Scale page"); - break; - - case 0x8e: - printf("Magnetic Stripe Reading (MSR) Devices"); - break; - - case 0x8f: - printf("Reserved Point of Sale pages"); - break; - - case 0x90: - printf("Camera Control Page"); - break; - - case 0x91: - printf("Arcade Page"); - break; - - default: - break; - } - } - - databytes_left--; - - if (!databytes_left) - { - printf(" (data=0x"); - for (j = 0; j < databytes_left2; ++j) - printf("%02x", buffer[i - j]); - printf(")\r\n"); - - state = ITEM_START; - } - break; - } - } } diff --git a/hardware/arduino/sam/system/USBHost/Usb.cpp b/hardware/arduino/sam/system/USBHost/Usb.cpp index 19d50ba3f..175f21ca8 100644 --- a/hardware/arduino/sam/system/USBHost/Usb.cpp +++ b/hardware/arduino/sam/system/USBHost/Usb.cpp @@ -1,26 +1,33 @@ -/* Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com */ -/* USB functions */ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com +*/ +/* USB functions */ #include "Arduino.h" #include "Usb.h" #include -//#define TRACE_USBHOST(x) x -#define TRACE_USBHOST(x) - static uint32_t usb_error = 0; static uint32_t usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; -DEV_RECORD devtable[USB_NUMDEVICES + 1]; - -// Endpoint data structure used during enumeration for uninitialized device. -EP_RECORD dev0ep; - /** * Class Constructor. */ -USBHost::USBHost () { +USBHost::USBHost () : bmHubPre(0) +{ // Set up state machine usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; @@ -33,21 +40,8 @@ USBHost::USBHost () { */ void USBHost::init() { - - uint8_t i = 0; - - for (i = 0; i < (USB_NUMDEVICES + 1); i++) - { - // Clear device table - devtable[i].epinfo = 0; - devtable[i].devclass = 0; - } - - // Set single EP for uninitialized device - devtable[0].epinfo = &dev0ep; - /* dev0ep.sndToggle = bmSNDTOG0; //set DATA0/1 toggles to 0 - dev0ep.rcvToggle = bmRCVTOG0; -*/ + devConfigIndex = 0; + bmHubPre = 0; } /** @@ -67,23 +61,77 @@ void USBHost::setUsbTaskState(uint32_t state) } /** - * Get device table entry. + * Get end point info from address. */ -EP_RECORD* USBHost::getDevTableEntry(uint32_t addr, uint32_t ep) +EpInfo* USBHost::getEpInfoEntry(uint32_t addr, uint32_t ep) { - EP_RECORD* ptr = 0; + UsbDevice *p = addrPool.GetUsbDevicePtr(addr); - ptr = devtable[addr].epinfo; - ptr += ep; - return ptr; + if (!p || !p->epinfo) + return NULL; + + EpInfo *pep = p->epinfo; + + for (uint32_t i = 0; i < p->epcount; i++) + { + if (pep->epAddr == ep) + return pep; + + pep++; + } + return NULL; } /** - * Set device table entry. + * Set device end point entry. + * Each device is different and has different number of endpoints. + * This function plugs endpoint record structure, defined in application to devtable. */ -void USBHost::setDevTableEntry(uint32_t addr, EP_RECORD* eprecord_ptr) +uint32_t USBHost::setEpInfoEntry(uint32_t addr, uint32_t epcount, EpInfo* eprecord_ptr) { - devtable[addr].epinfo = eprecord_ptr; + if (!eprecord_ptr) + return USB_ERROR_INVALID_ARGUMENT; + + UsbDevice *p = addrPool.GetUsbDevicePtr(addr); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->address = addr; + p->epinfo = eprecord_ptr; + p->epcount = epcount; + + return 0; +} + +uint32_t USBHost::SetAddress(uint32_t addr, uint32_t ep, EpInfo **ppep, uint32_t &nak_limit) +{ + UsbDevice *p = addrPool.GetUsbDevicePtr(addr); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + if (!p->epinfo) + return USB_ERROR_EPINFO_IS_NULL; + + *ppep = getEpInfoEntry(addr, ep); + + if (!*ppep) + return USB_ERROR_EP_NOT_FOUND_IN_TBL; + + nak_limit = (0x0001UL << ( ( (*ppep)->bmNakPower > USB_NAK_MAX_POWER ) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower) ); + nak_limit--; + + // Set peripheral address + //regWr( rPERADDR, addr ); + uhd_configure_address(ep, addr); + + ///////////////////////////////////////////////////////////////////////////////////////////// Y A TIL QQCHOSE A FAIRE??? + //uint8_t mode = regRd( rMODE ); + // Set bmLOWSPEED and bmHUBPRE in case of low-speed device, reset them otherwise + //regWr( rMODE, (p->lowspeed) ? mode | bmLOWSPEED | bmHubPre : mode & ~(bmHUBPRE | bmLOWSPEED)); + + return 0; } /** @@ -95,17 +143,22 @@ void USBHost::setDevTableEntry(uint32_t addr, EP_RECORD* eprecord_ptr) * 00 = success * 01-0f = non-zero HRSLT */ -uint32_t USBHost::ctrlReq(uint32_t addr, uint32_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, uint16_t wInd, uint32_t nbytes, uint8_t* dataptr, uint32_t nak_limit) +uint32_t USBHost::ctrlReq(uint32_t addr, uint32_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, uint16_t wInd, uint16_t total, uint32_t nbytes, uint8_t* dataptr, USBReadParser *p) { // Request direction, IN or OUT uint32_t direction = 0; uint32_t rcode = 0; SETUP_PKT setup_pkt; + EpInfo *pep = 0; + uint32_t nak_limit; + TRACE_USBHOST(printf(" => ctrlReq\r\n");) // Set peripheral address - //regWr(rPERADDR, addr); + rcode = SetAddress(addr, ep, &pep, nak_limit); + if (rcode) + return rcode; // Allocate EP0 with default 8 bytes size if not already initialized rcode = UHD_EP0_Alloc(0, 8); @@ -116,21 +169,19 @@ uint32_t USBHost::ctrlReq(uint32_t addr, uint32_t ep, uint8_t bmReqType, uint8_t } // Determine request direction - if (bmReqType & 0x80) - { - direction = 1; - } + direction = (( bmReqType & 0x80 ) > 0); // Fill in setup packet - setup_pkt.ReqType_u.bmRequestType = bmReqType; - setup_pkt.bRequest = bRequest; - setup_pkt.wVal_u.wValueLo = wValLo; - setup_pkt.wVal_u.wValueHi = wValHi; - setup_pkt.wIndex = wInd; - setup_pkt.wLength = nbytes; + setup_pkt.ReqType_u.bmRequestType = bmReqType; + setup_pkt.bRequest = bRequest; + setup_pkt.wVal_u.wValueLo = wValLo; + setup_pkt.wVal_u.wValueHi = wValHi; + setup_pkt.wIndex = wInd; + setup_pkt.wLength = total; - // Transfer to setup packet FIFO + // Configure and write the setup packet into the FIFO //bytesWr(rSUDFIFO, 8, (uint8_t *)&setup_pkt); + uhd_configure_pipe_token(0, tokSETUP); UHD_EP_Write(ep, 8, (uint8_t *)&setup_pkt); // Dispatch packet @@ -145,7 +196,39 @@ uint32_t USBHost::ctrlReq(uint32_t addr, uint32_t ep, uint8_t bmReqType, uint8_t // Data stage (if present) if (dataptr != 0) { - rcode = ctrlData(addr, ep, nbytes, dataptr, direction); + if (direction) + { + // IN transfer + TRACE_USBHOST(printf(" => ctrlData IN\r\n");) + uint32_t left = total; + + while (left) + { + // Bytes read into buffer + uint32_t read = nbytes; + + rcode = InTransfer(pep, nak_limit, &read, dataptr); + if (rcode) + return rcode; + + // Invoke callback function if inTransfer completed successfuly and callback function pointer is specified + if (!rcode && p) + ((USBReadParser*)p)->Parse(read, dataptr, total - left); + + left -= read; + + if (read < nbytes) + break; + } + } + else + { + // OUT transfer + //devtable[addr].epinfo[ep].sndToggle = bmSNDTOG1; + TRACE_USBHOST(printf(" => ctrlData OUT\r\n");) + rcode = OutTransfer(pep, nak_limit, nbytes, dataptr); + } + if (rcode) { TRACE_USBHOST(printf("/!\\ USBHost::ctrlData : Data packet error: %lu\r\n", rcode);) @@ -154,59 +237,7 @@ uint32_t USBHost::ctrlReq(uint32_t addr, uint32_t ep, uint8_t bmReqType, uint8_t } // Status stage - rcode = ctrlStatus(ep, direction); - return (rcode); - -} - -/** - * Control transfer with status stage and no data stage. - * Assumes peripheral address is already set. - */ -uint32_t USBHost::ctrlStatus(uint32_t ep, uint32_t direction, uint32_t nak_limit) -{ - uint32_t rcode = 0; - - if (direction) - { - // GET - TRACE_USBHOST(printf(" => ctrlStatus OUTHS\r\n");) - rcode = dispatchPkt(tokOUTHS, ep, nak_limit); - } - else - { - // SET - TRACE_USBHOST(printf(" => ctrlStatus INHS\r\n");) - rcode = dispatchPkt(tokINHS, ep, nak_limit); - } - - return (rcode); -} - -/** - * Control transfer with data stage. Stages 2 and 3 of control transfer. - * Assumes peripheral address is set and setup packet has been sent. - */ -uint32_t USBHost::ctrlData(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* dataptr, uint32_t direction, uint32_t nak_limit) -{ - uint32_t rcode = 0; - - if (direction) - { - // IN transfer - //devtable[addr].epinfo[ep].rcvToggle = bmRCVTOG1; - TRACE_USBHOST(printf(" => ctrlData IN\r\n");) - rcode = inTransfer(addr, ep, nbytes, dataptr, nak_limit); - return (rcode); - } - else - { - // OUT transfer - //devtable[addr].epinfo[ep].sndToggle = bmSNDTOG1; - TRACE_USBHOST(printf(" => ctrlData OUT\r\n");) - rcode = outTransfer(addr, ep, nbytes, dataptr, nak_limit); - return (rcode); - } + return dispatchPkt((direction) ? tokOUTHS : tokINHS, ep, nak_limit ); } /** @@ -218,12 +249,27 @@ uint32_t USBHost::ctrlData(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* * f0 means RCVDAVIRQ error * fe USB xfer timeout */ -uint32_t USBHost::inTransfer(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* data, uint32_t nak_limit) + uint32_t USBHost::inTransfer(uint32_t addr, uint32_t ep, uint32_t *nbytesptr, uint8_t* data) +{ + EpInfo *pep = NULL; + uint32_t nak_limit = 0; + + uint32_t rcode = SetAddress(addr, ep, &pep, nak_limit); + + if (rcode) + return rcode; + + return InTransfer(pep, nak_limit, nbytesptr, data); +} + +uint32_t USBHost::InTransfer(EpInfo *pep, uint32_t nak_limit, uint32_t *nbytesptr, uint8_t* data) { uint32_t rcode = 0; uint32_t pktsize = 0; - uint32_t maxpktsize = devtable[addr].epinfo[ep].MaxPktSize; - uint32_t xfrlen = 0; + uint16_t nbytes = *nbytesptr; + uint8_t maxpktsize = pep->maxPktSize; + + *nbytesptr = 0; // Set toggle value //regWr(rHCTL, devtable[addr].epinfo[ep].rcvToggle); @@ -232,7 +278,7 @@ uint32_t USBHost::inTransfer(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_ { // Use a 'return' to exit this loop // IN packet to EP-'endpoint'. Function takes care of NAKS. - rcode = dispatchPkt(tokIN, ep, nak_limit); + rcode = dispatchPkt(tokIN, pep->epAddr, nak_limit); if (rcode) { // Should be 0, indicating ACK. Else return error code. @@ -250,21 +296,21 @@ uint32_t USBHost::inTransfer(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_ // Number of received bytes //pktsize = regRd(rRCVBC); //data = bytesRd(rRCVFIFO, pktsize, data); - pktsize = uhd_byte_count(ep); + pktsize = uhd_byte_count(pep->epAddr); if (nbytes < pktsize) printf("ce test n'a pas ete fait...\r\n"); - data += UHD_EP_Read(ep, pktsize, data); + data += UHD_EP_Read(pep->epAddr, pktsize, data); // Clear the IRQ & free the buffer //regWr(rHIRQ, bmRCVDAVIRQ); // Add this packet's byte count to total transfer length - xfrlen += pktsize; + *nbytesptr += pktsize; // The transfer is complete under two conditions: // 1. The device sent a short packet (L.T. maxPacketSize) // 2. 'nbytes' have been transferred. - if ((pktsize < maxpktsize) || (xfrlen >= nbytes)) + if ((pktsize < maxpktsize) || (*nbytesptr >= nbytes)) { /*// Have we transferred 'nbytes' bytes? if (regRd(rHRSL) & bmRCVTOGRD) @@ -282,89 +328,6 @@ uint32_t USBHost::inTransfer(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_ } } -/** - * Google variant of inTransfer. - * Pasted verbatim from ADK. Returns length instead of error code. - * Provided for compatibility with Google Open Accessory code. - */ -int32_t USBHost::newInTransfer(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* data, uint32_t nak_limit) -{ -/* - uint32_t rcode = 0; - uint32_t pktsize = 0; - uint32_t maxpktsize = devtable[addr].epinfo[ep].MaxPktSize; - uint32_t xfrlen = 0; - - // Set toggle value - regWr(rHCTL, devtable[addr].epinfo[ep].rcvToggle); - - while (1) - { - // Use a 'return' to exit this loop - // IN packet to EP-'endpoint'. Function takes care of NAKS. - rcode = dispatchPkt(tokIN, ep, nak_limit); - if (rcode) - { - // Should be 0, indicating ACK. Else return error code. - return -1; - } - - // check for RCVDAVIRQ and generate error if not present - // the only case when absense of RCVDAVIRQ makes sense is when toggle error occured. Need to add handling for that - if ((regRd(rHIRQ) & bmRCVDAVIRQ) == 0) - { - // Receive error - return -1; - } - - // Number of received bytes - pktsize = regRd(rRCVBC); - - if (xfrlen + pktsize <= nbytes) - { - // Only copy the data to the buffer if the buffer's large enough. - data = bytesRd(rRCVFIFO, pktsize, data); - } - - // Clear the IRQ & free the buffer - regWr(rHIRQ, bmRCVDAVIRQ); - - // Add this packet's byte count to total transfer length - xfrlen += pktsize; - - // The transfer is complete under two conditions: - // 1. The device sent a short packet (L.T. maxPacketSize) - // 2. 'nbytes' have been transferred. - if ((pktsize < maxpktsize) || (xfrlen >= nbytes)) - { - // Have we transferred 'nbytes' bytes? - if (regRd(rHRSL) & bmRCVTOGRD) - { - // Save toggle value - devtable[addr].epinfo[ep].rcvToggle = bmRCVTOG1; - } - else - { - devtable[addr].epinfo[ep].rcvToggle = bmRCVTOG0; - } - - if (xfrlen <= nbytes) - { - return xfrlen; - } - else - { - // Buffer overflow avoided so treat it as an error rather - // than return partial data. - return -1; - } - } - } -*/ -printf("error2\r\n"); -return 1; -} - /** * OUT transfer to arbitrary endpoint. * Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. @@ -374,95 +337,87 @@ return 1; * * Major part of this function borrowed from code shared by Richard Ibbotson */ -uint32_t USBHost::outTransfer(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* data, uint32_t nak_limit) +uint32_t USBHost::outTransfer(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* data) { /* - uint32_t rcode, retry_count; - uint8_t* data_p = data; - uint32_t bytes_tosend, nak_count; - uint32_t bytes_left = nbytes; - uint32_t maxpktsize = devtable[addr].epinfo[ep].MaxPktSize; - uint32_t timeout = millis() + USB_XFER_TIMEOUT; + EpInfo *pep = NULL; + uint16_t nak_limit; - if (!maxpktsize) - { - // Todo: move this check close to epinfo init. Make it 1< pktsize <64 - return 0xFE; - } + uint8_t rcode = SetAddress(addr, ep, &pep, nak_limit); - // Set toggle value - regWr(rHCTL, devtable[addr].epinfo[ep].sndToggle); + if (rcode) + return rcode; - while (bytes_left) + return OutTransfer(pep, nak_limit, nbytes, data); +*/ +printf("j'ai beau etre matinal.. j'ai mal!!!!\r\n"); +return 1; +} + +uint32_t USBHost::OutTransfer(EpInfo *pep, uint32_t nak_limit, uint32_t nbytes, uint8_t *data) +{ +/* + uint8_t rcode, retry_count; + uint8_t *data_p = data; //local copy of the data pointer + uint16_t bytes_tosend, nak_count; + uint16_t bytes_left = nbytes; + + uint8_t maxpktsize = pep->maxPktSize; + + if (maxpktsize < 1 || maxpktsize > 64) + return USB_ERROR_INVALID_MAX_PKT_SIZE; + + unsigned long timeout = millis() + USB_XFER_TIMEOUT; + + regWr( rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0 ); //set toggle value + + while( bytes_left ) { retry_count = 0; nak_count = 0; - bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left; + bytes_tosend = ( bytes_left >= maxpktsize ) ? maxpktsize : bytes_left; + bytesWr( rSNDFIFO, bytes_tosend, data_p ); //filling output FIFO + regWr( rSNDBC, bytes_tosend ); //set number of bytes + regWr( rHXFR, ( tokOUT | pep->epAddr )); //dispatch packet + while(!(regRd( rHIRQ ) & bmHXFRDNIRQ )); //wait for the completion IRQ + regWr( rHIRQ, bmHXFRDNIRQ ); //clear IRQ + rcode = ( regRd( rHRSL ) & 0x0f ); - // Fill output FIFO - bytesWr(rSNDFIFO, bytes_tosend, data_p); - // Set number of bytes - regWr(rSNDBC, bytes_tosend); - - // Dispatch packet - regWr(rHXFR, (tokOUT | ep)); - - // Wait for the completion IRQ - while (!(regRd(rHIRQ) & bmHXFRDNIRQ)) - ; - - // Clear IRQ - regWr(rHIRQ, bmHXFRDNIRQ); - rcode = (regRd(rHRSL) & 0x0f); - - while (rcode && (timeout > millis())) + while( rcode && ( timeout > millis())) { - switch (rcode) + switch( rcode ) { - case hrNAK: - nak_count++; - if (nak_limit && (nak_count == USB_NAK_LIMIT)) { - return (rcode); - } - break; - case hrTIMEOUT: - retry_count++; - if (retry_count == USB_RETRY_LIMIT) { - return (rcode); - } - break; - default: - return (rcode); - } - - // Process NAK according to Host out NAK bug - regWr(rSNDBC, 0); - regWr(rSNDFIFO, *data_p); - regWr(rSNDBC, bytes_tosend); - - // Dispatch packet - regWr(rHXFR, (tokOUT | ep)); - - // Wait for the completion IRQ - while (!(regRd(rHIRQ) & bmHXFRDNIRQ)) - ; - - // Clear IRQ - regWr(rHIRQ, bmHXFRDNIRQ); - rcode = (regRd(rHRSL) & 0x0f); - } + case hrNAK: + nak_count ++; + if( nak_limit && ( nak_count == nak_limit )) + return( rcode ); + break; + case hrTIMEOUT: + retry_count ++; + if( retry_count == USB_RETRY_LIMIT ) + return( rcode ); + break; + default: + return( rcode ); + }//switch( rcode + // process NAK according to Host out NAK bug + regWr( rSNDBC, 0 ); + regWr( rSNDFIFO, *data_p ); + regWr( rSNDBC, bytes_tosend ); + regWr( rHXFR, ( tokOUT | pep->epAddr )); //dispatch packet + while(!(regRd( rHIRQ ) & bmHXFRDNIRQ )); //wait for the completion IRQ + regWr( rHIRQ, bmHXFRDNIRQ ); //clear IRQ + rcode = ( regRd( rHRSL ) & 0x0f ); + }//while( rcode && .... bytes_left -= bytes_tosend; data_p += bytes_tosend; - } - - // Update toggle - devtable[ addr ].epinfo[ ep ].sndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? bmSNDTOG1 : bmSNDTOG0; - return (rcode); -*/ -printf("error3\r\n"); + }//while( bytes_left... + pep->bmSndToggle = ( regRd( rHRSL ) & bmSNDTOGRD ) ? 1 : 0; //bmSNDTOG1 : bmSNDTOG0; //update toggle + return( rcode ); //should be 0 in all cases + */ + printf("j'ai beau etre matinal.. j'ai mal!!!! arggghh\r\n"); return 1; - } /** @@ -474,11 +429,15 @@ return 1; * rcode 0 for success * 1 for naked * 2 for timeout + * + * Note: pipe token MUST be configured first when the corresponding FIFO is used, + * else packet may be corrupted. */ uint32_t USBHost::dispatchPkt(uint32_t token, uint32_t ep, uint32_t nak_limit) { uint32_t timeout = millis() + USB_XFER_TIMEOUT; uint32_t nak_count = 0; + uint32_t rcode = USB_ERROR_TRANSFER_TIMEOUT; TRACE_USBHOST(printf(" => dispatchPkt token=%lu\r\n", token);) @@ -501,12 +460,156 @@ uint32_t USBHost::dispatchPkt(uint32_t token, uint32_t ep, uint32_t nak_limit) nak_count++; if (nak_limit && (nak_count == nak_limit)) { - return 1; + return 1; //////////////////////////// cree un code pour ca } } } - return 2; + return rcode; +} + +/** + * Configure a device using known device classes. + * The device get a new address even if its class remain unknown. + */ +uint32_t USBHost::Configuring(uint32_t parent, uint32_t port, uint32_t lowspeed) +{ + uint32_t rcode = 0; + + for (; devConfigIndex < USB_NUMDEVICES; ++devConfigIndex) + { + if (!devConfig[devConfigIndex]) + continue; + + rcode = devConfig[devConfigIndex]->Init(parent, port, lowspeed); + + if (!rcode) + { + TRACE_USBHOST(printf("USBHost::Configuring : found device class!\r\n");) + devConfigIndex = 0; + return 0; + } + + if (!(rcode == USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED || rcode == USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE)) + { + // in case of an error devConfigIndex should be reset to 0 + // in order to start from the very beginning the + // next time the program gets here + if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE) + devConfigIndex = 0; + + return rcode; + } + } + + // if we get here that means that the device class is not supported by any of registered classes + devConfigIndex = 0; + + rcode = DefaultAddressing(parent, port, lowspeed); + + return rcode; +} + +uint32_t USBHost::DefaultAddressing(uint32_t parent, uint32_t port, uint32_t lowspeed) +{ + uint32_t rcode = 0; + UsbDevice *p0 = 0, *p = 0; + + // Get pointer to pseudo device with address 0 assigned + p0 = addrPool.GetUsbDevicePtr(0); + + if (!p0) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + if (!p0->epinfo) + return USB_ERROR_EPINFO_IS_NULL; + + p0->lowspeed = (lowspeed) ? 1 : 0; + + // Allocate new address according to device class + uint32_t bAddress = addrPool.AllocAddress(parent, 0, port); + + if (!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + p = addrPool.GetUsbDevicePtr(bAddress); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + // Assign new address to the device + rcode = setAddr(0, 0, bAddress); + + if (rcode) + { + TRACE_USBHOST(printf("/!\\ USBHost::DefaultAddressing : Set address failed with code: %lu\r\n", rcode);) + addrPool.FreeAddress(bAddress); + bAddress = 0; + return rcode; + } + + return 0; +} + +uint32_t USBHost::ReleaseDevice(uint32_t addr) +{ + if (!addr) + return 0; + + for (uint32_t i = 0; i < USB_NUMDEVICES; ++i) + if (devConfig[i]->GetAddress() == addr) + return devConfig[i]->Release(); + + return 0; +} + +// Get device descriptor +uint32_t USBHost::getDevDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* dataptr) +{ + return (ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, nbytes, dataptr, 0)); +} + +// Get configuration descriptor +uint32_t USBHost::getConfDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint32_t conf, uint8_t* dataptr) +{ + return (ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, nbytes, dataptr, 0)); +} + +uint32_t USBHost::getConfDescr(uint32_t addr, uint32_t ep, uint32_t conf, USBReadParser *p) +{ + const uint32_t bufSize = 64; + uint8_t buf[bufSize]; + + uint32_t ret = getConfDescr(addr, ep, 8, conf, buf); + + if (ret) + return ret; + + uint32_t total = ((USB_CONFIGURATION_DESCRIPTOR*)buf)->wTotalLength; + delay(100); + + return (ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, total, bufSize, buf, p)); +} + +// Get string descriptor +uint32_t USBHost::getStrDescr(uint32_t addr, uint32_t ep, uint16_t ns, uint8_t index, uint16_t langid, uint8_t* dataptr) +{ + return (ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, ns, ns, dataptr, 0)); +} + +// Set address +uint32_t USBHost::setAddr(uint32_t oldaddr, uint32_t ep, uint32_t newaddr) +{ + TRACE_USBHOST(printf(" => setAddr\r\n");) + return ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, 0, 0); +} + +// Set configuration +uint32_t USBHost::setConf(uint32_t addr, uint32_t ep, uint32_t conf_value) +{ + return (ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, 0x0000, 0, 0)); } /** @@ -515,12 +618,10 @@ uint32_t USBHost::dispatchPkt(uint32_t token, uint32_t ep, uint32_t nak_limit) */ void USBHost::Task(void) { - uint32_t i = 0; uint32_t rcode = 0; - //static uint8_t tmpaddr = 0; volatile uint32_t tmpdata = 0; static uint32_t delay = 0; - USB_DEVICE_DESCRIPTOR buf; + uint32_t lowspeed = 0; // Update USB task state on Vbus change tmpdata = UHD_GetVBUSState(); @@ -529,6 +630,7 @@ void USBHost::Task(void) case UHD_STATE_ERROR: // Illegal state usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL; + lowspeed = 0; break; case UHD_STATE_DISCONNECTED: @@ -536,6 +638,7 @@ void USBHost::Task(void) if ((usb_task_state & USB_STATE_MASK) != USB_STATE_DETACHED) { usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; + lowspeed = 0; } break; @@ -545,10 +648,15 @@ void USBHost::Task(void) { delay = millis() + USB_SETTLE_DELAY; usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE; + ///////////////////////////////////////////////////////////lowspeed = 0 ou 1; faire un get speed } break; } + for (uint32_t i = 0; i < USB_NUMDEVICES; ++i) + if (devConfig[i]) + rcode = devConfig[i]->Poll(); + // USB state machine switch (usb_task_state) { @@ -559,6 +667,10 @@ void USBHost::Task(void) UHD_Init(); init(); + for (uint32_t i = 0; i < USB_NUMDEVICES; ++i) + if (devConfig[i]) + rcode = devConfig[i]->Release(); + usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE; break; @@ -614,93 +726,29 @@ void USBHost::Task(void) TRACE_USBHOST(printf(" + USB_ATTACHED_SUBSTATE_WAIT_SOF\r\n");) // 20ms waiting elapsed - usb_task_state = USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE; + usb_task_state = USB_STATE_CONFIGURING; } } break; - case USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE: - TRACE_USBHOST(printf(" + USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE\r\n");) - - // Get Device descriptor size - // Set max.packet size to the minimum allowed - devtable[0].epinfo->MaxPktSize = 8; - rcode = getDevDescr(0, 0, 8, (uint8_t*)&buf); - if (rcode == 0) - { - TRACE_USBHOST(printf(" + USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE : max pkt size = %d\r\n", buf.bMaxPacketSize0);) - devtable[0].epinfo->MaxPktSize = buf.bMaxPacketSize0; - - // Reconfigure EP0 with max pkt size. (should be done after a USB reset) - UHD_EP_Free(0, 0); - if (UHD_EP0_Alloc(0, devtable[0].epinfo->MaxPktSize) == 0) - { - usb_task_state = USB_STATE_ADDRESSING; - } - else - { - TRACE_USBHOST(printf(" + USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE : realloc failure!\r\n");) - usb_task_state = USB_STATE_ERROR; - } - } - else - { - usb_error = USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE; - usb_task_state = USB_STATE_ERROR; - } - break; - - case USB_STATE_ADDRESSING: - for (i = 1; i < USB_NUMDEVICES; i++) - { - TRACE_USBHOST(printf(" + USB_STATE_ADDRESSING (i=%lu)\r\n", i);) - - if (devtable[i].epinfo == 0) - { - // Set correct MaxPktSize - // Temporary record until plugged with real device endpoint structure - devtable[i].epinfo = devtable[0].epinfo; - - rcode = setAddr(0, 0, i); - if (rcode == 0) - { - // Free address 0 used to start enumeration - UHD_EP_Free(0, 0); - - // Alloc control endpoint with the new USB address - if (UHD_EP0_Alloc(i, devtable[i].epinfo->MaxPktSize) == 0) - { - usb_task_state = USB_STATE_CONFIGURING; - TRACE_USBHOST(printf(" + USB_STATE_CONFIGURING (i=%lu)\r\n", i);) - } - else - { - // Set address error - TRACE_USBHOST(printf(" + USB_STATE_CONFIGURING (i=%lu) : realloc failure!\r\n", i);) - usb_error = USB_STATE_ADDRESSING; - usb_task_state = USB_STATE_ERROR; - } - } - else - { - // Set address error - usb_error = USB_STATE_ADDRESSING; - usb_task_state = USB_STATE_ERROR; - } - // Break if address assigned or error occured during address assignment attempt - break; - } - } - - if (usb_task_state == USB_STATE_ADDRESSING) - { - // No vacant place in devtable - usb_error = 0xfe; - usb_task_state = USB_STATE_ERROR; - } - break; - case USB_STATE_CONFIGURING: + TRACE_USBHOST(printf(" + USB_STATE_CONFIGURING\r\n");) + rcode = Configuring(0, 0, lowspeed); + + if (rcode) + { + TRACE_USBHOST(printf("/!\\ USBHost::Task : USB_STATE_CONFIGURING failed with code: %lu\r\n", rcode);) + if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE) + { + usb_error = rcode; + usb_task_state = USB_STATE_ERROR; + } + } + else + { + usb_task_state = USB_STATE_RUNNING; + TRACE_USBHOST(printf(" + USB_STATE_RUNNING\r\n");) + } break; case USB_STATE_RUNNING: diff --git a/hardware/arduino/sam/system/USBHost/Usb.h b/hardware/arduino/sam/system/USBHost/Usb.h index adeb467c9..2dfd0ff09 100644 --- a/hardware/arduino/sam/system/USBHost/Usb.h +++ b/hardware/arduino/sam/system/USBHost/Usb.h @@ -1,30 +1,83 @@ -/* Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com */ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com +*/ /* USB functions */ + #ifndef USB_H_INCLUDED #define USB_H_INCLUDED +#define TRACE_USBHOST(x) x +//#define TRACE_USBHOST(x) + #include -#include "ch9.h" +#include "usb_ch9.h" +#include "address.h" /* Common setup data constant combinations */ #define bmREQ_GET_DESCR USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE // Get descriptor request type #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' #define bmREQ_CL_GET_INTF USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE // Get interface request type -/* HID requests */ -#define bmREQ_HIDOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE -#define bmREQ_HIDIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE -#define bmREQ_HIDREPORT USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_INTERFACE +// USB Device Classes +#define USB_CLASS_USE_CLASS_INFO 0x00 // Use Class Info in the Interface Descriptors +#define USB_CLASS_AUDIO 0x01 // Audio +#define USB_CLASS_COM_AND_CDC_CTRL 0x02 // Communications and CDC Control +#define USB_CLASS_HID 0x03 // HID +#define USB_CLASS_PHYSICAL 0x05 // Physical +#define USB_CLASS_IMAGE 0x06 // Image +#define USB_CLASS_PRINTER 0x07 // Printer +#define USB_CLASS_MASS_STORAGE 0x08 // Mass Storage +#define USB_CLASS_HUB 0x09 // Hub +#define USB_CLASS_CDC_DATA 0x0a // CDC-Data +#define USB_CLASS_SMART_CARD 0x0b // Smart-Card +#define USB_CLASS_CONTENT_SECURITY 0x0d // Content Security +#define USB_CLASS_VIDEO 0x0e // Video +#define USB_CLASS_PERSONAL_HEALTH 0x0f // Personal Healthcare +#define USB_CLASS_DIAGNOSTIC_DEVICE 0xdc // Diagnostic Device +#define USB_CLASS_WIRELESS_CTRL 0xe0 // Wireless Controller +#define USB_CLASS_MISC 0xef // Miscellaneous +#define USB_CLASS_APP_SPECIFIC 0xfe // Application Specific +#define USB_CLASS_VENDOR_SPECIFIC 0xff // Vendor Specific -#define USB_XFER_TIMEOUT 5000 // USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec -#define USB_NAK_LIMIT 32000 // NAK limit for a transfer. o means NAKs are not counted -#define USB_RETRY_LIMIT 3 // Retry limit for a transfer -#define USB_SETTLE_DELAY 200 // Settle delay in milliseconds -#define USB_NAK_NOWAIT 1 // Used in Richard's PS2/Wiimote code +// Additional Error Codes +#define USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED 0xD1 +#define USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE 0xD2 +#define USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS 0xD3 +#define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL 0xD4 +#define USB_ERROR_HUB_ADDRESS_OVERFLOW 0xD5 +#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL 0xD6 +#define USB_ERROR_EPINFO_IS_NULL 0xD7 +#define USB_ERROR_INVALID_ARGUMENT 0xD8 +#define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE 0xD9 +#define USB_ERROR_INVALID_MAX_PKT_SIZE 0xDA +#define USB_ERROR_EP_NOT_FOUND_IN_TBL 0xDB +#define USB_ERROR_TRANSFER_TIMEOUT 0xFF -#define USB_NUMDEVICES 2 // Number of USB devices +#define USB_XFER_TIMEOUT 5000 //USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec +//#define USB_NAK_LIMIT 32000 //NAK limit for a transfer. 0 means NAKs are not counted +#define USB_RETRY_LIMIT 3 //retry limit for a transfer +#define USB_SETTLE_DELAY 200 //settle delay in milliseconds + +#define USB_NUMDEVICES 16 //number of USB devices +//#define HUB_MAX_HUBS 7 // maximum number of hubs that can be attached to the host controller +#define HUB_PORT_RESET_DELAY 20 // hub port reset delay 10 ms recomended, can be up to 20 ms /* USB state machine states */ +#define USB_STATE_MASK 0xf0 + #define USB_STATE_DETACHED 0x10 #define USB_DETACHED_SUBSTATE_INITIALIZE 0x11 #define USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE 0x12 @@ -40,7 +93,7 @@ #define USB_STATE_ERROR 0xa0 #define USB_STATE_MASK 0xf0 -/* USB Setup Packet Structure */ +// USB Setup Packet Structure typedef struct { union @@ -67,137 +120,98 @@ typedef struct uint16_t wLength; // 6 Depends on bRequest } SETUP_PKT, *PSETUP_PKT; -/* Endpoint information structure */ -/* bToggle of endpoint 0 initialized to 0xff */ -/* during enumeration bToggle is set to 00 */ -typedef struct +// Base class for incoming data parser +class USBReadParser { - uint32_t epAddr; // Copy from endpoint descriptor. Bit 7 indicates direction (ignored for control endpoints) - uint8_t Attr; // Endpoint transfer type. - uint16_t MaxPktSize; // Maximum packet size. - uint8_t Interval; // Polling interval in frames. - uint8_t sndToggle; // Last toggle value, bitmask for HCTL toggle bits - uint8_t rcvToggle; // Last toggle value, bitmask for HCTL toggle bits - /* not sure if both are necessary */ -} EP_RECORD; - -/* Device record structure */ -typedef struct -{ - EP_RECORD* epinfo; // Device endpoint information - uint8_t devclass; // Device class -} DEV_RECORD; +public: + virtual void Parse(const uint32_t len, const uint8_t *pbuf, const uint32_t &offset) = 0; +}; /** - * USBHost Class + * USBDeviceConfig class. + */ +class USBDeviceConfig +{ +public: + virtual uint32_t Init(uint32_t parent, uint32_t port, uint32_t lowspeed) = 0; + virtual uint32_t Release() = 0; + virtual uint32_t Poll() = 0; + virtual uint32_t GetAddress() = 0; +}; + +/** + * USBHost Class. * The device table is filled during enumeration. * Index corresponds to device address and each entry contains pointer to endpoint structure and device class to use. */ class USBHost { + AddressPoolImpl addrPool; + USBDeviceConfig* devConfig[USB_NUMDEVICES]; + uint32_t devConfigIndex; + uint32_t bmHubPre; + public: - USBHost(void); + USBHost(void); + + //void SetHubPreMask() { bmHubPre |= bmHUBPRE; }; + //void ResetHubPreMask() { bmHubPre &= (~bmHUBPRE); }; + + AddressPool& GetAddressPool() + { + return (AddressPool&)addrPool; + }; + + uint32_t RegisterDeviceClass(USBDeviceConfig *pdev) + { + for (uint32_t i = 0; i < USB_NUMDEVICES; ++i) + { + if (!devConfig[i]) + { + devConfig[i] = pdev; + return 0; + } + } + return USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS; + }; + + void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) + { + addrPool.ForEachUsbDevice(pfunc); + }; + uint32_t getUsbTaskState(void); - void setUsbTaskState(uint32_t state); - EP_RECORD* getDevTableEntry(uint32_t addr, uint32_t ep); - void setDevTableEntry(uint32_t addr, EP_RECORD* eprecord_ptr); - uint32_t ctrlReq(uint32_t addr, uint32_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, uint16_t wInd, uint32_t nbytes, uint8_t* dataptr, uint32_t nak_limit = USB_NAK_LIMIT); + void setUsbTaskState(uint32_t state); + + EpInfo* getEpInfoEntry(uint32_t addr, uint32_t ep); + uint32_t setEpInfoEntry(uint32_t addr, uint32_t epcount, EpInfo* eprecord_ptr); /* Control requests */ - uint32_t getDevDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* dataptr, uint32_t nak_limit = USB_NAK_LIMIT); - uint32_t getConfDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t conf, uint8_t* dataptr, uint32_t nak_limit = USB_NAK_LIMIT); - uint32_t getStrDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t index, uint16_t langid, uint8_t* dataptr, uint32_t nak_limit = USB_NAK_LIMIT); - uint32_t setAddr(uint32_t oldaddr, uint32_t ep, uint32_t newaddr, uint32_t nak_limit = USB_NAK_LIMIT); - uint32_t setConf(uint32_t addr, uint32_t ep, uint8_t conf_value, uint32_t nak_limit = USB_NAK_LIMIT); + uint32_t getDevDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* dataptr); + uint32_t getConfDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint32_t conf, uint8_t* dataptr); + uint32_t getConfDescr(uint32_t addr, uint32_t ep, uint32_t conf, USBReadParser *p); + uint32_t getStrDescr(uint32_t addr, uint32_t ep, uint16_t ns, uint8_t index, uint16_t langid, uint8_t* dataptr); + uint32_t setAddr(uint32_t oldaddr, uint32_t ep, uint32_t newaddr); + uint32_t setConf(uint32_t addr, uint32_t ep, uint32_t conf_value); + uint32_t ctrlReq(uint32_t addr, uint32_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, + uint16_t wInd, uint16_t total, uint32_t nbytes, uint8_t* dataptr, USBReadParser *p); - /* Status requests */ - uint32_t setProto(uint32_t addr, uint32_t ep, uint8_t interface, uint8_t protocol, uint32_t nak_limit = USB_NAK_LIMIT); - uint32_t getProto(uint32_t addr, uint32_t ep, uint8_t interface, uint8_t* dataptr, uint32_t nak_limit = USB_NAK_LIMIT); - uint32_t getReportDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* dataptr, uint32_t nak_limit = USB_NAK_LIMIT); - uint32_t setReport(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t interface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr, uint32_t nak_limit = USB_NAK_LIMIT); - uint32_t getReport(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t interface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr, uint32_t nak_limit = USB_NAK_LIMIT); - uint32_t getIdle(uint32_t addr, uint32_t ep, uint8_t interface, uint8_t reportID, uint8_t* dataptr, uint32_t nak_limit = USB_NAK_LIMIT); - uint32_t setIdle(uint32_t addr, uint32_t ep, uint8_t interface, uint8_t reportID, uint8_t duration, uint32_t nak_limit = USB_NAK_LIMIT); + /* Transfer requests */ + uint32_t inTransfer(uint32_t addr, uint32_t ep, uint32_t *nbytesptr, uint8_t* data); + uint32_t outTransfer(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* data); + uint32_t dispatchPkt(uint32_t token, uint32_t ep, uint32_t nak_limit); - /* Transfer requests */ - uint32_t ctrlData(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* dataptr, uint32_t direction, uint32_t nak_limit = USB_NAK_LIMIT); - uint32_t ctrlStatus(uint32_t ep, uint32_t direction, uint32_t nak_limit = USB_NAK_LIMIT); - uint32_t inTransfer(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* data, uint32_t nak_limit = USB_NAK_LIMIT); - int32_t newInTransfer(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* data, uint32_t nak_limit = USB_NAK_LIMIT); - uint32_t outTransfer(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* data, uint32_t nak_limit = USB_NAK_LIMIT); - uint32_t dispatchPkt(uint32_t token, uint32_t ep, uint32_t nak_limit = USB_NAK_LIMIT); - void Task(void); + void Task(void); + + uint32_t DefaultAddressing(uint32_t parent, uint32_t port, uint32_t lowspeed); + uint32_t Configuring(uint32_t parent, uint32_t port, uint32_t lowspeed); + uint32_t ReleaseDevice(uint32_t addr); private: void init(); + uint32_t SetAddress(uint32_t addr, uint32_t ep, EpInfo **ppep, uint32_t &nak_limit); + uint32_t OutTransfer(EpInfo *pep, uint32_t nak_limit, uint32_t nbytes, uint8_t *data); + uint32_t InTransfer(EpInfo *pep, uint32_t nak_limit, uint32_t *nbytesptr, uint8_t* data); }; -// Get device descriptor -inline uint32_t USBHost::getDevDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* dataptr, uint32_t nak_limit) -{ - return (ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr, nak_limit)); -} - -// Get configuration descriptor -inline uint32_t USBHost::getConfDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t conf, uint8_t* dataptr, uint32_t nak_limit) -{ - return (ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr, nak_limit)); -} - -// Get string descriptor -inline uint32_t USBHost::getStrDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t index, uint16_t langid, uint8_t* dataptr, uint32_t nak_limit) -{ - return (ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nbytes, dataptr, nak_limit)); -} - -// Set address -inline uint32_t USBHost::setAddr(uint32_t oldaddr, uint32_t ep, uint32_t newaddr, uint32_t nak_limit) -{ - return (ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0, nak_limit)); -} - -// Set configuration -inline uint32_t USBHost::setConf(uint32_t addr, uint32_t ep, uint8_t conf_value, uint32_t nak_limit) -{ - return (ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, 0, nak_limit)); -} - -// Class requests -inline uint32_t USBHost::setProto(uint32_t addr, uint32_t ep, uint8_t interface, uint8_t protocol, uint32_t nak_limit) -{ - return (ctrlReq(addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, interface, 0x0000, 0, nak_limit)); -} - -inline uint32_t USBHost::getProto(uint32_t addr, uint32_t ep, uint8_t interface, uint8_t* dataptr, uint32_t nak_limit) -{ - return (ctrlReq(addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, interface, 0x0001, dataptr, nak_limit)); -} - -// Get HID report descriptor -inline uint32_t USBHost::getReportDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* dataptr, uint32_t nak_limit) -{ - return (ctrlReq(addr, ep, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, HID_DESCRIPTOR_REPORT, 0x0000, nbytes, dataptr, nak_limit)); -} - -inline uint32_t USBHost::setReport(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t interface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr, uint32_t nak_limit) -{ - return (ctrlReq(addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, report_id, report_type, interface, nbytes, dataptr, nak_limit)); -} - -inline uint32_t USBHost::getReport(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t interface, uint8_t report_type, uint8_t report_id, uint8_t* dataptr, uint32_t nak_limit) -{ - return (ctrlReq(addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, report_id, report_type, interface, nbytes, dataptr, nak_limit)); -} - -/* returns one uint8_t of data in dataptr */ -inline uint32_t USBHost::getIdle(uint32_t addr, uint32_t ep, uint8_t interface, uint8_t reportID, uint8_t* dataptr, uint32_t nak_limit) -{ - return (ctrlReq(addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_IDLE, reportID, 0, interface, 0x0001, dataptr, nak_limit)); -} - -inline uint32_t USBHost::setIdle(uint32_t addr, uint32_t ep, uint8_t interface, uint8_t reportID, uint8_t duration, uint32_t nak_limit) -{ - return (ctrlReq(addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_IDLE, reportID, duration, interface, 0x0000, 0, nak_limit)); -} - #endif /* USB_H_INCLUDED */ diff --git a/hardware/arduino/sam/system/USBHost/address.h b/hardware/arduino/sam/system/USBHost/address.h new file mode 100644 index 000000000..4a1d5e4bc --- /dev/null +++ b/hardware/arduino/sam/system/USBHost/address.h @@ -0,0 +1,293 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com +*/ + +#ifndef ADDRESS_H_INCLUDED +#define ADDRESS_H_INCLUDED + +#include + +/* NAK powers. To save space in endpoint data structure, amount of retries before giving up and returning 0x4 is stored in */ +/* bmNakPower as a power of 2. The actual nak_limit is then calculated as nak_limit = ( 2^bmNakPower - 1) */ +#define USB_NAK_MAX_POWER 16 //NAK binary order maximum value +#define USB_NAK_DEFAULT 14 //default 16K-1 NAKs before giving up +#define USB_NAK_NOWAIT 1 //Single NAK stops transfer +#define USB_NAK_NONAK 0 //Do not count NAKs, stop retrying after USB Timeout + +struct EpInfo +{ + uint32_t epAddr; // Endpoint address + uint32_t maxPktSize; // Maximum packet size + + union + { + uint8_t epAttribs; + + struct + { + uint8_t bmSndToggle : 1; // Send toggle, when zero bmSNDTOG0, bmSNDTOG1 otherwise + uint8_t bmRcvToggle : 1; // Send toggle, when zero bmRCVTOG0, bmRCVTOG1 otherwise + uint8_t bmNakPower : 6; // Binary order for NAK_LIMIT value + }; + }; +}; + +// 7 6 5 4 3 2 1 0 +// --------------------------------- +// | | H | P | P | P | A | A | A | +// --------------------------------- +// +// H - if 1 the address is a hub address +// P - parent hub address +// A - device address / port number in case of hub +// +struct UsbDeviceAddress +{ + union + { + struct + { + uint32_t bmAddress : 3; // device address/port number + uint32_t bmParent : 3; // parent hub address + uint32_t bmHub : 1; // hub flag + uint32_t bmReserved : 25; // reserved, must be zerro + }; + uint32_t devAddress; + }; +}; + +#define bmUSB_DEV_ADDR_ADDRESS 0x07 +#define bmUSB_DEV_ADDR_PARENT 0x38 +#define bmUSB_DEV_ADDR_HUB 0x40 + +struct UsbDevice +{ + EpInfo *epinfo; // endpoint info pointer + uint32_t address; // address + uint32_t epcount; // number of endpoints + uint32_t lowspeed; // indicates if a device is the low speed one +}; + +class AddressPool +{ +public: + virtual UsbDevice* GetUsbDevicePtr(uint32_t addr) = 0; + virtual uint32_t AllocAddress(uint32_t parent, uint32_t is_hub = 0, uint32_t port = 0) = 0; + virtual void FreeAddress(uint32_t addr) = 0; +}; + +typedef void (*UsbDeviceHandleFunc)(UsbDevice *pdev); + +#define ADDR_ERROR_INVALID_INDEX 0xFF +#define ADDR_ERROR_INVALID_ADDRESS 0xFF + +template +class AddressPoolImpl : public AddressPool +{ +private: + + EpInfo dev0ep; //Endpoint data structure used during enumeration for uninitialized device + + uint32_t hubCounter; // hub counter is kept + // in order to avoid hub address duplication + + UsbDevice thePool[MAX_DEVICES_ALLOWED]; + + // Initializes address pool entry + void InitEntry(uint32_t index) + { + thePool[index].address = 0; + thePool[index].epcount = 1; + thePool[index].lowspeed = 0; + thePool[index].epinfo = &dev0ep; + }; + + // Returns thePool index for a given address + uint32_t FindAddressIndex(uint32_t address = 0) + { + for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) + { + if (thePool[i].address == address) + return i; + } + return 0; + }; + + // Returns thePool child index for a given parent + uint32_t FindChildIndex(UsbDeviceAddress addr, uint32_t start = 1) + { + for (uint32_t i = (start < 1 || start >= MAX_DEVICES_ALLOWED) ? 1 : start; i < MAX_DEVICES_ALLOWED; i++) + { + if (((UsbDeviceAddress*)&thePool[i].address)->bmParent == addr.bmAddress) + return i; + } + return 0; + }; + + // Frees address entry specified by index parameter + void FreeAddressByIndex(uint32_t index) + { + // Zerro field is reserved and should not be affected + if (index == 0) + return; + + // If a hub was switched off all port addresses should be freed + if (((UsbDeviceAddress*)&thePool[index].address)->bmHub == 1) + { + for (uint32_t i = 1; (i = FindChildIndex(*((UsbDeviceAddress*)&thePool[index].address), i) > 0); ) + FreeAddressByIndex(i); + + // If the hub had the last allocated address, hubCounter should be decremented + if (hubCounter == ((UsbDeviceAddress*)&thePool[index].address)->bmAddress) + hubCounter --; + } + InitEntry(index); + } + + // Initializes the whole address pool at once + void InitAllAddresses() + { + for (uint32_t i = 1; i < MAX_DEVICES_ALLOWED; i++) + InitEntry(i); + + hubCounter = 0; + }; + +public: + AddressPoolImpl() : hubCounter(0) + { + // Init address zero (reserved) + InitEntry(0); + + // Init all remaing addresses + InitAllAddresses(); + + // Configure ep0 used for enumeration + dev0ep.epAddr = 0; + dev0ep.maxPktSize = 8; + }; + + // Returns a pointer to a specified address entry + virtual UsbDevice* GetUsbDevicePtr(uint32_t addr) + { + if (!addr) + return thePool; + + uint32_t index = FindAddressIndex(addr); + + return (!index) ? 0 : (thePool + index); + }; + + // Performs an operation specified by pfunc for each addressed device + void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) + { + if (!pfunc) + return; + + for (uint32_t i = 1; i < MAX_DEVICES_ALLOWED; i++) + if (thePool[i].address) + pfunc(thePool + i); + }; + + // Allocates new address + virtual uint32_t AllocAddress(uint32_t parent, uint32_t is_hub = 0, uint32_t port = 0) + { + if (parent > 127 || port > 7) + return 0; + + if (is_hub && hubCounter == 7) + return 0; + + // Finds first empty address entry starting from one + uint32_t index = FindAddressIndex(0); + + // If empty entry is not found + if (!index) + return 0; + + if (parent == 0) + { + if (is_hub) + { + thePool[index].address = 0x41; + hubCounter ++; + } + else + thePool[index].address = 1; + + return thePool[index].address; + } + + UsbDeviceAddress addr; + + addr.bmParent = ((UsbDeviceAddress*)&parent)->bmAddress; + + if (is_hub) + { + addr.bmHub = 1; + addr.bmAddress = ++hubCounter; + } + else + { + addr.bmHub = 0; + addr.bmAddress = port; + } + thePool[index].address = *((uint8_t*)&addr); +/* + Serial.print("Addr:"); + Serial.print(addr.bmHub, HEX); + Serial.print("."); + Serial.print(addr.bmParent, HEX); + Serial.print("."); + Serial.println(addr.bmAddress, HEX); +*/ + return thePool[index].address; + }; + + // Empties pool entry + virtual void FreeAddress(uint32_t addr) + { + // if the root hub is disconnected all the addresses should be initialized + if (addr == 0x41) + { + InitAllAddresses(); + return; + } + uint32_t index = FindAddressIndex(addr); + FreeAddressByIndex(index); + }; + + // Returns number of hubs attached + // It can be rather helpfull to find out if there are hubs attached than getting the exact number of hubs. + /*uint8_t GetNumHubs() + { + return hubCounter; + }; + + uint8_t GetNumDevices() + { + uint8_t counter = 0; + + for (uint8_t i=1; i +#include "parsetools.h" + +class UsbConfigXtracter +{ +public: + virtual void EndpointXtract(uint32_t conf, uint32_t iface, uint32_t alt, uint32_t proto, const USB_ENDPOINT_DESCRIPTOR *ep) = 0; +}; + +#define CP_MASK_COMPARE_CLASS 1 +#define CP_MASK_COMPARE_SUBCLASS 2 +#define CP_MASK_COMPARE_PROTOCOL 4 +#define CP_MASK_COMPARE_ALL 7 + +// Configuration Descriptor Parser Class Template +template +class ConfigDescParser : public USBReadParser +{ + UsbConfigXtracter *theXtractor; + MultiValueBuffer theBuffer; + MultiByteValueParser valParser; + ByteSkipper theSkipper; + uint8_t varBuffer[16 /*sizeof(USB_CONFIGURATION_DESCRIPTOR)*/]; + + uint32_t stateParseDescr; // ParseDescriptor state + + uint32_t dscrLen; // Descriptor length + uint32_t dscrType; // Descriptor type + + bool isGoodInterface; // Apropriate interface flag + uint32_t confValue; // Configuration value + uint32_t protoValue; // Protocol value + uint32_t ifaceNumber; // Interface number + uint32_t ifaceAltSet; // Interface alternate settings + + bool ParseDescriptor(uint8_t **pp, uint32_t *pcntdn); + + void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc); + +public: + ConfigDescParser(UsbConfigXtracter *xtractor); + virtual void Parse(const uint32_t len, const uint8_t *pbuf, const uint32_t &offset); +}; + +template +ConfigDescParser::ConfigDescParser(UsbConfigXtracter *xtractor) : + theXtractor(xtractor), + stateParseDescr(0), + dscrLen(0), + dscrType(0) +{ + theBuffer.pValue = varBuffer; + valParser.Initialize(&theBuffer); + theSkipper.Initialize(&theBuffer); +}; + +template +void ConfigDescParser::Parse(const uint32_t len, const uint8_t *pbuf, const uint32_t &offset) +{ + uint32_t cntdn = len; + uint8_t *p = (uint8_t*)pbuf; + + while(cntdn) + if (!ParseDescriptor(&p, &cntdn)) + return; +} +/* Parser for the configuration descriptor. Takes values for class, subclass, protocol fields in interface descriptor and + compare masks for them. When the match is found, calls EndpointXtract passing buffer containing endpoint descriptor */ +template +bool ConfigDescParser::ParseDescriptor(uint8_t **pp, uint32_t *pcntdn) +{ + switch (stateParseDescr) + { + case 0: + theBuffer.valueSize = 2; + valParser.Initialize(&theBuffer); + stateParseDescr = 1; + case 1: + if (!valParser.Parse(pp, pcntdn)) + return false; + dscrLen = *((uint8_t*)theBuffer.pValue); + dscrType = *((uint8_t*)theBuffer.pValue + 1); + stateParseDescr = 2; + case 2: + // This is a sort of hack. Assuming that two bytes are already in the buffer + // the pointer is positioned two bytes ahead in order for the rest of descriptor + // to be read right after the size and the type fields. + // This should be used carefuly. varBuffer should be used directly to handle data + // in the buffer. + theBuffer.pValue = varBuffer + 2; + stateParseDescr = 3; + case 3: + switch (dscrType) + { + case USB_DESCRIPTOR_INTERFACE: + isGoodInterface = false; + case USB_DESCRIPTOR_CONFIGURATION: + theBuffer.valueSize = sizeof(USB_CONFIGURATION_DESCRIPTOR) - 2; + break; + case USB_DESCRIPTOR_ENDPOINT: + theBuffer.valueSize = sizeof(USB_ENDPOINT_DESCRIPTOR) - 2; + break; + case HID_DESCRIPTOR_HID: + theBuffer.valueSize = dscrLen - 2; + break; + } + valParser.Initialize(&theBuffer); + stateParseDescr = 4; + case 4: + switch (dscrType) + { + case USB_DESCRIPTOR_CONFIGURATION: + if (!valParser.Parse(pp, pcntdn)) + return false; + confValue = ((USB_CONFIGURATION_DESCRIPTOR*)varBuffer)->bConfigurationValue; + break; + case USB_DESCRIPTOR_INTERFACE: + if (!valParser.Parse(pp, pcntdn)) + return false; + if ((MASK & CP_MASK_COMPARE_CLASS) && ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceClass != CLASS_ID) + break; + if ((MASK & CP_MASK_COMPARE_SUBCLASS) && ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceSubClass != SUBCLASS_ID) + break; + if ((MASK & CP_MASK_COMPARE_PROTOCOL) && ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceProtocol != PROTOCOL_ID) + break; + + isGoodInterface = true; + ifaceNumber = ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceNumber; + ifaceAltSet = ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bAlternateSetting; + protoValue = ((USB_INTERFACE_DESCRIPTOR*)varBuffer)->bInterfaceProtocol; + break; + case USB_DESCRIPTOR_ENDPOINT: + if (!valParser.Parse(pp, pcntdn)) + return false; + if (isGoodInterface) + if (theXtractor) + theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*)varBuffer); + break; + //case HID_DESCRIPTOR_HID: + // if (!valParser.Parse(pp, pcntdn)) + // return false; + // PrintHidDescriptor((const USB_HID_DESCRIPTOR*)varBuffer); + // break; + default: + if (!theSkipper.Skip(pp, pcntdn, dscrLen-2)) + return false; + } + theBuffer.pValue = varBuffer; + stateParseDescr = 0; + } + return true; +} + +template +void ConfigDescParser::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) +{ + /*Notify(PSTR("\r\n\r\nHID Descriptor:\r\n")); + Notify(PSTR("bDescLength:\t\t")); + PrintHex(pDesc->bLength); + + Notify(PSTR("\r\nbDescriptorType:\t")); + PrintHex(pDesc->bDescriptorType); + + Notify(PSTR("\r\nbcdHID:\t\t\t")); + PrintHex(pDesc->bcdHID); + + Notify(PSTR("\r\nbCountryCode:\t\t")); + PrintHex(pDesc->bCountryCode); + + Notify(PSTR("\r\nbNumDescriptors:\t")); + PrintHex(pDesc->bNumDescriptors); + + //Notify(PSTR("\r\nbDescrType:\t\t")); + //PrintHex(pDesc->bDescrType); + // + //Notify(PSTR("\r\nwDescriptorLength:\t")); + //PrintHex(pDesc->wDescriptorLength); + + for (uint8_t i=0; ibNumDescriptors; i++) + { + HID_CLASS_DESCRIPTOR_LEN_AND_TYPE *pLT = (HID_CLASS_DESCRIPTOR_LEN_AND_TYPE*)&(pDesc->bDescrType); + + Notify(PSTR("\r\nbDescrType:\t\t")); + PrintHex(pLT[i].bDescrType); + + Notify(PSTR("\r\nwDescriptorLength:\t")); + PrintHex(pLT[i].wDescriptorLength); + } + Notify(PSTR("\r\n"));*/ + printf("somebody save me!!!! orgazmo?!!!\r\n"); +} + +#endif /* CONFDESCPARSER_H_INCLUDED */ diff --git a/hardware/arduino/sam/system/USBHost/examples/USB_desc/descriptor_strings.h b/hardware/arduino/sam/system/USBHost/examples/USB_desc/descriptor_strings.h new file mode 100644 index 000000000..7fa34ac23 --- /dev/null +++ b/hardware/arduino/sam/system/USBHost/examples/USB_desc/descriptor_strings.h @@ -0,0 +1,50 @@ +#ifndef DESCRIPTOR_STRINGS_H_INCLUDED +#define DESCRIPTOR_STRINGS_H_INCLUDED + +// Buffer size +#define BUFSIZE 256 + +/* Print strings in Program Memory */ +const char Gen_Error_str[] = "\r\nRequest error. Error code:\t"; +const char Dev_Header_str[] = "\r\nDevice descriptor: "; +const char Dev_Length_str[] = "\r\nDescriptor Length:\t"; +const char Dev_Type_str[] = "\r\nDescriptor type:\t"; +const char Dev_Version_str[] = "\r\nUSB version:\t\t"; +const char Dev_Class_str[] = "\r\nDevice class:\t\t"; +const char Dev_Subclass_str[] = "\r\nDevice Subclass:\t"; +const char Dev_Protocol_str[] = "\r\nDevice Protocol:\t"; +const char Dev_Pktsize_str[] = "\r\nMax.packet size:\t"; +const char Dev_Vendor_str[] = "\r\nVendor ID:\t\t"; +const char Dev_Product_str[] = "\r\nProduct ID:\t\t"; +const char Dev_Revision_str[] = "\r\nRevision ID:\t\t"; +const char Dev_Mfg_str[] = "\r\nMfg.string index:\t"; +const char Dev_Prod_str[] = "\r\nProd.string index:\t"; +const char Dev_Serial_str[] = "\r\nSerial number index:\t"; +const char Dev_Nconf_str[] = "\r\nNumber of conf.:\t"; +const char Conf_Trunc_str[] = "Total length truncated to 256 bytes"; +const char Conf_Header_str[] = "\r\nConfiguration descriptor:"; +const char Conf_Totlen_str[] = "\r\nTotal length:\t\t"; +const char Conf_Nint_str[] = "\r\nNum.intf:\t\t"; +const char Conf_Value_str[] = "\r\nConf.value:\t\t"; +const char Conf_String_str[] = "\r\nConf.string:\t\t"; +const char Conf_Attr_str[] = "\r\nAttr.:\t\t\t"; +const char Conf_Pwr_str[] = "\r\nMax.pwr:\t\t"; +const char Int_Header_str[] = "\r\n\r\nInterface descriptor:"; +const char Int_Number_str[] = "\r\nIntf.number:\t\t"; +const char Int_Alt_str[] = "\r\nAlt.:\t\t\t"; +const char Int_Endpoints_str[] = "\r\nEndpoints:\t\t"; +const char Int_Class_str[] = "\r\nIntf. Class:\t\t"; +const char Int_Subclass_str[] = "\r\nIntf. Subclass:\t\t"; +const char Int_Protocol_str[] = "\r\nIntf. Protocol:\t\t"; +const char Int_String_str[] = "\r\nIntf.string:\t\t"; +const char End_Header_str[] = "\r\n\r\nEndpoint descriptor:"; +const char End_Address_str[] = "\r\nEndpoint address:\t"; +const char End_Attr_str[] = "\r\nAttr.:\t\t\t"; +const char End_Pktsize_str[] = "\r\nMax.pkt size:\t\t"; +const char End_Interval_str[] = "\r\nPolling interval:\t"; +const char Unk_Header_str[] = "\r\n\r\nUnknown descriptor:"; +const char Unk_Length_str[] = "\r\nLength:\t\t\t"; +const char Unk_Type_str[] = "\r\nType:\t\t\t"; +const char Unk_Contents_str[] = "\r\nContents:\t\t"; + +#endif /* DESCRIPTOR_STRINGS_H_INCLUDED */ diff --git a/hardware/arduino/sam/system/USBHost/examples/USB_desc/test_usb_host.cpp b/hardware/arduino/sam/system/USBHost/examples/USB_desc/test_usb_host.cpp new file mode 100644 index 000000000..9b1e17b0c --- /dev/null +++ b/hardware/arduino/sam/system/USBHost/examples/USB_desc/test_usb_host.cpp @@ -0,0 +1,281 @@ +#include "variant.h" +#include +#include "descriptor_strings.h" + +USBHost Usb; + +/* Forward declarations */ +void PrintAllAddresses(UsbDevice *pdev); +void PrintAddress(uint32_t addr); +void PrintDescriptors(uint32_t addr); +void PrintAllDescriptors(UsbDevice *pdev); +uint32_t getdevdescr(uint32_t addr, uint32_t &num_conf); +//void printhubdescr(uint8_t *descrptr, uint32_t addr); +uint32_t getconfdescr(uint32_t addr, uint32_t conf); +void printconfdescr(uint8_t* descr_ptr); +void printintfdescr(uint8_t* descr_ptr); +void printepdescr(uint8_t* descr_ptr); +void printunkdescr(uint8_t* descr_ptr); + +void setup() +{ + cpu_irq_enable(); + printf("\r\nProgram started:\r\n"); + delay(200); +} + +void loop() +{ + Usb.Task(); + + if( Usb.getUsbTaskState() == USB_STATE_RUNNING ) + { + + Usb.ForEachUsbDevice(&PrintAllDescriptors); + Usb.ForEachUsbDevice(&PrintAllAddresses); + + // Stop here + while( 1 ) + ; + } +} + +void PrintAllAddresses(UsbDevice *pdev) +{ + UsbDeviceAddress adr; + adr.devAddress = pdev->address; + printf("\r\nAddr: %lu (%lu.%lu.%lu)", adr.devAddress, adr.bmHub, adr.bmParent, adr.bmAddress); +} + +void PrintAddress(uint32_t addr) +{ + UsbDeviceAddress adr; + adr.devAddress = addr; + printf("\r\nAddr: %lu (%lu.%lu.%lu)", adr.devAddress, adr.bmHub, adr.bmParent, adr.bmAddress); +} + +void PrintDescriptors(uint32_t addr) +{ + uint32_t rcode = 0; + uint32_t num_conf = 0; + + // Get device descriptor + rcode = getdevdescr(addr, num_conf); + if (rcode) + { + printf("%s%lu\r\n", Gen_Error_str, rcode); + } + printf("\r\n"); + + for (uint32_t i = 0; i < num_conf; ++i) + { + // Get configuration descriptor + rcode = getconfdescr(addr, i); + if (rcode) + { + printf("%s%lu\r\n", Gen_Error_str, rcode); + } + printf("\r\n"); + } +} + +void PrintAllDescriptors(UsbDevice *pdev) +{ + printf("\r\nDevice address %lu:\r\n", pdev->address); + PrintDescriptors(pdev->address); +} + +uint32_t getdevdescr(uint32_t addr, uint32_t &num_conf) +{ + USB_DEVICE_DESCRIPTOR buf; + uint32_t rcode; + + rcode = Usb.getDevDescr(addr, 0, 0x12, (uint8_t*)&buf); + if (rcode) + { + return rcode; + } + + printf("%s", Dev_Header_str); + printf("%s0x%x", Dev_Length_str, buf.bLength); + printf("%s0x%x", Dev_Type_str, buf.bDescriptorType); + printf("%s0x%x", Dev_Version_str, buf.bcdUSB); + printf("%s0x%x", Dev_Class_str, buf.bDeviceClass); + printf("%s0x%x", Dev_Subclass_str, buf.bDeviceSubClass); + printf("%s0x%x", Dev_Protocol_str, buf.bDeviceProtocol); + printf("%s0x%x", Dev_Pktsize_str, buf.bMaxPacketSize0); + printf("%s0x%x", Dev_Vendor_str, buf.idVendor); + printf("%s0x%x", Dev_Product_str, buf.idProduct); + printf("%s0x%x", Dev_Revision_str, buf.bcdDevice); + printf("%s0x%x", Dev_Mfg_str, buf.iManufacturer); + printf("%s0x%x", Dev_Prod_str, buf.iProduct); + printf("%s0x%x", Dev_Serial_str, buf.iSerialNumber); + printf("%s0x%x", Dev_Nconf_str, buf.bNumConfigurations); + num_conf = buf.bNumConfigurations; + + return 0; +} + +/* +void printhubdescr(uint8_t *descrptr, uint32_t addr) +{ + HubDescriptor *pHub = (HubDescriptor*) descrptr; + uint8_t len = *((uint8_t*)descrptr); + + printf("%s", PSTR("\r\n\r\nHub Descriptor:\r\n")); + printf("%s", PSTR("bDescLength:\t\t")); + printfln(pHub->bDescLength, HEX); + + printf("%s", PSTR("bDescriptorType:\t")); + printfln(pHub->bDescriptorType, HEX); + + printf("%s", PSTR("bNbrPorts:\t\t")); + printfln(pHub->bNbrPorts, HEX); + + printf("%s", PSTR("LogPwrSwitchMode:\t")); + printfln(pHub->LogPwrSwitchMode, BIN); + + printf("%s", PSTR("CompoundDevice:\t\t")); + printfln(pHub->CompoundDevice, BIN); + + printf("%s", PSTR("OverCurrentProtectMode:\t")); + printfln(pHub->OverCurrentProtectMode, BIN); + + printf("%s", PSTR("TTThinkTime:\t\t")); + printfln(pHub->TTThinkTime, BIN); + + printf("%s", PSTR("PortIndicatorsSupported:")); + printfln(pHub->PortIndicatorsSupported, BIN); + + printf("%s", PSTR("Reserved:\t\t")); + printfln(pHub->Reserved, HEX); + + printf("%s", PSTR("bPwrOn2PwrGood:\t\t")); + printfln(pHub->bPwrOn2PwrGood, HEX); + + printf("%s", PSTR("bHubContrCurrent:\t")); + printfln(pHub->bHubContrCurrent, HEX); + + for (uint8_t i=7; ibNbrPorts; i++) + // PrintHubPortStatus(&Usb, addr, i, 1); +}*/ + +uint32_t getconfdescr(uint32_t addr, uint32_t conf) +{ + uint8_t buf[BUFSIZE]; + uint8_t* buf_ptr = buf; + uint32_t rcode = 0; + uint32_t descr_length = 0; + uint32_t descr_type = 0; + uint32_t total_length = 0; + + // Get total length + rcode = Usb.getConfDescr(addr, 0, 4, conf, buf); + if (rcode) + { + printf("\r\nError retrieving configuration length. Error code %lu\r\n", rcode); + return(0); + } + + total_length = buf[3] << 8; + total_length |= (buf[2] & 0xff); + + if( total_length > 256 ) + { + // Check if total length is larger than buffer + printf("%s", Conf_Trunc_str); + total_length = 256; + } + + // Get the whole descriptor + rcode = Usb.getConfDescr(addr, 0, total_length, conf, buf); + while (buf_ptr < buf + total_length) + { + // Parsing descriptors + descr_length = *(buf_ptr); + descr_type = *(buf_ptr + 1); + switch (descr_type) + { + case USB_DESCRIPTOR_CONFIGURATION: + printconfdescr(buf_ptr); + break; + case USB_DESCRIPTOR_INTERFACE: + printintfdescr(buf_ptr); + break; + case USB_DESCRIPTOR_ENDPOINT: + printepdescr(buf_ptr); + break; + /*case 0x29: + printhubdescr(buf_ptr, addr); + break;*/ + default: + printunkdescr(buf_ptr); + break; + } + // Advance buffer pointer + buf_ptr = (buf_ptr + descr_length); + } + return 0; +} + +/* function to print configuration descriptor */ +void printconfdescr(uint8_t* descr_ptr) +{ + USB_CONFIGURATION_DESCRIPTOR* conf_ptr = (USB_CONFIGURATION_DESCRIPTOR*)descr_ptr; + + printf("%s", Conf_Header_str); + printf("%s0x%x", Conf_Totlen_str, conf_ptr->wTotalLength); + printf("%s0x%x", Conf_Nint_str, conf_ptr->bNumInterfaces); + printf("%s0x%x", Conf_Value_str, conf_ptr->bConfigurationValue); + printf("%s0x%x", Conf_String_str, conf_ptr->iConfiguration); + printf("%s0x%x", Conf_Attr_str, conf_ptr->bmAttributes); + printf("%s0x%x", Conf_Pwr_str, conf_ptr->bMaxPower); +} + +/* function to print interface descriptor */ +void printintfdescr(uint8_t* descr_ptr) +{ + USB_INTERFACE_DESCRIPTOR* intf_ptr = (USB_INTERFACE_DESCRIPTOR*)descr_ptr; + + printf("%s", Int_Header_str); + printf("%s0x%x", Int_Number_str, intf_ptr->bInterfaceNumber); + printf("%s0x%x", Int_Alt_str, intf_ptr->bAlternateSetting); + printf("%s0x%x", Int_Endpoints_str, intf_ptr->bNumEndpoints); + printf("%s0x%x", Int_Class_str, intf_ptr->bInterfaceClass); + printf("%s0x%x", Int_Subclass_str, intf_ptr->bInterfaceSubClass); + printf("%s0x%x", Int_Protocol_str, intf_ptr->bInterfaceProtocol); + printf("%s0x%x", Int_String_str, intf_ptr->iInterface); +} + +/* function to print endpoint descriptor */ +void printepdescr(uint8_t* descr_ptr) +{ + USB_ENDPOINT_DESCRIPTOR* ep_ptr = (USB_ENDPOINT_DESCRIPTOR*)descr_ptr; + + printf("%s", End_Header_str); + printf("%s0x%x", End_Address_str, ep_ptr->bEndpointAddress); + printf("%s0x%x", End_Attr_str, ep_ptr->bmAttributes); + printf("%s0x%x", End_Pktsize_str, ep_ptr->wMaxPacketSize); + printf("%s0x%x", End_Interval_str, ep_ptr->bInterval); +} + +/* function to print unknown descriptor */ +void printunkdescr(uint8_t* descr_ptr) +{ + uint8_t length = *descr_ptr; + uint32_t i; + + printf("%s", Unk_Header_str); + printf("%s0x%x", Unk_Length_str, *descr_ptr); + printf("%s0x%x", Unk_Type_str, *(descr_ptr + 1)); + printf("%s0x", Unk_Contents_str); + descr_ptr += 2; + for( i = 0; i < length; i++ ) + { + printf("%02x", *descr_ptr); + descr_ptr++; + } +} diff --git a/hardware/arduino/sam/system/USBHost/examples/board_test/board_test.h b/hardware/arduino/sam/system/USBHost/examples/board_test/board_test.h deleted file mode 100644 index 7435d7d57..000000000 --- a/hardware/arduino/sam/system/USBHost/examples/board_test/board_test.h +++ /dev/null @@ -1,21 +0,0 @@ -/* USB Host Shield board test sketch header */ -#ifndef _BOARD_TEST_H_ -#define _BOARD_TEST_H_ - -/* PGMSPACE */ -#include -#include - -/* Messages */ -const char startBanner [] PROGMEM = "\r\nCircuits At Home 2010" - "\r\nUSB Host Shield QC test routine\r\n"; -const char anykey_msg [] PROGMEM = "\r\nPress any key to continue..."; -const char testpassed_msg [] PROGMEM = "\r\nTest PASSED"; -const char testfailed_msg [] PROGMEM = "\r\nTest FAILED*!*"; -const char osctest_oscstate_msg [] PROGMEM = " Oscillator state is "; -const char test_halted_msg [] PROGMEM = "\r\nTest Halted." - "\r\n0x55 pattern is being transmitted via SPI to aid in troubleshooting"; -const char spitest_fail_msg [] PROGMEM = "\r\nSPI transmit/receive mismatch" - "\r\nValue written: "; - -#endif diff --git a/hardware/arduino/sam/system/USBHost/examples/board_test/board_test.ino b/hardware/arduino/sam/system/USBHost/examples/board_test/board_test.ino deleted file mode 100644 index 1188fbf8e..000000000 --- a/hardware/arduino/sam/system/USBHost/examples/board_test/board_test.ino +++ /dev/null @@ -1,296 +0,0 @@ -/* USB Host Shield Board test routine. Runs after assembly to check board functionality */ - -/* USB related */ -//#include -#include -#include -#include - -#include "board_test.h" /* Board test messages */ - -//#define MAX_SS 10 - -void setup(); -void loop(); - -MAX3421E Max; -USB Usb; - -void setup() -{ - Serial.begin( 115200 ); - //Serial.println("Start"); - //Serial.println( SCK_PIN, DEC ); - Max.powerOn(); - printProgStr( startBanner ); - printProgStr( anykey_msg ); - //Serial.print( Max.getvar(), DEC); -} - -void loop() -{ - while( Serial.available() == 0 ); //wait for input - Serial.read(); //empty input buffer - /* start tests */ - /* SPI short test */ - if (!revregcheck()) test_halted(); - /* GPIO test */ - if (!gpiocheck()) printProgStr(PSTR("\r\nGPIO check failed. Make sure GPIO loopback adapter is installed")); - /* SPI long test */ - if (!spitest()) test_halted(); //test SPI for transmission errors - if (!osctest()) printProgStr(PSTR("OSCOK test failed. Check the oscillator")); - if (!usbtest()) printProgStr(PSTR("USB connection test failed. Check traces from USB connector to MAX3421E, as well as VBUS")); //never gets here - /* All tests passed */ - printProgStr( anykey_msg ); -} - -/* SPI short test. Checks connectivity to MAX3421E by reading REVISION register. */ -/* Die rev.1 returns 0x01, rev.2 0x12, rev.3 0x13. Any other value is considered communication error */ -bool revregcheck() -{ - byte tmpbyte; - printProgStr(PSTR("\r\nReading REVISION register...Die revision ")); - tmpbyte = Max.regRd( rREVISION ); - switch( tmpbyte ) { - case( 0x01 ): //rev.01 - printProgStr(PSTR("01")); - break; - case( 0x12 ): //rev.02 - printProgStr(PSTR("02")); - break; - case( 0x13 ): //rev.03 - printProgStr(PSTR("03")); - break; - default: - printProgStr(PSTR("invalid. Value returned: ")); - print_hex( tmpbyte, 8 ); - printProgStr( testfailed_msg ); - return( false ); - break; - }//switch( tmpbyte )... - printProgStr( testpassed_msg ); - return( true ); -} -/* SPI long test */ -bool spitest() -{ - byte l = 0; - byte k = 0; - byte gpinpol_copy = Max.regRd( rGPINPOL ); - printProgStr(PSTR("\r\nSPI test. Each '.' indicates 64K transferred. Stops after transferring 1MB (16 dots)\r\n")); - /**/ - for( byte j = 0; j < 16; j++ ) { - for( word i = 0; i < 65535; i++ ) { - Max.regWr( rGPINPOL, k ); - l = Max.regRd( rGPINPOL); - if( l != k ) { - printProgStr( spitest_fail_msg ); - print_hex( k, 8); - printProgStr(PSTR("Value read: ")); - print_hex( l, 8 ); - return( false ); //test failed - } - k++; - }//for( i = 0; i < 65535; i++ - Serial.print("."); - }//for j = 0; j < 16... - Max.regWr( rGPINPOL, gpinpol_copy ); - printProgStr(testpassed_msg); - return( true ); -} -/* Oscillator test */ -bool osctest() -{ - printProgStr(PSTR("\r\nOscillator start/stop test.")); - printProgStr( osctest_oscstate_msg ); - check_OSCOKIRQ(); //print OSCOK state - printProgStr(PSTR("\r\nSetting CHIP RESET.")); - Max.regWr( rUSBCTL, bmCHIPRES ); //Chip reset. This stops the oscillator - printProgStr( osctest_oscstate_msg ); - check_OSCOKIRQ(); //print OSCOK state - printProgStr(PSTR("\r\nClearing CHIP RESET. ")); - Max.regWr( rUSBCTL, 0x00 ); //Chip reset release - for( word i = 0; i < 65535; i++) { - if( Max.regRd( rUSBIRQ ) & bmOSCOKIRQ ) { - printProgStr(PSTR("PLL is stable. Time to stabilize - ")); - Serial.print( i, DEC ); - printProgStr(PSTR(" cycles")); - printProgStr( testpassed_msg ); - return( true ); - } - }//for i = - return(false); -} -/* Stop/start oscillator */ -void check_OSCOKIRQ() -{ - if( Max.regRd( rUSBIRQ ) & bmOSCOKIRQ ) { //checking oscillator state - printProgStr(PSTR("ON")); - } - else { - printProgStr(PSTR("OFF")); - } -} -/* Test USB connectivity */ -bool usbtest() -{ - byte rcode; - byte usbstate; - Max.powerOn(); - delay( 200 ); - printProgStr(PSTR("\r\nUSB Connectivity test. Waiting for device connection... ")); - while( 1 ) { - delay( 200 ); - Max.Task(); - Usb.Task(); - usbstate = Usb.getUsbTaskState(); - switch( usbstate ) { - case( USB_ATTACHED_SUBSTATE_RESET_DEVICE ): - printProgStr(PSTR("\r\nDevice connected. Resetting")); - break; - case( USB_ATTACHED_SUBSTATE_WAIT_SOF ): - printProgStr(PSTR("\r\nReset complete. Waiting for the first SOF...")); - //delay( 1000 ); - break; - case( USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE ): - printProgStr(PSTR("\r\nSOF generation started. Enumerating device.")); - break; - case( USB_STATE_ADDRESSING ): - printProgStr(PSTR("\r\nSetting device address")); - //delay( 100 ); - break; - case( USB_STATE_CONFIGURING ): - //delay( 1000 ); - printProgStr(PSTR("\r\nGetting device descriptor")); - rcode = getdevdescr( 1 ); - if( rcode ) { - printProgStr(PSTR("\r\nError reading device descriptor. Error code ")); - print_hex( rcode, 8 ); - } - else { - printProgStr(PSTR("\r\n\nAll tests passed. Press RESET to restart test")); - while(1); - } - break; - case( USB_STATE_ERROR ): - printProgStr(PSTR("\r\nUSB state machine reached error state")); - break; - default: - break; - }//switch - }//while(1) -} -/* Get device descriptor */ -byte getdevdescr( byte addr ) -{ - USB_DEVICE_DESCRIPTOR buf; - byte rcode; - rcode = Usb.getDevDescr( addr, 0, 0x12, ( char *)&buf ); - if( rcode ) { - return( rcode ); - } - printProgStr(PSTR("\r\nDevice descriptor: ")); - printProgStr(PSTR("\r\nDescriptor Length:\t")); - print_hex( buf.bLength, 8 ); - printProgStr(PSTR("\r\nDescriptor type:\t")); - print_hex( buf.bDescriptorType, 8 ); - printProgStr(PSTR("\r\nUSB version:\t")); - print_hex( buf.bcdUSB, 16 ); - printProgStr(PSTR("\r\nDevice class:\t")); - print_hex( buf.bDeviceClass, 8 ); - printProgStr(PSTR("\r\nDevice Subclass:\t")); - print_hex( buf.bDeviceSubClass, 8 ); - printProgStr(PSTR("\r\nDevice Protocol:\t")); - print_hex( buf.bDeviceProtocol, 8 ); - printProgStr(PSTR("\r\nMax.packet size:\t")); - print_hex( buf.bMaxPacketSize0, 8 ); - printProgStr(PSTR("\r\nVendor ID:\t")); - print_hex( buf.idVendor, 16 ); - printProgStr(PSTR("\r\nProduct ID:\t")); - print_hex( buf.idProduct, 16 ); - printProgStr(PSTR("\r\nRevision ID:\t")); - print_hex( buf.bcdDevice, 16 ); - printProgStr(PSTR("\r\nMfg.string index:\t")); - print_hex( buf.iManufacturer, 8 ); - printProgStr(PSTR("\r\nProd.string index:\t")); - print_hex( buf.iProduct, 8 ); - printProgStr(PSTR("\r\nSerial number index:\t")); - print_hex( buf.iSerialNumber, 8 ); - printProgStr(PSTR("\r\nNumber of conf.:\t")); - print_hex( buf.bNumConfigurations, 8 ); - return( 0 ); -} - -/* GPIO lines check. A loopback adapter connecting GPIN to GPOUT is assumed */ -bool gpiocheck() -{ - byte tmpbyte = 0; - printProgStr(PSTR("\r\nChecking GPIO lines. Install GPIO loopback adapter and press any key to continue...")); - while( Serial.available() == 0 ); //wait for input - Serial.read(); //empty input buffer - for( byte i = 0; i < 255; i++ ) { - Max.gpioWr( i ); - tmpbyte = Max.gpioRd(); - if( tmpbyte != i ) { - printProgStr(PSTR("GPIO read/write mismatch. Write: ")); - Serial.print(i, HEX); - printProgStr(PSTR(" Read: ")); - Serial.println( tmpbyte, HEX ); - return( false ); - }//if( tmpbyte != i ) - }//for( i= 0... - printProgStr( testpassed_msg ); - return( true ); -} -/* Test halted state. Generates 0x55 to aid in SPI troubleshooting */ -void test_halted() -{ - printProgStr( test_halted_msg ); - printProgStr(PSTR("\r\nPress RESET to restart test")); - while( 1 ) { //System Stop. Generating pattern to keep SCLK, MISO, MOSI, SS busy - digitalWrite(MAX_SS,LOW); - Max.regWr( 0x55, 0x55 ); -// Spi.transfer( 0x55 ); - digitalWrite(MAX_SS,HIGH); - } -} -/* given a PROGMEM string, use Serial.print() to send it out */ -/* Some non-intuitive casting necessary: */ -/* printProgStr(PSTR("Func.Mode:\t0x")); */ -/* printProgStr((char*)pgm_read_word(&mtpopNames[(op & 0xFF)])); */ -void printProgStr(const char* str ) -{ - if(!str) { - return; - } - char c; - while((c = pgm_read_byte(str++))) { - Serial.print(c,BYTE); - } -} -/* prints hex numbers with leading zeroes */ -// copyright, Peter H Anderson, Baltimore, MD, Nov, '07 -// source: http://www.phanderson.com/arduino/arduino_display.html -void print_hex(int v, int num_places) -{ - int mask=0, n, num_nibbles, digit; - - for (n=1; n<=num_places; n++) - { - mask = (mask << 1) | 0x0001; - } - v = v & mask; // truncate v to specified number of places - - num_nibbles = num_places / 4; - if ((num_places % 4) != 0) - { - ++num_nibbles; - } - - do - { - digit = ((v >> (num_nibbles-1) * 4)) & 0x0f; - Serial.print(digit, HEX); - } - while(--num_nibbles); -} diff --git a/hardware/arduino/sam/system/USBHost/examples/conf_descr_dump/conf_descr_dump.ino b/hardware/arduino/sam/system/USBHost/examples/conf_descr_dump/conf_descr_dump.ino deleted file mode 100644 index 56d7a5855..000000000 --- a/hardware/arduino/sam/system/USBHost/examples/conf_descr_dump/conf_descr_dump.ino +++ /dev/null @@ -1,181 +0,0 @@ -/* MAX3421E USB Host controller get configuration descriptor */ -#include -#include -#include - -#define LOBYTE(x) ((char*)(&(x)))[0] -#define HIBYTE(x) ((char*)(&(x)))[1] -#define BUFSIZE 256 //buffer size - -void setup(); -void loop(); - -MAX3421E Max; -USB Usb; - -void setup() -{ - byte tmpdata = 0; - Serial.begin( 9600 ); - Serial.println("Start"); - Max.powerOn(); - delay( 200 ); -} - -void loop() -{ - byte rcode; - byte tmpbyte; - Max.Task(); - Usb.Task(); - if( Usb.getUsbTaskState() >= USB_STATE_CONFIGURING ) { //state configuring or higher - /* entering configuration number to decode. Restricted to first 10 configurations */ - Serial.print("Enter configuration number: "); - while( Serial.available() == 0 ); //wait for input - tmpbyte = Serial.read(); - Serial.println( tmpbyte ); - tmpbyte -= 0x30; //convert to number - if( tmpbyte > 9 ) { - Serial.println("Not a number. Assuming configuration 0"); - tmpbyte = 0; - } - rcode = getconfdescr( 1, tmpbyte ); //get configuration descriptor - if( rcode ) { - Serial.println( rcode, HEX ); - } -// while( 1 ); //stop - } -} - -byte getconfdescr( byte addr, byte conf ) -{ - char buf[ BUFSIZE ]; - char* buf_ptr = buf; - byte rcode; - byte descr_length; - byte descr_type; - unsigned int total_length; - rcode = Usb.getConfDescr( addr, 0, 4, conf, buf ); //get total length - LOBYTE( total_length ) = buf[ 2 ]; - HIBYTE( total_length ) = buf[ 3 ]; - if( total_length > BUFSIZE ) { //check if total length is larger than buffer - Serial.println("Total length truncated to 256 bytes"); - total_length = BUFSIZE; - } - rcode = Usb.getConfDescr( addr, 0, total_length, conf, buf ); //get the whole descriptor - while( buf_ptr < buf + total_length ) { //parsing descriptors - descr_length = *( buf_ptr ); - descr_type = *( buf_ptr + 1 ); - switch( descr_type ) { - case( USB_DESCRIPTOR_CONFIGURATION ): - printconfdescr( buf_ptr ); - break; - case( USB_DESCRIPTOR_INTERFACE ): - printintfdescr( buf_ptr ); - break; - case( USB_DESCRIPTOR_ENDPOINT ): - printepdescr( buf_ptr ); - break; - default: - printunkdescr( buf_ptr ); - break; - }//switch( descr_type - Serial.println(""); - buf_ptr = ( buf_ptr + descr_length ); //advance buffer pointer - }//while( buf_ptr <=... - return( 0 ); -} -/* prints hex numbers with leading zeroes */ -// copyright, Peter H Anderson, Baltimore, MD, Nov, '07 -// source: http://www.phanderson.com/arduino/arduino_display.html -void print_hex(int v, int num_places) -{ - int mask=0, n, num_nibbles, digit; - - for (n=1; n<=num_places; n++) { - mask = (mask << 1) | 0x0001; - } - v = v & mask; // truncate v to specified number of places - - num_nibbles = num_places / 4; - if ((num_places % 4) != 0) { - ++num_nibbles; - } - do { - digit = ((v >> (num_nibbles-1) * 4)) & 0x0f; - Serial.print(digit, HEX); - } - while(--num_nibbles); -} -/* function to print configuration descriptor */ -void printconfdescr( char* descr_ptr ) -{ - USB_CONFIGURATION_DESCRIPTOR* conf_ptr = ( USB_CONFIGURATION_DESCRIPTOR* )descr_ptr; - Serial.println("Configuration descriptor:"); - Serial.print("Total length:\t"); - print_hex( conf_ptr->wTotalLength, 16 ); - Serial.print("\r\nNum.intf:\t\t"); - print_hex( conf_ptr->bNumInterfaces, 8 ); - Serial.print("\r\nConf.value:\t"); - print_hex( conf_ptr->bConfigurationValue, 8 ); - Serial.print("\r\nConf.string:\t"); - print_hex( conf_ptr->iConfiguration, 8 ); - Serial.print("\r\nAttr.:\t\t"); - print_hex( conf_ptr->bmAttributes, 8 ); - Serial.print("\r\nMax.pwr:\t\t"); - print_hex( conf_ptr->bMaxPower, 8 ); - return; -} -/* function to print interface descriptor */ -void printintfdescr( char* descr_ptr ) -{ - USB_INTERFACE_DESCRIPTOR* intf_ptr = ( USB_INTERFACE_DESCRIPTOR* )descr_ptr; - Serial.println("\r\nInterface descriptor:"); - Serial.print("Intf.number:\t"); - print_hex( intf_ptr->bInterfaceNumber, 8 ); - Serial.print("\r\nAlt.:\t\t"); - print_hex( intf_ptr->bAlternateSetting, 8 ); - Serial.print("\r\nEndpoints:\t\t"); - print_hex( intf_ptr->bNumEndpoints, 8 ); - Serial.print("\r\nClass:\t\t"); - print_hex( intf_ptr->bInterfaceClass, 8 ); - Serial.print("\r\nSubclass:\t\t"); - print_hex( intf_ptr->bInterfaceSubClass, 8 ); - Serial.print("\r\nProtocol:\t\t"); - print_hex( intf_ptr->bInterfaceProtocol, 8 ); - Serial.print("\r\nIntf.string:\t"); - print_hex( intf_ptr->iInterface, 8 ); - return; -} -/* function to print endpoint descriptor */ -void printepdescr( char* descr_ptr ) -{ - USB_ENDPOINT_DESCRIPTOR* ep_ptr = ( USB_ENDPOINT_DESCRIPTOR* )descr_ptr; - Serial.println("\r\nEndpoint descriptor:"); - Serial.print("Endpoint address:\t"); - print_hex( ep_ptr->bEndpointAddress, 8 ); - Serial.print("\r\nAttr.:\t\t"); - print_hex( ep_ptr->bmAttributes, 8 ); - Serial.print("\r\nMax.pkt size:\t"); - print_hex( ep_ptr->wMaxPacketSize, 16 ); - Serial.print("\r\nPolling interval:\t"); - print_hex( ep_ptr->bInterval, 8 ); - return; -} -/*function to print unknown descriptor */ -void printunkdescr( char* descr_ptr ) -{ - byte length = *descr_ptr; - byte i; - Serial.println("\r\nUnknown descriptor:"); - Serial. print("Length:\t\t"); - print_hex( *descr_ptr, 8 ); - Serial.print("\r\nType:\t\t"); - print_hex( *(descr_ptr + 1 ), 8 ); - Serial.print("\r\nContents:\t"); - descr_ptr += 2; - for( i = 0; i < length; i++ ) { - print_hex( *descr_ptr, 8 ); - descr_ptr++; - } -} diff --git a/hardware/arduino/sam/system/USBHost/examples/descriptor_parser/descriptor_parser.h b/hardware/arduino/sam/system/USBHost/examples/descriptor_parser/descriptor_parser.h deleted file mode 100644 index 757084186..000000000 --- a/hardware/arduino/sam/system/USBHost/examples/descriptor_parser/descriptor_parser.h +++ /dev/null @@ -1,284 +0,0 @@ -#ifndef _DESCRIPTOR_PARSER_ -#define _DESCRIPTOR_PARSER_ - -/* PGMSPACE */ -#include -#include - -typedef void (*PARSE)( uint8_t bytes ); - -/* Common Messages */ - -const char descr_len [] PROGMEM = "\r\nDescriptor Length:\t"; -const char descr_type [] PROGMEM = "\r\nDescriptor type:\t"; -const char class_str [] PROGMEM = "\r\nClass:\t\t\t"; -const char subclass_str [] PROGMEM = "\r\nSubclass:\t\t"; -const char protocol_str [] PROGMEM = "\r\nProtocol:\t\t"; -const char maxpktsize_str [] PROGMEM = "\r\nMax.packet size:\t"; -const char unk_msg [] PROGMEM = " Unknown"; -const char reserved_msg [] PROGMEM = "Reserved"; -const char rcode_error_msg [] PROGMEM = "\r\nRequest error. Reurn code: "; - -/* Endpoint attributes */ - -const char control_tr [] PROGMEM = "Control"; -const char iso_tr [] PROGMEM = "Isochronous"; -const char bulk_tr [] PROGMEM = "Bulk"; -const char int_tr [] PROGMEM = "Interrupt"; - -const char* transfer_types [] PROGMEM = -{ - control_tr, - iso_tr, - bulk_tr, - int_tr -}; - -const char nosync_type [] PROGMEM = "No Synchronization"; -const char async_type [] PROGMEM = "Asynchronous"; -const char adaptive_type [] PROGMEM = "Adaptive"; -const char sync_type [] PROGMEM = "Synchronous"; - -const char* sync_types [] PROGMEM = -{ - nosync_type, - async_type, - adaptive_type, - sync_type -}; - -const char data_usage [] PROGMEM = "Data"; -const char feedback_usage [] PROGMEM = "Feedback"; -const char implicit_usage [] PROGMEM = "Implicit Feedback Data"; -const char reserved_usage [] PROGMEM = "Reserved"; - -const char* usage_types [] PROGMEM = -{ - data_usage, - feedback_usage, - implicit_usage, - reserved_usage -}; - -/* HID Country Codes */ - -const char notsupported_cc [] PROGMEM = "Not Supported"; -const char arabic_cc [] PROGMEM = "Arabic"; -const char belgian_cc [] PROGMEM = "Belgian"; -const char canadianbi_cc [] PROGMEM = "Canadian-Bilingual"; -const char canadianfr_cc [] PROGMEM = "Canadian-French"; -const char czech_cc [] PROGMEM = "Czech Republic"; -const char danish_cc [] PROGMEM = "Danish"; -const char finnish_cc [] PROGMEM = "Finnish"; -const char french_cc [] PROGMEM = "French"; -const char german_cc [] PROGMEM = "German"; -const char greek_cc [] PROGMEM = "Greek"; -const char hebrew_cc [] PROGMEM = "Hebrew"; -const char hungary_cc [] PROGMEM = "Hungary"; -const char intl_cc [] PROGMEM = "International (ISO)"; -const char italian_cc [] PROGMEM = "Italian"; -const char japan_cc [] PROGMEM = "Japan (Katakana)"; -const char korean_cc [] PROGMEM = "Korean"; -const char latam_cc [] PROGMEM = "Latin American"; -const char dutch_cc [] PROGMEM = "Netherlands/Dutch"; -const char norwegian_cc [] PROGMEM = "Norwegian"; -const char persian_cc [] PROGMEM = "Persian (Farsi)"; -const char poland_cc [] PROGMEM = "Poland"; -const char portuguese_cc [] PROGMEM = "Portuguese"; -const char russia_cc [] PROGMEM = "Russia"; -const char slovakia_cc [] PROGMEM = "Slovakia"; -const char spanish_cc [] PROGMEM = "Spanish"; -const char swedish_cc [] PROGMEM = "Swedish"; -const char swiss_fr_cc [] PROGMEM = "Swiss/French"; -const char swiss_ger_cc [] PROGMEM = "Swiss/German"; -const char swiss_cc [] PROGMEM = "Switzerland"; -const char taiwan_cc [] PROGMEM = "Taiwan"; -const char turkish_q_cc [] PROGMEM = "Turkish-Q"; -const char uk_cc [] PROGMEM = "UK"; -const char us_cc [] PROGMEM = "US"; -const char yugo_cc [] PROGMEM = "Yugoslavia"; -const char turkish_f_cc [] PROGMEM = "Turkish-F"; - -const char* HID_Country_Codes [] PROGMEM = -{ -notsupported_cc, -arabic_cc, -belgian_cc, -canadianbi_cc, -canadianfr_cc, -czech_cc, -danish_cc, -finnish_cc, -french_cc, -german_cc, -greek_cc, -hebrew_cc, -hungary_cc, -intl_cc, -italian_cc, -japan_cc, -korean_cc, -latam_cc, -dutch_cc, -norwegian_cc, -persian_cc, -poland_cc, -portuguese_cc, -russia_cc, -slovakia_cc, -spanish_cc, -swedish_cc, -swiss_fr_cc, -swiss_ger_cc, -swiss_cc, -taiwan_cc, -turkish_q_cc, -uk_cc, -us_cc, -yugo_cc, -turkish_f_cc -}; - -/* HID report descriptor parser string definitions */ -/* Item type strings */ -const char btype_main [] PROGMEM = "Main"; -const char btype_global [] PROGMEM = "Global"; -const char btype_local [] PROGMEM = "Local"; -const char btype_reserved [] PROGMEM = "Reserved"; -/* Item types strings array. Array index corresponds to bType */ -const char* btypes [] PROGMEM = -{ - btype_main, - btype_global, - btype_local, - btype_reserved -}; -/* Main Item Tag Strings */ -const char main_tag_input [] PROGMEM = "Input\t\t"; -const char main_tag_output [] PROGMEM = "Output\t\t"; -const char main_tag_collection [] PROGMEM = "Collection\t\t"; -const char main_tag_feature [] PROGMEM = "Feature\t\t"; -const char main_tag_endcoll [] PROGMEM = "End Collection\t"; -/* Main Item Tags Strings Array */ -const char* maintags [] PROGMEM = -{ - main_tag_input, - main_tag_output, - main_tag_collection, - main_tag_feature, - main_tag_endcoll -}; -/* Global Item Tag Strings */ -const char global_tag_usagepage [] PROGMEM = "Usage Page\t\t"; -const char global_tag_logmin [] PROGMEM = "Logical Minimum\t"; -const char global_tag_logmax [] PROGMEM = "Logical Maximum\t"; -const char global_tag_physmin [] PROGMEM = "Physical Minimum\t"; -const char global_tag_physmax [] PROGMEM = "Physical Maximum\t"; -const char global_tag_unitexp [] PROGMEM = "Unit Exponent\t"; -const char global_tag_unit [] PROGMEM = "Unit\t\t"; -const char global_tag_repsize [] PROGMEM = "Report Size\t"; -const char global_tag_repid [] PROGMEM = "Report ID\t\t"; -const char global_tag_repcount [] PROGMEM = "Report Count\t"; -const char global_tag_push [] PROGMEM = "Push\t\t"; -const char global_tag_pop [] PROGMEM = "Pop\t\t"; -/* Global Item Tag Strings Array */ -const char* globaltags [] PROGMEM = -{ - global_tag_usagepage, - global_tag_logmin, - global_tag_logmax, - global_tag_physmin, - global_tag_physmax, - global_tag_unitexp, - global_tag_unit, - global_tag_repsize, - global_tag_repid, - global_tag_repcount, - global_tag_push, - global_tag_pop -}; -/* Local Item Tag Strings */ -const char local_tag_usage [] PROGMEM = "Usage\t\t"; -const char local_tag_usagemin [] PROGMEM = "Usage Minimum\t"; -const char local_tag_usagemax [] PROGMEM = "Usage Maximum\t"; -const char local_tag_desidx [] PROGMEM = "Designator Index\t"; -const char local_tag_desmin [] PROGMEM = "Designator Minimum\t"; -const char local_tag_desmax [] PROGMEM = "Designator Maximum\t"; -const char local_tag_stridx [] PROGMEM = "String Index\t"; -const char local_tag_strmin [] PROGMEM = "String Minimum\t"; -const char local_tag_strmax [] PROGMEM = "String Maximum\t"; -const char local_tag_delimiter [] PROGMEM = "Delimiter\t"; -/* Local Item Tag Strings Array */ -const char* localtags [] PROGMEM = -{ - local_tag_usage, - local_tag_usagemin, - local_tag_usagemax, - local_tag_desidx, - local_tag_desmin, - local_tag_desmax, - local_tag_stridx, - local_tag_strmin, - local_tag_strmax, - local_tag_delimiter -}; -/* Collection Types Strings */ -const char coll_phy [] PROGMEM = "Physical (group of axes)"; -const char coll_app [] PROGMEM = "Application (mouse, keyboard)"; -const char coll_log [] PROGMEM = "Logical (interrelated data)"; -const char coll_rep [] PROGMEM = "Report"; -const char coll_arr [] PROGMEM = "Named Array"; -const char coll_usw [] PROGMEM = "Usage Switch"; -const char coll_umod [] PROGMEM = "Usage Modifier"; -/* Collection Types Strings Array */ -const char* collections [] PROGMEM = -{ - coll_phy, - coll_app, - coll_log, - coll_rep, - coll_arr, - coll_usw, - coll_umod -}; -/* Usage Pages Strings */ -const char up_undef [] PROGMEM = "Undefined"; -const char up_gendesk [] PROGMEM = "Generic Desktop Controls"; -const char up_sim [] PROGMEM = "Simulation Controls"; -const char up_vr [] PROGMEM = "VR Controls"; -const char up_sport [] PROGMEM = "Sport Controls"; -const char up_game [] PROGMEM = "Game Controls"; -const char up_gendev [] PROGMEM = "Generic Device Controls"; -const char up_kbd [] PROGMEM = "Keyboard/Keypad"; -const char up_led [] PROGMEM = "LEDs"; -const char up_button [] PROGMEM = "Button"; -const char up_ord [] PROGMEM = "Ordinal"; -const char up_tele [] PROGMEM = "Telephony"; -const char up_cons [] PROGMEM = "Consumer"; -const char up_dig [] PROGMEM = "Digitizer"; -//const char up_res [] PROGMEM = "Reserved"; -const char up_pid [] PROGMEM = "PID Page"; -const char up_uni [] PROGMEM = "Unicode"; -/* Usage Pages Strings Array */ -const char * usage_pages [] PROGMEM = -{ - up_undef, - up_gendesk, - up_sim, - up_vr, - up_sport, - up_game, - up_gendev, - up_kbd, - up_led, - up_button, - up_ord, - up_tele, - up_cons, - up_dig, - reserved_msg, - up_pid, - up_uni -}; - -#endif //_DESCRIPTOR_PARSER_ diff --git a/hardware/arduino/sam/system/USBHost/examples/descriptor_parser/descriptor_parser.ino b/hardware/arduino/sam/system/USBHost/examples/descriptor_parser/descriptor_parser.ino deleted file mode 100644 index d417e76f8..000000000 --- a/hardware/arduino/sam/system/USBHost/examples/descriptor_parser/descriptor_parser.ino +++ /dev/null @@ -1,720 +0,0 @@ -/* MAX3421E USB Host controller configuration descriptor parser */ -#include -#include -#include -#include "descriptor_parser.h" - -#define LOBYTE(x) ((char*)(&(x)))[0] -#define HIBYTE(x) ((char*)(&(x)))[1] -#define BUFSIZE 256 //buffer size -#define DEVADDR 1 - -#define getReportDescr( addr, ep, nbytes, parse_func, nak_limit ) ctrlXfer( addr, ep, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, HID_DESCRIPTOR_REPORT, 0x0000, nbytes, parse_func, nak_limit ) -#define getReport( addr, ep, nbytes, interface, report_type, report_id, parse_func, nak_limit ) ctrlXfer( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, report_id, report_type, interface, nbytes, parse_func, nak_limit ) - -/* Foeward declarations */ -void setup(); -void loop(); -byte ctrlXfer( byte addr, byte ep, byte bmReqType, byte bRequest, byte wValLo, byte wValHi, unsigned int wInd, uint16_t nbytes, PARSE parse_func, uint16_t nak_limit ); -void HIDreport_parse( uint8_t* buf, uint8_t* head, uint8_t* tail); - -typedef struct { - uint8_t bDescriptorType; - uint16_t wDescriptorLength; -} HID_CLASS_DESCRIPTOR; - - -//typedef void (*PARSE)( int8_t*, int8_t*, int8_t ); - -MAX3421E Max; -USB Usb; - -void setup() -{ - Serial.begin( 115200 ); - printProgStr(PSTR("\r\nStart")); - Max.powerOn(); - delay( 200 ); -} - -void loop() -{ - uint8_t rcode; - uint8_t tmpbyte = 0; - //PARSE pf = &HIDreport_parse; - /**/ - Max.Task(); - Usb.Task(); - if( Usb.getUsbTaskState() >= USB_STATE_CONFIGURING ) { //state configuring or higher - /* printing device descriptor */ - printProgStr(PSTR("\r\nDevice addressed... ")); - printProgStr(PSTR("Requesting device descriptor.")); - tmpbyte = getdevdescr( DEVADDR ); //number of configurations, 0 if error - if( tmpbyte == 0 ) { - printProgStr(PSTR("\r\nDevice descriptor cannot be retrieved. Program Halted\r\n")); - while( 1 ); //stop - }//if( tmpbyte - /* print configuration descriptors for all configurations */ - for( uint8_t i = 0; i < tmpbyte; i++ ) { - getconfdescr( DEVADDR, i ); - } - /* Stop */ - while( 1 ); //stop - } -} - -/* Prints device descriptor. Returns number of configurations or zero if request error occured */ -byte getdevdescr( byte addr ) -{ - USB_DEVICE_DESCRIPTOR buf; - byte rcode; - //Max.toggle( BPNT_0 ); - rcode = Usb.getDevDescr( addr, 0, 0x12, ( char *)&buf ); - if( rcode ) { - printProgStr( rcode_error_msg ); - print_hex( rcode, 8 ); - return( 0 ); - } - printProgStr(PSTR("\r\nDevice descriptor: \r\n")); - //Descriptor length - printProgStr( descr_len ); - print_hex( buf.bLength, 8 ); - //Descriptor type -// printProgStr( descr_type ); -// print_hex( buf.bDescriptorType, 8 ); -// printProgStr( descrtype_parse( buf.bDescriptorType )); - //USB Version - printProgStr(PSTR("\r\nUSB version:\t\t")); - Serial.print(( HIBYTE( buf.bcdUSB )), HEX ); - Serial.print("."); - Serial.print(( LOBYTE( buf.bcdUSB )), HEX ); - //Device class - printProgStr( class_str ); - print_hex( buf.bDeviceClass, 8 ); - printProgStr( classname_parse( buf.bDeviceClass )); - //Device Subclass - printProgStr( subclass_str ); - print_hex( buf.bDeviceSubClass, 8 ); - //Device Protocol - printProgStr( protocol_str ); - print_hex( buf.bDeviceProtocol, 8 ); - //Max.packet size - printProgStr( maxpktsize_str ); - print_hex( buf.bMaxPacketSize0, 8 ); - //VID - printProgStr(PSTR("\r\nVendor ID:\t\t")); - print_hex( buf.idVendor, 16 ); - //PID - printProgStr(PSTR("\r\nProduct ID:\t\t")); - print_hex( buf.idProduct, 16 ); - //Revision - printProgStr(PSTR("\r\nRevision ID:\t\t")); - print_hex( buf.bcdDevice, 16 ); - //Mfg.string - printProgStr (PSTR("\r\nMfg.string index:\t")); - print_hex( buf.iManufacturer, 8 ); - getstrdescr( addr, buf.iManufacturer ); - //Prod.string - printProgStr(PSTR("\r\nProd.string index:\t")); - print_hex( buf.iProduct, 8 ); - //printProgStr( str_cont ); - getstrdescr( addr, buf.iProduct ); - //Serial number string - printProgStr(PSTR("\r\nSerial number index:\t")); - print_hex( buf.iSerialNumber, 8 ); - //printProgStr( str_cont ); - getstrdescr( addr, buf.iSerialNumber ); - //Number of configurations - printProgStr(PSTR("\r\nNumber of conf.:\t")); - print_hex( buf.bNumConfigurations, 8 ); - return( buf.bNumConfigurations ); -} -/* Get string descriptor. Takes device address and string index */ -byte getstrdescr( byte addr, byte idx ) -{ - char buf[ BUFSIZE ]; - byte rcode; - byte length; - byte i; - unsigned int langid; - if( idx == 0 ) { //don't try to get index zero - return( 0 ); - } - rcode = Usb.getStrDescr( addr, 0, 1, 0, 0, buf ); //get language table length - if( rcode ) { - printProgStr(PSTR("\r\nError retrieving LangID table length")); - return( rcode ); - } - length = buf[ 0 ]; //length is the first byte - rcode = Usb.getStrDescr( addr, 0, length, 0, 0, buf ); //get language table - if( rcode ) { - printProgStr(PSTR("\r\nError retrieving LangID table")); - return( rcode ); - } - HIBYTE( langid ) = buf[ 3 ]; //get first langid - LOBYTE( langid ) = buf[ 2 ]; //bytes are swapped to account for endiannes - //printProgStr(PSTR("\r\nLanguage ID: ")); - //print_hex( langid, 16 ); - rcode = Usb.getStrDescr( addr, 0, 1, idx, langid, buf ); - if( rcode ) { - printProgStr(PSTR("\r\nError retrieving string length")); - return( rcode ); - } - length = ( buf[ 0 ] < 254 ? buf[ 0 ] : 254 ); - printProgStr(PSTR(" Length: ")); - Serial.print( length, DEC ); - rcode = Usb.getStrDescr( addr, 0, length, idx, langid, buf ); - if( rcode ) { - printProgStr(PSTR("\r\nError retrieveing string")); - return( rcode ); - } - printProgStr(PSTR(" Contents: ")); - for( i = 2; i < length; i+=2 ) { - Serial.print( buf[ i ] ); - } - return( idx ); -} -/* Returns string to class name */ -const char* classname_parse( byte class_number ) -{ - switch( class_number ) { - case 0x00: - return PSTR(" Use class information in the Interface Descriptor"); - case 0x01: - return PSTR(" Audio"); - case 0x02: - return PSTR(" Communications and CDC Control"); - case 0x03: - return PSTR(" HID (Human Interface Device)"); - case 0x05: - return PSTR(" Physical"); - case 0x06: - return PSTR(" Image"); - case 0x07: - return PSTR(" Printer"); - case 0x08: - return PSTR(" Mass Storage"); - case 0x09: - return PSTR(" Hub"); - case 0x0a: - return PSTR(" CDC-Data"); - case 0x0b: - return PSTR(" Smart Card"); - case 0x0d: - return PSTR(" Content Security"); - case 0x0e: - return PSTR(" Video"); - case 0x0f: - return PSTR(" Personal Healthcare"); - case 0xdc: - return PSTR("Diagnostic Device"); - case 0xe0: - return PSTR(" Wireless Controller"); - case 0xef: - return PSTR(" Miscellaneous"); - case 0xfe: - return PSTR(" Application Specific"); - case 0xff: - return PSTR(" Vendor Specific"); - default: - return unk_msg; - }//switch( class_number -} -/* Getting configuration descriptor */ -byte getconfdescr( byte addr, byte conf ) -{ - char buf[ BUFSIZE ]; - char* buf_ptr = buf; - byte rcode; - byte descr_length; - byte descr_type; - unsigned int total_length; - printProgStr(PSTR("\r\n\nConfiguration number ")); - Serial.print( conf, HEX ); - rcode = Usb.getConfDescr( addr, 0, 4, conf, buf ); //get total length - if( rcode ) { - printProgStr(PSTR("Error retrieving configuration length. Error code ")); - Serial.println( rcode, HEX ); - return( 0 ); - }//if( rcode - LOBYTE( total_length ) = buf[ 2 ]; - HIBYTE( total_length ) = buf[ 3 ]; - printProgStr(PSTR("\r\nTotal configuration length: ")); - Serial.print( total_length, DEC ); - printProgStr(PSTR(" bytes")); - if( total_length > BUFSIZE ) { //check if total length is larger than buffer - printProgStr(PSTR("Total length truncated to ")); - Serial.print( BUFSIZE, DEC); - printProgStr(PSTR("bytes")); - total_length = BUFSIZE; - } - rcode = Usb.getConfDescr( addr, 0, total_length, conf, buf ); //get the whole descriptor - while( buf_ptr < buf + total_length ) { //parsing descriptors - descr_length = *( buf_ptr ); - descr_type = *( buf_ptr + 1 ); - switch( descr_type ) { - case( USB_DESCRIPTOR_CONFIGURATION ): - printconfdescr( buf_ptr ); - break; - case( USB_DESCRIPTOR_INTERFACE ): - printintfdescr( buf_ptr ); - break; - case( USB_DESCRIPTOR_ENDPOINT ): - printepdescr( buf_ptr ); - break; - case( HID_DESCRIPTOR_HID ): - printhid_descr( buf_ptr ); - break; - default: - printunkdescr( buf_ptr ); - break; - }//switch( descr_type - Serial.println(""); - buf_ptr = ( buf_ptr + descr_length ); //advance buffer pointer - }//while( buf_ptr <=... - return( 0 ); -} -/* function to print configuration descriptor */ -void printconfdescr( char* descr_ptr ) -{ - USB_CONFIGURATION_DESCRIPTOR* conf_ptr = ( USB_CONFIGURATION_DESCRIPTOR* )descr_ptr; - uint8_t tmpbyte; - printProgStr(PSTR("\r\n\nConfiguration descriptor:")); - printProgStr(PSTR("\r\nTotal length:\t\t")); - print_hex( conf_ptr->wTotalLength, 16 ); - printProgStr(PSTR("\r\nNumber of interfaces:\t")); - print_hex( conf_ptr->bNumInterfaces, 8 ); - printProgStr(PSTR("\r\nConfiguration value:\t")); - print_hex( conf_ptr->bConfigurationValue, 8 ); - printProgStr(PSTR("\r\nConfiguration string:\t")); - tmpbyte = conf_ptr->iConfiguration; - print_hex( tmpbyte, 8 ); - getstrdescr( DEVADDR, tmpbyte ); - printProgStr(PSTR("\r\nAttributes:\t\t")); - tmpbyte = conf_ptr->bmAttributes; - print_hex( tmpbyte, 8 ); - if( tmpbyte & 0x40 ) { //D6 - printProgStr(PSTR(" Self-powered")); - } - if( tmpbyte & 0x20 ) { //D5 - printProgStr(PSTR(" Remote Wakeup")); - } - printProgStr(PSTR("\r\nMax.power:\t\t")); - tmpbyte = conf_ptr->bMaxPower; - print_hex( tmpbyte, 8 ); - printProgStr(PSTR(" ")); - Serial.print(( tmpbyte * 2 ), DEC); - printProgStr(PSTR("ma")); - return; -} -/* function to print interface descriptor */ -void printintfdescr( char* descr_ptr ) -{ - USB_INTERFACE_DESCRIPTOR* intf_ptr = ( USB_INTERFACE_DESCRIPTOR* )descr_ptr; - uint8_t tmpbyte; - printProgStr(PSTR("\r\nInterface descriptor:")); - printProgStr(PSTR("\r\nInterface number:\t")); - print_hex( intf_ptr->bInterfaceNumber, 8 ); - printProgStr(PSTR("\r\nAlternate setting:\t")); - print_hex( intf_ptr->bAlternateSetting, 8 ); - printProgStr(PSTR("\r\nEndpoints:\t\t")); - print_hex( intf_ptr->bNumEndpoints, 8 ); - printProgStr( class_str ); - tmpbyte = intf_ptr->bInterfaceClass; - print_hex( tmpbyte, 8 ); - printProgStr(classname_parse( tmpbyte )); - printProgStr( subclass_str ); - print_hex( intf_ptr->bInterfaceSubClass, 8 ); - printProgStr( protocol_str ); - print_hex( intf_ptr->bInterfaceProtocol, 8 ); - printProgStr(PSTR("\r\nInterface string:\t")); - tmpbyte = intf_ptr->iInterface; - print_hex( tmpbyte, 8 ); - getstrdescr( DEVADDR, tmpbyte ); - return; -} -/* function to print endpoint descriptor */ -void printepdescr( char* descr_ptr ) -{ - USB_ENDPOINT_DESCRIPTOR* ep_ptr = ( USB_ENDPOINT_DESCRIPTOR* )descr_ptr; - uint8_t tmpbyte; - printProgStr(PSTR("\r\nEndpoint descriptor:")); - printProgStr(PSTR("\r\nEndpoint address:\t")); - tmpbyte = ep_ptr->bEndpointAddress; - print_hex( tmpbyte & 0x0f, 8 ); - printProgStr(PSTR(" Direction: ")); - ( tmpbyte & 0x80 ) ? printProgStr(PSTR("IN")) : printProgStr(PSTR("OUT")); - printProgStr(PSTR("\r\nAttributes:\t\t")); - tmpbyte = ep_ptr->bmAttributes; - print_hex( tmpbyte, 8 ); - printProgStr(PSTR(" Transfer type: ")); - printProgStr((char*)pgm_read_word(&transfer_types[(tmpbyte & 0x03)])); - if(( tmpbyte & 0x03 ) == 1 ) { //Isochronous Transfer - printProgStr(PSTR(", Sync Type: ")); - printProgStr((char*)pgm_read_word(&sync_types[(tmpbyte & 0x0c)])); - printProgStr(PSTR(", Usage Type: ")); - printProgStr((char*)pgm_read_word(&usage_types[(tmpbyte & 0x30)])); - }//if( tmpbyte & 0x01 - printProgStr( maxpktsize_str ); - print_hex( ep_ptr->wMaxPacketSize, 16 ); - printProgStr(PSTR("\r\nPolling interval:\t")); - tmpbyte = ep_ptr->bInterval; - print_hex( tmpbyte, 8 ); - printProgStr(PSTR(" ")); - Serial.print( tmpbyte, DEC ); - printProgStr(PSTR(" ms")); - return; -} -/* function to print HID descriptor */ -void printhid_descr( char* descr_ptr ) -{ - PARSE pf = &HIDreport_parse; - USB_HID_DESCRIPTOR* hid_ptr = ( USB_HID_DESCRIPTOR* )descr_ptr; - uint8_t tmpbyte; - /**/ - printProgStr(PSTR("\r\nHID descriptor:")); - printProgStr(PSTR("\r\nDescriptor length:\t")); - tmpbyte = hid_ptr->bLength; - print_hex( tmpbyte, 8 ); - printProgStr(PSTR(" ")); - Serial.print( tmpbyte, DEC ); - printProgStr(PSTR(" bytes")); - printProgStr(PSTR("\r\nHID version:\t\t")); - Serial.print(( HIBYTE( hid_ptr->bcdHID )), HEX ); - Serial.print("."); - Serial.print(( LOBYTE( hid_ptr->bcdHID )), HEX ); - tmpbyte = hid_ptr->bCountryCode; - printProgStr(PSTR("\r\nCountry Code:\t\t")); - Serial.print( tmpbyte, DEC ); - printProgStr(PSTR(" ")); - ( tmpbyte > 35 ) ? printProgStr(PSTR("Reserved")) : printProgStr((char*)pgm_read_word(&HID_Country_Codes[ tmpbyte ])); - tmpbyte = hid_ptr->bNumDescriptors; - printProgStr(PSTR("\r\nClass Descriptors:\t")); - Serial.print( tmpbyte, DEC ); - //Printing class descriptors - descr_ptr += 6; //advance buffer pointer - for( uint8_t i = 0; i < tmpbyte; i++ ) { - uint8_t tmpdata; - HID_CLASS_DESCRIPTOR* hidclass_ptr = ( HID_CLASS_DESCRIPTOR* )descr_ptr; - tmpdata = hidclass_ptr->bDescriptorType; - printProgStr(PSTR("\r\nClass Descriptor Type:\t")); - Serial.print( tmpdata, HEX ); - if(( tmpdata < 0x21 ) || ( tmpdata > 0x2f )) { - printProgStr(PSTR(" Invalid")); - } - switch( tmpdata ) { - case 0x21: - printProgStr(PSTR(" HID")); - break; - case 0x22: - printProgStr(PSTR(" Report")); - break; - case 0x23: - printProgStr(PSTR(" Physical")); - break; - default: - printProgStr(PSTR(" Reserved")); - break; - }//switch( tmpdata - printProgStr(PSTR("\r\nClass Descriptor Length:")); - Serial.print( hidclass_ptr->wDescriptorLength ); - printProgStr(PSTR(" bytes")); - printProgStr(PSTR("\r\n\nHID report descriptor:\r\n")); - getReportDescr( DEVADDR, 0 , hidclass_ptr->wDescriptorLength, pf, USB_NAK_LIMIT ); - descr_ptr += 3; //advance to the next record - }//for( uint8_t i=... - return; -} -/*function to print unknown descriptor */ -void printunkdescr( char* descr_ptr ) -{ - byte length = *descr_ptr; - byte i; - printProgStr(PSTR("\r\nUnknown descriptor:")); - printProgStr(PSTR("Length:\t\t")); - print_hex( *descr_ptr, 8 ); - printProgStr(PSTR("\r\nType:\t\t")); - print_hex( *(descr_ptr + 1 ), 8 ); - printProgStr(PSTR("\r\nContents:\t")); - descr_ptr += 2; - for( i = 0; i < length; i++ ) { - print_hex( *descr_ptr, 8 ); - descr_ptr++; - } -} -/* Control-IN transfer with callback. Sets address, endpoint, fills control packet with necessary data, dispatches control packet, and initiates bulk IN transfer */ -/* Control, data, and setup stages combined from standard USB library to be able to read large data blocks. Restricted to control-IN transfers with data stage */ -/* data read and MAX3421E RECV FIFO buffer release shall be performed by parse_func callback */ -/* return codes: */ -/* 00 = success */ -/* 01-0f = non-zero HRSLT */ -byte ctrlXfer( byte addr, byte ep, byte bmReqType, byte bRequest, byte wValLo, byte wValHi, unsigned int wInd, uint16_t nbytes, PARSE parse_func, uint16_t nak_limit = USB_NAK_LIMIT ) -{ - byte rcode; - SETUP_PKT sp; - EP_RECORD* ep_rec = Usb.getDevTableEntry( addr, ep ); - byte pktsize; - byte maxpktsize = ep_rec->MaxPktSize; - unsigned int xfrlen = 0; - /**/ - Max.regWr( rPERADDR, addr ); //set peripheral address - /* fill in setup packet */ - sp.ReqType_u.bmRequestType = bmReqType; - sp.bRequest = bRequest; - sp.wVal_u.wValueLo = wValLo; - sp.wVal_u.wValueHi = wValHi; - sp.wIndex = wInd; - sp.wLength = nbytes; - Max.bytesWr( rSUDFIFO, 8, ( char *)&sp ); //transfer to setup packet FIFO - rcode = Usb.dispatchPkt( tokSETUP, ep, nak_limit ); //dispatch packet - //Serial.println("Setup packet"); //DEBUG - if( rcode ) { //return HRSLT if not zero - printProgStr(PSTR("\r\nSetup packet error: ")); - Serial.print( rcode, HEX ); - return( rcode ); - } - /* Data stage */ - //ep_rec->rcvToggle = bmRCVTOG1; - Max.regWr( rHCTL, bmRCVTOG1 ); //set toggle - while( 1 ) { //exited by break - /* request data */ - rcode = Usb.dispatchPkt( tokIN, ep, nak_limit ); - if( rcode ) { - printProgStr(PSTR("\r\nData Stage Error: ")); - Serial.print( rcode, HEX ); - return( rcode ); - } - /* check for RCVDAVIRQ and generate error if not present */ - /* the only case when absense of RCVDAVIRQ makes sense is when toggle error occured. Need to add handling for that */ - if(( Max.regRd( rHIRQ ) & bmRCVDAVIRQ ) == 0 ) { - printProgStr(PSTR("\r\nData Toggle error.")); - return ( 0xf0 ); - } - pktsize = Max.regRd( rRCVBC ); //get received bytes count - parse_func( pktsize ); //call parse function. Parse is expected to read the FIFO completely - Max.regWr( rHIRQ, bmRCVDAVIRQ ); // Clear the IRQ & free the buffer - xfrlen += pktsize; // add this packet's byte count to total transfer length - /* The transfer is complete under two conditions: */ - /* 1. The device sent a short packet (L.T. maxPacketSize) */ - /* 2. 'nbytes' have been transferred. */ - if (( pktsize < maxpktsize ) || (xfrlen >= nbytes )) { // have we transferred 'nbytes' bytes? - break; - } - }//while( 1 ) - rcode = Usb.dispatchPkt( tokOUTHS, ep, nak_limit ); - if( rcode ) { //return error - printProgStr(PSTR("Status packet error: ")); - Serial.print( rcode, HEX ); - } - return( rcode ); -} -/* Parses bitfields in main items */ -void print_mainbitfield( uint8_t byte_toparse ) -{ - ( byte_toparse & 0x01 ) ? printProgStr(PSTR("Constant,")) : printProgStr(PSTR("Data,")); //bit 0 - ( byte_toparse & 0x02 ) ? printProgStr(PSTR("Variable,")) : printProgStr(PSTR("Array,")); //bit 1 - ( byte_toparse & 0x04 ) ? printProgStr(PSTR("Relative,")) : printProgStr(PSTR("Absolute,")); //... - ( byte_toparse & 0x08 ) ? printProgStr(PSTR("Wrap,")) : printProgStr(PSTR("No Wrap,")); - ( byte_toparse & 0x10 ) ? printProgStr(PSTR("Non Linear,")) : printProgStr(PSTR("Linear,")); - ( byte_toparse & 0x20 ) ? printProgStr(PSTR("No preferred,")) : printProgStr(PSTR("Preferred State,")); - ( byte_toparse & 0x40 ) ? printProgStr(PSTR("Null State,")) : printProgStr(PSTR("No Null Position,")); //bit 6 - ( byte_toparse & 0x40 ) ? printProgStr(PSTR("Volatile( ignore for Input),")) : printProgStr(PSTR("Non-volatile(Ignore for Input),")); //bit 7 -} -/* HID Report Desriptor Parser Callback */ -/* called repeatedly from Control transfer function */ -void HIDreport_parse( uint8_t pkt_size ) -{ -#define B_SIZE 0x03 //bSize bitmask -#define B_TYPE 0x0c //bType bitmask -#define B_TAG 0xf0 //bTag bitmask - /* parser states */ - enum STATE { ITEM_START, DATA_PARSE }; - static STATE state = ITEM_START; - static uint8_t databytes_left = 0; - static uint8_t prefix; //item prefix - type and tag - uint8_t byte_toparse; - uint8_t bType; - uint8_t tmpbyte; - /**/ - while( 1 ) { - if( pkt_size ) { - byte_toparse = Max.regRd( rRCVFIFO ); //read a byte from FIFO - pkt_size--; - } - else { - return; //all bytes read - } - switch( state ) { - case ITEM_START: //start of the record - prefix = byte_toparse >>2; //store prefix for databyte parsing - tmpbyte = byte_toparse & B_SIZE; - /* get item length */ - ( tmpbyte == 0x03 ) ? databytes_left = 4 : databytes_left = tmpbyte; - if( databytes_left ) { - state = DATA_PARSE; //read bytes after prefix - } - printProgStr(PSTR("\r\nLength: ")); - Serial.print( databytes_left, DEC ); - /* get item type */ - bType = ( byte_toparse & B_TYPE ) >>2; - printProgStr(PSTR(" Type: ")); - printProgStr((char*)pgm_read_word(&btypes[ bType ])); - /* get item tag */ - printProgStr(PSTR("\t\tTag: ")); - tmpbyte = ( byte_toparse & B_TAG ) >>4 ; - switch( bType ) { - case 0: //Main - if( tmpbyte < 0x08 ) { - printProgStr(PSTR("Invalid Tag")); - } - else if( tmpbyte > 0x0c ) { - printProgStr( reserved_msg ); - } - else { - printProgStr((char*)pgm_read_word(&maintags[ tmpbyte - 8 /* & 0x03 */])); - //Serial.print("Byte: "); - //Serial.println( tmpbyte, HEX ); - } - break;//case 0 Main - case 1: //Global - ( tmpbyte > 0x0b ) ? printProgStr( reserved_msg ) : printProgStr((char*)pgm_read_word(&globaltags[ tmpbyte ])); - break;//case 1 Global - case 2: //Local - ( tmpbyte > 0x0a ) ? printProgStr( reserved_msg ) : printProgStr((char*)pgm_read_word(&localtags[ tmpbyte ])); - break;//case 2 Local - default: - break; - }//switch( bType... - break;//case ITEM_START - case DATA_PARSE: - switch( prefix ) { - case 0x20: //Main Input - case 0x24: //Main Output - case 0x2c: //Main Feature - /* todo: add parsing 8th bit */ - print_mainbitfield( byte_toparse ); - break; - case 0x28: //Main Collection - if(( byte_toparse > 0x06 ) && ( byte_toparse < 0x80 )) { - printProgStr( reserved_msg ); - } - else if(( byte_toparse > 0x7f ) && ( byte_toparse <= 0xff )) { - printProgStr(PSTR("Vendor-defined")); - } - else { - printProgStr((char*)pgm_read_word(&collections[ byte_toparse ])); - } - break;//case 0x28 Main Collection - //case 0x30: //Main End Collection - case 0x01: //Global Usage Page - switch( byte_toparse ) { //see HID Usage Tables doc v.1.12 page 14 - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x08: - case 0x09: - case 0x0a: - case 0x0b: - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: - case 0x10: - printProgStr((char*)pgm_read_word(&usage_pages[ byte_toparse ])); - break; - case 0x14: - printProgStr(PSTR("Alphanumeric Display")); - break; - case 0x40: - printProgStr(PSTR("Medical Instruments")); - break; - case 0x80: - case 0x81: - case 0x82: - case 0x83: - printProgStr(PSTR("Monitor page")); - break; - case 0x84: - case 0x85: - case 0x86: - case 0x87: - printProgStr(PSTR("Power page")); - break; - case 0x8c: - printProgStr(PSTR("Bar Code Scanner page")); - break; - case 0x8d: - printProgStr(PSTR("Scale page")); - break; - case 0x8e: - printProgStr(PSTR("Magnetic Stripe Reading (MSR) Devices")); - break; - case 0x8f: - printProgStr(PSTR("Reserved Point of Sale pages")); - break; - case 0x90: - printProgStr(PSTR("Camera Control Page")); - break; - case 0x91: - printProgStr(PSTR("Arcade Page")); - break; - default: -// printProgStr(PSTR("Data: ")); -// print_hex( byte_toparse, 8 ); - //databytes_left--; - break; - }//switch case 0x01: //Global Usage Page - }//switch( prefix ... - printProgStr(PSTR(" Data: ")); - print_hex( byte_toparse, 8 ); - databytes_left--; - if( !databytes_left ) { - state = ITEM_START; - } - break; - }//switch( state... - }//while( 1 ... -} -/* prints hex numbers with leading zeroes */ -// copyright, Peter H Anderson, Baltimore, MD, Nov, '07 -// source: http://www.phanderson.com/arduino/arduino_display.html -void print_hex(int v, int num_places) -{ - int mask=0, n, num_nibbles, digit; - - for (n=1; n<=num_places; n++) { - mask = (mask << 1) | 0x0001; - } - v = v & mask; // truncate v to specified number of places - - num_nibbles = num_places / 4; - if ((num_places % 4) != 0) { - ++num_nibbles; - } - do { - digit = ((v >> (num_nibbles-1) * 4)) & 0x0f; - Serial.print(digit, HEX); - } - while(--num_nibbles); -} - -/* given a PROGMEM string, use Serial.print() to send it out */ -/* Some non-intuitive casting necessary: */ -/* printProgStr(PSTR("Func.Mode:\t0x")); */ -/* printProgStr((char*)pgm_read_word(&mtpopNames[(op & 0xFF)])); */ -void printProgStr(const char* str) -{ - if(!str) { - return; - } - char c; - while((c = pgm_read_byte(str++))) { - Serial.print(c,BYTE); - } - return; -} diff --git a/hardware/arduino/sam/system/USBHost/hid.h b/hardware/arduino/sam/system/USBHost/hid.h new file mode 100644 index 000000000..e95b120d8 --- /dev/null +++ b/hardware/arduino/sam/system/USBHost/hid.h @@ -0,0 +1,188 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com +*/ + +#ifndef HID_H_INCLUDED +#define HID_H_INCLUDED + +#include +#include "usb_ch9.h" +#include "Usb.h" +#include "Arduino.h" +#include "confdescparser.h" +#include "hidusagestr.h" + +#define DATA_SIZE_MASK 0x03 +#define TYPE_MASK 0x0C +#define TAG_MASK 0xF0 + +#define DATA_SIZE_0 0x00 +#define DATA_SIZE_1 0x01 +#define DATA_SIZE_2 0x02 +#define DATA_SIZE_4 0x03 + +#define TYPE_MAIN 0x00 +#define TYPE_GLOBAL 0x04 +#define TYPE_LOCAL 0x08 + +#define TAG_MAIN_INPUT 0x80 +#define TAG_MAIN_OUTPUT 0x90 +#define TAG_MAIN_COLLECTION 0xA0 +#define TAG_MAIN_FEATURE 0xB0 +#define TAG_MAIN_ENDCOLLECTION 0xC0 + +#define TAG_GLOBAL_USAGEPAGE 0x00 +#define TAG_GLOBAL_LOGICALMIN 0x10 +#define TAG_GLOBAL_LOGICALMAX 0x20 +#define TAG_GLOBAL_PHYSMIN 0x30 +#define TAG_GLOBAL_PHYSMAX 0x40 +#define TAG_GLOBAL_UNITEXP 0x50 +#define TAG_GLOBAL_UNIT 0x60 +#define TAG_GLOBAL_REPORTSIZE 0x70 +#define TAG_GLOBAL_REPORTID 0x80 +#define TAG_GLOBAL_REPORTCOUNT 0x90 +#define TAG_GLOBAL_PUSH 0xA0 +#define TAG_GLOBAL_POP 0xB0 + +#define TAG_LOCAL_USAGE 0x00 +#define TAG_LOCAL_USAGEMIN 0x10 +#define TAG_LOCAL_USAGEMAX 0x20 + +/* HID requests */ +#define bmREQ_HIDOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE +#define bmREQ_HIDIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE +#define bmREQ_HIDREPORT USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_INTERFACE + +/* HID constants. Not part of chapter 9 */ +/* Class-Specific Requests */ +#define HID_REQUEST_GET_REPORT 0x01 +#define HID_REQUEST_GET_IDLE 0x02 +#define HID_REQUEST_GET_PROTOCOL 0x03 +#define HID_REQUEST_SET_REPORT 0x09 +#define HID_REQUEST_SET_IDLE 0x0A +#define HID_REQUEST_SET_PROTOCOL 0x0B + +/* Class Descriptor Types */ +#define HID_DESCRIPTOR_HID 0x21 +#define HID_DESCRIPTOR_REPORT 0x22 +#define HID_DESRIPTOR_PHY 0x23 + +/* Protocol Selection */ +#define HID_BOOT_PROTOCOL 0x00 +#define HID_RPT_PROTOCOL 0x01 + +/* HID Interface Class Code */ +#define HID_INTF 0x03 + +/* HID Interface Class SubClass Codes */ +#define HID_BOOT_INTF_SUBCLASS 0x01 + +/* HID Interface Class Protocol Codes */ +#define HID_PROTOCOL_NONE 0x00 +#define HID_PROTOCOL_KEYBOARD 0x01 +#define HID_PROTOCOL_MOUSE 0x02 + +struct HidItemPrefix +{ + uint8_t bSize : 2; + uint8_t bType : 2; + uint8_t bTag : 4; +}; + +#define HID_ITEM_TYPE_MAIN 0 +#define HID_ITEM_TYPE_GLOBAL 1 +#define HID_ITEM_TYPE_LOCAL 2 +#define HID_ITEM_TYPE_RESERVED 3 + +#define HID_LONG_ITEM_PREFIX 0xfe // Long item prefix value + +#define bmHID_MAIN_ITEM_TAG 0xfc // Main item tag mask + +#define bmHID_MAIN_ITEM_INPUT 0x80 // Main item Input tag value +#define bmHID_MAIN_ITEM_OUTPUT 0x90 // Main item Output tag value +#define bmHID_MAIN_ITEM_FEATURE 0xb0 // Main item Feature tag value +#define bmHID_MAIN_ITEM_COLLECTION 0xa0 // Main item Collection tag value +#define bmHID_MAIN_ITEM_END_COLLECTION 0xce // Main item End Collection tag value + +#define HID_MAIN_ITEM_COLLECTION_PHYSICAL 0 +#define HID_MAIN_ITEM_COLLECTION_APPLICATION 1 +#define HID_MAIN_ITEM_COLLECTION_LOGICAL 2 +#define HID_MAIN_ITEM_COLLECTION_REPORT 3 +#define HID_MAIN_ITEM_COLLECTION_NAMED_ARRAY 4 +#define HID_MAIN_ITEM_COLLECTION_USAGE_SWITCH 5 +#define HID_MAIN_ITEM_COLLECTION_USAGE_MODIFIER 6 + +struct MainItemIOFeature +{ + uint8_t bmIsConstantOrData : 1; + uint8_t bmIsArrayOrVariable : 1; + uint8_t bmIsRelativeOrAbsolute : 1; + uint8_t bmIsWrapOrNoWrap : 1; + uint8_t bmIsNonLonearOrLinear : 1; + uint8_t bmIsNoPreferedOrPrefered : 1; + uint8_t bmIsNullOrNoNull : 1; + uint8_t bmIsVolatileOrNonVolatile : 1; +}; + +class HID; + +class HIDReportParser +{ +public: + virtual void Parse(HID *hid, bool is_rpt_id, uint32_t len, uint8_t *buf) = 0; +}; + +#define MAX_REPORT_PARSERS 2 +#define HID_MAX_HID_CLASS_DESCRIPTORS 5 + +class HID : public USBDeviceConfig, public UsbConfigXtracter +{ +protected: + USBHost *pUsb; // USB class instance pointer + uint32_t bAddress; // address + +protected: + static const uint32_t epInterruptInIndex = 1; // InterruptIN endpoint index + static const uint32_t epInterruptOutIndex = 2; // InterruptOUT endpoint index + + static const uint32_t maxHidInterfaces = 3; + static const uint32_t maxEpPerInterface = 2; + static const uint32_t totalEndpoints = (maxHidInterfaces * maxEpPerInterface + 1); + + void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); + void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc); + + virtual HIDReportParser* GetReportParser(uint32_t id) { return 0; }; + +public: + HID(USBHost *pusb) : pUsb(pusb) {}; + + const USBHost* GetUsb() { return pUsb; }; + virtual bool SetReportParser(uint32_t id, HIDReportParser *prs) { return false; }; + + uint32_t SetProtocol(uint32_t iface, uint32_t protocol); + uint32_t GetProtocol(uint32_t iface, uint8_t* dataptr); + uint32_t GetIdle(uint32_t iface, uint32_t reportID, uint8_t* dataptr); + uint32_t SetIdle(uint32_t iface, uint32_t reportID, uint32_t duration); + + uint32_t GetReportDescr(uint32_t ep, USBReadParser *parser = NULL); + + uint32_t GetHidDescr(uint32_t ep, uint32_t nbytes, uint8_t* dataptr); + uint32_t GetReport(uint32_t ep, uint32_t iface, uint32_t report_type, uint32_t report_id, uint32_t nbytes, uint8_t* dataptr); + uint32_t SetReport(uint32_t ep, uint32_t iface, uint32_t report_type, uint32_t report_id, uint32_t nbytes, uint8_t* dataptr); +}; + +#endif /* HID_H_INCLUDED */ diff --git a/hardware/arduino/sam/system/USBHost/hid2.cpp b/hardware/arduino/sam/system/USBHost/hid2.cpp new file mode 100644 index 000000000..cc3b46ebe --- /dev/null +++ b/hardware/arduino/sam/system/USBHost/hid2.cpp @@ -0,0 +1,101 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com +*/ + +#include "hid.h" + +// Get HID report descriptor +uint32_t HID::GetReportDescr(uint32_t ep, USBReadParser *parser) +{ + const uint32_t constBufLen = 64; + uint8_t buf[constBufLen]; + + return (pUsb->ctrlReq(bAddress, ep, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, + HID_DESCRIPTOR_REPORT, 0x0000, 128, constBufLen, buf, (USBReadParser*)parser)); +} + + +uint32_t HID::SetReport(uint32_t ep, uint32_t iface, uint32_t report_type, uint32_t report_id, uint32_t nbytes, uint8_t* dataptr) +{ + return (pUsb->ctrlReq(bAddress, ep, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, report_id, report_type, iface, nbytes, nbytes, dataptr, NULL)); +} + +uint32_t HID::GetReport(uint32_t ep, uint32_t iface, uint32_t report_type, uint32_t report_id, uint32_t nbytes, uint8_t* dataptr) +{ + return (pUsb->ctrlReq(bAddress, ep, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, report_id, report_type, iface, nbytes, nbytes, dataptr, NULL)); +} + +uint32_t HID::GetIdle(uint32_t iface, uint32_t reportID, uint8_t* dataptr) +{ + return (pUsb->ctrlReq(bAddress, 0, bmREQ_HIDIN, HID_REQUEST_GET_IDLE, reportID, 0, iface, 0x0001, 0x0001, dataptr, NULL)); +} + +uint32_t HID::SetIdle(uint32_t iface, uint32_t reportID, uint32_t duration) +{ + return (pUsb->ctrlReq(bAddress, 0, bmREQ_HIDOUT, HID_REQUEST_SET_IDLE, reportID, duration, iface, 0x0000, 0x0000, NULL, NULL)); +} + +uint32_t HID::SetProtocol(uint32_t iface, uint32_t protocol) +{ + return (pUsb->ctrlReq(bAddress, 0, bmREQ_HIDOUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, iface, 0x0000, 0x0000, NULL, NULL)); +} + +uint32_t HID::GetProtocol(uint32_t iface, uint8_t* dataptr) +{ + return (pUsb->ctrlReq(bAddress, 0, bmREQ_HIDIN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, iface, 0x0001, 0x0001, dataptr, NULL)); +} + +void HID::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) +{ + /*Notify(PSTR("Endpoint descriptor:")); + Notify(PSTR("\r\nLength:\t\t")); + PrintHex(ep_ptr->bLength); + Notify(PSTR("\r\nType:\t\t")); + PrintHex(ep_ptr->bDescriptorType); + Notify(PSTR("\r\nAddress:\t")); + PrintHex(ep_ptr->bEndpointAddress); + Notify(PSTR("\r\nAttributes:\t")); + PrintHex(ep_ptr->bmAttributes); + Notify(PSTR("\r\nMaxPktSize:\t")); + PrintHex(ep_ptr->wMaxPacketSize); + Notify(PSTR("\r\nPoll Intrv:\t")); + PrintHex(ep_ptr->bInterval);*/ +} + +void HID::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) +{ + /* Notify(PSTR("\r\n\r\nHID Descriptor:\r\n")); + Notify(PSTR("bDescLength:\t\t")); + PrintHex(pDesc->bLength); + + Notify(PSTR("\r\nbDescriptorType:\t")); + PrintHex(pDesc->bDescriptorType); + + Notify(PSTR("\r\nbcdHID:\t\t\t")); + PrintHex(pDesc->bcdHID); + + Notify(PSTR("\r\nbCountryCode:\t\t")); + PrintHex(pDesc->bCountryCode); + + Notify(PSTR("\r\nbNumDescriptors:\t")); + PrintHex(pDesc->bNumDescriptors); + + Notify(PSTR("\r\nbDescrType:\t\t")); + PrintHex(pDesc->bDescrType); + + Notify(PSTR("\r\nwDescriptorLength:\t")); + PrintHex(pDesc->wDescriptorLength);*/ +} diff --git a/hardware/arduino/sam/system/USBHost/hidboot.cpp b/hardware/arduino/sam/system/USBHost/hidboot.cpp new file mode 100644 index 000000000..fa96e5d0d --- /dev/null +++ b/hardware/arduino/sam/system/USBHost/hidboot.cpp @@ -0,0 +1,158 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com +*/ + +#include "hidboot.h" + +void MouseReportParser::Parse(HID *hid, bool is_rpt_id, uint32_t len, uint8_t *buf) +{ + MOUSEINFO *pmi = (MOUSEINFO*)buf; + + if (prevState.mouseInfo.bmLeftButton == 0 && pmi->bmLeftButton == 1) + OnLeftButtonDown(pmi); + + if (prevState.mouseInfo.bmLeftButton == 1 && pmi->bmLeftButton == 0) + OnLeftButtonUp(pmi); + + if (prevState.mouseInfo.bmRightButton == 0 && pmi->bmRightButton == 1) + OnRightButtonDown(pmi); + + if (prevState.mouseInfo.bmRightButton == 1 && pmi->bmRightButton == 0) + OnRightButtonUp(pmi); + + if (prevState.mouseInfo.bmMiddleButton == 0 && pmi->bmMiddleButton == 1) + OnMiddleButtonDown(pmi); + + if (prevState.mouseInfo.bmMiddleButton == 1 && pmi->bmMiddleButton == 0) + OnMiddleButtonUp(pmi); + + if (prevState.mouseInfo.dX != pmi->dX || prevState.mouseInfo.dY != pmi->dY) + OnMouseMove(pmi); + + for (uint32_t i = 0; i < 3; ++i) + prevState.bInfo[i] = buf[i]; +}; + +void KeyboardReportParser::Parse(HID *hid, bool is_rpt_id, uint32_t len, uint8_t *buf) +{ + // On error - return + if (buf[2] == 1) + return; + + //KBDINFO *pki = (KBDINFO*)buf; + + for (uint32_t i = 2; i < 8; ++i) + { + bool down = false; + bool up = false; + + for (uint8_t j=2; j<8; j++) + { + if (buf[i] == prevState.bInfo[j] && buf[i] != 1) + down = true; + if (buf[j] == prevState.bInfo[i] && prevState.bInfo[i] != 1) + up = true; + } + + if (!down) + { + HandleLockingKeys(hid, buf[i]); + OnKeyDown(*buf, buf[i]); + } + + if (!up) + OnKeyUp(prevState.bInfo[0], prevState.bInfo[i]); + } + + for (uint32_t i = 0; i < 8; ++i) + prevState.bInfo[i] = buf[i]; +}; + +uint8_t KeyboardReportParser::HandleLockingKeys(HID *hid, uint8_t key) +{ + uint8_t old_keys = kbdLockingKeys.bLeds; + + switch (key) + { + case KEY_NUM_LOCK: + kbdLockingKeys.kbdLeds.bmNumLock = ~kbdLockingKeys.kbdLeds.bmNumLock; + break; + case KEY_CAPS_LOCK: + kbdLockingKeys.kbdLeds.bmCapsLock = ~kbdLockingKeys.kbdLeds.bmCapsLock; + break; + case KEY_SCROLL_LOCK: + kbdLockingKeys.kbdLeds.bmScrollLock = ~kbdLockingKeys.kbdLeds.bmScrollLock; + break; + } + + if (old_keys != kbdLockingKeys.bLeds && hid) + return (hid->SetReport(0, 0/*hid->GetIface()*/, 2, 0, 1, &kbdLockingKeys.bLeds)); + + return 0; +} + +const uint8_t KeyboardReportParser::numKeys[] = { '!', '@', '#', '$', '%', '^', '&', '*', '(', ')' }; +const uint8_t KeyboardReportParser::symKeysUp[] = { '_', '+', '{', '}', '|', '~', ':', '"', '~', '<', '>', '?' }; +const uint8_t KeyboardReportParser::symKeysLo[] = { '-', '=', '[', ']', '\\', ' ', ';', '\'', '`', ',', '.', '/' }; +const uint8_t KeyboardReportParser::padKeys[] = { '/', '*', '-', '+', 0x13 }; + +uint8_t KeyboardReportParser::OemToAscii(uint8_t mod, uint8_t key) +{ + uint8_t shift = (mod & 0x22); + + // [a-z] + if (key > 0x03 && key < 0x1e) + { + // Upper case letters + if ( (kbdLockingKeys.kbdLeds.bmCapsLock == 0 && (mod & 2)) || + (kbdLockingKeys.kbdLeds.bmCapsLock == 1 && (mod & 2) == 0) ) + return (key - 4 + 'A'); + + // Lower case letters + else + return (key - 4 + 'a'); + } + // Numbers + else if (key > 0x1d && key < 0x27) + { + if (shift) + return (numKeys[key - 0x1e]); + else + return (key - 0x1e + '1'); + } + // Keypad Numbers + else if (key > 0x58 && key < 0x62) + { + if (kbdLockingKeys.kbdLeds.bmNumLock == 1) + return (key - 0x59 + '1'); + } + else if (key > 0x2c && key < 0x39) + return ((shift) ? symKeysUp[key-0x2d] : symKeysLo[key-0x2d]); + else if (key > 0x53 && key < 0x59) + return padKeys[key - 0x54]; + else + { + switch (key) + { + case KEY_SPACE: return (0x20); + case KEY_ENTER: return (0x13); + case KEY_ZERO: return ((shift) ? ')' : '0'); + case KEY_ZERO2: return ((kbdLockingKeys.kbdLeds.bmNumLock == 1) ? '0' : 0); + case KEY_PERIOD: return ((kbdLockingKeys.kbdLeds.bmNumLock == 1) ? '.' : 0); + } + } + return 0; +} diff --git a/hardware/arduino/sam/system/USBHost/hidboot.h b/hardware/arduino/sam/system/USBHost/hidboot.h new file mode 100644 index 000000000..a669771e4 --- /dev/null +++ b/hardware/arduino/sam/system/USBHost/hidboot.h @@ -0,0 +1,478 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com +*/ + +#ifndef HIDBOOT_H_INCLUDED +#define HIDBOOT_H_INCLUDED + +#include +#include "usb_ch9.h" +#include "Usb.h" +#include "hid.h" +#include "Arduino.h" +#include "confdescparser.h" + +#define KEY_SPACE 0x2c +#define KEY_ZERO 0x27 +#define KEY_ZERO2 0x62 +#define KEY_ENTER 0x28 +#define KEY_PERIOD 0x63 + +struct MOUSEINFO +{ + struct + { + uint8_t bmLeftButton : 1; + uint8_t bmRightButton : 1; + uint8_t bmMiddleButton : 1; + uint8_t bmDummy : 1; + }; + int8_t dX; + int8_t dY; +}; + +class MouseReportParser : public HIDReportParser +{ + union + { + MOUSEINFO mouseInfo; + uint8_t bInfo[3]; + } prevState; + +public: + virtual void Parse(HID *hid, bool is_rpt_id, uint32_t len, uint8_t *buf); + +protected: + virtual void OnMouseMove (MOUSEINFO *mi) {}; + virtual void OnLeftButtonUp (MOUSEINFO *mi) {}; + virtual void OnLeftButtonDown (MOUSEINFO *mi) {}; + virtual void OnRightButtonUp (MOUSEINFO *mi) {}; + virtual void OnRightButtonDown (MOUSEINFO *mi) {}; + virtual void OnMiddleButtonUp (MOUSEINFO *mi) {}; + virtual void OnMiddleButtonDown (MOUSEINFO *mi) {}; +}; + +struct MODIFIERKEYS +{ + uint8_t bmLeftCtrl : 1; + uint8_t bmLeftShift : 1; + uint8_t bmLeftAlt : 1; + uint8_t bmLeftGUI : 1; + uint8_t bmRightCtrl : 1; + uint8_t bmRightShift : 1; + uint8_t bmRightAlt : 1; + uint8_t bmRightGUI : 1; +}; + +struct KBDINFO +{ + struct + { + uint8_t bmLeftCtrl : 1; + uint8_t bmLeftShift : 1; + uint8_t bmLeftAlt : 1; + uint8_t bmLeftGUI : 1; + uint8_t bmRightCtrl : 1; + uint8_t bmRightShift : 1; + uint8_t bmRightAlt : 1; + uint8_t bmRightGUI : 1; + }; + uint8_t bReserved; + uint8_t Keys[6]; +}; + +struct KBDLEDS +{ + uint8_t bmNumLock : 1; + uint8_t bmCapsLock : 1; + uint8_t bmScrollLock : 1; + uint8_t bmCompose : 1; + uint8_t bmKana : 1; + uint8_t bmReserved : 3; +}; + +#define KEY_NUM_LOCK 0x53 +#define KEY_CAPS_LOCK 0x39 +#define KEY_SCROLL_LOCK 0x47 + +class KeyboardReportParser : public HIDReportParser +{ + static const uint8_t numKeys[]; + static const uint8_t symKeysUp[]; + static const uint8_t symKeysLo[]; + static const uint8_t padKeys[]; + +protected: + union + { + KBDINFO kbdInfo; + uint8_t bInfo[sizeof(KBDINFO)]; + } prevState; + + union + { + KBDLEDS kbdLeds; + uint8_t bLeds; + } kbdLockingKeys; + + uint8_t OemToAscii(uint8_t mod, uint8_t key); + +public: + KeyboardReportParser() { kbdLockingKeys.bLeds = 0; }; + + virtual void Parse(HID *hid, bool is_rpt_id, uint32_t len, uint8_t *buf); + +protected: + uint8_t HandleLockingKeys(HID* hid, uint8_t key); + + virtual void OnKeyDown (uint8_t mod, uint8_t key) {}; + virtual void OnKeyUp (uint8_t mod, uint8_t key) {}; +}; + +#define totalEndpoints 2 + +#define HID_MAX_HID_CLASS_DESCRIPTORS 5 + +template +class HIDBoot : public HID +{ + EpInfo epInfo[totalEndpoints]; + + HIDReportParser *pRptParser; + + uint32_t bConfNum; // configuration number + uint32_t bIfaceNum; // Interface Number + uint32_t bNumIface; // number of interfaces in the configuration + uint32_t bNumEP; // total number of EP in the configuration + uint32_t qNextPollTime; // next poll time + bool bPollEnable; // poll enable flag + + void Initialize(); + + virtual HIDReportParser* GetReportParser(uint32_t id) { return pRptParser; }; + +public: + HIDBoot(USBHost *p); + + virtual bool SetReportParser(uint32_t id, HIDReportParser *prs) { pRptParser = prs; return true;}; /////////////////////// le return ne sert a rien ?!!! + + // USBDeviceConfig implementation + virtual uint32_t Init(uint32_t parent, uint32_t port, uint32_t lowspeed); + virtual uint32_t Release(); + virtual uint32_t Poll(); + virtual uint32_t GetAddress() { return bAddress; }; + + // UsbConfigXtracter implementation + virtual void EndpointXtract(uint32_t conf, uint32_t iface, uint32_t alt, uint32_t proto, const USB_ENDPOINT_DESCRIPTOR *ep); +}; + +template +HIDBoot::HIDBoot(USBHost *p) : + HID(p), + pRptParser(NULL), + qNextPollTime(0), + bPollEnable(false) +{ + Initialize(); + + if (pUsb) + pUsb->RegisterDeviceClass(this); +} + +template +void HIDBoot::Initialize() +{ + for(uint32_t i = 0; i < totalEndpoints; ++i) + { + epInfo[i].epAddr = 0; + epInfo[i].maxPktSize = (i) ? 0 : 8; + epInfo[i].epAttribs = 0; + epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; + } + bNumEP = 1; + bNumIface = 0; + bConfNum = 0; +} + +template +uint32_t HIDBoot::Init(uint32_t parent, uint32_t port, uint32_t lowspeed) +{ + const uint32_t constBufSize = sizeof(USB_DEVICE_DESCRIPTOR); + + uint8_t buf[constBufSize]; + uint32_t rcode = 0; + UsbDevice *p = NULL; + EpInfo *oldep_ptr = NULL; + uint32_t len = 0; + + uint32_t num_of_conf; // number of configurations + + AddressPool &addrPool = pUsb->GetAddressPool(); + + if (bAddress) + return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; + + // Get pointer to pseudo device with address 0 assigned + p = addrPool.GetUsbDevicePtr(0); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + if (!p->epinfo) + { + TRACE_USBHOST(printf("HIDBoot::Init : epinfo is null!\r\n");) + return USB_ERROR_EPINFO_IS_NULL; + } + + // Save old pointer to EP_RECORD of address 0 + oldep_ptr = p->epinfo; + + // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence + p->epinfo = epInfo; + + p->lowspeed = lowspeed; + + // Get device descriptor + rcode = pUsb->getDevDescr( 0, 0, 8, (uint8_t*)buf ); + + if (!rcode) + len = (buf[0] > constBufSize) ? constBufSize : buf[0]; + + if (rcode) + { + // Restore p->epinfo + p->epinfo = oldep_ptr; + + goto FailGetDevDescr; + } + + // Restore p->epinfo + p->epinfo = oldep_ptr; + + // Allocate new address according to device class + bAddress = addrPool.AllocAddress(parent, false, port); + + if (!bAddress) + return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; + + // Extract Max Packet Size from the device descriptor + epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; + + // Assign new address to the device + rcode = pUsb->setAddr(0, 0, bAddress); + + if (rcode) + { + p->lowspeed = false; + addrPool.FreeAddress(bAddress); + bAddress = 0; + TRACE_USBHOST(printf("HIDBoot::Init : setAddr failed with rcode %lu\r\n", rcode);) + return rcode; + } + + TRACE_USBHOST(printf("HIDBoot::Init : device address is now %lu\r\n", bAddress);) + + p->lowspeed = false; + + p = addrPool.GetUsbDevicePtr(bAddress); + + if (!p) + return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; + + p->lowspeed = lowspeed; + + if (len) + rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf); + + if(rcode) + goto FailGetDevDescr; + + num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations; + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); + + if (rcode) + goto FailSetDevTblEntry; + + TRACE_USBHOST(printf("HIDBoot::Init : number of configuration is %lu\r\n", num_of_conf);) + + for (uint32_t i = 0; i < num_of_conf; ++i) + { + //HexDumper HexDump; + ConfigDescParser< + USB_CLASS_HID, + HID_BOOT_INTF_SUBCLASS, + BOOT_PROTOCOL, + CP_MASK_COMPARE_ALL> confDescrParser(this); + + //rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump); + rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); + + if (bNumEP > 1) + break; + } + + if (bNumEP < 2) + return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; + + TRACE_USBHOST(printf("HIDBoot::Init : bAddress: %lu\r\n", bAddress);) + TRACE_USBHOST(printf("HIDBoot::Init : bNumEP: %lu\r\n", bNumEP);) + + // Assign epInfo to epinfo pointer + rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo); + + TRACE_USBHOST(printf("HIDBoot::Init : bConfNum: %lu\r\n", bConfNum);) + + // Set Configuration Value + rcode = pUsb->setConf(bAddress, 0, bConfNum); + + if (rcode) + goto FailSetConfDescr; + + TRACE_USBHOST(printf("HIDBoot::Init : bIfaceNum: %lu\r\n", bIfaceNum);) + + rcode = SetProtocol(bIfaceNum, HID_BOOT_PROTOCOL); + + if (rcode) + goto FailSetProtocol; + + if (BOOT_PROTOCOL == 1) + { + rcode = SetIdle(bIfaceNum, 0, 0); + + if (rcode) + goto FailSetIdle; + } + + TRACE_USBHOST(printf("HIDBoot::Init : HID device configured successfully\r\n");) + + bPollEnable = true; + return 0; + +FailGetDevDescr: + //USBTRACE("getDevDescr:"); + goto Fail; + +FailSetDevTblEntry: + //USBTRACE("setDevTblEn:"); + goto Fail; + +FailSetProtocol: + //USBTRACE("SetProto:"); + goto Fail; + +FailSetIdle: + //USBTRACE("SetIdle:"); + goto Fail; + +FailSetConfDescr: + //USBTRACE("setConf:"); + goto Fail; + +Fail: + //Serial.println(rcode, HEX); + Release(); + return rcode; +} + +template +void HIDBoot::EndpointXtract(uint32_t conf, uint32_t iface, uint32_t alt, uint32_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) +{ + // If the first configuration satisfies, the others are not considered. + if (bNumEP > 1 && conf != bConfNum) + return; + + //ErrorMessage(PSTR("\r\nConf.Val"), conf); + //ErrorMessage(PSTR("Iface Num"), iface); + //ErrorMessage(PSTR("Alt.Set"), alt); + + bConfNum = conf; + bIfaceNum = iface; + + uint32_t index; + + if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) + { + index = epInterruptInIndex; + + // Fill in the endpoint info structure + epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); + epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize; + epInfo[index].epAttribs = 0; + + bNumEP++; + + TRACE_USBHOST(printf("HIDBoot::EndpointXtract : Found new endpoint\r\n");) + TRACE_USBHOST(printf("HIDBoot::EndpointXtract : epAddr: %lu\r\n", epInfo[index].epAddr);) + TRACE_USBHOST(printf("HIDBoot::EndpointXtract : maxPktSize: %lu\r\n", epInfo[index].maxPktSize);) + TRACE_USBHOST(printf("HIDBoot::EndpointXtract : index: %lu\r\n", index);) + + UHD_EP_Alloc(epInfo[index].epAddr, bAddress, 10, UOTGHS_HSTPIPCFG_PTYPE_INTRPT, UOTGHS_HSTPIPCFG_PTOKEN_IN, epInfo[index].maxPktSize, UOTGHS_HSTPIPCFG_PBK_1_BANK); + + //PrintEndpointDescriptor(pep); + } +} + + +template +uint32_t HIDBoot::Release() +{ + pUsb->GetAddressPool().FreeAddress(bAddress); + + bConfNum = 0; + bIfaceNum = 0; + bNumEP = 1; + bAddress = 0; + qNextPollTime = 0; + bPollEnable = false; + return 0; +} + +template +uint32_t HIDBoot::Poll() +{ + uint32_t rcode = 0; + + if (!bPollEnable) + return 0; + + if (qNextPollTime <= millis()) + { + qNextPollTime = millis() + 10; + + const uint32_t const_buff_len = 16; + uint8_t buf[const_buff_len]; + + uint32_t read = epInfo[epInterruptInIndex].maxPktSize; + + rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex].epAddr, &read, buf); + + if (rcode) + { + //if (rcode != hrNAK) + //USBTRACE2("Poll:", rcode); + return rcode; + } + + if (pRptParser) + pRptParser->Parse((HID*)this, 0, (uint32_t)read, buf); + } + + return rcode; +} + +#endif /* HIDBOOT_H_INCLUDED */ diff --git a/hardware/arduino/sam/system/USBHost/hidusagestr.h b/hardware/arduino/sam/system/USBHost/hidusagestr.h new file mode 100644 index 000000000..dd5175b9d --- /dev/null +++ b/hardware/arduino/sam/system/USBHost/hidusagestr.h @@ -0,0 +1,976 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com +*/ + +#ifndef HIDUSAGESTR_H_INCLUDED +#define HIDUSAGESTR_H_INCLUDED + +const char pstrSpace [] = " "; +const char pstrCRLF [] = "\r\n"; +const char pstrSingleTab [] = "\t"; +const char pstrDoubleTab [] = "\t\t"; +const char pstrTripleTab [] = "\t\t\t"; + +// Usage Page String Titles +const char pstrUsagePageUndefined [] = "Undef"; +const char pstrUsagePageGenericDesktopControls [] = "Gen Desktop Ctrls"; +const char pstrUsagePageSimulationControls [] = "Simu Ctrls"; +const char pstrUsagePageVRControls [] = "VR Ctrls"; +const char pstrUsagePageSportControls [] = "Sport Ctrls"; +const char pstrUsagePageGameControls [] = "Game Ctrls"; +const char pstrUsagePageGenericDeviceControls [] = "Gen Dev Ctrls"; +const char pstrUsagePageKeyboardKeypad [] = "Kbrd/Keypad"; +const char pstrUsagePageLEDs [] = "LEDs"; +const char pstrUsagePageButton [] = "Button"; +const char pstrUsagePageOrdinal [] = "Ordinal"; +const char pstrUsagePageTelephone [] = "Tel"; +const char pstrUsagePageConsumer [] = "Consumer"; +const char pstrUsagePageDigitizer [] = "Digitizer"; +const char pstrUsagePagePID [] = "PID"; +const char pstrUsagePageUnicode [] = "Unicode"; +const char pstrUsagePageAlphaNumericDisplay [] = "Alpha Num Disp"; +const char pstrUsagePageMedicalInstruments [] = "Medical Instr"; +const char pstrUsagePageMonitor [] = "Monitor"; +const char pstrUsagePagePower [] = "Power"; +const char pstrUsagePageBarCodeScanner [] = "Bar Code Scan"; +const char pstrUsagePageScale [] = "Scale"; +const char pstrUsagePageMSRDevices [] = "Magn Stripe Read Dev"; +const char pstrUsagePagePointOfSale [] = "POS"; +const char pstrUsagePageCameraControl [] = "Cam Ctrl"; +const char pstrUsagePageArcade [] = "Arcade"; +const char pstrUsagePageReserved [] = "Reserved"; +const char pstrUsagePageVendorDefined [] = "Vendor Def"; + +// Generic Desktop Controls Page +const char pstrUsagePointer [] = "Pointer"; +const char pstrUsageMouse [] = "Mouse"; +const char pstrUsageJoystick [] = "Joystick"; +const char pstrUsageGamePad [] = "Game Pad"; +const char pstrUsageKeyboard [] = "Kbrd"; +const char pstrUsageKeypad [] = "Keypad"; +const char pstrUsageMultiAxisController [] = "Multi-axis Ctrl"; +const char pstrUsageTabletPCSystemControls [] = "Tablet PC Sys Ctrls"; +const char pstrUsageX [] = "X"; +const char pstrUsageY [] = "Y"; +const char pstrUsageZ [] = "Z"; +const char pstrUsageRx [] = "Rx"; +const char pstrUsageRy [] = "Ry"; +const char pstrUsageRz [] = "Rz"; +const char pstrUsageSlider [] = "Slider"; +const char pstrUsageDial [] = "Dial"; +const char pstrUsageWheel [] = "Wheel"; +const char pstrUsageHatSwitch [] = "Hat Switch"; +const char pstrUsageCountedBuffer [] = "Counted Buf"; +const char pstrUsageByteCount [] = "Byte Count"; +const char pstrUsageMotionWakeup [] = "Motion Wakeup"; +const char pstrUsageStart [] = "Start"; +const char pstrUsageSelect [] = "Sel"; +const char pstrUsageVx [] = "Vx"; +const char pstrUsageVy [] = "Vy"; +const char pstrUsageVz [] = "Vz"; +const char pstrUsageVbrx [] = "Vbrx"; +const char pstrUsageVbry [] = "Vbry"; +const char pstrUsageVbrz [] = "Vbrz"; +const char pstrUsageVno [] = "Vno"; +const char pstrUsageFeatureNotification [] = "Feature Notif"; +const char pstrUsageResolutionMultiplier [] = "Res Mult"; +const char pstrUsageSystemControl [] = "Sys Ctrl"; +const char pstrUsageSystemPowerDown [] = "Sys Pwr Down"; +const char pstrUsageSystemSleep [] = "Sys Sleep"; +const char pstrUsageSystemWakeup [] = "Sys Wakeup"; +const char pstrUsageSystemContextMenu [] = "Sys Context Menu"; +const char pstrUsageSystemMainMenu [] = "Sys Main Menu"; +const char pstrUsageSystemAppMenu [] = "Sys App Menu"; +const char pstrUsageSystemMenuHelp [] = "Sys Menu Help"; +const char pstrUsageSystemMenuExit [] = "Sys Menu Exit"; +const char pstrUsageSystemMenuSelect [] = "Sys Menu Select"; +const char pstrUsageSystemMenuRight [] = "Sys Menu Right"; +const char pstrUsageSystemMenuLeft [] = "Sys Menu Left"; +const char pstrUsageSystemMenuUp [] = "Sys Menu Up"; +const char pstrUsageSystemMenuDown [] = "Sys Menu Down"; +const char pstrUsageSystemColdRestart [] = "Sys Cold Restart"; +const char pstrUsageSystemWarmRestart [] = "Sys Warm Restart"; +const char pstrUsageDPadUp [] = "D-pad Up"; +const char pstrUsageDPadDown [] = "D-pad Down"; +const char pstrUsageDPadRight [] = "D-pad Right"; +const char pstrUsageDPadLeft [] = "D-pad Left"; +const char pstrUsageSystemDock [] = "Sys Dock"; +const char pstrUsageSystemUndock [] = "Sys Undock"; +const char pstrUsageSystemSetup [] = "Sys Setup"; +const char pstrUsageSystemBreak [] = "Sys Break"; +const char pstrUsageSystemDebuggerBreak [] = "Sys Dbg Brk"; +const char pstrUsageApplicationBreak [] = "App Break"; +const char pstrUsageApplicationDebuggerBreak [] = "App Dbg Brk"; +const char pstrUsageSystemSpeakerMute [] = "Sys Spk Mute"; +const char pstrUsageSystemHibernate [] = "Sys Hiber"; +const char pstrUsageSystemDisplayInvert [] = "Sys Disp Inv"; +const char pstrUsageSystemDisplayInternal [] = "Sys Disp Int"; +const char pstrUsageSystemDisplayExternal [] = "Sys Disp Ext"; +const char pstrUsageSystemDisplayBoth [] = "Sys Disp Both"; +const char pstrUsageSystemDisplayDual [] = "Sys Disp Dual"; +const char pstrUsageSystemDisplayToggleIntExt [] = "Sys Disp Tgl Int/Ext"; +const char pstrUsageSystemDisplaySwapPriSec [] = "Sys Disp Swap Pri/Sec"; +const char pstrUsageSystemDisplayLCDAutoscale [] = "Sys Disp LCD Autoscale"; + +// Simulation Controls Page +const char pstrUsageFlightSimulationDevice [] = "Flight Simu Dev"; +const char pstrUsageAutomobileSimulationDevice [] = "Auto Simu Dev"; +const char pstrUsageTankSimulationDevice [] = "Tank Simu Dev"; +const char pstrUsageSpaceshipSimulationDevice [] = "Space Simu Dev"; +const char pstrUsageSubmarineSimulationDevice [] = "Subm Simu Dev"; +const char pstrUsageSailingSimulationDevice [] = "Sail Simu Dev"; +const char pstrUsageMotocicleSimulationDevice [] = "Moto Simu Dev"; +const char pstrUsageSportsSimulationDevice [] = "Sport Simu Dev"; +const char pstrUsageAirplaneSimulationDevice [] = "Airp Simu Dev"; +const char pstrUsageHelicopterSimulationDevice [] = "Heli Simu Dev"; +const char pstrUsageMagicCarpetSimulationDevice [] = "Magic Carpet Simu Dev"; +const char pstrUsageBicycleSimulationDevice [] = "Bike Simu Dev"; +const char pstrUsageFlightControlStick [] = "Flight Ctrl Stick"; +const char pstrUsageFlightStick [] = "Flight Stick"; +const char pstrUsageCyclicControl [] = "Cyclic Ctrl"; +const char pstrUsageCyclicTrim [] = "Cyclic Trim"; +const char pstrUsageFlightYoke [] = "Flight Yoke"; +const char pstrUsageTrackControl [] = "Track Ctrl"; +const char pstrUsageAileron [] = "Aileron"; +const char pstrUsageAileronTrim [] = "Aileron Trim"; +const char pstrUsageAntiTorqueControl [] = "Anti-Torque Ctrl"; +const char pstrUsageAutopilotEnable [] = "Autopilot Enable"; +const char pstrUsageChaffRelease [] = "Chaff Release"; +const char pstrUsageCollectiveControl [] = "Collective Ctrl"; +const char pstrUsageDiveBrake [] = "Dive Brake"; +const char pstrUsageElectronicCountermeasures [] = "El Countermeasures"; +const char pstrUsageElevator [] = "Elevator"; +const char pstrUsageElevatorTrim [] = "Elevator Trim"; +const char pstrUsageRudder [] = "Rudder"; +const char pstrUsageThrottle [] = "Throttle"; +const char pstrUsageFlightCommunications [] = "Flight Comm"; +const char pstrUsageFlareRelease [] = "Flare Release"; +const char pstrUsageLandingGear [] = "Landing Gear"; +const char pstrUsageToeBrake [] = "Toe Brake"; +const char pstrUsageTrigger [] = "Trigger"; +const char pstrUsageWeaponsArm [] = "Weapons Arm"; +const char pstrUsageWeaponsSelect [] = "Weapons Sel"; +const char pstrUsageWingFlaps [] = "Wing Flaps"; +const char pstrUsageAccelerator [] = "Accel"; +const char pstrUsageBrake [] = "Brake"; +const char pstrUsageClutch [] = "Clutch"; +const char pstrUsageShifter [] = "Shifter"; +const char pstrUsageSteering [] = "Steering"; +const char pstrUsageTurretDirection [] = "Turret Dir"; +const char pstrUsageBarrelElevation [] = "Barrel Ele"; +const char pstrUsageDivePlane [] = "Dive Plane"; +const char pstrUsageBallast [] = "Ballast"; +const char pstrUsageBicycleCrank [] = "Bicycle Crank"; +const char pstrUsageHandleBars [] = "Handle Bars"; +const char pstrUsageFrontBrake [] = "Front Brake"; +const char pstrUsageRearBrake [] = "Rear Brake"; + +// VR Controls Page +const char pstrUsageBelt [] = "Belt"; +const char pstrUsageBodySuit [] = "Body Suit"; +const char pstrUsageFlexor [] = "Flexor"; +const char pstrUsageGlove [] = "Glove"; +const char pstrUsageHeadTracker [] = "Head Track"; +const char pstrUsageHeadMountedDisplay [] = "Head Disp"; +const char pstrUsageHandTracker [] = "Hand Track"; +const char pstrUsageOculometer [] = "Oculometer"; +const char pstrUsageVest [] = "Vest"; +const char pstrUsageAnimatronicDevice [] = "Animat Dev"; +const char pstrUsageStereoEnable [] = "Stereo Enbl"; +const char pstrUsageDisplayEnable [] = "Display Enbl"; + +// Sport Controls Page +const char pstrUsageBaseballBat [] = "Baseball Bat"; +const char pstrUsageGolfClub [] = "Golf Club"; +const char pstrUsageRowingMachine [] = "Rowing Mach"; +const char pstrUsageTreadmill [] = "Treadmill"; +const char pstrUsageOar [] = "Oar"; +const char pstrUsageSlope [] = "Slope"; +const char pstrUsageRate [] = "Rate"; +const char pstrUsageStickSpeed [] = "Stick Speed"; +const char pstrUsageStickFaceAngle [] = "Stick Face Ang"; +const char pstrUsageStickHeelToe [] = "Stick Heel/Toe"; +const char pstrUsageStickFollowThough [] = "Stick Flw Thru"; +const char pstrUsageStickTempo [] = "Stick Tempo"; +const char pstrUsageStickType [] = "Stick Type"; +const char pstrUsageStickHeight [] = "Stick Hght"; +const char pstrUsagePutter [] = "Putter"; +const char pstrUsage1Iron [] = "1 Iron"; +const char pstrUsage2Iron [] = "2 Iron"; +const char pstrUsage3Iron [] = "3 Iron"; +const char pstrUsage4Iron [] = "4 Iron"; +const char pstrUsage5Iron [] = "5 Iron"; +const char pstrUsage6Iron [] = "6 Iron"; +const char pstrUsage7Iron [] = "7 Iron"; +const char pstrUsage8Iron [] = "8 Iron"; +const char pstrUsage9Iron [] = "9 Iron"; +const char pstrUsage10Iron [] = "10 Iron"; +const char pstrUsage11Iron [] = "11 Iron"; +const char pstrUsageSandWedge [] = "Sand Wedge"; +const char pstrUsageLoftWedge [] = "Loft Wedge"; +const char pstrUsagePowerWedge [] = "Pwr Wedge"; +const char pstrUsage1Wood [] = "1 Wood"; +const char pstrUsage3Wood [] = "3 Wood"; +const char pstrUsage5Wood [] = "5 Wood"; +const char pstrUsage7Wood [] = "7 Wood"; +const char pstrUsage9Wood [] = "9 Wood"; + +// Game Controls Page +const char pstrUsage3DGameController [] = "3D Game Ctrl"; +const char pstrUsagePinballDevice [] = "Pinball Dev"; +const char pstrUsageGunDevice [] = "Gun Dev"; +const char pstrUsagePointOfView [] = "POV"; +const char pstrUsageTurnRightLeft [] = "Turn Right Left"; +const char pstrUsagePitchForwardBackward [] = "Pitch Fwd/Back"; +const char pstrUsageRollRightLeft [] = "Roll Right/Left"; +const char pstrUsageMoveRightLeft [] = "Move Right/Left"; +const char pstrUsageMoveForwardBackward [] = "Move Fwd/Back"; +const char pstrUsageMoveUpDown [] = "Move Up/Down"; +const char pstrUsageLeanRightLeft [] = "Lean Right/Left"; +const char pstrUsageLeanForwardBackward [] = "Lean Fwd/Back"; +const char pstrUsageHeightOfPOV [] = "Height of POV"; +const char pstrUsageFlipper [] = "Flipper"; +const char pstrUsageSecondaryFlipper [] = "Second Flipper"; +const char pstrUsageBump [] = "Bump"; +const char pstrUsageNewGame [] = "New Game"; +const char pstrUsageShootBall [] = "Shoot Ball"; +const char pstrUsagePlayer [] = "Player"; +const char pstrUsageGunBolt [] = "Gun Bolt"; +const char pstrUsageGunClip [] = "Gun Clip"; +const char pstrUsageGunSelector [] = "Gun Sel"; +const char pstrUsageGunSingleShot [] = "Gun Sngl Shot"; +const char pstrUsageGunBurst [] = "Gun Burst"; +const char pstrUsageGunAutomatic [] = "Gun Auto"; +const char pstrUsageGunSafety [] = "Gun Safety"; +const char pstrUsageGamepadFireJump [] = "Gamepad Fire/Jump"; +const char pstrUsageGamepadTrigger [] = "Gamepad Trig"; + +// Generic Device Controls Page +const char pstrUsageBatteryStrength [] = "Bat Strength"; +const char pstrUsageWirelessChannel [] = "Wireless Ch"; +const char pstrUsageWirelessID [] = "Wireless ID"; +const char pstrUsageDiscoverWirelessControl [] = "Discover Wireless Ctrl"; +const char pstrUsageSecurityCodeCharEntered [] = "Sec Code Char Entrd"; +const char pstrUsageSecurityCodeCharErased [] = "Sec Code Char Erased"; +const char pstrUsageSecurityCodeCleared [] = "Sec Code Cleared"; + +// LED Page +const char pstrUsageNumLock [] = "Num Lock"; +const char pstrUsageCapsLock [] = "Caps Lock"; +const char pstrUsageScrollLock [] = "Scroll Lock"; +const char pstrUsageCompose [] = "Compose"; +const char pstrUsageKana [] = "Kana"; +const char pstrUsagePower [] = "Pwr"; +const char pstrUsageShift [] = "Shift"; +const char pstrUsageDoNotDisturb [] = "DND"; +const char pstrUsageMute [] = "Mute"; +const char pstrUsageToneEnable [] = "Tone Enbl"; +const char pstrUsageHighCutFilter [] = "High Cut Fltr"; +const char pstrUsageLowCutFilter [] = "Low Cut Fltr"; +const char pstrUsageEqualizerEnable [] = "Eq Enbl"; +const char pstrUsageSoundFieldOn [] = "Sound Field On"; +const char pstrUsageSurroundOn [] = "Surround On"; +const char pstrUsageRepeat [] = "Repeat"; +const char pstrUsageStereo [] = "Stereo"; +const char pstrUsageSamplingRateDetect [] = "Smpl Rate Detect"; +const char pstrUsageSpinning [] = "Spinning"; +const char pstrUsageCAV [] = "CAV"; +const char pstrUsageCLV [] = "CLV"; +const char pstrUsageRecordingFormatDetect [] = "Rec Format Detect"; +const char pstrUsageOffHook [] = "Off Hook"; +const char pstrUsageRing [] = "Ring"; +const char pstrUsageMessageWaiting [] = "Msg Wait"; +const char pstrUsageDataMode [] = "Data Mode"; +const char pstrUsageBatteryOperation [] = "Bat Op"; +const char pstrUsageBatteryOK [] = "Bat OK"; +const char pstrUsageBatteryLow [] = "Bat Low"; +const char pstrUsageSpeaker [] = "Speaker"; +const char pstrUsageHeadSet [] = "Head Set"; +const char pstrUsageHold [] = "Hold"; +const char pstrUsageMicrophone [] = "Mic"; +const char pstrUsageCoverage [] = "Coverage"; +const char pstrUsageNightMode [] = "Night Mode"; +const char pstrUsageSendCalls [] = "Send Calls"; +const char pstrUsageCallPickup [] = "Call Pickup"; +const char pstrUsageConference [] = "Conf"; +const char pstrUsageStandBy [] = "Stand-by"; +const char pstrUsageCameraOn [] = "Cam On"; +const char pstrUsageCameraOff [] = "Cam Off"; +const char pstrUsageOnLine [] = "On-Line"; +const char pstrUsageOffLine [] = "Off-Line"; +const char pstrUsageBusy [] = "Busy"; +const char pstrUsageReady [] = "Ready"; +const char pstrUsagePaperOut [] = "Paper Out"; +const char pstrUsagePaperJam [] = "Paper Jam"; +const char pstrUsageRemote [] = "Remote"; +const char pstrUsageForward [] = "Fwd"; +const char pstrUsageReverse [] = "Rev"; +const char pstrUsageStop [] = "Stop"; +const char pstrUsageRewind [] = "Rewind"; +const char pstrUsageFastForward [] = "Fast Fwd"; +const char pstrUsagePlay [] = "Play"; +const char pstrUsagePause [] = "Pause"; +const char pstrUsageRecord [] = "Rec"; +const char pstrUsageError [] = "Error"; +const char pstrUsageSelectedIndicator [] = "Usage Sel Ind"; +const char pstrUsageInUseIndicator [] = "Usage In Use Ind"; +const char pstrUsageMultiModeIndicator [] = "Usage Multi Mode Ind"; +const char pstrUsageIndicatorOn [] = "Ind On"; +const char pstrUsageIndicatorFlash [] = "Ind Flash"; +const char pstrUsageIndicatorSlowBlink [] = "Ind Slow Blk"; +const char pstrUsageIndicatorFastBlink [] = "Ind Fast Blk"; +const char pstrUsageIndicatorOff [] = "Ind Off"; +const char pstrUsageFlashOnTime [] = "Flash On Time"; +const char pstrUsageSlowBlinkOnTime [] = "Slow Blk On Time"; +const char pstrUsageSlowBlinkOffTime [] = "Slow Blk Off Time"; +const char pstrUsageFastBlinkOnTime [] = "Fast Blk On Time"; +const char pstrUsageFastBlinkOffTime [] = "Fast Blk Off Time"; +const char pstrUsageIndicatorColor [] = "Usage Ind Color"; +const char pstrUsageIndicatorRed [] = "Ind Red"; +const char pstrUsageIndicatorGreen [] = "Ind Green"; +const char pstrUsageIndicatorAmber [] = "Ind Amber"; +const char pstrUsageGenericIndicator [] = "Gen Ind"; +const char pstrUsageSystemSuspend [] = "Sys Suspend"; +const char pstrUsageExternalPowerConnected [] = "Ext Pwr Conn"; + +// Telephony Usage Page +const char pstrUsagePhone [] = "Phone"; +const char pstrUsageAnsweringMachine [] = "Answ Mach"; +const char pstrUsageMessageControls [] = "Msg Ctrls"; +const char pstrUsageHandset [] = "Handset"; +const char pstrUsageHeadset [] = "Headset"; +const char pstrUsageTelephonyKeyPad [] = "Tel Key Pad"; +const char pstrUsageProgrammableButton [] = "Prog Button"; +const char pstrUsageHookSwitch [] = "Hook Sw"; +const char pstrUsageFlash [] = "Flash"; +const char pstrUsageFeature [] = "Feature"; +//const char pstrUsageHold [] = "Hold"; +const char pstrUsageRedial [] = "Redial"; +const char pstrUsageTransfer [] = "Transfer"; +const char pstrUsageDrop [] = "Drop"; +const char pstrUsagePark [] = "Park"; +const char pstrUsageForwardCalls [] = "Fwd Calls"; +const char pstrUsageAlternateFunction [] = "Alt Func"; +const char pstrUsageLine [] = "Line"; +const char pstrUsageSpeakerPhone [] = "Spk Phone"; +//const char pstrUsageConference [] = "Conference"; +const char pstrUsageRingEnable [] = "Ring Enbl"; +const char pstrUsageRingSelect [] = "Ring Sel"; +const char pstrUsagePhoneMute [] = "Phone Mute"; +const char pstrUsageCallerID [] = "Caller ID"; +const char pstrUsageSend [] = "Send"; +const char pstrUsageSpeedDial [] = "Speed Dial"; +const char pstrUsageStoreNumber [] = "Store Num"; +const char pstrUsageRecallNumber [] = "Recall Num"; +const char pstrUsagePhoneDirectory [] = "Phone Dir"; +const char pstrUsageVoiceMail [] = "Voice Mail"; +const char pstrUsageScreenCalls [] = "Screen Calls"; +//const char pstrUsageDoNotDisturb [] = "Do Not Disturb"; +const char pstrUsageMessage [] = "Msg"; +const char pstrUsageAnswerOnOff [] = "Answer On/Off"; +const char pstrUsageInsideDialTone [] = "Inside Dial Tone"; +const char pstrUsageOutsideDialTone [] = "Outside Dial Tone"; +const char pstrUsageInsideRingTone [] = "Inside Ring Tone"; +const char pstrUsageOutsideRingTone [] = "Outside Ring Tone"; +const char pstrUsagePriorityRingTone [] = "Prior Ring Tone"; +const char pstrUsageInsideRingback [] = "Inside Ringback"; +const char pstrUsagePriorityRingback [] = "Priority Ringback"; +const char pstrUsageLineBusyTone [] = "Ln Busy Tone"; +const char pstrUsageReorderTone [] = "Reorder Tone"; +const char pstrUsageCallWaitingTone [] = "Call Wait Tone"; +const char pstrUsageConfirmationTone1 [] = "Cnfrm Tone1"; +const char pstrUsageConfirmationTone2 [] = "Cnfrm Tone2"; +const char pstrUsageTonesOff [] = "Tones Off"; +const char pstrUsageOutsideRingback [] = "Outside Ringback"; +const char pstrUsageRinger [] = "Ringer"; +const char pstrUsagePhoneKey0 [] = "0"; +const char pstrUsagePhoneKey1 [] = "1"; +const char pstrUsagePhoneKey2 [] = "2"; +const char pstrUsagePhoneKey3 [] = "3"; +const char pstrUsagePhoneKey4 [] = "4"; +const char pstrUsagePhoneKey5 [] = "5"; +const char pstrUsagePhoneKey6 [] = "6"; +const char pstrUsagePhoneKey7 [] = "7"; +const char pstrUsagePhoneKey8 [] = "8"; +const char pstrUsagePhoneKey9 [] = "9"; +const char pstrUsagePhoneKeyStar [] = "*"; +const char pstrUsagePhoneKeyPound [] = "#"; +const char pstrUsagePhoneKeyA [] = "A"; +const char pstrUsagePhoneKeyB [] = "B"; +const char pstrUsagePhoneKeyC [] = "C"; +const char pstrUsagePhoneKeyD [] = "D"; + +// Consumer Usage Page +const char pstrUsageConsumerControl [] = "Consumer Ctrl"; +const char pstrUsageNumericKeyPad [] = "Num Key Pad"; +//const char pstrUsageProgrammableButton [] = "Prog Btn"; +//const char pstrUsageMicrophone [] = "Mic"; +const char pstrUsageHeadphone [] = "Headphone"; +const char pstrUsageGraphicEqualizer [] = "Graph Eq"; +const char pstrUsagePlus10 [] = "+10"; +const char pstrUsagePlus100 [] = "+100"; +const char pstrUsageAMPM [] = "AM/PM"; +//const char pstrUsagePower [] = "Pwr"; +const char pstrUsageReset [] = "Reset"; +const char pstrUsageSleep [] = "Sleep"; +const char pstrUsageSleepAfter [] = "Sleep After"; +const char pstrUsageSleepMode [] = "Sleep Mode"; +const char pstrUsageIllumination [] = "Illumin"; +const char pstrUsageFunctionButtons [] = "Func Btns"; +const char pstrUsageMenu [] = "Menu"; +const char pstrUsageMenuPick [] = "Menu Pick"; +const char pstrUsageMenuUp [] = "Menu Up"; +const char pstrUsageMenuDown [] = "Menu Down"; +const char pstrUsageMenuLeft [] = "Menu Left"; +const char pstrUsageMenuRight [] = "Menu Right"; +const char pstrUsageMenuEscape [] = "Menu Esc"; +const char pstrUsageMenuValueIncrease [] = "Menu Val Inc"; +const char pstrUsageMenuValueDecrease [] = "Menu Val Dec"; +const char pstrUsageDataOnScreen [] = "Data On Scr"; +const char pstrUsageClosedCaption [] = "Closed Cptn"; +const char pstrUsageClosedCaptionSelect [] = "Closed Cptn Sel"; +const char pstrUsageVCRTV [] = "VCR/TV"; +const char pstrUsageBroadcastMode [] = "Brdcast Mode"; +const char pstrUsageSnapshot [] = "Snapshot"; +const char pstrUsageStill [] = "Still"; +const char pstrUsageSelection [] = "Sel"; +const char pstrUsageAssignSelection [] = "Assign Sel"; +const char pstrUsageModeStep [] = "Mode Step"; +const char pstrUsageRecallLast [] = "Recall Last"; +const char pstrUsageEnterChannel [] = "Entr Channel"; +const char pstrUsageOrderMovie [] = "Ord Movie"; +const char pstrUsageChannel [] = "Channel"; +const char pstrUsageMediaSelection [] = "Med Sel"; +const char pstrUsageMediaSelectComputer [] = "Med Sel Comp"; +const char pstrUsageMediaSelectTV [] = "Med Sel TV"; +const char pstrUsageMediaSelectWWW [] = "Med Sel WWW"; +const char pstrUsageMediaSelectDVD [] = "Med Sel DVD"; +const char pstrUsageMediaSelectTelephone [] = "Med Sel Tel"; +const char pstrUsageMediaSelectProgramGuide [] = "Med Sel PG"; +const char pstrUsageMediaSelectVideoPhone [] = "Med Sel Vid"; +const char pstrUsageMediaSelectGames [] = "Med Sel Games"; +const char pstrUsageMediaSelectMessages [] = "Med Sel Msg"; +const char pstrUsageMediaSelectCD [] = "Med Sel CD"; +const char pstrUsageMediaSelectVCR [] = "Med Sel VCR"; +const char pstrUsageMediaSelectTuner [] = "Med Sel Tuner"; +const char pstrUsageQuit [] = "Quit"; +const char pstrUsageHelp [] = "Help"; +const char pstrUsageMediaSelectTape [] = "Med Sel Tape"; +const char pstrUsageMediaSelectCable [] = "Med Sel Cbl"; +const char pstrUsageMediaSelectSatellite [] = "Med Sel Sat"; +const char pstrUsageMediaSelectSecurity [] = "Med Sel Secur"; +const char pstrUsageMediaSelectHome [] = "Med Sel Home"; +const char pstrUsageMediaSelectCall [] = "Med Sel Call"; +const char pstrUsageChannelIncrement [] = "Ch Inc"; +const char pstrUsageChannelDecrement [] = "Ch Dec"; +const char pstrUsageMediaSelectSAP [] = "Med Sel SAP"; +const char pstrUsageVCRPlus [] = "VCR+"; +const char pstrUsageOnce [] = "Once"; +const char pstrUsageDaily [] = "Daily"; +const char pstrUsageWeekly [] = "Weekly"; +const char pstrUsageMonthly [] = "Monthly"; +//const char pstrUsagePlay [] = "Play"; +//const char pstrUsagePause [] = "Pause"; +//const char pstrUsageRecord [] = "Rec"; +//const char pstrUsageFastForward [] = "FF"; +//const char pstrUsageRewind [] = "Rewind"; +const char pstrUsageScanNextTrack [] = "Next Track"; +const char pstrUsageScanPreviousTrack [] = "Prev Track"; +//const char pstrUsageStop [] = "Stop"; +const char pstrUsageEject [] = "Eject"; +const char pstrUsageRandomPlay [] = "Random"; +const char pstrUsageSelectDisk [] = "Sel Disk"; +const char pstrUsageEnterDisk [] = "Ent Disk"; +//const char pstrUsageRepeat [] = "Repeat"; +const char pstrUsageTracking [] = "Tracking"; +const char pstrUsageTrackNormal [] = "Trk Norm"; +const char pstrUsageSlowTracking [] = "Slow Trk"; +const char pstrUsageFrameForward [] = "Frm Fwd"; +const char pstrUsageFrameBackwards [] = "Frm Back"; +const char pstrUsageMark [] = "Mark"; +const char pstrUsageClearMark [] = "Clr Mark"; +const char pstrUsageRepeatFromMark [] = "Rpt Mark"; +const char pstrUsageReturnToMark [] = "Ret to Mark"; +const char pstrUsageSearchMarkForward [] = "Search Mark Fwd"; +const char pstrUsageSearchMarkBackwards [] = "Search Mark Back"; +const char pstrUsageCounterReset [] = "Counter Reset"; +const char pstrUsageShowCounter [] = "Show Counter"; +const char pstrUsageTrackingIncrement [] = "Track Inc"; +const char pstrUsageTrackingDecrement [] = "Track Dec"; +const char pstrUsageStopEject [] = "Stop/Eject"; +const char pstrUsagePlayPause [] = "Play/Pause"; +const char pstrUsagePlaySkip [] = "Play/Skip"; +const char pstrUsageVolume [] = "Vol"; +const char pstrUsageBalance [] = "Balance"; +//const char pstrUsageMute [] = "Mute"; +const char pstrUsageBass [] = "Bass"; +const char pstrUsageTreble [] = "Treble"; +const char pstrUsageBassBoost [] = "Bass Boost"; +const char pstrUsageSurroundMode [] = "Surround"; +const char pstrUsageLoudness [] = "Loud"; +const char pstrUsageMPX [] = "MPX"; +const char pstrUsageVolumeIncrement [] = "Vol Inc"; +const char pstrUsageVolumeDecrement [] = "Vol Dec"; +const char pstrUsageSpeedSelect [] = "Speed"; +const char pstrUsagePlaybackSpeed [] = "Play Speed"; +const char pstrUsageStandardPlay [] = "Std Play"; +const char pstrUsageLongPlay [] = "Long Play"; +const char pstrUsageExtendedPlay [] = "Ext Play"; +const char pstrUsageSlow [] = "Slow"; +const char pstrUsageFanEnable [] = "Fan Enbl"; +const char pstrUsageFanSpeed [] = "Fan Speed"; +const char pstrUsageLightEnable [] = "Light Enbl"; +const char pstrUsageLightIlluminationLevel [] = "Light Illum Lev"; +const char pstrUsageClimateControlEnable [] = "Climate Enbl"; +const char pstrUsageRoomTemperature [] = "Room Temp"; +const char pstrUsageSecurityEnable [] = "Secur Enbl"; +const char pstrUsageFireAlarm [] = "Fire Alm"; +const char pstrUsagePoliceAlarm [] = "Police Alm"; +const char pstrUsageProximity [] = "Prox"; +const char pstrUsageMotion [] = "Motion"; +const char pstrUsageDuresAlarm [] = "Dures Alm"; +const char pstrUsageHoldupAlarm [] = "Holdup Alm"; +const char pstrUsageMedicalAlarm [] = "Med Alm"; +const char pstrUsageBalanceRight [] = "Balance Right"; +const char pstrUsageBalanceLeft [] = "Balance Left"; +const char pstrUsageBassIncrement [] = "Bass Inc"; +const char pstrUsageBassDecrement [] = "Bass Dec"; +const char pstrUsageTrebleIncrement [] = "Treble Inc"; +const char pstrUsageTrebleDecrement [] = "Treble Dec"; +const char pstrUsageSpeakerSystem [] = "Spk Sys"; +const char pstrUsageChannelLeft [] = "Ch Left"; +const char pstrUsageChannelRight [] = "Ch Right"; +const char pstrUsageChannelCenter [] = "Ch Center"; +const char pstrUsageChannelFront [] = "Ch Front"; +const char pstrUsageChannelCenterFront [] = "Ch Cntr Front"; +const char pstrUsageChannelSide [] = "Ch Side"; +const char pstrUsageChannelSurround [] = "Ch Surround"; +const char pstrUsageChannelLowFreqEnhancement [] = "Ch Low Freq Enh"; +const char pstrUsageChannelTop [] = "Ch Top"; +const char pstrUsageChannelUnknown [] = "Ch Unk"; +const char pstrUsageSubChannel [] = "Sub-ch"; +const char pstrUsageSubChannelIncrement [] = "Sub-ch Inc"; +const char pstrUsageSubChannelDecrement [] = "Sub-ch Dec"; +const char pstrUsageAlternateAudioIncrement [] = "Alt Aud Inc"; +const char pstrUsageAlternateAudioDecrement [] = "Alt Aud Dec"; +const char pstrUsageApplicationLaunchButtons [] = "App Launch Btns"; +const char pstrUsageALLaunchButtonConfigTool [] = "AL Launch Conf Tl"; +const char pstrUsageALProgrammableButton [] = "AL Pgm Btn"; +const char pstrUsageALConsumerControlConfig [] = "AL Cons Ctrl Cfg"; +const char pstrUsageALWordProcessor [] = "AL Word Proc"; +const char pstrUsageALTextEditor [] = "AL Txt Edtr"; +const char pstrUsageALSpreadsheet [] = "AL Sprdsheet"; +const char pstrUsageALGraphicsEditor [] = "AL Graph Edtr"; +const char pstrUsageALPresentationApp [] = "AL Present App"; +const char pstrUsageALDatabaseApp [] = "AL DB App"; +const char pstrUsageALEmailReader [] = "AL E-mail Rdr"; +const char pstrUsageALNewsreader [] = "AL Newsrdr"; +const char pstrUsageALVoicemail [] = "AL Voicemail"; +const char pstrUsageALContactsAddressBook [] = "AL Addr Book"; +const char pstrUsageALCalendarSchedule [] = "AL Clndr/Schdlr"; +const char pstrUsageALTaskProjectManager [] = "AL Task/Prj Mgr"; +const char pstrUsageALLogJournalTimecard [] = "AL Log/Jrnl/Tmcrd"; +const char pstrUsageALCheckbookFinance [] = "AL Chckbook/Fin"; +const char pstrUsageALCalculator [] = "AL Calc"; +const char pstrUsageALAVCapturePlayback [] = "AL A/V Capt/Play"; +const char pstrUsageALLocalMachineBrowser [] = "AL Loc Mach Brow"; +const char pstrUsageALLANWANBrow [] = "AL LAN/WAN Brow"; +const char pstrUsageALInternetBrowser [] = "AL I-net Brow"; +const char pstrUsageALRemoteNetISPConnect [] = "AL Rem Net Con"; +const char pstrUsageALNetworkConference [] = "AL Net Conf"; +const char pstrUsageALNetworkChat [] = "AL Net Chat"; +const char pstrUsageALTelephonyDialer [] = "AL Tel/Dial"; +const char pstrUsageALLogon [] = "AL Logon"; +const char pstrUsageALLogoff [] = "AL Logoff"; +const char pstrUsageALLogonLogoff [] = "AL Logon/Logoff"; +const char pstrUsageALTermLockScrSav [] = "AL Term Lock/Scr Sav"; +const char pstrUsageALControlPannel [] = "AL Ctrl Pan"; +const char pstrUsageALCommandLineProcessorRun [] = "AL Cmd/Run"; +const char pstrUsageALProcessTaskManager [] = "AL Task Mgr"; +const char pstrUsageALSelectTaskApplication [] = "AL Sel App"; +const char pstrUsageALNextTaskApplication [] = "AL Next App"; +const char pstrUsageALPreviousTaskApplication [] = "AL Prev App"; +const char pstrUsageALPreemptiveHaltTaskApp [] = "AL Prmpt Halt App"; +const char pstrUsageALIntegratedHelpCenter [] = "AL Hlp Cntr"; +const char pstrUsageALDocuments [] = "AL Docs"; +const char pstrUsageALThesaurus [] = "AL Thsrs"; +const char pstrUsageALDictionary [] = "AL Dict"; +const char pstrUsageALDesktop [] = "AL Desktop"; +const char pstrUsageALSpellCheck [] = "AL Spell Chk"; +const char pstrUsageALGrammarCheck [] = "AL Gram Chk"; +const char pstrUsageALWirelessStatus [] = "AL Wireless Sts"; +const char pstrUsageALKeyboardLayout [] = "AL Kbd Layout"; +const char pstrUsageALVirusProtection [] = "AL Vir Protect"; +const char pstrUsageALEncryption [] = "AL Encrypt"; +const char pstrUsageALScreenSaver [] = "AL Scr Sav"; +const char pstrUsageALAlarms [] = "AL Alarms"; +const char pstrUsageALClock [] = "AL Clock"; +const char pstrUsageALFileBrowser [] = "AL File Brow"; +const char pstrUsageALPowerStatus [] = "AL Pwr Sts"; +const char pstrUsageALImageBrowser [] = "AL Img Brow"; +const char pstrUsageALAudioBrowser [] = "AL Aud Brow"; +const char pstrUsageALMovieBrowser [] = "AL Mov Brow"; +const char pstrUsageALDigitalRightsManager [] = "AL Dig Rights Mgr"; +const char pstrUsageALDigitalWallet [] = "AL Dig Wallet"; +const char pstrUsageALInstantMessaging [] = "AL Inst Msg"; +const char pstrUsageALOEMFeaturesBrowser [] = "AL OEM Tips Brow"; +const char pstrUsageALOEMHelp [] = "AL OEM Hlp"; +const char pstrUsageALOnlineCommunity [] = "AL Online Com"; +const char pstrUsageALEntertainmentContentBrow [] = "AL Ent Cont Brow"; +const char pstrUsageALOnlineShoppingBrowser [] = "AL Online Shop Brow"; +const char pstrUsageALSmartCardInfoHelp [] = "AL SmartCard Inf"; +const char pstrUsageALMarketMonitorFinBrowser [] = "AL Market Brow"; +const char pstrUsageALCustomCorpNewsBrowser [] = "AL Cust Corp News Brow"; +const char pstrUsageALOnlineActivityBrowser [] = "AL Online Act Brow"; +const char pstrUsageALResearchSearchBrowser [] = "AL Search Brow"; +const char pstrUsageALAudioPlayer [] = "AL Aud Player"; +const char pstrUsageGenericGUIAppControls [] = "Gen GUI App Ctrl"; +const char pstrUsageACNew [] = "AC New"; +const char pstrUsageACOpen [] = "AC Open"; +const char pstrUsageACClose [] = "AC Close"; +const char pstrUsageACExit [] = "AC Exit"; +const char pstrUsageACMaximize [] = "AC Max"; +const char pstrUsageACMinimize [] = "AC Min"; +const char pstrUsageACSave [] = "AC Save"; +const char pstrUsageACPrint [] = "AC Print"; +const char pstrUsageACProperties [] = "AC Prop"; +const char pstrUsageACUndo [] = "AC Undo"; +const char pstrUsageACCopy [] = "AC Copy"; +const char pstrUsageACCut [] = "AC Cut"; +const char pstrUsageACPaste [] = "AC Paste"; +const char pstrUsageACSelectAll [] = "AC Sel All"; +const char pstrUsageACFind [] = "AC Find"; +const char pstrUsageACFindAndReplace [] = "AC Find/Replace"; +const char pstrUsageACSearch [] = "AC Search"; +const char pstrUsageACGoto [] = "AC Goto"; +const char pstrUsageACHome [] = "AC Home"; +const char pstrUsageACBack [] = "AC Back"; +const char pstrUsageACForward [] = "AC Fwd"; +const char pstrUsageACStop [] = "AC Stop"; +const char pstrUsageACRefresh [] = "AC Refresh"; +const char pstrUsageACPreviousLink [] = "AC Prev Link"; +const char pstrUsageACNextLink [] = "AC Next Link"; +const char pstrUsageACBookmarks [] = "AC Bkmarks"; +const char pstrUsageACHistory [] = "AC Hist"; +const char pstrUsageACSubscriptions [] = "AC Subscr"; +const char pstrUsageACZoomIn [] = "AC Zoom In"; +const char pstrUsageACZoomOut [] = "AC Zoom Out"; +const char pstrUsageACZoom [] = "AC Zoom"; +const char pstrUsageACFullScreenView [] = "AC Full Scr"; +const char pstrUsageACNormalView [] = "AC Norm View"; +const char pstrUsageACViewToggle [] = "AC View Tgl"; +const char pstrUsageACScrollUp [] = "AC Scroll Up"; +const char pstrUsageACScrollDown [] = "AC Scroll Down"; +const char pstrUsageACScroll [] = "AC Scroll"; +const char pstrUsageACPanLeft [] = "AC Pan Left"; +const char pstrUsageACPanRight [] = "AC Pan Right"; +const char pstrUsageACPan [] = "AC Pan"; +const char pstrUsageACNewWindow [] = "AC New Wnd"; +const char pstrUsageACTileHoriz [] = "AC Tile Horiz"; +const char pstrUsageACTileVert [] = "AC Tile Vert"; +const char pstrUsageACFormat [] = "AC Frmt"; +const char pstrUsageACEdit [] = "AC Edit"; +const char pstrUsageACBold [] = "AC Bold"; +const char pstrUsageACItalics [] = "AC Ital"; +const char pstrUsageACUnderline [] = "AC Under"; +const char pstrUsageACStrikethrough [] = "AC Strike"; +const char pstrUsageACSubscript [] = "AC Sub"; +const char pstrUsageACSuperscript [] = "AC Super"; +const char pstrUsageACAllCaps [] = "AC All Caps"; +const char pstrUsageACRotate [] = "AC Rotate"; +const char pstrUsageACResize [] = "AC Resize"; +const char pstrUsageACFlipHorizontal [] = "AC Flp H"; +const char pstrUsageACFlipVertical [] = "AC Flp V"; +const char pstrUsageACMirrorHorizontal [] = "AC Mir H"; +const char pstrUsageACMirrorVertical [] = "AC Mir V"; +const char pstrUsageACFontSelect [] = "AC Fnt Sel"; +const char pstrUsageACFontColor [] = "AC Fnt Clr"; +const char pstrUsageACFontSize [] = "AC Fnt Size"; +const char pstrUsageACJustifyLeft [] = "AC Just Left"; +const char pstrUsageACJustifyCenterH [] = "AC Just Cent H"; +const char pstrUsageACJustifyRight [] = "AC Just Right"; +const char pstrUsageACJustifyBlockH [] = "AC Just Block H"; +const char pstrUsageACJustifyTop [] = "AC Just Top"; +const char pstrUsageACJustifyCenterV [] = "AC Just Cent V"; +const char pstrUsageACJustifyBottom [] = "AC Just Bot"; +const char pstrUsageACJustifyBlockV [] = "AC Just Block V"; +const char pstrUsageACIndentDecrease [] = "AC Indent Dec"; +const char pstrUsageACIndentIncrease [] = "AC Indent Inc"; +const char pstrUsageACNumberedList [] = "AC Num List"; +const char pstrUsageACRestartNumbering [] = "AC Res Num"; +const char pstrUsageACBulletedList [] = "AC Blt List"; +const char pstrUsageACPromote [] = "AC Promote"; +const char pstrUsageACDemote [] = "AC Demote"; +const char pstrUsageACYes [] = "AC Yes"; +const char pstrUsageACNo [] = "AC No"; +const char pstrUsageACCancel [] = "AC Cancel"; +const char pstrUsageACCatalog [] = "AC Ctlg"; +const char pstrUsageACBuyChkout [] = "AC Buy"; +const char pstrUsageACAddToCart [] = "AC Add2Cart"; +const char pstrUsageACExpand [] = "AC Xpnd"; +const char pstrUsageACExpandAll [] = "AC Xpand All"; +const char pstrUsageACCollapse [] = "AC Collapse"; +const char pstrUsageACCollapseAll [] = "AC Collapse All"; +const char pstrUsageACPrintPreview [] = "AC Prn Prevw"; +const char pstrUsageACPasteSpecial [] = "AC Paste Spec"; +const char pstrUsageACInsertMode [] = "AC Ins Mode"; +const char pstrUsageACDelete [] = "AC Del"; +const char pstrUsageACLock [] = "AC Lock"; +const char pstrUsageACUnlock [] = "AC Unlock"; +const char pstrUsageACProtect [] = "AC Prot"; +const char pstrUsageACUnprotect [] = "AC Unprot"; +const char pstrUsageACAttachComment [] = "AC Attach Cmnt"; +const char pstrUsageACDeleteComment [] = "AC Del Cmnt"; +const char pstrUsageACViewComment [] = "AC View Cmnt"; +const char pstrUsageACSelectWord [] = "AC Sel Word"; +const char pstrUsageACSelectSentence [] = "AC Sel Sntc"; +const char pstrUsageACSelectParagraph [] = "AC Sel Para"; +const char pstrUsageACSelectColumn [] = "AC Sel Col"; +const char pstrUsageACSelectRow [] = "AC Sel Row"; +const char pstrUsageACSelectTable [] = "AC Sel Tbl"; +const char pstrUsageACSelectObject [] = "AC Sel Obj"; +const char pstrUsageACRedoRepeat [] = "AC Redo"; +const char pstrUsageACSort [] = "AC Sort"; +const char pstrUsageACSortAscending [] = "AC Sort Asc"; +const char pstrUsageACSortDescending [] = "AC Sort Desc"; +const char pstrUsageACFilter [] = "AC Filt"; +const char pstrUsageACSetClock [] = "AC Set Clk"; +const char pstrUsageACViewClock [] = "AC View Clk"; +const char pstrUsageACSelectTimeZone [] = "AC Sel Time Z"; +const char pstrUsageACEditTimeZone [] = "AC Edt Time Z"; +const char pstrUsageACSetAlarm [] = "AC Set Alm"; +const char pstrUsageACClearAlarm [] = "AC Clr Alm"; +const char pstrUsageACSnoozeAlarm [] = "AC Snz Alm"; +const char pstrUsageACResetAlarm [] = "AC Rst Alm"; +const char pstrUsageACSyncronize [] = "AC Sync"; +const char pstrUsageACSendReceive [] = "AC Snd/Rcv"; +const char pstrUsageACSendTo [] = "AC Snd To"; +const char pstrUsageACReply [] = "AC Reply"; +const char pstrUsageACReplyAll [] = "AC Reply All"; +const char pstrUsageACForwardMessage [] = "AC Fwd Msg"; +const char pstrUsageACSend [] = "AC Snd"; +const char pstrUsageACAttachFile [] = "AC Att File"; +const char pstrUsageACUpload [] = "AC Upld"; +const char pstrUsageACDownload [] = "AC Dnld"; +const char pstrUsageACSetBorders [] = "AC Set Brd"; +const char pstrUsageACInsertRow [] = "AC Ins Row"; +const char pstrUsageACInsertColumn [] = "AC Ins Col"; +const char pstrUsageACInsertFile [] = "AC Ins File"; +const char pstrUsageACInsertPicture [] = "AC Ins Pic"; +const char pstrUsageACInsertObject [] = "AC Ins Obj"; +const char pstrUsageACInsertSymbol [] = "AC Ins Sym"; +const char pstrUsageACSaveAndClose [] = "AC Sav&Cls"; +const char pstrUsageACRename [] = "AC Rename"; +const char pstrUsageACMerge [] = "AC Merge"; +const char pstrUsageACSplit [] = "AC Split"; +const char pstrUsageACDistributeHorizontaly [] = "AC Dist Hor"; +const char pstrUsageACDistributeVerticaly [] = "AC Dist Ver"; + +// Digitaizers +const char pstrUsageDigitizer [] = "Digitizer"; +const char pstrUsagePen [] = "Pen"; +const char pstrUsageLightPen [] = "Light Pen"; +const char pstrUsageTouchScreen [] = "Touch Scr"; +const char pstrUsageTouchPad [] = "Touch Pad"; +const char pstrUsageWhiteBoard [] = "White Brd"; +const char pstrUsageCoordinateMeasuringMachine [] = "Coord Meas Mach"; +const char pstrUsage3DDigitizer [] = "3D Dgtz"; +const char pstrUsageStereoPlotter [] = "Stereo Plot"; +const char pstrUsageArticulatedArm [] = "Art Arm"; +const char pstrUsageArmature [] = "Armature"; +const char pstrUsageMultiplePointDigitizer [] = "Multi Point Dgtz"; +const char pstrUsageFreeSpaceWand [] = "Free Space Wand"; +const char pstrUsageStylus [] = "Stylus"; +const char pstrUsagePuck [] = "Puck"; +const char pstrUsageFinger [] = "Finger"; +const char pstrUsageTipPressure [] = "Tip Press"; +const char pstrUsageBarrelPressure [] = "Brl Press"; +const char pstrUsageInRange [] = "In Range"; +const char pstrUsageTouch [] = "Touch"; +const char pstrUsageUntouch [] = "Untouch"; +const char pstrUsageTap [] = "Tap"; +const char pstrUsageQuality [] = "Qlty"; +const char pstrUsageDataValid [] = "Data Valid"; +const char pstrUsageTransducerIndex [] = "Transducer Ind"; +const char pstrUsageTabletFunctionKeys [] = "Tabl Func Keys"; +const char pstrUsageProgramChangeKeys [] = "Pgm Chng Keys"; +//const char pstrUsageBatteryStrength [] = "Bat Strength"; +const char pstrUsageInvert [] = "Invert"; +const char pstrUsageXTilt [] = "X Tilt"; +const char pstrUsageYTilt [] = "Y Tilt"; +const char pstrUsageAzimuth [] = "Azimuth"; +const char pstrUsageAltitude [] = "Altitude"; +const char pstrUsageTwist [] = "Twist"; +const char pstrUsageTipSwitch [] = "Tip Sw"; +const char pstrUsageSecondaryTipSwitch [] = "Scnd Tip Sw"; +const char pstrUsageBarrelSwitch [] = "Brl Sw"; +const char pstrUsageEraser [] = "Eraser"; +const char pstrUsageTabletPick [] = "Tbl Pick"; + +// Alphanumeric Display Page +const char pstrUsageAlphanumericDisplay [] = "Alphanum Disp"; +const char pstrUsageBitmappedDisplay [] = "Bmp Disp"; +const char pstrUsageDisplayAttributesReport [] = "Disp Attr Rpt"; +const char pstrUsageASCIICharacterSet [] = "ASCII chset"; +const char pstrUsageDataReadBack [] = "Data Rd Back"; +const char pstrUsageFontReadBack [] = "Fnt Rd Back"; +const char pstrUsageDisplayControlReport [] = "Disp Ctrl Rpt"; +const char pstrUsageClearDisplay [] = "Clr Disp"; +//const char pstrUsageDisplayEnable [] = "Disp Enbl"; +const char pstrUsageScreenSaverDelay [] = "Scr Sav Delay"; +const char pstrUsageScreenSaverEnable [] = "Scr Sav Enbl"; +const char pstrUsageVerticalScroll [] = "V Scroll"; +const char pstrUsageHorizontalScroll [] = "H Scroll"; +const char pstrUsageCharacterReport [] = "Char Rpt"; +const char pstrUsageDisplayData [] = "Disp Data"; +const char pstrUsageDisplayStatus [] = "Disp Stat"; +const char pstrUsageStatusNotReady [] = "Stat !Ready"; +const char pstrUsageStatusReady [] = "Stat Ready"; +const char pstrUsageErrorNotALoadableCharacter [] = "Err Not Ld Char"; +const char pstrUsageErrorFotDataCanNotBeRead [] = "Fnt Data Rd Err"; +const char pstrUsageCursorPositionReport [] = "Cur Pos Rpt"; +const char pstrUsageRow [] = "Row"; +const char pstrUsageColumn [] = "Col"; +const char pstrUsageRows [] = "Rows"; +const char pstrUsageColumns [] = "Cols"; +const char pstrUsageCursorPixelPosition [] = "Cur Pix Pos"; +const char pstrUsageCursorMode [] = "Cur Mode"; +const char pstrUsageCursorEnable [] = "Cur Enbl"; +const char pstrUsageCursorBlink [] = "Cur Blnk"; +const char pstrUsageFontReport [] = "Fnt Rpt"; +const char pstrUsageFontData [] = "Fnt Data"; +const char pstrUsageCharacterWidth [] = "Char Wdth"; +const char pstrUsageCharacterHeight [] = "Char Hght"; +const char pstrUsageCharacterSpacingHorizontal [] = "Char Space H"; +const char pstrUsageCharacterSpacingVertical [] = "Char Space V"; +const char pstrUsageUnicodeCharset [] = "Unicode Char"; +const char pstrUsageFont7Segment [] = "Fnt 7-seg"; +const char pstrUsage7SegmentDirectMap [] = "7-seg map"; +const char pstrUsageFont14Segment [] = "Fnt 14-seg"; +const char pstrUsage14SegmentDirectMap [] = "14-seg map"; +const char pstrUsageDisplayBrightness [] = "Disp Bright"; +const char pstrUsageDisplayContrast [] = "Disp Cntrst"; +const char pstrUsageCharacterAttribute [] = "Char Attr"; +const char pstrUsageAttributeReadback [] = "Attr Readbk"; +const char pstrUsageAttributeData [] = "Attr Data"; +const char pstrUsageCharAttributeEnhance [] = "Char Attr Enh"; +const char pstrUsageCharAttributeUnderline [] = "Char Attr Undl"; +const char pstrUsageCharAttributeBlink [] = "Char Attr Blnk"; +const char pstrUsageBitmapSizeX [] = "Bmp Size X"; +const char pstrUsageBitmapSizeY [] = "Bmp Size Y"; +const char pstrUsageBitDepthFormat [] = "Bit Dpth Fmt"; +const char pstrUsageDisplayOrientation [] = "Disp Ornt"; +const char pstrUsagePaletteReport [] = "Pal Rpt"; +const char pstrUsagePaletteDataSize [] = "Pal Data Size"; +const char pstrUsagePaletteDataOffset [] = "Pal Data Off"; +const char pstrUsagePaletteData [] = "Pal Data"; +const char pstrUsageBlitReport [] = "Blit Rpt"; +const char pstrUsageBlitRectangleX1 [] = "Blit Rect X1"; +const char pstrUsageBlitRectangleY1 [] = "Blit Rect Y1"; +const char pstrUsageBlitRectangleX2 [] = "Blit Rect X2"; +const char pstrUsageBlitRectangleY2 [] = "Blit Rect Y2"; +const char pstrUsageBlitData [] = "Blit Data"; +const char pstrUsageSoftButton [] = "Soft Btn"; +const char pstrUsageSoftButtonID [] = "Soft Btn ID"; +const char pstrUsageSoftButtonSide [] = "Soft Btn Side"; +const char pstrUsageSoftButtonOffset1 [] = "Soft Btn Off1"; +const char pstrUsageSoftButtonOffset2 [] = "Soft Btn Off2"; +const char pstrUsageSoftButtonReport [] = "Soft Btn Rpt"; + +// Medical Instrument Page +const char pstrUsageMedicalUltrasound [] = "Med Ultrasnd"; +const char pstrUsageVCRAcquisition [] = "VCR/Acq"; +const char pstrUsageFreezeThaw [] = "Freeze"; +const char pstrUsageClipStore [] = "Clip Store"; +const char pstrUsageUpdate [] = "Update"; +const char pstrUsageNext [] = "Next"; +const char pstrUsageSave [] = "Save"; +const char pstrUsagePrint [] = "Print"; +const char pstrUsageMicrophoneEnable [] = "Mic Enbl"; +const char pstrUsageCine [] = "Cine"; +const char pstrUsageTransmitPower [] = "Trans Pwr"; +//const char pstrUsageVolume [] = "Vol"; +const char pstrUsageFocus [] = "Focus"; +const char pstrUsageDepth [] = "Depth"; +const char pstrUsageSoftStepPrimary [] = "Soft Stp-Pri"; +const char pstrUsageSoftStepSecondary [] = "Soft Stp-Sec"; +const char pstrUsageDepthGainCompensation [] = "Dpth Gain Comp"; +const char pstrUsageZoomSelect [] = "Zoom Sel"; +const char pstrUsageZoomAdjust [] = "Zoom Adj"; +const char pstrUsageSpectralDopplerModeSelect [] = "Spec Dop Mode Sel"; +const char pstrUsageSpectralDopplerModeAdjust [] = "Spec Dop Mode Adj"; +const char pstrUsageColorDopplerModeSelect [] = "Color Dop Mode Sel"; +const char pstrUsageColorDopplerModeAdjust [] = "Color Dop Mode Adj"; +const char pstrUsageMotionModeSelect [] = "Motion Mode Sel"; +const char pstrUsageMotionModeAdjust [] = "Motion Mode Adj"; +const char pstrUsage2DModeSelect [] = "2D Mode Sel"; +const char pstrUsage2DModeAdjust [] = "2D Mode Adj"; +const char pstrUsageSoftControlSelect [] = "Soft Ctrl Sel"; +const char pstrUsageSoftControlAdjust [] = "Soft Ctrl Adj"; + +//extern const char *usagePageTitles0[15]; +//const char *usagePageTitles1[]; +//const char *genDesktopTitles0[]; +//const char *genDesktopTitles1[]; +//const char *genDesktopTitles2[]; +//const char *genDesktopTitles3[]; +//const char *genDesktopTitles4[]; +//const char *simuTitles0[]; +//const char *simuTitles1[]; +//const char *simuTitles2[]; +//const char *vrTitles0[]; +//const char *vrTitles1[]; +//const char *sportsCtrlTitles0[]; +//const char *sportsCtrlTitles1[]; +//const char *sportsCtrlTitles2[]; +//const char *gameTitles0[]; +//const char *gameTitles1[]; +//const char *genDevCtrlTitles[]; +//const char *ledTitles[]; +//const char *telTitles0[]; +//const char *telTitles1[]; +//const char *telTitles2[]; +//const char *telTitles3[]; +//const char *telTitles4[]; +//const char *telTitles5[]; +//const char *consTitles0[]; +//const char *consTitles1[]; +//const char *consTitles2[]; +//const char *consTitles3[]; +//const char *consTitles4[]; +//const char *consTitles5[]; +//const char *consTitles6[]; +//const char *consTitles7[]; +//const char *consTitles8[]; +//const char *consTitles9[]; +//const char *consTitlesA[]; +//const char *consTitlesB[]; +//const char *consTitlesC[]; +//const char *consTitlesD[]; +//const char *consTitlesE[]; +//const char *digitTitles0[]; +//const char *digitTitles1[]; +//const char *digitTitles2[]; +//const char *aplphanumTitles0[]; +//const char *aplphanumTitles1[]; +//const char *aplphanumTitles2[]; +//const char *medInstrTitles0[]; +//const char *medInstrTitles1[]; +//const char *medInstrTitles2[]; +//const char *medInstrTitles3[]; +//const char *medInstrTitles4[]; + +#endif /* HIDUSAGESTR_H_INCLUDED */ diff --git a/hardware/arduino/sam/system/USBHost/parsetools.cpp b/hardware/arduino/sam/system/USBHost/parsetools.cpp new file mode 100644 index 000000000..3682d3e3b --- /dev/null +++ b/hardware/arduino/sam/system/USBHost/parsetools.cpp @@ -0,0 +1,73 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com +*/ + +#include "parsetools.h" + +bool MultiByteValueParser::Parse(uint8_t **pp, uint32_t *pcntdn) +{ + if (!pBuf) + { + //Notify(PSTR("Buffer pointer is NULL!\r\n")); + return false; + } + for (; countDown && (*pcntdn); countDown--, (*pcntdn)--, (*pp)++) + pBuf[valueSize-countDown] = (**pp); + + if (countDown) + return false; + + countDown = valueSize; + return true; +} + +bool PTPListParser::Parse(uint8_t **pp, uint32_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me) +{ + switch (nStage) + { + case 0: + pBuf->valueSize = lenSize; + theParser.Initialize(pBuf); + nStage = 1; + + case 1: + if (!theParser.Parse(pp, pcntdn)) + return false; + + arLen = 0; + arLen = (pBuf->valueSize >= 4) ? *((uint32_t*)pBuf->pValue) : (uint32_t)(*((uint16_t*)pBuf->pValue)); + arLenCntdn = arLen; + nStage = 2; + + case 2: + pBuf->valueSize = valSize; + theParser.Initialize(pBuf); + nStage = 3; + + case 3: + for (; arLenCntdn; arLenCntdn--) + { + if (!theParser.Parse(pp, pcntdn)) + return false; + + if (pf) + pf(pBuf, (arLen - arLenCntdn), me); + } + + nStage = 0; + } + return true; +} diff --git a/hardware/arduino/sam/system/USBHost/parsetools.h b/hardware/arduino/sam/system/USBHost/parsetools.h new file mode 100644 index 000000000..bb8e2ce3f --- /dev/null +++ b/hardware/arduino/sam/system/USBHost/parsetools.h @@ -0,0 +1,143 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com +*/ + +#ifndef PARSETOOLS_H_INCLUDED +#define PARSETOOLS_H_INCLUDED + +#include +#include "Arduino.h" + +struct MultiValueBuffer +{ + uint8_t valueSize; + void *pValue; +}; + +class MultiByteValueParser +{ + uint8_t *pBuf; + uint32_t countDown; + uint32_t valueSize; + +public: + MultiByteValueParser() : pBuf(NULL), countDown(0), valueSize(0) {}; + + const uint8_t* GetBuffer() { return pBuf; }; + + void Initialize(MultiValueBuffer * const pbuf) + { + pBuf = (uint8_t*)pbuf->pValue; + countDown = valueSize = pbuf->valueSize; + }; + + bool Parse(uint8_t **pp, uint32_t *pcntdn); +}; + +class ByteSkipper +{ + uint8_t *pBuf; + uint32_t nStage; + uint32_t countDown; + +public: + ByteSkipper() : pBuf(NULL), nStage(0), countDown(0) {}; + + void Initialize(MultiValueBuffer *pbuf) + { + pBuf = (uint8_t*)pbuf->pValue; + countDown = 0; + }; + + bool Skip(uint8_t **pp, uint32_t *pcntdn, uint32_t bytes_to_skip) + { + switch (nStage) + { + case 0: + countDown = bytes_to_skip; + nStage ++; + case 1: + for (; countDown && (*pcntdn); countDown--, (*pp)++, (*pcntdn)--); + + if (!countDown) + nStage = 0; + }; + return (!countDown); + }; +}; + +// Pointer to a callback function triggered for each element of PTP array when used with PTPArrayParser +typedef void (*PTP_ARRAY_EL_FUNC)(const MultiValueBuffer * const p, uint32_t count, const void *me); + +class PTPListParser +{ +public: + enum ParseMode { modeArray, modeRange/*, modeEnum*/ }; + +private: + uint32_t nStage; + uint32_t enStage; + + uint32_t arLen; + uint32_t arLenCntdn; + + uint32_t lenSize; // size of the array length field in bytes + uint32_t valSize; // size of the array element in bytes + + MultiValueBuffer *pBuf; + + // The only parser for both size and array element parsing + MultiByteValueParser theParser; + + uint32_t /*ParseMode*/ prsMode; + +public: + PTPListParser() : + nStage(0), + enStage(0), + arLen(0), + arLenCntdn(0), + lenSize(0), + valSize(0), + pBuf(NULL), + prsMode(modeArray) + {}; + + void Initialize(const uint32_t len_size, const uint32_t val_size, MultiValueBuffer * const p, const uint32_t mode = modeArray) + { + pBuf = p; + lenSize = len_size; + valSize = val_size; + prsMode = mode; + + if (prsMode == modeRange) + { + arLenCntdn = arLen = 3; + nStage = 2; + } + else + { + arLenCntdn = arLen = 0; + nStage = 0; + } + enStage = 0; + theParser.Initialize(p); + }; + + bool Parse(uint8_t **pp, uint32_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me = NULL); +}; + +#endif /* PARSETOOLS_H_INCLUDED */ diff --git a/hardware/arduino/sam/system/USBHost/ch9.h b/hardware/arduino/sam/system/USBHost/usb_ch9.h similarity index 73% rename from hardware/arduino/sam/system/USBHost/ch9.h rename to hardware/arduino/sam/system/USBHost/usb_ch9.h index d2bcdd734..86eb1f954 100644 --- a/hardware/arduino/sam/system/USBHost/ch9.h +++ b/hardware/arduino/sam/system/USBHost/usb_ch9.h @@ -1,174 +1,175 @@ -/* Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com */ -/* USB chapter 9 structures */ -#ifndef _ch9_h_ -#define _ch9_h_ - -#include - -/* Misc.USB constants */ -#define DEV_DESCR_LEN 18 //device descriptor length -#define CONF_DESCR_LEN 9 //configuration descriptor length -#define INTR_DESCR_LEN 9 //interface descriptor length -#define EP_DESCR_LEN 7 //endpoint descriptor length - -/* Standard Device Requests */ - -#define USB_REQUEST_GET_STATUS 0 // Standard Device Request - GET STATUS -#define USB_REQUEST_CLEAR_FEATURE 1 // Standard Device Request - CLEAR FEATURE -#define USB_REQUEST_SET_FEATURE 3 // Standard Device Request - SET FEATURE -#define USB_REQUEST_SET_ADDRESS 5 // Standard Device Request - SET ADDRESS -#define USB_REQUEST_GET_DESCRIPTOR 6 // Standard Device Request - GET DESCRIPTOR -#define USB_REQUEST_SET_DESCRIPTOR 7 // Standard Device Request - SET DESCRIPTOR -#define USB_REQUEST_GET_CONFIGURATION 8 // Standard Device Request - GET CONFIGURATION -#define USB_REQUEST_SET_CONFIGURATION 9 // Standard Device Request - SET CONFIGURATION -#define USB_REQUEST_GET_INTERFACE 10 // Standard Device Request - GET INTERFACE -#define USB_REQUEST_SET_INTERFACE 11 // Standard Device Request - SET INTERFACE -#define USB_REQUEST_SYNCH_FRAME 12 // Standard Device Request - SYNCH FRAME - -#define USB_FEATURE_ENDPOINT_HALT 0 // CLEAR/SET FEATURE - Endpoint Halt -#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // CLEAR/SET FEATURE - Device remote wake-up -#define USB_FEATURE_TEST_MODE 2 // CLEAR/SET FEATURE - Test mode - -/* Setup Data Constants */ - -#define USB_SETUP_HOST_TO_DEVICE 0x00 // Device Request bmRequestType transfer direction - host to device transfer -#define USB_SETUP_DEVICE_TO_HOST 0x80 // Device Request bmRequestType transfer direction - device to host transfer -#define USB_SETUP_TYPE_STANDARD 0x00 // Device Request bmRequestType type - standard -#define USB_SETUP_TYPE_CLASS 0x20 // Device Request bmRequestType type - class -#define USB_SETUP_TYPE_VENDOR 0x40 // Device Request bmRequestType type - vendor -#define USB_SETUP_RECIPIENT_DEVICE 0x00 // Device Request bmRequestType recipient - device -#define USB_SETUP_RECIPIENT_INTERFACE 0x01 // Device Request bmRequestType recipient - interface -#define USB_SETUP_RECIPIENT_ENDPOINT 0x02 // Device Request bmRequestType recipient - endpoint -#define USB_SETUP_RECIPIENT_OTHER 0x03 // Device Request bmRequestType recipient - other - -/* USB descriptors */ - -#define USB_DESCRIPTOR_DEVICE 0x01 // bDescriptorType for a Device Descriptor. -#define USB_DESCRIPTOR_CONFIGURATION 0x02 // bDescriptorType for a Configuration Descriptor. -#define USB_DESCRIPTOR_STRING 0x03 // bDescriptorType for a String Descriptor. -#define USB_DESCRIPTOR_INTERFACE 0x04 // bDescriptorType for an Interface Descriptor. -#define USB_DESCRIPTOR_ENDPOINT 0x05 // bDescriptorType for an Endpoint Descriptor. -#define USB_DESCRIPTOR_DEVICE_QUALIFIER 0x06 // bDescriptorType for a Device Qualifier. -#define USB_DESCRIPTOR_OTHER_SPEED 0x07 // bDescriptorType for a Other Speed Configuration. -#define USB_DESCRIPTOR_INTERFACE_POWER 0x08 // bDescriptorType for Interface Power. -#define USB_DESCRIPTOR_OTG 0x09 // bDescriptorType for an OTG Descriptor. - -/* OTG SET FEATURE Constants */ -#define OTG_FEATURE_B_HNP_ENABLE 3 // SET FEATURE OTG - Enable B device to perform HNP -#define OTG_FEATURE_A_HNP_SUPPORT 4 // SET FEATURE OTG - A device supports HNP -#define OTG_FEATURE_A_ALT_HNP_SUPPORT 5 // SET FEATURE OTG - Another port on the A device supports HNP - -/* USB Endpoint Transfer Types */ -#define USB_TRANSFER_TYPE_CONTROL 0x00 // Endpoint is a control endpoint. -#define USB_TRANSFER_TYPE_ISOCHRONOUS 0x01 // Endpoint is an isochronous endpoint. -#define USB_TRANSFER_TYPE_BULK 0x02 // Endpoint is a bulk endpoint. -#define USB_TRANSFER_TYPE_INTERRUPT 0x03 // Endpoint is an interrupt endpoint. -#define bmUSB_TRANSFER_TYPE 0x03 // bit mask to separate transfer type from ISO attributes - - -/* Standard Feature Selectors for CLEAR_FEATURE Requests */ -#define USB_FEATURE_ENDPOINT_STALL 0 // Endpoint recipient -#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // Device recipient -#define USB_FEATURE_TEST_MODE 2 // Device recipient - -/* HID constants. Not part of chapter 9 */ -/* Class-Specific Requests */ -#define HID_REQUEST_GET_REPORT 0x01 -#define HID_REQUEST_GET_IDLE 0x02 -#define HID_REQUEST_GET_PROTOCOL 0x03 -#define HID_REQUEST_SET_REPORT 0x09 -#define HID_REQUEST_SET_IDLE 0x0A -#define HID_REQUEST_SET_PROTOCOL 0x0B - -/* Class Descriptor Types */ -#define HID_DESCRIPTOR_HID 0x21 -#define HID_DESCRIPTOR_REPORT 0x22 -#define HID_DESRIPTOR_PHY 0x23 - -/* Protocol Selection */ -#define BOOT_PROTOCOL 0x00 -#define RPT_PROTOCOL 0x01 -/* HID Interface Class Code */ -#define HID_INTF 0x03 -/* HID Interface Class SubClass Codes */ -#define BOOT_INTF_SUBCLASS 0x01 -/* HID Interface Class Protocol Codes */ -#define HID_PROTOCOL_NONE 0x00 -#define HID_PROTOCOL_KEYBOARD 0x01 -#define HID_PROTOCOL_MOUSE 0x02 - - -_Pragma("pack(1)") - -/* descriptor data structures */ - -/* Device descriptor structure */ -typedef struct { - uint8_t bLength; // Length of this descriptor. - uint8_t bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE). - uint16_t bcdUSB; // USB Spec Release Number (BCD). - uint8_t bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. - uint8_t bDeviceSubClass; // Subclass code (assigned by the USB-IF). - uint8_t bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. - uint8_t bMaxPacketSize0; // Maximum packet size for endpoint 0. - uint16_t idVendor; // Vendor ID (assigned by the USB-IF). - uint16_t idProduct; // Product ID (assigned by the manufacturer). - uint16_t bcdDevice; // Device release number (BCD). - uint8_t iManufacturer; // Index of String Descriptor describing the manufacturer. - uint8_t iProduct; // Index of String Descriptor describing the product. - uint8_t iSerialNumber; // Index of String Descriptor with the device's serial number. - uint8_t bNumConfigurations; // Number of possible configurations. -} USB_DEVICE_DESCRIPTOR; - -/* Configuration descriptor structure */ -typedef struct -{ - uint8_t bLength; // Length of this descriptor. - uint8_t bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION). - uint16_t wTotalLength; // Total length of all descriptors for this configuration. - uint8_t bNumInterfaces; // Number of interfaces in this configuration. - uint8_t bConfigurationValue; // Value of this configuration (1 based). - uint8_t iConfiguration; // Index of String Descriptor describing the configuration. - uint8_t bmAttributes; // Configuration characteristics. - uint8_t bMaxPower; // Maximum power consumed by this configuration. -} USB_CONFIGURATION_DESCRIPTOR; - -/* Interface descriptor structure */ -typedef struct -{ - uint8_t bLength; // Length of this descriptor. - uint8_t bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE). - uint8_t bInterfaceNumber; // Number of this interface (0 based). - uint8_t bAlternateSetting; // Value of this alternate interface setting. - uint8_t bNumEndpoints; // Number of endpoints in this interface. - uint8_t bInterfaceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. - uint8_t bInterfaceSubClass; // Subclass code (assigned by the USB-IF). - uint8_t bInterfaceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. - uint8_t iInterface; // Index of String Descriptor describing the interface. -} USB_INTERFACE_DESCRIPTOR; - -/* Endpoint descriptor structure */ -typedef struct -{ - uint8_t bLength; // Length of this descriptor. - uint8_t bDescriptorType; // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT). - uint8_t bEndpointAddress; // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN). - uint8_t bmAttributes; // Endpoint transfer type. - uint16_t wMaxPacketSize; // Maximum packet size. - uint8_t bInterval; // Polling interval in frames. -} USB_ENDPOINT_DESCRIPTOR; - -/* HID descriptor */ -typedef struct { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t bcdHID; - uint8_t bCountryCode; - uint8_t bNumDescriptors; - uint8_t bDescrType; - uint16_t wDescriptorLength; -} USB_HID_DESCRIPTOR; - -_Pragma("pack()") - -#endif // _ch9_h_ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com +*/ +/* USB chapter 9 structures */ + +#ifndef USB_CH9_H_INCLUDED +#define USB_CH9_H_INCLUDED + +#include + +/* Misc.USB constants */ +#define DEV_DESCR_LEN 18 //device descriptor length +#define CONF_DESCR_LEN 9 //configuration descriptor length +#define INTR_DESCR_LEN 9 //interface descriptor length +#define EP_DESCR_LEN 7 //endpoint descriptor length + +/* Standard Device Requests */ + +#define USB_REQUEST_GET_STATUS 0 // Standard Device Request - GET STATUS +#define USB_REQUEST_CLEAR_FEATURE 1 // Standard Device Request - CLEAR FEATURE +#define USB_REQUEST_SET_FEATURE 3 // Standard Device Request - SET FEATURE +#define USB_REQUEST_SET_ADDRESS 5 // Standard Device Request - SET ADDRESS +#define USB_REQUEST_GET_DESCRIPTOR 6 // Standard Device Request - GET DESCRIPTOR +#define USB_REQUEST_SET_DESCRIPTOR 7 // Standard Device Request - SET DESCRIPTOR +#define USB_REQUEST_GET_CONFIGURATION 8 // Standard Device Request - GET CONFIGURATION +#define USB_REQUEST_SET_CONFIGURATION 9 // Standard Device Request - SET CONFIGURATION +#define USB_REQUEST_GET_INTERFACE 10 // Standard Device Request - GET INTERFACE +#define USB_REQUEST_SET_INTERFACE 11 // Standard Device Request - SET INTERFACE +#define USB_REQUEST_SYNCH_FRAME 12 // Standard Device Request - SYNCH FRAME + +#define USB_FEATURE_ENDPOINT_HALT 0 // CLEAR/SET FEATURE - Endpoint Halt +#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // CLEAR/SET FEATURE - Device remote wake-up +#define USB_FEATURE_TEST_MODE 2 // CLEAR/SET FEATURE - Test mode + +/* Setup Data Constants */ + +#define USB_SETUP_HOST_TO_DEVICE 0x00 // Device Request bmRequestType transfer direction - host to device transfer +#define USB_SETUP_DEVICE_TO_HOST 0x80 // Device Request bmRequestType transfer direction - device to host transfer +#define USB_SETUP_TYPE_STANDARD 0x00 // Device Request bmRequestType type - standard +#define USB_SETUP_TYPE_CLASS 0x20 // Device Request bmRequestType type - class +#define USB_SETUP_TYPE_VENDOR 0x40 // Device Request bmRequestType type - vendor +#define USB_SETUP_RECIPIENT_DEVICE 0x00 // Device Request bmRequestType recipient - device +#define USB_SETUP_RECIPIENT_INTERFACE 0x01 // Device Request bmRequestType recipient - interface +#define USB_SETUP_RECIPIENT_ENDPOINT 0x02 // Device Request bmRequestType recipient - endpoint +#define USB_SETUP_RECIPIENT_OTHER 0x03 // Device Request bmRequestType recipient - other + +/* USB descriptors */ + +#define USB_DESCRIPTOR_DEVICE 0x01 // bDescriptorType for a Device Descriptor. +#define USB_DESCRIPTOR_CONFIGURATION 0x02 // bDescriptorType for a Configuration Descriptor. +#define USB_DESCRIPTOR_STRING 0x03 // bDescriptorType for a String Descriptor. +#define USB_DESCRIPTOR_INTERFACE 0x04 // bDescriptorType for an Interface Descriptor. +#define USB_DESCRIPTOR_ENDPOINT 0x05 // bDescriptorType for an Endpoint Descriptor. +#define USB_DESCRIPTOR_DEVICE_QUALIFIER 0x06 // bDescriptorType for a Device Qualifier. +#define USB_DESCRIPTOR_OTHER_SPEED 0x07 // bDescriptorType for a Other Speed Configuration. +#define USB_DESCRIPTOR_INTERFACE_POWER 0x08 // bDescriptorType for Interface Power. +#define USB_DESCRIPTOR_OTG 0x09 // bDescriptorType for an OTG Descriptor. + +#define HID_DESCRIPTOR_HID 0x21 + + + +/* OTG SET FEATURE Constants */ +#define OTG_FEATURE_B_HNP_ENABLE 3 // SET FEATURE OTG - Enable B device to perform HNP +#define OTG_FEATURE_A_HNP_SUPPORT 4 // SET FEATURE OTG - A device supports HNP +#define OTG_FEATURE_A_ALT_HNP_SUPPORT 5 // SET FEATURE OTG - Another port on the A device supports HNP + +/* USB Endpoint Transfer Types */ +#define USB_TRANSFER_TYPE_CONTROL 0x00 // Endpoint is a control endpoint. +#define USB_TRANSFER_TYPE_ISOCHRONOUS 0x01 // Endpoint is an isochronous endpoint. +#define USB_TRANSFER_TYPE_BULK 0x02 // Endpoint is a bulk endpoint. +#define USB_TRANSFER_TYPE_INTERRUPT 0x03 // Endpoint is an interrupt endpoint. +#define bmUSB_TRANSFER_TYPE 0x03 // bit mask to separate transfer type from ISO attributes + + +/* Standard Feature Selectors for CLEAR_FEATURE Requests */ +#define USB_FEATURE_ENDPOINT_STALL 0 // Endpoint recipient +#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // Device recipient +#define USB_FEATURE_TEST_MODE 2 // Device recipient +_Pragma("pack(1)") + +/* descriptor data structures */ + +/* Device descriptor structure */ +typedef struct +{ + uint8_t bLength; // Length of this descriptor. + uint8_t bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE). + uint16_t bcdUSB; // USB Spec Release Number (BCD). + uint8_t bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. + uint8_t bDeviceSubClass; // Subclass code (assigned by the USB-IF). + uint8_t bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. + uint8_t bMaxPacketSize0; // Maximum packet size for endpoint 0. + uint16_t idVendor; // Vendor ID (assigned by the USB-IF). + uint16_t idProduct; // Product ID (assigned by the manufacturer). + uint16_t bcdDevice; // Device release number (BCD). + uint8_t iManufacturer; // Index of String Descriptor describing the manufacturer. + uint8_t iProduct; // Index of String Descriptor describing the product. + uint8_t iSerialNumber; // Index of String Descriptor with the device's serial number. + uint8_t bNumConfigurations; // Number of possible configurations. +} USB_DEVICE_DESCRIPTOR; + +/* Configuration descriptor structure */ +typedef struct +{ + uint8_t bLength; // Length of this descriptor. + uint8_t bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION). + uint16_t wTotalLength; // Total length of all descriptors for this configuration. + uint8_t bNumInterfaces; // Number of interfaces in this configuration. + uint8_t bConfigurationValue; // Value of this configuration (1 based). + uint8_t iConfiguration; // Index of String Descriptor describing the configuration. + uint8_t bmAttributes; // Configuration characteristics. + uint8_t bMaxPower; // Maximum power consumed by this configuration. +} USB_CONFIGURATION_DESCRIPTOR; + +/* Interface descriptor structure */ +typedef struct +{ + uint8_t bLength; // Length of this descriptor. + uint8_t bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE). + uint8_t bInterfaceNumber; // Number of this interface (0 based). + uint8_t bAlternateSetting; // Value of this alternate interface setting. + uint8_t bNumEndpoints; // Number of endpoints in this interface. + uint8_t bInterfaceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. + uint8_t bInterfaceSubClass; // Subclass code (assigned by the USB-IF). + uint8_t bInterfaceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. + uint8_t iInterface; // Index of String Descriptor describing the interface. +} USB_INTERFACE_DESCRIPTOR; + +/* Endpoint descriptor structure */ +typedef struct +{ + uint8_t bLength; // Length of this descriptor. + uint8_t bDescriptorType; // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT). + uint8_t bEndpointAddress; // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN). + uint8_t bmAttributes; // Endpoint transfer type. + uint16_t wMaxPacketSize; // Maximum packet size. + uint8_t bInterval; // Polling interval in frames. +} USB_ENDPOINT_DESCRIPTOR; + + +/* HID descriptor */ +typedef struct +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdHID; // HID class specification release + uint8_t bCountryCode; + uint8_t bNumDescriptors; // Number of additional class specific descriptors + uint8_t bDescrType; // Type of class descriptor + uint16_t wDescriptorLength; // Total size of the Report descriptor +} USB_HID_DESCRIPTOR; + +typedef struct +{ + uint8_t bDescrType; // Type of class descriptor + uint16_t wDescriptorLength; // Total size of the Report descriptor +} HID_CLASS_DESCRIPTOR_LEN_AND_TYPE; + +_Pragma("pack()") + +#endif /* USB_CH9_H_INCLUDED */ diff --git a/hardware/arduino/sam/system/libsam/include/USB_host.h b/hardware/arduino/sam/system/libsam/include/USB_host.h index 4262f7aa6..7dc822508 100644 --- a/hardware/arduino/sam/system/libsam/include/USB_host.h +++ b/hardware/arduino/sam/system/libsam/include/USB_host.h @@ -50,6 +50,7 @@ extern void UHD_Init(void); extern void UHD_BusReset(void); extern uhd_vbus_state_t UHD_GetVBUSState(void); extern uint32_t UHD_EP0_Alloc(uint32_t ul_add, uint32_t ul_ep_size); +extern uint32_t UHD_EP_Alloc(uint32_t ul_pipe, uint32_t ul_addr, uint32_t ul_interval, uint32_t ul_type, uint32_t ul_dir, uint32_t ul_maxsize, uint32_t ul_bank); extern void UHD_EP_Free(uint32_t add, uint32_t endp); extern uint32_t UHD_EP_Read(uint32_t ul_ep, uint32_t ul_size, uint8_t* data); extern void UHD_EP_Write(uint32_t ul_ep, uint32_t ul_size, uint8_t* data); diff --git a/hardware/arduino/sam/system/libsam/include/uotghs_host.h b/hardware/arduino/sam/system/libsam/include/uotghs_host.h index d634f124f..93ef2974f 100644 --- a/hardware/arduino/sam/system/libsam/include/uotghs_host.h +++ b/hardware/arduino/sam/system/libsam/include/uotghs_host.h @@ -244,14 +244,14 @@ # define uhd_enable_ping(p) (Set_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PINGEN)) //#endif #define uhd_configure_pipe(p, freq, ep_num, type, token, size, bank, bank_switch) \ - (Set_bits(UOTGHS->UOTGHS_HSTPIPCFG[p],\ + (UOTGHS->UOTGHS_HSTPIPCFG[p] = \ (bank)|\ ((uhd_format_pipe_size(size)<UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_CFGOK)) //! @} diff --git a/hardware/arduino/sam/system/libsam/source/uotghs_host.c b/hardware/arduino/sam/system/libsam/source/uotghs_host.c index ae5cdf176..dd23a792f 100644 --- a/hardware/arduino/sam/system/libsam/source/uotghs_host.c +++ b/hardware/arduino/sam/system/libsam/source/uotghs_host.c @@ -32,7 +32,7 @@ static void UHD_ISR(void) { // Manage dis/connection event if (Is_uhd_disconnection() && Is_uhd_disconnection_int_enabled()) { - printf(">>> UHD_ISR : Disconnection INT\r\n"); + TRACE_UOTGHS(printf(">>> UHD_ISR : Disconnection INT\r\n");) uhd_ack_disconnection(); uhd_disable_disconnection_int(); // Stop reset signal, in case of disconnection during reset @@ -48,7 +48,7 @@ static void UHD_ISR(void) return; } if (Is_uhd_connection() && Is_uhd_connection_int_enabled()) { - printf(">>> UHD_ISR : Connection INT\r\n"); + TRACE_UOTGHS(printf(">>> UHD_ISR : Connection INT\r\n");) uhd_ack_connection(); uhd_disable_connection_int(); uhd_ack_disconnection(); @@ -61,7 +61,7 @@ static void UHD_ISR(void) // Manage Vbus error if (Is_uhd_vbus_error_interrupt()) { - printf(">>> UHD_ISR : VBUS error INT\r\n"); + TRACE_UOTGHS(printf(">>> UHD_ISR : VBUS error INT\r\n");) uhd_ack_vbus_error_interrupt(); uhd_state = UHD_STATE_ERROR; return; @@ -78,23 +78,23 @@ static void UHD_ISR(void) otg_ack_vbus_transition(); if (Is_otg_vbus_high()) { - printf(">>> UHD_ISR : VBUS transition INT : UHD_STATE_DISCONNECT\r\n"); + TRACE_UOTGHS(printf(">>> UHD_ISR : VBUS transition INT : UHD_STATE_DISCONNECT\r\n");) uhd_state = UHD_STATE_DISCONNECTED; } else { - printf(">>> UHD_ISR : VBUS transition INT : UHD_STATE_NO_VBUS\r\n"); + TRACE_UOTGHS(printf(">>> UHD_ISR : VBUS transition INT : UHD_STATE_NO_VBUS\r\n");) otg_freeze_clock(); uhd_state = UHD_STATE_NO_VBUS; } - printf(">>> UHD_ISR : VBUS transition INT : done.\r\n"); + TRACE_UOTGHS(printf(">>> UHD_ISR : VBUS transition INT : done.\r\n");) return; } // Other errors if (Is_uhd_errors_interrupt()) { - printf(">>> UHD_ISR : Other error INT\r\n"); + TRACE_UOTGHS(printf(">>> UHD_ISR : Other error INT\r\n");) uhd_ack_errors_interrupt(); return; } @@ -247,10 +247,41 @@ uint32_t UHD_EP0_Alloc(uint32_t ul_add, uint32_t ul_ep_size) uhd_configure_address(0, ul_add); - // Always enable stall and error interrupts of control endpoint - /*uhd_enable_stall_interrupt(0); - uhd_enable_pipe_error_interrupt(0); - uhd_enable_pipe_interrupt(0);*/ + return 0; +} + +/** + * \brief Allocate FIFO for the specified pipe. + * + * \param ul_add Address of remote device for pipe 0. + * \param ul_ep_size Actual size of the FIFO in bytes. + * + * \retval 0 success. + * \retval 1 error. + */ +uint32_t UHD_EP_Alloc(uint32_t ul_pipe, uint32_t ul_addr, uint32_t ul_interval, uint32_t ul_type, uint32_t ul_dir, uint32_t ul_maxsize, uint32_t ul_bank) +{ + if (Is_uhd_pipe_enabled(ul_pipe)) + { + // Pipe is already allocated + return 0; + } + + uhd_enable_pipe(ul_pipe); + + uhd_configure_pipe(ul_pipe, ul_interval, ul_addr, ul_type, ul_dir, + ul_maxsize, ul_bank, UOTGHS_HSTPIPCFG_AUTOSW); + + uhd_allocate_memory(ul_pipe); + + if (!Is_uhd_pipe_configured(ul_pipe)) + { + uhd_disable_pipe(ul_pipe); + return 1; + } + + uhd_configure_address(ul_pipe, ul_addr); + return 0; } @@ -331,11 +362,12 @@ void UHD_EP_Send(uint32_t ul_ep, uint32_t ul_token_type) if (!Is_uhd_pipe_enabled(ul_ep)) { // Endpoint not valid - TRACE_UOTGHS(printf("/!\\ UHD_EP_Send : pipe is not enabled!\r\n");) + TRACE_UOTGHS(printf("/!\\ UHD_EP_Send : pipe %lu is not enabled!\r\n", ul_ep);) return; } - // Set token type + // Set token type for zero length packet + // When actually using the FIFO, pipe token MUST be configured first uhd_configure_pipe_token(ul_ep, ul_token_type); // Clear interrupt flags diff --git a/hardware/arduino/sam/variants/arduino_due_x/libsam_sam3x8e_gcc_rel.a b/hardware/arduino/sam/variants/arduino_due_x/libsam_sam3x8e_gcc_rel.a index f7503f1d87024856312cf2f97227eb88cd2fd709..dfca5a266e7cafba1ee74d2828eb21f423a9f195 100644 GIT binary patch delta 5049 zcmcgve^AuN6@UBv-oZgQIPQ+$7d#Fy_#?{wzDqQo94d+?L@?EfEodRZDI(&TsI56r z6O&3Dnq_h}qGOH8sNW<3!@2eKkhW<}IfEH3rdUchaUU`NTozhSCI=6&sC$+rgPf zR&m=xxoT2M&xT%?hE@$F*Lv(wUH#m~#vfN#&#G>0my9iH(v6U}hX~0prsEGG)x=lkXwNP80h#2LdzJ&5Yh+>}$2# zy?igY{(IZeoAQ7bZv*8(9K(Nh&Q_A4tF$M6}#J{$SXJtddH}qEK|qXI83YV74-R4;9HZ=fD*a?vZgl^;`F_^41vE;$r{l07*x6>q zjqE698(DC;xN}lp=%y;yuH0g%5i=SkRpy~$;t4r5x;E@h+R2f*;MB|Q}qO+27XkBs&jXP>g@vm!qZq4%> zo9mXW+7PH~rd=i)x{^*3q%%ji5j=WEdi_`?aniZR_~~QJiboO|9!ZWo=$%D$*`hi& zFK>0&qCKJq)#>$yo_vUWBI%BMRP^drBVBnyN7k^NPIqAKMP560LZ^Ni&qX@zKasEA zi!}pVSb7UJjx&w4B0MC@#s3ZJBru({CuGU^`8to1lWfD#fTUAzRske)Tb+n@BGS?> zDPQPN(O>7L(|<}j@;3cSdPLogA|u~TvrZ0(L`$_jb4W5>(ld#q)3x|D(ARt1+Ewzd zNsdl>KZmR&2^G?sC|anr`Jz!)1|{pH`FLY=9b^s4yR(mT|=OGH+nK z9H3an4#wR8_^9A|vt&6xC)kgllgH(Ag1A7ISIPRz8Giy`rHpHk2ibspU>qoBU~G>u z?E9u+Jd=DPT+b>`0Q;F)JK9qYB$WJ52ZLO(Nj4Oa`6k9I=u z;2C3F&wF>h7>Dd^qNPy}#zVzJIPL+;cspXAn$V*dxpQ1jbI-^r$%`o|Lt1f0BGlZM zM}O6Cq$f;o&=!YUy4+XG5^k30v=y^#bdC<}PLhf~RNPF5@qp#=RJ#vr_`8#8FCvH@ zj;rU3qW4e=idkWcK%^-bXA{9zEY<%mi_os^nGd6PFV^1Wa$vJemp=Yzhx|~8;)X$= zoav%oT)ZqLM>AjaVX^1>TP8&&?0!;3t_aG8Me*cwxxvFm=q^hn1uBJ!?pKq^7Ww{; zYUJvPCNrwR8!$MYP@bMlG4!zm4xnaB&f=d7Io+*O$p#^4DYumESzxI4m&EP=W5g7gRkD1LadE^~`H25K)-*GwpLNdH6s`p_`vaUU zpXJ76RoqC^JPzSrPUuwkn~xGbX%Oe5|6}54`l3r{tgu8im^I&6W-Q;c zz|$*^9tbRr6jYEA-}=H4-^MBal1PD096h#PRZtSi^C5v?X5SY66-Uo)cxt3&Zb>9x z_tXej8Ta(E2p(jSgl^qT;t;ZD=B+d@D=V#@S5aMA*H~+Q%-po5sm@&3u(8`}C3e#N zw2iz*5(W$aW!TFU`kS3BNXx`ypkWXx4oQWiq1K&-&{78}N-(3?hfOA$^~*`2gAP)W zP&3{m^lt~rCx>YNPD9q4s1x0ISiw?{N-SxZLgh{}NnMIp+W;MYFC&%Bn2p1V5eI8w z-P1lrq?B}^WHFcgV}j%gN_9*O4Ip0=(j}0|>MAty6FPj-K>J?OX`ApVZN_*!jB3TS^c3sFx8&8MPq4bcA6$c%>kVO+O zCdyAyBX6w@{nbLUGSVToOF9>}h34dwEV{o{pT?%c3UiC#E?^cRv<}6oF>hV;Fgvv3 zF>>npL#Uv~cQ0E~)@y*{6!=ocEgb9Mwv6!~KkBDKA}TX|AIEygkTHv!9us`NjN3U* z53PBe{0sm4RRvWj5Q=e47@rD|By%0(({N|XI8){(nVV%^Aak~+0xo`-aRqmbDRWfi?XzTDFLVCXLH+*# DfUJbP delta 4629 zcmcgv4Qx}_6+ZXbCb1hE$3L-29OC>?!cUF;Y(G08ThpX#>5>gnf)=f;N!GN@x{UB+ zHrfrGFt(xw5bcfnvMp$oQ7NEw8$70jLBsE=B4|fwgy^(RY+`CFjV@V}DMM}9xz{(* zGaZ5!byqp>-0z%o&$;LRoa=n@vGIdz#+|-oFcy!-qJDqS&zk=0_bcI`%*FmD3jmo5 zP*ipMwD2i_TT=3NjJ`mdU6%lEhq_wq~uME&h`S_NW&EXdb-pDaHo{KQwMiAKKZE(-o@?s{}Jy0 z9Rwp5FL1Io0LlK~b5Px97&PAjL0ovnUC=t!KrdMPe z(uNXy3|SA?S2uoTRr9yo9)Bo78#gr4lfD3MaV zmiS>pGE0zZ9rV6Up6oh;F8~T;A>B^LHhSDmLONypjsd_%|N2v>*03qlV9gW8R^)_c z4>)N@rlpy1X3Y@pK-(`j4uH23e5GzH|ptg zXAAPtYHcDBXkV0i!`L?z4wv!MAhX@3SzG#WiR!18sGe$D%C&1-tc3ol$zqVhAzYZb zwEmS!+PGu8micTJu})=*^$Dyj)9hEUr(cjOd4?{Lp_BflYj)~@@)R`hwnU~L_jUJ4lFZJc zlRo*(-BLKtw^ci@{?o|hy_<7UM&Iex^rQNBb!X`D%9q;=wD_pcxIEFmnikl+^uv7) zuGJnoZ@~HG58g}6^jm`k z#7Q^e*GhK{#^{wnyR{jkv1UUebZjt>%%sEL^O!esDGM@&s7oLh&0gi9Er(0d!+onf z+TO$SNWK12C{cZxP(nf7ky3*C!l20d)U! z3fzP|$pZ4g7$_|;%F`UjKJ6GU51%Nv!`bi&;5a{%qd$Eh>C68!!6Y|aEgU5T-@y1X zab?jVUx5bz_zED73p}8-kBPQ*=<1M`WIievM0&Ck_niI`|b&0j1K!{b6 z)AaI=EG>R2Ax)RUKD<`^nz;935C5hgiK7S#+3nND|4?dBXD=q1Cbk*;Ezl~?loKf= z)Bo7^)1tHOQT+dc&l{_}AB`l$JTE*dKWMp09cPK;Xn#JtMZD@M{G;JYQO;6{zI{ov zrOI3CS3uvpKli0@n2jHJ)JQH%dcij{$luZg4Hi;j)VUbwv5{xQTbuF`aF9%I%7RbA z7>SoDboYu<=b=o@2EfEl1>2&0$Q^ioK3OLvOKM7%^gI~7TvGGaq_5;cM#Tu@2PQh& zt44`*3j1$O!kp4$mH)cF#&{ufUi?^Q;X^>m4qWT}@YI;kkVo9LhSAjqXZ7hxh>jpt zk4lDAKNx+)U>Uiq#)c6_CVi3OQGyy@g!t{RT54c43Ax3sMWac{UhQoH6mmMordYuC z@VKS&tH=jd1&D*Rk`mW7m~iuXx~mMst{NBmjlT*LyVowCELuj!E7!~!uUtQ`x_Yw6 z4io)rjfJcyv2P{ob#M$5r&li>@2IMt^!t~NgUmR3!C)-#(`4Wui%3Ko_?k@oWS}EV zzE8}{8~{sDnWtWlkO$2@2-$+>sY{~>cO$Ii@Rw22ZoWLN^(ds6^wZ&Io$A*WVmH5s z8g{Sp)F%~EAk`Yw-zp@>eH=wB-5E%%ox=yCmW|53h)A#Ts@E0b`O*axo0;WQ!zbE~ z{X8Um#leWg=64lIKfD1IZOn1``>4@-uoN-Bhs^{t;_crv)KMJoxEJMIKP{*J**T6SC___L<9M5&q593_Zqp+f01cG< z&PmU2vRfk64`uv_elMl0&QNL~=P)1yY^r+Vh$t-ncImsa#Xy@yB>W*@h zFQG4CcZhW(^u+74JWiM?BBhuUas}