diff options
-rw-r--r-- | audio/pcm_bluetooth.c | 81 |
1 files changed, 51 insertions, 30 deletions
diff --git a/audio/pcm_bluetooth.c b/audio/pcm_bluetooth.c index da5927d0..9e5058c0 100644 --- a/audio/pcm_bluetooth.c +++ b/audio/pcm_bluetooth.c @@ -43,7 +43,7 @@ #define UINT_SECS_MAX (UINT_MAX / 1000000 - 1) -#define MIN_PERIOD_TIME 1000 +#define MIN_PERIOD_TIME 1 #define BUFFER_SIZE 2048 @@ -135,8 +135,8 @@ struct bluetooth_data { snd_pcm_ioplug_t io; volatile snd_pcm_sframes_t hw_ptr; struct ipc_data_cfg cfg; /* Bluetooth device config */ - int stream_fd; /* Audio stream filedescriptor */ - int sock; /* Daemon unix socket */ + struct pollfd stream; /* Audio stream filedescriptor */ + struct pollfd server; /* Audio daemon filedescriptor */ uint8_t buffer[BUFFER_SIZE]; /* Encoded transfer buffer */ int count; /* Transfer buffer counter */ struct bluetooth_a2dp a2dp; /* A2DP data */ @@ -166,6 +166,10 @@ static void *playback_hw_thread(void *param) unsigned int prev_periods; double period_time; struct timeval start; + struct pollfd fds[2]; + + fds[0] = data->server; + fds[1] = data->stream; prev_periods = 0; period_time = 1000000.0 * data->io.period_size / data->io.rate; @@ -175,6 +179,7 @@ static void *playback_hw_thread(void *param) while (1) { unsigned int dtime, periods; struct timeval cur, delta; + int ret; if (data->stopped) goto iter_sleep; @@ -208,11 +213,26 @@ static void *playback_hw_thread(void *param) } iter_sleep: - usleep(MIN_PERIOD_TIME); + ret = poll(fds, 2, MIN_PERIOD_TIME); + if (ret < 0) { + SNDERR("poll error: %s (%d)", strerror(errno), errno); + if (errno != EINTR) + break; + } else if (ret > 0) { + ret = (fds[0].revents) ? 0 : 1; + SNDERR("poll fd %d revents %d", ret, fds[ret].revents); + if (fds[ret].revents & POLLERR || + fds[ret].revents & POLLHUP || + fds[ret].revents & POLLNVAL) + break; + } /* Offer opportunity to be canceled by main thread */ pthread_testcancel(); } + + data->hw_thread = 0; + pthread_exit(NULL); } static int bluetooth_state_init(struct ipc_packet *pkt, int newstate) @@ -240,7 +260,7 @@ static int bluetooth_state(struct bluetooth_data *data, int newstate) if (ret < 0) return -ret; - ret = send(data->sock, pkt, sizeof(*pkt) + pkt->length, 0); + ret = send(data->server.fd, pkt, sizeof(*pkt) + pkt->length, 0); if (ret < 0) return -errno; else if (ret == 0) @@ -250,7 +270,7 @@ static int bluetooth_state(struct bluetooth_data *data, int newstate) memset(buf, 0, sizeof(buf)); - ret = recv(data->sock, buf, sizeof(*pkt) + sizeof(*state), 0); + ret = recv(data->server.fd, buf, sizeof(*pkt) + sizeof(*state), 0); if (ret < 0) return -errno; else if (ret == 0) @@ -314,11 +334,11 @@ static void bluetooth_exit(struct bluetooth_data *data) { struct bluetooth_a2dp *a2dp = &data->a2dp; - if (data->sock >= 0) - close(data->sock); + if (data->server.fd >= 0) + close(data->server.fd); - if (data->stream_fd >= 0) - close(data->stream_fd); + if (data->stream.fd >= 0) + close(data->stream.fd); if (data->hw_thread) { pthread_cancel(data->hw_thread); @@ -376,19 +396,19 @@ static int bluetooth_hsp_hw_params(snd_pcm_ioplug_t *io, uint32_t period_count = io->buffer_size / io->period_size; int opt_name, err; - DBG("fd=%d period_count=%d", data->stream_fd, period_count); + DBG("fd=%d period_count=%d", data->stream.fd, period_count); opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ? SCO_TXBUFS : SCO_RXBUFS; - if (setsockopt(data->stream_fd, SOL_SCO, opt_name, &period_count, + if (setsockopt(data->stream.fd, SOL_SCO, opt_name, &period_count, sizeof(period_count)) == 0) return 0; opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ? SO_SNDBUF : SO_RCVBUF; - if (setsockopt(data->stream_fd, SOL_SCO, opt_name, &period_count, + if (setsockopt(data->stream.fd, SOL_SCO, opt_name, &period_count, sizeof(period_count)) == 0) return 0; @@ -408,12 +428,12 @@ static int bluetooth_a2dp_hw_params(snd_pcm_ioplug_t *io, int opt_name, err; struct timeval t = { 0, period_count }; - DBG("fd=%d period_count=%d", data->stream_fd, period_count); + DBG("fd=%d period_count=%d", data->stream.fd, period_count); opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ? SO_SNDTIMEO : SO_RCVTIMEO; - if (setsockopt(data->stream_fd, SOL_SOCKET, opt_name, &t, + if (setsockopt(data->stream.fd, SOL_SOCKET, opt_name, &t, sizeof(t)) == 0) return 0; @@ -434,7 +454,7 @@ static int bluetooth_poll_descriptors(snd_pcm_ioplug_t *io, if (space < 1) return 0; - pfd[0].fd = data->stream_fd; + pfd[0].fd = data->stream.fd; pfd[0].events = POLLIN; pfd[0].revents = 0; @@ -512,7 +532,7 @@ static snd_pcm_sframes_t bluetooth_hsp_read(snd_pcm_ioplug_t *io, frame_size = areas->step / 8; - nrecv = recv(data->stream_fd, data->buffer, cfg.pkt_len, + nrecv = recv(data->stream.fd, data->buffer, cfg.pkt_len, MSG_WAITALL | (io->nonblock ? MSG_DONTWAIT : 0)); if (nrecv < 0) { @@ -592,7 +612,7 @@ static snd_pcm_sframes_t bluetooth_hsp_write(snd_pcm_ioplug_t *io, goto done; } - rsend = send(data->stream_fd, data->buffer, cfg.pkt_len, + rsend = send(data->stream.fd, data->buffer, cfg.pkt_len, io->nonblock ? MSG_DONTWAIT : 0); if (rsend > 0) { /* Reset count pointer */ @@ -636,7 +656,7 @@ static int avdtp_write(struct bluetooth_data *data) header->timestamp = htonl(a2dp->nsamples); header->ssrc = htonl(1); - ret = send(data->stream_fd, a2dp->buffer, a2dp->count, MSG_DONTWAIT); + ret = send(data->stream.fd, a2dp->buffer, a2dp->count, MSG_DONTWAIT); if (ret == -1) ret = -errno; @@ -919,7 +939,7 @@ static int bluetooth_recvmsg_fd(struct bluetooth_data *data) msgh.msg_control = &cmsg_b; msgh.msg_controllen = CMSG_LEN(sizeof(int)); - ret = recvmsg(data->sock, &msgh, 0); + ret = recvmsg(data->server.fd, &msgh, 0); if (ret < 0) { err = errno; SNDERR("Unable to receive fd: %s (%d)", strerror(err), err); @@ -931,8 +951,8 @@ static int bluetooth_recvmsg_fd(struct bluetooth_data *data) cmsg = CMSG_NXTHDR(&msgh, cmsg)) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { - data->stream_fd = (*(int *) CMSG_DATA(cmsg)); - DBG("stream_fd=%d", data->stream_fd); + data->stream.fd = (*(int *) CMSG_DATA(cmsg)); + DBG("stream_fd=%d", data->stream.fd); return 0; } } @@ -1132,7 +1152,7 @@ static int bluetooth_cfg(struct bluetooth_data *data, snd_pcm_stream_t stream, if (ret < 0) return -ret; - ret = send(data->sock, pkt, sizeof(*pkt) + pkt->length, 0); + ret = send(data->server.fd, pkt, sizeof(*pkt) + pkt->length, 0); if (ret < 0) return -errno; else if (ret == 0) @@ -1142,7 +1162,7 @@ static int bluetooth_cfg(struct bluetooth_data *data, snd_pcm_stream_t stream, memset(buf, 0, sizeof(buf)); - ret = recv(data->sock, buf, sizeof(*pkt) + sizeof(*cfg), 0); + ret = recv(data->server.fd, buf, sizeof(*pkt) + sizeof(*cfg), 0); if (ret < 0) return -errno; else if (ret == 0) @@ -1163,7 +1183,7 @@ static int bluetooth_cfg(struct bluetooth_data *data, snd_pcm_stream_t stream, if (cfg->codec != CFG_CODEC_SBC) goto done; - ret = recv(data->sock, sbc, sizeof(*sbc), 0); + ret = recv(data->server.fd, sbc, sizeof(*sbc), 0); if (ret < 0) return -errno; else if (ret == 0) @@ -1184,7 +1204,7 @@ done: DBG("Device configuration:"); DBG("\n\tfd=%d\n\tfd_opt=%u\n\tpkt_len=%u\n\tsample_size=%u\n\trate=%u", - data->stream_fd, data->cfg.fd_opt, data->cfg.pkt_len, + data->stream.fd, data->cfg.fd_opt, data->cfg.pkt_len, data->cfg.sample_size, data->cfg.rate); if (data->cfg.codec == CFG_CODEC_SBC) { @@ -1193,7 +1213,7 @@ done: return ret; } - if (data->stream_fd == -1) { + if (data->stream.fd == -1) { SNDERR("Error while configuring device: could not acquire audio socket"); return -EINVAL; } @@ -1204,7 +1224,7 @@ done: /* It is possible there is some outstanding data in the pipe - we have to empty it */ - while (recv(data->stream_fd, data->buffer, data->cfg.pkt_len, + while (recv(data->stream.fd, data->buffer, data->cfg.pkt_len, MSG_DONTWAIT) > 0); memset(data->buffer, 0, sizeof(data->buffer)); @@ -1225,7 +1245,7 @@ static int bluetooth_init(struct bluetooth_data *data, snd_pcm_stream_t stream, memset(data, 0, sizeof(struct bluetooth_data)); - data->sock = -1; + data->server.fd = -1; sk = socket(PF_LOCAL, SOCK_STREAM, 0); if (sk < 0) { @@ -1242,7 +1262,8 @@ static int bluetooth_init(struct bluetooth_data *data, snd_pcm_stream_t stream, return -err; } - data->sock = sk; + data->server.fd = sk; + data->server.events = POLLIN; data->pipefd[0] = -1; data->pipefd[1] = -1; |