aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/l2cap_core.c
diff options
context:
space:
mode:
authorMat Martineau <mathewm@codeaurora.org>2012-05-17 23:53:33 -0400
committerJohan Hedberg <johan.hedberg@intel.com>2012-06-04 23:34:02 -0400
commit3733937d96f3fe4dfc3b8da43385d739e905ff41 (patch)
treebb53d50b07268c0977c1c93d8bad3cca36dc196e /net/bluetooth/l2cap_core.c
parent608bcc6d70850be9e3aa7c3831045304a2a65fbb (diff)
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/l2cap_core.c')
-rw-r--r--net/bluetooth/l2cap_core.c48
1 files changed, 31 insertions, 17 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index c5232d25da5..25edccff4c9 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)
1650 __clear_retrans_timer(chan); 1650 __clear_retrans_timer(chan);
1651} 1651}
1652 1652
1653static void l2cap_streaming_send(struct l2cap_chan *chan) 1653static int l2cap_streaming_send(struct l2cap_chan *chan,
1654 struct sk_buff_head *skbs)
1654{ 1655{
1655 struct sk_buff *skb; 1656 struct sk_buff *skb;
1656 u32 control; 1657 struct l2cap_ctrl *control;
1657 u16 fcs;
1658 1658
1659 while ((skb = skb_dequeue(&chan->tx_q))) { 1659 BT_DBG("chan %p, skbs %p", chan, skbs);
1660 control = __get_control(chan, skb->data + L2CAP_HDR_SIZE); 1660
1661 control |= __set_txseq(chan, chan->next_tx_seq); 1661 if (chan->state != BT_CONNECTED)
1662 control |= __set_ctrl_sar(chan, bt_cb(skb)->control.sar); 1662 return -ENOTCONN;
1663 __put_control(chan, control, skb->data + L2CAP_HDR_SIZE); 1663
1664 skb_queue_splice_tail_init(skbs, &chan->tx_q);
1665
1666 while (!skb_queue_empty(&chan->tx_q)) {
1667
1668 skb = skb_dequeue(&chan->tx_q);
1669
1670 bt_cb(skb)->control.retries = 1;
1671 control = &bt_cb(skb)->control;
1672
1673 control->reqseq = 0;
1674 control->txseq = chan->next_tx_seq;
1675
1676 __pack_control(chan, control, skb);
1664 1677
1665 if (chan->fcs == L2CAP_FCS_CRC16) { 1678 if (chan->fcs == L2CAP_FCS_CRC16) {
1666 fcs = crc16(0, (u8 *)skb->data, 1679 u16 fcs = crc16(0, (u8 *) skb->data, skb->len);
1667 skb->len - L2CAP_FCS_SIZE); 1680 put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE));
1668 put_unaligned_le16(fcs,
1669 skb->data + skb->len - L2CAP_FCS_SIZE);
1670 } 1681 }
1671 1682
1672 l2cap_do_send(chan, skb); 1683 l2cap_do_send(chan, skb);
1673 1684
1685 BT_DBG("Sent txseq %d", (int)control->txseq);
1686
1674 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq); 1687 chan->next_tx_seq = __next_seq(chan, chan->next_tx_seq);
1688 chan->frames_sent++;
1675 } 1689 }
1690
1691 return 0;
1676} 1692}
1677 1693
1678static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq) 1694static 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,
2136 if (err) 2152 if (err)
2137 break; 2153 break;
2138 2154
2139 if (chan->mode == L2CAP_MODE_ERTM) { 2155 if (chan->mode == L2CAP_MODE_ERTM)
2140 err = l2cap_tx(chan, 0, &seg_queue, 2156 err = l2cap_tx(chan, 0, &seg_queue,
2141 L2CAP_EV_DATA_REQUEST); 2157 L2CAP_EV_DATA_REQUEST);
2142 } else { 2158 else
2143 skb_queue_splice_tail_init(&seg_queue, &chan->tx_q); 2159 err = l2cap_streaming_send(chan, &seg_queue);
2144 l2cap_streaming_send(chan);
2145 }
2146 2160
2147 if (!err) 2161 if (!err)
2148 err = len; 2162 err = len;