bb5ad94d6978ed485f0efe246ff8a1b99a81f022
[platform/upstream/connman.git] / plugins / hal.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2008  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <dbus/dbus.h>
27 #include <hal/libhal.h>
28
29 #include <connman/plugin.h>
30 #include <connman/element.h>
31 #include <connman/log.h>
32
33 static struct {
34         const char *name;
35         enum connman_element_subtype subtype;
36 } capabilities[] = {
37         { "net.80203", CONNMAN_ELEMENT_SUBTYPE_ETHERNET },
38         { "net.80211", CONNMAN_ELEMENT_SUBTYPE_WIFI     },
39         { }
40 };
41
42 static GStaticMutex element_mutex = G_STATIC_MUTEX_INIT;
43 static GSList *element_list = NULL;
44
45 static void device_info(LibHalContext *ctx, const char *udi,
46                                         struct connman_element *element)
47 {
48         char *parent, *subsys, *value;
49
50         parent = libhal_device_get_property_string(ctx, udi,
51                                                 "info.parent", NULL);
52
53         subsys = libhal_device_get_property_string(ctx, udi,
54                                                 "linux.subsystem", NULL);
55
56         value = libhal_device_get_property_string(ctx, udi,
57                                                 "info.linux.driver", NULL);
58         if (value == NULL) {
59                 value = libhal_device_get_property_string(ctx, parent,
60                                                 "info.linux.driver", NULL);
61                 if (value != NULL)
62                         element->info.driver = g_strdup(value);
63         }
64
65         if (g_str_equal(subsys, "net") == TRUE) {
66                 value = libhal_device_get_property_string(ctx, parent,
67                                                         "info.vendor", NULL);
68                 if (value != NULL)
69                         element->info.vendor = g_strdup(value);
70
71                 value = libhal_device_get_property_string(ctx, parent,
72                                                         "info.product", NULL);
73                 if (value != NULL)
74                         element->info.product = g_strdup(value);
75         }
76 }
77
78 static void device_netdev(LibHalContext *ctx, const char *udi,
79                                         struct connman_element *element)
80 {
81         if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_ETHERNET ||
82                         element->subtype == CONNMAN_ELEMENT_SUBTYPE_WIFI) {
83                 element->netdev.index = libhal_device_get_property_int(ctx,
84                                                 udi, "net.linux.ifindex", NULL);
85
86                 element->netdev.name = libhal_device_get_property_string(ctx,
87                                                 udi, "net.interface", NULL);
88         }
89 }
90
91 static void create_element(LibHalContext *ctx, const char *udi,
92                                         enum connman_element_subtype subtype)
93 {
94         struct connman_element *element;
95
96         DBG("ctx %p udi %s", ctx, udi);
97
98         element = connman_element_create();
99
100         element->name = g_path_get_basename(udi);
101         element->type = CONNMAN_ELEMENT_TYPE_DEVICE;
102         element->subtype = subtype;
103
104         device_info(ctx, udi, element);
105         device_netdev(ctx, udi, element);
106
107         g_static_mutex_lock(&element_mutex);
108
109         connman_element_register(element, NULL);
110
111         element_list = g_slist_append(element_list, element);
112
113         g_static_mutex_unlock(&element_mutex);
114 }
115
116 static void device_added(LibHalContext *ctx, const char *udi)
117 {
118         int i;
119
120         DBG("ctx %p udi %s", ctx, udi);
121
122         for (i = 0; capabilities[i].name; i++) {
123                 if (libhal_device_query_capability(ctx, udi,
124                                         capabilities[i].name, NULL) == TRUE)
125                         create_element(ctx, udi, capabilities[i].subtype);
126         }
127 }
128
129 static void device_removed(LibHalContext *ctx, const char *udi)
130 {
131         GSList *list;
132         gchar *name;
133
134         DBG("ctx %p udi %s", ctx, udi);
135
136         name = g_path_get_basename(udi);
137
138         g_static_mutex_lock(&element_mutex);
139
140         for (list = element_list; list; list = list->next) {
141                 struct connman_element *element = list->data;
142
143                 if (g_str_equal(element->name, name) == TRUE) {
144                         element_list = g_slist_remove(element_list, element);
145
146                         connman_element_unregister(element);
147                         connman_element_unref(element);
148                         break;
149                 }
150         }
151
152         g_static_mutex_unlock(&element_mutex);
153
154         g_free(name);
155 }
156
157 static void probe_capability(LibHalContext *ctx, const char *capability,
158                                         enum connman_element_subtype subtype)
159 {
160         char **list;
161         int num;
162
163         DBG("ctx %p capability %s", ctx, capability);
164
165         list = libhal_find_device_by_capability(ctx, capability, &num, NULL);
166         if (list) {
167                 char **tmp = list;
168
169                 while (*tmp) {
170                         create_element(ctx, *tmp, subtype);
171                         tmp++;
172                 }
173
174                 libhal_free_string_array(list);
175         }
176 }
177
178 static void find_devices(LibHalContext *ctx)
179 {
180         int i;
181
182         DBG("ctx %p", ctx);
183
184         for (i = 0; capabilities[i].name; i++)
185                 probe_capability(ctx, capabilities[i].name,
186                                                 capabilities[i].subtype);
187 }
188
189 static LibHalContext *hal_ctx = NULL;
190
191 static void libhal_init(void *data)
192 {
193         DBusConnection *conn = data;
194
195         DBG("conn %p", conn);
196
197         if (hal_ctx != NULL)
198                 return;
199
200         hal_ctx = libhal_ctx_new();
201         if (hal_ctx == NULL)
202                 return;
203
204         if (libhal_ctx_set_dbus_connection(hal_ctx, conn) == FALSE) {
205                 libhal_ctx_free(hal_ctx);
206                 return;
207         }
208
209         if (libhal_ctx_init(hal_ctx, NULL) == FALSE) {
210                 libhal_ctx_free(hal_ctx);
211                 return ;
212         }
213
214         libhal_ctx_set_device_added(hal_ctx, device_added);
215         libhal_ctx_set_device_removed(hal_ctx, device_removed);
216
217         //libhal_ctx_set_device_new_capability(hal_ctx, new_capability);
218         //libhal_ctx_set_device_lost_capability(hal_ctx, lost_capability);
219
220         find_devices(hal_ctx);
221 }
222
223 static void libhal_cleanup(void *data)
224 {
225         DBusConnection *conn = data;
226         GSList *list;
227
228         DBG("conn %p", conn);
229
230         g_static_mutex_lock(&element_mutex);
231
232         for (list = element_list; list; list = list->next) {
233                 struct connman_element *element = list->data;
234
235                 connman_element_unregister(element);
236                 connman_element_unref(element);
237         }
238
239         g_slist_free(element_list);
240         element_list = NULL;
241
242         g_static_mutex_unlock(&element_mutex);
243
244         if (hal_ctx == NULL)
245                 return;
246
247         libhal_ctx_shutdown(hal_ctx, NULL);
248
249         libhal_ctx_free(hal_ctx);
250
251         hal_ctx = NULL;
252 }
253
254 static int hal_init(void)
255 {
256         DBusConnection *conn;
257
258         conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
259         if (conn == NULL)
260                 return -EIO;
261
262         libhal_init(conn);
263
264         return 0;
265 }
266
267 static void hal_exit(void)
268 {
269         DBusConnection *conn;
270
271         conn = libhal_ctx_get_dbus_connection(hal_ctx);
272         if (conn == NULL)
273                 return;
274
275         libhal_cleanup(conn);
276
277         dbus_connection_unref(conn);
278 }
279
280 CONNMAN_PLUGIN_DEFINE("HAL", "Hardware detection plugin", VERSION,
281                                                         hal_init, hal_exit)