1
0
mirror of https://github.com/arduino/Arduino.git synced 2025-01-29 18:52:13 +01:00

[sam] USBHost HID Mouse example is working

This commit is contained in:
Thibault RICHARD 2012-06-12 14:43:52 +02:00
parent a7033f459e
commit c1aaef21e1
26 changed files with 3810 additions and 3251 deletions

View File

@ -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_

View File

@ -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 <stdio.h>
#include "descriptor_parser.h"
#include <hidboot.h>
#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 <avr/pgmspace.h>
#include <avrpins.h>
#include <max3421e.h>
#include <usbhost.h>
#include <usb_ch9.h>
#include <Usb.h>
#include <usbhub.h>
#include <avr/pgmspace.h>
#include <address.h>
#include <hidboot.h>
#include <printhex.h>
#include <message.h>
#include <hexdump.h>
#include <parsetools.h>
*/
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<HID_PROTOCOL_MOUSE> 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;
}
}
}

View File

@ -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 <stdio.h>
//#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:

View File

@ -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 <stdint.h>
#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<USB_NUMDEVICES> 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 */

View File

@ -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 <stdint.h>
/* 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 <const uint32_t MAX_DEVICES_ALLOWED>
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<MAX_DEVICES_ALLOWED; i++)
if (thePool[i].address != 0);
counter ++;
return counter;
};*/
};
#endif /* ADDRESS_H_INCLUDED */

View File

@ -0,0 +1,213 @@
/* 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 CONFDESCPARSER_H_INCLUDED
#define CONFDESCPARSER_H_INCLUDED
#include <stdint.h>
#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 <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
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 <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ConfigDescParser(UsbConfigXtracter *xtractor) :
theXtractor(xtractor),
stateParseDescr(0),
dscrLen(0),
dscrType(0)
{
theBuffer.pValue = varBuffer;
valParser.Initialize(&theBuffer);
theSkipper.Initialize(&theBuffer);
};
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::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 <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::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 <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc)
{
/*Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"));
Notify(PSTR("bDescLength:\t\t"));
PrintHex<uint8_t>(pDesc->bLength);
Notify(PSTR("\r\nbDescriptorType:\t"));
PrintHex<uint8_t>(pDesc->bDescriptorType);
Notify(PSTR("\r\nbcdHID:\t\t\t"));
PrintHex<uint16_t>(pDesc->bcdHID);
Notify(PSTR("\r\nbCountryCode:\t\t"));
PrintHex<uint8_t>(pDesc->bCountryCode);
Notify(PSTR("\r\nbNumDescriptors:\t"));
PrintHex<uint8_t>(pDesc->bNumDescriptors);
//Notify(PSTR("\r\nbDescrType:\t\t"));
//PrintHex<uint8_t>(pDesc->bDescrType);
//
//Notify(PSTR("\r\nwDescriptorLength:\t"));
//PrintHex<uint16_t>(pDesc->wDescriptorLength);
for (uint8_t i=0; i<pDesc->bNumDescriptors; i++)
{
HID_CLASS_DESCRIPTOR_LEN_AND_TYPE *pLT = (HID_CLASS_DESCRIPTOR_LEN_AND_TYPE*)&(pDesc->bDescrType);
Notify(PSTR("\r\nbDescrType:\t\t"));
PrintHex<uint8_t>(pLT[i].bDescrType);
Notify(PSTR("\r\nwDescriptorLength:\t"));
PrintHex<uint16_t>(pLT[i].wDescriptorLength);
}
Notify(PSTR("\r\n"));*/
printf("somebody save me!!!! orgazmo?!!!\r\n");
}
#endif /* CONFDESCPARSER_H_INCLUDED */

View File

@ -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 */

View File

@ -0,0 +1,281 @@
#include "variant.h"
#include <stdio.h>
#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; i<len; i++)
print_hex(descrptr[i], 8);
//for (uint8_t i=1; i<=pHub->bNbrPorts; 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++;
}
}

View File

@ -1,21 +0,0 @@
/* USB Host Shield board test sketch header */
#ifndef _BOARD_TEST_H_
#define _BOARD_TEST_H_
/* PGMSPACE */
#include <inttypes.h>
#include <avr/pgmspace.h>
/* 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

View File

@ -1,296 +0,0 @@
/* USB Host Shield Board test routine. Runs after assembly to check board functionality */
/* USB related */
//#include <Spi.h>
#include <Max3421e.h>
#include <Max3421e_constants.h>
#include <Usb.h>
#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);
}

View File

@ -1,181 +0,0 @@
/* MAX3421E USB Host controller get configuration descriptor */
#include <Spi.h>
#include <Max3421e.h>
#include <Usb.h>
#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++;
}
}

View File

@ -1,284 +0,0 @@
#ifndef _DESCRIPTOR_PARSER_
#define _DESCRIPTOR_PARSER_
/* PGMSPACE */
#include <inttypes.h>
#include <avr/pgmspace.h>
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_

View File

@ -1,720 +0,0 @@
/* MAX3421E USB Host controller configuration descriptor parser */
#include <Spi.h>
#include <Max3421e.h>
#include <Usb.h>
#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;
}

View File

@ -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 <stdint.h>
#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 */

View File

@ -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<uint8_t>(ep_ptr->bLength);
Notify(PSTR("\r\nType:\t\t"));
PrintHex<uint8_t>(ep_ptr->bDescriptorType);
Notify(PSTR("\r\nAddress:\t"));
PrintHex<uint8_t>(ep_ptr->bEndpointAddress);
Notify(PSTR("\r\nAttributes:\t"));
PrintHex<uint8_t>(ep_ptr->bmAttributes);
Notify(PSTR("\r\nMaxPktSize:\t"));
PrintHex<uint16_t>(ep_ptr->wMaxPacketSize);
Notify(PSTR("\r\nPoll Intrv:\t"));
PrintHex<uint8_t>(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<uint8_t>(pDesc->bLength);
Notify(PSTR("\r\nbDescriptorType:\t"));
PrintHex<uint8_t>(pDesc->bDescriptorType);
Notify(PSTR("\r\nbcdHID:\t\t\t"));
PrintHex<uint16_t>(pDesc->bcdHID);
Notify(PSTR("\r\nbCountryCode:\t\t"));
PrintHex<uint8_t>(pDesc->bCountryCode);
Notify(PSTR("\r\nbNumDescriptors:\t"));
PrintHex<uint8_t>(pDesc->bNumDescriptors);
Notify(PSTR("\r\nbDescrType:\t\t"));
PrintHex<uint8_t>(pDesc->bDescrType);
Notify(PSTR("\r\nwDescriptorLength:\t"));
PrintHex<uint16_t>(pDesc->wDescriptorLength);*/
}

View File

@ -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;
}

View File

@ -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 <stdint.h>
#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 <const uint8_t BOOT_PROTOCOL>
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 <const uint8_t BOOT_PROTOCOL>
HIDBoot<BOOT_PROTOCOL>::HIDBoot(USBHost *p) :
HID(p),
pRptParser(NULL),
qNextPollTime(0),
bPollEnable(false)
{
Initialize();
if (pUsb)
pUsb->RegisterDeviceClass(this);
}
template <const uint8_t BOOT_PROTOCOL>
void HIDBoot<BOOT_PROTOCOL>::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 <const uint8_t BOOT_PROTOCOL>
uint32_t HIDBoot<BOOT_PROTOCOL>::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<USBReadParser, uint16_t, uint16_t> 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 <const uint8_t BOOT_PROTOCOL>
void HIDBoot<BOOT_PROTOCOL>::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<uint8_t>(PSTR("\r\nConf.Val"), conf);
//ErrorMessage<uint8_t>(PSTR("Iface Num"), iface);
//ErrorMessage<uint8_t>(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 <const uint8_t BOOT_PROTOCOL>
uint32_t HIDBoot<BOOT_PROTOCOL>::Release()
{
pUsb->GetAddressPool().FreeAddress(bAddress);
bConfNum = 0;
bIfaceNum = 0;
bNumEP = 1;
bAddress = 0;
qNextPollTime = 0;
bPollEnable = false;
return 0;
}
template <const uint8_t BOOT_PROTOCOL>
uint32_t HIDBoot<BOOT_PROTOCOL>::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 */

View File

@ -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 */

View File

@ -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;
}

View File

@ -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 <stdint.h>
#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 */

View File

@ -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 <stdint.h>
/* 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 <stdint.h>
/* 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 */

View File

@ -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);

View File

