#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){} }