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