Hello,

Up to now pcscd is polling the card driver every 400ms
(PCSCLITE_STATUS_POLL_RATE) to detect a card movement. This will wake
up the CPU constantly and consume power.

Many CCID readers (but not all) can use an asynchronous message to
send a card movement event to the host. This is supported in the CCID
driver [1] version 1.3.3 with support of TAG_IFD_POLLING_THREAD.
You need to use a snapshot of pcsc-lite [2] to use this feature.

My problem is that the libusb function usb_interrupt_read() is not
efficient and will poll using a 1ms timeout.
So instead of a polling every 400ms by pcscd we have a polling every
1ms by libusb. The situation is worse regarding CPU usage :-(

The problem in libusb has been discovered thanks to powertop [3] and
be corrected in the subversion revision 657 [4] of
/trunk/libusb/linux.c [5]. I backported the patch (attached) for
libusb 0.1.12.
But I have no idea when a new stable version of libusb (with the
correction) will be available.

So what should I do?
I plan to disable TAG_IFD_POLLING_THREAD in the CCID driver by default
and allow a way to activate it using the driver Info.plist file.
Other ideas? proposals? comments?


libusb 0.1.x will not evolve much. libusb 1.0 [6] is on its way and is
in competition with OpenUSB [7]. libusb 1.0 or OpenUSB have no stable
release yet.

Regards,

[1] http://pcsclite.alioth.debian.org/ccid.html
[2] http://ludovic.rousseau.free.fr/softwares/pcsc-lite/
[3] http://www.lesswatts.org/projects/powertop/
[4] 
http://libusb.svn.sourceforge.net/viewvc/libusb/trunk/libusb/linux.c?r1=597&r2=657
[5] 
http://libusb.svn.sourceforge.net/viewvc/libusb/trunk/libusb/linux.c?view=log
|6] http://libusb.wiki.sourceforge.net/Libusb1.0
[7] http://openusb.sourceforge.net/

-- 
 Dr. Ludovic Rousseau
--- libusb-0.1.12/linux.c       2008-01-07 14:10:12.000000000 +0100
+++ libusb-0.1.12.poll/linux.c  2008-02-14 15:25:04.000000000 +0100
@@ -14,6 +14,7 @@
 #include <errno.h>
 #include <sys/time.h>
 #include <dirent.h>
+#include <poll.h>
 
 #include "linux.h"
 #include "usbi.h"
@@ -164,7 +165,7 @@
 {
   struct usb_urb urb;
   int bytesdone = 0, requested;
-  struct timeval tv, tv_ref, tv_now;
+  struct timeval tv_ref, tv_now;
   struct usb_urb *context;
   int ret, waiting;
 
@@ -191,8 +192,6 @@
   }
 
   do {
-    fd_set writefds;
-
     requested = size - bytesdone;
     if (requested > MAX_READ_WRITE)
       requested = MAX_READ_WRITE;
@@ -217,20 +216,21 @@
     waiting = 1;
     context = NULL;
     while (!urb.usercontext && ((ret = ioctl(dev->fd, IOCTL_USB_REAPURBNDELAY, 
&context)) == -1) && waiting) {
-      tv.tv_sec = 0;
-      tv.tv_usec = 1000; // 1 msec
-      FD_ZERO(&writefds);
-      FD_SET(dev->fd, &writefds);
-      select(dev->fd + 1, NULL, &writefds, NULL, &tv); //sub second wait
+       struct pollfd pollfd;
+       int poll_timeout = -1;
+ 
+       pollfd.fd = dev->fd;
+       pollfd.events = POLLOUT;
+       pollfd.revents = 0;
 
       if (timeout) {
-        /* compare with actual time, as the select timeout is not that precise 
*/
         gettimeofday(&tv_now, NULL);
-
-        if ((tv_now.tv_sec > tv_ref.tv_sec) ||
-            ((tv_now.tv_sec == tv_ref.tv_sec) && (tv_now.tv_usec >= 
tv_ref.tv_usec)))
-          waiting = 0;
+         poll_timeout = (tv_ref.tv_sec-tv_now.tv_sec)*1000 +
+                        (tv_ref.tv_usec-tv_now.tv_usec)/1000;
       }
+ 
+       if ((ret = poll(&pollfd, 1, poll_timeout)) != 1)
+         waiting = 0;
     }
 
     if (context && context != &urb) {
_______________________________________________
Muscle mailing list
[email protected]
http://lists.drizzle.com/mailman/listinfo/muscle

Reply via email to