Commit 62776cc8 authored by Igor Kovalenko's avatar Igor Kovalenko Committed by PulseAudio Marge Bot
Browse files

bluetooth: apply write MTU detection based on read packet size

HFP Audio Connection SCO configuration is negotiated symmetrically in both
directions, and USB HCI SCO packet framing is also symmetric in both directions.
This means that packet size will be the same for reads and writes over HFP SCO
socket.

HFP profile specification states that valid speech data shall exist on the
Synchronous Connection in both directions after the Audio Connection is
established.

This guarantees that an incoming packet will arrive shortly after SCO connection
is established. Use it's size to fix write MTU in case kernel value is wrong.

Discussion here https://lore.kernel.org/patchwork/patch/1303411/

Part-of: <!507>
parent 4444ecad
......@@ -365,6 +365,10 @@ static ssize_t sco_transport_write(pa_bluetooth_transport *t, int fd, const void
pa_assert(t);
/* since SCO setup is symmetric, fix write MTU to be size of last read packet */
if (t->last_read_size)
write_mtu = PA_MIN(t->last_read_size, write_mtu);
/* if encoder buffer has less data than required to make complete packet */
if (size < write_mtu)
return 0;
......@@ -386,6 +390,11 @@ static ssize_t sco_transport_write(pa_bluetooth_transport *t, int fd, const void
pa_log_debug("Got EAGAIN on write() after POLLOUT, probably there is a temporary connection loss.");
/* Drain write buffer */
written = size;
} else if (errno == EINVAL && t->last_read_size == 0) {
/* Likely write_link_mtu is still wrong, retry after next successful read */
pa_log_debug("got write EINVAL, next successful read should fix MTU");
/* Drain write buffer */
written = size;
} else {
pa_log_error("Failed to write data to socket: %s", pa_cstrerror(errno));
/* Report error from write call */
......
......@@ -90,6 +90,10 @@ static ssize_t sco_transport_write(pa_bluetooth_transport *t, int fd, const void
pa_assert(t);
/* since SCO setup is symmetric, fix write MTU to be size of last read packet */
if (t->last_read_size)
write_mtu = PA_MIN(t->last_read_size, write_mtu);
/* if encoder buffer has less data than required to make complete packet */
if (size < write_mtu)
return 0;
......@@ -111,6 +115,11 @@ static ssize_t sco_transport_write(pa_bluetooth_transport *t, int fd, const void
pa_log_debug("Got EAGAIN on write() after POLLOUT, probably there is a temporary connection loss.");
/* Drain write buffer */
written = size;
} else if (errno == EINVAL && t->last_read_size == 0) {
/* Likely write_link_mtu is still wrong, retry after next successful read */
pa_log_debug("got write EINVAL, next successful read should fix MTU");
/* Drain write buffer */
written = size;
} else {
pa_log_error("Failed to write data to socket: %s", pa_cstrerror(errno));
/* Report error from write call */
......
......@@ -103,6 +103,7 @@ struct pa_bluetooth_transport {
const pa_a2dp_codec *bt_codec;
int stream_write_type;
size_t last_read_size;
pa_volume_t source_volume;
pa_volume_t sink_volume;
......
......@@ -413,6 +413,9 @@ static ssize_t bt_transport_read(pa_bluetooth_transport *t, int fd, void *buffer
pa_assert((size_t) received <= size);
/* allow write side to find out size of last read packet */
t->last_read_size = received;
if (p_timestamp) {
/* TODO: get timestamp from rtp */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment