libopencm3-examples icon indicating copy to clipboard operation
libopencm3-examples copied to clipboard

Composite USB device example

Open PocketPi opened this issue 2 years ago • 7 comments

Hey

I am trying to make a composite usb device consisting of cdcacm and msc profiles.

I am using a STM32F411CEU

I have tried to merge the cdcacm and msc example but when i connect my device to the pc i get the following error:

Mar 07 13:47:02 thickpad kernel: usb 3-6.1.4: new full-speed USB device number 36 using xhci_hcd
Mar 07 13:47:02 thickpad kernel: usb 3-6.1.4: New USB device found, idVendor=aabb, idProduct=ccdd, bcdDevice= 2.00
Mar 07 13:47:02 thickpad kernel: usb 3-6.1.4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
Mar 07 13:47:02 thickpad kernel: usb 3-6.1.4: Product: wqer
Mar 07 13:47:02 thickpad kernel: usb 3-6.1.4: Manufacturer: asdf
Mar 07 13:47:02 thickpad kernel: usb 3-6.1.4: SerialNumber: 62908886
Mar 07 13:47:02 thickpad kernel: usb-storage 3-6.1.4:1.1: USB Mass Storage device detected
Mar 07 13:47:02 thickpad kernel: scsi host0: usb-storage 3-6.1.4:1.1
Mar 07 13:47:34 thickpad kernel: usb 3-6.1.4: reset full-speed USB device number 36 using xhci_hcd
Mar 07 13:47:49 thickpad kernel: usb 3-6.1.4: device descriptor read/64, error -110
Mar 07 13:48:05 thickpad kernel: usb 3-6.1.4: device descriptor read/64, error -110
Mar 07 13:48:05 thickpad kernel: usb 3-6.1.4: reset full-speed USB device number 36 using xhci_hcd

This is most of the code i am running:

#include "usb.h"
#include "buffered_printf.h"
#include "ramdisk.h"
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/usb/cdc.h>
// clang-format off
#include <libopencm3/usb/usbd.h>
#include <libopencm3/usb/msc.h>
// clang-format on
#include <stddef.h>

#define DEVICE_ID_ADDR 0x1FFF7A10

static char serialno[9] = {0};

static usbd_device *usb_device;

static const struct usb_device_descriptor dev_descr = {
    .bLength = USB_DT_DEVICE_SIZE,
    .bDescriptorType = USB_DT_DEVICE,
    .bcdUSB = 0x0200,
    .bDeviceClass = 0,
    .bDeviceSubClass = 0,
    .bDeviceProtocol = 0,
    .bMaxPacketSize0 = 64,
    .idVendor = 0xaabb,
    .idProduct = 0xccdd,
    .bcdDevice = 0x0200,
    .iManufacturer = 1,
    .iProduct = 2,
    .iSerialNumber = 3,
    .bNumConfigurations = 1,
};

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 = 0x81,
                                                               .bmAttributes = USB_ENDPOINT_ATTR_BULK,
                                                               .wMaxPacketSize = 64,
                                                               .bInterval = 1,
                                                           }};

static const struct usb_endpoint_descriptor msc_endp[] = {{
                                                              .bLength = USB_DT_ENDPOINT_SIZE,
                                                              .bDescriptorType = USB_DT_ENDPOINT,
                                                              .bEndpointAddress = 0x03,
                                                              .bmAttributes = USB_ENDPOINT_ATTR_BULK,
                                                              .wMaxPacketSize = 64,
                                                              .bInterval = 1,
                                                          },
                                                          {
                                                              .bLength = USB_DT_ENDPOINT_SIZE,
                                                              .bDescriptorType = USB_DT_ENDPOINT,
                                                              .bEndpointAddress = 0x83,
                                                              .bmAttributes = USB_ENDPOINT_ATTR_BULK,
                                                              .wMaxPacketSize = 64,
                                                              .bInterval = 1,
                                                          }};

static const struct usb_interface_descriptor data_iface[] = {{
    .bLength = USB_DT_INTERFACE_SIZE,
    .bDescriptorType = USB_DT_INTERFACE,
    .bInterfaceNumber = 0,
    .bAlternateSetting = 0,
    .bNumEndpoints = 2,
    .bInterfaceClass = USB_CLASS_DATA,
    .bInterfaceSubClass = 0,
    .bInterfaceProtocol = 0,
    .iInterface = 0,

    .endpoint = data_endp,
}};