@ -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_HSTPIPCFG_PSIZE_Pos)&UOTGHS_HSTPIPCFG_PSIZE_Msk)|\
(((token)<<UOTGHS_HSTPIPCFG_PTOKEN_Pos)&UOTGHS_HSTPIPCFG_PTOKEN_Msk)|\
(((type)<<UOTGHS_HSTPIPCFG_PTYPE_Pos)&UOTGHS_HSTPIPCFG_PTYPE_Msk)|\
((token)&UOTGHS_HSTPIPCFG_PTOKEN_Msk)|\
((type)&UOTGHS_HSTPIPCFG_PTYPE_Msk)|\
(((ep_num)<<UOTGHS_HSTPIPCFG_PEPNUM_Pos)&UOTGHS_HSTPIPCFG_PEPNUM_Msk)|\
bank_switch |\
(((freq)<<UOTGHS_HSTPIPCFG_INTFRQ_Pos)&UOTGHS_HSTPIPCFG_INTFRQ_Msk)))
(((freq)<<UOTGHS_HSTPIPCFG_INTFRQ_Pos)&UOTGHS_HSTPIPCFG_INTFRQ_Msk))
#define Is_uhd_pipe_configured(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_CFGOK))
//! @}

View File

@ -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

View File

@ -99,14 +99,14 @@ pwmc.o:
00000000 T PWMC_SetSyncChannelUpdateUnlock
00000000 T PWMC_WriteBuffer
U __assert_func
00000000 r __func__.3227
00000000 r __func__.3238
00000000 r __func__.3253
00000000 r __func__.3264
00000000 r __func__.3275
00000000 r __func__.3282
00000000 r __func__.3366
00000000 r __func__.3372
00000000 r __func__.3235
00000000 r __func__.3246
00000000 r __func__.3261
00000000 r __func__.3272
00000000 r __func__.3283
00000000 r __func__.3290
00000000 r __func__.3374
00000000 r __func__.3380
rtc.o:
00000000 T RTC_ClearSCCR
@ -122,9 +122,9 @@ rtc.o:
00000000 T RTC_SetTime
00000000 T RTC_SetTimeAlarm
U __assert_func
00000000 r __func__.3224
00000000 r __func__.3233
00000000 r __func__.3238
00000000 r __func__.3232
00000000 r __func__.3241
00000000 r __func__.3246
rtt.o:
00000000 T RTT_EnableIT
@ -133,8 +133,8 @@ rtt.o:
00000000 T RTT_SetAlarm
00000000 T RTT_SetPrescaler
U __assert_func
00000000 r __func__.3231
00000000 r __func__.3239
00000000 r __func__.3247
spi.o:
00000000 T SPI_Configure
@ -155,9 +155,9 @@ tc.o:
00000000 T TC_Start
00000000 T TC_Stop
U __assert_func
00000000 r __func__.3226
00000000 r __func__.3232
00000000 r __func__.3238
00000000 r __func__.3234
00000000 r __func__.3240
00000000 r __func__.3246
timetick.o:
00000000 T GetTickCount
@ -184,18 +184,18 @@ twi.o:
00000000 T TWI_TransferComplete
00000000 T TWI_WriteByte
U __assert_func
00000000 r __func__.3591
00000000 r __func__.3606
00000000 r __func__.3610
00000000 r __func__.3617
00000000 r __func__.3621
00000000 r __func__.3626
00000000 r __func__.3599
00000000 r __func__.3614
00000000 r __func__.3618
00000000 r __func__.3625
00000000 r __func__.3629
00000000 r __func__.3634
00000000 r __func__.3648
00000000 r __func__.3653
00000000 r __func__.3657
00000000 r __func__.3662
00000000 r __func__.3666
00000000 r __func__.3642
00000000 r __func__.3656
00000000 r __func__.3661
00000000 r __func__.3665
00000000 r __func__.3670
00000000 r __func__.3674
usart.o:
00000000 T USART_Configure
@ -214,7 +214,7 @@ usart.o:
00000000 T USART_Write
00000000 T USART_WriteBuffer
U __assert_func
00000000 r __func__.3512
00000000 r __func__.3520
wdt.o:
00000000 T WDT_Disable
@ -386,6 +386,7 @@ uotghs_device.o:
uotghs_host.o:
00000000 T UHD_BusReset
00000000 T UHD_EP0_Alloc
00000000 T UHD_EP_Alloc
00000000 T UHD_EP_Free
00000000 T UHD_EP_Is_Transfer_Complete
00000000 T UHD_EP_Read