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