Repostiory containing DAPLink source code with Reset Pin workaround for HANI_IOT board.

Upstream: https://github.com/ARMmbed/DAPLink

Committer:
Pawel Zarembski
Date:
Tue Apr 07 12:55:42 2020 +0200
Revision:
0:01f31e923fe2
hani: DAPLink with reset workaround

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Pawel Zarembski 0:01f31e923fe2 1 /**
Pawel Zarembski 0:01f31e923fe2 2 * @file usbd_cdc_acm.c
Pawel Zarembski 0:01f31e923fe2 3 * @brief Communication Device Class driver
Pawel Zarembski 0:01f31e923fe2 4 *
Pawel Zarembski 0:01f31e923fe2 5 * DAPLink Interface Firmware
Pawel Zarembski 0:01f31e923fe2 6 * Copyright (c) 2009-2016, ARM Limited, All Rights Reserved
Pawel Zarembski 0:01f31e923fe2 7 * SPDX-License-Identifier: Apache-2.0
Pawel Zarembski 0:01f31e923fe2 8 *
Pawel Zarembski 0:01f31e923fe2 9 * Licensed under the Apache License, Version 2.0 (the "License"); you may
Pawel Zarembski 0:01f31e923fe2 10 * not use this file except in compliance with the License.
Pawel Zarembski 0:01f31e923fe2 11 * You may obtain a copy of the License at
Pawel Zarembski 0:01f31e923fe2 12 *
Pawel Zarembski 0:01f31e923fe2 13 * http://www.apache.org/licenses/LICENSE-2.0
Pawel Zarembski 0:01f31e923fe2 14 *
Pawel Zarembski 0:01f31e923fe2 15 * Unless required by applicable law or agreed to in writing, software
Pawel Zarembski 0:01f31e923fe2 16 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
Pawel Zarembski 0:01f31e923fe2 17 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Pawel Zarembski 0:01f31e923fe2 18 * See the License for the specific language governing permissions and
Pawel Zarembski 0:01f31e923fe2 19 * limitations under the License.
Pawel Zarembski 0:01f31e923fe2 20 */
Pawel Zarembski 0:01f31e923fe2 21
Pawel Zarembski 0:01f31e923fe2 22 #include <string.h>
Pawel Zarembski 0:01f31e923fe2 23
Pawel Zarembski 0:01f31e923fe2 24 #include "rl_usb.h"
Pawel Zarembski 0:01f31e923fe2 25 #include "usb_for_lib.h"
Pawel Zarembski 0:01f31e923fe2 26
Pawel Zarembski 0:01f31e923fe2 27
Pawel Zarembski 0:01f31e923fe2 28 /* Module global variables */
Pawel Zarembski 0:01f31e923fe2 29
Pawel Zarembski 0:01f31e923fe2 30 /** \ingroup USBD_CDC_ACM_global_variables
Pawel Zarembski 0:01f31e923fe2 31 \defgroup USBD_CDC_ACM_GLOBAL_VAR Global Variables (GLOBAL_VAR)
Pawel Zarembski 0:01f31e923fe2 32 \brief Global variables used in USBD CDC ACM module
Pawel Zarembski 0:01f31e923fe2 33 */
Pawel Zarembski 0:01f31e923fe2 34 int32_t data_send_access; /*!< Flag active while send data (in the send intermediate buffer) is being accessed */
Pawel Zarembski 0:01f31e923fe2 35 int32_t data_send_active; /*!< Flag active while data is being sent */
Pawel Zarembski 0:01f31e923fe2 36 int32_t data_send_zlp; /*!< Flag active when ZLP needs to be sent */
Pawel Zarembski 0:01f31e923fe2 37 int32_t data_to_send_wr; /*!< Number of bytes written to the send intermediate buffer */
Pawel Zarembski 0:01f31e923fe2 38 int32_t data_to_send_rd; /*!< Number of bytes read from the send intermediate buffer */
Pawel Zarembski 0:01f31e923fe2 39 uint8_t *ptr_data_to_send; /*!< Pointer to the send intermediate buffer to the data to be sent */
Pawel Zarembski 0:01f31e923fe2 40 uint8_t *ptr_data_sent; /*!< Pointer to the send intermediate buffer to the data already sent */
Pawel Zarembski 0:01f31e923fe2 41
Pawel Zarembski 0:01f31e923fe2 42 int32_t data_read_access; /*!< Flag active while read data (in the receive intermediate buffer) is being accessed */
Pawel Zarembski 0:01f31e923fe2 43 int32_t data_receive_int_access; /*!< Flag active while read data (in the receive intermediate buffer) is being accessed from the IRQ function*/
Pawel Zarembski 0:01f31e923fe2 44 int32_t data_received_pending_pckts; /*!< Number of packets received but not handled (pending) */
Pawel Zarembski 0:01f31e923fe2 45 int32_t data_no_space_for_receive; /*!< Flag active while there is no more space for reception */
Pawel Zarembski 0:01f31e923fe2 46 uint8_t *ptr_data_received; /*!< Pointer to the receive intermediate buffer to the received unread data */
Pawel Zarembski 0:01f31e923fe2 47 uint8_t *ptr_data_read; /*!< Pointer to the receive intermediate buffer to the received read data */
Pawel Zarembski 0:01f31e923fe2 48
Pawel Zarembski 0:01f31e923fe2 49 uint16_t control_line_state; /*!< Control line state settings bitmap (0. bit - DTR state, 1. bit - RTS state) */
Pawel Zarembski 0:01f31e923fe2 50
Pawel Zarembski 0:01f31e923fe2 51 CDC_LINE_CODING line_coding; /*!< Communication settings */
Pawel Zarembski 0:01f31e923fe2 52
Pawel Zarembski 0:01f31e923fe2 53 /* end of group USBD_CDC_ACM_GLOBAL_VAR */
Pawel Zarembski 0:01f31e923fe2 54
Pawel Zarembski 0:01f31e923fe2 55
Pawel Zarembski 0:01f31e923fe2 56 /* Functions that should be provided by user to use standard Virtual COM port
Pawel Zarembski 0:01f31e923fe2 57 functionality */
Pawel Zarembski 0:01f31e923fe2 58 __weak int32_t USBD_CDC_ACM_PortInitialize(void)
Pawel Zarembski 0:01f31e923fe2 59 {
Pawel Zarembski 0:01f31e923fe2 60 return (0);
Pawel Zarembski 0:01f31e923fe2 61 }
Pawel Zarembski 0:01f31e923fe2 62 __weak int32_t USBD_CDC_ACM_PortUninitialize(void)
Pawel Zarembski 0:01f31e923fe2 63 {
Pawel Zarembski 0:01f31e923fe2 64 return (0);
Pawel Zarembski 0:01f31e923fe2 65 }
Pawel Zarembski 0:01f31e923fe2 66 __weak int32_t USBD_CDC_ACM_PortReset(void)
Pawel Zarembski 0:01f31e923fe2 67 {
Pawel Zarembski 0:01f31e923fe2 68 return (0);
Pawel Zarembski 0:01f31e923fe2 69 }
Pawel Zarembski 0:01f31e923fe2 70 __weak int32_t USBD_CDC_ACM_PortSetLineCoding(CDC_LINE_CODING *line_coding)
Pawel Zarembski 0:01f31e923fe2 71 {
Pawel Zarembski 0:01f31e923fe2 72 return (0);
Pawel Zarembski 0:01f31e923fe2 73 }
Pawel Zarembski 0:01f31e923fe2 74 __weak int32_t USBD_CDC_ACM_PortGetLineCoding(CDC_LINE_CODING *line_coding)
Pawel Zarembski 0:01f31e923fe2 75 {
Pawel Zarembski 0:01f31e923fe2 76 return (0);
Pawel Zarembski 0:01f31e923fe2 77 }
Pawel Zarembski 0:01f31e923fe2 78 __weak int32_t USBD_CDC_ACM_PortSetControlLineState(uint16_t ctrl_bmp)
Pawel Zarembski 0:01f31e923fe2 79 {
Pawel Zarembski 0:01f31e923fe2 80 return (0);
Pawel Zarembski 0:01f31e923fe2 81 }
Pawel Zarembski 0:01f31e923fe2 82
Pawel Zarembski 0:01f31e923fe2 83 /* Functions that can be used by user to use standard Virtual COM port
Pawel Zarembski 0:01f31e923fe2 84 functionality */
Pawel Zarembski 0:01f31e923fe2 85 int32_t USBD_CDC_ACM_DataSend(const uint8_t *buf, int32_t len);
Pawel Zarembski 0:01f31e923fe2 86 int32_t USBD_CDC_ACM_PutChar(const uint8_t ch);
Pawel Zarembski 0:01f31e923fe2 87 int32_t USBD_CDC_ACM_DataRead(uint8_t *buf, int32_t len);
Pawel Zarembski 0:01f31e923fe2 88 int32_t USBD_CDC_ACM_GetChar(void);
Pawel Zarembski 0:01f31e923fe2 89 __weak int32_t USBD_CDC_ACM_DataReceived(int32_t len)
Pawel Zarembski 0:01f31e923fe2 90 {
Pawel Zarembski 0:01f31e923fe2 91 return (0);
Pawel Zarembski 0:01f31e923fe2 92 }
Pawel Zarembski 0:01f31e923fe2 93 int32_t USBD_CDC_ACM_DataAvailable(void);
Pawel Zarembski 0:01f31e923fe2 94 int32_t USBD_CDC_ACM_Notify(uint16_t stat);
Pawel Zarembski 0:01f31e923fe2 95
Pawel Zarembski 0:01f31e923fe2 96 /* Functions handling CDC ACM requests (can be overridden to provide custom
Pawel Zarembski 0:01f31e923fe2 97 handling of CDC ACM requests) */
Pawel Zarembski 0:01f31e923fe2 98 __weak int32_t USBD_CDC_ACM_SendEncapsulatedCommand(void)
Pawel Zarembski 0:01f31e923fe2 99 {
Pawel Zarembski 0:01f31e923fe2 100 return (0);
Pawel Zarembski 0:01f31e923fe2 101 }
Pawel Zarembski 0:01f31e923fe2 102 __weak int32_t USBD_CDC_ACM_GetEncapsulatedResponse(void)
Pawel Zarembski 0:01f31e923fe2 103 {
Pawel Zarembski 0:01f31e923fe2 104 return (0);
Pawel Zarembski 0:01f31e923fe2 105 }
Pawel Zarembski 0:01f31e923fe2 106 __weak int32_t USBD_CDC_ACM_SetCommFeature(uint16_t feat)
Pawel Zarembski 0:01f31e923fe2 107 {
Pawel Zarembski 0:01f31e923fe2 108 return (0);
Pawel Zarembski 0:01f31e923fe2 109 }
Pawel Zarembski 0:01f31e923fe2 110 __weak int32_t USBD_CDC_ACM_GetCommFeature(uint16_t feat)
Pawel Zarembski 0:01f31e923fe2 111 {
Pawel Zarembski 0:01f31e923fe2 112 return (0);
Pawel Zarembski 0:01f31e923fe2 113 }
Pawel Zarembski 0:01f31e923fe2 114 __weak int32_t USBD_CDC_ACM_ClearCommFeature(uint16_t feat)
Pawel Zarembski 0:01f31e923fe2 115 {
Pawel Zarembski 0:01f31e923fe2 116 return (0);
Pawel Zarembski 0:01f31e923fe2 117 }
Pawel Zarembski 0:01f31e923fe2 118 __weak int32_t USBD_CDC_ACM_SendBreak(uint16_t dur)
Pawel Zarembski 0:01f31e923fe2 119 {
Pawel Zarembski 0:01f31e923fe2 120 return (0);
Pawel Zarembski 0:01f31e923fe2 121 }
Pawel Zarembski 0:01f31e923fe2 122
Pawel Zarembski 0:01f31e923fe2 123
Pawel Zarembski 0:01f31e923fe2 124 /* Local function prototypes */
Pawel Zarembski 0:01f31e923fe2 125 static void USBD_CDC_ACM_EP_BULKOUT_HandleData(void);
Pawel Zarembski 0:01f31e923fe2 126 static void USBD_CDC_ACM_EP_BULKIN_HandleData(void);
Pawel Zarembski 0:01f31e923fe2 127
Pawel Zarembski 0:01f31e923fe2 128
Pawel Zarembski 0:01f31e923fe2 129 /*----------------- USB CDC ACM class handling functions ---------------------*/
Pawel Zarembski 0:01f31e923fe2 130
Pawel Zarembski 0:01f31e923fe2 131 /** \brief Initialization of the USB CDC class (ACM)
Pawel Zarembski 0:01f31e923fe2 132
Pawel Zarembski 0:01f31e923fe2 133 The function calls USBD_CDC_ACM_PortInitialize function which
Pawel Zarembski 0:01f31e923fe2 134 initializes Virtual COM Port.
Pawel Zarembski 0:01f31e923fe2 135
Pawel Zarembski 0:01f31e923fe2 136 \return 0 Function failed.
Pawel Zarembski 0:01f31e923fe2 137 \return 1 Function succeeded.
Pawel Zarembski 0:01f31e923fe2 138 */
Pawel Zarembski 0:01f31e923fe2 139
Pawel Zarembski 0:01f31e923fe2 140 __weak int32_t USBD_CDC_ACM_Initialize(void)
Pawel Zarembski 0:01f31e923fe2 141 {
Pawel Zarembski 0:01f31e923fe2 142 data_send_access = 0;
Pawel Zarembski 0:01f31e923fe2 143 data_send_active = 0;
Pawel Zarembski 0:01f31e923fe2 144 data_send_zlp = 0;
Pawel Zarembski 0:01f31e923fe2 145 data_to_send_wr = 0;
Pawel Zarembski 0:01f31e923fe2 146 data_to_send_rd = 0;
Pawel Zarembski 0:01f31e923fe2 147 ptr_data_to_send = USBD_CDC_ACM_SendBuf;
Pawel Zarembski 0:01f31e923fe2 148 ptr_data_sent = USBD_CDC_ACM_SendBuf;
Pawel Zarembski 0:01f31e923fe2 149 data_read_access = 0;
Pawel Zarembski 0:01f31e923fe2 150 data_receive_int_access = 0;
Pawel Zarembski 0:01f31e923fe2 151 data_received_pending_pckts = 0;
Pawel Zarembski 0:01f31e923fe2 152 data_no_space_for_receive = 0;
Pawel Zarembski 0:01f31e923fe2 153 ptr_data_received = USBD_CDC_ACM_ReceiveBuf;
Pawel Zarembski 0:01f31e923fe2 154 ptr_data_read = USBD_CDC_ACM_ReceiveBuf;
Pawel Zarembski 0:01f31e923fe2 155 control_line_state = 0;
Pawel Zarembski 0:01f31e923fe2 156 line_coding.dwDTERate = 9600;
Pawel Zarembski 0:01f31e923fe2 157 line_coding.bCharFormat = 0;
Pawel Zarembski 0:01f31e923fe2 158 line_coding.bParityType = 0;
Pawel Zarembski 0:01f31e923fe2 159 line_coding.bDataBits = 8;
Pawel Zarembski 0:01f31e923fe2 160 return (USBD_CDC_ACM_PortInitialize());
Pawel Zarembski 0:01f31e923fe2 161 }
Pawel Zarembski 0:01f31e923fe2 162
Pawel Zarembski 0:01f31e923fe2 163
Pawel Zarembski 0:01f31e923fe2 164 /** \brief Uninitialization of the USB CDC class (ACM)
Pawel Zarembski 0:01f31e923fe2 165
Pawel Zarembski 0:01f31e923fe2 166 The function calls USBD_CDC_ACM_PortUninitialize function which
Pawel Zarembski 0:01f31e923fe2 167 uninitializes Virtual COM Port.
Pawel Zarembski 0:01f31e923fe2 168
Pawel Zarembski 0:01f31e923fe2 169 \return 0 Function failed.
Pawel Zarembski 0:01f31e923fe2 170 \return 1 Function succeeded.
Pawel Zarembski 0:01f31e923fe2 171 */
Pawel Zarembski 0:01f31e923fe2 172
Pawel Zarembski 0:01f31e923fe2 173 __weak int32_t USBD_CDC_ACM_Uninitialization(void)
Pawel Zarembski 0:01f31e923fe2 174 {
Pawel Zarembski 0:01f31e923fe2 175 return (USBD_CDC_ACM_PortUninitialize());
Pawel Zarembski 0:01f31e923fe2 176 }
Pawel Zarembski 0:01f31e923fe2 177
Pawel Zarembski 0:01f31e923fe2 178
Pawel Zarembski 0:01f31e923fe2 179 /** \brief Reset of the USB CDC class (ACM) variables and states
Pawel Zarembski 0:01f31e923fe2 180
Pawel Zarembski 0:01f31e923fe2 181 The function resets class variables and states, it calls
Pawel Zarembski 0:01f31e923fe2 182 USBD_CDC_ACM_PortReset function which resets Virtual COM Port variables
Pawel Zarembski 0:01f31e923fe2 183 and states and calls USBD_CDC_ACM_PortSetLineCoding function with
Pawel Zarembski 0:01f31e923fe2 184 default parameters to set default communication settings for the
Pawel Zarembski 0:01f31e923fe2 185 Virtual COM Port.
Pawel Zarembski 0:01f31e923fe2 186
Pawel Zarembski 0:01f31e923fe2 187 \return 0 Function failed.
Pawel Zarembski 0:01f31e923fe2 188 \return 1 Function succeeded.
Pawel Zarembski 0:01f31e923fe2 189 */
Pawel Zarembski 0:01f31e923fe2 190
Pawel Zarembski 0:01f31e923fe2 191 __weak int32_t USBD_CDC_ACM_Reset(void)
Pawel Zarembski 0:01f31e923fe2 192 {
Pawel Zarembski 0:01f31e923fe2 193 data_send_access = 0;
Pawel Zarembski 0:01f31e923fe2 194 data_send_active = 0;
Pawel Zarembski 0:01f31e923fe2 195 data_send_zlp = 0;
Pawel Zarembski 0:01f31e923fe2 196 data_to_send_wr = 0;
Pawel Zarembski 0:01f31e923fe2 197 data_to_send_rd = 0;
Pawel Zarembski 0:01f31e923fe2 198 ptr_data_to_send = USBD_CDC_ACM_SendBuf;
Pawel Zarembski 0:01f31e923fe2 199 ptr_data_sent = USBD_CDC_ACM_SendBuf;
Pawel Zarembski 0:01f31e923fe2 200 data_read_access = 0;
Pawel Zarembski 0:01f31e923fe2 201 data_receive_int_access = 0;
Pawel Zarembski 0:01f31e923fe2 202 data_received_pending_pckts = 0;
Pawel Zarembski 0:01f31e923fe2 203 data_no_space_for_receive = 0;
Pawel Zarembski 0:01f31e923fe2 204 ptr_data_received = USBD_CDC_ACM_ReceiveBuf;
Pawel Zarembski 0:01f31e923fe2 205 ptr_data_read = USBD_CDC_ACM_ReceiveBuf;
Pawel Zarembski 0:01f31e923fe2 206 control_line_state = 0;
Pawel Zarembski 0:01f31e923fe2 207 USBD_CDC_ACM_PortReset();
Pawel Zarembski 0:01f31e923fe2 208 line_coding.dwDTERate = 9600;
Pawel Zarembski 0:01f31e923fe2 209 line_coding.bCharFormat = 0;
Pawel Zarembski 0:01f31e923fe2 210 line_coding.bParityType = 0;
Pawel Zarembski 0:01f31e923fe2 211 line_coding.bDataBits = 8;
Pawel Zarembski 0:01f31e923fe2 212 return (USBD_CDC_ACM_PortSetLineCoding(&line_coding));
Pawel Zarembski 0:01f31e923fe2 213 }
Pawel Zarembski 0:01f31e923fe2 214
Pawel Zarembski 0:01f31e923fe2 215
Pawel Zarembski 0:01f31e923fe2 216 /** \brief Sets Line Coding for the USB CDC ACM Virtual COM Port
Pawel Zarembski 0:01f31e923fe2 217
Pawel Zarembski 0:01f31e923fe2 218 The function is a callback function that forwards USB CDC ACM request
Pawel Zarembski 0:01f31e923fe2 219 to set communication settings to the Virtual COM Port.
Pawel Zarembski 0:01f31e923fe2 220
Pawel Zarembski 0:01f31e923fe2 221 \return 0 Function failed.
Pawel Zarembski 0:01f31e923fe2 222 \return 1 Function succeeded.
Pawel Zarembski 0:01f31e923fe2 223 */
Pawel Zarembski 0:01f31e923fe2 224
Pawel Zarembski 0:01f31e923fe2 225 __weak int32_t USBD_CDC_ACM_SetLineCoding(void)
Pawel Zarembski 0:01f31e923fe2 226 {
Pawel Zarembski 0:01f31e923fe2 227 line_coding.dwDTERate = (USBD_EP0Buf[0] << 0) |
Pawel Zarembski 0:01f31e923fe2 228 (USBD_EP0Buf[1] << 8) |
Pawel Zarembski 0:01f31e923fe2 229 (USBD_EP0Buf[2] << 16) |
Pawel Zarembski 0:01f31e923fe2 230 (USBD_EP0Buf[3] << 24) ;
Pawel Zarembski 0:01f31e923fe2 231 line_coding.bCharFormat = USBD_EP0Buf[4];
Pawel Zarembski 0:01f31e923fe2 232 line_coding.bParityType = USBD_EP0Buf[5];
Pawel Zarembski 0:01f31e923fe2 233 line_coding.bDataBits = USBD_EP0Buf[6];
Pawel Zarembski 0:01f31e923fe2 234 return (USBD_CDC_ACM_PortSetLineCoding(&line_coding));
Pawel Zarembski 0:01f31e923fe2 235 }
Pawel Zarembski 0:01f31e923fe2 236
Pawel Zarembski 0:01f31e923fe2 237
Pawel Zarembski 0:01f31e923fe2 238 /** \brief Gets Line Coding from the USB CDC ACM Virtual COM Port
Pawel Zarembski 0:01f31e923fe2 239
Pawel Zarembski 0:01f31e923fe2 240 The function is a callback function that forwards USB CDC ACM request
Pawel Zarembski 0:01f31e923fe2 241 to get communication settings from the Virtual COM Port.
Pawel Zarembski 0:01f31e923fe2 242
Pawel Zarembski 0:01f31e923fe2 243 \return 0 Function failed.
Pawel Zarembski 0:01f31e923fe2 244 \return 1 Function succeeded.
Pawel Zarembski 0:01f31e923fe2 245 */
Pawel Zarembski 0:01f31e923fe2 246
Pawel Zarembski 0:01f31e923fe2 247 __weak int32_t USBD_CDC_ACM_GetLineCoding(void)
Pawel Zarembski 0:01f31e923fe2 248 {
Pawel Zarembski 0:01f31e923fe2 249 if (USBD_CDC_ACM_PortGetLineCoding(&line_coding)) {
Pawel Zarembski 0:01f31e923fe2 250 USBD_EP0Buf[0] = (line_coding.dwDTERate >> 0) & 0xFF;
Pawel Zarembski 0:01f31e923fe2 251 USBD_EP0Buf[1] = (line_coding.dwDTERate >> 8) & 0xFF;
Pawel Zarembski 0:01f31e923fe2 252 USBD_EP0Buf[2] = (line_coding.dwDTERate >> 16) & 0xFF;
Pawel Zarembski 0:01f31e923fe2 253 USBD_EP0Buf[3] = (line_coding.dwDTERate >> 24) & 0xFF;
Pawel Zarembski 0:01f31e923fe2 254 USBD_EP0Buf[4] = line_coding.bCharFormat;
Pawel Zarembski 0:01f31e923fe2 255 USBD_EP0Buf[5] = line_coding.bParityType;
Pawel Zarembski 0:01f31e923fe2 256 USBD_EP0Buf[6] = line_coding.bDataBits;
Pawel Zarembski 0:01f31e923fe2 257 return (1);
Pawel Zarembski 0:01f31e923fe2 258 }
Pawel Zarembski 0:01f31e923fe2 259
Pawel Zarembski 0:01f31e923fe2 260 return (0);
Pawel Zarembski 0:01f31e923fe2 261 }
Pawel Zarembski 0:01f31e923fe2 262
Pawel Zarembski 0:01f31e923fe2 263
Pawel Zarembski 0:01f31e923fe2 264 /** \brief Sets Control Line State for the USB CDC ACM Virtual COM Port
Pawel Zarembski 0:01f31e923fe2 265
Pawel Zarembski 0:01f31e923fe2 266 The function is a callback function that forwards USB CDC ACM request
Pawel Zarembski 0:01f31e923fe2 267 to set desired control line state to the Virtual COM Port.
Pawel Zarembski 0:01f31e923fe2 268
Pawel Zarembski 0:01f31e923fe2 269 \param [in] ctrl_bmp Control line settings bitmap (
Pawel Zarembski 0:01f31e923fe2 270 0. bit - DTR state,
Pawel Zarembski 0:01f31e923fe2 271 1. bit - RTS state).
Pawel Zarembski 0:01f31e923fe2 272 \return 0 Function failed.
Pawel Zarembski 0:01f31e923fe2 273 \return 1 Function succeeded.
Pawel Zarembski 0:01f31e923fe2 274 */
Pawel Zarembski 0:01f31e923fe2 275
Pawel Zarembski 0:01f31e923fe2 276 __weak int32_t USBD_CDC_ACM_SetControlLineState(uint16_t ctrl_bmp)
Pawel Zarembski 0:01f31e923fe2 277 {
Pawel Zarembski 0:01f31e923fe2 278 control_line_state = ctrl_bmp;
Pawel Zarembski 0:01f31e923fe2 279 return (USBD_CDC_ACM_PortSetControlLineState(ctrl_bmp));
Pawel Zarembski 0:01f31e923fe2 280 }
Pawel Zarembski 0:01f31e923fe2 281
Pawel Zarembski 0:01f31e923fe2 282
Pawel Zarembski 0:01f31e923fe2 283 /*----------------- USB CDC ACM user API functions ---------------------------*/
Pawel Zarembski 0:01f31e923fe2 284
Pawel Zarembski 0:01f31e923fe2 285 /** \brief Number of free bytes in the Send buffer
Pawel Zarembski 0:01f31e923fe2 286 */
Pawel Zarembski 0:01f31e923fe2 287 int32_t USBD_CDC_ACM_DataFree(void)
Pawel Zarembski 0:01f31e923fe2 288 {
Pawel Zarembski 0:01f31e923fe2 289 return ((int32_t)usbd_cdc_acm_sendbuf_sz) - (data_to_send_wr - data_to_send_rd);
Pawel Zarembski 0:01f31e923fe2 290 }
Pawel Zarembski 0:01f31e923fe2 291
Pawel Zarembski 0:01f31e923fe2 292 /** \brief Sends data over the USB CDC ACM Virtual COM Port
Pawel Zarembski 0:01f31e923fe2 293
Pawel Zarembski 0:01f31e923fe2 294 The function puts requested data to the send intermediate buffer and
Pawel Zarembski 0:01f31e923fe2 295 prepares it for sending over the Virtual COM Port.
Pawel Zarembski 0:01f31e923fe2 296
Pawel Zarembski 0:01f31e923fe2 297 \param [in] buf Buffer containing data to be sent.
Pawel Zarembski 0:01f31e923fe2 298 \param [in] len Maximum number of bytes to be sent.
Pawel Zarembski 0:01f31e923fe2 299 \return Number of bytes accepted to be sent.
Pawel Zarembski 0:01f31e923fe2 300 */
Pawel Zarembski 0:01f31e923fe2 301
Pawel Zarembski 0:01f31e923fe2 302 int32_t USBD_CDC_ACM_DataSend(const uint8_t *buf, int32_t len)
Pawel Zarembski 0:01f31e923fe2 303 {
Pawel Zarembski 0:01f31e923fe2 304 int32_t len_data, len_available, len_before_wrap;
Pawel Zarembski 0:01f31e923fe2 305 uint8_t *buf_loc;
Pawel Zarembski 0:01f31e923fe2 306 buf_loc = (uint8_t *)buf; /* Pointer to buf */
Pawel Zarembski 0:01f31e923fe2 307 len_data = data_to_send_wr - data_to_send_rd; /* Num of data in buffer*/
Pawel Zarembski 0:01f31e923fe2 308 len_available = ((int32_t)usbd_cdc_acm_sendbuf_sz) - len_data; /* Num of
Pawel Zarembski 0:01f31e923fe2 309 bytes of space available */
Pawel Zarembski 0:01f31e923fe2 310
Pawel Zarembski 0:01f31e923fe2 311 if (len_available <= 0) { /* If no space for data to send */
Pawel Zarembski 0:01f31e923fe2 312 return (0);
Pawel Zarembski 0:01f31e923fe2 313 }
Pawel Zarembski 0:01f31e923fe2 314
Pawel Zarembski 0:01f31e923fe2 315 if (len > len_available) /* If more data requested for sending
Pawel Zarembski 0:01f31e923fe2 316 then available space */
Pawel Zarembski 0:01f31e923fe2 317 {
Pawel Zarembski 0:01f31e923fe2 318 len = len_available; /* Correct to maximum available */
Pawel Zarembski 0:01f31e923fe2 319 }
Pawel Zarembski 0:01f31e923fe2 320
Pawel Zarembski 0:01f31e923fe2 321 len_before_wrap = 0; /* Circular buffer size before wrap */
Pawel Zarembski 0:01f31e923fe2 322
Pawel Zarembski 0:01f31e923fe2 323 if ((ptr_data_to_send >= ptr_data_sent) && /* If wrap is possible to happen */
Pawel Zarembski 0:01f31e923fe2 324 ((ptr_data_to_send + len) >= (USBD_CDC_ACM_SendBuf + usbd_cdc_acm_sendbuf_sz))) {
Pawel Zarembski 0:01f31e923fe2 325 /* If data wraps around end of buffer */
Pawel Zarembski 0:01f31e923fe2 326 len_before_wrap = USBD_CDC_ACM_SendBuf + usbd_cdc_acm_sendbuf_sz - ptr_data_to_send;
Pawel Zarembski 0:01f31e923fe2 327 memcpy(ptr_data_to_send, buf_loc, len_before_wrap); /* Copy data till end */
Pawel Zarembski 0:01f31e923fe2 328 buf_loc += len_before_wrap; /* Increment buf pointer */
Pawel Zarembski 0:01f31e923fe2 329 len -= len_before_wrap; /* Decrement bytes to send*/
Pawel Zarembski 0:01f31e923fe2 330 ptr_data_to_send = USBD_CDC_ACM_SendBuf; /* Wrap send buffer
Pawel Zarembski 0:01f31e923fe2 331 pointer to beginning of
Pawel Zarembski 0:01f31e923fe2 332 the send buffer */
Pawel Zarembski 0:01f31e923fe2 333 }
Pawel Zarembski 0:01f31e923fe2 334
Pawel Zarembski 0:01f31e923fe2 335 if (len) { /* If there are bytes to send */
Pawel Zarembski 0:01f31e923fe2 336 memcpy(ptr_data_to_send, buf_loc, len); /* Copy data to send buffer */
Pawel Zarembski 0:01f31e923fe2 337 ptr_data_to_send += len; /* Correct position of write pointer */
Pawel Zarembski 0:01f31e923fe2 338 }
Pawel Zarembski 0:01f31e923fe2 339
Pawel Zarembski 0:01f31e923fe2 340 len += len_before_wrap; /* Total number of bytes prepared for
Pawel Zarembski 0:01f31e923fe2 341 send */
Pawel Zarembski 0:01f31e923fe2 342 data_to_send_wr += len; /* Bytes prepared to send counter */
Pawel Zarembski 0:01f31e923fe2 343 return (len); /* Number of bytes accepted for send */
Pawel Zarembski 0:01f31e923fe2 344 }
Pawel Zarembski 0:01f31e923fe2 345
Pawel Zarembski 0:01f31e923fe2 346
Pawel Zarembski 0:01f31e923fe2 347 /** \brief Sends a single character over the USB CDC ACM Virtual COM Port
Pawel Zarembski 0:01f31e923fe2 348
Pawel Zarembski 0:01f31e923fe2 349 The function puts requested data character to the send intermediate buffer
Pawel Zarembski 0:01f31e923fe2 350 and prepares it for sending over the Virtual COM Port.
Pawel Zarembski 0:01f31e923fe2 351
Pawel Zarembski 0:01f31e923fe2 352 \param [in] ch Character to be sent.
Pawel Zarembski 0:01f31e923fe2 353 \return -1 Function failed.
Pawel Zarembski 0:01f31e923fe2 354 \return Character accepted to be sent.
Pawel Zarembski 0:01f31e923fe2 355 */
Pawel Zarembski 0:01f31e923fe2 356
Pawel Zarembski 0:01f31e923fe2 357 int32_t USBD_CDC_ACM_PutChar(const uint8_t ch)
Pawel Zarembski 0:01f31e923fe2 358 {
Pawel Zarembski 0:01f31e923fe2 359 if ((USBD_CDC_ACM_DataSend(&ch, 1)) == 1) {
Pawel Zarembski 0:01f31e923fe2 360 return ((uint32_t) ch);
Pawel Zarembski 0:01f31e923fe2 361 }
Pawel Zarembski 0:01f31e923fe2 362
Pawel Zarembski 0:01f31e923fe2 363 return (-1);
Pawel Zarembski 0:01f31e923fe2 364 }
Pawel Zarembski 0:01f31e923fe2 365
Pawel Zarembski 0:01f31e923fe2 366
Pawel Zarembski 0:01f31e923fe2 367 /** \brief Reads data received over the USB CDC ACM Virtual COM Port
Pawel Zarembski 0:01f31e923fe2 368
Pawel Zarembski 0:01f31e923fe2 369 The function reads data from the receive intermediate buffer that was
Pawel Zarembski 0:01f31e923fe2 370 received over the Virtual COM Port.
Pawel Zarembski 0:01f31e923fe2 371
Pawel Zarembski 0:01f31e923fe2 372 \param [in] buf Buffer to where data will be read.
Pawel Zarembski 0:01f31e923fe2 373 \param [in] len Maximum number of bytes to be read.
Pawel Zarembski 0:01f31e923fe2 374 \return Number of bytes actually read.
Pawel Zarembski 0:01f31e923fe2 375 */
Pawel Zarembski 0:01f31e923fe2 376
Pawel Zarembski 0:01f31e923fe2 377 int32_t USBD_CDC_ACM_DataRead(uint8_t *buf, int32_t len)
Pawel Zarembski 0:01f31e923fe2 378 {
Pawel Zarembski 0:01f31e923fe2 379 int32_t len_data;
Pawel Zarembski 0:01f31e923fe2 380
Pawel Zarembski 0:01f31e923fe2 381 if (ptr_data_received > ptr_data_read) { /*If there is already received data */
Pawel Zarembski 0:01f31e923fe2 382 len_data = ptr_data_received - ptr_data_read; /* Available bytes of data */
Pawel Zarembski 0:01f31e923fe2 383
Pawel Zarembski 0:01f31e923fe2 384 if (len > len_data) { /* If more requested then available */
Pawel Zarembski 0:01f31e923fe2 385 len = len_data; /* correct to return maximum available*/
Pawel Zarembski 0:01f31e923fe2 386 }
Pawel Zarembski 0:01f31e923fe2 387
Pawel Zarembski 0:01f31e923fe2 388 memcpy(buf, ptr_data_read, len); /* Copy received data to provided buf */
Pawel Zarembski 0:01f31e923fe2 389 ptr_data_read += len; /* Correct position of read pointer */
Pawel Zarembski 0:01f31e923fe2 390 } else {
Pawel Zarembski 0:01f31e923fe2 391 len = 0; /* No data received */
Pawel Zarembski 0:01f31e923fe2 392 }
Pawel Zarembski 0:01f31e923fe2 393
Pawel Zarembski 0:01f31e923fe2 394 return (len); /* Number of bytes actually read */
Pawel Zarembski 0:01f31e923fe2 395 }
Pawel Zarembski 0:01f31e923fe2 396
Pawel Zarembski 0:01f31e923fe2 397
Pawel Zarembski 0:01f31e923fe2 398 /** \brief Reads one character of data received over the USB CDC ACM Virtual COM Port
Pawel Zarembski 0:01f31e923fe2 399
Pawel Zarembski 0:01f31e923fe2 400 The function reads data character from the receive intermediate buffer that
Pawel Zarembski 0:01f31e923fe2 401 was received over the Virtual COM Port.
Pawel Zarembski 0:01f31e923fe2 402
Pawel Zarembski 0:01f31e923fe2 403 \return -1 No character available.
Pawel Zarembski 0:01f31e923fe2 404 \return Received character.
Pawel Zarembski 0:01f31e923fe2 405 */
Pawel Zarembski 0:01f31e923fe2 406
Pawel Zarembski 0:01f31e923fe2 407 int32_t USBD_CDC_ACM_GetChar(void)
Pawel Zarembski 0:01f31e923fe2 408 {
Pawel Zarembski 0:01f31e923fe2 409 uint8_t ch;
Pawel Zarembski 0:01f31e923fe2 410
Pawel Zarembski 0:01f31e923fe2 411 if ((USBD_CDC_ACM_DataRead(&ch, 1)) == 1) {
Pawel Zarembski 0:01f31e923fe2 412 return ((int32_t) ch);
Pawel Zarembski 0:01f31e923fe2 413 }
Pawel Zarembski 0:01f31e923fe2 414
Pawel Zarembski 0:01f31e923fe2 415 return (-1);
Pawel Zarembski 0:01f31e923fe2 416 }
Pawel Zarembski 0:01f31e923fe2 417
Pawel Zarembski 0:01f31e923fe2 418
Pawel Zarembski 0:01f31e923fe2 419 /** \brief Retrieves number of bytes received over the USB CDC ACM Virtual COM Port
Pawel Zarembski 0:01f31e923fe2 420
Pawel Zarembski 0:01f31e923fe2 421 The function retrieves number of bytes available in the intermediate buffer
Pawel Zarembski 0:01f31e923fe2 422 that were received over the Virtual COM Port.
Pawel Zarembski 0:01f31e923fe2 423
Pawel Zarembski 0:01f31e923fe2 424 \return Number of bytes available for read.
Pawel Zarembski 0:01f31e923fe2 425 */
Pawel Zarembski 0:01f31e923fe2 426
Pawel Zarembski 0:01f31e923fe2 427 int32_t USBD_CDC_ACM_DataAvailable(void)
Pawel Zarembski 0:01f31e923fe2 428 {
Pawel Zarembski 0:01f31e923fe2 429 return (ptr_data_received - ptr_data_read);
Pawel Zarembski 0:01f31e923fe2 430 }
Pawel Zarembski 0:01f31e923fe2 431
Pawel Zarembski 0:01f31e923fe2 432
Pawel Zarembski 0:01f31e923fe2 433 /** \brief Sends a notification of Virtual COM Port statuses and line states
Pawel Zarembski 0:01f31e923fe2 434
Pawel Zarembski 0:01f31e923fe2 435 The function sends error and line status of the Virtual COM Port over the
Pawel Zarembski 0:01f31e923fe2 436 Interrupt endpoint. (SerialState notification is defined in usbcdc11.pdf, 6.3.5.)
Pawel Zarembski 0:01f31e923fe2 437
Pawel Zarembski 0:01f31e923fe2 438 \param [in] stat Error and line statuses (
Pawel Zarembski 0:01f31e923fe2 439 6. bit - bOverRun,
Pawel Zarembski 0:01f31e923fe2 440 5. bit - bParity,
Pawel Zarembski 0:01f31e923fe2 441 4. bit - bFraming,
Pawel Zarembski 0:01f31e923fe2 442 3. bit - bRingSignal,
Pawel Zarembski 0:01f31e923fe2 443 2. bit - bBreak,
Pawel Zarembski 0:01f31e923fe2 444 1. bit - bTxCarrier (DSR line state),
Pawel Zarembski 0:01f31e923fe2 445 0. bit - bRxCarrier (DCD line status)).
Pawel Zarembski 0:01f31e923fe2 446 \return 0 Function failed.
Pawel Zarembski 0:01f31e923fe2 447 \return 1 Function succeeded.
Pawel Zarembski 0:01f31e923fe2 448 */
Pawel Zarembski 0:01f31e923fe2 449
Pawel Zarembski 0:01f31e923fe2 450 int32_t USBD_CDC_ACM_Notify(uint16_t stat)
Pawel Zarembski 0:01f31e923fe2 451 {
Pawel Zarembski 0:01f31e923fe2 452 if (USBD_Configuration) {
Pawel Zarembski 0:01f31e923fe2 453 USBD_CDC_ACM_NotifyBuf[0] = 0xA1; /* bmRequestType */
Pawel Zarembski 0:01f31e923fe2 454 USBD_CDC_ACM_NotifyBuf[1] = CDC_NOTIFICATION_SERIAL_STATE;/* bNotification
Pawel Zarembski 0:01f31e923fe2 455 (SERIAL_STATE) */
Pawel Zarembski 0:01f31e923fe2 456 USBD_CDC_ACM_NotifyBuf[2] = 0x00; /* wValue */
Pawel Zarembski 0:01f31e923fe2 457 USBD_CDC_ACM_NotifyBuf[3] = 0x00;
Pawel Zarembski 0:01f31e923fe2 458 USBD_CDC_ACM_NotifyBuf[4] = 0x00; /* wIndex (Interface 0) */
Pawel Zarembski 0:01f31e923fe2 459 USBD_CDC_ACM_NotifyBuf[5] = 0x00;
Pawel Zarembski 0:01f31e923fe2 460 USBD_CDC_ACM_NotifyBuf[6] = 0x02; /* wLength */
Pawel Zarembski 0:01f31e923fe2 461 USBD_CDC_ACM_NotifyBuf[7] = 0x00;
Pawel Zarembski 0:01f31e923fe2 462 USBD_CDC_ACM_NotifyBuf[8] = stat >> 0; /* UART State Bitmap */
Pawel Zarembski 0:01f31e923fe2 463 USBD_CDC_ACM_NotifyBuf[9] = stat >> 8;
Pawel Zarembski 0:01f31e923fe2 464 /* Write notification to be sent */
Pawel Zarembski 0:01f31e923fe2 465 USBD_WriteEP(usbd_cdc_acm_ep_intin | 0x80, USBD_CDC_ACM_NotifyBuf, 10);
Pawel Zarembski 0:01f31e923fe2 466 return (1);
Pawel Zarembski 0:01f31e923fe2 467 }
Pawel Zarembski 0:01f31e923fe2 468
Pawel Zarembski 0:01f31e923fe2 469 return (0);
Pawel Zarembski 0:01f31e923fe2 470 }
Pawel Zarembski 0:01f31e923fe2 471
Pawel Zarembski 0:01f31e923fe2 472
Pawel Zarembski 0:01f31e923fe2 473 /*----------------- USB CDC ACM communication event handlers -----------------*/
Pawel Zarembski 0:01f31e923fe2 474
Pawel Zarembski 0:01f31e923fe2 475 /** \brief Handle Reset Events
Pawel Zarembski 0:01f31e923fe2 476
Pawel Zarembski 0:01f31e923fe2 477 The function handles Reset events.
Pawel Zarembski 0:01f31e923fe2 478 */
Pawel Zarembski 0:01f31e923fe2 479
Pawel Zarembski 0:01f31e923fe2 480 void USBD_CDC_ACM_Reset_Event(void)
Pawel Zarembski 0:01f31e923fe2 481 {
Pawel Zarembski 0:01f31e923fe2 482 USBD_CDC_ACM_Reset();
Pawel Zarembski 0:01f31e923fe2 483 }
Pawel Zarembski 0:01f31e923fe2 484
Pawel Zarembski 0:01f31e923fe2 485
Pawel Zarembski 0:01f31e923fe2 486 /** \brief Handle SOF Events
Pawel Zarembski 0:01f31e923fe2 487
Pawel Zarembski 0:01f31e923fe2 488 The function handles Start Of Frame events. It checks if there is pending
Pawel Zarembski 0:01f31e923fe2 489 data on the Bulk Out endpoint and handles it
Pawel Zarembski 0:01f31e923fe2 490 (USBD_CDC_ACM_EP_BULKOUT_HandleData) if there is enough space in the
Pawel Zarembski 0:01f31e923fe2 491 intermediate receive buffer and it calls received function callback
Pawel Zarembski 0:01f31e923fe2 492 (USBD_CDC_ACM_DataReceived) it also activates data send over the Bulk In
Pawel Zarembski 0:01f31e923fe2 493 endpoint if there is data to be sent (USBD_CDC_ACM_EP_BULKIN_HandleData).
Pawel Zarembski 0:01f31e923fe2 494 */
Pawel Zarembski 0:01f31e923fe2 495
Pawel Zarembski 0:01f31e923fe2 496 void USBD_CDC_ACM_SOF_Event(void)
Pawel Zarembski 0:01f31e923fe2 497 {
Pawel Zarembski 0:01f31e923fe2 498 if (!USBD_Configuration) {
Pawel Zarembski 0:01f31e923fe2 499 // Don't process events until CDC is
Pawel Zarembski 0:01f31e923fe2 500 // configured and the endpoints enabled
Pawel Zarembski 0:01f31e923fe2 501 return;
Pawel Zarembski 0:01f31e923fe2 502 }
Pawel Zarembski 0:01f31e923fe2 503 if ((!data_read_access) && /* If not read active */
Pawel Zarembski 0:01f31e923fe2 504 (ptr_data_received == ptr_data_read) && /* If received and read
Pawel Zarembski 0:01f31e923fe2 505 pointers point to same
Pawel Zarembski 0:01f31e923fe2 506 the location */
Pawel Zarembski 0:01f31e923fe2 507 (ptr_data_received != USBD_CDC_ACM_ReceiveBuf)) {
Pawel Zarembski 0:01f31e923fe2 508 /* and if receive
Pawel Zarembski 0:01f31e923fe2 509 pointer does not already
Pawel Zarembski 0:01f31e923fe2 510 point to the start of
Pawel Zarembski 0:01f31e923fe2 511 the receive buffer */
Pawel Zarembski 0:01f31e923fe2 512 data_read_access = 1; /* Block access to read data */
Pawel Zarembski 0:01f31e923fe2 513 ptr_data_received = USBD_CDC_ACM_ReceiveBuf; /* Correct received pointer
Pawel Zarembski 0:01f31e923fe2 514 to point to the start of
Pawel Zarembski 0:01f31e923fe2 515 the receive buffer */
Pawel Zarembski 0:01f31e923fe2 516 ptr_data_read = USBD_CDC_ACM_ReceiveBuf; /* Correct read pointer to
Pawel Zarembski 0:01f31e923fe2 517 point to the start of the
Pawel Zarembski 0:01f31e923fe2 518 receive buffer */
Pawel Zarembski 0:01f31e923fe2 519 data_no_space_for_receive = 0; /* There is space for
Pawel Zarembski 0:01f31e923fe2 520 reception available */
Pawel Zarembski 0:01f31e923fe2 521 data_read_access = 0; /* Allow access to read data */
Pawel Zarembski 0:01f31e923fe2 522 }
Pawel Zarembski 0:01f31e923fe2 523
Pawel Zarembski 0:01f31e923fe2 524 if (data_received_pending_pckts && /* If packets are pending */
Pawel Zarembski 0:01f31e923fe2 525 (!data_read_access) && /* and if not read active */
Pawel Zarembski 0:01f31e923fe2 526 (!data_no_space_for_receive)) { /* and if there is space to receive */
Pawel Zarembski 0:01f31e923fe2 527 data_read_access = 1; /* Disable access to read data */
Pawel Zarembski 0:01f31e923fe2 528 USBD_CDC_ACM_EP_BULKOUT_HandleData(); /* Handle received data */
Pawel Zarembski 0:01f31e923fe2 529 data_read_access = 0; /* Enable access to read data */
Pawel Zarembski 0:01f31e923fe2 530
Pawel Zarembski 0:01f31e923fe2 531 if (ptr_data_received != ptr_data_read) {
Pawel Zarembski 0:01f31e923fe2 532 USBD_CDC_ACM_DataReceived(ptr_data_received - ptr_data_read);
Pawel Zarembski 0:01f31e923fe2 533 } /* Call
Pawel Zarembski 0:01f31e923fe2 534
Pawel Zarembski 0:01f31e923fe2 535 received callback */
Pawel Zarembski 0:01f31e923fe2 536 }
Pawel Zarembski 0:01f31e923fe2 537
Pawel Zarembski 0:01f31e923fe2 538 if ((!data_send_access) && /* If send data is not being accessed */
Pawel Zarembski 0:01f31e923fe2 539 (!data_send_active) && /* and send is not active */
Pawel Zarembski 0:01f31e923fe2 540 (data_to_send_wr - data_to_send_rd) /* and if there is data to be sent */
Pawel Zarembski 0:01f31e923fe2 541 //&& ((control_line_state & 3) == 3) /* and if DTR and RTS is 1 */
Pawel Zarembski 0:01f31e923fe2 542 ) {
Pawel Zarembski 0:01f31e923fe2 543 data_send_access = 1; /* Block access to send data */
Pawel Zarembski 0:01f31e923fe2 544 data_send_active = 1; /* Start data sending */
Pawel Zarembski 0:01f31e923fe2 545 USBD_CDC_ACM_EP_BULKIN_HandleData();/* Handle data to send */
Pawel Zarembski 0:01f31e923fe2 546 data_send_access = 0; /* Allow access to send data */
Pawel Zarembski 0:01f31e923fe2 547 }
Pawel Zarembski 0:01f31e923fe2 548 }
Pawel Zarembski 0:01f31e923fe2 549
Pawel Zarembski 0:01f31e923fe2 550
Pawel Zarembski 0:01f31e923fe2 551 /** \brief Handle Interrupt In Endpoint Events
Pawel Zarembski 0:01f31e923fe2 552
Pawel Zarembski 0:01f31e923fe2 553 The function handles Interrupt In endpoint events.
Pawel Zarembski 0:01f31e923fe2 554
Pawel Zarembski 0:01f31e923fe2 555 \param [in] event Type of event (USBD_EVT_IN - input event).
Pawel Zarembski 0:01f31e923fe2 556 */
Pawel Zarembski 0:01f31e923fe2 557
Pawel Zarembski 0:01f31e923fe2 558 void USBD_CDC_ACM_EP_INTIN_Event(uint32_t event)
Pawel Zarembski 0:01f31e923fe2 559 {
Pawel Zarembski 0:01f31e923fe2 560 /* Notification will be loadad aynchronously and sent automatically upon
Pawel Zarembski 0:01f31e923fe2 561 Interrupt IN token reception */
Pawel Zarembski 0:01f31e923fe2 562 }
Pawel Zarembski 0:01f31e923fe2 563
Pawel Zarembski 0:01f31e923fe2 564
Pawel Zarembski 0:01f31e923fe2 565 /** \brief Handle Bulk Out Endpoint Received Data
Pawel Zarembski 0:01f31e923fe2 566
Pawel Zarembski 0:01f31e923fe2 567 The function handles data received on the Bulk Out endpoint. It reads the
Pawel Zarembski 0:01f31e923fe2 568 received data to the receive intermediate buffer if there is enough space
Pawel Zarembski 0:01f31e923fe2 569 available.
Pawel Zarembski 0:01f31e923fe2 570 */
Pawel Zarembski 0:01f31e923fe2 571
Pawel Zarembski 0:01f31e923fe2 572 static void USBD_CDC_ACM_EP_BULKOUT_HandleData()
Pawel Zarembski 0:01f31e923fe2 573 {
Pawel Zarembski 0:01f31e923fe2 574 uint32_t len_free_to_recv;
Pawel Zarembski 0:01f31e923fe2 575 int32_t len_received;
Pawel Zarembski 0:01f31e923fe2 576
Pawel Zarembski 0:01f31e923fe2 577 if ((usbd_cdc_acm_receivebuf_sz - (ptr_data_received - USBD_CDC_ACM_ReceiveBuf)) >= usbd_cdc_acm_maxpacketsize1[USBD_HighSpeed]) {
Pawel Zarembski 0:01f31e923fe2 578 /* If there is space for 1 max packet */
Pawel Zarembski 0:01f31e923fe2 579 /* Read received packet to receive buf*/
Pawel Zarembski 0:01f31e923fe2 580 len_free_to_recv = usbd_cdc_acm_receivebuf_sz - (ptr_data_received - USBD_CDC_ACM_ReceiveBuf);
Pawel Zarembski 0:01f31e923fe2 581 len_received = USBD_ReadEP(usbd_cdc_acm_ep_bulkout, ptr_data_received, len_free_to_recv);
Pawel Zarembski 0:01f31e923fe2 582 ptr_data_received += len_received; /* Correct pointer to received data */
Pawel Zarembski 0:01f31e923fe2 583
Pawel Zarembski 0:01f31e923fe2 584 if (data_received_pending_pckts && /* If packet was pending */
Pawel Zarembski 0:01f31e923fe2 585 !data_receive_int_access) { /* and not interrupt access */
Pawel Zarembski 0:01f31e923fe2 586 data_received_pending_pckts--; /* Decrement pending packets number */
Pawel Zarembski 0:01f31e923fe2 587 }
Pawel Zarembski 0:01f31e923fe2 588 } else {
Pawel Zarembski 0:01f31e923fe2 589 data_no_space_for_receive = 1; /* There is no space in receive buffer
Pawel Zarembski 0:01f31e923fe2 590 for the newly received data */
Pawel Zarembski 0:01f31e923fe2 591
Pawel Zarembski 0:01f31e923fe2 592 if (data_receive_int_access) {
Pawel Zarembski 0:01f31e923fe2 593 /* If this access is from interrupt
Pawel Zarembski 0:01f31e923fe2 594 function */
Pawel Zarembski 0:01f31e923fe2 595 data_received_pending_pckts++; /* then this is new unhandled packet */
Pawel Zarembski 0:01f31e923fe2 596 }
Pawel Zarembski 0:01f31e923fe2 597 }
Pawel Zarembski 0:01f31e923fe2 598 }
Pawel Zarembski 0:01f31e923fe2 599
Pawel Zarembski 0:01f31e923fe2 600
Pawel Zarembski 0:01f31e923fe2 601 /** \brief Handle Bulk In Endpoint Data to Send
Pawel Zarembski 0:01f31e923fe2 602
Pawel Zarembski 0:01f31e923fe2 603 The function handles data to be sent on the Bulk In endpoint. It transmits
Pawel Zarembski 0:01f31e923fe2 604 pending data to be sent that is already in the send intermediate buffer,
Pawel Zarembski 0:01f31e923fe2 605 and it also sends Zero Length Packet if last packet sent was not a short
Pawel Zarembski 0:01f31e923fe2 606 packet.
Pawel Zarembski 0:01f31e923fe2 607 */
Pawel Zarembski 0:01f31e923fe2 608
Pawel Zarembski 0:01f31e923fe2 609 static void USBD_CDC_ACM_EP_BULKIN_HandleData(void)
Pawel Zarembski 0:01f31e923fe2 610 {
Pawel Zarembski 0:01f31e923fe2 611 int32_t len_to_send, len_sent;
Pawel Zarembski 0:01f31e923fe2 612
Pawel Zarembski 0:01f31e923fe2 613 if (!data_send_active) { /* If sending is not active */
Pawel Zarembski 0:01f31e923fe2 614 return;
Pawel Zarembski 0:01f31e923fe2 615 }
Pawel Zarembski 0:01f31e923fe2 616
Pawel Zarembski 0:01f31e923fe2 617 len_to_send = data_to_send_wr - data_to_send_rd; /* Num of data to send */
Pawel Zarembski 0:01f31e923fe2 618
Pawel Zarembski 0:01f31e923fe2 619 /* Check if sending is finished */
Pawel Zarembski 0:01f31e923fe2 620 if (!len_to_send && /* If all data was sent */
Pawel Zarembski 0:01f31e923fe2 621 !data_send_zlp) { /* and ZLP was sent if necessary also */
Pawel Zarembski 0:01f31e923fe2 622 data_send_active = 0; /* Sending not active any more */
Pawel Zarembski 0:01f31e923fe2 623 return;
Pawel Zarembski 0:01f31e923fe2 624 }
Pawel Zarembski 0:01f31e923fe2 625
Pawel Zarembski 0:01f31e923fe2 626 /* Check if data needs to be sent */
Pawel Zarembski 0:01f31e923fe2 627 if (len_to_send) {
Pawel Zarembski 0:01f31e923fe2 628 /* If there is data available do be
Pawel Zarembski 0:01f31e923fe2 629 sent */
Pawel Zarembski 0:01f31e923fe2 630 if ((ptr_data_sent >= ptr_data_to_send) && /* If data before end of buf avail*/
Pawel Zarembski 0:01f31e923fe2 631 ((ptr_data_sent + len_to_send) >= (USBD_CDC_ACM_SendBuf + usbd_cdc_acm_sendbuf_sz))) {
Pawel Zarembski 0:01f31e923fe2 632 /* and if available data wraps around
Pawel Zarembski 0:01f31e923fe2 633 the end of the send buffer */
Pawel Zarembski 0:01f31e923fe2 634 /* Correct bytes to send to data
Pawel Zarembski 0:01f31e923fe2 635 available untill end of send buf */
Pawel Zarembski 0:01f31e923fe2 636 len_to_send = USBD_CDC_ACM_SendBuf + usbd_cdc_acm_sendbuf_sz - ptr_data_sent;
Pawel Zarembski 0:01f31e923fe2 637 }
Pawel Zarembski 0:01f31e923fe2 638
Pawel Zarembski 0:01f31e923fe2 639 if (len_to_send > usbd_cdc_acm_maxpacketsize1[USBD_HighSpeed]) {
Pawel Zarembski 0:01f31e923fe2 640 /* If
Pawel Zarembski 0:01f31e923fe2 641 there is more data to be sent then
Pawel Zarembski 0:01f31e923fe2 642 can be sent in a single packet */
Pawel Zarembski 0:01f31e923fe2 643 /* Correct to send maximum pckt size */
Pawel Zarembski 0:01f31e923fe2 644 len_to_send = usbd_cdc_acm_maxpacketsize1[USBD_HighSpeed];
Pawel Zarembski 0:01f31e923fe2 645 }
Pawel Zarembski 0:01f31e923fe2 646 } else if (data_send_zlp) { /* or if ZLP should be sent */
Pawel Zarembski 0:01f31e923fe2 647 len_to_send = 0;
Pawel Zarembski 0:01f31e923fe2 648 }
Pawel Zarembski 0:01f31e923fe2 649
Pawel Zarembski 0:01f31e923fe2 650 data_send_zlp = 0;
Pawel Zarembski 0:01f31e923fe2 651 /* Send data */
Pawel Zarembski 0:01f31e923fe2 652 len_sent = USBD_WriteEP(usbd_cdc_acm_ep_bulkin | 0x80, ptr_data_sent, len_to_send);
Pawel Zarembski 0:01f31e923fe2 653 ptr_data_sent += len_sent; /* Correct position of sent pointer */
Pawel Zarembski 0:01f31e923fe2 654 data_to_send_rd += len_sent; /* Correct num of bytes left to send */
Pawel Zarembski 0:01f31e923fe2 655
Pawel Zarembski 0:01f31e923fe2 656 if (ptr_data_sent == USBD_CDC_ACM_SendBuf + usbd_cdc_acm_sendbuf_sz)
Pawel Zarembski 0:01f31e923fe2 657 /* If pointer to sent data wraps */
Pawel Zarembski 0:01f31e923fe2 658 {
Pawel Zarembski 0:01f31e923fe2 659 ptr_data_sent = USBD_CDC_ACM_SendBuf;
Pawel Zarembski 0:01f31e923fe2 660 } /* Correct it to beginning of send
Pawel Zarembski 0:01f31e923fe2 661
Pawel Zarembski 0:01f31e923fe2 662 buffer */
Pawel Zarembski 0:01f31e923fe2 663
Pawel Zarembski 0:01f31e923fe2 664 if ((data_to_send_wr == data_to_send_rd) && /* If there are no more
Pawel Zarembski 0:01f31e923fe2 665 bytes available to be sent */
Pawel Zarembski 0:01f31e923fe2 666 (len_sent == usbd_cdc_acm_maxpacketsize1[USBD_HighSpeed])) {
Pawel Zarembski 0:01f31e923fe2 667 /* If last packet size was same as
Pawel Zarembski 0:01f31e923fe2 668 maximum packet size */
Pawel Zarembski 0:01f31e923fe2 669 data_send_zlp = 1; /* ZLP packet should be sent */
Pawel Zarembski 0:01f31e923fe2 670 } else {
Pawel Zarembski 0:01f31e923fe2 671 data_send_zlp = 0; /* No ZLP packet should be sent */
Pawel Zarembski 0:01f31e923fe2 672 }
Pawel Zarembski 0:01f31e923fe2 673 }
Pawel Zarembski 0:01f31e923fe2 674
Pawel Zarembski 0:01f31e923fe2 675
Pawel Zarembski 0:01f31e923fe2 676 /** \brief Handle Bulk Out Endpoint Events
Pawel Zarembski 0:01f31e923fe2 677
Pawel Zarembski 0:01f31e923fe2 678 The function handles Bulk Out endpoint events. It calls
Pawel Zarembski 0:01f31e923fe2 679 USBD_CDC_ACM_EP_BULKOUT_HandleData function to handle received data
Pawel Zarembski 0:01f31e923fe2 680 unless data was being accessed in which case function just acknowledges
Pawel Zarembski 0:01f31e923fe2 681 that there is data to be handled later.
Pawel Zarembski 0:01f31e923fe2 682
Pawel Zarembski 0:01f31e923fe2 683 \param [in] event Type of event (USBD_EVT_OUT - output event).
Pawel Zarembski 0:01f31e923fe2 684 */
Pawel Zarembski 0:01f31e923fe2 685
Pawel Zarembski 0:01f31e923fe2 686 void USBD_CDC_ACM_EP_BULKOUT_Event(uint32_t event)
Pawel Zarembski 0:01f31e923fe2 687 {
Pawel Zarembski 0:01f31e923fe2 688 if (data_read_access) {
Pawel Zarembski 0:01f31e923fe2 689 /* If data is being accessed from
Pawel Zarembski 0:01f31e923fe2 690 read function */
Pawel Zarembski 0:01f31e923fe2 691 data_received_pending_pckts++; /* 1 more packet received and not
Pawel Zarembski 0:01f31e923fe2 692 handled */
Pawel Zarembski 0:01f31e923fe2 693 return;
Pawel Zarembski 0:01f31e923fe2 694 }
Pawel Zarembski 0:01f31e923fe2 695
Pawel Zarembski 0:01f31e923fe2 696 data_read_access = 1; /* Block access to read data */
Pawel Zarembski 0:01f31e923fe2 697 data_receive_int_access = 1; /* Read access from interrupt function*/
Pawel Zarembski 0:01f31e923fe2 698 USBD_CDC_ACM_EP_BULKOUT_HandleData(); /* Handle received data */
Pawel Zarembski 0:01f31e923fe2 699 data_receive_int_access = 0; /* Read access from interrupt func end*/
Pawel Zarembski 0:01f31e923fe2 700 data_read_access = 0; /* Allow access to read data */
Pawel Zarembski 0:01f31e923fe2 701
Pawel Zarembski 0:01f31e923fe2 702 if (ptr_data_received != ptr_data_read) {
Pawel Zarembski 0:01f31e923fe2 703 USBD_CDC_ACM_DataReceived(ptr_data_received - ptr_data_read);
Pawel Zarembski 0:01f31e923fe2 704 } /* Call
Pawel Zarembski 0:01f31e923fe2 705
Pawel Zarembski 0:01f31e923fe2 706 received callback */
Pawel Zarembski 0:01f31e923fe2 707 }
Pawel Zarembski 0:01f31e923fe2 708
Pawel Zarembski 0:01f31e923fe2 709
Pawel Zarembski 0:01f31e923fe2 710 /** \brief Handle Bulk In Endpoint Events
Pawel Zarembski 0:01f31e923fe2 711
Pawel Zarembski 0:01f31e923fe2 712 The function handles Bulk In endpoint events. It calls
Pawel Zarembski 0:01f31e923fe2 713 USBD_CDC_ACM_EP_BULKIN_HandleData function to handle send data
Pawel Zarembski 0:01f31e923fe2 714 unless data was being accessed in which case function just returns.
Pawel Zarembski 0:01f31e923fe2 715
Pawel Zarembski 0:01f31e923fe2 716 \param [in] event Type of event (USBD_EVT_IN - input event).
Pawel Zarembski 0:01f31e923fe2 717 */
Pawel Zarembski 0:01f31e923fe2 718
Pawel Zarembski 0:01f31e923fe2 719 void USBD_CDC_ACM_EP_BULKIN_Event(uint32_t event)
Pawel Zarembski 0:01f31e923fe2 720 {
Pawel Zarembski 0:01f31e923fe2 721 if (data_send_access /* If send data is being accessed */
Pawel Zarembski 0:01f31e923fe2 722 // ||((control_line_state & 3) != 3) /* or if DTR or RTS is 0 */
Pawel Zarembski 0:01f31e923fe2 723 ) {
Pawel Zarembski 0:01f31e923fe2 724 return;
Pawel Zarembski 0:01f31e923fe2 725 }
Pawel Zarembski 0:01f31e923fe2 726
Pawel Zarembski 0:01f31e923fe2 727 data_send_access = 1; /* Block access to send data */
Pawel Zarembski 0:01f31e923fe2 728 USBD_CDC_ACM_EP_BULKIN_HandleData(); /* Handle data to send */
Pawel Zarembski 0:01f31e923fe2 729 data_send_access = 0; /* Allow access to send data */
Pawel Zarembski 0:01f31e923fe2 730 }
Pawel Zarembski 0:01f31e923fe2 731
Pawel Zarembski 0:01f31e923fe2 732
Pawel Zarembski 0:01f31e923fe2 733 /** \brief Handle Bulk In/Out Endpoint Events
Pawel Zarembski 0:01f31e923fe2 734
Pawel Zarembski 0:01f31e923fe2 735 The function handles Bulk In/Out endpoint events. It is used for endpoints
Pawel Zarembski 0:01f31e923fe2 736 that do In and Out functionality on the same endpoint number. It dispatches
Pawel Zarembski 0:01f31e923fe2 737 events to appropriate In or Out event handlers.
Pawel Zarembski 0:01f31e923fe2 738
Pawel Zarembski 0:01f31e923fe2 739 \param [in] event Type of event (
Pawel Zarembski 0:01f31e923fe2 740 USBD_EVT_IN - input event,
Pawel Zarembski 0:01f31e923fe2 741 USBD_EVT_OUT - output event).
Pawel Zarembski 0:01f31e923fe2 742 */
Pawel Zarembski 0:01f31e923fe2 743
Pawel Zarembski 0:01f31e923fe2 744 void USBD_CDC_ACM_EP_BULK_Event(uint32_t event)
Pawel Zarembski 0:01f31e923fe2 745 {
Pawel Zarembski 0:01f31e923fe2 746 if (event & USBD_EVT_OUT) {
Pawel Zarembski 0:01f31e923fe2 747 USBD_CDC_ACM_EP_BULKOUT_Event(event);
Pawel Zarembski 0:01f31e923fe2 748 }
Pawel Zarembski 0:01f31e923fe2 749
Pawel Zarembski 0:01f31e923fe2 750 if (event & USBD_EVT_IN) {
Pawel Zarembski 0:01f31e923fe2 751 USBD_CDC_ACM_EP_BULKIN_Event(event);
Pawel Zarembski 0:01f31e923fe2 752 }
Pawel Zarembski 0:01f31e923fe2 753 }
Pawel Zarembski 0:01f31e923fe2 754
Pawel Zarembski 0:01f31e923fe2 755
Pawel Zarembski 0:01f31e923fe2 756 #ifdef __RTX /* RTX tasks for handling events */
Pawel Zarembski 0:01f31e923fe2 757
Pawel Zarembski 0:01f31e923fe2 758 /** \brief Task Handling Interrupt In Endpoint Events
Pawel Zarembski 0:01f31e923fe2 759
Pawel Zarembski 0:01f31e923fe2 760 The task dispatches Interrupt In events to the Interrupt In handling
Pawel Zarembski 0:01f31e923fe2 761 function (USBD_CDC_ACM_EP_INTIN_Event).
Pawel Zarembski 0:01f31e923fe2 762 */
Pawel Zarembski 0:01f31e923fe2 763
Pawel Zarembski 0:01f31e923fe2 764 void USBD_RTX_CDC_ACM_EP_INTIN_Event(void)
Pawel Zarembski 0:01f31e923fe2 765 {
Pawel Zarembski 0:01f31e923fe2 766 for (;;) {
Pawel Zarembski 0:01f31e923fe2 767 usbd_os_evt_wait_or(0xFFFF, 0xFFFF);
Pawel Zarembski 0:01f31e923fe2 768 USBD_CDC_ACM_EP_INTIN_Event(usbd_os_evt_get());
Pawel Zarembski 0:01f31e923fe2 769 }
Pawel Zarembski 0:01f31e923fe2 770 }
Pawel Zarembski 0:01f31e923fe2 771
Pawel Zarembski 0:01f31e923fe2 772
Pawel Zarembski 0:01f31e923fe2 773 /** \brief Task Handling Bulk In Endpoint Events
Pawel Zarembski 0:01f31e923fe2 774
Pawel Zarembski 0:01f31e923fe2 775 The task dispatches Bulk In events to the Bulk In handling
Pawel Zarembski 0:01f31e923fe2 776 function (USBD_CDC_ACM_EP_BULKIN_Event).
Pawel Zarembski 0:01f31e923fe2 777 */
Pawel Zarembski 0:01f31e923fe2 778
Pawel Zarembski 0:01f31e923fe2 779 void USBD_RTX_CDC_ACM_EP_BULKIN_Event(void)
Pawel Zarembski 0:01f31e923fe2 780 {
Pawel Zarembski 0:01f31e923fe2 781 for (;;) {
Pawel Zarembski 0:01f31e923fe2 782 usbd_os_evt_wait_or(0xFFFF, 0xFFFF);
Pawel Zarembski 0:01f31e923fe2 783
Pawel Zarembski 0:01f31e923fe2 784 if (usbd_os_evt_get() & USBD_EVT_IN) {
Pawel Zarembski 0:01f31e923fe2 785 USBD_CDC_ACM_EP_BULKIN_Event(0);
Pawel Zarembski 0:01f31e923fe2 786 }
Pawel Zarembski 0:01f31e923fe2 787 }
Pawel Zarembski 0:01f31e923fe2 788 }
Pawel Zarembski 0:01f31e923fe2 789
Pawel Zarembski 0:01f31e923fe2 790
Pawel Zarembski 0:01f31e923fe2 791 /** \brief Task Handling Bulk Out Endpoint Events
Pawel Zarembski 0:01f31e923fe2 792
Pawel Zarembski 0:01f31e923fe2 793 The task dispatches Bulk Out events to the Bulk Out handling
Pawel Zarembski 0:01f31e923fe2 794 function (USBD_CDC_ACM_EP_BULKOUT_Event).
Pawel Zarembski 0:01f31e923fe2 795 */
Pawel Zarembski 0:01f31e923fe2 796
Pawel Zarembski 0:01f31e923fe2 797 void USBD_RTX_CDC_ACM_EP_BULKOUT_Event(void)
Pawel Zarembski 0:01f31e923fe2 798 {
Pawel Zarembski 0:01f31e923fe2 799 for (;;) {
Pawel Zarembski 0:01f31e923fe2 800 usbd_os_evt_wait_or(0xFFFF, 0xFFFF);
Pawel Zarembski 0:01f31e923fe2 801
Pawel Zarembski 0:01f31e923fe2 802 if (usbd_os_evt_get() & USBD_EVT_OUT) {
Pawel Zarembski 0:01f31e923fe2 803 USBD_CDC_ACM_EP_BULKOUT_Event(0);
Pawel Zarembski 0:01f31e923fe2 804 }
Pawel Zarembski 0:01f31e923fe2 805 }
Pawel Zarembski 0:01f31e923fe2 806 }
Pawel Zarembski 0:01f31e923fe2 807
Pawel Zarembski 0:01f31e923fe2 808
Pawel Zarembski 0:01f31e923fe2 809 /** \brief Task Handling Bulk In/Out Endpoint Events
Pawel Zarembski 0:01f31e923fe2 810
Pawel Zarembski 0:01f31e923fe2 811 The task dispatches Bulk In/Out events to the Bulk In/Out handling
Pawel Zarembski 0:01f31e923fe2 812 function (USBD_CDC_ACM_EP_BULK_Event).
Pawel Zarembski 0:01f31e923fe2 813 */
Pawel Zarembski 0:01f31e923fe2 814
Pawel Zarembski 0:01f31e923fe2 815 void USBD_RTX_CDC_ACM_EP_BULK_Event(void)
Pawel Zarembski 0:01f31e923fe2 816 {
Pawel Zarembski 0:01f31e923fe2 817 for (;;) {
Pawel Zarembski 0:01f31e923fe2 818 usbd_os_evt_wait_or(0xFFFF, 0xFFFF);
Pawel Zarembski 0:01f31e923fe2 819 USBD_CDC_ACM_EP_BULK_Event(usbd_os_evt_get());
Pawel Zarembski 0:01f31e923fe2 820 }
Pawel Zarembski 0:01f31e923fe2 821 }
Pawel Zarembski 0:01f31e923fe2 822 #endif
Pawel Zarembski 0:01f31e923fe2 823