add native uevent handling

Change-Id: I2315f5638668ab802a4b3c723afd97b7edf0c695
diff --git a/uevent/uevent.c b/uevent/uevent.c
index d1d4b8e..396bad4 100644
--- a/uevent/uevent.c
+++ b/uevent/uevent.c
@@ -19,12 +19,23 @@
 #include <string.h>
 #include <unistd.h>
 #include <poll.h>
+#include <pthread.h>
 
 #include <sys/socket.h>
 #include <sys/un.h>
+#include <sys/queue.h>
 #include <linux/netlink.h>
 
 
+LIST_HEAD(uevent_handler_head, uevent_handler) uevent_handler_list;
+pthread_mutex_t uevent_handler_list_lock = PTHREAD_MUTEX_INITIALIZER;
+
+struct uevent_handler {
+    void (*handler)(void *data, const char *msg, int msg_len);
+    void *handler_data;
+    LIST_ENTRY(uevent_handler) list;
+};
+
 static int fd = -1;
 
 /* Returns 0 on failure, 1 on success */
@@ -68,6 +79,12 @@
         if(nr > 0 && fds.revents == POLLIN) {
             int count = recv(fd, buffer, buffer_length, 0);
             if (count > 0) {
+                struct uevent_handler *h;
+                pthread_mutex_lock(&uevent_handler_list_lock);
+                LIST_FOREACH(h, &uevent_handler_list, list)
+                    h->handler(h->handler_data, buffer, buffer_length);
+                pthread_mutex_unlock(&uevent_handler_list_lock);
+
                 return count;
             } 
         }
@@ -76,3 +93,39 @@
     // won't get here
     return 0;
 }
+
+int uevent_add_native_handler(void (*handler)(void *data, const char *msg, int msg_len),
+                             void *handler_data)
+{
+    struct uevent_handler *h;
+
+    h = malloc(sizeof(struct uevent_handler));
+    if (h == NULL)
+        return -1;
+    h->handler = handler;
+    h->handler_data = handler_data;
+
+    pthread_mutex_lock(&uevent_handler_list_lock);
+    LIST_INSERT_HEAD(&uevent_handler_list, h, list);
+    pthread_mutex_unlock(&uevent_handler_list_lock);
+
+    return 0;
+}
+
+int uevent_remove_native_handler(void (*handler)(void *data, const char *msg, int msg_len))
+{
+    struct uevent_handler *h;
+    int err = -1;
+
+    pthread_mutex_lock(&uevent_handler_list_lock);
+    LIST_FOREACH(h, &uevent_handler_list, list) {
+        if (h->handler == handler) {
+            LIST_REMOVE(h, list);
+            err = 0;
+            break;
+       }
+    }
+    pthread_mutex_unlock(&uevent_handler_list_lock);
+
+    return err;
+}