diff options
author | Gustavo F. Padovan <gustavo@las.ic.unicamp.br> | 2009-08-20 21:26:01 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2009-08-22 17:57:58 -0400 |
commit | 6840ed0770d79b9bb0800e5e026a067040ef18f5 (patch) | |
tree | 7904a7bfc6bb1e57f30139cac47676bf589db7b7 /net/bluetooth | |
parent | e90bac061b17cd81bd0df30606c64f4543bf5ca0 (diff) |
Bluetooth: Enable Streaming Mode for L2CAP
Streaming Mode is helpful for the Bluetooth streaming based profiles, such
as A2DP. It doesn't have any error control or flow control.
Signed-off-by: Gustavo F. Padovan <gustavo@las.ic.unicamp.br>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/l2cap.c | 82 |
1 files changed, 73 insertions, 9 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 97172f7c0a6a..7f835e761822 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c | |||
@@ -1245,6 +1245,39 @@ static inline int l2cap_do_send(struct sock *sk, struct sk_buff *skb) | |||
1245 | return err; | 1245 | return err; |
1246 | } | 1246 | } |
1247 | 1247 | ||
1248 | static int l2cap_streaming_send(struct sock *sk) | ||
1249 | { | ||
1250 | struct sk_buff *skb, *tx_skb; | ||
1251 | struct l2cap_pinfo *pi = l2cap_pi(sk); | ||
1252 | u16 control; | ||
1253 | int err; | ||
1254 | |||
1255 | while ((skb = sk->sk_send_head)) { | ||
1256 | tx_skb = skb_clone(skb, GFP_ATOMIC); | ||
1257 | |||
1258 | control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); | ||
1259 | control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT; | ||
1260 | put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE); | ||
1261 | |||
1262 | err = l2cap_do_send(sk, tx_skb); | ||
1263 | if (err < 0) { | ||
1264 | l2cap_send_disconn_req(pi->conn, sk); | ||
1265 | return err; | ||
1266 | } | ||
1267 | |||
1268 | pi->next_tx_seq = (pi->next_tx_seq + 1) % 64; | ||
1269 | |||
1270 | if (skb_queue_is_last(TX_QUEUE(sk), skb)) | ||
1271 | sk->sk_send_head = NULL; | ||
1272 | else | ||
1273 | sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb); | ||
1274 | |||
1275 | skb = skb_dequeue(TX_QUEUE(sk)); | ||
1276 | kfree_skb(skb); | ||
1277 | } | ||
1278 | return 0; | ||
1279 | } | ||
1280 | |||
1248 | static int l2cap_ertm_send(struct sock *sk) | 1281 | static int l2cap_ertm_send(struct sock *sk) |
1249 | { | 1282 | { |
1250 | struct sk_buff *skb, *tx_skb; | 1283 | struct sk_buff *skb, *tx_skb; |
@@ -1383,7 +1416,7 @@ static struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *ms | |||
1383 | return skb; | 1416 | return skb; |
1384 | } | 1417 | } |
1385 | 1418 | ||
1386 | static struct sk_buff *l2cap_create_ertm_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen) | 1419 | static struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen) |
1387 | { | 1420 | { |
1388 | struct l2cap_conn *conn = l2cap_pi(sk)->conn; | 1421 | struct l2cap_conn *conn = l2cap_pi(sk)->conn; |
1389 | struct sk_buff *skb; | 1422 | struct sk_buff *skb; |
@@ -1429,7 +1462,7 @@ static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, siz | |||
1429 | 1462 | ||
1430 | __skb_queue_head_init(&sar_queue); | 1463 | __skb_queue_head_init(&sar_queue); |
1431 | control = L2CAP_SDU_START; | 1464 | control = L2CAP_SDU_START; |
1432 | skb = l2cap_create_ertm_pdu(sk, msg, pi->max_pdu_size, control, len); | 1465 | skb = l2cap_create_iframe_pdu(sk, msg, pi->max_pdu_size, control, len); |
1433 | if (IS_ERR(skb)) | 1466 | if (IS_ERR(skb)) |
1434 | return PTR_ERR(skb); | 1467 | return PTR_ERR(skb); |
1435 | 1468 | ||
@@ -1449,7 +1482,7 @@ static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, siz | |||
1449 | buflen = len; | 1482 | buflen = len; |
1450 | } | 1483 | } |
1451 | 1484 | ||
1452 | skb = l2cap_create_ertm_pdu(sk, msg, buflen, control, 0); | 1485 | skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0); |
1453 | if (IS_ERR(skb)) { | 1486 | if (IS_ERR(skb)) { |
1454 | skb_queue_purge(&sar_queue); | 1487 | skb_queue_purge(&sar_queue); |
1455 | return PTR_ERR(skb); | 1488 | return PTR_ERR(skb); |
@@ -1518,10 +1551,11 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms | |||
1518 | break; | 1551 | break; |
1519 | 1552 | ||
1520 | case L2CAP_MODE_ERTM: | 1553 | case L2CAP_MODE_ERTM: |
1554 | case L2CAP_MODE_STREAMING: | ||
1521 | /* Entire SDU fits into one PDU */ | 1555 | /* Entire SDU fits into one PDU */ |
1522 | if (len <= pi->max_pdu_size) { | 1556 | if (len <= pi->max_pdu_size) { |
1523 | control = L2CAP_SDU_UNSEGMENTED; | 1557 | control = L2CAP_SDU_UNSEGMENTED; |
1524 | skb = l2cap_create_ertm_pdu(sk, msg, len, control, 0); | 1558 | skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0); |
1525 | if (IS_ERR(skb)) { | 1559 | if (IS_ERR(skb)) { |
1526 | err = PTR_ERR(skb); | 1560 | err = PTR_ERR(skb); |
1527 | goto done; | 1561 | goto done; |
@@ -1536,7 +1570,11 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms | |||
1536 | goto done; | 1570 | goto done; |
1537 | } | 1571 | } |
1538 | 1572 | ||
1539 | err = l2cap_ertm_send(sk); | 1573 | if (pi->mode == L2CAP_MODE_STREAMING) |
1574 | err = l2cap_streaming_send(sk); | ||
1575 | else | ||
1576 | err = l2cap_ertm_send(sk); | ||
1577 | |||
1540 | if (!err) | 1578 | if (!err) |
1541 | err = len; | 1579 | err = len; |
1542 | break; | 1580 | break; |
@@ -2050,7 +2088,7 @@ static int l2cap_mode_supported(__u8 mode, __u32 feat_mask) | |||
2050 | { | 2088 | { |
2051 | u32 local_feat_mask = l2cap_feat_mask; | 2089 | u32 local_feat_mask = l2cap_feat_mask; |
2052 | if (enable_ertm) | 2090 | if (enable_ertm) |
2053 | local_feat_mask |= L2CAP_FEAT_ERTM; | 2091 | local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING; |
2054 | 2092 | ||
2055 | switch (mode) { | 2093 | switch (mode) { |
2056 | case L2CAP_MODE_ERTM: | 2094 | case L2CAP_MODE_ERTM: |
@@ -2771,7 +2809,7 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cm | |||
2771 | rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK); | 2809 | rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK); |
2772 | rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); | 2810 | rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); |
2773 | if (enable_ertm) | 2811 | if (enable_ertm) |
2774 | feat_mask |= L2CAP_FEAT_ERTM; | 2812 | feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING; |
2775 | put_unaligned(cpu_to_le32(feat_mask), (__le32 *) rsp->data); | 2813 | put_unaligned(cpu_to_le32(feat_mask), (__le32 *) rsp->data); |
2776 | l2cap_send_cmd(conn, cmd->ident, | 2814 | l2cap_send_cmd(conn, cmd->ident, |
2777 | L2CAP_INFO_RSP, sizeof(buf), buf); | 2815 | L2CAP_INFO_RSP, sizeof(buf), buf); |
@@ -3096,7 +3134,9 @@ static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, str | |||
3096 | static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb) | 3134 | static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb) |
3097 | { | 3135 | { |
3098 | struct sock *sk; | 3136 | struct sock *sk; |
3137 | struct l2cap_pinfo *pi; | ||
3099 | u16 control, len; | 3138 | u16 control, len; |
3139 | u8 tx_seq; | ||
3100 | int err; | 3140 | int err; |
3101 | 3141 | ||
3102 | sk = l2cap_get_chan_by_scid(&conn->chan_list, cid); | 3142 | sk = l2cap_get_chan_by_scid(&conn->chan_list, cid); |
@@ -3105,19 +3145,21 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk | |||
3105 | goto drop; | 3145 | goto drop; |
3106 | } | 3146 | } |
3107 | 3147 | ||
3148 | pi = l2cap_pi(sk); | ||
3149 | |||
3108 | BT_DBG("sk %p, len %d", sk, skb->len); | 3150 | BT_DBG("sk %p, len %d", sk, skb->len); |
3109 | 3151 | ||
3110 | if (sk->sk_state != BT_CONNECTED) | 3152 | if (sk->sk_state != BT_CONNECTED) |
3111 | goto drop; | 3153 | goto drop; |
3112 | 3154 | ||
3113 | switch (l2cap_pi(sk)->mode) { | 3155 | switch (pi->mode) { |
3114 | case L2CAP_MODE_BASIC: | 3156 | case L2CAP_MODE_BASIC: |
3115 | /* If socket recv buffers overflows we drop data here | 3157 | /* If socket recv buffers overflows we drop data here |
3116 | * which is *bad* because L2CAP has to be reliable. | 3158 | * which is *bad* because L2CAP has to be reliable. |
3117 | * But we don't have any other choice. L2CAP doesn't | 3159 | * But we don't have any other choice. L2CAP doesn't |
3118 | * provide flow control mechanism. */ | 3160 | * provide flow control mechanism. */ |
3119 | 3161 | ||
3120 | if (l2cap_pi(sk)->imtu < skb->len) | 3162 | if (pi->imtu < skb->len) |
3121 | goto drop; | 3163 | goto drop; |
3122 | 3164 | ||
3123 | if (!sock_queue_rcv_skb(sk, skb)) | 3165 | if (!sock_queue_rcv_skb(sk, skb)) |
@@ -3149,6 +3191,28 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk | |||
3149 | goto done; | 3191 | goto done; |
3150 | break; | 3192 | break; |
3151 | 3193 | ||
3194 | case L2CAP_MODE_STREAMING: | ||
3195 | control = get_unaligned_le16(skb->data); | ||
3196 | skb_pull(skb, 2); | ||
3197 | len = skb->len; | ||
3198 | |||
3199 | if (__is_sar_start(control)) | ||
3200 | len -= 2; | ||
3201 | |||
3202 | if (len > L2CAP_DEFAULT_MAX_PDU_SIZE || __is_sframe(control)) | ||
3203 | goto drop; | ||
3204 | |||
3205 | tx_seq = __get_txseq(control); | ||
3206 | |||
3207 | if (pi->expected_tx_seq == tx_seq) | ||
3208 | pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64; | ||
3209 | else | ||
3210 | pi->expected_tx_seq = tx_seq + 1; | ||
3211 | |||
3212 | err = l2cap_sar_reassembly_sdu(sk, skb, control); | ||
3213 | |||
3214 | goto done; | ||
3215 | |||
3152 | default: | 3216 | default: |
3153 | BT_DBG("sk %p: bad mode 0x%2.2x", sk, l2cap_pi(sk)->mode); | 3217 | BT_DBG("sk %p: bad mode 0x%2.2x", sk, l2cap_pi(sk)->mode); |
3154 | break; | 3218 | break; |