1 /*
2 * @brief Virtual Comm port call back routines
3 *
4 * @note
5 * Copyright(C) NXP Semiconductors, 2013
6 * All rights reserved.
7 *
8 * @par
9 * Software that is described herein is for illustrative purposes only
10 * which provides customers with programming information regarding the
11 * LPC products. This software is supplied "AS IS" without any warranties of
12 * any kind, and NXP Semiconductors and its licensor disclaim any and
13 * all warranties, express or implied, including all implied warranties of
14 * merchantability, fitness for a particular purpose and non-infringement of
15 * intellectual property rights. NXP Semiconductors assumes no responsibility
16 * or liability for the use of the software, conveys no license or rights under any
17 * patent, copyright, mask work right, or any other intellectual property rights in
18 * or to any products. NXP Semiconductors reserves the right to make changes
19 * in the software without notification. NXP Semiconductors also makes no
20 * representation or warranty that such application will be suitable for the
21 * specified use without further testing or modification.
22 *
23 * @par
24 * Permission to use, copy, modify, and distribute this software and its
25 * documentation is hereby granted, under NXP Semiconductors' and its
26 * licensor's relevant copyrights in the software, without fee, provided that it
27 * is used in conjunction with NXP Semiconductors microcontrollers. This
28 * copyright, permission, and disclaimer notice must appear in all copies of
29 * this code.
30 */
31 #include <string.h>
32 #include "app_usbd_cfg.h"
33 #include "board.h"
34 #include "cdc_vcom.h"
35
36 /*****************************************************************************
37 * Private types/enumerations/variables
38 ****************************************************************************/
39
40 /*****************************************************************************
41 * Public types/enumerations/variables
42 ****************************************************************************/
43
44 /**
45 * Global variable to hold Virtual COM port control data.
46 */
47 VCOM_DATA_T g_vCOM;
48
49 /*****************************************************************************
50 * Private functions
51 ****************************************************************************/
52
53 /* VCOM bulk EP_IN endpoint handler */
VCOM_bulk_in_hdlr(USBD_HANDLE_T hUsb,void * data,uint32_t event)54 static ErrorCode_t VCOM_bulk_in_hdlr(USBD_HANDLE_T hUsb, void *data, uint32_t event)
55 {
56 VCOM_DATA_T *pVcom = (VCOM_DATA_T *) data;
57
58 if (event == USB_EVT_IN) {
59 pVcom->tx_flags &= ~VCOM_TX_BUSY;
60 }
61 return LPC_OK;
62 }
63
64 /* VCOM bulk EP_OUT endpoint handler */
VCOM_bulk_out_hdlr(USBD_HANDLE_T hUsb,void * data,uint32_t event)65 static ErrorCode_t VCOM_bulk_out_hdlr(USBD_HANDLE_T hUsb, void *data, uint32_t event)
66 {
67 VCOM_DATA_T *pVcom = (VCOM_DATA_T *) data;
68
69 switch (event) {
70 case USB_EVT_OUT:
71 pVcom->rx_count = USBD_API->hw->ReadEP(hUsb, USB_CDC_OUT_EP, pVcom->rx_buff);
72 if (pVcom->rx_flags & VCOM_RX_BUF_QUEUED) {
73 pVcom->rx_flags &= ~VCOM_RX_BUF_QUEUED;
74 if (pVcom->rx_count != 0) {
75 pVcom->rx_flags |= VCOM_RX_BUF_FULL;
76 }
77
78 }
79 else if (pVcom->rx_flags & VCOM_RX_DB_QUEUED) {
80 pVcom->rx_flags &= ~VCOM_RX_DB_QUEUED;
81 pVcom->rx_flags |= VCOM_RX_DONE;
82 }
83 break;
84
85 case USB_EVT_OUT_NAK:
86 /* queue free buffer for RX */
87 if ((pVcom->rx_flags & (VCOM_RX_BUF_FULL | VCOM_RX_BUF_QUEUED)) == 0) {
88 USBD_API->hw->ReadReqEP(hUsb, USB_CDC_OUT_EP, pVcom->rx_buff, VCOM_RX_BUF_SZ);
89 pVcom->rx_flags |= VCOM_RX_BUF_QUEUED;
90 }
91 break;
92
93 default:
94 break;
95 }
96
97 return LPC_OK;
98 }
99
100 /* Set line coding call back routine */
VCOM_SetLineCode(USBD_HANDLE_T hCDC,CDC_LINE_CODING * line_coding)101 static ErrorCode_t VCOM_SetLineCode(USBD_HANDLE_T hCDC, CDC_LINE_CODING *line_coding)
102 {
103 VCOM_DATA_T *pVcom = &g_vCOM;
104
105 /* Called when baud rate is changed/set. Using it to know host connection state */
106 pVcom->tx_flags = VCOM_TX_CONNECTED; /* reset other flags */
107
108 return LPC_OK;
109 }
110
111 /*****************************************************************************
112 * Public functions
113 ****************************************************************************/
114
115 /* Virtual com port init routine */
vcom_init(USBD_HANDLE_T hUsb,USB_CORE_DESCS_T * pDesc,USBD_API_INIT_PARAM_T * pUsbParam)116 ErrorCode_t vcom_init(USBD_HANDLE_T hUsb, USB_CORE_DESCS_T *pDesc, USBD_API_INIT_PARAM_T *pUsbParam)
117 {
118 USBD_CDC_INIT_PARAM_T cdc_param;
119 ErrorCode_t ret = LPC_OK;
120 uint32_t ep_indx;
121
122 g_vCOM.hUsb = hUsb;
123 memset((void *) &cdc_param, 0, sizeof(USBD_CDC_INIT_PARAM_T));
124 cdc_param.mem_base = pUsbParam->mem_base;
125 cdc_param.mem_size = pUsbParam->mem_size;
126 cdc_param.cif_intf_desc = (uint8_t *) find_IntfDesc(pDesc->high_speed_desc, CDC_COMMUNICATION_INTERFACE_CLASS);
127 cdc_param.dif_intf_desc = (uint8_t *) find_IntfDesc(pDesc->high_speed_desc, CDC_DATA_INTERFACE_CLASS);
128 cdc_param.SetLineCode = VCOM_SetLineCode;
129
130 ret = USBD_API->cdc->init(hUsb, &cdc_param, &g_vCOM.hCdc);
131
132 if (ret == LPC_OK) {
133 /* allocate transfer buffers */
134 g_vCOM.rx_buff = (uint8_t *) cdc_param.mem_base;
135 cdc_param.mem_base += VCOM_RX_BUF_SZ;
136 cdc_param.mem_size -= VCOM_RX_BUF_SZ;
137
138 /* register endpoint interrupt handler */
139 ep_indx = (((USB_CDC_IN_EP & 0x0F) << 1) + 1);
140 ret = USBD_API->core->RegisterEpHandler(hUsb, ep_indx, VCOM_bulk_in_hdlr, &g_vCOM);
141 if (ret == LPC_OK) {
142 /* register endpoint interrupt handler */
143 ep_indx = ((USB_CDC_OUT_EP & 0x0F) << 1);
144 ret = USBD_API->core->RegisterEpHandler(hUsb, ep_indx, VCOM_bulk_out_hdlr, &g_vCOM);
145
146 }
147 /* update mem_base and size variables for cascading calls. */
148 pUsbParam->mem_base = cdc_param.mem_base;
149 pUsbParam->mem_size = cdc_param.mem_size;
150 }
151
152 return ret;
153 }
154
155 /* Virtual com port buffered read routine */
vcom_bread(uint8_t * pBuf,uint32_t buf_len)156 uint32_t vcom_bread(uint8_t *pBuf, uint32_t buf_len)
157 {
158 VCOM_DATA_T *pVcom = &g_vCOM;
159 uint16_t cnt = 0;
160 /* read from the default buffer if any data present */
161 if (pVcom->rx_count) {
162 cnt = (pVcom->rx_count < buf_len) ? pVcom->rx_count : buf_len;
163 memcpy(pBuf, pVcom->rx_buff, cnt);
164 pVcom->rx_rd_count += cnt;
165
166 /* enter critical section */
167 NVIC_DisableIRQ(USB0_IRQn);
168 if (pVcom->rx_rd_count >= pVcom->rx_count) {
169 pVcom->rx_flags &= ~VCOM_RX_BUF_FULL;
170 pVcom->rx_rd_count = pVcom->rx_count = 0;
171 }
172 /* exit critical section */
173 NVIC_EnableIRQ(USB0_IRQn);
174 }
175 return cnt;
176
177 }
178
179 /* Virtual com port read routine */
vcom_read_req(uint8_t * pBuf,uint32_t len)180 ErrorCode_t vcom_read_req(uint8_t *pBuf, uint32_t len)
181 {
182 VCOM_DATA_T *pVcom = &g_vCOM;
183
184 /* check if we queued Rx buffer */
185 if (pVcom->rx_flags & (VCOM_RX_BUF_QUEUED | VCOM_RX_DB_QUEUED)) {
186 return ERR_BUSY;
187 }
188 /* enter critical section */
189 NVIC_DisableIRQ(USB0_IRQn);
190 /* if not queue the request and return 0 bytes */
191 USBD_API->hw->ReadReqEP(pVcom->hUsb, USB_CDC_OUT_EP, pBuf, len);
192 /* exit critical section */
193 NVIC_EnableIRQ(USB0_IRQn);
194 pVcom->rx_flags |= VCOM_RX_DB_QUEUED;
195
196 return LPC_OK;
197 }
198
199 /* Gets current read count. */
vcom_read_cnt(void)200 uint32_t vcom_read_cnt(void)
201 {
202 VCOM_DATA_T *pVcom = &g_vCOM;
203 uint32_t ret = 0;
204
205 if (pVcom->rx_flags & VCOM_RX_DONE) {
206 ret = pVcom->rx_count;
207 pVcom->rx_count = 0;
208 }
209
210 return ret;
211 }
212
213 /* Virtual com port write routine*/
vcom_write(uint8_t * pBuf,uint32_t len)214 uint32_t vcom_write(uint8_t *pBuf, uint32_t len)
215 {
216 VCOM_DATA_T *pVcom = &g_vCOM;
217 uint32_t ret = 0;
218
219 if ( (pVcom->tx_flags & VCOM_TX_CONNECTED) && ((pVcom->tx_flags & VCOM_TX_BUSY) == 0) ) {
220 pVcom->tx_flags |= VCOM_TX_BUSY;
221
222 /* enter critical section */
223 NVIC_DisableIRQ(USB0_IRQn);
224 ret = USBD_API->hw->WriteEP(pVcom->hUsb, USB_CDC_IN_EP, pBuf, len);
225 /* exit critical section */
226 NVIC_EnableIRQ(USB0_IRQn);
227 }
228
229 return ret;
230 }
231