Changeset 1114 for trunk/src


Ignore:
Timestamp:
01/03/09 11:35:00 (3 years ago)
Author:
alonbl
Message:

Support event mode for drivers

Current implementation forces poll loop every one second or so,
this consume CPU and power.

This changeset adds the ability for a driver to provide file
descriptor for event handling, removing the need to poll.

Only Linux USB interface was modified to use this new interface.

All other environments will fall-back into the poll mode.

New driver methods:

before_command

Executed before command, makes it easy to remove event capture.

after_command

Execute after command, makes it easy to add event capture.

get_eventfd

Get an event fd out of the driver, if unsupported -1 should
be returned, this fall-back into the poll mode.

event

Event method to call with th evntfd is signaled.

before_command

Execute whatever needed before executing a command. Useful
if driver need to turn off event capture.

after_command

Execute whatever needed before blocking. Useful if driver
need to turn on event capture.

New device methods:

get_eventfd

Gets eventfd if available.

New USB methods:

ifd_usb_get_eventfd

Get event fd to poll for events.

ifd_usb_capture_event

None blocking capture.

New CT socket methods:

error

Called with POLLERR is received.

New configuration file options:

force_poll

Force polling, default is true (as correct behavior),
until Linux kernel will resolve its issues.

New command-line options:

ifdhandler -p

Force polling.

Linux specific notes:

This enable safe detection of device removal and allow USB drivers
to stop polling device, even if they do not have interrupt interface.

As OpenCT uses /dev/bus/usb namespace if exists, and this feature worked
only on usbfs prior to linux-2.6.28, it will not work with older kernels.

linux-2.6.28 has a bug that cause the signal not to be sent if kernel
is configured without CONFIG_USB_DEVICEFS, see [1].

linux-2.6.29 is expected to solve this issue.

Even if ccid driver works correctly, as it uses interrupt endpoint,
by default polling will be forced.

[1]  http://marc.info/?t=123075926900001&r=1&w=2

M src/ifd/ifdhandler.c
M src/ifd/utils.c
M src/ifd/process.c
M src/ifd/sys-osx.c
M src/ifd/sys-null.c
M src/ifd/device.c
M src/ifd/internal.h
M src/ifd/usb.c
M src/ifd/reader.c
M src/ifd/sys-linux.c
M src/ifd/sys-bsd.c
M src/ifd/sys-solaris.c
M src/ifd/sys-sunray.c
M src/include/openct/driver.h
M src/include/openct/device.h
M src/include/openct/ifd.h
M src/include/openct/socket.h
M src/ct/mainloop.c
M etc/openct.conf.in

