SAMV71 Xplained Ultra Software Package 1.5

HIDDKeyboard.c

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------- */
00002 /*                  Atmel Microcontroller Software Support                      */
00003 /*                       SAM Software Package License                           */
00004 /* ---------------------------------------------------------------------------- */
00005 /* Copyright (c) 2015, Atmel Corporation                                        */
00006 /*                                                                              */
00007 /* All rights reserved.                                                         */
00008 /*                                                                              */
00009 /* Redistribution and use in source and binary forms, with or without           */
00010 /* modification, are permitted provided that the following condition is met:    */
00011 /*                                                                              */
00012 /* - Redistributions of source code must retain the above copyright notice,     */
00013 /* this list of conditions and the disclaimer below.                            */
00014 /*                                                                              */
00015 /* Atmel's name may not be used to endorse or promote products derived from     */
00016 /* this software without specific prior written permission.                     */
00017 /*                                                                              */
00018 /* DISCLAIMER:  THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR   */
00019 /* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
00020 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE   */
00021 /* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,      */
00022 /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
00023 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,  */
00024 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    */
00025 /* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING         */
00026 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
00027 /* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                           */
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 COMPILER_ALIGNED(32) static KBDInputReport inputReport;
00126 
00127 /** HIDD Keyboard Output Report Instance */
00128 COMPILER_ALIGNED(32) static KBDOutputReport outputReport;
00129 
00130 /** Static instance of the HIDD keyboard device driver. */
00131 COMPILER_ALIGNED(32) 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 ((void *)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         } else {
00315 
00316             HIDDKeyboardInputReport_PressStandardKey(
00317                 pReport,
00318                 *pressedKeys);
00319         }
00320 
00321         pressedKeysSize--;
00322         pressedKeys++;
00323     }
00324 
00325     /* Release keys */
00326     while (releasedKeysSize > 0) {
00327 
00328         /* Check if this is a standard or modifier key */
00329         if (HIDKeypad_IsModifierKey(*releasedKeys)) {
00330 
00331             /* Set the corresponding bit in the input report */
00332             HIDDKeyboardInputReport_ReleaseModifierKey(
00333                 pReport,
00334                 *releasedKeys);
00335         } else {
00336 
00337             HIDDKeyboardInputReport_ReleaseStandardKey(
00338                 pReport,
00339                 *releasedKeys);
00340         }
00341 
00342         releasedKeysSize--;
00343         releasedKeys++;
00344     }
00345 
00346     /* Send input report through the interrupt IN endpoint */
00347     return USBD_Write(pHidd->bPipeIN,
00348                       pReport,
00349                       sizeof(HIDDKeyboardInputReport),
00350                       0,
00351                       0);
00352 }
00353 
00354 /**
00355  * Starts a remote wake-up sequence if the host has explicitely enabled it
00356  * by sending the appropriate SET_FEATURE request.
00357  */
00358 void HIDDKeyboard_RemoteWakeUp(void)
00359 {
00360     HIDDKeyboard *pKbd = &hiddKeyboard;
00361     HIDDFunction *pHidd = &pKbd->hidDrv;
00362     USBDDriver *pUsbd = pHidd->pUsbd;
00363 
00364     /* Remote wake-up has been enabled */
00365     if (USBDDriver_IsRemoteWakeUpEnabled(pUsbd))
00366         USBD_RemoteWakeUp();
00367 }
00368 
00369 /**@}*/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines