Home | History | Annotate | Download | only in server
      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