1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-06-22 08:22:04 +03:00

USBHost library to new format

This commit is contained in:
Fede85
2013-07-04 14:10:26 +02:00
parent 10a4241ba7
commit 0608c9f83f
24 changed files with 10 additions and 0 deletions

View File

@ -0,0 +1,40 @@
/*
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 <KeyboardController.h>
extern "C" {
void __keyboardControllerEmptyCallback() { }
}
void keyPressed() __attribute__ ((weak, alias("__keyboardControllerEmptyCallback")));
void keyReleased() __attribute__ ((weak, alias("__keyboardControllerEmptyCallback")));
void KeyboardController::OnKeyDown(uint8_t _mod, uint8_t _oemKey) {
modifiers = _mod;
keyOem = _oemKey;
key = OemToAscii(_mod, _oemKey);
keyPressed();
}
void KeyboardController::OnKeyUp(uint8_t _mod, uint8_t _oemKey) {
modifiers = _mod;
keyOem = _oemKey;
key = OemToAscii(_mod, _oemKey);
keyReleased();
}

View File

@ -0,0 +1,54 @@
/*
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
*/
#ifndef KEYBOARD_CONTROLLER_H
#define KEYBOARD_CONTROLLER_H
#include <hidboot.h>
enum KeyboardModifiers {
LeftCtrl = 1,
LeftShift = 2,
Alt = 4,
LeftCmd = 8,
RightCtrl = 16,
RightShift = 32,
AltGr = 64,
RightCmd = 128
};
class KeyboardController : public KeyboardReportParser {
public:
KeyboardController(USBHost &usb) : hostKeyboard(&usb), key(0), keyOem(0), modifiers(0) {
hostKeyboard.SetReportParser(0, this);
};
uint8_t getKey() { return key; };
uint8_t getModifiers() { return modifiers; };
uint8_t getOemKey() { return keyOem; };
protected:
virtual void OnKeyDown(uint8_t mod, uint8_t key);
virtual void OnKeyUp(uint8_t mod, uint8_t key);
private:
HIDBoot<HID_PROTOCOL_KEYBOARD> hostKeyboard;
uint8_t key, keyOem, modifiers;
};
#endif

View File

@ -0,0 +1,83 @@
/*
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 <MouseController.h>
extern "C" {
void __mouseControllerEmptyCallback() { }
}
void mouseClicked() __attribute__ ((weak, alias("__mouseControllerEmptyCallback")));
void mouseDragged() __attribute__ ((weak, alias("__mouseControllerEmptyCallback")));
void mouseMoved() __attribute__ ((weak, alias("__mouseControllerEmptyCallback")));
void mousePressed() __attribute__ ((weak, alias("__mouseControllerEmptyCallback")));
void mouseReleased() __attribute__ ((weak, alias("__mouseControllerEmptyCallback")));
int MouseController::getXChange() {
int r = dx;
dx = 0;
return r;
}
int MouseController::getYChange() {
int r = dy;
dy = 0;
return r;
}
void MouseController::OnMouseMove(MOUSEINFO *mi) {
dx += mi->dX;
dy += mi->dY;
if (buttons != 0)
mouseDragged();
else
mouseMoved();
}
void MouseController::OnLeftButtonUp(MOUSEINFO *mi) {
buttons &= ~LEFT_BUTTON;
mouseReleased();
mouseClicked();
}
void MouseController::OnLeftButtonDown(MOUSEINFO *mi) {
buttons |= LEFT_BUTTON;
mousePressed();
}
void MouseController::OnMiddleButtonUp(MOUSEINFO *mi) {
buttons &= ~MIDDLE_BUTTON;
mouseReleased();
mouseClicked();
}
void MouseController::OnMiddleButtonDown(MOUSEINFO *mi) {
buttons |= MIDDLE_BUTTON;
mousePressed();
}
void MouseController::OnRightButtonUp(MOUSEINFO *mi) {
buttons &= ~RIGHT_BUTTON;
mouseReleased();
mouseClicked();
}
void MouseController::OnRightButtonDown(MOUSEINFO *mi) {
buttons |= RIGHT_BUTTON;
mousePressed();
}

View File

@ -0,0 +1,57 @@
/*
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
*/
#ifndef MOUSE_CONTROLLER_H
#define MOUSE_CONTROLLER_H
#include <hidboot.h>
enum MouseButton {
LEFT_BUTTON = 0x01,
MIDDLE_BUTTON = 0x02,
RIGHT_BUTTON = 0x04
};
class MouseController : public MouseReportParser
{
public:
MouseController(USBHost &usb) : hostMouse(&usb), dx(0), dy(0), buttons(0) {
hostMouse.SetReportParser(0, this);
};
bool getButton(MouseButton button) { return (buttons & button) == button; };
int getXChange();
int getYChange();
// int getWheelChange(); // Not implemented
protected:
virtual void OnMouseMove(MOUSEINFO *mi);
virtual void OnLeftButtonUp(MOUSEINFO *mi);
virtual void OnLeftButtonDown(MOUSEINFO *mi);
virtual void OnMiddleButtonUp(MOUSEINFO *mi);
virtual void OnMiddleButtonDown(MOUSEINFO *mi);
virtual void OnRightButtonUp(MOUSEINFO *mi);
virtual void OnRightButtonDown(MOUSEINFO *mi);
private:
HIDBoot<HID_PROTOCOL_MOUSE> hostMouse;
int dx, dy;
int buttons;
};
#endif

View File

@ -0,0 +1,856 @@
/* 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>
static uint32_t usb_error = 0;
static uint32_t usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
/**
* \brief USBHost class constructor.
*/
USBHost::USBHost() : bmHubPre(0)
{
// Set up state machine
usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
// Init host stack
init();
}
/**
* \brief Initialize USBHost class.
*/
void USBHost::init()
{
devConfigIndex = 0;
bmHubPre = 0;
}
/**
* \brief Get USBHost state.
*
* \return USB enumeration status (see USBHost::task).
*/
uint32_t USBHost::getUsbTaskState(void)
{
return (usb_task_state);
}
/**
* \brief Set USB state.
*
* \param state New USBHost status to be set.
*/
void USBHost::setUsbTaskState(uint32_t state)
{
usb_task_state = state;
}
/**
* \brief Get endpoint info from USB device address and device endpoint.
*
* \note This function should be used to know which host pipe is being used for
* the corresponding device endpoint.
*
* \param addr USB device address.
* \param ep USB device endpoint number.
*
* \return Pointer to an EpInfo structure.
*/
EpInfo* USBHost::getEpInfoEntry(uint32_t addr, uint32_t ep)
{
UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
if (!p || !p->epinfo)
return NULL;
EpInfo *pep = p->epinfo;
for (uint32_t i = 0; i < p->epcount; i++)
{
if (pep->deviceEpNum == ep)
return pep;
pep++;
}
return NULL;
}
/**
* \brief Set device endpoint entry.
*
* \note Each device is different and has a different number of endpoints.
* This function sets endpoint record structure to the device using address
* addr in the address pool.
*
* \param ul_pipe Pipe address.
* \param ul_token_type Token type.
*
* \retval 0 on success.
* \retval USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL device not found.
*/
uint32_t USBHost::setEpInfoEntry(uint32_t addr, uint32_t epcount, 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;
}
/**
* \brief Set host pipe target address and set ppep pointer to the endpoint
* structure matching the specified USB device address and endpoint.
*
* \param addr USB device address.
* \param ep USB device endpoint number.
* \param ppep Endpoint info structure pointer set by setPipeAddress.
* \param nak_limit Maximum number of NAK permitted.
*
* \retval 0 on success.
* \retval USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL device not found.
* \retval USB_ERROR_EPINFO_IS_NULL no endpoint structure found for this device.
* \retval USB_ERROR_EP_NOT_FOUND_IN_TBL the specified device endpoint cannot be found.
*/
uint32_t USBHost::setPipeAddress(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
TRACE_USBHOST(printf(" => SetAddress deviceEP=%lu configued as hostPIPE=%lu sending to address=%lu\r\n", ep, (*ppep)->hostPipeNum, addr);)
uhd_configure_address((*ppep)->hostPipeNum, addr);
return 0;
}
/**
* \brief Send a control request.
* Sets address, endpoint, fills control packet with necessary data, dispatches
* control packet, and initiates bulk IN transfer depending on request.
*
* \param addr USB device address.
* \param ep USB device endpoint number.
* \param bmReqType Request direction.
* \param bRequest Request type.
* \param wValLo Value low.
* \param wValHi Value high.
* \param wInd Index field.
* \param total Request length.
* \param nbytes Number of bytes to read.
* \param dataptr Data pointer.
* \param p USB class reader.
*
* \return 0 on success, error code otherwise.
*/
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
rcode = setPipeAddress(addr, ep, &pep, nak_limit);
if (rcode)
return rcode;
// Allocate Pipe0 with default 64 bytes size if not already initialized
// TODO : perform a get device descriptor first to get device endpoint size (else data can be missed if device ep0 > host pipe0)
rcode = UHD_Pipe0_Alloc(0, 64);
if (rcode)
{
TRACE_USBHOST(printf("/!\\ USBHost::ctrlReq : EP0 allocation error: %lu\r\n", rcode);)
return (rcode);
}
// Determine request direction
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 = total;
// Configure and write the setup packet into the FIFO
uhd_configure_pipe_token(0, tokSETUP);
UHD_Pipe_Write(pep->hostPipeNum, 8, (uint8_t *)&setup_pkt);
// Dispatch packet
rcode = dispatchPkt(tokSETUP, pep->hostPipeNum, nak_limit);
if (rcode)
{
// Return HRSLT if not zero
TRACE_USBHOST(printf("/!\\ USBHost::ctrlReq : Setup packet error: %lu\r\n", rcode);)
return (rcode);
}
// Data stage (if present)
if (dataptr != 0)
{
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
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);)
return (rcode);
}
}
// Status stage
return dispatchPkt((direction) ? tokOUTHS : tokINHS, pep->hostPipeNum, nak_limit);
}
/**
* \brief Perform IN request to the specified USB device.
*
* \note This function handles multiple packets (if necessary) and can
* receive a maximum of 'nbytesptr' bytes. It keep sending INs and writes data
* to memory area pointed by 'data'. The actual amount of received bytes is
* stored in 'nbytesptr'.
*
* \param addr USB device address.
* \param ep USB device endpoint number.
* \param nbytesptr Receive buffer size. It is set to the amount of received
* bytes when the function returns.
* \param data Buffer to store received data.
*
* \return 0 on success, error code otherwise.
*/
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 = setPipeAddress(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 nbytes = *nbytesptr;
uint32_t maxpktsize = pep->maxPktSize;
*nbytesptr = 0;
while (1)
{
// Use a 'return' to exit this loop
// IN packet to EP-'endpoint'. Function takes care of NAKS.
rcode = dispatchPkt(tokIN, pep->hostPipeNum, nak_limit);
if (rcode)
{
if (rcode == 1)
{
// Pipe freeze is mandatory to avoid sending IN endlessly (else reception becomes messy then)
uhd_freeze_pipe(pep->hostPipeNum);
}
// Should be 1, indicating NAK. Else return error code.
return rcode;
}
// Number of received bytes
pktsize = uhd_byte_count(pep->hostPipeNum);
if (nbytes < pktsize)
{
TRACE_USBHOST(printf("/!\\ USBHost::InTransfer : receive buffer is too small, size=%lu, expected=%lu\r\n", nbytes, pktsize);)
}
data += UHD_Pipe_Read(pep->hostPipeNum, pktsize, data);
// Add this packet's byte count to total transfer length
*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) || (*nbytesptr >= nbytes))
{
return 0;
}
}
}
/**
* \brief Perform OUT request to the specified USB device.
*
* \note This function handles multiple packets (if necessary) and sends
* 'nbytes' bytes.
*
* \param addr USB device address.
* \param ep USB device endpoint number.
* \param nbytes Buffer size to be sent.
* \param data Buffer to send.
*
* \return 0 on success, error code otherwise.
*/
uint32_t USBHost::outTransfer(uint32_t addr, uint32_t ep, uint32_t nbytes, uint8_t* data)
{
EpInfo *pep = NULL;
uint32_t nak_limit = 0;
uint32_t rcode = setPipeAddress(addr, ep, &pep, nak_limit);
if (rcode)
{
return rcode;
}
return OutTransfer(pep, nak_limit, nbytes, data);
}
uint32_t USBHost::OutTransfer(EpInfo *pep, uint32_t nak_limit, uint32_t nbytes, uint8_t *data)
{
uint32_t rcode = 0;
uint32_t bytes_tosend = 0;
uint32_t bytes_left = nbytes;
uint32_t maxpktsize = pep->maxPktSize;
if (maxpktsize < 1)
return USB_ERROR_INVALID_MAX_PKT_SIZE;
while (bytes_left)
{
bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left;
// Write FIFO
UHD_Pipe_Write(pep->hostPipeNum, bytes_tosend, data);
// Use a 'return' to exit this loop
// OUT packet to EP-'endpoint'. Function takes care of NAKS.
rcode = dispatchPkt(tokOUT, pep->hostPipeNum, nak_limit);
if (rcode)
{
// Should be 0, indicating ACK. Else return error code.
return rcode;
}
bytes_left -= bytes_tosend;
data += bytes_tosend;
}
// Should be 0 in all cases
return rcode;
}
/**
* \brief Dispatch USB packet.
*
* \note Ensure peripheral address is set and relevant buffer is loaded/empty.
* If NAK, tries to re-send up to nak_limit times.
* If nak_limit == 0, do not count NAKs, exit after timeout.
*
* \param token Token type (Setup, In or Out).
* \param hostPipeNum Host pipe number to use for sending USB packet.
* \param nak_limit Maximum number of NAK permitted.
*
* \return 0 on success, error code otherwise.
*/
uint32_t USBHost::dispatchPkt(uint32_t token, uint32_t hostPipeNum, 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 pipe=%lu nak_limit=%lu\r\n", token, hostPipeNum, nak_limit);)
// Launch the transfer
UHD_Pipe_Send(hostPipeNum, token);
// Check timeout but don't hold timeout if VBUS is lost
while ((timeout > millis()) && (UHD_GetVBUSState() == UHD_STATE_CONNECTED))
{
// Wait for transfer completion
if (UHD_Pipe_Is_Transfer_Complete(hostPipeNum, token))
{
return 0;
}
// Is NAK received?
if (Is_uhd_nak_received(hostPipeNum))
{
uhd_ack_nak_received(hostPipeNum);
nak_count++;
if (nak_limit && (nak_count == nak_limit))
{
// Return NAK
return 1;
}
}
}
return rcode;
}
/**
* \brief Configure device using known device classes.
* The device get a new address even if its class remain unknown.
*
* \param parent USB device address of the device's parent (0 if root).
* \param port USB device base address (see AddressPoolImpl).
* \param lowspeed Device speed.
*
* \return 0 on success, error code otherwise.
*/
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)
{
TRACE_USBHOST(printf("USBHost::Configuring : ERROR : device not supported!\r\n");)
}
else if (rcode == USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE)
{
TRACE_USBHOST(printf("USBHost::Configuring : ERROR : class instance already in use!\r\n");)
}
else
{
// 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;
}
}
// Device class is not supported by any of the registered classes
devConfigIndex = 0;
rcode = DefaultAddressing(parent, port, lowspeed);
return rcode;
}
/**
* \brief Configure device with unknown USB class.
*
* \param parent USB device address of the device's parent (0 if root).
* \param port USB device base address (see AddressPoolImpl).
* \param lowspeed Device speed.
*
* \return 0 on success, error code otherwise.
*/
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;
}
/**
* \brief Release device and free associated resources.
*
* \param addr USB device address.
*
* \return 0 on success, error code otherwise.
*/
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;
}
/**
* \brief Get device descriptor.
*
* \param addr USB device address.
* \param ep USB device endpoint number.
* \param nbytes Buffer size.
* \param dataptr Buffer to store received descriptor.
*
* \return 0 on success, error code otherwise.
*/
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));
}
/**
* \brief Get configuration descriptor.
*
* \param addr USB device address.
* \param ep USB device endpoint number.
* \param nbytes Buffer size.
* \param conf Configuration number.
* \param dataptr Buffer to store received descriptor.
*
* \return 0 on success, error code otherwise.
*/
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));
}
/**
* \brief Get configuration descriptor and extract endpoints using USBReadParser object.
*
* \param addr USB device address.
* \param ep USB device endpoint number.
* \param conf Configuration number.
* \param p USBReadParser object pointer used to extract endpoints.
*
* \return 0 on success, error code otherwise.
*/
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));
}
/**
* \brief Get string descriptor.
*
* \param addr USB device address.
* \param ep USB device endpoint number.
* \param nbytes Buffer size.
* \param index String index.
* \param langid Language ID.
* \param dataptr Buffer to store received descriptor.
*
* \return 0 on success, error code otherwise.
*/
uint32_t USBHost::getStrDescr(uint32_t addr, uint32_t ep, uint32_t nbytes, 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, nbytes, nbytes, dataptr, 0));
}
/**
* \brief Set USB device address.
*
* \param oldaddr Current USB device address.
* \param ep USB device endpoint number.
* \param addr New USB device address to be set.
*
* \return 0 on success, error code otherwise.
*/
uint32_t USBHost::setAddr(uint32_t oldaddr, uint32_t ep, uint32_t newaddr)
{
TRACE_USBHOST(printf(" => USBHost::setAddr\r\n");)
return ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, 0, 0);
}
/**
* \brief Set configuration.
*
* \param addr USB device address.
* \param ep USB device endpoint number.
* \param conf_value New configuration value to be set.
*
* \return 0 on success, error code otherwise.
*/
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));
}
/**
* \brief USB main task, responsible for enumeration and clean up stage.
*
* \note Must be periodically called from loop().
*/
void USBHost::Task(void)
{
uint32_t rcode = 0;
volatile uint32_t tmpdata = 0;
static uint32_t delay = 0;
uint32_t lowspeed = 0;
// Update USB task state on Vbus change
tmpdata = UHD_GetVBUSState();
switch (tmpdata)
{
case UHD_STATE_ERROR:
// Illegal state
usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;
lowspeed = 0;
break;
case UHD_STATE_DISCONNECTED:
// Disconnected state
if ((usb_task_state & USB_STATE_MASK) != USB_STATE_DETACHED)
{
usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
lowspeed = 0;
}
break;
case UHD_STATE_CONNECTED:
// Attached state
if ((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED)
{
delay = millis() + USB_SETTLE_DELAY;
usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
//FIXME TODO: lowspeed = 0 ou 1; already done by hardware?
}
break;
}
// Poll connected devices (if required)
for (uint32_t i = 0; i < USB_NUMDEVICES; ++i)
if (devConfig[i])
rcode = devConfig[i]->Poll();
// Perform USB enumeration stage and clean up
switch (usb_task_state)
{
case USB_DETACHED_SUBSTATE_INITIALIZE:
TRACE_USBHOST(printf(" + USB_DETACHED_SUBSTATE_INITIALIZE\r\n");)
// Init USB stack and driver
UHD_Init();
init();
// Free all USB resources
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;
case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE:
// Nothing to do
break;
case USB_DETACHED_SUBSTATE_ILLEGAL:
// Nothing to do
break;
case USB_ATTACHED_SUBSTATE_SETTLE:
// Settle time for just attached device
if (delay < millis())
{
TRACE_USBHOST(printf(" + USB_ATTACHED_SUBSTATE_SETTLE\r\n");)
usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
}
break;
case USB_ATTACHED_SUBSTATE_RESET_DEVICE:
TRACE_USBHOST(printf(" + USB_ATTACHED_SUBSTATE_RESET_DEVICE\r\n");)
// Trigger Bus Reset
UHD_BusReset();
usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE;
break;
case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE:
if (Is_uhd_reset_sent())
{
TRACE_USBHOST(printf(" + USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE\r\n");)
// Clear Bus Reset flag
uhd_ack_reset_sent();
// Enable Start Of Frame generation
uhd_enable_sof();
usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
// Wait 20ms after Bus Reset (USB spec)
delay = millis() + 20;
}
break;
case USB_ATTACHED_SUBSTATE_WAIT_SOF:
// Wait for SOF received first
if (Is_uhd_sof())
{
if (delay < millis())
{
TRACE_USBHOST(printf(" + USB_ATTACHED_SUBSTATE_WAIT_SOF\r\n");)
// 20ms waiting elapsed
usb_task_state = USB_STATE_CONFIGURING;
}
}
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:
break;
case USB_STATE_ERROR:
break;
}
}

230
libraries/USBHost/src/Usb.h Normal file
View File

@ -0,0 +1,230 @@
/* 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 "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
// 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
// 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_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
#define USB_DETACHED_SUBSTATE_ILLEGAL 0x13
#define USB_ATTACHED_SUBSTATE_SETTLE 0x20
#define USB_ATTACHED_SUBSTATE_RESET_DEVICE 0x30
#define USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE 0x40
#define USB_ATTACHED_SUBSTATE_WAIT_SOF 0x50
#define USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE 0x60
#define USB_STATE_ADDRESSING 0x70
#define USB_STATE_CONFIGURING 0x80
#define USB_STATE_RUNNING 0x90
#define USB_STATE_ERROR 0xa0
#define USB_STATE_MASK 0xf0
// USB Setup Packet Structure
typedef struct
{
union
{ // offset description
uint8_t bmRequestType; // 0 Bit-map of request type
struct
{
uint8_t recipient: 5; // Recipient of the request
uint8_t type: 2; // Type of request
uint8_t direction: 1; // Direction of data X-fer
};
} ReqType_u;
uint8_t bRequest; // 1 Request
union
{
uint16_t wValue; // 2 Depends on bRequest
struct
{
uint8_t wValueLo;
uint8_t wValueHi;
};
} wVal_u;
uint16_t wIndex; // 4 Depends on bRequest
uint16_t wLength; // 6 Depends on bRequest
} SETUP_PKT, *PSETUP_PKT;
/**
* \class USBReadParser
*
* \brief Base class used for USB descriptor parsing.
*/
class USBReadParser
{
public:
virtual void Parse(const uint32_t len, const uint8_t *pbuf, const uint32_t &offset) = 0;
};
/**
* \class USBDeviceConfig
*
* \brief Device configuration class used for managing device life cycle.
*/
class USBDeviceConfig
{
public:
//! @brief Perform final enumeration stage.
virtual uint32_t Init(uint32_t parent, uint32_t port, uint32_t lowspeed) = 0;
//! @brief Free USB allocated resources (pipes and address).
virtual uint32_t Release() = 0;
//! @brief Poll USB device. Call is made for each connected USB device on USBHost.task() call.
virtual uint32_t Poll() = 0;
//! @brief Retrieve USB device address.
virtual uint32_t GetAddress() = 0;
};
/**
* \class USBHost
*
* \brief Main USB host class.
*/
class USBHost
{
AddressPoolImpl<USB_NUMDEVICES> addrPool;
USBDeviceConfig* devConfig[USB_NUMDEVICES];
uint32_t devConfigIndex;
uint32_t bmHubPre;
public:
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);
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 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, uint32_t nbytes, 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);
/* 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);
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 setPipeAddress(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);
};
#endif /* USB_H_INCLUDED */

View File

@ -0,0 +1,392 @@
/* 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
/**
* \brief Device endpoint definition.
*
* \note hostPipeNum is the allocated pipe used for the communication with
* deviceEpNum remote device endpoint.
* There is exactly one hostPipeNum corresponding to a deviceEpNum.
*
* \note The number of host pipe is limited by the hardware (10 on SAM3X).
* Moreover hostPipeNum allocation is static, meaning that only a limited
* amount of device endpoints can be opened at the same time, thus limitating
* the maximum number of connected devices at the same time.
*/
struct EpInfo
{
uint32_t deviceEpNum; // Device endpoint number
uint32_t hostPipeNum; // Host corresponding pipe number
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
};
};
};
/**
* \brief USB device address definition.
*
* \note The 8 bits USB address is defined like this:
*
* 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
/**
* \brief USB device definition.
*
* \note epinfo is used to store the list of device endpoints currently used
* by the USBHost stack. This field is set during enumeration process when
* a supported USB class is found. See any USB classes implementing
* USBDeviceConfig and init() method for reference.
*/
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 Abstract AddressPool definition.
*/
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
/**
* \class AddressPoolImpl definition.
* Used to store the list of connected devices and to keep track of free USB
* addresses.
*/
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];
/**
* \brief Initialize the specified address pool entry.
*
* \param index Index pointing to a UsbDevice instance in the address pool.
*/
void InitEntry(uint32_t index)
{
thePool[index].address = 0;
thePool[index].epcount = 1;
thePool[index].lowspeed = 0;
thePool[index].epinfo = &dev0ep;
};
/**
* \brief Return an address pool index for a given address. This index can
* further be used to retrieve the corresponding USB device instance
* UsbDevice.
*
* \param index Index pointing to a UsbDevice instance in the address pool.
*
* \return Index number if found, 0 otherwise.
* \note Index 0 is reserved for address 0 and shall never be used.
*/
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;
};
/**
* \brief Return address pool child index for a given parent. This index can
* further be used to retrieve the corresponding USB device instance
* UsbDevice.
*
* \param addr Parent USB address.
* \param start Search in the pool from this index. Calling multiple time
* this function with the returned index + 1 can be used to walk through
* all children.
*
* \return Child index number if found, 0 otherwise.
* \note Index 0 is reserved for address 0 and shall never be used.
*/
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;
};
/**
* \brief Free address entry specified by index parameter.
*
* \note Calling FreeAddressByIndex only frees the USB address for possible
* further assignement. However, it does not free the actual USB resources
* used by the device. This can be made by calling the release() method
* from any UsbDevice class implementing USBDeviceConfig.
*
* \param index Index pointing to a UsbDevice instance in the address pool.
*
* \note Calling FreeAddressByIndex with a 0 index param has no effect.
*/
void FreeAddressByIndex(uint32_t index)
{
// Zero 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);
}
/**
* \brief Initialize all address poll entries at once.
*/
void InitAllAddresses()
{
for (uint32_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
InitEntry(i);
hubCounter = 0;
};
public:
/**
* \brief AddressPoolImpl class constructor.
*/
AddressPoolImpl() : hubCounter(0)
{
// Init address zero (reserved)
InitEntry(0);
// Init all remaing addresses
InitAllAddresses();
// Configure ep0 used for enumeration
dev0ep.deviceEpNum = 0;
dev0ep.hostPipeNum = 0;
dev0ep.maxPktSize = 8;
};
/**
* \brief Get a UsbDevice pointer from a USB device address.
*
* \param addr USB device address.
*
* \return UsbDevice pointer on success, 0 otherwise.
*/
virtual UsbDevice* GetUsbDevicePtr(uint32_t addr)
{
if (!addr)
return thePool;
uint32_t index = FindAddressIndex(addr);
return (!index) ? 0 : (thePool + index);
};
/**
* \brief Perform an operation specified by pfunc for each addressed
* USB device.
*
* \param pfunc Any function pointer with type UsbDeviceHandleFunc.
*/
void ForEachUsbDevice(UsbDeviceHandleFunc pfunc)
{
if (!pfunc)
return;
for (uint32_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
if (thePool[i].address)
pfunc(thePool + i);
};
/**
* \brief Allocate a new USB device address.
*
* \note See UsbDeviceAddress definition for better understanding.
*
* \param parent USB device address of the Parent device.
* \param is_hub Set to true if the corresponding device is a Hub, false
* otherwise.
* \param port USB device base address.
*
* \return UsbDevice pointer on success, 0 otherwise.
*/
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);
return thePool[index].address;
};
/**
* \brief Free the specified USB device address.
*
* \param addr USB device address to free.
*/
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.
/*uint32_t GetNumHubs()
{
return hubCounter;
};
uint32_t GetNumDevices()
{
uint32_t counter = 0;
for (uint32_t i = 1; i < MAX_DEVICES_ALLOWED; ++i)
if (thePool[i].address != 0);
counter++;
return counter;
};*/
};
#endif /* ADDRESS_H_INCLUDED */

View File

