Home | History | Annotate | Download | only in server
      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 
     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 
     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 
     90 int hfp_info_has_iodev(struct hfp_info *info)
     91 {
     92 	return info->odev || info->idev;
     93 }
     94 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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  */
    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 
    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 
    329 int hfp_info_running(struct hfp_info *info)
    330 {
    331 	return info->started;
    332 }
    333 
    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 
    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 
    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