Bluetooth: RFCOMM: Handle data and credit from peer
Data is transferred in UIH frame to a valid dlci. In this case the meaning of PF bit is different, if PF bit is 1 then credit is there in the frame otherwise no credit (only user data). So basically UIH frame to a valid dlci can be "Only data, Only credit, both credit and data" Only credit > ACL Data RX: Handle 256 flags 0x02 dlen 9 Channel: 64 len 5 [PSM 3 mode 0] {chan 0} RFCOMM: Unnumbered Info with Header Check (UIH) (0xef) Address: 0x0b cr 1 dlci 0x02 Control: 0xff poll/final 1 Length: 0 FCS: 0x86 Credits: 33 86 Only data > ACL Data RX: Handle 256 flags 0x02 dlen 9 Channel: 64 len 5 [PSM 3 mode 0] {chan 0} RFCOMM: Unnumbered Info with Header Check (UIH) (0xef) Address: 0x0b cr 1 dlci 0x02 Control: 0xef poll/final 0 Length: 1 FCS: 0x9a ff 9a Change-Id: Iaa48f9aa022f33e1a1217f19dc59ce761cfeac74 Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
This commit is contained in:
parent
d6af0ef091
commit
407013f3c7
2 changed files with 49 additions and 0 deletions
|
@ -460,6 +460,48 @@ static void rfcomm_handle_msg(struct bt_rfcomm_session *session,
|
|||
}
|
||||
}
|
||||
|
||||
static void rfcomm_handle_data(struct bt_rfcomm_session *session,
|
||||
struct net_buf *buf, uint8_t dlci, uint8_t pf)
|
||||
|
||||
{
|
||||
struct bt_rfcomm_dlc *dlc;
|
||||
|
||||
BT_DBG("dlci %d, pf %d", dlci, pf);
|
||||
|
||||
dlc = rfcomm_dlcs_lookup_dlci(session->dlcs, dlci);
|
||||
if (!dlc) {
|
||||
BT_ERR("Data recvd in non existing DLC");
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("dlc %p rx credit %d", dlc, dlc->rx_credit);
|
||||
|
||||
if (dlc->state != BT_RFCOMM_STATE_CONNECTED) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dlc->rx_credit) {
|
||||
BT_ERR("Data recvd when rx credit is 0");
|
||||
/* Disconnect */
|
||||
return;
|
||||
}
|
||||
|
||||
if (pf == BT_RFCOMM_PF_CREDIT) {
|
||||
/* TODO: Modify it to semaphore */
|
||||
dlc->tx_credit += net_buf_pull_u8(buf);
|
||||
BT_DBG("updated tx credit %d", dlc->tx_credit);
|
||||
}
|
||||
|
||||
if (buf->len > BT_RFCOMM_FCS_SIZE) {
|
||||
/* Remove FCS */
|
||||
buf->len -= BT_RFCOMM_FCS_SIZE;
|
||||
if (dlc->ops && dlc->ops->recv) {
|
||||
dlc->ops->recv(dlc, buf);
|
||||
}
|
||||
dlc->rx_credit--;
|
||||
}
|
||||
}
|
||||
|
||||
static void rfcomm_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
|
||||
{
|
||||
struct bt_rfcomm_session *session = RFCOMM_SESSION(chan);
|
||||
|
@ -498,6 +540,9 @@ static void rfcomm_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
|
|||
case BT_RFCOMM_UIH:
|
||||
if (!dlci) {
|
||||
rfcomm_handle_msg(session, buf);
|
||||
} else {
|
||||
rfcomm_handle_data(session, buf, dlci,
|
||||
BT_RFCOMM_GET_PF(hdr->control));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -90,6 +90,7 @@ struct bt_rfcomm_msc {
|
|||
#define BT_RFCOMM_GET_MSG_CR(type) (((type) & 0x02) >> 1)
|
||||
#define BT_RFCOMM_GET_LEN(len) (((len) & 0xfe) >> 1)
|
||||
#define BT_RFCOMM_GET_CHANNEL(dlci) ((dlci) >> 1)
|
||||
#define BT_RFCOMM_GET_PF(ctrl) (((ctrl) & 0x10) >> 4)
|
||||
|
||||
#define BT_RFCOMM_SET_ADDR(dlci, cr) ((((dlci) & 0x3f) << 2) | \
|
||||
((cr) << 1) | 0x01)
|
||||
|
@ -109,5 +110,8 @@ struct bt_rfcomm_msc {
|
|||
#define BT_RFCOMM_FCS_LEN_UIH 2
|
||||
#define BT_RFCOMM_FCS_LEN_NON_UIH 3
|
||||
|
||||
#define BT_RFCOMM_PF_CREDIT 1
|
||||
#define BT_RFCOMM_PF_NO_CREDIT 0
|
||||
|
||||
/* Initialize RFCOMM signal layer */
|
||||
void bt_rfcomm_init(void);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue