Skip to content

Instantly share code, notes, and snippets.

@duanebester
Created August 20, 2014 19:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save duanebester/068c87d84d8708603d6c to your computer and use it in GitHub Desktop.
Save duanebester/068c87d84d8708603d6c to your computer and use it in GitHub Desktop.
#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