summaryrefslogtreecommitdiff
path: root/scd/app.c
diff options
context:
space:
mode:
Diffstat (limited to 'scd/app.c')
-rw-r--r--scd/app.c160
1 files changed, 85 insertions, 75 deletions
diff --git a/scd/app.c b/scd/app.c
index b10a452..1d81631 100644
--- a/scd/app.c
+++ b/scd/app.c
@@ -136,45 +136,38 @@ check_application_conflict (const char *name, app_t app)
}
-static void
-release_application_internal (app_t app)
-{
- if (!app->ref_count)
- log_bug ("trying to release an already released context\n");
-
- --app->ref_count;
-}
-
gpg_error_t
app_reset (app_t app, ctrl_t ctrl, int send_reset)
{
- gpg_error_t err;
-
- err = lock_app (app, ctrl);
- if (err)
- return err;
+ gpg_error_t err = 0;
if (send_reset)
{
- int sw = apdu_reset (app->slot);
+ int sw;
+
+ lock_app (app, ctrl);
+ sw = apdu_reset (app->slot);
if (sw)
err = gpg_error (GPG_ERR_CARD_RESET);
- /* Release the same application which is used by other sessions. */
- send_client_notifications (app, 1);
+ app->reset_requested = 1;
+ unlock_app (app);
+
+ scd_kick_the_loop ();
+ gnupg_sleep (1);
}
else
{
ctrl->app_ctx = NULL;
- release_application_internal (app);
+ release_application (app, 0);
}
- unlock_app (app);
return err;
}
static gpg_error_t
-app_new_register (int slot, ctrl_t ctrl, const char *name)
+app_new_register (int slot, ctrl_t ctrl, const char *name,
+ int periodical_check_needed)
{
gpg_error_t err = 0;
app_t app = NULL;
@@ -192,6 +185,7 @@ app_new_register (int slot, ctrl_t ctrl, const char *name)
}
app->slot = slot;
+ app->card_status = (unsigned int)-1;
if (npth_mutex_init (&app->lock, NULL))
{
@@ -302,7 +296,7 @@ app_new_register (int slot, ctrl_t ctrl, const char *name)
return err;
}
- app->require_get_status = 1; /* For token, this can be 0. */
+ app->periodical_check_needed = periodical_check_needed;
npth_mutex_lock (&app_list_lock);
app->next = app_top;
@@ -329,7 +323,9 @@ select_application (ctrl_t ctrl, const char *name, app_t *r_app,
if (scan || !app_top)
{
struct dev_list *l;
+ int periodical_check_needed = 0;
+ /* Scan the devices to find new device(s). */
err = apdu_dev_list_start (opt.reader_port, &l);
if (err)
return err;
@@ -337,38 +333,36 @@ select_application (ctrl_t ctrl, const char *name, app_t *r_app,
while (1)
{
int slot;
- int sw;
+ int periodical_check_needed_this;
- slot = apdu_open_reader (l);
+ slot = apdu_open_reader (l, !app_top);
if (slot < 0)
break;
- err = 0;
- sw = apdu_connect (slot);
-
- if (sw == SW_HOST_CARD_INACTIVE)
+ periodical_check_needed_this = apdu_connect (slot);
+ if (periodical_check_needed_this < 0)
{
- /* Try again. */
- sw = apdu_reset (slot);
+ /* We close a reader with no card. */
+ err = gpg_error (GPG_ERR_ENODEV);
}
-
- if (!sw || sw == SW_HOST_ALREADY_CONNECTED)
- err = 0;
- else if (sw == SW_HOST_NO_CARD)
- err = gpg_error (GPG_ERR_CARD_NOT_PRESENT);
- else
- err = gpg_error (GPG_ERR_ENODEV);
-
- if (!err)
- err = app_new_register (slot, ctrl, name);
else
{
- /* We close a reader with no card. */
- apdu_close_reader (slot);
+ err = app_new_register (slot, ctrl, name,
+ periodical_check_needed_this);
+ if (periodical_check_needed_this)
+ periodical_check_needed = 1;
}
+
+ if (err)
+ apdu_close_reader (slot);
}
apdu_dev_list_finish (l);
+
+ /* If periodical check is needed for new device(s), kick the
+ scdaemon loop. */
+ if (periodical_check_needed)
+ scd_kick_the_loop ();
}
npth_mutex_lock (&app_list_lock);
@@ -464,6 +458,8 @@ deallocate_app (app_t app)
}
xfree (app->serialno);
+
+ unlock_app (app);
xfree (app);
}
@@ -473,7 +469,7 @@ deallocate_app (app_t app)
actually deferring the deallocation to allow for a later reuse by
a new connection. */
void
-release_application (app_t app)
+release_application (app_t app, int locked_already)
{
if (!app)
return;
@@ -483,9 +479,15 @@ release_application (app_t app)
is using the card - this way the PIN cache and other cached data
are preserved. */
- lock_app (app, NULL);
- release_application_internal (app);
- unlock_app (app);
+ if (!locked_already)
+ lock_app (app, NULL);
+
+ if (!app->ref_count)
+ log_bug ("trying to release an already released context\n");
+
+ --app->ref_count;
+ if (!locked_already)
+ unlock_app (app);
}
@@ -1014,21 +1016,26 @@ report_change (int slot, int old_status, int cur_status)
xfree (homestr);
}
-void
+int
scd_update_reader_status_file (void)
{
app_t a, app_next;
+ int periodical_check_needed = 0;
npth_mutex_lock (&app_list_lock);
for (a = app_top; a; a = app_next)
{
+ int sw;
+ unsigned int status;
+
+ lock_app (a, NULL);
app_next = a->next;
- if (a->require_get_status)
+
+ if (a->reset_requested)
+ status = 0;
+ else
{
- int sw;
- unsigned int status;
sw = apdu_get_status (a->slot, 0, &status);
-
if (sw == SW_HOST_NO_READER)
{
/* Most likely the _reader_ has been unplugged. */
@@ -1037,26 +1044,42 @@ scd_update_reader_status_file (void)
else if (sw)
{
/* Get status failed. Ignore that. */
+ if (a->periodical_check_needed)
+ periodical_check_needed = 1;
+ unlock_app (a);
continue;
}
+ }
- if (a->card_status != status)
+ if (a->card_status != status)
+ {
+ report_change (a->slot, a->card_status, status);
+ send_client_notifications (a, status == 0);
+
+ if (status == 0)
{
- report_change (a->slot, a->card_status, status);
- send_client_notifications (a, status == 0);
-
- if (status == 0)
- {
- log_debug ("Removal of a card: %d\n", a->slot);
- apdu_close_reader (a->slot);
- deallocate_app (a);
- }
- else
- a->card_status = status;
+ log_debug ("Removal of a card: %d\n", a->slot);
+ apdu_close_reader (a->slot);
+ deallocate_app (a);
}
+ else
+ {
+ a->card_status = status;
+ if (a->periodical_check_needed)
+ periodical_check_needed = 1;
+ unlock_app (a);
+ }
+ }
+ else
+ {
+ if (a->periodical_check_needed)
+ periodical_check_needed = 1;
+ unlock_app (a);
}
}
npth_mutex_unlock (&app_list_lock);
+
+ return periodical_check_needed;
}
/* This function must be called once to initialize this module. This
@@ -1078,19 +1101,6 @@ initialize_module_command (void)
return apdu_init ();
}
-app_t
-app_list_start (void)
-{
- npth_mutex_lock (&app_list_lock);
- return app_top;
-}
-
-void
-app_list_finish (void)
-{
- npth_mutex_unlock (&app_list_lock);
-}
-
void
app_send_card_list (ctrl_t ctrl)
{