1/* Copyright (c) 2013 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/socket.h>
7#include <syslog.h>
8
9#include "cras_audio_area.h"
10#include "cras_hfp_iodev.h"
11#include "cras_hfp_info.h"
12#include "cras_hfp_slc.h"
13#include "cras_iodev.h"
14#include "cras_system_state.h"
15#include "cras_util.h"
16#include "sfh.h"
17#include "utlist.h"
18
19
20struct hfp_io {
21	struct cras_iodev base;
22	struct cras_bt_device *device;
23	struct hfp_slc_handle *slc;
24	struct hfp_info *info;
25};
26
27static int update_supported_formats(struct cras_iodev *iodev)
28{
29	// 16 bit, mono, 8kHz
30	iodev->format->format = SND_PCM_FORMAT_S16_LE;
31
32	free(iodev->supported_rates);
33	iodev->supported_rates = (size_t *)malloc(2 * sizeof(size_t));
34	iodev->supported_rates[0] = 8000;
35	iodev->supported_rates[1] = 0;
36
37	free(iodev->supported_channel_counts);
38	iodev->supported_channel_counts = (size_t *)malloc(2 * sizeof(size_t));
39	iodev->supported_channel_counts[0] = 1;
40	iodev->supported_channel_counts[1] = 0;
41
42	free(iodev->supported_formats);
43	iodev->supported_formats =
44		(snd_pcm_format_t *)malloc(2 * sizeof(snd_pcm_format_t));
45	iodev->supported_formats[0] = SND_PCM_FORMAT_S16_LE;
46	iodev->supported_formats[1] = 0;
47
48	return 0;
49}
50
51static int frames_queued(const struct cras_iodev *iodev,
52			 struct timespec *tstamp)
53{
54	struct hfp_io *hfpio = (struct hfp_io *)iodev;
55
56	if (!hfp_info_running(hfpio->info))
57		return -1;
58
59	/* Do not enable timestamp mechanism on HFP device because last time
60	 * stamp might be a long time ago and it is not really useful. */
61	clock_gettime(CLOCK_MONOTONIC_RAW, tstamp);
62	return hfp_buf_queued(hfpio->info, iodev);
63}
64
65/* Modify the hfpio's buffer_size when the SCO packet size has changed. */
66static void hfp_packet_size_changed(void *data)
67{
68	struct hfp_io *hfpio = (struct hfp_io *)data;
69	struct cras_iodev *iodev = &hfpio->base;
70
71	if (!cras_iodev_is_open(iodev))
72		return;
73	iodev->buffer_size = hfp_buf_size(hfpio->info, iodev);
74	cras_bt_device_iodev_buffer_size_changed(hfpio->device);
75}
76
77static int open_dev(struct cras_iodev *iodev)
78{
79	struct hfp_io *hfpio = (struct hfp_io *)iodev;
80	int sk, err, mtu;
81
82	/* Assert format is set before opening device. */
83	if (iodev->format == NULL)
84		return -EINVAL;
85	iodev->format->format = SND_PCM_FORMAT_S16_LE;
86	cras_iodev_init_audio_area(iodev, iodev->format->num_channels);
87
88	if (hfp_info_running(hfpio->info))
89		goto add_dev;
90
91	sk = cras_bt_device_sco_connect(hfpio->device);
92	if (sk < 0)
93		goto error;
94
95	mtu = cras_bt_device_sco_mtu(hfpio->device, sk);
96
97	/* Start hfp_info */
98	err = hfp_info_start(sk, mtu, hfpio->info);
99	if (err)
100		goto error;
101
102add_dev:
103	hfp_info_add_iodev(hfpio->info, iodev);
104	hfp_set_call_status(hfpio->slc, 1);
105
106	iodev->buffer_size = hfp_buf_size(hfpio->info, iodev);
107
108	return 0;
109error:
110	syslog(LOG_ERR, "Failed to open HFP iodev");
111	return -1;
112}
113
114static int close_dev(struct cras_iodev *iodev)
115{
116	struct hfp_io *hfpio = (struct hfp_io *)iodev;
117
118	hfp_info_rm_iodev(hfpio->info, iodev);
119	if (hfp_info_running(hfpio->info) && !hfp_info_has_iodev(hfpio->info)) {
120		hfp_info_stop(hfpio->info);
121		hfp_set_call_status(hfpio->slc, 0);
122	}
123
124	cras_iodev_free_format(iodev);
125	cras_iodev_free_audio_area(iodev);
126	return 0;
127}
128
129static void set_hfp_volume(struct cras_iodev *iodev)
130{
131	size_t volume;
132	struct hfp_io *hfpio = (struct hfp_io *)iodev;
133
134	volume = cras_system_get_volume();
135	if (iodev->active_node)
136		volume = cras_iodev_adjust_node_volume(iodev->active_node, volume);
137
138	hfp_event_speaker_gain(hfpio->slc, volume);
139}
140
141static int delay_frames(const struct cras_iodev *iodev)
142{
143	struct timespec tstamp;
144
145	return frames_queued(iodev, &tstamp);
146}
147
148static int get_buffer(struct cras_iodev *iodev,
149		      struct cras_audio_area **area,
150		      unsigned *frames)
151{
152	struct hfp_io *hfpio = (struct hfp_io *)iodev;
153	uint8_t *dst = NULL;
154
155	if (!hfp_info_running(hfpio->info))
156		return -1;
157
158	hfp_buf_acquire(hfpio->info, iodev, &dst, frames);
159
160	iodev->area->frames = *frames;
161	/* HFP is mono only. */
162	iodev->area->channels[0].step_bytes =
163		cras_get_format_bytes(iodev->format);
164	iodev->area->channels[0].buf = dst;
165
166	*area = iodev->area;
167	return 0;
168}
169
170static int put_buffer(struct cras_iodev *iodev, unsigned nwritten)
171{
172	struct hfp_io *hfpio = (struct hfp_io *)iodev;
173
174	if (!hfp_info_running(hfpio->info))
175		return -1;
176
177	hfp_buf_release(hfpio->info, iodev, nwritten);
178	return 0;
179}
180
181static int flush_buffer(struct cras_iodev *iodev)
182{
183	struct hfp_io *hfpio = (struct hfp_io *)iodev;
184	unsigned nframes;
185
186	if (iodev->direction == CRAS_STREAM_INPUT) {
187		nframes = hfp_buf_queued(hfpio->info, iodev);
188		hfp_buf_release(hfpio->info, iodev, nframes);
189	}
190	return 0;
191}
192
193static void update_active_node(struct cras_iodev *iodev, unsigned node_idx,
194			       unsigned dev_enabled)
195{
196}
197
198void hfp_free_resources(struct hfp_io *hfpio)
199{
200	struct cras_ionode *node;
201	node = hfpio->base.active_node;
202	if (node) {
203		cras_iodev_rm_node(&hfpio->base, node);
204		free(node);
205	}
206	free(hfpio->base.supported_channel_counts);
207	free(hfpio->base.supported_rates);
208}
209
210struct cras_iodev *hfp_iodev_create(
211		enum CRAS_STREAM_DIRECTION dir,
212		struct cras_bt_device *device,
213		struct hfp_slc_handle *slc,
214		enum cras_bt_device_profile profile,
215		struct hfp_info *info)
216{
217	struct hfp_io *hfpio;
218	struct cras_iodev *iodev;
219	struct cras_ionode *node;
220	const char *name;
221
222	hfpio = (struct hfp_io *)calloc(1, sizeof(*hfpio));
223	if (!hfpio)
224		goto error;
225
226	iodev = &hfpio->base;
227	iodev->direction = dir;
228
229	hfpio->device = device;
230	hfpio->slc = slc;
231
232	/* Set iodev's name to device readable name or the address. */
233	name = cras_bt_device_name(device);
234	if (!name)
235		name = cras_bt_device_object_path(device);
236
237	snprintf(iodev->info.name, sizeof(iodev->info.name), "%s", name);
238	iodev->info.name[ARRAY_SIZE(iodev->info.name) - 1] = 0;
239	iodev->info.stable_id = SuperFastHash(
240			cras_bt_device_object_path(device),
241			strlen(cras_bt_device_object_path(device)),
242			strlen(cras_bt_device_object_path(device)));
243	iodev->info.stable_id_new = iodev->info.stable_id;
244
245	iodev->open_dev= open_dev;
246	iodev->frames_queued = frames_queued;
247	iodev->delay_frames = delay_frames;
248	iodev->get_buffer = get_buffer;
249	iodev->put_buffer = put_buffer;
250	iodev->flush_buffer = flush_buffer;
251	iodev->close_dev = close_dev;
252	iodev->update_supported_formats = update_supported_formats;
253	iodev->update_active_node = update_active_node;
254	iodev->set_volume = set_hfp_volume;
255
256	node = (struct cras_ionode *)calloc(1, sizeof(*node));
257	node->dev = iodev;
258	strcpy(node->name, iodev->info.name);
259
260	node->plugged = 1;
261	node->type = CRAS_NODE_TYPE_BLUETOOTH;
262	node->volume = 100;
263	gettimeofday(&node->plugged_time, NULL);
264
265	cras_bt_device_append_iodev(device, iodev, profile);
266	cras_iodev_add_node(iodev, node);
267	cras_iodev_set_active_node(iodev, node);
268
269	hfpio->info = info;
270	hfp_register_packet_size_changed_callback(info,
271						  hfp_packet_size_changed,
272						  hfpio);
273
274	return iodev;
275
276error:
277	if (hfpio) {
278		hfp_free_resources(hfpio);
279		free(hfpio);
280	}
281	return NULL;
282}
283
284void hfp_iodev_destroy(struct cras_iodev *iodev)
285{
286	struct hfp_io *hfpio = (struct hfp_io *)iodev;
287
288	cras_bt_device_rm_iodev(hfpio->device, iodev);
289	hfp_unregister_packet_size_changed_callback(hfpio->info, hfpio);
290	hfp_free_resources(hfpio);
291	free(hfpio);
292}
293