Use element->index and element->name variables
[connman] / 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         { "modem",     CONNMAN_ELEMENT_SUBTYPE_MODEM    },
40         { }
41 };
42
43 static GStaticMutex element_mutex = G_STATIC_MUTEX_INIT;
44 static GSList *element_list = NULL;
45
46 static void device_info(LibHalContext *ctx, const char *udi,
47                                         struct connman_element *element)
48 {
49         char *parent, *subsys, *value;
50
51         parent = libhal_device_get_property_string(ctx, udi,
52                                                 "info.parent", NULL);
53
54         subsys = libhal_device_get_property_string(ctx, udi,
55                                                 "linux.subsystem", NULL);
56
57         value = libhal_device_get_property_string(ctx, udi,
58                                                 "info.linux.driver", NULL);
59         if (value == NULL) {
60                 value = libhal_device_get_property_string(ctx, parent,
61                                                 "info.linux.driver", NULL);
62                 if (value != NULL)
63                         connman_element_add_static_property(element,
64                                         "Driver", DBUS_TYPE_STRING, &value);
65         }
66
67         if (g_str_equal(subsys, "net") == TRUE ||
68                                         g_str_equal(subsys, "tty") == TRUE) {
69                 value = libhal_device_get_property_string(ctx, parent,
70                                                         "info.vendor", NULL);
71                 if (value != NULL)
72                         connman_element_add_static_property(element,
73                                         "Vendor", DBUS_TYPE_STRING, &value);
74
75                 value = libhal_device_get_property_string(ctx, parent,
76                                                         "info.product", NULL);
77                 if (value != NULL)
78                         connman_element_add_static_property(element,
79                                         "Product", DBUS_TYPE_STRING, &value);
80         }
81 }
82
83 static void device_netdev(LibHalContext *ctx, const char *udi,
84                                         struct connman_element *element)
85 {
86         if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_ETHERNET ||
87                         element->subtype == CONNMAN_ELEMENT_SUBTYPE_WIFI) {
88                 element->index = libhal_device_get_property_int(ctx,
89                                                 udi, "net.linux.ifindex", NULL);
90
91                 element->name = libhal_device_get_property_string(ctx,
92                                                 udi, "net.interface", NULL);
93         }
94
95         if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_MODEM) {
96                 element->index = libhal_device_get_property_int(ctx,
97                                                 udi, "serial.port", NULL);
98
99                 element->name = libhal_device_get_property_string(ctx,
100                                                 udi, "serial.device", NULL);
101         }
102 }
103
104 static void create_element(LibHalContext *ctx, const char *udi,
105                                         enum connman_element_subtype subtype)
106 {
107         struct connman_element *element;
108
109         DBG("ctx %p udi %s", ctx, udi);
110
111         element = connman_element_create(NULL);
112
113         element->type = CONNMAN_ELEMENT_TYPE_DEVICE;
114         element->subtype = subtype;
115
116         device_info(ctx, udi, element);
117         device_netdev(ctx, udi, element);
118
119         if (element->name == NULL) {
120                 element->name = g_path_get_basename(udi);
121                 if (element->name == NULL) {
122                         connman_element_unref(element);
123                         return;
124                 }
125         }
126
127         g_static_mutex_lock(&element_mutex);
128
129         connman_element_register(element, NULL);
130
131         element_list = g_slist_append(element_list, element);
132
133         g_static_mutex_unlock(&element_mutex);
134 }
135
136 static void device_added(LibHalContext *ctx, const char *udi)
137 {
138         int i;
139
140         DBG("ctx %p udi %s", ctx, udi);
141
142         for (i = 0; capabilities[i].name; i++) {
143                 if (libhal_device_query_capability(ctx, udi,
144                                         capabilities[i].name, NULL) == TRUE)
145                         create_element(ctx, udi, capabilities[i].subtype);
146         }
147 }
148
149 static void device_removed(LibHalContext *ctx, const char *udi)
150 {
151         GSList *list;
152         gchar *name;
153
154         DBG("ctx %p udi %s", ctx, udi);
155
156         name = g_path_get_basename(udi);
157
158         g_static_mutex_lock(&element_mutex);
159
160         for (list = element_list; list; list = list->next) {
161                 struct connman_element *element = list->data;
162
163                 if (g_str_equal(element->name, name) == TRUE) {
164                         element_list = g_slist_remove(element_list, element);
165
166                         connman_element_unregister(element);
167                         connman_element_unref(element);
168                         break;
169                 }
170         }
171
172         g_static_mutex_unlock(&element_mutex);
173
174         g_free(name);
175 }
176
177 static void probe_capability(LibHalContext *ctx, const char *capability,
178                                         enum connman_element_subtype subtype)
179 {
180         char **list;
181         int num;
182
183         DBG("ctx %p capability %s", ctx, capability);
184
185         list = libhal_find_device_by_capability(ctx, capability, &num, NULL);
186         if (list) {
187                 char **tmp = list;
188
189                 while (*tmp) {
190                         create_element(ctx, *tmp, subtype);
191                         tmp++;
192                 }
193
194                 libhal_free_string_array(list);
195         }
196 }
197
198 static void find_devices(LibHalContext *ctx)
199 {
200         int i;
201
202         DBG("ctx %p", ctx);
203
204         for (i = 0; capabilities[i].name; i++)
205                 probe_capability(ctx, capabilities[i].name,
206                                                 capabilities[i].subtype);
207 }
208
209 static LibHalContext *hal_ctx = NULL;
210
211 static void libhal_init(void *data)
212 {
213         DBusConnection *conn = data;
214
215         DBG("conn %p", conn);
216
217         if (hal_ctx != NULL)
218                 return;
219
220         hal_ctx = libhal_ctx_new();
221         if (hal_ctx == NULL)
222                 return;
223
224         if (libhal_ctx_set_dbus_connection(hal_ctx, conn) == FALSE) {
225                 libhal_ctx_free(hal_ctx);
226                 return;
227         }
228
229         if (libhal_ctx_init(hal_ctx, NULL) == FALSE) {
230                 libhal_ctx_free(hal_ctx);
231                 return ;
232         }
233
234         libhal_ctx_set_device_added(hal_ctx, device_added);
235         libhal_ctx_set_device_removed(hal_ctx, device_removed);
236
237         //libhal_ctx_set_device_new_capability(hal_ctx, new_capability);
238         //libhal_ctx_set_device_lost_capability(hal_ctx, lost_capability);
239
240         find_devices(hal_ctx);
241 }
242
243 static void libhal_cleanup(void *data)
244 {
245         DBusConnection *conn = data;
246         GSList *list;
247
248         DBG("conn %p", conn);
249
250         g_static_mutex_lock(&element_mutex);
251
252         for (list = element_list; list; list = list->next) {
253                 struct connman_element *element = list->data;
254
255                 connman_element_unregister(element);
256                 connman_element_unref(element);
257         }
258
259         g_slist_free(element_list);
260         element_list = NULL;
261
262         g_static_mutex_unlock(&element_mutex);
263
264         if (hal_ctx == NULL)
265                 return;
266
267         libhal_ctx_shutdown(hal_ctx, NULL);
268
269         libhal_ctx_free(hal_ctx);
270
271         hal_ctx = NULL;
272 }
273
274 static int hal_init(void)
275 {
276         DBusConnection *conn;
277
278         conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
279         if (conn == NULL)
280                 return -EIO;
281
282         libhal_init(conn);
283
284         return 0;
285 }
286
287 static void hal_exit(void)
288 {
289         DBusConnection *conn;
290
291         conn = libhal_ctx_get_dbus_connection(hal_ctx);
292         if (conn == NULL)
293                 return;
294
295         libhal_cleanup(conn);
296
297         dbus_connection_unref(conn);
298 }
299
300 CONNMAN_PLUGIN_DEFINE("hal", "Hardware detection plugin", VERSION,
301                                                         hal_init, hal_exit)