Skip to content

Instantly share code, notes, and snippets.

@vdudouyt
Last active February 28, 2021 14:21
Show Gist options
  • Save vdudouyt/9352c694c86779c5a71f18b482dca395 to your computer and use it in GitHub Desktop.
Save vdudouyt/9352c694c86779c5a71f18b482dca395 to your computer and use it in GitHub Desktop.
USB bulk device example with libopencm3 & libusb-1.0
#include <libusb.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
int main()
{
libusb_init(NULL);
libusb_device_handle *handle;
assert(handle = libusb_open_device_with_vid_pid(NULL, 0x0483, 0x5740));
assert(libusb_claim_interface(handle, 0));
char request[] = "Test", response[8];
memset(response, 0, sizeof(response));
int bytes_transferred;
libusb_bulk_transfer(handle, 0x01, request, sizeof(request), &bytes_transferred, 0);
libusb_bulk_transfer(handle, 0x82, response, sizeof(response), &bytes_transferred, 0);
printf("Response=%s\n", response);
libusb_close(handle);
}
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/usb/usbd.h>
#include <stdlib.h>
static const struct usb_device_descriptor dev = {
.bLength = USB_DT_DEVICE_SIZE,
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = 0x0200,
.bDeviceClass = 0xff,
.bDeviceSubClass = 0,
.bDeviceProtocol = 0,
.bMaxPacketSize0 = 64,
.idVendor = 0x0483,
.idProduct = 0x5740,
.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 = 0x82,
.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 = 1,
.bAlternateSetting = 0,
.bNumEndpoints = 2,
.bInterfaceClass = 0xff,
.bInterfaceSubClass = 0,
.bInterfaceProtocol = 0,
.iInterface = 0,
.endpoint = data_endp,
}};
static const struct usb_interface ifaces[] = {{
.num_altsetting = 1,
.altsetting = data_iface,
}};
static const struct usb_config_descriptor config = {
.bLength = USB_DT_CONFIGURATION_SIZE,
.bDescriptorType = USB_DT_CONFIGURATION,
.wTotalLength = 0,
.bNumInterfaces = 1,
.bConfigurationValue = 1,
.iConfiguration = 0,
.bmAttributes = 0x80,
.bMaxPower = 0x32,
.interface = ifaces,
};
static void usb_setup(void)
{
/* Enable clocks for GPIO port A (for GPIO_USART2_TX) and USART2. */
rcc_usb_prescale_1();
rcc_periph_clock_enable(RCC_USB);
rcc_periph_clock_enable(RCC_GPIOA);
/* Setup GPIO pin GPIO_USART2_TX/GPIO9 on GPIO port A for transmit. */
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO11 | GPIO12);
gpio_set_af(GPIOA, GPIO_AF14, GPIO11 | GPIO12);
}
static void usbdev_data_rx_cb(usbd_device *usbd_dev, uint8_t ep)
{
(void)ep;
(void)usbd_dev;
char buf[64];
int len = usbd_ep_read_packet(usbd_dev, 0x01, buf, 64);
if (len) {
usbd_ep_write_packet(usbd_dev, 0x82, buf, len);
buf[len] = 0;
}
}
static void usbdev_set_config(usbd_device *usbd_dev, uint16_t wValue)
{
(void)wValue;
(void)usbd_dev;
usbd_ep_setup(usbd_dev, 0x01, USB_ENDPOINT_ATTR_BULK, 64, usbdev_data_rx_cb);
usbd_ep_setup(usbd_dev, 0x82, USB_ENDPOINT_ATTR_BULK, 64, NULL);
}
static const char *usb_strings[] = {
"Black Sphere Technologies",
"CDC-ACM Demo",
"DEMO",
};
uint8_t usbd_control_buffer[128];
int main(void)
{
int i;
usbd_device *usbd_dev;
rcc_clock_setup_hsi(&rcc_hsi_8mhz[RCC_CLOCK_48MHZ]);
usb_setup();
usbd_dev = usbd_init(&st_usbfs_v1_usb_driver, &dev, &config, usb_strings,
3, usbd_control_buffer, sizeof(usbd_control_buffer));
usbd_register_set_config_callback(usbd_dev, usbdev_set_config);
for (i = 0; i < 0x800000; i++)
__asm__("nop");
while (1)
usbd_poll(usbd_dev);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment