device.c 16.8 KB
Newer Older
Daniel Drake's avatar
Daniel Drake committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
 * /net/reactivated/Fprint/Device/foo object implementation
 * Copyright (C) 2008 Daniel Drake <dsd@gentoo.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

20 21
#include "config.h"

Daniel Drake's avatar
Daniel Drake committed
22
#include <dbus/dbus-glib-bindings.h>
23
#include <dbus/dbus-glib-lowlevel.h>
Daniel Drake's avatar
Daniel Drake committed
24
#include <glib.h>
25
#include <glib/gi18n.h>
Daniel Drake's avatar
Daniel Drake committed
26 27 28 29
#include <libfprint/fprint.h>
#include <glib-object.h>

#include "fprintd.h"
30
#include "storage.h"
Daniel Drake's avatar
Daniel Drake committed
31

32 33
extern DBusGConnection *fprintd_dbus_conn;

Bastien Nocera's avatar
Bastien Nocera committed
34
static void fprint_device_claim(FprintDevice *rdev,
Daniel Drake's avatar
Daniel Drake committed
35
	DBusGMethodInvocation *context);
Bastien Nocera's avatar
Bastien Nocera committed
36
static void fprint_device_release(FprintDevice *rdev,
Daniel Drake's avatar
Daniel Drake committed
37
	DBusGMethodInvocation *context);
Bastien Nocera's avatar
Bastien Nocera committed
38
static void fprint_device_unload_print_data(FprintDevice *rdev,
39
	guint32 print_id, DBusGMethodInvocation *context);
Bastien Nocera's avatar
Bastien Nocera committed
40
static void fprint_device_verify_start(FprintDevice *rdev,
41
	guint32 print_id, DBusGMethodInvocation *context);
Bastien Nocera's avatar
Bastien Nocera committed
42
static void fprint_device_verify_stop(FprintDevice *rdev,
Daniel Drake's avatar
Daniel Drake committed
43
	DBusGMethodInvocation *context);
Bastien Nocera's avatar
Bastien Nocera committed
44
static void fprint_device_enroll_start(FprintDevice *rdev,
45
	guint32 finger_num, DBusGMethodInvocation *context);
Bastien Nocera's avatar
Bastien Nocera committed
46
static void fprint_device_enroll_stop(FprintDevice *rdev,
Daniel Drake's avatar
Daniel Drake committed
47
	DBusGMethodInvocation *context);
48 49
static gboolean fprint_device_set_storage_type(FprintDevice *rdev,
	gint type);
50 51
static void fprint_device_list_enrolled_fingers(FprintDevice *rdev, 
	DBusGMethodInvocation *context);
Bastien Nocera's avatar
Bastien Nocera committed
52 53
static void fprint_device_load_print_data(FprintDevice *rdev,
	guint32 finger_num, DBusGMethodInvocation *context);
Daniel Drake's avatar
Daniel Drake committed
54 55 56 57

#include "device-dbus-glue.h"

struct session_data {
Daniel Drake's avatar
Daniel Drake committed
58 59 60
	/* finger being enrolled */
	int enroll_finger;

Daniel Drake's avatar
Daniel Drake committed
61 62 63 64 65 66 67 68
	/* method invocation for async ClaimDevice() */
	DBusGMethodInvocation *context_claim_device;

	/* method invocation for async ReleaseDevice() */
	DBusGMethodInvocation *context_release_device;

	/* a list of loaded prints */
	GSList *loaded_prints;
69

Daniel Drake's avatar
Daniel Drake committed
70 71 72 73 74 75 76 77 78 79 80 81
};

struct loaded_print {
	guint32 id;
	struct fp_print_data *data;
};

struct FprintDevicePrivate {
	guint32 id;
	struct fp_dscv_dev *ddev;
	struct fp_dev *dev;
	struct session_data *session;
82

83 84 85
	/* The current user of the device, if claimed */
	char *sender;

86 87
	/* type of storage */
	int storage_type;
Daniel Drake's avatar
Daniel Drake committed
88 89 90 91 92 93 94 95 96 97
};

typedef struct FprintDevicePrivate FprintDevicePrivate;

#define DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), FPRINT_TYPE_DEVICE, FprintDevicePrivate))

