diff options
author | Mat Martineau <mathewm@codeaurora.org> | 2012-05-18 05:53:33 +0200 |
---|---|---|
committer | Johan Hedberg <johan.hedberg@intel.com> | 2012-06-05 05:34:02 +0200 |
commit | 3733937d96f3fe4dfc3b8da43385d739e905ff41 (patch) | |
tree | bb53d50b07268c0977c1c93d8bad3cca36dc196e /net/bluetooth | |
parent | Bluetooth: Add a new L2CAP ERTM transmit state machine. (diff) | |
download | linux-3733937d96f3fe4dfc3b8da43385d739e905ff41.tar.xz linux-3733937d96f3fe4dfc3b8da43385d739e905ff41.zip |
Bluetooth: Refactor l2cap_streaming_send
This new implementation uses struct l2cap_ctrl to compose the
streaming mode headers.
Signed-off-by: Mat Martineau <mathewm@codeaurora.org>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/l2cap_core.c | 48 |
1 files changed, 31 insertions, 17 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index c5232d25da52..25edccff4c94 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1650,29 +1650,45 @@ static void l2cap_drop_acked_frames(struct l2cap_chan *chan) __clear_retrans_timer(chan); } -static void l2cap_streaming_send(struct l2cap_chan *chan) +static int l2cap_streaming_send(struct l2cap_chan *chan, + struct sk_buff_head *skbs) { struct sk_buff *skb; - u32 control; - u16 fcs; + struct l2cap_ctrl *control; - while ((skb = skb_dequeue(&chan->tx_q))) { - control = __get_control(chan, skb->data + L2CAP_HDR_SIZE); - control |= __set_txseq(chan, chan->next_tx_seq); - control |= __set_ctrl_sar(chan, bt_cb(skb)->control.sar); - __put_control(chan, control, skb->data + L2CAP_HDR_SIZE); + BT_DBG("chan %p, skbs %p", chan, skbs); + + if (chan->state != BT_CONNECTED) + return -ENOTCONN; + + skb_queue_splice_tail_init(skbs, &chan->tx_q); + + while (!skb_queue_empty(&chan->tx_q)) { + + skb = skb_dequeue(&chan->tx_q); + + bt_cb(skb)->control.retries = 1; + control = &bt_cb(skb)->control; + + control->reqseq = 0; + control->txseq = chan->next_tx_seq; + + __pack_control(chan, control, skb); if (chan->fcs == L2CAP_FCS_CRC16) { - fcs = crc16(0, (u8 *)skb->data, - skb->len - L2CAP_FCS_SIZE); - put_unaligned_le16(fcs, - skb->data + skb->len - L2CAP_FCS_SIZE); + u16 fcs = crc16(0, (u8 *) skb->data, skb->len); + put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); } l2cap_do_send(chan, skb); + BT_DBG("Sent txseq %d", (int)control->txseq); + chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); + chan->frames_sent++; } + + return 0; } static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq) @@ -2136,13 +2152,11 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, if (err) break; - if (chan->mode == L2CAP_MODE_ERTM) { + if (chan->mode == L2CAP_MODE_ERTM) err = l2cap_tx(chan, 0, &seg_queue, L2CAP_EV_DATA_REQUEST); - } else { - skb_queue_splice_tail_init(&seg_queue, &chan->tx_q); - l2cap_streaming_send(chan); - } + else + err = l2cap_streaming_send(chan, &seg_queue); if (!err) err = len; |