xref: /aosp_15_r20/hardware/libhardware_legacy/uevent.c (revision 79330504eb3d14022296e3b041867f86289dd52c)
1*79330504STreehugger Robot /*
2*79330504STreehugger Robot  * Copyright (C) 2008 The Android Open Source Project
3*79330504STreehugger Robot  *
4*79330504STreehugger Robot  * Licensed under the Apache License, Version 2.0 (the "License");
5*79330504STreehugger Robot  * you may not use this file except in compliance with the License.
6*79330504STreehugger Robot  * You may obtain a copy of the License at
7*79330504STreehugger Robot  *
8*79330504STreehugger Robot  *      http://www.apache.org/licenses/LICENSE-2.0
9*79330504STreehugger Robot  *
10*79330504STreehugger Robot  * Unless required by applicable law or agreed to in writing, software
11*79330504STreehugger Robot  * distributed under the License is distributed on an "AS IS" BASIS,
12*79330504STreehugger Robot  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*79330504STreehugger Robot  * See the License for the specific language governing permissions and
14*79330504STreehugger Robot  * limitations under the License.
15*79330504STreehugger Robot  */
16*79330504STreehugger Robot 
17*79330504STreehugger Robot #include <hardware_legacy/uevent.h>
18*79330504STreehugger Robot 
19*79330504STreehugger Robot #include <malloc.h>
20*79330504STreehugger Robot #include <string.h>
21*79330504STreehugger Robot #include <unistd.h>
22*79330504STreehugger Robot #include <poll.h>
23*79330504STreehugger Robot #include <pthread.h>
24*79330504STreehugger Robot 
25*79330504STreehugger Robot #include <sys/socket.h>
26*79330504STreehugger Robot #include <sys/un.h>
27*79330504STreehugger Robot #include <sys/queue.h>
28*79330504STreehugger Robot #include <linux/netlink.h>
29*79330504STreehugger Robot 
30*79330504STreehugger Robot 
31*79330504STreehugger Robot LIST_HEAD(uevent_handler_head, uevent_handler) uevent_handler_list;
32*79330504STreehugger Robot pthread_mutex_t uevent_handler_list_lock = PTHREAD_MUTEX_INITIALIZER;
33*79330504STreehugger Robot 
34*79330504STreehugger Robot struct uevent_handler {
35*79330504STreehugger Robot     void (*handler)(void *data, const char *msg, int msg_len);
36*79330504STreehugger Robot     void *handler_data;
37*79330504STreehugger Robot     LIST_ENTRY(uevent_handler) list;
38*79330504STreehugger Robot };
39*79330504STreehugger Robot 
40*79330504STreehugger Robot static int fd = -1;
41*79330504STreehugger Robot 
42*79330504STreehugger Robot /* Returns 0 on failure, 1 on success */
uevent_init()43*79330504STreehugger Robot int uevent_init()
44*79330504STreehugger Robot {
45*79330504STreehugger Robot     struct sockaddr_nl addr;
46*79330504STreehugger Robot     int sz = 64*1024;
47*79330504STreehugger Robot     int s;
48*79330504STreehugger Robot 
49*79330504STreehugger Robot     memset(&addr, 0, sizeof(addr));
50*79330504STreehugger Robot     addr.nl_family = AF_NETLINK;
51*79330504STreehugger Robot     addr.nl_pid = getpid();
52*79330504STreehugger Robot     addr.nl_groups = 0xffffffff;
53*79330504STreehugger Robot 
54*79330504STreehugger Robot     s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
55*79330504STreehugger Robot     if(s < 0)
56*79330504STreehugger Robot         return 0;
57*79330504STreehugger Robot 
58*79330504STreehugger Robot     setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz));
59*79330504STreehugger Robot 
60*79330504STreehugger Robot     if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
61*79330504STreehugger Robot         close(s);
62*79330504STreehugger Robot         return 0;
63*79330504STreehugger Robot     }
64*79330504STreehugger Robot 
65*79330504STreehugger Robot     fd = s;
66*79330504STreehugger Robot     return (fd > 0);
67*79330504STreehugger Robot }
68*79330504STreehugger Robot 
uevent_get_fd()69*79330504STreehugger Robot int uevent_get_fd()
70*79330504STreehugger Robot {
71*79330504STreehugger Robot     return fd;
72*79330504STreehugger Robot }
73*79330504STreehugger Robot 
uevent_next_event(char * buffer,int buffer_length)74*79330504STreehugger Robot int uevent_next_event(char* buffer, int buffer_length)
75*79330504STreehugger Robot {
76*79330504STreehugger Robot     while (1) {
77*79330504STreehugger Robot         struct pollfd fds;
78*79330504STreehugger Robot         int nr;
79*79330504STreehugger Robot 
80*79330504STreehugger Robot         fds.fd = fd;
81*79330504STreehugger Robot         fds.events = POLLIN;
82*79330504STreehugger Robot         fds.revents = 0;
83*79330504STreehugger Robot         nr = poll(&fds, 1, -1);
84*79330504STreehugger Robot 
85*79330504STreehugger Robot         if(nr > 0 && (fds.revents & POLLIN)) {
86*79330504STreehugger Robot             int count = recv(fd, buffer, buffer_length, 0);
87*79330504STreehugger Robot             if (count > 0) {
88*79330504STreehugger Robot                 struct uevent_handler *h;
89*79330504STreehugger Robot                 pthread_mutex_lock(&uevent_handler_list_lock);
90*79330504STreehugger Robot                 LIST_FOREACH(h, &uevent_handler_list, list)
91*79330504STreehugger Robot                     h->handler(h->handler_data, buffer, buffer_length);
92*79330504STreehugger Robot                 pthread_mutex_unlock(&uevent_handler_list_lock);
93*79330504STreehugger Robot 
94*79330504STreehugger Robot                 return count;
95*79330504STreehugger Robot             }
96*79330504STreehugger Robot         }
97*79330504STreehugger Robot     }
98*79330504STreehugger Robot 
99*79330504STreehugger Robot     // won't get here
100*79330504STreehugger Robot     return 0;
101*79330504STreehugger Robot }
102*79330504STreehugger Robot 
uevent_add_native_handler(void (* handler)(void * data,const char * msg,int msg_len),void * handler_data)103*79330504STreehugger Robot int uevent_add_native_handler(void (*handler)(void *data, const char *msg, int msg_len),
104*79330504STreehugger Robot                              void *handler_data)
105*79330504STreehugger Robot {
106*79330504STreehugger Robot     struct uevent_handler *h;
107*79330504STreehugger Robot 
108*79330504STreehugger Robot     h = malloc(sizeof(struct uevent_handler));
109*79330504STreehugger Robot     if (h == NULL)
110*79330504STreehugger Robot         return -1;
111*79330504STreehugger Robot     h->handler = handler;
112*79330504STreehugger Robot     h->handler_data = handler_data;
113*79330504STreehugger Robot 
114*79330504STreehugger Robot     pthread_mutex_lock(&uevent_handler_list_lock);
115*79330504STreehugger Robot     LIST_INSERT_HEAD(&uevent_handler_list, h, list);
116*79330504STreehugger Robot     pthread_mutex_unlock(&uevent_handler_list_lock);
117*79330504STreehugger Robot 
118*79330504STreehugger Robot     return 0;
119*79330504STreehugger Robot }
120*79330504STreehugger Robot 
uevent_remove_native_handler(void (* handler)(void * data,const char * msg,int msg_len))121*79330504STreehugger Robot int uevent_remove_native_handler(void (*handler)(void *data, const char *msg, int msg_len))
122*79330504STreehugger Robot {
123*79330504STreehugger Robot     struct uevent_handler *h;
124*79330504STreehugger Robot     int err = -1;
125*79330504STreehugger Robot 
126*79330504STreehugger Robot     pthread_mutex_lock(&uevent_handler_list_lock);
127*79330504STreehugger Robot     LIST_FOREACH(h, &uevent_handler_list, list) {
128*79330504STreehugger Robot         if (h->handler == handler) {
129*79330504STreehugger Robot             LIST_REMOVE(h, list);
130*79330504STreehugger Robot             err = 0;
131*79330504STreehugger Robot             break;
132*79330504STreehugger Robot        }
133*79330504STreehugger Robot     }
134*79330504STreehugger Robot     pthread_mutex_unlock(&uevent_handler_list_lock);
135*79330504STreehugger Robot 
136*79330504STreehugger Robot     return err;
137*79330504STreehugger Robot }
138