enum fprint_device_properties {
	FPRINT_DEVICE_CONSTRUCT_DDEV = 1,
};

98
enum fprint_device_signals {
Daniel Drake's avatar
Daniel Drake committed
99 100
	SIGNAL_VERIFY_STATUS,
	SIGNAL_ENROLL_STATUS,
101 102 103
	NUM_SIGNALS,
};

Daniel Drake's avatar
Daniel Drake committed
104 105
static GObjectClass *parent_class = NULL;
static guint32 last_id = ~0;
106
static guint signals[NUM_SIGNALS] = { 0, };
Daniel Drake's avatar
Daniel Drake committed
107

108
static void fprint_device_finalize(GObject *object)
Daniel Drake's avatar
Daniel Drake committed
109 110 111 112
{
	/* FIXME close and stuff */
}

113
static void fprint_device_set_property(GObject *object, guint property_id,
Daniel Drake's avatar
Daniel Drake committed
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
	const GValue *value, GParamSpec *pspec)
{
	FprintDevice *self = (FprintDevice *) object;
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(self);

	switch (property_id) {
	case FPRINT_DEVICE_CONSTRUCT_DDEV:
		priv->ddev = g_value_get_pointer(value);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
		break;
	}
}

129
static void fprint_device_class_init(FprintDeviceClass *klass)
Daniel Drake's avatar
Daniel Drake committed
130 131 132 133 134 135 136 137
{
	GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
	GParamSpec *pspec;

	dbus_g_object_type_install_info(FPRINT_TYPE_DEVICE,
		&dbus_glib_fprint_device_object_info);
	parent_class = g_type_class_peek_parent(klass);

138 139
	gobject_class->finalize = fprint_device_finalize;
	gobject_class->set_property = fprint_device_set_property;
140
	g_type_class_add_private(klass, sizeof(FprintDevicePrivate));
Daniel Drake's avatar
Daniel Drake committed
141 142 143 144 145 146 147

	pspec = g_param_spec_pointer("discovered-dev", "Discovered device",
		"Set discovered device construction property",
		G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE);
	g_object_class_install_property(gobject_class,
		FPRINT_DEVICE_CONSTRUCT_DDEV, pspec);

Daniel Drake's avatar
Daniel Drake committed
148 149 150 151
	signals[SIGNAL_VERIFY_STATUS] = g_signal_new("verify-status",
		G_TYPE_FROM_CLASS(gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL,
		g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
	signals[SIGNAL_ENROLL_STATUS] = g_signal_new("enroll-status",
152 153
		G_TYPE_FROM_CLASS(gobject_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL,
		g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
Daniel Drake's avatar
Daniel Drake committed
154 155
}

156
static void fprint_device_init(FprintDevice *device)
Daniel Drake's avatar
Daniel Drake committed
157
{
158
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(device);
Daniel Drake's avatar
Daniel Drake committed
159
	priv->id = ++last_id;
160 161
	priv->storage_type = FP_FILE_STORAGE;
	storages[priv->storage_type].init();
Daniel Drake's avatar
Daniel Drake committed
162 163
}

164
G_DEFINE_TYPE(FprintDevice, fprint_device, G_TYPE_OBJECT);
Daniel Drake's avatar
Daniel Drake committed
165 166 167 168 169 170 171 172 173 174 175

FprintDevice *fprint_device_new(struct fp_dscv_dev *ddev)
{
	return g_object_new(FPRINT_TYPE_DEVICE, "discovered-dev", ddev, NULL);	
}

guint32 _fprint_device_get_id(FprintDevice *rdev)
{
	return DEVICE_GET_PRIVATE(rdev)->id;
}

176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
static gboolean
_fprint_device_check_claimed (FprintDevice *rdev,
			      DBusGMethodInvocation *context,
			      GError **error)
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	DBusConnection *conn;
	char *sender;
	gboolean retval;

	/* The device wasn't claimed, exit */
	if (priv->sender == NULL) {
		g_set_error (error, FPRINT_ERROR, FPRINT_ERROR_CLAIM_DEVICE,
			     _("Device was not claimed before use"));
		return FALSE;
	}

	conn = dbus_g_connection_get_connection (fprintd_dbus_conn);
	sender = dbus_g_method_get_sender (context);
	retval = g_str_equal (sender, priv->sender);
	g_free (sender);

	if (retval == FALSE) {
		g_set_error (error, FPRINT_ERROR, FPRINT_ERROR_ALREADY_IN_USE,
			     _("Device already in use by another user"));
	}

	return retval;
}

Daniel Drake's avatar
Daniel Drake committed
206 207 208 209 210 211 212 213 214 215
static void dev_open_cb(struct fp_dev *dev, int status, void *user_data)
{
	FprintDevice *rdev = user_data;
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	struct session_data *session = priv->session;

	g_message("device %d claim status %d", priv->id, status);

	if (status != 0) {
		GError *error;
216 217 218 219

		g_free (priv->sender);
		priv->sender = NULL;

Daniel Drake's avatar
Daniel Drake committed
220 221 222 223 224 225 226 227 228 229
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_CLAIM_DEVICE,
			"Open failed with error %d", status);
		dbus_g_method_return_error(session->context_claim_device, error);
		return;
	}

	priv->dev = dev;
	dbus_g_method_return(session->context_claim_device);
}

Bastien Nocera's avatar
Bastien Nocera committed
230
static void fprint_device_claim(FprintDevice *rdev,
Daniel Drake's avatar
Daniel Drake committed
231 232 233 234
	DBusGMethodInvocation *context)
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	GError *error = NULL;
235 236 237 238
	DBusConnection *conn;
	DBusError dbus_error;
	char *sender;
	unsigned long uid;
Daniel Drake's avatar
Daniel Drake committed
239 240
	int r;

241 242 243 244
	if (priv->sender != NULL) {
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_CLAIM_DEVICE,
			    "Device was already claimed");
		dbus_g_method_return_error(context, error);
Bastien Nocera's avatar
Bastien Nocera committed
245
		return;
246 247 248 249 250 251 252 253 254 255 256 257
	}

	conn = dbus_g_connection_get_connection (fprintd_dbus_conn);
	sender = dbus_g_method_get_sender (context);
	dbus_error_init (&dbus_error);
	uid = dbus_bus_get_unix_user (conn, sender, &dbus_error);

	if (dbus_error_is_set(&dbus_error)) {
		g_free (sender);
		dbus_set_g_error (&error, &dbus_error);
		dbus_g_method_return_error(context, error);
		g_error_free (error);
Bastien Nocera's avatar
Bastien Nocera committed
258
		return;
259 260 261 262 263 264 265
	}

	priv->sender = sender;

	g_message ("user claiming the device: %ld", uid);
	/* FIXME call polkit to check whether allowed */

Daniel Drake's avatar
Daniel Drake committed
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
	g_message("claiming device %d", priv->id);
	priv->session = g_slice_new0(struct session_data);
	priv->session->context_claim_device = context;

	r = fp_async_dev_open(priv->ddev, dev_open_cb, rdev);
	if (r < 0) {
		g_slice_free(struct session_data, priv->session);
		priv->session = NULL;
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_CLAIM_DEVICE,
			"Could not attempt device open, error %d", r);
		dbus_g_method_return_error(context, error);
	}
}

