@@ -1211,19 +1211,22 @@ static uint16_t l2cap_br_conf_opt_mtu(struct bt_l2cap_chan *chan,
1211
1211
struct net_buf * buf , size_t len )
1212
1212
{
1213
1213
uint16_t mtu , result = BT_L2CAP_CONF_SUCCESS ;
1214
+ struct bt_l2cap_conf_opt_mtu * opt_mtu ;
1214
1215
1215
1216
/* Core 4.2 [Vol 3, Part A, 5.1] MTU payload length */
1216
- if (len != 2 ) {
1217
+ if (len != sizeof ( * opt_mtu ) ) {
1217
1218
LOG_ERR ("tx MTU length %zu invalid" , len );
1218
1219
result = BT_L2CAP_CONF_REJECT ;
1219
1220
goto done ;
1220
1221
}
1221
1222
1222
- /* pulling MTU value moves buf data to next option item */
1223
- mtu = net_buf_pull_le16 (buf );
1223
+ opt_mtu = (struct bt_l2cap_conf_opt_mtu * )buf -> data ;
1224
+
1225
+ mtu = sys_le16_to_cpu (opt_mtu -> mtu );
1224
1226
if (mtu < L2CAP_BR_MIN_MTU ) {
1225
1227
result = BT_L2CAP_CONF_UNACCEPT ;
1226
1228
BR_CHAN (chan )-> tx .mtu = L2CAP_BR_MIN_MTU ;
1229
+ opt_mtu -> mtu = sys_cpu_to_le16 (L2CAP_BR_MIN_MTU );
1227
1230
LOG_DBG ("tx MTU %u invalid" , mtu );
1228
1231
goto done ;
1229
1232
}
@@ -1234,6 +1237,116 @@ static uint16_t l2cap_br_conf_opt_mtu(struct bt_l2cap_chan *chan,
1234
1237
return result ;
1235
1238
}
1236
1239
1240
+ static uint16_t l2cap_br_conf_opt_flush_timeout (struct bt_l2cap_chan * chan ,
1241
+ struct net_buf * buf , size_t len )
1242
+ {
1243
+ uint16_t result = BT_L2CAP_CONF_SUCCESS ;
1244
+ struct bt_l2cap_conf_opt_flush_timeout * opt_to ;
1245
+
1246
+ if (len != sizeof (* opt_to )) {
1247
+ LOG_ERR ("qos frame length %zu invalid" , len );
1248
+ result = BT_L2CAP_CONF_REJECT ;
1249
+ goto done ;
1250
+ }
1251
+
1252
+ opt_to = (struct bt_l2cap_conf_opt_flush_timeout * )buf -> data ;
1253
+
1254
+ LOG_DBG ("Flush timeout %u" , opt_to -> timeout );
1255
+
1256
+ opt_to -> timeout = sys_cpu_to_le16 (0xFFFF );
1257
+ result = BT_L2CAP_CONF_UNACCEPT ;
1258
+ done :
1259
+ return result ;
1260
+ }
1261
+
1262
+ static uint16_t l2cap_br_conf_opt_qos (struct bt_l2cap_chan * chan ,
1263
+ struct net_buf * buf , size_t len )
1264
+ {
1265
+ uint16_t result = BT_L2CAP_CONF_SUCCESS ;
1266
+ struct bt_l2cap_conf_opt_qos * opt_qos ;
1267
+
1268
+ if (len != sizeof (* opt_qos )) {
1269
+ LOG_ERR ("qos frame length %zu invalid" , len );
1270
+ result = BT_L2CAP_CONF_REJECT ;
1271
+ goto done ;
1272
+ }
1273
+
1274
+ opt_qos = (struct bt_l2cap_conf_opt_qos * )buf -> data ;
1275
+
1276
+ LOG_DBG ("QOS Type %u" , opt_qos -> service_type );
1277
+
1278
+ if (opt_qos -> service_type == BT_L2CAP_QOS_TYPE_GUARANTEED ) {
1279
+ /* Set to default value */
1280
+ result = BT_L2CAP_CONF_UNACCEPT ;
1281
+ opt_qos -> flags = 0x00 ;
1282
+ /* do not care */
1283
+ opt_qos -> token_rate = sys_cpu_to_le32 (0x00000000 );
1284
+ /* no token bucket is needed */
1285
+ opt_qos -> token_bucket_size = sys_cpu_to_le32 (0x00000000 );
1286
+ /* do not care */
1287
+ opt_qos -> peak_bandwidth = sys_cpu_to_le32 (0x00000000 );
1288
+ /* do not care */
1289
+ opt_qos -> latency = sys_cpu_to_le32 (0xFFFFFFFF );
1290
+ /* do not care */
1291
+ opt_qos -> delay_variation = sys_cpu_to_le32 (0xFFFFFFFF );
1292
+ }
1293
+
1294
+ done :
1295
+ return result ;
1296
+ }
1297
+
1298
+ static uint16_t l2cap_br_conf_opt_ret_fc (struct bt_l2cap_chan * chan ,
1299
+ struct net_buf * buf , size_t len )
1300
+ {
1301
+ uint16_t result = BT_L2CAP_CONF_SUCCESS ;
1302
+ struct bt_l2cap_conf_opt_ret_fc * opt_ret_fc ;
1303
+
1304
+ if (len != sizeof (* opt_ret_fc )) {
1305
+ LOG_ERR ("ret_fc frame length %zu invalid" , len );
1306
+ result = BT_L2CAP_CONF_REJECT ;
1307
+ goto done ;
1308
+ }
1309
+
1310
+ opt_ret_fc = (struct bt_l2cap_conf_opt_ret_fc * )buf -> data ;
1311
+
1312
+ LOG_DBG ("ret_fc mode %u" , opt_ret_fc -> mode );
1313
+
1314
+ if (opt_ret_fc -> mode != BT_L2CAP_RET_FC_MODE_BASIC ) {
1315
+ /* Set to default value */
1316
+ result = BT_L2CAP_CONF_UNACCEPT ;
1317
+ opt_ret_fc -> mode = BT_L2CAP_RET_FC_MODE_BASIC ;
1318
+ }
1319
+
1320
+ done :
1321
+ return result ;
1322
+ }
1323
+
1324
+ static uint16_t l2cap_br_conf_opt_fcs (struct bt_l2cap_chan * chan ,
1325
+ struct net_buf * buf , size_t len )
1326
+ {
1327
+ uint16_t result = BT_L2CAP_CONF_SUCCESS ;
1328
+ struct bt_l2cap_conf_opt_fcs * opt_fcs ;
1329
+
1330
+ if (len != sizeof (* opt_fcs )) {
1331
+ LOG_ERR ("fcs frame length %zu invalid" , len );
1332
+ result = BT_L2CAP_CONF_REJECT ;
1333
+ goto done ;
1334
+ }
1335
+
1336
+ opt_fcs = (struct bt_l2cap_conf_opt_fcs * )buf -> data ;
1337
+
1338
+ LOG_DBG ("FCS type %u" , opt_fcs -> type );
1339
+
1340
+ if (opt_fcs -> type != BT_L2CAP_FCS_TYPE_NO ) {
1341
+ /* Set to default value */
1342
+ result = BT_L2CAP_CONF_UNACCEPT ;
1343
+ opt_fcs -> type = BT_L2CAP_FCS_TYPE_NO ;
1344
+ }
1345
+
1346
+ done :
1347
+ return result ;
1348
+ }
1349
+
1237
1350
static void l2cap_br_conf_req (struct bt_l2cap_br * l2cap , uint8_t ident ,
1238
1351
uint16_t len , struct net_buf * buf )
1239
1352
{
@@ -1260,9 +1373,10 @@ static void l2cap_br_conf_req(struct bt_l2cap_br *l2cap, uint8_t ident,
1260
1373
chan = bt_l2cap_br_lookup_rx_cid (conn , dcid );
1261
1374
if (!chan ) {
1262
1375
LOG_ERR ("rx channel mismatch!" );
1263
- struct bt_l2cap_cmd_reject_cid_data data = {.scid = req -> dcid ,
1264
- .dcid = 0 ,
1265
- };
1376
+ struct bt_l2cap_cmd_reject_cid_data data = {
1377
+ .scid = req -> dcid ,
1378
+ .dcid = 0 ,
1379
+ };
1266
1380
1267
1381
l2cap_br_send_reject (conn , ident , BT_L2CAP_REJ_INVALID_CID ,
1268
1382
& data , sizeof (data ));
@@ -1298,17 +1412,46 @@ static void l2cap_br_conf_req(struct bt_l2cap_br *l2cap, uint8_t ident,
1298
1412
* way out here.
1299
1413
*/
1300
1414
goto send_rsp ;
1415
+ case BT_L2CAP_CONF_OPT_FLUSH_TIMEOUT :
1416
+ result = l2cap_br_conf_opt_flush_timeout (chan , buf , opt -> len );
1417
+ if (result != BT_L2CAP_CONF_SUCCESS ) {
1418
+ goto send_rsp ;
1419
+ }
1420
+ break ;
1421
+ case BT_L2CAP_CONF_OPT_QOS :
1422
+ result = l2cap_br_conf_opt_qos (chan , buf , opt -> len );
1423
+ if (result != BT_L2CAP_CONF_SUCCESS ) {
1424
+ goto send_rsp ;
1425
+ }
1426
+ break ;
1427
+ case BT_L2CAP_CONF_OPT_RET_FC :
1428
+ result = l2cap_br_conf_opt_ret_fc (chan , buf , opt -> len );
1429
+ if (result != BT_L2CAP_CONF_SUCCESS ) {
1430
+ goto send_rsp ;
1431
+ }
1432
+ break ;
1433
+ case BT_L2CAP_CONF_OPT_FCS :
1434
+ result = l2cap_br_conf_opt_fcs (chan , buf , opt -> len );
1435
+ if (result != BT_L2CAP_CONF_SUCCESS ) {
1436
+ goto send_rsp ;
1437
+ }
1438
+ break ;
1439
+ case BT_L2CAP_CONF_OPT_EXT_FLOW_SPEC :
1440
+ __fallthrough ;
1441
+ case BT_L2CAP_CONF_OPT_EXT_WIN_SIZE :
1442
+ result = BT_L2CAP_CONF_REJECT ;
1443
+ goto send_rsp ;
1301
1444
default :
1302
1445
if (!hint ) {
1303
1446
LOG_DBG ("option %u not handled" , opt -> type );
1304
1447
result = BT_L2CAP_CONF_UNKNOWN_OPT ;
1305
1448
goto send_rsp ;
1306
1449
}
1307
-
1308
- /* Update buffer to point at next option */
1309
- net_buf_pull (buf , opt -> len );
1310
1450
break ;
1311
1451
}
1452
+
1453
+ /* Update buffer to point at next option */
1454
+ net_buf_pull (buf , opt -> len );
1312
1455
}
1313
1456
1314
1457
send_rsp :
@@ -1328,9 +1471,7 @@ static void l2cap_br_conf_req(struct bt_l2cap_br *l2cap, uint8_t ident,
1328
1471
* the options chain need to be modified and taken into account when
1329
1472
* sending back to peer.
1330
1473
*/
1331
- if (result == BT_L2CAP_CONF_UNACCEPT ) {
1332
- l2cap_br_conf_add_mtu (buf , BR_CHAN (chan )-> tx .mtu );
1333
- } else if (result == BT_L2CAP_CONF_UNKNOWN_OPT ) {
1474
+ if ((result == BT_L2CAP_CONF_UNKNOWN_OPT ) || (result == BT_L2CAP_CONF_UNACCEPT )) {
1334
1475
if (opt ) {
1335
1476
l2cap_br_conf_add_opt (buf , opt );
1336
1477
}
0 commit comments