diff --git a/.gitignore b/.gitignore index 46b26f7..faf3f9f 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,8 @@ config.log config.status .deps client-bindings.h -server-bindings.h +*-dbus-glue.h demo *.o fprintd +*.swp diff --git a/examples/Makefile.am b/examples/Makefile.am index 982616d..061a9cd 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -1,4 +1,4 @@ -BUILT_SOURCES = client-bindings.h +BUILT_SOURCES = manager-dbus-glue.h device-dbus-glue.h noinst_HEADERS = $(BUILT_SOURCES) CLEANFILES = $(BUILT_SOURCES) @@ -8,7 +8,9 @@ demo_SOURCES = demo.c demo_CFLAGS = $(AM_CFLAGS) $(DBUS_GLIB_CFLAGS) demo_LDADD = $(DBUS_GLIB_LIBS) -client-bindings.h: ../src/fprintd.xml - dbus-binding-tool --prefix=fprint --mode=glib-client $< --output=$@ +manager-dbus-glue.h: ../src/manager.xml + dbus-binding-tool --prefix=fprint_manager --mode=glib-client $< --output=$@ +device-dbus-glue.h: ../src/device.xml + dbus-binding-tool --prefix=fprint_device --mode=glib-client $< --output=$@ diff --git a/examples/demo.c b/examples/demo.c index 560717f..3729150 100644 --- a/examples/demo.c +++ b/examples/demo.c @@ -19,9 +19,10 @@ #include #include -#include "client-bindings.h" +#include "manager-dbus-glue.h" +#include "device-dbus-glue.h" -static DBusGProxy *proxy = NULL; +static DBusGProxy *manager = NULL; static DBusGConnection *connection = NULL; enum fp_verify_result { @@ -94,7 +95,7 @@ static const char *fingerstr(guint32 fingernum) } } -static void create_proxy(void) +static void create_manager(void) { GError *error = NULL; @@ -102,49 +103,51 @@ static void create_proxy(void) if (connection == NULL) g_error("Failed to connect to session bus: %s", error->message); - proxy = dbus_g_proxy_new_for_name_owner(connection, - "net.reactivated.Fprint", "/net/reactivated/Fprint", - "net.reactivated.Fprint", &error); - if (proxy == NULL) + manager = dbus_g_proxy_new_for_name_owner(connection, + "net.reactivated.Fprint", "/net/reactivated/Fprint/Manager", + "net.reactivated.Fprint.Manager", &error); + if (manager == NULL) g_error("Failed to create proxy: %s", error->message); } -static guint32 open_device(void) +static DBusGProxy *open_device(void) { GError *error = NULL; - GArray *device_ids; - char **drvnames; - char **fullnames; + GPtrArray *devices; + gchar *path; + DBusGProxy *dev; guint i; - guint32 device_id; - if (!net_reactivated_Fprint_list_devices(proxy, &device_ids, &drvnames, - &fullnames, &error)) + if (!net_reactivated_Fprint_Manager_get_devices(manager, &devices, &error)) g_error("list_devices failed: %s", error->message); - if (device_ids->len == 0) { + if (devices->len == 0) { g_print("No devices found\n"); exit(1); } - g_print("found %d devices\n", device_ids->len); - for (i = 0; i < device_ids->len; i++) { - g_print("Device #%d: %s (%s)\n", g_array_index(device_ids, guint32, i), - fullnames[i], drvnames[i]); + g_print("found %d devices\n", devices->len); + for (i = 0; i < devices->len; i++) { + path = g_ptr_array_index(devices, i); + g_print("Device at %s\n", path); } - device_id = g_array_index(device_ids, int, 0); - g_strfreev(drvnames); - g_strfreev(fullnames); - g_array_free(device_ids, TRUE); + path = g_ptr_array_index(devices, 0); + g_print("Using device %s\n", path); - g_print("using device #%d\n", device_id); - if (!net_reactivated_Fprint_claim_device(proxy, device_id, &error)) + /* FIXME use for_name_owner?? */ + dev = dbus_g_proxy_new_for_name(connection, "net.reactivated.Fprint", + path, "net.reactivated.Fprint.Device"); + + g_ptr_array_foreach(devices, (GFunc) g_free, NULL); + g_ptr_array_free(devices, TRUE); + + if (!net_reactivated_Fprint_Device_claim(dev, &error)) g_error("failed to claim device: %s", error->message); - return device_id; + return dev; } -static guint32 find_finger(guint32 device_id) +static guint32 find_finger(DBusGProxy *dev) { GError *error = NULL; GArray *fingers; @@ -152,7 +155,7 @@ static guint32 find_finger(guint32 device_id) int fingernum; guint32 print_id; - if (!net_reactivated_Fprint_list_enrolled_fingers(proxy, 0, &fingers, &error)) + if (!net_reactivated_Fprint_Device_list_enrolled_fingers(dev, &fingers, &error)) g_error("ListEnrolledFingers failed: %s", error->message); if (fingers->len == 0) { @@ -170,64 +173,64 @@ static guint32 find_finger(guint32 device_id) g_array_free(fingers, TRUE); g_print("Verifying: %s\n", fingerstr(fingernum)); - if (!net_reactivated_Fprint_load_print_data(proxy, device_id, fingernum, &print_id, &error)) + if (!net_reactivated_Fprint_Device_load_print_data(dev, fingernum, &print_id, &error)) g_error("LoadPrintData failed: %s", error->message); return print_id; } -static int do_verify(guint32 device_id, guint32 print_id) +static int do_verify(DBusGProxy *dev, guint32 print_id) { GError *error; gboolean more_results; int result; - if (!net_reactivated_Fprint_verify_start(proxy, device_id, print_id, &error)) + if (!net_reactivated_Fprint_Device_verify_start(dev, print_id, &error)) g_error("VerifyStart failed: %s", error->message); do { - if (!net_reactivated_Fprint_get_verify_result(proxy, device_id, &result, &more_results, &error)) + if (!net_reactivated_Fprint_Device_get_verify_result(dev, &result, &more_results, &error)) g_error("GetVerifyResult failed: %s", error->message); g_print("Verify result: %s (%d)\n", verify_result_str(result), result); } while (result != VERIFY_NO_MATCH && result != VERIFY_MATCH); - if (!net_reactivated_Fprint_verify_stop(proxy, device_id, &error)) + if (!net_reactivated_Fprint_Device_verify_stop(dev, &error)) g_error("VerifyStop failed: %s", error->message); return result; } -static void unload_print(guint32 device_id, guint32 print_id) +static void unload_print(DBusGProxy *dev, guint32 print_id) { GError *error = NULL; - if (!net_reactivated_Fprint_unload_print_data(proxy, device_id, print_id, &error)) + if (!net_reactivated_Fprint_Device_unload_print_data(dev, print_id, &error)) g_error("UnloadPrint failed: %s", error->message); } -static void release_device(guint32 device_id) +static void release_device(DBusGProxy *dev) { GError *error = NULL; - if (!net_reactivated_Fprint_release_device(proxy, device_id, &error)) + if (!net_reactivated_Fprint_Device_release(dev, &error)) g_error("ReleaseDevice failed: %s", error->message); } int main(int argc, char **argv) { GMainLoop *loop; - guint32 device_id; + DBusGProxy *dev; guint32 print_id; int verify_result; g_type_init(); loop = g_main_loop_new(NULL, FALSE); - create_proxy(); + create_manager(); - device_id = open_device(); - print_id = find_finger(device_id); - verify_result = do_verify(device_id, print_id); - unload_print(device_id, print_id); - release_device(device_id); + dev = open_device(); + print_id = find_finger(dev); + verify_result = do_verify(dev, print_id); + unload_print(dev, print_id); + release_device(dev); return 0; } diff --git a/src/Makefile.am b/src/Makefile.am index 273da6c..16658ca 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,4 @@ -BUILT_SOURCES = server-bindings.h +BUILT_SOURCES = manager-dbus-glue.h device-dbus-glue.h noinst_HEADERS = $(BUILT_SOURCES) CLEANFILES = $(BUILT_SOURCES) @@ -6,10 +6,13 @@ EXTRA_DIST = fprintd.xml bin_PROGRAMS = fprintd -fprintd_SOURCES = main.c +fprintd_SOURCES = main.c manager.c device.c fprintd_LDADD = $(GLIB_LIBS) $(DBUS_GLIB_LIBS) $(FPRINT_LIBS) fprintd_CFLAGS = $(AM_CFLAGS) $(GLIB_CFLAGS) $(DBUS_GLIB_CFLAGS) $(FPRINT_CFLAGS) -server-bindings.h: fprintd.xml - dbus-binding-tool --prefix=fprint --mode=glib-server $< --output=$@ +manager-dbus-glue.h: manager.xml + dbus-binding-tool --prefix=fprint_manager --mode=glib-server $< --output=$@ + +device-dbus-glue.h: device.xml + dbus-binding-tool --prefix=fprint_device --mode=glib-server $< --output=$@ diff --git a/src/device.c b/src/device.c new file mode 100644 index 0000000..2e37456 --- /dev/null +++ b/src/device.c @@ -0,0 +1,485 @@ +/* + * /net/reactivated/Fprint/Device/foo object implementation + * Copyright (C) 2008 Daniel Drake + * + * 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. + */ + +#include +#include +#include +#include + +#include "fprintd.h" + +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, + GArray **fingers, GError **error); +static gboolean fprint_device_load_print_data(FprintDevice *rdev, + guint32 finger_num, guint32 *print_id, GError **error); +static gboolean fprint_device_unload_print_data(FprintDevice *rdev, + guint32 print_id, GError **error); +static gboolean fprint_device_verify_start(FprintDevice *rdev, + guint32 print_id, GError **error); +static gboolean fprint_device_verify_stop(FprintDevice *rdev, + DBusGMethodInvocation *context); +static gboolean fprint_device_get_verify_result(FprintDevice *rdev, + DBusGMethodInvocation *context); + +#include "device-dbus-glue.h" + +struct session_data { + /* a list of pending verify results to be returned via GetVerifyResult() */ + GList *verify_results; + + /* method invocation for async ClaimDevice() */ + DBusGMethodInvocation *context_claim_device; + + /* method invocation for async ReleaseDevice() */ + DBusGMethodInvocation *context_release_device; + + /* method invocation for async GetVerifyResult() */ + DBusGMethodInvocation *context_get_verify_result; + + /* a list of loaded prints */ + GSList *loaded_prints; +}; + +struct verify_result { + int result; + struct fp_img *img; +}; + +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; +}; + +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, +}; + +static GObjectClass *parent_class = NULL; +static guint32 last_id = ~0; + +static void device_finalize(GObject *object) +{ + /* FIXME close and stuff */ +} + +static void device_set_property(GObject *object, guint property_id, + 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; + } +} + +static void device_class_init(FprintDeviceClass *klass) +{ + 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); + + gobject_class->finalize = device_finalize; + gobject_class->set_property = device_set_property; + + 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); + + g_type_class_add_private(klass, sizeof(FprintDevicePrivate)); +} + +static void device_init(GTypeInstance *instance, gpointer g_class) +{ + FprintDevice *self = (FprintDevice *) instance; + FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(self); + priv->id = ++last_id; +} + +GType fprint_device_get_type(void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof(FprintDeviceClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) device_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(FprintDevice), + 0, /* n_preallocs */ + device_init, + }; + type = g_type_register_static(G_TYPE_OBJECT, "FprintDeviceType", + &info, 0); + } + return type; +} + +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; +} + +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; + 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; + int r; + + 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; + + 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; + + /* 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, + GArray **fingers, GError **error) +{ + FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev); + struct fp_dscv_print **prints; + struct fp_dscv_print **print; + GArray *ret; + + prints = fp_discover_prints(); + if (!prints) { + g_set_error(error, FPRINT_ERROR, FPRINT_ERROR_DISCOVER_PRINTS, + "Failed to discover prints"); + 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; + return TRUE; +} + +static gboolean fprint_device_load_print_data(FprintDevice *rdev, + guint32 finger_num, guint32 *print_id, GError **error) +{ + 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; + int r; + + if (!dprints) { + g_set_error(error, FPRINT_ERROR, FPRINT_ERROR_DISCOVER_PRINTS, + "Failed to discover prints"); + 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); + g_set_error(error, FPRINT_ERROR, FPRINT_ERROR_PRINT_NOT_FOUND, + "Print not found"); + return FALSE; + } + + r = fp_print_data_from_dscv_print(selected_print, &data); + fp_dscv_prints_free(dprints); + if (r < 0) { + g_set_error(error, FPRINT_ERROR, FPRINT_ERROR_PRINT_LOAD, + "Print load failed with error %d", r); + 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; + return TRUE; +} + +static gboolean fprint_device_unload_print_data(FprintDevice *rdev, + guint32 print_id, GError **error) +{ + FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev); + struct session_data *session = priv->session; + GSList *elem = session->loaded_prints; + + g_message("unload print data %d for device %d", print_id, priv->id); + if (!elem) { + g_set_error(error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_LOADED_PRINT, + "No such loaded print %d", print_id); + 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); + return TRUE; + } while ((elem = g_slist_next(elem)) != NULL); + + g_set_error(error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_LOADED_PRINT, + "No such loaded print %d", print_id); + return FALSE; +} + +static void verify_cb(struct fp_dev *dev, int r, 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("verify_cb: result %d", r); + + if (session->context_get_verify_result) { + /* if we have an app waiting on a verify result, report it + * immediately */ + dbus_g_method_return(session->context_get_verify_result, r, FALSE); + fp_img_free(img); + session->context_get_verify_result = NULL; + } else { + /* otherwise nobody is listening. add it to the queue of pending + * results */ + struct verify_result *result = g_slice_new(struct verify_result); + result->result = r; + result->img = img; + session->verify_results = g_list_append(session->verify_results, + result); + } +} + +static gboolean fprint_device_verify_start(FprintDevice *rdev, + guint32 print_id, GError **error) +{ + FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev); + struct session_data *session = priv->session; + GSList *elem = session->loaded_prints; + struct fp_print_data *data = NULL; + int r; + + g_message("start verification device %d print %d", priv->id, print_id); + if (!elem) { + g_set_error(error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_LOADED_PRINT, + "No such loaded print %d", print_id); + 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) { + g_set_error(error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_LOADED_PRINT, + "No such loaded print %d", print_id); + return FALSE; + } + + /* FIXME check freeing/copying of data */ + r = fp_async_verify_start(priv->dev, data, verify_cb, rdev); + if (r < 0) { + g_set_error(error, FPRINT_ERROR, FPRINT_ERROR_VERIFY_START, + "Verify start failed with error %d", r); + return FALSE; + } + + return TRUE; +} + +static gboolean fprint_device_get_verify_result(FprintDevice *rdev, + DBusGMethodInvocation *context) +{ + FprintDevicePrivate *priv = DEVICE_GET_PRIVATE(rdev); + struct session_data *session = priv->session; + GList *elem = session->verify_results; + + if (elem == NULL) { + /* no pending results, asynchronously wait for the next one */ + session->context_get_verify_result = context; + g_message("get_verify_result: none pending, waiting for next one"); + } else { + struct verify_result *result = elem->data; + gboolean has_next = (g_list_next(elem) != NULL); + g_message("GetVerifyResult: returning pending result %d", + result->result); + dbus_g_method_return(context, result->result, has_next); + fp_img_free(result->img); + session->verify_results = g_list_delete_link(session->verify_results, + elem); + g_slice_free(struct verify_result, result); + } + + 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); + struct session_data *session = priv->session; + GList *elem = session->verify_results; + int r; + + /* Free all unreaped verify results */ + if (elem) { + do { + struct verify_result *result = elem->data; + fp_img_free(result->img); + g_slice_free(struct verify_result, result); + } while ((elem = g_list_next(elem)) != NULL); + g_list_free(session->verify_results); + session->verify_results = NULL; + } + + r = fp_async_verify_stop(priv->dev, verify_stop_cb, context); + if (r < 0) { + GError *error; + 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; +} + diff --git a/src/fprintd.xml b/src/device.xml similarity index 54% rename from src/fprintd.xml rename to src/device.xml index 1efec05..4afba0e 100644 --- a/src/fprintd.xml +++ b/src/device.xml @@ -1,58 +1,50 @@ + + + - - - - - - - - + + - + - - - - - - - + - - - - - - - - - - - + + + + + + + + diff --git a/src/fprintd.h b/src/fprintd.h new file mode 100644 index 0000000..e632a3d --- /dev/null +++ b/src/fprintd.h @@ -0,0 +1,100 @@ +/* + * fprintd header file + * Copyright (C) 2008 Daniel Drake + * + * 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. + */ + +#ifndef __FPRINTD_H__ +#define __FPRINTD_H__ + +#include +#include + +/* General */ +#define FPRINT_SERVICE_NAME "net.reactivated.Fprint" +extern DBusGConnection *fprintd_dbus_conn; +GQuark fprint_error_quark(void); + +/* Errors */ +#define FPRINT_ERROR fprint_error_quark() +typedef enum { + FPRINT_ERROR_NO_SUCH_DEVICE, + FPRINT_ERROR_DISCOVER_PRINTS, + FPRINT_ERROR_PRINT_NOT_FOUND, + FPRINT_ERROR_PRINT_LOAD, + FPRINT_ERROR_NO_SUCH_LOADED_PRINT, + FPRINT_ERROR_CLAIM_DEVICE, + FPRINT_ERROR_VERIFY_START, + FPRINT_ERROR_VERIFY_STOP, + FPRINT_ERROR_FAILED, +} FprintError; + +/* Manager */ +#define FPRINT_TYPE_MANAGER (fprint_manager_get_type()) +#define FPRINT_MANAGER(object) (G_TYPE_CHECK_INSTANCE_CAST((object), FPRINT_MANAGER_TYPE, FprintManager)) +#define FPRINT_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), FPRINT_MANAGER_TYPE, FprintManagerClass)) +#define FPRINT_IS_MANAGER(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), FPRINT_MANAGER_TYPE)) +#define FPRINT_IS_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), FPRINT_TYPE_MANAGER)) +#define FPRINT_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), FPRINT_TYPE_MANAGER, FprintManagerClass)) + +struct FprintManager { + GObject parent; + GSList *dev_registry; +}; + +struct FprintManagerClass { + GObjectClass parent; +}; + +typedef struct FprintManager FprintManager; +typedef struct FprintManagerClass FprintManagerClass; + +FprintManager *fprint_manager_new(void); +GType fprint_manager_get_type(void); + +/* Device */ +#define FPRINT_TYPE_DEVICE (fprint_device_get_type()) +#define FPRINT_DEVICE(object) (G_TYPE_CHECK_INSTANCE_CAST((object), FPRINT_DEVICE_TYPE, FprintDevice)) +#define FPRINT_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), FPRINT_DEVICE_TYPE, FprintDeviceClass)) +#define FPRINT_IS_DEVICE(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), FPRINT_TYPE_DEVICE)) +#define FPRINT_IS_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), FPRINT_TYPE_DEVICE)) +#define FPRINT_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), FPRINT_TYPE_DEVICE, FprintDeviceClass)) + +struct FprintDevice { + GObject parent; +}; + +struct FprintDeviceClass { + GObjectClass parent; +}; + +typedef struct FprintDevice FprintDevice; +typedef struct FprintDeviceClass FprintDeviceClass; + +FprintDevice *fprint_device_new(struct fp_dscv_dev *ddev); +GType fprint_device_get_type(void); +guint32 _fprint_device_get_id(FprintDevice *rdev); +/* Print */ +/* TODO */ + +/* Binding data included in main.c thorugh server-bindings.h which individual + * class implementations need to access. + */ +extern const DBusGObjectInfo dbus_glib_fprint_manager_object_info; +extern const DBusGObjectInfo dbus_glib_fprint_device_object_info; + +#endif + diff --git a/src/main.c b/src/main.c index db9fd9a..34fb822 100644 --- a/src/main.c +++ b/src/main.c @@ -25,105 +25,11 @@ #include #include -#define FPRINT_TYPE (fprint_get_type()) -#define FPRINT(object) (G_TYPE_CHECK_INSTANCE_CAST((object), FPRINT_TYPE, Fprint)) -#define FPRINT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), FPRINT_TYPE, FprintClass)) -#define IS_FPRINT(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), FPRINT_TYPE)) -#define IS_FPRINT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), FPRINT_TYPE)) -#define FPRINT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), FPRINT_TYPE, FprintClass)) +#include "fprintd.h" -struct Fprint { - GObject parent; -}; +DBusGConnection *fprintd_dbus_conn = NULL; -struct FprintClass { - GObjectClass parent; -}; - -typedef struct Fprint Fprint; -typedef struct FprintClass FprintClass; - -/* Generate the GObject boilerplate */ -G_DEFINE_TYPE(Fprint, fprint, G_TYPE_OBJECT) - -static gboolean fprint_list_devices(Fprint *fprint, GArray **ids, - char ***drivers, char ***fullnames, GError **error); -static gboolean fprint_list_enrolled_fingers(Fprint *fprint, guint32 device_id, - GArray **fingers, GError **error); -static gboolean fprint_load_print_data(Fprint *fprint, guint32 device_id, - guint32 finger_num, guint32 *print_id, GError **error); -static gboolean fprint_unload_print_data(Fprint *fprint, guint32 device_id, - guint32 print_id, GError **error); -static gboolean fprint_claim_device(Fprint *fprint, guint32 device_id, - DBusGMethodInvocation *minv); -static gboolean fprint_release_device(Fprint *fprint, guint32 device_id, - DBusGMethodInvocation *minv); -static gboolean fprint_verify_start(Fprint *fprint, guint32 device_id, - guint32 finger, GError **error); -static gboolean fprint_get_verify_result(Fprint *fprint, guint32 device_id, - DBusGMethodInvocation *minv); -static gboolean fprint_verify_stop(Fprint *fprint, guint32 device_id, - DBusGMethodInvocation *minv); - -#include "server-bindings.h" - -#define FPRINT_SERVICE_NAME "net.reactivated.Fprint" - -#define FPRINT_ERROR fprint_error_quark() -typedef enum { - FPRINT_ERROR_NO_SUCH_DEVICE, - FPRINT_ERROR_DISCOVER_PRINTS, - FPRINT_ERROR_PRINT_NOT_FOUND, - FPRINT_ERROR_PRINT_LOAD, - FPRINT_ERROR_NO_SUCH_LOADED_PRINT, - FPRINT_ERROR_CLAIM_DEVICE, - FPRINT_ERROR_VERIFY_START, - FPRINT_ERROR_VERIFY_STOP, - FPRINT_ERROR_FAILED, -} FprintError; - -struct verify_result { - int result; - struct fp_img *img; -}; - -struct loaded_print { - guint32 id; - struct fp_print_data *data; -}; - -struct session_data { - /* a list of pending verify results to be returned via GetVerifyResult() */ - GList *verify_results; - - /* method invocation for async ClaimDevice() */ - DBusGMethodInvocation *minv_claim_device; - - /* method invocation for async ReleaseDevice() */ - DBusGMethodInvocation *minv_release_device; - - /* method invocation for async GetVerifyResult() */ - DBusGMethodInvocation *minv_get_verify_result; - - /* a list of loaded prints */ - GSList *loaded_prints; -}; - -/* known devices are "registered" in a catalogue when they become known. - * each registered device may be simply discovered, but is later opened when - * claimed by an application and closed upon release. - */ -struct registered_dev { - guint32 id; - struct fp_dscv_dev *ddev; - struct fp_dev *dev; - struct session_data *session; -}; - -static GSList *dev_catalogue; -static guint32 last_id = ~0; - -static GQuark fprint_error_quark(void) +GQuark fprint_error_quark(void) { static GQuark quark = 0; if (!quark) @@ -131,448 +37,6 @@ static GQuark fprint_error_quark(void) return quark; } -static void fprint_class_init(FprintClass *fprint_class) -{ - dbus_g_object_type_install_info(FPRINT_TYPE, &dbus_glib_fprint_object_info); -} - -static void fprint_init(Fprint *fprint) -{ -} - -static struct registered_dev *find_rdev_by_id(guint32 device_id) -{ - GSList *elem = dev_catalogue; - - if (!elem) - return NULL; - - do { - struct registered_dev *rdev = elem->data; - if (rdev->id == device_id) - return rdev; - } while ((elem = g_slist_next(elem)) != NULL); - - return NULL; -} - -static gboolean fprint_list_devices(Fprint *fprint, GArray **ids, - char ***drivers, char ***fullnames, GError **error) -{ - int num_open = g_slist_length(dev_catalogue); - gchar **drvlist = g_malloc(sizeof(gchar *) * (num_open + 1)); - gchar **namelist = g_malloc(sizeof(gchar *) * (num_open + 1)); - GArray *idlist = g_array_sized_new(FALSE, FALSE, sizeof(guint32), num_open); - GSList *elem = dev_catalogue; - guint32 i = 0; - - g_message("list_devices request, returning %d results", num_open); - drvlist[num_open] = NULL; - namelist[num_open] = NULL; - if (num_open == 0) - goto out; - - do { - struct registered_dev *rdev = elem->data; - struct fp_dscv_dev *ddev = rdev->ddev; - struct fp_driver *drv = fp_dscv_dev_get_driver(ddev); - idlist = g_array_append_val(idlist, rdev->id); - drvlist[i] = g_strdup(fp_driver_get_name(drv)); - namelist[i++] = g_strdup(fp_driver_get_full_name(drv)); - } while ((elem = g_slist_next(elem)) != NULL); - -out: - *ids = idlist; - *drivers = drvlist; - *fullnames = namelist; - return TRUE; -} - -static void dev_open_cb(struct fp_dev *dev, int status, void *user_data) -{ - struct registered_dev *rdev = user_data; - struct session_data *session = rdev->session; - - g_message("device %d claim status %d", rdev->id, status); - - if (status != 0) { - GError *error; - g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_CLAIM_DEVICE, - "Open failed with error %d", status); - dbus_g_method_return_error(session->minv_claim_device, error); - return; - } - - rdev->dev = dev; - dbus_g_method_return(session->minv_claim_device); -} - -static gboolean fprint_claim_device(Fprint *fprint, guint32 device_id, - DBusGMethodInvocation *minv) -{ - struct registered_dev *rdev = find_rdev_by_id(device_id); - GError *error = NULL; - int r; - - g_message("claiming device %d", device_id); - - if (!rdev) { - g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_DEVICE, - "No such device %d", device_id); - dbus_g_method_return_error(minv, error); - return FALSE; - } - - rdev->session = g_slice_new0(struct session_data); - rdev->session->minv_claim_device = minv; - - r = fp_async_dev_open(rdev->ddev, dev_open_cb, rdev); - if (r < 0) { - g_slice_free(struct session_data, rdev->session); - rdev->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(minv, error); - return FALSE; - } - - return TRUE; -} - -static void dev_close_cb(struct fp_dev *dev, void *user_data) -{ - struct registered_dev *rdev = user_data; - struct session_data *session = rdev->session; - DBusGMethodInvocation *minv = session->minv_release_device; - - rdev->dev = NULL; - g_slice_free(struct session_data, session); - rdev->session = NULL; - - g_message("released device %d", rdev->id); - dbus_g_method_return(minv); -} - -static gboolean fprint_release_device(Fprint *fprint, guint32 device_id, - DBusGMethodInvocation *minv) -{ - struct registered_dev *rdev = find_rdev_by_id(device_id); - struct session_data *session; - GError *error = NULL; - GSList *elem; - - if (!rdev) { - g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_DEVICE, - "No such device %d", device_id); - dbus_g_method_return_error(minv, error); - return FALSE; - } - - /* Unload any loaded prints */ - session = rdev->session; - elem = session->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->minv_release_device = minv; - fp_async_dev_close(rdev->dev, dev_close_cb, rdev); - return TRUE; -} - -static gboolean fprint_list_enrolled_fingers(Fprint *fprint, guint32 device_id, - GArray **fingers, GError **error) -{ - struct registered_dev *rdev = find_rdev_by_id(device_id); - struct fp_dscv_print **prints; - struct fp_dscv_print **print; - GArray *ret; - - if (!rdev) { - g_set_error(error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_DEVICE, - "No such device %d", device_id); - return FALSE; - } - - prints = fp_discover_prints(); - if (!prints) { - g_set_error(error, FPRINT_ERROR, FPRINT_ERROR_DISCOVER_PRINTS, - "Failed to discover prints"); - return FALSE; - } - - ret = g_array_new(FALSE, FALSE, sizeof(int)); - for (print = prints; *print; print++) - if (fp_dev_supports_dscv_print(rdev->dev, *print)) { - int finger = fp_dscv_print_get_finger(*print); - ret = g_array_append_val(ret, finger); - } - - fp_dscv_prints_free(prints); - *fingers = ret; - return TRUE; -} - -static gboolean fprint_load_print_data(Fprint *fprint, guint32 device_id, - guint32 finger_num, guint32 *print_id, GError **error) -{ - struct registered_dev *rdev = find_rdev_by_id(device_id); - struct session_data *session; - struct loaded_print *lprint; - struct fp_dscv_print **dprints; - struct fp_dscv_print **dprint; - struct fp_dscv_print *selected_print = NULL; - struct fp_print_data *data; - int r; - - if (!rdev) { - g_set_error(error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_DEVICE, - "No such device %d", device_id); - return FALSE; - } - - session = rdev->session; - dprints = fp_discover_prints(); - if (!dprints) { - g_set_error(error, FPRINT_ERROR, FPRINT_ERROR_DISCOVER_PRINTS, - "Failed to discover prints"); - return FALSE; - } - - for (dprint = dprints; *dprint; dprint++) - if (fp_dev_supports_dscv_print(rdev->dev, *dprint) - && fp_dscv_print_get_finger(*dprint) == finger_num) { - selected_print = *dprint; - break; - } - - if (!selected_print) { - fp_dscv_prints_free(dprints); - g_set_error(error, FPRINT_ERROR, FPRINT_ERROR_PRINT_NOT_FOUND, - "Print not found"); - return FALSE; - } - - r = fp_print_data_from_dscv_print(selected_print, &data); - fp_dscv_prints_free(dprints); - if (r < 0) { - g_set_error(error, FPRINT_ERROR, FPRINT_ERROR_PRINT_LOAD, - "Print load failed with error %d", r); - 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, device_id, lprint->id); - *print_id = lprint->id; - return TRUE; -} - -static gboolean fprint_unload_print_data(Fprint *fprint, guint32 device_id, - guint32 print_id, GError **error) -{ - struct registered_dev *rdev = find_rdev_by_id(device_id); - struct session_data *session; - GSList *elem; - - if (!rdev) { - g_set_error(error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_DEVICE, - "No such device %d", device_id); - return FALSE; - } - - session = rdev->session; - elem = session->loaded_prints; - - g_message("unload print data %d for device %d", print_id, device_id); - if (!elem) { - g_set_error(error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_LOADED_PRINT, - "No such loaded print %d", print_id); - 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); - return TRUE; - } while ((elem = g_slist_next(elem)) != NULL); - - g_set_error(error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_LOADED_PRINT, - "No such loaded print %d", print_id); - return FALSE; -} - -static void verify_cb(struct fp_dev *dev, int r, struct fp_img *img, - void *user_data) -{ - struct registered_dev *rdev = user_data; - struct session_data *session = rdev->session; - g_message("verify_cb: result %d", r); - - if (session->minv_get_verify_result) { - /* if we have an app waiting on a verify result, report it - * immediately */ - dbus_g_method_return(session->minv_get_verify_result, r, FALSE); - fp_img_free(img); - session->minv_get_verify_result = NULL; - } else { - /* otherwise nobody is listening. add it to the queue of pending - * results */ - struct verify_result *result = g_slice_new(struct verify_result); - result->result = r; - result->img = img; - session->verify_results = g_list_append(session->verify_results, - result); - } -} - -static gboolean fprint_verify_start(Fprint *fprint, guint32 device_id, - guint32 print_id, GError **error) -{ - int r; - struct registered_dev *rdev = find_rdev_by_id(device_id); - struct session_data *session; - struct fp_print_data *data = NULL; - GSList *elem; - - if (!rdev) { - g_set_error(error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_DEVICE, - "No such device %d", device_id); - return FALSE; - } - - session = rdev->session; - elem = session->loaded_prints; - - g_message("start verification device %d print %d", device_id, print_id); - if (!elem) { - g_set_error(error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_LOADED_PRINT, - "No such loaded print %d", print_id); - 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) { - g_set_error(error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_LOADED_PRINT, - "No such loaded print %d", print_id); - return FALSE; - } - - /* FIXME check freeing/copying of data */ - r = fp_async_verify_start(rdev->dev, data, verify_cb, rdev); - if (r < 0) { - g_set_error(error, FPRINT_ERROR, FPRINT_ERROR_VERIFY_START, - "Verify start failed with error %d", r); - return FALSE; - } - - return TRUE; -} - -static gboolean fprint_get_verify_result(Fprint *fprint, guint32 device_id, - DBusGMethodInvocation *minv) -{ - struct registered_dev *rdev = find_rdev_by_id(device_id); - struct session_data *session; - GList *elem; - - if (!rdev) { - GError *error; - g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_DEVICE, - "No such device %d", device_id); - dbus_g_method_return_error(minv, error); - return FALSE; - } - - session = rdev->session; - elem = session->verify_results; - - if (elem == NULL) { - /* no pending results, asynchronously wait for the next one */ - session->minv_get_verify_result = minv; - g_message("get_verify_result: none pending, waiting for next one"); - } else { - struct verify_result *result = elem->data; - gboolean has_next = (g_list_next(elem) != NULL); - g_message("GetVerifyResult: returning pending result %d", - result->result); - dbus_g_method_return(minv, result->result, has_next); - fp_img_free(result->img); - session->verify_results = g_list_delete_link(session->verify_results, - elem); - g_slice_free(struct verify_result, result); - } - - return TRUE; -} - -static void verify_stop_cb(struct fp_dev *dev, void *user_data) -{ - dbus_g_method_return((DBusGMethodInvocation *) user_data); -} - -static gboolean fprint_verify_stop(Fprint *fprint, guint32 device_id, - DBusGMethodInvocation *minv) -{ - struct registered_dev *rdev = find_rdev_by_id(device_id); - struct session_data *session; - GList *elem; - int r; - - if (!rdev) { - GError *error; - g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_NO_SUCH_DEVICE, - "No such device %d", device_id); - dbus_g_method_return_error(minv, error); - return FALSE; - } - - /* Free all unreaped verify results */ - session = rdev->session; - elem = session->verify_results; - - if (elem) { - do { - struct verify_result *result = elem->data; - fp_img_free(result->img); - g_slice_free(struct verify_result, result); - } while ((elem = g_list_next(elem)) != NULL); - g_list_free(session->verify_results); - session->verify_results = NULL; - } - - r = fp_async_verify_stop(rdev->dev, verify_stop_cb, minv); - if (r < 0) { - GError *error; - g_set_error(&error, FPRINT_ERROR, FPRINT_ERROR_VERIFY_STOP, - "Verify stop failed with error %d", r); - dbus_g_method_return_error(minv, error); - return FALSE; - } - - return TRUE; -} - struct fdsource { GSource source; GSList *pollfds; @@ -732,32 +196,11 @@ static int setup_pollfds(void) return 0; } -static int find_devices(void) -{ - struct fp_dscv_dev **discovered_devs = fp_discover_devs(); - struct fp_dscv_dev *ddev; - int i = 0; - - if (!discovered_devs) - return -1; - - while ((ddev = discovered_devs[i++]) != NULL) { - struct fp_driver *drv = fp_dscv_dev_get_driver(ddev); - struct registered_dev *rdev = g_slice_new0(struct registered_dev); - g_message("found device %s", fp_driver_get_full_name(drv)); - rdev->id = ++last_id; - rdev->ddev = ddev; - dev_catalogue = g_slist_prepend(dev_catalogue, rdev); - } - return 0; -} - int main(int argc, char **argv) { GMainLoop *loop; - DBusGConnection *connection; GError *error = NULL; - GObject *obj; + FprintManager *manager; DBusGProxy *driver_proxy; guint32 request_name_ret; int r = 0; @@ -777,25 +220,19 @@ int main(int argc, char **argv) goto err; } - r = find_devices(); - if (r < 0) { - g_print("open devices failed\n"); - goto err; - } - g_print("Launching FprintObject\n"); /* Obtain a connection to the session bus */ - connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error); - if (connection == NULL) + fprintd_dbus_conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error); + if (fprintd_dbus_conn == NULL) g_error("Failed to open connection to bus: %s", error->message); - obj = g_object_new(FPRINT_TYPE, NULL); - dbus_g_connection_register_g_object(connection, "/net/reactivated/Fprint", - obj); + /* create the one instance of the Manager object to be shared between + * all fprintd users */ + manager = fprint_manager_new(); - driver_proxy = dbus_g_proxy_new_for_name(connection, DBUS_SERVICE_DBUS, - DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); + driver_proxy = dbus_g_proxy_new_for_name(fprintd_dbus_conn, + DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); if (!org_freedesktop_DBus_request_name(driver_proxy, FPRINT_SERVICE_NAME, 0, &request_name_ret, &error)) diff --git a/src/manager.c b/src/manager.c new file mode 100644 index 0000000..72356f3 --- /dev/null +++ b/src/manager.c @@ -0,0 +1,124 @@ +/* + * /net/reactivated/Fprint/Manager object implementation + * Copyright (C) 2008 Daniel Drake + * + * 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. + */ + +#include +#include +#include +#include + +#include "fprintd.h" + +static gboolean fprint_manager_get_devices(FprintManager *manager, + GPtrArray **devices, GError **error); + +#include "manager-dbus-glue.h" + +static GObjectClass *parent_class = NULL; + +static void manager_finalize(GObject *object) +{ + FprintManager *self = (FprintManager *) object; + g_slist_free(self->dev_registry); + G_OBJECT_CLASS(parent_class)->finalize(object); +} + +static void manager_class_init(FprintManagerClass *klass) +{ + dbus_g_object_type_install_info(FPRINT_TYPE_MANAGER, + &dbus_glib_fprint_manager_object_info); + + G_OBJECT_CLASS(klass)->finalize = manager_finalize; + parent_class = g_type_class_peek_parent(klass); +} + +GType fprint_manager_get_type(void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof(FprintManagerClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) manager_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof(FprintManager), + 0, /* n_preallocs */ + NULL, + }; + type = g_type_register_static(G_TYPE_OBJECT, "FprintManagerType", + &info, 0); + } + return type; +} + +static gchar *get_device_path(FprintDevice *rdev) +{ + return g_strdup_printf("/net/reactivated/Fprint/Device/%d", + _fprint_device_get_id(rdev)); +} + +FprintManager *fprint_manager_new(void) +{ + FprintManager *manager; + struct fp_dscv_dev **discovered_devs = fp_discover_devs(); + struct fp_dscv_dev *ddev; + int i = 0; + + /* FIXME some or all of this should probably be moved into FprintManager + * ctor. however i'm not sure how to raise errors from a constructor... */ + + if (!discovered_devs) + return NULL; + + manager = g_object_new(FPRINT_TYPE_MANAGER, NULL); + dbus_g_connection_register_g_object(fprintd_dbus_conn, + "/net/reactivated/Fprint/Manager", G_OBJECT(manager)); + + while ((ddev = discovered_devs[i++]) != NULL) { + FprintDevice *rdev = fprint_device_new(ddev); + gchar *path; + + manager->dev_registry = g_slist_prepend(manager->dev_registry, rdev); + path = get_device_path(rdev); + dbus_g_connection_register_g_object(fprintd_dbus_conn, path, + G_OBJECT(rdev)); + g_free(path); + } + + return manager; +} + +static gboolean fprint_manager_get_devices(FprintManager *manager, + GPtrArray **devices, GError **error) +{ + GSList *elem = manager->dev_registry; + int num_open = g_slist_length(elem); + GPtrArray *devs = g_ptr_array_sized_new(num_open); + + if (num_open > 0) + do { + FprintDevice *rdev = elem->data; + g_ptr_array_add(devs, get_device_path(rdev)); + } while ((elem = g_slist_next(elem)) != NULL); + + *devices = devs; + return TRUE; +} + diff --git a/src/manager.xml b/src/manager.xml new file mode 100644 index 0000000..7d33003 --- /dev/null +++ b/src/manager.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + +