Arrow / Mbed OS DAPLink Reset
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers usbd_cdc_acm.c Source File

usbd_cdc_acm.c

Go to the documentation of this file.
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