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:
parent
a7033f459e
commit
c1aaef21e1
@ -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_
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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 */
|
||||
|
293
hardware/arduino/sam/system/USBHost/address.h
Normal file
293
hardware/arduino/sam/system/USBHost/address.h
Normal 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 */
|
213
hardware/arduino/sam/system/USBHost/confdescparser.h
Normal file
213
hardware/arduino/sam/system/USBHost/confdescparser.h
Normal 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 */
|
@ -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 */
|
@ -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++;
|
||||
}
|
||||
}
|
@ -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
|
@ -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);
|
||||
}
|
@ -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++;
|
||||
}
|
||||
}
|
@ -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_
|
@ -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;
|
||||
}
|
188
hardware/arduino/sam/system/USBHost/hid.h
Normal file
188
hardware/arduino/sam/system/USBHost/hid.h
Normal 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 */
|
101
hardware/arduino/sam/system/USBHost/hid2.cpp
Normal file
101
hardware/arduino/sam/system/USBHost/hid2.cpp
Normal 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);*/
|
||||
}
|
158
hardware/arduino/sam/system/USBHost/hidboot.cpp
Normal file
158
hardware/arduino/sam/system/USBHost/hidboot.cpp
Normal 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;
|
||||
}
|
478
hardware/arduino/sam/system/USBHost/hidboot.h
Normal file
478
hardware/arduino/sam/system/USBHost/hidboot.h
Normal 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 */
|
976
hardware/arduino/sam/system/USBHost/hidusagestr.h
Normal file
976
hardware/arduino/sam/system/USBHost/hidusagestr.h
Normal 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 */
|
73
hardware/arduino/sam/system/USBHost/parsetools.cpp
Normal file
73
hardware/arduino/sam/system/USBHost/parsetools.cpp
Normal 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;
|
||||
}
|
143
hardware/arduino/sam/system/USBHost/parsetools.h
Normal file
143
hardware/arduino/sam/system/USBHost/parsetools.h
Normal 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 */
|
@ -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 */
|
@ -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);
|
||||
|
@ -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))
|
||||
//! @}
|
||||
|
@ -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
|
||||
|
Binary file not shown.
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user