2 ******************************************************************************
3 * @addtogroup PIOS PIOS Core hardware abstraction layer
5 * @addtogroup PIOS_USB_COM USB COM Functions
6 * @brief PIOS USB COM implementation for CDC interfaces
7 * @notes This implements a CDC Serial Port
10 * @file pios_usb_com_cdc.c
11 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
12 * @brief USB COM functions (STM32 dependent code)
13 * @see The GNU Public License (GPL) Version 3
15 *****************************************************************************/
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 3 of the License, or
20 * (at your option) any later version.
22 * This program is distributed in the hope that it will be useful, but
23 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
27 * You should have received a copy of the GNU General Public License along
28 * with this program; if not, write to the Free Software Foundation, Inc.,
29 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
34 #ifdef PIOS_INCLUDE_USB_CDC
36 #include "pios_usb_cdc_priv.h"
37 #include "pios_usb_board_data.h" /* PIOS_BOARD_*_DATA_LENGTH */
38 #include "pios_usbhook.h" /* PIOS_USBHOOK_* */
40 /* Implement COM layer driver API */
41 static void PIOS_USB_CDC_RegisterTxCallback(uint32_t usbcdc_id
, pios_com_callback tx_out_cb
, uint32_t context
);
42 static void PIOS_USB_CDC_RegisterRxCallback(uint32_t usbcdc_id
, pios_com_callback rx_in_cb
, uint32_t context
);
43 static void PIOS_USB_CDC_TxStart(uint32_t usbcdc_id
, uint16_t tx_bytes_avail
);
44 static void PIOS_USB_CDC_RxStart(uint32_t usbcdc_id
, uint16_t rx_bytes_avail
);
45 static bool PIOS_USB_CDC_Available(uint32_t usbcdc_id
);
47 const struct pios_com_driver pios_usb_cdc_com_driver
= {
48 .tx_start
= PIOS_USB_CDC_TxStart
,
49 .rx_start
= PIOS_USB_CDC_RxStart
,
50 .bind_tx_cb
= PIOS_USB_CDC_RegisterTxCallback
,
51 .bind_rx_cb
= PIOS_USB_CDC_RegisterRxCallback
,
52 .available
= PIOS_USB_CDC_Available
,
55 enum pios_usb_cdc_dev_magic
{
56 PIOS_USB_CDC_DEV_MAGIC
= 0xAABBCCDD,
59 struct pios_usb_cdc_dev
{
60 enum pios_usb_cdc_dev_magic magic
;
61 const struct pios_usb_cdc_cfg
*cfg
;
65 pios_com_callback rx_in_cb
;
66 uint32_t rx_in_context
;
67 pios_com_callback tx_out_cb
;
68 uint32_t tx_out_context
;
70 bool usb_ctrl_if_enabled
;
71 bool usb_data_if_enabled
;
73 uint8_t rx_packet_buffer
[PIOS_USB_BOARD_CDC_DATA_LENGTH
] __attribute__((aligned(4)));
74 volatile bool rx_active
;
77 * NOTE: This is -1 as somewhat of a hack. It ensures that we always send packets
78 * that are strictly < maxPacketSize for this interface which means we never have
79 * to bother with zero length packets (ZLP).
81 uint8_t tx_packet_buffer
[PIOS_USB_BOARD_CDC_DATA_LENGTH
- 1] __attribute__((aligned(4)));
82 volatile bool tx_active
;
84 uint8_t ctrl_tx_packet_buffer
[PIOS_USB_BOARD_CDC_MGMT_LENGTH
] __attribute__((aligned(4)));
90 * Used to hold the current state of the simulated UART. Changes to this
91 * variable may trigger new USB CDC Notification packets to be sent to the host.
93 volatile uint16_t prev_uart_state
;
96 static bool PIOS_USB_CDC_validate(struct pios_usb_cdc_dev
*usb_cdc_dev
)
98 return usb_cdc_dev
&& (usb_cdc_dev
->magic
== PIOS_USB_CDC_DEV_MAGIC
);
101 #if defined(PIOS_INCLUDE_FREERTOS)
102 static struct pios_usb_cdc_dev
*PIOS_USB_CDC_alloc(void)
104 struct pios_usb_cdc_dev
*usb_cdc_dev
;
106 usb_cdc_dev
= (struct pios_usb_cdc_dev
*)pios_malloc(sizeof(struct pios_usb_cdc_dev
));
111 memset(usb_cdc_dev
, 0, sizeof(struct pios_usb_cdc_dev
));
112 usb_cdc_dev
->magic
= PIOS_USB_CDC_DEV_MAGIC
;
116 static struct pios_usb_cdc_dev pios_usb_cdc_devs
[PIOS_USB_CDC_MAX_DEVS
];
117 static uint8_t pios_usb_cdc_num_devs
;
118 static struct pios_usb_cdc_dev
*PIOS_USB_CDC_alloc(void)
120 struct pios_usb_cdc_dev
*usb_cdc_dev
;
122 if (pios_usb_cdc_num_devs
>= PIOS_USB_CDC_MAX_DEVS
) {
126 usb_cdc_dev
= &pios_usb_cdc_devs
[pios_usb_cdc_num_devs
++];
128 memset(usb_cdc_dev
, 0, sizeof(struct pios_usb_cdc_dev
));
129 usb_cdc_dev
->magic
= PIOS_USB_CDC_DEV_MAGIC
;
133 #endif /* if defined(PIOS_INCLUDE_FREERTOS) */
135 /* Implement USB_IFOPS for CDC Control Interface */
136 static void PIOS_USB_CDC_CTRL_IF_Init(uint32_t usb_cdc_id
);
137 static void PIOS_USB_CDC_CTRL_IF_DeInit(uint32_t usb_cdc_id
);
138 static bool PIOS_USB_CDC_CTRL_IF_Setup(uint32_t usb_cdc_id
, struct usb_setup_request
*req
);
139 static void PIOS_USB_CDC_CTRL_IF_CtrlDataOut(uint32_t usb_cdc_id
, const struct usb_setup_request
*req
);
141 static struct pios_usb_ifops usb_cdc_ctrl_ifops
= {
142 .init
= PIOS_USB_CDC_CTRL_IF_Init
,
143 .deinit
= PIOS_USB_CDC_CTRL_IF_DeInit
,
144 .setup
= PIOS_USB_CDC_CTRL_IF_Setup
,
145 .ctrl_data_out
= PIOS_USB_CDC_CTRL_IF_CtrlDataOut
,
148 /* Implement USB_IFOPS for CDC Data Interface */
149 static void PIOS_USB_CDC_DATA_IF_Init(uint32_t usb_cdc_id
);
150 static void PIOS_USB_CDC_DATA_IF_DeInit(uint32_t usb_cdc_id
);
151 static bool PIOS_USB_CDC_DATA_IF_Setup(uint32_t usb_cdc_id
, struct usb_setup_request
*req
);
152 static void PIOS_USB_CDC_DATA_IF_CtrlDataOut(uint32_t usb_cdc_id
, const struct usb_setup_request
*req
);
154 static struct pios_usb_ifops usb_cdc_data_ifops
= {
155 .init
= PIOS_USB_CDC_DATA_IF_Init
,
156 .deinit
= PIOS_USB_CDC_DATA_IF_DeInit
,
157 .setup
= PIOS_USB_CDC_DATA_IF_Setup
,
158 .ctrl_data_out
= PIOS_USB_CDC_DATA_IF_CtrlDataOut
,
161 static uint32_t pios_usb_cdc_id
;
163 int32_t PIOS_USB_CDC_Init(uint32_t *usbcdc_id
, const struct pios_usb_cdc_cfg
*cfg
, uint32_t lower_id
)
165 PIOS_Assert(usbcdc_id
);
168 struct pios_usb_cdc_dev
*usb_cdc_dev
;
170 usb_cdc_dev
= (struct pios_usb_cdc_dev
*)PIOS_USB_CDC_alloc();
175 /* Bind the configuration to the device instance */
176 usb_cdc_dev
->cfg
= cfg
;
177 usb_cdc_dev
->lower_id
= lower_id
;
179 pios_usb_cdc_id
= (uint32_t)usb_cdc_dev
;
181 /* Rx and Tx are not active yet */
182 usb_cdc_dev
->rx_active
= false;
183 usb_cdc_dev
->tx_active
= false;
186 usb_cdc_dev
->rx_dropped
= 0;
187 usb_cdc_dev
->rx_oversize
= 0;
189 /* Initialize the uart state */
190 usb_cdc_dev
->prev_uart_state
= 0;
192 /* Register class specific interface callbacks with the USBHOOK layer */
193 usb_cdc_dev
->usb_ctrl_if_enabled
= false;
194 PIOS_USBHOOK_RegisterIfOps(cfg
->ctrl_if
, &usb_cdc_ctrl_ifops
, (uint32_t)usb_cdc_dev
);
196 /* Register class specific interface callbacks with the USBHOOK layer */
197 usb_cdc_dev
->usb_data_if_enabled
= false;
198 PIOS_USBHOOK_RegisterIfOps(cfg
->data_if
, &usb_cdc_data_ifops
, (uint32_t)usb_cdc_dev
);
200 *usbcdc_id
= (uint32_t)usb_cdc_dev
;
208 static bool PIOS_USB_CDC_SendData(struct pios_usb_cdc_dev
*usb_cdc_dev
)
210 uint16_t bytes_to_tx
;
212 if (!usb_cdc_dev
->tx_out_cb
) {
216 bool need_yield
= false;
217 bytes_to_tx
= (usb_cdc_dev
->tx_out_cb
)(usb_cdc_dev
->tx_out_context
,
218 usb_cdc_dev
->tx_packet_buffer
,
219 sizeof(usb_cdc_dev
->tx_packet_buffer
),
222 if (bytes_to_tx
== 0) {
227 * Mark this endpoint as being tx active _before_ actually transmitting
228 * to make sure we don't race with the Tx completion interrupt
230 usb_cdc_dev
->tx_active
= true;
232 PIOS_USBHOOK_EndpointTx(usb_cdc_dev
->cfg
->data_tx_ep
,
233 usb_cdc_dev
->tx_packet_buffer
,
236 #if defined(PIOS_INCLUDE_FREERTOS)
240 #endif /* PIOS_INCLUDE_FREERTOS */
245 static void PIOS_USB_CDC_RxStart(uint32_t usbcdc_id
, uint16_t rx_bytes_avail
)
247 struct pios_usb_cdc_dev
*usb_cdc_dev
= (struct pios_usb_cdc_dev
*)usbcdc_id
;
249 bool valid
= PIOS_USB_CDC_validate(usb_cdc_dev
);
253 /* Make sure this USB interface has been initialized */
254 if (!usb_cdc_dev
->usb_data_if_enabled
) {
258 if (!PIOS_USB_CheckAvailable(usb_cdc_dev
->lower_id
)) {
262 // If endpoint was stalled and there is now space make it valid
263 if (!usb_cdc_dev
->rx_active
&& (rx_bytes_avail
>= PIOS_USB_BOARD_CDC_DATA_LENGTH
)) {
264 PIOS_USBHOOK_EndpointRx(usb_cdc_dev
->cfg
->data_rx_ep
,
265 usb_cdc_dev
->rx_packet_buffer
,
266 sizeof(usb_cdc_dev
->rx_packet_buffer
));
267 usb_cdc_dev
->rx_active
= true;
271 static void PIOS_USB_CDC_TxStart(uint32_t usbcdc_id
, __attribute__((unused
)) uint16_t tx_bytes_avail
)
273 struct pios_usb_cdc_dev
*usb_cdc_dev
= (struct pios_usb_cdc_dev
*)usbcdc_id
;
275 bool valid
= PIOS_USB_CDC_validate(usb_cdc_dev
);
279 /* Make sure this USB interface has been initialized */
280 if (!usb_cdc_dev
->usb_data_if_enabled
) {
284 if (!PIOS_USB_CheckAvailable(usb_cdc_dev
->lower_id
)) {
288 if (!usb_cdc_dev
->tx_active
) {
289 /* Transmitter is not currently active, send a report */
290 PIOS_USB_CDC_SendData(usb_cdc_dev
);
294 static void PIOS_USB_CDC_RegisterRxCallback(uint32_t usbcdc_id
, pios_com_callback rx_in_cb
, uint32_t context
)
296 struct pios_usb_cdc_dev
*usb_cdc_dev
= (struct pios_usb_cdc_dev
*)usbcdc_id
;
298 bool valid
= PIOS_USB_CDC_validate(usb_cdc_dev
);
303 * Order is important in these assignments since ISR uses _cb
304 * field to determine if it's ok to dereference _cb and _context
306 usb_cdc_dev
->rx_in_context
= context
;
307 usb_cdc_dev
->rx_in_cb
= rx_in_cb
;
310 static void PIOS_USB_CDC_RegisterTxCallback(uint32_t usbcdc_id
, pios_com_callback tx_out_cb
, uint32_t context
)
312 struct pios_usb_cdc_dev
*usb_cdc_dev
= (struct pios_usb_cdc_dev
*)usbcdc_id
;
314 bool valid
= PIOS_USB_CDC_validate(usb_cdc_dev
);
319 * Order is important in these assignments since ISR uses _cb
320 * field to determine if it's ok to dereference _cb and _context
322 usb_cdc_dev
->tx_out_context
= context
;
323 usb_cdc_dev
->tx_out_cb
= tx_out_cb
;
326 static bool PIOS_USB_CDC_CTRL_EP_IN_Callback(uint32_t usb_cdc_id
, uint8_t epnum
, uint16_t len
);
328 static void PIOS_USB_CDC_CTRL_IF_Init(uint32_t usb_cdc_id
)
330 struct pios_usb_cdc_dev
*usb_cdc_dev
= (struct pios_usb_cdc_dev
*)usb_cdc_id
;
332 if (!PIOS_USB_CDC_validate(usb_cdc_dev
)) {
336 /* Register endpoint specific callbacks with the USBHOOK layer */
337 PIOS_USBHOOK_RegisterEpInCallback(usb_cdc_dev
->cfg
->ctrl_tx_ep
,
338 sizeof(usb_cdc_dev
->ctrl_tx_packet_buffer
),
339 PIOS_USB_CDC_CTRL_EP_IN_Callback
,
340 (uint32_t)usb_cdc_dev
);
341 usb_cdc_dev
->usb_ctrl_if_enabled
= true;
344 static void PIOS_USB_CDC_CTRL_IF_DeInit(uint32_t usb_cdc_id
)
346 struct pios_usb_cdc_dev
*usb_cdc_dev
= (struct pios_usb_cdc_dev
*)usb_cdc_id
;
348 if (!PIOS_USB_CDC_validate(usb_cdc_dev
)) {
352 /* DeRegister endpoint specific callbacks with the USBHOOK layer */
353 usb_cdc_dev
->usb_data_if_enabled
= false;
356 static uint8_t cdc_altset
;
357 static struct usb_cdc_line_coding line_coding
= {
358 .dwDTERate
= htousbl(57600),
359 .bCharFormat
= USB_CDC_LINE_CODING_STOP_1
,
360 .bParityType
= USB_CDC_LINE_CODING_PARITY_NONE
,
364 static uint16_t control_line_state
;
366 static bool PIOS_USB_CDC_CTRL_IF_Setup(uint32_t usb_cdc_id
, struct usb_setup_request
*req
)
368 struct pios_usb_cdc_dev
*usb_cdc_dev
= (struct pios_usb_cdc_dev
*)usb_cdc_id
;
370 if (!PIOS_USB_CDC_validate(usb_cdc_dev
)) {
374 /* Make sure this is a request for an interface we know about */
375 uint8_t ifnum
= req
->wIndex
& 0xFF;
376 if (ifnum
!= usb_cdc_dev
->cfg
->ctrl_if
) {
380 switch (req
->bmRequestType
& (USB_REQ_TYPE_MASK
| USB_REQ_RECIPIENT_MASK
)) {
381 case (USB_REQ_TYPE_STANDARD
| USB_REQ_RECIPIENT_INTERFACE
):
382 switch (req
->bRequest
) {
383 case USB_REQ_GET_INTERFACE
:
384 PIOS_USBHOOK_CtrlTx(&cdc_altset
, 1);
386 case USB_REQ_SET_INTERFACE
:
387 cdc_altset
= (uint8_t)(req
->wValue
);
390 /* Unhandled standard request */
396 case (USB_REQ_TYPE_CLASS
| USB_REQ_RECIPIENT_INTERFACE
):
397 switch (req
->bRequest
) {
398 case USB_CDC_REQ_SET_LINE_CODING
:
399 PIOS_USBHOOK_CtrlRx((uint8_t *)&line_coding
, sizeof(line_coding
));
401 case USB_CDC_REQ_GET_LINE_CODING
:
402 PIOS_USBHOOK_CtrlTx((uint8_t *)&line_coding
, sizeof(line_coding
));
404 case USB_CDC_REQ_SET_CONTROL_LINE_STATE
:
405 control_line_state
= req
->wValue
;
408 /* Unhandled class request */
415 /* Unhandled request */
422 static bool PIOS_USB_CDC_Available(uint32_t usbcdc_id
)
424 struct pios_usb_cdc_dev
*usb_cdc_dev
= (struct pios_usb_cdc_dev
*)usbcdc_id
;
426 bool valid
= PIOS_USB_CDC_validate(usb_cdc_dev
);
430 return PIOS_USB_CheckAvailable(usb_cdc_dev
->lower_id
) &&
431 (control_line_state
& USB_CDC_CONTROL_LINE_STATE_DTE_PRESENT
);
435 * Called *after* the data has been written to the buffer provided in the setup stage. The
436 * setup request is passed in here again so we know *which* EP0 data out has just completed.
438 static void PIOS_USB_CDC_CTRL_IF_CtrlDataOut(uint32_t usb_cdc_id
, const struct usb_setup_request
*req
)
440 struct pios_usb_cdc_dev
*usb_cdc_dev
= (struct pios_usb_cdc_dev
*)usb_cdc_id
;
442 if (!PIOS_USB_CDC_validate(usb_cdc_dev
)) {
446 /* Make sure this is a request for an interface we know about */
447 uint8_t ifnum
= req
->wIndex
& 0xFF;
448 if (ifnum
!= usb_cdc_dev
->cfg
->ctrl_if
) {
452 switch (req
->bmRequestType
& (USB_REQ_TYPE_MASK
| USB_REQ_RECIPIENT_MASK
)) {
453 case (USB_REQ_TYPE_STANDARD
| USB_REQ_RECIPIENT_INTERFACE
):
454 switch (req
->bRequest
) {
456 /* Unhandled standard request */
462 case (USB_REQ_TYPE_CLASS
| USB_REQ_RECIPIENT_INTERFACE
):
463 switch (req
->bRequest
) {
464 case USB_CDC_REQ_SET_LINE_CODING
:
466 * If we cared to, this is where we would apply the new line coding
467 * that is now stored in the line_coding struct. This could be used
468 * to notify the upper COM layer that the baud rate has changed. This
469 * may be useful in the case of a COM USB bridge where we would
470 * auto-adjust the USART baud rate based on the line coding set here.
474 /* Unhandled class request */
481 /* Unhandled request */
486 static struct usb_cdc_serial_state_report uart_state
= {
487 .bmRequestType
= 0xA1,
488 .bNotification
= USB_CDC_NOTIFICATION_SERIAL_STATE
,
490 .wIndex
= htousbs(1),
491 .wLength
= htousbs(2),
492 .bmUartState
= htousbs(0),
495 static bool PIOS_USB_CDC_CTRL_EP_IN_Callback(
496 __attribute__((unused
)) uint32_t usb_cdc_id
,
497 __attribute__((unused
)) uint8_t epnum
,
498 __attribute__((unused
)) uint16_t len
)
500 struct pios_usb_cdc_dev
*usb_cdc_dev
= (struct pios_usb_cdc_dev
*)pios_usb_cdc_id
;
502 bool valid
= PIOS_USB_CDC_validate(usb_cdc_dev
);
506 /* Give back UART State Bitmap */
509 * 6: bOverRun overrun error
510 * 5: bParity parity error
511 * 4: bFraming framing error
513 * 2: bBreak break reception
518 /* Currently, we only handle TxCarrier and RxCarrier reporting */
519 uint16_t new_uart_state
= 0;
520 if (usb_cdc_dev
->tx_out_cb
) {
521 /* Someone is going to providing FC->PC data, advertise an RxCarrier to the host */
522 new_uart_state
|= 0x1;
524 if (usb_cdc_dev
->rx_in_cb
) {
525 /* Someone is consuming PC->FC data, advertise a TxCarrier to the host */
526 new_uart_state
|= 0x2;
529 /* Has anything changed since we last sent a notification? */
530 if ((new_uart_state
^ usb_cdc_dev
->prev_uart_state
) & 0x3) {
531 usb_cdc_dev
->prev_uart_state
= new_uart_state
;
533 uart_state
.bmUartState
= htousbs(new_uart_state
);
535 PIOS_USBHOOK_EndpointTx(usb_cdc_dev
->cfg
->ctrl_tx_ep
,
536 (uint8_t *)&uart_state
,
543 static bool PIOS_USB_CDC_DATA_EP_IN_Callback(uint32_t usb_cdc_id
, uint8_t epnum
, uint16_t len
);
544 static bool PIOS_USB_CDC_DATA_EP_OUT_Callback(uint32_t usb_cdc_id
, uint8_t epnum
, uint16_t len
);
546 static void PIOS_USB_CDC_DATA_IF_Init(uint32_t usb_cdc_id
)
548 struct pios_usb_cdc_dev
*usb_cdc_dev
= (struct pios_usb_cdc_dev
*)usb_cdc_id
;
550 if (!PIOS_USB_CDC_validate(usb_cdc_dev
)) {
554 /* Register endpoint specific callbacks with the USBHOOK layer */
555 PIOS_USBHOOK_RegisterEpInCallback(usb_cdc_dev
->cfg
->data_tx_ep
,
556 sizeof(usb_cdc_dev
->tx_packet_buffer
),
557 PIOS_USB_CDC_DATA_EP_IN_Callback
,
558 (uint32_t)usb_cdc_dev
);
559 PIOS_USBHOOK_RegisterEpOutCallback(usb_cdc_dev
->cfg
->data_rx_ep
,
560 sizeof(usb_cdc_dev
->rx_packet_buffer
),
561 PIOS_USB_CDC_DATA_EP_OUT_Callback
,
562 (uint32_t)usb_cdc_dev
);
563 usb_cdc_dev
->usb_data_if_enabled
= true;
566 static void PIOS_USB_CDC_DATA_IF_DeInit(uint32_t usb_cdc_id
)
568 struct pios_usb_cdc_dev
*usb_cdc_dev
= (struct pios_usb_cdc_dev
*)usb_cdc_id
;
570 if (!PIOS_USB_CDC_validate(usb_cdc_dev
)) {
574 /* DeRegister endpoint specific callbacks with the USBHOOK layer */
575 usb_cdc_dev
->usb_data_if_enabled
= false;
576 PIOS_USBHOOK_DeRegisterEpInCallback(usb_cdc_dev
->cfg
->data_tx_ep
);
577 PIOS_USBHOOK_DeRegisterEpOutCallback(usb_cdc_dev
->cfg
->data_rx_ep
);
580 static bool PIOS_USB_CDC_DATA_IF_Setup(
581 __attribute__((unused
)) uint32_t usb_cdc_id
,
582 __attribute__((unused
)) struct usb_setup_request
*req
)
584 /* There are no valid EP0 transactions for CDC DATA interfaces */
591 * Called *after* the data has been written to the buffer provided in the setup stage. The
592 * setup request is passed in here again so we know *which* EP0 data out has just completed.
594 static void PIOS_USB_CDC_DATA_IF_CtrlDataOut(
595 __attribute__((unused
)) uint32_t usb_cdc_id
,
596 __attribute__((unused
)) const struct usb_setup_request
*req
)
598 /* CDC DATA interfaces don't have any OUT data stages on the control endpoint */
603 * @brief Callback used to indicate a transmission from device INto host completed
604 * Checks if any data remains, pads it into HID packet and sends.
606 static bool PIOS_USB_CDC_DATA_EP_IN_Callback(
607 __attribute__((unused
)) uint32_t usb_cdc_id
,
608 __attribute__((unused
)) uint8_t epnum
,
609 __attribute__((unused
)) uint16_t len
)
611 struct pios_usb_cdc_dev
*usb_cdc_dev
= (struct pios_usb_cdc_dev
*)pios_usb_cdc_id
;
613 bool valid
= PIOS_USB_CDC_validate(usb_cdc_dev
);
617 bool rc
= PIOS_USB_CDC_SendData(usb_cdc_dev
);
619 /* No additional data was transmitted, note that tx is no longer active */
620 usb_cdc_dev
->tx_active
= false;
626 static bool PIOS_USB_CDC_DATA_EP_OUT_Callback(
627 __attribute__((unused
)) uint32_t usb_cdc_id
,
628 __attribute__((unused
)) uint8_t epnum
,
631 struct pios_usb_cdc_dev
*usb_cdc_dev
= (struct pios_usb_cdc_dev
*)pios_usb_cdc_id
;
633 if (!PIOS_USB_CDC_validate(usb_cdc_dev
)) {
637 if (len
> sizeof(usb_cdc_dev
->rx_packet_buffer
)) {
638 len
= sizeof(usb_cdc_dev
->rx_packet_buffer
);
641 if (!usb_cdc_dev
->rx_in_cb
) {
642 /* No Rx call back registered, disable the receiver */
643 usb_cdc_dev
->rx_active
= false;
648 bool need_yield
= false;
650 bytes_rxed
= (usb_cdc_dev
->rx_in_cb
)(usb_cdc_dev
->rx_in_context
,
651 usb_cdc_dev
->rx_packet_buffer
,
656 if (bytes_rxed
< len
) {
657 /* Lost bytes on rx */
658 usb_cdc_dev
->rx_dropped
+= (len
- bytes_rxed
);
662 if (headroom
>= sizeof(usb_cdc_dev
->rx_packet_buffer
)) {
663 /* We have room for a maximum length message */
664 PIOS_USBHOOK_EndpointRx(usb_cdc_dev
->cfg
->data_rx_ep
,
665 usb_cdc_dev
->rx_packet_buffer
,
666 sizeof(usb_cdc_dev
->rx_packet_buffer
));
669 /* Not enough room left for a message, apply backpressure */
670 usb_cdc_dev
->rx_active
= false;
674 #if defined(PIOS_INCLUDE_FREERTOS)
678 #endif /* PIOS_INCLUDE_FREERTOS */
683 #endif /* PIOS_INCLUDE_USB_CDC */