@ -0,0 +1,405 @@
/* 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
*/
/* Google ADK interface */
#include "adk.h"
const uint32_t ADK::epDataInIndex = 1;
const uint32_t ADK::epDataOutIndex = 2;
/**
* \brief ADK class constructor.
*/
ADK::ADK(USBHost *p, const char* pmanufacturer,
const char* pmodel,
const char* pdescription,
const char* pversion,
const char* puri,
const char* pserial) :
manufacturer(pmanufacturer),
model(pmodel),
description(pdescription),
version(pversion),
uri(puri),
serial(pserial),
pUsb(p),
bAddress(0),
bNumEP(1),
ready(false)
{
// Initialize endpoint data structures
for (uint32_t i = 0; i < ADK_MAX_ENDPOINTS; ++i)
{
epInfo[i].deviceEpNum = 0;
epInfo[i].hostPipeNum = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0;
epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
}
// Register in USB subsystem
if (pUsb)
{
pUsb->RegisterDeviceClass(this);
}
}
/**
* \brief Initialize connection to an Android Phone.
*
* \param parent USB device address of the Parent device.
* \param port USB device base address.
* \param lowspeed USB device speed.
*
* \return 0 on success, error code otherwise.
*/
uint32_t ADK::Init(uint32_t parent, uint32_t port, uint32_t lowspeed)
{
uint8_t buf[sizeof(USB_DEVICE_DESCRIPTOR)];
uint32_t rcode = 0;
UsbDevice *p = NULL;
EpInfo *oldep_ptr = NULL;
uint32_t adkproto = -1;
uint32_t num_of_conf = 0;
// Get memory address of USB device address pool
AddressPool &addrPool = pUsb->GetAddressPool();
TRACE_USBHOST(printf("ADK::Init\r\n");)
// Check if address has already been assigned to an instance
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)
{
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, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);
// Restore p->epinfo
p->epinfo = oldep_ptr;
if (rcode)
{
goto FailGetDevDescr;
}
// Allocate new address according to device class
bAddress = addrPool.AllocAddress(parent, false, port);
// Extract Max Packet Size from 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("ADK::Init : setAddr failed with rcode %lu\r\n", rcode);)
return rcode;
}
TRACE_USBHOST(printf("ADK::Init : device address is now %lu\r\n", bAddress);)
p->lowspeed = false;
//get pointer to assigned address record
p = addrPool.GetUsbDevicePtr(bAddress);
if (!p)
{
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
}
p->lowspeed = lowspeed;
// Assign epInfo to epinfo pointer - only EP0 is known
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
if (rcode)
{
goto FailSetDevTblEntry;
}
// Check if ADK device is already in accessory mode; if yes, configure and exit
if (((USB_DEVICE_DESCRIPTOR*)buf)->idVendor == ADK_VID &&
(((USB_DEVICE_DESCRIPTOR*)buf)->idProduct == ADK_PID || ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct == ADB_PID))
{
TRACE_USBHOST(printf("ADK::Init : Accessory mode device detected\r\n");)
/* Go through configurations, find first bulk-IN, bulk-OUT EP, fill epInfo and quit */
num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations;
TRACE_USBHOST(printf("ADK::Init : number of configuration is %lu\r\n", num_of_conf);)
for (uint32_t i = 0; i < num_of_conf; ++i)
{
ConfigDescParser<0, 0, 0, 0> confDescrParser(this);
delay(1);
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
#if defined(XOOM)
//Added by Jaylen Scott Vanorden
if (rcode)
{
TRACE_USBHOST(printf("ADK::Init : Got 1st bad code for config: %lu\r\n", rcode);)
// Try once more
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
}
#endif
if (rcode)
{
goto FailGetConfDescr;
}
if (bNumEP > 2)
{
break;
}
}
if (bNumEP == 3)
{
// Assign epInfo to epinfo pointer - this time all 3 endpoins
rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);
if (rcode)
{
goto FailSetDevTblEntry;
}
}
// Set Configuration Value
rcode = pUsb->setConf(bAddress, 0, bConfNum);
if (rcode)
{
goto FailSetConf;
}
TRACE_USBHOST(printf("ADK::Init : ADK device configured successfully\r\n");)
ready = true;
return 0;
}
// Probe device - get accessory protocol revision
delay(1);
rcode = getProto((uint8_t*)&adkproto);
#if defined(XOOM)
// Added by Jaylen Scott Vanorden
if (rcode)
{
TRACE_USBHOST(printf("ADK::Init : Got 1st bad code for config: %lu\r\n", rcode);)
// Try once more
rcode = getProto((uint8_t*)&adkproto );
}
#endif
if (rcode)
{
goto FailGetProto;
}
TRACE_USBHOST(printf("ADK::Init : DK protocol rev. %lu", adkproto);)
// Send ID strings
sendStr(ACCESSORY_STRING_MANUFACTURER, manufacturer);
sendStr(ACCESSORY_STRING_MODEL, model);
sendStr(ACCESSORY_STRING_DESCRIPTION, description);
sendStr(ACCESSORY_STRING_VERSION, version);
sendStr(ACCESSORY_STRING_URI, uri);
sendStr(ACCESSORY_STRING_SERIAL, serial);
// Switch to accessory mode
// The Android phone will reset
rcode = switchAcc();
if (rcode)
{
goto FailSwAcc;
}
rcode = -1;
goto SwAttempt; // Switch to accessory mode
// Diagnostic messages
FailGetDevDescr:
TRACE_USBHOST(printf("ADK::Init getDevDescr : ");)
goto Fail;
FailSetDevTblEntry:
TRACE_USBHOST(printf("ADK::Init setDevTblEn : ");)
goto Fail;
FailGetProto:
TRACE_USBHOST(printf("ADK::Init getProto : ");)
goto Fail;
FailSwAcc:
TRACE_USBHOST(printf("ADK::Init swAcc : ");)
goto Fail;
SwAttempt:
TRACE_USBHOST(printf("ADK::Init Accessory mode switch attempt : ");)
goto Fail;
FailGetConfDescr:
TRACE_USBHOST(printf("ADK::Init getConf : ");)
goto Fail;
FailSetConf:
TRACE_USBHOST(printf("ADK::Init setConf : ");)
goto Fail;
Fail:
TRACE_USBHOST(printf("error code: %lu\r\n", rcode);)
Release();
return rcode;
}
/**
* \brief Extract bulk-IN and bulk-OUT endpoint information from configuration
* descriptor.
*
* \param conf Configuration number.
* \param iface Interface number.
* \param alt Alternate setting.
* \param proto Protocol version used.
* \param pep Pointer to endpoint descriptor.
*/
void ADK::EndpointXtract(uint32_t conf, uint32_t iface, uint32_t alt, uint32_t proto, const USB_ENDPOINT_DESCRIPTOR *pep)
{
if (bNumEP == 3)
{
return;
}
bConfNum = conf;
uint32_t index = 0;
uint32_t pipe = 0;
if ((pep->bmAttributes & 0x02) == 2)
{
index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
}
// Fill in the endpoint info structure
epInfo[index].deviceEpNum = pep->bEndpointAddress & 0x0F;
epInfo[index].maxPktSize = pep->wMaxPacketSize;
TRACE_USBHOST(printf("ADK::EndpointXtract : Found new endpoint\r\n");)
TRACE_USBHOST(printf("ADK::EndpointXtract : deviceEpNum: %lu\r\n", epInfo[index].deviceEpNum);)
TRACE_USBHOST(printf("ADK::EndpointXtract : maxPktSize: %lu\r\n", epInfo[index].maxPktSize);)
TRACE_USBHOST(printf("ADK::EndpointXtract : index: %lu\r\n", index);)
if (index == epDataInIndex)
pipe = UHD_Pipe_Alloc(bAddress, epInfo[index].deviceEpNum, UOTGHS_HSTPIPCFG_PTYPE_BLK, UOTGHS_HSTPIPCFG_PTOKEN_IN, epInfo[index].maxPktSize, 0, UOTGHS_HSTPIPCFG_PBK_1_BANK);
else if (index == epDataOutIndex)
pipe = UHD_Pipe_Alloc(bAddress, epInfo[index].deviceEpNum, UOTGHS_HSTPIPCFG_PTYPE_BLK, UOTGHS_HSTPIPCFG_PTOKEN_OUT, epInfo[index].maxPktSize, 0, UOTGHS_HSTPIPCFG_PBK_1_BANK);
// Ensure pipe allocation is okay
if (pipe == 0)
{
TRACE_USBHOST(printf("ADK::EndpointXtract : Pipe allocation failure\r\n");)
// Enumeration failed, so user should not perform write/read since isConnected will return false
return;
}
epInfo[index].hostPipeNum = pipe;
bNumEP++;
}
/**
* \brief Release USB allocated resources (pipes and address).
*
* \note Release call is made from USBHost.task() on disconnection events.
* \note Release call is made from Init() on enumeration failure.
*
* \return Always 0.
*/
uint32_t ADK::Release()
{
// Free allocated host pipes
UHD_Pipe_Free(epInfo[epDataInIndex].hostPipeNum);
UHD_Pipe_Free(epInfo[epDataOutIndex].hostPipeNum);
// Free allocated USB address
pUsb->GetAddressPool().FreeAddress(bAddress);
// Must have to be reset to 1
bNumEP = 1;
bAddress = 0;
ready = false;
return 0;
}
/**
* \brief Read from ADK.
*
* \param nreadbytes Return value containing the number of read bytes.
* \param datalen Buffer length.
* \param dataptr Buffer to store the incoming data.
*
* \return 0 on success, error code otherwise.
*/
uint32_t ADK::read(uint32_t *nreadbytes, uint32_t datalen, uint8_t *dataptr)
{
*nreadbytes = datalen;
return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].deviceEpNum, nreadbytes, dataptr);
}
/**
* \brief Write to ADK.
*
* \param datalen Amount of data to send. This parameter shall not exceed
* dataptr length.
* \param dataptr Buffer containing the data to be sent.
*
* \return 0 on success, error code otherwise.
*/
uint32_t ADK::write(uint32_t datalen, uint8_t *dataptr)
{
return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].deviceEpNum, datalen, dataptr);
}

150
libraries/USBHost/src/adk.h Normal file
View File

@ -0,0 +1,150 @@
/* 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
*/
/* Google ADK interface support header */
#ifndef ADK_H_INCLUDED
#define ADK_H_INCLUDED
#include <stdint.h>
#include "usb_ch9.h"
#include "Usb.h"
#include "hid.h"
#include "Arduino.h"
#include "confdescparser.h"
#define ADK_VID 0x18D1
#define ADK_PID 0x2D00
#define ADB_PID 0x2D01
#define XOOM //enables repeating getProto() and getConf() attempts
//necessary for slow devices such as Motorola XOOM
//defined by default, can be commented out to save memory
/* Requests */
#define ADK_GETPROTO 51 //check USB accessory protocol version
#define ADK_SENDSTR 52 //send identifying string
#define ADK_ACCSTART 53 //start device in accessory mode
#define bmREQ_ADK_GET USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_VENDOR|USB_SETUP_RECIPIENT_DEVICE
#define bmREQ_ADK_SEND USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_VENDOR|USB_SETUP_RECIPIENT_DEVICE
#define ACCESSORY_STRING_MANUFACTURER 0
#define ACCESSORY_STRING_MODEL 1
#define ACCESSORY_STRING_DESCRIPTION 2
#define ACCESSORY_STRING_VERSION 3
#define ACCESSORY_STRING_URI 4
#define ACCESSORY_STRING_SERIAL 5
#define ADK_MAX_ENDPOINTS 3 //endpoint 0, bulk_IN, bulk_OUT
/**
* \class ADK definition.
*/
class ADK : public USBDeviceConfig, public UsbConfigXtracter
{
private:
/* ID strings */
const char* manufacturer;
const char* model;
const char* description;
const char* version;
const char* uri;
const char* serial;
/* ADK proprietary requests */
uint32_t getProto(uint8_t* adkproto);
uint32_t sendStr(uint32_t index, const char* str);
uint32_t switchAcc(void);
protected:
static const uint32_t epDataInIndex; // DataIn endpoint index
static const uint32_t epDataOutIndex; // DataOUT endpoint index
/* Mandatory members */
USBHost *pUsb;
uint32_t bAddress; // Device USB address
uint32_t bConfNum; // configuration number
uint32_t bNumEP; // total number of EP in the configuration
bool ready;
/* Endpoint data structure describing the device EP */
EpInfo epInfo[ADK_MAX_ENDPOINTS];
public:
ADK(USBHost *pUsb, const char* pmanufacturer,
const char* pmodel,
const char* pdescription,
const char* pversion,
const char* puri,
const char* pserial);
// Methods for receiving and sending data
uint32_t read(uint32_t *nreadbytes, uint32_t datalen, uint8_t *dataptr);
uint32_t write(uint32_t datalen, uint8_t *dataptr);
// USBDeviceConfig implementation
virtual uint32_t Init(uint32_t parent, uint32_t port, uint32_t lowspeed);
virtual uint32_t Release();
virtual uint32_t Poll() { return 0; }; // not implemented
virtual uint32_t GetAddress() { return bAddress; };
virtual bool isReady() { return ready; };
// UsbConfigXtracter implementation
virtual void EndpointXtract(uint32_t conf, uint32_t iface, uint32_t alt, uint32_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
};
/**
* \brief Get ADK protocol version.
*
* \param adkproto Empty buffer to be filled by getProto (2 bytes) with the ADK
* protocol version value.
*
* \return 0 on success, error code otherwise.
*/
inline uint32_t ADK::getProto(uint8_t* adkproto)
{
return (pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_GET, ADK_GETPROTO, 0, 0, 0, 2, 2, adkproto, NULL));
}
/**
* \brief Send ADK string.
*
* \param index String index.
* \param str String to send.
*
* \return 0 on success, error code otherwise.
*/
inline uint32_t ADK::sendStr(uint32_t index, const char* str)
{
return (pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_SENDSTR, 0, 0, index, strlen(str) + 1, strlen(str) + 1, (uint8_t*)str, NULL));
}
/**
* \brief Send a switch to accessory mode request.
*
* \return 0 on success, error code otherwise.
*/
inline uint32_t ADK::switchAcc(void)
{
return (pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_ACCSTART, 0, 0, 0, 0, 0, NULL, NULL));
}
#endif /* ADK_H_INCLUDED */

View File

@ -0,0 +1,241 @@
/* 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 Abstract UsbConfigXtracter definition.
*
* \note This class is used for extracting USB endpoint descriptors.
*/
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
/**
* \class ConfigDescParser definition.
*
* \note This class is used for parsing configuration descriptors.
*/
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);
};
/**
* \brief ConfigDescParser class constructor.
*
* \param xtractor Is saved as ConfigDescParser attribute and later used as a
* callback for parsing the endpoint descriptors.
*
* \note During enumeration stage, all supported USB classes invoke
* ConfigDescParser with "this" as parameter, meaning that one class is also
* responsible for parsing its endpoint descriptors. This makes sense since
* each USB class handles different number of endpoints and configurations.
* For instance see ADK::Init from ADK class.
*/
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);
};
/**
* \brief Parse a complete USB configuration descriptor.
*
* \param len Buffer length.
* \param pbuf Buffer containing the configuration descriptor.
* \param offset Current offset position.
*/
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;
}
/**
* \brief Parse a USB 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.
*
* \note This method should not be called directly, use Parse() instead.
*
* \param pcntdn Buffer length.
* \param pp Buffer containing the configuration descriptor.
*
* \return true if data remains in the buffer for parsing, false otherwise.
*/
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;
}
/**
* \brief Print HID descriptor.
*
* \note TRACE_USBHOST macro must be enabled. See Usb.h for reference.
*
* \param pDesc Pointer to HID descriptor.
*/
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)
{
TRACE_USBHOST(printf("ConfigDescParser::PrintHidDescriptor : bDescLength: %d\r\n", pDesc->bLength);)
TRACE_USBHOST(printf("ConfigDescParser::PrintHidDescriptor : bDescriptorType: %d\r\n", pDesc->bDescriptorType);)
TRACE_USBHOST(printf("ConfigDescParser::PrintHidDescriptor : bcdHID: %d\r\n", pDesc->bcdHID);)
TRACE_USBHOST(printf("ConfigDescParser::PrintHidDescriptor : bCountryCode: %d\r\n", pDesc->bCountryCode);)
TRACE_USBHOST(printf("ConfigDescParser::PrintHidDescriptor : bNumDescriptors: %d\r\n", pDesc->bNumDescriptors);)
TRACE_USBHOST(printf("ConfigDescParser::PrintHidDescriptor : bDescrType: %d\r\n", pDesc->bDescrType);)
TRACE_USBHOST(printf("ConfigDescParser::PrintHidDescriptor : wDescriptorLength: %d\r\n", pDesc->wDescriptorLength);)
for (uint32_t i = 0; i < pDesc->bNumDescriptors; ++i)
{
HID_CLASS_DESCRIPTOR_LEN_AND_TYPE *pLT = (HID_CLASS_DESCRIPTOR_LEN_AND_TYPE*)&(pDesc->bDescrType);
TRACE_USBHOST(printf("ConfigDescParser::PrintHidDescriptor : bDescrType: %d\r\n", pLT[i].bDescrType);)
TRACE_USBHOST(printf("ConfigDescParser::PrintHidDescriptor : wDescriptorLength: %d\r\n", pLT[i].wDescriptorLength);)
}
}
#endif /* CONFDESCPARSER_H_INCLUDED */

202
libraries/USBHost/src/hid.h Normal file
View File

