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 <stdint.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <sys/socket.h>
10 #include <syslog.h>
11
12 #include "audio_thread.h"
13 #include "byte_buffer.h"
14 #include "cras_iodev_list.h"
15 #include "cras_hfp_info.h"
16 #include "utlist.h"
17
18 /* The max buffer size. Note that the actual used size must set to multiple
19 * of SCO packet size, and the packet size does not necessarily be equal to
20 * MTU.
21 */
22 #define MAX_HFP_BUF_SIZE_BYTES 16384
23
24 /* rate(8kHz) * sample_size(2 bytes) * channels(1) */
25 #define HFP_BYTE_RATE 16000
26
27 /* Structure to hold variables for a HFP connection. Since HFP supports
28 * bi-direction audio, two iodevs should share one hfp_info if they
29 * represent two directions of the same HFP headset
30 * Members:
31 * fd - The file descriptor for SCO socket.
32 * started - If the hfp_info has started to read/write SCO data.
33 * mtu - The max transmit unit reported from BT adapter.
34 * packet_size - The size of SCO packet to read/write preferred by
35 * adapter, could be different than mtu.
36 * capture_buf - The buffer to hold samples read from SCO socket.
37 * playback_buf - The buffer to hold samples about to write to SCO socket.
38 * idev - The input iodev using this hfp_info.
39 * odev - The output iodev using this hfp_info.
40 * packet_size_changed_cbs - The callbacks to trigger when SCO packet
41 * size changed.
42 */
43 struct hfp_info {
44 int fd;
45 int started;
46 unsigned int mtu;
47 unsigned int packet_size;
48 struct byte_buffer *capture_buf;
49 struct byte_buffer *playback_buf;
50
51 struct cras_iodev *idev;
52 struct cras_iodev *odev;
53 struct hfp_packet_size_changed_callback *packet_size_changed_cbs;
54 };
55
hfp_info_add_iodev(struct hfp_info * info,struct cras_iodev * dev)56 int hfp_info_add_iodev(struct hfp_info *info, struct cras_iodev *dev)
57 {
58 if (dev->direction == CRAS_STREAM_OUTPUT) {
59 if (info->odev)
60 goto invalid;
61 info->odev = dev;
62
63 buf_reset(info->playback_buf);
64 } else if (dev->direction == CRAS_STREAM_INPUT) {
65 if (info->idev)
66 goto invalid;
67 info->idev = dev;
68
69 buf_reset(info->capture_buf);
70 }
71
72 return 0;
73
74 invalid:
75 return -EINVAL;
76 }
77
hfp_info_rm_iodev(struct hfp_info * info,struct cras_iodev * dev)78 int hfp_info_rm_iodev(struct hfp_info *info, struct cras_iodev *dev)
79 {
80 if (dev->direction == CRAS_STREAM_OUTPUT && info->odev == dev) {
81 info->odev = NULL;
82 } else if (dev->direction == CRAS_STREAM_INPUT && info->idev == dev){
83 info->idev = NULL;
84 } else
85 return -EINVAL;
86
87 return 0;
88 }
89
hfp_info_has_iodev(struct hfp_info * info)90 int hfp_info_has_iodev(struct hfp_info *info)
91 {
92 return info->odev || info->idev;
93 }
94
hfp_buf_acquire(struct hfp_info * info,struct cras_iodev * dev,uint8_t ** buf,unsigned * count)95 void hfp_buf_acquire(struct hfp_info *info, struct cras_iodev *dev,
96 uint8_t **buf, unsigned *count)
97 {
98 size_t format_bytes;
99 unsigned int buf_avail;
100 format_bytes = cras_get_format_bytes(dev->format);
101
102 *count *= format_bytes;
103
104 if (dev->direction == CRAS_STREAM_OUTPUT)
105 *buf = buf_write_pointer_size(info->playback_buf, &buf_avail);
106 else
107 *buf = buf_read_pointer_size(info->capture_buf, &buf_avail);
108
109 if (*count > buf_avail)
110 *count = buf_avail;
111 *count /= format_bytes;
112 }
113
hfp_buf_size(struct hfp_info * info,struct cras_iodev * dev)114 int hfp_buf_size(struct hfp_info *info, struct cras_iodev *dev)
115 {
116 return info->playback_buf->used_size / cras_get_format_bytes(dev->format);
117 }
118
hfp_buf_release(struct hfp_info * info,struct cras_iodev * dev,unsigned written_frames)119 void hfp_buf_release(struct hfp_info *info, struct cras_iodev *dev,
120 unsigned written_frames)
121 {
122 size_t format_bytes;
123 format_bytes = cras_get_format_bytes(dev->format);
124
125 written_frames *= format_bytes;
126
127 if (dev->direction == CRAS_STREAM_OUTPUT)
128 buf_increment_write(info->playback_buf, written_frames);
129 else
130 buf_increment_read(info->capture_buf, written_frames);
131 }
132
hfp_buf_queued(struct hfp_info * info,const struct cras_iodev * dev)133 int hfp_buf_queued(struct hfp_info *info, const struct cras_iodev *dev)
134 {
135 size_t format_bytes;
136 format_bytes = cras_get_format_bytes(dev->format);
137
138 if (dev->direction == CRAS_STREAM_OUTPUT)
139 return buf_queued_bytes(info->playback_buf) / format_bytes;
140 else
141 return buf_queued_bytes(info->capture_buf) / format_bytes;
142 }
143
hfp_write(struct hfp_info * info)144 int hfp_write(struct hfp_info *info)
145 {
146 int err = 0;
147 unsigned to_send;
148 uint8_t *samples;
149
150 /* Write something */
151 samples = buf_read_pointer_size(info->playback_buf, &to_send);
152 if (to_send < info->packet_size)
153 return 0;
154 to_send = info->packet_size;
155
156 send_sample:
157 err = send(info->fd, samples, to_send, 0);
158 if (err < 0) {
159 if (errno == EINTR)
160 goto send_sample;
161
162 return err;
163 }
164
165 if (err != (int)info->packet_size) {
166 syslog(LOG_ERR,
167 "Partially write %d bytes for SCO packet size %u",
168 err, info->packet_size);
169 return -1;
170 }
171
172 buf_increment_read(info->playback_buf, to_send);
173
174 return err;
175 }
176
177
hfp_info_set_packet_size(struct hfp_info * info,unsigned int packet_size)178 static void hfp_info_set_packet_size(struct hfp_info *info,
179 unsigned int packet_size)
180 {
181 struct hfp_packet_size_changed_callback *callback;
182 unsigned int used_size =
183 MAX_HFP_BUF_SIZE_BYTES / packet_size * packet_size;
184 info->packet_size = packet_size;
185 byte_buffer_set_used_size(info->playback_buf, used_size);
186 byte_buffer_set_used_size(info->capture_buf, used_size);
187
188 DL_FOREACH(info->packet_size_changed_cbs, callback)
189 callback->cb(callback->data);
190 }
191
hfp_register_packet_size_changed_callback(struct hfp_info * info,void (* cb)(void * data),void * data)192 void hfp_register_packet_size_changed_callback(struct hfp_info *info,
193 void (*cb)(void *data),
194 void *data)
195 {
196 struct hfp_packet_size_changed_callback *callback =
197 (struct hfp_packet_size_changed_callback *)calloc(1,
198 sizeof(struct hfp_packet_size_changed_callback));
199 callback->data = data;
200 callback->cb = cb;
201 DL_APPEND(info->packet_size_changed_cbs, callback);
202 }
203
hfp_unregister_packet_size_changed_callback(struct hfp_info * info,void * data)204 void hfp_unregister_packet_size_changed_callback(struct hfp_info *info,
205 void *data)
206 {
207 struct hfp_packet_size_changed_callback *callback;
208 DL_FOREACH(info->packet_size_changed_cbs, callback) {
209 if (data == callback->data) {
210 DL_DELETE(info->packet_size_changed_cbs, callback);
211 free(callback);
212 }
213 }
214 }
215
hfp_read(struct hfp_info * info)216 int hfp_read(struct hfp_info *info)
217 {
218 int err = 0;
219 unsigned to_read;
220 uint8_t *capture_buf;
221
222 capture_buf = buf_write_pointer_size(info->capture_buf, &to_read);
223
224 if (to_read < info->packet_size)
225 return 0;
226 to_read = info->packet_size;
227
228 recv_sample:
229 err = recv(info->fd, capture_buf, to_read, 0);
230 if (err < 0) {
231 syslog(LOG_ERR, "Read error %s", strerror(errno));
232 if (errno == EINTR)
233 goto recv_sample;
234
235 return err;
236 }
237
238 if (err != (int)info->packet_size) {
239 /* Allow the SCO packet size be modified from the default MTU
240 * value to the size of SCO data we first read. This is for
241 * some adapters who prefers a different value than MTU for
242 * transmitting SCO packet.
243 */
244 if (err && (info->packet_size == info->mtu)) {
245 hfp_info_set_packet_size(info, err);
246 } else {
247 syslog(LOG_ERR, "Partially read %d bytes for %u size SCO packet",
248 err, info->packet_size);
249 return -1;
250 }
251 }
252
253 buf_increment_write(info->capture_buf, err);
254
255 return err;
256 }
257
258 /* Callback function to handle sample read and write.
259 * Note that we poll the SCO socket for read sample, since it reflects
260 * there is actual some sample to read while the socket always reports
261 * writable even when device buffer is full.
262 * The strategy is to synchronize read & write operations:
263 * 1. Read one chunk of MTU bytes of data.
264 * 2. When input device not attached, ignore the data just read.
265 * 3. When output device attached, write one chunk of MTU bytes of data.
266 */
hfp_info_callback(void * arg)267 static int hfp_info_callback(void *arg)
268 {
269 struct hfp_info *info = (struct hfp_info *)arg;
270 int err;
271
272 if (!info->started)
273 goto read_write_error;
274
275 err = hfp_read(info);
276 if (err < 0) {
277 syslog(LOG_ERR, "Read error");
278 goto read_write_error;
279 }
280
281 /* Ignore the MTU bytes just read if input dev not in present */
282 if (!info->idev)
283 buf_increment_read(info->capture_buf, info->packet_size);
284
285 if (info->odev) {
286 err = hfp_write(info);
287 if (err < 0) {
288 syslog(LOG_ERR, "Write error");
289 goto read_write_error;
290 }
291 }
292
293 return 0;
294
295 read_write_error:
296 hfp_info_stop(info);
297
298 return 0;
299 }
300
hfp_info_create()301 struct hfp_info *hfp_info_create()
302 {
303 struct hfp_info *info;
304 info = (struct hfp_info *)calloc(1, sizeof(*info));
305 if (!info)
306 goto error;
307
308 info->capture_buf = byte_buffer_create(MAX_HFP_BUF_SIZE_BYTES);
309 if (!info->capture_buf)
310 goto error;
311
312 info->playback_buf = byte_buffer_create(MAX_HFP_BUF_SIZE_BYTES);
313 if (!info->playback_buf)
314 goto error;
315
316 return info;
317
318 error:
319 if (info) {
320 if (info->capture_buf)
321 byte_buffer_destroy(info->capture_buf);
322 if (info->playback_buf)
323 byte_buffer_destroy(info->playback_buf);
324 free(info);
325 }
326 return NULL;
327 }
328
hfp_info_running(struct hfp_info * info)329 int hfp_info_running(struct hfp_info *info)
330 {
331 return info->started;
332 }
333
hfp_info_start(int fd,unsigned int mtu,struct hfp_info * info)334 int hfp_info_start(int fd, unsigned int mtu, struct hfp_info *info)
335 {
336 info->fd = fd;
337 info->mtu = mtu;
338
339 /* Make sure buffer size is multiple of packet size, which initially
340 * set to MTU. */
341 hfp_info_set_packet_size(info, mtu);
342 buf_reset(info->playback_buf);
343 buf_reset(info->capture_buf);
344
345 audio_thread_add_callback(info->fd, hfp_info_callback, info);
346
347 info->started = 1;
348
349 return 0;
350 }
351
hfp_info_stop(struct hfp_info * info)352 int hfp_info_stop(struct hfp_info *info)
353 {
354 if (!info->started)
355 return 0;
356
357 audio_thread_rm_callback_sync(
358 cras_iodev_list_get_audio_thread(),
359 info->fd);
360
361 close(info->fd);
362 info->fd = 0;
363 info->started = 0;
364
365 return 0;
366 }
367
hfp_info_destroy(struct hfp_info * info)368 void hfp_info_destroy(struct hfp_info *info)
369 {
370 if (info->capture_buf)
371 byte_buffer_destroy(info->capture_buf);
372
373 if (info->playback_buf)
374 byte_buffer_destroy(info->playback_buf);
375
376 free(info);
377 }
378