1 /*
2 *
3 * BlueZ - Bluetooth protocol stack for Linux
4 *
5 * Copyright (C) 2006-2010 Nokia Corporation
6 * Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
7 * Copyright (C) 2005-2007 Johan Hedberg <johan.hedberg@nokia.com>
8 *
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 *
24 */
25
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29
30 #include <stdio.h>
31 #include <errno.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35 #include <sys/ioctl.h>
36
37 #include <bluetooth/bluetooth.h>
38
39 #include <glib.h>
40 #include <dbus/dbus.h>
41 #include <gdbus.h>
42
43 #include "log.h"
44
45 #include "adapter.h"
46 #include "manager.h"
47 #include "event.h"
48 #include "dbus-common.h"
49
50 static DBusConnection *connection = NULL;
51
append_variant(DBusMessageIter * iter,int type,void * val)52 static void append_variant(DBusMessageIter *iter, int type, void *val)
53 {
54 DBusMessageIter value;
55 char sig[2] = { type, '\0' };
56
57 dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, sig, &value);
58
59 dbus_message_iter_append_basic(&value, type, val);
60
61 dbus_message_iter_close_container(iter, &value);
62 }
63
append_array_variant(DBusMessageIter * iter,int type,void * val,int n_elements)64 static void append_array_variant(DBusMessageIter *iter, int type, void *val,
65 int n_elements)
66 {
67 DBusMessageIter variant, array;
68 char type_sig[2] = { type, '\0' };
69 char array_sig[3] = { DBUS_TYPE_ARRAY, type, '\0' };
70
71 dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
72 array_sig, &variant);
73
74 dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY,
75 type_sig, &array);
76
77 if (dbus_type_is_fixed(type) == TRUE) {
78 dbus_message_iter_append_fixed_array(&array, type, val,
79 n_elements);
80 } else if (type == DBUS_TYPE_STRING || type == DBUS_TYPE_OBJECT_PATH) {
81 const char ***str_array = val;
82 int i;
83
84 for (i = 0; i < n_elements; i++)
85 dbus_message_iter_append_basic(&array, type,
86 &((*str_array)[i]));
87 }
88
89 dbus_message_iter_close_container(&variant, &array);
90
91 dbus_message_iter_close_container(iter, &variant);
92 }
93
dict_append_entry(DBusMessageIter * dict,const char * key,int type,void * val)94 void dict_append_entry(DBusMessageIter *dict,
95 const char *key, int type, void *val)
96 {
97 DBusMessageIter entry;
98
99 if (type == DBUS_TYPE_STRING) {
100 const char *str = *((const char **) val);
101 if (str == NULL)
102 return;
103 }
104
105 dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
106 NULL, &entry);
107
108 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
109
110 append_variant(&entry, type, val);
111
112 dbus_message_iter_close_container(dict, &entry);
113 }
114
dict_append_array(DBusMessageIter * dict,const char * key,int type,void * val,int n_elements)115 void dict_append_array(DBusMessageIter *dict, const char *key, int type,
116 void *val, int n_elements)
117 {
118 DBusMessageIter entry;
119
120 dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
121 NULL, &entry);
122
123 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
124
125 append_array_variant(&entry, type, val, n_elements);
126
127 dbus_message_iter_close_container(dict, &entry);
128 }
129
emit_property_changed(DBusConnection * conn,const char * path,const char * interface,const char * name,int type,void * value)130 dbus_bool_t emit_property_changed(DBusConnection *conn,
131 const char *path,
132 const char *interface,
133 const char *name,
134 int type, void *value)
135 {
136 DBusMessage *signal;
137 DBusMessageIter iter;
138
139 signal = dbus_message_new_signal(path, interface, "PropertyChanged");
140
141 if (!signal) {
142 error("Unable to allocate new %s.PropertyChanged signal",
143 interface);
144 return FALSE;
145 }
146
147 dbus_message_iter_init_append(signal, &iter);
148
149 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);
150
151 append_variant(&iter, type, value);
152
153 return g_dbus_send_message(conn, signal);
154 }
155
emit_array_property_changed(DBusConnection * conn,const char * path,const char * interface,const char * name,int type,void * value,int num)156 dbus_bool_t emit_array_property_changed(DBusConnection *conn,
157 const char *path,
158 const char *interface,
159 const char *name,
160 int type, void *value, int num)
161 {
162 DBusMessage *signal;
163 DBusMessageIter iter;
164
165 signal = dbus_message_new_signal(path, interface, "PropertyChanged");
166
167 if (!signal) {
168 error("Unable to allocate new %s.PropertyChanged signal",
169 interface);
170 return FALSE;
171 }
172
173 dbus_message_iter_init_append(signal, &iter);
174
175 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);
176
177 append_array_variant(&iter, type, value, num);
178
179 return g_dbus_send_message(conn, signal);
180 }
181
set_dbus_connection(DBusConnection * conn)182 void set_dbus_connection(DBusConnection *conn)
183 {
184 connection = conn;
185 }
186
get_dbus_connection(void)187 DBusConnection *get_dbus_connection(void)
188 {
189 return connection;
190 }
191
class_to_icon(uint32_t class)192 const char *class_to_icon(uint32_t class)
193 {
194 switch ((class & 0x1f00) >> 8) {
195 case 0x01:
196 return "computer";
197 case 0x02:
198 switch ((class & 0xfc) >> 2) {
199 case 0x01:
200 case 0x02:
201 case 0x03:
202 case 0x05:
203 return "phone";
204 case 0x04:
205 return "modem";
206 }
207 break;
208 case 0x03:
209 return "network-wireless";
210 case 0x04:
211 switch ((class & 0xfc) >> 2) {
212 case 0x01:
213 case 0x02:
214 return "audio-card"; /* Headset */
215 case 0x06:
216 return "audio-card"; /* Headphone */
217 case 0x0b: /* VCR */
218 case 0x0c: /* Video Camera */
219 case 0x0d: /* Camcorder */
220 return "camera-video";
221 default:
222 return "audio-card"; /* Other audio device */
223 }
224 break;
225 case 0x05:
226 switch ((class & 0xc0) >> 6) {
227 case 0x00:
228 switch ((class & 0x1e) >> 2) {
229 case 0x01:
230 case 0x02:
231 return "input-gaming";
232 }
233 break;
234 case 0x01:
235 return "input-keyboard";
236 case 0x02:
237 switch ((class & 0x1e) >> 2) {
238 case 0x05:
239 return "input-tablet";
240 default:
241 return "input-mouse";
242 }
243 }
244 break;
245 case 0x06:
246 if (class & 0x80)
247 return "printer";
248 if (class & 0x20)
249 return "camera-photo";
250 break;
251 }
252
253 return NULL;
254 }
255