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 
6 #include <alsa/asoundlib.h>
7 #include <linux/input.h>
8 #include <regex.h>
9 #include <syslog.h>
10 
11 #include "cras_alsa_jack.h"
12 #include "cras_alsa_mixer.h"
13 #include "cras_alsa_ucm.h"
14 #include "cras_system_state.h"
15 #include "cras_gpio_jack.h"
16 #include "cras_tm.h"
17 #include "cras_util.h"
18 #include "edid_utils.h"
19 #include "utlist.h"
20 
21 static const unsigned int DISPLAY_INFO_RETRY_DELAY_MS = 200;
22 static const unsigned int DISPLAY_INFO_MAX_RETRIES = 10;
23 static const unsigned int DISPLAY_INFO_GPIO_MAX_RETRIES = 25;
24 
25 /* Constants used to retrieve monitor name from ELD buffer. */
26 static const unsigned int ELD_MNL_MASK = 31;
27 static const unsigned int ELD_MNL_OFFSET = 4;
28 static const unsigned int ELD_MONITOR_NAME_OFFSET = 20;
29 
30 /* Keeps an fd that is registered with system settings.  A list of fds must be
31  * kept so that they can be removed when the jack list is destroyed. */
32 struct jack_poll_fd {
33 	int fd;
34 	struct jack_poll_fd *prev, *next;
35 };
36 
37 /* cras_gpio_jack:  Describes headphone & microphone jack connected to GPIO
38  *
39  *   On Arm-based systems, the headphone & microphone jacks are
40  *   connected to GPIOs which are plumbed through the /dev/input/event
41  *   system.  For these jacks, the software is written to open the
42  *   corresponding /dev/input/event file and monitor it for 'insert' &
43  *   'remove' activity.
44  *
45  *   fd           : File descriptor corresponding to the /dev/input/event file.
46  *
47  *   switch_event : Indicates the type of the /dev/input/event file.
48  *                  Either SW_HEADPHONE_INSERT, or SW_MICROPHONE_INSERT.
49  *
50  *   current_state: 0 -> device not plugged in
51  *                  1 -> device plugged in
52  *   device_name  : Device name extracted from /dev/input/event[0..9]+.
53  *                  Allocated on heap; must free.
54  */
55 struct cras_gpio_jack {
56 	int fd;
57 	unsigned switch_event;
58 	unsigned current_state;
59 	char *device_name;
60 };
61 
62 /* Represents a single alsa Jack, e.g. "Headphone Jack" or "Mic Jack".
63  *    is_gpio: 1 -> gpio switch (union field: gpio)
64  *             0 -> Alsa 'jack' (union field: elem)
65  *    elem - alsa hcontrol element for this jack, when is_gpio == 0.
66  *    gpio - description of gpio-based jack, when is_gpio != 0.
67  *    eld_control - mixer control for ELD info buffer.
68  *    jack_list - list of jacks this belongs to.
69  *    mixer_output - mixer output control used to control audio to this jack.
70  *        This will be null for input jacks.
71  *    mixer_input - mixer input control used to control audio to this jack.
72  *        This will be null for output jacks.
73  *    ucm_device - Name of the ucm device if found, otherwise, NULL.
74  *    edid_file - File to read the EDID from (if available, HDMI only).
75  *    display_info_timer - Timer used to poll display info for HDMI jacks.
76  *    display_info_retries - Number of times to retry reading display info.
77  *
78  *    mixer_output/mixer_input fields are only used to find the node for this
79  *    jack. These are not used for setting volume or mute. There should be a
80  *    1:1 map between node and jack. node->jack follows the pointer; jack->node
81  *    is done by either searching node->jack pointers or searching the node that
82  *    has the same mixer_control as the jack.
83  */
84 struct cras_alsa_jack {
85 	unsigned is_gpio;	/* !0 -> 'gpio' valid
86 				 *  0 -> 'elem' valid
87 				 */
88 	union {
89 		snd_hctl_elem_t *elem;
90 		struct cras_gpio_jack gpio;
91 	};
92 
93 	snd_hctl_elem_t *eld_control;
94 	struct cras_alsa_jack_list *jack_list;
95 	struct mixer_control *mixer_output;
96 	struct mixer_control *mixer_input;
97 	char *ucm_device;
98 	const char *dsp_name;
99 	const char* override_type_name;
100 	const char *edid_file;
101 	struct cras_timer *display_info_timer;
102 	unsigned int display_info_retries;
103 	struct cras_alsa_jack *prev, *next;
104 };
105 
106 /* Contains all Jacks for a given device.
107  *    hctl - alsa hcontrol for this device's card
108  *         - not opened by the jack list.
109  *    mixer - cras mixer for the card providing this device.
110  *    ucm - CRAS use case manager if available.
111  *    card_index - Index ALSA uses to refer to the card.  The X in "hw:X".
112  *    card_name - The name of the card.
113  *    device_index - Index ALSA uses to refer to the device.  The Y in "hw:X,Y".
114  *    is_first_device - whether this device is the first device on the card.
115  *    direction - Input or output.
116  *    change_callback - function to call when the state of a jack changes.
117  *    callback_data - data to pass back to the callback.
118  *    jacks - list of jacks for this device.
119  */
120 struct cras_alsa_jack_list {
121 	snd_hctl_t *hctl;
122 	struct cras_alsa_mixer *mixer;
123 	struct cras_use_case_mgr *ucm;
124 	unsigned int card_index;
125 	const char *card_name;
126 	size_t device_index;
127 	int is_first_device;
128 	enum CRAS_STREAM_DIRECTION direction;
129 	jack_state_change_callback *change_callback;
130 	void *callback_data;
131 	struct cras_alsa_jack *jacks;
132 };
133 
134 /* Used to contain information needed while looking through GPIO jacks.
135  *    jack_list - The current jack_list.
136  *    section - An associated UCM section.
137  *    result_jack - The resulting jack.
138  *    rc - The return code for the operation.
139  */
140 struct gpio_switch_list_data {
141 	struct cras_alsa_jack_list *jack_list;
142 	struct ucm_section *section;
143 	struct cras_alsa_jack *result_jack;
144 	int rc;
145 };
146 
147 /*
148  * Local Helpers.
149  */
150 
151 #define BITS_PER_BYTE		(8)
152 #define BITS_PER_LONG		(sizeof(long) * BITS_PER_BYTE)
153 #define NBITS(x)		((((x) - 1) / BITS_PER_LONG) + 1)
154 #define OFF(x)			((x) % BITS_PER_LONG)
155 #define BIT(x)			(1UL << OFF(x))
156 #define LONG(x)			((x) / BITS_PER_LONG)
157 #define IS_BIT_SET(bit, array)	!!((array[LONG(bit)]) & (1UL << OFF(bit)))
158 
sys_input_get_switch_state(int fd,unsigned sw,unsigned * state)159 static int sys_input_get_switch_state(int fd, unsigned sw, unsigned *state)
160 {
161 	unsigned long bits[NBITS(SW_CNT)];
162 	const unsigned long switch_no = sw;
163 
164 	memset(bits, '\0', sizeof(bits));
165 	/* If switch event present & supported, get current state. */
166 	if (gpio_switch_eviocgbit(fd, bits, sizeof(bits)) < 0)
167 		return -EIO;
168 
169 	if (IS_BIT_SET(switch_no, bits))
170 		if (gpio_switch_eviocgsw(fd, bits, sizeof(bits)) >= 0) {
171 			*state = IS_BIT_SET(switch_no, bits);
172 			return 0;
173 		}
174 
175 	return -1;
176 }
177 
cras_alloc_jack(int is_gpio)178 static inline struct cras_alsa_jack *cras_alloc_jack(int is_gpio)
179 {
180 	struct cras_alsa_jack *jack = calloc(1, sizeof(*jack));
181 	if (jack == NULL)
182 		return NULL;
183 	jack->is_gpio = is_gpio;
184 	return jack;
185 }
186 
cras_free_jack(struct cras_alsa_jack * jack,int rm_select_fd)187 static void cras_free_jack(struct cras_alsa_jack *jack,
188 			   int rm_select_fd)
189 {
190 	if (!jack)
191 		return;
192 
193 	free(jack->ucm_device);
194 	free((void *)jack->edid_file);
195 	if (jack->display_info_timer)
196 		cras_tm_cancel_timer(cras_system_state_get_tm(),
197 				     jack->display_info_timer);
198 
199 	if (jack->is_gpio) {
200 		free(jack->gpio.device_name);
201 		if (jack->gpio.fd >= 0) {
202 			if (rm_select_fd)
203 				cras_system_rm_select_fd(jack->gpio.fd);
204 			close(jack->gpio.fd);
205 		}
206 	}
207 
208 	/*
209 	 * Remove the jack callback set on hctl. Otherwise, snd_hctl_close will
210 	 * trigger a callback while iodev might already be destroyed.
211 	 */
212 	if (!jack->is_gpio && jack->elem)
213 		snd_hctl_elem_set_callback(jack->elem, NULL);
214 
215 	free((void *)jack->override_type_name);
216 	free((void *)jack->dsp_name);
217 	free(jack);
218 }
219 
220 /* Gets the current plug state of the jack */
get_jack_current_state(struct cras_alsa_jack * jack)221 static int get_jack_current_state(struct cras_alsa_jack *jack)
222 {
223 	snd_ctl_elem_value_t *elem_value;
224 
225 	if (jack->is_gpio)
226 		return jack->gpio.current_state;
227 
228 	snd_ctl_elem_value_alloca(&elem_value);
229 	snd_hctl_elem_read(jack->elem, elem_value);
230 
231 	return snd_ctl_elem_value_get_boolean(elem_value, 0);
232 }
233 
read_jack_edid(const struct cras_alsa_jack * jack,uint8_t * edid)234 static int read_jack_edid(const struct cras_alsa_jack *jack, uint8_t *edid)
235 {
236 	int fd, nread;
237 
238 	fd = open(jack->edid_file, O_RDONLY);
239 	if (fd < 0)
240 		return -1;
241 
242 	nread = read(fd, edid, EEDID_SIZE);
243 	close(fd);
244 
245 	if (nread < EDID_SIZE || !edid_valid(edid))
246 		return -1;
247 	return 0;
248 }
249 
check_jack_edid(struct cras_alsa_jack * jack)250 static int check_jack_edid(struct cras_alsa_jack *jack)
251 {
252 	uint8_t edid[EEDID_SIZE];
253 
254 	if (read_jack_edid(jack, edid))
255 		return -1;
256 
257 	/* If the jack supports EDID, check that it supports audio, clearing
258 	 * the plugged state if it doesn't.
259 	 */
260 	if (!edid_lpcm_support(edid, edid[EDID_EXT_FLAG]))
261 		jack->gpio.current_state = 0;
262 	return 0;
263 }
264 
get_jack_edid_monitor_name(const struct cras_alsa_jack * jack,char * buf,unsigned int buf_size)265 static int get_jack_edid_monitor_name(const struct cras_alsa_jack *jack,
266 				      char *buf,
267 				      unsigned int buf_size)
268 {
269 	uint8_t edid[EEDID_SIZE];
270 
271 	if (read_jack_edid(jack, edid))
272 		return -1;
273 
274 	return edid_get_monitor_name(edid, buf, buf_size);
275 }
276 
277 /* Checks the ELD control of the jack to see if the ELD buffer
278  * is ready to read and report the plug status.
279  */
check_jack_eld(struct cras_alsa_jack * jack)280 static int check_jack_eld(struct cras_alsa_jack *jack)
281 {
282 	snd_ctl_elem_info_t *elem_info;
283 	snd_ctl_elem_info_alloca(&elem_info);
284 
285 	/* Poll ELD control by getting the count of ELD buffer.
286 	 * When seeing zero buffer count, retry after a delay until
287 	 * it's ready or reached the max number of retries. */
288 	if (snd_hctl_elem_info(jack->eld_control, elem_info) != 0)
289 		return -1;
290 	if (snd_ctl_elem_info_get_count(elem_info) == 0)
291 		return -1;
292 	return 0;
293 }
294 
295 static void display_info_delay_cb(struct cras_timer *timer, void *arg);
296 
297 /* Callback function doing following things:
298  * 1. Reset timer and update max number of retries.
299  * 2. Check all conditions to see if it's okay or needed to
300  *    report jack status directly. E.g. jack is unplugged or
301  *    EDID is not ready for some reason.
302  * 3. Check if max number of retries is reached and decide
303  *    to set timer for next callback or report jack state.
304  */
jack_state_change_cb(struct cras_alsa_jack * jack,int retry)305 static inline void jack_state_change_cb(struct cras_alsa_jack *jack, int retry)
306 {
307 	struct cras_tm *tm = cras_system_state_get_tm();
308 
309 	if (jack->display_info_timer) {
310 		cras_tm_cancel_timer(tm, jack->display_info_timer);
311 		jack->display_info_timer = NULL;
312 	}
313 	if (retry) {
314 		jack->display_info_retries =
315 				jack->is_gpio ? DISPLAY_INFO_GPIO_MAX_RETRIES
316 					      : DISPLAY_INFO_MAX_RETRIES;
317 	}
318 
319 	if (!get_jack_current_state(jack))
320 		goto report_jack_state;
321 
322 	/* If there is an edid file, check it.  If it is ready continue, if we
323 	 * need to try again later, return here as the timer has been armed and
324 	 * will check again later.
325 	 */
326 	if (jack->edid_file == NULL && jack->eld_control == NULL)
327 		goto report_jack_state;
328 	if (jack->edid_file && (check_jack_edid(jack) == 0))
329 		goto report_jack_state;
330 	if (jack->eld_control && (check_jack_eld(jack) == 0))
331 		goto report_jack_state;
332 
333 	if (--jack->display_info_retries == 0) {
334 		if (jack->is_gpio)
335 			jack->gpio.current_state = 0;
336 		if (jack->edid_file)
337 			syslog(LOG_ERR, "Timeout to read EDID from %s",
338 			       jack->edid_file);
339 		goto report_jack_state;
340 	}
341 
342 	jack->display_info_timer = cras_tm_create_timer(tm,
343 						DISPLAY_INFO_RETRY_DELAY_MS,
344 						display_info_delay_cb, jack);
345 	return;
346 
347 report_jack_state:
348 	jack->jack_list->change_callback(jack,
349 					 get_jack_current_state(jack),
350 					 jack->jack_list->callback_data);
351 }
352 
353 /* gpio_switch_initial_state
354  *
355  *   Determines the initial state of a gpio-based switch.
356  */
gpio_switch_initial_state(struct cras_alsa_jack * jack)357 static void gpio_switch_initial_state(struct cras_alsa_jack *jack)
358 {
359 	unsigned v;
360 	int r = sys_input_get_switch_state(jack->gpio.fd,
361 					   jack->gpio.switch_event, &v);
362 	jack->gpio.current_state = r == 0 ? v : 0;
363 	jack_state_change_cb(jack, 1);
364 }
365 
366 /* Check if the input event is an audio switch event. */
is_audio_switch_event(const struct input_event * ev,int sw_code)367 static inline int is_audio_switch_event(const struct input_event *ev,
368 					int sw_code)
369 {
370 	return (ev->type == EV_SW && ev->code == sw_code);
371 }
372 
373 /* Timer callback to read display info after a hotplug event for an HDMI jack.
374  */
display_info_delay_cb(struct cras_timer * timer,void * arg)375 static void display_info_delay_cb(struct cras_timer *timer, void *arg)
376 {
377 	struct cras_alsa_jack *jack = (struct cras_alsa_jack *)arg;
378 
379 	jack->display_info_timer = NULL;
380 	jack_state_change_cb(jack, 0);
381 }
382 
383 /* gpio_switch_callback
384  *
385  *   This callback is invoked whenever the associated /dev/input/event
386  *   file has data to read.  Perform autoswitching to / from the
387  *   associated device when data is available.
388  */
gpio_switch_callback(void * arg)389 static void gpio_switch_callback(void *arg)
390 {
391 	struct cras_alsa_jack *jack = arg;
392 	int i;
393 	int r;
394 	struct input_event ev[64];
395 
396 	r = gpio_switch_read(jack->gpio.fd, ev,
397 			     ARRAY_SIZE(ev) * sizeof(struct input_event));
398 	if (r < 0)
399 		return;
400 
401 	for (i = 0; i < r / sizeof(struct input_event); ++i)
402 		if (is_audio_switch_event(&ev[i], jack->gpio.switch_event)) {
403 			jack->gpio.current_state = ev[i].value;
404 
405 			jack_state_change_cb(jack, 1);
406 		}
407 }
408 
409 /* Determines if the GPIO jack should be associated with the device of the
410  * jack list. If the device name is not specified in UCM (common case),
411  * assume it should be associated with the first input device or the first
412  * output device on the card.
413  */
gpio_jack_match_device(const struct cras_alsa_jack * jack,struct cras_alsa_jack_list * jack_list,const char * card_name,enum CRAS_STREAM_DIRECTION direction)414 static unsigned int gpio_jack_match_device(const struct cras_alsa_jack *jack,
415 			struct cras_alsa_jack_list* jack_list,
416 			const char *card_name,
417 			enum CRAS_STREAM_DIRECTION direction)
418 {
419 	const char* target_device_name = NULL;
420 	char current_device_name[CRAS_IODEV_NAME_BUFFER_SIZE];
421 	unsigned int rc;
422 
423 	/* If the device name is not specified in UCM, assume it should be
424 	 * associated with device 0. */
425 	if (!jack_list->ucm || !jack->ucm_device)
426 		return jack_list->is_first_device;
427 
428 	/* Look for device name specified in a device section of UCM. */
429 	target_device_name = ucm_get_device_name_for_dev(
430 				jack_list->ucm, jack->ucm_device, direction);
431 
432 	if (!target_device_name)
433 		return jack_list->is_first_device;
434 
435 	syslog(LOG_DEBUG, "Matching GPIO jack, target device name: %s, "
436 	       "current card name: %s, device index: %zu\n",
437 		target_device_name, card_name, jack_list->device_index);
438 
439 	/* Device name of format "hw:<card_name>,<device_index>", should fit
440 	 * in the string of size CRAS_IODEV_NAME_BUFFER_SIZE.*/
441 	snprintf(current_device_name,
442 		 sizeof(current_device_name),
443 		 "hw:%s,%zu",
444 		 card_name,
445 		 jack_list->device_index);
446 
447 	rc = !strcmp(current_device_name, target_device_name);
448 	free((void*)target_device_name);
449 	return rc;
450 }
451 
create_jack_for_gpio(struct cras_alsa_jack_list * jack_list,const char * pathname,const char * dev_name,unsigned switch_event,struct cras_alsa_jack ** out_jack)452 static int create_jack_for_gpio(struct cras_alsa_jack_list *jack_list,
453 				const char *pathname,
454 				const char *dev_name,
455 				unsigned switch_event,
456 				struct cras_alsa_jack **out_jack)
457 {
458 	struct cras_alsa_jack *jack;
459 	unsigned long bits[NBITS(SW_CNT)];
460 	const char *card_name = jack_list->card_name;
461 	int r;
462 
463 	if (!out_jack)
464 		return -EINVAL;
465 	*out_jack = NULL;
466 
467 	jack = cras_alloc_jack(1);
468 	if (jack == NULL)
469 		return -ENOMEM;
470 
471 	jack->gpio.fd = gpio_switch_open(pathname);
472 	if (jack->gpio.fd == -1) {
473 		r = -EIO;
474 		goto error;
475 	}
476 
477 	jack->gpio.switch_event = switch_event;
478 	jack->jack_list = jack_list;
479 	jack->gpio.device_name = strdup(dev_name);
480 	if (!jack->gpio.device_name) {
481 		r = -ENOMEM;
482 		goto error;
483 	}
484 
485 	if (!strstr(jack->gpio.device_name, card_name) ||
486 	    (gpio_switch_eviocgbit(jack->gpio.fd, bits, sizeof(bits)) < 0) ||
487 	    !IS_BIT_SET(switch_event, bits)) {
488 		r = -EIO;
489 		goto error;
490 	}
491 
492 	*out_jack = jack;
493 	return 0;
494 
495 error:
496 	/* Not yet registered with system select. */
497 	cras_free_jack(jack, 0);
498 	return r;
499 }
500 
501 /* Take ownership and finish setup of the jack.
502  * Add the jack to the jack_list if everything goes well, or destroy it.
503  */
cras_complete_gpio_jack(struct gpio_switch_list_data * data,struct cras_alsa_jack * jack,unsigned switch_event)504 static int cras_complete_gpio_jack(struct gpio_switch_list_data *data,
505 				   struct cras_alsa_jack *jack,
506 				   unsigned switch_event)
507 {
508 	struct cras_alsa_jack_list *jack_list = data->jack_list;
509 	enum CRAS_STREAM_DIRECTION direction = jack_list->direction;
510 	int r;
511 
512 	if (jack->ucm_device) {
513 		jack->edid_file = ucm_get_edid_file_for_dev(jack_list->ucm,
514 							    jack->ucm_device);
515 		jack->dsp_name = ucm_get_dsp_name(
516 			jack->jack_list->ucm, jack->ucm_device, direction);
517 	}
518 
519 	r = sys_input_get_switch_state(jack->gpio.fd, switch_event,
520 				       &jack->gpio.current_state);
521 	if (r < 0) {
522 		cras_free_jack(jack, 0);
523 		return -EIO;
524 	}
525 	r = cras_system_add_select_fd(jack->gpio.fd,
526 				      gpio_switch_callback, jack);
527 	if (r < 0) {
528 		/* Not yet registered with system select. */
529 		cras_free_jack(jack, 0);
530 		return r;
531 	}
532 
533 	DL_APPEND(jack_list->jacks, jack);
534 	if (!data->result_jack)
535 		data->result_jack = jack;
536 	else if (data->section)
537 		syslog(LOG_ERR,
538 		       "More than one jack for SectionDevice '%s'.",
539 		       data->section->name);
540 	return 0;
541 }
542 
543 /* open_and_monitor_gpio:
544  *
545  *   Opens a /dev/input/event file associated with a headphone /
546  *   microphone jack and watches it for activity.
547  *   Returns 0 when a jack has been successfully added.
548  */
open_and_monitor_gpio(struct gpio_switch_list_data * data,const char * pathname,const char * dev_name,unsigned switch_event)549 static int open_and_monitor_gpio(struct gpio_switch_list_data *data,
550 				 const char *pathname,
551 				 const char *dev_name,
552 				 unsigned switch_event)
553 {
554 	struct cras_alsa_jack *jack;
555 	struct cras_alsa_jack_list *jack_list = data->jack_list;
556 	const char *card_name = jack_list->card_name;
557 	enum CRAS_STREAM_DIRECTION direction = jack_list->direction;
558 	int r;
559 
560 	r = create_jack_for_gpio(jack_list, pathname, dev_name,
561 				 switch_event, &jack);
562 	if (r != 0)
563 		return r;
564 
565 	if (jack_list->ucm)
566 		jack->ucm_device =
567 			ucm_get_dev_for_jack(jack_list->ucm,
568 					     jack->gpio.device_name,
569 					     direction);
570 
571 	if (!gpio_jack_match_device(jack, jack_list, card_name, direction)) {
572 		cras_free_jack(jack, 0);
573 		return -EIO;
574 	}
575 
576 	if (direction == CRAS_STREAM_OUTPUT &&
577 	    (strstr(jack->gpio.device_name, "Headphone") ||
578 	     strstr(jack->gpio.device_name, "Headset")))
579 		jack->mixer_output = cras_alsa_mixer_get_output_matching_name(
580 			jack_list->mixer,
581 			"Headphone");
582 	else if (direction == CRAS_STREAM_OUTPUT &&
583 		 strstr(jack->gpio.device_name, "HDMI"))
584 		jack->mixer_output = cras_alsa_mixer_get_output_matching_name(
585 			jack_list->mixer,
586 			"HDMI");
587 
588 	if (jack->ucm_device && direction == CRAS_STREAM_INPUT) {
589 		char *control_name;
590 		control_name = ucm_get_cap_control(jack->jack_list->ucm,
591 						   jack->ucm_device);
592 		if (control_name)
593 			jack->mixer_input =
594 				cras_alsa_mixer_get_input_matching_name(
595 					jack_list->mixer,
596 					control_name);
597 	}
598 
599 	return cras_complete_gpio_jack(data, jack, switch_event);
600 }
601 
open_and_monitor_gpio_with_section(struct gpio_switch_list_data * data,const char * pathname,unsigned switch_event)602 static int open_and_monitor_gpio_with_section(
603 			struct gpio_switch_list_data *data,
604 			const char *pathname,
605 			unsigned switch_event)
606 {
607 	struct cras_alsa_jack *jack;
608 	struct cras_alsa_jack_list *jack_list = data->jack_list;
609 	struct ucm_section *section = data->section;
610 	enum CRAS_STREAM_DIRECTION direction = jack_list->direction;
611 	int r;
612 
613 	r = create_jack_for_gpio(jack_list, pathname, section->jack_name,
614 				 switch_event, &jack);
615 	if (r != 0)
616 		return r;
617 
618 	jack->ucm_device = strdup(section->name);
619 	if (!jack->ucm_device) {
620 		cras_free_jack(jack, 0);
621 		return -ENOMEM;
622 	}
623 
624 	if (direction == CRAS_STREAM_OUTPUT)
625 		jack->mixer_output = cras_alsa_mixer_get_control_for_section(
626 						jack_list->mixer, section);
627 	else if (direction == CRAS_STREAM_INPUT)
628 		jack->mixer_input = cras_alsa_mixer_get_control_for_section(
629 						jack_list->mixer, section);
630 
631 	return cras_complete_gpio_jack(data, jack, switch_event);
632 }
633 
634 /* Monitor GPIO switches for this jack_list.
635  * Args:
636  *    data - Data for GPIO switch search.
637  *    dev_path - Device full path.
638  *    dev_name - Device name.
639  * Returns:
640  *    0 for success, or negative on error. Assumes success if no jack is
641  *    found, or if the jack could not be accessed.
642  */
gpio_switches_monitor_device(struct gpio_switch_list_data * data,const char * dev_path,const char * dev_name)643 static int gpio_switches_monitor_device(struct gpio_switch_list_data *data,
644 					const char *dev_path,
645 					const char *dev_name)
646 {
647 	static const int out_switches[] = {SW_HEADPHONE_INSERT,
648 					   SW_LINEOUT_INSERT};
649 	static const int in_switches[] = {SW_MICROPHONE_INSERT};
650 	int sw;
651 	const int *switches = out_switches;
652 	int num_switches = ARRAY_SIZE(out_switches);
653 	int success = 1;
654 	int rc = 0;
655 
656 	if (data->section && data->section->jack_switch >= 0) {
657 		switches = &data->section->jack_switch;
658 		num_switches = 1;
659 	}
660 	else if (data->jack_list->direction == CRAS_STREAM_INPUT) {
661 		switches = in_switches;
662 		num_switches = ARRAY_SIZE(in_switches);
663 	}
664 
665 	/* Assume that -EIO is returned for jacks that we shouldn't
666 	 * be looking at, but stop trying if we run into another
667 	 * type of error.
668 	 */
669 	for (sw = 0; (rc == 0 || rc == -EIO)
670 		     && sw < num_switches; sw++) {
671 		if (data->section)
672 			rc = open_and_monitor_gpio_with_section(
673 				data, dev_path, switches[sw]);
674 		else
675 			rc = open_and_monitor_gpio(
676 				data, dev_path, dev_name, switches[sw]);
677 		if (rc != 0 && rc != -EIO)
678 			success = 0;
679 	}
680 
681 	if (success)
682 		return 0;
683 	return rc;
684 }
685 
gpio_switch_list_with_section(const char * dev_path,const char * dev_name,void * arg)686 static int gpio_switch_list_with_section(const char *dev_path,
687 					 const char *dev_name,
688 					 void *arg)
689 {
690 	struct gpio_switch_list_data *data =
691 		(struct gpio_switch_list_data *)arg;
692 
693 	if (strcmp(dev_name, data->section->jack_name)) {
694 		/* No match: continue searching. */
695 		return 0;
696 	}
697 
698 	data->rc = gpio_switches_monitor_device(data, dev_path, dev_name);
699 	/* Found the only possible match: stop searching. */
700 	return 1;
701 }
702 
703 /* Match the given jack name to the given regular expression.
704  * Args:
705  *    jack_name - The jack's name.
706  *    re - Regular expression string.
707  * Returns:
708  *    Non-zero for success, or 0 for failure.
709  */
jack_matches_regex(const char * jack_name,const char * re)710 static int jack_matches_regex(const char *jack_name, const char *re)
711 {
712 	regmatch_t m[1];
713 	regex_t regex;
714 	int rc;
715 
716 	rc = regcomp(&regex, re, REG_EXTENDED);
717 	if (rc != 0) {
718 		syslog(LOG_ERR, "Failed to compile regular expression: %s", re);
719 		return 0;
720 	}
721 
722 	rc = regexec(&regex, jack_name, ARRAY_SIZE(m), m, 0) == 0;
723 	regfree(&regex);
724 	return rc;
725 }
726 
gpio_switch_list_by_matching(const char * dev_path,const char * dev_name,void * arg)727 static int gpio_switch_list_by_matching(const char *dev_path,
728 					const char *dev_name,
729 					void *arg)
730 {
731 	struct gpio_switch_list_data *data =
732 		(struct gpio_switch_list_data *)arg;
733 
734 	if (data->jack_list->direction == CRAS_STREAM_INPUT) {
735 		if (!jack_matches_regex(dev_name, "^.*Mic Jack$") &&
736 		    !jack_matches_regex(dev_name, "^.*Headset Jack$")) {
737 			/* Continue searching. */
738 			return 0;
739 		}
740 	}
741 	else if (data->jack_list->direction == CRAS_STREAM_OUTPUT) {
742 		if (!jack_matches_regex(dev_name, "^.*Headphone Jack$") &&
743 		    !jack_matches_regex(dev_name, "^.*Headset Jack$") &&
744 		    !jack_matches_regex(dev_name, "^.*HDMI Jack$")) {
745 			/* Continue searching. */
746 			return 0;
747 		}
748 	}
749 
750 	data->rc = gpio_switches_monitor_device(data, dev_path, dev_name);
751 	/* Stop searching for failure. */
752 	return data->rc;
753 }
754 
755 /* Find GPIO jacks for this jack_list.
756  * Args:
757  *    jack_list - Jack list to add to.
758  *    section - UCM section.
759  *    result_jack - Filled with a pointer to the resulting cras_alsa_jack.
760  * Returns:
761  *    0 for success, or negative on error. Assumes success if no jack is
762  *    found, or if the jack could not be accessed.
763  */
find_gpio_jacks(struct cras_alsa_jack_list * jack_list,struct ucm_section * section,struct cras_alsa_jack ** result_jack)764 static int find_gpio_jacks(struct cras_alsa_jack_list *jack_list,
765 			   struct ucm_section *section,
766 			   struct cras_alsa_jack **result_jack)
767 {
768 	/* GPIO switches are on Arm-based machines, and are
769 	 * only associated with on-board devices.
770 	 */
771 	struct gpio_switch_list_data data;
772 	int rc;
773 
774 	rc = wait_for_dev_input_access();
775 	if (rc != 0) {
776 		syslog(LOG_WARNING, "Could not access /dev/input/event0: %s",
777 		       strerror(rc));
778 		return 0;
779 	}
780 
781 	data.jack_list = jack_list;
782 	data.section = section;
783 	data.result_jack = NULL;
784 	data.rc = 0;
785 
786 	if (section)
787 		gpio_switch_list_for_each(
788 			gpio_switch_list_with_section, &data);
789 	else
790 		gpio_switch_list_for_each(
791 			gpio_switch_list_by_matching, &data);
792 	if (result_jack)
793 		*result_jack = data.result_jack;
794 	return data.rc;
795 }
796 
797 /* Callback from alsa when a jack control changes.  This is registered with
798  * snd_hctl_elem_set_callback in find_jack_controls and run by calling
799  * snd_hctl_handle_events in alsa_control_event_pending below.
800  * Args:
801  *    elem - The ALSA control element that has changed.
802  *    mask - unused.
803  */
hctl_jack_cb(snd_hctl_elem_t * elem,unsigned int mask)804 static int hctl_jack_cb(snd_hctl_elem_t *elem, unsigned int mask)
805 {
806 	const char *name;
807 	snd_ctl_elem_value_t *elem_value;
808 	struct cras_alsa_jack *jack;
809 
810 	jack = snd_hctl_elem_get_callback_private(elem);
811 	if (jack == NULL) {
812 		syslog(LOG_ERR, "Invalid jack from control event.");
813 		return -EINVAL;
814 	}
815 
816 	snd_ctl_elem_value_alloca(&elem_value);
817 	snd_hctl_elem_read(elem, elem_value);
818 	name = snd_hctl_elem_get_name(elem);
819 
820 	syslog(LOG_DEBUG,
821 	       "Jack %s %s",
822 	       name,
823 	       snd_ctl_elem_value_get_boolean(elem_value, 0) ? "plugged"
824 							     : "unplugged");
825 	jack_state_change_cb(jack, 1);
826 	return 0;
827 }
828 
829 /* Determines the device associated with this jack if any.  If the device cannot
830  * be determined (common case), assume device 0. */
hctl_jack_device_index(const char * name)831 static unsigned int hctl_jack_device_index(const char *name)
832 {
833 	/* Look for the substring 'pcm=<device number>' in the element name. */
834 	static const char pcm_search[] = "pcm=";
835 	const char *substr;
836 	int device_index;
837 
838 	substr = strstr(name, pcm_search);
839 	if (substr == NULL)
840 		return 0;
841 	substr += ARRAY_SIZE(pcm_search) - 1;
842 	if (*substr == '\0')
843 		return 0;
844 	device_index = atoi(substr);
845 	if (device_index < 0)
846 		return 0;
847 	return (unsigned int)device_index;
848 }
849 
850 /* For non-gpio jack, check if it's of type hdmi/dp by
851  * matching jack name. */
is_jack_hdmi_dp(const char * jack_name)852 static int is_jack_hdmi_dp(const char *jack_name)
853 {
854 	static const char *hdmi_dp = "HDMI/DP";
855 	return strncmp(jack_name, hdmi_dp, strlen(hdmi_dp)) == 0;
856 }
857 
858 /* Checks if the given control name is in the supplied list of possible jack
859  * control base names. */
is_jack_control_in_list(const char * const * list,unsigned int list_length,const char * control_name)860 static int is_jack_control_in_list(const char * const *list,
861 				   unsigned int list_length,
862 				   const char *control_name)
863 {
864 	unsigned int i;
865 
866 	for (i = 0; i < list_length; i++)
867 		if (strncmp(control_name, list[i], strlen(list[i])) == 0)
868 			return 1;
869 	return 0;
870 }
871 
872 /* Check if the given name is a jack created for the connector control of a
873  * input/output terminal entity on a USB Audio Class 2.0 device. */
is_jack_uac2(const char * jack_name,enum CRAS_STREAM_DIRECTION direction)874 static int is_jack_uac2(const char *jack_name,
875 			enum CRAS_STREAM_DIRECTION direction)
876 {
877 	return jack_matches_regex(jack_name, direction == CRAS_STREAM_OUTPUT ?
878 				  "^.* - Output Jack$" : "^.* - Input Jack$");
879 }
880 
881 /* Looks for any JACK controls.  Monitors any found controls for changes and
882  * decides to route based on plug/unlpug events. */
find_jack_controls(struct cras_alsa_jack_list * jack_list)883 static int find_jack_controls(struct cras_alsa_jack_list *jack_list)
884 {
885 	snd_hctl_elem_t *elem;
886 	struct cras_alsa_jack *jack;
887 	const char *name;
888 	static const char * const output_jack_base_names[] = {
889 		"Headphone Jack",
890 		"Front Headphone Jack",
891 		"HDMI/DP",
892 		"Speaker Phantom Jack",
893 	};
894 	static const char * const input_jack_base_names[] = {
895 		"Mic Jack",
896 	};
897 	static const char eld_control_name[] = "ELD";
898 	const char * const *jack_names;
899 	unsigned int num_jack_names;
900 
901 	if (!jack_list->hctl) {
902 		syslog(LOG_WARNING, "Can't search hctl for jacks.");
903 		return 0;
904 	}
905 
906 	if (jack_list->direction == CRAS_STREAM_OUTPUT) {
907 		jack_names = output_jack_base_names;
908 		num_jack_names = ARRAY_SIZE(output_jack_base_names);
909 	} else {
910 		jack_names = input_jack_base_names;
911 		num_jack_names = ARRAY_SIZE(input_jack_base_names);
912 	}
913 
914 	for (elem = snd_hctl_first_elem(jack_list->hctl); elem != NULL;
915 			elem = snd_hctl_elem_next(elem)) {
916 		snd_ctl_elem_iface_t iface;
917 
918 		iface = snd_hctl_elem_get_interface(elem);
919 		if (iface != SND_CTL_ELEM_IFACE_CARD)
920 			continue;
921 		name = snd_hctl_elem_get_name(elem);
922 		if (!is_jack_control_in_list(jack_names, num_jack_names, name) &&
923 		    !is_jack_uac2(name, jack_list->direction))
924 			continue;
925 		if (hctl_jack_device_index(name) != jack_list->device_index)
926 			continue;
927 
928 		jack = cras_alloc_jack(0);
929 		if (jack == NULL)
930 			return -ENOMEM;
931 		jack->elem = elem;
932 		jack->jack_list = jack_list;
933 		DL_APPEND(jack_list->jacks, jack);
934 
935 		snd_hctl_elem_set_callback(elem, hctl_jack_cb);
936 		snd_hctl_elem_set_callback_private(elem, jack);
937 
938 		if (jack_list->direction == CRAS_STREAM_OUTPUT)
939 			jack->mixer_output =
940 				cras_alsa_mixer_get_output_matching_name(
941 					jack_list->mixer,
942 					name);
943 		if (jack_list->ucm)
944 			jack->ucm_device =
945 				ucm_get_dev_for_jack(jack_list->ucm, name,
946 						     jack_list->direction);
947 
948 		if (jack->ucm_device && jack_list->direction == CRAS_STREAM_INPUT) {
949 			char *control_name;
950 			control_name = ucm_get_cap_control(jack->jack_list->ucm,
951 						       jack->ucm_device);
952 			if (control_name)
953 				jack->mixer_input =
954 					cras_alsa_mixer_get_input_matching_name(
955 						jack_list->mixer,
956 						control_name);
957 		}
958 
959 		if (jack->ucm_device) {
960 			jack->dsp_name = ucm_get_dsp_name(
961 				jack->jack_list->ucm, jack->ucm_device,
962 				jack_list->direction);
963 			jack->override_type_name = ucm_get_override_type_name(
964 				jack->jack_list->ucm, jack->ucm_device);
965 		}
966 	}
967 
968 	/* Look up ELD controls */
969 	DL_FOREACH(jack_list->jacks, jack) {
970 		if (jack->is_gpio || jack->eld_control)
971 			continue;
972 		name = snd_hctl_elem_get_name(jack->elem);
973 		if (!is_jack_hdmi_dp(name))
974 			continue;
975 		for (elem = snd_hctl_first_elem(jack_list->hctl); elem != NULL;
976 		     elem = snd_hctl_elem_next(elem)) {
977 			if (strcmp(snd_hctl_elem_get_name(elem),
978 				   eld_control_name))
979 				continue;
980 			if (snd_hctl_elem_get_device(elem)
981 			    != jack_list->device_index)
982 				continue;
983 			jack->eld_control = elem;
984 			break;
985 		}
986 	}
987 
988 	return 0;
989 }
990 
991 /*
992  * Exported Interface.
993  */
994 
cras_alsa_jack_list_find_jacks_by_name_matching(struct cras_alsa_jack_list * jack_list)995 int cras_alsa_jack_list_find_jacks_by_name_matching(
996 	struct cras_alsa_jack_list *jack_list)
997 {
998 	int rc;
999 
1000 	rc = find_jack_controls(jack_list);
1001 	if (rc != 0)
1002 		return rc;
1003 
1004 	return find_gpio_jacks(jack_list, NULL, NULL);
1005 }
1006 
find_hctl_jack_for_section(struct cras_alsa_jack_list * jack_list,struct ucm_section * section,struct cras_alsa_jack ** result_jack)1007 static int find_hctl_jack_for_section(
1008 		struct cras_alsa_jack_list *jack_list,
1009 		struct ucm_section *section,
1010 		struct cras_alsa_jack **result_jack)
1011 {
1012 	static const char eld_control_name[] = "ELD";
1013 	snd_hctl_elem_t *elem;
1014 	snd_ctl_elem_id_t *elem_id;
1015 	struct cras_alsa_jack *jack;
1016 
1017 	if (!jack_list->hctl) {
1018 		syslog(LOG_WARNING, "Can't search hctl for jacks.");
1019 		return -ENODEV;
1020 	}
1021 
1022 	snd_ctl_elem_id_alloca(&elem_id);
1023 	snd_ctl_elem_id_clear(elem_id);
1024 	snd_ctl_elem_id_set_interface(elem_id, SND_CTL_ELEM_IFACE_CARD);
1025 	snd_ctl_elem_id_set_device(elem_id, jack_list->device_index);
1026 	snd_ctl_elem_id_set_name(elem_id, section->jack_name);
1027 	elem = snd_hctl_find_elem(jack_list->hctl, elem_id);
1028 	if (!elem)
1029 		return -ENOENT;
1030 
1031 	syslog(LOG_DEBUG, "Found Jack: %s for %s",
1032 	       section->jack_name, section->name);
1033 
1034 	jack = cras_alloc_jack(0);
1035 	if (jack == NULL)
1036 		return -ENOMEM;
1037 	jack->elem = elem;
1038 	jack->jack_list = jack_list;
1039 
1040 	jack->ucm_device = strdup(section->name);
1041 	if (!jack->ucm_device) {
1042 		free(jack);
1043 		return -ENOMEM;
1044 	}
1045 	if (jack_list->direction == CRAS_STREAM_OUTPUT)
1046 		jack->mixer_output = cras_alsa_mixer_get_control_for_section(
1047 					jack_list->mixer, section);
1048 	else if (jack_list->direction == CRAS_STREAM_INPUT)
1049 		jack->mixer_input = cras_alsa_mixer_get_control_for_section(
1050 					jack_list->mixer, section);
1051 
1052 	jack->dsp_name = ucm_get_dsp_name(
1053 		jack->jack_list->ucm, jack->ucm_device,
1054 		jack_list->direction);
1055 
1056 	snd_hctl_elem_set_callback(elem, hctl_jack_cb);
1057 	snd_hctl_elem_set_callback_private(elem, jack);
1058 	DL_APPEND(jack_list->jacks, jack);
1059 	if (result_jack)
1060 		*result_jack = jack;
1061 
1062 	if (!strcmp(jack->ucm_device, "HDMI") ||
1063 	    !strcmp(jack->ucm_device, "DP"))
1064 		return 0;
1065 
1066 	/* Look up ELD control. */
1067 	snd_ctl_elem_id_set_name(elem_id, eld_control_name);
1068 	elem = snd_hctl_find_elem(jack_list->hctl, elem_id);
1069 	if (elem)
1070 		jack->eld_control = elem;
1071 	return 0;
1072 }
1073 
1074 /*
1075  * Exported Interface.
1076  */
1077 
cras_alsa_jack_list_add_jack_for_section(struct cras_alsa_jack_list * jack_list,struct ucm_section * ucm_section,struct cras_alsa_jack ** result_jack)1078 int cras_alsa_jack_list_add_jack_for_section(
1079 	struct cras_alsa_jack_list *jack_list,
1080 	struct ucm_section *ucm_section,
1081 	struct cras_alsa_jack **result_jack)
1082 {
1083 	if (result_jack)
1084 		*result_jack = NULL;
1085 	if (!ucm_section)
1086 		return -EINVAL;
1087 
1088 	if (!ucm_section->jack_name) {
1089 		/* No jacks defined for this device. */
1090 		return 0;
1091 	}
1092 
1093 	if (!ucm_section->jack_type) {
1094 		syslog(LOG_ERR,
1095 		       "Must specify the JackType for jack '%s' in '%s'.",
1096 		       ucm_section->jack_name, ucm_section->name);
1097 		return -EINVAL;
1098 	}
1099 
1100 	if (!strcmp(ucm_section->jack_type, "hctl")) {
1101 		return find_hctl_jack_for_section(
1102 				jack_list, ucm_section, result_jack);
1103 	} else if (!strcmp(ucm_section->jack_type, "gpio")) {
1104 		return find_gpio_jacks(jack_list, ucm_section, result_jack);
1105 	} else {
1106 		syslog(LOG_ERR,
1107 		       "Invalid JackType '%s' in '%s'.",
1108 		       ucm_section->jack_type, ucm_section->name);
1109 		return -EINVAL;
1110 	}
1111 }
1112 
cras_alsa_jack_list_create(unsigned int card_index,const char * card_name,unsigned int device_index,int is_first_device,struct cras_alsa_mixer * mixer,struct cras_use_case_mgr * ucm,snd_hctl_t * hctl,enum CRAS_STREAM_DIRECTION direction,jack_state_change_callback * cb,void * cb_data)1113 struct cras_alsa_jack_list *cras_alsa_jack_list_create(
1114 		unsigned int card_index,
1115 		const char *card_name,
1116 		unsigned int device_index,
1117 		int is_first_device,
1118 		struct cras_alsa_mixer *mixer,
1119 		struct cras_use_case_mgr *ucm,
1120 		snd_hctl_t *hctl,
1121 		enum CRAS_STREAM_DIRECTION direction,
1122 		jack_state_change_callback *cb,
1123 		void *cb_data)
1124 {
1125 	struct cras_alsa_jack_list *jack_list;
1126 
1127 	if (direction != CRAS_STREAM_INPUT && direction != CRAS_STREAM_OUTPUT)
1128 		return NULL;
1129 
1130 	jack_list = (struct cras_alsa_jack_list *)calloc(1, sizeof(*jack_list));
1131 	if (jack_list == NULL)
1132 		return NULL;
1133 
1134 	jack_list->change_callback = cb;
1135 	jack_list->callback_data = cb_data;
1136 	jack_list->mixer = mixer;
1137 	jack_list->ucm = ucm;
1138 	jack_list->hctl = hctl;
1139 	jack_list->card_index = card_index;
1140 	jack_list->card_name = card_name;
1141 	jack_list->device_index = device_index;
1142 	jack_list->is_first_device = is_first_device;
1143 	jack_list->direction = direction;
1144 
1145 	return jack_list;
1146 }
1147 
cras_alsa_jack_list_destroy(struct cras_alsa_jack_list * jack_list)1148 void cras_alsa_jack_list_destroy(struct cras_alsa_jack_list *jack_list)
1149 {
1150 	struct cras_alsa_jack *jack;
1151 
1152 	if (jack_list == NULL)
1153 		return;
1154 	DL_FOREACH(jack_list->jacks, jack) {
1155 		DL_DELETE(jack_list->jacks, jack);
1156 		cras_free_jack(jack, 1);
1157 	}
1158 	free(jack_list);
1159 }
1160 
cras_alsa_jack_list_has_hctl_jacks(struct cras_alsa_jack_list * jack_list)1161 int cras_alsa_jack_list_has_hctl_jacks(struct cras_alsa_jack_list *jack_list)
1162 {
1163 	struct cras_alsa_jack *jack;
1164 
1165 	if (!jack_list)
1166 		return 0;
1167 	DL_FOREACH(jack_list->jacks, jack) {
1168 		if (!jack->is_gpio)
1169 			return 1;
1170 	}
1171 	return 0;
1172 }
1173 
cras_alsa_jack_get_mixer_output(const struct cras_alsa_jack * jack)1174 struct mixer_control *cras_alsa_jack_get_mixer_output(
1175 		const struct cras_alsa_jack *jack)
1176 {
1177 	if (jack == NULL)
1178 		return NULL;
1179 	return jack->mixer_output;
1180 }
1181 
cras_alsa_jack_get_mixer_input(const struct cras_alsa_jack * jack)1182 struct mixer_control *cras_alsa_jack_get_mixer_input(
1183 		const struct cras_alsa_jack *jack)
1184 {
1185 	return jack ? jack->mixer_input : NULL;
1186 }
1187 
cras_alsa_jack_list_report(const struct cras_alsa_jack_list * jack_list)1188 void cras_alsa_jack_list_report(const struct cras_alsa_jack_list *jack_list)
1189 {
1190 	struct cras_alsa_jack *jack;
1191 
1192 	if (jack_list == NULL)
1193 		return;
1194 
1195 	DL_FOREACH(jack_list->jacks, jack)
1196 		if (jack->is_gpio)
1197 			gpio_switch_initial_state(jack);
1198 		else
1199 			hctl_jack_cb(jack->elem, 0);
1200 }
1201 
cras_alsa_jack_get_name(const struct cras_alsa_jack * jack)1202 const char *cras_alsa_jack_get_name(const struct cras_alsa_jack *jack)
1203 {
1204 	if (jack == NULL)
1205 		return NULL;
1206 	if (jack->is_gpio)
1207 		return jack->gpio.device_name;
1208 	return snd_hctl_elem_get_name(jack->elem);
1209 }
1210 
cras_alsa_jack_get_ucm_device(const struct cras_alsa_jack * jack)1211 const char *cras_alsa_jack_get_ucm_device(const struct cras_alsa_jack *jack)
1212 {
1213 	return jack->ucm_device;
1214 }
1215 
cras_alsa_jack_update_monitor_name(const struct cras_alsa_jack * jack,char * name_buf,unsigned int buf_size)1216 void cras_alsa_jack_update_monitor_name(const struct cras_alsa_jack *jack,
1217 					char *name_buf,
1218 					unsigned int buf_size)
1219 {
1220 	snd_ctl_elem_value_t *elem_value;
1221 	snd_ctl_elem_info_t *elem_info;
1222 	const char *buf = NULL;
1223 	int count;
1224 	int mnl = 0;
1225 
1226 	if (!jack->eld_control) {
1227 		if (jack->edid_file)
1228 			get_jack_edid_monitor_name(jack, name_buf, buf_size);
1229 		return;
1230 	}
1231 
1232 	snd_ctl_elem_info_alloca(&elem_info);
1233 	if (snd_hctl_elem_info(jack->eld_control, elem_info) < 0)
1234 		goto fallback_jack_name;
1235 
1236 	count = snd_ctl_elem_info_get_count(elem_info);
1237 	if (count <= ELD_MNL_OFFSET)
1238 		goto fallback_jack_name;
1239 
1240 	snd_ctl_elem_value_alloca(&elem_value);
1241 	if (snd_hctl_elem_read(jack->eld_control, elem_value) < 0)
1242 		goto fallback_jack_name;
1243 
1244 	buf = (const char *)snd_ctl_elem_value_get_bytes(elem_value);
1245 	mnl = buf[ELD_MNL_OFFSET] & ELD_MNL_MASK;
1246 
1247 	if (count < ELD_MONITOR_NAME_OFFSET + mnl)
1248 		goto fallback_jack_name;
1249 
1250 	/* Note that monitor name string does not contain terminate character.
1251 	 * Check monitor name length with name buffer size.
1252 	 */
1253 	if (mnl >= buf_size)
1254 		mnl = buf_size - 1;
1255 	strncpy(name_buf, buf + ELD_MONITOR_NAME_OFFSET, mnl);
1256 	name_buf[mnl] = '\0';
1257 
1258 	return;
1259 
1260 fallback_jack_name:
1261 	buf = cras_alsa_jack_get_name(jack);
1262 	strncpy(name_buf, buf, buf_size - 1);
1263 
1264 	return;
1265 }
1266 
cras_alsa_jack_update_node_type(const struct cras_alsa_jack * jack,enum CRAS_NODE_TYPE * type)1267 void cras_alsa_jack_update_node_type(const struct cras_alsa_jack *jack,
1268 				     enum CRAS_NODE_TYPE *type)
1269 {
1270 	if (!jack->override_type_name)
1271 		return;
1272 	if (!strcmp(jack->override_type_name, "Internal Speaker"))
1273 		*type = CRAS_NODE_TYPE_INTERNAL_SPEAKER;
1274 	return;
1275 }
1276 
cras_alsa_jack_get_dsp_name(const struct cras_alsa_jack * jack)1277 const char *cras_alsa_jack_get_dsp_name(const struct cras_alsa_jack *jack)
1278 {
1279 	if (jack == NULL)
1280 		return NULL;
1281 	return jack->dsp_name;
1282 }
1283 
cras_alsa_jack_enable_ucm(const struct cras_alsa_jack * jack,int enable)1284 void cras_alsa_jack_enable_ucm(const struct cras_alsa_jack *jack, int enable)
1285 {
1286 	if (jack && jack->ucm_device)
1287 		ucm_set_enabled(jack->jack_list->ucm, jack->ucm_device, enable);
1288 }
1289