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 (at) holtmann.org> 7 * Copyright (C) 2005-2007 Johan Hedberg <johan.hedberg (at) 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 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 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 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 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 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 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 182 void set_dbus_connection(DBusConnection *conn) 183 { 184 connection = conn; 185 } 186 187 DBusConnection *get_dbus_connection(void) 188 { 189 return connection; 190 } 191 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