* ccid-driver.c (struct ccid_driver_s): Add fields last_progress,

progress_cb and progress_cb_arg.
(ccid_set_progress_cb): New.
(print_progress): New.
(ccid_transceive): Call print_progress for wait time extensions.
* apdu.c (struct reader_table_s): Add field set_progress_cb.
(new_reader_slot): Clear that field.
(open_ccid_reader): Set it to ..
(set_progress_cb_ccid_reader): ... new fucntion.
* app.c (print_progress_line): New.
(lock_reader): Add arg CTRL to set a progress callback and
change all callers to provide it.
(unlock_reader): Remove the progress callback.
This commit is contained in:
Werner Koch 2009-07-13 09:59:22 +00:00
parent 806b0acad7
commit d0d4931e00
4 changed files with 126 additions and 20 deletions

View File

@ -1,3 +1,19 @@
2009-07-13 Werner Koch <wk@g10code.com>
* ccid-driver.c (struct ccid_driver_s): Add fields last_progress,
progress_cb and progress_cb_arg.
(ccid_set_progress_cb): New.
(print_progress): New.
(ccid_transceive): Call print_progress for wait time extensions.
* apdu.c (struct reader_table_s): Add field set_progress_cb.
(new_reader_slot): Clear that field.
(open_ccid_reader): Set it to ..
(set_progress_cb_ccid_reader): ... new fucntion.
* app.c (print_progress_line): New.
(lock_reader): Add arg CTRL to set a progress callback and
change all callers to provide it.
(unlock_reader): Remove the progress callback.
2009-07-10 Werner Koch <wk@g10code.com> 2009-07-10 Werner Koch <wk@g10code.com>
* iso7816.c (iso7816_compute_ds): Add args EXTENDED_MODE and LE. * iso7816.c (iso7816_compute_ds): Add args EXTENDED_MODE and LE.

View File

