So, what’s next? If you have been reading this blog for a while, you may wonder if this project is (as a matter of fact, if I am) active any longer. Well, there is not an easy answer to this question. The real answer is yes and no.
The answer is “no” because, starting from the end of June, we have at home with us our second baby. This has resulted in a drastic transformation of the spacial-temporal parameters of my electronics hobbying life: there is no time for heating my soldering iron, nor can I find anywhere in sight the countless hours that I used to need to experiment with my board. Plus, there is no space on which I can lay my half-finished boards, SMD components, voltmeters, soldering paste, phone sets, etc., at least not without risking one of the kids swallowing any of the above (ok, not the voltmeter and the phone set, but the rest, yes, why not?), burning itself with the soldering iron or getting tangled with the various cables, while I am busy nursing the other one. And, of course, my lab desk has been evicted from the house, in order to make room for new beds, drawers, toys and other equipment.
Although taking care of two kids in parallel requires my wife and me to move at speeds approaching the speed of light, apparently the result is that the available space and time shrink both proportionally to one another, contrary to what Albert Einstein’s theory of relativity predicts. It seems that the mechanics of baby care somehow eluded the great physicist when he was creating this monumental work, or else I am sure he would have formulated his theory so as to cover this exception. The solution might be to add to the equations a new quantity, called “love”; this quantity would grow inversely to the product of the available space and time, so as to restore the theory’s correctness, even in extreme conditions like the ones I am describing above.
The answer about the project’s activity is “yes” as well. I haven’t dumped completely the project, since I have turned my attention to porting it to the Linux world. After all, if you check my replies to the comments on the “About” page of this blog (e.g., replies to Denver or Vincent), you will see that I think about targeting the project for Linux/Asterisk (which was my initial plan anyway). As you may have guessed, there are two challenges to this; the first one is called “Linux” and the second one “Asterisk”.
Let me first start from the “Linux” part. In order to get me somewhat prepared, I thought that a good idea would be to study the Linux kernel and device driver modules to see how they deal with USB communication. Without claiming that I have mastered even the slightest part of it, it seems that a classless (“custom”) USB device driver is not that difficult to write – at least not in principle. While the trickiest task is to handle correctly the various kernel beasties such as spinlocks, semaphores and the like, USB primitives themselves seem very clear and simple to use. Even isochronous communication is very much like in (the Windows flavor of) libusb: one simply has to initialize a transfer by specifying the packet size, and then one needs to queue one or more buffers, while the kernel core handles the packetization and actual I/O. Checking for the completion of a transfer is done asynchronously; one needs to do that, in order to queue up additional buffers.
As a quick grep reveals, some devices (e.g. USB cameras) use extensively isochronous USB I/O. In principle, I could learn by studying the respective device drivers and produce a driver for Open USB FXS.
Asterisk, on the other hand, is another story. In order to create a device that Asterisk can understand, one needs to write code for a “channel”. I am still studying Asterisk and DAHDI (the Asterisk ex-Zaptel device drivers), in order to see how to proceed with this task. Whereas writing a Linux driver does not seem too hard, the “channel” code looks a bit tangled to me. I am sure that I will eventually understand better its insides after some studying — whenever I manage to do that studying, of course…
One additional piece of work that needs to be done is to update the board’s firmware in order to fit some status reporting along with the isochronous PCM data. My reply to Vincent’s comment on the “About” page explains this somewhat.
So, this is where I stand for the time being. My progress is awfully slow, so I must apologize to any readers who expect a quick something, such as a project “code release”. On the other hand, since I am not burried in the loneliness of soldering components, but instead I am trying to write Linux code, and since the project’s code is posted in public, anyone (e.g., kernel driver code developers, etc.) interested in contributing to the project is warmly welcome to contact me and provide help. Feel free — this is an Open project anyway!
Update Nov 9 2009: after studying a bit David’s chan_mp code (see his comment below) and some Linux USB device drivers (particularly some ones with isochronous transfers), I think I ‘ve got a grasp of the whole thing. First of all, writing a device driver is not strictly necessary. I could rely on usbdevfs to access the device (I verified that a Linux systems sees the board and all its USB endpoints as usbdevfs descriptors), and write all code in userland using libusb (plus some trickery for ISO transfers that the plain libusb does not support yet). Although feasible, this is somewhat too tricky and would result in ugly code. It seems that the best separation between driver and userspace functionality would be to orchestrate the isochronous transfer code in the device driver and the higher-level handling in userspace. Doing that has a great advantage: the kernel can invoke a callback function in the device driver code every time an isochronous transfer is completed, and that callback can do several things, like freeing buffer space, queueing additional data, etc. — quite different from the polling model I ‘ve been using in my strictly-userspace code. Moreover, I can hide tons of low-level functionality in the device driver code (like, initialize the ProSLIC, etc.) and provide a high-level IOCTL interface to the userland. Not bad. At least, in principle, before drowning myself in all the kernel oopses and crashes I am likely going to trigger in my device driver code.
And one more piece of news: Open USB FXS now has its own USB VID/PID pair. I have not bought a VID (it’s very expensive), however, Microchip have a VID/PID sublicensing program, to which I applied and they responded immediately with the magic numbers 0X04D8 and 0XFCF1. Thanks, Microchip! The code is not adapted yet, however, in (the extremely unlikely) case that someone out there is experimenting with my board and my code, they should from now on avoid abusing the company’s own demo card VID/PID and use the above id numbers instead.
Update Nov 15 2009: currently reading “Linux Device Drivers“, 3rd ed. by J. Corbet, A. Rubini and G. Kroah-Hartman. Thank you, dear authors, for putting this excellent book online; it’s a valuable resource! My goal is to progress through the various book chapters while writing at the same time some basic building blocks of my openusbfxs Linux device driver. Let’s see how fast (and how correctly) I can accomplish that [it turns out that I had better read the entire book before putting down a single line of code]. While reading the book, some interesting questions arise. Here is one: is it better to write a complicated device driver, where I will hide all the internals of isochronous I/O, or is it better to provide a dumb driver which will just implement device files and basic SLIC interworking (like register peek/write)? I guess that reading throughout the rest of the chapters will provide me with some hints as to that. Let’s see…