diff options
| author | Yuval Adam <yuv.adm@gmail.com> | 2012-10-29 23:08:53 +0200 |
|---|---|---|
| committer | Yuval Adam <yuv.adm@gmail.com> | 2012-10-29 23:08:53 +0200 |
| commit | c241dbd7e78c50327781a35d88d9f2db7ff2b271 (patch) | |
| tree | 2c84fe512c0cd3ee328244bca2f8ed4f9622074d /usblib/device/usbdhidkeyb.c | |
| parent | 4ba8614c006f9828f0796c140bc3e13c9e67938c (diff) | |
Added usblib
Diffstat (limited to 'usblib/device/usbdhidkeyb.c')
| -rw-r--r-- | usblib/device/usbdhidkeyb.c | 1119 |
1 files changed, 1119 insertions, 0 deletions
diff --git a/usblib/device/usbdhidkeyb.c b/usblib/device/usbdhidkeyb.c new file mode 100644 index 0000000..8b4aa95 --- /dev/null +++ b/usblib/device/usbdhidkeyb.c @@ -0,0 +1,1119 @@ +//*****************************************************************************
+//
+// usbdhidkeyb.c - USB HID Keyboard device class driver.
+//
+// Copyright (c) 2008-2012 Texas Instruments Incorporated. All rights reserved.
+// Software License Agreement
+//
+// Texas Instruments (TI) is supplying this software for use solely and
+// exclusively on TI's microcontroller products. The software is owned by
+// TI and/or its suppliers, and is protected under applicable copyright
+// laws. You may not combine this software with "viral" open-source
+// software in order to form a larger program.
+//
+// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
+// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
+// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
+// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
+// DAMAGES, FOR ANY REASON WHATSOEVER.
+//
+// This is part of revision 9453 of the Stellaris USB Library.
+//
+//*****************************************************************************
+
+#include "inc/hw_types.h"
+#include "driverlib/debug.h"
+#include "driverlib/usb.h"
+#include "usblib/usblib.h"
+#include "usblib/device/usbdevice.h"
+#include "usblib/usbhid.h"
+#include "usblib/device/usbdhid.h"
+#include "usblib/device/usbdhidkeyb.h"
+
+//*****************************************************************************
+//
+//! \addtogroup hid_keyboard_device_class_api
+//! @{
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// The following is the HID report structure definition that is passed back
+// to the host.
+//
+//*****************************************************************************
+static const unsigned char g_pucKeybReportDescriptor[]=
+{
+ UsagePage(USB_HID_GENERIC_DESKTOP),
+ Usage(USB_HID_KEYBOARD),
+ 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),
+
+ //
+ // Keyboard 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 class descriptor table. For the keyboard class, we have only a
+// single report descriptor.
+//
+//*****************************************************************************
+static const unsigned char * const g_pKeybClassDescriptors[] =
+{
+ g_pucKeybReportDescriptor
+};
+
+//*****************************************************************************
+//
+// The HID descriptor for the keyboard device.
+//
+//*****************************************************************************
+static const tHIDDescriptor g_sKeybHIDDescriptor =
+{
+ 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_pucKeybReportDescriptor) // Size of report descriptor
+ }
+ }
+};
+
+//*****************************************************************************
+//
+// Forward references for keyboard device callback functions.
+//
+//*****************************************************************************
+static unsigned long HIDKeyboardRxHandler(void *pvCBData,
+ unsigned long ulEvent,
+ unsigned long ulMsgData,
+ void *pvMsgData);
+static unsigned long HIDKeyboardTxHandler(void *pvCBData,
+ unsigned long ulEvent,
+ unsigned long ulMsgData,
+ void *pvMsgData);
+
+//*****************************************************************************
+//
+// Main HID device class event handler function.
+//
+// \param pvCBData is the event callback pointer provided during USBDHIDInit().
+// This is a pointer to our HID device structure (&g_sHIDKeybDevice).
+// \param ulEvent identifies the event we are being called back for.
+// \param ulMsgData 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
+// keyboard HID device.
+//
+// \return Returns a value which is event-specific.
+//
+//*****************************************************************************
+static unsigned long
+HIDKeyboardRxHandler(void *pvCBData, unsigned long ulEvent,
+ unsigned long ulMsgData, void *pvMsgData)
+{
+ tHIDKeyboardInstance *psInst;
+ tUSBDHIDKeyboardDevice *psDevice;
+
+ //
+ // Make sure we didn't get a NULL pointer.
+ //
+ ASSERT(pvCBData);
+
+ //
+ // Get a pointer to our instance data
+ //
+ psDevice = (tUSBDHIDKeyboardDevice *)pvCBData;
+ psInst = psDevice->psPrivateHIDKbdData;
+
+ //
+ // Which event were we sent?
+ //
+ switch (ulEvent)
+ {
+ //
+ // The host has connected to us and configured the device.
+ //
+ case USB_EVENT_CONNECTED:
+ {
+ psInst->ucUSBConfigured = true;
+
+ //
+ // Pass the information on to the client.
+ //
+ psDevice->pfnCallback(psDevice->pvCBData, USB_EVENT_CONNECTED,
+ 0, (void *)0);
+
+ break;
+ }
+
+ //
+ // The host has disconnected from us.
+ //
+ case USB_EVENT_DISCONNECTED:
+ {
+ psInst->ucUSBConfigured = false;
+
+ //
+ // Pass the information on to the client.
+ //
+ psDevice->pfnCallback(psDevice->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 ulMsgValue parameter in this case. Set the report pointer
+ // in *pvMsgData and return the length of the report in bytes.
+ //
+ *(unsigned char **)pvMsgData = psInst->pucReport;
+ return(KEYB_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((unsigned long)pvMsgData == KEYB_OUT_REPORT_SIZE )
+ {
+ //
+ // Yes - return our pointer.
+ //
+ return((unsigned long)psInst->pucDataBuffer);
+ }
+ 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:
+ {
+ //
+ // Inform the application if the keyboard LEDs have changed.
+ //
+ if(psInst->ucLEDStates != psInst->pucDataBuffer[0])
+ {
+ //
+ // Note the new LED states.
+ //
+ psInst->ucLEDStates = psInst->pucDataBuffer[0];
+
+ //
+ // Pass the information on to the client.
+ //
+ psDevice->pfnCallback(psDevice->pvCBData,
+ USBD_HID_KEYB_EVENT_SET_LEDS,
+ psInst->pucDataBuffer[0], (void *)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->ucProtocol = ulMsgData;
+ 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->ucProtocol);
+ }
+
+ //
+ // Pass ERROR, SUSPEND and RESUME to the client unchanged.
+ //
+ case USB_EVENT_ERROR:
+ case USB_EVENT_SUSPEND:
+ case USB_EVENT_RESUME:
+ {
+ return(psDevice->pfnCallback(psDevice->pvCBData, ulEvent,
+ ulMsgData, pvMsgData));
+ }
+
+ //
+ // We ignore all other events.
+ //
+ default:
+ {
+ break;
+ }
+ }
+ return(0);
+}
+
+//*****************************************************************************
+//
+// HID device class transmit channel event handler function.
+//
+// \param pvCBData is the event callback pointer provided during USBDHIDInit().
+// This is a pointer to our HID device structure (&g_sHIDKeybDevice).
+// \param ulEvent identifies the event we are being called back for.
+// \param ulMsgData 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 unsigned long
+HIDKeyboardTxHandler(void *pvCBData, unsigned long ulEvent,
+ unsigned long ulMsgData, void *pvMsgData)
+{
+ tHIDKeyboardInstance *psInst;
+ tUSBDHIDKeyboardDevice *psDevice;
+ tUSBDHIDDevice *psHIDDevice;
+ unsigned long ulCount;
+
+ //
+ // Make sure we didn't get a NULL pointer.
+ //
+ ASSERT(pvCBData);
+
+ //
+ // Get a pointer to our instance data
+ //
+ psDevice = (tUSBDHIDKeyboardDevice *)pvCBData;
+ psInst = psDevice->psPrivateHIDKbdData;
+ psHIDDevice = &psDevice->psPrivateHIDKbdData->sHIDDevice;
+
+ //
+ // Which event were we sent?
+ //
+ switch (ulEvent)
+ {
+ //
+ // A report transmitted via the interrupt IN endpoint was acknowledged
+ // by the host.
+ //
+ case USB_EVENT_TX_COMPLETE:
+ {
+ //
+ // Do we have any pending changes needing transmitted?
+ //
+ if(psInst->bChangeMade)
+ {
+ //
+ // Yes - go ahead and send another report immediately.
+ //
+ ulCount = USBDHIDReportWrite((void *)psHIDDevice,
+ psInst->pucReport,
+ KEYB_IN_REPORT_SIZE, true);
+
+ //
+ // If we scheduled the report for transmission, clear the
+ // change flag.
+ //
+ if(ulCount != 0)
+ {
+ psInst->bChangeMade = false;
+ }
+ }
+ else
+ {
+ //
+ // Our last transmission is complete and we have nothing more
+ // to send.
+ //
+ psInst->eKeyboardState = HID_KEYBOARD_STATE_IDLE;
+ }
+
+ //
+ // Pass the event on to the client.
+ //
+ psDevice->pfnCallback(psDevice->pvCBData, USB_EVENT_TX_COMPLETE,
+ ulMsgData, (void *)0);
+
+ break;
+ }
+
+ //
+ // We ignore all other events related to transmission of reports via
+ // the interrupt IN endpoint.
+ //
+ default:
+ {
+ break;
+ }
+ }
+
+ return(0);
+}
+
+//*****************************************************************************
+//
+// Add the supplied usage code to the list of keys currently in the pressed
+// state.
+//
+// \param ucUsageCode is the HID usage code of the newly pressed key.
+//
+// This function adds the supplied usage code to the global list of keys which
+// are currently pressed (assuming it is not already noted as pressed and that
+// there is space in the list to hold the new information). The return code
+// indicates success if the list did not overflow and failure if the list
+// already contains as many pressed keys as can be reported.
+//
+// \return Returns \b true if the usage code was successfully added to the
+// list or \b false if there was insufficient space to hold the new key
+// press (in which case the caller should report a roll over error to the host).
+//
+//*****************************************************************************
+static tBoolean
+AddKeyToPressedList(tHIDKeyboardInstance *psInst, unsigned char ucUsageCode)
+{
+ unsigned long ulLoop;
+ tBoolean bRetcode;
+
+ //
+ // Assume all is well until we determine otherwise.
+ //
+ bRetcode = true;
+
+ //
+ // Look through the list of existing pressed keys to see if the new one
+ // is already there.
+ //
+ for(ulLoop = 0; ulLoop < (unsigned long)psInst->ucKeyCount; ulLoop++)
+ {
+ //
+ // Is this key already included in the list of keys in the pressed
+ // state?
+ //
+ if(ucUsageCode == psInst->pucKeysPressed[ulLoop])
+ {
+ //
+ // Yes - drop out.
+ //
+ break;
+ }
+ }
+
+ //
+ // If we exited the loop at the end of the existing key presses, this
+ // key does not exist already so add it if space exists.
+ //
+ if(ulLoop >= psInst->ucKeyCount)
+ {
+ if(psInst->ucKeyCount < KEYB_MAX_CHARS_PER_REPORT)
+ {
+ //
+ // We have room so store the new key press in the list.
+ //
+ psInst->pucKeysPressed[psInst->ucKeyCount] = ucUsageCode;
+ psInst->ucKeyCount++;
+ bRetcode = true;
+ }
+ else
+ {
+ //
+ // We have no room for the new key - declare a rollover error.
+ //
+ bRetcode = false;
+ }
+ }
+
+ return(bRetcode);
+}
+
+//*****************************************************************************
+//
+// Remove the supplied usage code from the list of keys currently in the
+// pressed state.
+//
+// \param ucUsageCode is the HID usage code of the newly released key.
+//
+// This function removes the supplied usage code from the global list of keys
+// which are currently pressed. The return code indicates whether the key was
+// found in the list. On exit, the list will have been cleaned up to ensure
+// that all key presses are contiguous starting at the first entry.
+//
+// \return Returns \b true if the usage code was found and removed from the
+// list or \b false if the code was not found. The caller need not pass a new
+// report to the host if \b false is returned since the key list will not have
+// changed.
+//
+//*****************************************************************************
+static tBoolean
+RemoveKeyFromPressedList(tHIDKeyboardInstance *psInst,
+ unsigned char ucUsageCode)
+{
+ unsigned long ulLoop;
+ unsigned long ulPos;
+
+ //
+ // Keep the compiler happy by setting ulPos to something.
+ //
+ ulPos = 0;
+
+ //
+ // Find the usage code in the current list.
+ //
+ for(ulLoop = 0; ulLoop < KEYB_MAX_CHARS_PER_REPORT; ulLoop++)
+ {
+ if(psInst->pucKeysPressed[ulLoop] == ucUsageCode)
+ {
+ ulPos = ulLoop;
+ break;
+ }
+ }
+
+ //
+ // If we dropped out at the end of the loop, we couldn't find the code so
+ // just return false.
+ //
+ if(ulLoop == KEYB_MAX_CHARS_PER_REPORT)
+ {
+ return(false);
+ }
+
+ //
+ // Now shuffle all the values to the right of the usage code we found
+ // down one position to fill the gap left by removing it.
+ //
+ for(ulLoop = (ulPos + 1); ulLoop < KEYB_MAX_CHARS_PER_REPORT; ulLoop++)
+ {
+ psInst->pucKeysPressed[ulLoop - 1] = psInst->pucKeysPressed[ulLoop];
+ }
+
+ //
+ // Clear the last entry in the array and adjust the number of keys in the
+ // array.
+ //
+ psInst->pucKeysPressed[KEYB_MAX_CHARS_PER_REPORT - 1] =
+ HID_KEYB_USAGE_RESERVED;
+ psInst->ucKeyCount--;
+
+ //
+ // Tell the caller we were successful.
+ //
+ return(true);
+}
+
+//*****************************************************************************
+//
+//! Initializes HID keyboard device operation for a given USB controller.
+//!
+//! \param ulIndex is the index of the USB controller which is to be
+//! initialized for HID keyboard device operation.
+//! \param psDevice points to a structure containing parameters customizing
+//! the operation of the HID keyboard device.
+//!
+//! An application wishing to offer a USB HID keyboard interface to a USB host
+//! must call this function to initialize the USB controller and attach the
+//! keyboard device to the USB bus. This function performs all required USB
+//! initialization.
+//!
+//! On successful completion, this function will return the \e psDevice pointer
+//! passed to it. This must be passed on all future calls to the HID keyboard
+//! device driver.
+//!
+//! When a host connects and configures the device, the application callback
+//! will receive \b USB_EVENT_CONNECTED after which calls can be made to
+//! USBDHIDKeyboardKeyStateChange() 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 keyboard device class
+//! API. Doing so will cause unpredictable (though almost certainly
+//! unpleasant) behavior.
+//!
+//! \return Returns NULL on failure or the psDevice pointer on success.
+//
+//*****************************************************************************
+void *
+USBDHIDKeyboardInit(unsigned long ulIndex,
+ const tUSBDHIDKeyboardDevice *psDevice)
+{
+ void *pvRetcode;
+ tUSBDHIDDevice *psHIDDevice;
+
+ //
+ // Check parameter validity.
+ //
+ ASSERT(psDevice);
+ ASSERT(psDevice->ppStringDescriptors);
+ ASSERT(psDevice->psPrivateHIDKbdData);
+ ASSERT(psDevice->pfnCallback);
+
+ //
+ // Get a pointer to the HID device data.
+ //
+ psHIDDevice = &psDevice->psPrivateHIDKbdData->sHIDDevice;
+
+ //
+ // Call the common initialization routine.
+ //
+ pvRetcode = USBDHIDKeyboardCompositeInit(ulIndex, psDevice);
+
+ //
+ // 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
+ // keyboard.
+ //
+ pvRetcode = USBDHIDInit(ulIndex, psHIDDevice);
+
+ return((void *)psDevice);
+ }
+ else
+ {
+ return((void *)0);
+ }
+}
+
+//*****************************************************************************
+//
+//! Initializes HID keyboard device operation for a given USB controller.
+//!
+//! \param ulIndex is the index of the USB controller which is to be
+//! initialized for HID keyboard device operation.
+//! \param psDevice points to a structure containing parameters customizing
+//! the operation of the HID keyboard device.
+//!
+//! This call is very similar to USBDKeyboardInit() except that it is used for
+//! initializing an instance of the HID keyboard device for use in a composite
+//! device.
+//!
+//! \return Returns zero on failure or a non-zero instance value that should be
+//! used with the remaining USB HID Keyboard APIs.
+//
+//*****************************************************************************
+void *
+USBDHIDKeyboardCompositeInit(unsigned long ulIndex,
+ const tUSBDHIDKeyboardDevice *psDevice)
+{
+ tHIDKeyboardInstance *psInst;
+ unsigned long ulLoop;
+ tUSBDHIDDevice *psHIDDevice;
+
+ //
+ // Check parameter validity.
+ //
+ ASSERT(psDevice);
+ ASSERT(psDevice->ppStringDescriptors);
+ ASSERT(psDevice->psPrivateHIDKbdData);
+ ASSERT(psDevice->pfnCallback);
+
+ //
+ // Get a pointer to our instance data
+ //
+ psInst = psDevice->psPrivateHIDKbdData;
+
+ //
+ // Initialize the various fields in our instance structure.
+ //
+ psInst->ucUSBConfigured = 0;
+ psInst->ucProtocol = USB_HID_PROTOCOL_REPORT;
+ psInst->sReportIdle.ucDuration4mS = 125;
+ psInst->sReportIdle.ucReportID = 0;
+ psInst->sReportIdle.ulTimeSinceReportmS = 0;
+ psInst->sReportIdle.usTimeTillNextmS = 0;
+ psInst->ucLEDStates = 0;
+ psInst->ucKeyCount = 0;
+ for(ulLoop = 0; ulLoop < KEYB_MAX_CHARS_PER_REPORT; ulLoop++)
+ {
+ psInst->pucKeysPressed[ulLoop] = HID_KEYB_USAGE_RESERVED;
+ }
+
+ psInst->eKeyboardState = HID_KEYBOARD_STATE_UNCONFIGURED;
+
+ //
+ // Get a pointer to the HID device data.
+ //
+ psHIDDevice = &psDevice->psPrivateHIDKbdData->sHIDDevice;
+
+ //
+ // Initialize the HID device class instance structure based on input from
+ // the caller.
+ //
+ psHIDDevice->usPID = psDevice->usPID;
+ psHIDDevice->usVID = psDevice->usVID;
+ psHIDDevice->usMaxPowermA = psDevice->usMaxPowermA;
+ psHIDDevice->ucPwrAttributes = psDevice->ucPwrAttributes;
+ psHIDDevice->ucSubclass = USB_HID_SCLASS_BOOT;
+ psHIDDevice->ucProtocol = USB_HID_PROTOCOL_KEYB;
+ psHIDDevice->ucNumInputReports = 1;
+ psHIDDevice->psReportIdle = 0;
+ psHIDDevice->pfnRxCallback = HIDKeyboardRxHandler;
+ psHIDDevice->pvRxCBData = (void *)psDevice;
+ psHIDDevice->pfnTxCallback = HIDKeyboardTxHandler;
+ psHIDDevice->pvTxCBData = (void *)psDevice;
+ psHIDDevice->bUseOutEndpoint = false,
+ psHIDDevice->psHIDDescriptor = &g_sKeybHIDDescriptor;
+ psHIDDevice->ppClassDescriptors = g_pKeybClassDescriptors;
+ psHIDDevice->ppStringDescriptors = psDevice->ppStringDescriptors;
+ psHIDDevice->ulNumStringDescriptors = psDevice->ulNumStringDescriptors;
+ psHIDDevice->psPrivateHIDData = &psInst->sHIDInstance;
+ 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 keyboard.
+ //
+ return(USBDHIDCompositeInit(ulIndex, psHIDDevice));
+}
+
+//*****************************************************************************
+//
+//! Shuts down the HID keyboard device.
+//!
+//! \param pvInstance is the pointer to the device instance structure as
+//! returned by USBDHIDKeyboardInit().
+//!
+//! This function terminates HID keyboard operation for the instance supplied
+//! and removes the device from the USB bus. Following this call, the \e
+//! pvInstance instance may not me used in any other call to the HID keyboard
+//! device other than USBDHIDKeyboardInit().
+//!
+//! \return None.
+//
+//*****************************************************************************
+void
+USBDHIDKeyboardTerm(void *pvInstance)
+{
+ tUSBDHIDKeyboardDevice *psDevice;
+ tUSBDHIDDevice *psHIDDevice;
+
+ ASSERT(pvInstance);
+
+ //
+ // Get a pointer to the device.
+ //
+ psDevice = (tUSBDHIDKeyboardDevice *)pvInstance;
+
+ //
+ // Get a pointer to the HID device data.
+ //
+ psHIDDevice = &psDevice->psPrivateHIDKbdData->sHIDDevice;
+
+ //
+ // Mark the device as no longer configured.
+ //
+ psDevice->psPrivateHIDKbdData->ucUSBConfigured = 0;
+
+ //
+ // Terminate the low level HID driver.
+ //
+ USBDHIDTerm(psHIDDevice);
+}
+
+//*****************************************************************************
+//
+//! Sets the client-specific pointer parameter for the keyboard callback.
+//!
+//! \param pvInstance is the pointer to the device instance structure as
+//! returned by USBDHIDKeyboardInit().
+//! \param pvCBData is the pointer that client wishes to be provided on each
+//! event sent to the keyboard 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 USBDHIDKeyboardInit().
+//!
+//! If a client wants to make runtime changes in the callback pointer, it must
+//! ensure that the pvInstance structure passed to USBDHIDKeyboardInit() resides
+//! in RAM. If this structure is in flash, callback data changes will not be
+//! possible.
+//!
+//! \return Returns the previous callback pointer that was set for this
+//! instance.
+//
+//*****************************************************************************
+void *
+USBDHIDKeyboardSetCBData(void *pvInstance, void *pvCBData)
+{
+ void *pvOldCBData;
+ tUSBDHIDKeyboardDevice *psKeyboard;
+
+ //
+ // Check for a NULL pointer in the device parameter.
+ //
+ ASSERT(pvInstance);
+
+ //
+ // Get a pointer to our keyboard device.
+ //
+ psKeyboard = (tUSBDHIDKeyboardDevice *)pvInstance;
+
+ //
+ // Save the old callback pointer and replace it with the new value.
+ //
+ pvOldCBData = psKeyboard->pvCBData;
+ psKeyboard->pvCBData = pvCBData;
+
+ //
+ // Pass the old callback pointer back to the caller.
+ //
+ return(pvOldCBData);
+}
+
+//*****************************************************************************
+//
+//! Reports a key state change to the USB host.
+//!
+//! \param pvInstance is the pointer to the device instance structure as
+//! returned by USBDHIDKeyboardInit().
+//! \param ucModifiers contains the states of each of the keyboard 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 ucUsageCode 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 keyboard state. If the maximum number of simultaneous
+//! key presses are already recorded, the report to the host will contain the
+//! rollover error code, HID_KEYB_USAGE_ROLLOVER instead of key usage codes
+//! and the caller will receive return code 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 keyboard
+//! 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.
+//
+//*****************************************************************************
+unsigned long
+USBDHIDKeyboardKeyStateChange(void *pvInstance, unsigned char ucModifiers,
+ unsigned char ucUsageCode, tBoolean bPress)
+{
+ tBoolean bRetcode;
+ unsigned long ulLoop;
+ unsigned long ulCount;
+ tHIDKeyboardInstance *psInst;
+ tUSBDHIDKeyboardDevice *psDevice;
+ tUSBDHIDDevice *psHIDDevice;
+
+ psDevice = (tUSBDHIDKeyboardDevice *)pvInstance;
+
+ //
+ // Get a pointer to the HID device data.
+ //
+ psHIDDevice = &psDevice->psPrivateHIDKbdData->sHIDDevice;
+
+ //
+ // Assume all is well until we determine otherwise.
+ //
+ bRetcode = true;
+
+ //
+ // Get a pointer to our instance data
+ //
+ psInst = psDevice->psPrivateHIDKbdData;
+
+ //
+ // Update the global keyboard report with the information passed.
+ //
+ psInst->pucReport[0] = ucModifiers;
+ psInst->pucReport[1] = 0;
+
+ //
+ // Were we passed a usage code for a new key press or release or was
+ // this call just telling us about a modifier change?
+ //
+ if(ucUsageCode != HID_KEYB_USAGE_RESERVED)
+ {
+ //
+ // Has a key been pressed or released?
+ //
+ if(bPress)
+ {
+ //
+ // A key has been pressed - add it to the list if there is space an
+ // and the key is not already in the list.
+ //
+ bRetcode = AddKeyToPressedList(psInst, ucUsageCode);
+ }
+ else
+ {
+ //
+ // A key has been released - remove it from the list.
+ //
+ bRetcode = RemoveKeyFromPressedList(psInst, ucUsageCode);
+
+ //
+ // The return code here indicates whether the key was found. If it
+ // wasn't, the list has not changes so merely exit at this point
+ // without sending anything to the host.
+ //
+ if(!bRetcode)
+ {
+ return(KEYB_ERR_NOT_FOUND);
+ }
+ }
+
+ //
+ // 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(ulLoop = 0; ulLoop < KEYB_MAX_CHARS_PER_REPORT; ulLoop++)
+ {
+ psInst->pucReport[2 + ulLoop] = (bRetcode ?
+ psInst->pucKeysPressed[ulLoop] : HID_KEYB_USAGE_ROLLOVER);
+ }
+ }
+
+ //
+ // If we are not configured, return an error here before trying to send
+ // anything.
+ //
+ if(!psInst->ucUSBConfigured)
+ {
+ 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->eKeyboardState = HID_KEYBOARD_STATE_SEND;
+ ulCount = USBDHIDReportWrite((void *)psHIDDevice,
+ psInst->pucReport, KEYB_IN_REPORT_SIZE,
+ true);
+
+ //
+ // Did we schedule a packet for transmission correctly?
+ //
+ if(!ulCount)
+ {
+ //
+ // 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(bRetcode ? KEYB_SUCCESS : KEYB_ERR_TOO_MANY_KEYS);
+}
+
+//*****************************************************************************
+//
+//! Reports the device power status (bus or self powered) to the USB library.
+//!
+//! \param pvInstance is the pointer to the keyboard device instance structure.
+//! \param ucPower 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
+USBDHIDKeyboardPowerStatusSet(void *pvInstance, unsigned char ucPower)
+{
+ tUSBDHIDKeyboardDevice *psDevice;
+ tUSBDHIDDevice *psHIDDevice;
+
+ ASSERT(pvInstance);
+
+ //
+ // Get the keyboard device pointer.
+ //
+ psDevice = (tUSBDHIDKeyboardDevice *)pvInstance;
+
+ //
+ // Get a pointer to the HID device data.
+ //
+ psHIDDevice = &psDevice->psPrivateHIDKbdData->sHIDDevice;
+
+ //
+ // Pass the request through to the lower layer.
+ //
+ USBDHIDPowerStatusSet((void *)psHIDDevice, ucPower);
+}
+
+//*****************************************************************************
+//
+//! Requests a remote wake up to resume communication when in suspended state.
+//!
+//! \param pvInstance is the pointer to the keyboard 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 will cause the bus
+//! to resume operation within 20mS. If the host has disabled remote wake up,
+//! \b false will be 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.
+//
+//*****************************************************************************
+tBoolean
+USBDHIDKeyboardRemoteWakeupRequest(void *pvInstance)
+{
+ tUSBDHIDKeyboardDevice *psDevice;
+ tUSBDHIDDevice *psHIDDevice;
+
+ ASSERT(pvInstance);
+
+ //
+ // Get the keyboard device pointer.
+ //
+ psDevice = (tUSBDHIDKeyboardDevice *)pvInstance;
+
+ //
+ // Get a pointer to the HID device data.
+ //
+ psHIDDevice = &psDevice->psPrivateHIDKbdData->sHIDDevice;
+
+ //
+ // Pass the request through to the lower layer.
+ //
+ return(USBDHIDRemoteWakeupRequest((void *)psHIDDevice));
+}
+
+//*****************************************************************************
+//
+// Close the Doxygen group.
+//! @}
+//
+//*****************************************************************************
|
