diff options
author | Gustavo F. Padovan <padovan@profusion.mobi> | 2010-05-01 15:15:39 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2010-05-10 03:28:48 -0400 |
commit | 7b1c0049be3aabc18831ada339dbcf41ba8c81fd (patch) | |
tree | 61d3e22c735d3e6e4ae3ad5d702ca6bfff846db0 /net/bluetooth | |
parent | 2fb862e215e53630066c677e06d7551fa38bf235 (diff) |
Bluetooth: Read RFC conf option on a successful Conf RSP
On Enhanced Retransmission Mode and Streaming Mode a entity can send, on
a successful Conf RSP, new values for the RFC fields. For example, the
entity can send txWindow and MPS values less than the value received on
a Conf REQ.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/l2cap.c | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index f604405fe667..c50c05738fb6 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c | |||
@@ -2602,6 +2602,42 @@ static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 fla | |||
2602 | return ptr - data; | 2602 | return ptr - data; |
2603 | } | 2603 | } |
2604 | 2604 | ||
2605 | static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len) | ||
2606 | { | ||
2607 | struct l2cap_pinfo *pi = l2cap_pi(sk); | ||
2608 | int type, olen; | ||
2609 | unsigned long val; | ||
2610 | struct l2cap_conf_rfc rfc; | ||
2611 | |||
2612 | BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len); | ||
2613 | |||
2614 | if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING)) | ||
2615 | return; | ||
2616 | |||
2617 | while (len >= L2CAP_CONF_OPT_SIZE) { | ||
2618 | len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); | ||
2619 | |||
2620 | switch (type) { | ||
2621 | case L2CAP_CONF_RFC: | ||
2622 | if (olen == sizeof(rfc)) | ||
2623 | memcpy(&rfc, (void *)val, olen); | ||
2624 | goto done; | ||
2625 | } | ||
2626 | } | ||
2627 | |||
2628 | done: | ||
2629 | switch (rfc.mode) { | ||
2630 | case L2CAP_MODE_ERTM: | ||
2631 | pi->remote_tx_win = rfc.txwin_size; | ||
2632 | pi->retrans_timeout = rfc.retrans_timeout; | ||
2633 | pi->monitor_timeout = rfc.monitor_timeout; | ||
2634 | pi->mps = le16_to_cpu(rfc.max_pdu_size); | ||
2635 | break; | ||
2636 | case L2CAP_MODE_STREAMING: | ||
2637 | pi->mps = le16_to_cpu(rfc.max_pdu_size); | ||
2638 | } | ||
2639 | } | ||
2640 | |||
2605 | static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) | 2641 | static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) |
2606 | { | 2642 | { |
2607 | struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data; | 2643 | struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data; |
@@ -2881,6 +2917,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
2881 | struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; | 2917 | struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; |
2882 | u16 scid, flags, result; | 2918 | u16 scid, flags, result; |
2883 | struct sock *sk; | 2919 | struct sock *sk; |
2920 | int len = cmd->len - sizeof(*rsp); | ||
2884 | 2921 | ||
2885 | scid = __le16_to_cpu(rsp->scid); | 2922 | scid = __le16_to_cpu(rsp->scid); |
2886 | flags = __le16_to_cpu(rsp->flags); | 2923 | flags = __le16_to_cpu(rsp->flags); |
@@ -2895,11 +2932,11 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
2895 | 2932 | ||
2896 | switch (result) { | 2933 | switch (result) { |
2897 | case L2CAP_CONF_SUCCESS: | 2934 | case L2CAP_CONF_SUCCESS: |
2935 | l2cap_conf_rfc_get(sk, rsp->data, len); | ||
2898 | break; | 2936 | break; |
2899 | 2937 | ||
2900 | case L2CAP_CONF_UNACCEPT: | 2938 | case L2CAP_CONF_UNACCEPT: |
2901 | if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { | 2939 | if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) { |
2902 | int len = cmd->len - sizeof(*rsp); | ||
2903 | char req[64]; | 2940 | char req[64]; |
2904 | 2941 | ||
2905 | if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { | 2942 | if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) { |