Add support for Update method via D-Bus
[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         { "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->netdev.index = libhal_device_get_property_int(ctx,
89                                                 udi, "net.linux.ifindex", NULL);
90
91                 element->netdev.name = libhal_device_get_property_string(ctx,
92                                                 udi, "net.interface", NULL);
93         }
94
95         if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_MODEM) {
96                 element->netdev.index = libhal_device_get_property_int(ctx,
97                                                 udi, "serial.port", NULL);
98
99                 element->netdev.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();
112
113         element->name = g_path_get_basename(udi);
114         element->type = CONNMAN_ELEMENT_TYPE_DEVICE;
115         element->subtype = subtype;
116
117         device_info(ctx, udi, element);
118         device_netdev(ctx, udi, element);
119
120         g_static_mutex_lock(&element_mutex);
121
122         connman_element_register(element, NULL);
123
124         element_list = g_slist_append(element_list, element);
125
126         g_static_mutex_unlock(&element_mutex);
127 }
128
129 static void device_added(LibHalContext *ctx, const char *udi)
130 {
131         int i;
132
133         DBG("ctx %p udi %s", ctx, udi);
134
135         for (i = 0; capabilities[i].name; i++) {
136                 if (libhal_device_query_capability(ctx, udi,
137                                         capabilities[i].name, NULL) == TRUE)
138                         create_element(ctx, udi, capabilities[i].subtype);
139         }
140 }
141
142 static void device_removed(LibHalContext *ctx, const char *udi)
143 {
144         GSList *list;
145         gchar *name;
146
147         DBG("ctx %p udi %s", ctx, udi);
148
149         name = g_path_get_basename(udi);
150
151         g_static_mutex_lock(&element_mutex);
152
153         for (list = element_list; list; list = list->next) {
154                 struct connman_element *element = list->data;
155
156                 if (g_str_equal(element->name, name) == TRUE) {
157                         element_list = g_slist_remove(element_list, element);
158
159                         connman_element_unregister(element);
160                         connman_element_unref(element);
161                         break;
162                 }
163         }
164
165         g_static_mutex_unlock(&element_mutex);
166
167         g_free(name);
168 }
169
170 static void probe_capability(LibHalContext *ctx, const char *capability,
171                                         enum connman_element_subtype subtype)
172 {
173         char **list;
174         int num;
175
176         DBG("ctx %p capability %s", ctx, capability);
177
178         list = libhal_find_device_by_capability(ctx, capability, &num, NULL);
179         if (list) {
180                 char **tmp = list;
181
182                 while (*tmp) {
183                         create_element(ctx, *tmp, subtype);
184                         tmp++;
185                 }
186
187                 libhal_free_string_array(list);
188         }
189 }
190
191 static void find_devices(LibHalContext *ctx)
192 {
193         int i;
194
195         DBG("ctx %p", ctx);
196
197         for (i = 0; capabilities[i].name; i++)
198                 probe_capability(ctx, capabilities[i].name,
199                                                 capabilities[i].subtype);
200 }
201
202 static LibHalContext *hal_ctx = NULL;
203
204 static void libhal_init(void *data)
205 {
206         DBusConnection *conn = data;
207
208         DBG("conn %p", conn);
209
210         if (hal_ctx != NULL)
211                 return;
212
213         hal_ctx = libhal_ctx_new();
214         if (hal_ctx == NULL)
215                 return;
216
217         if (libhal_ctx_set_dbus_connection(hal_ctx, conn) == FALSE) {
218                 libhal_ctx_free(hal_ctx);
219                 return;
220         }
221
222         if (libhal_ctx_init(hal_ctx, NULL) == FALSE) {
223                 libhal_ctx_free(hal_ctx);
224                 return ;
225         }
226
227         libhal_ctx_set_device_added(hal_ctx, device_added);
228         libhal_ctx_set_device_removed(hal_ctx, device_removed);
229
230         //libhal_ctx_set_device_new_capability(hal_ctx, new_capability);
231         //libhal_ctx_set_device_lost_capability(hal_ctx, lost_capability);
232
233         find_devices(hal_ctx);
234 }
235
236 static void libhal_cleanup(void *data)
237 {
238         DBusConnection *conn = data;
239         GSList *list;
240
241         DBG("conn %p", conn);
242
243         g_static_mutex_lock(&element_mutex);
244
245         for (list = element_list; list; list = list->next) {
246                 struct connman_element *element = list->data;
247
248                 connman_element_unregister(element);
249                 connman_element_unref(element);
250         }
251
252         g_slist_free(element_list);
253         element_list = NULL;
254
255         g_static_mutex_unlock(&element_mutex);
256
257         if (hal_ctx == NULL)
258                 return;
259
260         libhal_ctx_shutdown(hal_ctx, NULL);
261
262         libhal_ctx_free(hal_ctx);
263
264         hal_ctx = NULL;
265 }
266
267 static int hal_init(void)
268 {
269         DBusConnection *conn;
270
271         conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
272         if (conn == NULL)
273                 return -EIO;
274
275         libhal_init(conn);
276
277         return 0;
278 }
279
280 static void hal_exit(void)
281 {
282         DBusConnection *conn;
283
284         conn = libhal_ctx_get_dbus_connection(hal_ctx);
285         if (conn == NULL)
286                 return;
287
288         libhal_cleanup(conn);
289
290         dbus_connection_unref(conn);
291 }
292
293 CONNMAN_PLUGIN_DEFINE("HAL", "Hardware detection plugin", VERSION,
294                                                         hal_init, hal_exit)