@ -0,0 +1,202 @@
/* 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
/**
* \brief HidItemPrefix definition.
*/
struct HidItemPrefix // Not used
{
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
/**
* \brief MainItemIOFeature definition.
*/
struct MainItemIOFeature // Not used
{
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 Abstract HIDReportParser definition.
*
* \note This class is used to implement HID report parsing.
*/
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 definition.
*/
class HID : public USBDeviceConfig, public UsbConfigXtracter
{
protected:
USBHost *pUsb; // USB class instance pointer
uint32_t bAddress; // address
protected:
static const uint32_t epInterruptInIndex = 1; // InterruptIN endpoint index
static const uint32_t epInterruptOutIndex = 2; // InterruptOUT endpoint index
static const uint32_t maxHidInterfaces = 3;
static const uint32_t maxEpPerInterface = 2;
static const uint32_t totalEndpoints = (maxHidInterfaces * maxEpPerInterface + 1);
void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);
void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc);
virtual HIDReportParser* GetReportParser(uint32_t id) { return 0; };
public:
HID(USBHost *pusb) : pUsb(pusb) {};
const USBHost* GetUsb() { return pUsb; };
virtual bool SetReportParser(uint32_t id, HIDReportParser *prs) { return false; };
uint32_t SetProtocol(uint32_t iface, uint32_t protocol);
uint32_t GetProtocol(uint32_t iface, uint8_t* dataptr);
uint32_t GetIdle(uint32_t iface, uint32_t reportID, uint8_t* dataptr);
uint32_t SetIdle(uint32_t iface, uint32_t reportID, uint32_t duration);
uint32_t GetReportDescr(uint32_t ep, USBReadParser *parser = NULL);
uint32_t GetHidDescr(uint32_t ep, uint32_t nbytes, uint8_t* dataptr);
uint32_t GetReport(uint32_t ep, uint32_t iface, uint32_t report_type, uint32_t report_id, uint32_t nbytes, uint8_t* dataptr);
uint32_t SetReport(uint32_t ep, uint32_t iface, uint32_t report_type, uint32_t report_id, uint32_t nbytes, uint8_t* dataptr);
};
#endif /* HID_H_INCLUDED */

View File

@ -0,0 +1,141 @@
/* 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"
/**
* \brief Get HID report descriptor and parse it.
*
* \param ep USB device endpoint.
* \param parser Parser used to decode report.
*
* \return 0 on success, error code otherwise.
*/
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));
}
/**
* \brief Set HID report descriptor.
*
* \param ep USB device endpoint.
* \param iface Interface number.
* \param report_type HID report type.
* \param report_id HID report ID.
* \param nbytes Buffer length.
* \param dataptr Buffer containing the HID report to send.
*
* \return 0 on success, error code otherwise.
*/
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));
}
/**
* \brief Get HID report descriptor.
*
* \param ep USB device endpoint.
* \param iface Interface number.
* \param report_type HID report type.
* \param report_id HID report ID.
* \param nbytes Buffer length.
* \param dataptr Buffer containing the HID report to send.
*
* \return 0 on success, error code otherwise.
*/
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));
}
/**
* \brief Get HID idle status.
*
* \param iface Interface number.
* \param report_id HID report ID.
* \param dataptr Buffer to receive data. Size must be >= 1.
*
* \return 0 on success, error code otherwise.
*/
uint32_t HID::GetIdle(uint32_t iface, uint32_t report_id, uint8_t* dataptr)
{
return (pUsb->ctrlReq(bAddress, 0, bmREQ_HIDIN, HID_REQUEST_GET_IDLE, report_id, 0, iface, 0x0001, 0x0001, dataptr, NULL));
}
/**
* \brief Set HID idle status.
*
* \param iface Interface number.
* \param report_id HID report ID.
* \param duration Status duration.
*
* \return 0 on success, error code otherwise.
*/
uint32_t HID::SetIdle(uint32_t iface, uint32_t report_id, uint32_t duration)
{
return (pUsb->ctrlReq(bAddress, 0, bmREQ_HIDOUT, HID_REQUEST_SET_IDLE, report_id, duration, iface, 0x0000, 0x0000, NULL, NULL));
}
/**
* \brief Set HID protocol.
*
* \param iface Interface number.
* \param protocol Protocol value.
*
* \return 0 on success, error code otherwise.
*/
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));
}
/**
* \brief Get HID protocol.
*
* \param iface Interface number.
* \param dataptr Buffer used to store protocol value. Size must be >= 1.
*
* \return 0 on success, error code otherwise.
*/
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));
}
/**
* \brief Print HID descriptor.
*
* \note TRACE_USBHOST macro must be enabled. See Usb.h for reference.
*
* \param pDesc Pointer to HID descriptor.
*/
void HID::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc)
{
TRACE_USBHOST(printf("HID::PrintHidDescriptor : bDescLength: %d\r\n", pDesc->bLength);)
TRACE_USBHOST(printf("HID::PrintHidDescriptor : bDescriptorType: %d\r\n", pDesc->bDescriptorType);)
TRACE_USBHOST(printf("HID::PrintHidDescriptor : bcdHID: %d\r\n", pDesc->bcdHID);)
TRACE_USBHOST(printf("HID::PrintHidDescriptor : bCountryCode: %d\r\n", pDesc->bCountryCode);)
TRACE_USBHOST(printf("HID::PrintHidDescriptor : bNumDescriptors: %d\r\n", pDesc->bNumDescriptors);)
TRACE_USBHOST(printf("HID::PrintHidDescriptor : bDescrType: %d\r\n", pDesc->bDescrType);)
TRACE_USBHOST(printf("HID::PrintHidDescriptor : wDescriptorLength: %d\r\n", pDesc->wDescriptorLength);)
}

View File

@ -0,0 +1,192 @@
/* 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"
/**
* \brief Parse HID mouse report.
*
* \param hid HID device pointer.
* \param is_rpt_id True if this is a report ID.
* \param len Buffer length.
* \param buf Buffer containing report data.
*/
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];
};
/**
* \brief Parse HID keyboard report.
*
* \param hid HID device pointer.
* \param is_rpt_id True if this is a report ID.
* \param len Buffer length.
* \param buf Buffer containing report data.
*/
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];
};
/**
* \brief Handle keyboard locking keys and manage keyboard leds using USB
* report.
*
* \param hid HID device pointer.
* \param key Locking key.
*
* \return 0 on success, error code otherwise.
*/
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 };
/**
* \brief Manage keyboard OEM to ASCII conversion.
*
* \param mod Keyboard modifier.
* \param key Key value to convert.
*
* \return Keyboard corresponding ASCII value on success, 0 otherwise.
*/
uint8_t KeyboardReportParser::OemToAscii(uint8_t mod, uint8_t key)
{
uint8_t shift = (mod & 0x22);
// [a-z]
if (key > 0x03 && key < 0x1e)
{
// Upper case letters
if ( (kbdLockingKeys.kbdLeds.bmCapsLock == 0 && (mod & 2)) ||
(kbdLockingKeys.kbdLeds.bmCapsLock == 1 && (mod & 2) == 0) )
return (key - 4 + 'A');
// Lower case letters
else
return (key - 4 + 'a');
}
// Numbers
else if (key > 0x1d && key < 0x27)
{
if (shift)
return (numKeys[key - 0x1e]);
else
return (key - 0x1e + '1');
}
// Keypad Numbers
else if (key > 0x58 && key < 0x62)
{
if (kbdLockingKeys.kbdLeds.bmNumLock == 1)
return (key - 0x59 + '1');
}
else if (key > 0x2c && key < 0x39)
return ((shift) ? symKeysUp[key-0x2d] : symKeysLo[key-0x2d]);
else if (key > 0x53 && key < 0x59)
return padKeys[key - 0x54];
else
{
switch (key)
{
case KEY_SPACE: return (0x20);
case KEY_ENTER: return (0x13);
case KEY_ZERO: return ((shift) ? ')' : '0');
case KEY_ZERO2: return ((kbdLockingKeys.kbdLeds.bmNumLock == 1) ? '0' : 0);
case KEY_PERIOD: return ((kbdLockingKeys.kbdLeds.bmNumLock == 1) ? '.' : 0);
}
}
return 0;
}

View File

@ -0,0 +1,553 @@
/* 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
/**
* \brief MOUSEINFO definition.
*/
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 definition.
*/
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) {};
};
/**
* \brief MODIFIERKEYS definition.
*/
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;
};
/**
* \brief KBDINFO definition.
*/
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];
};
/**
* \brief KBDLEDS definition.
*/
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
// Clear compiler warning
#ifdef KEY_CAPS_LOCK
#undef KEY_CAPS_LOCK
#endif
#define KEY_CAPS_LOCK 0x39
#define KEY_SCROLL_LOCK 0x47
/**
* \class KeyboardReportParser definition.
*/
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
/**
* \class HIDBoot definition.
*/
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; };
// 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);
};
/**
* \brief HIDBoot class constructor.
*/
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);
}
/**
* \brief Initialize HIDBoot class.
*/
template <const uint8_t BOOT_PROTOCOL>
void HIDBoot<BOOT_PROTOCOL>::Initialize()
{
for (uint32_t i = 0; i < totalEndpoints; ++i)
{
epInfo[i].deviceEpNum = 0;
epInfo[i].hostPipeNum = 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;
}
/**
* \brief Initialize connection to an HID device.
*
* \param parent USB device address of the Parent device.
* \param port USB device base address.
* \param lowspeed USB device speed.
*
* \return 0 on success, error code otherwise.
*/
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 = 0;
EpInfo *oldep_ptr = 0;
uint32_t len = 0;
uint32_t num_of_conf = 0; // number of configurations
AddressPool &addrPool = pUsb->GetAddressPool();
TRACE_USBHOST(printf("HIDBoot::Init\r\n");)
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)
{
ConfigDescParser<
USB_CLASS_HID,
HID_BOOT_INTF_SUBCLASS,
BOOT_PROTOCOL,
CP_MASK_COMPARE_ALL> confDescrParser(this);
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:
TRACE_USBHOST(printf("HIDBoot::Init getDevDescr : ");)
goto Fail;
FailSetDevTblEntry:
TRACE_USBHOST(printf("HIDBoot::Init setDevTblEn : ");)
goto Fail;
FailSetProtocol:
TRACE_USBHOST(printf("HIDBoot::Init SetProto : ");)
goto Fail;
FailSetIdle:
TRACE_USBHOST(printf("HIDBoot::Init SetIdle : ");)
goto Fail;
FailSetConfDescr:
TRACE_USBHOST(printf("HIDBoot::Init setConf : ");)
goto Fail;
Fail:
TRACE_USBHOST(printf("error code: %lu\r\n", rcode);)
Release();
return rcode;
}
/**
* \brief Extract interrupt-IN endpoint information from configuration
* descriptor.
*
* \param conf Configuration number.
* \param iface Interface number.
* \param alt Alternate setting.
* \param proto Protocol version used.
* \param pep Pointer to endpoint descriptor.
*/
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;
bConfNum = conf;
bIfaceNum = iface;
uint32_t index = 0;
uint32_t pipe = 0;
if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
{
index = epInterruptInIndex;
// Fill in the endpoint info structure
epInfo[index].deviceEpNum = (pep->bEndpointAddress & 0x0F);
epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
epInfo[index].epAttribs = 0;
TRACE_USBHOST(printf("HIDBoot::EndpointXtract : Found new endpoint\r\n");)
TRACE_USBHOST(printf("HIDBoot::EndpointXtract : deviceEpNum: %lu\r\n", epInfo[index].deviceEpNum);)
TRACE_USBHOST(printf("HIDBoot::EndpointXtract : maxPktSize: %lu\r\n", epInfo[index].maxPktSize);)
TRACE_USBHOST(printf("HIDBoot::EndpointXtract : index: %lu\r\n", index);)
// Ensure pipe allocation is okay
pipe = UHD_Pipe_Alloc(bAddress, epInfo[index].deviceEpNum, UOTGHS_HSTPIPCFG_PTYPE_INTRPT, UOTGHS_HSTPIPCFG_PTOKEN_IN, epInfo[index].maxPktSize, 10, UOTGHS_HSTPIPCFG_PBK_1_BANK);
if (pipe == 0)
{
TRACE_USBHOST(printf("HIDBoot::EndpointXtract : Pipe allocation failure\r\n");)
// Enumeration failed
return;
}
epInfo[index].hostPipeNum = pipe;
bNumEP++;
}
}
/**
* \brief Release USB allocated resources (pipes and address).
*
* \note Release call is made from USBHost.task() on disconnection events.
* \note Release call is made from Init() on enumeration failure.
*
* \return Always 0.
*/
template <const uint8_t BOOT_PROTOCOL>
uint32_t HIDBoot<BOOT_PROTOCOL>::Release()
{
// Free allocated host pipes
UHD_Pipe_Free(epInfo[epInterruptInIndex].hostPipeNum);
// Free allocated USB address
pUsb->GetAddressPool().FreeAddress(bAddress);
bConfNum = 0;
bIfaceNum = 0;
bNumEP = 1;
bAddress = 0;
qNextPollTime = 0;
bPollEnable = false;
return 0;
}
/**
* \brief Poll USB device activity.
*
* \note Poll call is periodically made from USBHost.task().
*
* \return 0 on success, error code otherwise.
*/
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].deviceEpNum, &read, buf);
if (rcode)
{
return rcode;
}
if (pRptParser)
pRptParser->Parse((HID*)this, 0, (uint32_t)read, buf);
}
return rcode;
}
#endif /* HIDBOOT_H_INCLUDED */

View File

