static void l2cap_conn_ready(struct l2cap_conn *conn) { struct l2cap_chan_list *l = &conn->chan_list; struct sock *sk; BT_DBG("conn %p", conn); read_lock(&l->lock); for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) { bh_lock_sock(sk); if (sk->type != SOCK_SEQPACKET) { l2cap_sock_clear_timer(sk); sk->state = BT_CONNECTED; sk->state_change(sk); } else if (sk->state == BT_CONNECT) { l2cap_conn_req req; req.scid = __cpu_to_le16(l2cap_pi(sk)->scid); req.psm = l2cap_pi(sk)->psm; l2cap_send_req(conn, L2CAP_CONN_REQ, L2CAP_CONN_REQ_SIZE, &req); } bh_unlock_sock(sk); } read_unlock(&l->lock); }
static int l2cap_sock_shutdown(struct socket *sock, int how) { struct sock *sk = sock->sk; int err = 0; BT_DBG("sock %p, sk %p", sock, sk); if (!sk) return 0; lock_sock(sk); if (!sk->sk_shutdown) { if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) { err = __l2cap_wait_ack(sk); l2cap_ertm_shutdown(sk); } sk->sk_shutdown = SHUTDOWN_MASK; l2cap_sock_clear_timer(sk); __l2cap_sock_close(sk, 0); if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime); } if (!err && sk->sk_err) err = -sk->sk_err; release_sock(sk); return err; }
/* Delete channel. * Must be called on the locked socket. */ static void l2cap_chan_del(struct sock *sk, int err) { struct l2cap_conn *conn = l2cap_pi(sk)->conn; struct sock *parent = bluez_pi(sk)->parent; l2cap_sock_clear_timer(sk); BT_DBG("sk %p, conn %p, err %d", sk, conn, err); if (conn) { /* Unlink from channel list */ l2cap_chan_unlink(&conn->chan_list, sk); l2cap_pi(sk)->conn = NULL; hci_conn_put(conn->hcon); } sk->state = BT_CLOSED; sk->zapped = 1; if (err) sk->err = err; if (parent) parent->data_ready(parent, 0); else sk->state_change(sk); }
/* Must be called on unlocked socket. */ static void l2cap_sock_close(struct sock *sk) { l2cap_sock_clear_timer(sk); lock_sock(sk); __l2cap_sock_close(sk, ECONNRESET); release_sock(sk); l2cap_sock_kill(sk); }
static int l2cap_do_connect(struct sock *sk) { bdaddr_t *src = &bluez_pi(sk)->src; bdaddr_t *dst = &bluez_pi(sk)->dst; struct l2cap_conn *conn; struct hci_conn *hcon; struct hci_dev *hdev; int err = 0; BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst), l2cap_pi(sk)->psm); if (!(hdev = hci_get_route(dst, src))) return -EHOSTUNREACH; hci_dev_lock_bh(hdev); err = -ENOMEM; hcon = hci_connect(hdev, ACL_LINK, dst); if (!hcon) goto done; conn = l2cap_conn_add(hcon, 0); if (!conn) { hci_conn_put(hcon); goto done; } err = 0; /* Update source addr of the socket */ bacpy(src, conn->src); l2cap_chan_add(conn, sk, NULL); sk->state = BT_CONNECT; l2cap_sock_set_timer(sk, sk->sndtimeo); if (hcon->state == BT_CONNECTED) { if (sk->type == SOCK_SEQPACKET) { l2cap_conn_req req; req.scid = __cpu_to_le16(l2cap_pi(sk)->scid); req.psm = l2cap_pi(sk)->psm; l2cap_send_req(conn, L2CAP_CONN_REQ, L2CAP_CONN_REQ_SIZE, &req); } else { l2cap_sock_clear_timer(sk); sk->state = BT_CONNECTED; } } done: hci_dev_unlock_bh(hdev); hci_dev_put(hdev); return err; }
static int l2cap_sock_shutdown(struct socket *sock, int how) { struct sock *sk = sock->sk; int err = 0; BT_DBG("sock %p, sk %p", sock, sk); if (!sk) return 0; lock_sock(sk); if (!sk->shutdown) { sk->shutdown = SHUTDOWN_MASK; l2cap_sock_clear_timer(sk); __l2cap_sock_close(sk, 0); if (sk->linger) err = bluez_sock_wait_state(sk, BT_CLOSED, sk->lingertime); } release_sock(sk); return err; }
static void l2cap_chan_ready(struct sock *sk) { struct sock *parent = bluez_pi(sk)->parent; BT_DBG("sk %p, parent %p", sk, parent); l2cap_pi(sk)->conf_state = 0; l2cap_sock_clear_timer(sk); if (!parent) { /* Outgoing channel. * Wake up socket sleeping on connect. */ sk->state = BT_CONNECTED; sk->state_change(sk); } else { /* Incomming channel. * Wake up socket sleeping on accept. */ parent->data_ready(parent, 0); } }