27 #include <libopencm3/stm32/desig.h>
28 #include <libopencm3/stm32/gpio.h>
29 #include <libopencm3/stm32/rcc.h>
30 #include <libopencm3/usb/usbd.h>
31 #include <libopencm3/usb/cdc.h>
32 #include <libopencm3/cm3/scb.h>
39 #ifndef CONFIG_USB_MAX_POWER
40 #define CONFIG_USB_MAX_POWER 100
43 static const struct usb_device_descriptor desc = {
44 .bLength = USB_DT_DEVICE_SIZE,
45 .bDescriptorType = USB_DT_DEVICE,
47 .bDeviceClass = USB_CLASS_CDC,
50 .bMaxPacketSize0 = 64,
57 .bNumConfigurations = 1,
65 static const struct usb_endpoint_descriptor comm_endp[] = {{
66 .bLength = USB_DT_ENDPOINT_SIZE,
67 .bDescriptorType = USB_DT_ENDPOINT,
68 .bEndpointAddress = 0x83,
69 .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
74 static const struct usb_endpoint_descriptor data_endp[] = {{
75 .bLength = USB_DT_ENDPOINT_SIZE,
76 .bDescriptorType = USB_DT_ENDPOINT,
77 .bEndpointAddress = 0x01,
78 .bmAttributes = USB_ENDPOINT_ATTR_BULK,
82 .bLength = USB_DT_ENDPOINT_SIZE,
83 .bDescriptorType = USB_DT_ENDPOINT,
84 .bEndpointAddress = 0x82,
85 .bmAttributes = USB_ENDPOINT_ATTR_BULK,
91 struct usb_cdc_header_descriptor
header;
92 struct usb_cdc_call_management_descriptor
call_mgmt;
93 struct usb_cdc_acm_descriptor
acm;
97 .bFunctionLength =
sizeof(
struct usb_cdc_header_descriptor),
98 .bDescriptorType = CS_INTERFACE,
99 .bDescriptorSubtype = USB_CDC_TYPE_HEADER,
104 sizeof(
struct usb_cdc_call_management_descriptor),
105 .bDescriptorType = CS_INTERFACE,
106 .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT,
111 .bFunctionLength =
sizeof(
struct usb_cdc_acm_descriptor),
112 .bDescriptorType = CS_INTERFACE,
113 .bDescriptorSubtype = USB_CDC_TYPE_ACM,
117 .bFunctionLength =
sizeof(
struct usb_cdc_union_descriptor),
118 .bDescriptorType = CS_INTERFACE,
119 .bDescriptorSubtype = USB_CDC_TYPE_UNION,
120 .bControlInterface = 0,
121 .bSubordinateInterface0 = 1,
125 static const struct usb_interface_descriptor comm_iface[] = {{
126 .bLength = USB_DT_INTERFACE_SIZE,
127 .bDescriptorType = USB_DT_INTERFACE,
128 .bInterfaceNumber = 0,
129 .bAlternateSetting = 0,
131 .bInterfaceClass = USB_CLASS_CDC,
132 .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
133 .bInterfaceProtocol = USB_CDC_PROTOCOL_AT,
136 .endpoint = comm_endp,
138 .extra = &cdcacm_functional_descriptors,
139 .extralen =
sizeof(cdcacm_functional_descriptors)
142 static const struct usb_interface_descriptor data_iface[] = {{
143 .bLength = USB_DT_INTERFACE_SIZE,
144 .bDescriptorType = USB_DT_INTERFACE,
145 .bInterfaceNumber = 1,
146 .bAlternateSetting = 0,
148 .bInterfaceClass = USB_CLASS_DATA,
149 .bInterfaceSubClass = 0,
150 .bInterfaceProtocol = 0,
153 .endpoint = data_endp,
156 static const struct usb_interface ifaces[] = {{
158 .altsetting = comm_iface,
161 .altsetting = data_iface,
164 static const struct usb_config_descriptor config = {
165 .bLength = USB_DT_CONFIGURATION_SIZE,
166 .bDescriptorType = USB_DT_CONFIGURATION,
169 .bConfigurationValue = 1,
171 .bmAttributes = 0x80,
177 static char serial_no[25];
179 static const char * usb_strings[] = {
180 "redfelineninja.org.uk",
181 "CDC-ADM command console",
186 static uint8_t outbuf[1024];
188 static usbd_device *usbd_dev;
194 int _write(
int fd,
char *ptr,
int len);
195 static void cdcacm_set_config(usbd_device *usbd_dev, uint16_t wValue);
222 while (!usbd_ep_write_packet(usbd_dev, 0x82, &t->
ch, 1))
234 static void usb_hwinit(
void)
238 rcc_periph_clock_enable(RCC_GPIOA);
239 rcc_periph_clock_enable(RCC_GPIOB);
242 gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL,
244 gpio_clear(GPIOA, GPIO11 | GPIO12);
250 desig_get_unique_id_as_string(serial_no,
sizeof(serial_no));
256 usbd_init(&st_usbfs_v1_usb_driver, &desc, &config, usb_strings, 3,
257 usbd_control_buffer,
sizeof(usbd_control_buffer));
259 #elif defined(STM32F4)
260 static void usb_hwinit(
void)
262 rcc_periph_clock_enable(RCC_GPIOA);
263 rcc_periph_clock_enable(RCC_OTGFS);
265 gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE,
266 GPIO9 | GPIO11 | GPIO12);
267 gpio_set_af(GPIOA, GPIO_AF10, GPIO9 | GPIO11 | GPIO12);
269 usbd_dev = usbd_init(&otgfs_usb_driver, &desc, &config,
271 usbd_control_buffer,
sizeof(usbd_control_buffer));
274 #error Unsupported part
283 usbd_register_set_config_callback(usbd_dev, cdcacm_set_config);
294 static int cdcacm_control_request(usbd_device *dev,
295 struct usb_setup_data *req, uint8_t **buf, uint16_t *len,
296 void (**complete)(usbd_device *dev,
struct usb_setup_data *req))
302 switch (req->bRequest) {
303 case USB_CDC_REQ_SET_CONTROL_LINE_STATE: {
310 case USB_CDC_REQ_SET_LINE_CODING:
311 if (*len <
sizeof(
struct usb_cdc_line_coding)) {
320 static void cdcacm_data_rx_cb(usbd_device *dev, uint8_t ep)
325 int len = usbd_ep_read_packet(dev, 0x01, buf, 64);
327 for (
int i = 0; i < len; i++) {
329 if (buf[i] ==
'\r') {
339 static void cdcacm_set_config(usbd_device *dev, uint16_t wValue)
343 usbd_ep_setup(dev, 0x01, USB_ENDPOINT_ATTR_BULK, 64,
345 usbd_ep_setup(dev, 0x82, USB_ENDPOINT_ATTR_BULK, 64, NULL);
346 usbd_ep_setup(dev, 0x83, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL);
348 usbd_register_control_callback(
349 dev, USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
350 USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, cdcacm_control_request);
355 if (fd == 1 || fd == 2) {
356 for (
int i=0; i<len; i++) {
#define containerof(ptr, type, member)
uint64_t time64_now(void)
#define RINGBUF_VAR_INIT(bufp, buf_len)
Static initializer for a ring buffer descriptor.
#define FIBRE_VAR_INIT(fn)
Static initializer for a fibre descriptor.
int _write(int fd, char *ptr, int len)
void console_hwinit(console_t *c)
Platform dependant function that will be called during console_init().
void console_putchar(console_t *c, char d)
Asynchronously send a character to the command processor.
int ringbuf_get(ringbuf_t *rb)
Extract a byte from the ring buffer.
#define CONFIG_USB_MAX_POWER
struct usb_cdc_union_descriptor cdc_union
uint8_t usbd_control_buffer[128]
int32_t cyclecmp32(uint32_t a, uint32_t b)
Compares values that may be subject to overflow.
struct usb_cdc_acm_descriptor acm
struct usb_cdc_header_descriptor header
bool fibre_run_atomic(fibre_t *f)
#define PT_BEGIN_FIBRE(f)
Fibre aware alternative to PT_BEGIN().
struct usb_cdc_call_management_descriptor call_mgmt
bool ringbuf_put(ringbuf_t *rb, uint8_t d)
Insert a byte into the ring buffer.
void fibre_run(fibre_t *f)
bool fibre_timeout(uint32_t duetime)
struct output_task __attribute__