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-mouse/HIDDMouseDriver.c | 392 ++++++++++++++++ usb/device/hid-mouse/HIDDMouseDriver.h | 107 +++++ usb/device/hid-mouse/HIDDMouseDriverDescriptors.c | 385 +++++++++++++++ usb/device/hid-mouse/HIDDMouseDriverDescriptors.h | 86 ++++ usb/device/hid-mouse/HIDDMouseInputReport.c | 72 +++ usb/device/hid-mouse/HIDDMouseInputReport.h | 93 ++++ usb/device/hid-mouse/hid-mouse.dir | 544 ++++++++++++++++++++++ 7 files changed, 1679 insertions(+) create mode 100644 usb/device/hid-mouse/HIDDMouseDriver.c create mode 100644 usb/device/hid-mouse/HIDDMouseDriver.h create mode 100644 usb/device/hid-mouse/HIDDMouseDriverDescriptors.c create mode 100644 usb/device/hid-mouse/HIDDMouseDriverDescriptors.h create mode 100644 usb/device/hid-mouse/HIDDMouseInputReport.c create mode 100644 usb/device/hid-mouse/HIDDMouseInputReport.h create mode 100644 usb/device/hid-mouse/hid-mouse.dir (limited to 'usb/device/hid-mouse') diff --git a/usb/device/hid-mouse/HIDDMouseDriver.c b/usb/device/hid-mouse/HIDDMouseDriver.c new file mode 100644 index 0000000..dc2378c --- /dev/null +++ b/usb/device/hid-mouse/HIDDMouseDriver.c @@ -0,0 +1,392 @@ +/* ---------------------------------------------------------------------------- + * 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 "HIDDMouseDriver.h" +#include "HIDDMouseDriverDescriptors.h" +#include "HIDDMouseInputReport.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//------------------------------------------------------------------------------ +// Internal Defines +//------------------------------------------------------------------------------ + +/// Tag bit (Always 1) +#define HIDDMouse_TAG (1 << 3) + +/// Xsign bit +#define HIDDMouse_Xsign (1 << 4) + +/// Ysign bit +#define HIDDMouse_Ysign (1 << 5) + + +//------------------------------------------------------------------------------ +// 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; + /// + unsigned char inputProtocol; + /// Input report instance. + HIDDMouseInputReport inputReport; + +} HIDDMouseDriver; + +//------------------------------------------------------------------------------ +// Internal variables +//------------------------------------------------------------------------------ + +/// Static instance of the HID mouse device driver. +static HIDDMouseDriver hiddMouseDriver; + +//------------------------------------------------------------------------------ +// 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 HIDDMouseDriver_GetDescriptor(unsigned char type, + unsigned char length) +{ + const USBConfigurationDescriptor *pConfiguration; + HIDDescriptor *hidDescriptors[2]; + + switch (type) { + + case HIDGenericDescriptor_REPORT: + TRACE_INFO("Report "); + + // Adjust length and send report descriptor + if (length > HIDDMouseDriverDescriptors_REPORTSIZE) { + + length = HIDDMouseDriverDescriptors_REPORTSIZE; + } + USBD_Write(0, &hiddReportDescriptor, length, 0, 0); + break; + + case HIDGenericDescriptor_HID: + TRACE_INFO("HID "); + + // Configuration descriptor is different depending on configuration + if (USBD_IsHighSpeed()) { + + pConfiguration = + hiddMouseDriver.usbdDriver.pDescriptors->pHsConfiguration; + } + else { + + pConfiguration = + hiddMouseDriver.usbdDriver.pDescriptors->pFsConfiguration; + } + + // Parse the device configuration to get the HID descriptor + USBConfigurationDescriptor_Parse(pConfiguration, 0, 0, + (USBGenericDescriptor **) &hidDescriptors[0]); + + // 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 HIDDMouseDriver_GetIdle() +{ + TRACE_INFO("gIdle "); + + USBD_Write(0, &(hiddMouseDriver.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 HIDDMouseDriver_SetIdle(unsigned char idleRate) +{ + TRACE_INFO("sIdle(%d) ", idleRate); + + hiddMouseDriver.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 HIDDMouseDriver_GetReport(unsigned char type, + unsigned short length) +{ + TRACE_INFO("gReport "); + + // Check report type + switch (type) { + + case HIDReportRequest_INPUT: + TRACE_INFO("In "); + + // Adjust size and send report + if (length > sizeof(HIDDMouseInputReport)) { + + length = sizeof(HIDDMouseInputReport); + } + USBD_Write(0, // Endpoint #0 + &(hiddMouseDriver.inputReport), + length, + 0, // No callback + 0); + break; + + default: + USBD_Stall(0); + } +} + +//------------------------------------------------------------------------------ +/// Retrieves the new value of a report from the host and saves it. +/// \param type Report type. +/// \param length Report length. +//------------------------------------------------------------------------------ +static void HIDDMouseDriver_SetReport(unsigned char type, + unsigned short length) +{ + TRACE_INFO("sReport "); + + // Check report type + switch (type) { + + case HIDReportRequest_INPUT: + // SET_REPORT requests on input reports are ignored + USBD_Stall(0); + break; + + default: + USBD_Stall(0); + } +} + +//------------------------------------------------------------------------------ +// Optional RequestReceived() callback re-implementation +//------------------------------------------------------------------------------ +#if !defined(NOAUTOCALLBACK) + +//------------------------------------------------------------------------------ +/// Callback function when new request receivce from host +/// \param request Pointer to the USBGenericRequest instance +//------------------------------------------------------------------------------ +void USBDCallbacks_RequestReceived(const USBGenericRequest *request) +{ + HIDDMouseDriver_RequestHandler(request); +} + +#endif + +//------------------------------------------------------------------------------ +// ConfigurationChanged() callback re-implementation +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Callback function when configureation changed +/// \param cfgnum New configuration number +//------------------------------------------------------------------------------ +void USBDDriverCallbacks_ConfigurationChanged(unsigned char cfgnum) +{ + if (cfgnum > 0) { + + } +} + +//------------------------------------------------------------------------------ +// Exported functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Initializes the HID Mouse %device driver. +//------------------------------------------------------------------------------ +void HIDDMouseDriver_Initialize(void) +{ + hiddMouseDriver.inputReportIdleRate = 0; + HIDDMouseInputReport_Initialize(&(hiddMouseDriver.inputReport)); + USBDDriver_Initialize(&(hiddMouseDriver.usbdDriver), + &hiddMouseDriverDescriptors, + 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 HIDDMouseDriver_RequestHandler(const USBGenericRequest *request) +{ + TRACE_INFO("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 (!HIDDMouseDriver_GetDescriptor( + USBGetDescriptorRequest_GetDescriptorType(request), + USBGenericRequest_GetLength(request))) { + + USBDDriver_RequestHandler(&(hiddMouseDriver.usbdDriver), + request); + } + break; + + default: + USBDDriver_RequestHandler(&(hiddMouseDriver.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: + HIDDMouseDriver_GetIdle(); + break; + + case HIDGenericRequest_SETIDLE: + HIDDMouseDriver_SetIdle(HIDIdleRequest_GetIdleRate(request)); + break; + + case HIDGenericRequest_GETREPORT: + HIDDMouseDriver_GetReport( + HIDReportRequest_GetReportType(request), + USBGenericRequest_GetLength(request)); + break; + + case HIDGenericRequest_SETREPORT: + HIDDMouseDriver_SetReport( + HIDReportRequest_GetReportType(request), + USBGenericRequest_GetLength(request)); + break; + + case HIDGenericRequest_GETPROTOCOL: + USBD_Write(0, &hiddMouseDriver.inputProtocol, 1, 0, 0); + break; + + case HIDGenericRequest_SETPROTOCOL: + hiddMouseDriver.inputProtocol = request->wValue; + USBD_Write(0, 0, 0, 0, 0); + break; + + default: + TRACE_WARNING( + "HIDDMouseDriver_RequestHandler: Unknown request 0x%02X\n\r", + USBGenericRequest_GetRequest(request)); + USBD_Stall(0); + } + } + else { + + // Vendor request ? + USBD_Stall(0); + } +} + +//------------------------------------------------------------------------------ +/// Update the Mouse button status and location changes via input report +/// to host +/// \param bmButtons Bit map of the button status +/// \param deltaX Movment on X direction +/// \param deltaY Movment on Y direction +//------------------------------------------------------------------------------ +unsigned char HIDDMouseDriver_ChangePoints(unsigned char bmButtons, + signed char deltaX, + signed char deltaY) +{ + hiddMouseDriver.inputReport.bmButtons = (bmButtons & 0x07) + | HIDDMouse_TAG; + hiddMouseDriver.inputReport.bX = deltaX; + hiddMouseDriver.inputReport.bY = deltaY; + // Send input report through the interrupt IN endpoint + return USBD_Write(HIDDMouseDriverDescriptors_INTERRUPTIN, + &(hiddMouseDriver.inputReport), + sizeof(HIDDMouseInputReport), + 0, + 0); +} + +//------------------------------------------------------------------------------ +/// Starts a remote wake-up sequence if the host has explicitely enabled it +/// by sending the appropriate SET_FEATURE request. +//------------------------------------------------------------------------------ +void HIDDMouseDriver_RemoteWakeUp(void) +{ + // Remote wake-up has been enabled + if (USBDDriver_IsRemoteWakeUpEnabled(&(hiddMouseDriver.usbdDriver))) { + + USBD_RemoteWakeUp(); + } +} + diff --git a/usb/device/hid-mouse/HIDDMouseDriver.h b/usb/device/hid-mouse/HIDDMouseDriver.h new file mode 100644 index 0000000..94dac3a --- /dev/null +++ b/usb/device/hid-mouse/HIDDMouseDriver.h @@ -0,0 +1,107 @@ +/* ---------------------------------------------------------------------------- + * 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 + + !!!Purpose + + Definition of methods for using a HID mouse device driver. + + !!!Usage + + -# Re-implement the USBDCallbacks_RequestReceived callback to forward + requests to HIDDMouseDriver_RequestHandler. This is done + automatically unless the NOAUTOCALLBACK symbol is defined during + compilation. + -# Initialize the driver using HIDDMouseDriver_Initialize. The + USB driver is automatically initialized by this method. + -# Call the HIDDMouseDriver_ChangePoints method when one or more + keys are pressed/released. +*/ + +#ifndef HIDDKEYBOARDDRIVER_H +#define HIDDKEYBOARDDRIVER_H + +//------------------------------------------------------------------------------ +// Headers +//------------------------------------------------------------------------------ + +#include + +//------------------------------------------------------------------------------ +// Definitions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// \page "HID Mouse Button bitmaps" +/// ... +/// !Bits +/// - HIDDMouse_LEFT_BUTTON +/// - HIDDMouse_RIGHT_BUTTON +/// - HIDDMouse_MIDDLE_BUTTON + +/// Left mouse button +#define HIDDMouse_LEFT_BUTTON (1 << 0) + +/// Right mouse button +#define HIDDMouse_RIGHT_BUTTON (1 << 1) + +/// Middle mouse button +#define HIDDMouse_MIDDLE_BUTTON (1 << 2) + +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +// Exported functions +//------------------------------------------------------------------------------ +/* + Function: HIDDMouseDriver_Initialize + Initializes the HID keyboard device driver. +*/ +extern void HIDDMouseDriver_Initialize(void); + +/* + Function: HIDDMouseDriver_RequestHandler + Handles HID-specific SETUP request sent by the host. + + Parameters: + request - Pointer to a USBGenericRequest instance. +*/ +extern void HIDDMouseDriver_RequestHandler(const USBGenericRequest *request); + +extern unsigned char HIDDMouseDriver_ChangePoints(unsigned char bmButtons, + signed char deltaX, + signed char deltaY); + +extern void HIDDMouseDriver_RemoteWakeUp(void); + +#endif //#ifndef HIDDKEYBOARDDRIVER_H + diff --git a/usb/device/hid-mouse/HIDDMouseDriverDescriptors.c b/usb/device/hid-mouse/HIDDMouseDriverDescriptors.c new file mode 100644 index 0000000..6a66d83 --- /dev/null +++ b/usb/device/hid-mouse/HIDDMouseDriverDescriptors.c @@ -0,0 +1,385 @@ +/* ---------------------------------------------------------------------------- + * 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: HIDDMouseDriverDescriptors + + About: Purpose + Declaration of the descriptors used by the HID device keyboard driver. +*/ + +//------------------------------------------------------------------------------ +// Headers +//------------------------------------------------------------------------------ + +#include "HIDDMouseDriverDescriptors.h" +#include "HIDDMouseInputReport.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//------------------------------------------------------------------------------ +// Definitions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// \page "HID Mouse Device Descriptor IDs" +/// ... +/// +/// !IDs +/// - HIDDMouseDriverDescriptors_PRODUCTID +/// - HIDDMouseDriverDescriptors_VENDORID +/// - HIDDMouseDriverDescriptors_RELEASE + +/// Device product ID. +#define HIDDMouseDriverDescriptors_PRODUCTID 0x6200 +/// Device vendor ID. +#define HIDDMouseDriverDescriptors_VENDORID 0x03EB +/// Device release number. +#define HIDDMouseDriverDescriptors_RELEASE 0x0100 +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Internal types +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// List of descriptors that make up the configuration descriptors of a +/// %device using the HID Mouse driver. +//------------------------------------------------------------------------------ +typedef struct { + + /// Configuration descriptor. + USBConfigurationDescriptor configuration; + /// Interface descriptor. + USBInterfaceDescriptor interface; + /// HID descriptor. + HIDDescriptor hid; + /// Interrupt IN endpoint descriptor. + USBEndpointDescriptor interruptIn; + +} __attribute__ ((packed)) HIDDMouseDriverConfigurationDescriptors; + +//------------------------------------------------------------------------------ +// 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), + HIDDMouseDriverDescriptors_VENDORID, + HIDDMouseDriverDescriptors_PRODUCTID, + HIDDMouseDriverDescriptors_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 HIDDMouseDriverConfigurationDescriptors configurationDescriptors = { + + // Configuration descriptor + { + sizeof(USBConfigurationDescriptor), + USBGenericDescriptor_CONFIGURATION, + sizeof(HIDDMouseDriverConfigurationDescriptors), + 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 + 1, // One endpoints used + HIDInterfaceDescriptor_CLASS, + HIDInterfaceDescriptor_SUBCLASS_NONE, + HIDInterfaceDescriptor_PROTOCOL_MOUSE, + 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, + HIDDMouseDriverDescriptors_REPORTSIZE + }, + // Interrupt IN endpoint descriptor + { + sizeof(USBEndpointDescriptor), + USBGenericDescriptor_ENDPOINT, + USBEndpointDescriptor_ADDRESS( + USBEndpointDescriptor_IN, + HIDDMouseDriverDescriptors_INTERRUPTIN), + USBEndpointDescriptor_INTERRUPT, + sizeof(HIDDMouseInputReport), + HIDDMouseDriverDescriptors_INTERRUPTIN_POLLING + } +}; + +#if defined (CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS) +/// Other-speed configuration descriptor. +static const HIDDMouseDriverConfigurationDescriptors otherSpeedDescriptors = { + + // Configuration descriptor + { + sizeof(USBConfigurationDescriptor), + USBGenericDescriptor_OTHERSPEEDCONFIGURATION, + sizeof(HIDDMouseDriverConfigurationDescriptors), + 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_MOUSE, + 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, + HIDDMouseDriverDescriptors_REPORTSIZE + }, + // Interrupt IN endpoint descriptor + { + sizeof(USBEndpointDescriptor), + USBGenericDescriptor_ENDPOINT, + USBEndpointDescriptor_ADDRESS( + USBEndpointDescriptor_IN, + HIDDMouseDriverDescriptors_INTERRUPTIN), + USBEndpointDescriptor_INTERRUPT, + sizeof(HIDDMouseInputReport), + HIDDMouseDriverDescriptors_INTERRUPTIN_POLLING + } +}; +#endif + +/* + Variables: String descriptors + languageIdDescriptor - Language ID string descriptor. + manufacturerDescriptor - Manufacturer name. + productDescriptor - Product name. + serialNumberDescriptor - Product serial number. + stringDescriptors - Array of pointers to string descriptors. +*/ +static const unsigned char languageIdDescriptor[] = { + + USBStringDescriptor_LENGTH(1), + USBGenericDescriptor_STRING, + USBStringDescriptor_ENGLISH_US +}; + +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') +}; + +static const unsigned char productDescriptor[] = { + + USBStringDescriptor_LENGTH(19), + 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('M'), + USBStringDescriptor_UNICODE('O'), + USBStringDescriptor_UNICODE('U'), + USBStringDescriptor_UNICODE('S'), + USBStringDescriptor_UNICODE('E'), +}; + +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') +}; + +static const unsigned char *stringDescriptors[] = { + + languageIdDescriptor, + manufacturerDescriptor, + productDescriptor, + serialNumberDescriptor +}; + +//------------------------------------------------------------------------------ +// Exported variables +//------------------------------------------------------------------------------ + +/// List of descriptors used by the HID keyboard driver. +USBDDriverDescriptors hiddMouseDriverDescriptors = { + + &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[] = { + + // Global Usage Page + HIDReport_GLOBAL_USAGEPAGE + 1, HIDGenericDesktop_PAGEID, + // Collection: Application + HIDReport_LOCAL_USAGE + 1, HIDGenericDesktop_MOUSE, + HIDReport_COLLECTION + 1, HIDReport_COLLECTION_APPLICATION, + // Physical collection: Pointer + HIDReport_LOCAL_USAGE + 1, HIDGenericDesktop_POINTER, + HIDReport_COLLECTION + 1, HIDReport_COLLECTION_PHYSICAL, + + // Input report: buttons + HIDReport_GLOBAL_USAGEPAGE + 1, HIDButton_PAGEID, + HIDReport_GLOBAL_REPORTCOUNT + 1, 3, + HIDReport_GLOBAL_REPORTSIZE + 1, 1, + HIDReport_LOCAL_USAGEMINIMUM + 1, 1, + HIDReport_LOCAL_USAGEMAXIMUM + 1, 3, + HIDReport_GLOBAL_LOGICALMINIMUM + 1, 0, + HIDReport_GLOBAL_LOGICALMAXIMUM + 1, 1, + HIDReport_INPUT + 1, HIDReport_VARIABLE, // 3 button bits + + // Input report: padding + HIDReport_GLOBAL_REPORTCOUNT + 1, 1, + HIDReport_GLOBAL_REPORTSIZE + 1, 5, + HIDReport_INPUT + 1, HIDReport_CONSTANT, // 5 bit padding + + // Input report: pointer + HIDReport_GLOBAL_USAGEPAGE + 1, HIDGenericDesktop_PAGEID, + HIDReport_GLOBAL_REPORTSIZE + 1, 8, + HIDReport_GLOBAL_REPORTCOUNT + 1, 2, + HIDReport_LOCAL_USAGE + 1, HIDGenericDesktop_X, + HIDReport_LOCAL_USAGE + 1, HIDGenericDesktop_Y, + HIDReport_GLOBAL_LOGICALMINIMUM + 1, (unsigned char) -127, + HIDReport_GLOBAL_LOGICALMAXIMUM + 1, 127, + HIDReport_INPUT + 1, HIDReport_VARIABLE | HIDReport_RELATIVE, + + HIDReport_ENDCOLLECTION, + HIDReport_ENDCOLLECTION +}; + diff --git a/usb/device/hid-mouse/HIDDMouseDriverDescriptors.h b/usb/device/hid-mouse/HIDDMouseDriverDescriptors.h new file mode 100644 index 0000000..4f27dec --- /dev/null +++ b/usb/device/hid-mouse/HIDDMouseDriverDescriptors.h @@ -0,0 +1,86 @@ +/* ---------------------------------------------------------------------------- + * 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 + + !!!Purpose + + Definitions of the descriptors required by the HID device keyboard + driver. + + !!!Usage + -# Use the hiddMouseDriverDescriptors 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 + +//------------------------------------------------------------------------------ +// Definitions +//------------------------------------------------------------------------------ +/* + Constants: Endpoints + HIDDMouseDriverDescriptors_INTERRUPTIN - Interrupt IN endpoint number. + HIDDMouseDriverDescriptors_INTERRUPTIN_POLLING - Interrupt IN endpoint + polling rate (in milliseconds). +*/ +#define HIDDMouseDriverDescriptors_INTERRUPTIN 1 +#define HIDDMouseDriverDescriptors_INTERRUPTIN_POLLING 10 + +/* + Constants: Report descriptor + HIDDMouseDriverDescriptors_REPORTSIZE - Size of the report descriptor + in bytes. +*/ +#define HIDDMouseDriverDescriptors_REPORTSIZE 50 + +//------------------------------------------------------------------------------ +// Exported variables +//------------------------------------------------------------------------------ +/* + Variables: HID keyboard driver descriptors + hiddMouseDriverDescriptors - List of descriptors used by the HID + keyboard driver. + hiddReportDescriptor - Report descriptor used by the driver. +*/ +extern USBDDriverDescriptors hiddMouseDriverDescriptors; +extern const unsigned char hiddReportDescriptor[]; + +#endif //#ifndef HIDDKEYBOARDDRIVERDESCRIPTORS_H + diff --git a/usb/device/hid-mouse/HIDDMouseInputReport.c b/usb/device/hid-mouse/HIDDMouseInputReport.c new file mode 100644 index 0000000..1c1c979 --- /dev/null +++ b/usb/device/hid-mouse/HIDDMouseInputReport.c @@ -0,0 +1,72 @@ +/* ---------------------------------------------------------------------------- + * 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: HIDDMouseInputReport implementation + + About: Purpose + Implementation of the HIDDMouseInputReport class. +*/ + +//------------------------------------------------------------------------------ +// Headers +//------------------------------------------------------------------------------ + +#include "HIDDMouseInputReport.h" +#include "HIDDMouseDriverDescriptors.h" +#include + +//------------------------------------------------------------------------------ +// Exported functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Initializes a mouse input report instance. +/// \param report Pointer to a HIDDMouseInputReport instance. +//------------------------------------------------------------------------------ +void HIDDMouseInputReport_Initialize(HIDDMouseInputReport *report) +{ + report->bmButtons = 0; + report->bX = 0; + report->bY = 0; +} + +/* +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +void HIDDMouseInputReport_UpdateButtons(HIDDMouseInputReport *report) +{ +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +void HIDDMouseInputReport_UpdateAxis(HIDDMouseInputReport *report) +{ +} +*/ diff --git a/usb/device/hid-mouse/HIDDMouseInputReport.h b/usb/device/hid-mouse/HIDDMouseInputReport.h new file mode 100644 index 0000000..ca074fd --- /dev/null +++ b/usb/device/hid-mouse/HIDDMouseInputReport.h @@ -0,0 +1,93 @@ +/* ---------------------------------------------------------------------------- + * 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 + + !!!Purpose + + Class for manipulating HID Mouse input reports. + + !!!Usage + + -# Initialize a newly created input report with + HIDDMouseInputReport_Initialize +*/ + +#ifndef HIDDKEYBOARDINPUTREPORT_H +#define HIDDKEYBOARDINPUTREPORT_H + +//------------------------------------------------------------------------------ +// Definitions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// \page "HID Mouse Keys" + +/// Mouse Left Click Button +#define HIDDMouseInputReport_LEFT_BUTTON (1 << 0) +/// Mouse Right Click Button +#define HIDDMouseInputReport_RIGHT_BUTTON (1 << 1) +/// Mouse Middle Button +#define HIDDMouseInputReport_MIDDLE_BUTTON (1 << 2) +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Types +//------------------------------------------------------------------------------ + +#ifdef __ICCARM__ // IAR +#pragma pack(1) // IAR +#define __attribute__(...) // IAR +#endif // IAR + +//------------------------------------------------------------------------------ +/// HID input report structure used by the Mouse driver to notify the +/// host of pressed keys. +//------------------------------------------------------------------------------ +typedef struct { + + unsigned char bmButtons; /// Bitmap state of three mouse buttons. + signed char bX; /// Pointer displacement along the X axis. + signed char bY; /// Pointer displacement along the Y axis. + +} __attribute__ ((packed)) HIDDMouseInputReport; // GCC + +#ifdef __ICCARM__ // IAR +#pragma pack() // IAR +#endif // IAR + +//------------------------------------------------------------------------------ +// Exported functions +//------------------------------------------------------------------------------ + +extern void HIDDMouseInputReport_Initialize(HIDDMouseInputReport *report); + +#endif //#ifndef HIDDKEYBOARDINPUTREPORT_H + diff --git a/usb/device/hid-mouse/hid-mouse.dir b/usb/device/hid-mouse/hid-mouse.dir new file mode 100644 index 0000000..9dd733b --- /dev/null +++ b/usb/device/hid-mouse/hid-mouse.dir @@ -0,0 +1,544 @@ +/* ---------------------------------------------------------------------------- + * 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 Mouse driver, to implement an USB Mouse %device. +/// +/// !!!Contents +/// +/// There are three things for the implement of the USB HID Mouse 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 Mouse device's descriptors that should be passed to +/// the USBDDriver instance on initialization, so that the host can +/// recognize the %device as a USB Mouse %device. +/// - Implement methods to update the Mouse keys status, so that host can +/// get it through USB. +/// +/// For more information about what a particular group contains, please refer to +/// "USB HID Mouse". +//------------------------------------------------------------------------------ + +/** + \page "USB HID Mouse" + This page describes how to use the "AT91 USB device framework" to produce a USB + HID Mouse driver, which appears as a USB Mouse 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), + HIDDMouseDriverDescriptors_VENDORID, + HIDDMouseDriverDescriptors_PRODUCTID, + HIDDMouseDriverDescriptors_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(HIDDMouseDriverConfigurationDescriptors), + 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 + HIDDMouseDriverConfigurationDescriptors structure has been declared for + that. + + !!HID Class Interface Descriptor + Since a Mouse %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 Mouse %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 Mouse 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 Mouse, there will only be one HID class + descriptor specified here. + + For a Mouse, 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, + HIDDMouseDriverDescriptors_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_Mouse, +\endcode + + As in the mouse example, the }Generic Desktop} page is used. This time, the + specific usage is the }Mouse} 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, + HIDDMouseDriverDescriptors_FIRSTMODIFIERKEY, + HIDReport_LOCAL_USAGEMAXIMUM + 1, + HIDDMouseDriverDescriptors_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, + HIDDMouseDriverDescriptors_FIRSTSTANDARDKEY, + HIDReport_GLOBAL_LOGICALMAXIMUM + 1, + HIDDMouseDriverDescriptors_LASTSTANDARDKEY, + HIDReport_GLOBAL_USAGEPAGE + 1, HIDKeypad_PAGEID, + HIDReport_LOCAL_USAGEMINIMUM + 1, + HIDDMouseDriverDescriptors_FIRSTSTANDARDKEY, + HIDReport_LOCAL_USAGEMAXIMUM + 1, + HIDDMouseDriverDescriptors_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[HIDDMouseInputReport_MAXKEYPRESSES]; + +} __attribute__ ((packed)) HIDDMouseInputReport; // 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)) HIDDMouseOutputReport; // GCC +\endcode + + An instance of each one of the reports is stored in a HIDDMouseDriver + structure, which holds the standard class driver and HID Mouse-specific + data. + + !!Physical Descriptor + A Physical descriptor is useless for a Mouse %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, + HIDDMouseDriverDescriptors_INTERRUPTIN), + USBEndpointDescriptor_INTERRUPT, + sizeof(HIDDMouseInputReport), + HIDDMouseDriverDescriptors_INTERRUPTIN_POLLING +}, +// Interrupt OUT endpoint descriptor +{ + sizeof(USBEndpointDescriptor), + USBGenericDescriptor_ENDPOINT, + USBEndpointDescriptor_ADDRESS( + USBEndpointDescriptor_OUT, + HIDDMouseDriverDescriptors_INTERRUPTOUT), + USBEndpointDescriptor_INTERRUPT, + sizeof(HIDDMouseOutputReport), + HIDDMouseDriverDescriptors_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 (!HIDDMouseDriver_GetDescriptor( + USBGetDescriptorRequest_GetDescriptorType(request), + USBGenericRequest_GetLength(request))) { + + USBDDriver_RequestHandler(&(hiddMouseDriver.usbdDriver), + request); + } + break; + + default: + USBDDriver_RequestHandler(&(hiddMouseDriver.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 Mouse 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(HIDDMouseInputReport)) { + + length = sizeof(HIDDMouseInputReport); + } + USBD_Write(0, // Endpoint #0 + &(hiddMouseDriver.inputReport), + length, + 0, // No callback + 0); + break; + + case HIDReportRequest_OUTPUT: + + // Adjust size and send report + if (length > sizeof(HIDDMouseOutputReport)) { + + length = sizeof(HIDDMouseOutputReport); + } + USBD_Write(0, // Endpoint #0 + &(hiddMouseDriver.outputReport), + length, + 0, // No callback + 0); + break; + + default: + USBD_Stall(0); + } +break; +\endcode + + !!SetReport + For an HID Mouse, 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 + Mouse; 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(HIDDMouseOutputReport)) { + + USBD_Stall(0); + } + else { + + USBD_Read(0, // Endpoint #0 + &(hiddMouseDriver.outputReport), + length, + (TransferCallback) HIDDMouseDriver_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 Mouse 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: +//----------------------------- + hiddMouseDriver.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, &(hiddMouseDriver.inputReportIdleRate), 1, 0, 0); +break; +\endcode + + !!GetProtocol, SetProtocol + This HID Mouse 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. + +*/ \ No newline at end of file -- cgit v1.2.3