@ -0,0 +1,976 @@
/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
This software may be distributed and modified under the terms of the GNU
General Public License version 2 (GPL2) as published by the Free Software
Foundation and appearing in the file GPL2.TXT included in the packaging of
this file. Please note that GPL2 Section 2[b] requires that all works based
on this software must also be made publicly available under the terms of
the GPL2 ("Copyleft").
Contact information
-------------------
Circuits At Home, LTD
Web : http://www.circuitsathome.com
e-mail : support@circuitsathome.com
*/
#ifndef HIDUSAGESTR_H_INCLUDED
#define HIDUSAGESTR_H_INCLUDED
const char pstrSpace [] = " ";
const char pstrCRLF [] = "\r\n";
const char pstrSingleTab [] = "\t";
const char pstrDoubleTab [] = "\t\t";
const char pstrTripleTab [] = "\t\t\t";
// Usage Page String Titles
const char pstrUsagePageUndefined [] = "Undef";
const char pstrUsagePageGenericDesktopControls [] = "Gen Desktop Ctrls";
const char pstrUsagePageSimulationControls [] = "Simu Ctrls";
const char pstrUsagePageVRControls [] = "VR Ctrls";
const char pstrUsagePageSportControls [] = "Sport Ctrls";
const char pstrUsagePageGameControls [] = "Game Ctrls";
const char pstrUsagePageGenericDeviceControls [] = "Gen Dev Ctrls";
const char pstrUsagePageKeyboardKeypad [] = "Kbrd/Keypad";
const char pstrUsagePageLEDs [] = "LEDs";
const char pstrUsagePageButton [] = "Button";
const char pstrUsagePageOrdinal [] = "Ordinal";
const char pstrUsagePageTelephone [] = "Tel";
const char pstrUsagePageConsumer [] = "Consumer";
const char pstrUsagePageDigitizer [] = "Digitizer";
const char pstrUsagePagePID [] = "PID";
const char pstrUsagePageUnicode [] = "Unicode";
const char pstrUsagePageAlphaNumericDisplay [] = "Alpha Num Disp";
const char pstrUsagePageMedicalInstruments [] = "Medical Instr";
const char pstrUsagePageMonitor [] = "Monitor";
const char pstrUsagePagePower [] = "Power";
const char pstrUsagePageBarCodeScanner [] = "Bar Code Scan";
const char pstrUsagePageScale [] = "Scale";
const char pstrUsagePageMSRDevices [] = "Magn Stripe Read Dev";
const char pstrUsagePagePointOfSale [] = "POS";
const char pstrUsagePageCameraControl [] = "Cam Ctrl";
const char pstrUsagePageArcade [] = "Arcade";
const char pstrUsagePageReserved [] = "Reserved";
const char pstrUsagePageVendorDefined [] = "Vendor Def";
// Generic Desktop Controls Page
const char pstrUsagePointer [] = "Pointer";
const char pstrUsageMouse [] = "Mouse";
const char pstrUsageJoystick [] = "Joystick";
const char pstrUsageGamePad [] = "Game Pad";
const char pstrUsageKeyboard [] = "Kbrd";
const char pstrUsageKeypad [] = "Keypad";
const char pstrUsageMultiAxisController [] = "Multi-axis Ctrl";
const char pstrUsageTabletPCSystemControls [] = "Tablet PC Sys Ctrls";
const char pstrUsageX [] = "X";
const char pstrUsageY [] = "Y";
const char pstrUsageZ [] = "Z";
const char pstrUsageRx [] = "Rx";
const char pstrUsageRy [] = "Ry";
const char pstrUsageRz [] = "Rz";
const char pstrUsageSlider [] = "Slider";
const char pstrUsageDial [] = "Dial";
const char pstrUsageWheel [] = "Wheel";
const char pstrUsageHatSwitch [] = "Hat Switch";
const char pstrUsageCountedBuffer [] = "Counted Buf";
const char pstrUsageByteCount [] = "Byte Count";
const char pstrUsageMotionWakeup [] = "Motion Wakeup";
const char pstrUsageStart [] = "Start";
const char pstrUsageSelect [] = "Sel";
const char pstrUsageVx [] = "Vx";
const char pstrUsageVy [] = "Vy";
const char pstrUsageVz [] = "Vz";
const char pstrUsageVbrx [] = "Vbrx";
const char pstrUsageVbry [] = "Vbry";
const char pstrUsageVbrz [] = "Vbrz";
const char pstrUsageVno [] = "Vno";
const char pstrUsageFeatureNotification [] = "Feature Notif";
const char pstrUsageResolutionMultiplier [] = "Res Mult";
const char pstrUsageSystemControl [] = "Sys Ctrl";
const char pstrUsageSystemPowerDown [] = "Sys Pwr Down";
const char pstrUsageSystemSleep [] = "Sys Sleep";
const char pstrUsageSystemWakeup [] = "Sys Wakeup";
const char pstrUsageSystemContextMenu [] = "Sys Context Menu";
const char pstrUsageSystemMainMenu [] = "Sys Main Menu";
const char pstrUsageSystemAppMenu [] = "Sys App Menu";
const char pstrUsageSystemMenuHelp [] = "Sys Menu Help";
const char pstrUsageSystemMenuExit [] = "Sys Menu Exit";
const char pstrUsageSystemMenuSelect [] = "Sys Menu Select";
const char pstrUsageSystemMenuRight [] = "Sys Menu Right";
const char pstrUsageSystemMenuLeft [] = "Sys Menu Left";
const char pstrUsageSystemMenuUp [] = "Sys Menu Up";
const char pstrUsageSystemMenuDown [] = "Sys Menu Down";
const char pstrUsageSystemColdRestart [] = "Sys Cold Restart";
const char pstrUsageSystemWarmRestart [] = "Sys Warm Restart";
const char pstrUsageDPadUp [] = "D-pad Up";
const char pstrUsageDPadDown [] = "D-pad Down";
const char pstrUsageDPadRight [] = "D-pad Right";
const char pstrUsageDPadLeft [] = "D-pad Left";
const char pstrUsageSystemDock [] = "Sys Dock";
const char pstrUsageSystemUndock [] = "Sys Undock";
const char pstrUsageSystemSetup [] = "Sys Setup";
const char pstrUsageSystemBreak [] = "Sys Break";
const char pstrUsageSystemDebuggerBreak [] = "Sys Dbg Brk";
const char pstrUsageApplicationBreak [] = "App Break";
const char pstrUsageApplicationDebuggerBreak [] = "App Dbg Brk";
const char pstrUsageSystemSpeakerMute [] = "Sys Spk Mute";
const char pstrUsageSystemHibernate [] = "Sys Hiber";
const char pstrUsageSystemDisplayInvert [] = "Sys Disp Inv";
const char pstrUsageSystemDisplayInternal [] = "Sys Disp Int";
const char pstrUsageSystemDisplayExternal [] = "Sys Disp Ext";
const char pstrUsageSystemDisplayBoth [] = "Sys Disp Both";
const char pstrUsageSystemDisplayDual [] = "Sys Disp Dual";
const char pstrUsageSystemDisplayToggleIntExt [] = "Sys Disp Tgl Int/Ext";
const char pstrUsageSystemDisplaySwapPriSec [] = "Sys Disp Swap Pri/Sec";
const char pstrUsageSystemDisplayLCDAutoscale [] = "Sys Disp LCD Autoscale";
// Simulation Controls Page
const char pstrUsageFlightSimulationDevice [] = "Flight Simu Dev";
const char pstrUsageAutomobileSimulationDevice [] = "Auto Simu Dev";
const char pstrUsageTankSimulationDevice [] = "Tank Simu Dev";
const char pstrUsageSpaceshipSimulationDevice [] = "Space Simu Dev";
const char pstrUsageSubmarineSimulationDevice [] = "Subm Simu Dev";
const char pstrUsageSailingSimulationDevice [] = "Sail Simu Dev";
const char pstrUsageMotocicleSimulationDevice [] = "Moto Simu Dev";
const char pstrUsageSportsSimulationDevice [] = "Sport Simu Dev";
const char pstrUsageAirplaneSimulationDevice [] = "Airp Simu Dev";
const char pstrUsageHelicopterSimulationDevice [] = "Heli Simu Dev";
const char pstrUsageMagicCarpetSimulationDevice [] = "Magic Carpet Simu Dev";
const char pstrUsageBicycleSimulationDevice [] = "Bike Simu Dev";
const char pstrUsageFlightControlStick [] = "Flight Ctrl Stick";
const char pstrUsageFlightStick [] = "Flight Stick";
const char pstrUsageCyclicControl [] = "Cyclic Ctrl";
const char pstrUsageCyclicTrim [] = "Cyclic Trim";
const char pstrUsageFlightYoke [] = "Flight Yoke";
const char pstrUsageTrackControl [] = "Track Ctrl";
const char pstrUsageAileron [] = "Aileron";
const char pstrUsageAileronTrim [] = "Aileron Trim";
const char pstrUsageAntiTorqueControl [] = "Anti-Torque Ctrl";
const char pstrUsageAutopilotEnable [] = "Autopilot Enable";
const char pstrUsageChaffRelease [] = "Chaff Release";
const char pstrUsageCollectiveControl [] = "Collective Ctrl";
const char pstrUsageDiveBrake [] = "Dive Brake";
const char pstrUsageElectronicCountermeasures [] = "El Countermeasures";
const char pstrUsageElevator [] = "Elevator";
const char pstrUsageElevatorTrim [] = "Elevator Trim";
const char pstrUsageRudder [] = "Rudder";
const char pstrUsageThrottle [] = "Throttle";
const char pstrUsageFlightCommunications [] = "Flight Comm";
const char pstrUsageFlareRelease [] = "Flare Release";
const char pstrUsageLandingGear [] = "Landing Gear";
const char pstrUsageToeBrake [] = "Toe Brake";
const char pstrUsageTrigger [] = "Trigger";
const char pstrUsageWeaponsArm [] = "Weapons Arm";
const char pstrUsageWeaponsSelect [] = "Weapons Sel";
const char pstrUsageWingFlaps [] = "Wing Flaps";
const char pstrUsageAccelerator [] = "Accel";
const char pstrUsageBrake [] = "Brake";
const char pstrUsageClutch [] = "Clutch";
const char pstrUsageShifter [] = "Shifter";
const char pstrUsageSteering [] = "Steering";
const char pstrUsageTurretDirection [] = "Turret Dir";
const char pstrUsageBarrelElevation [] = "Barrel Ele";
const char pstrUsageDivePlane [] = "Dive Plane";
const char pstrUsageBallast [] = "Ballast";
const char pstrUsageBicycleCrank [] = "Bicycle Crank";
const char pstrUsageHandleBars [] = "Handle Bars";
const char pstrUsageFrontBrake [] = "Front Brake";
const char pstrUsageRearBrake [] = "Rear Brake";
// VR Controls Page
const char pstrUsageBelt [] = "Belt";
const char pstrUsageBodySuit [] = "Body Suit";
const char pstrUsageFlexor [] = "Flexor";
const char pstrUsageGlove [] = "Glove";
const char pstrUsageHeadTracker [] = "Head Track";
const char pstrUsageHeadMountedDisplay [] = "Head Disp";
const char pstrUsageHandTracker [] = "Hand Track";
const char pstrUsageOculometer [] = "Oculometer";
const char pstrUsageVest [] = "Vest";
const char pstrUsageAnimatronicDevice [] = "Animat Dev";
const char pstrUsageStereoEnable [] = "Stereo Enbl";
const char pstrUsageDisplayEnable [] = "Display Enbl";
// Sport Controls Page
const char pstrUsageBaseballBat [] = "Baseball Bat";
const char pstrUsageGolfClub [] = "Golf Club";
const char pstrUsageRowingMachine [] = "Rowing Mach";
const char pstrUsageTreadmill [] = "Treadmill";
const char pstrUsageOar [] = "Oar";
const char pstrUsageSlope [] = "Slope";
const char pstrUsageRate [] = "Rate";
const char pstrUsageStickSpeed [] = "Stick Speed";
const char pstrUsageStickFaceAngle [] = "Stick Face Ang";
const char pstrUsageStickHeelToe [] = "Stick Heel/Toe";
const char pstrUsageStickFollowThough [] = "Stick Flw Thru";
const char pstrUsageStickTempo [] = "Stick Tempo";
const char pstrUsageStickType [] = "Stick Type";
const char pstrUsageStickHeight [] = "Stick Hght";
const char pstrUsagePutter [] = "Putter";
const char pstrUsage1Iron [] = "1 Iron";
const char pstrUsage2Iron [] = "2 Iron";
const char pstrUsage3Iron [] = "3 Iron";
const char pstrUsage4Iron [] = "4 Iron";
const char pstrUsage5Iron [] = "5 Iron";
const char pstrUsage6Iron [] = "6 Iron";
const char pstrUsage7Iron [] = "7 Iron";
const char pstrUsage8Iron [] = "8 Iron";
const char pstrUsage9Iron [] = "9 Iron";
const char pstrUsage10Iron [] = "10 Iron";
const char pstrUsage11Iron [] = "11 Iron";
const char pstrUsageSandWedge [] = "Sand Wedge";
const char pstrUsageLoftWedge [] = "Loft Wedge";
const char pstrUsagePowerWedge [] = "Pwr Wedge";
const char pstrUsage1Wood [] = "1 Wood";
const char pstrUsage3Wood [] = "3 Wood";
const char pstrUsage5Wood [] = "5 Wood";
const char pstrUsage7Wood [] = "7 Wood";
const char pstrUsage9Wood [] = "9 Wood";
// Game Controls Page
const char pstrUsage3DGameController [] = "3D Game Ctrl";
const char pstrUsagePinballDevice [] = "Pinball Dev";
const char pstrUsageGunDevice [] = "Gun Dev";
const char pstrUsagePointOfView [] = "POV";
const char pstrUsageTurnRightLeft [] = "Turn Right Left";
const char pstrUsagePitchForwardBackward [] = "Pitch Fwd/Back";
const char pstrUsageRollRightLeft [] = "Roll Right/Left";
const char pstrUsageMoveRightLeft [] = "Move Right/Left";
const char pstrUsageMoveForwardBackward [] = "Move Fwd/Back";
const char pstrUsageMoveUpDown [] = "Move Up/Down";
const char pstrUsageLeanRightLeft [] = "Lean Right/Left";
const char pstrUsageLeanForwardBackward [] = "Lean Fwd/Back";
const char pstrUsageHeightOfPOV [] = "Height of POV";
const char pstrUsageFlipper [] = "Flipper";
const char pstrUsageSecondaryFlipper [] = "Second Flipper";
const char pstrUsageBump [] = "Bump";
const char pstrUsageNewGame [] = "New Game";
const char pstrUsageShootBall [] = "Shoot Ball";
const char pstrUsagePlayer [] = "Player";
const char pstrUsageGunBolt [] = "Gun Bolt";
const char pstrUsageGunClip [] = "Gun Clip";
const char pstrUsageGunSelector [] = "Gun Sel";
const char pstrUsageGunSingleShot [] = "Gun Sngl Shot";
const char pstrUsageGunBurst [] = "Gun Burst";
const char pstrUsageGunAutomatic [] = "Gun Auto";
const char pstrUsageGunSafety [] = "Gun Safety";
const char pstrUsageGamepadFireJump [] = "Gamepad Fire/Jump";
const char pstrUsageGamepadTrigger [] = "Gamepad Trig";
// Generic Device Controls Page
const char pstrUsageBatteryStrength [] = "Bat Strength";
const char pstrUsageWirelessChannel [] = "Wireless Ch";
const char pstrUsageWirelessID [] = "Wireless ID";
const char pstrUsageDiscoverWirelessControl [] = "Discover Wireless Ctrl";
const char pstrUsageSecurityCodeCharEntered [] = "Sec Code Char Entrd";
const char pstrUsageSecurityCodeCharErased [] = "Sec Code Char Erased";
const char pstrUsageSecurityCodeCleared [] = "Sec Code Cleared";
// LED Page
const char pstrUsageNumLock [] = "Num Lock";
const char pstrUsageCapsLock [] = "Caps Lock";
const char pstrUsageScrollLock [] = "Scroll Lock";
const char pstrUsageCompose [] = "Compose";
const char pstrUsageKana [] = "Kana";
const char pstrUsagePower [] = "Pwr";
const char pstrUsageShift [] = "Shift";
const char pstrUsageDoNotDisturb [] = "DND";
const char pstrUsageMute [] = "Mute";
const char pstrUsageToneEnable [] = "Tone Enbl";
const char pstrUsageHighCutFilter [] = "High Cut Fltr";
const char pstrUsageLowCutFilter [] = "Low Cut Fltr";
const char pstrUsageEqualizerEnable [] = "Eq Enbl";
const char pstrUsageSoundFieldOn [] = "Sound Field On";
const char pstrUsageSurroundOn [] = "Surround On";
const char pstrUsageRepeat [] = "Repeat";
const char pstrUsageStereo [] = "Stereo";
const char pstrUsageSamplingRateDetect [] = "Smpl Rate Detect";
const char pstrUsageSpinning [] = "Spinning";
const char pstrUsageCAV [] = "CAV";
const char pstrUsageCLV [] = "CLV";
const char pstrUsageRecordingFormatDetect [] = "Rec Format Detect";
const char pstrUsageOffHook [] = "Off Hook";
const char pstrUsageRing [] = "Ring";
const char pstrUsageMessageWaiting [] = "Msg Wait";
const char pstrUsageDataMode [] = "Data Mode";
const char pstrUsageBatteryOperation [] = "Bat Op";
const char pstrUsageBatteryOK [] = "Bat OK";
const char pstrUsageBatteryLow [] = "Bat Low";
const char pstrUsageSpeaker [] = "Speaker";
const char pstrUsageHeadSet [] = "Head Set";
const char pstrUsageHold [] = "Hold";
const char pstrUsageMicrophone [] = "Mic";
const char pstrUsageCoverage [] = "Coverage";
const char pstrUsageNightMode [] = "Night Mode";
const char pstrUsageSendCalls [] = "Send Calls";
const char pstrUsageCallPickup [] = "Call Pickup";
const char pstrUsageConference [] = "Conf";
const char pstrUsageStandBy [] = "Stand-by";
const char pstrUsageCameraOn [] = "Cam On";
const char pstrUsageCameraOff [] = "Cam Off";
const char pstrUsageOnLine [] = "On-Line";
const char pstrUsageOffLine [] = "Off-Line";
const char pstrUsageBusy [] = "Busy";
const char pstrUsageReady [] = "Ready";
const char pstrUsagePaperOut [] = "Paper Out";
const char pstrUsagePaperJam [] = "Paper Jam";
const char pstrUsageRemote [] = "Remote";
const char pstrUsageForward [] = "Fwd";
const char pstrUsageReverse [] = "Rev";
const char pstrUsageStop [] = "Stop";
const char pstrUsageRewind [] = "Rewind";
const char pstrUsageFastForward [] = "Fast Fwd";
const char pstrUsagePlay [] = "Play";
const char pstrUsagePause [] = "Pause";
const char pstrUsageRecord [] = "Rec";
const char pstrUsageError [] = "Error";
const char pstrUsageSelectedIndicator [] = "Usage Sel Ind";
const char pstrUsageInUseIndicator [] = "Usage In Use Ind";
const char pstrUsageMultiModeIndicator [] = "Usage Multi Mode Ind";
const char pstrUsageIndicatorOn [] = "Ind On";
const char pstrUsageIndicatorFlash [] = "Ind Flash";
const char pstrUsageIndicatorSlowBlink [] = "Ind Slow Blk";
const char pstrUsageIndicatorFastBlink [] = "Ind Fast Blk";
const char pstrUsageIndicatorOff [] = "Ind Off";
const char pstrUsageFlashOnTime [] = "Flash On Time";
const char pstrUsageSlowBlinkOnTime [] = "Slow Blk On Time";
const char pstrUsageSlowBlinkOffTime [] = "Slow Blk Off Time";
const char pstrUsageFastBlinkOnTime [] = "Fast Blk On Time";
const char pstrUsageFastBlinkOffTime [] = "Fast Blk Off Time";
const char pstrUsageIndicatorColor [] = "Usage Ind Color";
const char pstrUsageIndicatorRed [] = "Ind Red";
const char pstrUsageIndicatorGreen [] = "Ind Green";
const char pstrUsageIndicatorAmber [] = "Ind Amber";
const char pstrUsageGenericIndicator [] = "Gen Ind";
const char pstrUsageSystemSuspend [] = "Sys Suspend";
const char pstrUsageExternalPowerConnected [] = "Ext Pwr Conn";
// Telephony Usage Page
const char pstrUsagePhone [] = "Phone";
const char pstrUsageAnsweringMachine [] = "Answ Mach";
const char pstrUsageMessageControls [] = "Msg Ctrls";
const char pstrUsageHandset [] = "Handset";
const char pstrUsageHeadset [] = "Headset";
const char pstrUsageTelephonyKeyPad [] = "Tel Key Pad";
const char pstrUsageProgrammableButton [] = "Prog Button";
const char pstrUsageHookSwitch [] = "Hook Sw";
const char pstrUsageFlash [] = "Flash";
const char pstrUsageFeature [] = "Feature";
//const char pstrUsageHold [] = "Hold";
const char pstrUsageRedial [] = "Redial";
const char pstrUsageTransfer [] = "Transfer";
const char pstrUsageDrop [] = "Drop";
const char pstrUsagePark [] = "Park";
const char pstrUsageForwardCalls [] = "Fwd Calls";
const char pstrUsageAlternateFunction [] = "Alt Func";
const char pstrUsageLine [] = "Line";
const char pstrUsageSpeakerPhone [] = "Spk Phone";
//const char pstrUsageConference [] = "Conference";
const char pstrUsageRingEnable [] = "Ring Enbl";
const char pstrUsageRingSelect [] = "Ring Sel";
const char pstrUsagePhoneMute [] = "Phone Mute";
const char pstrUsageCallerID [] = "Caller ID";
const char pstrUsageSend [] = "Send";
const char pstrUsageSpeedDial [] = "Speed Dial";
const char pstrUsageStoreNumber [] = "Store Num";
const char pstrUsageRecallNumber [] = "Recall Num";
const char pstrUsagePhoneDirectory [] = "Phone Dir";
const char pstrUsageVoiceMail [] = "Voice Mail";
const char pstrUsageScreenCalls [] = "Screen Calls";
//const char pstrUsageDoNotDisturb [] = "Do Not Disturb";
const char pstrUsageMessage [] = "Msg";
const char pstrUsageAnswerOnOff [] = "Answer On/Off";
const char pstrUsageInsideDialTone [] = "Inside Dial Tone";
const char pstrUsageOutsideDialTone [] = "Outside Dial Tone";
const char pstrUsageInsideRingTone [] = "Inside Ring Tone";
const char pstrUsageOutsideRingTone [] = "Outside Ring Tone";
const char pstrUsagePriorityRingTone [] = "Prior Ring Tone";
const char pstrUsageInsideRingback [] = "Inside Ringback";
const char pstrUsagePriorityRingback [] = "Priority Ringback";
const char pstrUsageLineBusyTone [] = "Ln Busy Tone";
const char pstrUsageReorderTone [] = "Reorder Tone";
const char pstrUsageCallWaitingTone [] = "Call Wait Tone";
const char pstrUsageConfirmationTone1 [] = "Cnfrm Tone1";
const char pstrUsageConfirmationTone2 [] = "Cnfrm Tone2";
const char pstrUsageTonesOff [] = "Tones Off";
const char pstrUsageOutsideRingback [] = "Outside Ringback";
const char pstrUsageRinger [] = "Ringer";
const char pstrUsagePhoneKey0 [] = "0";
const char pstrUsagePhoneKey1 [] = "1";
const char pstrUsagePhoneKey2 [] = "2";
const char pstrUsagePhoneKey3 [] = "3";
const char pstrUsagePhoneKey4 [] = "4";
const char pstrUsagePhoneKey5 [] = "5";
const char pstrUsagePhoneKey6 [] = "6";
const char pstrUsagePhoneKey7 [] = "7";
const char pstrUsagePhoneKey8 [] = "8";
const char pstrUsagePhoneKey9 [] = "9";
const char pstrUsagePhoneKeyStar [] = "*";
const char pstrUsagePhoneKeyPound [] = "#";
const char pstrUsagePhoneKeyA [] = "A";
const char pstrUsagePhoneKeyB [] = "B";
const char pstrUsagePhoneKeyC [] = "C";
const char pstrUsagePhoneKeyD [] = "D";
// Consumer Usage Page
const char pstrUsageConsumerControl [] = "Consumer Ctrl";
const char pstrUsageNumericKeyPad [] = "Num Key Pad";
//const char pstrUsageProgrammableButton [] = "Prog Btn";
//const char pstrUsageMicrophone [] = "Mic";
const char pstrUsageHeadphone [] = "Headphone";
const char pstrUsageGraphicEqualizer [] = "Graph Eq";
const char pstrUsagePlus10 [] = "+10";
const char pstrUsagePlus100 [] = "+100";
const char pstrUsageAMPM [] = "AM/PM";
//const char pstrUsagePower [] = "Pwr";
const char pstrUsageReset [] = "Reset";
const char pstrUsageSleep [] = "Sleep";
const char pstrUsageSleepAfter [] = "Sleep After";
const char pstrUsageSleepMode [] = "Sleep Mode";
const char pstrUsageIllumination [] = "Illumin";
const char pstrUsageFunctionButtons [] = "Func Btns";
const char pstrUsageMenu [] = "Menu";
const char pstrUsageMenuPick [] = "Menu Pick";
const char pstrUsageMenuUp [] = "Menu Up";
const char pstrUsageMenuDown [] = "Menu Down";
const char pstrUsageMenuLeft [] = "Menu Left";
const char pstrUsageMenuRight [] = "Menu Right";
const char pstrUsageMenuEscape [] = "Menu Esc";
const char pstrUsageMenuValueIncrease [] = "Menu Val Inc";
const char pstrUsageMenuValueDecrease [] = "Menu Val Dec";
const char pstrUsageDataOnScreen [] = "Data On Scr";
const char pstrUsageClosedCaption [] = "Closed Cptn";
const char pstrUsageClosedCaptionSelect [] = "Closed Cptn Sel";
const char pstrUsageVCRTV [] = "VCR/TV";
const char pstrUsageBroadcastMode [] = "Brdcast Mode";
const char pstrUsageSnapshot [] = "Snapshot";
const char pstrUsageStill [] = "Still";
const char pstrUsageSelection [] = "Sel";
const char pstrUsageAssignSelection [] = "Assign Sel";
const char pstrUsageModeStep [] = "Mode Step";
const char pstrUsageRecallLast [] = "Recall Last";
const char pstrUsageEnterChannel [] = "Entr Channel";
const char pstrUsageOrderMovie [] = "Ord Movie";
const char pstrUsageChannel [] = "Channel";
const char pstrUsageMediaSelection [] = "Med Sel";
const char pstrUsageMediaSelectComputer [] = "Med Sel Comp";
const char pstrUsageMediaSelectTV [] = "Med Sel TV";
const char pstrUsageMediaSelectWWW [] = "Med Sel WWW";
const char pstrUsageMediaSelectDVD [] = "Med Sel DVD";
const char pstrUsageMediaSelectTelephone [] = "Med Sel Tel";
const char pstrUsageMediaSelectProgramGuide [] = "Med Sel PG";
const char pstrUsageMediaSelectVideoPhone [] = "Med Sel Vid";
const char pstrUsageMediaSelectGames [] = "Med Sel Games";
const char pstrUsageMediaSelectMessages [] = "Med Sel Msg";
const char pstrUsageMediaSelectCD [] = "Med Sel CD";
const char pstrUsageMediaSelectVCR [] = "Med Sel VCR";
const char pstrUsageMediaSelectTuner [] = "Med Sel Tuner";
const char pstrUsageQuit [] = "Quit";
const char pstrUsageHelp [] = "Help";
const char pstrUsageMediaSelectTape [] = "Med Sel Tape";
const char pstrUsageMediaSelectCable [] = "Med Sel Cbl";
const char pstrUsageMediaSelectSatellite [] = "Med Sel Sat";
const char pstrUsageMediaSelectSecurity [] = "Med Sel Secur";
const char pstrUsageMediaSelectHome [] = "Med Sel Home";
const char pstrUsageMediaSelectCall [] = "Med Sel Call";
const char pstrUsageChannelIncrement [] = "Ch Inc";
const char pstrUsageChannelDecrement [] = "Ch Dec";
const char pstrUsageMediaSelectSAP [] = "Med Sel SAP";
const char pstrUsageVCRPlus [] = "VCR+";
const char pstrUsageOnce [] = "Once";
const char pstrUsageDaily [] = "Daily";
const char pstrUsageWeekly [] = "Weekly";
const char pstrUsageMonthly [] = "Monthly";
//const char pstrUsagePlay [] = "Play";
//const char pstrUsagePause [] = "Pause";
//const char pstrUsageRecord [] = "Rec";
//const char pstrUsageFastForward [] = "FF";
//const char pstrUsageRewind [] = "Rewind";
const char pstrUsageScanNextTrack [] = "Next Track";
const char pstrUsageScanPreviousTrack [] = "Prev Track";
//const char pstrUsageStop [] = "Stop";
const char pstrUsageEject [] = "Eject";
const char pstrUsageRandomPlay [] = "Random";
const char pstrUsageSelectDisk [] = "Sel Disk";
const char pstrUsageEnterDisk [] = "Ent Disk";
//const char pstrUsageRepeat [] = "Repeat";
const char pstrUsageTracking [] = "Tracking";
const char pstrUsageTrackNormal [] = "Trk Norm";
const char pstrUsageSlowTracking [] = "Slow Trk";
const char pstrUsageFrameForward [] = "Frm Fwd";
const char pstrUsageFrameBackwards [] = "Frm Back";
const char pstrUsageMark [] = "Mark";
const char pstrUsageClearMark [] = "Clr Mark";
const char pstrUsageRepeatFromMark [] = "Rpt Mark";
const char pstrUsageReturnToMark [] = "Ret to Mark";
const char pstrUsageSearchMarkForward [] = "Search Mark Fwd";
const char pstrUsageSearchMarkBackwards [] = "Search Mark Back";
const char pstrUsageCounterReset [] = "Counter Reset";
const char pstrUsageShowCounter [] = "Show Counter";
const char pstrUsageTrackingIncrement [] = "Track Inc";
const char pstrUsageTrackingDecrement [] = "Track Dec";
const char pstrUsageStopEject [] = "Stop/Eject";
const char pstrUsagePlayPause [] = "Play/Pause";
const char pstrUsagePlaySkip [] = "Play/Skip";
const char pstrUsageVolume [] = "Vol";
const char pstrUsageBalance [] = "Balance";
//const char pstrUsageMute [] = "Mute";
const char pstrUsageBass [] = "Bass";
const char pstrUsageTreble [] = "Treble";
const char pstrUsageBassBoost [] = "Bass Boost";
const char pstrUsageSurroundMode [] = "Surround";
const char pstrUsageLoudness [] = "Loud";
const char pstrUsageMPX [] = "MPX";
const char pstrUsageVolumeIncrement [] = "Vol Inc";
const char pstrUsageVolumeDecrement [] = "Vol Dec";
const char pstrUsageSpeedSelect [] = "Speed";
const char pstrUsagePlaybackSpeed [] = "Play Speed";
const char pstrUsageStandardPlay [] = "Std Play";
const char pstrUsageLongPlay [] = "Long Play";
const char pstrUsageExtendedPlay [] = "Ext Play";
const char pstrUsageSlow [] = "Slow";
const char pstrUsageFanEnable [] = "Fan Enbl";
const char pstrUsageFanSpeed [] = "Fan Speed";
const char pstrUsageLightEnable [] = "Light Enbl";
const char pstrUsageLightIlluminationLevel [] = "Light Illum Lev";
const char pstrUsageClimateControlEnable [] = "Climate Enbl";
const char pstrUsageRoomTemperature [] = "Room Temp";
const char pstrUsageSecurityEnable [] = "Secur Enbl";
const char pstrUsageFireAlarm [] = "Fire Alm";
const char pstrUsagePoliceAlarm [] = "Police Alm";
const char pstrUsageProximity [] = "Prox";
const char pstrUsageMotion [] = "Motion";
const char pstrUsageDuresAlarm [] = "Dures Alm";
const char pstrUsageHoldupAlarm [] = "Holdup Alm";
const char pstrUsageMedicalAlarm [] = "Med Alm";
const char pstrUsageBalanceRight [] = "Balance Right";
const char pstrUsageBalanceLeft [] = "Balance Left";
const char pstrUsageBassIncrement [] = "Bass Inc";
const char pstrUsageBassDecrement [] = "Bass Dec";
const char pstrUsageTrebleIncrement [] = "Treble Inc";
const char pstrUsageTrebleDecrement [] = "Treble Dec";
const char pstrUsageSpeakerSystem [] = "Spk Sys";
const char pstrUsageChannelLeft [] = "Ch Left";
const char pstrUsageChannelRight [] = "Ch Right";
const char pstrUsageChannelCenter [] = "Ch Center";
const char pstrUsageChannelFront [] = "Ch Front";
const char pstrUsageChannelCenterFront [] = "Ch Cntr Front";
const char pstrUsageChannelSide [] = "Ch Side";
const char pstrUsageChannelSurround [] = "Ch Surround";
const char pstrUsageChannelLowFreqEnhancement [] = "Ch Low Freq Enh";
const char pstrUsageChannelTop [] = "Ch Top";
const char pstrUsageChannelUnknown [] = "Ch Unk";
const char pstrUsageSubChannel [] = "Sub-ch";
const char pstrUsageSubChannelIncrement [] = "Sub-ch Inc";
const char pstrUsageSubChannelDecrement [] = "Sub-ch Dec";
const char pstrUsageAlternateAudioIncrement [] = "Alt Aud Inc";
const char pstrUsageAlternateAudioDecrement [] = "Alt Aud Dec";
const char pstrUsageApplicationLaunchButtons [] = "App Launch Btns";
const char pstrUsageALLaunchButtonConfigTool [] = "AL Launch Conf Tl";
const char pstrUsageALProgrammableButton [] = "AL Pgm Btn";
const char pstrUsageALConsumerControlConfig [] = "AL Cons Ctrl Cfg";
const char pstrUsageALWordProcessor [] = "AL Word Proc";
const char pstrUsageALTextEditor [] = "AL Txt Edtr";
const char pstrUsageALSpreadsheet [] = "AL Sprdsheet";
const char pstrUsageALGraphicsEditor [] = "AL Graph Edtr";
const char pstrUsageALPresentationApp [] = "AL Present App";
const char pstrUsageALDatabaseApp [] = "AL DB App";
const char pstrUsageALEmailReader [] = "AL E-mail Rdr";
const char pstrUsageALNewsreader [] = "AL Newsrdr";
const char pstrUsageALVoicemail [] = "AL Voicemail";
const char pstrUsageALContactsAddressBook [] = "AL Addr Book";
const char pstrUsageALCalendarSchedule [] = "AL Clndr/Schdlr";
const char pstrUsageALTaskProjectManager [] = "AL Task/Prj Mgr";
const char pstrUsageALLogJournalTimecard [] = "AL Log/Jrnl/Tmcrd";
const char pstrUsageALCheckbookFinance [] = "AL Chckbook/Fin";
const char pstrUsageALCalculator [] = "AL Calc";
const char pstrUsageALAVCapturePlayback [] = "AL A/V Capt/Play";
const char pstrUsageALLocalMachineBrowser [] = "AL Loc Mach Brow";
const char pstrUsageALLANWANBrow [] = "AL LAN/WAN Brow";
const char pstrUsageALInternetBrowser [] = "AL I-net Brow";
const char pstrUsageALRemoteNetISPConnect [] = "AL Rem Net Con";
const char pstrUsageALNetworkConference [] = "AL Net Conf";
const char pstrUsageALNetworkChat [] = "AL Net Chat";
const char pstrUsageALTelephonyDialer [] = "AL Tel/Dial";
const char pstrUsageALLogon [] = "AL Logon";
const char pstrUsageALLogoff [] = "AL Logoff";
const char pstrUsageALLogonLogoff [] = "AL Logon/Logoff";
const char pstrUsageALTermLockScrSav [] = "AL Term Lock/Scr Sav";
const char pstrUsageALControlPannel [] = "AL Ctrl Pan";
const char pstrUsageALCommandLineProcessorRun [] = "AL Cmd/Run";
const char pstrUsageALProcessTaskManager [] = "AL Task Mgr";
const char pstrUsageALSelectTaskApplication [] = "AL Sel App";
const char pstrUsageALNextTaskApplication [] = "AL Next App";
const char pstrUsageALPreviousTaskApplication [] = "AL Prev App";
const char pstrUsageALPreemptiveHaltTaskApp [] = "AL Prmpt Halt App";
const char pstrUsageALIntegratedHelpCenter [] = "AL Hlp Cntr";
const char pstrUsageALDocuments [] = "AL Docs";
const char pstrUsageALThesaurus [] = "AL Thsrs";
const char pstrUsageALDictionary [] = "AL Dict";
const char pstrUsageALDesktop [] = "AL Desktop";
const char pstrUsageALSpellCheck [] = "AL Spell Chk";
const char pstrUsageALGrammarCheck [] = "AL Gram Chk";
const char pstrUsageALWirelessStatus [] = "AL Wireless Sts";
const char pstrUsageALKeyboardLayout [] = "AL Kbd Layout";
const char pstrUsageALVirusProtection [] = "AL Vir Protect";
const char pstrUsageALEncryption [] = "AL Encrypt";
const char pstrUsageALScreenSaver [] = "AL Scr Sav";
const char pstrUsageALAlarms [] = "AL Alarms";
const char pstrUsageALClock [] = "AL Clock";
const char pstrUsageALFileBrowser [] = "AL File Brow";
const char pstrUsageALPowerStatus [] = "AL Pwr Sts";
const char pstrUsageALImageBrowser [] = "AL Img Brow";
const char pstrUsageALAudioBrowser [] = "AL Aud Brow";
const char pstrUsageALMovieBrowser [] = "AL Mov Brow";
const char pstrUsageALDigitalRightsManager [] = "AL Dig Rights Mgr";
const char pstrUsageALDigitalWallet [] = "AL Dig Wallet";
const char pstrUsageALInstantMessaging [] = "AL Inst Msg";
const char pstrUsageALOEMFeaturesBrowser [] = "AL OEM Tips Brow";
const char pstrUsageALOEMHelp [] = "AL OEM Hlp";
const char pstrUsageALOnlineCommunity [] = "AL Online Com";
const char pstrUsageALEntertainmentContentBrow [] = "AL Ent Cont Brow";
const char pstrUsageALOnlineShoppingBrowser [] = "AL Online Shop Brow";
const char pstrUsageALSmartCardInfoHelp [] = "AL SmartCard Inf";
const char pstrUsageALMarketMonitorFinBrowser [] = "AL Market Brow";
const char pstrUsageALCustomCorpNewsBrowser [] = "AL Cust Corp News Brow";
const char pstrUsageALOnlineActivityBrowser [] = "AL Online Act Brow";
const char pstrUsageALResearchSearchBrowser [] = "AL Search Brow";
const char pstrUsageALAudioPlayer [] = "AL Aud Player";
const char pstrUsageGenericGUIAppControls [] = "Gen GUI App Ctrl";
const char pstrUsageACNew [] = "AC New";
const char pstrUsageACOpen [] = "AC Open";
const char pstrUsageACClose [] = "AC Close";
const char pstrUsageACExit [] = "AC Exit";
const char pstrUsageACMaximize [] = "AC Max";
const char pstrUsageACMinimize [] = "AC Min";
const char pstrUsageACSave [] = "AC Save";
const char pstrUsageACPrint [] = "AC Print";
const char pstrUsageACProperties [] = "AC Prop";
const char pstrUsageACUndo [] = "AC Undo";
const char pstrUsageACCopy [] = "AC Copy";
const char pstrUsageACCut [] = "AC Cut";
const char pstrUsageACPaste [] = "AC Paste";
const char pstrUsageACSelectAll [] = "AC Sel All";
const char pstrUsageACFind [] = "AC Find";
const char pstrUsageACFindAndReplace [] = "AC Find/Replace";
const char pstrUsageACSearch [] = "AC Search";
const char pstrUsageACGoto [] = "AC Goto";
const char pstrUsageACHome [] = "AC Home";
const char pstrUsageACBack [] = "AC Back";
const char pstrUsageACForward [] = "AC Fwd";
const char pstrUsageACStop [] = "AC Stop";
const char pstrUsageACRefresh [] = "AC Refresh";
const char pstrUsageACPreviousLink [] = "AC Prev Link";
const char pstrUsageACNextLink [] = "AC Next Link";
const char pstrUsageACBookmarks [] = "AC Bkmarks";
const char pstrUsageACHistory [] = "AC Hist";
const char pstrUsageACSubscriptions [] = "AC Subscr";
const char pstrUsageACZoomIn [] = "AC Zoom In";
const char pstrUsageACZoomOut [] = "AC Zoom Out";
const char pstrUsageACZoom [] = "AC Zoom";
const char pstrUsageACFullScreenView [] = "AC Full Scr";
const char pstrUsageACNormalView [] = "AC Norm View";
const char pstrUsageACViewToggle [] = "AC View Tgl";
const char pstrUsageACScrollUp [] = "AC Scroll Up";
const char pstrUsageACScrollDown [] = "AC Scroll Down";
const char pstrUsageACScroll [] = "AC Scroll";
const char pstrUsageACPanLeft [] = "AC Pan Left";
const char pstrUsageACPanRight [] = "AC Pan Right";
const char pstrUsageACPan [] = "AC Pan";
const char pstrUsageACNewWindow [] = "AC New Wnd";
const char pstrUsageACTileHoriz [] = "AC Tile Horiz";
const char pstrUsageACTileVert [] = "AC Tile Vert";
const char pstrUsageACFormat [] = "AC Frmt";
const char pstrUsageACEdit [] = "AC Edit";
const char pstrUsageACBold [] = "AC Bold";
const char pstrUsageACItalics [] = "AC Ital";
const char pstrUsageACUnderline [] = "AC Under";
const char pstrUsageACStrikethrough [] = "AC Strike";
const char pstrUsageACSubscript [] = "AC Sub";
const char pstrUsageACSuperscript [] = "AC Super";
const char pstrUsageACAllCaps [] = "AC All Caps";
const char pstrUsageACRotate [] = "AC Rotate";
const char pstrUsageACResize [] = "AC Resize";
const char pstrUsageACFlipHorizontal [] = "AC Flp H";
const char pstrUsageACFlipVertical [] = "AC Flp V";
const char pstrUsageACMirrorHorizontal [] = "AC Mir H";
const char pstrUsageACMirrorVertical [] = "AC Mir V";
const char pstrUsageACFontSelect [] = "AC Fnt Sel";
const char pstrUsageACFontColor [] = "AC Fnt Clr";
const char pstrUsageACFontSize [] = "AC Fnt Size";
const char pstrUsageACJustifyLeft [] = "AC Just Left";
const char pstrUsageACJustifyCenterH [] = "AC Just Cent H";
const char pstrUsageACJustifyRight [] = "AC Just Right";
const char pstrUsageACJustifyBlockH [] = "AC Just Block H";
const char pstrUsageACJustifyTop [] = "AC Just Top";
const char pstrUsageACJustifyCenterV [] = "AC Just Cent V";
const char pstrUsageACJustifyBottom [] = "AC Just Bot";
const char pstrUsageACJustifyBlockV [] = "AC Just Block V";
const char pstrUsageACIndentDecrease [] = "AC Indent Dec";
const char pstrUsageACIndentIncrease [] = "AC Indent Inc";
const char pstrUsageACNumberedList [] = "AC Num List";
const char pstrUsageACRestartNumbering [] = "AC Res Num";
const char pstrUsageACBulletedList [] = "AC Blt List";
const char pstrUsageACPromote [] = "AC Promote";
const char pstrUsageACDemote [] = "AC Demote";
const char pstrUsageACYes [] = "AC Yes";
const char pstrUsageACNo [] = "AC No";
const char pstrUsageACCancel [] = "AC Cancel";
const char pstrUsageACCatalog [] = "AC Ctlg";
const char pstrUsageACBuyChkout [] = "AC Buy";
const char pstrUsageACAddToCart [] = "AC Add2Cart";
const char pstrUsageACExpand [] = "AC Xpnd";
const char pstrUsageACExpandAll [] = "AC Xpand All";
const char pstrUsageACCollapse [] = "AC Collapse";
const char pstrUsageACCollapseAll [] = "AC Collapse All";
const char pstrUsageACPrintPreview [] = "AC Prn Prevw";
const char pstrUsageACPasteSpecial [] = "AC Paste Spec";
const char pstrUsageACInsertMode [] = "AC Ins Mode";
const char pstrUsageACDelete [] = "AC Del";
const char pstrUsageACLock [] = "AC Lock";
const char pstrUsageACUnlock [] = "AC Unlock";
const char pstrUsageACProtect [] = "AC Prot";
const char pstrUsageACUnprotect [] = "AC Unprot";
const char pstrUsageACAttachComment [] = "AC Attach Cmnt";
const char pstrUsageACDeleteComment [] = "AC Del Cmnt";
const char pstrUsageACViewComment [] = "AC View Cmnt";
const char pstrUsageACSelectWord [] = "AC Sel Word";
const char pstrUsageACSelectSentence [] = "AC Sel Sntc";
const char pstrUsageACSelectParagraph [] = "AC Sel Para";
const char pstrUsageACSelectColumn [] = "AC Sel Col";
const char pstrUsageACSelectRow [] = "AC Sel Row";
const char pstrUsageACSelectTable [] = "AC Sel Tbl";
const char pstrUsageACSelectObject [] = "AC Sel Obj";
const char pstrUsageACRedoRepeat [] = "AC Redo";
const char pstrUsageACSort [] = "AC Sort";
const char pstrUsageACSortAscending [] = "AC Sort Asc";
const char pstrUsageACSortDescending [] = "AC Sort Desc";
const char pstrUsageACFilter [] = "AC Filt";
const char pstrUsageACSetClock [] = "AC Set Clk";
const char pstrUsageACViewClock [] = "AC View Clk";
const char pstrUsageACSelectTimeZone [] = "AC Sel Time Z";
const char pstrUsageACEditTimeZone [] = "AC Edt Time Z";
const char pstrUsageACSetAlarm [] = "AC Set Alm";
const char pstrUsageACClearAlarm [] = "AC Clr Alm";
const char pstrUsageACSnoozeAlarm [] = "AC Snz Alm";
const char pstrUsageACResetAlarm [] = "AC Rst Alm";
const char pstrUsageACSyncronize [] = "AC Sync";
const char pstrUsageACSendReceive [] = "AC Snd/Rcv";
const char pstrUsageACSendTo [] = "AC Snd To";
const char pstrUsageACReply [] = "AC Reply";
const char pstrUsageACReplyAll [] = "AC Reply All";
const char pstrUsageACForwardMessage [] = "AC Fwd Msg";
const char pstrUsageACSend [] = "AC Snd";
const char pstrUsageACAttachFile [] = "AC Att File";
const char pstrUsageACUpload [] = "AC Upld";
const char pstrUsageACDownload [] = "AC Dnld";
const char pstrUsageACSetBorders [] = "AC Set Brd";
const char pstrUsageACInsertRow [] = "AC Ins Row";
const char pstrUsageACInsertColumn [] = "AC Ins Col";
const char pstrUsageACInsertFile [] = "AC Ins File";
const char pstrUsageACInsertPicture [] = "AC Ins Pic";
const char pstrUsageACInsertObject [] = "AC Ins Obj";
const char pstrUsageACInsertSymbol [] = "AC Ins Sym";
const char pstrUsageACSaveAndClose [] = "AC Sav&Cls";
const char pstrUsageACRename [] = "AC Rename";
const char pstrUsageACMerge [] = "AC Merge";
const char pstrUsageACSplit [] = "AC Split";
const char pstrUsageACDistributeHorizontaly [] = "AC Dist Hor";
const char pstrUsageACDistributeVerticaly [] = "AC Dist Ver";
// Digitaizers
const char pstrUsageDigitizer [] = "Digitizer";
const char pstrUsagePen [] = "Pen";
const char pstrUsageLightPen [] = "Light Pen";
const char pstrUsageTouchScreen [] = "Touch Scr";
const char pstrUsageTouchPad [] = "Touch Pad";
const char pstrUsageWhiteBoard [] = "White Brd";
const char pstrUsageCoordinateMeasuringMachine [] = "Coord Meas Mach";
const char pstrUsage3DDigitizer [] = "3D Dgtz";
const char pstrUsageStereoPlotter [] = "Stereo Plot";
const char pstrUsageArticulatedArm [] = "Art Arm";
const char pstrUsageArmature [] = "Armature";
const char pstrUsageMultiplePointDigitizer [] = "Multi Point Dgtz";
const char pstrUsageFreeSpaceWand [] = "Free Space Wand";
const char pstrUsageStylus [] = "Stylus";
const char pstrUsagePuck [] = "Puck";
const char pstrUsageFinger [] = "Finger";
const char pstrUsageTipPressure [] = "Tip Press";
const char pstrUsageBarrelPressure [] = "Brl Press";
const char pstrUsageInRange [] = "In Range";
const char pstrUsageTouch [] = "Touch";
const char pstrUsageUntouch [] = "Untouch";
const char pstrUsageTap [] = "Tap";
const char pstrUsageQuality [] = "Qlty";
const char pstrUsageDataValid [] = "Data Valid";
const char pstrUsageTransducerIndex [] = "Transducer Ind";
const char pstrUsageTabletFunctionKeys [] = "Tabl Func Keys";
const char pstrUsageProgramChangeKeys [] = "Pgm Chng Keys";
//const char pstrUsageBatteryStrength [] = "Bat Strength";
const char pstrUsageInvert [] = "Invert";
const char pstrUsageXTilt [] = "X Tilt";
const char pstrUsageYTilt [] = "Y Tilt";
const char pstrUsageAzimuth [] = "Azimuth";
const char pstrUsageAltitude [] = "Altitude";
const char pstrUsageTwist [] = "Twist";
const char pstrUsageTipSwitch [] = "Tip Sw";
const char pstrUsageSecondaryTipSwitch [] = "Scnd Tip Sw";
const char pstrUsageBarrelSwitch [] = "Brl Sw";
const char pstrUsageEraser [] = "Eraser";
const char pstrUsageTabletPick [] = "Tbl Pick";
// Alphanumeric Display Page
const char pstrUsageAlphanumericDisplay [] = "Alphanum Disp";
const char pstrUsageBitmappedDisplay [] = "Bmp Disp";
const char pstrUsageDisplayAttributesReport [] = "Disp Attr Rpt";
const char pstrUsageASCIICharacterSet [] = "ASCII chset";
const char pstrUsageDataReadBack [] = "Data Rd Back";
const char pstrUsageFontReadBack [] = "Fnt Rd Back";
const char pstrUsageDisplayControlReport [] = "Disp Ctrl Rpt";
const char pstrUsageClearDisplay [] = "Clr Disp";
//const char pstrUsageDisplayEnable [] = "Disp Enbl";
const char pstrUsageScreenSaverDelay [] = "Scr Sav Delay";
const char pstrUsageScreenSaverEnable [] = "Scr Sav Enbl";
const char pstrUsageVerticalScroll [] = "V Scroll";
const char pstrUsageHorizontalScroll [] = "H Scroll";
const char pstrUsageCharacterReport [] = "Char Rpt";
const char pstrUsageDisplayData [] = "Disp Data";
const char pstrUsageDisplayStatus [] = "Disp Stat";
const char pstrUsageStatusNotReady [] = "Stat !Ready";
const char pstrUsageStatusReady [] = "Stat Ready";
const char pstrUsageErrorNotALoadableCharacter [] = "Err Not Ld Char";
const char pstrUsageErrorFotDataCanNotBeRead [] = "Fnt Data Rd Err";
const char pstrUsageCursorPositionReport [] = "Cur Pos Rpt";
const char pstrUsageRow [] = "Row";
const char pstrUsageColumn [] = "Col";
const char pstrUsageRows [] = "Rows";
const char pstrUsageColumns [] = "Cols";
const char pstrUsageCursorPixelPosition [] = "Cur Pix Pos";
const char pstrUsageCursorMode [] = "Cur Mode";
const char pstrUsageCursorEnable [] = "Cur Enbl";
const char pstrUsageCursorBlink [] = "Cur Blnk";
const char pstrUsageFontReport [] = "Fnt Rpt";
const char pstrUsageFontData [] = "Fnt Data";
const char pstrUsageCharacterWidth [] = "Char Wdth";
const char pstrUsageCharacterHeight [] = "Char Hght";
const char pstrUsageCharacterSpacingHorizontal [] = "Char Space H";
const char pstrUsageCharacterSpacingVertical [] = "Char Space V";
const char pstrUsageUnicodeCharset [] = "Unicode Char";
const char pstrUsageFont7Segment [] = "Fnt 7-seg";
const char pstrUsage7SegmentDirectMap [] = "7-seg map";
const char pstrUsageFont14Segment [] = "Fnt 14-seg";
const char pstrUsage14SegmentDirectMap [] = "14-seg map";
const char pstrUsageDisplayBrightness [] = "Disp Bright";
const char pstrUsageDisplayContrast [] = "Disp Cntrst";
const char pstrUsageCharacterAttribute [] = "Char Attr";
const char pstrUsageAttributeReadback [] = "Attr Readbk";
const char pstrUsageAttributeData [] = "Attr Data";
const char pstrUsageCharAttributeEnhance [] = "Char Attr Enh";
const char pstrUsageCharAttributeUnderline [] = "Char Attr Undl";
const char pstrUsageCharAttributeBlink [] = "Char Attr Blnk";
const char pstrUsageBitmapSizeX [] = "Bmp Size X";
const char pstrUsageBitmapSizeY [] = "Bmp Size Y";
const char pstrUsageBitDepthFormat [] = "Bit Dpth Fmt";
const char pstrUsageDisplayOrientation [] = "Disp Ornt";
const char pstrUsagePaletteReport [] = "Pal Rpt";
const char pstrUsagePaletteDataSize [] = "Pal Data Size";
const char pstrUsagePaletteDataOffset [] = "Pal Data Off";
const char pstrUsagePaletteData [] = "Pal Data";
const char pstrUsageBlitReport [] = "Blit Rpt";
const char pstrUsageBlitRectangleX1 [] = "Blit Rect X1";
const char pstrUsageBlitRectangleY1 [] = "Blit Rect Y1";
const char pstrUsageBlitRectangleX2 [] = "Blit Rect X2";
const char pstrUsageBlitRectangleY2 [] = "Blit Rect Y2";
const char pstrUsageBlitData [] = "Blit Data";
const char pstrUsageSoftButton [] = "Soft Btn";
const char pstrUsageSoftButtonID [] = "Soft Btn ID";
const char pstrUsageSoftButtonSide [] = "Soft Btn Side";
const char pstrUsageSoftButtonOffset1 [] = "Soft Btn Off1";
const char pstrUsageSoftButtonOffset2 [] = "Soft Btn Off2";
const char pstrUsageSoftButtonReport [] = "Soft Btn Rpt";
// Medical Instrument Page
const char pstrUsageMedicalUltrasound [] = "Med Ultrasnd";
const char pstrUsageVCRAcquisition [] = "VCR/Acq";
const char pstrUsageFreezeThaw [] = "Freeze";
const char pstrUsageClipStore [] = "Clip Store";
const char pstrUsageUpdate [] = "Update";
const char pstrUsageNext [] = "Next";
const char pstrUsageSave [] = "Save";
const char pstrUsagePrint [] = "Print";
const char pstrUsageMicrophoneEnable [] = "Mic Enbl";
const char pstrUsageCine [] = "Cine";
const char pstrUsageTransmitPower [] = "Trans Pwr";
//const char pstrUsageVolume [] = "Vol";
const char pstrUsageFocus [] = "Focus";
const char pstrUsageDepth [] = "Depth";
const char pstrUsageSoftStepPrimary [] = "Soft Stp-Pri";
const char pstrUsageSoftStepSecondary [] = "Soft Stp-Sec";
const char pstrUsageDepthGainCompensation [] = "Dpth Gain Comp";
const char pstrUsageZoomSelect [] = "Zoom Sel";
const char pstrUsageZoomAdjust [] = "Zoom Adj";
const char pstrUsageSpectralDopplerModeSelect [] = "Spec Dop Mode Sel";
const char pstrUsageSpectralDopplerModeAdjust [] = "Spec Dop Mode Adj";
const char pstrUsageColorDopplerModeSelect [] = "Color Dop Mode Sel";
const char pstrUsageColorDopplerModeAdjust [] = "Color Dop Mode Adj";
const char pstrUsageMotionModeSelect [] = "Motion Mode Sel";
const char pstrUsageMotionModeAdjust [] = "Motion Mode Adj";
const char pstrUsage2DModeSelect [] = "2D Mode Sel";
const char pstrUsage2DModeAdjust [] = "2D Mode Adj";
const char pstrUsageSoftControlSelect [] = "Soft Ctrl Sel";
const char pstrUsageSoftControlAdjust [] = "Soft Ctrl Adj";
//extern const char *usagePageTitles0[15];
//const char *usagePageTitles1[];
//const char *genDesktopTitles0[];
//const char *genDesktopTitles1[];
//const char *genDesktopTitles2[];
//const char *genDesktopTitles3[];
//const char *genDesktopTitles4[];
//const char *simuTitles0[];
//const char *simuTitles1[];
//const char *simuTitles2[];
//const char *vrTitles0[];
//const char *vrTitles1[];
//const char *sportsCtrlTitles0[];
//const char *sportsCtrlTitles1[];
//const char *sportsCtrlTitles2[];
//const char *gameTitles0[];
//const char *gameTitles1[];
//const char *genDevCtrlTitles[];
//const char *ledTitles[];
//const char *telTitles0[];
//const char *telTitles1[];
//const char *telTitles2[];
//const char *telTitles3[];
//const char *telTitles4[];
//const char *telTitles5[];
//const char *consTitles0[];
//const char *consTitles1[];
//const char *consTitles2[];
//const char *consTitles3[];
//const char *consTitles4[];
//const char *consTitles5[];
//const char *consTitles6[];
//const char *consTitles7[];
//const char *consTitles8[];
//const char *consTitles9[];
//const char *consTitlesA[];
//const char *consTitlesB[];
//const char *consTitlesC[];
//const char *consTitlesD[];
//const char *consTitlesE[];
//const char *digitTitles0[];
//const char *digitTitles1[];
//const char *digitTitles2[];
//const char *aplphanumTitles0[];
//const char *aplphanumTitles1[];
//const char *aplphanumTitles2[];
//const char *medInstrTitles0[];
//const char *medInstrTitles1[];
//const char *medInstrTitles2[];
//const char *medInstrTitles3[];
//const char *medInstrTitles4[];
#endif /* HIDUSAGESTR_H_INCLUDED */

