summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Schmidt <philschmidt@gmx.net>2013-07-15 11:05:11 +0200
committerPhilipp Schmidt <philschmidt@gmx.net>2013-07-15 11:05:11 +0200
commitfd649f71d008a15fd9cd4c7b0b48be4edd9ca51d (patch)
treeb0ecb01558a461bafd6f4598164e64f1b45adba7
parent35e3ca39894ead43c9839dd523233ff72d5bec7b (diff)
downloadlibmtp-fd649f71d008a15fd9cd4c7b0b48be4edd9ca51d.tar.gz
Implement udev listener.
-rw-r--r--daemon/mtpd.c5
-rw-r--r--daemon/udev_listener.c158
-rw-r--r--daemon/udev_listener.h40
3 files changed, 202 insertions, 1 deletions
diff --git a/daemon/mtpd.c b/daemon/mtpd.c
index e9e2fd3..c8e0011 100644
--- a/daemon/mtpd.c
+++ b/daemon/mtpd.c
@@ -24,6 +24,8 @@
#include <signal.h>
#include <syslog.h>
+#include "udev_listener.h"
+
void
signal_handler(int sig) {
@@ -36,7 +38,8 @@ signal_handler(int sig) {
case SIGQUIT:
// Graceful shutdown
- //TODO
+ MTPD_stop_udev_listener();
+
break;
diff --git a/daemon/udev_listener.c b/daemon/udev_listener.c
new file mode 100644
index 0000000..fe4928a
--- /dev/null
+++ b/daemon/udev_listener.c
@@ -0,0 +1,158 @@
+/**
+ * \file udev_listener.c
+ *
+ * Copyright (C) 2013 Philipp Schmidt <philschmidt@gmx.net>
+ *
+ * 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 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "udev_listener.h"
+
+#include <pthread.h>
+#include <fcntl.h>
+#include <libmtp.h>
+#include <libudev.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include <glib.h>
+
+struct device_ident_t
+{
+ int busnum;
+ int devnum;
+};
+
+struct callbacks_t
+{
+ const MTPD_device_added_t device_added_callback;
+ const MTPD_device_removed_t device_removed_callback;
+};
+
+pthread_t thread;
+
+void MTPD_run_udev_listener(void *arg)
+{
+ callbacks_t* callbacks = (callbacks_t*)arg;
+
+ struct udev *udev;
+ struct udev_device *dev;
+ struct udev_monitor *mon;
+
+ GArray *ident_list;
+
+ udev = udev_new();
+
+
+ if (!udev)
+ {
+ stderr << "Can't create udev";
+ return;
+ }
+
+ // Get monitor and set subsystem to usb and device type to usb devices
+ mon = udev_monitor_new_from_netlink(udev, "udev");
+ udev_monitor_filter_add_match_subsystem_devtype(mon, "usb", "usb_device");
+ udev_monitor_enable_receiving(mon);
+
+ // Get fildescriptor and set it to blocking mode (default is non blocking)
+ int fd = udev_monitor_get_fd(mon);
+ int flags = fcntl(fd, F_GETFL);
+ fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
+
+ ident_list = g_array_new (FALSE, FALSE, sizeof (device_ident_t));
+
+ //While the thread runs, wait for incoming udev-events
+ while (1)
+ {
+ fd_set fds;
+ int ret;
+
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+
+ // Use select so we have a canncellation point
+ ret = select(fd+1, &fds, NULL, NULL, NULL);
+
+ if (ret > 0 && FD_ISSET(fd, &fds))
+ {
+ dev = udev_monitor_receive_device(mon);
+
+ device_identificator ident;
+ const char* action = udev_device_get_action(dev);
+
+ device_ident_t ident;
+
+ ident.busnum = atoi(udev_device_get_property_value(dev, "BUSNUM"));
+ pthread_t thread;
+ ident.devnum = atoi(udev_device_get_property_value(dev, "DEVNUM"));
+
+ if (strcmp("add", action) == 0)
+ {
+ int isMtpDevice = LIBMTP_Check_Specific_Device(ident.busnum, ident.devnum);
+ if (isMtpDevice == 1)
+ {
+ // Add to internal device list
+ g_array_append_vals(ident_list, ident);
+
+ callbacks->device_added_callback( ident.busnum, ident.devnum );
+ }
+ }
+ if (strcmp("remove", action) == 0)
+ { my_struct* foo = (my_struct*)arg;
+ int device_index = -1;
+ for ( int i = 0; i < ident_list->len; i++ )
+ {
+ device_ident_t current = g_array_index( ident_list, device_ident_t, i );
+
+ if (current.busnum == ident.busnum && current.devnum == ident.devnum)
+ {
+ device_index = i;
+ break;
+ }
+ }
+
+ if (device_index >= 0)
+ {
+ g_array_remove_index(device_index);
+ callbacks->device_removed_callback(ident.busnum, ident.devnum);
+ }
+ }
+
+ udev_device_unref(dev);
+ }
+ }
+
+ g_array_free( ident_list );
+}
+
+void MTPD_start_udev_listener(const MTPD_device_added_t device_added_callback, const MTPD_device_removed_t device_removed_callback)
+{
+ callbacks_t *callbacks = malloc(sizeof(callbacks_t));
+ callbacks->device_added_callback = device_added_callback;
+ callbacks->device_removed_callback = device_removed_callback;
+
+ pthread_create(&thread, NULL, MTPD_run_udev_listener, callbacks);
+
+}
+
+void MTPD_stop_udev_listener()
+{
+ pthread_cancel(&thread);
+}
+
diff --git a/daemon/udev_listener.h b/daemon/udev_listener.h
new file mode 100644
index 0000000..00ac8f5
--- /dev/null
+++ b/daemon/udev_listener.h
@@ -0,0 +1,40 @@
+/**
+ * \file udev_listener.h
+ *
+ * Copyright (C) 2013 Philipp Schmidt <philschmidt@gmx.net>
+ *
+ * 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 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef UDEV_LISTENER_H
+#define UDEV_LISTENER_H
+
+/**
+ * The callback type definition for the function that is called when a device is added.
+ */
+typedef int (* MTPD_device_added_t) (uint32_t const busid, uint32_t const devid);
+
+/**
+ * The callback type definition for the function that is called when a device was removed.
+ */
+typedef int (* MTPD_device_removed_t) (uint32_t const busid, uint32_t const devid);
+
+void
+MTPD_start_udev_listener( MTPD_device_added_t const, MTPD_device_removed_t const );
+void
+MTPD_stop_udev_listener();
+
+#endif //UDEV_LISTENER_H