static void dev_close_cb(struct fp_dev *dev, void *user_data)
{
	FprintDevice *rdev = user_data;
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	struct session_data *session = priv->session;
	DBusGMethodInvocation *context = session->context_release_device;

	priv->dev = NULL;
	g_slice_free(struct session_data, session);
	priv->session = NULL;

291 292 293
	g_free (priv->sender);
	priv->sender = NULL;

Daniel Drake's avatar
Daniel Drake committed
294 295 296 297
	g_message("released device %d", priv->id);
	dbus_g_method_return(context);
}

Bastien Nocera's avatar
Bastien Nocera committed
298
static void fprint_device_release(FprintDevice *rdev,
Daniel Drake's avatar
Daniel Drake committed
299 300 301 302 303
	DBusGMethodInvocation *context)
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	struct session_data *session = priv->session;
	GSList *elem = session->loaded_prints;
304 305 306 307
	GError *error = NULL;

	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
Bastien Nocera's avatar
Bastien Nocera committed
308
		return;
309
	}
Daniel Drake's avatar
Daniel Drake committed
310 311 312 313 314 315 316 317 318 319 320 321 322

	/* Unload any loaded prints */
	if (elem) {
		do
			g_slice_free(struct loaded_print, elem->data);
		while ((elem = g_slist_next(elem)) != NULL);
		g_slist_free(session->loaded_prints);
	}

	session->context_release_device = context;
	fp_async_dev_close(priv->dev, dev_close_cb, rdev);
}

