enroll.c 6.23 KB
Newer Older
1
2
/*
 * Example fingerprint enrollment program
Bastien Nocera's avatar
Bastien Nocera committed
3
 * Enrolls your chosen finger and saves the print to disk
4
 * Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
5
 * Copyright (C) 2019 Marco Trevisan <marco.trevisan@canonical.com>
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

22
23
#define FP_COMPONENT "example-enroll"

24
25
#include <stdio.h>
#include <libfprint/fprint.h>
26
#include <glib-unix.h>
27

28
#include "storage.h"
29
#include "utilities.h"
30

31
32
typedef struct _EnrollData
{
33
34
35
36
37
  GMainLoop    *loop;
  GCancellable *cancellable;
  unsigned int  sigint_handler;
  FpFinger      finger;
  int           ret_value;
38
39
40
41
42
} EnrollData;

static void
enroll_data_free (EnrollData *enroll_data)
{
43
44
  g_clear_handle_id (&enroll_data->sigint_handler, g_source_remove);
  g_clear_object (&enroll_data->cancellable);
45
46
  g_main_loop_unref (enroll_data->loop);
  g_free (enroll_data);
47
48
49
50
}
G_DEFINE_AUTOPTR_CLEANUP_FUNC (EnrollData, enroll_data_free)

static void
51
52
53
on_device_closed (FpDevice *dev, GAsyncResult *res, void *user_data)
{
  EnrollData *enroll_data = user_data;
54

55
  g_autoptr(GError) error = NULL;
56

57
  fp_device_close_finish (dev, res, &error);
58

59
60
61
62
  if (error)
    g_warning ("Failed closing device %s\n", error->message);

  g_main_loop_quit (enroll_data->loop);
63
}
64

65
static void
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
on_enroll_completed (FpDevice *dev, GAsyncResult *res, void *user_data)
{
  EnrollData *enroll_data = user_data;

  g_autoptr(FpPrint) print = NULL;
  g_autoptr(GError) error = NULL;

  print = fp_device_enroll_finish (dev, res, &error);

  if (!error)
    {
      enroll_data->ret_value = EXIT_SUCCESS;

      if (!fp_device_has_storage (dev))
        {
          g_debug ("Device has not storage, saving locally");
82
          int r = print_data_save (print, enroll_data->finger);
83
84
85
86
87
88
89
90
91
92
93
94
95
96
          if (r < 0)
            {
              g_warning ("Data save failed, code %d", r);
              enroll_data->ret_value = EXIT_FAILURE;
            }
        }
    }
  else
    {
      g_warning ("Enroll failed with error %s\n", error->message);
    }

  fp_device_close (dev, NULL, (GAsyncReadyCallback) on_device_closed,
                   enroll_data);
97
98
99
100
}

static void
on_enroll_progress (FpDevice *device,
101
102
103
104
                    gint      completed_stages,
                    FpPrint  *print,
                    gpointer  user_data,
                    GError   *error)
105
{
106
107
108
109
110
111
112
113
114
  if (error)
    {
      g_warning ("Enroll stage %d of %d failed with error %s",
                 completed_stages,
                 fp_device_get_nr_enroll_stages (device),
                 error->message);
      return;
    }

115
  if (print && fp_print_get_image (print) &&
116
117
118
119
120
      print_image_save (print, "enrolled.pgm"))
    printf ("Wrote scanned image to enrolled.pgm\n");

  printf ("Enroll stage %d of %d passed. Yay!\n", completed_stages,
          fp_device_get_nr_enroll_stages (device));
121
122
123
124
125
}

static void
on_device_opened (FpDevice *dev, GAsyncResult *res, void *user_data)
{
126
127
128
129
130
131
132
133
134
135
136
137
138
  EnrollData *enroll_data = user_data;
  FpPrint *print_template;

  g_autoptr(GError) error = NULL;

  if (!fp_device_open_finish (dev, res, &error))
    {
      g_warning ("Failed to open device: %s", error->message);
      g_main_loop_quit (enroll_data->loop);
      return;
    }

  printf ("Opened device. It's now time to enroll your finger.\n\n");
139
140
141
  printf ("You will need to successfully scan your %s finger %d times to "
          "complete the process.\n\n", finger_to_string (enroll_data->finger),
          fp_device_get_nr_enroll_stages (dev));
142
143
  printf ("Scan your finger now.\n");

144
  print_template = print_create_template (dev, enroll_data->finger);
145
146
147
  fp_device_enroll (dev, print_template, enroll_data->cancellable,
                    on_enroll_progress, NULL, NULL,
                    (GAsyncReadyCallback) on_enroll_completed,
148
                    enroll_data);
149
150
}

151
152
153
154
155
156
157
158
159
160
static gboolean
sigint_cb (void *user_data)
{
  EnrollData *enroll_data = user_data;

  g_cancellable_cancel (enroll_data->cancellable);

  return G_SOURCE_CONTINUE;
}

161
162
int
main (void)
163
{
164
165
166
167
  g_autoptr(FpContext) ctx = NULL;
  g_autoptr(EnrollData) enroll_data = NULL;
  GPtrArray *devices;
  FpDevice *dev;
168
  FpFinger finger;
169

170
171
172
173
  g_print ("This program will enroll the selected finger, unconditionally "
           "overwriting any print for the same finger that was enrolled "
           "previously. If you want to continue, press enter, otherwise hit "
           "Ctrl+C\n");
174
  getchar ();
175

176
177
178
179
180
181
182
183
184
  g_print ("Choose the finger to enroll:\n");
  finger = finger_chooser ();

  if (finger == FP_FINGER_UNKNOWN)
    {
      g_warning ("Unknown finger selected");
      return EXIT_FAILURE;
    }

185
  setenv ("G_MESSAGES_DEBUG", "all", 0);
186

187
  ctx = fp_context_new ();
188

189
190
191
192
193
194
  devices = fp_context_get_devices (ctx);
  if (!devices)
    {
      g_warning ("Impossible to get devices");
      return EXIT_FAILURE;
    }
195

196
197
198
199
200
201
  dev = discover_device (devices);
  if (!dev)
    {
      g_warning ("No devices detected.");
      return EXIT_FAILURE;
    }
202

203
  enroll_data = g_new0 (EnrollData, 1);
204
  enroll_data->finger = finger;
205
206
  enroll_data->ret_value = EXIT_FAILURE;
  enroll_data->loop = g_main_loop_new (NULL, FALSE);
207
208
209
210
211
212
213
214
215
  enroll_data->cancellable = g_cancellable_new ();
  enroll_data->sigint_handler = g_unix_signal_add_full (G_PRIORITY_HIGH,
                                                        SIGINT,
                                                        sigint_cb,
                                                        enroll_data,
                                                        NULL);

  fp_device_open (dev, enroll_data->cancellable,
                  (GAsyncReadyCallback) on_device_opened,
216
                  enroll_data);
217

218
  g_main_loop_run (enroll_data->loop);
219

220
  return enroll_data->ret_value;
221
}