@ -109,6 +109,7 @@ struct reader_table_s {
unsigned char *, size_t *, struct pininfo_s *); unsigned char *, size_t *, struct pininfo_s *);
int (*check_keypad)(int, int, int, int, int, int); int (*check_keypad)(int, int, int, int, int, int);
void (*dump_status_reader)(int); void (*dump_status_reader)(int);
int (*set_progress_cb)(int, gcry_handler_progress_t, void*);
struct { struct {
ccid_driver_t handle; ccid_driver_t handle;
@ -339,6 +340,7 @@ new_reader_slot (void)
reader_table[reader].send_apdu_reader = NULL; reader_table[reader].send_apdu_reader = NULL;
reader_table[reader].check_keypad = NULL; reader_table[reader].check_keypad = NULL;
reader_table[reader].dump_status_reader = NULL; reader_table[reader].dump_status_reader = NULL;
reader_table[reader].set_progress_cb = NULL;
reader_table[reader].used = 1; reader_table[reader].used = 1;
reader_table[reader].any_status = 0; reader_table[reader].any_status = 0;
@ -1834,6 +1836,15 @@ reset_ccid_reader (int slot)
} }
static int
set_progress_cb_ccid_reader (int slot, gcry_handler_progress_t cb, void *cb_arg)
{
reader_table_t slotp = reader_table + slot;
return ccid_set_progress_cb (slotp->ccid.handle, cb, cb_arg);
}
static int static int
get_status_ccid (int slot, unsigned int *status) get_status_ccid (int slot, unsigned int *status)
{ {
@ -1955,6 +1966,7 @@ open_ccid_reader (const char *portstr)
reader_table[slot].send_apdu_reader = send_apdu_ccid; reader_table[slot].send_apdu_reader = send_apdu_ccid;
reader_table[slot].check_keypad = check_ccid_keypad; reader_table[slot].check_keypad = check_ccid_keypad;
reader_table[slot].dump_status_reader = dump_ccid_reader_status; reader_table[slot].dump_status_reader = dump_ccid_reader_status;
reader_table[slot].set_progress_cb = set_progress_cb_ccid_reader;
/* Our CCID reader code does not support T=0 at all, thus reset the /* Our CCID reader code does not support T=0 at all, thus reset the
flag. */ flag. */
reader_table[slot].is_t0 = 0; reader_table[slot].is_t0 = 0;
@ -2601,6 +2613,30 @@ apdu_disconnect (int slot)
} }
/* Set the progress callback of SLOT to CB and its args to CB_ARG. If
CB is NULL the progress callback is removed. */
int
apdu_set_progress_cb (int slot, gcry_handler_progress_t cb, void *cb_arg)
{
int sw;
if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
return SW_HOST_NO_DRIVER;
if (reader_table[slot].set_progress_cb)
{
sw = lock_slot (slot);
if (!sw)
{
sw = reader_table[slot].set_progress_cb (slot, cb, cb_arg);
unlock_slot (slot);
}
}
else
sw = 0;
return sw;
}
/* Do a reset for the card in reader at SLOT. */ /* Do a reset for the card in reader at SLOT. */
int int
@ -2681,7 +2717,6 @@ apdu_activate (int slot)
} }
unsigned char * unsigned char *
apdu_get_atr (int slot, size_t *atrlen) apdu_get_atr (int slot, size_t *atrlen)
{ {

View File

@ -48,6 +48,20 @@ static void deallocate_app (app_t app);
static void
print_progress_line (void *opaque, const char *what, int pc, int cur, int tot)
{
ctrl_t ctrl = opaque;
char line[100];
if (ctrl)
{
snprintf (line, sizeof line, "%s %c %d %d", what, pc, cur, tot);
send_status_direct (ctrl, "PROGRESS", line);
}
}
/* Lock the reader SLOT. This function shall be used right before /* Lock the reader SLOT. This function shall be used right before
calling any of the actual application functions to serialize access calling any of the actual application functions to serialize access
to the reader. We do this always even if the reader is not to the reader. We do this always even if the reader is not
@ -56,7 +70,7 @@ static void deallocate_app (app_t app);
success; only then the unlock_reader function must be called after success; only then the unlock_reader function must be called after
returning from the handler. */ returning from the handler. */
static gpg_error_t static gpg_error_t
lock_reader (int slot) lock_reader (int slot, ctrl_t ctrl)
{ {
gpg_error_t err; gpg_error_t err;
@ -84,6 +98,8 @@ lock_reader (int slot)
return err; return err;
} }
apdu_set_progress_cb (slot, print_progress_line, ctrl);
return 0; return 0;
} }
@ -95,10 +111,11 @@ unlock_reader (int slot)
|| !lock_table[slot].initialized) || !lock_table[slot].initialized)
log_bug ("unlock_reader called for invalid slot %d\n", slot); log_bug ("unlock_reader called for invalid slot %d\n", slot);
apdu_set_progress_cb (slot, NULL, NULL);
if (!pth_mutex_release (&lock_table[slot].lock)) if (!pth_mutex_release (&lock_table[slot].lock))
log_error ("failed to release APP lock for slot %d: %s\n", log_error ("failed to release APP lock for slot %d: %s\n",
slot, strerror (errno)); slot, strerror (errno));
} }
@ -171,7 +188,7 @@ application_notify_card_reset (int slot)
return; return;
/* FIXME: We are ignoring any error value here. */ /* FIXME: We are ignoring any error value here. */
lock_reader (slot); lock_reader (slot, NULL);
/* Mark application as non-reusable. */ /* Mark application as non-reusable. */
if (lock_table[slot].app) if (lock_table[slot].app)
@ -229,7 +246,7 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app)
*r_app = NULL; *r_app = NULL;
err = lock_reader (slot); err = lock_reader (slot, ctrl);
if (err) if (err)
return err; return err;
@ -461,7 +478,7 @@ release_application (app_t app)
/* Move the reference to the application in the lock table. */ /* Move the reference to the application in the lock table. */
slot = app->slot; slot = app->slot;
/* FIXME: We are ignoring any error value. */ /* FIXME: We are ignoring any error value. */
lock_reader (slot); lock_reader (slot, NULL);
if (lock_table[slot].app != app) if (lock_table[slot].app != app)
{ {
unlock_reader (slot); unlock_reader (slot);
@ -579,7 +596,7 @@ app_write_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
if (app->apptype && !(flags & 1)) if (app->apptype && !(flags & 1))
send_status_info (ctrl, "APPTYPE", send_status_info (ctrl, "APPTYPE",
app->apptype, strlen (app->apptype), NULL, 0); app->apptype, strlen (app->apptype), NULL, 0);
err = lock_reader (app->slot); err = lock_reader (app->slot, ctrl);
if (err) if (err)
return err; return err;
err = app->fnc.learn_status (app, ctrl, flags); err = app->fnc.learn_status (app, ctrl, flags);
@ -604,7 +621,7 @@ app_readcert (app_t app, const char *certid,
return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
if (!app->fnc.readcert) if (!app->fnc.readcert)
return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
err = lock_reader (app->slot); err = lock_reader (app->slot, NULL/* FIXME*/);
if (err) if (err)
return err; return err;
err = app->fnc.readcert (app, certid, cert, certlen); err = app->fnc.readcert (app, certid, cert, certlen);
@ -636,7 +653,7 @@ app_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen)
return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
if (!app->fnc.readkey) if (!app->fnc.readkey)
return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
err = lock_reader (app->slot); err = lock_reader (app->slot, NULL /*FIXME*/);
if (err) if (err)
return err; return err;
err= app->fnc.readkey (app, keyid, pk, pklen); err= app->fnc.readkey (app, keyid, pk, pklen);
@ -678,7 +695,7 @@ app_getattr (app_t app, ctrl_t ctrl, const char *name)
if (!app->fnc.getattr) if (!app->fnc.getattr)
return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
err = lock_reader (app->slot); err = lock_reader (app->slot, ctrl);
if (err) if (err)
return err; return err;
err = app->fnc.getattr (app, ctrl, name); err = app->fnc.getattr (app, ctrl, name);
@ -701,7 +718,7 @@ app_setattr (app_t app, const char *name,
return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
if (!app->fnc.setattr) if (!app->fnc.setattr)
return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
err = lock_reader (app->slot); err = lock_reader (app->slot, NULL /*FIXME*/);
if (err) if (err)
return err; return err;
err = app->fnc.setattr (app, name, pincb, pincb_arg, value, valuelen); err = app->fnc.setattr (app, name, pincb, pincb_arg, value, valuelen);
@ -727,7 +744,7 @@ app_sign (app_t app, const char *keyidstr, int hashalgo,
return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
if (!app->fnc.sign) if (!app->fnc.sign)
return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
err = lock_reader (app->slot); err = lock_reader (app->slot, NULL /*FIXME*/);
if (err) if (err)
return err; return err;
err = app->fnc.sign (app, keyidstr, hashalgo, err = app->fnc.sign (app, keyidstr, hashalgo,
@ -759,7 +776,7 @@ app_auth (app_t app, const char *keyidstr,
return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
if (!app->fnc.auth) if (!app->fnc.auth)
return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
err = lock_reader (app->slot); err = lock_reader (app->slot, NULL /*FIXME*/);
if (err) if (err)
return err; return err;
err = app->fnc.auth (app, keyidstr, err = app->fnc.auth (app, keyidstr,
@ -791,7 +808,7 @@ app_decipher (app_t app, const char *keyidstr,
return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
if (!app->fnc.decipher) if (!app->fnc.decipher)
return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
err = lock_reader (app->slot); err = lock_reader (app->slot, NULL /*FIXME*/);
if (err) if (err)
return err; return err;
err = app->fnc.decipher (app, keyidstr, err = app->fnc.decipher (app, keyidstr,
@ -821,7 +838,7 @@ app_writecert (app_t app, ctrl_t ctrl,
return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
if (!app->fnc.writecert) if (!app->fnc.writecert)
return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
err = lock_reader (app->slot); err = lock_reader (app->slot, ctrl);
if (err) if (err)
return err; return err;
err = app->fnc.writecert (app, ctrl, certidstr, err = app->fnc.writecert (app, ctrl, certidstr,
@ -849,7 +866,7 @@ app_writekey (app_t app, ctrl_t ctrl,
return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
if (!app->fnc.writekey) if (!app->fnc.writekey)
return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
err = lock_reader (app->slot); err = lock_reader (app->slot, ctrl);
if (err) if (err)
return err; return err;
err = app->fnc.writekey (app, ctrl, keyidstr, flags, err = app->fnc.writekey (app, ctrl, keyidstr, flags,
@ -876,7 +893,7 @@ app_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
if (!app->fnc.genkey) if (!app->fnc.genkey)
return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
err = lock_reader (app->slot); err = lock_reader (app->slot, ctrl);
if (err) if (err)
return err; return err;
err = app->fnc.genkey (app, ctrl, keynostr, flags, err = app->fnc.genkey (app, ctrl, keynostr, flags,
@ -900,7 +917,7 @@ app_get_challenge (app_t app, size_t nbytes, unsigned char *buffer)
return gpg_error (GPG_ERR_INV_VALUE); return gpg_error (GPG_ERR_INV_VALUE);
if (!app->ref_count) if (!app->ref_count)
return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
err = lock_reader (app->slot); err = lock_reader (app->slot, NULL /*FIXME*/);
if (err) if (err)
return err; return err;
err = iso7816_get_challenge (app->slot, nbytes, buffer); err = iso7816_get_challenge (app->slot, nbytes, buffer);
@ -924,7 +941,7 @@ app_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, int reset_mode,
return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
if (!app->fnc.change_pin) if (!app->fnc.change_pin)
return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
err = lock_reader (app->slot); err = lock_reader (app->slot, ctrl);
if (err) if (err)
return err; return err;
err = app->fnc.change_pin (app, ctrl, chvnostr, reset_mode, err = app->fnc.change_pin (app, ctrl, chvnostr, reset_mode,
@ -952,7 +969,7 @@ app_check_pin (app_t app, const char *keyidstr,
return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED); return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
if (!app->fnc.check_pin) if (!app->fnc.check_pin)
return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION); return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
err = lock_reader (app->slot); err = lock_reader (app->slot, NULL /*FIXME*/);
if (err) if (err)
return err; return err;
err = app->fnc.check_pin (app, keyidstr, pincb, pincb_arg); err = app->fnc.check_pin (app, keyidstr, pincb, pincb_arg);

View File

@ -254,6 +254,12 @@ struct ccid_driver_s
int apdu_level; /* Reader supports short APDU level exchange. int apdu_level; /* Reader supports short APDU level exchange.
With a value of 2 short and extended level is With a value of 2 short and extended level is
supported.*/ supported.*/
time_t last_progress; /* Last time we sent progress line. */
/* The progress callback and its first arg as supplied to
ccid_set_progress_cb. */
void (*progress_cb)(void *, const char *, int, int, int);
void *progress_cb_arg;
}; };
@ -302,6 +308,23 @@ set_msg_len (unsigned char *msg, unsigned int length)
} }
static void
print_progress (ccid_driver_t handle)
{
time_t ct = time (NULL);
/* We don't want to print progress lines too often. */
if (ct == handle->last_progress)
return;
if (handle->progress_cb)
handle->progress_cb (handle->progress_cb_arg, "card_busy", 'w', 0, 0);
handle->last_progress = ct;
}
/* Pint an error message for a failed CCID command including a textual /* Pint an error message for a failed CCID command including a textual
error code. MSG shall be the CCID message at a minimum of 10 bytes. */ error code. MSG shall be the CCID message at a minimum of 10 bytes. */
static void static void
@ -1670,6 +1693,20 @@ ccid_shutdown_reader (ccid_driver_t handle)
} }
int
ccid_set_progress_cb (ccid_driver_t handle,
void (*cb)(void *, const char *, int, int, int),
void *cb_arg)
{
if (!handle || !handle->rid)
return CCID_DRIVER_ERR_INV_VALUE;
handle->progress_cb = cb;
handle->progress_cb_arg = cb_arg;
return 0;
}
/* Close the reader HANDLE. */ /* Close the reader HANDLE. */
int int
ccid_close_reader (ccid_driver_t handle) ccid_close_reader (ccid_driver_t handle)
@ -2894,6 +2931,7 @@ ccid_transceive (ccid_driver_t handle,
tpdu[tpdulen++] = (edc >> 8); tpdu[tpdulen++] = (edc >> 8);
tpdu[tpdulen++] = edc; tpdu[tpdulen++] = edc;
DEBUGOUT_1 ("T=1: waittime extension of bwi=%d\n", bwi); DEBUGOUT_1 ("T=1: waittime extension of bwi=%d\n", bwi);
print_progress (handle);
} }
else if ( (tpdu[1] & 0x20) && (tpdu[1] & 0x1f) == 0 && !tpdu[2]) else if ( (tpdu[1] & 0x20) && (tpdu[1] & 0x1f) == 0 && !tpdu[2])
{ {