View File

@ -0,0 +1,73 @@
/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
This software may be distributed and modified under the terms of the GNU
General Public License version 2 (GPL2) as published by the Free Software
Foundation and appearing in the file GPL2.TXT included in the packaging of
this file. Please note that GPL2 Section 2[b] requires that all works based
on this software must also be made publicly available under the terms of
the GPL2 ("Copyleft").
Contact information
-------------------
Circuits At Home, LTD
Web : http://www.circuitsathome.com
e-mail : support@circuitsathome.com
*/
#include "parsetools.h"
bool MultiByteValueParser::Parse(uint8_t **pp, uint32_t *pcntdn)
{
if (!pBuf)
{
//Notify(PSTR("Buffer pointer is NULL!\r\n"));
return false;
}
for (; countDown && (*pcntdn); countDown--, (*pcntdn)--, (*pp)++)
pBuf[valueSize-countDown] = (**pp);
if (countDown)
return false;
countDown = valueSize;
return true;
}
bool PTPListParser::Parse(uint8_t **pp, uint32_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me)
{
switch (nStage)
{
case 0:
pBuf->valueSize = lenSize;
theParser.Initialize(pBuf);
nStage = 1;
case 1:
if (!theParser.Parse(pp, pcntdn))
return false;
arLen = 0;
arLen = (pBuf->valueSize >= 4) ? *((uint32_t*)pBuf->pValue) : (uint32_t)(*((uint16_t*)pBuf->pValue));
arLenCntdn = arLen;
nStage = 2;
case 2:
pBuf->valueSize = valSize;
theParser.Initialize(pBuf);
nStage = 3;
case 3:
for (; arLenCntdn; arLenCntdn--)
{
if (!theParser.Parse(pp, pcntdn))
return false;
if (pf)
pf(pBuf, (arLen - arLenCntdn), me);
}
nStage = 0;
}
return true;
}

