/src/adhd/cras/src/server/cras_bt_io.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright 2014 The ChromiumOS Authors |
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 "cras/src/server/cras_bt_io.h" |
7 | | |
8 | | #include <stdbool.h> |
9 | | #include <stdint.h> |
10 | | #include <stdlib.h> |
11 | | #include <sys/time.h> |
12 | | #include <syslog.h> |
13 | | #include <time.h> |
14 | | |
15 | | #include "cras/src/server/cras_bt_device.h" |
16 | | #include "cras/src/server/cras_bt_policy.h" |
17 | | #include "cras/src/server/cras_iodev.h" |
18 | | #include "cras/src/server/cras_iodev_list.h" |
19 | | #include "cras/src/server/cras_system_state.h" |
20 | | #include "cras/src/server/cras_utf8.h" |
21 | | #include "cras_types.h" |
22 | | #include "third_party/strlcpy/strlcpy.h" |
23 | | #include "third_party/superfasthash/sfh.h" |
24 | | #include "third_party/utlist/utlist.h" |
25 | | |
26 | 434 | #define DEFAULT_BT_DEVICE_NAME "BLUETOOTH" |
27 | | |
28 | | /* Extends cras_ionode to hold bluetooth profile information |
29 | | * so that iodevs of different profile(A2DP or HFP) can be |
30 | | * associated with the same bt_io. |
31 | | */ |
32 | | struct bt_node { |
33 | | // The base class cras_ionode. |
34 | | struct cras_ionode base; |
35 | | // Pointer to the profile specific iodev. |
36 | | struct cras_iodev* profile_dev; |
37 | | }; |
38 | | |
39 | | /* The structure represents a virtual input or output device of a |
40 | | * bluetooth audio device, speaker or headset for example. A node |
41 | | * will be added to this virtual iodev for each profile supported |
42 | | * by the bluetooth audio device. |
43 | | */ |
44 | | struct bt_io { |
45 | | // The base class cras_iodev |
46 | | struct cras_iodev base; |
47 | | // The index will give to the next node |
48 | | unsigned int next_node_id; |
49 | | // Pointer to the bt_io_manager that is responsible for |
50 | | // profile switching when |bt_io| opens or closes. |
51 | | struct bt_io_manager* mgr; |
52 | | }; |
53 | | |
54 | | static struct bt_io_manager* bt_io_managers; |
55 | | |
56 | | /* |
57 | | * Sets up the volume to HFP or A2DP iodev using the cached volume |
58 | | * lastly updated by headset volume events. |
59 | | */ |
60 | | static void set_bt_volume(struct cras_iodev* iodev); |
61 | | |
62 | 2.62k | static inline enum CRAS_BT_FLAGS btflags_to_profile(uint32_t btflags) { |
63 | 2.62k | if (btflags & CRAS_BT_FLAG_A2DP) { |
64 | 1.58k | return CRAS_BT_FLAG_A2DP; |
65 | 1.58k | } |
66 | 1.04k | if (btflags & CRAS_BT_FLAG_HFP) { |
67 | 1.04k | return CRAS_BT_FLAG_HFP; |
68 | 1.04k | } |
69 | 0 | return CRAS_BT_FLAG_NONE; |
70 | 1.04k | } |
71 | | |
72 | | // Returns the active profile specific iodev. |
73 | 0 | static struct cras_iodev* active_profile_dev(const struct cras_iodev* iodev) { |
74 | 0 | struct bt_node* active = (struct bt_node*)iodev->active_node; |
75 | |
|
76 | 0 | return active->profile_dev; |
77 | 0 | } |
78 | | |
79 | | // Adds a profile specific iodev to btio. |
80 | | static struct cras_ionode* add_profile_dev(struct cras_iodev* bt_iodev, |
81 | 1.42k | struct cras_iodev* dev) { |
82 | 1.42k | struct bt_node* n; |
83 | 1.42k | struct bt_io* btio = (struct bt_io*)bt_iodev; |
84 | | |
85 | 1.42k | n = (struct bt_node*)calloc(1, sizeof(*n)); |
86 | 1.42k | if (!n) { |
87 | 0 | return NULL; |
88 | 0 | } |
89 | | |
90 | 1.42k | n->base.dev = bt_iodev; |
91 | 1.42k | n->base.btflags = dev->active_node->btflags; |
92 | 1.42k | n->base.idx = btio->next_node_id++; |
93 | 1.42k | n->base.type = CRAS_NODE_TYPE_BLUETOOTH; |
94 | 1.42k | n->base.volume = 100; |
95 | 1.42k | n->base.stable_id = dev->info.stable_id; |
96 | 1.42k | n->base.internal_capture_gain = 0; |
97 | 1.42k | gettimeofday(&n->base.plugged_time, NULL); |
98 | | |
99 | 1.42k | strlcpy(n->base.name, dev->info.name, sizeof(n->base.name)); |
100 | 1.42k | n->profile_dev = dev; |
101 | | |
102 | 1.42k | cras_iodev_add_node(bt_iodev, &n->base); |
103 | 1.42k | return &n->base; |
104 | 1.42k | } |
105 | | |
106 | | // Looks up for the node of given profile and returns if it exist or not. |
107 | 752 | static bool bt_io_has_a2dp(struct cras_iodev* bt_iodev) { |
108 | 752 | struct cras_ionode* node; |
109 | 986 | DL_FOREACH (bt_iodev->nodes, node) { |
110 | 986 | if (node->btflags & CRAS_BT_FLAG_A2DP) { |
111 | 600 | return true; |
112 | 600 | } |
113 | 986 | } |
114 | 152 | return false; |
115 | 752 | } |
116 | | |
117 | 311 | static bool bt_io_has_hfp(struct cras_iodev* bt_iodev) { |
118 | 311 | struct cras_ionode* node; |
119 | 622 | DL_FOREACH (bt_iodev->nodes, node) { |
120 | 622 | if (node->btflags & CRAS_BT_FLAG_HFP) { |
121 | 0 | return true; |
122 | 0 | } |
123 | 622 | } |
124 | 311 | return false; |
125 | 311 | } |
126 | | |
127 | 816 | int bt_io_manager_has_a2dp(struct bt_io_manager* mgr) { |
128 | 816 | struct cras_iodev* odev = mgr->bt_iodevs[CRAS_STREAM_OUTPUT]; |
129 | | |
130 | | // Check if there is an output iodev with A2DP node attached. |
131 | 816 | return odev && bt_io_has_a2dp(odev); |
132 | 816 | } |
133 | | |
134 | | void bt_io_manager_set_use_hardware_volume(struct bt_io_manager* mgr, |
135 | 498 | int use_hardware_volume) { |
136 | 498 | struct cras_iodev* iodev; |
137 | | |
138 | 498 | iodev = mgr->bt_iodevs[CRAS_STREAM_OUTPUT]; |
139 | 498 | if (iodev) { |
140 | | /* |
141 | | * For BlueZ, whether HFP uses software volume depends on the support of |
142 | | * AVRCP. |
143 | | */ |
144 | 498 | iodev->software_volume_needed = !use_hardware_volume; |
145 | 498 | } |
146 | 498 | } |
147 | | |
148 | | void bt_io_manager_update_hardware_volume(struct bt_io_manager* mgr, |
149 | | int volume, |
150 | 608 | enum CRAS_BT_FLAGS btflag) { |
151 | 608 | struct cras_iodev* iodev; |
152 | 608 | enum CRAS_BT_FLAGS active_profile, event_profile; |
153 | | |
154 | 608 | iodev = mgr->bt_iodevs[CRAS_STREAM_OUTPUT]; |
155 | 608 | if (iodev == NULL) { |
156 | 1 | return; |
157 | 1 | } |
158 | | |
159 | | /* If the volume update event isn't from the active profile, ignore it. */ |
160 | 607 | active_profile = btflags_to_profile(mgr->active_btflag); |
161 | 607 | event_profile = btflags_to_profile(btflag); |
162 | 607 | if (active_profile != CRAS_BT_FLAG_NONE && active_profile != event_profile) { |
163 | 69 | return; |
164 | 69 | } |
165 | | |
166 | 538 | iodev->active_node->volume = volume; |
167 | 538 | cras_iodev_list_notify_node_volume(iodev->active_node); |
168 | 538 | } |
169 | | |
170 | | /* |
171 | | * When A2DP is connected and appends iodev to |mgr| we prefer to use if |
172 | | * possible. And the logic to whether it's allowed is by checking if BT |
173 | | * input and bluetooth telephony is now being used or not. |
174 | | */ |
175 | 765 | static int can_switch_to_a2dp(struct bt_io_manager* mgr) { |
176 | 765 | struct cras_iodev* idev = mgr->bt_iodevs[CRAS_STREAM_INPUT]; |
177 | | |
178 | | // When BT telephony is in use, always stick to HFP. |
179 | 765 | if (mgr->telephony_use) { |
180 | 0 | return false; |
181 | 0 | } |
182 | | |
183 | | // If BT input is being used, has to be HFP |
184 | 765 | if (idev && cras_iodev_is_open(idev)) { |
185 | 0 | return false; |
186 | 0 | } |
187 | | |
188 | 765 | return bt_io_manager_has_a2dp(mgr); |
189 | 765 | } |
190 | | |
191 | | /* When bt_io opens or closes so that A2DP better serves the use case, |
192 | | * check with |btio->mgr| to see if that's possible and if so switches |
193 | | * the active profile to A2DP. */ |
194 | 51 | static void possibly_switch_to_a2dp(struct bt_io_manager* mgr) { |
195 | 51 | if (!bt_io_manager_has_a2dp(mgr)) { |
196 | 0 | return; |
197 | 0 | } |
198 | 51 | mgr->active_btflag = CRAS_BT_FLAG_A2DP; |
199 | 51 | cras_bt_policy_switch_profile(mgr); |
200 | 51 | } |
201 | | |
202 | 21 | static void switch_to_hfp(struct bt_io_manager* mgr) { |
203 | 21 | mgr->active_btflag = CRAS_BT_FLAG_HFP; |
204 | 21 | cras_bt_policy_switch_profile(mgr); |
205 | 21 | } |
206 | | |
207 | | /* Checks if the condition is met to switch to a different profile based |
208 | | * on two rules: |
209 | | * (1) Prefer to use A2DP for output since the audio quality is better. |
210 | | * (2) Must use HFP for input since A2DP doesn't support audio input. |
211 | | * |
212 | | * If the profile switch happens, return non-zero error code, otherwise |
213 | | * return zero. |
214 | | */ |
215 | 0 | static int open_dev(struct cras_iodev* iodev) { |
216 | 0 | struct bt_io* btio = (struct bt_io*)iodev; |
217 | 0 | struct cras_iodev* dev = active_profile_dev(iodev); |
218 | 0 | int rc; |
219 | |
|
220 | 0 | cras_iodev_set_active_nc_provider(iodev); |
221 | | |
222 | | // Make sure not to open when there is a pending profile-switch event. |
223 | 0 | if (btio->mgr->is_profile_switching) { |
224 | 0 | return -EAGAIN; |
225 | 0 | } |
226 | | |
227 | | // Force to use HFP if opening input dev. |
228 | 0 | if (btio->mgr->active_btflag == CRAS_BT_FLAG_A2DP && |
229 | 0 | iodev->direction == CRAS_STREAM_INPUT) { |
230 | 0 | switch_to_hfp(btio->mgr); |
231 | 0 | return -EAGAIN; |
232 | 0 | } |
233 | | |
234 | 0 | if (dev && dev->open_dev) { |
235 | 0 | rc = dev->open_dev(dev); |
236 | 0 | if (rc == 0) { |
237 | 0 | return 0; |
238 | 0 | } |
239 | | |
240 | | // If input iodev open fails, switch profile back to A2DP. |
241 | 0 | if (iodev->direction == CRAS_STREAM_INPUT) { |
242 | 0 | possibly_switch_to_a2dp(btio->mgr); |
243 | 0 | } |
244 | 0 | return rc; |
245 | 0 | } |
246 | | |
247 | 0 | return 0; |
248 | 0 | } |
249 | | |
250 | 0 | static int update_supported_formats(struct cras_iodev* iodev) { |
251 | 0 | struct cras_iodev* dev = active_profile_dev(iodev); |
252 | 0 | int rc, length, i; |
253 | |
|
254 | 0 | if (!dev) { |
255 | 0 | return -EINVAL; |
256 | 0 | } |
257 | | |
258 | 0 | if (dev->update_supported_formats) { |
259 | 0 | rc = dev->update_supported_formats(dev); |
260 | 0 | if (rc) { |
261 | 0 | return rc; |
262 | 0 | } |
263 | 0 | } |
264 | | |
265 | | // Fill in the supported rates and channel counts. |
266 | 0 | for (length = 0; dev->supported_rates[length]; length++) |
267 | 0 | ; |
268 | 0 | free(iodev->supported_rates); |
269 | 0 | iodev->supported_rates = |
270 | 0 | (size_t*)malloc((length + 1) * sizeof(*iodev->supported_rates)); |
271 | 0 | for (i = 0; i < length + 1; i++) { |
272 | 0 | iodev->supported_rates[i] = dev->supported_rates[i]; |
273 | 0 | } |
274 | |
|
275 | 0 | for (length = 0; dev->supported_channel_counts[length]; length++) |
276 | 0 | ; |
277 | 0 | free(iodev->supported_channel_counts); |
278 | 0 | iodev->supported_channel_counts = |
279 | 0 | (size_t*)malloc((length + 1) * sizeof(*iodev->supported_channel_counts)); |
280 | 0 | for (i = 0; i < length + 1; i++) { |
281 | 0 | iodev->supported_channel_counts[i] = dev->supported_channel_counts[i]; |
282 | 0 | } |
283 | |
|
284 | 0 | for (length = 0; dev->supported_formats[length]; length++) |
285 | 0 | ; |
286 | 0 | free(iodev->supported_formats); |
287 | 0 | iodev->supported_formats = (snd_pcm_format_t*)malloc( |
288 | 0 | (length + 1) * sizeof(*iodev->supported_formats)); |
289 | 0 | for (i = 0; i < length + 1; i++) { |
290 | 0 | iodev->supported_formats[i] = dev->supported_formats[i]; |
291 | 0 | } |
292 | | |
293 | | // Record max supported channels into cras_iodev_info. |
294 | 0 | iodev->info.max_supported_channels = dev->info.max_supported_channels; |
295 | 0 | return 0; |
296 | 0 | } |
297 | | |
298 | 0 | static int configure_dev(struct cras_iodev* iodev) { |
299 | 0 | int rc; |
300 | 0 | struct cras_iodev* dev = active_profile_dev(iodev); |
301 | 0 | if (!dev) { |
302 | 0 | return -EINVAL; |
303 | 0 | } |
304 | | |
305 | | // Fill back the format iodev is using. |
306 | 0 | if (dev->format == NULL) { |
307 | 0 | dev->format = (struct cras_audio_format*)malloc(sizeof(*dev->format)); |
308 | 0 | if (!dev->format) { |
309 | 0 | return -ENOMEM; |
310 | 0 | } |
311 | 0 | *dev->format = *iodev->format; |
312 | 0 | } |
313 | | |
314 | 0 | rc = dev->configure_dev(dev); |
315 | 0 | if (rc) { |
316 | 0 | return rc; |
317 | 0 | } |
318 | | |
319 | | /* Apply the node's volume after profile dev is configured. Doing this |
320 | | * is necessary because the volume can not sync to hardware until |
321 | | * it is opened. */ |
322 | 0 | set_bt_volume(iodev); |
323 | |
|
324 | 0 | iodev->buffer_size = dev->buffer_size; |
325 | 0 | iodev->min_buffer_level = dev->min_buffer_level; |
326 | 0 | if (cras_iodev_can_start(dev)) { |
327 | 0 | dev->state = CRAS_IODEV_STATE_OPEN; |
328 | 0 | } else { |
329 | 0 | dev->state = CRAS_IODEV_STATE_NO_STREAM_RUN; |
330 | 0 | } |
331 | |
|
332 | 0 | return 0; |
333 | 0 | } |
334 | | |
335 | 0 | static int close_dev(struct cras_iodev* iodev) { |
336 | 0 | struct bt_io* btio = (struct bt_io*)iodev; |
337 | 0 | int rc; |
338 | 0 | struct cras_iodev* dev = active_profile_dev(iodev); |
339 | 0 | if (!dev) { |
340 | 0 | return -EINVAL; |
341 | 0 | } |
342 | | |
343 | | /* If telephony is not in use, input iodev is in open state and being closed, |
344 | | * switch profile from HFP to A2DP. |
345 | | * However, don't switch to A2DP if a profile-switch event is being queued, |
346 | | * which could be a special case where we want to simply restart an |
347 | | * existing HFP connection. |
348 | | */ |
349 | 0 | if (!btio->mgr->telephony_use && cras_iodev_is_open(iodev) && |
350 | 0 | btio->mgr->active_btflag == CRAS_BT_FLAG_HFP && |
351 | 0 | iodev->direction == CRAS_STREAM_INPUT && |
352 | 0 | !btio->mgr->is_profile_switching) { |
353 | 0 | possibly_switch_to_a2dp(btio->mgr); |
354 | 0 | } |
355 | |
|
356 | 0 | rc = dev->close_dev(dev); |
357 | 0 | if (rc < 0) { |
358 | 0 | return rc; |
359 | 0 | } |
360 | 0 | cras_iodev_free_format(iodev); |
361 | 0 | dev->state = CRAS_IODEV_STATE_CLOSE; |
362 | 0 | return 0; |
363 | 0 | } |
364 | | |
365 | 0 | static void set_bt_volume(struct cras_iodev* iodev) { |
366 | 0 | struct cras_iodev* dev = active_profile_dev(iodev); |
367 | 0 | if (!dev) { |
368 | 0 | return; |
369 | 0 | } |
370 | | |
371 | | // Do nothing for volume if this is an input iodev. |
372 | 0 | if (iodev->direction == CRAS_STREAM_INPUT) { |
373 | 0 | return; |
374 | 0 | } |
375 | | |
376 | 0 | if (dev->active_node) { |
377 | 0 | dev->active_node->volume = iodev->active_node->volume; |
378 | 0 | } |
379 | | |
380 | | /* The parent bt_iodev could set software_volume_needed flag for cases |
381 | | * that software volume provides better experience across profiles |
382 | | * (HFP and A2DP). Otherwise, use the profile specific implementation |
383 | | * to adjust volume. */ |
384 | 0 | if (dev->set_volume && !iodev->software_volume_needed) { |
385 | 0 | dev->set_volume(dev); |
386 | 0 | } |
387 | 0 | } |
388 | | |
389 | | static int frames_queued(const struct cras_iodev* iodev, |
390 | 0 | struct timespec* tstamp) { |
391 | 0 | struct cras_iodev* dev = active_profile_dev(iodev); |
392 | 0 | if (!dev) { |
393 | 0 | return -EINVAL; |
394 | 0 | } |
395 | 0 | return dev->frames_queued(dev, tstamp); |
396 | 0 | } |
397 | | |
398 | 0 | static int delay_frames(const struct cras_iodev* iodev) { |
399 | 0 | struct cras_iodev* dev = active_profile_dev(iodev); |
400 | 0 | if (!dev) { |
401 | 0 | return -EINVAL; |
402 | 0 | } |
403 | 0 | return dev->delay_frames(dev); |
404 | 0 | } |
405 | | |
406 | | static int get_buffer(struct cras_iodev* iodev, |
407 | | struct cras_audio_area** area, |
408 | 0 | unsigned* frames) { |
409 | 0 | struct cras_iodev* dev = active_profile_dev(iodev); |
410 | 0 | if (!dev) { |
411 | 0 | return -EINVAL; |
412 | 0 | } |
413 | 0 | return dev->get_buffer(dev, area, frames); |
414 | 0 | } |
415 | | |
416 | 0 | static int put_buffer(struct cras_iodev* iodev, unsigned nwritten) { |
417 | 0 | struct cras_iodev* dev = active_profile_dev(iodev); |
418 | 0 | if (!dev) { |
419 | 0 | return -EINVAL; |
420 | 0 | } |
421 | 0 | return dev->put_buffer(dev, nwritten); |
422 | 0 | } |
423 | | |
424 | 0 | static int flush_buffer(struct cras_iodev* iodev) { |
425 | 0 | struct cras_iodev* dev = active_profile_dev(iodev); |
426 | 0 | if (!dev) { |
427 | 0 | return -EINVAL; |
428 | 0 | } |
429 | 0 | return dev->flush_buffer(dev); |
430 | 0 | } |
431 | | |
432 | | /* If the first private iodev doesn't match the active profile stored on |
433 | | * device, select to the correct private iodev. |
434 | | */ |
435 | | static void update_active_node(struct cras_iodev* iodev, |
436 | | unsigned node_idx, |
437 | 362 | unsigned dev_enabled) { |
438 | 362 | struct bt_io* btio = (struct bt_io*)iodev; |
439 | 362 | struct cras_ionode* node; |
440 | 362 | struct bt_node* active = (struct bt_node*)iodev->active_node; |
441 | 362 | struct cras_iodev* dev; |
442 | 362 | int rc; |
443 | | |
444 | | // While there is a pending profile-switch request, do not alter |
445 | | // |profile_dev| so as to avoid state de-sync. |
446 | 362 | if (btio->mgr->is_profile_switching) { |
447 | 362 | return; |
448 | 362 | } |
449 | | |
450 | 0 | if (btio->mgr->active_btflag & active->base.btflags) { |
451 | 0 | goto leave; |
452 | 0 | } |
453 | | |
454 | | // Switch to the correct dev using active_btflag. |
455 | 0 | DL_FOREACH (iodev->nodes, node) { |
456 | 0 | struct bt_node* n = (struct bt_node*)node; |
457 | 0 | if (n == active) { |
458 | 0 | continue; |
459 | 0 | } |
460 | | |
461 | 0 | if (btio->mgr->active_btflag & n->base.btflags) { |
462 | 0 | active->base.btflags = n->base.btflags; |
463 | 0 | active->profile_dev = n->profile_dev; |
464 | | |
465 | | // Set volume for the new profile. |
466 | 0 | set_bt_volume(iodev); |
467 | 0 | } |
468 | 0 | } |
469 | |
|
470 | 0 | leave: |
471 | 0 | dev = active_profile_dev(iodev); |
472 | 0 | if (dev) { |
473 | 0 | if (dev->update_active_node) { |
474 | 0 | dev->update_active_node(dev, node_idx, dev_enabled); |
475 | 0 | } |
476 | 0 | } |
477 | | |
478 | | /* Update supported formats here to get the supported formats from the |
479 | | * new updated active profile dev. |
480 | | */ |
481 | 0 | rc = update_supported_formats(iodev); |
482 | 0 | if (rc) { |
483 | 0 | syslog(LOG_WARNING, "Failed to update supported formats, rc=%d", rc); |
484 | 0 | } |
485 | 0 | } |
486 | | |
487 | 0 | static int output_underrun(struct cras_iodev* iodev) { |
488 | 0 | struct cras_iodev* dev = active_profile_dev(iodev); |
489 | 0 | int frames; |
490 | 0 | if (!dev) { |
491 | 0 | return -EINVAL; |
492 | 0 | } |
493 | | |
494 | 0 | if (!dev->output_underrun) { |
495 | 0 | syslog(LOG_WARNING, "No output_underrun handler for active profile"); |
496 | 0 | return 0; |
497 | 0 | } |
498 | | |
499 | 0 | dev->min_cb_level = iodev->min_cb_level; |
500 | 0 | dev->max_cb_level = iodev->max_cb_level; |
501 | 0 | dev->buffer_size = iodev->buffer_size; |
502 | 0 | frames = dev->output_underrun(dev); |
503 | 0 | if (frames > 0) { |
504 | 0 | cras_iodev_update_underrun_duration(iodev, frames); |
505 | 0 | } |
506 | 0 | return frames; |
507 | 0 | } |
508 | | |
509 | 0 | static int no_stream(struct cras_iodev* iodev, int enable) { |
510 | 0 | struct cras_iodev* dev = active_profile_dev(iodev); |
511 | 0 | int rc; |
512 | |
|
513 | 0 | if (!dev) { |
514 | 0 | return -EINVAL; |
515 | 0 | } |
516 | | |
517 | 0 | if (dev->no_stream) { |
518 | | /* |
519 | | * Copy iodev->min_cb_level and iodev->max_cb_level from the |
520 | | * parent (i.e. bt_io). no_stream() of hfp_alsa_iodev will |
521 | | * use them. |
522 | | * A2DP and HFP dev will use buffer and callback sizes to fill |
523 | | * zeros in no stream state. |
524 | | */ |
525 | 0 | dev->min_cb_level = iodev->min_cb_level; |
526 | 0 | dev->max_cb_level = iodev->max_cb_level; |
527 | 0 | dev->buffer_size = iodev->buffer_size; |
528 | 0 | rc = dev->no_stream(dev, enable); |
529 | 0 | if (rc < 0) { |
530 | 0 | return rc; |
531 | 0 | } |
532 | 0 | } |
533 | 0 | if (enable) { |
534 | 0 | dev->state = CRAS_IODEV_STATE_NO_STREAM_RUN; |
535 | 0 | } else { |
536 | 0 | dev->state = CRAS_IODEV_STATE_NORMAL_RUN; |
537 | 0 | } |
538 | |
|
539 | 0 | return 0; |
540 | 0 | } |
541 | | |
542 | 0 | static int is_free_running(const struct cras_iodev* iodev) { |
543 | 0 | struct cras_iodev* dev = active_profile_dev(iodev); |
544 | 0 | if (!dev) { |
545 | 0 | return -EINVAL; |
546 | 0 | } |
547 | | |
548 | 0 | if (dev->is_free_running) { |
549 | 0 | return dev->is_free_running(dev); |
550 | 0 | } |
551 | | |
552 | 0 | return 0; |
553 | 0 | } |
554 | | |
555 | 0 | static bool can_start(const struct cras_iodev* iodev) { |
556 | 0 | struct cras_iodev* dev = active_profile_dev(iodev); |
557 | 0 | return cras_iodev_can_start(dev); |
558 | 0 | } |
559 | | |
560 | 0 | static int start(struct cras_iodev* iodev) { |
561 | 0 | struct cras_iodev* dev = active_profile_dev(iodev); |
562 | 0 | int rc; |
563 | |
|
564 | 0 | if (!dev) { |
565 | 0 | return -EINVAL; |
566 | 0 | } |
567 | | |
568 | 0 | if (cras_iodev_can_start(dev)) { |
569 | | /* |
570 | | * Fill in properties set by audio thread. A2dp or hfp |
571 | | * iodevs might need them to initialize states. |
572 | | */ |
573 | 0 | dev->min_cb_level = iodev->min_cb_level; |
574 | 0 | dev->max_cb_level = iodev->max_cb_level; |
575 | 0 | dev->buffer_size = iodev->buffer_size; |
576 | |
|
577 | 0 | rc = dev->start(dev); |
578 | 0 | if (rc) { |
579 | 0 | return rc; |
580 | 0 | } |
581 | 0 | } |
582 | 0 | dev->state = CRAS_IODEV_STATE_NORMAL_RUN; |
583 | 0 | return 0; |
584 | 0 | } |
585 | | |
586 | | static unsigned int frames_to_play_in_sleep(struct cras_iodev* iodev, |
587 | | unsigned int* hw_level, |
588 | 0 | struct timespec* hw_tstamp) { |
589 | 0 | struct cras_iodev* dev = active_profile_dev(iodev); |
590 | 0 | if (!dev || !dev->frames_to_play_in_sleep) { |
591 | 0 | return cras_iodev_default_frames_to_play_in_sleep(iodev, hw_level, |
592 | 0 | hw_tstamp); |
593 | 0 | } |
594 | | |
595 | 0 | return dev->frames_to_play_in_sleep(dev, hw_level, hw_tstamp); |
596 | 0 | } |
597 | | |
598 | | static int get_valid_frames(struct cras_iodev* iodev, |
599 | 0 | struct timespec* hw_tstamp) { |
600 | 0 | struct cras_iodev* dev = active_profile_dev(iodev); |
601 | 0 | if (!dev) { |
602 | 0 | return -EINVAL; |
603 | 0 | } |
604 | | |
605 | 0 | if (dev->get_valid_frames) { |
606 | 0 | return dev->get_valid_frames(dev, hw_tstamp); |
607 | 0 | } |
608 | | |
609 | 0 | return cras_iodev_frames_queued(iodev, hw_tstamp); |
610 | 0 | } |
611 | | |
612 | | // Creates a bt_io iodev wrapper. |
613 | | static struct cras_iodev* bt_io_create(struct bt_io_manager* mgr, |
614 | 1.09k | struct cras_iodev* dev) { |
615 | 1.09k | struct bt_io* btio; |
616 | 1.09k | struct cras_iodev* iodev; |
617 | 1.09k | struct cras_ionode* node; |
618 | 1.09k | struct bt_node* active; |
619 | 1.09k | enum CRAS_BT_FLAGS profile_flag; |
620 | | |
621 | 1.09k | if (!dev || !dev->active_node) { |
622 | 0 | return NULL; |
623 | 0 | } |
624 | | |
625 | 1.09k | btio = (struct bt_io*)calloc(1, sizeof(*btio)); |
626 | 1.09k | if (!btio) { |
627 | 0 | goto error; |
628 | 0 | } |
629 | 1.09k | btio->mgr = mgr; |
630 | | |
631 | 1.09k | iodev = &btio->base; |
632 | 1.09k | iodev->direction = dev->direction; |
633 | 1.09k | strlcpy(iodev->info.name, dev->info.name, sizeof(iodev->info.name)); |
634 | 1.09k | iodev->info.stable_id = dev->info.stable_id; |
635 | | |
636 | 1.09k | iodev->open_dev = open_dev; |
637 | 1.09k | iodev->configure_dev = configure_dev; |
638 | 1.09k | iodev->frames_queued = frames_queued; |
639 | 1.09k | iodev->delay_frames = delay_frames; |
640 | 1.09k | iodev->get_buffer = get_buffer; |
641 | 1.09k | iodev->put_buffer = put_buffer; |
642 | 1.09k | iodev->flush_buffer = flush_buffer; |
643 | 1.09k | iodev->close_dev = close_dev; |
644 | 1.09k | iodev->update_supported_formats = update_supported_formats; |
645 | 1.09k | iodev->update_active_node = update_active_node; |
646 | 1.09k | iodev->no_stream = no_stream; |
647 | 1.09k | iodev->output_underrun = output_underrun; |
648 | 1.09k | iodev->is_free_running = is_free_running; |
649 | 1.09k | iodev->get_valid_frames = get_valid_frames; |
650 | 1.09k | iodev->can_start = can_start; |
651 | 1.09k | iodev->start = start; |
652 | 1.09k | iodev->frames_to_play_in_sleep = frames_to_play_in_sleep; |
653 | | |
654 | 1.09k | if (dev->direction == CRAS_STREAM_OUTPUT) { |
655 | 654 | iodev->software_volume_needed = dev->software_volume_needed; |
656 | 654 | iodev->set_volume = set_bt_volume; |
657 | 654 | } |
658 | | |
659 | | /* Create the fake node so it's the only node exposed to UI, and |
660 | | * point it to the first profile dev. */ |
661 | 1.09k | active = (struct bt_node*)calloc(1, sizeof(*active)); |
662 | 1.09k | if (!active) { |
663 | 0 | goto error; |
664 | 0 | } |
665 | 1.09k | active->base.dev = iodev; |
666 | 1.09k | active->base.btflags = dev->active_node->btflags; |
667 | 1.09k | active->base.idx = btio->next_node_id++; |
668 | 1.09k | active->base.type = dev->active_node->type; |
669 | 1.09k | active->base.volume = 100; |
670 | 1.09k | active->base.stable_id = iodev->info.stable_id; |
671 | 1.09k | active->base.ui_gain_scaler = 1.0f; |
672 | | /* |
673 | | * If the same headset is connected in wideband mode, we shall assign |
674 | | * a separate stable_id so the node priority/preference mechanism in |
675 | | * Chrome UI doesn't break. |
676 | | */ |
677 | 1.09k | if ((active->base.type == CRAS_NODE_TYPE_BLUETOOTH) && |
678 | 1.09k | (dev->direction == CRAS_STREAM_INPUT)) { |
679 | 161 | active->base.stable_id = |
680 | 161 | SuperFastHash((const char*)&active->base.type, |
681 | 161 | sizeof(active->base.type), active->base.stable_id); |
682 | 161 | } |
683 | | |
684 | 1.09k | active->base.btflags = dev->active_node->btflags; |
685 | 1.09k | active->profile_dev = dev; |
686 | 1.09k | strlcpy(active->base.name, dev->info.name, sizeof(active->base.name)); |
687 | | // The node name exposed to UI should be a valid UTF8 string. |
688 | 1.09k | if (!is_utf8_string(active->base.name)) { |
689 | 434 | strlcpy(active->base.name, DEFAULT_BT_DEVICE_NAME, |
690 | 434 | sizeof(active->base.name)); |
691 | 434 | } |
692 | | |
693 | | // Configure NC. |
694 | 1.09k | if (dev->direction == CRAS_STREAM_INPUT && |
695 | 1.09k | cras_system_get_ap_nc_supported_on_bluetooth()) { |
696 | 440 | active->base.nc_providers = CRAS_NC_PROVIDER_AP; |
697 | 440 | } |
698 | | |
699 | 1.09k | cras_iodev_add_node(iodev, &active->base); |
700 | | |
701 | 1.09k | node = add_profile_dev(&btio->base, dev); |
702 | 1.09k | if (node == NULL) { |
703 | 0 | goto error; |
704 | 0 | } |
705 | | |
706 | | /* Now we're creating a new cras_bt_io for |active->base.btflags| |
707 | | * check what does the bt_io_manager currently use as active_btflag. |
708 | | * If |active_btflag| hasn't been set at all, assign |btflag| to it. |
709 | | * Or if this is A2DP which we treat as higiher priority, set to A2DP |
710 | | * if we can. |
711 | | */ |
712 | 1.09k | profile_flag = btflags_to_profile(active->base.btflags); |
713 | 1.09k | if (!btio->mgr->active_btflag || |
714 | 1.09k | (profile_flag == CRAS_BT_FLAG_A2DP && can_switch_to_a2dp(btio->mgr))) { |
715 | 620 | btio->mgr->active_btflag = profile_flag; |
716 | 620 | } |
717 | | |
718 | 1.09k | if (cras_iodev_list_add(iodev)) { |
719 | 0 | goto error; |
720 | 0 | } |
721 | | |
722 | 1.09k | cras_iodev_set_active_node(iodev, &active->base); |
723 | 1.09k | return &btio->base; |
724 | | |
725 | 0 | error: |
726 | 0 | free(btio); |
727 | 0 | return NULL; |
728 | 1.09k | } |
729 | | |
730 | 1.09k | static void bt_io_free_resources(struct cras_iodev* bt_iodev) { |
731 | 1.09k | struct cras_ionode* node; |
732 | 1.09k | struct bt_node* n; |
733 | | |
734 | 1.09k | free(bt_iodev->supported_rates); |
735 | 1.09k | free(bt_iodev->supported_channel_counts); |
736 | 1.09k | free(bt_iodev->supported_formats); |
737 | | |
738 | 2.18k | DL_FOREACH (bt_iodev->nodes, node) { |
739 | 2.18k | n = (struct bt_node*)node; |
740 | 2.18k | cras_iodev_rm_node(bt_iodev, node); |
741 | 2.18k | free(n); |
742 | 2.18k | } |
743 | | |
744 | 1.09k | cras_iodev_free_resources(bt_iodev); |
745 | 1.09k | } |
746 | | |
747 | | // Destroys a bt_io iodev wrapper. |
748 | 1.09k | static void bt_io_destroy(struct cras_iodev* bt_iodev) { |
749 | 1.09k | struct bt_io* btio = (struct bt_io*)bt_iodev; |
750 | 1.09k | int rc = cras_iodev_list_rm(bt_iodev); |
751 | | |
752 | 1.09k | if (rc == -EBUSY) { |
753 | 0 | return; |
754 | 0 | } |
755 | | |
756 | 1.09k | bt_io_free_resources(bt_iodev); |
757 | 1.09k | free(btio); |
758 | 1.09k | } |
759 | | |
760 | 328 | static int bt_io_append(struct cras_iodev* bt_iodev, struct cras_iodev* dev) { |
761 | 328 | struct cras_ionode* node; |
762 | 328 | struct bt_io* btio = (struct bt_io*)bt_iodev; |
763 | | |
764 | 328 | node = add_profile_dev(bt_iodev, dev); |
765 | 328 | if (!node) { |
766 | 0 | return -ENOMEM; |
767 | 0 | } |
768 | | |
769 | | // TODO(hychao): refine below after BT stop sending asynchronous |
770 | | // A2DP and HFP connection to CRAS. |
771 | 328 | if ((node->btflags & CRAS_BT_FLAG_A2DP) && can_switch_to_a2dp(btio->mgr)) { |
772 | 17 | possibly_switch_to_a2dp(btio->mgr); |
773 | 17 | } |
774 | 328 | return 0; |
775 | 328 | } |
776 | | |
777 | 362 | static int bt_io_remove(struct cras_iodev* bt_iodev, struct cras_iodev* dev) { |
778 | 362 | struct cras_ionode* node; |
779 | 362 | struct bt_node* btnode; |
780 | | |
781 | 1.05k | DL_FOREACH (bt_iodev->nodes, node) { |
782 | 1.05k | btnode = (struct bt_node*)node; |
783 | 1.05k | if (btnode->profile_dev != dev) { |
784 | 403 | continue; |
785 | 403 | } |
786 | | |
787 | | /* If this is the active node, reset it. Otherwise delete |
788 | | * this node. */ |
789 | 649 | if (node == bt_iodev->active_node) { |
790 | 321 | btnode->profile_dev = NULL; |
791 | 321 | btnode->base.btflags = CRAS_BT_FLAG_NONE; |
792 | 328 | } else { |
793 | 328 | DL_DELETE(bt_iodev->nodes, node); |
794 | 328 | free(node); |
795 | 328 | } |
796 | 649 | } |
797 | | |
798 | | /* The node of active profile could have been removed, update it. |
799 | | * Return err when fail to locate the active profile dev. */ |
800 | 362 | update_active_node(bt_iodev, 0, 1); |
801 | 362 | btnode = (struct bt_node*)bt_iodev->active_node; |
802 | 362 | if ((btnode->base.btflags == CRAS_BT_FLAG_NONE) || |
803 | 362 | (btnode->profile_dev == NULL)) { |
804 | 321 | return -EINVAL; |
805 | 321 | } |
806 | | |
807 | 41 | return 0; |
808 | 362 | } |
809 | | |
810 | 2.05k | struct bt_io_manager* bt_io_manager_create() { |
811 | 2.05k | struct bt_io_manager* mgr; |
812 | | |
813 | 2.05k | mgr = (struct bt_io_manager*)calloc(1, sizeof(*mgr)); |
814 | 2.05k | if (mgr == NULL) { |
815 | 0 | syslog(LOG_ERR, "No memory to create bt_io_manager"); |
816 | 0 | return NULL; |
817 | 0 | } |
818 | 2.05k | DL_APPEND(bt_io_managers, mgr); |
819 | 2.05k | return mgr; |
820 | 2.05k | } |
821 | | |
822 | 2.05k | void bt_io_manager_destroy(struct bt_io_manager* mgr) { |
823 | 2.05k | DL_DELETE(bt_io_managers, mgr); |
824 | 2.05k | if (mgr->bt_iodevs[CRAS_STREAM_INPUT]) { |
825 | 0 | syslog(LOG_WARNING, "Potential input bt_iodev leak"); |
826 | 0 | } |
827 | 2.05k | if (mgr->bt_iodevs[CRAS_STREAM_OUTPUT]) { |
828 | 0 | syslog(LOG_WARNING, "Potential output bt_iodev leak"); |
829 | 0 | } |
830 | | |
831 | 2.05k | free(mgr); |
832 | 2.05k | } |
833 | | |
834 | 0 | bool bt_io_manager_exists(struct bt_io_manager* target) { |
835 | 0 | struct bt_io_manager* mgr; |
836 | 0 | DL_FOREACH (bt_io_managers, mgr) { |
837 | 0 | if (mgr == target) { |
838 | 0 | return true; |
839 | 0 | } |
840 | 0 | } |
841 | 0 | return false; |
842 | 0 | } |
843 | | |
844 | | /* |
845 | | * Sets the audio nodes to 'plugged' means UI can select it and open it |
846 | | * for streams. Sets to 'unplugged' to hide these nodes from UI, when device |
847 | | * disconnects in progress. |
848 | | */ |
849 | 2.24k | void bt_io_manager_set_nodes_plugged(struct bt_io_manager* mgr, int plugged) { |
850 | 2.24k | struct cras_iodev* iodev; |
851 | | |
852 | 2.24k | iodev = mgr->bt_iodevs[CRAS_STREAM_INPUT]; |
853 | 2.24k | if (iodev) { |
854 | 1.35k | cras_iodev_set_node_plugged(iodev->active_node, plugged); |
855 | 1.35k | } |
856 | | |
857 | 2.24k | iodev = mgr->bt_iodevs[CRAS_STREAM_OUTPUT]; |
858 | 2.24k | if (iodev) { |
859 | 1.65k | cras_iodev_set_node_plugged(iodev->active_node, plugged); |
860 | 1.65k | } |
861 | 2.24k | } |
862 | | |
863 | | void bt_io_manager_append_iodev(struct bt_io_manager* mgr, |
864 | | struct cras_iodev* iodev, |
865 | 1.42k | enum CRAS_BT_FLAGS pflag) { |
866 | 1.42k | struct cras_iodev* bt_iodev; |
867 | | |
868 | 1.42k | bt_iodev = mgr->bt_iodevs[iodev->direction]; |
869 | | |
870 | 1.42k | if (!(iodev->active_node->btflags & pflag)) { |
871 | 0 | syslog(LOG_WARNING, "Incorrect btflags %.4x for dev %s as profile %.4x", |
872 | 0 | iodev->active_node->btflags, iodev->info.name, pflag); |
873 | 0 | return; |
874 | 0 | } |
875 | | |
876 | 1.42k | if (bt_iodev) { |
877 | 328 | bool exists = false; |
878 | 328 | switch (pflag) { |
879 | 17 | case CRAS_BT_FLAG_A2DP: |
880 | 17 | exists = bt_io_has_a2dp(bt_iodev); |
881 | 17 | break; |
882 | 311 | case CRAS_BT_FLAG_HFP: |
883 | 311 | exists = bt_io_has_hfp(bt_iodev); |
884 | 311 | break; |
885 | 0 | default: |
886 | 0 | return; // -EINVAL |
887 | 328 | } |
888 | | |
889 | 328 | if (exists) { |
890 | 0 | return; |
891 | 0 | } |
892 | | |
893 | 328 | bt_io_append(bt_iodev, iodev); |
894 | 1.09k | } else { |
895 | 1.09k | mgr->bt_iodevs[iodev->direction] = bt_io_create(mgr, iodev); |
896 | 1.09k | } |
897 | 1.42k | } |
898 | | |
899 | | void bt_io_manager_remove_iodev(struct bt_io_manager* mgr, |
900 | 1.42k | struct cras_iodev* iodev) { |
901 | 1.42k | struct cras_iodev* bt_iodev; |
902 | 1.42k | struct cras_ionode* node; |
903 | 1.42k | struct bt_node *active, *btnode; |
904 | 1.42k | unsigned int new_flag = CRAS_BT_FLAG_NONE; |
905 | 1.42k | int rc; |
906 | | |
907 | 1.42k | bt_io_manager_set_nodes_plugged(mgr, 0); |
908 | | |
909 | 1.42k | bt_iodev = mgr->bt_iodevs[iodev->direction]; |
910 | 1.42k | if (bt_iodev == NULL) { |
911 | 287 | return; |
912 | 287 | } |
913 | | |
914 | | // Check what will be the fallback profile if we remove |iodev|. |
915 | 1.13k | active = (struct bt_node*)bt_iodev->active_node; |
916 | 1.13k | if (active->profile_dev == iodev) { |
917 | 2.50k | DL_FOREACH (bt_iodev->nodes, node) { |
918 | 2.50k | btnode = (struct bt_node*)node; |
919 | | /* Skip the active node and the node we're trying |
920 | | * to remove. */ |
921 | 2.50k | if (btnode == active || btnode->profile_dev == iodev) { |
922 | 2.18k | continue; |
923 | 2.18k | } |
924 | 321 | new_flag = btnode->base.btflags; |
925 | 321 | break; |
926 | 2.50k | } |
927 | 1.09k | } else { |
928 | 41 | new_flag = active->base.btflags; |
929 | 41 | } |
930 | 1.13k | if (new_flag == CRAS_BT_FLAG_NONE) { |
931 | 773 | goto destroy_bt_io; |
932 | 773 | } |
933 | | |
934 | | /* If the check result |new_flag| doesn't match with the active |
935 | | * btflags we are currently using, switch to the profile specified |
936 | | * by |new_flag| before actually remove the iodev. |
937 | | */ |
938 | 362 | if (new_flag != active->base.btflags) { |
939 | 321 | mgr->active_btflag = btflags_to_profile(new_flag); |
940 | | |
941 | | // TODO(hychao): remove below code after BT remove HFP |
942 | | // and A2DP from CRAS in one synchronous event. |
943 | 321 | cras_bt_policy_switch_profile(mgr); |
944 | 321 | } |
945 | 362 | rc = bt_io_remove(bt_iodev, iodev); |
946 | 362 | if (rc) { |
947 | 321 | syslog(LOG_WARNING, "Fail to fallback to profile %u", new_flag); |
948 | 321 | goto destroy_bt_io; |
949 | 321 | } |
950 | | |
951 | 41 | return; |
952 | | |
953 | 1.09k | destroy_bt_io: |
954 | 1.09k | mgr->bt_iodevs[iodev->direction] = NULL; |
955 | 1.09k | bt_io_destroy(bt_iodev); |
956 | | |
957 | 1.09k | if (!mgr->bt_iodevs[CRAS_STREAM_INPUT] && |
958 | 1.09k | !mgr->bt_iodevs[CRAS_STREAM_OUTPUT]) { |
959 | 622 | mgr->active_btflag = CRAS_BT_FLAG_NONE; |
960 | 622 | } |
961 | 1.09k | } |
962 | | |
963 | | void bt_io_manager_set_telephony_use(struct bt_io_manager* mgr, |
964 | 693 | bool telephony_use) { |
965 | 693 | mgr->telephony_use = telephony_use; |
966 | | |
967 | 693 | if (mgr->active_btflag != CRAS_BT_FLAG_A2DP && can_switch_to_a2dp(mgr)) { |
968 | 34 | possibly_switch_to_a2dp(mgr); |
969 | 659 | } else if (mgr->active_btflag != CRAS_BT_FLAG_HFP && |
970 | 659 | !can_switch_to_a2dp(mgr)) { |
971 | 21 | switch_to_hfp(mgr); |
972 | 21 | } |
973 | 693 | } |