This should guarantee that any outstanding command in the queue is
cancelled, accourding to the avdtp spec:
"6.16 Abort
Because AVDTP is typically used on unreliable channels, signaling messages
can be lost due to L2CAP Flush Timeouts. To react to inconsistencies
between the INT and ACP states, the Abort Command may be used."
It also says abort can be send regardless of the state even in case of
packet fragmantation:
"Note that it is permitted to breakdown a packet sequence (command or
response message) to send an Abort command message in the same direction.
The remaining packets consecutive to an aborted message shall be flushed by
the sender."
Make it consistent with the logic when abort timeout since the original
intent is to cancel a pending request there is no point in keeping the
connection if it is in an unrecoverable state.
The pending request might be freed twice when receiving an Abort
response, in handle_unanswered_req and session_cb. Avoid freeing
it in handle_unanswered_req.
If the connection is lost when there is an AVDTP request the remote has
not replied to and which has not timed out, then at least in some cases
the callback for the request is not called leading to no Error response
being sent on the Audio API.
This patch checks if there is an outstanding request when the stream
state goes to idle and in that case triggers the corresponding callback
with an error.
Since request_timeout() does callbacks into a2dp.c before sending the
ABORT command we need to make sure that none of the callbacks can
trigger sending any further AVDTP commands. This is easiest done by
setting the stream->abort_int flag early in the request_timeout function
and then checking for it in the send_request function.
The media stream could be gone by the time that the AVDTP command timeout
expires (e.g. if the media transport channel gets closed prematurely). In
such a case there's no need to send a separate ABORT command but we can
directly proceed with closing the signalling channel.
The transition to ABORTING state when acting as initiator should happen
when we receive the ABORT reply and not when we send the initial ABORT
command. The reply handling is already correct but since there's a state
change also in the sending part the later state change request would fail.
This patch fixes the issue by removing the state change when sending the
ABORT command.
We might not have a stream anymore when receiving the reply to a AVDTP
command that assumes that there is an existing stream. So ignore the
replies to these commands if we don't have a stream anymore.
A device may attempt to initiate a duplicate avdtp channel while
a host-initiated channel connection is still pending. This
situation is referred to as 'XCASE connect:connect' in sink.c and
source.c. This fix rejects the device-initiated connection in this
circumstance.
When manager.c (HFP/HSP), avdtp.c (A2DP) or control.c wants to cancel an
authorization request it shouldnd't affect the requests of the other
modules. So btd_cancel_authorization cannot be used. This patch adds a new
cancellation function to device.c which will remove the specific callback
from the list and only if the list is empty call btd_cancel_authorization.
ESR04 (Errata Service Release to the Bluetooth spec) clarifies the content
of the general reject AVDTP message to contain the original signal
identifier. It also specifies a new message type 0x01 for the general
reject. The change is also present in the latest AVDTP test specification.
In the case that the AVDTP session references weren't fully dropped when a
disconnection happens, in later reconnections the disconnect_timeout
function cound have a reference count higher than 1. These bugs naturally
need to fixed (and there's a proper error() call to log them) but we can
still handle the situation semi-cleanly instead of asserting and aborting
since the AVDTP session struct will just silently hang around and get
reused at the next connection attempt.
This makes sure that no other process (e.g. pulseaudio) reads or writes
the stream channel after it is logically closed through the AVDTP
signalling channel.
Some headsets (Nokia HS-12W) connects first on avrcp and only then on hfp
so in case Trusted property is not set this will cause agent_authorize to
return -EBUSY and drop hfp connection.
The proper solution would be to group all connections requests only
sending one authorization so the agent either accept them all or not, but
that would require API changes which we are avoiding right now, so the
current fix only send one connection request which the reponse is used for
the rest of the connections.
Situations where both sides end up sending commands are rare but they can
happen. They are also not fatal since one side will usually just end up
getting a "SEP in bad state" error and give up its setup procedure while
the other sides setup succeeds.
If we have a command that's pending a reply for don't set the disconnect
timer after processing a command from the other device (this is especially
important since the timeout for our pending requests is longer than the
disconnect timeout (4 seconds vs. 1 second).
Driver should be probed when adding a reference so that can be released
when the device is temporary using .remove callback. In case of AVDTP as
it is not possible to verify if it is a source or sink it uses the same
uuid used for authorization request which is advance audio uuid.
a2dp adapter driver was not calling avdtp_exit on adapter removal so the next
time it is probed it fail since the kernel reports that the address is already
in use.
In the case that someone calls Adapter.RemoveDevice while we're connected to an
audio profile some function calls could be triggered to manager_get_device.
This patch makes sure these calls don't recreate the device object that was
just removed.
avctp_get_internal will return NULL if we are waiting for authorizatoin to
succeed. This patch adds a check for it and rejects the connect attempt when
necessary.