@@ -395,6 +395,24 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr,
395395 return sizeof (struct sockaddr_l2 );
396396}
397397
398+ static int l2cap_get_mode (struct l2cap_chan * chan )
399+ {
400+ switch (chan -> mode ) {
401+ case L2CAP_MODE_BASIC :
402+ return BT_MODE_BASIC ;
403+ case L2CAP_MODE_ERTM :
404+ return BT_MODE_ERTM ;
405+ case L2CAP_MODE_STREAMING :
406+ return BT_MODE_STREAMING ;
407+ case L2CAP_MODE_LE_FLOWCTL :
408+ return BT_MODE_LE_FLOWCTL ;
409+ case L2CAP_MODE_EXT_FLOWCTL :
410+ return BT_MODE_EXT_FLOWCTL ;
411+ }
412+
413+ return - EINVAL ;
414+ }
415+
398416static int l2cap_sock_getsockopt_old (struct socket * sock , int optname ,
399417 char __user * optval , int __user * optlen )
400418{
@@ -522,7 +540,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
522540 struct bt_security sec ;
523541 struct bt_power pwr ;
524542 u32 phys ;
525- int len , err = 0 ;
543+ int len , mode , err = 0 ;
526544
527545 BT_DBG ("sk %p" , sk );
528546
@@ -638,6 +656,27 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
638656 err = - EFAULT ;
639657 break ;
640658
659+ case BT_MODE :
660+ if (!enable_ecred ) {
661+ err = - ENOPROTOOPT ;
662+ break ;
663+ }
664+
665+ if (chan -> chan_type != L2CAP_CHAN_CONN_ORIENTED ) {
666+ err = - EINVAL ;
667+ break ;
668+ }
669+
670+ mode = l2cap_get_mode (chan );
671+ if (mode < 0 ) {
672+ err = mode ;
673+ break ;
674+ }
675+
676+ if (put_user (mode , (u8 __user * ) optval ))
677+ err = - EFAULT ;
678+ break ;
679+
641680 default :
642681 err = - ENOPROTOOPT ;
643682 break ;
@@ -780,6 +819,45 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
780819 return err ;
781820}
782821
822+ static int l2cap_set_mode (struct l2cap_chan * chan , u8 mode )
823+ {
824+ switch (mode ) {
825+ case BT_MODE_BASIC :
826+ if (bdaddr_type_is_le (chan -> src_type ))
827+ return - EINVAL ;
828+ mode = L2CAP_MODE_BASIC ;
829+ clear_bit (CONF_STATE2_DEVICE , & chan -> conf_state );
830+ break ;
831+ case BT_MODE_ERTM :
832+ if (!disable_ertm || bdaddr_type_is_le (chan -> src_type ))
833+ return - EINVAL ;
834+ mode = L2CAP_MODE_ERTM ;
835+ break ;
836+ case BT_MODE_STREAMING :
837+ if (!disable_ertm || bdaddr_type_is_le (chan -> src_type ))
838+ return - EINVAL ;
839+ mode = L2CAP_MODE_STREAMING ;
840+ break ;
841+ case BT_MODE_LE_FLOWCTL :
842+ if (!bdaddr_type_is_le (chan -> src_type ))
843+ return - EINVAL ;
844+ mode = L2CAP_MODE_LE_FLOWCTL ;
845+ break ;
846+ case BT_MODE_EXT_FLOWCTL :
847+ /* TODO: Add support for ECRED PDUs to BR/EDR */
848+ if (!bdaddr_type_is_le (chan -> src_type ))
849+ return - EINVAL ;
850+ mode = L2CAP_MODE_EXT_FLOWCTL ;
851+ break ;
852+ default :
853+ return - EINVAL ;
854+ }
855+
856+ chan -> mode = mode ;
857+
858+ return 0 ;
859+ }
860+
783861static int l2cap_sock_setsockopt (struct socket * sock , int level , int optname ,
784862 char __user * optval , unsigned int optlen )
785863{
@@ -985,6 +1063,39 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
9851063
9861064 break ;
9871065
1066+ case BT_MODE :
1067+ if (!enable_ecred ) {
1068+ err = - ENOPROTOOPT ;
1069+ break ;
1070+ }
1071+
1072+ BT_DBG ("sk->sk_state %u" , sk -> sk_state );
1073+
1074+ if (sk -> sk_state != BT_BOUND ) {
1075+ err = - EINVAL ;
1076+ break ;
1077+ }
1078+
1079+ if (chan -> chan_type != L2CAP_CHAN_CONN_ORIENTED ) {
1080+ err = - EINVAL ;
1081+ break ;
1082+ }
1083+
1084+ if (get_user (opt , (u8 __user * ) optval )) {
1085+ err = - EFAULT ;
1086+ break ;
1087+ }
1088+
1089+ BT_DBG ("opt %u" , opt );
1090+
1091+ err = l2cap_set_mode (chan , opt );
1092+ if (err )
1093+ break ;
1094+
1095+ BT_DBG ("mode 0x%2.2x" , chan -> mode );
1096+
1097+ break ;
1098+
9881099 default :
9891100 err = - ENOPROTOOPT ;
9901101 break ;
0 commit comments