From 044ad7c3987460ede48ff27afd6bdb0ca05a0432 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 4 Jul 2011 20:52:54 +0200 Subject: import at91lib from at91lib_20100901_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 --- usb/device/hid-keyboard/HIDClassArch.png | Bin 0 -> 3495 bytes usb/device/hid-keyboard/HIDDKeyboardCallbacks.h | 57 ++ .../HIDDKeyboardCallbacks_LedsChanged.c | 59 ++ usb/device/hid-keyboard/HIDDKeyboardDriver.c | 477 +++++++++++++ usb/device/hid-keyboard/HIDDKeyboardDriver.h | 75 ++ .../hid-keyboard/HIDDKeyboardDriverDescriptors.c | 420 +++++++++++ .../hid-keyboard/HIDDKeyboardDriverDescriptors.h | 114 +++ usb/device/hid-keyboard/HIDDKeyboardInputReport.c | 164 +++++ usb/device/hid-keyboard/HIDDKeyboardInputReport.h | 149 ++++ usb/device/hid-keyboard/HIDDKeyboardOutputReport.c | 94 +++ usb/device/hid-keyboard/HIDDKeyboardOutputReport.h | 96 +++ usb/device/hid-keyboard/hid-keyboard.dir | 787 +++++++++++++++++++++ 12 files changed, 2492 insertions(+) create mode 100644 usb/device/hid-keyboard/HIDClassArch.png create mode 100644 usb/device/hid-keyboard/HIDDKeyboardCallbacks.h create mode 100644 usb/device/hid-keyboard/HIDDKeyboardCallbacks_LedsChanged.c create mode 100644 usb/device/hid-keyboard/HIDDKeyboardDriver.c create mode 100644 usb/device/hid-keyboard/HIDDKeyboardDriver.h create mode 100644 usb/device/hid-keyboard/HIDDKeyboardDriverDescriptors.c create mode 100644 usb/device/hid-keyboard/HIDDKeyboardDriverDescriptors.h create mode 100644 usb/device/hid-keyboard/HIDDKeyboardInputReport.c create mode 100644 usb/device/hid-keyboard/HIDDKeyboardInputReport.h create mode 100644 usb/device/hid-keyboard/HIDDKeyboardOutputReport.c create mode 100644 usb/device/hid-keyboard/HIDDKeyboardOutputReport.h create mode 100644 usb/device/hid-keyboard/hid-keyboard.dir (limited to 'usb/device/hid-keyboard') diff --git a/usb/device/hid-keyboard/HIDClassArch.png b/usb/device/hid-keyboard/HIDClassArch.png new file mode 100644 index 0000000..6d09580 Binary files /dev/null and b/usb/device/hid-keyboard/HIDClassArch.png differ 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 + +//------------------------------------------------------------------------------ +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//------------------------------------------------------------------------------ +// 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 + +//------------------------------------------------------------------------------ +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//------------------------------------------------------------------------------ +// 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 +#include + +//------------------------------------------------------------------------------ +// 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 + +//------------------------------------------------------------------------------ +// 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" + - + Universal Serial Bus Revision 2.0 specification + (.zip file format, size 9.80 MB) + - + Device Class Definition for HID 1.11 + - + HID Usage Tables 1.12 + + !!!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" + - + Universal Serial Bus Revision 2.0 specification + (.zip file format, size 9.80 MB) + - + Device Class Definition for HID 1.11 + - + HID Usage Tables 1.12 + + + +*/ + +/** + \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 -- cgit v1.2.3