summaryrefslogtreecommitdiff
path: root/src/libs/usb/cdc-acm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/usb/cdc-acm.c')
-rw-r--r--src/libs/usb/cdc-acm.c184
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){}
+}