device.c 20.1 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;

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

#include "device-dbus-glue.h"

struct session_data {
Daniel Drake's avatar
Daniel Drake committed
62
63
64
	/* finger being enrolled */
	int enroll_finger;

Daniel Drake's avatar
Daniel Drake committed
65
66
67
68
69
70
71
72
	/* 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;
73

Daniel Drake's avatar
Daniel Drake committed
74
75
76
77
78
79
80
81
82
83
84
85
};

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;
86

87
88
89
	/* The current user of the device, if claimed */
	char *sender;

90
91
	/* type of storage */
	int storage_type;
Daniel Drake's avatar
Daniel Drake committed
92
93
94
95
96
97
98
99
100
101
};

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,
};

102
enum fprint_device_signals {
Daniel Drake's avatar
Daniel Drake committed
103
104
	SIGNAL_VERIFY_STATUS,
	SIGNAL_ENROLL_STATUS,
105
106
107
	NUM_SIGNALS,
};

Daniel Drake's avatar
Daniel Drake committed
108
109
static GObjectClass *parent_class = NULL;
static guint32 last_id = ~0;
110
static guint signals[NUM_SIGNALS] = { 0, };
Daniel Drake's avatar
Daniel Drake committed
111

112
static void fprint_device_finalize(GObject *object)
Daniel Drake's avatar
Daniel Drake committed
113
114
115
116
{
	/* FIXME close and stuff */
}

117
static void fprint_device_set_property(GObject *object, guint property_id,
Daniel Drake's avatar
Daniel Drake committed
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
	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;
	}
}

133
static void fprint_device_class_init(FprintDeviceClass *klass)
Daniel Drake's avatar
Daniel Drake committed
134
135
136
137
138
139
140
141
{
	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);

142
143
	gobject_class->finalize = fprint_device_finalize;
	gobject_class->set_property = fprint_device_set_property;
144
	g_type_class_add_private(klass, sizeof(FprintDevicePrivate));
Daniel Drake's avatar
Daniel Drake committed
145
146
147
148
149
150
151

	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
152
153
154
155
	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",
156
157
		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
158
159
}

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

168
G_DEFINE_TYPE(FprintDevice, fprint_device, G_TYPE_OBJECT);
Daniel Drake's avatar
Daniel Drake committed
169
170
171
172
173
174
175
176
177
178
179

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;
}

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
206
207
208
209
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
210
211
212
213
214
215
216
217
218
219
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;
220
221
222
223

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

Daniel Drake's avatar
Daniel Drake committed
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
		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);
}

static gboolean fprint_device_claim(FprintDevice *rdev,
	DBusGMethodInvocation *context)
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	GError *error = NULL;
239
240
241
242
	DBusConnection *conn;
	DBusError dbus_error;
	char *sender;
	unsigned long uid;
Daniel Drake's avatar
Daniel Drake committed
243
244
	int r;

245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
	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);
		return FALSE;
	}

	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);
		return FALSE;
	}

	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
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
	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);
		return FALSE;
	}

	return TRUE;
}

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;

298
299
300
	g_free (priv->sender);
	priv->sender = NULL;

Daniel Drake's avatar
Daniel Drake committed
301
302
303
304
305
306
307
308
309
310
	g_message("released device %d", priv->id);
	dbus_g_method_return(context);
}

static gboolean fprint_device_release(FprintDevice *rdev,
	DBusGMethodInvocation *context)
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	struct session_data *session = priv->session;
	GSList *elem = session->loaded_prints;
311
312
313
314
315
316
	GError *error = NULL;

	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
		return FALSE;
	}
