diff options
author | Andrei Emeltchenko <andrei.emeltchenko@intel.com> | 2011-10-17 07:35:30 -0400 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-10-17 16:09:06 -0400 |
commit | 42dceae2819b5ac6fc9a0d414ae05a8960e2a1d9 (patch) | |
tree | 1ca8c1faf83db4152aa0b257a8381a8e07ea4bd8 /net/bluetooth/l2cap_core.c | |
parent | c8f791626a8840fe60a05ab55468dfb3922cb35a (diff) |
Bluetooth: EFS: parse L2CAP config request
Add parsing Extended Flow Specification option in L2CAP Config Request
Based upon haijun.liu <haijun.liu@atheros.com> series of patches
(sent Sun, 22 Aug 2010)
Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth/l2cap_core.c')
-rw-r--r-- | net/bluetooth/l2cap_core.c | 44 |
1 files changed, 43 insertions, 1 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 78911269d901..bda6da797734 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -2115,6 +2115,8 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) | |||
2115 | int type, hint, olen; | 2115 | int type, hint, olen; |
2116 | unsigned long val; | 2116 | unsigned long val; |
2117 | struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; | 2117 | struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; |
2118 | struct l2cap_conf_efs efs; | ||
2119 | u8 remote_efs = 0; | ||
2118 | u16 mtu = L2CAP_DEFAULT_MTU; | 2120 | u16 mtu = L2CAP_DEFAULT_MTU; |
2119 | u16 result = L2CAP_CONF_SUCCESS; | 2121 | u16 result = L2CAP_CONF_SUCCESS; |
2120 | u16 size; | 2122 | u16 size; |
@@ -2147,7 +2149,12 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) | |||
2147 | case L2CAP_CONF_FCS: | 2149 | case L2CAP_CONF_FCS: |
2148 | if (val == L2CAP_FCS_NONE) | 2150 | if (val == L2CAP_FCS_NONE) |
2149 | set_bit(CONF_NO_FCS_RECV, &chan->conf_state); | 2151 | set_bit(CONF_NO_FCS_RECV, &chan->conf_state); |
2152 | break; | ||
2150 | 2153 | ||
2154 | case L2CAP_CONF_EFS: | ||
2155 | remote_efs = 1; | ||
2156 | if (olen == sizeof(efs)) | ||
2157 | memcpy(&efs, (void *) val, olen); | ||
2151 | break; | 2158 | break; |
2152 | 2159 | ||
2153 | case L2CAP_CONF_EWS: | 2160 | case L2CAP_CONF_EWS: |
@@ -2182,6 +2189,13 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) | |||
2182 | break; | 2189 | break; |
2183 | } | 2190 | } |
2184 | 2191 | ||
2192 | if (remote_efs) { | ||
2193 | if (__l2cap_efs_supported(chan)) | ||
2194 | set_bit(FLAG_EFS_ENABLE, &chan->flags); | ||
2195 | else | ||
2196 | return -ECONNREFUSED; | ||
2197 | } | ||
2198 | |||
2185 | if (chan->mode != rfc.mode) | 2199 | if (chan->mode != rfc.mode) |
2186 | return -ECONNREFUSED; | 2200 | return -ECONNREFUSED; |
2187 | 2201 | ||
@@ -2200,7 +2214,6 @@ done: | |||
2200 | sizeof(rfc), (unsigned long) &rfc); | 2214 | sizeof(rfc), (unsigned long) &rfc); |
2201 | } | 2215 | } |
2202 | 2216 | ||
2203 | |||
2204 | if (result == L2CAP_CONF_SUCCESS) { | 2217 | if (result == L2CAP_CONF_SUCCESS) { |
2205 | /* Configure output options and let the other side know | 2218 | /* Configure output options and let the other side know |
2206 | * which ones we don't like. */ | 2219 | * which ones we don't like. */ |
@@ -2213,6 +2226,22 @@ done: | |||
2213 | } | 2226 | } |
2214 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu); | 2227 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu); |
2215 | 2228 | ||
2229 | if (remote_efs) { | ||
2230 | if (chan->local_stype != L2CAP_SERV_NOTRAFIC && | ||
2231 | efs.stype != L2CAP_SERV_NOTRAFIC && | ||
2232 | efs.stype != chan->local_stype) { | ||
2233 | |||
2234 | result = L2CAP_CONF_UNACCEPT; | ||
2235 | |||
2236 | if (chan->num_conf_req >= 1) | ||
2237 | return -ECONNREFUSED; | ||
2238 | |||
2239 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, | ||
2240 | sizeof(efs), | ||
2241 | (unsigned long) &efs); | ||
2242 | } | ||
2243 | } | ||
2244 | |||
2216 | switch (rfc.mode) { | 2245 | switch (rfc.mode) { |
2217 | case L2CAP_MODE_BASIC: | 2246 | case L2CAP_MODE_BASIC: |
2218 | chan->fcs = L2CAP_FCS_NONE; | 2247 | chan->fcs = L2CAP_FCS_NONE; |
@@ -2245,6 +2274,19 @@ done: | |||
2245 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, | 2274 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, |
2246 | sizeof(rfc), (unsigned long) &rfc); | 2275 | sizeof(rfc), (unsigned long) &rfc); |
2247 | 2276 | ||
2277 | if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { | ||
2278 | chan->remote_id = efs.id; | ||
2279 | chan->remote_stype = efs.stype; | ||
2280 | chan->remote_msdu = le16_to_cpu(efs.msdu); | ||
2281 | chan->remote_flush_to = | ||
2282 | le32_to_cpu(efs.flush_to); | ||
2283 | chan->remote_acc_lat = | ||
2284 | le32_to_cpu(efs.acc_lat); | ||
2285 | chan->remote_sdu_itime = | ||
2286 | le32_to_cpu(efs.sdu_itime); | ||
2287 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, | ||
2288 | sizeof(efs), (unsigned long) &efs); | ||
2289 | } | ||
2248 | break; | 2290 | break; |
2249 | 2291 | ||
2250 | case L2CAP_MODE_STREAMING: | 2292 | case L2CAP_MODE_STREAMING: |