Print discovery
Add concept of "discovered prints" and flesh out the API. A discovered print was found based on file name but has not been checked for file integrity, and of course there is no guarantee that it is usable when you try to use it later (might have been deleted, etc). The .fprint directory structure was changed - instead of using mnemonics like "rind" we use their numeric value in the fp_finger enum as the filename.
This commit is contained in:
parent
b96aade69c
commit
447b1f01b3
4 changed files with 353 additions and 95 deletions
|
@ -101,7 +101,7 @@ static void register_drivers(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct fp_driver *find_supporting_driver(struct usb_device *udev,
|
static struct fp_driver *find_supporting_driver(struct usb_device *udev,
|
||||||
unsigned long *driver_data)
|
const struct usb_id **usb_id)
|
||||||
{
|
{
|
||||||
GList *elem = registered_drivers;
|
GList *elem = registered_drivers;
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ static struct fp_driver *find_supporting_driver(struct usb_device *udev,
|
||||||
udev->descriptor.idProduct == id->product) {
|
udev->descriptor.idProduct == id->product) {
|
||||||
fp_dbg("driver %s supports USB device %04x:%04x",
|
fp_dbg("driver %s supports USB device %04x:%04x",
|
||||||
drv->name, id->vendor, id->product);
|
drv->name, id->vendor, id->product);
|
||||||
*driver_data = id->driver_data;
|
*usb_id = id;
|
||||||
return drv;
|
return drv;
|
||||||
}
|
}
|
||||||
} while (elem = g_list_next(elem));
|
} while (elem = g_list_next(elem));
|
||||||
|
@ -123,7 +123,7 @@ static struct fp_driver *find_supporting_driver(struct usb_device *udev,
|
||||||
|
|
||||||
static struct fp_dscv_dev *discover_dev(struct usb_device *udev)
|
static struct fp_dscv_dev *discover_dev(struct usb_device *udev)
|
||||||
{
|
{
|
||||||
struct usb_id *usb_id;
|
const struct usb_id *usb_id;
|
||||||
struct fp_driver *drv = find_supporting_driver(udev, &usb_id);
|
struct fp_driver *drv = find_supporting_driver(udev, &usb_id);
|
||||||
struct fp_dscv_dev *ddev;
|
struct fp_dscv_dev *ddev;
|
||||||
uint32_t devtype = 0;
|
uint32_t devtype = 0;
|
||||||
|
@ -212,6 +212,58 @@ API_EXPORTED uint32_t fp_dscv_dev_get_devtype(struct fp_dscv_dev *dev)
|
||||||
return dev->devtype;
|
return dev->devtype;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum fp_print_data_type fpi_driver_get_data_type(struct fp_driver *drv)
|
||||||
|
{
|
||||||
|
switch (drv->type) {
|
||||||
|
case DRIVER_PRIMITIVE:
|
||||||
|
return PRINT_DATA_RAW;
|
||||||
|
case DRIVER_IMAGING:
|
||||||
|
return PRINT_DATA_NBIS_MINUTIAE;
|
||||||
|
default:
|
||||||
|
fp_err("unrecognised drv type %d", drv->type);
|
||||||
|
return PRINT_DATA_RAW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORTED int fp_dscv_dev_supports_print_data(struct fp_dscv_dev *dev,
|
||||||
|
struct fp_print_data *data)
|
||||||
|
{
|
||||||
|
return fpi_print_data_compatible(dev->drv->id, dev->devtype,
|
||||||
|
fpi_driver_get_data_type(dev->drv), data->driver_id, data->devtype,
|
||||||
|
data->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORTED int fp_dscv_dev_supports_dscv_print(struct fp_dscv_dev *dev,
|
||||||
|
struct fp_dscv_print *data)
|
||||||
|
{
|
||||||
|
return fpi_print_data_compatible(dev->drv->id, dev->devtype, 0,
|
||||||
|
data->driver_id, data->devtype, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORTED struct fp_dscv_dev *fp_dscv_dev_for_print_data(struct fp_dscv_dev **devs,
|
||||||
|
struct fp_print_data *data)
|
||||||
|
{
|
||||||
|
struct fp_dscv_dev *ddev;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; ddev = devs[i]; i++)
|
||||||
|
if (fp_dscv_dev_supports_print_data(ddev, data))
|
||||||
|
return ddev;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORTED struct fp_dscv_dev *fp_dscv_dev_for_dscv_print(struct fp_dscv_dev **devs,
|
||||||
|
struct fp_dscv_print *print)
|
||||||
|
{
|
||||||
|
struct fp_dscv_dev *ddev;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; ddev = devs[i]; i++)
|
||||||
|
if (fp_dscv_dev_supports_dscv_print(ddev, print))
|
||||||
|
return ddev;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
API_EXPORTED struct fp_dev *fp_dev_open(struct fp_dscv_dev *ddev)
|
API_EXPORTED struct fp_dev *fp_dev_open(struct fp_dscv_dev *ddev)
|
||||||
{
|
{
|
||||||
struct fp_dev *dev;
|
struct fp_dev *dev;
|
||||||
|
@ -267,6 +319,21 @@ API_EXPORTED uint32_t fp_dev_get_devtype(struct fp_dev *dev)
|
||||||
return dev->devtype;
|
return dev->devtype;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
API_EXPORTED int fp_dev_supports_print_data(struct fp_dev *dev,
|
||||||
|
struct fp_print_data *data)
|
||||||
|
{
|
||||||
|
return fpi_print_data_compatible(dev->drv->id, dev->devtype,
|
||||||
|
fpi_driver_get_data_type(dev->drv), data->driver_id, data->devtype,
|
||||||
|
data->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORTED int fp_dev_supports_dscv_print(struct fp_dev *dev,
|
||||||
|
struct fp_dscv_print *data)
|
||||||
|
{
|
||||||
|
return fpi_print_data_compatible(dev->drv->id, dev->devtype,
|
||||||
|
0, data->driver_id, data->devtype, 0);
|
||||||
|
}
|
||||||
|
|
||||||
API_EXPORTED const char *fp_driver_get_name(struct fp_driver *drv)
|
API_EXPORTED const char *fp_driver_get_name(struct fp_driver *drv)
|
||||||
{
|
{
|
||||||
return drv->name;
|
return drv->name;
|
||||||
|
@ -372,7 +439,7 @@ API_EXPORTED int fp_verify_finger(struct fp_dev *dev,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fpi_print_data_compatible(enrolled_print, dev)) {
|
if (!fp_dev_supports_print_data(dev, enrolled_print)) {
|
||||||
fp_err("print is not compatible with device");
|
fp_err("print is not compatible with device");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
325
libfprint/data.c
325
libfprint/data.c
|
@ -48,38 +48,29 @@ static void storage_setup(void)
|
||||||
/* FIXME handle failure */
|
/* FIXME handle failure */
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *finger_code_to_str(enum fp_finger finger)
|
#define FP_FINGER_IS_VALID(finger) \
|
||||||
|
((finger) >= LEFT_THUMB && (finger) <= RIGHT_LITTLE)
|
||||||
|
|
||||||
|
/* for debug messages only */
|
||||||
|
static const char *finger_num_to_str(enum fp_finger finger)
|
||||||
{
|
{
|
||||||
const char *names[] = {
|
const char *names[] = {
|
||||||
[LEFT_THUMB] = "lthu",
|
[LEFT_THUMB] = "left thumb",
|
||||||
[LEFT_INDEX] = "lind",
|
[LEFT_INDEX] = "left index",
|
||||||
[LEFT_MIDDLE] = "lmid",
|
[LEFT_MIDDLE] = "left middle",
|
||||||
[LEFT_RING] = "lrin",
|
[LEFT_RING] = "left ring",
|
||||||
[LEFT_LITTLE] = "llit",
|
[LEFT_LITTLE] = "left little",
|
||||||
[RIGHT_THUMB] = "rthu",
|
[RIGHT_THUMB] = "right thumb",
|
||||||
[RIGHT_INDEX] = "rind",
|
[RIGHT_INDEX] = "right index",
|
||||||
[RIGHT_MIDDLE] = "rmid",
|
[RIGHT_MIDDLE] = "right middle",
|
||||||
[RIGHT_RING] = "rrin",
|
[RIGHT_RING] = "right ring",
|
||||||
[RIGHT_LITTLE] = "rlit",
|
[RIGHT_LITTLE] = "right little",
|
||||||
};
|
};
|
||||||
if (finger < LEFT_THUMB || finger > RIGHT_LITTLE)
|
if (!FP_FINGER_IS_VALID(finger))
|
||||||
return NULL;
|
return "UNKNOWN";
|
||||||
return names[finger];
|
return names[finger];
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum fp_print_data_type get_data_type_for_dev(struct fp_dev *dev)
|
|
||||||
{
|
|
||||||
switch (dev->drv->type) {
|
|
||||||
case DRIVER_PRIMITIVE:
|
|
||||||
return PRINT_DATA_RAW;
|
|
||||||
case DRIVER_IMAGING:
|
|
||||||
return PRINT_DATA_NBIS_MINUTIAE;
|
|
||||||
default:
|
|
||||||
fp_err("unrecognised drv type %d", dev->drv->type);
|
|
||||||
return PRINT_DATA_RAW;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct fp_print_data *print_data_new(uint16_t driver_id,
|
static struct fp_print_data *print_data_new(uint16_t driver_id,
|
||||||
uint32_t devtype, enum fp_print_data_type type, size_t length)
|
uint32_t devtype, enum fp_print_data_type type, size_t length)
|
||||||
{
|
{
|
||||||
|
@ -98,7 +89,7 @@ struct fp_print_data *fpi_print_data_new(struct fp_dev *dev, size_t length)
|
||||||
struct fp_print_data *data = g_malloc(sizeof(*data) + length);
|
struct fp_print_data *data = g_malloc(sizeof(*data) + length);
|
||||||
memset(data, 0, sizeof(*data));
|
memset(data, 0, sizeof(*data));
|
||||||
return print_data_new(dev->drv->id, dev->devtype,
|
return print_data_new(dev->drv->id, dev->devtype,
|
||||||
get_data_type_for_dev(dev), length);
|
fpi_driver_get_data_type(dev->drv), length);
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORTED size_t fp_print_data_get_data(struct fp_print_data *data,
|
API_EXPORTED size_t fp_print_data_get_data(struct fp_print_data *data,
|
||||||
|
@ -148,7 +139,7 @@ API_EXPORTED struct fp_print_data *fp_print_data_from_data(unsigned char *buf,
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *__get_path_to_storedir(uint16_t driver_id, uint32_t devtype)
|
static char *get_path_to_storedir(uint16_t driver_id, uint32_t devtype)
|
||||||
{
|
{
|
||||||
char idstr[5];
|
char idstr[5];
|
||||||
char devtypestr[9];
|
char devtypestr[9];
|
||||||
|
@ -159,53 +150,55 @@ static char *__get_path_to_storedir(uint16_t driver_id, uint32_t devtype)
|
||||||
return g_build_filename(base_store, idstr, devtypestr, NULL);
|
return g_build_filename(base_store, idstr, devtypestr, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *get_path_to_storedir(struct fp_dev *dev)
|
static char *__get_path_to_print(uint16_t driver_id, uint32_t devtype,
|
||||||
{
|
enum fp_finger finger)
|
||||||
return __get_path_to_storedir(dev->drv->id, dev->devtype);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *get_path_to_print(struct fp_dev *dev, const char *fingerstr)
|
|
||||||
{
|
{
|
||||||
char *dirpath;
|
char *dirpath;
|
||||||
char *path;
|
char *path;
|
||||||
|
char fingername[2];
|
||||||
|
|
||||||
dirpath = get_path_to_storedir(dev);
|
g_snprintf(fingername, 2, "%x", finger);
|
||||||
path = g_build_filename(dirpath, fingerstr, NULL);
|
|
||||||
|
dirpath = get_path_to_storedir(driver_id, devtype);
|
||||||
|
path = g_build_filename(dirpath, fingername, NULL);
|
||||||
g_free(dirpath);
|
g_free(dirpath);
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *get_path_to_print(struct fp_dev *dev, enum fp_finger finger)
|
||||||
|
{
|
||||||
|
return __get_path_to_print(dev->drv->id, dev->devtype, finger);
|
||||||
|
}
|
||||||
|
|
||||||
API_EXPORTED int fp_print_data_save(struct fp_print_data *data,
|
API_EXPORTED int fp_print_data_save(struct fp_print_data *data,
|
||||||
enum fp_finger finger)
|
enum fp_finger finger)
|
||||||
{
|
{
|
||||||
GError *err = NULL;
|
GError *err = NULL;
|
||||||
char *path;
|
char *path;
|
||||||
char *dirpath;
|
char *dirpath;
|
||||||
const char *fingerstr = finger_code_to_str(finger);
|
|
||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
size_t len;
|
size_t len;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (!fingerstr)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (!base_store)
|
if (!base_store)
|
||||||
storage_setup();
|
storage_setup();
|
||||||
|
|
||||||
fp_dbg("save %s print from driver %04x", fingerstr, data->driver_id);
|
fp_dbg("save %s print from driver %04x", finger_num_to_str(finger),
|
||||||
|
data->driver_id);
|
||||||
len = fp_print_data_get_data(data, &buf);
|
len = fp_print_data_get_data(data, &buf);
|
||||||
if (!len)
|
if (!len)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
dirpath = __get_path_to_storedir(data->driver_id, data->devtype);
|
path = __get_path_to_print(data->driver_id, data->devtype, finger);
|
||||||
|
dirpath = g_path_get_dirname(path);
|
||||||
r = g_mkdir_with_parents(dirpath, DIR_PERMS);
|
r = g_mkdir_with_parents(dirpath, DIR_PERMS);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
fp_err("couldn't create storage directory");
|
fp_err("couldn't create storage directory");
|
||||||
|
g_free(path);
|
||||||
g_free(dirpath);
|
g_free(dirpath);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
path = g_build_filename(dirpath, fingerstr, NULL);
|
|
||||||
fp_dbg("saving to %s", path);
|
fp_dbg("saving to %s", path);
|
||||||
g_file_set_contents(path, buf, len, &err);
|
g_file_set_contents(path, buf, len, &err);
|
||||||
free(buf);
|
free(buf);
|
||||||
|
@ -213,7 +206,7 @@ API_EXPORTED int fp_print_data_save(struct fp_print_data *data,
|
||||||
g_free(path);
|
g_free(path);
|
||||||
if (err) {
|
if (err) {
|
||||||
r = err->code;
|
r = err->code;
|
||||||
fp_err("%s save failed: %s", fingerstr, err->message);
|
fp_err("save failed: %s", err->message);
|
||||||
g_error_free(err);
|
g_error_free(err);
|
||||||
/* FIXME interpret error codes */
|
/* FIXME interpret error codes */
|
||||||
return r;
|
return r;
|
||||||
|
@ -222,65 +215,39 @@ API_EXPORTED int fp_print_data_save(struct fp_print_data *data,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean fpi_print_data_compatible(struct fp_print_data *data,
|
gboolean fpi_print_data_compatible(uint16_t driver_id1, uint32_t devtype1,
|
||||||
struct fp_dev *dev)
|
enum fp_print_data_type type1, uint16_t driver_id2, uint32_t devtype2,
|
||||||
|
enum fp_print_data_type type2)
|
||||||
{
|
{
|
||||||
struct fp_driver *drv = dev->drv;
|
if (driver_id1 != driver_id2) {
|
||||||
|
fp_dbg("driver ID mismatch: %02x vs %02x", driver_id1, driver_id2);
|
||||||
if (drv->id != data->driver_id) {
|
|
||||||
fp_dbg("driver name mismatch: %02x vs %02x", drv->id, data->driver_id);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->devtype != data->devtype) {
|
if (devtype1 != devtype2) {
|
||||||
fp_dbg("devtype mismatch: %04x vs %04x", dev->devtype, data->devtype);
|
fp_dbg("devtype mismatch: %04x vs %04x", devtype1, devtype2);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (data->type) {
|
if (type1 != type2) {
|
||||||
case PRINT_DATA_RAW:
|
fp_dbg("type mismatch: %d vs %d", type1, type2);
|
||||||
if (drv->type != DRIVER_PRIMITIVE) {
|
|
||||||
fp_dbg("raw data vs primitive driver mismatch");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PRINT_DATA_NBIS_MINUTIAE:
|
|
||||||
if (drv->type != DRIVER_IMAGING) {
|
|
||||||
fp_dbg("minutiae data vs imaging driver mismatch");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
fp_err("unrecognised data type %d", data->type);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORTED int fp_print_data_load(struct fp_dev *dev,
|
static int load_from_file(char *path, struct fp_print_data **data)
|
||||||
enum fp_finger finger, struct fp_print_data **data)
|
|
||||||
{
|
{
|
||||||
const char *fingerstr = finger_code_to_str(finger);
|
|
||||||
gchar *path;
|
|
||||||
gsize length;
|
gsize length;
|
||||||
gchar *contents;
|
gchar *contents;
|
||||||
GError *err = NULL;
|
GError *err = NULL;
|
||||||
struct fp_print_data *fdata;
|
|
||||||
|
|
||||||
if (!fingerstr)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (!base_store)
|
|
||||||
storage_setup();
|
|
||||||
|
|
||||||
path = get_path_to_print(dev, fingerstr);
|
|
||||||
fp_dbg("from %s", path);
|
fp_dbg("from %s", path);
|
||||||
g_file_get_contents(path, &contents, &length, &err);
|
g_file_get_contents(path, &contents, &length, &err);
|
||||||
g_free(path);
|
|
||||||
if (err) {
|
if (err) {
|
||||||
int r = err->code;
|
int r = err->code;
|
||||||
fp_err("%s load failed: %s", fingerstr, err->message);
|
fp_err("%s load failed: %s", path, err->message);
|
||||||
g_error_free(err);
|
g_error_free(err);
|
||||||
/* FIXME interpret more error codes */
|
/* FIXME interpret more error codes */
|
||||||
if (r == G_FILE_ERROR_NOENT)
|
if (r == G_FILE_ERROR_NOENT)
|
||||||
|
@ -289,11 +256,30 @@ API_EXPORTED int fp_print_data_load(struct fp_dev *dev,
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
fdata = fp_print_data_from_data(contents, length);
|
*data = fp_print_data_from_data(contents, length);
|
||||||
g_free(contents);
|
g_free(contents);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!fpi_print_data_compatible(fdata, dev)) {
|
API_EXPORTED int fp_print_data_load(struct fp_dev *dev,
|
||||||
|
enum fp_finger finger, struct fp_print_data **data)
|
||||||
|
{
|
||||||
|
gchar *path;
|
||||||
|
struct fp_print_data *fdata;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (!base_store)
|
||||||
|
storage_setup();
|
||||||
|
|
||||||
|
path = get_path_to_print(dev, finger);
|
||||||
|
r = load_from_file(path, &fdata);
|
||||||
|
g_free(path);
|
||||||
|
if (r)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (!fp_dev_supports_print_data(dev, fdata)) {
|
||||||
fp_err("print data is not compatible!");
|
fp_err("print data is not compatible!");
|
||||||
|
fp_print_data_free(fdata);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,6 +287,12 @@ API_EXPORTED int fp_print_data_load(struct fp_dev *dev,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
API_EXPORTED int fp_print_data_from_dscv_print(struct fp_dscv_print *print,
|
||||||
|
struct fp_print_data **data)
|
||||||
|
{
|
||||||
|
return load_from_file(print->path, data);
|
||||||
|
}
|
||||||
|
|
||||||
API_EXPORTED void fp_print_data_free(struct fp_print_data *data)
|
API_EXPORTED void fp_print_data_free(struct fp_print_data *data)
|
||||||
{
|
{
|
||||||
g_free(data);
|
g_free(data);
|
||||||
|
@ -315,3 +307,170 @@ API_EXPORTED uint32_t fp_print_data_get_devtype(struct fp_print_data *data)
|
||||||
{
|
{
|
||||||
return data->devtype;
|
return data->devtype;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GSList *scan_dev_store_dir(char *devpath, uint16_t driver_id,
|
||||||
|
uint32_t devtype, GSList *list)
|
||||||
|
{
|
||||||
|
GError *err = NULL;
|
||||||
|
const gchar *ent;
|
||||||
|
struct fp_dscv_print *print;
|
||||||
|
|
||||||
|
GDir *dir = g_dir_open(devpath, 0, &err);
|
||||||
|
if (!dir) {
|
||||||
|
fp_err("opendir %s failed: %s", devpath, err->message);
|
||||||
|
g_error_free(err);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (ent = g_dir_read_name(dir)) {
|
||||||
|
/* ent is an 1 hex character fp_finger code */
|
||||||
|
guint64 val;
|
||||||
|
enum fp_finger finger;
|
||||||
|
gchar *endptr;
|
||||||
|
|
||||||
|
if (*ent == 0 || strlen(ent) != 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
val = g_ascii_strtoull(ent, &endptr, 16);
|
||||||
|
if (endptr == ent || !FP_FINGER_IS_VALID(val)) {
|
||||||
|
fp_dbg("skipping print file %s", ent);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
finger = (enum fp_finger) val;
|
||||||
|
print = g_malloc(sizeof(*print));
|
||||||
|
print->driver_id = driver_id;
|
||||||
|
print->devtype = devtype;
|
||||||
|
print->path = g_build_filename(devpath, ent, NULL);
|
||||||
|
print->finger = finger;
|
||||||
|
list = g_slist_prepend(list, print);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_dir_close(dir);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GSList *scan_driver_store_dir(char *drvpath, uint16_t driver_id,
|
||||||
|
GSList *list)
|
||||||
|
{
|
||||||
|
GError *err = NULL;
|
||||||
|
const gchar *ent;
|
||||||
|
|
||||||
|
GDir *dir = g_dir_open(drvpath, 0, &err);
|
||||||
|
if (!dir) {
|
||||||
|
fp_err("opendir %s failed: %s", drvpath, err->message);
|
||||||
|
g_error_free(err);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (ent = g_dir_read_name(dir)) {
|
||||||
|
/* ent is an 8 hex character devtype */
|
||||||
|
guint64 val;
|
||||||
|
uint32_t devtype;
|
||||||
|
gchar *endptr;
|
||||||
|
gchar *path;
|
||||||
|
|
||||||
|
if (*ent == 0 || strlen(ent) != 8)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
val = g_ascii_strtoull(ent, &endptr, 16);
|
||||||
|
if (endptr == ent) {
|
||||||
|
fp_dbg("skipping devtype %s", ent);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
devtype = (uint32_t) val;
|
||||||
|
path = g_build_filename(drvpath, ent, NULL);
|
||||||
|
list = scan_dev_store_dir(path, driver_id, devtype, list);
|
||||||
|
g_free(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_dir_close(dir);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORTED struct fp_dscv_print **fp_discover_prints(void)
|
||||||
|
{
|
||||||
|
GDir *dir;
|
||||||
|
const gchar *ent;
|
||||||
|
GError *err = NULL;
|
||||||
|
GSList *tmplist = NULL;
|
||||||
|
GSList *elem;
|
||||||
|
unsigned int tmplist_len;
|
||||||
|
struct fp_dscv_print **list;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (!base_store)
|
||||||
|
storage_setup();
|
||||||
|
|
||||||
|
dir = g_dir_open(base_store, 0, &err);
|
||||||
|
if (!dir) {
|
||||||
|
fp_err("opendir %s failed: %s", base_store, err->message);
|
||||||
|
g_error_free(err);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (ent = g_dir_read_name(dir)) {
|
||||||
|
/* ent is a 4 hex digit driver_id */
|
||||||
|
gchar *endptr;
|
||||||
|
gchar *path;
|
||||||
|
guint64 val;
|
||||||
|
uint16_t driver_id;
|
||||||
|
|
||||||
|
if (*ent == 0 || strlen(ent) != 4)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
val = g_ascii_strtoull(ent, &endptr, 16);
|
||||||
|
if (endptr == ent) {
|
||||||
|
fp_dbg("skipping drv id %s", ent);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
driver_id = (uint16_t) val;
|
||||||
|
path = g_build_filename(base_store, ent, NULL);
|
||||||
|
tmplist = scan_driver_store_dir(path, driver_id, tmplist);
|
||||||
|
g_free(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_dir_close(dir);
|
||||||
|
tmplist_len = g_slist_length(tmplist);
|
||||||
|
list = g_malloc(sizeof(*list) * (tmplist_len + 1));
|
||||||
|
elem = tmplist;
|
||||||
|
for (i = 0; i < tmplist_len; i++, elem = g_slist_next(elem))
|
||||||
|
list[i] = elem->data;
|
||||||
|
list[tmplist_len] = NULL; /* NULL-terminate */
|
||||||
|
|
||||||
|
g_slist_free(tmplist);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORTED void fp_dscv_prints_free(struct fp_dscv_print **prints)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct fp_dscv_print *print;
|
||||||
|
|
||||||
|
if (!prints)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; print = prints[i]; i++) {
|
||||||
|
if (print)
|
||||||
|
g_free(print->path);
|
||||||
|
g_free(print);
|
||||||
|
}
|
||||||
|
g_free(prints);
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORTED uint16_t fp_dscv_print_get_driver_id(struct fp_dscv_print *print)
|
||||||
|
{
|
||||||
|
return print->driver_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORTED uint32_t fp_dscv_print_get_devtype(struct fp_dscv_print *print)
|
||||||
|
{
|
||||||
|
return print->devtype;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORTED enum fp_finger fp_dscv_print_get_finger(struct fp_dscv_print *print)
|
||||||
|
{
|
||||||
|
return print->finger;
|
||||||
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ struct fp_driver {
|
||||||
void *priv;
|
void *priv;
|
||||||
|
|
||||||
/* Device operations */
|
/* Device operations */
|
||||||
int (*discover)(struct usb_id *usb_id, uint32_t *devtype);
|
int (*discover)(const struct usb_id *usb_id, uint32_t *devtype);
|
||||||
int (*init)(struct fp_dev *dev, unsigned long driver_data);
|
int (*init)(struct fp_dev *dev, unsigned long driver_data);
|
||||||
void (*exit)(struct fp_dev *dev);
|
void (*exit)(struct fp_dev *dev);
|
||||||
int (*enroll)(struct fp_dev *dev, gboolean initial, int stage,
|
int (*enroll)(struct fp_dev *dev, gboolean initial, int stage,
|
||||||
|
@ -111,6 +111,8 @@ struct fp_driver {
|
||||||
int (*verify)(struct fp_dev *dev, struct fp_print_data *data);
|
int (*verify)(struct fp_dev *dev, struct fp_print_data *data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum fp_print_data_type fpi_driver_get_data_type(struct fp_driver *drv);
|
||||||
|
|
||||||
/* flags for fp_img_driver.flags */
|
/* flags for fp_img_driver.flags */
|
||||||
#define FP_IMGDRV_SUPPORTS_UNCONDITIONAL_CAPTURE (1 << 0)
|
#define FP_IMGDRV_SUPPORTS_UNCONDITIONAL_CAPTURE (1 << 0)
|
||||||
|
|
||||||
|
@ -145,6 +147,13 @@ struct fp_dscv_dev {
|
||||||
uint32_t devtype;
|
uint32_t devtype;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct fp_dscv_print {
|
||||||
|
uint16_t driver_id;
|
||||||
|
uint32_t devtype;
|
||||||
|
enum fp_finger finger;
|
||||||
|
char *path;
|
||||||
|
};
|
||||||
|
|
||||||
enum fp_print_data_type {
|
enum fp_print_data_type {
|
||||||
PRINT_DATA_RAW = 0, /* memset-imposed default */
|
PRINT_DATA_RAW = 0, /* memset-imposed default */
|
||||||
PRINT_DATA_NBIS_MINUTIAE,
|
PRINT_DATA_NBIS_MINUTIAE,
|
||||||
|
@ -167,8 +176,9 @@ struct fpi_print_data_fp1 {
|
||||||
} __attribute__((__packed__));
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
struct fp_print_data *fpi_print_data_new(struct fp_dev *dev, size_t length);
|
struct fp_print_data *fpi_print_data_new(struct fp_dev *dev, size_t length);
|
||||||
gboolean fpi_print_data_compatible(struct fp_print_data *data,
|
gboolean fpi_print_data_compatible(uint16_t driver_id1, uint32_t devtype1,
|
||||||
struct fp_dev *dev);
|
enum fp_print_data_type type1, uint16_t driver_id2, uint32_t devtype2,
|
||||||
|
enum fp_print_data_type type2);
|
||||||
|
|
||||||
/* bit values for fp_img.flags */
|
/* bit values for fp_img.flags */
|
||||||
#define FP_IMG_V_FLIPPED (1<<0)
|
#define FP_IMG_V_FLIPPED (1<<0)
|
||||||
|
|
|
@ -20,8 +20,11 @@
|
||||||
#ifndef __FPRINT_H__
|
#ifndef __FPRINT_H__
|
||||||
#define __FPRINT_H__
|
#define __FPRINT_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
/* structs that applications are not allowed to peek into */
|
/* structs that applications are not allowed to peek into */
|
||||||
struct fp_dscv_dev;
|
struct fp_dscv_dev;
|
||||||
|
struct fp_dscv_print;
|
||||||
struct fp_dev;
|
struct fp_dev;
|
||||||
struct fp_driver;
|
struct fp_driver;
|
||||||
struct fp_print_data;
|
struct fp_print_data;
|
||||||
|
@ -41,17 +44,37 @@ enum fp_finger {
|
||||||
RIGHT_LITTLE,
|
RIGHT_LITTLE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Drivers */
|
||||||
|
const char *fp_driver_get_name(struct fp_driver *drv);
|
||||||
|
const char *fp_driver_get_full_name(struct fp_driver *drv);
|
||||||
|
uint16_t fp_driver_get_driver_id(struct fp_driver *drv);
|
||||||
|
|
||||||
/* Device discovery */
|
/* Device discovery */
|
||||||
struct fp_dscv_dev **fp_discover_devs(void);
|
struct fp_dscv_dev **fp_discover_devs(void);
|
||||||
void fp_dscv_devs_free(struct fp_dscv_dev **devs);
|
void fp_dscv_devs_free(struct fp_dscv_dev **devs);
|
||||||
struct fp_driver *fp_dscv_dev_get_driver(struct fp_dscv_dev *dev);
|
struct fp_driver *fp_dscv_dev_get_driver(struct fp_dscv_dev *dev);
|
||||||
uint32_t fp_dscv_dev_get_devtype(struct fp_dscv_dev *dev);
|
uint32_t fp_dscv_dev_get_devtype(struct fp_dscv_dev *dev);
|
||||||
|
int fp_dscv_dev_supports_print_data(struct fp_dscv_dev *dev,
|
||||||
|
struct fp_print_data *print);
|
||||||
|
int fp_dscv_dev_supports_dscv_print(struct fp_dscv_dev *dev,
|
||||||
|
struct fp_dscv_print *print);
|
||||||
|
struct fp_dscv_dev *fp_dscv_dev_for_print_data(struct fp_dscv_dev **devs,
|
||||||
|
struct fp_print_data *print);
|
||||||
|
struct fp_dscv_dev *fp_dscv_dev_for_dscv_print(struct fp_dscv_dev **devs,
|
||||||
|
struct fp_dscv_print *print);
|
||||||
|
|
||||||
static inline uint16_t fp_dscv_dev_get_driver_id(struct fp_dscv_dev *dev)
|
static inline uint16_t fp_dscv_dev_get_driver_id(struct fp_dscv_dev *dev)
|
||||||
{
|
{
|
||||||
return fp_driver_get_driver_id(fp_dscv_dev_get_driver(dev));
|
return fp_driver_get_driver_id(fp_dscv_dev_get_driver(dev));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Print discovery */
|
||||||
|
struct fp_dscv_print **fp_discover_prints(void);
|
||||||
|
void fp_dscv_prints_free(struct fp_dscv_print **prints);
|
||||||
|
uint16_t fp_dscv_print_get_driver_id(struct fp_dscv_print *print);
|
||||||
|
uint32_t fp_dscv_print_get_devtype(struct fp_dscv_print *print);
|
||||||
|
enum fp_finger fp_dscv_print_get_finger(struct fp_dscv_print *print);
|
||||||
|
|
||||||
/* Device handling */
|
/* Device handling */
|
||||||
struct fp_dev *fp_dev_open(struct fp_dscv_dev *ddev);
|
struct fp_dev *fp_dev_open(struct fp_dscv_dev *ddev);
|
||||||
void fp_dev_close(struct fp_dev *dev);
|
void fp_dev_close(struct fp_dev *dev);
|
||||||
|
@ -59,11 +82,8 @@ struct fp_driver *fp_dev_get_driver(struct fp_dev *dev);
|
||||||
int fp_dev_get_nr_enroll_stages(struct fp_dev *dev);
|
int fp_dev_get_nr_enroll_stages(struct fp_dev *dev);
|
||||||
struct fp_img_dev *fp_dev_to_img_dev(struct fp_dev *dev);
|
struct fp_img_dev *fp_dev_to_img_dev(struct fp_dev *dev);
|
||||||
uint32_t fp_dev_get_devtype(struct fp_dev *dev);
|
uint32_t fp_dev_get_devtype(struct fp_dev *dev);
|
||||||
|
int fp_dev_supports_print_data(struct fp_dev *dev, struct fp_print_data *data);
|
||||||
/* Drivers */
|
int fp_dev_supports_dscv_print(struct fp_dev *dev, struct fp_dscv_print *print);
|
||||||
const char *fp_driver_get_name(struct fp_driver *drv);
|
|
||||||
const char *fp_driver_get_full_name(struct fp_driver *drv);
|
|
||||||
uint16_t fp_driver_get_driver_id(struct fp_driver *drv);
|
|
||||||
|
|
||||||
/* Enrollment */
|
/* Enrollment */
|
||||||
enum fp_enroll_result {
|
enum fp_enroll_result {
|
||||||
|
@ -93,6 +113,8 @@ int fp_verify_finger(struct fp_dev *dev, struct fp_print_data *enrolled_print);
|
||||||
/* Data handling */
|
/* Data handling */
|
||||||
int fp_print_data_load(struct fp_dev *dev, enum fp_finger finger,
|
int fp_print_data_load(struct fp_dev *dev, enum fp_finger finger,
|
||||||
struct fp_print_data **data);
|
struct fp_print_data **data);
|
||||||
|
int fp_print_data_from_dscv_print(struct fp_dscv_print *print,
|
||||||
|
struct fp_print_data **data);
|
||||||
int fp_print_data_save(struct fp_print_data *data, enum fp_finger finger);
|
int fp_print_data_save(struct fp_print_data *data, enum fp_finger finger);
|
||||||
void fp_print_data_free(struct fp_print_data *data);
|
void fp_print_data_free(struct fp_print_data *data);
|
||||||
size_t fp_print_data_get_data(struct fp_print_data *data, unsigned char **ret);
|
size_t fp_print_data_get_data(struct fp_print_data *data, unsigned char **ret);
|
||||||
|
|
Loading…
Reference in a new issue