cras_bt_adapter.c revision 1668d94b1813ef49aae6dfce1d59fbeeafbf1b80
1/* Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 * Use of this source code is governed by a BSD-style license that can be 3 * found in the LICENSE file. 4 */ 5 6#include <dbus/dbus.h> 7 8#include <errno.h> 9#include <stdint.h> 10#include <stdlib.h> 11#include <string.h> 12#include <syslog.h> 13#include <sys/socket.h> 14#include <sys/ioctl.h> 15 16#include "bluetooth.h" 17#include "cras_bt_adapter.h" 18#include "cras_bt_constants.h" 19#include "utlist.h" 20 21struct cras_bt_adapter { 22 char *object_path; 23 char *address; 24 char *name; 25 uint32_t bluetooth_class; 26 int powered; 27 int bus_type; 28 29 struct cras_bt_adapter *prev, *next; 30}; 31 32static struct cras_bt_adapter *adapters; 33 34static int cras_bt_adapter_query_bus_type(struct cras_bt_adapter *adapter) 35{ 36 static const char *hci_str = "hci"; 37 struct hci_dev_info dev_info; 38 char *pos; 39 int ctl, err; 40 41 /* Object path [variable prefix]/{hci0,hci1,...} */ 42 pos = strstr(adapter->object_path, hci_str); 43 if (!pos) 44 return -1; 45 46 ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); 47 if (ctl < 0) { 48 syslog(LOG_ERR, "Error creating HCI ctl socket"); 49 return -1; 50 } 51 52 /* dev_id = 0 for hci0 */ 53 dev_info.dev_id = atoi(pos + 3); 54 err = ioctl(ctl, HCIGETDEVINFO, (void *)&dev_info); 55 if (err) { 56 syslog(LOG_ERR, "HCI get dev info error %s", strerror(errno)); 57 close(ctl); 58 return -1; 59 } 60 if ((dev_info.type & 0x0f) < HCI_BUS_MAX) 61 adapter->bus_type = (dev_info.type & 0x0f); 62 63 close(ctl); 64 return 0; 65} 66 67struct cras_bt_adapter *cras_bt_adapter_create(const char *object_path) 68{ 69 struct cras_bt_adapter *adapter; 70 71 adapter = calloc(1, sizeof(*adapter)); 72 if (adapter == NULL) 73 return NULL; 74 75 adapter->object_path = strdup(object_path); 76 if (adapter->object_path == NULL) { 77 free(adapter); 78 return NULL; 79 } 80 81 DL_APPEND(adapters, adapter); 82 83 /* Set bus type to USB as default when query fails. */ 84 if (cras_bt_adapter_query_bus_type(adapter)) 85 adapter->bus_type = HCI_USB; 86 87 return adapter; 88} 89 90void cras_bt_adapter_destroy(struct cras_bt_adapter *adapter) 91{ 92 DL_DELETE(adapters, adapter); 93 94 free(adapter->object_path); 95 free(adapter->address); 96 free(adapter->name); 97 free(adapter); 98} 99 100void cras_bt_adapter_reset() 101{ 102 while (adapters) { 103 syslog(LOG_INFO, "Bluetooth Adapter: %s removed", 104 adapters->address); 105 cras_bt_adapter_destroy(adapters); 106 } 107} 108 109 110struct cras_bt_adapter *cras_bt_adapter_get(const char *object_path) 111{ 112 struct cras_bt_adapter *adapter; 113 114 DL_FOREACH(adapters, adapter) { 115 if (strcmp(adapter->object_path, object_path) == 0) 116 return adapter; 117 } 118 119 return NULL; 120} 121 122size_t cras_bt_adapter_get_list(struct cras_bt_adapter ***adapter_list_out) 123{ 124 struct cras_bt_adapter *adapter; 125 struct cras_bt_adapter **adapter_list = NULL; 126 size_t num_adapters = 0; 127 128 DL_FOREACH(adapters, adapter) { 129 struct cras_bt_adapter **tmp; 130 131 tmp = realloc(adapter_list, 132 sizeof(adapter_list[0]) * (num_adapters + 1)); 133 if (!tmp) { 134 free(adapter_list); 135 return -ENOMEM; 136 } 137 138 adapter_list = tmp; 139 adapter_list[num_adapters++] = adapter; 140 } 141 142 *adapter_list_out = adapter_list; 143 return num_adapters; 144} 145 146const char *cras_bt_adapter_object_path(const struct cras_bt_adapter *adapter) 147{ 148 return adapter->object_path; 149} 150 151const char *cras_bt_adapter_address(const struct cras_bt_adapter *adapter) 152{ 153 return adapter->address; 154} 155 156const char *cras_bt_adapter_name(const struct cras_bt_adapter *adapter) 157{ 158 return adapter->name; 159} 160 161int cras_bt_adapter_powered(const struct cras_bt_adapter *adapter) 162{ 163 return adapter->powered; 164} 165 166 167void cras_bt_adapter_update_properties(struct cras_bt_adapter *adapter, 168 DBusMessageIter *properties_array_iter, 169 DBusMessageIter *invalidated_array_iter) 170{ 171 while (dbus_message_iter_get_arg_type(properties_array_iter) != 172 DBUS_TYPE_INVALID) { 173 DBusMessageIter properties_dict_iter, variant_iter; 174 const char *key; 175 int type; 176 177 dbus_message_iter_recurse(properties_array_iter, 178 &properties_dict_iter); 179 180 dbus_message_iter_get_basic(&properties_dict_iter, &key); 181 dbus_message_iter_next(&properties_dict_iter); 182 183 dbus_message_iter_recurse(&properties_dict_iter, &variant_iter); 184 type = dbus_message_iter_get_arg_type(&variant_iter); 185 186 if (type == DBUS_TYPE_STRING) { 187 const char *value; 188 189 dbus_message_iter_get_basic(&variant_iter, &value); 190 191 if (strcmp(key, "Address") == 0) { 192 free(adapter->address); 193 adapter->address = strdup(value); 194 195 } else if (strcmp(key, "Alias") == 0) { 196 free(adapter->name); 197 adapter->name = strdup(value); 198 199 } 200 201 } else if (type == DBUS_TYPE_UINT32) { 202 uint32_t value; 203 204 dbus_message_iter_get_basic(&variant_iter, &value); 205 206 if (strcmp(key, "Class") == 0) 207 adapter->bluetooth_class = value; 208 209 } else if (type == DBUS_TYPE_BOOLEAN) { 210 int value; 211 212 dbus_message_iter_get_basic(&variant_iter, &value); 213 214 if (strcmp(key, "Powered") == 0) 215 adapter->powered = value; 216 217 } 218 219 dbus_message_iter_next(properties_array_iter); 220 } 221 222 while (invalidated_array_iter && 223 dbus_message_iter_get_arg_type(invalidated_array_iter) != 224 DBUS_TYPE_INVALID) { 225 const char *key; 226 227 dbus_message_iter_get_basic(invalidated_array_iter, &key); 228 229 if (strcmp(key, "Address") == 0) { 230 free(adapter->address); 231 adapter->address = NULL; 232 } else if (strcmp(key, "Alias") == 0) { 233 free(adapter->name); 234 adapter->name = NULL; 235 } else if (strcmp(key, "Class") == 0) { 236 adapter->bluetooth_class = 0; 237 } else if (strcmp(key, "Powered") == 0) { 238 adapter->powered = 0; 239 } 240 241 dbus_message_iter_next(invalidated_array_iter); 242 } 243} 244 245int cras_bt_adapter_on_usb(struct cras_bt_adapter *adapter) 246{ 247 return !!(adapter->bus_type == HCI_USB); 248}