/* Callback function to handle sample read and write. * Note that we poll the SCO socket for read sample, since it reflects * there is actual some sample to read while the socket always reports * writable even when device buffer is full. * The strategy is to synchronize read & write operations: * 1. Read one chunk of MTU bytes of data. * 2. When input device not attached, ignore the data just read. * 3. When output device attached, write one chunk of MTU bytes of data. */ static int hfp_info_callback(void *arg) { struct hfp_info *info = (struct hfp_info *)arg; int err; if (!info->started) goto read_write_error; err = hfp_read(info); if (err < 0) { syslog(LOG_ERR, "Read error"); goto read_write_error; } /* Ignore the MTU bytes just read if input dev not in present */ if (!info->idev) buf_increment_read(info->capture_buf, info->packet_size); if (info->odev) { err = hfp_write(info); if (err < 0) { syslog(LOG_ERR, "Write error"); goto read_write_error; } } return 0; read_write_error: hfp_info_stop(info); return 0; }
static int close_dev(struct cras_iodev *iodev) { struct hfp_io *hfpio = (struct hfp_io *)iodev; hfp_info_rm_iodev(hfpio->info, iodev); if (hfp_info_running(hfpio->info) && !hfp_info_has_iodev(hfpio->info)) { hfp_info_stop(hfpio->info); hfp_set_call_status(hfpio->slc, 0); } cras_iodev_free_format(iodev); cras_iodev_free_audio_area(iodev); return 0; }
static void destroy_audio_gateway(struct audio_gateway *ag) { DL_DELETE(connected_ags, ag); if (ag->idev) hfp_iodev_destroy(ag->idev); if (ag->odev) hfp_iodev_destroy(ag->odev); if (ag->info) { if (hfp_info_running(ag->info)) hfp_info_stop(ag->info); hfp_info_destroy(ag->info); } if (ag->slc_handle) hfp_slc_destroy(ag->slc_handle); /* If the bt device is not using a2dp, do a deeper clean up * to force disconnect it. */ if (!cras_bt_device_has_a2dp(ag->device)) cras_bt_device_disconnect(ag->conn, ag->device); free(ag); }