diff options
author | Harald Welte <laforge@gnumonks.org> | 2011-07-04 20:52:54 +0200 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2011-07-04 20:52:54 +0200 |
commit | 044ad7c3987460ede48ff27afd6bdb0ca05a0432 (patch) | |
tree | 924818cdb0d39ca08aec540d18da7bd406eaae8c /usb/device/hid-keyboard |
import at91lib from at91lib_20100901_softpack_1_9_v_1_0_svn_v1501120100901_softpack_1_9_v_1_0_svn_v15011
it's sad to see that atmel doesn't publish their svn repo or has
a centralized location or even puts proper version/release info
into the library itself
Diffstat (limited to 'usb/device/hid-keyboard')
-rw-r--r-- | usb/device/hid-keyboard/HIDClassArch.png | bin | 0 -> 3495 bytes | |||
-rw-r--r-- | usb/device/hid-keyboard/HIDDKeyboardCallbacks.h | 57 | ||||
-rw-r--r-- | usb/device/hid-keyboard/HIDDKeyboardCallbacks_LedsChanged.c | 59 | ||||
-rw-r--r-- | usb/device/hid-keyboard/HIDDKeyboardDriver.c | 477 | ||||
-rw-r--r-- | usb/device/hid-keyboard/HIDDKeyboardDriver.h | 75 | ||||
-rw-r--r-- | usb/device/hid-keyboard/HIDDKeyboardDriverDescriptors.c | 420 | ||||
-rw-r--r-- | usb/device/hid-keyboard/HIDDKeyboardDriverDescriptors.h | 114 | ||||
-rw-r--r-- | usb/device/hid-keyboard/HIDDKeyboardInputReport.c | 164 | ||||
-rw-r--r-- | usb/device/hid-keyboard/HIDDKeyboardInputReport.h | 149 | ||||
-rw-r--r-- | usb/device/hid-keyboard/HIDDKeyboardOutputReport.c | 94 | ||||
-rw-r--r-- | usb/device/hid-keyboard/HIDDKeyboardOutputReport.h | 96 | ||||
-rw-r--r-- | usb/device/hid-keyboard/hid-keyboard.dir | 787 |
12 files changed, 2492 insertions, 0 deletions
diff --git a/usb/device/hid-keyboard/HIDClassArch.png b/usb/device/hid-keyboard/HIDClassArch.png Binary files differnew file mode 100644 index 0000000..6d09580 --- /dev/null +++ b/usb/device/hid-keyboard/HIDClassArch.png diff --git a/usb/device/hid-keyboard/HIDDKeyboardCallbacks.h b/usb/device/hid-keyboard/HIDDKeyboardCallbacks.h new file mode 100644 index 0000000..6bbfaea --- /dev/null +++ b/usb/device/hid-keyboard/HIDDKeyboardCallbacks.h @@ -0,0 +1,57 @@ +/* ----------------------------------------------------------------------------
+ * ATMEL Microcontroller Software Support
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit HIDDKeyboardCallbacks
+
+ !!!Purpose
+
+ Definitions of callbacks used by the HID keyboard device driver to
+ notify the application of events.
+
+ !!!Usage
+
+ -# Re-implement any number of these callbacks anywhere in the program;
+ they will be called automatically by the driver when the related
+ event occurs.
+*/
+
+#ifndef HIDDKEYBOARDCALLBACKS_H
+#define HIDDKEYBOARDCALLBACKS_H
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern void HIDDKeyboardCallbacks_LedsChanged(unsigned char numLockStatus,
+ unsigned char capsLockStatus,
+ unsigned char scrollLockStatus);
+
+#endif //#ifndef HIDDKEYBOARDCALLBACKS_H
+
diff --git a/usb/device/hid-keyboard/HIDDKeyboardCallbacks_LedsChanged.c b/usb/device/hid-keyboard/HIDDKeyboardCallbacks_LedsChanged.c new file mode 100644 index 0000000..be8963d --- /dev/null +++ b/usb/device/hid-keyboard/HIDDKeyboardCallbacks_LedsChanged.c @@ -0,0 +1,59 @@ +/* ----------------------------------------------------------------------------
+ * ATMEL Microcontroller Software Support
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "HIDDKeyboardCallbacks.h"
+#include <utility/trace.h>
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Indicates that the status of one or more LEDs has been changed by the
+/// host.
+/// \param numLockStatus Indicates the current status of the num. lock key.
+/// \param capsLockStatus Indicates the current status of the caps lock key.
+/// \param scrollLockStatus Indicates the current status of the scroll lock key.
+//------------------------------------------------------------------------------
+void HIDDKeyboardCallbacks_LedsChanged(
+ unsigned char numLockStatus,
+ unsigned char capsLockStatus,
+ unsigned char scrollLockStatus)
+{
+ TRACE_INFO(
+ "LEDs status: %d, %d, %d\n\r",
+ numLockStatus,
+ capsLockStatus,
+ scrollLockStatus);
+}
+
diff --git a/usb/device/hid-keyboard/HIDDKeyboardDriver.c b/usb/device/hid-keyboard/HIDDKeyboardDriver.c new file mode 100644 index 0000000..e244cb5 --- /dev/null +++ b/usb/device/hid-keyboard/HIDDKeyboardDriver.c @@ -0,0 +1,477 @@ +/* ----------------------------------------------------------------------------
+ * ATMEL Microcontroller Software Support
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "HIDDKeyboardDriver.h"
+#include "HIDDKeyboardDriverDescriptors.h"
+#include "HIDDKeyboardCallbacks.h"
+#include "HIDDKeyboardInputReport.h"
+#include "HIDDKeyboardOutputReport.h"
+#include <utility/trace.h>
+#include <usb/common/core/USBGetDescriptorRequest.h>
+#include <usb/common/hid/HIDGenericDescriptor.h>
+#include <usb/common/hid/HIDDescriptor.h>
+#include <usb/common/hid/HIDGenericRequest.h>
+#include <usb/common/hid/HIDReportRequest.h>
+#include <usb/common/hid/HIDIdleRequest.h>
+#include <usb/common/hid/HIDKeypad.h>
+#include <usb/device/core/USBD.h>
+#include <usb/device/core/USBDDriver.h>
+
+//------------------------------------------------------------------------------
+// Internal types
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Driver structure for an HID device implementing keyboard functionalities.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Standard USB device driver instance.
+ USBDDriver usbdDriver;
+ /// Idle rate (in milliseconds) of the input report.
+ unsigned char inputReportIdleRate;
+ /// Input report instance.
+ HIDDKeyboardInputReport inputReport;
+ /// Output report instance.
+ HIDDKeyboardOutputReport outputReport;
+
+} HIDDKeyboardDriver;
+
+//------------------------------------------------------------------------------
+// Internal variables
+//------------------------------------------------------------------------------
+
+/// Static instance of the HID keyboard device driver.
+static HIDDKeyboardDriver hiddKeyboardDriver;
+
+//------------------------------------------------------------------------------
+// Internal functions
+//------------------------------------------------------------------------------
+
+/**
+ Returns the descriptor requested by the host.
+
+\param type Descriptor type.
+\param length Maximum number of bytes to send.
+\return 1 if the request has been handled by this function, otherwise 0.
+*/
+static unsigned char HIDDKeyboardDriver_GetDescriptor(unsigned char type,
+ unsigned char length)
+{
+ const USBConfigurationDescriptor *pConfiguration;
+ HIDDescriptor *hidDescriptors[2];
+
+ switch (type) {
+
+ case HIDGenericDescriptor_REPORT:
+ TRACE_INFO_WP("Report ");
+
+ // Adjust length and send report descriptor
+ if (length > HIDDKeyboardDriverDescriptors_REPORTSIZE) {
+
+ length = HIDDKeyboardDriverDescriptors_REPORTSIZE;
+ }
+ USBD_Write(0, &hiddReportDescriptor, length, 0, 0);
+ break;
+
+ case HIDGenericDescriptor_HID:
+ TRACE_INFO_WP("HID ");
+
+ // Configuration descriptor is different depending on configuration
+ if (USBD_IsHighSpeed()) {
+
+ pConfiguration = hiddKeyboardDriver.usbdDriver.pDescriptors->pHsConfiguration;
+ }
+ else {
+
+ pConfiguration = hiddKeyboardDriver.usbdDriver.pDescriptors->pFsConfiguration;
+ }
+
+ // Parse the device configuration to get the HID descriptor
+ USBConfigurationDescriptor_Parse(
+ pConfiguration,
+ 0,
+ 0,
+ (USBGenericDescriptor **) hidDescriptors);
+
+ // Adjust length and send HID descriptor
+ if (length > sizeof(HIDDescriptor)) {
+
+ length = sizeof(HIDDescriptor);
+ }
+ USBD_Write(0, hidDescriptors[0], length, 0, 0);
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+/**
+ Sends the current Idle rate of the input report to the host.
+*/
+static void HIDDKeyboardDriver_GetIdle()
+{
+ TRACE_INFO_WP("gIdle ");
+
+ USBD_Write(0, &(hiddKeyboardDriver.inputReportIdleRate), 1, 0, 0);
+}
+
+/**
+ Retrieves the new idle rate of the input report from the USB host.
+
+ \param idleRate New input report idle rate.
+*/
+static void HIDDKeyboardDriver_SetIdle(unsigned char idleRate)
+{
+ TRACE_INFO_WP("sIdle(%d) ", idleRate);
+
+ hiddKeyboardDriver.inputReportIdleRate = idleRate;
+ USBD_Write(0, 0, 0, 0, 0);
+}
+
+/**
+ Sends the requested report to the host.
+
+\param type Report type.
+\param length Maximum number of bytes to send.
+*/
+static void HIDDKeyboardDriver_GetReport(unsigned char type,
+ unsigned short length)
+{
+ TRACE_INFO_WP("gReport ");
+
+ // Check report type
+ switch (type) {
+
+ case HIDReportRequest_INPUT:
+ TRACE_INFO_WP("In ");
+
+ // Adjust size and send report
+ if (length > sizeof(HIDDKeyboardInputReport)) {
+
+ length = sizeof(HIDDKeyboardInputReport);
+ }
+ USBD_Write(0, // Endpoint #0
+ &(hiddKeyboardDriver.inputReport),
+ length,
+ 0, // No callback
+ 0);
+ break;
+
+ case HIDReportRequest_OUTPUT:
+ TRACE_INFO_WP("Out ");
+
+ // Adjust size and send report
+ if (length > sizeof(HIDDKeyboardOutputReport)) {
+
+ length = sizeof(HIDDKeyboardOutputReport);
+ }
+ USBD_Write(0, // Endpoint #0
+ &(hiddKeyboardDriver.outputReport),
+ length,
+ 0, // No callback
+ 0);
+ break;
+
+ default:
+ USBD_Stall(0);
+ }
+}
+
+/**
+ Callback invoked when an output report has been received from the host.
+ Forward the new status of the LEDs to the user program via the
+ HIDDKeyboardCallbacks_LedsChanged callback.
+*/
+static void HIDDKeyboardDriver_ReportReceived()
+{
+ TRACE_INFO_WP("oReport ");
+
+ // Trigger callback
+ HIDDKeyboardCallbacks_LedsChanged(
+ HIDDKeyboardOutputReport_GetNumLockStatus(&(hiddKeyboardDriver.outputReport)),
+ HIDDKeyboardOutputReport_GetCapsLockStatus(&(hiddKeyboardDriver.outputReport)),
+ HIDDKeyboardOutputReport_GetScrollLockStatus(&(hiddKeyboardDriver.outputReport)));
+
+ // Restart transfer
+ USBD_Read(HIDDKeyboardDriverDescriptors_INTERRUPTOUT,
+ &(hiddKeyboardDriver.outputReport),
+ sizeof(HIDDKeyboardOutputReport),
+ (TransferCallback) HIDDKeyboardDriver_ReportReceived,
+ 0); // No argument for callback function
+}
+
+/**
+ Retrieves the new value of a report from the host and saves it.
+
+\param type Report type.
+\param length Report length.
+*/
+static void HIDDKeyboardDriver_SetReport(unsigned char type,
+ unsigned short length)
+{
+ TRACE_INFO_WP("sReport ");
+
+ // Check report type
+ switch (type) {
+
+ case HIDReportRequest_INPUT:
+ // SET_REPORT requests on input reports are ignored
+ USBD_Stall(0);
+ break;
+
+ case HIDReportRequest_OUTPUT:
+ // Check report length
+ if (length != sizeof(HIDDKeyboardOutputReport)) {
+
+ USBD_Stall(0);
+ }
+ else {
+
+ USBD_Read(0, // Endpoint #0
+ &(hiddKeyboardDriver.outputReport),
+ length,
+ (TransferCallback) HIDDKeyboardDriver_ReportReceived,
+ 0); // No argument to the callback function
+ }
+ break;
+
+ default:
+ USBD_Stall(0);
+ }
+}
+
+//------------------------------------------------------------------------------
+// Optional RequestReceived() callback re-implementation
+//------------------------------------------------------------------------------
+#if !defined(NOAUTOCALLBACK)
+
+void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
+{
+ HIDDKeyboardDriver_RequestHandler(request);
+}
+
+#endif
+
+//------------------------------------------------------------------------------
+// ConfigurationChanged() callback re-implementation
+//------------------------------------------------------------------------------
+void USBDDriverCallbacks_ConfigurationChanged(unsigned char cfgnum)
+{
+ if (cfgnum > 0) {
+
+ // Start receiving output reports
+ USBD_Read(HIDDKeyboardDriverDescriptors_INTERRUPTOUT,
+ &(hiddKeyboardDriver.outputReport),
+ sizeof(HIDDKeyboardOutputReport),
+ (TransferCallback) HIDDKeyboardDriver_ReportReceived,
+ 0); // No argument for callback function
+ }
+}
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+/**
+ Initializes the HID keyboard device driver.
+*/
+void HIDDKeyboardDriver_Initialize()
+{
+ hiddKeyboardDriver.inputReportIdleRate = 0;
+ HIDDKeyboardInputReport_Initialize(&(hiddKeyboardDriver.inputReport));
+ HIDDKeyboardOutputReport_Initialize(&(hiddKeyboardDriver.outputReport));
+ USBDDriver_Initialize(&(hiddKeyboardDriver.usbdDriver),
+ &hiddKeyboardDriverDescriptors,
+ 0); // Multiple interface settings not supported
+ USBD_Init();
+}
+
+/**
+ Handles HID-specific SETUP request sent by the host.
+
+ \param request Pointer to a USBGenericRequest instance.
+*/
+void HIDDKeyboardDriver_RequestHandler(const USBGenericRequest *request)
+{
+ TRACE_INFO_WP("NewReq ");
+
+ // Check if this is a standard request
+ if (USBGenericRequest_GetType(request) == USBGenericRequest_STANDARD) {
+
+ // This is a standard request
+ switch (USBGenericRequest_GetRequest(request)) {
+
+ case USBGenericRequest_GETDESCRIPTOR:
+ // Check if this is a HID descriptor, otherwise forward it to
+ // the standard driver
+ if (!HIDDKeyboardDriver_GetDescriptor(
+ USBGetDescriptorRequest_GetDescriptorType(request),
+ USBGenericRequest_GetLength(request))) {
+
+ USBDDriver_RequestHandler(&(hiddKeyboardDriver.usbdDriver),
+ request);
+ }
+ break;
+
+ default:
+ USBDDriver_RequestHandler(&(hiddKeyboardDriver.usbdDriver),
+ request);
+ }
+ }
+ // Check if this is a class request
+ else if (USBGenericRequest_GetType(request) == USBGenericRequest_CLASS) {
+
+ // This is a class-specific request
+ switch (USBGenericRequest_GetRequest(request)) {
+
+ case HIDGenericRequest_GETIDLE:
+ HIDDKeyboardDriver_GetIdle();
+ break;
+
+ case HIDGenericRequest_SETIDLE:
+ HIDDKeyboardDriver_SetIdle(HIDIdleRequest_GetIdleRate(request));
+ break;
+
+ case HIDGenericRequest_GETREPORT:
+ HIDDKeyboardDriver_GetReport(
+ HIDReportRequest_GetReportType(request),
+ USBGenericRequest_GetLength(request));
+ break;
+
+ case HIDGenericRequest_SETREPORT:
+ HIDDKeyboardDriver_SetReport(
+ HIDReportRequest_GetReportType(request),
+ USBGenericRequest_GetLength(request));
+ break;
+
+ default:
+ TRACE_WARNING(
+ "HIDDKeyboardDriver_RequestHandler: Unknown REQ 0x%02X\n\r",
+ USBGenericRequest_GetRequest(request));
+ USBD_Stall(0);
+ }
+ }
+ else {
+
+ // Vendor request ?
+ USBD_Stall(0);
+ }
+}
+
+/**
+ Reports a change in which keys are currently pressed or release to the
+ host.
+
+\param pressedKeys Pointer to an array of key codes indicating keys that have
+ been pressed since the last call to HIDDKeyboardDriver_ChangeKeys.
+\param pressedKeysSize Number of key codes in the pressedKeys array.
+\param releasedKeys Pointer to an array of key codes indicates keys that have
+ been released since the last call to HIDDKeyboardDriver_ChangeKeys.
+\param releasedKeysSize Number of key codes in the releasedKeys array.
+\return USBD_STATUS_SUCCESS if the report has been sent to the host;
+ otherwise an error code.
+*/
+unsigned char HIDDKeyboardDriver_ChangeKeys(unsigned char *pressedKeys,
+ unsigned char pressedKeysSize,
+ unsigned char *releasedKeys,
+ unsigned char releasedKeysSize)
+{
+ // Press keys
+ while (pressedKeysSize > 0) {
+
+ // Check if this is a standard or modifier key
+ if (HIDKeypad_IsModifierKey(*pressedKeys)) {
+
+ // Set the corresponding bit in the input report
+ HIDDKeyboardInputReport_PressModifierKey(
+ &(hiddKeyboardDriver.inputReport),
+ *pressedKeys);
+ }
+ else {
+
+ HIDDKeyboardInputReport_PressStandardKey(
+ &(hiddKeyboardDriver.inputReport),
+ *pressedKeys);
+ }
+
+ pressedKeysSize--;
+ pressedKeys++;
+ }
+
+ // Release keys
+ while (releasedKeysSize > 0) {
+
+ // Check if this is a standard or modifier key
+ if (HIDKeypad_IsModifierKey(*releasedKeys)) {
+
+ // Set the corresponding bit in the input report
+ HIDDKeyboardInputReport_ReleaseModifierKey(
+ &(hiddKeyboardDriver.inputReport),
+ *releasedKeys);
+ }
+ else {
+
+ HIDDKeyboardInputReport_ReleaseStandardKey(
+ &(hiddKeyboardDriver.inputReport),
+ *releasedKeys);
+ }
+
+ releasedKeysSize--;
+ releasedKeys++;
+ }
+
+ // Send input report through the interrupt IN endpoint
+ return USBD_Write(HIDDKeyboardDriverDescriptors_INTERRUPTIN,
+ &(hiddKeyboardDriver.inputReport),
+ sizeof(HIDDKeyboardInputReport),
+ 0,
+ 0);
+}
+
+//------------------------------------------------------------------------------
+/// Starts a remote wake-up sequence if the host has explicitely enabled it
+/// by sending the appropriate SET_FEATURE request.
+//------------------------------------------------------------------------------
+void HIDDKeyboardDriver_RemoteWakeUp(void)
+{
+ // Remote wake-up has been enabled
+ if (USBDDriver_IsRemoteWakeUpEnabled(&(hiddKeyboardDriver.usbdDriver))) {
+
+ USBD_RemoteWakeUp();
+ }
+}
+
diff --git a/usb/device/hid-keyboard/HIDDKeyboardDriver.h b/usb/device/hid-keyboard/HIDDKeyboardDriver.h new file mode 100644 index 0000000..42dc0a2 --- /dev/null +++ b/usb/device/hid-keyboard/HIDDKeyboardDriver.h @@ -0,0 +1,75 @@ +/* ----------------------------------------------------------------------------
+ * ATMEL Microcontroller Software Support
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit HIDDKeyboardDriver
+
+ !!!Purpose
+
+ Definition of methods for using a HID keyboard device driver.
+
+ !!!Usage
+
+ -# Re-implement the USBDCallbacks_RequestReceived callback to forward
+ requests to HIDDKeyboardDriver_RequestHandler. This is done
+ automatically unless the NOAUTOCALLBACK symbol is defined during
+ compilation.
+ -# Initialize the driver using HIDDKeyboardDriver_Initialize. The
+ USB driver is automatically initialized by this method.
+ -# Call the HIDDKeyboardDriver_ChangeKeys method when one or more
+ keys are pressed/released.
+*/
+
+#ifndef HIDDKEYBOARDDRIVER_H
+#define HIDDKEYBOARDDRIVER_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include <usb/common/core/USBGenericRequest.h>
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern void HIDDKeyboardDriver_Initialize();
+
+extern void HIDDKeyboardDriver_RequestHandler(const USBGenericRequest *request);
+
+extern unsigned char HIDDKeyboardDriver_ChangeKeys(
+ unsigned char *pressedKeys,
+ unsigned char pressedKeysSize,
+ unsigned char *releasedKeys,
+ unsigned char releasedKeysSize);
+
+extern void HIDDKeyboardDriver_RemoteWakeUp(void);
+
+#endif //#ifndef HIDDKEYBOARDDRIVER_H
+
diff --git a/usb/device/hid-keyboard/HIDDKeyboardDriverDescriptors.c b/usb/device/hid-keyboard/HIDDKeyboardDriverDescriptors.c new file mode 100644 index 0000000..51dfb48 --- /dev/null +++ b/usb/device/hid-keyboard/HIDDKeyboardDriverDescriptors.c @@ -0,0 +1,420 @@ +/* ----------------------------------------------------------------------------
+ * ATMEL Microcontroller Software Support
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: HIDDKeyboardDriverDescriptors
+
+ About: Purpose
+ Declaration of the descriptors used by the HID device keyboard driver.
+*/
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "HIDDKeyboardDriverDescriptors.h"
+#include "HIDDKeyboardInputReport.h"
+#include "HIDDKeyboardOutputReport.h"
+#include <board.h>
+#include <usb/common/core/USBDeviceDescriptor.h>
+#include <usb/common/core/USBConfigurationDescriptor.h>
+#include <usb/common/core/USBInterfaceDescriptor.h>
+#include <usb/common/core/USBEndpointDescriptor.h>
+#include <usb/common/core/USBStringDescriptor.h>
+#include <usb/common/hid/HIDGenericDescriptor.h>
+#include <usb/common/hid/HIDDeviceDescriptor.h>
+#include <usb/common/hid/HIDInterfaceDescriptor.h>
+#include <usb/common/hid/HIDDescriptor.h>
+#include <usb/common/hid/HIDReport.h>
+#include <usb/common/hid/HIDGenericDesktop.h>
+#include <usb/common/hid/HIDLeds.h>
+#include <usb/common/hid/HIDKeypad.h>
+#include <usb/device/core/USBDDriverDescriptors.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID Device Descriptor IDs"
+/// This page lists VID, PID & Release number.
+///
+/// !IDs
+/// - HIDDKeyboardDriverDescriptors_PRODUCTID
+/// - HIDDKeyboardDriverDescriptors_VENDORID
+/// - HIDDKeyboardDriverDescriptors_RELEASE
+
+/// Device product ID.
+#define HIDDKeyboardDriverDescriptors_PRODUCTID 0x6127
+/// Device vendor ID.
+#define HIDDKeyboardDriverDescriptors_VENDORID 0x03EB
+/// Device release number.
+#define HIDDKeyboardDriverDescriptors_RELEASE 0x0100
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Internal types
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// List of descriptors that make up the configuration descriptors of a
+/// device using the HID keyboard driver.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// Configuration descriptor.
+ USBConfigurationDescriptor configuration;
+ /// Interface descriptor.
+ USBInterfaceDescriptor interface;
+ /// HID descriptor.
+ HIDDescriptor hid;
+ /// Interrupt IN endpoint descriptor.
+ USBEndpointDescriptor interruptIn;
+ /// Interrupt OUT endpoint descriptor.
+ USBEndpointDescriptor interruptOut;
+
+} __attribute__ ((packed)) HIDDKeyboardDriverConfigurationDescriptors;
+
+//------------------------------------------------------------------------------
+// Internal variables
+//------------------------------------------------------------------------------
+
+/// Device descriptor.
+static const USBDeviceDescriptor deviceDescriptor = {
+
+ sizeof(USBDeviceDescriptor),
+ USBGenericDescriptor_DEVICE,
+ USBDeviceDescriptor_USB2_00,
+ HIDDeviceDescriptor_CLASS,
+ HIDDeviceDescriptor_SUBCLASS,
+ HIDDeviceDescriptor_PROTOCOL,
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ HIDDKeyboardDriverDescriptors_VENDORID,
+ HIDDKeyboardDriverDescriptors_PRODUCTID,
+ HIDDKeyboardDriverDescriptors_RELEASE,
+ 1, // Index of manufacturer description
+ 2, // Index of product description
+ 3, // Index of serial number description
+ 1 // One possible configuration
+};
+
+#if defined (CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+/// Device qualifier descriptor (high-speed only).
+static const USBDeviceQualifierDescriptor qualifierDescriptor = {
+
+ sizeof(USBDeviceQualifierDescriptor),
+ USBGenericDescriptor_DEVICEQUALIFIER,
+ HIDDeviceDescriptor_CLASS,
+ HIDDeviceDescriptor_SUBCLASS,
+ HIDDeviceDescriptor_PROTOCOL,
+ CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ 1, // One possible configuration
+ 0 // Reserved
+};
+#endif
+
+/// Configuration descriptor.
+static const HIDDKeyboardDriverConfigurationDescriptors configurationDescriptors = {
+
+ // Configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(HIDDKeyboardDriverConfigurationDescriptors),
+ 1, // One interface in this configuration
+ 1, // This is configuration #1
+ 0, // No associated string descriptor
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+ // Interface descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 0, // This is interface #0
+ 0, // This is alternate setting #0
+ 2, // Two endpoints used
+ HIDInterfaceDescriptor_CLASS,
+ HIDInterfaceDescriptor_SUBCLASS_NONE,
+ HIDInterfaceDescriptor_PROTOCOL_NONE,
+ 0 // No associated string descriptor
+ },
+ // HID descriptor
+ {
+ sizeof(HIDDescriptor),
+ HIDGenericDescriptor_HID,
+ HIDDescriptor_HID1_11,
+ 0, // Device is not localized, no country code
+ 1, // One HID-specific descriptor (apart from this one)
+ HIDGenericDescriptor_REPORT,
+ HIDDKeyboardDriverDescriptors_REPORTSIZE
+ },
+ // Interrupt IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ HIDDKeyboardDriverDescriptors_INTERRUPTIN),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDKeyboardInputReport),
+ HIDDKeyboardDriverDescriptors_INTERRUPTIN_POLLING
+ },
+ // Interrupt OUT endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ HIDDKeyboardDriverDescriptors_INTERRUPTOUT),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDKeyboardOutputReport),
+ HIDDKeyboardDriverDescriptors_INTERRUPTIN_POLLING
+ }
+};
+
+#if defined (CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+/// Other-speed configuration descriptor.
+static const HIDDKeyboardDriverConfigurationDescriptors otherSpeedDescriptors = {
+
+ // Configuration descriptor
+ {
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_OTHERSPEEDCONFIGURATION,
+ sizeof(HIDDKeyboardDriverConfigurationDescriptors),
+ 1, // One interface in this configuration
+ 1, // This is configuration #1
+ 0, // No associated string descriptor
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+ },
+ // Interface descriptor
+ {
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 0, // This is interface #0
+ 0, // This is alternate setting #0
+ 2, // Two endpoints used
+ HIDInterfaceDescriptor_CLASS,
+ HIDInterfaceDescriptor_SUBCLASS_NONE,
+ HIDInterfaceDescriptor_PROTOCOL_NONE,
+ 0 // No associated string descriptor
+ },
+ // HID descriptor
+ {
+ sizeof(HIDDescriptor),
+ HIDGenericDescriptor_HID,
+ HIDDescriptor_HID1_11,
+ 0, // Device is not localized, no country code
+ 1, // One HID-specific descriptor (apart from this one)
+ HIDGenericDescriptor_REPORT,
+ HIDDKeyboardDriverDescriptors_REPORTSIZE
+ },
+ // Interrupt IN endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ HIDDKeyboardDriverDescriptors_INTERRUPTIN),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDKeyboardInputReport),
+ HIDDKeyboardDriverDescriptors_INTERRUPTIN_POLLING
+ },
+ // Interrupt OUT endpoint descriptor
+ {
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ HIDDKeyboardDriverDescriptors_INTERRUPTOUT),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDKeyboardOutputReport),
+ HIDDKeyboardDriverDescriptors_INTERRUPTOUT_POLLING
+ }
+};
+#endif
+
+/// Language ID string descriptor.
+static const unsigned char languageIdDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(1),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_ENGLISH_US
+};
+
+/// Manufacturer name.
+static const unsigned char manufacturerDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(5),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('A'),
+ USBStringDescriptor_UNICODE('T'),
+ USBStringDescriptor_UNICODE('M'),
+ USBStringDescriptor_UNICODE('E'),
+ USBStringDescriptor_UNICODE('L')
+};
+
+/// Product name.
+static const unsigned char productDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(23),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('A'),
+ USBStringDescriptor_UNICODE('T'),
+ USBStringDescriptor_UNICODE('M'),
+ USBStringDescriptor_UNICODE('E'),
+ USBStringDescriptor_UNICODE('L'),
+ USBStringDescriptor_UNICODE(' '),
+ USBStringDescriptor_UNICODE('A'),
+ USBStringDescriptor_UNICODE('T'),
+ USBStringDescriptor_UNICODE('9'),
+ USBStringDescriptor_UNICODE('1'),
+ USBStringDescriptor_UNICODE(' '),
+ USBStringDescriptor_UNICODE('H'),
+ USBStringDescriptor_UNICODE('I'),
+ USBStringDescriptor_UNICODE('D'),
+ USBStringDescriptor_UNICODE(' '),
+ USBStringDescriptor_UNICODE('K'),
+ USBStringDescriptor_UNICODE('E'),
+ USBStringDescriptor_UNICODE('Y'),
+ USBStringDescriptor_UNICODE('B'),
+ USBStringDescriptor_UNICODE('O'),
+ USBStringDescriptor_UNICODE('A'),
+ USBStringDescriptor_UNICODE('R'),
+ USBStringDescriptor_UNICODE('D')
+};
+
+/// Product serial number.
+static const unsigned char serialNumberDescriptor[] = {
+
+ USBStringDescriptor_LENGTH(12),
+ USBGenericDescriptor_STRING,
+ USBStringDescriptor_UNICODE('0'),
+ USBStringDescriptor_UNICODE('1'),
+ USBStringDescriptor_UNICODE('2'),
+ USBStringDescriptor_UNICODE('3'),
+ USBStringDescriptor_UNICODE('4'),
+ USBStringDescriptor_UNICODE('5'),
+ USBStringDescriptor_UNICODE('6'),
+ USBStringDescriptor_UNICODE('7'),
+ USBStringDescriptor_UNICODE('8'),
+ USBStringDescriptor_UNICODE('9'),
+ USBStringDescriptor_UNICODE('A'),
+ USBStringDescriptor_UNICODE('F')
+};
+
+/// Array of pointers to string descriptors.
+static const unsigned char *stringDescriptors[] = {
+
+ languageIdDescriptor,
+ manufacturerDescriptor,
+ productDescriptor,
+ serialNumberDescriptor
+};
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+/// List of descriptors used by the HID keyboard driver.
+USBDDriverDescriptors hiddKeyboardDriverDescriptors = {
+
+ &deviceDescriptor,
+ (USBConfigurationDescriptor *) &configurationDescriptors,
+#if defined (CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
+ &qualifierDescriptor,
+ (USBConfigurationDescriptor *) &otherSpeedDescriptors,
+ &deviceDescriptor,
+ (USBConfigurationDescriptor *) &configurationDescriptors,
+ &qualifierDescriptor,
+ (USBConfigurationDescriptor *) &otherSpeedDescriptors,
+#else
+ 0, // No full-speed device qualifier descriptor
+ 0, // No full-speed other speed configuration
+ 0, // No high-speed device descriptor
+ 0, // No high-speed configuration descriptor
+ 0, // No high-speed device qualifier descriptor
+ 0, // No high-speed other speed configuration descriptor
+#endif
+ stringDescriptors,
+ 4 // Four string descriptors in list
+};
+
+/// Report descriptor used by the driver.
+const unsigned char hiddReportDescriptor[] = {
+
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDGenericDesktop_PAGEID,
+ HIDReport_LOCAL_USAGE + 1, HIDGenericDesktop_KEYBOARD,
+ HIDReport_COLLECTION + 1, HIDReport_COLLECTION_APPLICATION,
+
+ // Input report: modifier keys
+ HIDReport_GLOBAL_REPORTSIZE + 1, 1,
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 8,
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDKeypad_PAGEID,
+ HIDReport_LOCAL_USAGEMINIMUM + 1,
+ HIDDKeyboardDriverDescriptors_FIRSTMODIFIERKEY,
+ HIDReport_LOCAL_USAGEMAXIMUM + 1,
+ HIDDKeyboardDriverDescriptors_LASTMODIFIERKEY,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1, 0,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1, 1,
+ HIDReport_INPUT + 1, HIDReport_VARIABLE,
+
+ // Input report: standard keys
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 3,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 8,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1,
+ HIDDKeyboardDriverDescriptors_FIRSTSTANDARDKEY,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1,
+ HIDDKeyboardDriverDescriptors_LASTSTANDARDKEY,
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDKeypad_PAGEID,
+ HIDReport_LOCAL_USAGEMINIMUM + 1,
+ HIDDKeyboardDriverDescriptors_FIRSTSTANDARDKEY,
+ HIDReport_LOCAL_USAGEMAXIMUM + 1,
+ HIDDKeyboardDriverDescriptors_LASTSTANDARDKEY,
+ HIDReport_INPUT + 1, 0 /* Data array */,
+
+ // Output report: LEDs
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 3,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 1,
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDLeds_PAGEID,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1, 0,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1, 1,
+ HIDReport_LOCAL_USAGEMINIMUM + 1, HIDLeds_NUMLOCK,
+ HIDReport_LOCAL_USAGEMAXIMUM + 1, HIDLeds_SCROLLLOCK,
+ HIDReport_OUTPUT + 1, HIDReport_VARIABLE,
+
+ // Output report: padding
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 1,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 5,
+ HIDReport_OUTPUT + 1, HIDReport_CONSTANT,
+
+ HIDReport_ENDCOLLECTION
+};
+
diff --git a/usb/device/hid-keyboard/HIDDKeyboardDriverDescriptors.h b/usb/device/hid-keyboard/HIDDKeyboardDriverDescriptors.h new file mode 100644 index 0000000..9a2dc2f --- /dev/null +++ b/usb/device/hid-keyboard/HIDDKeyboardDriverDescriptors.h @@ -0,0 +1,114 @@ +/* ----------------------------------------------------------------------------
+ * ATMEL Microcontroller Software Support
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit HIDDKeyboardDriverDescriptors
+
+ !!!Purpose
+
+ Definitions of the descriptors required by the HID device keyboard
+ driver.
+
+ !!!Usage
+
+ -# Use the hiddKeyboardDriverDescriptors variable to initialize a
+ USBDDriver instance.
+ -# Send hiddReportDescriptor to the host when a GET_DESCRIPTOR request
+ for the report descriptor is received.
+*/
+
+#ifndef HIDDKEYBOARDDRIVERDESCRIPTORS_H
+#define HIDDKEYBOARDDRIVERDESCRIPTORS_H
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include <usb/device/core/USBDDriverDescriptors.h>
+#include <usb/common/hid/HIDKeypad.h>
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID Endpoints"
+/// This page lists endpoint addresses and polling settings.
+///
+/// !Endpoints
+/// - HIDDKeyboardDriverDescriptors_INTERRUPTIN
+/// - HIDDKeyboardDriverDescriptors_INTERRUPTOUT
+///
+/// !Polling Rates
+/// - HIDDKeyboardDriverDescriptors_INTERRUPTIN_POLLING
+/// - HIDDKeyboardDriverDescriptors_INTERRUPTOUT_POLLING
+
+/// Interrupt IN endpoint number.
+#define HIDDKeyboardDriverDescriptors_INTERRUPTIN 1
+/// Interrupt IN endpoint polling rate (in milliseconds).
+#define HIDDKeyboardDriverDescriptors_INTERRUPTIN_POLLING 10
+/// Interrupt OUT endpoint number.
+#define HIDDKeyboardDriverDescriptors_INTERRUPTOUT 2
+/// Interrupt OUT endpoint polling rate (in milliseconds).
+#define HIDDKeyboardDriverDescriptors_INTERRUPTOUT_POLLING 10
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// \page "HID Keypad keys"
+/// This page lists definition for HID keypad keys.
+///
+/// !Keys
+/// - HIDDKeyboardDriverDescriptors_FIRSTMODIFIERKEY
+/// - HIDDKeyboardDriverDescriptors_LASTMODIFIERKEY
+/// - HIDDKeyboardDriverDescriptors_FIRSTSTANDARDKEY
+/// - HIDDKeyboardDriverDescriptors_LASTSTANDARDKEY
+
+/// Key code of the first accepted modifier key.
+#define HIDDKeyboardDriverDescriptors_FIRSTMODIFIERKEY HIDKeypad_LEFTCONTROL
+/// Key code of the last accepted modifier key.
+#define HIDDKeyboardDriverDescriptors_LASTMODIFIERKEY HIDKeypad_RIGHTGUI
+/// Key code of the first accepted standard key.
+#define HIDDKeyboardDriverDescriptors_FIRSTSTANDARDKEY 0
+/// Key code of the last accepted standard key.
+#define HIDDKeyboardDriverDescriptors_LASTSTANDARDKEY HIDKeypad_NUMLOCK
+//------------------------------------------------------------------------------
+
+/// Size of the report descriptor in bytes.
+#define HIDDKeyboardDriverDescriptors_REPORTSIZE 61
+
+//------------------------------------------------------------------------------
+// Exported variables
+//------------------------------------------------------------------------------
+
+extern USBDDriverDescriptors hiddKeyboardDriverDescriptors;
+
+extern const unsigned char hiddReportDescriptor[];
+
+#endif //#ifndef HIDDKEYBOARDDRIVERDESCRIPTORS_H
+
diff --git a/usb/device/hid-keyboard/HIDDKeyboardInputReport.c b/usb/device/hid-keyboard/HIDDKeyboardInputReport.c new file mode 100644 index 0000000..3257bdb --- /dev/null +++ b/usb/device/hid-keyboard/HIDDKeyboardInputReport.c @@ -0,0 +1,164 @@ +/* ----------------------------------------------------------------------------
+ * ATMEL Microcontroller Software Support
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: HIDDKeyboardInputReport implementation
+
+ About: Purpose
+ Implementation of the HIDDKeyboardInputReport class.
+*/
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "HIDDKeyboardInputReport.h"
+#include "HIDDKeyboardDriverDescriptors.h"
+#include <utility/assert.h>
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Initializes a keyboard input report instance.
+/// \param report Pointer to a HIDDKeyboardInputReport instance.
+//------------------------------------------------------------------------------
+void HIDDKeyboardInputReport_Initialize(HIDDKeyboardInputReport *report)
+{
+ unsigned int i;
+
+ report->bmModifierKeys = 0;
+ for (i = 0; i < HIDDKeyboardInputReport_MAXKEYPRESSES; i++) {
+
+ report->pressedKeys[i] = 0;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Reports a standard key as being pressed.
+/// \param report Pointer to a HIDDKeyboardInputReport instance.
+/// \param key Key code of the standard key.
+//------------------------------------------------------------------------------
+void HIDDKeyboardInputReport_PressStandardKey(HIDDKeyboardInputReport *report,
+ unsigned char key)
+{
+ ASSERT(key <= HIDDKeyboardDriverDescriptors_LASTSTANDARDKEY,
+ "Invalid standard key code (%d)\n\r",
+ key);
+
+ // Find first available slot
+ unsigned int i = 0;
+ unsigned char found = 0;
+ while ((i < HIDDKeyboardInputReport_MAXKEYPRESSES) && !found) {
+
+ // Free slot: no key referenced (code = 0) or ErrorRollOver
+ if ((report->pressedKeys[i] == 0)
+ || (report->pressedKeys[i] == HIDKeypad_ERRORROLLOVER)) {
+
+ found = 1;
+ report->pressedKeys[i] = key;
+ }
+
+ i++;
+ }
+
+ // Report ErrorRollOver in all fields if too many keys are pressed
+ if (!found) {
+
+ for (i=0; i < HIDDKeyboardInputReport_MAXKEYPRESSES; i++) {
+
+ report->pressedKeys[i] = HIDKeypad_ERRORROLLOVER;
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Reports a standard key as not being pressed anymore.
+/// \param report Pointer to a HIDDKeyboardInputReport instance.
+/// \param key Key code of the standard key
+//------------------------------------------------------------------------------
+void HIDDKeyboardInputReport_ReleaseStandardKey(HIDDKeyboardInputReport *report,
+ unsigned char key)
+{
+ ASSERT(key <= HIDDKeyboardDriverDescriptors_LASTSTANDARDKEY,
+ "Invalid standard key code (%d)\n\r",
+ key);
+
+ // Look for key in array
+ unsigned int i = 0;
+ unsigned char found = 0;
+ while ((i < HIDDKeyboardInputReport_MAXKEYPRESSES) && !found) {
+
+ if (report->pressedKeys[i] == key) {
+
+ found = 1;
+ report->pressedKeys[i] = 0;
+ }
+
+ i++;
+ }
+}
+
+//------------------------------------------------------------------------------
+/// Reports a modifier key as being currently pressed.
+/// \param report Pointer to a HIDDKeyboardInputReport instance.
+/// \param key Key code of the modifier key.
+//------------------------------------------------------------------------------
+void HIDDKeyboardInputReport_PressModifierKey(HIDDKeyboardInputReport *report,
+ unsigned char key)
+{
+ ASSERT((key >= HIDDKeyboardDriverDescriptors_FIRSTMODIFIERKEY)
+ && (key <= HIDDKeyboardDriverDescriptors_LASTMODIFIERKEY),
+ "Invalid standard key code (%d)\n\r",
+ key);
+
+ // Set corresponding bit
+ unsigned char bit = key - HIDDKeyboardDriverDescriptors_FIRSTMODIFIERKEY;
+ report->bmModifierKeys |= 1 << bit;
+}
+
+//------------------------------------------------------------------------------
+/// Reports a modifier key as not being pressed anymore.
+/// \param report Pointer to a HIDDKeyboardInputReport instance.
+/// \param key Key code of the modifier key.
+//------------------------------------------------------------------------------
+void HIDDKeyboardInputReport_ReleaseModifierKey(HIDDKeyboardInputReport *report,
+ unsigned char key)
+{
+ ASSERT((key >= HIDDKeyboardDriverDescriptors_FIRSTMODIFIERKEY)
+ && (key <= HIDDKeyboardDriverDescriptors_LASTMODIFIERKEY),
+ "Invalid standard key code (%d)\n\r",
+ key);
+
+ // Clear corresponding bit
+ unsigned char bit = key - HIDDKeyboardDriverDescriptors_FIRSTMODIFIERKEY;
+ report->bmModifierKeys &= ~(1 << bit);
+}
+
diff --git a/usb/device/hid-keyboard/HIDDKeyboardInputReport.h b/usb/device/hid-keyboard/HIDDKeyboardInputReport.h new file mode 100644 index 0000000..7eeafd8 --- /dev/null +++ b/usb/device/hid-keyboard/HIDDKeyboardInputReport.h @@ -0,0 +1,149 @@ +/* ----------------------------------------------------------------------------
+ * ATMEL Microcontroller Software Support
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit HIDDKeyboardInputReport.h
+
+ !!!Purpose
+
+ Class for manipulating HID keyboard input reports.
+
+ !!!Usage
+
+ -# Initialize a newly created input report with
+ HIDDKeyboardInputReport_Initialize.
+ -# Change the standard keys that are pressed and released using
+ HIDDKeyboardInputReport_PressStandardKey and
+ HIDDKeyboardInputReport_ReleaseStandardKey.
+ -# Change the modifier keys that are currently pressed and released
+ using HIDDKeyboardInputReport_PressModifierKey and
+ HIDDKeyboardInputReport_ReleaseModifierKey.
+*/
+
+#ifndef HIDDKEYBOARDINPUTREPORT_H
+#define HIDDKEYBOARDINPUTREPORT_H
+
+//------------------------------------------------------------------------------
+// Definitions
+//------------------------------------------------------------------------------
+
+/// Maximum number of simultaneous key presses.
+#define HIDDKeyboardInputReport_MAXKEYPRESSES 3
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// HID input report structure used by the keyboard driver to notify the
+/// host of pressed keys.
+///
+/// The first byte is used to report the state of modifier keys. The
+/// other three contains the keycodes of the currently pressed keys.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ /// State of modifier keys.
+ unsigned char bmModifierKeys:8;
+ /// Key codes of pressed keys.
+ unsigned char pressedKeys[HIDDKeyboardInputReport_MAXKEYPRESSES];
+
+} __attribute__ ((packed)) HIDDKeyboardInputReport; // GCC
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+/*
+ Function: HIDDKeyboardInputReport_Initialize
+ Initializes a keyboard input report instance.
+
+ Parameters:
+ report - Pointer to a HIDDKeyboardInputReport instance.
+*/
+extern void HIDDKeyboardInputReport_Initialize(HIDDKeyboardInputReport *report);
+
+/*
+ Function: HIDDKeyboardInputReport_PressStandardKey
+ Reports a standard key as being pressed.
+
+ Parameters:
+ report - Pointer to a HIDDKeyboardInputReport instance.
+ key - Key code of the standard key.
+*/
+extern void HIDDKeyboardInputReport_PressStandardKey(
+ HIDDKeyboardInputReport *report,
+ unsigned char key);
+
+/*
+ Function: HIDDKeyboardInputReport_ReleaseStandardKey
+ Reports a standard key as not being pressed anymore.
+
+ Parameters:
+ report - Pointer to a HIDDKeyboardInputReport instance.
+ key - Key code of the standard key
+*/
+extern void HIDDKeyboardInputReport_ReleaseStandardKey(
+ HIDDKeyboardInputReport *report,
+ unsigned char key);
+
+/*
+ Function: HIDDKeyboardInputReport_PressModifierKey
+ Reports a modifier key as being currently pressed.
+
+ Parameters:
+ report - Pointer to a HIDDKeyboardInputReport instance.
+ key - Key code of the modifier key.
+*/
+extern void HIDDKeyboardInputReport_PressModifierKey(
+ HIDDKeyboardInputReport *report,
+ unsigned char key);
+
+/*
+ Function: HIDDKeyboardInputReport_ReleaseModifierKey
+ Reports a modifier key as not being pressed anymore.
+
+ Parameters:
+ report - Pointer to a HIDDKeyboardInputReport instance.
+ key - Key code of the modifier key.
+*/
+extern void HIDDKeyboardInputReport_ReleaseModifierKey(
+ HIDDKeyboardInputReport *report,
+ unsigned char key);
+
+#endif //#ifndef HIDDKEYBOARDINPUTREPORT_H
+
diff --git a/usb/device/hid-keyboard/HIDDKeyboardOutputReport.c b/usb/device/hid-keyboard/HIDDKeyboardOutputReport.c new file mode 100644 index 0000000..f79d7ac --- /dev/null +++ b/usb/device/hid-keyboard/HIDDKeyboardOutputReport.c @@ -0,0 +1,94 @@ +/* ----------------------------------------------------------------------------
+ * ATMEL Microcontroller Software Support
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+/*
+ Title: HIDDKeyboardOutputReport implementation
+
+ About: Purpose
+ Implementation of the HIDDKeyboardOutputReport class.
+*/
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+
+#include "HIDDKeyboardOutputReport.h"
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+/// Initializes a keyboard output report.
+/// \param report Pointer to a HIDDKeyboardOutputReport instance.
+//------------------------------------------------------------------------------
+void HIDDKeyboardOutputReport_Initialize(HIDDKeyboardOutputReport *report)
+{
+ report->numLockStatus = 0;
+ report->capsLockStatus = 0;
+ report->scrollLockStatus = 0;
+ report->padding = 0;
+}
+
+//------------------------------------------------------------------------------
+/// Indicates the current status of the num. lock LED according to the
+/// given report.
+/// \param report Pointer to a HIDDKeyboardOutputReport instance.
+/// \return 1 if the num. lock LED is light on; otherwise 0.
+//------------------------------------------------------------------------------
+unsigned char HIDDKeyboardOutputReport_GetNumLockStatus(
+ const HIDDKeyboardOutputReport *report)
+{
+ return report->numLockStatus;
+}
+
+//------------------------------------------------------------------------------
+/// Indicates the current status of the caps lock LED according to the
+/// given report.
+/// \param report Pointer to a HIDDKeyboardOutputReport instance.
+/// \return 1 if the caps lock LED is light on; otherwise 0.
+//------------------------------------------------------------------------------
+unsigned char HIDDKeyboardOutputReport_GetCapsLockStatus(
+ const HIDDKeyboardOutputReport *report)
+{
+ return report->capsLockStatus;
+}
+
+//------------------------------------------------------------------------------
+/// Indicates the current status of the scroll lock LED according to the
+/// given report.
+/// \param report Pointer to a HIDDKeyboardOutputReport instance.
+/// \return 1 if the scroll lock LED is light on; otherwise 0.
+//------------------------------------------------------------------------------
+unsigned char HIDDKeyboardOutputReport_GetScrollLockStatus(
+ const HIDDKeyboardOutputReport *report)
+{
+ return report->scrollLockStatus;
+}
+
diff --git a/usb/device/hid-keyboard/HIDDKeyboardOutputReport.h b/usb/device/hid-keyboard/HIDDKeyboardOutputReport.h new file mode 100644 index 0000000..760df1b --- /dev/null +++ b/usb/device/hid-keyboard/HIDDKeyboardOutputReport.h @@ -0,0 +1,96 @@ +/* ----------------------------------------------------------------------------
+ * ATMEL Microcontroller Software Support
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+/**
+ \unit HIDDKeyboardOutputReport
+
+ !!!Purpose
+
+ Definition of a class for manipulating HID keyboard output reports.
+
+ !!!Usage
+
+ -# Initialize a newly-created output report instance with
+ HIDDKeyboardOutputReport_Initialize.
+ -# Retrieve the status of the three LEDs using
+ HIDDKeyboardOutputReport_GetNumLockStatus,
+ HIDDKeyboardOutputReport_GetCapsLockStatus and
+ HIDDKeyboardOutputReport_GetScrollLockStatus.
+*/
+
+#ifndef HIDKEYBOARDOUTPUTREPORT_H
+#define HIDKEYBOARDOUTPUTREPORT_H
+
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+#ifdef __ICCARM__ // IAR
+#pragma pack(1) // IAR
+#define __attribute__(...) // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+/// HID output report structure used by the host to control the state of
+/// the keyboard LEDs.
+///
+/// Only the first three bits are relevant, the other 5 are used as
+/// padding bits.
+//------------------------------------------------------------------------------
+typedef struct {
+
+ unsigned char numLockStatus:1, /// State of the num. lock LED.
+ capsLockStatus:1, /// State of the caps lock LED.
+ scrollLockStatus:1, /// State of the scroll lock LED.
+ padding:5; /// Padding bits.
+
+} __attribute__ ((packed)) HIDDKeyboardOutputReport; // GCC
+
+#ifdef __ICCARM__ // IAR
+#pragma pack() // IAR
+#endif // IAR
+
+//------------------------------------------------------------------------------
+// Exported functions
+//------------------------------------------------------------------------------
+
+extern void HIDDKeyboardOutputReport_Initialize(
+ HIDDKeyboardOutputReport *report);
+
+extern unsigned char HIDDKeyboardOutputReport_GetNumLockStatus(
+ const HIDDKeyboardOutputReport *report);
+
+extern unsigned char HIDDKeyboardOutputReport_GetCapsLockStatus(
+ const HIDDKeyboardOutputReport *report);
+
+extern unsigned char HIDDKeyboardOutputReport_GetScrollLockStatus(
+ const HIDDKeyboardOutputReport *report);
+
+#endif //#ifndef HIDKEYBOARDOUTPUTREPORT_H
+
diff --git a/usb/device/hid-keyboard/hid-keyboard.dir b/usb/device/hid-keyboard/hid-keyboard.dir new file mode 100644 index 0000000..923a362 --- /dev/null +++ b/usb/device/hid-keyboard/hid-keyboard.dir @@ -0,0 +1,787 @@ +/* ----------------------------------------------------------------------------
+ * ATMEL Microcontroller Software Support
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2008, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+//------------------------------------------------------------------------------
+/// \dir
+///
+/// !!!Purpose
+///
+/// This directory provides definitions, structs and functions for a USB HID
+/// %device - USB HID Keyboard driver, to implement an USB keyboard %device.
+///
+/// !!!Contents
+///
+/// There are three things for the implement of the USB HID Keyboard driver:
+/// - Implement the USB HID driver structs and functions for the %device,
+/// to initialize, to handle HID-specific requests and dispach
+/// standard requests in USBD callbacks, to read/write through assigned USB
+/// endpoints,
+/// - Create the HID Keyboard device's descriptors that should be passed to
+/// the USBDDriver instance on initialization, so that the host can
+/// recognize the %device as a USB Keyboard %device.
+/// - Implement methods to update the keyboard keys status, so that host can
+/// get it through USB.
+///
+/// For more information about what a particular group contains, please refer to
+/// "USB HID Keyboard".
+//------------------------------------------------------------------------------
+
+/**
+ \page "USB HID Keyboard"
+ This page describes how to use the "AT91 USB device framework" to produce a USB
+ HID Keyboard driver, which appears as a USB keyboard on host.
+
+ Details about the USB and the HID class can be found in the }USB specification
+ 2.0} and the }HID specification 1.11}, respectively.
+
+ !!!References
+ - "AT91 USB device framework"
+ - "USB Device Enumeration"
+ - <a href="http://www.usb.org/developers/docs/usb_20_040908.zip">
+ Universal Serial Bus Revision 2.0 specification
+ </a> (.zip file format, size 9.80 MB)
+ - <a href="http://www.usb.org/developers/devclass_docs/HID1_11.pdf">
+ Device Class Definition for HID 1.11</a>
+ - <a href="http://www.usb.org/developers/devclass_docs/Hut1_12.pdf">
+ HID Usage Tables 1.12</a>
+
+ !!!HID Basic
+ See "USB HID Basic".
+
+ !!!Architecture
+ See "USB Device Framework Architecture".
+
+ !!!Descriptors
+
+ ...
+
+ !!Device Descriptor
+ The Device descriptor of an HID %device is very basic, since the HID class
+ code is only specified at the Interface level. Thus, it only contains
+ standard values, as shown below:
+\code
+static const USBDeviceDescriptor deviceDescriptor = {
+
+ sizeof(USBDeviceDescriptor),
+ USBGenericDescriptor_DEVICE,
+ USBDeviceDescriptor_USB2_00,
+ HIDDeviceDescriptor_CLASS,
+ HIDDeviceDescriptor_SUBCLASS,
+ HIDDeviceDescriptor_PROTOCOL,
+ BOARD_USB_ENDPOINTS_MAXPACKETSIZE(0),
+ HIDDKeyboardDriverDescriptors_VENDORID,
+ HIDDKeyboardDriverDescriptors_PRODUCTID,
+ HIDDKeyboardDriverDescriptors_RELEASE,
+ 1, // Index of manufacturer description
+ 2, // Index of product description
+ 3, // Index of serial number description
+ 1 // One possible configuration
+};
+\endcode
+ Note that the Vendor ID is a special value attributed by the USB-IF
+ organization. The product ID can be chosen freely by the vendor.
+
+ !!Configuration Descriptor
+ Since one interface is required by the HID specification, this must be
+ specified in the Configuration descriptor. There is no other value of
+ interest to put here.
+\code
+// Configuration descriptor
+{
+ sizeof(USBConfigurationDescriptor),
+ USBGenericDescriptor_CONFIGURATION,
+ sizeof(HIDDKeyboardDriverConfigurationDescriptors),
+ 1, // One interface in this configuration
+ 1, // This is configuration #1
+ 0, // No associated string descriptor
+ BOARD_USB_BMATTRIBUTES,
+ USBConfigurationDescriptor_POWER(100)
+},
+\endcode
+ When the Configuration descriptor is requested by the host (by using the
+ GET_DESCRIPTOR command), the %device must also sent all the related
+ descriptors, i.e. Interface, Endpoint and Class-Specific descriptors. It is
+ convenient to create a single structure to hold all this data, for sending
+ everything in one chunk. In the example software, a
+ HIDDKeyboardDriverConfigurationDescriptors structure has been declared for
+ that.
+
+ !!HID Class Interface Descriptor
+ Since a keyboard %device needs to transmit as well as receive data, two
+ Interrupt (IN & OUT) endpoints are needed. This must be indicated in the
+ Interface descriptor. Conversely to the mouse example, the Boot protocol is
+ not implemented here, since there are more constraints on a keyboard %device.
+\code
+// Interface descriptor
+{
+ sizeof(USBInterfaceDescriptor),
+ USBGenericDescriptor_INTERFACE,
+ 0, // This is interface #0
+ 0, // This is alternate setting #0
+ 2, // Two endpoints used
+ HIDInterfaceDescriptor_CLASS,
+ HIDInterfaceDescriptor_SUBCLASS_NONE,
+ HIDInterfaceDescriptor_PROTOCOL_NONE,
+ 0 // No associated string descriptor
+},
+\endcode
+
+ !!HID Descriptor
+ While a HID keyboard produces two different reports, one Input and one Output,
+ only one Report descriptor can be used to describe them. Since having Physical
+ descriptors is also useless for a keyboard, there will only be one HID class
+ descriptor specified here.
+
+ For a keyboard, the }bCountryCode} field can be used to specify the language
+ of the key caps. As this is optional, it is simply set to 00h in the example:
+\code
+// HID descriptor
+{
+ sizeof(HIDDescriptor),
+ HIDGenericDescriptor_HID,
+ HIDDescriptor_HID1_11,
+ 0, // Device is not localized, no country code
+ 1, // One HID-specific descriptor (apart from this one)
+ HIDGenericDescriptor_REPORT,
+ HIDDKeyboardDriverDescriptors_REPORTSIZE
+},
+\endcode
+
+ !!Report Descriptor
+ Two current reports are defined in the Report descriptor. The first one is
+ used to notify the host of which keys are pressed, with both modifier keys
+ (alt, ctrl, etc.) and alphanumeric keys. The second report is necessary for
+ the host to send the LED (num lock, caps lock, etc.) states.
+
+ The Report descriptor starts with the global %device functionality, described
+ with a #Usage Page# and a #Usage# items:
+\code
+const unsigned char hiddReportDescriptor[] = {
+
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDGenericDesktop_PAGEID,
+ HIDReport_LOCAL_USAGE + 1, HIDGenericDesktop_KEYBOARD,
+\endcode
+
+ As in the mouse example, the }Generic Desktop} page is used. This time, the
+ specific usage is the }Keyboard} one. An Application collection is then
+ defined to group the reports together:
+\code
+ HIDReport_COLLECTION + 1, HIDReport_COLLECTION_APPLICATION,
+\endcode
+
+ The first report to be defined is the modifier keys. They are represented as a
+ bitmap field, indicating whether or not each key is pressed. A single byte is
+ used to map keys \#224-231 defined in the }HID Usage Tables} document:
+ LeftControl, LeftShift, LeftAlt, LeftGUI (e.g. Windows key),
+ RightControl, RightShift, RightAlt and RightGUI.
+ The }Keypad} usage page must be specified for this report, and since this is a
+ bitmap value, the data is flagged as }Variable}:
+\code
+ // Input report: modifier keys
+ HIDReport_GLOBAL_REPORTSIZE + 1, 1,
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 8,
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDKeypad_PAGEID,
+ HIDReport_LOCAL_USAGEMINIMUM + 1,
+ HIDDKeyboardDriverDescriptors_FIRSTMODIFIERKEY,
+ HIDReport_LOCAL_USAGEMAXIMUM + 1,
+ HIDDKeyboardDriverDescriptors_LASTMODIFIERKEY,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1, 0,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1, 1,
+ HIDReport_INPUT + 1, HIDReport_VARIABLE,
+\endcode
+
+ Then, the actual alphanumeric key report is described. This is done by
+ defining several bytes of data, one for each pressed key. In the example,
+ up to three keys can be pressed at the same time (and detected) by the user.
+ Once again, the usage page is set to }Keypad}. This time however, the data
+ must be specified as an }Array}, since the same control (the keypad) produces
+ several values:
+\code
+ // Input report: standard keys
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 3,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 8,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1,
+ HIDDKeyboardDriverDescriptors_FIRSTSTANDARDKEY,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1,
+ HIDDKeyboardDriverDescriptors_LASTSTANDARDKEY,
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDKeypad_PAGEID,
+ HIDReport_LOCAL_USAGEMINIMUM + 1,
+ HIDDKeyboardDriverDescriptors_FIRSTSTANDARDKEY,
+ HIDReport_LOCAL_USAGEMAXIMUM + 1,
+ HIDDKeyboardDriverDescriptors_LASTSTANDARDKEY,
+ HIDReport_INPUT + 1, 0 /* Data array */,
+\endcode
+
+ The LED array is then defined, with the associated usage page. The Report
+ descriptor is formatted in this order to avoid redefining unchanged }Global}
+ items, in order to save memory. This time again, the LED status is reported as
+ a bitmap field. Three LEDs are used here: Num Lock, Caps Lock and Scroll Lock
+ (IDs 01h to 03h). It is important to note that this is an #Output# report:
+\code
+ // Output report: LEDs
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 3,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 1,
+ HIDReport_GLOBAL_USAGEPAGE + 1, HIDLeds_PAGEID,
+ HIDReport_GLOBAL_LOGICALMINIMUM + 1, 0,
+ HIDReport_GLOBAL_LOGICALMAXIMUM + 1, 1,
+ HIDReport_LOCAL_USAGEMINIMUM + 1, HIDLeds_NUMLOCK,
+ HIDReport_LOCAL_USAGEMAXIMUM + 1, HIDLeds_SCROLLLOCK,
+ HIDReport_OUTPUT + 1, HIDReport_VARIABLE,
+\endcode
+
+ Since the previous report only contains 3 bits, the data must be padded to a
+ multiple of one byte. This is done by using constant Output data, as follows:
+\code
+ // Output report: padding
+ HIDReport_GLOBAL_REPORTCOUNT + 1, 1,
+ HIDReport_GLOBAL_REPORTSIZE + 1, 5,
+ HIDReport_OUTPUT + 1, HIDReport_CONSTANT,
+\endcode
+
+ The last item, }End Collection}, is necessary to close the previously opened
+ }Application Collection}.
+\code
+ HIDReport_ENDCOLLECTION
+};
+\endcode
+
+ The Input and Output reports defined by this descriptor can be modeled by the
+ following structures:
+\code
+// HID Input Report
+typedef struct {
+
+ // State of modifier keys.
+ unsigned char bmModifierKeys:8;
+ // Key codes of pressed keys.
+ unsigned char pressedKeys[HIDDKeyboardInputReport_MAXKEYPRESSES];
+
+} __attribute__ ((packed)) HIDDKeyboardInputReport; // GCC
+// HID Output Report
+typedef struct {
+
+ unsigned char numLockStatus:1, // State of the num. lock LED.
+ capsLockStatus:1, // State of the caps lock LED.
+ scrollLockStatus:1, // State of the scroll lock LED.
+ padding:5; // Padding bits.
+
+} __attribute__ ((packed)) HIDDKeyboardOutputReport; // GCC
+\endcode
+
+ An instance of each one of the reports is stored in a HIDDKeyboardDriver
+ structure, which holds the standard class driver and HID keyboard-specific
+ data.
+
+ !!Physical Descriptor
+ A Physical descriptor is useless for a keyboard %device, so none are defined
+ in this example.
+
+ !!Endpoint Descriptor
+ Following the Interface and HID-specific descriptors, the two necessary
+ endpoints are defined.
+\code
+// Interrupt IN endpoint descriptor
+{
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_IN,
+ HIDDKeyboardDriverDescriptors_INTERRUPTIN),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDKeyboardInputReport),
+ HIDDKeyboardDriverDescriptors_INTERRUPTIN_POLLING
+},
+// Interrupt OUT endpoint descriptor
+{
+ sizeof(USBEndpointDescriptor),
+ USBGenericDescriptor_ENDPOINT,
+ USBEndpointDescriptor_ADDRESS(
+ USBEndpointDescriptor_OUT,
+ HIDDKeyboardDriverDescriptors_INTERRUPTOUT),
+ USBEndpointDescriptor_INTERRUPT,
+ sizeof(HIDDKeyboardOutputReport),
+ HIDDKeyboardDriverDescriptors_INTERRUPTIN_POLLING
+}
+\endcode
+
+ !!String Descriptors
+ Please refer to "Usage: USBD VID, PID & Strings".
+
+ !!!Class-specific requests
+ A driver request handler should first differentiate between class-specific and
+ standard requests using the corresponding bits in the }bmRequestType} field.
+ In most cases, standard requests can be immediately forwarded to the standard
+ request handler method; class-specific methods must be decoded and treated by
+ the custom handler.
+
+ !!GetDescriptor
+ Three values have been added by the HID specification for the #GET_DESCRIPTOR#
+ request. The high byte of the }wValue} field contains the type of the
+ requested descriptor; in addition to the standard types, the #HID
+ specification# adds the #HID descriptor# (21h), the #Report descriptor#
+ (22h) and the #Physical descriptor# (23h) types.
+
+ There is no particular action to perform besides sending the descriptor. This
+ can be done by using the USBD_Write method, after the requested descriptor has
+ been identified:
+\code
+switch (USBGenericRequest_GetRequest(request)) {
+
+ case USBGenericRequest_GETDESCRIPTOR:
+ // Check if this is a HID descriptor,
+ // otherwise forward it to
+ // the standard driver
+ if (!HIDDKeyboardDriver_GetDescriptor(
+ USBGetDescriptorRequest_GetDescriptorType(request),
+ USBGenericRequest_GetLength(request))) {
+
+ USBDDriver_RequestHandler(&(hiddKeyboardDriver.usbdDriver),
+ request);
+ }
+ break;
+
+ default:
+ USBDDriver_RequestHandler(&(hiddKeyboardDriver.usbdDriver),
+ request);
+}
+\endcode
+ A slight complexity of the GET_DESCRIPTOR and SET_DESCRIPTOR requests is that
+ those are standard requests, but the standard request handler
+ (USBDDriver_RequestHandler) must not always be called to treat them (since
+ they may refer to HID descriptors). The solution is to first identify
+ GET/SET_DESCRIPTOR requests, treat the HID-specific cases and, finally,
+ forward any other request to the standard handler.
+
+ In this case, a GET_DESCRIPTOR request for the Physical descriptor is first
+ forwarded to the standard handler, and STALLed there because it is not
+ recognized. This is done because the %device does not have any Physical
+ descriptors, and thus, does not need to handle the associated request.
+
+ !!SetDescriptor
+ This request is optional and is never issued by most hosts. It is not
+ implemented in this example.
+
+ !!GetReport
+ Since the HID keyboard defines two different reports, the Report Type value
+ specified by this request (upper byte of the }wValue} field) must be examined
+ to decide which report to send. If the type value is 01h, then the Input
+ report must be returned; if it is 02h, the Output report is requested:
+\code
+case HIDGenericRequest_GETREPORT:
+//-------------------------------
+ type = HIDReportRequest_GetReportType(request);
+ length = USBGenericRequest_GetLength(request);
+ switch (type) {
+
+ case HIDReportRequest_INPUT:
+
+ // Adjust size and send report
+ if (length > sizeof(HIDDKeyboardInputReport)) {
+
+ length = sizeof(HIDDKeyboardInputReport);
+ }
+ USBD_Write(0, // Endpoint #0
+ &(hiddKeyboardDriver.inputReport),
+ length,
+ 0, // No callback
+ 0);
+ break;
+
+ case HIDReportRequest_OUTPUT:
+
+ // Adjust size and send report
+ if (length > sizeof(HIDDKeyboardOutputReport)) {
+
+ length = sizeof(HIDDKeyboardOutputReport);
+ }
+ USBD_Write(0, // Endpoint #0
+ &(hiddKeyboardDriver.outputReport),
+ length,
+ 0, // No callback
+ 0);
+ break;
+
+ default:
+ USBD_Stall(0);
+ }
+break;
+\endcode
+
+ !!SetReport
+ For an HID keyboard, the #SET_REPORT# command can be sent by the host to
+ change the state of the LEDs. Normally, the dedicated Interrupt OUT endpoint
+ will be used for this; but in some cases, using the default Control endpoint
+ can save some bandwidth on the host side.
+
+ Note that the SET_REPORT request can be directed at the Input report of the
+ keyboard; in this case, it can be safely discarded, according to the HID
+ specification. Normally, most host drivers only target the Output report. The
+ Report Type value is stored in the upper byte of the }wValue} field.
+
+ The length of the data phase to follow is stored in the }wLength} field of the
+ request. It should be equal to the total length of the Output report. If it is
+ different, the report status must still be updated with the received data as
+ best as possible.
+
+ When the reception of the new data is completed, some processing must be done
+ to enable/disable the corresponding LEDs. This is done in the callback
+ function passed as an argument to USBD_Read:
+\code
+case HIDGenericRequest_SETREPORT:
+//-------------------------------
+ type = HIDReportRequest_GetReportType(request);
+ length = USBGenericRequest_GetLength(request);
+ switch(type) {
+
+ case HIDReportRequest_INPUT:
+ // SET_REPORT requests on input reports are ignored
+ USBD_Stall(0);
+ break;
+
+ case HIDReportRequest_OUTPUT:
+ // Check report length
+ if (length != sizeof(HIDDKeyboardOutputReport)) {
+
+ USBD_Stall(0);
+ }
+ else {
+
+ USBD_Read(0, // Endpoint #0
+ &(hiddKeyboardDriver.outputReport),
+ length,
+ (TransferCallback) HIDDKeyboardDriver_ReportReceived,
+ 0); // No argument to the callback function
+ }
+ break;
+
+ default:
+ USBD_Stall(0);
+ }
+break;
+\endcode
+
+ !!SetIdle
+ In this case study, the #SET_IDLE# request is used to set a delay before a key
+ is repeated. This is common behavior on keyboard devices. Usually, this delay
+ is set to about 500 ms by the host.
+
+ The only action here is to store the new Idle rate. The management of this
+ setting must be done in the main function, since Interrupt IN reports are sent
+ from there.
+
+ In practice, it is not necessary to perform any action, apart from sending a
+ zero-length packet to acknowledge it. The main application however has to make
+ sure that only new reports are sent by the %device.
+\code
+case HIDGenericRequest_SETIDLE:
+//-----------------------------
+ hiddKeyboardDriver.inputReportIdleRate =
+ HIDIdleRequest_GetIdleRate(request);
+ USBD_Write(0, 0, 0, 0, 0);
+break;
+\endcode
+
+ !!GetIdle
+ The only necessary operation for this request is to send the previously saved
+ Idle rate. This is done by calling the USBD_Write method with the one-byte
+ variable as its parameter:
+\code
+case HIDGenericRequest_GETIDLE:
+//-----------------------------
+ USBD_Write(0, &(hiddKeyboardDriver.inputReportIdleRate), 1, 0, 0);
+break;
+\endcode
+
+ !!GetProtocol, SetProtocol
+ This HID keyboard example does not support the Boot protocol, so there is no
+ need to implement the SET_PROTOCOL and GET_PROTOCOL requests. This means they
+ can be safely STALLed when received.
+
+ !!!Main Application
+ Like the mouse example, the main program must perform two different
+ operations. First, it has to monitor the physical inputs used as keys. In the
+ example software, the buttons present on the evaluation boards are used to
+ produce several modifier and alphanumeric keys.
+
+ Also, the main program is in charge of sending reports as they are modified,
+ taking into account the Idle rate specified by the host. Idle rate management
+ can be carried out by firing/resetting a timer once a new report is sent; if
+ the timer expires, this means the Input report has not changed since.
+ According to the HID specification, a single instance of the report must be
+ sent in this case.
+
+ Finally, the HID specification also defines that if too many keys are pressed
+ at the same time, the %device should report an }ErrorRollOver} usage value
+ (01h) in every byte of the key array. This has to be handled by the main
+ application as well.
+
+*/
+
+/**
+ \page "USB HID Mouse"
+ This page describes how to implement a mouse %device using the HID class and
+ the "AT91 USB device framework". Details about the USB and the HID class can
+ be found in the }USB specification 2.0} and the }HID specification 1.11}
+ documents, respectively.
+
+ !!!References
+ - "AT91 USB device framework"
+ - "USB Device Enumeration"
+ - <a href="http://www.usb.org/developers/docs/usb_20_040908.zip">
+ Universal Serial Bus Revision 2.0 specification
+ </a> (.zip file format, size 9.80 MB)
+ - <a href="http://www.usb.org/developers/devclass_docs/HID1_11.pdf">
+ Device Class Definition for HID 1.11</a>
+ - <a href="http://www.usb.org/developers/devclass_docs/Hut1_12.pdf">
+ HID Usage Tables 1.12</a>
+
+
+
+*/
+
+/**
+ \page "USB HID Basic"
+
+ This page gives generic details on the HID class, including its purpose,
+ architecture and how it is supported by various operating systems.
+
+ !!!Purpose
+
+ The HID class has been specifically designed for Human Interface Devices,
+ i.e., devices which are manipulated by humans to control a computer or an
+ electronic %device. This includes common peripherals such as a keyboard, a
+ mouse or a joystick, as well as many other interfaces: remote controllers,
+ switches, buttons, dedicated game controls, and so on.
+
+ It is also possible to use the HID class for devices which do not require
+ human interaction, but still deliver information in a similar format. For
+ example, devices like a thermometer or a battery indicator are supported.
+
+ In addition, the HID class also makes it possible to not only receive data
+ from devices but also to send commands to them. Indeed, many devices offer
+ some kind of display to give back information to the user, e.g., the LEDs on a
+ keyboard.
+
+ Finally, since it is quite simple to send and receive data using the HID
+ class, it can be used as a generic means of communication between a %device
+ and a host. This is made possible because of the very flexible framework
+ defined in the HID specification.
+
+ In this document, three uses of the HID class will be detailed step-by-step,
+ each showing one particular feature of the class. The first example shows the
+ interaction with a simple mouse. In the second example, a keyboard is
+ implemented to demonstrate the possibility to send data to a peripheral. The
+ last example explains how to use HID as a simple two-way communication
+ channel.
+
+ !!!Architecture
+ ...
+
+ !!Interface
+ An HID %device only needs #one interface descriptor#. It should have the HID
+ interface class code in its bInterfaceClass field. There are special subclass
+ and protocol codes to specify if the HID %device is a mouse or a keyboard, and
+ must be supported by the BIOS. In such a case, the interface must be declared
+ as a Boot Interface, and the type of the %device (mouse or keyboard) must be
+ given in the bInterfaceProtocol field.
+
+ !!Endpoints
+ Up to three endpoints can be used with an HID interface. The first two are the
+ default Control endpoint 0, as well as an Interrupt IN endpoint. They are
+ mandatory and shall always be declared. An optional Interrupt OUT endpoint can
+ be added as well.
+
+ Endpoint 0 is used for class-specific requests, as well as receiving data from
+ the host if no Interrupt OUT endpoint has been defined. In addition, the host
+ can also explicitly request or send report data through this endpoint.
+
+ The Interrupt IN and OUT pipes are used for sending asynchronous data to the
+ host, and to receive low-latency information.
+
+ \image HIDClassArch.png "HID Class Driver Architecture"
+
+ !!Class-Specific Descriptors
+ There are three class-specific descriptors defined in the }HID specification
+ 1.11}: the HID descriptor, the report descriptor and the physical descriptor.
+
+ !HID Descriptor
+ The HID descriptor gives information about the HID specification revision
+ used, the country for which a %device is localized, and lists the number of
+ class-specific descriptors, including their length and type.
+
+ HID Descriptor Format
+||Field||Size(bytes)||Description
+|bLength|1|Total length of the HID descriptor
+|bDescriptorType|1|HID descriptor type (21h)
+|bcdHID|2|HID specification release number in BCD format
+|bCountryCode|1|Code of the country for which the %device is located.\n
+ Should be 0 if the %device is not localized.
+|bNumDescriptors|1|Number of class-specific descriptors used by the %device.
+|bDescriptorType|1|Type of the first class-specific descriptor.
+|bDescriptorLength|1|Total length of the first class-specific descriptor.
+|[bDescriptorType]|1|Type of the second class-specific descriptor.
+|[bDescriptorLength]|1|Total length of the second class-specific descriptor.
+|...| |
+
+ There is always at least one Report descriptor for an HID %device, so the
+ corresponding fields must be present in the HID descriptor. If other
+ descriptors are defined, they must also be described here.
+
+ !Report Descriptor
+ A HID %device must have at least one #Report descriptor#. It defines the type
+ of data manipulated by the %device, which is referred to as report. When the
+ %device wants to notify that the cursor has moved, for example, it sends the
+ corresponding report in the format previously defined in the Report
+ descriptor.
+
+ This descriptor is quite different from others, as it does not have a fixed
+ table of values. Instead, it is made up of a variable number of items, which
+ collectively identify the information that a host can expect from or send to
+ the %device.
+
+ There are five categories of items:
+ - #Input# items, which define the format and type of the data sent by the
+ %device.
+ - #Output# items, which define the format and type of the data expected by
+ the %device
+ - #Feature# items, which define data sent to or received from the %device,
+ and not intended for the end user, such as configuration parameters.
+- #Collection# items, which identify a set of data as related to the same
+ group.
+- #End Collection# items, which close other Collection items.
+
+ Usually, a Report descriptor defines only one use (report) for a %device, e.g.,
+ a mouse. However, it is possible to declare several reports to perform
+ different tasks, e.g., mouse & keyboard. This is done by assigning a different
+ #Report ID# to each report; this makes it possible for the %device to send
+ both reports through the same Interrupt endpoint, while still permitting the
+ host to correctly identify the data. Using only a single endpoint for several
+ functionalities is very powerful, as the remaining ones can then be used by
+ other interfaces (CDC, MSD, etc.) for an even more versatile %device.
+
+ More details about Report descriptors will be given in the implementation
+ examples. For more information about the possible items, tags and values,
+ please refer to the }HID specification 1.11.}
+
+ !Physical Descriptor
+ A #Physical descriptor# can be used to give information about which human body
+ part is used to activate a particular control. While this is a useless piece
+ of information for most devices, it can be relevant for complex devices which
+ provide many similar controls. In such a case, a Physical descriptor allows an
+ application to assign its functionalities more appropriately; for example, a
+ game controller often has a large number of buttons, with some of them more
+ accessible than the others. Those buttons would be assigned the most useful
+ actions.
+
+ Since physical descriptors are not used very often, and are not useful in the
+ case studies described in this document, they will not be discussed further.
+
+ !!Class-specific Requests
+ ...
+
+ !GetDescriptor
+ While #GET_DESCRIPTOR# is a standard request (defined in the }USB
+ specification 2.0}), new descriptor type values have been added for the HID
+ class. They make it possible for the host to request the HID descriptor,
+ Report descriptor and Physical descriptors used by the %device.
+
+ When requesting a HID-specific descriptor, the }wIndex} field of the request
+ must be set to the HID interface number. For standard requests, this field is
+ either set to 0 or, for String descriptors, to the index of the language ID
+ used.
+
+ !SetDescriptor
+ Similarly, #SET_DESCRIPTOR# is a standard request with added HID-specific
+ values. It is used by the host to change the HID descriptors of a %device.
+ This is an optional request, and has few practical uses.
+
+ !GetReport
+ The host can explicitly ask the %device for a report by using the #GET_REPORT#
+ request. However, it should be used primarily to get the state of feature
+ items and absolute values at initialization time, not for consistent %device
+ polling.
+
+ The requested report is identified either by its Report ID (if they are used),
+ and/or by its type (Input, Output or Feature).
+
+ Please note that a GET_REPORT request is different from a GET_DESCRIPTOR
+ request for the Report descriptor. The latter returns the whole Report
+ descriptor, i.e., all the items declared. The former returns the data defined
+ by this descriptor.
+
+ !SetReport
+ #SET_REPORT# is similar to GET_REPORT, except this request is used for
+ changing the state of a report, instead of simply retrieving it.
+
+ For an Input report, this request can either be considered meaningless, or can
+ be used to reset the current status of a control. For example, it could be
+ used to calibrate the neutral position of a joystick.
+
+ !SetIdle
+ This request is used to specify the minimum amount of time, called #Idle
+ rate#, that a %device must wait before transmitting a report if its state has
+ not changed. This means the %device must NAK all polls on its Interrupt IN
+ endpoint until the report state changes, or the guarding period expires.
+
+ The SET_IDLE command can either be issued for a particular duration, or for an
+ undefined period of time. The upper byte of the wValue field is used to
+ specify this duration. In addition, if the %device generates multiple reports,
+ the Report ID of the target report to affect can be specified in the lower
+ byte.
+
+ In practice, this request is often used with a keyboard to put a small delay
+ before a key is repeated continuously. For a mouse, it must be set to 0,
+ meaning that the %device should never report an unchanged state.
+
+ !GetIdle
+ The GET_IDLE request is issued by the host to retrieve the current Idle rate
+ of the %device. A particular Report can be specified with its Report ID.
+
+ !GetProtocol
+ This request returns the protocol currently used by the %device. This can
+ either be the Report protocol (}wValue} set to 0) or the Boot protocol
+ (}wValue} set to 1). Since a %device supporting the Boot protocol can operate
+ differently depending on which mode it is in, the host system can retrieve or
+ change this mode with the GET_PROTOCOL and SET_PROTOCOL requests.
+
+ This request is only need for devices supporting the Boot protocol.
+
+ !SetProtocol
+ Whenever an HID %device starts up, it should use the Report protocol by
+ default. However, the host driver shall still use the SET_PROTOCOL
+ request to specify if the %device should use the Report protocol or the
+ Boot protocol.
+
+ !!!Host Drivers
+ Most operating systems provide a generic HID driver which automatically
+ handles standard devices, such as keyboard, mice and joystick. In addition,
+ the driver can also be used by the application to easily access custom and
+ vendor-specific devices.
+
+*/
\ No newline at end of file |