1cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project/*
2cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project *
4cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * you may not use this file except in compliance with the License.
6cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * You may obtain a copy of the License at
7cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project *
8cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project *
10cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * See the License for the specific language governing permissions and
14cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * limitations under the License.
15cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project */
16cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
17cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include <hardware_legacy/uevent.h>
18cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
19cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include <string.h>
20cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include <unistd.h>
21cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include <poll.h>
221cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling#include <pthread.h>
23cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
24cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include <sys/socket.h>
25cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include <sys/un.h>
261cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling#include <sys/queue.h>
27cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include <linux/netlink.h>
28cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
29cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
301cb1728b1870a5e37360f65864a3642d5a37b21cErik GillingLIST_HEAD(uevent_handler_head, uevent_handler) uevent_handler_list;
311cb1728b1870a5e37360f65864a3642d5a37b21cErik Gillingpthread_mutex_t uevent_handler_list_lock = PTHREAD_MUTEX_INITIALIZER;
321cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling
331cb1728b1870a5e37360f65864a3642d5a37b21cErik Gillingstruct uevent_handler {
341cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling    void (*handler)(void *data, const char *msg, int msg_len);
351cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling    void *handler_data;
361cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling    LIST_ENTRY(uevent_handler) list;
371cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling};
381cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling
39cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectstatic int fd = -1;
40cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
41cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project/* Returns 0 on failure, 1 on success */
42cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectint uevent_init()
43cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
44cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    struct sockaddr_nl addr;
45cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int sz = 64*1024;
46cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int s;
47cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
48cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    memset(&addr, 0, sizeof(addr));
49cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    addr.nl_family = AF_NETLINK;
50cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    addr.nl_pid = getpid();
51cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    addr.nl_groups = 0xffffffff;
52cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
53cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
54cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if(s < 0)
55cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return 0;
56cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
57cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz));
58cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
59cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
60cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        close(s);
61cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return 0;
62cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
63cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
64cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    fd = s;
65cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return (fd > 0);
66cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
67cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
68020418ec646f989ca14f26e3abd8f23208e9cd4dErik Gillingint uevent_get_fd()
69020418ec646f989ca14f26e3abd8f23208e9cd4dErik Gilling{
70020418ec646f989ca14f26e3abd8f23208e9cd4dErik Gilling    return fd;
71020418ec646f989ca14f26e3abd8f23208e9cd4dErik Gilling}
72020418ec646f989ca14f26e3abd8f23208e9cd4dErik Gilling
73cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectint uevent_next_event(char* buffer, int buffer_length)
74cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
75cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    while (1) {
76cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        struct pollfd fds;
77cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        int nr;
78cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
79cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        fds.fd = fd;
80cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        fds.events = POLLIN;
81cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        fds.revents = 0;
82cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        nr = poll(&fds, 1, -1);
83cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
843aabb260ceef10377c31c9e45fb239247f5cfebaMathias Agopian        if(nr > 0 && (fds.revents & POLLIN)) {
85cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            int count = recv(fd, buffer, buffer_length, 0);
86cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            if (count > 0) {
871cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling                struct uevent_handler *h;
881cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling                pthread_mutex_lock(&uevent_handler_list_lock);
891cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling                LIST_FOREACH(h, &uevent_handler_list, list)
901cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling                    h->handler(h->handler_data, buffer, buffer_length);
911cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling                pthread_mutex_unlock(&uevent_handler_list_lock);
921cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling
93cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project                return count;
94cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            }
95cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        }
96cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
97cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
98cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    // won't get here
99cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return 0;
100cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
1011cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling
1021cb1728b1870a5e37360f65864a3642d5a37b21cErik Gillingint uevent_add_native_handler(void (*handler)(void *data, const char *msg, int msg_len),
1031cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling                             void *handler_data)
1041cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling{
1051cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling    struct uevent_handler *h;
1061cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling
1071cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling    h = malloc(sizeof(struct uevent_handler));
1081cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling    if (h == NULL)
1091cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling        return -1;
1101cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling    h->handler = handler;
1111cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling    h->handler_data = handler_data;
1121cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling
1131cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling    pthread_mutex_lock(&uevent_handler_list_lock);
1141cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling    LIST_INSERT_HEAD(&uevent_handler_list, h, list);
1151cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling    pthread_mutex_unlock(&uevent_handler_list_lock);
1161cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling
1171cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling    return 0;
1181cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling}
1191cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling
1201cb1728b1870a5e37360f65864a3642d5a37b21cErik Gillingint uevent_remove_native_handler(void (*handler)(void *data, const char *msg, int msg_len))
1211cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling{
1221cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling    struct uevent_handler *h;
1231cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling    int err = -1;
1241cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling
1251cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling    pthread_mutex_lock(&uevent_handler_list_lock);
1261cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling    LIST_FOREACH(h, &uevent_handler_list, list) {
1271cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling        if (h->handler == handler) {
1281cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling            LIST_REMOVE(h, list);
1291cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling            err = 0;
1301cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling            break;
1311cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling       }
1321cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling    }
1331cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling    pthread_mutex_unlock(&uevent_handler_list_lock);
1341cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling
1351cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling    return err;
1361cb1728b1870a5e37360f65864a3642d5a37b21cErik Gilling}
137