Daniel Drake's avatar
Daniel Drake committed
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331

	/* 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);
	return TRUE;
}

static gboolean fprint_device_list_enrolled_fingers(FprintDevice *rdev,
332
	GArray **fingers, DBusGMethodInvocation *context)
Daniel Drake's avatar
Daniel Drake committed
333
334
335
336
337
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	struct fp_dscv_print **prints;
	struct fp_dscv_print **print;
	GArray *ret;
338
339
340
341
342
343
	GError *error = NULL;

	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
		return FALSE;
	}
Daniel Drake's avatar
Daniel Drake committed
344
345
346

	prints = fp_discover_prints();
	if (!prints) {
347
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_DISCOVER_PRINTS,
Daniel Drake's avatar
Daniel Drake committed
348
			"Failed to discover prints");
349
		dbus_g_method_return_error(context, error);
Daniel Drake's avatar
Daniel Drake committed
350
351
352
353
354
355
356
357
358
359
360
361
		return FALSE;
	}

	ret = g_array_new(FALSE, FALSE, sizeof(int));
	for (print = prints; *print; print++)
		if (fp_dev_supports_dscv_print(priv->dev, *print)) {
			int finger = fp_dscv_print_get_finger(*print);
			ret = g_array_append_val(ret, finger);
		}

	fp_dscv_prints_free(prints);
	*fingers = ret;
362
363

	dbus_g_method_return(context);
Daniel Drake's avatar
Daniel Drake committed
364
365
366
367
	return TRUE;
}

static gboolean fprint_device_load_print_data(FprintDevice *rdev,
368
	guint32 finger_num, guint32 *print_id, DBusGMethodInvocation *context)
Daniel Drake's avatar
Daniel Drake committed
369
370
371
372
373
374
375
376
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	struct session_data *session = priv->session;
	struct loaded_print *lprint;
	struct fp_dscv_print **dprints = fp_discover_prints();
	struct fp_dscv_print **dprint;
	struct fp_dscv_print *selected_print = NULL;
	struct fp_print_data *data;
377
	GError *error = NULL;
Daniel Drake's avatar
Daniel Drake committed
378
379
	int r;

380
381
382
383
384
	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
		return FALSE;
	}

Daniel Drake's avatar
Daniel Drake committed
385
	if (!dprints) {
386
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_DISCOVER_PRINTS,
Daniel Drake's avatar
Daniel Drake committed
387
			"Failed to discover prints");
388
		dbus_g_method_return_error(context, error);
Daniel Drake's avatar
Daniel Drake committed
389
390
391
392
393
394
395
396
397
398
399
400
		return FALSE;
	}

	for (dprint = dprints; *dprint; dprint++)
		if (fp_dev_supports_dscv_print(priv->dev, *dprint)
				&& fp_dscv_print_get_finger(*dprint) == finger_num) {
			selected_print = *dprint;
			break;
		}
	
	if (!selected_print) {
		fp_dscv_prints_free(dprints);
401
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_PRINT_NOT_FOUND,
Daniel Drake's avatar
Daniel Drake committed
402
			"Print not found");
403
		dbus_g_method_return_error(context, error);
Daniel Drake's avatar
Daniel Drake committed
404
405
406
407
408
409
		return FALSE;
	}

	r = fp_print_data_from_dscv_print(selected_print, &data);
	fp_dscv_prints_free(dprints);
	if (r < 0) {
410
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_PRINT_LOAD,
Daniel Drake's avatar
Daniel Drake committed
411
			"Print load failed with error %d", r);
412
		dbus_g_method_return_error(context, error);
Daniel Drake's avatar
Daniel Drake committed
413
414
415
416
417
418
419
420
421
422
423
		return FALSE;
	}

	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);
	*print_id = lprint->id;
424
425

	dbus_g_method_return(context);
Daniel Drake's avatar
Daniel Drake committed
426
427
428
429
	return TRUE;
}

static gboolean fprint_device_unload_print_data(FprintDevice *rdev,
430
	guint32 print_id, DBusGMethodInvocation *context)
Daniel Drake's avatar
Daniel Drake committed
431
432
433
434
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	struct session_data *session = priv->session;
	GSList *elem = session->loaded_prints;
435
436
437
438
439
440
	GError *error = NULL;

	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
		return FALSE;
	}
Daniel Drake's avatar
Daniel Drake committed
441
442
443

	g_message("unload print data %d for device %d", print_id, priv->id);
	if (!elem) {
444
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_LOADED_PRINT,
Daniel Drake's avatar
Daniel Drake committed
445
			"No such loaded print %d", print_id);
446
		dbus_g_method_return_error(context, error);
Daniel Drake's avatar
Daniel Drake committed
447
448
449
450
451
452
453
454
455
456
457
		return FALSE;
	}

	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);
458
		dbus_g_method_return(context);
Daniel Drake's avatar
Daniel Drake committed
459
460
461
		return TRUE;
	} while ((elem = g_slist_next(elem)) != NULL);

462
	g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_LOADED_PRINT,
Daniel Drake's avatar
Daniel Drake committed
463
		"No such loaded print %d", print_id);
464
	dbus_g_method_return_error(context, error);
Daniel Drake's avatar
Daniel Drake committed
465
466
467
468
469
470
471
472
473
	return FALSE;
}

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
474
	g_signal_emit(rdev, signals[SIGNAL_VERIFY_STATUS], 0, r);
475
	fp_img_free(img);
Daniel Drake's avatar
Daniel Drake committed
476
477
478
}

static gboolean fprint_device_verify_start(FprintDevice *rdev,
479
	guint32 print_id, DBusGMethodInvocation *context)
Daniel Drake's avatar
Daniel Drake committed
480
481
482
483
484
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	struct session_data *session = priv->session;
	GSList *elem = session->loaded_prints;
	struct fp_print_data *data = NULL;
485
	GError *error = NULL;
Daniel Drake's avatar
Daniel Drake committed
486
487
	int r;

488
489
490
491
492
	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
		return FALSE;
	}

Daniel Drake's avatar
Daniel Drake committed
493
494
	g_message("start verification device %d print %d", priv->id, print_id);
	if (!elem) {
495
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_LOADED_PRINT,
Daniel Drake's avatar
Daniel Drake committed
496
			"No such loaded print %d", print_id);
497
		dbus_g_method_return_error(context, error);
Daniel Drake's avatar
Daniel Drake committed
498
499
500
501
502
503
504
505
506
507
508
509
		return FALSE;
	}
	
	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) {
510
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_LOADED_PRINT,
Daniel Drake's avatar
Daniel Drake committed
511
			"No such loaded print %d", print_id);
512
		dbus_g_method_return_error(context, error);
Daniel Drake's avatar
Daniel Drake committed
513
514
515
516
517
518
		return FALSE;
	}

	/* FIXME check freeing/copying of data */
	r = fp_async_verify_start(priv->dev, data, verify_cb, rdev);
	if (r < 0) {
519
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_VERIFY_START,
Daniel Drake's avatar
Daniel Drake committed
520
			"Verify start failed with error %d", r);
