Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
usbd_hid.c
00001 /** 00002 * @file usbd_hid.c 00003 * @brief Human Interface Device driver 00004 * 00005 * DAPLink Interface Firmware 00006 * Copyright (c) 2009-2016, ARM Limited, All Rights Reserved 00007 * SPDX-License-Identifier: Apache-2.0 00008 * 00009 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00010 * not use this file except in compliance with the License. 00011 * You may obtain a copy of the License at 00012 * 00013 * http://www.apache.org/licenses/LICENSE-2.0 00014 * 00015 * Unless required by applicable law or agreed to in writing, software 00016 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00017 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00018 * See the License for the specific language governing permissions and 00019 * limitations under the License. 00020 */ 00021 00022 #include <string.h> 00023 00024 #include "rl_usb.h" 00025 #include "usb_for_lib.h" 00026 00027 00028 U8 USBD_HID_Protocol; 00029 00030 BOOL DataOutAsyncReq; 00031 U32 DataOutUpdateReqMask; 00032 U8 *ptrDataOut; 00033 volatile U16 DataOutToSendLen; 00034 U16 DataOutSentLen; 00035 BOOL DataOutEndWithShortPacket; 00036 00037 U8 *ptrDataIn; 00038 U16 DataInReceMax; 00039 U16 DataInReceLen; 00040 00041 U8 *ptrDataFeat; 00042 U16 DataFeatReceLen; 00043 00044 00045 /* Dummy Weak Functions that need to be provided by user */ 00046 __weak void usbd_hid_init(void) 00047 { 00048 00049 } 00050 __weak int usbd_hid_get_report(U8 rtype, U8 rid, U8 *buf, U8 req) 00051 { 00052 return (0); 00053 }; 00054 __weak void usbd_hid_set_report(U8 rtype, U8 rid, U8 *buf, int len, U8 req) 00055 { 00056 00057 } 00058 __weak U8 usbd_hid_get_protocol(void) 00059 { 00060 return (0); 00061 }; 00062 __weak void usbd_hid_set_protocol(U8 protocol) 00063 { 00064 00065 }; 00066 00067 00068 /* 00069 * USB Device HID Get Report Request Callback 00070 * Called automatically on USB Device HID Get Report Request 00071 * Parameters: None 00072 * Return Value: TRUE - Success, FALSE - Error 00073 */ 00074 00075 BOOL USBD_HID_GetReport(void) 00076 { 00077 U8 *ptr_buf = 0; 00078 00079 /* Report Type = USBD_SetupPacket.wValueH */ 00080 /* Report ID = USBD_SetupPacket.wValueL */ 00081 /* Report Length = USBD_SetupPacket.wLength */ 00082 switch (USBD_SetupPacket.wValueH) { 00083 case HID_REPORT_INPUT: 00084 ptr_buf = &USBD_HID_InReport[1]; 00085 break; 00086 00087 case HID_REPORT_OUTPUT: 00088 return (__FALSE); /* Not Supported */ 00089 00090 case HID_REPORT_FEATURE: 00091 ptr_buf = &USBD_HID_FeatReport[1]; 00092 break; 00093 } 00094 00095 usbd_hid_get_report(USBD_SetupPacket.wValueH, USBD_SetupPacket.wValueL, ptr_buf, USBD_HID_REQ_EP_CTRL); 00096 return (__TRUE); 00097 } 00098 00099 00100 /* 00101 * USB Device HID Set Report Request Callback 00102 * Called automatically on USB Device HID Set Report Request 00103 * Parameters: None 00104 * Return Value: TRUE - Success, FALSE - Error 00105 */ 00106 00107 BOOL USBD_HID_SetReport(void) 00108 { 00109 U8 *ptr_buf = 0; 00110 00111 /* Report Type = USBD_SetupPacket.wValueH */ 00112 /* Report ID = USBD_SetupPacket.wValueL */ 00113 /* Report Length = USBD_SetupPacket.wLength */ 00114 switch (USBD_SetupPacket.wValueH) { 00115 case HID_REPORT_INPUT: 00116 return (__FALSE); /* Not Supported */ 00117 00118 case HID_REPORT_OUTPUT: 00119 ptr_buf = &USBD_HID_OutReport[1]; 00120 break; 00121 00122 case HID_REPORT_FEATURE: 00123 ptr_buf = &USBD_HID_FeatReport[1]; 00124 break; 00125 } 00126 00127 usbd_hid_set_report(USBD_SetupPacket.wValueH, USBD_SetupPacket.wValueL, ptr_buf, USBD_SetupPacket.wLength, USBD_HID_REQ_EP_CTRL); 00128 return (__TRUE); 00129 } 00130 00131 00132 /* 00133 * USB Device HID Get Idle Request Callback 00134 * Called automatically on USB Device HID Get Idle Request 00135 * Parameters: None 00136 * Return Value: TRUE - Success, FALSE - Error 00137 */ 00138 00139 BOOL USBD_HID_GetIdle(void) 00140 { 00141 USBD_EP0Buf[0] = USBD_HID_IdleSet[USBD_SetupPacket.wValueL]; 00142 return (__TRUE); 00143 } 00144 00145 00146 /* 00147 * USB Device HID Set Idle Request Callback 00148 * Called automatically on USB Device HID Set Idle Request 00149 * Parameters: None 00150 * Return Value: TRUE - Success, FALSE - Error 00151 */ 00152 00153 BOOL USBD_HID_SetIdle(void) 00154 { 00155 U8 i; 00156 00157 if (USBD_SetupPacket.wValueL) { /* If > 0 Report ID specified */ 00158 USBD_HID_IdleSet[USBD_SetupPacket.wValueL - 1] = USBD_SetupPacket.wValueH; 00159 } else { /* If == 0 all reports */ 00160 for (i = 0; i < usbd_hid_inreport_num; i++) { 00161 USBD_HID_IdleSet[i] = USBD_SetupPacket.wValueH; 00162 } 00163 } 00164 00165 return (__TRUE); 00166 } 00167 00168 00169 /* 00170 * USB Device HID Get Protocol Request Callback 00171 * Called automatically on USB Device HID Get Protocol Request 00172 * Parameters: None 00173 * Return Value: TRUE - Success, FALSE - Error 00174 */ 00175 00176 BOOL USBD_HID_GetProtocol(void) 00177 { 00178 USBD_EP0Buf[0] = usbd_hid_get_protocol(); 00179 return (__TRUE); 00180 } 00181 00182 00183 /* 00184 * USB Device HID Set Protocol Request Callback 00185 * Called automatically on USB Device HID Set Protocol Request 00186 * Parameters: None 00187 * Return Value: TRUE - Success, FALSE - Error 00188 */ 00189 00190 BOOL USBD_HID_SetProtocol(void) 00191 { 00192 usbd_hid_set_protocol(USBD_SetupPacket.wValueL); 00193 return (__TRUE); 00194 } 00195 00196 00197 /* 00198 * USB Device HID Interrupt In Endpoint Event Callback 00199 * Parameters: event: not used (just for compatibility) 00200 * Return Value: None 00201 */ 00202 00203 void USBD_HID_EP_INTIN_Event(U32 event) 00204 { 00205 U8 i; 00206 U16 bytes_to_send; 00207 00208 /* Check if sending is finished */ 00209 if ((DataOutSentLen >= DataOutToSendLen) && 00210 !DataOutEndWithShortPacket) { /* If all sent and short packet also */ 00211 ptrDataOut = NULL; 00212 DataOutSentLen = 0; 00213 DataOutToSendLen = usbd_hid_get_report(HID_REPORT_INPUT, USBD_HID_InReport[0], &USBD_HID_InReport[1], USBD_HID_REQ_EP_INT); 00214 00215 if (DataOutToSendLen) { /* If new send should be started */ 00216 ptrDataOut = USBD_HID_InReport; 00217 00218 if (usbd_hid_inreport_num <= 1) { /* If only in 1 report skip ReportID */ 00219 ptrDataOut++; 00220 } else { /* If more in reports, send ReportID */ 00221 DataOutToSendLen++; 00222 } 00223 } 00224 } 00225 00226 /* Check if new data out sending should be started */ 00227 if (!DataOutToSendLen) { /* If send not in progress */ 00228 if (DataOutAsyncReq) { /* If asynchronous send requested */ 00229 DataOutAsyncReq = __FALSE; 00230 } else if (DataOutUpdateReqMask) { /* If update requested */ 00231 if (usbd_hid_inreport_num <= 1) { /* If only one in report in system */ 00232 if (DataOutUpdateReqMask) { 00233 USBD_HID_InReport[0] = 0; /* ReportID = 0 */ 00234 DataOutSentLen = 0; 00235 DataOutToSendLen = usbd_hid_get_report(HID_REPORT_INPUT, 0, &USBD_HID_InReport[1], USBD_HID_REQ_PERIOD_UPDATE); 00236 00237 if (DataOutToSendLen) { 00238 ptrDataOut = &USBD_HID_InReport[1]; 00239 } 00240 00241 DataOutUpdateReqMask = 0; 00242 } 00243 } else { /* If multiple reports in system */ 00244 for (i = USBD_HID_InReport[0]; ; i++) { 00245 if (i >= 32) { 00246 i = 0; 00247 } 00248 00249 if (DataOutUpdateReqMask & (1 << i)) { 00250 USBD_HID_InReport[0] = i + 1; /* ReportID */ 00251 DataOutSentLen = 0; 00252 DataOutToSendLen = usbd_hid_get_report(HID_REPORT_INPUT, i + 1, &USBD_HID_InReport[1], USBD_HID_REQ_PERIOD_UPDATE); 00253 00254 if (DataOutToSendLen) { 00255 ptrDataOut = USBD_HID_InReport; 00256 DataOutToSendLen++; 00257 } 00258 00259 DataOutUpdateReqMask &= ~(1 << i); 00260 break; 00261 } 00262 } 00263 } 00264 } 00265 } 00266 00267 /* Check if data needs to be sent */ 00268 if (DataOutToSendLen || 00269 DataOutEndWithShortPacket) { /* If sending is in progress */ 00270 bytes_to_send = DataOutToSendLen - DataOutSentLen; 00271 00272 if (bytes_to_send > usbd_hid_maxpacketsize[USBD_HighSpeed]) { 00273 bytes_to_send = usbd_hid_maxpacketsize[USBD_HighSpeed]; 00274 } 00275 00276 if (usbd_hid_ep_intin != 0) { //control ep does the sending to host 00277 USBD_WriteEP(usbd_hid_ep_intin | 0x80, ptrDataOut, bytes_to_send); 00278 } 00279 00280 ptrDataOut += bytes_to_send; 00281 DataOutSentLen += bytes_to_send; 00282 00283 if ((DataOutSentLen < usbd_hid_inreport_max_sz) && 00284 (bytes_to_send == usbd_hid_maxpacketsize[USBD_HighSpeed])) { 00285 /* If short packet should be sent also*/ 00286 DataOutEndWithShortPacket = __TRUE; 00287 } else { 00288 DataOutEndWithShortPacket = __FALSE; 00289 } 00290 } 00291 } 00292 00293 00294 /* 00295 * USB Device HID Interrupt Out Endpoint Event Callback 00296 * Parameters: event: not used (just for compatibility) 00297 * Return Value: None 00298 */ 00299 00300 void USBD_HID_EP_INTOUT_Event(U32 event) 00301 { 00302 U16 bytes_rece; 00303 00304 if (!DataInReceLen) { /* Check if new reception */ 00305 ptrDataIn = USBD_HID_OutReport; 00306 DataInReceMax = usbd_hid_outreport_max_sz; 00307 DataInReceLen = 0; 00308 } 00309 00310 bytes_rece = USBD_ReadEP(usbd_hid_ep_intout, ptrDataIn, DataInReceMax - DataInReceLen); 00311 ptrDataIn += bytes_rece; 00312 DataInReceLen += bytes_rece; 00313 00314 if (!bytes_rece || 00315 (DataInReceLen >= usbd_hid_outreport_max_sz) || 00316 (bytes_rece < usbd_hid_maxpacketsize[USBD_HighSpeed])) { 00317 if (usbd_hid_outreport_num <= 1) { /* If only one out report in system */ 00318 usbd_hid_set_report(HID_REPORT_OUTPUT, 0 , USBD_HID_OutReport , DataInReceLen, USBD_HID_REQ_EP_INT); 00319 } else { 00320 usbd_hid_set_report(HID_REPORT_OUTPUT, USBD_HID_OutReport[0], &USBD_HID_OutReport[1], DataInReceLen - 1, USBD_HID_REQ_EP_INT); 00321 } 00322 00323 DataInReceLen = 0; 00324 } 00325 } 00326 00327 00328 /* 00329 * USB Device HID Configure Callback 00330 * Parameters: None 00331 * Return Value: None 00332 */ 00333 00334 void USBD_HID_Configure_Event(void) 00335 { 00336 /* Reset all variables after connect event */ 00337 USBD_HID_Protocol = 0; 00338 DataOutAsyncReq = __FALSE; 00339 DataOutUpdateReqMask = __FALSE; 00340 ptrDataOut = NULL; 00341 DataOutToSendLen = 0; 00342 DataOutSentLen = 0; 00343 DataOutEndWithShortPacket = __FALSE; 00344 ptrDataIn = NULL; 00345 DataInReceMax = 0; 00346 DataInReceLen = 0; 00347 ptrDataFeat = NULL; 00348 DataFeatReceLen = 0; 00349 } 00350 00351 00352 /* 00353 * USB Device HID Interrupt In/Out Endpoint Event Callback 00354 * Parameters: event: USB Device Event 00355 * USBD_EVT_IN: Input Event 00356 * USBD_EVT_OUT: Output Event 00357 * Return Value: None 00358 */ 00359 00360 void USBD_HID_EP_INT_Event(U32 event) 00361 { 00362 if (event & USBD_EVT_IN) { 00363 USBD_HID_EP_INTIN_Event(event); 00364 } 00365 00366 if (event & USBD_EVT_OUT) { 00367 USBD_HID_EP_INTOUT_Event(event); 00368 } 00369 } 00370 00371 00372 /* 00373 * USB Device HID SOF Handler (handles report timings: polling and idle times) 00374 * Called automatically on USB Device Start of Frame 00375 * Parameters: None 00376 * Return Value: None 00377 */ 00378 00379 void USBD_HID_SOF_Event(void) 00380 { 00381 static U8 cnt_for_4ms = 0; 00382 U8 i; 00383 BOOL tick_4ms, do_polling, polling_reload, idle_reload; 00384 00385 if (USBD_Configuration) { 00386 tick_4ms = __FALSE; 00387 00388 if (cnt_for_4ms++ >= ((4 << (3 * USBD_HighSpeed))) - 1) { 00389 cnt_for_4ms = 0; 00390 tick_4ms = __TRUE; 00391 } 00392 00393 polling_reload = __FALSE; 00394 00395 if (USBD_HID_PollingCnt < 255) { 00396 USBD_HID_PollingCnt++; 00397 } 00398 00399 if (USBD_HID_PollingCnt == usbd_hid_interval[USBD_HighSpeed]) { 00400 polling_reload = __TRUE; /* If polling interval expired */ 00401 } 00402 00403 for (i = 0; i < usbd_hid_inreport_num; i++) { 00404 idle_reload = __FALSE; 00405 00406 if (tick_4ms) { 00407 if (USBD_HID_IdleCnt[i] < 255) { 00408 USBD_HID_IdleCnt[i]++; 00409 } 00410 00411 if (USBD_HID_IdleReload[i]) { 00412 if (USBD_HID_IdleCnt[i] >= USBD_HID_IdleReload[i]) { 00413 idle_reload = __TRUE; /* If idle period expired */ 00414 } 00415 } 00416 } 00417 00418 do_polling = (usbd_hid_interval[USBD_HighSpeed] > ((U16)(USBD_HID_IdleReload[i]) << (2 << (3 * USBD_HighSpeed)))) && (USBD_HID_IdleReload[i] != 0); 00419 00420 if (polling_reload) { 00421 if (do_polling) { 00422 /* If polling is longer than idle */ 00423 DataOutUpdateReqMask |= (1 << i); 00424 } 00425 } 00426 00427 if (USBD_HID_IdleReload[i] != USBD_HID_IdleSet[i]) { 00428 if (USBD_HID_IdleCnt[i] >= USBD_HID_IdleSet[i]) { 00429 DataOutUpdateReqMask |= (1 << i); 00430 cnt_for_4ms = 0; 00431 } 00432 00433 USBD_HID_IdleReload[i] = USBD_HID_IdleSet[i]; 00434 } 00435 00436 if (idle_reload) { 00437 if (!do_polling) { 00438 DataOutUpdateReqMask |= (1 << i); 00439 } 00440 00441 USBD_HID_IdleCnt[i] = 0; 00442 } 00443 } 00444 00445 if (polling_reload) { 00446 USBD_HID_PollingCnt = 0; 00447 } 00448 00449 if (DataOutUpdateReqMask && !DataOutToSendLen) { /* If pending */ 00450 /* refresh request and no active data */ 00451 /* out then start data out */ 00452 USBD_HID_EP_INTIN_Event(0); 00453 } 00454 } 00455 } 00456 00457 00458 #ifdef __RTX /* RTX task for handling events */ 00459 00460 /* 00461 * USB Device HID Interrupt In Endpoint Event Handler Task 00462 * Parameters: None 00463 * Return Value: None 00464 */ 00465 00466 void USBD_RTX_HID_EP_INTIN_Event(void) 00467 { 00468 for (;;) { 00469 usbd_os_evt_wait_or(0xFFFF, 0xFFFF); 00470 00471 if (usbd_os_evt_get() & USBD_EVT_IN) { 00472 USBD_HID_EP_INTIN_Event(0); 00473 } 00474 } 00475 } 00476 00477 00478 /* 00479 * USB Device HID Interrupt Out Endpoint Event Handler Task 00480 * Parameters: None 00481 * Return Value: None 00482 */ 00483 00484 void USBD_RTX_HID_EP_INTOUT_Event(void) 00485 { 00486 for (;;) { 00487 usbd_os_evt_wait_or(0xFFFF, 0xFFFF); 00488 00489 if (usbd_os_evt_get() & USBD_EVT_OUT) { 00490 USBD_HID_EP_INTOUT_Event(0); 00491 } 00492 } 00493 } 00494 00495 00496 /* 00497 * USB Device HID Interrupt In/Out Endpoint Event Handler Task 00498 * Parameters: None 00499 * Return Value: None 00500 */ 00501 00502 void USBD_RTX_HID_EP_INT_Event(void) 00503 { 00504 for (;;) { 00505 usbd_os_evt_wait_or(0xFFFF, 0xFFFF); 00506 USBD_HID_EP_INT_Event(usbd_os_evt_get()); 00507 } 00508 } 00509 #endif 00510 00511 00512 /* 00513 * USB Device HID Get Report Trigger (asynchronous Get_Report request) 00514 * Parameters: rid: Report ID 00515 * buf: Pointer to data buffer 00516 * len: Number of bytes to be sent 00517 * Return Value: TRUE - Success, FALSE - Error 00518 */ 00519 00520 BOOL usbd_hid_get_report_trigger(U8 rid, U8 *buf, int len) 00521 { 00522 if (len > usbd_hid_inreport_max_sz) { 00523 return (__FALSE); 00524 } 00525 00526 if (USBD_Configuration) { 00527 DataOutAsyncReq = __TRUE; /* Asynchronous data out request */ 00528 00529 while (DataOutToSendLen) { 00530 if (!USBD_Configuration) { /* If device not configured reject rq */ 00531 DataOutAsyncReq = __FALSE; /* Asynchronous data out request */ 00532 ptrDataOut = NULL; 00533 DataOutSentLen = 0; 00534 DataOutToSendLen = 0; 00535 return (__FALSE); 00536 } 00537 } 00538 00539 USBD_HID_InReport[0] = rid; 00540 memcpy(&USBD_HID_InReport[1], buf, len); 00541 ptrDataOut = USBD_HID_InReport; 00542 DataOutSentLen = 0; 00543 DataOutToSendLen = len; 00544 00545 if (usbd_hid_inreport_num <= 1) { /* If only 1 in report skip ReportID */ 00546 ptrDataOut ++; 00547 } else { /* If more in reports, send ReportID */ 00548 DataOutToSendLen ++; 00549 } 00550 00551 USBD_HID_EP_INTIN_Event(0); 00552 USBD_HID_IdleCnt[rid] = 0; 00553 return (__TRUE); 00554 } 00555 00556 return (__FALSE); 00557 }
Generated on Tue Jul 12 2022 15:37:26 by
1.7.2