#include "cdc.h" #include #include "../usb_device_types.h" #include "../usb.h" #include #include // state static USB_CdcState cdcs = { 0 }; static uint8_t tx_buffer[USB_CDC_PCKT_BUFSIZE]; #define USB_CDC_FIFO_MEM_SIZE (3072) // FIXME: ez vagy a blocking FIFO bugos static uint8_t fifo_mem[USB_CDC_FIFO_MEM_SIZE]; static BFifo fifo; void usb_cdc_read_callback(const uint8_t * data, uint32_t size); void usb_cdc_init(const USB_CdcAssignments *as) { // clear the structure memset(&cdcs, 0, sizeof(USB_CdcState)); // fill-in default values USB_Cdc_LineCodingStruct *lc = &cdcs.line_coding; lc->dwDTERate = USB_CDC_DEFAULT_BITRATE; lc->bCharFormat = USB_CDC_DEFAULT_CHAR_FORMAT; lc->bParityType = USB_CDC_DEFAULT_PARITY_TYPE; lc->bDataBits = USB_CDC_DEFAULT_DATA_BITS; // fill-in assigments cdcs.ep_assignments = *as; // initialize buffer bfifo_create(&fifo, fifo_mem, USB_CDC_FIFO_MEM_SIZE); // from now on CDC is considered initialized cdcs.initialized = true; } //static uint8_t replyBuf[sizeof(USB_Cdc_LineCodingStruct)]; int usb_cdc_process_and_return(USB_CallbackEvent *cbevt) { int ret = -1; switch (cbevt->type) { case USB_CBEVT_UNKNOWN_REQ: { switch (cbevt->setup_request->bRequest) { case USB_CDC_SET_LINE_CODING: // set line coding memcpy(&cdcs.line_coding, cbevt->data, sizeof(USB_Cdc_LineCodingStruct)); //MSG("%u\n", cdcs.line_coding.dwDTERate); ret = 0; break; case USB_CDC_GET_LINE_CODING: // get line coding cbevt->reply_data = (const uint8_t *) &cdcs.line_coding; // expert move: pass the pointer, no copying cbevt->reply_size = sizeof(USB_Cdc_LineCodingStruct); cbevt->reply_valid = true; // the reply has been set to something valid ret = 0; break; case USB_CDC_SEND_BREAK: // send break // do nothing ret = 0; break; case USB_CDC_SET_CONTROL_LINE_STATE: // set control line state memcpy(&cdcs.control_line_state, cbevt->data, sizeof(USB_Cdc_ControlLineStateStruct)); //MSG("%u\n", cdcs.control_line_state.D); ret = 0; break; default: break; } // send a ZLP reply if (ret != -1) { cbevt->reply_data = NULL; cbevt->reply_size = 0; cbevt->reply_valid = true; } break; } case USB_CBEVT_OUT: { if (cbevt->ep == cdcs.ep_assignments.data_ep) { //MSG("%c\n", cbevt->data[0]); ret = 0; usb_cdc_read_callback(cbevt->data, cbevt->size); //usbcore_write(cdcs.ep_assignments.data_ep, cbevt->data, cbevt->size); // echo } break; } case USB_CBEVT_IN: { if (cbevt->ep == cdcs.ep_assignments.control_ep) { // if notification feeding is requested usbcore_write(cdcs.ep_assignments.control_ep, NULL, 0); // send ZLP ret = 0; } else if (cbevt->ep == cdcs.ep_assignments.data_ep) { // if data are requested //usbcore_write(cdcs.ep_assignments.data_ep, NULL, 0); // send ZLP ret = 0; // read from the fifo uint32_t readSize = bfifo_read(&fifo, tx_buffer, USB_CDC_PCKT_BUFSIZE); if (readSize > 0) { uint32_t writeSize = usbcore_write(cdcs.ep_assignments.data_ep, tx_buffer, readSize); // write data acquired from the buffer bfifo_pop(&fifo, writeSize, 0); // pop with no blocking } } } default: break; } return ret; } // void usb_event_callback(USB_CallbackEvent *cbevt) { // usb_cdc_process_and_return(cbevt); // } void usb_cdc_write(const uint8_t * data, uint32_t size) { if (cdcs.initialized) { bfifo_push_all(&fifo, data, size); } } __attribute__((weak)) void usb_cdc_read_callback(const uint8_t * data, uint32_t size) { (void) data; (void) size; return; }