521
		dbus_g_method_return_error(context, error);
Daniel Drake's avatar
Daniel Drake committed
522
523
524
		return FALSE;
	}

525
	dbus_g_method_return(context);
Daniel Drake's avatar
Daniel Drake committed
526
527
528
529
530
531
532
533
534
535
536
537
	return TRUE;
}

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

static gboolean fprint_device_verify_stop(FprintDevice *rdev,
	DBusGMethodInvocation *context)
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
538
	GError *error = NULL;
Daniel Drake's avatar
Daniel Drake committed
539
540
	int r;

541
542
543
544
545
	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
		return FALSE;
	}

Daniel Drake's avatar
Daniel Drake committed
546
547
548
549
550
551
552
553
554
555
556
	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);
		return FALSE;
	}

	return TRUE;
}

Daniel Drake's avatar
Daniel Drake committed
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
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;

	g_message("enroll_stage_cb: result %d", result);
	if (result == FP_ENROLL_COMPLETE)
		fp_print_data_save(print, session->enroll_finger);

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

static gboolean fprint_device_enroll_start(FprintDevice *rdev,
574
	guint32 finger_num, DBusGMethodInvocation *context)
Daniel Drake's avatar
Daniel Drake committed
575
576
577
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	struct session_data *session = priv->session;
578
	GError *error = NULL;
Daniel Drake's avatar
Daniel Drake committed
579
580
	int r;

581
582
583
584
585
	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
		return FALSE;
	}

Daniel Drake's avatar
Daniel Drake committed
586
587
588
589
590
	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) {
591
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_ENROLL_START,
Daniel Drake's avatar
Daniel Drake committed
592
			"Enroll start failed with error %d", r);
593
		dbus_g_method_return_error(context, error);
Daniel Drake's avatar
Daniel Drake committed
594
595
596
		return FALSE;
	}

597
	dbus_g_method_return(context);
Daniel Drake's avatar
Daniel Drake committed
598
599
600
601
602
603
604
605
606
607
608
609
	return TRUE;
}

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

static gboolean fprint_device_enroll_stop(FprintDevice *rdev,
	DBusGMethodInvocation *context)
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
610
	GError *error = NULL;
Daniel Drake's avatar
Daniel Drake committed
611
612
	int r;

613
614
615
616
617
	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
		return FALSE;
	}

Daniel Drake's avatar
Daniel Drake committed
618
619
620
621
622
623
624
625
626
627
628
	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);
		return FALSE;
	}

	return TRUE;
}

629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
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;
}

static gboolean fprint_device_list_enrolled_fingers_from_storage(FprintDevice *rdev,
644
	gchar *username, GArray **fingers, DBusGMethodInvocation *context)
645
646
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
647
	GError *error = NULL;
648
649
650
651
	GSList *prints;
	GSList *item;
	GArray *ret;

652
653
654
655
656
	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
		return FALSE;
	}

657
658
	prints = storages[priv->storage_type].discover_prints(priv->dev, username);
	if (!prints) {
659
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_DISCOVER_PRINTS,
660
			"Failed to discover prints");
661
		dbus_g_method_return_error(context, error);
662
663
664
665
666
667
668
669
670
671
672
		return FALSE;
	}

	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);
	*fingers = ret;
673
674

	dbus_g_method_return(context);
675
676
677
678
	return TRUE;
}

static gboolean fprint_device_load_print_data_from_storage(FprintDevice *rdev,
679
	guint32 finger_num, gchar *username, guint32 *print_id, DBusGMethodInvocation *context)
680
681
682
683
684
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	struct session_data *session = priv->session;
	struct loaded_print *lprint;
	struct fp_print_data *data;
685
	GError *error = NULL;
686
687
	int r;

688
689
690
691
692
	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
		return FALSE;
	}

693
694
695
696
	r = storages[priv->storage_type].print_data_load(priv->dev, (enum fp_finger)finger_num, 
		&data, (char *)username);

	if (r < 0) {
697
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_PRINT_LOAD,
698
			"Print load failed with error %d", r);
699
		dbus_g_method_return_error(context, error);
700
701
702
703
704
705
706
707
708
709
710
		return FALSE;
	}

	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);
	*print_id = lprint->id;
711
712

	dbus_g_method_return(context);
713
714
715
	return TRUE;
}