int bt_l2cap_chan_disconnect(struct bt_l2cap_chan *chan) { struct bt_conn *conn = chan->conn; struct net_buf *buf; struct bt_l2cap_disconn_req *req; struct bt_l2cap_le_chan *ch; if (!conn) { return -ENOTCONN; } if (IS_ENABLED(CONFIG_BLUETOOTH_BREDR) && conn->type == BT_CONN_TYPE_BR) { return bt_l2cap_br_chan_disconnect(chan); } ch = BT_L2CAP_LE_CHAN(chan); BT_DBG("chan %p scid 0x%04x dcid 0x%04x", chan, ch->rx.cid, ch->tx.cid); ch->chan.ident = get_ident(); buf = l2cap_create_le_sig_pdu(BT_L2CAP_DISCONN_REQ, ch->chan.ident, sizeof(*req)); req = net_buf_add(buf, sizeof(*req)); req->dcid = sys_cpu_to_le16(ch->tx.cid); req->scid = sys_cpu_to_le16(ch->rx.cid); l2cap_chan_send_req(ch, buf, L2CAP_DISC_TIMEOUT); bt_l2cap_chan_set_state(chan, BT_L2CAP_DISCONNECT); return 0; }
int bt_l2cap_chan_disconnect(struct bt_l2cap_chan *chan) { struct bt_conn *conn = chan->conn; struct net_buf *buf; struct bt_l2cap_disconn_req *req; struct bt_l2cap_sig_hdr *hdr; struct bt_l2cap_le_chan *ch; if (!conn) { return -ENOTCONN; } #if defined(CONFIG_BLUETOOTH_BREDR) if (conn->type == BT_CONN_TYPE_BR) { return bt_l2cap_br_chan_disconnect(chan); } #endif /* CONFIG_BLUETOOTH_BREDR */ ch = LE_CHAN(chan); BT_DBG("chan %p scid 0x%04x dcid 0x%04x", chan, ch->rx.cid, ch->tx.cid); buf = bt_l2cap_create_pdu(&le_sig); if (!buf) { BT_ERR("Unable to send L2CP disconnect request"); return -ENOMEM; } hdr = net_buf_add(buf, sizeof(*hdr)); hdr->code = BT_L2CAP_DISCONN_REQ; hdr->ident = get_ident(); hdr->len = sys_cpu_to_le16(sizeof(*req)); req = net_buf_add(buf, sizeof(*req)); req->dcid = sys_cpu_to_le16(ch->tx.cid); req->scid = sys_cpu_to_le16(ch->rx.cid); bt_l2cap_send(conn, BT_L2CAP_CID_LE_SIG, buf); return 0; }