Archive for April, 2010

Astral wars

April 29, 2010

Tell me the truth: did you really think I was going to sit idle, drinking beer and celebrating my first Asterisk call? Naaahhh, I didn’t think so myself… That first Asterisk call made me so restless that it was impossible to abstain from hacking on the project. So there is lots of news.

Before all else, please let me spend a few words on the title of this post. “Astral weeks” has been the title of an album from Van Morison, which I used to like a lot (that was in the previous century, though). And I guess that everyone knows what “Star wars” refers to. I wanted to use “star wars” as a title to refer to my first combats with the star-named PBX, but I found “astral” much more poetic (yes, the old 60’s and 70’s rock-n-roll songs seem to be a recurring motto in this blog). Why “wars”? Well, I was to fight with the Beast, and although bloodshed was less severe than I expected, every war has its casualties (in this case, just a board, read on for the details). The news from the front are both good and bad. Although I prefer to listen to the bad news first, when it comes to battlefront news, I think it is best to report them in their chronological order. Here they are, then:

Item #1 (good news): As I reported in my previous post, I was able to place an Asterisk call over VMWare using my board. The audio quality was lousy, but I guessed (correctly, as it will follow) that VMWare was the culprit for that. Then I wrote the previous post.

Item #2 (good news): I assembled a dongle board using my version-2 design. The actual assembly was finished before the Asterisk test, but I had not had the time to test the new dongle before my previous post. So, the good news is that the dongle worked fine (at first, as it will follow). The heat problems seem to have vanished and I was able to run all the tests (like ringing the phone, inputting and outputting ulaw samples, dtmf, etc.) without any issues.

Item #3 (good news): I tried installing my new driver and running Asterisk over it on a native Linux installation (Ubuntu/wubi). The sound quality was really good, and there were no clicks or other signs of USB packet loss. Great!

Item #4 (bad news): DTMF works intermittently. At times Asterisk understands the dialed digits, at other times it does not. As David Rowe pointed out to me in a private email of his, this might be due either to distorted/clipped IN audio, or to the lack of an echo canceller (I have not added an echo canceller yet). I think that the most plausible explanation is the second one, because at the absence of an echo cancellation process, the OUT signal may garble the IN tone so that it becomes unrecognizable.

Item #5 (particularly worrysome): The symptom of DTMF not being recognized is board-dependent. My older, large-form board worked fine, however the (hot, version-1) dongle board proved to be problematic. As to my (corrected, version-2) board…

Item #6 (bad news, but not so bad after all): … the second board decided to succumb to its wounds during the Asterisk tests. While initially working (with intermittent and problematic DTMF recognition, but otherwise working), the board suddenly started to refuse to power up the DC-DC converter, the phone did not ring, etc. It now steadily refuses to power up the converter during the first go, it then succeeds on a later try, but VBAT drops very low (-9V) as soon as the linefeed is set to “forward active”. This looks like the converter cannot supply enough current to the circuit or there is a power leak somewhere. News is not so bad after all, since the board has worked for a while, however it makes me worry about design issues. I ‘ll have to either hardware-debug the board, or assemble a new one (I tend to choose the second alternative).

Item #7 (good news): I was able to place a call through an IAX connection to Digium’s server (500 from the main pre-installed demo IVR menu), and the call went perfectly OK (apart from an expected audio quality degradation due to a flaky Internet connection at the place where I work, I was able to hear to the full voice message from Digium’s server).

Item #8 (bad news): My driver is still missing a hook state debouncing algorithm, so funny things happen from time to time, with the funniest one being that Asterisk occasionally interprets back-on-hook as a “flash” event (momentary off-/on-/off-hook transition). Funniest thing, this happened during the IAX call to Digium, which I managed to place into a three-way conferencing state. Yes, Open USB FXS can do three-way conferencing (like any other dahdi hardware)!

