1 /* Copyright (c) 2012 The Chromium OS 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 #include <assert.h> 6 #include <libudev.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <string.h> 10 #include <unistd.h> 11 #include <errno.h> 12 #include <sys/stat.h> 13 #include <sys/types.h> 14 #include <regex.h> 15 #include <syslog.h> 16 17 #include "cras_system_state.h" 18 #include "cras_types.h" 19 #include "cras_util.h" 20 #include "cras_checksum.h" 21 22 struct udev_callback_data { 23 struct udev_monitor *mon; 24 struct udev *udev; 25 int fd; 26 }; 27 28 static unsigned is_action(const char *desired, 29 const char *actual) __attribute__((nonnull(1))); 30 31 /* Matches Alsa sound device entries generated by udev. For 32 * example: 33 * 34 * /devices/pci0000:00/0000:00:1b.0/sound/card1/pcmC1D0p 35 * 36 * We want to be able to extract: 37 * 38 * o The card number 39 * o The device number 40 * o If it's 'playback' (p) or 'capture' (c). (It may not be both.) 41 * 42 * Given the example above, the following matches should occur: 43 * 44 * 45 * | A | 46 * BBCCCD 47 * /devices/pci0000:00/0000:00:1b.0/sound/card1/pcmC1D10p 48 * 49 * A: The whole regex will be matched. 50 * B: The card. 51 * C: The device. 52 * D: 'p' (playback) or 'c' (capture) 53 * 54 * The order of the offsets in the 'pmatch' buffer does not appear 55 * to match with the documentation: 56 * 57 * Each rm_so element that is not -1 indicates the start 58 * offset of the next largest substring match within the 59 * string. 60 * 61 * But are, instead, filled in the same order presented in the 62 * string. To alleviate possible issudes, the 'C' (card) and 'D' 63 * (device) identifying characters are included in the result. 64 */ 65 static const char pcm_regex_string[] = "^.*pcm(C[0-9]+)(D[0-9]+)([pc])"; 66 static regex_t pcm_regex; 67 68 /* Card regex is similar to above, but only has one field -- the card. The 69 * format is the same with the exception of the leaf node being of the form: 70 * 71 * /devices/...../card0 72 * 73 * Where 0 is the card number and the only thing we care about in 74 * this case. 75 */ 76 77 static const char card_regex_string[] = "^.*/card([0-9]+)"; 78 static regex_t card_regex; 79 80 static char const * const subsystem = "sound"; 81 static const unsigned int MAX_DESC_NAME_LEN = 256; 82 83 static unsigned is_action(const char *desired, const char *actual) 84 { 85 return actual != NULL && strcmp(desired, actual) == 0; 86 } 87 88 static unsigned is_action_change(const char *action) 89 { 90 return is_action("change", action); 91 } 92 93 static unsigned is_action_remove(const char *action) 94 { 95 return is_action("remove", action); 96 } 97 98 static unsigned is_internal_bus(const char *bus) 99 { 100 return (bus != NULL && 101 (strcmp(bus, "pci") == 0 || 102 strcmp(bus, "platform") == 0)); 103 } 104 105 static unsigned is_external_bus(const char *bus) 106 { 107 return (bus != NULL && (strcmp(bus, "usb") == 0)); 108 } 109 110 static unsigned is_internal_device(struct udev_device *dev) 111 { 112 struct udev_device *parent = udev_device_get_parent(dev); 113 while (parent != NULL) { 114 const char *name = udev_device_get_subsystem(parent); 115 116 if (name != NULL) { 117 if (is_external_bus(name)) 118 return 0; 119 else if (is_internal_bus(name)) 120 return 1; 121 } 122 parent = udev_device_get_parent(parent); 123 } 124 return 0; 125 } 126 127 static unsigned is_card_device(struct udev_device *dev, 128 unsigned *internal, 129 unsigned *card_number, 130 const char **sysname) 131 { 132 regmatch_t m[2]; 133 const char *devpath = udev_device_get_devpath(dev); 134 135 if (devpath != NULL && 136 regexec(&card_regex, devpath, ARRAY_SIZE(m), m, 0) == 0) { 137 *sysname = udev_device_get_sysname(dev); 138 *internal = is_internal_device(dev); 139 *card_number = (unsigned)atoi(&devpath[m[1].rm_so]); 140 return 1; 141 } 142 143 return 0; 144 } 145 146 static void set_factory_default(unsigned card_number) 147 { 148 static const char alsactl[] = "/usr/sbin/alsactl"; 149 static const char asound_state[] = "/etc/asound.state"; 150 char cmd_buf[128]; 151 struct stat stat_buf; 152 int r; 153 154 if (stat(asound_state, &stat_buf) == 0) { 155 syslog(LOG_INFO, "%s: init card '%u' to factory default", 156 __FUNCTION__, card_number); 157 r = snprintf(cmd_buf, ARRAY_SIZE(cmd_buf), 158 "%s --file %s restore %u", 159 alsactl, asound_state, card_number); 160 cmd_buf[ARRAY_SIZE(cmd_buf) - 1] = '\0'; 161 r = system(cmd_buf); 162 if (r != 0) 163 syslog(LOG_ERR, 164 "%s: failed to init card '%d' " 165 "to factory default. Failure: %d. Command: %s", 166 __FUNCTION__, card_number, r, cmd_buf); 167 } 168 } 169 170 static inline void udev_delay_for_alsa() 171 { 172 /* Provide a small delay so that the udev message can 173 * propogate throughout the whole system, and Alsa can set up 174 * the new device. Without a small delay, an error of the 175 * form: 176 * 177 * Fail opening control hw:? 178 * 179 * will be produced by cras_alsa_card_create(). 180 */ 181 usleep(125000); /* 0.125 second */ 182 } 183 184 /* Reads the "descriptors" file of the usb device and returns the 185 * checksum of the contents. Returns 0 if the file can not be read */ 186 static uint32_t calculate_desc_checksum(struct udev_device *dev) 187 { 188 char path[MAX_DESC_NAME_LEN]; 189 struct stat stat_buf; 190 int fd; 191 unsigned char *buf = NULL; 192 int buf_size = 0; 193 int read_size; 194 ssize_t n; 195 uint32_t result; 196 197 if (snprintf(path, sizeof(path), "%s/descriptors", 198 udev_device_get_syspath(dev)) >= sizeof(path)) { 199 syslog(LOG_ERR, "failed to build path"); 200 return 0; 201 } 202 203 if (stat(path, &stat_buf) < 0) { 204 syslog(LOG_ERR, "failed to stat file %s: %s", 205 path, strerror(errno)); 206 return 0; 207 } 208 209 fd = open(path, O_RDONLY); 210 if (fd < 0) { 211 syslog(LOG_ERR, "failed to open file %s: %s", 212 path, strerror(errno)); 213 return 0; 214 } 215 216 read_size = 0; 217 while (read_size < stat_buf.st_size) { 218 if (read_size == buf_size) { 219 if (buf_size == 0) 220 buf_size = 256; 221 else 222 buf_size *= 2; 223 uint8_t *new_buf = realloc(buf, buf_size); 224 if (new_buf == NULL) { 225 syslog(LOG_ERR, 226 "no memory to read file %s", path); 227 goto bail; 228 } 229 buf = new_buf; 230 } 231 n = read(fd, buf + read_size, buf_size - read_size); 232 if (n == 0) 233 break; 234 if (n < 0) { 235 syslog(LOG_ERR, "failed to read file %s", path); 236 goto bail; 237 } 238 read_size += n; 239 } 240 241 close(fd); 242 result = crc32_checksum(buf, read_size); 243 free(buf); 244 return result; 245 bail: 246 close(fd); 247 free(buf); 248 return 0; 249 } 250 251 static void fill_usb_card_info(struct cras_alsa_card_info *card_info, 252 struct udev_device *dev) 253 { 254 const char *sysattr; 255 struct udev_device *parent_dev = 256 udev_device_get_parent_with_subsystem_devtype(dev, 257 "usb", 258 "usb_device"); 259 if (!parent_dev) 260 return; 261 262 sysattr = udev_device_get_sysattr_value(parent_dev, "idVendor"); 263 if (sysattr) 264 card_info->usb_vendor_id = strtol(sysattr, NULL, 16); 265 sysattr = udev_device_get_sysattr_value(parent_dev, "idProduct"); 266 if (sysattr) 267 card_info->usb_product_id = strtol(sysattr, NULL, 16); 268 sysattr = udev_device_get_sysattr_value(parent_dev, "serial"); 269 if (sysattr) { 270 strncpy(card_info->usb_serial_number, sysattr, 271 USB_SERIAL_NUMBER_BUFFER_SIZE - 1); 272 card_info->usb_serial_number[USB_SERIAL_NUMBER_BUFFER_SIZE - 1] 273 = '\0'; 274 } 275 276 card_info->usb_desc_checksum = calculate_desc_checksum(parent_dev); 277 278 syslog(LOG_ERR, "USB card: vendor:%04x, product:%04x, serial num:%s, " 279 "checksum:%08x", 280 card_info->usb_vendor_id, card_info->usb_product_id, 281 card_info->usb_serial_number, card_info->usb_desc_checksum); 282 } 283 284 static void device_add_alsa(struct udev_device *dev, 285 const char *sysname, 286 unsigned card, 287 unsigned internal) 288 { 289 struct cras_alsa_card_info card_info; 290 memset(&card_info, 0, sizeof(card_info)); 291 292 udev_delay_for_alsa(); 293 card_info.card_index = card; 294 if (internal) { 295 card_info.card_type = ALSA_CARD_TYPE_INTERNAL; 296 } else { 297 card_info.card_type = ALSA_CARD_TYPE_USB; 298 fill_usb_card_info(&card_info, dev); 299 } 300 301 cras_system_add_alsa_card(&card_info); 302 } 303 304 void device_remove_alsa(const char *sysname, unsigned card) 305 { 306 udev_delay_for_alsa(); 307 cras_system_remove_alsa_card(card); 308 } 309 310 static int udev_sound_initialized(struct udev_device *dev) 311 { 312 /* udev will set SOUND_INITALIZED=1 for the main card node when the 313 * system has already been initialized, i.e. when cras is restarted 314 * on an already running system. 315 */ 316 const char *s; 317 318 s = udev_device_get_property_value(dev, "SOUND_INITIALIZED"); 319 if (s) 320 return 1; 321 322 return 0; 323 } 324 325 static void change_udev_device_if_alsa_device(struct udev_device *dev) 326 { 327 /* If the device, 'dev' is an alsa device, add it to the set of 328 * devices available for I/O. Mark it as the active device. 329 */ 330 unsigned internal; 331 unsigned card_number; 332 const char *sysname; 333 334 if (is_card_device(dev, &internal, &card_number, &sysname) && 335 udev_sound_initialized(dev) && 336 !cras_system_alsa_card_exists(card_number)) { 337 if (internal) 338 set_factory_default(card_number); 339 device_add_alsa(dev, sysname, card_number, internal); 340 } 341 } 342 343 static void remove_device_if_card(struct udev_device *dev) 344 { 345 unsigned internal; 346 unsigned card_number; 347 const char *sysname; 348 349 if (is_card_device(dev, &internal, &card_number, &sysname)) 350 device_remove_alsa(sysname, card_number); 351 } 352 353 static void enumerate_devices(struct udev_callback_data *data) 354 { 355 struct udev_enumerate *enumerate = udev_enumerate_new(data->udev); 356 struct udev_list_entry *dl; 357 struct udev_list_entry *dev_list_entry; 358 359 udev_enumerate_add_match_subsystem(enumerate, subsystem); 360 udev_enumerate_scan_devices(enumerate); 361 dl = udev_enumerate_get_list_entry(enumerate); 362 363 udev_list_entry_foreach(dev_list_entry, dl) { 364 const char *path = udev_list_entry_get_name(dev_list_entry); 365 struct udev_device *dev = 366 udev_device_new_from_syspath(data->udev, path); 367 368 change_udev_device_if_alsa_device(dev); 369 udev_device_unref(dev); 370 } 371 udev_enumerate_unref(enumerate); 372 } 373 374 static void udev_sound_subsystem_callback(void *arg) 375 { 376 struct udev_callback_data *data = (struct udev_callback_data *)arg; 377 struct udev_device *dev; 378 379 dev = udev_monitor_receive_device(data->mon); 380 if (dev) { 381 const char *action = udev_device_get_action(dev); 382 383 if (is_action_change(action)) 384 change_udev_device_if_alsa_device(dev); 385 else if (is_action_remove(action)) 386 remove_device_if_card(dev); 387 udev_device_unref(dev); 388 } else 389 syslog(LOG_WARNING, 390 "%s (internal error): " 391 "No device obtained", __FUNCTION__); 392 } 393 394 static void compile_regex(regex_t *regex, const char *str) 395 { 396 int r = regcomp(regex, str, REG_EXTENDED); 397 assert(r == 0); 398 } 399 400 static struct udev_callback_data udev_data; 401 void cras_udev_start_sound_subsystem_monitor() 402 { 403 int r; 404 405 udev_data.udev = udev_new(); 406 assert(udev_data.udev != NULL); 407 udev_data.mon = udev_monitor_new_from_netlink(udev_data.udev, "udev"); 408 409 udev_monitor_filter_add_match_subsystem_devtype(udev_data.mon, 410 subsystem, NULL); 411 udev_monitor_enable_receiving(udev_data.mon); 412 udev_data.fd = udev_monitor_get_fd(udev_data.mon); 413 414 r = cras_system_add_select_fd(udev_data.fd, 415 udev_sound_subsystem_callback, 416 &udev_data); 417 assert(r == 0); 418 compile_regex(&pcm_regex, pcm_regex_string); 419 compile_regex(&card_regex, card_regex_string); 420 421 enumerate_devices(&udev_data); 422 } 423 424 void cras_udev_stop_sound_subsystem_monitor() 425 { 426 udev_unref(udev_data.udev); 427 regfree(&pcm_regex); 428 regfree(&card_regex); 429 } 430