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