Skip to content

Commit fd0b3ff

Browse files
committed
Bluetooth: Add proper shutdown support to SCO sockets
The SCO sockets for Bluetooth audio setup and streaming are missing the shutdown implementation. This hasn't been a problem so far, but with a more deeper integration with PulseAudio it is important to shutdown SCO sockets properly. Also the Headset profile 1.2 has more detailed qualification tests that require that SCO and RFCOMM channels are terminated in the right order. A proper shutdown function is necessary for this. Based on a report by Johan Hedberg <johan.hedberg@nokia.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Tested-by: Johan Hedberg <johan.hedberg@nokia.com>
1 parent f8f2109 commit fd0b3ff

File tree

1 file changed

+34
-15
lines changed

1 file changed

+34
-15
lines changed

net/bluetooth/sco.c

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -359,20 +359,9 @@ static void sco_sock_kill(struct sock *sk)
359359
sock_put(sk);
360360
}
361361

362-
/* Close socket.
363-
* Must be called on unlocked socket.
364-
*/
365-
static void sco_sock_close(struct sock *sk)
362+
static void __sco_sock_close(struct sock *sk)
366363
{
367-
struct sco_conn *conn;
368-
369-
sco_sock_clear_timer(sk);
370-
371-
lock_sock(sk);
372-
373-
conn = sco_pi(sk)->conn;
374-
375-
BT_DBG("sk %p state %d conn %p socket %p", sk, sk->sk_state, conn, sk->sk_socket);
364+
BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
376365

377366
switch (sk->sk_state) {
378367
case BT_LISTEN:
@@ -390,9 +379,15 @@ static void sco_sock_close(struct sock *sk)
390379
sock_set_flag(sk, SOCK_ZAPPED);
391380
break;
392381
}
382+
}
393383

384+
/* Must be called on unlocked socket. */
385+
static void sco_sock_close(struct sock *sk)
386+
{
387+
sco_sock_clear_timer(sk);
388+
lock_sock(sk);
389+
__sco_sock_close(sk);
394390
release_sock(sk);
395-
396391
sco_sock_kill(sk);
397392
}
398393

@@ -748,6 +743,30 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char
748743
return err;
749744
}
750745

746+
static int sco_sock_shutdown(struct socket *sock, int how)
747+
{
748+
struct sock *sk = sock->sk;
749+
int err = 0;
750+
751+
BT_DBG("sock %p, sk %p", sock, sk);
752+
753+
if (!sk)
754+
return 0;
755+
756+
lock_sock(sk);
757+
if (!sk->sk_shutdown) {
758+
sk->sk_shutdown = SHUTDOWN_MASK;
759+
sco_sock_clear_timer(sk);
760+
__sco_sock_close(sk);
761+
762+
if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
763+
err = bt_sock_wait_state(sk, BT_CLOSED,
764+
sk->sk_lingertime);
765+
}
766+
release_sock(sk);
767+
return err;
768+
}
769+
751770
static int sco_sock_release(struct socket *sock)
752771
{
753772
struct sock *sk = sock->sk;
@@ -969,7 +988,7 @@ static const struct proto_ops sco_sock_ops = {
969988
.ioctl = bt_sock_ioctl,
970989
.mmap = sock_no_mmap,
971990
.socketpair = sock_no_socketpair,
972-
.shutdown = sock_no_shutdown,
991+
.shutdown = sco_sock_shutdown,
973992
.setsockopt = sco_sock_setsockopt,
974993
.getsockopt = sco_sock_getsockopt
975994
};

0 commit comments

Comments
 (0)