static const struct usb_interface_descriptor msc_iface[] = {{
    .bLength = USB_DT_INTERFACE_SIZE,
    .bDescriptorType = USB_DT_INTERFACE,
    .bInterfaceNumber = 1,
    .bAlternateSetting = 0,
    .bNumEndpoints = 2,
    .bInterfaceClass = USB_CLASS_MSC,
    .bInterfaceSubClass = USB_MSC_SUBCLASS_SCSI,
    .bInterfaceProtocol = USB_MSC_PROTOCOL_BBB,
    .iInterface = 0,

    .endpoint = msc_endp,
}};

static const struct usb_interface ifaces[] = {{
                                                  .num_altsetting = 1,
                                                  .altsetting = data_iface,
                                              },
                                              {
                                                  .num_altsetting = 1,
                                                  .altsetting = msc_iface,
                                              }};

static const struct usb_config_descriptor config_descr = {
    .bLength = USB_DT_CONFIGURATION_SIZE,
    .bDescriptorType = USB_DT_CONFIGURATION,
    .wTotalLength = 0,
    .bNumInterfaces = 2,
    .bConfigurationValue = 1,
    .iConfiguration = 0,
    .bmAttributes = 0x80,
    .bMaxPower = 0x32,

    .interface = ifaces,
};

static const char *usb_strings[] = {
    "asdf",
    "wqer",
    serialno,
};

/* Buffer to be used for control requests. */
uint8_t usbd_control_buffer[128];

static void cdcacm_sof_callback(void) {
    char buf[64];
    uint16_t i = 0;
    while (!usb_fifo_is_empty() && i < 64) {
        usb_fifo_get(&buf[i++]);
    }

    if (i && usb_device) {
        while (usbd_ep_write_packet(usb_device, 0x82, buf, i) == 0) {
        };
    }
}

static void cdcacm_data_rx_cb(usbd_device *usbd_dev, uint8_t ep) {
    (void)ep;

    char buf[64];
    uint16_t len = usbd_ep_read_packet(usbd_dev, 0x01, buf, 64);
}

static void cdcacm_set_config(usbd_device *usbd_dev, uint16_t wValue) {
    (void)wValue;

    usbd_ep_setup(usbd_dev, 0x01, USB_ENDPOINT_ATTR_BULK, 64, cdcacm_data_rx_cb);
    usbd_ep_setup(usbd_dev, 0x81, USB_ENDPOINT_ATTR_BULK, 64, NULL);

    usbd_register_sof_callback(usbd_dev, cdcacm_sof_callback);
}

static void serialno_read(char *buf) {
    volatile uint32_t *DEVICE_ID = (volatile uint32_t *)DEVICE_ID_ADDR;
    const uint32_t uid = *DEVICE_ID + *(DEVICE_ID + 1) + *(DEVICE_ID + 2);

    /* Fetch serial number from chip's unique ID. */
    for (int i = 0; i < 8; i++)
        buf[7 - i] = ((uid >> (4 * i)) & 0xF) + '0';

    for (int i = 0; i < 8; i++)
        if (buf[i] > '9')
            buf[i] += 'A' - '9' - 1;
    buf[8] = 0;
}

void usb_setup(void) {
    serialno_read(serialno);

    usb_device = usbd_init(
        &otgfs_usb_driver, &dev_descr, &config_descr, usb_strings, 3, usbd_control_buffer, sizeof(usbd_control_buffer));

    usbd_register_set_config_callback(usb_device, cdcacm_set_config);

    ramdisk_init();
    usb_msc_init(
        usb_device, 0x83, 64, 0x03, 64, "VendorID", "ProductID", "0.00", ramdisk_blocks(), ramdisk_read, ramdisk_write);

    /* NVIC setup. */
    nvic_enable_irq(NVIC_OTG_FS_IRQ);
    nvic_set_priority(NVIC_OTG_FS_IRQ, 1);
}

void otg_fs_isr(void) {
    if (usb_device) {
        usbd_poll(usb_device);
    }
}

Can you guys help me find out how to progress either with concrete changes to the code or how to debug the problem.

PocketPi avatar Mar 07 '23 12:03 PocketPi