Bastien Nocera's avatar
Bastien Nocera committed
323
static void fprint_device_unload_print_data(FprintDevice *rdev,
324
	guint32 print_id, DBusGMethodInvocation *context)
Daniel Drake's avatar
Daniel Drake committed
325 326 327 328
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	struct session_data *session = priv->session;
	GSList *elem = session->loaded_prints;
329 330 331 332
	GError *error = NULL;

	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
Bastien Nocera's avatar
Bastien Nocera committed
333
		return;
334
	}
Daniel Drake's avatar
Daniel Drake committed
335 336 337

	g_message("unload print data %d for device %d", print_id, priv->id);
	if (!elem) {
338
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_LOADED_PRINT,
Daniel Drake's avatar
Daniel Drake committed
339
			"No such loaded print %d", print_id);
340
		dbus_g_method_return_error(context, error);
Bastien Nocera's avatar
Bastien Nocera committed
341
		return;
Daniel Drake's avatar
Daniel Drake committed
342 343 344 345 346 347 348 349 350 351
	}

	do {
		struct loaded_print *print = elem->data;
		if (print->id != print_id)
			continue;

		session->loaded_prints = g_slist_delete_link(session->loaded_prints,
			elem);
		g_slice_free(struct loaded_print, print);
352
		dbus_g_method_return(context);
Bastien Nocera's avatar
Bastien Nocera committed
353
		return;
Daniel Drake's avatar
Daniel Drake committed
354 355
	} while ((elem = g_slist_next(elem)) != NULL);

356
	g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_LOADED_PRINT,
Daniel Drake's avatar
Daniel Drake committed
357
		"No such loaded print %d", print_id);
358
	dbus_g_method_return_error(context, error);
Daniel Drake's avatar
Daniel Drake committed
359 360 361 362 363 364 365 366
}

static void verify_cb(struct fp_dev *dev, int r, struct fp_img *img,
	void *user_data)
{
	struct FprintDevice *rdev = user_data;
	g_message("verify_cb: result %d", r);

Daniel Drake's avatar
Daniel Drake committed
367
	g_signal_emit(rdev, signals[SIGNAL_VERIFY_STATUS], 0, r);
368
	fp_img_free(img);
Daniel Drake's avatar
Daniel Drake committed
369 370
}

Bastien Nocera's avatar
Bastien Nocera committed
371
static void fprint_device_verify_start(FprintDevice *rdev,
372
	guint32 print_id, DBusGMethodInvocation *context)
Daniel Drake's avatar
Daniel Drake committed
373 374 375 376 377
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	struct session_data *session = priv->session;
	GSList *elem = session->loaded_prints;
	struct fp_print_data *data = NULL;
378
	GError *error = NULL;
Daniel Drake's avatar
Daniel Drake committed
379 380
	int r;

381 382
	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
Bastien Nocera's avatar
Bastien Nocera committed
383
		return;
384 385
	}

Daniel Drake's avatar
Daniel Drake committed
386 387
	g_message("start verification device %d print %d", priv->id, print_id);
	if (!elem) {
388
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_LOADED_PRINT,
Daniel Drake's avatar
Daniel Drake committed
389
			"No such loaded print %d", print_id);
390
		dbus_g_method_return_error(context, error);
Bastien Nocera's avatar
Bastien Nocera committed
391
		return;
Daniel Drake's avatar
Daniel Drake committed
392 393 394 395 396 397 398 399 400 401 402
	}
	
	do {
		struct loaded_print *print = elem->data;
		if (print->id == print_id) {
			data = print->data;
			break;
		}
	} while ((elem = g_slist_next(elem)) != NULL);

	if (!data) {
403
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_LOADED_PRINT,
Daniel Drake's avatar
Daniel Drake committed
404
			"No such loaded print %d", print_id);
