@@ -617,6 +617,29 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
617
617
return ;
618
618
}
619
619
620
+ static void l2cap_chan_le_connect_reject (struct l2cap_chan * chan )
621
+ {
622
+ struct l2cap_conn * conn = chan -> conn ;
623
+ struct l2cap_le_conn_rsp rsp ;
624
+ u16 result ;
625
+
626
+ if (test_bit (FLAG_DEFER_SETUP , & chan -> flags ))
627
+ result = L2CAP_CR_AUTHORIZATION ;
628
+ else
629
+ result = L2CAP_CR_BAD_PSM ;
630
+
631
+ l2cap_state_change (chan , BT_DISCONN );
632
+
633
+ rsp .dcid = cpu_to_le16 (chan -> scid );
634
+ rsp .mtu = cpu_to_le16 (chan -> imtu );
635
+ rsp .mps = __constant_cpu_to_le16 (L2CAP_LE_DEFAULT_MPS );
636
+ rsp .credits = __constant_cpu_to_le16 (L2CAP_LE_MAX_CREDITS );
637
+ rsp .result = cpu_to_le16 (result );
638
+
639
+ l2cap_send_cmd (conn , chan -> ident , L2CAP_LE_CONN_RSP , sizeof (rsp ),
640
+ & rsp );
641
+ }
642
+
620
643
static void l2cap_chan_connect_reject (struct l2cap_chan * chan )
621
644
{
622
645
struct l2cap_conn * conn = chan -> conn ;
@@ -663,6 +686,8 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)
663
686
if (chan -> chan_type == L2CAP_CHAN_CONN_ORIENTED ) {
664
687
if (conn -> hcon -> type == ACL_LINK )
665
688
l2cap_chan_connect_reject (chan );
689
+ else if (conn -> hcon -> type == LE_LINK )
690
+ l2cap_chan_le_connect_reject (chan );
666
691
}
667
692
668
693
l2cap_chan_del (chan , reason );
@@ -3641,6 +3666,23 @@ static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data,
3641
3666
return ptr - data ;
3642
3667
}
3643
3668
3669
+ void __l2cap_le_connect_rsp_defer (struct l2cap_chan * chan )
3670
+ {
3671
+ struct l2cap_le_conn_rsp rsp ;
3672
+ struct l2cap_conn * conn = chan -> conn ;
3673
+
3674
+ BT_DBG ("chan %p" , chan );
3675
+
3676
+ rsp .dcid = cpu_to_le16 (chan -> scid );
3677
+ rsp .mtu = cpu_to_le16 (chan -> imtu );
3678
+ rsp .mps = __constant_cpu_to_le16 (L2CAP_LE_DEFAULT_MPS );
3679
+ rsp .credits = __constant_cpu_to_le16 (L2CAP_LE_MAX_CREDITS );
3680
+ rsp .result = __constant_cpu_to_le16 (L2CAP_CR_SUCCESS );
3681
+
3682
+ l2cap_send_cmd (conn , chan -> ident , L2CAP_LE_CONN_RSP , sizeof (rsp ),
3683
+ & rsp );
3684
+ }
3685
+
3644
3686
void __l2cap_connect_rsp_defer (struct l2cap_chan * chan )
3645
3687
{
3646
3688
struct l2cap_conn_rsp rsp ;
@@ -5382,6 +5424,113 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
5382
5424
return err ;
5383
5425
}
5384
5426
5427
+ static int l2cap_le_connect_req (struct l2cap_conn * conn ,
5428
+ struct l2cap_cmd_hdr * cmd , u16 cmd_len ,
5429
+ u8 * data )
5430
+ {
5431
+ struct l2cap_le_conn_req * req = (struct l2cap_le_conn_req * ) data ;
5432
+ struct l2cap_le_conn_rsp rsp ;
5433
+ struct l2cap_chan * chan , * pchan ;
5434
+ u16 dcid , scid , mtu , mps ;
5435
+ __le16 psm ;
5436
+ u8 result ;
5437
+
5438
+ if (cmd_len != sizeof (* req ))
5439
+ return - EPROTO ;
5440
+
5441
+ scid = __le16_to_cpu (req -> scid );
5442
+ mtu = __le16_to_cpu (req -> mtu );
5443
+ mps = __le16_to_cpu (req -> mps );
5444
+ psm = req -> psm ;
5445
+ dcid = 0 ;
5446
+
5447
+ if (mtu < 23 || mps < 23 )
5448
+ return - EPROTO ;
5449
+
5450
+ BT_DBG ("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u" , __le16_to_cpu (psm ),
5451
+ scid , mtu , mps );
5452
+
5453
+ /* Check if we have socket listening on psm */
5454
+ pchan = l2cap_global_chan_by_psm (BT_LISTEN , psm , & conn -> hcon -> src ,
5455
+ & conn -> hcon -> dst , LE_LINK );
5456
+ if (!pchan ) {
5457
+ result = L2CAP_CR_BAD_PSM ;
5458
+ chan = NULL ;
5459
+ goto response ;
5460
+ }
5461
+
5462
+ mutex_lock (& conn -> chan_lock );
5463
+ l2cap_chan_lock (pchan );
5464
+
5465
+ if (!smp_sufficient_security (conn -> hcon , pchan -> sec_level )) {
5466
+ result = L2CAP_CR_AUTHENTICATION ;
5467
+ chan = NULL ;
5468
+ goto response_unlock ;
5469
+ }
5470
+
5471
+ /* Check if we already have channel with that dcid */
5472
+ if (__l2cap_get_chan_by_dcid (conn , scid )) {
5473
+ result = L2CAP_CR_NO_MEM ;
5474
+ chan = NULL ;
5475
+ goto response_unlock ;
5476
+ }
5477
+
5478
+ chan = pchan -> ops -> new_connection (pchan );
5479
+ if (!chan ) {
5480
+ result = L2CAP_CR_NO_MEM ;
5481
+ goto response_unlock ;
5482
+ }
5483
+
5484
+ bacpy (& chan -> src , & conn -> hcon -> src );
5485
+ bacpy (& chan -> dst , & conn -> hcon -> dst );
5486
+ chan -> src_type = bdaddr_type (conn -> hcon , conn -> hcon -> src_type );
5487
+ chan -> dst_type = bdaddr_type (conn -> hcon , conn -> hcon -> dst_type );
5488
+ chan -> psm = psm ;
5489
+ chan -> dcid = scid ;
5490
+ chan -> omtu = mtu ;
5491
+ chan -> remote_mps = mps ;
5492
+
5493
+ __l2cap_chan_add (conn , chan );
5494
+ dcid = chan -> scid ;
5495
+
5496
+ __set_chan_timer (chan , chan -> ops -> get_sndtimeo (chan ));
5497
+
5498
+ chan -> ident = cmd -> ident ;
5499
+
5500
+ if (test_bit (FLAG_DEFER_SETUP , & chan -> flags )) {
5501
+ l2cap_state_change (chan , BT_CONNECT2 );
5502
+ result = L2CAP_CR_PEND ;
5503
+ chan -> ops -> defer (chan );
5504
+ } else {
5505
+ l2cap_chan_ready (chan );
5506
+ result = L2CAP_CR_SUCCESS ;
5507
+ }
5508
+
5509
+ response_unlock :
5510
+ l2cap_chan_unlock (pchan );
5511
+ mutex_unlock (& conn -> chan_lock );
5512
+
5513
+ if (result == L2CAP_CR_PEND )
5514
+ return 0 ;
5515
+
5516
+ response :
5517
+ if (chan ) {
5518
+ rsp .mtu = cpu_to_le16 (chan -> imtu );
5519
+ rsp .mps = __constant_cpu_to_le16 (L2CAP_LE_DEFAULT_MPS );
5520
+ } else {
5521
+ rsp .mtu = 0 ;
5522
+ rsp .mps = 0 ;
5523
+ }
5524
+
5525
+ rsp .dcid = cpu_to_le16 (dcid );
5526
+ rsp .credits = __constant_cpu_to_le16 (L2CAP_LE_MAX_CREDITS );
5527
+ rsp .result = cpu_to_le16 (result );
5528
+
5529
+ l2cap_send_cmd (conn , cmd -> ident , L2CAP_LE_CONN_RSP , sizeof (rsp ), & rsp );
5530
+
5531
+ return 0 ;
5532
+ }
5533
+
5385
5534
static inline int l2cap_le_sig_cmd (struct l2cap_conn * conn ,
5386
5535
struct l2cap_cmd_hdr * cmd , u16 cmd_len ,
5387
5536
u8 * data )
@@ -5400,6 +5549,9 @@ static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
5400
5549
l2cap_le_connect_rsp (conn , cmd , cmd_len , data );
5401
5550
return 0 ;
5402
5551
5552
+ case L2CAP_LE_CONN_REQ :
5553
+ return l2cap_le_connect_req (conn , cmd , cmd_len , data );
5554
+
5403
5555
default :
5404
5556
BT_ERR ("Unknown LE signaling command 0x%2.2x" , cmd -> code );
5405
5557
return - EINVAL ;
0 commit comments