Item #9 (good news?): I have placed all the newest driver code, Eagle files, etc. on the project’s Google code site. If you wish to compile the new module, you have to place it into a directory named /usr/src/dahdi-2.2.XXX/drivers/dahdi/oufxs/ and either issue “make” within that directory, or add “oufxs/” (without any other path component) to EXTRADIRS and issue a “make” from the top Dahdi directory (/usr/src/dahdi-2.2.XXX). The plain “make” inside the oufxs directory failed on my Ubuntu tests. In Ubuntu, you need to modify the “dkms.conf” file provided with the dahdi source. I have not yet uploaded a modified dkms.conf, but I will. A word of warning: if you plan to produce your own PCB from the newest (v-2) dongle Eagle files, please take into account that (a) the only such prototype I ‘ve made has failed and (b) the LED and RLED should be swapped to place the LED under the RJ-11 plug. Also, an updated BOM is now in place. Please consider all the upload code and other files as drafts and don’t shoot me if they don’t compile on your system.

Item #9 (good news): After all, if I manage to assemble some working dongle-v2 prototypes and get the DTMF working with them, I think I am going to produce a limited number of dongles (ready-made or DIY kits) at nominal price for interested people to get. I am getting myself organized and will post details soon.

All the above sound like Open USB FXS is slowly conquering the star-land. It may be just ambition, it may be the reality. The next days will show and a soon-to-be post is due as soon as something significant occurs. The next steps are to assemble a couple of dongle-v2 prototypes, to get hook debouncing and to do something with the echo cancellation, then re-test. Expect to have news, sooner or later, and let’s hope it’s going to be exclusively good news this time!

Update, May 2: I am currently looking at the changes I need to make to involve (correctly) an echo canceller. I think that the best way is to work along the following lines. In order to keep a consistent time difference between OUT and IN samples, I need to keep track of the number of samples sent and received. To this, it is vastly more convenient to have the same number of samples (or “packets” in oufxs.c terminology) per URB. Currently, the driver allows module parameters for setting these two independently. This was a great tool for debugging and tuning, but I think the two distinct parameters are not really needed anymore. So, I will merge the two distinct set of module parameters and associated variables into one. After that, I will just need to keep track of an offset between URBs that are sent OUT and the respective IN ones. Normally, this offset should be constant, however the board may delay the receipt of an OUT USB frame, so I need to look carefully at this, using the mirrored sequence numbers to resynchronize in the case of delayed or lost USB frames (note, this was a real issue before I hacked the clock of the ISR to be consistent with the USB SOF frame rate, but normally it should not happen anymore — need to check though). After getting this inter-URB offset, I think that just invoking the echo canceller will be trivial. Basically this is it; however, the devil always lies in the details, so I will report more as I ‘ll be going through my plan. Let’s see.

Update, May 3: In the meantime, I have assembled another two V2 dongle boards. The results — at least for those who see the glass half-full —  are not discouraging: one of the two new boards worked right away, showing no excessive heat issues. The other board failed in an early test stage (problems in communication between the PIC and the 3210, which usually translates into a problem in the PCM bus and especially the FSYNC signal, which in turn means a badly soldered 3210 pin or a totally damaged chip). Both boards might be fixable, but this means time-consuming labwork to diagnose the problem and perform surgery to the failed board. That is, things that I could not possibly do in a production line.

Let me summarize: out of three V2 dongles, one died while on duty (DC-DC converter issue), one worked perfectly well (so far…) and another was found dead in early testing. I don’t know if all this sounds satisfactory to you, however, if I were to read this blog, I would tend to say that the hardware is problematic. I don’t know if this is due to hand-soldering, so that I can expect better rates when I get to mass-produce boards. The experience of readers w.r.t. similar projects would help me there. You see, I am reluctant to go and order a quantity of assembled boards from some assembly factory if rate of dead boards is expected to be 50% or even more… If, on the other hand, hand-soldering delicate SMD materials is known to cause a high rate of damaged boards compared to what one can expect from an industrial grade assembly facility, then I am probably OK to go on (OK, after trying and possibly incorporating the patch proposed by Gabor). Moreover, this means that a DIY kit will have high chances of resulting into a brick circuit, a situation that will eventually kick back to me for providing the DIY option to the blog readers, even at a not-for-profit price. What do you, blog readers, think about this?

On a different course now: I am progressing with the driver. I have implemented hook debouncing and am going to test it soon. And, I have put some more thought into the echo cancellation issue. Fortunately enough, I already have sequence numbers in my USB packet headers. I can use these to deduce the actual OUT sample that is being acknowledged by each IN sample, so that I can match the two when calling the echo canceller. In addtion, I think I can fix this mapping between sequence numbers and samples to be static, so I won’t need to update it (thus, I will need no complex structures and locking).

I will report more on this a bit later; for the time, what I would appreciate very much would be to receive some comments on the dead boards issue, in particular from people who have experience in similar projects.

Hello, Asterisk!

April 25, 2010

Yes, you guessed right: this post is about Open USB FXS interworking with Asterisk. And it does work indeed! After a setup of half an hour, I was able to get Asterisk to recognize the board (the respective Dahdi channel, to be exact), to dial from a phone set attached to the board and to listen some Asterisk voice prompts. Not bad at all, is it?

The environment on which I tested was a Debian lenny system, with some packages installed from sid (the latest unstable Debian version). The main such packages were Asterisk v1.6 and Dahdi v2.2. All related .deb packages were built from the respective source packages. I don’t know if other Asterisk versions work with the dahdi drivers. Maybe not, and the driver needs porting to zaptel as well (if so, it’s not a problem anyway, porting should be trivial).

Of course, there is a list of several serious caveats. To begin with, the voice quality on VMWare is horrible. Probably this is due to the insufficient CPU and I/O resources that the VMWare environment can offer to Asterisk and the driver, which require both real-time priority to work. I haven’t yet tried to run the whole thing under a native Linux. I trust things will be better there, but I promise to report any uncurable issues that I will run into.

The second serious caveat is the plug-and-play nature of a USB device as opposed to the relatively fixed nature of Asterisk and its configuration. When I configured my device under the [phones] section of /etc/asterisk/chan_dahdi.conf (the location may vary in your system) and started Asterisk without the dongle board being plugged in yet, Asterisk managed to get itself a majestic SIGSEGV (or was it SIGABORT? I forget). It does not make sense for the channel driver to insist in working if a configured device does not even have an associated device file on the system (this is exactly the case here). So this segmentation fault is probably a bug, which needs further investigation.

Another issue is that, depending on the order in which more than one Open USB FXS devices are plugged in the system, they may be assigned different channel numbers each time. This will in turn mean that, depending on the order in which a phone is plugged in the system, it may get a different extension number (this is for sure a great feature, don’t you agree? Imagine yourself being a VoiP provider and mixing up customers’ extension numbers each time a device is plugged or removed from the system; wow!…).

An additional yet unresolved caveat is the echo canceller. I have not yet built one into the oufxs driver; that’s not an issue in itself, but it turns out that it is not very easy to write the actual code, because the IN and OUT completion callbacks are asynchronous. So, the event sequence IN(n), OUT(n), OUT(n+1), IN(n+1) is perfectly valid. OK, but now if you think about how to submit the samples of such a sequence to the echo canceller, you ‘ll see that it gets to be a bit tricky.

Believe me or not, none of the above sounds anymore like a real problem to me. The next few days will show, however my project’s biggest goal from its first conception has now been achieved. I am really moved and excited about it, though my writing style probably does not reveal too many emotions. I believe I ‘ll offer myself a few days off the project now (plus the necessary quantity of beer to celebrate it). I am also thinking about writing a dedications page, where I will make sure not to forget that person who, one year from now or so, mailed me asking my phone number, and then called me in order to try to convince me that it was not going to work — “you are not going to get yourself anywhere with the PIC”, was his final argument.

Land, Ho!

April 16, 2010

No, I am not going to repeat the lyrics of the famous Doors’ song here. It’s just that I have decided to start a new post for reporting my progress and open issues in porting my driver to dahdi. To begin by a short summary, dahdi porting is going very well, modulo some problems that I think I will be able to resolve sooner or later. All this makes me feel like when approaching land after a long sea journey, hence the title of this post.

Here are the details (nasty as usual).

My new module, called oufxs.ko, loads successfully and registers with dahdi-base without any problems.  I have now fixed the “location” of the card, so dahdi_cfg when the card is first plugged into a USB port reports e.g.:

description=Open USB FXS board 1: setup not started
manufacturer=Angelos Varvitsiotis
devicetype=Open USB FXS
location=USB 2-1 device #6

OK, you noticed the “USB 2-1 device #6” above; did you also notice the “description” message with the “setup not started” note? This is thanks to the board initialization worker thread, that changes the description string as it goes along with initialization, so successive calls to dahdi_scan report the following, in the order listed here, with changes from one step to the next taking approx. half to one second, depending on the initialization step:

description=Open USB FXS board 1: setup not started
description=Open USB FXS board 1: SLIC sanity check
description=Open USB FXS board 1: initial powerdown
description=Open USB FXS board 1: set indirect regs
description=Open USB FXS board 1: set dc-dc convrtr
description=Open USB FXS board 1: dc-dc cnv powerup
description=Open USB FXS board 1: VBAT pwrleak test
description=Open USB FXS board 1: ADC calibration
description=Open USB FXS board 1: Q5/6 calibration
description=Open USB FXS board 1: LBAL calibration
description=Open USB FXS board 1: final step setup
description=Open USB FXS board 1: up-and-running

BTW, dahdi_tool also reports correctly the board and displays the description, refreshing it whenever the current board status changes. The “alarms=UNCONFIGURED” line is the next thing to worry about. The dahdi_cfg utility needs to be executed to configure signaling before the board can be used by dahdi. After some guesswork, I think that the only configuration really required in /etc/dahdi/system.conf is a line containing “fxols=N”, where N is the the dahdi channel for the board (1, if no other dahdi hardware exists on the system). After that, dahdi_scan reports:

description=Open USB FXS board 1: up-and-running
manufacturer=Angelos Varvitsiotis
devicetype=Open USB FXS
location=USB 2-1 device #7

At this stage, “fxstest” can be used to play with the board. For example, “fxstest /dev/dahdi/1 stats” proudly reports:

TIP: -3.3840 Volts
RING: -27.8240 Volts
VBAT: -36.8480 Volts

(yes, this is the low-power mode that Edwin suggested in his comment to my previous post), while “fxstest /dev/dahdi/1 regdump” outputs the following, very enlightening dump:

Direct registers:
  0. 05    1. 28    2. 01    3. 00    4. 01    5. 00    6. 00    7. 00 
  8. 00    9. 00   10. 08   11. 33   12. 00   13. 00   14. 00   15. 00 
 16. 00   17. 00   18. 00   19. 00   20. 00   21. 00   22. ff   23. 01 
 24. 00   25. 00   26. 00   27. 00   28. 00   29. 00   30. 00   31. 00 
 32. 00   33. 00   34. 00   35. 00   36. 00   37. 00   38. 00   39. 00 
 40. 00   41. 00   42. 00   43. 00   44. 00   45. 00   46. 00   47. 00 
 48. 00   49. 00   50. 00   51. 00   52. 00   53. 00   54. 00   55. 00 
 56. 00   57. 00   58. 00   59. 00   60. 00   61. 00   62. 00   63. 54 
 64. 11   65. 61   66. 01   67. 1f   68. 04   69. 0a   70. 0a   71. 00 
 72. 10   73. 02   74. 2c   75. 28   76. 00   77. 00   78. 10   79. 42 
 80. 09   81. 49   82. 62   83. 62   84. 01   85. 16   86. 00   87. 00 
 88. 00   89. 00   90. 00   91. 00   92. ca   93. 0c   94. 65   95. 00 
 96. 00   97. 00   98. 0b   99. 12  100. 0f  101. 0f  102. 05  103. 46 
104. 05  105. 27  106. 02  107. 08  108. eb 

Indirect registers:
  0. 55c2    1. 51e6    2. 4b85    3. 4937    4. 3333    5. 0202 
  6. 0202    7. 0198    8. 0198    9. 0611   10. 0202   11. 00e5 
 12. 0a1c   13. 7b30   14. 0063   15. 0000   16. 7870   17. 007d 
 18. 0000   19. 0000   20. 7ef0   21. 0108   22. 0000   23. 2000 
 24. 2000   25. 0000   26. 2000   27. 4000   28. 1000   29. 3600 
 30. 1000   31. 0200   32. 0ff0   33. 7f80   34. 0ff0   35. 8000 
 36. 0320   37. 0010   38. 0010   39. 0010   40. 0000   41. 0c00 
 42. b4f9   43. 1000   44. 0000   45. 0000   46. 0000   47. 0000 
 48. 0000   49. 0000   50. 0000   51. 0000   52. 0000   53. 0000 
 54. 0000   55. 0000   56. 0000   57. 0000   58. 0000   59. 0000 
 60. 0000   61. 0000   62. 0000   63. 0000   64. 0000   65. 0000 
 66. 0000   67. 0000   68. 0000   69. 0000   70. 0000   71. 0000 
 72. 0000   73. 0000   74. 0000   75. 0000   76. 0000   77. 0000 
 78. 0000   79. 0000   80. 0000   81. 0000   82. 0000   83. 0000 
 84. 0000   85. 0000   86. 0000   87. 0000   88. 0000   89. 0000 
 90. 0000   91. 0000   92. 0000   93. 0000   94. 0000   95. 0000 
 96. 0000   97. 0000   98. 0000   99. 4bfe  100. b6c4  101. 9ea5 
102. 99ef  103. bffe  104. c699

Notice in the above dunp that unimplemented or reserved 3210 registers are not probed for their contents, and their contents are printed as zeros.

How about actual audio? So far I have implemented only the OUT part (if you ask why not also the IN part, I was too lazy — or precautious, if you prefer — to start writing the IN leg of the code without having yet tested thouroughly the OUT one). The OUT part appears to be working OK: using “fxstest /dev/dahdi/1 tones” as a test, I hear various beeping tones, including “dial tone”, “ring tone”, “busy tone”, etc., in succession. A few audible clicks from time to time can, according to my former experience, be attributed to VMWare’s sploppiness, so no worries here, although I owe to test more thoroughly under native (non-virtualized) linux. Provided that everything goes OK with the OUT part, I trust that the IN part will not be that hard to write as well. Summary: dahdi does fine with sending audio to my board by means of the new driver, and receiving audio does not look like an issue at all.

