static void *simple_sink_thread (void *param) { char *name = (char *) param; int status; char buf [USB_BUFSIZE]; status = sink_open (name); if (status < 0) return 0; sink_fd = status; /* synchronous reads of endless streams of data */ pthread_cleanup_push (close_fd, &sink_fd); do { /* original LinuxThreads cancelation didn't work right * so test for it explicitly. */ pthread_testcancel (); errno = 0; status = read (sink_fd, buf, sizeof buf); if (status < 0) break; status = empty_out_buf (buf, status); } while (status > 0); if (status == 0) { if (verbose) fprintf (stderr, "done %s\n", __FUNCTION__); } else if (verbose > 2 || errno != ESHUTDOWN) /* normal disconnect */ perror ("read"); fflush (stdout); fflush (stderr); pthread_cleanup_pop (1); return 0; }
static void *aio_out_thread (void *param) { char *name = (char *) param; int status; io_context_t ctx = 0; struct iocb *queue, *iocb; unsigned i; status = sink_open (name); if (status < 0) return 0; sink_fd = status; pthread_cleanup_push (close_fd, &sink_fd); /* initialize i/o queue */ status = io_setup (aio_out, &ctx); if (status < 0) { perror ("aio_out_thread, io_setup"); return 0; } pthread_cleanup_push (queue_release, &ctx); if (aio_out == 0) aio_out = 1; queue = alloca (aio_out * sizeof *iocb); /* populate and (re)run the queue */ for (i = 0, iocb = queue; i < aio_out; i++, iocb++) { char *buf = malloc (iosize); if (!buf) { fprintf(stderr, "%s can't get buffer[%d]\n", __FUNCTION__, i); return 0; } /* data can be processed in out_complete() */ io_prep_pread (iocb, sink_fd, buf, iosize, 0); io_set_callback (iocb, out_complete); iocb->key = USB_DIR_OUT; status = io_submit (ctx, 1, &iocb); if (status < 0) { perror (__FUNCTION__); break; } aio_out_pending++; if (verbose > 2) fprintf(stderr, "%s submit uiocb %p\n", __FUNCTION__, iocb); } status = io_run (ctx, &aio_out_pending); if (status < 0) perror ("aio_out_thread, io_run"); /* clean up */ fflush (stderr); pthread_cleanup_pop (1); pthread_cleanup_pop (1); return 0; }
/* ccid thread, forwards ccid requests to pcsc and returns results */ static void *ccid (void *param) { char **names = (char **) param; char *source_name = names[0]; char *sink_name = names[1]; int result; size_t bufsize = sizeof(PC_to_RDR_XfrBlock_t) + CCID_EXT_APDU_MAX; __u8 inbuf[bufsize]; source_fd = source_open (source_name); if (source_fd < 0) { if (verbose > 1) perror("source_fd"); goto error; } pthread_cleanup_push (close_fd, &source_fd); sink_fd = sink_open (sink_name); if (sink_fd < 0) { if (verbose > 1) perror("sink_fd"); goto error; } pthread_cleanup_push (close_fd, &sink_fd); pthread_cleanup_push (close_ccid, NULL); __u8 *outbuf = NULL; pthread_cleanup_push (free, outbuf); do { /* original LinuxThreads cancelation didn't work right * so test for it explicitly. */ pthread_testcancel (); if (verbose > 1) fprintf(stderr, "bulk loop: reading %lu bytes... ", (long unsigned) bufsize); result = read(sink_fd, inbuf, bufsize); if (result < 0) break; if (verbose > 1) fprintf(stderr, "bulk loop: got %d, done.\n", result); if (!result) break; result = ccid_parse_bulkout(inbuf, result, &outbuf); if (result < 0) break; if (verbose > 1) fprintf(stderr, "bulk loop: writing %d bytes... ", result); result = write(source_fd, outbuf, result); if (verbose > 1) fprintf(stderr, "done (%d written).\n", result); } while (result >= 0); if (errno != ESHUTDOWN || result < 0) { perror ("ccid loop aborted"); pthread_cancel(ep0); } pthread_cleanup_pop (1); pthread_cleanup_pop (1); pthread_cleanup_pop (1); pthread_cleanup_pop (1); fflush (stdout); fflush (stderr); return 0; error: pthread_cancel(ep0); pthread_exit(0); }