As discussed earlier on this list, we are building a few devices which provide two serial interfaces via a USB port. Since we last spoke, we now have a valid VID+PID pair (thank you OpenMoko!) and the interface seems to work out. Dan, you said you needed to add this device to a "no probe" list so that it didn't get queried with ATx commands. I've attached the output of lsusb -v, which hopefully provides you with enough information to exclude it. However, the cdc-acm already recognizes that it "is not a modem", so is this still necessary? Greg, I've attached a small Linux driver which recognizes and the USB-Wishbone functionality of the device. It just adds two vendor messages to signal to the FPGA that the device has been opened. Please let me know what needs to be improved before it could be considered for inclusion in the kernel proper. The hardware interface solution I opted for was: 1- user-interactive console follows the CDC-ACM standard and appears as /dev/ttyACMx without any driver needed 2- the proprietary USB-Wishbone bridge uses an interface id of 0xFF and uses a custom driver to handle the extra signalling it needs When attached, I see: usb 1-3: new high-speed USB device number 46 using ehci_hcd usb 1-3: New USB device found, idVendor=1d50, idProduct=6062 usb 1-3: New USB device strings: Mfr=1, Product=2, SerialNumber=0 usb 1-3: Product: USB-{Serial,Wishbone} adapter usb 1-3: Manufacturer: GSI Helmholtzzentrum cdc_acm 1-3:1.0: This device cannot do calls on its own. It is not a modem. cdc_acm 1-3:1.0: ttyACM0: USB ACM device usb_wb 1-3:1.2: usb_wb converter detected usb 1-3: usb_wb converter now attached to ttyUSB0
Bus 001 Device 046: ID 1d50:6062 OpenMoko, Inc. Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.00 bDeviceClass 2 Communications bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 64 idVendor 0x1d50 OpenMoko, Inc. idProduct 0x6062 bcdDevice 1.00 iManufacturer 1 GSI Helmholtzzentrum iProduct 2 USB-{Serial,Wishbone} adapter iSerial 0 bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 90 bNumInterfaces 3 bConfigurationValue 1 iConfiguration 0 bmAttributes 0xa0 (Bus Powered) Remote Wakeup MaxPower 60mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 bNumEndpoints 1 bInterfaceClass 2 Communications bInterfaceSubClass 2 Abstract (modem) bInterfaceProtocol 0 None iInterface 3 White Rabbit Console (Comm) CDC Header: bcdCDC 1.10 CDC Call Management: bmCapabilities 0x00 bDataInterface 1 CDC ACM: bmCapabilities 0x01 get/set/clear comm features CDC Union: bMasterInterface 0 bSlaveInterface 1 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes 3 Transfer Type Interrupt Synch Type None Usage Type Data wMaxPacketSize 0x0040 1x 64 bytes bInterval 2 Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 1 bAlternateSetting 0 bNumEndpoints 2 bInterfaceClass 10 CDC Data bInterfaceSubClass 0 Unused bInterfaceProtocol 0 iInterface 4 White Rabbit Console (Data) Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x88 EP 8 IN bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x04 EP 4 OUT bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 2 bAlternateSetting 0 bNumEndpoints 2 bInterfaceClass 255 Vendor Specific Class bInterfaceSubClass 255 Vendor Specific Subclass bInterfaceProtocol 255 Vendor Specific Protocol iInterface 5 USB-Wishbone Bridge Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x86 EP 6 IN bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x02 EP 2 OUT bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 Device Qualifier (for other device speed): bLength 10 bDescriptorType 6 bcdUSB 2.00 bDeviceClass 2 Communications bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 64 bNumConfigurations 1 Device Status: 0x0000 (Bus Powered)
/* * USB-WB adapter driver * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 as published by the Free Software Foundation. */ #include <linux/kernel.h> #include <linux/init.h> #include <linux/tty.h> #include <linux/module.h> #include <linux/usb.h> #include <linux/usb/serial.h> #include <linux/uaccess.h> #define GSI_VENDOR_OPENCLOSE 0xB0 static const struct usb_device_id id_table[] = { { USB_DEVICE_AND_INTERFACE_INFO(0x1D50, 0x6062, 0xFF, 0xFF, 0xFF) }, { }, }; MODULE_DEVICE_TABLE(usb, id_table); static struct usb_driver usb_wb_driver = { .name = "usb_wb", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, .no_dynamic_id = 1, }; static int usb_wb_open(struct tty_struct *tty, struct usb_serial_port *port) { struct usb_device *dev = port->serial->dev; int result; result = usb_control_msg( dev, usb_sndctrlpipe(dev, 0), /* Send to EP0OUT */ GSI_VENDOR_OPENCLOSE, USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, 1, /* wValue (2..3) = device is open */ port->serial->interface->cur_altsetting->desc.bInterfaceNumber, 0, 0, /* no data stage */ 5000); /* timeout */ if (result < 0) dev_err(&dev->dev, "Could not mark device as open (result = %d)\n", result); return usb_serial_generic_open(tty, port); } static void usb_wb_close(struct usb_serial_port *port) { struct usb_device *dev = port->serial->dev; int result; result = usb_control_msg( dev, usb_sndctrlpipe(dev, 0), /* Send to EP0OUT */ GSI_VENDOR_OPENCLOSE, USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, 0, /* wValue (2..3) = device is closed */ port->serial->interface->cur_altsetting->desc.bInterfaceNumber, 0, 0, /* no data stage */ 5000); /* timeout */ if (result < 0) dev_err(&dev->dev, "Could not mark device as closed (result = %d)\n", result); return usb_serial_generic_close(port); } static struct usb_serial_driver usb_wb_device = { .driver = { .owner = THIS_MODULE, .name = "usb_wb", }, .id_table = id_table, .usb_driver = &usb_wb_driver, .num_ports = 1, .open = &usb_wb_open, .close = &usb_wb_close, }; static int __init usb_wb_init(void) { int retval; retval = usb_serial_register(&usb_wb_device); if (retval) return retval; retval = usb_register(&usb_wb_driver); if (retval) usb_serial_deregister(&usb_wb_device); return retval; } static void __exit usb_wb_exit(void) { usb_deregister(&usb_wb_driver); usb_serial_deregister(&usb_wb_device); } MODULE_AUTHOR("Wesley W. Terpstra <w.terpstra@xxxxxx>"); MODULE_DESCRIPTION("Wishbone-USB adapter"); MODULE_LICENSE("GPL"); module_init(usb_wb_init); module_exit(usb_wb_exit);