OpenSolaris and USB Communication Device Class - Abstract Control Model
By psum on Oct 19, 2005
What is now
OpenSolaris currently doesn't support any USB device of Communication Device Class (CDC). In this article I want to explain what CDC is, how it is supported in other systems and how you can use some of those devices in OpenSolaris even without native driver.
Communication Device Class (CDC) is used for USB devices such as analog Modems, ISDN modems, telephone sets, Ethernet controls, ATM controls, etc. For particular types of device, CDC defines separates subclasses. One of probably mostly used subclasses is an Abstract Control Model (ACM). USB CDC-ACM device can be described as device which understands standard V.25ter (AT) commands. Since I am interested only in CDC-ACM devices (understand I have one of those), I will focus on this subclass only.
As I already stated OpenSolaris doesn't contain CDC native support at all. What about the other open systems? They do support it. Linux has got its cdc-acm driver and BSD clones (FreeBSD, OpenBSD, NetBSD) have their umodem (umodem(4)).
So, what we can do under OpenSolaris? We can try to write our own native CDC-ACM driver (the best start would be to use USB skeleton driver), use UGEN driver or potentially libusb(3LIB).
I will try to explain my particular experience with using of UGEN driver (man ugen(7D)). UGEN stands for USB generic driver and it was ported from NetBSD (NetBSD man page for ugen(4)).
Using USB CDC-ACM device under OpenSolaris to connect to internet via PPP
This procedure was tested with USB CDMA modem GPC-6420, which is used in Czech Republic by one of internet providers. Detailed description how to connect to internet from Solaris operating system with this device can be found on Vitezslav Batrla's blog (in Czech).
- Bind UGEN driver to CDC-ACM device
prtconf -vD, to get alias name for this command).
Example (note that examples here are specific to GPC-6420 modem):
add_drv -i '"usb5c6,3196.0"' -m '\* 0666 root sys' ugen
After UGEN is successfully bound and device is connected to USB port, there is created new directory structure under /dev/usb.
cntrl0 devstat if0in1stat if1in10stat if1out11stat
cntrl0stat if0in1 if1in10 if1out11
This structure describes connected USB device and can be used for communication with the device. Communication can be done be using standard I/O operations such as open, read, write, ...
- Typical USB CDC-ACM device has the following structure
Control endpoint (every USB device has it) can be used in case of CDC-ACM for setting or inquiring of modem parameters (bit rate, data bits, ...). Corresponding UGEN files are cntrl0 (read/write) and cntrl0stat (used to read error code, when I/O operation on this endpoint fails).
- endpoint: notification from device (events such connected/disconnected), corresponding UGEN files: if0in1 (interrupt mode) and if0in1stat (used to read error code, when I/O operation on this endpoint fails).
- endpoint: data in (data from device, including response to AT commands), corresponding UGEN files: if1in10 (bulk mode) and if1in10stat (used to read error code, when I/O operation on this endpoint fails)
- endpoint: data out (data to device, including AT commands), corresponding UGEN files: if1out11 (bulk mode) and if1out11stat (used to read error code, when I/O operation on this endpoint fails)
Note: device status can be read from UGEN file: devstat
- Dealing with UGEN timeouts
For our purposes we will use only if1in10 and if1out11. But before we can use it, we must change default timeout of 10 seconds. Otherwise we will receive EIO error, after reading from bulk endpoint (when there are no data available).
This can be done in Solaris 10 by adding the following line in /etc/system
set ugen:ugen_bulk_timeout = 3600
And the line for newer versions of Solaris operating system (Nevada) is:
set usba:ugen_bulk_timeout = 3600
Note: There is known issue (6333195), which makes x86/32 kernel to ignore this setting. One of possible workarounds is to ping to some IP address. Monitor Vita's blog for others.
- Configure PPP connection for your internet provider
The important point here is, that you should use
notty. This options will allow us to use as data channel redirected standard input/output from/to pppd instead of using real terminal device.
Connection to internet can be done then for example in this way:
cat /dev/usb/5c6.3196/0/if1in10 | pppd call [your_isp] > /dev/usb/5c6.3196/0/if1out11
Does OpenSolaris need native CDC-ACM driver?
My guess is that it would be better. Well, the solution I tried to present here is perfectly working and there doesn't seem to be any speed degradation. The main problem is that there are many existing applications (tip(1) is one of them :-) which expect real terminal device. It means they expect one device file to which they can write, read from and use standard terminal ioctls on it.