cras_bt_io.c revision 532e64eee91fc4acf5796e0a61c242a442a4cc04
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 <syslog.h>
7
8#include "cras_bt_io.h"
9#include "cras_bt_device.h"
10#include "cras_iodev.h"
11#include "cras_iodev_list.h"
12#include "utlist.h"
13
14/* Extends cras_ionode to hold bluetooth profile information
15 * so that iodevs of different profile(A2DP or HFP/HSP) can be
16 * associated with the same bt_io.
17 * Members:
18 *    base - The base class cras_ionode.
19 *    profile_dev - Pointer to the profile specific iodev.
20 *    profile - The bluetooth profile profile_dev runs on.
21 */
22struct bt_node {
23	struct cras_ionode base;
24	struct cras_iodev *profile_dev;
25	enum cras_bt_device_profile profile;
26};
27
28/* The structure represents a virtual input or output device of a
29 * bluetooth audio device, speaker or headset for example. A node
30 * will be added to this virtual iodev for each profile supported
31 * by the bluetooth audio device.
32 * Member:
33 *    base - The base class cras_iodev
34 *    next_node_id - The index will give to the next node
35 */
36struct bt_io {
37	struct cras_iodev base;
38	unsigned int next_node_id;
39	struct cras_bt_device *device;
40};
41
42/* Returns the active profile specific iodev. */
43static struct cras_iodev *active_profile_dev(const struct cras_iodev *iodev)
44{
45	struct bt_node *active = (struct bt_node *)iodev->active_node;
46
47	return active->profile_dev;
48}
49
50/* Adds a profile specific iodev to btio. */
51static struct cras_ionode *add_profile_dev(struct cras_iodev *bt_iodev,
52					   struct cras_iodev *dev,
53					   enum cras_bt_device_profile profile)
54{
55	struct bt_node *n;
56	struct bt_io *btio = (struct bt_io *)bt_iodev;
57
58	n = (struct bt_node *)calloc(1, sizeof(*n));
59	if (!n)
60		return NULL;
61
62	n->base.dev = bt_iodev;
63	n->base.idx = btio->next_node_id++;
64	n->base.type = CRAS_NODE_TYPE_BLUETOOTH;
65	n->base.volume = 100;
66	gettimeofday(&n->base.plugged_time, NULL);
67
68	strcpy(n->base.name, dev->info.name);
69	n->profile_dev = dev;
70	n->profile = profile;
71
72	cras_iodev_add_node(bt_iodev, &n->base);
73	return &n->base;
74}
75
76/* Forces bt device to switch to use the given profile. Note that if
77 * it has already been open for streaming, the new active profile will
78 * take effect after the related btio(s) are reopened.
79 */
80static void bt_switch_to_profile(struct cras_bt_device *device,
81				 enum cras_bt_device_profile profile)
82{
83	switch (profile) {
84	case CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY:
85	case CRAS_BT_DEVICE_PROFILE_HSP_AUDIOGATEWAY:
86		cras_bt_device_set_active_profile(device,
87				CRAS_BT_DEVICE_PROFILE_HSP_AUDIOGATEWAY |
88				CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
89		break;
90	case CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE:
91		cras_bt_device_set_active_profile(device,
92				CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE);
93		break;
94	default:
95		syslog(LOG_ERR, "Unexpect profile %u", profile);
96		break;
97	}
98}
99
100/* Checks if bt device is active for the given profile.
101 */
102static int device_using_profile(struct cras_bt_device *device,
103				unsigned int profile)
104{
105	return cras_bt_device_get_active_profile(device) & profile;
106}
107
108/* Checks if the condition is met to switch to a different profile
109 * when trying to set the format to btio before open it. Base on two
110 * rules:
111 * (1) Prefer to use A2DP for output since the audio quality is better.
112 * (2) Must use HFP/HSP for input since A2DP doesn't support audio input.
113 *
114 * If the profile switch happens, return non-zero error code, otherwise
115 * return zero.
116 */
117static int update_supported_formats(struct cras_iodev *iodev)
118{
119	struct bt_io *btio = (struct bt_io *)iodev;
120	struct cras_iodev *dev = active_profile_dev(iodev);
121	int rc, length, i;
122
123	/* Force to use HFP if opening input dev. */
124	if (device_using_profile(btio->device,
125				 CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE) &&
126	    iodev->direction == CRAS_STREAM_INPUT) {
127		bt_switch_to_profile(btio->device,
128				     CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY);
129		cras_bt_device_switch_profile_on_open(btio->device, iodev);
130		return -EAGAIN;
131	}
132
133	if (dev->format == NULL) {
134		dev->format = (struct cras_audio_format *)
135				malloc(sizeof(*dev->format));
136		*dev->format = *iodev->format;
137	}
138
139	if (dev->update_supported_formats) {
140		rc = dev->update_supported_formats(dev);
141		if (rc)
142			return rc;
143	}
144
145	/* Fill in the supported rates and channel counts. */
146	for (length = 0; dev->supported_rates[length]; length++);
147	free(iodev->supported_rates);
148	iodev->supported_rates = (size_t *)malloc(
149			(length + 1) * sizeof(*iodev->supported_rates));
150	for (i = 0; i < length + 1; i++)
151		iodev->supported_rates[i] = dev->supported_rates[i];
152
153	for (length = 0; dev->supported_channel_counts[length]; length++);
154	iodev->supported_channel_counts = (size_t *)malloc(
155		(length + 1) * sizeof(*iodev->supported_channel_counts));
156	for (i = 0; i < length + 1; i++)
157		iodev->supported_channel_counts[i] =
158			dev->supported_channel_counts[i];
159
160	for (length = 0; dev->supported_formats[length]; length++);
161	iodev->supported_formats = (snd_pcm_format_t *)malloc(
162		(length + 1) * sizeof(*iodev->supported_formats));
163	for (i = 0; i < length + 1; i++)
164		iodev->supported_formats[i] =
165			dev->supported_formats[i];
166	return 0;
167}
168
169static int open_dev(struct cras_iodev *iodev)
170{
171	int rc;
172	struct cras_iodev *dev = active_profile_dev(iodev);
173	if (!dev)
174		return -EINVAL;
175
176	/* Fill back the format iodev is using. */
177	*dev->format = *iodev->format;
178
179	rc = dev->open_dev(dev);
180	if (rc)
181		return rc;
182
183	iodev->buffer_size = dev->buffer_size;
184	iodev->min_buffer_level = dev->min_buffer_level;
185	return 0;
186}
187
188static int close_dev(struct cras_iodev *iodev)
189{
190	struct bt_io *btio = (struct bt_io *)iodev;
191	int rc;
192	struct cras_iodev *dev = active_profile_dev(iodev);
193
194	/* Force back to A2DP if closing HFP. */
195	if (device_using_profile(btio->device,
196			CRAS_BT_DEVICE_PROFILE_HSP_AUDIOGATEWAY |
197			CRAS_BT_DEVICE_PROFILE_HFP_AUDIOGATEWAY) &&
198	    iodev->direction == CRAS_STREAM_INPUT &&
199	    cras_bt_device_supports_profile(btio->device,
200			CRAS_BT_DEVICE_PROFILE_A2DP_SINK)) {
201		cras_bt_device_set_active_profile(btio->device,
202				CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE);
203		cras_bt_device_switch_profile_on_close(btio->device,
204						       iodev);
205	}
206
207	rc = dev->close_dev(dev);
208	if (rc < 0)
209		return rc;
210	cras_iodev_free_format(iodev);
211	return 0;
212}
213
214static int is_open(const struct cras_iodev *iodev)
215{
216	struct cras_iodev *dev = active_profile_dev(iodev);
217	if (!dev)
218		return 0;
219	return dev->is_open(dev);
220}
221
222static int frames_queued(const struct cras_iodev *iodev)
223{
224	struct cras_iodev *dev = active_profile_dev(iodev);
225	if (!dev)
226		return -EINVAL;
227	return dev->frames_queued(dev);
228}
229
230static int dev_running(const struct cras_iodev *iodev)
231{
232	struct cras_iodev *dev = active_profile_dev(iodev);
233	if (!dev)
234		return -EINVAL;
235	return dev->dev_running(dev);
236}
237
238static int delay_frames(const struct cras_iodev *iodev)
239{
240	struct cras_iodev *dev = active_profile_dev(iodev);
241	if (!dev)
242		return -EINVAL;
243	return dev->delay_frames(dev);
244}
245
246static int get_buffer(struct cras_iodev *iodev,
247		      struct cras_audio_area **area,
248		      unsigned *frames)
249{
250	struct cras_iodev *dev = active_profile_dev(iodev);
251	if (!dev)
252		return -EINVAL;
253	return dev->get_buffer(dev, area, frames);
254}
255
256static int put_buffer(struct cras_iodev *iodev, unsigned nwritten)
257{
258	struct cras_iodev *dev = active_profile_dev(iodev);
259	if (!dev)
260		return -EINVAL;
261	return dev->put_buffer(dev, nwritten);
262}
263
264/* If the first private iodev doesn't match the active profile stored on
265 * device, select to the correct private iodev.
266 */
267static void update_active_node(struct cras_iodev *iodev)
268{
269	struct bt_io *btio = (struct bt_io *)iodev;
270	struct cras_ionode *node;
271	struct bt_node *active = (struct bt_node *)iodev->active_node;
272
273	if (device_using_profile(btio->device, active->profile))
274		return;
275
276	/* Switch to the correct dev using active_profile. */
277	DL_FOREACH(iodev->nodes, node) {
278		struct bt_node *n = (struct bt_node *)node;
279		if (n == active)
280			continue;
281
282		if (device_using_profile(btio->device, n->profile)) {
283			active->profile = n->profile;
284			active->profile_dev = n->profile_dev;
285		}
286	}
287}
288
289struct cras_iodev *cras_bt_io_create(struct cras_bt_device *device,
290				     struct cras_iodev *dev,
291				     enum cras_bt_device_profile profile)
292{
293	int err;
294	struct bt_io *btio;
295	struct cras_iodev *iodev;
296	struct cras_ionode *node;
297	struct bt_node *active;
298
299	if (!dev)
300		return NULL;
301
302	btio = (struct bt_io *)calloc(1, sizeof(*btio));
303	if (!btio)
304		goto error;
305	btio->device = device;
306
307	bt_switch_to_profile(device, profile);
308
309	iodev = &btio->base;
310	iodev->direction = dev->direction;
311	strcpy(iodev->info.name, dev->info.name);
312
313	iodev->open_dev = open_dev;
314	iodev->is_open = is_open; /* Needed by thread_add_stream */
315	iodev->frames_queued = frames_queued;
316	iodev->dev_running = dev_running;
317	iodev->delay_frames = delay_frames;
318	iodev->get_buffer = get_buffer;
319	iodev->put_buffer = put_buffer;
320	iodev->close_dev = close_dev;
321	iodev->update_supported_formats = update_supported_formats;
322	iodev->update_active_node = update_active_node;
323	iodev->software_volume_needed = 1;
324
325	/* Create the dummy node set to plugged so it's the only node exposed
326	 * to UI, and point it to the first profile dev. */
327	active = (struct bt_node *)calloc(1, sizeof(*active));
328	if (!active)
329		return NULL;
330	active->base.dev = iodev;
331	active->base.idx = btio->next_node_id++;
332	active->base.type = CRAS_NODE_TYPE_BLUETOOTH;
333	active->base.volume = 100;
334	active->base.plugged = 1;
335	active->profile = profile;
336	active->profile_dev = dev;
337	gettimeofday(&active->base.plugged_time, NULL);
338	strcpy(active->base.name, dev->info.name);
339	cras_iodev_add_node(iodev, &active->base);
340
341	node = add_profile_dev(&btio->base, dev, profile);
342	if (node == NULL)
343		goto error;
344
345	if (iodev->direction == CRAS_STREAM_OUTPUT)
346		err = cras_iodev_list_add_output(iodev);
347	else
348		err = cras_iodev_list_add_input(iodev);
349	if (err)
350		goto error;
351
352	cras_iodev_set_active_node(iodev, &active->base);
353	return &btio->base;
354
355error:
356	if (btio)
357		free(btio);
358	return NULL;
359}
360
361void cras_bt_io_destroy(struct cras_iodev *bt_iodev)
362{
363	int rc;
364	struct bt_io *btio = (struct bt_io *)bt_iodev;
365	struct cras_ionode *node;
366	struct bt_node *n;
367
368	if (bt_iodev->direction == CRAS_STREAM_OUTPUT)
369		rc = cras_iodev_list_rm_output(bt_iodev);
370	else
371		rc = cras_iodev_list_rm_input(bt_iodev);
372	if (rc == -EBUSY)
373		return;
374
375	DL_FOREACH(bt_iodev->nodes, node) {
376		n = (struct bt_node *)node;
377		cras_iodev_rm_node(bt_iodev, node);
378		free(n);
379	}
380	free(btio);
381}
382
383int cras_bt_io_has_dev(struct cras_iodev *bt_iodev,
384			  struct cras_iodev *dev)
385{
386	struct cras_ionode *node;
387
388	DL_FOREACH(bt_iodev->nodes, node) {
389		struct bt_node *n = (struct bt_node *)node;
390		if (n->profile_dev == dev)
391			return 1;
392	}
393	return 0;
394}
395
396int cras_bt_io_append(struct cras_iodev *bt_iodev,
397		      struct cras_iodev *dev,
398		      enum cras_bt_device_profile profile)
399{
400	struct cras_ionode *node;
401	struct bt_io *btio = (struct bt_io *)bt_iodev;
402
403	if (cras_bt_io_has_dev(bt_iodev, dev))
404		return -EEXIST;
405
406	node = add_profile_dev(bt_iodev, dev, profile);
407	if (!node)
408		return -ENOMEM;
409
410	if (profile == CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE &&
411	    cras_bt_device_can_switch_to_a2dp(btio->device)) {
412		bt_switch_to_profile(btio->device,
413				     CRAS_BT_DEVICE_PROFILE_A2DP_SOURCE);
414		cras_bt_device_switch_profile_on_open(btio->device, bt_iodev);
415		syslog(LOG_ERR, "Switch to A2DP on append");
416	}
417	return 0;
418}
419
420unsigned int cras_bt_io_try_remove(struct cras_iodev *bt_iodev,
421				   struct cras_iodev *dev)
422{
423	struct cras_ionode *node;
424	struct bt_node *active, *btnode;
425	unsigned int try_profile = 0;
426
427	active = (struct bt_node *)bt_iodev->active_node;
428
429	if (active->profile_dev == dev) {
430		DL_FOREACH(bt_iodev->nodes, node) {
431			btnode = (struct bt_node *)node;
432			/* Skip the active node and the node we're trying
433			 * to remove. */
434			if (btnode == active || btnode->profile_dev == dev)
435				continue;
436			try_profile = btnode->profile;
437			break;
438		}
439	} else {
440		try_profile = active->profile;
441	}
442	return try_profile;
443}
444
445int cras_bt_io_remove(struct cras_iodev *bt_iodev,
446		      struct cras_iodev *dev)
447{
448	struct cras_ionode *node;
449	struct bt_node *btnode;
450
451	DL_SEARCH_SCALAR_WITH_CAST(bt_iodev->nodes, node, btnode,
452				   profile_dev, dev);
453	if (node) {
454		DL_DELETE(bt_iodev->nodes, node);
455		free(node);
456	}
457	return 0;
458}
459