405
		dbus_g_method_return_error(context, error);
Bastien Nocera's avatar
Bastien Nocera committed
406
		return;
Daniel Drake's avatar
Daniel Drake committed
407 408 409 410 411
	}

	/* FIXME check freeing/copying of data */
	r = fp_async_verify_start(priv->dev, data, verify_cb, rdev);
	if (r < 0) {
412
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_VERIFY_START,
Daniel Drake's avatar
Daniel Drake committed
413
			"Verify start failed with error %d", r);
414
		dbus_g_method_return_error(context, error);
Bastien Nocera's avatar
Bastien Nocera committed
415
		return;
Daniel Drake's avatar
Daniel Drake committed
416 417
	}

418
	dbus_g_method_return(context);
Daniel Drake's avatar
Daniel Drake committed
419 420 421 422 423 424 425
}

static void verify_stop_cb(struct fp_dev *dev, void *user_data)
{
	dbus_g_method_return((DBusGMethodInvocation *) user_data);
}

Bastien Nocera's avatar
Bastien Nocera committed
426
static void fprint_device_verify_stop(FprintDevice *rdev,
Daniel Drake's avatar
Daniel Drake committed
427 428 429
	DBusGMethodInvocation *context)
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
430
	GError *error = NULL;
Daniel Drake's avatar
Daniel Drake committed
431 432
	int r;

433 434
	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
Bastien Nocera's avatar
Bastien Nocera committed
435
		return;
436 437
	}

Daniel Drake's avatar
Daniel Drake committed
438 439 440 441 442 443 444 445
	r = fp_async_verify_stop(priv->dev, verify_stop_cb, context);
	if (r < 0) {
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_VERIFY_STOP,
			"Verify stop failed with error %d", r);
		dbus_g_method_return_error(context, error);
	}
}

Daniel Drake's avatar
Daniel Drake committed
446 447 448 449 450 451
static void enroll_stage_cb(struct fp_dev *dev, int result,
	struct fp_print_data *print, struct fp_img *img, void *user_data)
{
	struct FprintDevice *rdev = user_data;
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	struct session_data *session = priv->session;
Bastien Nocera's avatar
Bastien Nocera committed
452 453
	const char *username = "hadess"; // FIXME
	int r;
Daniel Drake's avatar
Daniel Drake committed
454 455

	g_message("enroll_stage_cb: result %d", result);
Bastien Nocera's avatar
Bastien Nocera committed
456 457 458 459 460
	if (result == FP_ENROLL_COMPLETE) {
		r = storages[priv->storage_type].print_data_save(print, session->enroll_finger, username);
		if (r < 0)
			result = FP_ENROLL_FAIL;
	}
Daniel Drake's avatar
Daniel Drake committed
461 462 463 464 465 466

	g_signal_emit(rdev, signals[SIGNAL_ENROLL_STATUS], 0, result);
	fp_img_free(img);
	fp_print_data_free(print);
}

Bastien Nocera's avatar
Bastien Nocera committed
467
static void fprint_device_enroll_start(FprintDevice *rdev,
468
	guint32 finger_num, DBusGMethodInvocation *context)
Daniel Drake's avatar
Daniel Drake committed
469 470 471
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	struct session_data *session = priv->session;
472
	GError *error = NULL;
Daniel Drake's avatar
Daniel Drake committed
473 474
	int r;

475 476
	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
Bastien Nocera's avatar
Bastien Nocera committed
477
		return;
478 479
	}

Daniel Drake's avatar
Daniel Drake committed
480 481 482 483 484
	g_message("start enrollment device %d finger %d", priv->id, finger_num);
	session->enroll_finger = finger_num;
	
	r = fp_async_enroll_start(priv->dev, enroll_stage_cb, rdev);
	if (r < 0) {
485
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_ENROLL_START,
Daniel Drake's avatar
Daniel Drake committed
486
			"Enroll start failed with error %d", r);
487
		dbus_g_method_return_error(context, error);
Bastien Nocera's avatar
Bastien Nocera committed
488
		return;
Daniel Drake's avatar
Daniel Drake committed
489 490
	}

