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 <[email protected]>");
MODULE_DESCRIPTION("Wishbone-USB adapter");
MODULE_LICENSE("GPL");
module_init(usb_wb_init);
module_exit(usb_wb_exit);