Bluetooth: RFCOMM: Initiate DLC
This patch initiate a DLC when user calls connect. It first does Parameter negotiation and then establish connection to the dlci derived from channel given by user. < ACL Data TX: Handle 256 flags 0x00 dlen 18 Channel: 64 len 14 [PSM 3 mode 0] {chan 0} RFCOMM: Unnumbered Info with Header Check (UIH) (0xef) Address: 0x03 cr 1 dlci 0x00 Control: 0xef poll/final 0 Length: 10 FCS: 0x70 MCC Message type: DLC Parameter Negotiation CMD (0x20) Length: 8 dlci 3 frame_type 0 credit_flow 15 pri 0 ack_timer 0 frame_size 30 max_retrans 0 credits 4 > ACL Data RX: Handle 256 flags 0x02 dlen 18 Channel: 64 len 14 [PSM 3 mode 0] {chan 0} RFCOMM: Unnumbered Info with Header Check (UIH) (0xef) Address: 0x01 cr 0 dlci 0x00 Control: 0xef poll/final 0 Length: 10 FCS: 0xaa MCC Message type: DLC Parameter Negotiation RSP (0x20) Length: 8 dlci 3 frame_type 0 credit_flow 14 pri 0 ack_timer 0 frame_size 30 max_retrans 0 credits 7 < ACL Data TX: Handle 256 flags 0x00 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Set Async Balance Mode (SABM) (0x2f) Address: 0x0b cr 1 dlci 0x02 Control: 0x3f poll/final 1 Length: 0 FCS: 0x59 > ACL Data RX: Handle 256 flags 0x02 dlen 8 Channel: 64 len 4 [PSM 3 mode 0] {chan 0} RFCOMM: Unnumbered Ack (UA) (0x63) Address: 0x0b cr 1 dlci 0x02 Control: 0x73 poll/final 1 Length: 0 FCS: 0x92 Change-Id: I62a19f624fc4bb89eb9a109a5352fa763c1241d2 Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
This commit is contained in:
parent
d9eb0fb2a0
commit
8166de77db
2 changed files with 58 additions and 4 deletions
|
@ -718,14 +718,36 @@ static int rfcomm_send_credit(struct bt_rfcomm_dlc *dlc, uint8_t credits)
|
|||
return bt_l2cap_chan_send(&dlc->session->br_chan.chan, buf);
|
||||
}
|
||||
|
||||
static void rfcomm_dlc_start(struct bt_rfcomm_dlc *dlc)
|
||||
{
|
||||
BT_DBG("dlc %p", dlc);
|
||||
|
||||
/* TODO: Need to check Security */
|
||||
dlc->mtu = min(dlc->mtu, dlc->session->mtu);
|
||||
dlc->state = BT_RFCOMM_STATE_CONFIG;
|
||||
rfcomm_send_pn(dlc, BT_RFCOMM_MSG_CMD_CR);
|
||||
}
|
||||
|
||||
static void rfcomm_handle_ua(struct bt_rfcomm_session *session, uint8_t dlci)
|
||||
{
|
||||
struct bt_rfcomm_dlc *dlc;
|
||||
|
||||
if (!dlci) {
|
||||
if (session->state != BT_RFCOMM_STATE_CONNECTING) {
|
||||
return;
|
||||
}
|
||||
session->state = BT_RFCOMM_STATE_CONNECTED;
|
||||
/* TODO: STart dlc */
|
||||
for (dlc = session->dlcs; dlc; dlc = dlc->_next) {
|
||||
if (dlc->role == BT_RFCOMM_ROLE_INITIATOR &&
|
||||
dlc->state == BT_RFCOMM_STATE_INIT) {
|
||||
rfcomm_dlc_start(dlc);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dlc = rfcomm_dlcs_lookup_dlci(session->dlcs, dlci);
|
||||
if (dlc && dlc->state == BT_RFCOMM_STATE_CONNECTING) {
|
||||
rfcomm_dlc_connected(dlc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -789,6 +811,15 @@ static void rfcomm_handle_pn(struct bt_rfcomm_session *session,
|
|||
}
|
||||
dlc->mtu = min(dlc->mtu, sys_le16_to_cpu(pn->mtu));
|
||||
rfcomm_send_pn(dlc, BT_RFCOMM_MSG_RESP_CR);
|
||||
} else {
|
||||
if (dlc->state != BT_RFCOMM_STATE_CONFIG) {
|
||||
return;
|
||||
}
|
||||
|
||||
dlc->mtu = min(dlc->mtu, sys_le16_to_cpu(pn->mtu));
|
||||
rfcomm_dlc_tx_give_credits(dlc, pn->credits);
|
||||
dlc->state = BT_RFCOMM_STATE_CONNECTING;
|
||||
rfcomm_send_sabm(session, dlc->dlci);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1066,6 +1097,7 @@ int bt_rfcomm_dlc_connect(struct bt_conn *conn, struct bt_rfcomm_dlc *dlc,
|
|||
{
|
||||
struct bt_rfcomm_session *session;
|
||||
struct bt_l2cap_chan *chan;
|
||||
uint8_t dlci;
|
||||
int ret;
|
||||
|
||||
BT_DBG("conn %p dlc %p channel %d", conn, dlc, channel);
|
||||
|
@ -1082,6 +1114,10 @@ int bt_rfcomm_dlc_connect(struct bt_conn *conn, struct bt_rfcomm_dlc *dlc,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!BT_RFCOMM_CHECK_MTU(dlc->mtu)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
session = rfcomm_sessions_lookup_bt_conn(conn);
|
||||
if (!session) {
|
||||
session = rfcomm_session_new(BT_RFCOMM_ROLE_INITIATOR);
|
||||
|
@ -1090,6 +1126,14 @@ int bt_rfcomm_dlc_connect(struct bt_conn *conn, struct bt_rfcomm_dlc *dlc,
|
|||
}
|
||||
}
|
||||
|
||||
dlci = BT_RFCOMM_DLCI(session->role, channel);
|
||||
|
||||
if (rfcomm_dlcs_lookup_dlci(session->dlcs, dlci)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
rfcomm_dlc_init(dlc, session, dlci, BT_RFCOMM_ROLE_INITIATOR);
|
||||
|
||||
switch (session->state) {
|
||||
case BT_RFCOMM_STATE_INIT:
|
||||
if (session->role == BT_RFCOMM_ROLE_ACCEPTOR) {
|
||||
|
@ -1100,21 +1144,28 @@ int bt_rfcomm_dlc_connect(struct bt_conn *conn, struct bt_rfcomm_dlc *dlc,
|
|||
ret = bt_l2cap_chan_connect(conn, chan, BT_L2CAP_PSM_RFCOMM);
|
||||
if (ret < 0) {
|
||||
session->state = BT_RFCOMM_STATE_IDLE;
|
||||
return ret;
|
||||
goto fail;
|
||||
}
|
||||
session->state = BT_RFCOMM_STATE_CONNECTING;
|
||||
break;
|
||||
case BT_RFCOMM_STATE_CONNECTING:
|
||||
break;
|
||||
case BT_RFCOMM_STATE_CONNECTED:
|
||||
/* TODO: Start dlc */
|
||||
rfcomm_dlc_start(dlc);
|
||||
break;
|
||||
default:
|
||||
BT_ERR("Invalid session state %d", session->state);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
rfcomm_dlcs_remove_dlci(session->dlcs, dlc->dlci);
|
||||
dlc->state = BT_RFCOMM_STATE_IDLE;
|
||||
dlc->session = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rfcomm_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
|
||||
|
|
|
@ -135,6 +135,9 @@ struct bt_rfcomm_msc {
|
|||
#define BT_RFCOMM_MSG_CMD_CR 1
|
||||
#define BT_RFCOMM_MSG_RESP_CR 0
|
||||
|
||||
#define BT_RFCOMM_DLCI(role, channel) ((((channel) & 0x1f) << 1) | \
|
||||
((role) == BT_RFCOMM_ROLE_ACCEPTOR))
|
||||
|
||||
/* Excluding ext bit */
|
||||
#define BT_RFCOMM_MAX_LEN_8 127
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue