LaForge's home page (Posts about usb)https://laforge.gnumonks.org/blog/tags/usb.atom2022-06-21T07:49:56ZHarald WelteNikolaSometimes software development is a strugglehttps://laforge.gnumonks.org/blog/20190929-development_is_hard/2019-09-29T00:00:00+02:002019-09-29T00:00:00+02:00Harald Welte<p>I'm currently working on the firmware for a new project, an 8-slot smart
card reader. I will share more about the architecture and design ideas
behind this project soon, but today I'll simply write about how hard it
sometimes is to actually get software development done. Seemingly trivial
things suddenly take ages. I guess everyone writing code knows this, but
today I felt like I had to share this story.</p>
<div class="section" id="chapter-1-introduction">
<h2>Chapter 1 - Introduction</h2>
<p>As I'm quite convinced of test-driven development these days, I don't
want to simply write firmware code that can only execute in the target,
but I'm actually working on a USB CCID (USb Class for Smart Card
readers) stack which is hardware-independent, and which can also run
entirely in userspace on a Linux device with USB gadget (device)
controller. This way it's much easier to instrument, trace, introspect
and test the code base, and tests with actual target board hardware are
limited to those functions provided by the board.</p>
<p>So the current architecture for development of the CCID implementation
looks like this:</p>
<ul class="simple">
<li><p>Implement the USB CCID device using <a class="reference external" href="https://www.kernel.org/doc/Documentation/usb/functionfs.txt">FunctionFS</a>
(I did this some months ago, and in fact developing this was a similarly
much more time consuming task than expected, maybe I find time to expand on that)</p></li>
<li><p>Attach this USB gadget to a virtual USB bus + host controller using
the Linux kernel <cite>dummy_hcd</cite> module</p></li>
<li><p>Talk to a dumb <cite>phoenix</cite> style serial SIM card reader attached to a
USB UART, which is connected to an actual SIM card (or any smart card,
for that matter)</p></li>
</ul>
<p>By using a "stupid" UART based smart card reader, I am very close to the
target environment on a Cortex-M microcntroller, where I also have to
talk to a UART and hence implement all the beauty of ISO 7816-3. Hence,
the test / mock / development environment is as close as possible to the
target environment.</p>
<p>So I implemented the various bits and pieces and ended up at a point
where I wanted to test. And I'm not getting any response from the UART
/ SIM card at all. I check all my code, add lots of debugging, play
around with various RTS / DTR / ... handshake settings (which sometimes
control power) - no avail.</p>
<p>In the end, after many hours of trial + error I actually inserted a
different SIM card and finally, I got an ATR from the card. In more
than 20 years of working with smart cards and SIM cards, this is the
first time I've actually seen a SIM card die in front of me, with no
response whatsoever from the card.</p>
</div>
<div class="section" id="chapter-2-linux-is-broken">
<h2>Chapter 2 - Linux is broken</h2>
<p>Anyway, the next step was to get the T=0 protocol of ISO 7816-3 going.
Since there is only one I/O line between SIM card and reader for both
directions, the protocol is a half-duplex protocol. This is unlike
"normal" RS232-style UART communication, where you have a separate Rx
and Tx line.</p>
<p>On the hardware side, this is most often implemented by simply
connecting both the Rx and Tx line of the UART to the SIM I/O pin. This
in turn means that you're always getting an echo back for every byte you
write.</p>
<p>One could discard such bytes, but then I'm targeting a microcontroller,
which should be running eight cards in parallel, at preferably
baud-rates up to ~1 megabit speeds, so having to read and discard all
those bytes seems like a big waste of resources.</p>
<p>The obvious solution around that is to disable the receiver inside the
UART before you start transmitting, and re-enable it after you're done
transmitting. This is typically done rather easily, as most UART
registers in hardware provide some way to selectively enable transmitter
and/or receiver independently.</p>
<p>But since I'm working in Linux userspace in my development environment:
How do I approximate this kind of behavior? At least the older readers
of this blog will remember something called the CREAD flag of <a class="reference external" href="http://man7.org/linux/man-pages/man3/termios.3.html">termios</a>. Clearing that
flag will disable the receiver. Back in the 1990ies, I did tons of work
with serial ports, and I remembered there was such a flag.</p>
<p>So I implement my <a class="reference external" href="http://git.osmocom.org/osmo-ccid-firmware/tree/ccid/cuart_driver_tty.c?h=laforge/fsm">userspace UART backend</a>
and somehow it simply doesn't want to work. Again of course I assume I
must be doing something wrong. I'm using strace, I'm single-stepping
through code - no avail.</p>
<p>In the end, it turns out that I've just found <a class="reference external" href="https://bugzilla.kernel.org/show_bug.cgi?id=205033">a bug in the Linux kernel</a>, one that appears
to be there at least ever since the git history of
linux-2.6.git started. Almost all USB serial device drivers do not
implement CREAD, and there is no sotware fall-back implemented in the
core serial (or usb-serial) handling that would discard any received
bytes inside the kernel if CREAD is cleared. Interestingly, the non-USB
serial drivers for classic UARTs attached to local bus, PCI, ... seem to
support it.</p>
<p>The problem would be half as much of a problem if the syscall to clear
CREAD would actually fail with an error. But no, it simply returns
success but bytes continue to be received from the UART/tty :/</p>
<p>So that's the second big surprise of this weekend...</p>
</div>
<div class="section" id="chapter-3-again-a-broken-card">
<h2>Chapter 3 - Again a broken card?</h2>
<p>So I settle for implementing the 'receive as many characters as you
wrote' work-around. Once that is done, I continue to test the code.
And what happens? Somehow my state machine (implemented using <a class="reference external" href="http://ftp.osmocom.org/api/latest/libosmocore/core/html/group__fsm.html#details">osmo-fsm</a>,
of course) for reading the ATR (code found <a class="reference external" href="http://git.osmocom.org/osmo-ccid-firmware/tree/ccid/iso7816_fsm.c?h=laforge/fsm#n469">here</a>)
somehow never wants to complete. The last byte of the ATR always is
missing. How can that be?</p>
<p>Well, guess what, the second SIM card I used is sending a broken,
non-spec compliant ATR where the header indicates 9 historical bytes are
present, but then in reality only 8 bytes are sent by the card.</p>
<p>Of course every reader has a timeout at that point, but that timeout was
not yet implemented in my code, and I also wasn't expecting to hit that
timeout.</p>
<p>So after using yet another SIM card (now a sysmoUSIM-SJS1, not sure why
I didn't even start with that one), it suddenly works.</p>
<p>After a weekend of detours, each of which I would not have assumed at
all before, I finally have code that can obtain the ATR and exchange T=0
TPDUs with cards. Of course I could have had that very easily if I
wanted (we do have code in pySim for this, e.g.) but not in the
architecture that is as close as it gets to the firmware environment of
the microcontroller of my target board.</p>
</div>Re-launching openmoko USB Product ID and Ethernet OUI registryhttps://laforge.gnumonks.org/blog/20180609-openmoko-usb_id/2018-06-09T00:00:00+02:002018-06-09T00:00:00+02:00Harald Welte<p>Some time after <a class="reference external" href="http://openmoko.org/">Openmoko</a> went out of business, they
made available their USB Vendor IDs and IEEE OUI (Ethernet MAC address prefix)
available to Open Source Hardware / FOSS projects.</p>
<p>After maintaining that for some years myself, I was unable to find time to continue
the work and I had handed it over some time ago to two volunteers. However, as
things go, those volunteers also stopped to respond to PID / OUI requests, and
we're now launching the third attempt of continuing this service.</p>
<p>As the openmoko.org wiki will soon be moved into an archive of static web pages only,
we're also moving the list of allocated PID and OUIs into a git repository.</p>
<p>Since git.openmoko.org is also about to be decommissioned, the repository is now
at <a class="reference external" href="https://github.com/openmoko/openmoko-usb-oui">https://github.com/openmoko/openmoko-usb-oui</a>, next to all the archived openmoko.org
repository mirrors.</p>
<p>This also means that in addition to sending an e-mail application for getting an allocation
in those ranges, you can now send a pull-request via github.</p>
<p>Thanks to <a class="reference external" href="https://github.com/cuvoodoo">cuvoodoo</a> for volunteering to maintain the
Openmoko USB PID and IEEE OUI allocations from now on!</p>Power-cycling a USB port should be simple, right?https://laforge.gnumonks.org/blog/20170524-usb-port-powercycle/2017-05-24T00:00:00+02:002017-05-24T00:00:00+02:00Harald Welte<p>Every so often I happen to be involved in designing electronics
equipment that's supposed to run reliably remotely in inaccessible
locations,without any ability for "remote hands" to perform things like
power-cycling or the like. I'm talking about <em>really</em> remote locations,
possible with no but limited back-haul, and a <em>very</em> high cost of ever
sending somebody there for remote maintenance.</p>
<p>Given that a lot of computer peripherals (chips, modules, ...) use USB
these days, this is often some kind of an embedded ARM (rarely x86) SoM
or SBC, which is hooked up to a custom board that contains a USB hub
chip as well as a line of peripherals.</p>
<p>One of the most important lectures I've learned from experience is:
<strong>Never trust reset signals / lines, always include power-switching
capability</strong>. There are many chips and electronics modules available on
the market that have either no RESET, or even might claim to have a
hardware RESET line which you later (painfully) discover just to be a
GPIO polled by software which can get stuck, and hence no way to really
hard-reset the given component.</p>
<p>In the case of a USB-attached device (even though the USB
might only exist on a circuit board between two ICs), this is typically
rather easy: The USB hub is generally capable of switching the power of
its downstream ports. Many cheap USB hubs don't implement this at all,
or implement only ganged switching, but if you carefully select your USB
hub (or in the case of a custom PCB), you can make sure that the given
USB hub supports individual port power switching.</p>
<p>Now the next step is how to actually use this from your (embedded) Linux
system. It turns out to be harder than expected. After all, we're
talking about a standard feature that's present in the USB
specifications since USB 1.x in the late 1990ies. So the expectation is
that it should be straight-forward to do with any decent operating
system.</p>
<p>I don't know how it's on other operating systems, but on Linux I
couldn't really find a proper way how to do this in a clean way. For
more details, please read <a class="reference external" href="http://marc.info/?l=linux-usb&m=149557709602259&w=2">my post to the linux-usb mailing list</a>.</p>
<p>Why am I running into this now? Is it such a strange idea? I mean,
power-cycling a device should be the most simple and straight-forward
thing to do in order to recover from any kind of "stuck state" or other
related issue. Logical enabling/disabling of the port, resetting the
USB device via USB protocol, etc. are all just "soft" forms of a reset
which at best help with USB related issues, but not with any other part
of a USB device.</p>
<p>And in the case of e.g. an USB-attached cellular modem, we're actually
talking about a multi-processor system with multiple built-in
micro-controllers, at least one DSP, an ARM core that might run another
Linux itself (to implement the USB gadget), ... - certainly enough
complex software that you would want to be able to power-cycle it...</p>
<p>I'm curious what the response of the Linux USB gurus is.</p>Volunteer for Openmoko.org USB Product ID maintenancehttps://laforge.gnumonks.org/blog/20151206-volunterr-wanted-usb_iids/2015-12-06T00:00:00+01:002015-12-06T00:00:00+01:00Harald Welte<p>Back when Openmoko took the fall, we donated the Openmoko, Inc. USB
Vendor ID to the community and started the registry of free Product ID
allocations at <a class="reference external" href="http://wiki.openmoko.org/wiki/USB_Product_IDs">http://wiki.openmoko.org/wiki/USB_Product_IDs</a></p>
<p>Given my many other involvements and constant overload, I've been doing a
poor job at maintaining it, i.e. handling incoming requests.</p>
<p>So I'm looking for somebody who can reliably take care of it, including</p>
<blockquote>
<ul class="simple">
<li><p>reviewing if the project fulfills the criteria (hardware or software
already released under FOSS license)</p></li>
<li><p>entering new allocations to the wiki</p></li>
<li><p>informing applicants of their allocation</p></li>
</ul>
</blockquote>
<p>The amount of work is actually not that much (like one mail per week), but
it needs somebody to reliably respond to the requests in a shorter time
frame than I can currently do.</p>
<p>Please let me know if you'd like to volunteer.</p>