• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2014 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 <sys/time.h>
7 #include <syslog.h>
8 
9 #include "cras_bt_io.h"
10 #include "cras_bt_device.h"
11 #include "cras_hfp_iodev.h"
12 #include "cras_utf8.h"
13 #include "cras_iodev.h"
14 #include "cras_iodev_list.h"
15 #include "sfh.h"
16 #include "utlist.h"
17 
18 #define DEFAULT_BT_DEVICE_NAME "BLUETOOTH"
19 
20 /* Extends cras_ionode to hold bluetooth profile information
21  * so that iodevs of different profile(A2DP or HFP/HSP) can be
22  * associated with the same bt_io.
23  * Members:
24  *    base - The base class cras_ionode.
25  *    profile_dev - Pointer to the profile specific iodev.
26  *    profile - The bluetooth profile profile_dev runs on.
27  */
28 struct bt_node {
29 	struct cras_ionode base;
30 	struct cras_iodev *profile_dev;
31 	unsigned int profile;
32 };
33 
34 /* The structure represents a virtual input or output device of a
35  * bluetooth audio device, speaker or headset for example. A node
36  * will be added to this virtual iodev for each profile supported
37  * by the bluetooth audio device.
38  * Member:
39  *    base - The base class cras_iodev
40  *    next_node_id - The index will give to the next node
41  */
42 struct bt_io {
43 	struct cras_iodev base;
44 	unsigned int next_node_id;
45 	struct cras_bt_device *device;
46 };
47 
48 /* Returns the active profile specific iodev. */
active_profile_dev(const struct cras_iodev * iodev)49 static struct cras_iodev *active_profile_dev(const struct cras_iodev *iodev)
50 {
51 	struct bt_node *active = (struct bt_node *)iodev->active_node;
52 
53 	return active->profile_dev;
54 }
55 
56 /* Adds a profile specific iodev to btio. */
add_profile_dev(struct cras_iodev * bt_iodev,struct cras_iodev * dev,enum cras_bt_device_profile profile)57 static struct cras_ionode *add_profile_dev(struct cras_iodev *bt_iodev,
58 					   struct cras_iodev *dev,
59 					   enum cras_bt_device_profile profile)
60 {
61 	struct bt_node *n;
62 	struct bt_io *btio = (struct bt_io *)bt_iodev;
63 
64 	n = (struct bt_node *)calloc(1, sizeof(*n));
65 	if (!n)
66 		return NULL;
67 
68 	n->base.dev = bt_iodev;
69 	n->base.idx = btio->next_node_id++;
70 	n->base.type = CRAS_NODE_TYPE_BLUETOOTH;
71 	n->base.volume = 100;
72 	n->base.stable_id = dev->info.stable_id;
73 	n->base.capture_gain = 0;
74 	gettimeofday(&n->base.plugged_time, NULL);
75 
76 	strcpy(n->base.name, dev->info.name);
77 	n->profile_dev = dev;
78 	n->profile = profile;
79 
80 	cras_iodev_add_node(bt_iodev, &n->base);
81 	return &n->base;
82 }
83 
84 /* Forces bt device to switch to use the given profile. Note that if
85  * it has already been open for streaming, the new active profile will
86  * take effect after the related btio(s) are reopened.
87  */
bt_switch_to_profile(struct cras_bt_device * device,enum cras_bt_device_profile profile)88 static void bt_switch_to_profile(struct cras_bt_device *device,
89 				 enum cras_bt_device_profile profile)
90 {
91 	switch (profile) {
92 	case CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY:
93 	case CRAS_BT_DEVICE_PROFILE_HSP_AUDIOGATEWAY:
94 		cras_bt_device_set_active_profile(
95 			device,
96 			CRAS_BT_DEVICE_PROFILE_HSP_AUDIOGATEWAY |
97 				CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
98 		break;
99 	case CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE:
100 		cras_bt_device_set_active_profile(
101 			device, CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE);
102 		break;
103 	default:
104 		syslog(LOG_ERR, "Unexpect profile %u", profile);
105 		break;
106 	}
107 }
108 
109 /* Switches the active profile to A2DP if it can. */
bt_possibly_switch_to_a2dp(struct bt_io * btio)110 static void bt_possibly_switch_to_a2dp(struct bt_io *btio)
111 {
112 	if (!cras_bt_device_has_a2dp(btio->device))
113 		return;
114 	cras_bt_device_set_active_profile(btio->device,
115 					  CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE);
116 	cras_bt_device_switch_profile(btio->device, &btio->base);
117 }
118 
119 /* Checks if bt device is active for the given profile.
120  */
device_using_profile(struct cras_bt_device * device,unsigned int profile)121 static int device_using_profile(struct cras_bt_device *device,
122 				unsigned int profile)
123 {
124 	return cras_bt_device_get_active_profile(device) & profile;
125 }
126 
127 /* Checks if the condition is met to switch to a different profile based
128  * on two rules:
129  * (1) Prefer to use A2DP for output since the audio quality is better.
130  * (2) Must use HFP/HSP for input since A2DP doesn't support audio input.
131  *
132  * If the profile switch happens, return non-zero error code, otherwise
133  * return zero.
134  */
open_dev(struct cras_iodev * iodev)135 static int open_dev(struct cras_iodev *iodev)
136 {
137 	struct bt_io *btio = (struct bt_io *)iodev;
138 	struct cras_iodev *dev = active_profile_dev(iodev);
139 	int rc;
140 
141 	/* Force to use HFP if opening input dev. */
142 	if (device_using_profile(btio->device,
143 				 CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE) &&
144 	    iodev->direction == CRAS_STREAM_INPUT) {
145 		bt_switch_to_profile(btio->device,
146 				     CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
147 		cras_bt_device_switch_profile_enable_dev(btio->device, iodev);
148 		return -EAGAIN;
149 	}
150 
151 	if (dev && dev->open_dev) {
152 		rc = dev->open_dev(dev);
153 		if (rc == 0)
154 			return 0;
155 
156 		/* If input iodev open fails, switch profile back to A2DP. */
157 		if (iodev->direction == CRAS_STREAM_INPUT)
158 			bt_possibly_switch_to_a2dp(btio);
159 		return rc;
160 	}
161 
162 	return 0;
163 }
164 
update_supported_formats(struct cras_iodev * iodev)165 static int update_supported_formats(struct cras_iodev *iodev)
166 {
167 	struct cras_iodev *dev = active_profile_dev(iodev);
168 	int rc, length, i;
169 
170 	if (!dev)
171 		return -EINVAL;
172 
173 	if (dev->update_supported_formats) {
174 		rc = dev->update_supported_formats(dev);
175 		if (rc)
176 			return rc;
177 	}
178 
179 	/* Fill in the supported rates and channel counts. */
180 	for (length = 0; dev->supported_rates[length]; length++)
181 		;
182 	free(iodev->supported_rates);
183 	iodev->supported_rates = (size_t *)malloc(
184 		(length + 1) * sizeof(*iodev->supported_rates));
185 	for (i = 0; i < length + 1; i++)
186 		iodev->supported_rates[i] = dev->supported_rates[i];
187 
188 	for (length = 0; dev->supported_channel_counts[length]; length++)
189 		;
190 	iodev->supported_channel_counts = (size_t *)malloc(
191 		(length + 1) * sizeof(*iodev->supported_channel_counts));
192 	for (i = 0; i < length + 1; i++)
193 		iodev->supported_channel_counts[i] =
194 			dev->supported_channel_counts[i];
195 
196 	for (length = 0; dev->supported_formats[length]; length++)
197 		;
198 
199 	iodev->supported_formats = (snd_pcm_format_t *)malloc(
200 		(length + 1) * sizeof(*iodev->supported_formats));
201 	for (i = 0; i < length + 1; i++)
202 		iodev->supported_formats[i] = dev->supported_formats[i];
203 
204 	/* Record max supported channels into cras_iodev_info. */
205 	iodev->info.max_supported_channels = dev->info.max_supported_channels;
206 	return 0;
207 }
208 
configure_dev(struct cras_iodev * iodev)209 static int configure_dev(struct cras_iodev *iodev)
210 {
211 	int rc;
212 	struct cras_iodev *dev = active_profile_dev(iodev);
213 	if (!dev)
214 		return -EINVAL;
215 
216 	/* Fill back the format iodev is using. */
217 	if (dev->format == NULL) {
218 		dev->format = (struct cras_audio_format *)malloc(
219 			sizeof(*dev->format));
220 		if (!dev->format)
221 			return -ENOMEM;
222 		*dev->format = *iodev->format;
223 	}
224 
225 	rc = dev->configure_dev(dev);
226 	if (rc)
227 		return rc;
228 
229 	iodev->buffer_size = dev->buffer_size;
230 	iodev->min_buffer_level = dev->min_buffer_level;
231 	if (dev->start)
232 		dev->state = CRAS_IODEV_STATE_OPEN;
233 	else
234 		dev->state = CRAS_IODEV_STATE_NO_STREAM_RUN;
235 
236 	return 0;
237 }
238 
close_dev(struct cras_iodev * iodev)239 static int close_dev(struct cras_iodev *iodev)
240 {
241 	struct bt_io *btio = (struct bt_io *)iodev;
242 	int rc;
243 	struct cras_iodev *dev = active_profile_dev(iodev);
244 	if (!dev)
245 		return -EINVAL;
246 
247 	/* If input iodev is in open state and being closed, switch profile
248 	 * from HFP to A2DP. */
249 	if (cras_iodev_is_open(iodev) &&
250 	    device_using_profile(
251 		    btio->device,
252 		    CRAS_BT_DEVICE_PROFILE_HSP_AUDIOGATEWAY |
253 			    CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY) &&
254 	    (iodev->direction == CRAS_STREAM_INPUT))
255 		bt_possibly_switch_to_a2dp(btio);
256 
257 	rc = dev->close_dev(dev);
258 	if (rc < 0)
259 		return rc;
260 	cras_iodev_free_format(iodev);
261 	dev->state = CRAS_IODEV_STATE_CLOSE;
262 	return 0;
263 }
264 
set_bt_volume(struct cras_iodev * iodev)265 static void set_bt_volume(struct cras_iodev *iodev)
266 {
267 	struct cras_iodev *dev = active_profile_dev(iodev);
268 	if (!dev)
269 		return;
270 
271 	if (dev->active_node)
272 		dev->active_node->volume = iodev->active_node->volume;
273 
274 	/* The parent bt_iodev could set software_volume_needed flag for cases
275 	 * that software volume provides better experience across profiles
276 	 * (HFP and A2DP). Otherwise, use the profile specific implementation
277 	 * to adjust volume. */
278 	if (dev->set_volume && !iodev->software_volume_needed)
279 		dev->set_volume(dev);
280 }
281 
frames_queued(const struct cras_iodev * iodev,struct timespec * tstamp)282 static int frames_queued(const struct cras_iodev *iodev,
283 			 struct timespec *tstamp)
284 {
285 	struct cras_iodev *dev = active_profile_dev(iodev);
286 	if (!dev)
287 		return -EINVAL;
288 	return dev->frames_queued(dev, tstamp);
289 }
290 
delay_frames(const struct cras_iodev * iodev)291 static int delay_frames(const struct cras_iodev *iodev)
292 {
293 	struct cras_iodev *dev = active_profile_dev(iodev);
294 	if (!dev)
295 		return -EINVAL;
296 	return dev->delay_frames(dev);
297 }
298 
get_buffer(struct cras_iodev * iodev,struct cras_audio_area ** area,unsigned * frames)299 static int get_buffer(struct cras_iodev *iodev, struct cras_audio_area **area,
300 		      unsigned *frames)
301 {
302 	struct cras_iodev *dev = active_profile_dev(iodev);
303 	if (!dev)
304 		return -EINVAL;
305 	return dev->get_buffer(dev, area, frames);
306 }
307 
put_buffer(struct cras_iodev * iodev,unsigned nwritten)308 static int put_buffer(struct cras_iodev *iodev, unsigned nwritten)
309 {
310 	struct cras_iodev *dev = active_profile_dev(iodev);
311 	if (!dev)
312 		return -EINVAL;
313 	return dev->put_buffer(dev, nwritten);
314 }
315 
flush_buffer(struct cras_iodev * iodev)316 static int flush_buffer(struct cras_iodev *iodev)
317 {
318 	struct cras_iodev *dev = active_profile_dev(iodev);
319 	if (!dev)
320 		return -EINVAL;
321 	return dev->flush_buffer(dev);
322 }
323 
324 /* If the first private iodev doesn't match the active profile stored on
325  * device, select to the correct private iodev.
326  */
update_active_node(struct cras_iodev * iodev,unsigned node_idx,unsigned dev_enabled)327 static void update_active_node(struct cras_iodev *iodev, unsigned node_idx,
328 			       unsigned dev_enabled)
329 {
330 	struct bt_io *btio = (struct bt_io *)iodev;
331 	struct cras_ionode *node;
332 	struct bt_node *active = (struct bt_node *)iodev->active_node;
333 	struct cras_iodev *dev;
334 	int rc;
335 
336 	if (device_using_profile(btio->device, active->profile))
337 		goto leave;
338 
339 	/* Switch to the correct dev using active_profile. */
340 	DL_FOREACH (iodev->nodes, node) {
341 		struct bt_node *n = (struct bt_node *)node;
342 		if (n == active)
343 			continue;
344 
345 		if (device_using_profile(btio->device, n->profile)) {
346 			active->profile = n->profile;
347 			active->profile_dev = n->profile_dev;
348 
349 			/* Set volume for the new profile. */
350 			set_bt_volume(iodev);
351 		}
352 	}
353 
354 leave:
355 	dev = active_profile_dev(iodev);
356 	if (dev && dev->update_active_node)
357 		dev->update_active_node(dev, node_idx, dev_enabled);
358 
359 	/* Update supported formats here to get the supported formats from the
360 	 * new updated active profile dev.
361 	 */
362 	rc = update_supported_formats(iodev);
363 	if (rc) {
364 		syslog(LOG_ERR, "Failed to update supported formats, rc=%d",
365 		       rc);
366 	}
367 }
368 
output_underrun(struct cras_iodev * iodev)369 static int output_underrun(struct cras_iodev *iodev)
370 {
371 	struct cras_iodev *dev = active_profile_dev(iodev);
372 	if (!dev)
373 		return -EINVAL;
374 
375 	if (dev->output_underrun) {
376 		dev->min_cb_level = iodev->min_cb_level;
377 		dev->max_cb_level = iodev->max_cb_level;
378 		dev->buffer_size = iodev->buffer_size;
379 		return dev->output_underrun(dev);
380 	}
381 
382 	return 0;
383 }
384 
no_stream(struct cras_iodev * iodev,int enable)385 static int no_stream(struct cras_iodev *iodev, int enable)
386 {
387 	struct cras_iodev *dev = active_profile_dev(iodev);
388 	int rc;
389 
390 	if (!dev)
391 		return -EINVAL;
392 
393 	if (dev->no_stream) {
394 		/*
395 		 * Copy iodev->min_cb_level and iodev->max_cb_level from the
396 		 * parent (i.e. bt_io).  no_stream() of hfp_alsa_iodev will
397 		 * use them.
398 		 * A2DP and HFP dev will use buffer and callback sizes to fill
399 		 * zeros in no stream state.
400 		 */
401 		dev->min_cb_level = iodev->min_cb_level;
402 		dev->max_cb_level = iodev->max_cb_level;
403 		dev->buffer_size = iodev->buffer_size;
404 		rc = dev->no_stream(dev, enable);
405 		if (rc < 0)
406 			return rc;
407 	}
408 	if (enable)
409 		dev->state = CRAS_IODEV_STATE_NO_STREAM_RUN;
410 	else
411 		dev->state = CRAS_IODEV_STATE_NORMAL_RUN;
412 
413 	return 0;
414 }
415 
is_free_running(const struct cras_iodev * iodev)416 static int is_free_running(const struct cras_iodev *iodev)
417 {
418 	struct cras_iodev *dev = active_profile_dev(iodev);
419 	if (!dev)
420 		return -EINVAL;
421 
422 	if (dev->is_free_running)
423 		return dev->is_free_running(dev);
424 
425 	return 0;
426 }
427 
start(const struct cras_iodev * iodev)428 static int start(const struct cras_iodev *iodev)
429 {
430 	struct cras_iodev *dev = active_profile_dev(iodev);
431 	int rc;
432 
433 	if (!dev)
434 		return -EINVAL;
435 
436 	if (dev->start) {
437 		rc = dev->start(dev);
438 		if (rc)
439 			return rc;
440 	}
441 	dev->state = CRAS_IODEV_STATE_NORMAL_RUN;
442 	return 0;
443 }
444 
frames_to_play_in_sleep(struct cras_iodev * iodev,unsigned int * hw_level,struct timespec * hw_tstamp)445 static unsigned int frames_to_play_in_sleep(struct cras_iodev *iodev,
446 					    unsigned int *hw_level,
447 					    struct timespec *hw_tstamp)
448 {
449 	struct cras_iodev *dev = active_profile_dev(iodev);
450 	if (!dev || !dev->frames_to_play_in_sleep)
451 		return cras_iodev_default_frames_to_play_in_sleep(
452 			iodev, hw_level, hw_tstamp);
453 
454 	return dev->frames_to_play_in_sleep(dev, hw_level, hw_tstamp);
455 }
456 
get_valid_frames(struct cras_iodev * iodev,struct timespec * hw_tstamp)457 static int get_valid_frames(struct cras_iodev *iodev,
458 			    struct timespec *hw_tstamp)
459 {
460 	struct cras_iodev *dev = active_profile_dev(iodev);
461 	if (!dev)
462 		return -EINVAL;
463 
464 	if (dev->get_valid_frames)
465 		return dev->get_valid_frames(dev, hw_tstamp);
466 
467 	return cras_iodev_frames_queued(iodev, hw_tstamp);
468 }
469 
cras_bt_io_create(struct cras_bt_device * device,struct cras_iodev * dev,enum cras_bt_device_profile profile)470 struct cras_iodev *cras_bt_io_create(struct cras_bt_device *device,
471 				     struct cras_iodev *dev,
472 				     enum cras_bt_device_profile profile)
473 {
474 	int err;
475 	struct bt_io *btio;
476 	struct cras_iodev *iodev;
477 	struct cras_ionode *node;
478 	struct bt_node *active;
479 
480 	if (!dev)
481 		return NULL;
482 
483 	btio = (struct bt_io *)calloc(1, sizeof(*btio));
484 	if (!btio)
485 		goto error;
486 	btio->device = device;
487 
488 	iodev = &btio->base;
489 	iodev->direction = dev->direction;
490 	strcpy(iodev->info.name, dev->info.name);
491 	iodev->info.stable_id = dev->info.stable_id;
492 
493 	iodev->open_dev = open_dev;
494 	iodev->configure_dev = configure_dev;
495 	iodev->frames_queued = frames_queued;
496 	iodev->delay_frames = delay_frames;
497 	iodev->get_buffer = get_buffer;
498 	iodev->put_buffer = put_buffer;
499 	iodev->flush_buffer = flush_buffer;
500 	iodev->close_dev = close_dev;
501 	iodev->update_supported_formats = update_supported_formats;
502 	iodev->update_active_node = update_active_node;
503 	iodev->no_stream = no_stream;
504 	iodev->output_underrun = output_underrun;
505 	iodev->is_free_running = is_free_running;
506 	iodev->get_valid_frames = get_valid_frames;
507 	iodev->start = start;
508 	iodev->frames_to_play_in_sleep = frames_to_play_in_sleep;
509 
510 	/* Input also checks |software_volume_needed| flag for using software
511 	 * gain. Keep it as false for BT input.
512 	 * TODO(hychao): after wide band speech mode is supported, consider
513 	 * enable software gain.
514 	 */
515 	if (dev->direction == CRAS_STREAM_OUTPUT) {
516 		iodev->software_volume_needed =
517 			!cras_bt_device_get_use_hardware_volume(device);
518 		iodev->set_volume = set_bt_volume;
519 	}
520 
521 	/* Create the fake node so it's the only node exposed to UI, and
522 	 * point it to the first profile dev. */
523 	active = (struct bt_node *)calloc(1, sizeof(*active));
524 	if (!active)
525 		goto error;
526 	active->base.dev = iodev;
527 	active->base.idx = btio->next_node_id++;
528 	active->base.type = dev->active_node->type;
529 	active->base.volume = 100;
530 	active->base.stable_id = cras_bt_device_get_stable_id(device);
531 	active->base.ui_gain_scaler = 1.0f;
532 	/*
533 	 * If the same headset is connected in wideband mode, we shall assign
534 	 * a separate stable_id so the node priority/preference mechanism in
535 	 * Chrome UI doesn't break.
536 	 */
537 	if ((active->base.type == CRAS_NODE_TYPE_BLUETOOTH) &&
538 	    (dev->direction == CRAS_STREAM_INPUT))
539 		active->base.stable_id =
540 			SuperFastHash((const char *)&active->base.type,
541 				      sizeof(active->base.type),
542 				      active->base.stable_id);
543 	active->profile = profile;
544 	active->profile_dev = dev;
545 	strcpy(active->base.name, dev->info.name);
546 	/* The node name exposed to UI should be a valid UTF8 string. */
547 	if (!is_utf8_string(active->base.name))
548 		strcpy(active->base.name, DEFAULT_BT_DEVICE_NAME);
549 	cras_iodev_add_node(iodev, &active->base);
550 
551 	node = add_profile_dev(&btio->base, dev, profile);
552 	if (node == NULL)
553 		goto error;
554 
555 	/* Default active profile to a2dp whenever it's allowed. */
556 	if (!cras_bt_device_get_active_profile(device) ||
557 	    (profile == CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE &&
558 	     cras_bt_device_can_switch_to_a2dp(device)))
559 		bt_switch_to_profile(device, profile);
560 
561 	if (iodev->direction == CRAS_STREAM_OUTPUT)
562 		err = cras_iodev_list_add_output(iodev);
563 	else
564 		err = cras_iodev_list_add_input(iodev);
565 	if (err)
566 		goto error;
567 
568 	cras_iodev_set_active_node(iodev, &active->base);
569 	return &btio->base;
570 
571 error:
572 	if (btio)
573 		free(btio);
574 	return NULL;
575 }
576 
cras_bt_io_free_resources(struct cras_iodev * bt_iodev)577 void cras_bt_io_free_resources(struct cras_iodev *bt_iodev)
578 {
579 	struct cras_ionode *node;
580 	struct bt_node *n;
581 
582 	free(bt_iodev->supported_rates);
583 	free(bt_iodev->supported_channel_counts);
584 	free(bt_iodev->supported_formats);
585 
586 	DL_FOREACH (bt_iodev->nodes, node) {
587 		n = (struct bt_node *)node;
588 		cras_iodev_rm_node(bt_iodev, node);
589 		free(n);
590 	}
591 
592 	cras_iodev_free_resources(bt_iodev);
593 }
594 
cras_bt_io_destroy(struct cras_iodev * bt_iodev)595 void cras_bt_io_destroy(struct cras_iodev *bt_iodev)
596 {
597 	int rc;
598 	struct bt_io *btio = (struct bt_io *)bt_iodev;
599 
600 	if (bt_iodev->direction == CRAS_STREAM_OUTPUT)
601 		rc = cras_iodev_list_rm_output(bt_iodev);
602 	else
603 		rc = cras_iodev_list_rm_input(bt_iodev);
604 	if (rc == -EBUSY)
605 		return;
606 
607 	cras_bt_io_free_resources(bt_iodev);
608 	free(btio);
609 }
610 
cras_bt_io_get_profile(struct cras_iodev * bt_iodev,enum cras_bt_device_profile profile)611 struct cras_ionode *cras_bt_io_get_profile(struct cras_iodev *bt_iodev,
612 					   enum cras_bt_device_profile profile)
613 {
614 	struct cras_ionode *node;
615 	DL_FOREACH (bt_iodev->nodes, node) {
616 		struct bt_node *n = (struct bt_node *)node;
617 		if (n->profile & profile)
618 			return node;
619 	}
620 	return NULL;
621 }
622 
cras_bt_io_append(struct cras_iodev * bt_iodev,struct cras_iodev * dev,enum cras_bt_device_profile profile)623 int cras_bt_io_append(struct cras_iodev *bt_iodev, struct cras_iodev *dev,
624 		      enum cras_bt_device_profile profile)
625 {
626 	struct cras_ionode *node;
627 	struct bt_io *btio = (struct bt_io *)bt_iodev;
628 
629 	if (cras_bt_io_get_profile(bt_iodev, profile))
630 		return -EEXIST;
631 
632 	node = add_profile_dev(bt_iodev, dev, profile);
633 	if (!node)
634 		return -ENOMEM;
635 
636 	if (profile == CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE &&
637 	    cras_bt_device_can_switch_to_a2dp(btio->device)) {
638 		bt_switch_to_profile(btio->device,
639 				     CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE);
640 		cras_bt_device_switch_profile(btio->device, bt_iodev);
641 		syslog(LOG_ERR, "Switch to A2DP on append");
642 	}
643 	return 0;
644 }
645 
cras_bt_io_on_profile(struct cras_iodev * bt_iodev,enum cras_bt_device_profile profile)646 int cras_bt_io_on_profile(struct cras_iodev *bt_iodev,
647 			  enum cras_bt_device_profile profile)
648 {
649 	struct bt_node *btnode = (struct bt_node *)bt_iodev->active_node;
650 	return !!(profile & btnode->profile);
651 }
652 
653 enum cras_bt_device_profile
cras_bt_io_profile_to_log(struct cras_iodev * bt_iodev)654 cras_bt_io_profile_to_log(struct cras_iodev *bt_iodev)
655 {
656 	struct bt_node *btnode = (struct bt_node *)bt_iodev->active_node;
657 
658 	if (btnode->profile & CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE)
659 		return CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE;
660 
661 	if (hfp_iodev_is_hsp(btnode->profile_dev))
662 		return CRAS_BT_DEVICE_PROFILE_HSP_AUDIOGATEWAY;
663 	else
664 		return CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY;
665 }
666 
cras_bt_io_try_remove(struct cras_iodev * bt_iodev,struct cras_iodev * dev)667 unsigned int cras_bt_io_try_remove(struct cras_iodev *bt_iodev,
668 				   struct cras_iodev *dev)
669 {
670 	struct cras_ionode *node;
671 	struct bt_node *active, *btnode;
672 	unsigned int try_profile = 0;
673 
674 	active = (struct bt_node *)bt_iodev->active_node;
675 
676 	if (active->profile_dev == dev) {
677 		DL_FOREACH (bt_iodev->nodes, node) {
678 			btnode = (struct bt_node *)node;
679 			/* Skip the active node and the node we're trying
680 			 * to remove. */
681 			if (btnode == active || btnode->profile_dev == dev)
682 				continue;
683 			try_profile = btnode->profile;
684 			break;
685 		}
686 	} else {
687 		try_profile = active->profile;
688 	}
689 	return try_profile;
690 }
691 
cras_bt_io_remove(struct cras_iodev * bt_iodev,struct cras_iodev * dev)692 int cras_bt_io_remove(struct cras_iodev *bt_iodev, struct cras_iodev *dev)
693 {
694 	struct cras_ionode *node;
695 	struct bt_node *btnode;
696 
697 	DL_FOREACH (bt_iodev->nodes, node) {
698 		btnode = (struct bt_node *)node;
699 		if (btnode->profile_dev != dev)
700 			continue;
701 
702 		/* If this is the active node, reset it. Otherwise delete
703 		 * this node. */
704 		if (node == bt_iodev->active_node) {
705 			btnode->profile_dev = NULL;
706 			btnode->profile = 0;
707 		} else {
708 			DL_DELETE(bt_iodev->nodes, node);
709 			free(node);
710 		}
711 	}
712 
713 	/* The node of active profile could have been removed, update it.
714 	 * Return err when fail to locate the active profile dev. */
715 	update_active_node(bt_iodev, 0, 1);
716 	btnode = (struct bt_node *)bt_iodev->active_node;
717 	if ((btnode->profile == 0) || (btnode->profile_dev == NULL))
718 		return -EINVAL;
719 
720 	return 0;
721 }
722