Commit 4ea1c48f authored by Bastien Nocera's avatar Bastien Nocera Committed by Daniel Drake

Detect when a device is disconnected

Pretty hacky way to detect whether the device we're handling has
been disconnected during a verify or enrollment. This should allow
us to avoid users having to wait when somebody pulls the plug.
parent bbead87f
...@@ -154,7 +154,7 @@ static DBusGProxy *create_manager (pam_handle_t *pamh, DBusGConnection **ret_con ...@@ -154,7 +154,7 @@ static DBusGProxy *create_manager (pam_handle_t *pamh, DBusGConnection **ret_con
return manager; return manager;
} }
static close_and_unref (DBusGConnection *connection) static void close_and_unref (DBusGConnection *connection)
{ {
DBusConnection *conn; DBusConnection *conn;
...@@ -335,7 +335,11 @@ static int do_verify(GMainLoop *loop, pam_handle_t *pamh, DBusGProxy *dev) ...@@ -335,7 +335,11 @@ static int do_verify(GMainLoop *loop, pam_handle_t *pamh, DBusGProxy *dev)
ret = PAM_SUCCESS; ret = PAM_SUCCESS;
else if (g_str_equal (data->result, "verify-unknown-error")) else if (g_str_equal (data->result, "verify-unknown-error"))
ret = PAM_AUTHINFO_UNAVAIL; ret = PAM_AUTHINFO_UNAVAIL;
else { else if (g_str_equal (data->result, "verify-disconnected")) {
ret = PAM_AUTHINFO_UNAVAIL;
g_free (data->result);
break;
} else {
send_info_msg (data->pamh, "An unknown error occured"); send_info_msg (data->pamh, "An unknown error occured");
ret = PAM_AUTH_ERR; ret = PAM_AUTH_ERR;
g_free (data->result); g_free (data->result);
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <pwd.h> #include <pwd.h>
#include <errno.h>
#include "fprintd-marshal.h" #include "fprintd-marshal.h"
#include "fprintd.h" #include "fprintd.h"
...@@ -119,6 +120,8 @@ struct FprintDevicePrivate { ...@@ -119,6 +120,8 @@ struct FprintDevicePrivate {
FprintDeviceAction current_action; FprintDeviceAction current_action;
/* Whether we should ignore new signals on the device */ /* Whether we should ignore new signals on the device */
gboolean action_done; gboolean action_done;
/* Whether the device was disconnected */
gboolean disconnected;
}; };
typedef struct FprintDevicePrivate FprintDevicePrivate; typedef struct FprintDevicePrivate FprintDevicePrivate;
...@@ -368,6 +371,8 @@ verify_result_to_name (int result) ...@@ -368,6 +371,8 @@ verify_result_to_name (int result)
return "verify-finger-not-centered"; return "verify-finger-not-centered";
case FP_VERIFY_RETRY_REMOVE_FINGER: case FP_VERIFY_RETRY_REMOVE_FINGER:
return "verify-remove-and-retry"; return "verify-remove-and-retry";
case -EPROTO:
return "verify-disconnected";
default: default:
return "verify-unknown-error"; return "verify-unknown-error";
} }
...@@ -391,11 +396,21 @@ enroll_result_to_name (int result) ...@@ -391,11 +396,21 @@ enroll_result_to_name (int result)
return "enroll-finger-not-centered"; return "enroll-finger-not-centered";
case FP_ENROLL_RETRY_REMOVE_FINGER: case FP_ENROLL_RETRY_REMOVE_FINGER:
return "enroll-remove-and-retry"; return "enroll-remove-and-retry";
case -EPROTO:
return "enroll-disconnected";
default: default:
return "enroll-unknown-error"; return "enroll-unknown-error";
} }
} }
static void
set_disconnected (FprintDevicePrivate *priv, const char *res)
{
if (g_str_equal (res, "enroll-disconnected") ||
g_str_equal (res, "verify-disconnected"))
priv->disconnected = TRUE;
}
static gboolean static gboolean
_fprint_device_check_claimed (FprintDevice *rdev, _fprint_device_check_claimed (FprintDevice *rdev,
DBusGMethodInvocation *context, DBusGMethodInvocation *context,
...@@ -790,6 +805,7 @@ static void verify_cb(struct fp_dev *dev, int r, struct fp_img *img, ...@@ -790,6 +805,7 @@ static void verify_cb(struct fp_dev *dev, int r, struct fp_img *img,
if (r == FP_VERIFY_NO_MATCH || r == FP_VERIFY_MATCH || r < 0) if (r == FP_VERIFY_NO_MATCH || r == FP_VERIFY_MATCH || r < 0)
priv->action_done = TRUE; priv->action_done = TRUE;
set_disconnected (priv, name);
g_signal_emit(rdev, signals[SIGNAL_VERIFY_STATUS], 0, name, priv->action_done); g_signal_emit(rdev, signals[SIGNAL_VERIFY_STATUS], 0, name, priv->action_done);
fp_img_free(img); fp_img_free(img);
...@@ -813,6 +829,7 @@ static void identify_cb(struct fp_dev *dev, int r, ...@@ -813,6 +829,7 @@ static void identify_cb(struct fp_dev *dev, int r,
if (r == FP_VERIFY_NO_MATCH || r == FP_VERIFY_MATCH || r < 0) if (r == FP_VERIFY_NO_MATCH || r == FP_VERIFY_MATCH || r < 0)
priv->action_done = TRUE; priv->action_done = TRUE;
set_disconnected (priv, name);
g_signal_emit(rdev, signals[SIGNAL_VERIFY_STATUS], 0, name, priv->action_done); g_signal_emit(rdev, signals[SIGNAL_VERIFY_STATUS], 0, name, priv->action_done);
fp_img_free(img); fp_img_free(img);
...@@ -986,7 +1003,10 @@ static void fprint_device_verify_stop(FprintDevice *rdev, ...@@ -986,7 +1003,10 @@ static void fprint_device_verify_stop(FprintDevice *rdev,
fp_print_data_free (priv->verify_data); fp_print_data_free (priv->verify_data);
priv->verify_data = NULL; priv->verify_data = NULL;
} }
r = fp_async_verify_stop(priv->dev, verify_stop_cb, context); if (!priv->disconnected)
r = fp_async_verify_stop(priv->dev, verify_stop_cb, context);
else
r = 0;
} else if (priv->current_action == ACTION_IDENTIFY) { } else if (priv->current_action == ACTION_IDENTIFY) {
if (priv->identify_data != NULL) { if (priv->identify_data != NULL) {
guint i; guint i;
...@@ -995,7 +1015,10 @@ static void fprint_device_verify_stop(FprintDevice *rdev, ...@@ -995,7 +1015,10 @@ static void fprint_device_verify_stop(FprintDevice *rdev,
g_free (priv->identify_data); g_free (priv->identify_data);
priv->identify_data = NULL; priv->identify_data = NULL;
} }
r = fp_async_identify_stop(priv->dev, identify_stop_cb, context); if (!priv->disconnected)
r = fp_async_identify_stop(priv->dev, identify_stop_cb, context);
else
r = 0;
} else { } else {
g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_ACTION_IN_PROGRESS, g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_ACTION_IN_PROGRESS,
"No verification in progress"); "No verification in progress");
...@@ -1010,6 +1033,8 @@ static void fprint_device_verify_stop(FprintDevice *rdev, ...@@ -1010,6 +1033,8 @@ static void fprint_device_verify_stop(FprintDevice *rdev,
dbus_g_method_return_error(context, error); dbus_g_method_return_error(context, error);
g_error_free (error); g_error_free (error);
} }
if (priv->disconnected)
dbus_g_method_return(context);
priv->current_action = ACTION_NONE; priv->current_action = ACTION_NONE;
} }
...@@ -1020,6 +1045,7 @@ static void enroll_stage_cb(struct fp_dev *dev, int result, ...@@ -1020,6 +1045,7 @@ static void enroll_stage_cb(struct fp_dev *dev, int result,
struct FprintDevice *rdev = user_data; struct FprintDevice *rdev = user_data;
FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev); FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
struct session_data *session = priv->session; struct session_data *session = priv->session;
const char *name = enroll_result_to_name (result);
int r; int r;
/* We're done, ignore new events for the action */ /* We're done, ignore new events for the action */
...@@ -1035,8 +1061,9 @@ static void enroll_stage_cb(struct fp_dev *dev, int result, ...@@ -1035,8 +1061,9 @@ static void enroll_stage_cb(struct fp_dev *dev, int result,
if (result == FP_ENROLL_COMPLETE || result == FP_ENROLL_FAIL || result < 0) if (result == FP_ENROLL_COMPLETE || result == FP_ENROLL_FAIL || result < 0)
priv->action_done = TRUE; priv->action_done = TRUE;
set_disconnected (priv, name);
g_signal_emit(rdev, signals[SIGNAL_ENROLL_STATUS], 0, enroll_result_to_name (result), priv->action_done); g_signal_emit(rdev, signals[SIGNAL_ENROLL_STATUS], 0, name, priv->action_done);
fp_img_free(img); fp_img_free(img);
fp_print_data_free(print); fp_print_data_free(print);
...@@ -1129,13 +1156,18 @@ static void fprint_device_enroll_stop(FprintDevice *rdev, ...@@ -1129,13 +1156,18 @@ static void fprint_device_enroll_stop(FprintDevice *rdev,
return; return;
} }
r = fp_async_enroll_stop(priv->dev, enroll_stop_cb, context); if (!priv->disconnected)
r = fp_async_enroll_stop(priv->dev, enroll_stop_cb, context);
else
r = 0;
if (r < 0) { if (r < 0) {
g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_INTERNAL, g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_INTERNAL,
"Enroll stop failed with error %d", r); "Enroll stop failed with error %d", r);
dbus_g_method_return_error(context, error); dbus_g_method_return_error(context, error);
g_error_free (error); g_error_free (error);
} }
if (priv->disconnected)
dbus_g_method_return(context);
priv->current_action = ACTION_NONE; priv->current_action = ACTION_NONE;
} }
......
...@@ -182,6 +182,12 @@ ...@@ -182,6 +182,12 @@
The user should remove their finger from the reader and retry scanning their finger, the verification is still ongoing. The user should remove their finger from the reader and retry scanning their finger, the verification is still ongoing.
</doc:definition> </doc:definition>
</doc:item> </doc:item>
<doc:item>
<doc:term>verify-disconnected</doc:term>
<doc:definition>
The device was disconnected during the verification, no other actions should be taken, and you shouldn't use the device any more.
</doc:definition>
</doc:item>
<doc:item> <doc:item>
<doc:term>verify-unknown-error</doc:term> <doc:term>verify-unknown-error</doc:term>
<doc:definition> <doc:definition>
...@@ -239,6 +245,13 @@ ...@@ -239,6 +245,13 @@
The user should remove their finger from the reader and retry scanning their finger, the enrollment is still ongoing. The user should remove their finger from the reader and retry scanning their finger, the enrollment is still ongoing.
</doc:definition> </doc:definition>
</doc:item> </doc:item>
<doc:item>
<doc:term>enroll-disconnected</doc:term>
<doc:definition>
The device was disconnected during the enrollment, no other actions should be taken, and you shouldn't use the device any more.
</doc:definition>
</doc:item>
<doc:item> <doc:item>
<doc:term>enroll-unknown-error</doc:term> <doc:term>enroll-unknown-error</doc:term>
<doc:definition> <doc:definition>
......
...@@ -100,7 +100,7 @@ static void find_finger(DBusGProxy *dev, const char *username) ...@@ -100,7 +100,7 @@ static void find_finger(DBusGProxy *dev, const char *username)
static void verify_result(GObject *object, const char *result, gboolean done, void *user_data) static void verify_result(GObject *object, const char *result, gboolean done, void *user_data)
{ {
gboolean *verify_completed = user_data; gboolean *verify_completed = user_data;
g_print("Verify result: %s\n", result); g_print("Verify result: %s (%s)\n", result, done ? "done" : "not done");
if (done != FALSE) if (done != FALSE)
*verify_completed = TRUE; *verify_completed = TRUE;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment