summaryrefslogtreecommitdiff
path: root/firmware/usbstack/drivers/device/usb_serial.c
diff options
context:
space:
mode:
authorChristian Gmeiner <christian.gmeiner@gmail.com>2007-08-27 16:04:32 +0000
committerChristian Gmeiner <christian.gmeiner@gmail.com>2007-08-27 16:04:32 +0000
commit8181a0c905a591caef684a2d7487feedbec84c10 (patch)
tree3939183e8e73928d1b5dcfc97b40f33b6baa309b /firmware/usbstack/drivers/device/usb_serial.c
parent9305c86f5b8fdfd60882428f884ba29bded8da78 (diff)
Usb Stack: only setup packet handling, and not enabled by default as there is a lot to do.
* settings code is not fully ready -> changing device driver has no effect * clean ups * check copyriths * find a way to detect IN transfers * support for full and highspeed * ... git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14470 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/usbstack/drivers/device/usb_serial.c')
-rw-r--r--firmware/usbstack/drivers/device/usb_serial.c300
1 files changed, 300 insertions, 0 deletions
diff --git a/firmware/usbstack/drivers/device/usb_serial.c b/firmware/usbstack/drivers/device/usb_serial.c
new file mode 100644
index 0000000000..fe1e52f25a
--- /dev/null
+++ b/firmware/usbstack/drivers/device/usb_serial.c
@@ -0,0 +1,300 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id: $
+ *
+ * Copyright (C) 2007 by Christian Gmeiner
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "usb_serial.h"
+#include <string.h>
+
+static struct usb_dcd_controller_ops* ops;
+
+struct usb_device_driver usb_serial_driver = {
+ .name = "serial",
+ .bind = usb_serial_driver_bind,
+ .unbind = NULL,
+ .request = usb_serial_driver_request,
+ .suspend = NULL,
+ .resume = NULL,
+ .speed = usb_serial_driver_speed,
+};
+
+/*-------------------------------------------------------------------------*/
+/* usb descriptors */
+
+/* TODO: implement strings */
+#define GS_MANUFACTURER_STR_ID 0
+#define GS_PRODUCT_STR_ID 0
+#define GS_SERIAL_STR_ID 0
+#define GS_BULK_CONFIG_STR_ID 0
+#define GS_DATA_STR_ID 0
+
+#define GS_BULK_CONFIG_ID 1
+
+static struct usb_device_descriptor serial_device_desc = {
+ .bLength = USB_DT_DEVICE_SIZE,
+ .bDescriptorType = USB_DT_DEVICE,
+ .bcdUSB = 0x0200,
+ .bDeviceClass = USB_CLASS_COMM,
+ .bDeviceSubClass = 0,
+ .bDeviceProtocol = 0,
+ .idVendor = 0x0525,
+ .idProduct = 0xa4a6,
+ .iManufacturer = GS_MANUFACTURER_STR_ID,
+ .iProduct = GS_PRODUCT_STR_ID,
+ .iSerialNumber = GS_SERIAL_STR_ID,
+ .bNumConfigurations = 1,
+};
+
+static struct usb_config_descriptor serial_bulk_config_desc = {
+ .bLength = USB_DT_CONFIG_SIZE,
+ .bDescriptorType = USB_DT_CONFIG,
+
+ .bNumInterfaces = 1,
+ .bConfigurationValue = GS_BULK_CONFIG_ID,
+ .iConfiguration = GS_BULK_CONFIG_STR_ID,
+ .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+ .bMaxPower = 1,
+};
+
+static struct usb_interface_descriptor serial_bulk_interface_desc = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = USB_CLASS_CDC_DATA,
+ .bInterfaceSubClass = 0,
+ .bInterfaceProtocol = 0,
+ .iInterface = GS_DATA_STR_ID,
+};
+
+static struct usb_endpoint_descriptor serial_fullspeed_in_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 8,
+};
+
+static struct usb_endpoint_descriptor serial_fullspeed_out_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 8,
+};
+
+static struct usb_debug_descriptor serial_debug_desc = {
+ .bLength = sizeof(struct usb_debug_descriptor),
+ .bDescriptorType = USB_DT_DEBUG,
+};
+
+static struct usb_qualifier_descriptor serial_qualifier_desc = {
+ .bLength = sizeof(struct usb_qualifier_descriptor),
+ .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
+ .bcdUSB = 0x0200,
+ .bDeviceClass = USB_CLASS_COMM,
+ .bNumConfigurations = 1,
+};
+
+struct usb_descriptor_header *serial_bulk_fullspeed_function[] = {
+ (struct usb_descriptor_header *) &serial_bulk_interface_desc,
+ (struct usb_descriptor_header *) &serial_fullspeed_in_desc,
+ (struct usb_descriptor_header *) &serial_fullspeed_out_desc,
+ NULL,
+};
+
+#define BUFFER_SIZE 100
+uint8_t buf[BUFFER_SIZE];
+
+struct usb_response res;
+
+/* helper functions */
+static int config_buf(uint8_t *buf, uint8_t type, unsigned index);
+static int set_config(int config);
+
+
+struct device {
+ struct usb_ep* in;
+ struct usb_ep* out;
+ uint32_t used_config;
+};
+
+static struct device dev;
+
+/*-------------------------------------------------------------------------*/
+
+void usb_serial_driver_init(void) {
+
+ logf("usb serial: register");
+ usb_device_driver_register(&usb_serial_driver);
+}
+
+/*-------------------------------------------------------------------------*/
+
+void usb_serial_driver_bind(void* controler_ops) {
+
+ logf("usb serial: bind");
+ ops = controler_ops;
+
+ /* serach and asign endpoints */
+ usb_ep_autoconfig_reset();
+
+ dev.in = usb_ep_autoconfig(&serial_fullspeed_in_desc);
+ if (!dev.in) {
+ goto autoconf_fail;
+ }
+ dev.in->claimed = true;
+ logf("usb serial: in: %s", dev.in->name);
+
+ dev.out = usb_ep_autoconfig(&serial_fullspeed_out_desc);
+ if (!dev.out) {
+ goto autoconf_fail;
+ }
+ dev.out->claimed = true;
+ logf("usb serial: out: %s", dev.out->name);
+
+ /* update device decsriptor */
+ serial_device_desc.bMaxPacketSize0 = ops->ep0->maxpacket;
+
+ /* update qualifie descriptor */
+ serial_qualifier_desc.bMaxPacketSize0 = ops->ep0->maxpacket;
+
+ /* update debug descriptor */
+ serial_debug_desc.bDebugInEndpoint = dev.in->ep_num;
+ serial_debug_desc.bDebugOutEndpoint = dev.out->ep_num;
+
+ return;
+
+autoconf_fail:
+ logf("failed to find endpoiunts");
+}
+
+int usb_serial_driver_request(struct usb_ctrlrequest* request) {
+
+ int ret = -EOPNOTSUPP;
+ logf("usb serial: request");
+
+ res.length = 0;
+ res.buf = NULL;
+
+ switch (request->bRequestType & USB_TYPE_MASK) {
+ case USB_TYPE_STANDARD:
+
+ switch (request->bRequest) {
+ case USB_REQ_GET_DESCRIPTOR:
+
+ switch (request->wValue >> 8) {
+ case USB_DT_DEVICE:
+ logf("usb serial: sending device desc");
+ ret = MIN(sizeof(struct usb_device_descriptor), request->wLength);
+ res.buf = &serial_device_desc;
+ break;
+
+ case USB_DT_DEVICE_QUALIFIER:
+ logf("usb serial: sending qualifier dec");
+ ret = MIN(sizeof(struct usb_qualifier_descriptor), request->wLength);
+ res.buf = &serial_qualifier_desc;
+
+ case USB_DT_CONFIG:
+ logf("usb serial: sending config desc");
+
+ ret = config_buf(buf, request->wValue >> 8, request->wValue & 0xff);
+ if (ret >= 0) {
+ logf("%d, vs %d", request->wLength, ret);
+ ret = MIN(request->wLength, (uint16_t)ret);
+ }
+ res.buf = buf;
+ break;
+
+ case USB_DT_DEBUG:
+ logf("usb serial: sending debug desc");
+ ret = MIN(sizeof(struct usb_debug_descriptor), request->wLength);
+ res.buf = &serial_debug_desc;
+ break;
+ }
+ break;
+
+ case USB_REQ_SET_CONFIGURATION:
+ logf("usb serial: set configuration %d", request->wValue);
+ ret = set_config(request->wValue);
+ break;
+
+ case USB_REQ_GET_CONFIGURATION:
+ logf("usb serial: get configuration");
+ ret = 1;
+ res.buf = &dev.used_config;
+ break;
+ }
+ }
+
+ if (ret >= 0) {
+ res.length = ret;
+ ret = ops->send(NULL, &res);
+ }
+
+ return ret;
+}
+
+void usb_serial_driver_speed(enum usb_device_speed speed) {
+
+ switch (speed) {
+ case USB_SPEED_LOW:
+ case USB_SPEED_FULL:
+ logf("usb serial: using fullspeed");
+ break;
+ case USB_SPEED_HIGH:
+ logf("usb serial: using highspeed");
+ break;
+ default:
+ logf("speed: hmm");
+ break;
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+/* helper functions */
+
+static int config_buf(uint8_t *buf, uint8_t type, unsigned index) {
+
+ int len;
+
+ /* TODO check index*/
+
+ len = usb_stack_configdesc(&serial_bulk_config_desc, buf, BUFFER_SIZE, serial_bulk_fullspeed_function);
+ if (len < 0) {
+ return len;
+ }
+ ((struct usb_config_descriptor *)buf)->bDescriptorType = type;
+ return len;
+}
+
+static int set_config(int config) {
+
+ /* TODO check config*/
+
+ /* enable endpoints */
+ logf("setup %s", dev.in->name);
+ ops->enable(dev.in);
+ logf("setup %s", dev.out->name);
+ ops->enable(dev.out);
+
+ /* store config */
+ logf("using config %d", config);
+ dev.used_config = config;
+
+ return 0;
+}