SAMV71 Xplained Ultra Software Package 1.4

HIDDKeyboard.c

Go to the documentation of this file.
00001 /* ----------------------------------------------------------------------------
00002  *         ATMEL Microcontroller Software Support
00003  * ----------------------------------------------------------------------------
00004  * Copyright (c) 2008, Atmel Corporation
00005  *
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *
00011  * - Redistributions of source code must retain the above copyright notice,
00012  * this list of conditions and the disclaimer below.
00013  *
00014  * Atmel's name may not be used to endorse or promote products derived from
00015  * this software without specific prior written permission.
00016  *
00017  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
00020  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00022  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00023  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00024  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00025  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
00026  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  * ----------------------------------------------------------------------------
00028  */
00029 
00030 /** \file
00031  * \addtogroup usbd_hid_key
00032  *@{
00033  * Implement HID Keyboard Function For USB Device.
00034  */
00035 
00036 /*------------------------------------------------------------------------------
00037  *         Headers
00038  *------------------------------------------------------------------------------*/
00039 
00040 #include <HIDDKeyboard.h>
00041 #include <HIDDFunction.h>
00042 
00043 #include <USBLib_Trace.h>
00044 
00045 #include <USBRequests.h>
00046 #include <HIDDescriptors.h>
00047 #include <HIDRequests.h>
00048 #include <HIDReports.h>
00049 #include <HIDUsages.h>
00050 
00051 #include "USBD.h"
00052 #include <USBD_HAL.h>
00053 #include <USBDDriver.h>
00054 
00055 /*------------------------------------------------------------------------------
00056  *         Internal types
00057  *------------------------------------------------------------------------------*/
00058 
00059 /**
00060  * Extended struct for an HID Keyboard Input report, for transfer driver to
00061  * send reports.
00062  */
00063 typedef struct _KBDInputReport {
00064     /** Callback when report done */
00065     HIDDReportEventCallback fCallback;
00066     /** Callback arguments */
00067     void* pArg;
00068 
00069     /** Report size (ID + DATA) */
00070     uint16_t wMaxSize;
00071     /** Transfered size */
00072     uint16_t wTransferred;
00073     /** Report idle rate */
00074     uint8_t bIdleRate;
00075     /** Delay count for Idle */
00076     uint8_t bDelay;
00077     /** Report ID */
00078     uint8_t bID;
00079     /** Input Report Data Block */
00080     HIDDKeyboardInputReport sReport;
00081 } KBDInputReport;
00082 
00083 /**
00084  * Extended struct for an HID Keyboard Output report, for transfer driver to
00085  * polling reports.
00086  */
00087 typedef struct _KBDOutputReport {
00088     /** Callback when report done */
00089     HIDDReportEventCallback fCallback;
00090     /** Callback arguments */
00091     void* pArg;
00092 
00093     /** Report size (ID + DATA) */
00094     uint16_t wMaxSize;
00095     /** Transfered size */
00096     uint16_t wTransferred;
00097     /** Report idle rate */
00098     uint8_t bIdleRate;
00099     /** Delay count for Idle */
00100     uint8_t bDelay;
00101     /** Report ID */
00102     uint8_t bID;
00103     /** Output Report Data Block */
00104     HIDDKeyboardOutputReport sReport;
00105 } KBDOutputReport;
00106 
00107 /**
00108  *  Driver structure for an HID device implementing keyboard functionalities.
00109  */
00110 typedef struct _HIDDKeyboard {
00111 
00112     /** USB HID Functionn */
00113     HIDDFunction hidDrv;
00114     /** Input report list */
00115     HIDDReport *inputReports[1];
00116     /** Output report list */
00117     HIDDReport *outputReports[1];
00118 } HIDDKeyboard;
00119 
00120 /*------------------------------------------------------------------------------
00121  *         Internal variables
00122  *------------------------------------------------------------------------------*/
00123 
00124 /** HIDD Keyboard Input Report Instance */
00125 static KBDInputReport inputReport;
00126 
00127 /** HIDD Keyboard Output Report Instance */
00128 static KBDOutputReport outputReport;
00129 
00130 /** Static instance of the HIDD keyboard device driver. */
00131 static HIDDKeyboard hiddKeyboard;
00132 
00133 /** Report descriptor used by the driver. */
00134 const uint8_t hiddKeyboardReportDescriptor[] = {
00135 
00136     HIDReport_GLOBAL_USAGEPAGE + 1, HIDGenericDesktop_PAGEID,
00137     HIDReport_LOCAL_USAGE + 1, HIDGenericDesktop_KEYBOARD,
00138     HIDReport_COLLECTION + 1, HIDReport_COLLECTION_APPLICATION,
00139 
00140         /* Input report: modifier keys */
00141         HIDReport_GLOBAL_REPORTSIZE + 1, 1,
00142         HIDReport_GLOBAL_REPORTCOUNT + 1, 8,
00143         HIDReport_GLOBAL_USAGEPAGE + 1, HIDKeypad_PAGEID,
00144         HIDReport_LOCAL_USAGEMINIMUM + 1,
00145             HIDDKeyboardDescriptors_FIRSTMODIFIERKEY,
00146         HIDReport_LOCAL_USAGEMAXIMUM + 1,
00147             HIDDKeyboardDescriptors_LASTMODIFIERKEY,
00148         HIDReport_GLOBAL_LOGICALMINIMUM + 1, 0,
00149         HIDReport_GLOBAL_LOGICALMAXIMUM + 1, 1,
00150         HIDReport_INPUT + 1, HIDReport_VARIABLE,
00151 
00152         /* Input report: standard keys */
00153         HIDReport_GLOBAL_REPORTCOUNT + 1, 3,
00154         HIDReport_GLOBAL_REPORTSIZE + 1, 8,
00155         HIDReport_GLOBAL_LOGICALMINIMUM + 1,
00156             HIDDKeyboardDescriptors_FIRSTSTANDARDKEY,
00157         HIDReport_GLOBAL_LOGICALMAXIMUM + 1,
00158             HIDDKeyboardDescriptors_LASTSTANDARDKEY,
00159         HIDReport_GLOBAL_USAGEPAGE + 1, HIDKeypad_PAGEID,
00160         HIDReport_LOCAL_USAGEMINIMUM + 1,
00161             HIDDKeyboardDescriptors_FIRSTSTANDARDKEY,
00162         HIDReport_LOCAL_USAGEMAXIMUM + 1,
00163             HIDDKeyboardDescriptors_LASTSTANDARDKEY,
00164         HIDReport_INPUT + 1, 0 /* Data array */,
00165 
00166         /* Output report: LEDs */
00167         HIDReport_GLOBAL_REPORTCOUNT + 1, 3,
00168         HIDReport_GLOBAL_REPORTSIZE + 1, 1,
00169         HIDReport_GLOBAL_USAGEPAGE + 1, HIDLeds_PAGEID,
00170         HIDReport_GLOBAL_LOGICALMINIMUM + 1, 0,
00171         HIDReport_GLOBAL_LOGICALMAXIMUM + 1, 1,
00172         HIDReport_LOCAL_USAGEMINIMUM + 1, HIDLeds_NUMLOCK,
00173         HIDReport_LOCAL_USAGEMAXIMUM + 1, HIDLeds_SCROLLLOCK,
00174         HIDReport_OUTPUT + 1, HIDReport_VARIABLE,
00175 
00176         /* Output report: padding */
00177         HIDReport_GLOBAL_REPORTCOUNT + 1, 1,
00178         HIDReport_GLOBAL_REPORTSIZE + 1, 5,
00179         HIDReport_OUTPUT + 1, HIDReport_CONSTANT,
00180 
00181     HIDReport_ENDCOLLECTION
00182 };
00183 
00184 /*------------------------------------------------------------------------------
00185  *         Internal functions
00186  *------------------------------------------------------------------------------*/
00187 
00188 /**
00189  * Callback invoked when an output report has been received from the host.
00190  * Forward the new status of the LEDs to the user program via the
00191  * HIDDKeyboardCallbacks_LedsChanged callback.
00192  */
00193 static void HIDDKeyboard_ReportReceived(void)
00194 {
00195     HIDDKeyboardOutputReport *pOut = &outputReport.sReport;
00196 
00197     /* Trigger callback */
00198     if (HIDDKeyboardCallbacks_LedsChanged != NULL) {
00199         HIDDKeyboardCallbacks_LedsChanged(
00200             pOut->numLockStatus,
00201             pOut->capsLockStatus,
00202             pOut->scrollLockStatus);
00203     }
00204 }
00205 
00206 /*------------------------------------------------------------------------------
00207  *      Exported functions
00208  *------------------------------------------------------------------------------*/
00209 
00210 /**
00211  * Initializes the HID keyboard device driver SW.
00212  * (Init USBDDriver .., Init function driver .., Init USBD ...)
00213  * \param pUsbd        Pointer to USBDDriver instance.
00214  * \param bInterfaceNb Interface number for the function.
00215  */
00216 void HIDDKeyboard_Initialize(USBDDriver* pUsbd, uint8_t bInterfaceNb)
00217 {
00218     HIDDKeyboard *pKbd = &hiddKeyboard;
00219     HIDDFunction *pHidd = &pKbd->hidDrv;
00220 
00221     /* One input report */
00222     pKbd->inputReports[0] = (HIDDReport*)&inputReport;
00223     HIDDFunction_InitializeReport(pKbd->inputReports[0],
00224                                   sizeof(HIDDKeyboardInputReport),
00225                                   0,
00226                                   0, 0);
00227     /* One output report */
00228     pKbd->outputReports[0] = (HIDDReport*)&outputReport;
00229     HIDDFunction_InitializeReport(
00230         pKbd->outputReports[0],
00231         sizeof(HIDDKeyboardOutputReport),
00232         0,
00233         (HIDDReportEventCallback)HIDDKeyboard_ReportReceived, 0);
00234 
00235     /* Function initialize */
00236     HIDDFunction_Initialize(pHidd,
00237                             pUsbd, bInterfaceNb,
00238                             hiddKeyboardReportDescriptor,
00239                             pKbd->inputReports, 1,
00240                             pKbd->outputReports, 1);
00241 }
00242 
00243 /**
00244  * Configure function with expected descriptors and start functionality.
00245  * Usually invoked when device is configured.
00246  * \pDescriptors Pointer to the descriptors for function configure.
00247  * \wLength      Length of descriptors in number of bytes.
00248  */
00249 void HIDDKeyboard_ConfigureFunction(USBGenericDescriptor *pDescriptors,
00250                                     uint16_t wLength)
00251 {
00252     HIDDKeyboard *pKbd = &hiddKeyboard;
00253     HIDDFunction *pHidd = &pKbd->hidDrv;
00254     pDescriptors = pDescriptors; wLength = wLength;
00255     HIDDFunction_ParseInterface(pHidd,
00256                                 pDescriptors,
00257                                 wLength);
00258 
00259     /* Start receiving output reports */
00260     HIDDFunction_StartPollingOutputs(pHidd);
00261 }
00262 
00263 /**
00264  * Handles HID-specific SETUP request sent by the host.
00265  * \param request Pointer to a USBGenericRequest instance.
00266  * \return USBRC_SUCCESS if request is handled.
00267  */
00268 uint32_t HIDDKeyboard_RequestHandler(const USBGenericRequest *request)
00269 {
00270     HIDDKeyboard *pKbd = &hiddKeyboard;
00271     HIDDFunction *pHidd = &pKbd->hidDrv;
00272 
00273     TRACE_INFO_WP("Kbd ");
00274 
00275     /* Process HID requests */
00276     return HIDDFunction_RequestHandler(pHidd, request);
00277 }
00278 
00279 /**
00280  * Reports a change in which keys are currently pressed or release to the
00281  * host.
00282  *
00283  * \param pressedKeys Pointer to an array of key codes indicating keys that have
00284  *                    been pressed since the last call to
00285  *                    HIDDKeyboardDriver_ChangeKeys().
00286  * \param pressedKeysSize Number of key codes in the pressedKeys array.
00287  * \param releasedKeys Pointer to an array of key codes indicates keys that have
00288  *                     been released since the last call to
00289  *                     HIDDKeyboardDriver_ChangeKeys().
00290  * \param releasedKeysSize Number of key codes in the releasedKeys array.
00291  * \return USBD_STATUS_SUCCESS if the report has been sent to the host;
00292  *        otherwise an error code.
00293  */
00294 uint32_t HIDDKeyboard_ChangeKeys(uint8_t *pressedKeys,
00295                                  uint8_t pressedKeysSize,
00296                                  uint8_t *releasedKeys,
00297                                  uint8_t releasedKeysSize)
00298 {
00299     HIDDKeyboard *pKbd = &hiddKeyboard;
00300     HIDDFunction *pHidd = &pKbd->hidDrv;
00301     HIDDKeyboardInputReport *pReport =
00302         (HIDDKeyboardInputReport *)pKbd->inputReports[0]->bData;
00303 
00304     /* Press keys */
00305     while (pressedKeysSize > 0) {
00306 
00307         /* Check if this is a standard or modifier key */
00308         if (HIDKeypad_IsModifierKey(*pressedKeys)) {
00309 
00310             /* Set the corresponding bit in the input report */
00311             HIDDKeyboardInputReport_PressModifierKey(
00312                 pReport,
00313                 *pressedKeys);
00314         }
00315         else {
00316 
00317             HIDDKeyboardInputReport_PressStandardKey(
00318                 pReport,
00319                 *pressedKeys);
00320         }
00321 
00322         pressedKeysSize--;
00323         pressedKeys++;
00324     }
00325 
00326     /* Release keys */
00327     while (releasedKeysSize > 0) {
00328 
00329         /* Check if this is a standard or modifier key */
00330         if (HIDKeypad_IsModifierKey(*releasedKeys)) {
00331 
00332             /* Set the corresponding bit in the input report */
00333             HIDDKeyboardInputReport_ReleaseModifierKey(
00334                 pReport,
00335                 *releasedKeys);
00336         }
00337         else {
00338 
00339             HIDDKeyboardInputReport_ReleaseStandardKey(
00340                 pReport,
00341                 *releasedKeys);
00342         }
00343 
00344         releasedKeysSize--;
00345         releasedKeys++;
00346     }
00347 
00348     /* Send input report through the interrupt IN endpoint */
00349     return USBD_Write(pHidd->bPipeIN,
00350                       pReport,
00351                       sizeof(HIDDKeyboardInputReport),
00352                       0,
00353                       0);
00354 }
00355 
00356 /**
00357  * Starts a remote wake-up sequence if the host has explicitely enabled it
00358  * by sending the appropriate SET_FEATURE request.
00359  */
00360 void HIDDKeyboard_RemoteWakeUp(void)
00361 {
00362     HIDDKeyboard *pKbd = &hiddKeyboard;
00363     HIDDFunction *pHidd = &pKbd->hidDrv;
00364     USBDDriver *pUsbd = pHidd->pUsbd;
00365 
00366     /* Remote wake-up has been enabled */
00367     if (USBDDriver_IsRemoteWakeUpEnabled(pUsbd)) {
00368 
00369         USBD_RemoteWakeUp();
00370     }
00371 }
00372 
00373 /**@}*/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines