diff options
Diffstat (limited to 'src/libs/usb/cdc-acm.c')
| -rw-r--r-- | src/libs/usb/cdc-acm.c | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/src/libs/usb/cdc-acm.c b/src/libs/usb/cdc-acm.c new file mode 100644 index 0000000..711bc99 --- /dev/null +++ b/src/libs/usb/cdc-acm.c @@ -0,0 +1,184 @@ +#include "cdc-acm.h" +#include "cusb.h" +#include "proto.h" +#include "../gpio.h" +#include "../addrmap.h" + +void cdc_acm_ep1_in_handler(u8 *buffer, int len); +void cdc_acm_ep2_in_handler(u8 *buffer, int len); +void cdc_acm_ep3_out_handler(u8 *buffer, int len); +void cdc_acm_setup_handler(UD_SETUP *pkt); +void cdc_acm_setup_ack_handler(void); +void cdc_acm_eoi(void); + +u8 configuration_descriptor[128]; +u8 *send_buffer; +u8 send_buffer_size=0; +u8 *recv_buffer; +u8 recv_buffer_size=0; + +DeviceConfiguration CDC_ACM_CONFIG ={ + .device_descriptor = { + .bDeviceClass = USB_DEVICE_CLASS_CDC, + .idProduct = 1, + .iManufacturer = 1, // String id 1 + .iProduct = 2 // String id 2 + }, + .configuration_descriptor = { + .bNumInterfaces = 2 + }, + .interface_descriptors = { + { + .bInterfaceClass = USB_INTERFACE_CLASS_COMMUNICATION, + .bInterfaceSubClass = USB_INTERFACE_SUBCLASS_ACM, + .bInterfaceProtocol = USB_INTERFACE_COMMUNICATION_PROTOCOL_NOPROTO, + .bInterfaceNumber = 0, + .bNumEndpoints = 1 // SHOULD BE 1 (IT IS 0 BECAUSE GET_CONFIG DESCRIPTOR MUST BE UPDATED) + }, + { + .bInterfaceClass = USB_INTERFACE_CLASS_DATA, + .bInterfaceProtocol = USB_INTERFACE_COMMUNICATION_PROTOCOL_NOPROTO, + .bInterfaceNumber = 1, + .bNumEndpoints = 2 + } + }, + .endpoints = { + { + .endpoint_descriptor = { + .bEndpointAddress = B_ENDPOINT_ADDRESS(1, USB_DIRECTION_IN), + .wMaxPacketSize=64, + .bmAttributes = USB_TRANSFERT_TYPE_INTERRUPT, + .bInterval = 0 + }, + .handler = cdc_acm_ep1_in_handler + }, + { + .endpoint_descriptor = { + .bEndpointAddress = B_ENDPOINT_ADDRESS(2, USB_DIRECTION_IN), + .wMaxPacketSize=64, + .bmAttributes = USB_TRANSFERT_TYPE_BULK, + .bInterval = 0 + }, + .handler = cdc_acm_ep2_in_handler + }, + { + .endpoint_descriptor = { + .bEndpointAddress = B_ENDPOINT_ADDRESS(3, USB_DIRECTION_OUT), + .wMaxPacketSize=64, + .bmAttributes = USB_TRANSFERT_TYPE_BULK, + .bInterval = 0 + }, + .handler = cdc_acm_ep3_out_handler + }, + }, + .descriptor_strings = { + "Raspberry Pi", // Vendor + "Pico RP2040" // Product + }, + .supported_languages = { + .wLANGID0 = USB_LANG_ENGLISH_US + }, + .setup_handler = cdc_acm_setup_handler, + .setup_ack_handler = cdc_acm_setup_ack_handler, + .eoi=cdc_acm_eoi +}; + + +void usb_cdc_acm_init(void) { + cusb_init(&CDC_ACM_CONFIG); + USB_CDC_ACM_FUNCTIONAL_DESCRIPTOR f; + f.header_descriptor.bFunctionLength=sizeof(USB_CDC_HEADER_FUNCTIONAL_DESCRIPTOR); + f.header_descriptor.bDescriptorType=0x24; + f.header_descriptor.bcdCDC=0b0110; + f.acm_descriptor.bFunctionLength=sizeof(USB_ACM_FUNCTIONAL_DESCRIPTOR); + f.acm_descriptor.bDescriptorType=0x24; + f.acm_descriptor.bDescriptorSubtype=0x02; + f.acm_descriptor.bmCapabilities=0xf; + f.union_descriptor.bFunctionLength=sizeof(USB_UNION_INTERFACE_DESCRIPTOR); + f.union_descriptor.bDescriptorType=0x24; + f.union_descriptor.bDescriptorSubtype=0x06; + f.union_descriptor.bMasterInterface=0; + f.union_descriptor.bSlaveInterface0=1; + + // ----- Setting-up full configuration descriptor ----- + u8 *ptr=configuration_descriptor; + // Configuration descriptor + memcpy(ptr,(void*) &(CDC_ACM_CONFIG.configuration_descriptor), sizeof(USB_CONFIGURATION_DESCRIPTOR)); + ptr+=sizeof(USB_CONFIGURATION_DESCRIPTOR); + // Communication interface descriptor + memcpy(ptr,(void*) &(CDC_ACM_CONFIG.interface_descriptors[0]), sizeof(USB_INTERFACE_DESCRIPTOR)); + ptr+=sizeof(USB_INTERFACE_DESCRIPTOR); + memcpy(ptr,(void*) &f, sizeof(USB_CDC_ACM_FUNCTIONAL_DESCRIPTOR)); // Functional descriptor + ptr+=sizeof(USB_CDC_ACM_FUNCTIONAL_DESCRIPTOR); + memcpy(ptr,(void*) &(CDC_ACM_CONFIG.endpoints[0].endpoint_descriptor), sizeof(USB_ENDPOINT_DESCRIPTOR)); // Endpoint descriptor + ptr+=sizeof(USB_ENDPOINT_DESCRIPTOR); + + // Data interface descriptor + memcpy(ptr,(void*) &(CDC_ACM_CONFIG.interface_descriptors[1]), sizeof(USB_INTERFACE_DESCRIPTOR)); + ptr+=sizeof(USB_INTERFACE_DESCRIPTOR); + memcpy(ptr,(void*) &(CDC_ACM_CONFIG.endpoints[1].endpoint_descriptor), sizeof(USB_ENDPOINT_DESCRIPTOR)); + ptr+=sizeof(USB_ENDPOINT_DESCRIPTOR); + memcpy(ptr,(void*) &(CDC_ACM_CONFIG.endpoints[2].endpoint_descriptor), sizeof(USB_ENDPOINT_DESCRIPTOR)); + ptr+=sizeof(USB_ENDPOINT_DESCRIPTOR); + + // Setup full descriptor length + USB_CONFIGURATION_DESCRIPTOR *conf=(USB_CONFIGURATION_DESCRIPTOR*)configuration_descriptor; + conf->wTotalLength=ptr-configuration_descriptor; + + // Finalize + CDC_ACM_CONFIG.full_configuration_descriptor=configuration_descriptor; + + // Start receiving from host + cusb_start_xfer(0,64,&(CDC_ACM_CONFIG.endpoints[2])); +} + +void cdc_acm_ep1_in_handler(u8 *buffer, int len) {} + +void cdc_acm_ep2_in_handler(u8 *buffer, int len) { + send_buffer_size=0; +} + +void cdc_acm_ep3_out_handler(u8 *buffer, int len) { + if(recv_buffer_size){ + memcpy(recv_buffer, buffer, len); + recv_buffer_size=0; // Prevent further receive until usb_cdc_acm_recv() is called again + cusb_start_xfer(0,64,&(CDC_ACM_CONFIG.endpoints[2])); + } +} + +void cdc_acm_setup_handler(UD_SETUP *pkt){ + u8 direction=pkt->bmRequestType & BM_REQUEST_TYPE_DIR_BIT; + if(pkt->bRequest == USB_REQUEST_CODE_SET_LINE_CODING){ + // TODO + } + else if(pkt->bRequest == USB_REQUEST_CODE_SET_CONTROL_LINE_STATE){ + // TODO + } + else if(pkt->bRequest == USB_REQUEST_CODE_SEND_BREAK){ + // TODO + } + else { + // TODO + } + +} +void cdc_acm_setup_ack_handler(void){ +} + +void cdc_acm_eoi(void){ + if(send_buffer_size) + cusb_start_xfer(send_buffer,send_buffer_size,&(CDC_ACM_CONFIG.endpoints[1])); +} + +void usb_cdc_acm_send(char *data, int size){ + send_buffer=data; + send_buffer_size=size; + cusb_isr_trigger(); + while(send_buffer_size){}; +} + +void usb_cdc_acm_recv(char *data, int size){ + recv_buffer=data; + recv_buffer_size=size; + while(recv_buffer_size){} +} |
