Created
August 20, 2014 19:26
-
-
Save duanebester/068c87d84d8708603d6c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdbool.h> | |
#include <stdint.h> | |
#include "inc/hw_types.h" | |
#include "driverlib/debug.h" | |
#include "driverlib/usb.h" | |
#include "usblib/usblib.h" | |
#include "usblib/usblibpriv.h" | |
#include "usblib/device/usbdevice.h" | |
#include "usblib/usbhid.h" | |
#include "usblib/device/usbdhid.h" | |
#include "usblib/device/usbdhidgeneric.h" | |
//***************************************************************************** | |
// | |
//! \addtogroup hid_Generic_device_class_api | |
//! @{ | |
// | |
//***************************************************************************** | |
//***************************************************************************** | |
// | |
// HID device configuration descriptor. | |
// | |
// It is vital that the configuration descriptor bConfigurationValue field | |
// (byte 6) is 1 for the first configuration and increments by 1 for each | |
// additional configuration defined here. This relationship is assumed in the | |
// device stack for simplicity even though the USB 2.0 specification imposes | |
// no such restriction on the bConfigurationValue values. | |
// | |
// Note that this structure is deliberately located in RAM since we need to | |
// be able to patch some values in it based on client requirements. | |
// | |
//***************************************************************************** | |
static uint8_t g_pui8GenDescriptor[] = | |
{ | |
// | |
// Configuration descriptor header. | |
// | |
9, // Size of the configuration descriptor. | |
USB_DTYPE_CONFIGURATION, // Type of this descriptor. | |
USBShort(34), // The total size of this full structure. | |
1, // The number of interfaces in this | |
// configuration. | |
1, // The unique value for this configuration. | |
5, // The string identifier that describes this | |
// configuration. | |
USB_CONF_ATTR_SELF_PWR, // Bus Powered, Self Powered, remote wake up. | |
250, // The maximum power in 2mA increments. | |
}; | |
//***************************************************************************** | |
// | |
// The remainder of the configuration descriptor is stored in flash since we | |
// don't need to modify anything in it at runtime. | |
// | |
//***************************************************************************** | |
static uint8_t g_pui8HIDInterface[HIDINTERFACE_SIZE] = | |
{ | |
// | |
// HID Device Class Interface Descriptor. | |
// | |
9, // Size of the interface descriptor. | |
USB_DTYPE_INTERFACE, // Type of this descriptor. | |
0, // The index for this interface. | |
0, // The alternate setting for this interface. | |
1, // The number of endpoints used by this | |
// interface. | |
USB_CLASS_HID, // The interface class | |
USB_HID_SCLASS_NONE, // The interface sub-class. | |
USB_HID_PROTOCOL_NONE, // The interface protocol for the sub-class | |
// specified above. | |
4, // The string index for this interface. | |
}; | |
static const uint8_t g_pui8HIDInEndpoint[HIDINENDPOINT_SIZE] = | |
{ | |
// | |
// Interrupt IN endpoint descriptor | |
// | |
7, // The size of the endpoint descriptor. | |
USB_DTYPE_ENDPOINT, // Descriptor type is an endpoint. | |
USB_EP_DESC_IN | USBEPToIndex(USB_EP_1), | |
USB_EP_ATTR_INT, // Endpoint is an interrupt endpoint. | |
USBShort(USBFIFOSizeToBytes(USB_FIFO_SZ_64)), | |
// The maximum packet size. | |
1, // The polling interval for this endpoint. | |
}; | |
static const uint8_t g_pui8HIDOutEndpoint[HIDOUTENDPOINT_SIZE] = | |
{ | |
// | |
// Interrupt OUT endpoint descriptor | |
// | |
7, // The size of the endpoint descriptor. | |
USB_DTYPE_ENDPOINT, // Descriptor type is an endpoint. | |
USB_EP_DESC_OUT | USBEPToIndex(USB_EP_2), | |
USB_EP_ATTR_INT, // Endpoint is an interrupt endpoint. | |
USBShort(USBFIFOSizeToBytes(USB_FIFO_SZ_64)), | |
// The maximum packet size. | |
1, // The polling interval for this endpoint. | |
}; | |
//***************************************************************************** | |
// | |
// The following is the HID report structure definition that is passed back | |
// to the host. | |
// | |
//***************************************************************************** | |
static const uint8_t g_pui8GenReportDescriptor[] = | |
{ | |
UsagePageVendor(0x00), // 06 00 FF | |
Usage(0x01), // 09 01 | |
Collection(USB_HID_APPLICATION), // A1 01 | |
UsageMinimum(0), // 19 00 | |
UsageMaximum(64), // 29 40 | |
LogicalMinimum(0), // 15 00 | |
LogicalMaximum(255), // 26 FF 00 | |
ReportSize(8), // 75 08 | |
ReportCount(64), // 95 40 | |
Input(USB_HID_INPUT_DATA | USB_HID_INPUT_VARIABLE | USB_HID_INPUT_ABS), // 81 00 | |
UsageMinimum(0), // 19 00 | |
UsageMaximum(64), // 29 40 | |
LogicalMinimum(0), // 15 00 | |
LogicalMaximum(255), // 26 FF 00 | |
ReportSize(8), // 75 08 | |
ReportCount(64), // 95 40 | |
Output(USB_HID_OUTPUT_DATA | USB_HID_OUTPUT_VARIABLE | USB_HID_OUTPUT_ABS), // 91 00 | |
EndCollection, // C0 | |
}; | |
/* | |
static const uint8_t g_pui8KeybReportDescriptor[] = | |
{ | |
UsagePage(USB_HID_GENERIC_DESKTOP), | |
Usage(USB_HID_Generic), | |
Collection(USB_HID_APPLICATION), | |
// | |
// Modifier keys. | |
// 8 - 1 bit values indicating the modifier keys (ctrl, shift...) | |
// | |
ReportSize(1), | |
ReportCount(8), | |
UsagePage(USB_HID_USAGE_KEYCODES), | |
UsageMinimum(224), | |
UsageMaximum(231), | |
LogicalMinimum(0), | |
LogicalMaximum(1), | |
Input(USB_HID_INPUT_DATA | USB_HID_INPUT_VARIABLE | USB_HID_INPUT_ABS), | |
// | |
// One byte of rsvd data required by HID spec. | |
// | |
ReportCount(1), | |
ReportSize(8), | |
Input(USB_HID_INPUT_CONSTANT), | |
// | |
// Generic LEDs. | |
// 5 - 1 bit values. | |
// | |
ReportCount(5), | |
ReportSize(1), | |
UsagePage(USB_HID_USAGE_LEDS), | |
UsageMinimum(1), | |
UsageMaximum(5), | |
Output(USB_HID_OUTPUT_DATA | USB_HID_OUTPUT_VARIABLE | | |
USB_HID_OUTPUT_ABS), | |
// | |
// 1 - 3 bit value to pad out to a full byte. | |
// | |
ReportCount(1), | |
ReportSize(3), | |
Output(USB_HID_OUTPUT_CONSTANT), //LED report padding | |
// | |
// The Key buffer. | |
// 6 - 8 bit values to store the current key state. | |
// | |
ReportCount(6), | |
ReportSize(8), | |
LogicalMinimum(0), | |
LogicalMaximum(101), | |
UsagePage(USB_HID_USAGE_KEYCODES), | |
UsageMinimum (0), | |
UsageMaximum (101), | |
Input(USB_HID_INPUT_DATA | USB_HID_INPUT_ARRAY), | |
EndCollection | |
}; | |
*/ | |
//***************************************************************************** | |
// | |
// The HID descriptor for the Generic device. | |
// | |
//***************************************************************************** | |
static const tHIDDescriptor g_sGenHIDDescriptor = | |
{ | |
9, // bLength | |
USB_HID_DTYPE_HID, // bDescriptorType | |
0x111, // bcdHID (version 1.11 compliant) | |
0, // bCountryCode (not localized) | |
1, // bNumDescriptors | |
{ | |
{ | |
USB_HID_DTYPE_REPORT, // Report descriptor | |
sizeof(g_pui8GenReportDescriptor) | |
// Size of report descriptor | |
} | |
} | |
}; | |
//***************************************************************************** | |
// | |
// The HID configuration descriptor is defined as four or five sections | |
// depending upon the client's configuration choice. These sections are: | |
// | |
// 1. The 9 byte configuration descriptor (RAM). | |
// 2. The interface descriptor (RAM). | |
// 3. The HID report and physical descriptors (provided by the client) | |
// (FLASH). | |
// 4. The mandatory interrupt IN endpoint descriptor (FLASH). | |
// 5. The optional interrupt OUT endpoint descriptor (FLASH). | |
// | |
//***************************************************************************** | |
static const tConfigSection g_sHIDConfigSection = | |
{ | |
sizeof(g_pui8GenDescriptor), | |
g_pui8GenDescriptor | |
}; | |
static const tConfigSection g_sHIDInterfaceSection = | |
{ | |
sizeof(g_pui8HIDInterface), | |
g_pui8HIDInterface | |
}; | |
static const tConfigSection g_sHIDInEndpointSection = | |
{ | |
sizeof(g_pui8HIDInEndpoint), | |
g_pui8HIDInEndpoint | |
}; | |
static const tConfigSection g_sHIDOutEndpointSection = | |
{ | |
sizeof(g_pui8HIDOutEndpoint), | |
g_pui8HIDOutEndpoint | |
}; | |
//***************************************************************************** | |
// | |
// Place holder for the user's HID descriptor block. | |
// | |
//***************************************************************************** | |
static tConfigSection g_sHIDDescriptorSection = | |
{ | |
sizeof(g_sGenHIDDescriptor), | |
(const uint8_t *)&g_sGenHIDDescriptor | |
}; | |
//***************************************************************************** | |
// | |
// This array lists all the sections that must be concatenated to make a | |
// single, complete HID configuration descriptor. | |
// | |
//***************************************************************************** | |
static const tConfigSection *g_psHIDSections[] = | |
{ | |
&g_sHIDConfigSection, | |
&g_sHIDInterfaceSection, | |
&g_sHIDDescriptorSection, | |
&g_sHIDInEndpointSection, | |
&g_sHIDOutEndpointSection | |
}; | |
#define NUM_HID_SECTIONS ((sizeof(g_psHIDSections) / \ | |
sizeof(g_psHIDSections[0])) - 1) | |
//***************************************************************************** | |
// | |
// The header for the single configuration we support. This is the root of | |
// the data structure that defines all the bits and pieces that are pulled | |
// together to generate the configuration descriptor. Note that this must be | |
// in RAM since we need to include or exclude the final section based on | |
// client supplied initialization parameters. | |
// | |
//***************************************************************************** | |
static tConfigHeader g_sHIDConfigHeader = | |
{ | |
NUM_HID_SECTIONS, | |
g_psHIDSections | |
}; | |
//***************************************************************************** | |
// | |
// Configuration Descriptor. | |
// | |
//***************************************************************************** | |
static const tConfigHeader * const g_ppsHIDConfigDescriptors[] = | |
{ | |
&g_sHIDConfigHeader | |
}; | |
//***************************************************************************** | |
// | |
// The HID class descriptor table. For the Generic class, we have only a | |
// single report descriptor. | |
// | |
//***************************************************************************** | |
static const uint8_t * const g_pui8GenClassDescriptors[] = | |
{ | |
g_pui8GenReportDescriptor | |
}; | |
//***************************************************************************** | |
// | |
// Forward references for Generic device callback functions. | |
// | |
//***************************************************************************** | |
static uint32_t HIDGenRxHandler(void *pvGenDevice, uint32_t ui32Event, | |
uint32_t ui32MsgData, void *pvMsgData); | |
static uint32_t HIDGenTxHandler(void *pvGenDevice, uint32_t ui32Event, | |
uint32_t ui32MsgData, void *pvMsgData); | |
//***************************************************************************** | |
// | |
// Main HID device class event handler function. | |
// | |
// \param pvGenericDevice is the event callback pointer provided during | |
// USBDHIDInit().This is a pointer to our HID device structure | |
// (&g_sHIDKeybDevice). | |
// \param ui32Event identifies the event we are being called back for. | |
// \param ui32MsgData is an event-specific value. | |
// \param pvMsgData is an event-specific pointer. | |
// | |
// This function is called by the HID device class driver to inform the | |
// application of particular asynchronous events related to operation of the | |
// Generic HID device. | |
// | |
// \return Returns a value which is event-specific. | |
// | |
//***************************************************************************** | |
static uint32_t | |
HIDGenRxHandler(void *pvGenDevice, uint32_t ui32Event, | |
uint32_t ui32MsgData, void *pvMsgData) | |
{ | |
tHIDGenericInstance *psInst; | |
tUSBDHIDGenericDevice *psGenericDevice; | |
// | |
// Make sure we did not get a NULL pointer. | |
// | |
ASSERT(pvGenDevice); | |
// | |
// Get a pointer to our instance data | |
// | |
psGenericDevice = (tUSBDHIDGenericDevice *)pvGenDevice; | |
psInst = &psGenericDevice->sPrivateData; | |
// | |
// Which event were we sent? | |
// | |
switch (ui32Event) | |
{ | |
// | |
// The host has connected to us and configured the device. | |
// | |
case USB_EVENT_CONNECTED: | |
{ | |
psInst->ui8USBConfigured = true; | |
// | |
// Pass the information on to the client. | |
// | |
psGenericDevice->pfnCallback(psGenericDevice->pvCBData, | |
USB_EVENT_CONNECTED, 0, (void *)0); | |
break; | |
} | |
// | |
// The host has disconnected from us. | |
// | |
case USB_EVENT_DISCONNECTED: | |
{ | |
psInst->ui8USBConfigured = false; | |
// | |
// Pass the information on to the client. | |
// | |
psGenericDevice->pfnCallback(psGenericDevice->pvCBData, | |
USB_EVENT_DISCONNECTED, 0, | |
(void *)0); | |
break; | |
} | |
// | |
// The host is polling us for a particular report and the HID driver | |
// is asking for the latest version to transmit. | |
// | |
case USBD_HID_EVENT_IDLE_TIMEOUT: | |
case USBD_HID_EVENT_GET_REPORT: | |
{ | |
// | |
// We only support a single input report so we don't need to check | |
// the ui32MsgValue parameter in this case. Set the report pointer | |
// in *pvMsgData and return the length of the report in bytes. | |
// | |
*(uint8_t **)pvMsgData = psInst->pui8Report; | |
return(GENERIC_IN_REPORT_SIZE); | |
} | |
// | |
// The device class driver has completed sending a report to the | |
// host in response to a Get_Report request. | |
// | |
case USBD_HID_EVENT_REPORT_SENT: | |
{ | |
// | |
// We have nothing to do here. | |
// | |
break; | |
} | |
// | |
// This event is sent in response to a host Set_Report request. We | |
// must return a pointer to a buffer large enough to receive the | |
// report into. | |
// | |
case USBD_HID_EVENT_GET_REPORT_BUFFER: | |
{ | |
// | |
// Are we being asked for a report that is shorter than the storage | |
// we have set aside for this? The only output report we define is | |
// 8 bits long so we really expect to see a length of 1 passed. | |
// | |
if((uint32_t)pvMsgData == GENERIC_OUT_REPORT_SIZE ) | |
{ | |
// | |
// Yes - return our pointer. | |
// | |
return((uint32_t)psInst->pui8DataBuffer); | |
} | |
else | |
{ | |
// | |
// We are being passed a report that is longer than the | |
// only report we expect so return NULL. This causes the | |
// device class driver to stall the request. | |
// | |
return(0); | |
} | |
} | |
// | |
// This event indicates that the host has sent us an Output or | |
// Feature report and that the report is now in the buffer we provided | |
// on the previous USBD_HID_EVENT_GET_REPORT_BUFFER callback. | |
// | |
case USBD_HID_EVENT_SET_REPORT: | |
{ | |
// | |
// Pass the information on to the client. | |
// | |
psGenericDevice->pfnCallback( | |
psGenericDevice->pvCBData, | |
USBD_HID_KEYB_EVENT_SET_LEDS, | |
psInst->pui8DataBuffer[0], | |
(void *) &psInst->pui8DataBuffer[0]); | |
break; | |
} | |
// | |
// The host is asking us to set either boot or report protocol (not | |
// that it makes any difference to this particular mouse). | |
// | |
case USBD_HID_EVENT_SET_PROTOCOL: | |
{ | |
psInst->ui8Protocol = ui32MsgData; | |
break; | |
} | |
// | |
// The host is asking us to tell it which protocol we are currently | |
// using, boot or request. | |
// | |
case USBD_HID_EVENT_GET_PROTOCOL: | |
{ | |
return(psInst->ui8Protocol); | |
} | |
// | |
// Pass ERROR, SUSPEND and RESUME to the client unchanged. | |
// | |
case USB_EVENT_ERROR: | |
case USB_EVENT_SUSPEND: | |
case USB_EVENT_RESUME: | |
case USB_EVENT_LPM_RESUME: | |
case USB_EVENT_LPM_SLEEP: | |
case USB_EVENT_LPM_ERROR: | |
{ | |
return(psGenericDevice->pfnCallback( | |
psGenericDevice->pvCBData, | |
ui32Event, ui32MsgData, pvMsgData)); | |
} | |
// | |
// We ignore all other events. | |
// | |
default: | |
{ | |
break; | |
} | |
} | |
return(0); | |
} | |
//***************************************************************************** | |
// | |
// HID device class transmit channel event handler function. | |
// | |
// \param pvGenericDevice is the event callback pointer provided during | |
// USBDHIDInit(). This is a pointer to our HID device structure | |
// (&g_sHIDKeybDevice). | |
// \param ui32Event identifies the event we are being called back for. | |
// \param ui32MsgData is an event-specific value. | |
// \param pvMsgData is an event-specific pointer. | |
// | |
// This function is called by the HID device class driver to inform the | |
// application of particular asynchronous events related to report | |
// transmissions made using the interrupt IN endpoint. | |
// | |
// \return Returns a value which is event-specific. | |
// | |
//***************************************************************************** | |
static uint32_t | |
HIDGenTxHandler(void *pvGenericDevice, uint32_t ui32Event, | |
uint32_t ui32MsgData, void *pvMsgData) | |
{ | |
tHIDGenericInstance *psInst; | |
tUSBDHIDGenericDevice *psHIDGenDevice; | |
tUSBDHIDDevice *psHIDDevice; | |
// | |
// Make sure we did not get a NULL pointer. | |
// | |
ASSERT(pvGenericDevice); | |
// | |
// Get a pointer to our instance data | |
// | |
psHIDGenDevice = (tUSBDHIDGenericDevice *)pvGenericDevice; | |
psInst = &psHIDGenDevice->sPrivateData; | |
psHIDDevice = &psInst->sHIDDevice; | |
// | |
// Which event were we sent? | |
// | |
switch (ui32Event) | |
{ | |
// | |
// A report transmitted via the interrupt IN endpoint was acknowledged | |
// by the host. | |
// | |
case USB_EVENT_TX_COMPLETE: | |
{ | |
// | |
// Yes - go ahead and send another report immediately. | |
// | |
USBDHIDReportWrite((void *)psHIDDevice, | |
psInst->pui8Report, | |
GENERIC_IN_REPORT_SIZE, true); | |
// | |
// Pass the event on to the client. | |
// | |
psHIDGenDevice->pfnCallback(psHIDGenDevice->pvCBData, | |
USB_EVENT_TX_COMPLETE, ui32MsgData, | |
(void *)0); | |
break; | |
} | |
// | |
// We ignore all other events related to transmission of reports via | |
// the interrupt IN endpoint. | |
// | |
default: | |
{ | |
break; | |
} | |
} | |
return(0); | |
} | |
//***************************************************************************** | |
// | |
//! Initializes HID Generic device operation for a given USB controller. | |
//! | |
//! \param ui32Index is the index of the USB controller which is to be | |
//! initialized for HID Generic device operation. | |
//! \param psHIDKbDevice points to a structure containing parameters | |
//! customizing the operation of the HID Generic device. | |
//! | |
//! An application wishing to offer a USB HID Generic interface to a USB host | |
//! must call this function to initialize the USB controller and attach the | |
//! Generic device to the USB bus. This function performs all required USB | |
//! initialization. | |
//! | |
//! On successful completion, this function returns the \e psHIDKbDevice | |
//! pointer passed to it. This must be passed on all future calls to the HID | |
//! Generic device driver. | |
//! | |
//! When a host connects and configures the device, the application callback | |
//! receives \b USB_EVENT_CONNECTED after which calls can be made to | |
//! USBDHIDGenericKeyStateChange() to report key presses and releases to the | |
//! USB host. | |
//! | |
//! \note The application must not make any calls to the lower level USB device | |
//! interfaces if interacting with USB via the USB HID Generic device class | |
//! API. Doing so causes unpredictable (though almost certainly | |
//! unpleasant) behavior. | |
//! | |
//! \return Returns NULL on failure or the \e psHIDKbDevice pointer on success. | |
// | |
//***************************************************************************** | |
tUSBDHIDGenericDevice * | |
USBDHIDGenericInit(uint32_t ui32Index, tUSBDHIDGenericDevice *psHIDGenDevice) | |
{ | |
void *pvRetcode; | |
tUSBDHIDDevice *psHIDDevice; | |
tConfigDescriptor *pConfigDesc; | |
// | |
// Check parameter validity. | |
// | |
ASSERT(psHIDGenDevice); | |
ASSERT(psHIDGenDevice->ppui8StringDescriptors); | |
ASSERT(psHIDGenDevice->pfnCallback); | |
// | |
// Get a pointer to the HID device data. | |
// | |
psHIDDevice = &psHIDGenDevice->sPrivateData.sHIDDevice; | |
// | |
// Call the common initialization routine. | |
// | |
pvRetcode = USBDHIDGenericCompositeInit(ui32Index, psHIDGenDevice, 0); | |
pConfigDesc = (tConfigDescriptor *)g_pui8GenDescriptor; | |
pConfigDesc->bmAttributes = psHIDGenDevice->ui8PwrAttributes; | |
pConfigDesc->bMaxPower = (uint8_t)(psHIDGenDevice->ui16MaxPowermA / 2); | |
// | |
// If we initialized the HID layer successfully, pass our device pointer | |
// back as the return code, otherwise return NULL to indicate an error. | |
// | |
if(pvRetcode) | |
{ | |
// | |
// Initialize the lower layer HID driver and pass it the various | |
// structures and descriptors necessary to declare that we are a | |
// Generic. | |
// | |
pvRetcode = USBDHIDInit(ui32Index, psHIDDevice); | |
return((void *)psHIDGenDevice); | |
} | |
else | |
{ | |
return((void *)0); | |
} | |
} | |
//***************************************************************************** | |
// | |
//! Initializes HID Generic device operation for a given USB controller. | |
//! | |
//! \param ui32Index is the index of the USB controller which is to be | |
//! initialized for HID Generic device operation. | |
//! \param psHIDKbDevice points to a structure containing parameters | |
//! customizing the operation of the HID Generic device. | |
//! \param psCompEntry is the composite device entry to initialize when | |
//! creating a composite device. | |
//! | |
//! This call is very similar to USBDHIDGenericInit() except that it is used | |
//! for initializing an instance of the HID Generic device for use in a | |
//! composite device. If this HID Generic is part of a composite device, then | |
//! the \e psCompEntry should point to the composite device entry to | |
//! initialize. This is part of the array that is passed to the | |
//! USBDCompositeInit() function. | |
//! | |
//! \return Returns zero on failure or a non-zero instance value that should be | |
//! used with the remaining USB HID Generic APIs. | |
// | |
//***************************************************************************** | |
tUSBDHIDGenericDevice * | |
USBDHIDGenericCompositeInit(uint32_t ui32Index, | |
tUSBDHIDGenericDevice *psHIDGenDevice, | |
tCompositeEntry *psCompEntry) | |
{ | |
tHIDGenericInstance *psInst; | |
tUSBDHIDDevice *psHIDDevice; | |
// | |
// Check parameter validity. | |
// | |
ASSERT(psHIDGenDevice); | |
ASSERT(psHIDGenDevice->ppui8StringDescriptors); | |
ASSERT(psHIDGenDevice->pfnCallback); | |
// | |
// Get a pointer to our instance data | |
// | |
psInst = &psHIDGenDevice->sPrivateData; | |
// | |
// Initialize the various fields in our instance structure. | |
// | |
psInst->ui8USBConfigured = 0; | |
psInst->ui8Protocol = USB_HID_PROTOCOL_REPORT; | |
psInst->sReportIdle.ui8Duration4mS = 125; | |
psInst->sReportIdle.ui8ReportID = 0; | |
psInst->sReportIdle.ui32TimeSinceReportmS = 0; | |
psInst->sReportIdle.ui16TimeTillNextmS = 0; | |
psInst->eGenericState = HID_GENERIC_STATE_UNCONFIGURED; | |
// | |
// Get a pointer to the HID device data. | |
// | |
psHIDDevice = &psInst->sHIDDevice; | |
// | |
// Initialize the HID device class instance structure based on input from | |
// the caller. | |
// | |
psHIDDevice->ui16PID = psHIDGenDevice->ui16PID; | |
psHIDDevice->ui16VID = psHIDGenDevice->ui16VID; | |
psHIDDevice->ui16MaxPowermA = psHIDGenDevice->ui16MaxPowermA; | |
psHIDDevice->ui8PwrAttributes = psHIDGenDevice->ui8PwrAttributes; | |
psHIDDevice->ui8Subclass = USB_HID_SCLASS_BOOT; | |
psHIDDevice->ui8Protocol = USB_HID_PROTOCOL_KEYB; | |
psHIDDevice->ui8NumInputReports = 1; | |
psHIDDevice->psReportIdle = 0; | |
psHIDDevice->pfnRxCallback = HIDGenRxHandler; | |
psHIDDevice->pvRxCBData = (void *)psHIDGenDevice; | |
psHIDDevice->pfnTxCallback = HIDGenTxHandler; | |
psHIDDevice->pvTxCBData = (void *)psHIDGenDevice; | |
psHIDDevice->bUseOutEndpoint = false, | |
psHIDDevice->psHIDDescriptor = &g_sGenHIDDescriptor; | |
psHIDDevice->ppui8ClassDescriptors = g_pui8GenClassDescriptors; | |
psHIDDevice->ppui8StringDescriptors = | |
psHIDGenDevice->ppui8StringDescriptors; | |
psHIDDevice->ui32NumStringDescriptors = | |
psHIDGenDevice->ui32NumStringDescriptors; | |
psHIDDevice->ppsConfigDescriptor = g_ppsHIDConfigDescriptors; | |
psHIDDevice->psReportIdle = &psInst->sReportIdle; | |
// | |
// Initialize the lower layer HID driver and pass it the various structures | |
// and descriptors necessary to declare that we are a Generic. | |
// | |
return(USBDHIDCompositeInit(ui32Index, psHIDDevice, psCompEntry)); | |
} | |
//***************************************************************************** | |
// | |
//! Shuts down the HID Generic device. | |
//! | |
//! \param pvGenericDevice is the pointer to the device instance structure | |
//! as returned by USBDHIDGenericInit(). | |
//! | |
//! This function terminates HID Generic operation for the instance supplied | |
//! and removes the device from the USB bus. Following this call, the | |
//! \e pvGenericDevice instance may not me used in any other call to the HID | |
//! Generic device other than USBDHIDGenericInit(). | |
//! | |
//! \return None. | |
// | |
//***************************************************************************** | |
void | |
USBDHIDGenericTerm(void *pvGenericDevice) | |
{ | |
tUSBDHIDGenericDevice *psHIDGenDevice; | |
tUSBDHIDDevice *psHIDDevice; | |
ASSERT(pvGenericDevice); | |
// | |
// Get a pointer to the device. | |
// | |
psHIDGenDevice = (tUSBDHIDGenericDevice *)pvGenericDevice; | |
// | |
// Get a pointer to the HID device data. | |
// | |
psHIDDevice = &psHIDGenDevice->sPrivateData.sHIDDevice; | |
// | |
// Mark the device as no longer configured. | |
// | |
psHIDGenDevice->sPrivateData.ui8USBConfigured = 0; | |
// | |
// Terminate the low level HID driver. | |
// | |
USBDHIDTerm(psHIDDevice); | |
} | |
//***************************************************************************** | |
// | |
//! Sets the client-specific pointer parameter for the Generic callback. | |
//! | |
//! \param pvGenericDevice is the pointer to the device instance structure | |
//! as returned by USBDHIDGenericInit(). | |
//! \param pvCBData is the pointer that client wishes to be provided on each | |
//! event sent to the Generic callback function. | |
//! | |
//! The client uses this function to change the callback pointer passed in | |
//! the first parameter on all callbacks to the \e pfnCallback function | |
//! passed on USBDHIDGenericInit(). | |
//! | |
//! If a client wants to make runtime changes in the callback pointer, it must | |
//! ensure that the \e pvGenericDevice structure passed to | |
//! USBDHIDGenericInit() resides in RAM. If this structure is in flash, | |
//! callback data changes is not possible. | |
//! | |
//! \return Returns the previous callback pointer that was set for this | |
//! instance. | |
// | |
//***************************************************************************** | |
void * | |
USBDHIDGenericSetCBData(void *pvGenericDevice, void *pvCBData) | |
{ | |
void *pvOldCBData; | |
tUSBDHIDGenericDevice *psGeneric; | |
// | |
// Check for a NULL pointer in the device parameter. | |
// | |
ASSERT(pvGenericDevice); | |
// | |
// Get a pointer to our Generic device. | |
// | |
psGeneric = (tUSBDHIDGenericDevice *)pvGenericDevice; | |
// | |
// Save the old callback pointer and replace it with the new value. | |
// | |
pvOldCBData = psGeneric->pvCBData; | |
psGeneric->pvCBData = pvCBData; | |
// | |
// Pass the old callback pointer back to the caller. | |
// | |
return(pvOldCBData); | |
} | |
//***************************************************************************** | |
// | |
//! Reports a key state change to the USB host. | |
//! | |
//! \param pvGenericDevice is the pointer to the device instance structure | |
//! as returned by USBDHIDGenericInit(). | |
//! \param ui8Modifiers contains the states of each of the Generic modifiers | |
//! (left/right shift, ctrl, alt or GUI keys). Valid values are logical OR | |
//! combinations of the labels \b HID_KEYB_LEFT_CTRL, \b HID_KEYB_LEFT_SHIFT, | |
//! \b HID_KEYB_LEFT_ALT, \b HID_KEYB_LEFT_GUI, \b HID_KEYB_RIGHT_CTRL, \b | |
//! HID_KEYB_RIGHT_SHIFT, \b HID_KEYB_RIGHT_ALT and \b HID_KEYB_RIGHT_GUI. | |
//! Presence of one of these bit flags indicates that the relevant modifier | |
//! key is pressed and absence indicates that it is released. | |
//! \param ui8UsageCode is the usage code of the key whose state has changed. | |
//! If only modifier keys have changed, \b HID_KEYB_USAGE_RESERVED should be | |
//! passed in this parameter. | |
//! \param bPress is \b true if the key has been pressed or \b false if it has | |
//! been released. If only modifier keys have changed state, this parameter is | |
//! ignored. | |
//! | |
//! This function adds or removes a key usage code from the list of keys | |
//! currently pressed and schedules a report transmission to the host to | |
//! inform it of the new Generic state. If the maximum number of simultaneous | |
//! key presses are already recorded, the report to the host contains the | |
//! rollover error code, \b HID_KEYB_USAGE_ROLLOVER instead of key usage codes | |
//! and the caller receives return code \b KEYB_ERR_TOO_MANY_KEYS. | |
//! | |
//! \return Returns \b KEYB_SUCCESS if the key usage code was added to or | |
//! removed from the current list successfully. \b KEYB_ERR_TOO_MANY_KEYS is | |
//! returned if an attempt is made to press a 7th key (the BIOS Generic | |
//! protocol can report no more than 6 simultaneously pressed keys). If called | |
//! before the USB host has configured the device, \b KEYB_ERR_NOT_CONFIGURED | |
//! is returned and, if an error is reported while attempting to transmit the | |
//! report, \b KEYB_ERR_TX_ERROR is returned. If an attempt is made to remove | |
//! a key from the pressed list (by setting parameter \e bPressed to \b false) | |
//! but the key usage code is not found, \b KEYB_ERR_NOT_FOUND is returned. | |
// | |
//***************************************************************************** | |
uint32_t | |
USBDHIDGenericKeyStateChange(void *pvGenericDevice, uint8_t * buffer) | |
{ | |
uint32_t ui32Loop, ui32Count; | |
tHIDGenericInstance *psInst; | |
tUSBDHIDGenericDevice *psHIDKbDevice; | |
tUSBDHIDDevice *psHIDDevice; | |
psHIDKbDevice = (tUSBDHIDGenericDevice *)pvGenericDevice; | |
// | |
// Get a pointer to the HID device data. | |
// | |
psHIDDevice = &psHIDKbDevice->sPrivateData.sHIDDevice; | |
// | |
// Assume all is well until we determine otherwise. | |
// | |
// | |
// Get a pointer to our instance data | |
// | |
psInst = &psHIDKbDevice->sPrivateData; | |
// | |
// Build the report from the current list of keys. If we added a key | |
// and got a bad return code indicating a roll over error, we need to | |
// send a roll over report | |
// | |
for(ui32Loop = 0; ui32Loop < GENERIC_IN_REPORT_SIZE; ui32Loop++) | |
{ | |
psInst->pui8Report[ui32Loop] = buffer[ui32Loop]; | |
} | |
// | |
// If we are not configured, return an error here before trying to send | |
// anything. | |
// | |
if(!psInst->ui8USBConfigured) | |
{ | |
return(KEYB_ERR_NOT_CONFIGURED); | |
} | |
// | |
// Only send a report if the transmitter is currently free. | |
// | |
if(USBDHIDTxPacketAvailable((void *)psHIDDevice)) | |
{ | |
// | |
// Send the report to the host. | |
// | |
psInst->eGenericState = HID_GENERIC_STATE_SEND; | |
ui32Count = USBDHIDReportWrite((void *)psHIDDevice, | |
psInst->pui8Report, GENERIC_IN_REPORT_SIZE, | |
true); | |
// | |
// Did we schedule a packet for transmission correctly? | |
// | |
if(!ui32Count) | |
{ | |
// | |
// No - report the error to the caller. | |
// | |
return(KEYB_ERR_TX_ERROR); | |
} | |
} | |
else | |
{ | |
// | |
// We can't send the report immediately so mark the instance so that | |
// it is sent next time the transmitter is free. | |
// | |
} | |
// | |
// If we get this far, the key information was sent successfully. Are | |
// too many keys currently pressed, though? | |
// | |
return(KEYB_SUCCESS); | |
} | |
uint32_t | |
USBDHIDSendData(void *pvGenericDevice, uint8_t * buffer) | |
{ | |
uint32_t ui32Loop, ui32Count; | |
tHIDGenericInstance *psInst; | |
tUSBDHIDGenericDevice *psHIDGenDevice; | |
tUSBDHIDDevice *psHIDDevice; | |
psHIDGenDevice = (tUSBDHIDGenericDevice *)pvGenericDevice; | |
// | |
// Get a pointer to the HID device data. | |
// | |
psHIDDevice = &psHIDGenDevice->sPrivateData.sHIDDevice; | |
// | |
// Get a pointer to our instance data | |
// | |
psInst = &psHIDGenDevice->sPrivateData; | |
// | |
// Build the report from the current list of keys. If we added a key | |
// and got a bad return code indicating a roll over error, we need to | |
// send a roll over report | |
// | |
for(ui32Loop = 0; ui32Loop < GENERIC_OUT_REPORT_SIZE; ui32Loop++) | |
{ | |
psInst->pui8Report[ui32Loop] = buffer[ui32Loop]; | |
} | |
// | |
// If we are not configured, return an error here before trying to send | |
// anything. | |
// | |
if(!psInst->ui8USBConfigured) | |
{ | |
return(KEYB_ERR_NOT_CONFIGURED); | |
} | |
// | |
// Only send a report if the transmitter is currently free. | |
// | |
if(USBDHIDTxPacketAvailable((void *)psHIDDevice)) | |
{ | |
// | |
// Send the report to the host. | |
// | |
psInst->eGenericState = HID_GENERIC_STATE_SEND; | |
ui32Count = USBDHIDReportWrite((void *)psHIDDevice, | |
psInst->pui8Report, GENERIC_IN_REPORT_SIZE, | |
true); | |
// | |
// Did we schedule a packet for transmission correctly? | |
// | |
if(!ui32Count) | |
{ | |
// | |
// No - report the error to the caller. | |
// | |
return(KEYB_ERR_TX_ERROR); | |
} | |
} | |
else | |
{ | |
// | |
// We can't send the report immediately so mark the instance so that | |
// it is sent next time the transmitter is free. | |
// | |
//psInst->bChangeMade = true; | |
} | |
// | |
// If we get this far, the key information was sent successfully. Are | |
// too many keys currently pressed, though? | |
// | |
return(KEYB_SUCCESS); | |
} | |
#ifndef DEPRECATED | |
//***************************************************************************** | |
// | |
//! Reports the device power status (bus or self powered) to the USB library. | |
//! | |
//! \param pvGenericDevice is the pointer to the Generic device instance | |
//! structure. | |
//! \param ui8Power indicates the current power status, either | |
//! \b USB_STATUS_SELF_PWR or \b USB_STATUS_BUS_PWR. | |
//! | |
//! Applications which support switching between bus or self powered | |
//! operation should call this function whenever the power source changes | |
//! to indicate the current power status to the USB library. This information | |
//! is required by the USB library to allow correct responses to be provided | |
//! when the host requests status from the device. | |
//! | |
//! \return None. | |
// | |
//***************************************************************************** | |
void | |
USBDHIDGenericPowerStatusSet(void *pvGenericDevice, uint8_t ui8Power) | |
{ | |
tUSBDHIDGenericDevice *psHIDKbDevice; | |
tUSBDHIDDevice *psHIDDevice; | |
ASSERT(pvGenericDevice); | |
// | |
// Get the Generic device pointer. | |
// | |
psHIDKbDevice = (tUSBDHIDGenericDevice *)pvGenericDevice; | |
// | |
// Get a pointer to the HID device data. | |
psHIDDevice = &psHIDKbDevice->sPrivateData.sHIDDevice; | |
// | |
// Pass the request through to the lower layer. | |
// | |
USBDHIDPowerStatusSet((void *)psHIDDevice, ui8Power); | |
} | |
#endif | |
//***************************************************************************** | |
// | |
//! Requests a remote wake up to resume communication when in suspended state. | |
//! | |
//! \param pvGenericDevice is the pointer to the Generic device instance | |
//! structure. | |
//! | |
//! When the bus is suspended, an application which supports remote wake up | |
//! (advertised to the host via the configuration descriptor) may call this | |
//! function to initiate remote wake up signaling to the host. If the remote | |
//! wake up feature has not been disabled by the host, this causes the bus | |
//! to resume operation within 20mS. If the host has disabled remote wake up, | |
//! \b false is returned to indicate that the wake up request was not | |
//! successful. | |
//! | |
//! \return Returns \b true if the remote wake up is not disabled and the | |
//! signaling was started or \b false if remote wake up is disabled or if | |
//! signaling is currently ongoing following a previous call to this function. | |
// | |
//***************************************************************************** | |
bool | |
USBDHIDGenericRemoteWakeupRequest(void *pvGenericDevice) | |
{ | |
tUSBDHIDGenericDevice *psHIDKbDevice; | |
tUSBDHIDDevice *psHIDDevice; | |
ASSERT(pvGenericDevice); | |
// | |
// Get the Generic device pointer. | |
// | |
psHIDKbDevice = (tUSBDHIDGenericDevice *)pvGenericDevice; | |
// | |
// Get a pointer to the HID device data. | |
// | |
psHIDDevice = &psHIDKbDevice->sPrivateData.sHIDDevice; | |
// | |
// Pass the request through to the lower layer. | |
// | |
return(USBDHIDRemoteWakeupRequest((void *)psHIDDevice)); | |
} | |
//***************************************************************************** | |
// | |
// Close the Doxygen group. | |
//! @} | |
// | |
//***************************************************************************** |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment