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_cdc_acm.c
00001 /** 00002 * @file usbd_cdc_acm.c 00003 * @brief Communication Device Class 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 /* Module global variables */ 00029 00030 /** \ingroup USBD_CDC_ACM_global_variables 00031 \defgroup USBD_CDC_ACM_GLOBAL_VAR Global Variables (GLOBAL_VAR) 00032 \brief Global variables used in USBD CDC ACM module 00033 */ 00034 int32_t data_send_access ; /*!< Flag active while send data (in the send intermediate buffer) is being accessed */ 00035 int32_t data_send_active ; /*!< Flag active while data is being sent */ 00036 int32_t data_send_zlp ; /*!< Flag active when ZLP needs to be sent */ 00037 int32_t data_to_send_wr ; /*!< Number of bytes written to the send intermediate buffer */ 00038 int32_t data_to_send_rd ; /*!< Number of bytes read from the send intermediate buffer */ 00039 uint8_t *ptr_data_to_send ; /*!< Pointer to the send intermediate buffer to the data to be sent */ 00040 uint8_t *ptr_data_sent ; /*!< Pointer to the send intermediate buffer to the data already sent */ 00041 00042 int32_t data_read_access ; /*!< Flag active while read data (in the receive intermediate buffer) is being accessed */ 00043 int32_t data_receive_int_access ; /*!< Flag active while read data (in the receive intermediate buffer) is being accessed from the IRQ function*/ 00044 int32_t data_received_pending_pckts ; /*!< Number of packets received but not handled (pending) */ 00045 int32_t data_no_space_for_receive ; /*!< Flag active while there is no more space for reception */ 00046 uint8_t *ptr_data_received ; /*!< Pointer to the receive intermediate buffer to the received unread data */ 00047 uint8_t *ptr_data_read ; /*!< Pointer to the receive intermediate buffer to the received read data */ 00048 00049 uint16_t control_line_state ; /*!< Control line state settings bitmap (0. bit - DTR state, 1. bit - RTS state) */ 00050 00051 CDC_LINE_CODING line_coding ; /*!< Communication settings */ 00052 00053 /* end of group USBD_CDC_ACM_GLOBAL_VAR */ 00054 00055 00056 /* Functions that should be provided by user to use standard Virtual COM port 00057 functionality */ 00058 __weak int32_t USBD_CDC_ACM_PortInitialize(void) 00059 { 00060 return (0); 00061 } 00062 __weak int32_t USBD_CDC_ACM_PortUninitialize(void) 00063 { 00064 return (0); 00065 } 00066 __weak int32_t USBD_CDC_ACM_PortReset(void) 00067 { 00068 return (0); 00069 } 00070 __weak int32_t USBD_CDC_ACM_PortSetLineCoding(CDC_LINE_CODING *line_coding ) 00071 { 00072 return (0); 00073 } 00074 __weak int32_t USBD_CDC_ACM_PortGetLineCoding(CDC_LINE_CODING *line_coding ) 00075 { 00076 return (0); 00077 } 00078 __weak int32_t USBD_CDC_ACM_PortSetControlLineState(uint16_t ctrl_bmp) 00079 { 00080 return (0); 00081 } 00082 00083 /* Functions that can be used by user to use standard Virtual COM port 00084 functionality */ 00085 int32_t USBD_CDC_ACM_DataSend(const uint8_t *buf, int32_t len); 00086 int32_t USBD_CDC_ACM_PutChar(const uint8_t ch); 00087 int32_t USBD_CDC_ACM_DataRead(uint8_t *buf, int32_t len); 00088 int32_t USBD_CDC_ACM_GetChar(void); 00089 __weak int32_t USBD_CDC_ACM_DataReceived(int32_t len) 00090 { 00091 return (0); 00092 } 00093 int32_t USBD_CDC_ACM_DataAvailable(void); 00094 int32_t USBD_CDC_ACM_Notify(uint16_t stat); 00095 00096 /* Functions handling CDC ACM requests (can be overridden to provide custom 00097 handling of CDC ACM requests) */ 00098 __weak int32_t USBD_CDC_ACM_SendEncapsulatedCommand(void) 00099 { 00100 return (0); 00101 } 00102 __weak int32_t USBD_CDC_ACM_GetEncapsulatedResponse(void) 00103 { 00104 return (0); 00105 } 00106 __weak int32_t USBD_CDC_ACM_SetCommFeature(uint16_t feat) 00107 { 00108 return (0); 00109 } 00110 __weak int32_t USBD_CDC_ACM_GetCommFeature(uint16_t feat) 00111 { 00112 return (0); 00113 } 00114 __weak int32_t USBD_CDC_ACM_ClearCommFeature(uint16_t feat) 00115 { 00116 return (0); 00117 } 00118 __weak int32_t USBD_CDC_ACM_SendBreak(uint16_t dur) 00119 { 00120 return (0); 00121 } 00122 00123 00124 /* Local function prototypes */ 00125 static void USBD_CDC_ACM_EP_BULKOUT_HandleData(void); 00126 static void USBD_CDC_ACM_EP_BULKIN_HandleData(void); 00127 00128 00129 /*----------------- USB CDC ACM class handling functions ---------------------*/ 00130 00131 /** \brief Initialization of the USB CDC class (ACM) 00132 00133 The function calls USBD_CDC_ACM_PortInitialize function which 00134 initializes Virtual COM Port. 00135 00136 \return 0 Function failed. 00137 \return 1 Function succeeded. 00138 */ 00139 00140 __weak int32_t USBD_CDC_ACM_Initialize(void) 00141 { 00142 data_send_access = 0; 00143 data_send_active = 0; 00144 data_send_zlp = 0; 00145 data_to_send_wr = 0; 00146 data_to_send_rd = 0; 00147 ptr_data_to_send = USBD_CDC_ACM_SendBuf; 00148 ptr_data_sent = USBD_CDC_ACM_SendBuf; 00149 data_read_access = 0; 00150 data_receive_int_access = 0; 00151 data_received_pending_pckts = 0; 00152 data_no_space_for_receive = 0; 00153 ptr_data_received = USBD_CDC_ACM_ReceiveBuf; 00154 ptr_data_read = USBD_CDC_ACM_ReceiveBuf; 00155 control_line_state = 0; 00156 line_coding .dwDTERate = 9600; 00157 line_coding .bCharFormat = 0; 00158 line_coding .bParityType = 0; 00159 line_coding .bDataBits = 8; 00160 return (USBD_CDC_ACM_PortInitialize()); 00161 } 00162 00163 00164 /** \brief Uninitialization of the USB CDC class (ACM) 00165 00166 The function calls USBD_CDC_ACM_PortUninitialize function which 00167 uninitializes Virtual COM Port. 00168 00169 \return 0 Function failed. 00170 \return 1 Function succeeded. 00171 */ 00172 00173 __weak int32_t USBD_CDC_ACM_Uninitialization(void) 00174 { 00175 return (USBD_CDC_ACM_PortUninitialize()); 00176 } 00177 00178 00179 /** \brief Reset of the USB CDC class (ACM) variables and states 00180 00181 The function resets class variables and states, it calls 00182 USBD_CDC_ACM_PortReset function which resets Virtual COM Port variables 00183 and states and calls USBD_CDC_ACM_PortSetLineCoding function with 00184 default parameters to set default communication settings for the 00185 Virtual COM Port. 00186 00187 \return 0 Function failed. 00188 \return 1 Function succeeded. 00189 */ 00190 00191 __weak int32_t USBD_CDC_ACM_Reset(void) 00192 { 00193 data_send_access = 0; 00194 data_send_active = 0; 00195 data_send_zlp = 0; 00196 data_to_send_wr = 0; 00197 data_to_send_rd = 0; 00198 ptr_data_to_send = USBD_CDC_ACM_SendBuf; 00199 ptr_data_sent = USBD_CDC_ACM_SendBuf; 00200 data_read_access = 0; 00201 data_receive_int_access = 0; 00202 data_received_pending_pckts = 0; 00203 data_no_space_for_receive = 0; 00204 ptr_data_received = USBD_CDC_ACM_ReceiveBuf; 00205 ptr_data_read = USBD_CDC_ACM_ReceiveBuf; 00206 control_line_state = 0; 00207 USBD_CDC_ACM_PortReset(); 00208 line_coding .dwDTERate = 9600; 00209 line_coding .bCharFormat = 0; 00210 line_coding .bParityType = 0; 00211 line_coding .bDataBits = 8; 00212 return (USBD_CDC_ACM_PortSetLineCoding(&line_coding )); 00213 } 00214 00215 00216 /** \brief Sets Line Coding for the USB CDC ACM Virtual COM Port 00217 00218 The function is a callback function that forwards USB CDC ACM request 00219 to set communication settings to the Virtual COM Port. 00220 00221 \return 0 Function failed. 00222 \return 1 Function succeeded. 00223 */ 00224 00225 __weak int32_t USBD_CDC_ACM_SetLineCoding(void) 00226 { 00227 line_coding .dwDTERate = (USBD_EP0Buf[0] << 0) | 00228 (USBD_EP0Buf[1] << 8) | 00229 (USBD_EP0Buf[2] << 16) | 00230 (USBD_EP0Buf[3] << 24) ; 00231 line_coding .bCharFormat = USBD_EP0Buf[4]; 00232 line_coding .bParityType = USBD_EP0Buf[5]; 00233 line_coding .bDataBits = USBD_EP0Buf[6]; 00234 return (USBD_CDC_ACM_PortSetLineCoding(&line_coding )); 00235 } 00236 00237 00238 /** \brief Gets Line Coding from the USB CDC ACM Virtual COM Port 00239 00240 The function is a callback function that forwards USB CDC ACM request 00241 to get communication settings from the Virtual COM Port. 00242 00243 \return 0 Function failed. 00244 \return 1 Function succeeded. 00245 */ 00246 00247 __weak int32_t USBD_CDC_ACM_GetLineCoding(void) 00248 { 00249 if (USBD_CDC_ACM_PortGetLineCoding(&line_coding )) { 00250 USBD_EP0Buf[0] = (line_coding .dwDTERate >> 0) & 0xFF; 00251 USBD_EP0Buf[1] = (line_coding .dwDTERate >> 8) & 0xFF; 00252 USBD_EP0Buf[2] = (line_coding .dwDTERate >> 16) & 0xFF; 00253 USBD_EP0Buf[3] = (line_coding .dwDTERate >> 24) & 0xFF; 00254 USBD_EP0Buf[4] = line_coding .bCharFormat; 00255 USBD_EP0Buf[5] = line_coding .bParityType; 00256 USBD_EP0Buf[6] = line_coding .bDataBits; 00257 return (1); 00258 } 00259 00260 return (0); 00261 } 00262 00263 00264 /** \brief Sets Control Line State for the USB CDC ACM Virtual COM Port 00265 00266 The function is a callback function that forwards USB CDC ACM request 00267 to set desired control line state to the Virtual COM Port. 00268 00269 \param [in] ctrl_bmp Control line settings bitmap ( 00270 0. bit - DTR state, 00271 1. bit - RTS state). 00272 \return 0 Function failed. 00273 \return 1 Function succeeded. 00274 */ 00275 00276 __weak int32_t USBD_CDC_ACM_SetControlLineState(uint16_t ctrl_bmp) 00277 { 00278 control_line_state = ctrl_bmp; 00279 return (USBD_CDC_ACM_PortSetControlLineState(ctrl_bmp)); 00280 } 00281 00282 00283 /*----------------- USB CDC ACM user API functions ---------------------------*/ 00284 00285 /** \brief Number of free bytes in the Send buffer 00286 */ 00287 int32_t USBD_CDC_ACM_DataFree(void) 00288 { 00289 return ((int32_t)usbd_cdc_acm_sendbuf_sz) - (data_to_send_wr - data_to_send_rd ); 00290 } 00291 00292 /** \brief Sends data over the USB CDC ACM Virtual COM Port 00293 00294 The function puts requested data to the send intermediate buffer and 00295 prepares it for sending over the Virtual COM Port. 00296 00297 \param [in] buf Buffer containing data to be sent. 00298 \param [in] len Maximum number of bytes to be sent. 00299 \return Number of bytes accepted to be sent. 00300 */ 00301 00302 int32_t USBD_CDC_ACM_DataSend(const uint8_t *buf, int32_t len) 00303 { 00304 int32_t len_data, len_available, len_before_wrap; 00305 uint8_t *buf_loc; 00306 buf_loc = (uint8_t *)buf; /* Pointer to buf */ 00307 len_data = data_to_send_wr - data_to_send_rd ; /* Num of data in buffer*/ 00308 len_available = ((int32_t)usbd_cdc_acm_sendbuf_sz) - len_data; /* Num of 00309 bytes of space available */ 00310 00311 if (len_available <= 0) { /* If no space for data to send */ 00312 return (0); 00313 } 00314 00315 if (len > len_available) /* If more data requested for sending 00316 then available space */ 00317 { 00318 len = len_available; /* Correct to maximum available */ 00319 } 00320 00321 len_before_wrap = 0; /* Circular buffer size before wrap */ 00322 00323 if ((ptr_data_to_send >= ptr_data_sent ) && /* If wrap is possible to happen */ 00324 ((ptr_data_to_send + len) >= (USBD_CDC_ACM_SendBuf + usbd_cdc_acm_sendbuf_sz))) { 00325 /* If data wraps around end of buffer */ 00326 len_before_wrap = USBD_CDC_ACM_SendBuf + usbd_cdc_acm_sendbuf_sz - ptr_data_to_send ; 00327 memcpy(ptr_data_to_send, buf_loc, len_before_wrap); /* Copy data till end */ 00328 buf_loc += len_before_wrap; /* Increment buf pointer */ 00329 len -= len_before_wrap; /* Decrement bytes to send*/ 00330 ptr_data_to_send = USBD_CDC_ACM_SendBuf; /* Wrap send buffer 00331 pointer to beginning of 00332 the send buffer */ 00333 } 00334 00335 if (len) { /* If there are bytes to send */ 00336 memcpy(ptr_data_to_send , buf_loc, len); /* Copy data to send buffer */ 00337 ptr_data_to_send += len; /* Correct position of write pointer */ 00338 } 00339 00340 len += len_before_wrap; /* Total number of bytes prepared for 00341 send */ 00342 data_to_send_wr += len; /* Bytes prepared to send counter */ 00343 return (len); /* Number of bytes accepted for send */ 00344 } 00345 00346 00347 /** \brief Sends a single character over the USB CDC ACM Virtual COM Port 00348 00349 The function puts requested data character to the send intermediate buffer 00350 and prepares it for sending over the Virtual COM Port. 00351 00352 \param [in] ch Character to be sent. 00353 \return -1 Function failed. 00354 \return Character accepted to be sent. 00355 */ 00356 00357 int32_t USBD_CDC_ACM_PutChar(const uint8_t ch) 00358 { 00359 if ((USBD_CDC_ACM_DataSend(&ch, 1)) == 1) { 00360 return ((uint32_t) ch); 00361 } 00362 00363 return (-1); 00364 } 00365 00366 00367 /** \brief Reads data received over the USB CDC ACM Virtual COM Port 00368 00369 The function reads data from the receive intermediate buffer that was 00370 received over the Virtual COM Port. 00371 00372 \param [in] buf Buffer to where data will be read. 00373 \param [in] len Maximum number of bytes to be read. 00374 \return Number of bytes actually read. 00375 */ 00376 00377 int32_t USBD_CDC_ACM_DataRead(uint8_t *buf, int32_t len) 00378 { 00379 int32_t len_data; 00380 00381 if (ptr_data_received > ptr_data_read ) { /*If there is already received data */ 00382 len_data = ptr_data_received - ptr_data_read ; /* Available bytes of data */ 00383 00384 if (len > len_data) { /* If more requested then available */ 00385 len = len_data; /* correct to return maximum available*/ 00386 } 00387 00388 memcpy(buf, ptr_data_read, len); /* Copy received data to provided buf */ 00389 ptr_data_read += len; /* Correct position of read pointer */ 00390 } else { 00391 len = 0; /* No data received */ 00392 } 00393 00394 return (len); /* Number of bytes actually read */ 00395 } 00396 00397 00398 /** \brief Reads one character of data received over the USB CDC ACM Virtual COM Port 00399 00400 The function reads data character from the receive intermediate buffer that 00401 was received over the Virtual COM Port. 00402 00403 \return -1 No character available. 00404 \return Received character. 00405 */ 00406 00407 int32_t USBD_CDC_ACM_GetChar(void) 00408 { 00409 uint8_t ch; 00410 00411 if ((USBD_CDC_ACM_DataRead(&ch, 1)) == 1) { 00412 return ((int32_t) ch); 00413 } 00414 00415 return (-1); 00416 } 00417 00418 00419 /** \brief Retrieves number of bytes received over the USB CDC ACM Virtual COM Port 00420 00421 The function retrieves number of bytes available in the intermediate buffer 00422 that were received over the Virtual COM Port. 00423 00424 \return Number of bytes available for read. 00425 */ 00426 00427 int32_t USBD_CDC_ACM_DataAvailable(void) 00428 { 00429 return (ptr_data_received - ptr_data_read ); 00430 } 00431 00432 00433 /** \brief Sends a notification of Virtual COM Port statuses and line states 00434 00435 The function sends error and line status of the Virtual COM Port over the 00436 Interrupt endpoint. (SerialState notification is defined in usbcdc11.pdf, 6.3.5.) 00437 00438 \param [in] stat Error and line statuses ( 00439 6. bit - bOverRun, 00440 5. bit - bParity, 00441 4. bit - bFraming, 00442 3. bit - bRingSignal, 00443 2. bit - bBreak, 00444 1. bit - bTxCarrier (DSR line state), 00445 0. bit - bRxCarrier (DCD line status)). 00446 \return 0 Function failed. 00447 \return 1 Function succeeded. 00448 */ 00449 00450 int32_t USBD_CDC_ACM_Notify(uint16_t stat) 00451 { 00452 if (USBD_Configuration) { 00453 USBD_CDC_ACM_NotifyBuf[0] = 0xA1; /* bmRequestType */ 00454 USBD_CDC_ACM_NotifyBuf[1] = CDC_NOTIFICATION_SERIAL_STATE;/* bNotification 00455 (SERIAL_STATE) */ 00456 USBD_CDC_ACM_NotifyBuf[2] = 0x00; /* wValue */ 00457 USBD_CDC_ACM_NotifyBuf[3] = 0x00; 00458 USBD_CDC_ACM_NotifyBuf[4] = 0x00; /* wIndex (Interface 0) */ 00459 USBD_CDC_ACM_NotifyBuf[5] = 0x00; 00460 USBD_CDC_ACM_NotifyBuf[6] = 0x02; /* wLength */ 00461 USBD_CDC_ACM_NotifyBuf[7] = 0x00; 00462 USBD_CDC_ACM_NotifyBuf[8] = stat >> 0; /* UART State Bitmap */ 00463 USBD_CDC_ACM_NotifyBuf[9] = stat >> 8; 00464 /* Write notification to be sent */ 00465 USBD_WriteEP(usbd_cdc_acm_ep_intin | 0x80, USBD_CDC_ACM_NotifyBuf, 10); 00466 return (1); 00467 } 00468 00469 return (0); 00470 } 00471 00472 00473 /*----------------- USB CDC ACM communication event handlers -----------------*/ 00474 00475 /** \brief Handle Reset Events 00476 00477 The function handles Reset events. 00478 */ 00479 00480 void USBD_CDC_ACM_Reset_Event(void) 00481 { 00482 USBD_CDC_ACM_Reset(); 00483 } 00484 00485 00486 /** \brief Handle SOF Events 00487 00488 The function handles Start Of Frame events. It checks if there is pending 00489 data on the Bulk Out endpoint and handles it 00490 (USBD_CDC_ACM_EP_BULKOUT_HandleData) if there is enough space in the 00491 intermediate receive buffer and it calls received function callback 00492 (USBD_CDC_ACM_DataReceived) it also activates data send over the Bulk In 00493 endpoint if there is data to be sent (USBD_CDC_ACM_EP_BULKIN_HandleData). 00494 */ 00495 00496 void USBD_CDC_ACM_SOF_Event(void) 00497 { 00498 if (!USBD_Configuration) { 00499 // Don't process events until CDC is 00500 // configured and the endpoints enabled 00501 return; 00502 } 00503 if ((!data_read_access ) && /* If not read active */ 00504 (ptr_data_received == ptr_data_read ) && /* If received and read 00505 pointers point to same 00506 the location */ 00507 (ptr_data_received != USBD_CDC_ACM_ReceiveBuf)) { 00508 /* and if receive 00509 pointer does not already 00510 point to the start of 00511 the receive buffer */ 00512 data_read_access = 1; /* Block access to read data */ 00513 ptr_data_received = USBD_CDC_ACM_ReceiveBuf; /* Correct received pointer 00514 to point to the start of 00515 the receive buffer */ 00516 ptr_data_read = USBD_CDC_ACM_ReceiveBuf; /* Correct read pointer to 00517 point to the start of the 00518 receive buffer */ 00519 data_no_space_for_receive = 0; /* There is space for 00520 reception available */ 00521 data_read_access = 0; /* Allow access to read data */ 00522 } 00523 00524 if (data_received_pending_pckts && /* If packets are pending */ 00525 (!data_read_access ) && /* and if not read active */ 00526 (!data_no_space_for_receive )) { /* and if there is space to receive */ 00527 data_read_access = 1; /* Disable access to read data */ 00528 USBD_CDC_ACM_EP_BULKOUT_HandleData(); /* Handle received data */ 00529 data_read_access = 0; /* Enable access to read data */ 00530 00531 if (ptr_data_received != ptr_data_read ) { 00532 USBD_CDC_ACM_DataReceived(ptr_data_received - ptr_data_read ); 00533 } /* Call 00534 00535 received callback */ 00536 } 00537 00538 if ((!data_send_access ) && /* If send data is not being accessed */ 00539 (!data_send_active ) && /* and send is not active */ 00540 (data_to_send_wr - data_to_send_rd ) /* and if there is data to be sent */ 00541 //&& ((control_line_state & 3) == 3) /* and if DTR and RTS is 1 */ 00542 ) { 00543 data_send_access = 1; /* Block access to send data */ 00544 data_send_active = 1; /* Start data sending */ 00545 USBD_CDC_ACM_EP_BULKIN_HandleData();/* Handle data to send */ 00546 data_send_access = 0; /* Allow access to send data */ 00547 } 00548 } 00549 00550 00551 /** \brief Handle Interrupt In Endpoint Events 00552 00553 The function handles Interrupt In endpoint events. 00554 00555 \param [in] event Type of event (USBD_EVT_IN - input event). 00556 */ 00557 00558 void USBD_CDC_ACM_EP_INTIN_Event(uint32_t event) 00559 { 00560 /* Notification will be loadad aynchronously and sent automatically upon 00561 Interrupt IN token reception */ 00562 } 00563 00564 00565 /** \brief Handle Bulk Out Endpoint Received Data 00566 00567 The function handles data received on the Bulk Out endpoint. It reads the 00568 received data to the receive intermediate buffer if there is enough space 00569 available. 00570 */ 00571 00572 static void USBD_CDC_ACM_EP_BULKOUT_HandleData() 00573 { 00574 uint32_t len_free_to_recv; 00575 int32_t len_received; 00576 00577 if ((usbd_cdc_acm_receivebuf_sz - (ptr_data_received - USBD_CDC_ACM_ReceiveBuf)) >= usbd_cdc_acm_maxpacketsize1[USBD_HighSpeed]) { 00578 /* If there is space for 1 max packet */ 00579 /* Read received packet to receive buf*/ 00580 len_free_to_recv = usbd_cdc_acm_receivebuf_sz - (ptr_data_received - USBD_CDC_ACM_ReceiveBuf); 00581 len_received = USBD_ReadEP(usbd_cdc_acm_ep_bulkout, ptr_data_received , len_free_to_recv); 00582 ptr_data_received += len_received; /* Correct pointer to received data */ 00583 00584 if (data_received_pending_pckts && /* If packet was pending */ 00585 !data_receive_int_access ) { /* and not interrupt access */ 00586 data_received_pending_pckts --; /* Decrement pending packets number */ 00587 } 00588 } else { 00589 data_no_space_for_receive = 1; /* There is no space in receive buffer 00590 for the newly received data */ 00591 00592 if (data_receive_int_access ) { 00593 /* If this access is from interrupt 00594 function */ 00595 data_received_pending_pckts ++; /* then this is new unhandled packet */ 00596 } 00597 } 00598 } 00599 00600 00601 /** \brief Handle Bulk In Endpoint Data to Send 00602 00603 The function handles data to be sent on the Bulk In endpoint. It transmits 00604 pending data to be sent that is already in the send intermediate buffer, 00605 and it also sends Zero Length Packet if last packet sent was not a short 00606 packet. 00607 */ 00608 00609 static void USBD_CDC_ACM_EP_BULKIN_HandleData(void) 00610 { 00611 int32_t len_to_send, len_sent; 00612 00613 if (!data_send_active ) { /* If sending is not active */ 00614 return; 00615 } 00616 00617 len_to_send = data_to_send_wr - data_to_send_rd ; /* Num of data to send */ 00618 00619 /* Check if sending is finished */ 00620 if (!len_to_send && /* If all data was sent */ 00621 !data_send_zlp ) { /* and ZLP was sent if necessary also */ 00622 data_send_active = 0; /* Sending not active any more */ 00623 return; 00624 } 00625 00626 /* Check if data needs to be sent */ 00627 if (len_to_send) { 00628 /* If there is data available do be 00629 sent */ 00630 if ((ptr_data_sent >= ptr_data_to_send ) && /* If data before end of buf avail*/ 00631 ((ptr_data_sent + len_to_send) >= (USBD_CDC_ACM_SendBuf + usbd_cdc_acm_sendbuf_sz))) { 00632 /* and if available data wraps around 00633 the end of the send buffer */ 00634 /* Correct bytes to send to data 00635 available untill end of send buf */ 00636 len_to_send = USBD_CDC_ACM_SendBuf + usbd_cdc_acm_sendbuf_sz - ptr_data_sent ; 00637 } 00638 00639 if (len_to_send > usbd_cdc_acm_maxpacketsize1[USBD_HighSpeed]) { 00640 /* If 00641 there is more data to be sent then 00642 can be sent in a single packet */ 00643 /* Correct to send maximum pckt size */ 00644 len_to_send = usbd_cdc_acm_maxpacketsize1[USBD_HighSpeed]; 00645 } 00646 } else if (data_send_zlp ) { /* or if ZLP should be sent */ 00647 len_to_send = 0; 00648 } 00649 00650 data_send_zlp = 0; 00651 /* Send data */ 00652 len_sent = USBD_WriteEP(usbd_cdc_acm_ep_bulkin | 0x80, ptr_data_sent , len_to_send); 00653 ptr_data_sent += len_sent; /* Correct position of sent pointer */ 00654 data_to_send_rd += len_sent; /* Correct num of bytes left to send */ 00655 00656 if (ptr_data_sent == USBD_CDC_ACM_SendBuf + usbd_cdc_acm_sendbuf_sz) 00657 /* If pointer to sent data wraps */ 00658 { 00659 ptr_data_sent = USBD_CDC_ACM_SendBuf; 00660 } /* Correct it to beginning of send 00661 00662 buffer */ 00663 00664 if ((data_to_send_wr == data_to_send_rd) && /* If there are no more 00665 bytes available to be sent */ 00666 (len_sent == usbd_cdc_acm_maxpacketsize1[USBD_HighSpeed])) { 00667 /* If last packet size was same as 00668 maximum packet size */ 00669 data_send_zlp = 1; /* ZLP packet should be sent */ 00670 } else { 00671 data_send_zlp = 0; /* No ZLP packet should be sent */ 00672 } 00673 } 00674 00675 00676 /** \brief Handle Bulk Out Endpoint Events 00677 00678 The function handles Bulk Out endpoint events. It calls 00679 USBD_CDC_ACM_EP_BULKOUT_HandleData function to handle received data 00680 unless data was being accessed in which case function just acknowledges 00681 that there is data to be handled later. 00682 00683 \param [in] event Type of event (USBD_EVT_OUT - output event). 00684 */ 00685 00686 void USBD_CDC_ACM_EP_BULKOUT_Event(uint32_t event) 00687 { 00688 if (data_read_access ) { 00689 /* If data is being accessed from 00690 read function */ 00691 data_received_pending_pckts ++; /* 1 more packet received and not 00692 handled */ 00693 return; 00694 } 00695 00696 data_read_access = 1; /* Block access to read data */ 00697 data_receive_int_access = 1; /* Read access from interrupt function*/ 00698 USBD_CDC_ACM_EP_BULKOUT_HandleData(); /* Handle received data */ 00699 data_receive_int_access = 0; /* Read access from interrupt func end*/ 00700 data_read_access = 0; /* Allow access to read data */ 00701 00702 if (ptr_data_received != ptr_data_read ) { 00703 USBD_CDC_ACM_DataReceived(ptr_data_received - ptr_data_read ); 00704 } /* Call 00705 00706 received callback */ 00707 } 00708 00709 00710 /** \brief Handle Bulk In Endpoint Events 00711 00712 The function handles Bulk In endpoint events. It calls 00713 USBD_CDC_ACM_EP_BULKIN_HandleData function to handle send data 00714 unless data was being accessed in which case function just returns. 00715 00716 \param [in] event Type of event (USBD_EVT_IN - input event). 00717 */ 00718 00719 void USBD_CDC_ACM_EP_BULKIN_Event(uint32_t event) 00720 { 00721 if (data_send_access /* If send data is being accessed */ 00722 // ||((control_line_state & 3) != 3) /* or if DTR or RTS is 0 */ 00723 ) { 00724 return; 00725 } 00726 00727 data_send_access = 1; /* Block access to send data */ 00728 USBD_CDC_ACM_EP_BULKIN_HandleData(); /* Handle data to send */ 00729 data_send_access = 0; /* Allow access to send data */ 00730 } 00731 00732 00733 /** \brief Handle Bulk In/Out Endpoint Events 00734 00735 The function handles Bulk In/Out endpoint events. It is used for endpoints 00736 that do In and Out functionality on the same endpoint number. It dispatches 00737 events to appropriate In or Out event handlers. 00738 00739 \param [in] event Type of event ( 00740 USBD_EVT_IN - input event, 00741 USBD_EVT_OUT - output event). 00742 */ 00743 00744 void USBD_CDC_ACM_EP_BULK_Event(uint32_t event) 00745 { 00746 if (event & USBD_EVT_OUT) { 00747 USBD_CDC_ACM_EP_BULKOUT_Event(event); 00748 } 00749 00750 if (event & USBD_EVT_IN) { 00751 USBD_CDC_ACM_EP_BULKIN_Event(event); 00752 } 00753 } 00754 00755 00756 #ifdef __RTX /* RTX tasks for handling events */ 00757 00758 /** \brief Task Handling Interrupt In Endpoint Events 00759 00760 The task dispatches Interrupt In events to the Interrupt In handling 00761 function (USBD_CDC_ACM_EP_INTIN_Event). 00762 */ 00763 00764 void USBD_RTX_CDC_ACM_EP_INTIN_Event(void) 00765 { 00766 for (;;) { 00767 usbd_os_evt_wait_or(0xFFFF, 0xFFFF); 00768 USBD_CDC_ACM_EP_INTIN_Event(usbd_os_evt_get()); 00769 } 00770 } 00771 00772 00773 /** \brief Task Handling Bulk In Endpoint Events 00774 00775 The task dispatches Bulk In events to the Bulk In handling 00776 function (USBD_CDC_ACM_EP_BULKIN_Event). 00777 */ 00778 00779 void USBD_RTX_CDC_ACM_EP_BULKIN_Event(void) 00780 { 00781 for (;;) { 00782 usbd_os_evt_wait_or(0xFFFF, 0xFFFF); 00783 00784 if (usbd_os_evt_get() & USBD_EVT_IN) { 00785 USBD_CDC_ACM_EP_BULKIN_Event(0); 00786 } 00787 } 00788 } 00789 00790 00791 /** \brief Task Handling Bulk Out Endpoint Events 00792 00793 The task dispatches Bulk Out events to the Bulk Out handling 00794 function (USBD_CDC_ACM_EP_BULKOUT_Event). 00795 */ 00796 00797 void USBD_RTX_CDC_ACM_EP_BULKOUT_Event(void) 00798 { 00799 for (;;) { 00800 usbd_os_evt_wait_or(0xFFFF, 0xFFFF); 00801 00802 if (usbd_os_evt_get() & USBD_EVT_OUT) { 00803 USBD_CDC_ACM_EP_BULKOUT_Event(0); 00804 } 00805 } 00806 } 00807 00808 00809 /** \brief Task Handling Bulk In/Out Endpoint Events 00810 00811 The task dispatches Bulk In/Out events to the Bulk In/Out handling 00812 function (USBD_CDC_ACM_EP_BULK_Event). 00813 */ 00814 00815 void USBD_RTX_CDC_ACM_EP_BULK_Event(void) 00816 { 00817 for (;;) { 00818 usbd_os_evt_wait_or(0xFFFF, 0xFFFF); 00819 USBD_CDC_ACM_EP_BULK_Event(usbd_os_evt_get()); 00820 } 00821 } 00822 #endif 00823
Generated on Tue Jul 12 2022 15:37:26 by
1.7.2