Location:
trunk/src
Files:
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/ct/mainloop.c

    r654 r1114  
    4444                unsigned int nsockets = 0, npoll = 0; 
    4545                unsigned int n = 0, listening; 
     46                int have_driver_with_poll = 0; 
    4647                int rc; 
    4748 
     
    6667                        poll_socket[npoll] = sock; 
    6768                        if (sock->poll) { 
     69                                have_driver_with_poll = 1; 
    6870                                if (sock->poll(sock, &pfd[npoll]) == 1) 
    6971                                        npoll++; 
     
    8183                        break; 
    8284 
    83                 rc = poll(pfd, npoll, 1000); 
     85                rc = poll(pfd, npoll, have_driver_with_poll ? 1000 : -1); 
    8486                if (rc < 0) { 
    8587                        if (errno == EINTR) 
     
    99101                        } 
    100102 
     103                        if (pfd[n].revents & POLLERR) { 
     104                                if (sock->error(sock) < 0) { 
     105                                        ct_socket_free(sock); 
     106                                        continue; 
     107                                } 
     108                        } 
    101109                        if (pfd[n].revents & POLLOUT) { 
    102110                                if (sock->send(sock) < 0) { 
  • trunk/src/ifd/device.c

    r893 r1114  
    171171} 
    172172 
     173int ifd_device_get_eventfd(ifd_device_t * dev) 
     174{ 
     175        if (!dev || !dev->ops) 
     176                return -1; 
     177        if (!dev->ops->get_eventfd) 
     178                return -1; 
     179        return dev->ops->get_eventfd(dev); 
     180} 
     181 
    173182void ifd_device_close(ifd_device_t * dev) 
    174183{ 
  • trunk/src/ifd/ifdhandler.c

    r964 r1114  
    3636static int opt_foreground = 0; 
    3737static int opt_info = 0; 
     38static int opt_poll = 0; 
    3839static const char *opt_reader = NULL; 
    3940 
     
    4243static void ifdhandler_run(ifd_reader_t *); 
    4344static int ifdhandler_poll_presence(ct_socket_t *, struct pollfd *); 
     45static int ifdhandler_event(ct_socket_t * sock); 
    4446static int ifdhandler_accept(ct_socket_t *); 
     47static int ifdhandler_error(ct_socket_t *); 
    4548static int ifdhandler_recv(ct_socket_t *); 
    4649static int ifdhandler_send(ct_socket_t *); 
     
    5861        umask(033); 
    5962 
    60         while ((c = getopt(argc, argv, "dFHhvir:s")) != -1) { 
     63        while ((c = getopt(argc, argv, "dFHhvipr:s")) != -1) { 
    6164                switch (c) { 
    6265                case 'd': 
     
    7174                case 'i': 
    7275                        opt_info = 1; 
     76                        break; 
     77                case 'p': 
     78                        opt_poll = 1; 
    7379                        break; 
    7480                case 'r': 
     
    227233        /* Encapsulate the reader into a socket struct */ 
    228234        sock = ct_socket_new(0); 
    229         sock->fd = 0x7FFFFFFF; 
    230         sock->poll = ifdhandler_poll_presence; 
     235        if (opt_poll) { 
     236                sock->fd = -1; 
     237        } 
     238        else { 
     239                sock->fd = ifd_get_eventfd(reader); 
     240        } 
     241        if (sock->fd == -1) { 
     242                ifd_debug(1, "events inactive for reader %s", reader->name); 
     243                sock->fd = 0x7FFFFFFF; 
     244                sock->poll = ifdhandler_poll_presence; 
     245        } 
     246        else { 
     247                ifd_debug(1, "events active for reader %s", reader->name); 
     248                sock->error = ifdhandler_error; 
     249                sock->send = ifdhandler_event; 
     250                sock->events = POLLOUT; 
     251                ifd_before_command(reader); 
     252                ifd_poll(reader); 
     253                ifd_after_command(reader); 
     254        } 
    231255        sock->user_data = reader; 
    232256        ct_mainloop_add_socket(sock); 
     
    243267} 
    244268 
     269static void exit_on_device_disconnect(ifd_reader_t *reader) 
     270{ 
     271        ifd_debug(1, "Reader %s detached", reader->name); 
     272        memset(reader->status, 0, sizeof(*reader->status)); 
     273        exit(0); 
     274} 
     275 
    245276/* 
    246277 * Poll for presence of hotplug device 
     
    250281        ifd_reader_t *reader = (ifd_reader_t *) sock->user_data; 
    251282        ifd_device_t *dev = reader->device; 
    252         unsigned int n; 
    253  
    254         /* Check if the card status changed */ 
    255         for (n = 0; n < reader->nslots; n++) { 
    256                 static unsigned int card_seq = 1; 
    257                 unsigned int prev_seq, new_seq; 
    258                 ct_info_t *info; 
    259                 time_t now; 
    260                 int rc, status; 
    261  
    262                 time(&now); 
    263                 if (now < reader->slot[n].next_update) 
    264                         continue; 
    265  
    266                 /* Poll card status at most once a second 
    267                  * XXX: make this configurable */ 
    268                 reader->slot[n].next_update = now + 1; 
    269  
    270                 if ((rc = ifd_card_status(reader, n, &status)) < 0) { 
    271                         /* Don't return error; let the hotplug test 
    272                          * pick up the detach 
    273                          if (rc == IFD_ERROR_DEVICE_DISCONNECTED) 
    274                          return rc; 
    275                          */ 
    276                         continue; 
    277                 } 
    278  
    279                 info = reader->status; 
    280                 new_seq = prev_seq = info->ct_card[n]; 
    281                 if (!(status & IFD_CARD_PRESENT)) 
    282                         new_seq = 0; 
    283                 else if (!prev_seq || (status & IFD_CARD_STATUS_CHANGED)) { 
    284                         new_seq = card_seq++; 
    285                 } 
    286  
    287                 if (prev_seq != new_seq) { 
    288                         ifd_debug(1, "card status change: %u -> %u", 
    289                                   prev_seq, new_seq); 
    290                         info->ct_card[n] = new_seq; 
    291                         ct_status_update(info); 
    292                 } 
    293         } 
     283 
     284        ifd_poll(reader); 
    294285 
    295286        if (dev->hotplug && ifd_device_poll_presence(dev, pfd) == 0) { 
    296                 ifd_debug(1, "Reader %s detached", reader->name); 
    297                 memset(reader->status, 0, sizeof(*reader->status)); 
    298                 exit(0); 
     287                exit_on_device_disconnect(reader); 
    299288        } 
    300289 
    301290        return 1; 
     291} 
     292 
     293/* 
     294 * Error from socket 
     295 */ 
     296static int ifdhandler_error(ct_socket_t * sock) 
     297{ 
     298        ifd_reader_t *reader = (ifd_reader_t *) sock->user_data; 
     299 
     300        if (ifd_error(reader) < 0) { 
     301                exit_on_device_disconnect(reader); 
     302        } 
     303 
     304        return 0; 
     305} 
     306 
     307/* 
     308 * Receive data from client 
     309 */ 
     310static int ifdhandler_event(ct_socket_t * sock) 
     311{ 
     312        ifd_reader_t *reader = (ifd_reader_t *) sock->user_data; 
     313 
     314        if (ifd_event(reader) < 0) { 
     315                exit_on_device_disconnect(reader); 
     316        } 
     317 
     318        return 0; 
    302319} 
    303320 
     
    443460                "  -F   stay in foreground\n" 
    444461                "  -H   hotplug device, monitor for detach\n" 
     462                "  -p   force polling device even if events supported\n" 
    445463                "  -s   send error and debug messages to syslog\n" 
    446464                "  -d   enable debugging; repeat to increase verbosity\n" 
  • trunk/src/ifd/internal.h

    r1082 r1114  
    6666 
    6767        void (*close) (ifd_device_t *); 
     68 
     69        int (*get_eventfd) (ifd_device_t *); 
    6870 
    6971        /* Poll for device presence. This function is called 
     
    165167/* Internal system dependent device functions */ 
    166168extern int ifd_sysdep_usb_poll_presence(ifd_device_t *, struct pollfd *); 
     169extern int ifd_sysdep_usb_get_eventfd(ifd_device_t *); 
    167170extern int ifd_sysdep_usb_control(ifd_device_t *, 
    168171                                  unsigned int, 
     
    177180extern int ifd_sysdep_usb_begin_capture(ifd_device_t *, int, int, size_t, 
    178181                                        ifd_usb_capture_t **); 
     182extern int ifd_sysdep_usb_capture_event(ifd_device_t *, ifd_usb_capture_t *, 
     183                           void *, size_t); 
    179184extern int ifd_sysdep_usb_capture(ifd_device_t *, ifd_usb_capture_t *, void *, 
    180185                                  size_t, long); 
  • trunk/src/ifd/process.c

    r976 r1114  
    5555} 
    5656 
     57static int do_before_command(ifd_reader_t *); 
     58static int do_after_command(ifd_reader_t *); 
    5759static int do_status(ifd_reader_t *, int, 
    5860                     ct_tlv_parser_t *, ct_tlv_builder_t *); 
     
    103105        } 
    104106 
     107        if ((rc = do_before_command(reader)) < 0) { 
     108                return rc; 
     109        } 
     110 
    105111        memset(&args, 0, sizeof(args)); 
    106112        if (ct_tlv_parse(&args, argbuf) < 0) 
     
    162168                rc = resp.error; 
    163169 
     170        /* 
     171         * TODO consider checking error 
     172         */ 
     173        do_after_command(reader); 
     174 
    164175        return rc; 
     176} 
     177 
     178/* 
     179 * Before command 
     180 */ 
     181static int do_before_command(ifd_reader_t * reader) 
     182{ 
     183        return ifd_before_command(reader); 
     184} 
     185 
     186/* 
     187 * After command 
     188 */ 
     189static int do_after_command(ifd_reader_t * reader) 
     190{ 
     191        return ifd_after_command(reader); 
    165192} 
    166193 
  • trunk/src/ifd/reader.c

    r964 r1114  
    560560        free(reader); 
    561561} 
     562 
     563/* 
     564 * Before command 
     565 */ 
     566int ifd_before_command(ifd_reader_t *reader) 
     567{ 
     568        if (reader->driver->ops->before_command) 
     569                return reader->driver->ops->before_command(reader); 
     570        else 
     571                return 0; 
     572} 
     573 
     574/* 
     575 * After command 
     576 */ 
     577int ifd_after_command(ifd_reader_t *reader) 
     578{ 
     579        if (reader->driver->ops->after_command) 
     580                return reader->driver->ops->after_command(reader); 
     581        else 
     582                return 0; 
     583} 
     584 
     585/* 
     586 * Get eventfd 
     587 */ 
     588int ifd_get_eventfd(ifd_reader_t *reader) 
     589{ 
     590        if (reader->driver->ops->get_eventfd) { 
     591                return reader->driver->ops->get_eventfd(reader); 
     592        } 
     593        else { 
     594                return -1; 
     595        } 
     596} 
     597 
     598static void ifd_slot_status_update(ifd_reader_t *reader, int slot, int status) 
     599{ 
     600        static unsigned int card_seq = 1; 
     601 
     602        ct_info_t *info = reader->status; 
     603        unsigned int prev_seq, new_seq; 
     604 
     605        new_seq = prev_seq = info->ct_card[slot]; 
     606 
     607        if (!(status & IFD_CARD_PRESENT)) { 
     608                new_seq = 0; 
     609        } 
     610        else if (!prev_seq || (status & IFD_CARD_STATUS_CHANGED)) { 
     611                new_seq = card_seq++; 
     612        } 
     613 
     614        if (prev_seq != new_seq) { 
     615                ifd_debug(1, "card status change slot %d: %u -> %u", 
     616                          slot, prev_seq, new_seq); 
     617                info->ct_card[slot] = new_seq; 
     618                ct_status_update(info); 
     619        } 
     620} 
     621 
     622void ifd_poll(ifd_reader_t *reader) 
     623{ 
     624        unsigned slot; 
     625 
     626        /* Check if the card status changed */ 
     627        for (slot = 0; slot < reader->nslots; slot++) { 
     628                time_t now; 
     629                int status; 
     630 
     631                time(&now); 
     632                if (now < reader->slot[slot].next_update) 
     633                        continue; 
     634 
     635                /* Poll card status at most once a second 
     636                 * XXX: make this configurable */ 
     637                reader->slot[slot].next_update = now + 1; 
     638 
     639                if (ifd_card_status(reader, slot, &status) < 0) { 
     640                        /* Don't return error; let the hotplug test 
     641                         * pick up the detach 
     642                         if (rc == IFD_ERROR_DEVICE_DISCONNECTED) 
     643                         return rc; 
     644                         */ 
     645                        continue; 
     646                } 
     647 
     648                ifd_slot_status_update(reader, slot, status); 
     649        } 
     650} 
     651 
     652int ifd_error(ifd_reader_t *reader) 
     653{ 
     654        if (reader->driver->ops->error == NULL) { 
     655                return IFD_ERROR_NOT_SUPPORTED; 
     656        } 
     657 
     658        return reader->driver->ops->error(reader); 
     659} 
     660 
     661int ifd_event(ifd_reader_t *reader) 
     662{ 
     663        int status[OPENCT_MAX_SLOTS]; 
     664        unsigned slot; 
     665        int rc; 
     666 
     667        if (reader->driver->ops->event == NULL) { 
     668                return IFD_ERROR_NOT_SUPPORTED; 
     669        } 
     670 
     671        rc = reader->driver->ops->event(reader, status, reader->nslots); 
     672 
     673        for (slot=0;slot<reader->nslots;slot++) { 
     674                ifd_slot_status_update(reader, slot, status[slot]); 
     675        } 
     676 
     677        return rc; 
     678} 
     679 
  • trunk/src/ifd/sys-bsd.c

    r1051 r1114  
    148148} 
    149149 
     150int ifd_sysdep_usb_get_eventfd(ifd_device_t * dev) 
     151{ 
     152        return -1; 
     153} 
     154 
    150155/* 
    151156 * USB URB capture 
     
    183188        *capret = cap; 
    184189        return 0; 
     190} 
     191 
     192int ifd_sysdep_usb_capture_event(ifd_device_t * dev, ifd_usb_capture_t * cap, 
     193                           void *buffer, size_t len) 
     194{ 
     195        return IFD_ERROR_NOT_SUPPORTED; 
    185196} 
    186197 
  • trunk/src/ifd/sys-linux.c

    r1110 r1114  
    146146/* end of import from usbdevice_fs.h */ 
    147147 
     148#define USB_DISCONNECT_SIGNAL (SIGRTMIN) 
     149 
    148150/* 
    149151 * Poll for presence of USB device 
     
    156158        pfd->events = POLLHUP; 
    157159        return 1; 
     160} 
     161 
     162/* 
     163 * Event fd to use. 
     164 */ 
     165int ifd_sysdep_usb_get_eventfd(ifd_device_t * dev) 
     166{ 
     167        return dev->fd; 
    158168} 
    159169 
     
    302312} 
    303313 
     314int ifd_sysdep_usb_capture_event(ifd_device_t * dev, ifd_usb_capture_t * cap, 
     315                           void *buffer, size_t len) 
     316{ 
     317        struct usbdevfs_urb *purb; 
     318        size_t copied = 0; 
     319        int rc = 0; 
     320 
     321        purb = NULL; 
     322        rc = ioctl(dev->fd, USBDEVFS_REAPURBNDELAY, &purb); 
     323        if (rc < 0) { 
     324                if (errno == EAGAIN) 
     325                        return 0; 
     326                ct_error("usb_reapurb failed: %m"); 
     327                return IFD_ERROR_COMM_ERROR; 
     328        } 
     329 
     330        if (purb != &cap->urb) { 
     331                ifd_debug(2, "reaped usb urb %p", purb); 
     332                return 0; 
     333        } 
     334 
     335        if (purb->status == -1) { 
     336                return IFD_ERROR_COMM_ERROR; 
     337        } 
     338 
     339        if (purb->actual_length) { 
     340                ifd_debug(6, "usb reapurb: len=%u", 
     341                          purb->actual_length); 
     342                if ((copied = purb->actual_length) > len) 
     343                        copied = len; 
     344                if (copied && buffer) 
     345                        memcpy(buffer, purb->buffer, copied); 
     346        } 
     347        else { 
     348                usleep(10000); 
     349        } 
     350 
     351        /* Re-submit URB */ 
     352        usb_submit_urb(dev->fd, cap); 
     353 
     354        return copied; 
     355} 
     356 
    304357int ifd_sysdep_usb_capture(ifd_device_t * dev, ifd_usb_capture_t * cap, 
    305358                           void *buffer, size_t len, long timeout) 
    306359{ 
    307         struct usbdevfs_urb *purb; 
    308360        struct timeval begin; 
    309361        size_t copied; 
     
    326378                        continue; 
    327379 
    328                 purb = NULL; 
    329                 rc = ioctl(dev->fd, USBDEVFS_REAPURBNDELAY, &purb); 
     380                rc = ifd_sysdep_usb_capture_event(dev, cap, buffer, len); 
    330381                if (rc < 0) { 
    331                         if (errno == EAGAIN) 
    332                                 continue; 
    333                         ct_error("usb_reapurb failed: %m"); 
    334                         return IFD_ERROR_COMM_ERROR; 
     382                        return rc; 
    335383                } 
    336  
    337                 if (purb != &cap->urb) { 
    338                         ifd_debug(2, "reaped usb urb %p", purb); 
    339                         continue; 
    340                 } 
    341  
    342                 if (purb->actual_length) { 
    343                         ifd_debug(6, "usb reapurb: len=%u", 
    344                                   purb->actual_length); 
    345                         if ((copied = purb->actual_length) > len) 
    346                                 copied = len; 
    347                         if (copied && buffer) 
    348                                 memcpy(buffer, purb->buffer, copied); 
    349                 } else { 
    350                         usleep(10000); 
    351                 } 
    352  
    353                 /* Re-submit URB */ 
    354                 usb_submit_urb(dev->fd, cap); 
     384                copied = (size_t)rc; 
    355385        } while (!copied); 
    356386 
     
    379409int ifd_sysdep_usb_open(const char *device) 
    380410{ 
    381         return open(device, O_RDWR); 
     411        struct usbdevfs_disconnectsignal ds; 
     412        struct sigaction act; 
     413        int fd = -1; 
     414        int ret = -1; 
     415 
     416        fd = open(device, O_RDWR); 
     417        if (fd == -1) { 
     418                goto cleanup; 
     419        } 
     420 
     421        /* 
     422         * The following will send signal 
     423         * to the process when device is disconnected 
     424         * even if the signal is ignored the blocking 
     425         * call will exit. 
     426         * <linux.2.6.28 - This code will have no affect. 
     427         * =linux-2.6.28 - CONFIG_USB_DEVICEFS must be on. 
     428         * >=linux-2.6.29 - works. 
     429         */ 
     430        memset(&act, 0, sizeof(act)); 
     431        act.sa_handler = SIG_IGN; 
     432        if (sigaction(USB_DISCONNECT_SIGNAL, &act, NULL) == -1) { 
     433                goto cleanup; 
     434        } 
     435 
     436        memset(&ds, 0, sizeof(ds)); 
     437        ds.signr = USB_DISCONNECT_SIGNAL; 
     438        if (ioctl(fd, USBDEVFS_DISCSIGNAL, &ds) == -1) { 
     439                goto cleanup; 
     440        } 
     441 
     442        ret = fd; 
     443        fd = -1; 
     444 
     445cleanup: 
     446        if (fd != -1) { 
     447                close(fd); 
     448        } 
     449 
     450        return ret; 
    382451} 
    383452 
  • trunk/src/ifd/sys-null.c

    r972 r1114  
    2828        return -1; 
    2929#endif 
     30} 
     31 
     32int ifd_sysdep_usb_get_eventfd(ifd_device_t * dev) 
     33{ 
     34        return -1; 
    3035} 
    3136 
     
    8388} 
    8489 
     90int ifd_sysdep_usb_capture_event(ifd_device_t * dev, ifd_usb_capture_t * cap, 
     91                           void *buffer, size_t len) 
     92{ 
     93        return IFD_ERROR_NOT_SUPPORTED; 
     94} 
     95 
    8596int ifd_sysdep_usb_capture(ifd_device_t * dev, ifd_usb_capture_t * cap, 
    8697                           void *buffer, size_t len, long timeout) 
  • trunk/src/ifd/sys-osx.c

    r1023 r1114  
    1616 */ 
    1717int ifd_sysdep_usb_poll_presence(ifd_device_t * dev, struct pollfd *pfd) 
     18{ 
     19        return -1; 
     20} 
     21 
     22int ifd_sysdep_usb_get_eventfd(ifd_device_t * dev) 
    1823{ 
    1924        return -1; 
     
    7378} 
    7479 
     80int ifd_sysdep_usb_capture_event(ifd_device_t * dev, ifd_usb_capture_t * cap, 
     81                           void *buffer, size_t len) 
     82{ 
     83        return IFD_ERROR_NOT_SUPPORTED; 
     84} 
     85 
    7586int ifd_sysdep_usb_capture(ifd_device_t * dev, ifd_usb_capture_t * cap, 
    7687                           void *buffer, size_t len, long timeout) 
  • trunk/src/ifd/sys-solaris.c

    r964 r1114  
    252252 
    253253/* 
     254 * Event fd 
     255 */ 
     256int ifd_sysdep_usb_get_eventfd(ifd_device_t * dev) 
     257{ 
     258        return -1; 
     259} 
     260 
     261/* 
    254262 * USB control command 
    255263 */ 
     
    448456        *capret = cap; 
    449457        return 0; 
     458} 
     459 
     460int ifd_sysdep_usb_capture_event(ifd_device_t * dev, ifd_usb_capture_t * cap, 
     461                           void *buffer, size_t len) 
     462{ 
     463        return IFD_ERROR_NOT_SUPPORTED; 
    450464} 
    451465 
  • trunk/src/ifd/sys-sunray.c

    r964 r1114  
    129129#endif 
    130130 
     131int ifd_sysdep_usb_capture_event(ifd_device_t * dev, ifd_usb_capture_t * cap, 
     132                           void *buffer, size_t len) 
     133{ 
     134        return IFD_ERROR_NOT_SUPPORTED; 
     135} 
     136 
    131137int ifd_sysdep_usb_capture(ifd_device_t * dev, ifd_usb_capture_t * cap, 
    132138                           void *buffer, size_t len, long timeout) 
     
    169175                free(cap); 
    170176        return 0; 
     177} 
     178 
     179/* 
     180 * Event fd 
     181 */ 
     182int ifd_sysdep_usb_get_eventfd(ifd_device_t * dev) 
     183{ 
     184        return -1; 
    171185} 
    172186 
  • trunk/src/ifd/usb.c

    r964 r1114  
    6161        return ifd_sysdep_usb_begin_capture(dev, type, endpoint, maxpacket, 
    6262                                            capret); 
     63} 
     64 
     65int ifd_usb_capture_event(ifd_device_t * dev, ifd_usb_capture_t * cap, void *buffer, 
     66                    size_t len) 
     67{ 
     68        int rc; 
     69 
     70        if (dev->type != IFD_DEVICE_TYPE_USB) 
     71                return -1; 
     72 
     73        ifd_debug(5, "called."); 
     74        rc = ifd_sysdep_usb_capture_event(dev, cap, buffer, len); 
     75        if (ct_config.debug >= 3) { 
     76                if (rc < 0) 
     77                        ifd_debug(1, "usb event capture: %s", ct_strerror(rc)); 
     78                if (rc > 0) 
     79                        ifd_debug(5, "usb event capture: recv %s", 
     80                                  ct_hexdump(buffer, rc)); 
     81                if (rc == 0) 
     82                        ifd_debug(5, "usb event capture: rc=%d (timeout?)", rc); 
     83        } 
     84        return rc; 
    6385} 
    6486 
     
    87109int ifd_usb_end_capture(ifd_device_t * dev, ifd_usb_capture_t * cap) 
    88110{ 
     111        ifd_debug(5, "called."); 
     112 
    89113        if (dev->type != IFD_DEVICE_TYPE_USB) 
    90114                return -1; 
     
    176200} 
    177201 
     202static int usb_get_eventfd(ifd_device_t * dev) 
     203{ 
     204        int rc; 
     205 
     206        rc = ifd_sysdep_usb_get_eventfd(dev); 
     207 
     208        return rc; 
     209} 
     210 
    178211static struct ifd_device_ops ifd_usb_ops; 
    179212 
     
    196229        ifd_usb_ops.recv = usb_recv; 
    197230        ifd_usb_ops.reset = usb_reset; 
     231        ifd_usb_ops.get_eventfd = usb_get_eventfd; 
    198232 
    199233        dev = ifd_device_new(device, &ifd_usb_ops, sizeof(*dev)); 
  • trunk/src/ifd/utils.c

    r1042 r1114  
    9191        pid_t pid; 
    9292        char *user = NULL; 
     93        int force_poll = 1; 
    9394 
    9495        ifd_debug(1, "driver=%s, devtype=%s, index=%d", driver, devtype, idx); 
     
    127128                debug[0] = '-'; 
    128129                argv[argc++] = debug; 
     130        } 
     131 
     132        ifd_conf_get_bool("ifdhandler.force_poll", &force_poll); 
     133        if (force_poll) { 
     134                argv[argc++] = "-p"; 
    129135        } 
    130136 
  • trunk/src/include/openct/device.h

    r765 r1114  
    9191extern int              ifd_device_control(ifd_device_t *, void *, size_t); 
    9292extern void             ifd_device_set_hotplug(ifd_device_t *, int); 
     93extern int              ifd_device_get_eventfd(ifd_device_t *); 
    9394extern int              ifd_device_poll_presence(ifd_device_t *, 
    9495                                struct pollfd *); 
     
    109110                                size_t maxpacket, 
    110111                                ifd_usb_capture_t **); 
     112extern int              ifd_usb_capture_event(ifd_device_t *, 
     113                                ifd_usb_capture_t *, 
     114                                void *buffer, size_t len); 
    111115extern int              ifd_usb_capture(ifd_device_t *, 
    112116                                ifd_usb_capture_t *, 
  • trunk/src/include/openct/driver.h

    r970 r1114  
    324324                                const void *sbuf, const size_t slen, 
    325325                                void *rbuf, size_t rlen); 
     326 
     327        /** 
     328         * Execute before command. 
     329         * 
     330         * Provides a chance to setup device to accept new commands. 
     331         * 
     332         * @return Error code <0 if failure, 0 if success. 
     333         */ 
     334        int (*before_command) (ifd_reader_t *); 
     335 
     336        /** 
     337         * Execute after command. 
     338         * 
     339         * Provides a chance to setup device to accept events. 
     340         * 
     341         * @return Error code <0 if failure, 0 if success. 
     342         */ 
     343        int (*after_command) (ifd_reader_t *); 
     344 
     345        /** 
     346         * Get event fd. 
     347         * 
     348         * This will allow the mainloop to wait for event instead of polling. 
     349         * May be NULL if unsupported. 
     350         * 
     351         * @return fd. 
     352         */ 
     353        int (*get_eventfd) (ifd_reader_t *); 
     354 
     355        /** 
     356         * Event callback. 
     357         * 
     358         * Will be called if an event is set. 
     359         * May be NULL if unsupported. 
     360         * 
     361         * @return Error code <0 if failure, 0 if success. 
     362         */ 
     363        int (*event) (ifd_reader_t *, int *status, size_t status_size); 
     364 
     365        /** 
     366         * Error callback. 
     367         * 
     368         * Will be called if an error is set on event fd. 
     369         * May be NULL if unsupported. 
     370         * 
     371         * @return Error code <0 if failure, 0 if success. If reader 
     372         * should be freed, return an error. 
     373         */ 
     374        int (*error) (ifd_reader_t *); 
    326375}; 
    327376 
  • trunk/src/include/openct/ifd.h

    r959 r1114  
    178178                                        const unsigned char *, size_t); 
    179179extern void                     ifd_protocol_free(ifd_protocol_t *); 
     180extern int                      ifd_before_command(ifd_reader_t *); 
     181extern int                      ifd_after_command(ifd_reader_t *); 
     182extern int                      ifd_get_eventfd(ifd_reader_t *); 
     183extern void                     ifd_poll(ifd_reader_t *); 
     184extern int                      id_event(ifd_reader_t *); 
    180185 
    181186/* Debugging macro */ 
  • trunk/src/include/openct/socket.h

    r851 r1114  
    4242        void *          user_data; 
    4343        int             (*poll)(struct ct_socket *, struct pollfd *); 
     44        int             (*error)(struct ct_socket *); 
    4445        int             (*recv)(struct ct_socket *); 
    4546        int             (*send)(struct ct_socket *); 
Note: See TracChangeset for help on using the changeset viewer.