View File

@ -0,0 +1,143 @@
/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
This software may be distributed and modified under the terms of the GNU
General Public License version 2 (GPL2) as published by the Free Software
Foundation and appearing in the file GPL2.TXT included in the packaging of
this file. Please note that GPL2 Section 2[b] requires that all works based
on this software must also be made publicly available under the terms of
the GPL2 ("Copyleft").
Contact information
-------------------
Circuits At Home, LTD
Web : http://www.circuitsathome.com
e-mail : support@circuitsathome.com
*/
#ifndef PARSETOOLS_H_INCLUDED
#define PARSETOOLS_H_INCLUDED
#include <stdint.h>
#include "Arduino.h"
struct MultiValueBuffer
{
uint8_t valueSize;
void *pValue;
};
class MultiByteValueParser
{
uint8_t *pBuf;
uint32_t countDown;
uint32_t valueSize;
public:
MultiByteValueParser() : pBuf(NULL), countDown(0), valueSize(0) {};
const uint8_t* GetBuffer() { return pBuf; };
void Initialize(MultiValueBuffer * const pbuf)
{
pBuf = (uint8_t*)pbuf->pValue;
countDown = valueSize = pbuf->valueSize;
};
bool Parse(uint8_t **pp, uint32_t *pcntdn);
};
class ByteSkipper
{
uint8_t *pBuf;
uint32_t nStage;
uint32_t countDown;
public:
ByteSkipper() : pBuf(NULL), nStage(0), countDown(0) {};
void Initialize(MultiValueBuffer *pbuf)
{
pBuf = (uint8_t*)pbuf->pValue;
countDown = 0;
};
bool Skip(uint8_t **pp, uint32_t *pcntdn, uint32_t bytes_to_skip)
{
switch (nStage)
{
case 0:
countDown = bytes_to_skip;
nStage ++;
case 1:
for (; countDown && (*pcntdn); countDown--, (*pp)++, (*pcntdn)--);
if (!countDown)
nStage = 0;
};
return (!countDown);
};
};
// Pointer to a callback function triggered for each element of PTP array when used with PTPArrayParser
typedef void (*PTP_ARRAY_EL_FUNC)(const MultiValueBuffer * const p, uint32_t count, const void *me);
class PTPListParser
{
public:
enum ParseMode { modeArray, modeRange/*, modeEnum*/ };
private:
uint32_t nStage;
uint32_t enStage;
uint32_t arLen;
uint32_t arLenCntdn;
uint32_t lenSize; // size of the array length field in bytes
uint32_t valSize; // size of the array element in bytes
MultiValueBuffer *pBuf;
// The only parser for both size and array element parsing
MultiByteValueParser theParser;
uint32_t /*ParseMode*/ prsMode;
public:
PTPListParser() :
nStage(0),
enStage(0),
arLen(0),
arLenCntdn(0),
lenSize(0),
valSize(0),
pBuf(NULL),
prsMode(modeArray)
{};
void Initialize(const uint32_t len_size, const uint32_t val_size, MultiValueBuffer * const p, const uint32_t mode = modeArray)
{
pBuf = p;
lenSize = len_size;
valSize = val_size;
prsMode = mode;
if (prsMode == modeRange)
{
arLenCntdn = arLen = 3;
nStage = 2;
}
else
{
arLenCntdn = arLen = 0;
nStage = 0;
}
enStage = 0;
theParser.Initialize(p);
};
bool Parse(uint8_t **pp, uint32_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me = NULL);
};
#endif /* PARSETOOLS_H_INCLUDED */

View File

@ -0,0 +1,176 @@
/* 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 */