So far, so good. Now come the bad news: “fxstest /dev/dahdi/1 ring” (or “fxstest /dev/dahdi/1 polarity, which also sets the phone set ringing for a very short while) cause a complete system hang :-(. So far, I have not been able to find a good explanation for that. The nature of the hang is similar to what I have seen when trying to lock a spinlock twice, and by means of various debugging attempts (e.g., by not loading a tonezone in /etc/dahdi/system.conf and expecting the code circa line 5323 of dahdi-base.c to return -ENODATA since no zone is loaded, but contrarily to what is expected, getting another system hang), it could be related to the locking of chan->lock in line 5324 (my version is from debian source package dahdi-linux- Why would this lock hang the system is a little mystery to me, but I trust I ‘ll be able to debug the situation further, if not otherwise, by means of extensive printk statements in the dahdi code.

There is also another caveat that I need to resolve. Wctdm.c, whose logic I am mimicking in my new driver, reads or sets various board and ProSLIC (3210/3215 in Digium boards) registers in interrupt context. As an example, while servicing a PCI interrupt from the board, if the data received indicates a 3210 hook change alarm, the hook-state ProSLIC register 68 is checked in-band. OK, this is fine if you work with a PCI board, where setting a 3210 register only involves a few inb/outb instructions, however it’s a disaster with USB, where one needs at least one bulk OUT packet (and its confirmation, hence a 2-ms separate I/O sequence) in order to communicate with the board. So, I guess that I need to somehow embed such commands within the isochronous OUT stream. This is not as hard as it sounds. The above example (checking the hook state) is already serviced in this manner (status is embedded in the IN packet stream) in my former driver, so copying it here is no problem. But embedding commands into the OUT stream will definitely need some additional work and will require a firmware upgrade.

Meanwhile, Alok Prasad (see his comments in previous posts) has reported an issue with porting the original openusbfxs driver to kernels prior to 2.6.20. The problem lies in usb_anchor, which was introduced in late kernel versions. In my reply to Alok, I am holding that

…the anchor is a place where pending URBs can be stored in order to cancel them easily if need be (e.g., if the driver unloads). It is relatively easy to craft a workaround, because in my code the active URBs are known at any time: I use usb_bulk_msg() for bulk IN/OUT, so the anchor is not used there. For isochronous IN/OUT, if one does not have an anchor, one can cancel active urbs by walking through dev->outbufs[] and dev->in_bufs[] and checking for the state of each of those: if dev->XXXbufs[i].state==st_sbmtd then dev->XXXbufs[i].urb is submitted to the core and must be canceled in case of a disconnect or driver unload. With this workaround, the anchor can be avoided.

While I keep myself busy with hunting nasty spinlock bugs and with other ugly details of dahdi porting, if any reader of this blog can assist by coming up with the above usb_anchor workaround, this would be of great help.

This is the situation right now. I am going to report further progress later in this post. Apart from the worrysome system hang, everything else looks really good! Maybe the board’s “hello, Asterisk!” day is not anymore that far away. Even though this day is not today or tomorrow, or not even next week, I have to admit that it certainly looks much, much closer now than when I first started the project. After all, this post is great news: while not yet in the harbor, I can see land ahead — hence the title.

Update, April 17: The kernel lockup/hang mystery has just been solved! It seems I fell a victim of my own thoughts when I wrote

OK, this is fine if you work with a PCI board, where setting a 3210 register only involves a few inb/outb instructions, however it’s a disaster with USB, where one needs at least one bulk OUT packet (and its confirmation, hence a 2-ms separate I/O sequence) in order to communicate with the board.

just a few paragraphs above. It turns out that the kernel lockup nightmare was hidden exactly in this paragraph. Why? Because, what is by far worse than the 2ms delay that I was babbling about, is the fact that bulk USB communication between the driver and the board is based on usb_bulk_msg(), which presumably is using blocking I/O. This means that the invoking process issues a bulk OUT URB and is then put in a sleep state while waiting for a URB completion  or a timeout. Now, here is what was happening: when the DAHDI_TXSIG_START ioctl was handled by the driver, I had chosen to do the same thing that wctdm.c does: write 3210’s DR 64 of course, to set the phone ringing! This operation is done with the channel spinlock locked (chan->lock  — this lock is acquired by dahdi-base right before invoking the ioctl handler in the hardware device driver), and at the same time, the isochronous engine was running, meaning that dahdi_transmit() would be called eight times each millisecond. What is one of the first things that dahdi_transmit() does? Acquire the channel spinlock, of course! So, the channel lock was acquired by dahdi-base on behalf of fxstest, then the calling process for fxstest went to sleep for two milliseconds (one to transmit the bulk OUT URB for setting DR 64, and one to receive a confirmation). To begin with, letting a process hold a spinlock while going to sleep is a very serious kernel programming error that can result in lockups. Meanwhile, just to make sure that the lockup would occur, the background isochronous engine thread was still running and invoking dahdi_transmit, which tried first-thing to acquire the same spinlock that was being held by the sleeping fxstest process. This was causing a kernel lockup. Bingo! I verified my guess by removing the dr_write() macros that set various DRs in all places but the initialization worker thread. And — yes! — the kernel hang disappeared. Of course the phone set did not ring, since DR64 is not yet being set, however my driver did no more lockup the kernel. Now I have resolved this issue, I am going to fix these to use isochronous OUT piggybacking. This means that, if no other unpleasant surprises wait for me down the road, the dahdi driver will be ready within a few days from now!

Update, April 18: I have implemented the DR set piggybacking logic in both the driver and the firmware. It did not work right away, so some testing and debugging is still needed, but the basis is there and there should be no fundamental error in the logic. What’s nice is that the kernel does not hang anymore on the DAHDI_RING ioctl. I do get a couple of serious errors though. When disconnecting the board, fxstest receives a SIGSEGV and the module count remains 1, even though the program that has opened the device gets killed. As a result, the module cannot be unloaded anymore and becomes a zombie. Some fixes here and there cured another kernel hang when the board was unplugged and then plugged back in. All these I guess are race conditions, as the usb core calls the module’s disconnect() method, which in turn starts dismantling the device instance, while the device is still hooked within dahdi. Anyway, I ‘ll soon resolve these errors, I ‘m sure.

Update, April 20: I think I fixed the module reference errors. The most significant error was that I was calling dahdi_unregister() too early, and thus the close() that occurred when the calling process exited was not received by my driver. Hence, the module’s reference count was left equal to one and the module could not be unloaded. Moving dahdi_unregister() from the oufxs_disconnect() callback to the oufxs_delete() one fixed it (you may check the source of the older driver to see what these do). So the driver looks stable now, does not hang or freeze the system and does not put the module into a zombie state anymore. Next thing to do is to debug the piggyback register setting capability. Once this is fixed as well, all that’s left is the IN isochronous engine, and then the driver will be ready!

Update, April 20 (later): Piggybacking of register set commands on OUT packet headers now works perfect and “fxstest /dev/dahdi/1 ring” rings the phone!

Update, April 22: One more nasty bug resolved: when lowpower mode was set to zero (normal power mode), the phone refused to ring! I chased this down to a wrong 3210 register setting during longitudinal balance mode calibration, due to a stupid copy-paste error of mine (I think that I ‘ve already written quite a few times in this blog that code copy-paste-due bugs were by far the worst ones I ‘ve dealt with). The fix to this bug resolved also an intolerable noise issue in audio, which I had swept under the rug for the time. Perfect! Another bug still remains, but this is kernel-related, so — I guess — easier to fix: when I plug the board with the module already loaded and then right away, before the board initializes, I reload the driver, I get a kernel freeze. By now, I ‘m experienced enough to suspect that this is a double spinlock locking, due to a race condition that occurs when the board plugging with the old module instance causes dahd_register() to be invoked shortly before or at the same time that disconnect() is called, which starts dismantling the device. Ugly, but definitely fixable. So, my short-term roadmap is to resolve this last lockup bug, then to write the IN isochronous engine (and hook/dtmf monitoring) and then — provided that no new bugs come up, of course — to publish the new driver code, along with the modified firmware. I have forgotten to mention that, in the meantime, I have assembled one new version-2 dongle board, which is now patiently waiting for me to finish with kernel driver bug-hunting in order to program and test it! So now — unless of course the new dongle blows in smoke on my face — things feel really like approaching the harbor, aren’t they?

Update, April 22 (later): The IN part works now (of course, after fixing another nasty copy-paste bug — I was using the OUT USB endpoint instead of the IN one). The audio quality is perfect in both playout and recording. It’s not ready, of course: I need to add the hook state checks, dtmf state, statistics, and a whole lot more (especially the echo canceller, which is one more thing that I have been sweeping under the rug all this time). However, by now the “ship” is in a “safe harbor”: Open USB FXS works with Dahdi, full stop. So, this is going to be my last update for this post. Prepare for the next one — titled “Hello, Asterisk!” or something similar (I ‘m sure you are guessing correctly it is going to be about, aren’t you?).