device.c 17.6 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_list_enrolled_fingers(FprintDevice *rdev,
39
	DBusGMethodInvocation *context);
Bastien Nocera's avatar
Bastien Nocera committed
40
static void fprint_device_unload_print_data(FprintDevice *rdev,
41
	guint32 print_id, DBusGMethodInvocation *context);
Bastien Nocera's avatar
Bastien Nocera committed
42
static void fprint_device_verify_start(FprintDevice *rdev,
43
	guint32 print_id, DBusGMethodInvocation *context);
Bastien Nocera's avatar
Bastien Nocera committed
44
static void fprint_device_verify_stop(FprintDevice *rdev,
Daniel Drake's avatar
Daniel Drake committed
45
	DBusGMethodInvocation *context);
Bastien Nocera's avatar
Bastien Nocera committed
46
static void fprint_device_enroll_start(FprintDevice *rdev,
47
	guint32 finger_num, DBusGMethodInvocation *context);
Bastien Nocera's avatar
Bastien Nocera committed
48
static void fprint_device_enroll_stop(FprintDevice *rdev,
Daniel Drake's avatar
Daniel Drake committed
49
	DBusGMethodInvocation *context);
50
51
static gboolean fprint_device_set_storage_type(FprintDevice *rdev,
	gint type);
Bastien Nocera's avatar
Bastien Nocera committed
52
static void fprint_device_list_enrolled_fingers_from_storage(FprintDevice *rdev, 
53
	gchar *username, DBusGMethodInvocation *context);
Bastien Nocera's avatar
Bastien Nocera committed
54
55
static void fprint_device_load_print_data(FprintDevice *rdev,
	guint32 finger_num, DBusGMethodInvocation *context);
Daniel Drake's avatar
Daniel Drake committed
56
57
58
59

#include "device-dbus-glue.h"

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

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

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

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

85
86
87
	/* The current user of the device, if claimed */
	char *sender;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Daniel Drake's avatar
Daniel Drake committed
222
223
224
225
226
227
228
229
230
231
		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
232
static void fprint_device_claim(FprintDevice *rdev,
Daniel Drake's avatar
Daniel Drake committed
233
234
235
236
	DBusGMethodInvocation *context)
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	GError *error = NULL;
237
238
239
240
	DBusConnection *conn;
	DBusError dbus_error;
	char *sender;
	unsigned long uid;
Daniel Drake's avatar
Daniel Drake committed
241
242
	int r;

243
244
245
246
	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
247
		return;
248
249
250
251
252
253
254
255
256
257
258
259
	}

	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
260
		return;
261
262
263
264
265
266
267
	}

	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
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
	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;

293
294
295
	g_free (priv->sender);
	priv->sender = NULL;

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

Bastien Nocera's avatar
Bastien Nocera committed
300
static void fprint_device_release(FprintDevice *rdev,
Daniel Drake's avatar
Daniel Drake committed
301
302
303
304
305
	DBusGMethodInvocation *context)
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	struct session_data *session = priv->session;
	GSList *elem = session->loaded_prints;
306
307
308
309
	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
310
		return;
311
	}
Daniel Drake's avatar
Daniel Drake committed
312
313
314
315
316
317
318
319
320
321
322
323
324

	/* 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
325
static void fprint_device_list_enrolled_fingers(FprintDevice *rdev,
326
	DBusGMethodInvocation *context)
Daniel Drake's avatar
Daniel Drake committed
327
328
329
330
331
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	struct fp_dscv_print **prints;
	struct fp_dscv_print **print;
	GArray *ret;
332
333
334
335
	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
336
		return;
337
	}
Daniel Drake's avatar
Daniel Drake committed
338
339
340

	prints = fp_discover_prints();
	if (!prints) {
341
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_DISCOVER_PRINTS,
Daniel Drake's avatar
Daniel Drake committed
342
			"Failed to discover prints");
343
		dbus_g_method_return_error(context, error);
Bastien Nocera's avatar
Bastien Nocera committed
344
		return;
Daniel Drake's avatar
Daniel Drake committed
345
346
347
348
349
350
351
352
353
354
	}

	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);
355

356
	dbus_g_method_return(context, ret);
Daniel Drake's avatar
Daniel Drake committed
357
358
}

Bastien Nocera's avatar
Bastien Nocera committed
359
static void fprint_device_unload_print_data(FprintDevice *rdev,
360
	guint32 print_id, DBusGMethodInvocation *context)
Daniel Drake's avatar
Daniel Drake committed
361
362
363
364
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	struct session_data *session = priv->session;
	GSList *elem = session->loaded_prints;
365
366
367
368
	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
369
		return;
370
	}
Daniel Drake's avatar
Daniel Drake committed
371
372
373

	g_message("unload print data %d for device %d", print_id, priv->id);
	if (!elem) {
374
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_LOADED_PRINT,
Daniel Drake's avatar
Daniel Drake committed
375
			"No such loaded print %d", print_id);
376
		dbus_g_method_return_error(context, error);
Bastien Nocera's avatar
Bastien Nocera committed
377
		return;
Daniel Drake's avatar
Daniel Drake committed
378
379
380
381
382
383
384
385
386
387
	}

	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);
388
		dbus_g_method_return(context);
Bastien Nocera's avatar
Bastien Nocera committed
389
		return;
Daniel Drake's avatar
Daniel Drake committed
390
391
	} while ((elem = g_slist_next(elem)) != NULL);

392
	g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_LOADED_PRINT,
Daniel Drake's avatar
Daniel Drake committed
393
		"No such loaded print %d", print_id);
394
	dbus_g_method_return_error(context, error);
Daniel Drake's avatar
Daniel Drake committed
395
396
397
398
399
400
401
402
}

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
403
	g_signal_emit(rdev, signals[SIGNAL_VERIFY_STATUS], 0, r);
404
	fp_img_free(img);
Daniel Drake's avatar
Daniel Drake committed
405
406
}

Bastien Nocera's avatar
Bastien Nocera committed
407
static void fprint_device_verify_start(FprintDevice *rdev,
408
	guint32 print_id, DBusGMethodInvocation *context)
Daniel Drake's avatar
Daniel Drake committed
409
410
411
412
413
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	struct session_data *session = priv->session;
	GSList *elem = session->loaded_prints;
	struct fp_print_data *data = NULL;
414
	GError *error = NULL;
Daniel Drake's avatar
Daniel Drake committed
415
416
	int r;

417
418
	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
Bastien Nocera's avatar
Bastien Nocera committed
419
		return;
420
421
	}

Daniel Drake's avatar
Daniel Drake committed
422
423
	g_message("start verification device %d print %d", priv->id, print_id);
	if (!elem) {
424
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_LOADED_PRINT,
Daniel Drake's avatar
Daniel Drake committed
425
			"No such loaded print %d", print_id);
426
		dbus_g_method_return_error(context, error);
Bastien Nocera's avatar
Bastien Nocera committed
427
		return;
Daniel Drake's avatar
Daniel Drake committed
428
429
430
431
432
433
434
435
436
437
438
	}
	
	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) {
439
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_LOADED_PRINT,
Daniel Drake's avatar
Daniel Drake committed
440
			"No such loaded print %d", print_id);
441
		dbus_g_method_return_error(context, error);
Bastien Nocera's avatar
Bastien Nocera committed
442
		return;
Daniel Drake's avatar
Daniel Drake committed
443
444
445
446
447
	}

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

454
	dbus_g_method_return(context);
Daniel Drake's avatar
Daniel Drake committed
455
456
457
458
459
460
461
}

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
462
static void fprint_device_verify_stop(FprintDevice *rdev,
Daniel Drake's avatar
Daniel Drake committed
463
464
465
	DBusGMethodInvocation *context)
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
466
	GError *error = NULL;
Daniel Drake's avatar
Daniel Drake committed
467
468
	int r;

469
470
	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
Bastien Nocera's avatar
Bastien Nocera committed
471
		return;
472
473
	}

Daniel Drake's avatar
Daniel Drake committed
474
475
476
477
478
479
480
481
	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
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
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);
}

Bastien Nocera's avatar
Bastien Nocera committed
498
static void fprint_device_enroll_start(FprintDevice *rdev,
499
	guint32 finger_num, DBusGMethodInvocation *context)
Daniel Drake's avatar
Daniel Drake committed
500
501
502
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
	struct session_data *session = priv->session;
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
	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) {
516
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_ENROLL_START,
Daniel Drake's avatar
Daniel Drake committed
517
			"Enroll start failed with error %d", r);
518
		dbus_g_method_return_error(context, error);
Bastien Nocera's avatar
Bastien Nocera committed
519
		return;
Daniel Drake's avatar
Daniel Drake committed
520
521
	}

522
	dbus_g_method_return(context);
Daniel Drake's avatar
Daniel Drake committed
523
524
525
526
527
528
529
}

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
530
static void fprint_device_enroll_stop(FprintDevice *rdev,
Daniel Drake's avatar
Daniel Drake committed
531
532
533
	DBusGMethodInvocation *context)
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
534
	GError *error = NULL;
Daniel Drake's avatar
Daniel Drake committed
535
536
	int r;

537
538
	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
Bastien Nocera's avatar
Bastien Nocera committed
539
		return;
540
541
	}

Daniel Drake's avatar
Daniel Drake committed
542
543
544
545
546
	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
547
		return;
Daniel Drake's avatar
Daniel Drake committed
548
549
550
	}
}

551
552
553
554
555
556
557
558
559
560
561
562
563
564
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;
}

Bastien Nocera's avatar
Bastien Nocera committed
565
static void fprint_device_list_enrolled_fingers_from_storage(FprintDevice *rdev,
566
	gchar *username, DBusGMethodInvocation *context)
567
568
{
	FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev);
569
	GError *error = NULL;
570
571
572
573
	GSList *prints;
	GSList *item;
	GArray *ret;

574
575
	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
Bastien Nocera's avatar
Bastien Nocera committed
576
		return;
577
578
	}

579
580
	prints = storages[priv->storage_type].discover_prints(priv->dev, username);
	if (!prints) {
581
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_DISCOVER_PRINTS,
582
			"Failed to discover prints");
583
		dbus_g_method_return_error(context, error);
Bastien Nocera's avatar
Bastien Nocera committed
584
		return;
585
586
587
588
589
590
591
592
593
	}

	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);
594

595
	dbus_g_method_return(context, ret);
596
597
}

Bastien Nocera's avatar
Bastien Nocera committed
598
599
static void fprint_device_load_print_data(FprintDevice *rdev,
	guint32 finger_num, DBusGMethodInvocation *context)
600
601
602
603
604
{
	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
605
	const char *username = "hadess"; //FIXME
606
	GError *error = NULL;
607
608
	int r;

609
610
	if (_fprint_device_check_claimed(rdev, context, &error) == FALSE) {
		dbus_g_method_return_error (context, error);
Bastien Nocera's avatar
Bastien Nocera committed
611
		return;
612
613
	}

614
615
616
617
	r = storages[priv->storage_type].print_data_load(priv->dev, (enum fp_finger)finger_num, 
		&data, (char *)username);

	if (r < 0) {
618
		g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_PRINT_LOAD,
619
			"Print load failed with error %d", r);
620
		dbus_g_method_return_error(context, error);
Bastien Nocera's avatar
Bastien Nocera committed
621
		return;
622
623
624
625
626
627
628
629
630
	}

	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);
631

632
	dbus_g_method_return(context, lprint->id);
633
634
}