From 823ceca1345882abd7ac42bb399e45d0ac5a30f1 Mon Sep 17 00:00:00 2001 From: arighi Date: Fri, 17 Sep 2010 16:06:55 +0000 Subject: [PATCH] USB: implement generic usb-serial device driver A generic board that includes this module can be plugged to a USB host system (e.g., Linux, Windows, ...) to be seen as a generic usb-serial adapter device (e.g., /dev/ttyUSB0 in Linux). This module export the following functions to communicate between the micro and the host over the usb-serial channel: ssize_t usb_serial_read(void *buf, ssize_t size); ssize_t usb_serial_write(const void *buf, ssize_t size); git-svn-id: https://src.develer.com/svnoss/bertos/trunk@4241 38d2e660-2303-0410-9eaa-f027e97ec537 --- bertos/cfg/cfg_usb_serial.h | 57 +++++++++++ bertos/drv/usb_serial.c | 195 ++++++++++++++++++++++++++++++++++++ bertos/drv/usb_serial.h | 50 +++++++++ 3 files changed, 302 insertions(+) create mode 100644 bertos/cfg/cfg_usb_serial.h create mode 100644 bertos/drv/usb_serial.c create mode 100644 bertos/drv/usb_serial.h diff --git a/bertos/cfg/cfg_usb_serial.h b/bertos/cfg/cfg_usb_serial.h new file mode 100644 index 00000000..70740947 --- /dev/null +++ b/bertos/cfg/cfg_usb_serial.h @@ -0,0 +1,57 @@ +/** + * \file + * + * + * \author Andrea Righi + * + * \brief Configuration file for the USB serial driver module + */ + +#ifndef CFG_USB_SERIAL_H +#define CFG_USB_SERIAL_H + +/** + * Module logging level. + * + * $WIZ$ type = "enum" + * $WIZ$ value_list = "log_level" + */ +#define USB_SERIAL_LOG_LEVEL LOG_LVL_INFO + +/** + * module logging format. + * + * $WIZ$ type = "enum" + * $WIZ$ value_list = "log_format" + */ +#define USB_SERIAL_LOG_FORMAT LOG_FMT_TERSE + +#endif /* CFG_USB_H */ diff --git a/bertos/drv/usb_serial.c b/bertos/drv/usb_serial.c new file mode 100644 index 00000000..e3054bbd --- /dev/null +++ b/bertos/drv/usb_serial.c @@ -0,0 +1,195 @@ +/** + * \file + * + * + * \author Andrea Righi + * + * \brief Generic USB serial device driver. + * + */ + +#include "cfg/cfg_usb_serial.h" + +#define LOG_LEVEL USB_SERIAL_LOG_LEVEL +#define LOG_FORMAT USB_SERIAL_LOG_FORMAT + +#include +#include +#include + +#include +#include + +#include /* IRQ_DISABLE / IRQ_ENABLE */ +#include /* cpu_relax() */ + +#include + +#include /* memcpy() */ + +#include "drv/usb_serial.h" + +#define USB_SERIAL_VENDOR_ID 0x05f9 +#define USB_SERIAL_PRODUCT_ID 0xffff + +#define USB_SERIAL_INTERFACES 1 +#define USB_SERIAL_ENDPOINTS 3 + +#define USB_STRING_MANUFACTURER 1 +#define USB_STRING_PRODUCT 2 +#define USB_STRING_SERIAL 3 + +static usb_device_descriptor_t usb_serial_device_descriptor = +{ + .bLength = sizeof(usb_serial_device_descriptor), + .bDescriptorType = USB_DT_DEVICE, + .bcdUSB = 0x110, + .bDeviceClass = USB_CLASS_COMM, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, + .idVendor = USB_SERIAL_VENDOR_ID, + .idProduct = USB_SERIAL_PRODUCT_ID, + .bcdDevice = 0, + .iManufacturer = USB_STRING_MANUFACTURER, + .iProduct = USB_STRING_PRODUCT, + .iSerialNumber = USB_STRING_SERIAL, + .bNumConfigurations = 1, +}; + +static usb_config_descriptor_t usb_serial_config_descriptor = +{ + .bLength = sizeof(usb_serial_config_descriptor), + .bDescriptorType = USB_DT_CONFIG, + .bNumInterfaces = USB_SERIAL_INTERFACES, + .bConfigurationValue = 1, + .iConfiguration = 0, + .bmAttributes = USB_CONFIG_ATT_ONE, + .bMaxPower = 50, /* 100 mA */ +}; + +static usb_interface_descriptor_t usb_serial_interface_descriptor = +{ + .bLength = sizeof(usb_serial_interface_descriptor), + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = USB_SERIAL_ENDPOINTS, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .iInterface = 0, +}; + +static usb_endpoint_descriptor_t usb_serial_ep_report_descriptor = +{ + .bLength = sizeof(usb_serial_ep_report_descriptor), + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_IN | 1, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = usb_cpu_to_le16(8), + .bInterval = 1, +}; + +static usb_endpoint_descriptor_t usb_serial_ep_in_descriptor = +{ + .bLength = sizeof(usb_serial_ep_in_descriptor), + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_IN | 3, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = usb_cpu_to_le16(64), + .bInterval = 0, +}; + +static usb_endpoint_descriptor_t usb_serial_ep_out_descriptor = +{ + .bLength = sizeof(usb_serial_ep_in_descriptor), + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_OUT | 2, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = usb_cpu_to_le16(64), + .bInterval = 0, +}; + +static usb_descriptor_header_t *usb_serial_config[] = +{ + (usb_descriptor_header_t *)&usb_serial_config_descriptor, + (usb_descriptor_header_t *)&usb_serial_interface_descriptor, + (usb_descriptor_header_t *)&usb_serial_ep_report_descriptor, + (usb_descriptor_header_t *)&usb_serial_ep_in_descriptor, + (usb_descriptor_header_t *)&usb_serial_ep_out_descriptor, + NULL, +}; + +static DEFINE_USB_STRING(language_str, "\x09\x04"); // Language ID: en_US +static DEFINE_USB_STRING(manufacturer_str, + USB_STRING("B", "e", "R", "T", "O", "S")); +static DEFINE_USB_STRING(product_str, + USB_STRING("U", "S", "B", "-", "s", "e", "r", "i", "a", "l")); +static DEFINE_USB_STRING(serial_str, + USB_STRING("0", "0", "1")); + +static usb_string_descriptor_t *usb_serial_strings[] = +{ + (usb_string_descriptor_t *)&language_str, + (usb_string_descriptor_t *)&manufacturer_str, + (usb_string_descriptor_t *)&product_str, + (usb_string_descriptor_t *)&serial_str, + NULL, +}; + +static struct usb_device usb_serial = { + .device = &usb_serial_device_descriptor, + .config = usb_serial_config, + .strings = usb_serial_strings, +}; + +ssize_t usb_serial_read(void *buffer, ssize_t size) +{ + return usb_ep_read(usb_serial_ep_out_descriptor.bEndpointAddress, + buffer, size); +} + +ssize_t usb_serial_write(const void *buffer, ssize_t size) +{ + return usb_ep_write(usb_serial_ep_in_descriptor.bEndpointAddress, + buffer, size); +} + +int usb_serial_init(void) +{ +#if CONFIG_KERN + MOD_CHECK(proc); +#endif + if (usb_device_register(&usb_serial) < 0) + return -1; + LOG_INFO("usb-serial: registered new USB interface driver\n"); + return 0; +} diff --git a/bertos/drv/usb_serial.h b/bertos/drv/usb_serial.h new file mode 100644 index 00000000..d27f7a98 --- /dev/null +++ b/bertos/drv/usb_serial.h @@ -0,0 +1,50 @@ +/** + * \file + * + * + * \author Andrea Righi + * + * \brief Generic USB serial device driver. + * + * $WIZ$ module_name = "usb_serial" + * $WIZ$ module_configuration = "bertos/cfg/cfg_usb_serial.h" + * $WIZ$ module_depends = "usb" + */ + +#ifndef USB_SERIAL_H +#define USB_SERIAL_H + +ssize_t usb_serial_read(void *buf, ssize_t size); +ssize_t usb_serial_write(const void *buf, ssize_t size); + +int usb_serial_init(void); + +#endif /* USB_SERIAL_H */ -- 2.25.1