491
	dbus_g_method_return(context);
Daniel Drake's avatar
Daniel Drake committed
492 493 494 495 496 497 498
}

static void enroll_stop_cb(struct fp_dev *dev, void *user_data)
{
	dbus_g_method_return((DBusGMethodInvocation *) user_data);
}

Bastien Nocera's avatar
Bastien Nocera committed
499
static void fprint_device_enroll_stop(FprintDevice *rdev,
Daniel Drake's avatar
Daniel Drake committed
500 501 502
	DBusGMethodInvocation *context)
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
503
	GError *error = NULL;
Daniel Drake's avatar
Daniel Drake committed
504 505
	int r;

506 507
	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
Bastien Nocera's avatar
Bastien Nocera committed
508
		return;
509 510
	}

Daniel Drake's avatar
Daniel Drake committed
511 512 513 514 515
	r = fp_async_enroll_stop(priv->dev, enroll_stop_cb, context);
	if (r < 0) {
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_ENROLL_STOP,
			"Enroll stop failed with error %d", r);
		dbus_g_method_return_error(context, error);
Bastien Nocera's avatar
Bastien Nocera committed
516
		return;
Daniel Drake's avatar
Daniel Drake committed
517 518 519
	}
}

520 521 522 523 524 525 526 527 528 529 530 531 532 533
static gboolean fprint_device_set_storage_type(FprintDevice *rdev,
	gint type)
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);

	if (type >= FP_STORAGES_COUNT) return FALSE;

	storages[priv->storage_type].deinit();
	priv->storage_type = type;
	storages[priv->storage_type].init();

	return TRUE;
}

534 535
static void fprint_device_list_enrolled_fingers(FprintDevice *rdev,
	DBusGMethodInvocation *context)
536 537
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
538
	GError *error = NULL;
539
	const char *username = "hadess"; //FIXME
540 541 542 543
	GSList *prints;
	GSList *item;
	GArray *ret;

544 545
	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
Bastien Nocera's avatar
Bastien Nocera committed
546
		return;
547 548
	}

549 550
	prints = storages[priv->storage_type].discover_prints(priv->dev, username);
	if (!prints) {
551
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_DISCOVER_PRINTS,
552
			"Failed to discover prints");
553
		dbus_g_method_return_error(context, error);
Bastien Nocera's avatar
Bastien Nocera committed
554
		return;
555 556 557 558 559 560 561 562 563
	}

	ret = g_array_new(FALSE, FALSE, sizeof(int));
	for (item = prints; item; item = item->next) {
		int *fingerptr = (int *)item->data;
		ret = g_array_append_val(ret, *fingerptr);
	}

	g_slist_free(prints);
564

565
	dbus_g_method_return(context, ret);
566 567
}

Bastien Nocera's avatar
Bastien Nocera committed
568 569
static void fprint_device_load_print_data(FprintDevice *rdev,
	guint32 finger_num, DBusGMethodInvocation *context)
570 571 572 573 574
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	struct session_data *session = priv->session;
	struct loaded_print *lprint;
	struct fp_print_data *data;
Bastien Nocera's avatar
Bastien Nocera committed
575
	const char *username = "hadess"; //FIXME
576
	GError *error = NULL;
577 578
	int r;

579 580
	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
Bastien Nocera's avatar
Bastien Nocera committed
581
		return;
582 583
	}

584 585 586 587
	r = storages[priv->storage_type].print_data_load(priv->dev, (enum fp_finger)finger_num, 
		&data, (char *)username);

	if (r < 0) {
588
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_PRINT_LOAD,
589
			"Print load failed with error %d", r);
590
		dbus_g_method_return_error(context, error);
Bastien Nocera's avatar
Bastien Nocera committed
591
		return;
592 593 594 595 596 597 598 599 600
	}

	lprint = g_slice_new(struct loaded_print);
	lprint->data = data;
	lprint->id = ++last_id;
	session->loaded_prints = g_slist_prepend(session->loaded_prints, lprint);

	g_message("load print data finger %d for device %d = %d",
		finger_num, priv->id, lprint->id);
601

602
	dbus_g_method_return(context, lprint->id);
603 604
}