#include "project.h" static const struct usb_endpoint_descriptor comm_endp[] = { { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = 0x83, .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT, .wMaxPacketSize = 16, .bInterval = 255, } }; static const struct usb_endpoint_descriptor data_endp[] = { { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = 0x01, .bmAttributes = USB_ENDPOINT_ATTR_BULK, .wMaxPacketSize = 64, .bInterval = 1, }, { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = 0x82, .bmAttributes = USB_ENDPOINT_ATTR_BULK, .wMaxPacketSize = 64, .bInterval = 1, } }; static const struct { struct usb_cdc_header_descriptor header; struct usb_cdc_call_management_descriptor call_mgmt; struct usb_cdc_acm_descriptor acm; struct usb_cdc_union_descriptor cdc_union; } __attribute__ ((packed)) cdcacm_functional_descriptors = { .header = { .bFunctionLength = sizeof (struct usb_cdc_header_descriptor),.bDescriptorType = CS_INTERFACE,.bDescriptorSubtype = USB_CDC_TYPE_HEADER,.bcdCDC = 0x0110,},.call_mgmt = { .bFunctionLength = sizeof (struct usb_cdc_call_management_descriptor),.bDescriptorType = CS_INTERFACE,.bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT,.bmCapabilities = 0,.bDataInterface = 1,},.acm = { .bFunctionLength = sizeof (struct usb_cdc_acm_descriptor),.bDescriptorType = CS_INTERFACE,.bDescriptorSubtype = USB_CDC_TYPE_ACM,.bmCapabilities = 0,},.cdc_union = { .bFunctionLength = sizeof (struct usb_cdc_union_descriptor),.bDescriptorType = CS_INTERFACE,.bDescriptorSubtype = USB_CDC_TYPE_UNION,.bControlInterface = 0,.bSubordinateInterface0 = 1,} }; const struct usb_interface_descriptor comm_iface[] = { { .bLength = USB_DT_INTERFACE_SIZE, .bDescriptorType = USB_DT_INTERFACE, .bInterfaceNumber = 0, .bAlternateSetting = 0, .bNumEndpoints = 1, .bInterfaceClass = USB_CLASS_CDC, .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, .iInterface = 0, .endpoint = comm_endp, .extra = &cdcacm_functional_descriptors, .extralen = sizeof (cdcacm_functional_descriptors)} }; const struct usb_interface_descriptor data_iface[] = { { .bLength = USB_DT_INTERFACE_SIZE, .bDescriptorType = USB_DT_INTERFACE, .bInterfaceNumber = 1, .bAlternateSetting = 0, .bNumEndpoints = 2, .bInterfaceClass = USB_CLASS_DATA, .bInterfaceSubClass = 0, .bInterfaceProtocol = 0, .iInterface = 0, .endpoint = data_endp, } }; int cdcacm_control_request (usbd_device * usbd_dev, struct usb_setup_data *req, uint8_t ** buf, uint16_t * len, int (**complete) (usbd_device * usbd_dev, struct usb_setup_data * req)) { (void) complete; (void) buf; (void) usbd_dev; switch (req->bRequest) { case USB_CDC_REQ_SET_CONTROL_LINE_STATE: { /* * This Linux cdc_acm driver requires this to be implemented * even though it's optional in the CDC spec, and we don't * advertise it in the ACM functional descriptor. */ char local_buf[10]; struct usb_cdc_notification *notif = (void *) local_buf; /* We echo signals back to host as notification. */ notif->bmRequestType = 0xA1; notif->bNotification = USB_CDC_NOTIFY_SERIAL_STATE; notif->wValue = 0; notif->wIndex = 0; notif->wLength = 2; local_buf[8] = req->wValue & 3; local_buf[9] = 0; // usbd_ep_write_packet(0x83, buf, 10); return 1; } case USB_CDC_REQ_SET_LINE_CODING: if (*len < sizeof (struct usb_cdc_line_coding)) { return 0; } return 1; } return 0; } void cdcacm_data_tx (void *buf, size_t len) { usbd_ep_write_packet (usbd_dev, 0x82, buf, len); } void cdcacm_data_rx_cb (usbd_device * usbd_dev, uint8_t ep) { (void) ep; char buf[64]; int len = usbd_ep_read_packet (usbd_dev, 0x01, buf, 64); if (len) usart2_tx (buf, len); }