35 #if defined(PIOS_INCLUDE_USB_CDC)
43 static void PIOS_USB_CDC_RegisterTxCallback(uintptr_t usbcdc_id,
pios_com_callback tx_out_cb, uintptr_t context);
44 static void PIOS_USB_CDC_RegisterRxCallback(uintptr_t usbcdc_id,
pios_com_callback rx_in_cb, uintptr_t context);
45 static void PIOS_USB_CDC_TxStart(uintptr_t usbcdc_id, uint16_t tx_bytes_avail);
46 static void PIOS_USB_CDC_RxStart(uintptr_t usbcdc_id, uint16_t rx_bytes_avail);
47 static bool PIOS_USB_CDC_Available (uintptr_t usbcdc_id);
51 .rx_start = PIOS_USB_CDC_RxStart,
52 .bind_tx_cb = PIOS_USB_CDC_RegisterTxCallback,
53 .bind_rx_cb = PIOS_USB_CDC_RegisterRxCallback,
54 .available = PIOS_USB_CDC_Available,
57 enum pios_usb_cdc_dev_magic {
58 PIOS_USB_CDC_DEV_MAGIC = 0xAABBCCDD,
61 struct pios_usb_cdc_dev {
62 enum pios_usb_cdc_dev_magic
magic;
68 uintptr_t rx_in_context;
70 uintptr_t tx_out_context;
72 bool usb_ctrl_if_enabled;
73 bool usb_data_if_enabled;
76 volatile bool rx_active;
84 volatile bool tx_active;
95 volatile uint16_t prev_uart_state;
98 static bool PIOS_USB_CDC_validate(
struct pios_usb_cdc_dev * usb_cdc_dev)
100 return (usb_cdc_dev && (usb_cdc_dev->magic == PIOS_USB_CDC_DEV_MAGIC));
103 static struct pios_usb_cdc_dev * PIOS_USB_CDC_alloc(
void)
105 struct pios_usb_cdc_dev * usb_cdc_dev;
107 usb_cdc_dev = (
struct pios_usb_cdc_dev *)
PIOS_malloc(
sizeof(*usb_cdc_dev));
108 if (!usb_cdc_dev)
return(NULL);
110 memset(usb_cdc_dev, 0,
sizeof(*usb_cdc_dev));
111 usb_cdc_dev->magic = PIOS_USB_CDC_DEV_MAGIC;
116 static void PIOS_USB_CDC_CTRL_IF_Init(uintptr_t usb_cdc_id);
117 static void PIOS_USB_CDC_CTRL_IF_DeInit(uintptr_t usb_cdc_id);
118 static bool PIOS_USB_CDC_CTRL_IF_Setup(uintptr_t usb_cdc_id,
struct usb_setup_request *req);
119 static void PIOS_USB_CDC_CTRL_IF_CtrlDataOut(uintptr_t usb_cdc_id,
const struct usb_setup_request *req);
122 .
init = PIOS_USB_CDC_CTRL_IF_Init,
123 .deinit = PIOS_USB_CDC_CTRL_IF_DeInit,
124 .setup = PIOS_USB_CDC_CTRL_IF_Setup,
125 .ctrl_data_out = PIOS_USB_CDC_CTRL_IF_CtrlDataOut,
129 static void PIOS_USB_CDC_DATA_IF_Init(uintptr_t usb_cdc_id);
130 static void PIOS_USB_CDC_DATA_IF_DeInit(uintptr_t usb_cdc_id);
131 static bool PIOS_USB_CDC_DATA_IF_Setup(uintptr_t usb_cdc_id,
struct usb_setup_request *req);
132 static void PIOS_USB_CDC_DATA_IF_CtrlDataOut(uintptr_t usb_cdc_id,
const struct usb_setup_request *req);
135 .
init = PIOS_USB_CDC_DATA_IF_Init,
136 .deinit = PIOS_USB_CDC_DATA_IF_DeInit,
137 .setup = PIOS_USB_CDC_DATA_IF_Setup,
138 .ctrl_data_out = PIOS_USB_CDC_DATA_IF_CtrlDataOut,
141 static uintptr_t pios_usb_cdc_id;
148 struct pios_usb_cdc_dev * usb_cdc_dev;
150 usb_cdc_dev = (
struct pios_usb_cdc_dev *) PIOS_USB_CDC_alloc();
151 if (!usb_cdc_dev)
goto out_fail;
154 usb_cdc_dev->cfg =
cfg;
155 usb_cdc_dev->lower_id = lower_id;
157 pios_usb_cdc_id = (uintptr_t) usb_cdc_dev;
160 usb_cdc_dev->rx_active =
false;
161 usb_cdc_dev->tx_active =
false;
164 usb_cdc_dev->rx_dropped = 0;
165 usb_cdc_dev->rx_oversize = 0;
168 usb_cdc_dev->prev_uart_state = 0;
171 usb_cdc_dev->usb_ctrl_if_enabled =
false;
175 usb_cdc_dev->usb_data_if_enabled =
false;
178 *usbcdc_id = (uintptr_t) usb_cdc_dev;
186 static bool PIOS_USB_CDC_SendData(
struct pios_usb_cdc_dev * usb_cdc_dev)
188 uint16_t bytes_to_tx;
190 if (!usb_cdc_dev->tx_out_cb) {
194 bool need_yield =
false;
195 bytes_to_tx = (usb_cdc_dev->tx_out_cb)(usb_cdc_dev->tx_out_context,
196 usb_cdc_dev->tx_packet_buffer,
197 sizeof(usb_cdc_dev->tx_packet_buffer),
200 if (bytes_to_tx == 0) {
201 usb_cdc_dev->tx_active =
false;
210 usb_cdc_dev->tx_active =
true;
213 usb_cdc_dev->tx_packet_buffer,
219 static void PIOS_USB_CDC_RxStart(uintptr_t usbcdc_id, uint16_t rx_bytes_avail) {
220 struct pios_usb_cdc_dev * usb_cdc_dev = (
struct pios_usb_cdc_dev *)usbcdc_id;
222 bool valid = PIOS_USB_CDC_validate(usb_cdc_dev);
226 if (!usb_cdc_dev->usb_data_if_enabled) {
237 usb_cdc_dev->rx_packet_buffer,
238 sizeof(usb_cdc_dev->rx_packet_buffer));
239 usb_cdc_dev->rx_active =
true;
243 static void PIOS_USB_CDC_TxStart(uintptr_t usbcdc_id, uint16_t tx_bytes_avail)
245 struct pios_usb_cdc_dev * usb_cdc_dev = (
struct pios_usb_cdc_dev *)usbcdc_id;
247 bool valid = PIOS_USB_CDC_validate(usb_cdc_dev);
251 if (!usb_cdc_dev->usb_data_if_enabled) {
259 if (!usb_cdc_dev->tx_active) {
261 PIOS_USB_CDC_SendData(usb_cdc_dev);
265 static void PIOS_USB_CDC_RegisterRxCallback(uintptr_t usbcdc_id,
pios_com_callback rx_in_cb, uintptr_t context)
267 struct pios_usb_cdc_dev * usb_cdc_dev = (
struct pios_usb_cdc_dev *)usbcdc_id;
269 bool valid = PIOS_USB_CDC_validate(usb_cdc_dev);
276 usb_cdc_dev->rx_in_context = context;
277 usb_cdc_dev->rx_in_cb = rx_in_cb;
280 static void PIOS_USB_CDC_RegisterTxCallback(uintptr_t usbcdc_id,
pios_com_callback tx_out_cb, uintptr_t context)
282 struct pios_usb_cdc_dev * usb_cdc_dev = (
struct pios_usb_cdc_dev *)usbcdc_id;
284 bool valid = PIOS_USB_CDC_validate(usb_cdc_dev);
291 usb_cdc_dev->tx_out_context = context;
292 usb_cdc_dev->tx_out_cb = tx_out_cb;
295 static bool PIOS_USB_CDC_CTRL_EP_IN_Callback(uintptr_t usb_cdc_id, uint8_t epnum, uint16_t len);
297 static void PIOS_USB_CDC_CTRL_IF_Init(uintptr_t usb_cdc_id)
299 struct pios_usb_cdc_dev * usb_cdc_dev = (
struct pios_usb_cdc_dev *)usb_cdc_id;
301 if (!PIOS_USB_CDC_validate(usb_cdc_dev)) {
307 sizeof(usb_cdc_dev->ctrl_tx_packet_buffer),
308 PIOS_USB_CDC_CTRL_EP_IN_Callback,
309 (uintptr_t) usb_cdc_dev);
310 usb_cdc_dev->usb_ctrl_if_enabled =
true;
313 static void PIOS_USB_CDC_CTRL_IF_DeInit(uintptr_t usb_cdc_id)
315 struct pios_usb_cdc_dev * usb_cdc_dev = (
struct pios_usb_cdc_dev *)usb_cdc_id;
317 if (!PIOS_USB_CDC_validate(usb_cdc_dev)) {
322 usb_cdc_dev->usb_ctrl_if_enabled =
false;
325 static uint8_t cdc_altset;
333 static uint16_t control_line_state;
335 static bool PIOS_USB_CDC_CTRL_IF_Setup(uintptr_t usb_cdc_id,
struct usb_setup_request *req)
337 struct pios_usb_cdc_dev * usb_cdc_dev = (
struct pios_usb_cdc_dev *)usb_cdc_id;
339 if (!PIOS_USB_CDC_validate(usb_cdc_dev)) {
344 uint8_t ifnum = req->
wIndex & 0xFF;
345 if (ifnum != usb_cdc_dev->cfg->ctrl_if) {
356 cdc_altset = (uint8_t)(req->
wValue);
373 control_line_state = req->
wValue;
389 static bool PIOS_USB_CDC_Available (uintptr_t usbcdc_id)
391 struct pios_usb_cdc_dev * usb_cdc_dev = (
struct pios_usb_cdc_dev *)usbcdc_id;
393 bool valid = PIOS_USB_CDC_validate(usb_cdc_dev);
403 static void PIOS_USB_CDC_CTRL_IF_CtrlDataOut(uintptr_t usb_cdc_id,
const struct usb_setup_request *req)
405 struct pios_usb_cdc_dev * usb_cdc_dev = (
struct pios_usb_cdc_dev *)usb_cdc_id;
407 if (!PIOS_USB_CDC_validate(usb_cdc_dev)) {
412 uint8_t ifnum = req->
wIndex & 0xFF;
413 if (ifnum != usb_cdc_dev->cfg->ctrl_if) {
457 .bmUartState =
htousbs(2 | 1 ),
460 static bool PIOS_USB_CDC_CTRL_EP_IN_Callback(uintptr_t usb_cdc_id, uint8_t epnum, uint16_t len)
462 struct pios_usb_cdc_dev * usb_cdc_dev = (
struct pios_usb_cdc_dev *)pios_usb_cdc_id;
464 bool valid = PIOS_USB_CDC_validate(usb_cdc_dev);
468 (uint8_t *)&uart_state,
474 static bool PIOS_USB_CDC_DATA_EP_IN_Callback(uintptr_t usb_cdc_id, uint8_t epnum, uint16_t len);
475 static bool PIOS_USB_CDC_DATA_EP_OUT_Callback(uintptr_t usb_cdc_id, uint8_t epnum, uint16_t len);
477 static void PIOS_USB_CDC_DATA_IF_Init(uintptr_t usb_cdc_id)
479 struct pios_usb_cdc_dev * usb_cdc_dev = (
struct pios_usb_cdc_dev *)usb_cdc_id;
481 if (!PIOS_USB_CDC_validate(usb_cdc_dev)) {
487 sizeof(usb_cdc_dev->tx_packet_buffer),
488 PIOS_USB_CDC_DATA_EP_IN_Callback,
489 (uintptr_t) usb_cdc_dev);
491 sizeof(usb_cdc_dev->rx_packet_buffer),
492 PIOS_USB_CDC_DATA_EP_OUT_Callback,
493 (uintptr_t) usb_cdc_dev);
494 usb_cdc_dev->usb_data_if_enabled =
true;
497 static void PIOS_USB_CDC_DATA_IF_DeInit(uintptr_t usb_cdc_id)
499 struct pios_usb_cdc_dev * usb_cdc_dev = (
struct pios_usb_cdc_dev *)usb_cdc_id;
501 if (!PIOS_USB_CDC_validate(usb_cdc_dev)) {
506 usb_cdc_dev->rx_active =
false;
507 usb_cdc_dev->rx_dropped = 0;
508 usb_cdc_dev->rx_oversize = 0;
509 usb_cdc_dev->tx_active =
false;
510 usb_cdc_dev->usb_data_if_enabled =
false;
517 static bool PIOS_USB_CDC_DATA_IF_Setup(uintptr_t usb_cdc_id,
struct usb_setup_request *req)
529 static void PIOS_USB_CDC_DATA_IF_CtrlDataOut(uintptr_t usb_cdc_id,
const struct usb_setup_request *req)
539 static bool PIOS_USB_CDC_DATA_EP_IN_Callback(uintptr_t usb_cdc_id, uint8_t epnum, uint16_t len)
541 struct pios_usb_cdc_dev * usb_cdc_dev = (
struct pios_usb_cdc_dev *)pios_usb_cdc_id;
543 bool valid = PIOS_USB_CDC_validate(usb_cdc_dev);
546 bool rc = PIOS_USB_CDC_SendData(usb_cdc_dev);
551 static bool PIOS_USB_CDC_DATA_EP_OUT_Callback(uintptr_t usb_cdc_id, uint8_t epnum, uint16_t len)
553 struct pios_usb_cdc_dev * usb_cdc_dev = (
struct pios_usb_cdc_dev *)pios_usb_cdc_id;
555 if (!PIOS_USB_CDC_validate(usb_cdc_dev)) {
559 if (len >
sizeof(usb_cdc_dev->rx_packet_buffer)) {
560 len =
sizeof(usb_cdc_dev->rx_packet_buffer);
563 if (!usb_cdc_dev->rx_in_cb) {
565 usb_cdc_dev->rx_active =
false;
570 bool need_yield =
false;
572 bytes_rxed = (usb_cdc_dev->rx_in_cb)(usb_cdc_dev->rx_in_context,
573 usb_cdc_dev->rx_packet_buffer,
578 if (bytes_rxed < len) {
580 usb_cdc_dev->rx_dropped += (len - bytes_rxed);
584 if (headroom >=
sizeof(usb_cdc_dev->rx_packet_buffer)) {
587 usb_cdc_dev->rx_packet_buffer,
588 sizeof(usb_cdc_dev->rx_packet_buffer));
592 usb_cdc_dev->rx_active =
false;
void PIOS_USBHOOK_CtrlTx(const uint8_t *buf, uint16_t len)
USB_CDC_LINE_CODING_STOP_1
Main PiOS header to include all the compiled in PiOS options.
const struct pios_com_driver pios_usb_cdc_com_driver
#define USB_REQ_TYPE_CLASS
APIs for PIOS_USBHOOK layer.
void PIOS_USBHOOK_CtrlRx(uint8_t *buf, uint16_t len)
USB_CDC_NOTIFICATION_SERIAL_STATE
#define USB_REQ_TYPE_MASK
#define USB_REQ_TYPE_STANDARD
void * PIOS_malloc(size_t size)
bool PIOS_USB_CheckAvailable(uintptr_t id)
#define USB_REQ_RECIPIENT_MASK
#define PIOS_USB_BOARD_CDC_MGMT_LENGTH
void(* init)(uintptr_t context)
static struct flyingpicmd_cfg_fa cfg
void PIOS_USBHOOK_EndpointRx(uint8_t epnum, uint8_t *buf, uint16_t len)
#define USB_REQ_RECIPIENT_INTERFACE
void PIOS_USBHOOK_RegisterEpInCallback(uint8_t epnum, uint16_t max_len, pios_usbhook_epcb cb, uintptr_t context)
USB HID layer functions header.
void PIOS_USBHOOK_EndpointTx(uint8_t epnum, const uint8_t *buf, uint16_t len)
void PIOS_USBHOOK_DeRegisterEpInCallback(uint8_t epnum)
void PIOS_USBHOOK_RegisterEpOutCallback(uint8_t epnum, uint16_t max_len, pios_usbhook_epcb cb, uintptr_t context)
#define PIOS_USB_BOARD_CDC_DATA_LENGTH
int32_t PIOS_USB_CDC_Init(uintptr_t *usbcdc_id, const struct pios_usb_cdc_cfg *cfg, uintptr_t lower_id)
USB COM CDC private definitions.
void PIOS_USBHOOK_DeRegisterEpOutCallback(uint8_t epnum)
#define PIOS_Assert(test)
USB_CDC_LINE_CODING_PARITY_NONE
void(* tx_start)(uintptr_t id, uint16_t tx_bytes_avail)
void PIOS_USBHOOK_RegisterIfOps(uint8_t ifnum, struct pios_usb_ifops *ifops, uintptr_t context)
uint16_t(* pios_com_callback)(uintptr_t context, uint8_t *buf, uint16_t buf_len, uint16_t *headroom, bool *task_woken)