Note on getting NFC support for BuildRoot #1

I have been working on getting my ACR 122U NFC reader from ACS working with buildroot and ARM v5 board. It should have been a simple task, knowing that it has large support from Debian (Dr. Ludovic Rosseau) and there is an official Linux driver from ACS. In the first step, I tried to test it with pcsc-tools package on Ubuntu 10.04 and it works flawlessly. You can reproduce this step by installing the needed package on Ubuntu/Debian:

$ apt-cache search pcscd
libacr38u - PC/SC driver for the ACR38U smart card reader
libasedrive-serial - PC/SC driver for the Athena ASEDrive IIIe serial smart card reader
libasedrive-usb - PC/SC driver for the Athena ASEDrive IIIe USB smart card reader
libccid - PC/SC driver for USB CCID smart card readers
libgempc410 - PC/SC driver for the GemPC 410, 412, 413 and 415 smart card readers
libgempc430 - PC/SC driver for the GemPC 430, 432, 435 smart card readers
pcscd - Middleware to access a smart card using PC/SC (daemon side)
libacsccid - PC/SC driver for ACS USB CCID smart card readers

Only need some packages from buildroot to make it work, it was my assumption. Then I wrote a simple buildroot package file for pcsc-lite, ccid, and pcsc-tools. PCSC-LITE needs either libusb or libudev. I choosen libusb because I read on the busybox list that newer udev package has some conflict with recent uClibc (sorry, this is from my memory, could be invalid), and seems the version of libusb (1.0.8) is the latest one.

The patch is available here: http://pastebin.com/4N8vBVpz

I think everything is ready, now time to cook. The building process of pcsc-lite, ccid are simple thanks to AUTOCONF/AUTORECONF macro of buildroot makefile, only need some tweak when building pcsc-tools, and it also works as gold.

Unfortunately, making pcscd runs on the target board is really a tough job for me. Following is the note:

*** pcscd got segmentation fault caused by libpthread, specifically when calling pthread_mutex_lock() ***

I knew libpthread is coming from the toolchain that we used, it is part of libc. Previously I used uClibc toolchain which came with buildroot, but then I switched to many different toolchain for building buildroot based rootfs; CodeSourcery (2010.09, 2010-q1, 2009-q1), Crosstool-NG, vendor toolchain (looks like in house developped glibc toolchain)

All the same, there was still issue with pthread_mutex_lock which cause SIGSEGV. By common sense, we can say that it is obvious, the code is accessing illegal part of the memory, that could be dangling pointer or nil. But where is part of the code that illegally accessing forbidden address? I was so freaking crazy to find out this issue. Then I started to flood the mailing list of buildroot, muscle, CodeSourcery support, id-embedded, all with the very identical title and content, my gdb backtrace.

gdb /usr/sbin/pcscd
GNU gdb 6.8
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "arm-unknown-linux-gnueabi"...
(gdb) run --foreground --debug --apdu
Starting program: /usr/sbin/pcscd --foreground --debug --apdu
[Thread debugging using libthread_db enabled]
debuglog.c:277:DebugLogSetLevel() debug level=debug
debuglog.c:306:DebugLogSetCategory() Debug options: APDU
pcscdaemon.c:550:main() pcsc-lite 1.7.2 daemon ready.
[New Thread 0x4001a000 (LWP 147)]
[New Thread 0x40a8e470 (LWP 150)]

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x40a8e470 (LWP 150)]
0x401304e8 in pthread_mutex_lock () from /lib/libpthread.so.0
(gdb) info threads
* 2 Thread 0x40a8e470 (LWP 150)  0x401304e8 in pthread_mutex_lock ()
 from /lib/libpthread.so.0
 1 Thread 0x4001a000 (LWP 147)  0x40136e64 in read ()
 from /lib/libpthread.so.0
(gdb) bt 20
#0  0x401304e8 in pthread_mutex_lock () from /lib/libpthread.so.0
#1  0x40103e60 in usbi_get_device_by_session_id (ctx=0x0, session_id=257)
  at core.c:560
#2  0x4010962c in enumerate_device (ctx=0x0, _discdevs=0x40a8dcd8,
  busnum=, devaddr=,
  sysfs_dir=0x351ed3 "usb1") at os/linux_usbfs.c:1393
#3  0x40109930 in sysfs_scan_device (ctx=0x0, _discdevs=0x40a8dcd8,
  devname=0x351ed3 "usb1", usbfs_fallback=)
  at os/linux_usbfs.c:1393
#4  0x40109ba0 in op_get_device_list (ctx=0x0, _discdevs=0x40a8dd0c)
  at os/linux_usbfs.c:1393
#5  0x401040e4 in libusb_get_device_list (ctx=0x0, list=0x40a8dd9c)
  at core.c:644
#6  0x000149b4 in HPRescanUsbBus () at hotplug_libusb.c:166
#7  0x000157a8 in HPEstablishUSBNotifications (pipefd=0xbed94b44)
  at hotplug_libusb.c:166
#8  0x4012db60 in start_thread () from /lib/libpthread.so.0
#9  0x4021fc58 in clone () from /lib/libc.so.6
(gdb)

So, actually my assumption is *probably* right, see the ctx=0x0 and it is passed to  usbi_get_device_by_session_id being used as an argument to usbi_mutex_lock which is a wrapper of pthread_mutex_lock. That should have been enough answer for the SIGSEGV emitter.

I dig more into the pcsc-lite-1.7.4 code which is available here (https://alioth.debian.org/projects/pcsclite/), then I found that libusb_init() return value is not checked, and when checked, it was barely failed, so this is the root cause of that segmentation fault, not the libpthread.

in src/libusb_hotplug.c

       rv = libusb_init(ctx);
       if (rv < 0) {
               fprintf(stderr, "failed to initialise libusb\n");
               exit(1);
       }

I also found that the return value of libusb_init is -99 which is defined as LIBUSB_ERROR_OTHER, and I came to conclusion that it came from libusb backend, more specific: libusb/os/linux_usbfs.c

Anyway, this work is not done yet (so, it’s better for me to work on it instead of writing this crap) but I relearn something that programming is not about feeling, but fact. So, don’t rely on your feeling that an API call is success or not, but simply check its return value.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s