@@ -571,7 +571,7 @@ static int set_pairable(struct sock *sk, unsigned char *data, u16 len)
571
571
return err ;
572
572
}
573
573
574
- static int uuid_rsp (struct sock * sk , u16 opcode , u16 index )
574
+ static int index_rsp (struct sock * sk , u16 opcode , u16 index )
575
575
{
576
576
struct mgmt_hdr * hdr ;
577
577
struct mgmt_ev_cmd_complete * ev ;
@@ -596,6 +596,39 @@ static int uuid_rsp(struct sock *sk, u16 opcode, u16 index)
596
596
return 0 ;
597
597
}
598
598
599
+ static u8 get_service_classes (struct hci_dev * hdev )
600
+ {
601
+ struct list_head * p ;
602
+ u8 val = 0 ;
603
+
604
+ list_for_each (p , & hdev -> uuids ) {
605
+ struct bt_uuid * uuid = list_entry (p , struct bt_uuid , list );
606
+
607
+ val |= uuid -> svc_hint ;
608
+ }
609
+
610
+ return val ;
611
+ }
612
+
613
+ static int update_class (struct hci_dev * hdev )
614
+ {
615
+ u8 cod [3 ];
616
+
617
+ BT_DBG ("%s" , hdev -> name );
618
+
619
+ if (test_bit (HCI_SERVICE_CACHE , & hdev -> flags ))
620
+ return 0 ;
621
+
622
+ cod [0 ] = hdev -> minor_class ;
623
+ cod [1 ] = hdev -> major_class ;
624
+ cod [2 ] = get_service_classes (hdev );
625
+
626
+ if (memcmp (cod , hdev -> dev_class , 3 ) == 0 )
627
+ return 0 ;
628
+
629
+ return hci_send_cmd (hdev , HCI_OP_WRITE_CLASS_OF_DEV , sizeof (cod ), cod );
630
+ }
631
+
599
632
static int add_uuid (struct sock * sk , unsigned char * data , u16 len )
600
633
{
601
634
struct mgmt_cp_add_uuid * cp ;
@@ -622,10 +655,15 @@ static int add_uuid(struct sock *sk, unsigned char *data, u16 len)
622
655
}
623
656
624
657
memcpy (uuid -> uuid , cp -> uuid , 16 );
658
+ uuid -> svc_hint = cp -> svc_hint ;
625
659
626
660
list_add (& uuid -> list , & hdev -> uuids );
627
661
628
- err = uuid_rsp (sk , MGMT_OP_ADD_UUID , dev_id );
662
+ err = update_class (hdev );
663
+ if (err < 0 )
664
+ goto failed ;
665
+
666
+ err = index_rsp (sk , MGMT_OP_ADD_UUID , dev_id );
629
667
630
668
failed :
631
669
hci_dev_unlock_bh (hdev );
@@ -676,7 +714,11 @@ static int remove_uuid(struct sock *sk, unsigned char *data, u16 len)
676
714
goto unlock ;
677
715
}
678
716
679
- err = uuid_rsp (sk , MGMT_OP_REMOVE_UUID , dev_id );
717
+ err = update_class (hdev );
718
+ if (err < 0 )
719
+ goto unlock ;
720
+
721
+ err = index_rsp (sk , MGMT_OP_REMOVE_UUID , dev_id );
680
722
681
723
unlock :
682
724
hci_dev_unlock_bh (hdev );
@@ -685,6 +727,73 @@ static int remove_uuid(struct sock *sk, unsigned char *data, u16 len)
685
727
return err ;
686
728
}
687
729
730
+ static int set_dev_class (struct sock * sk , unsigned char * data , u16 len )
731
+ {
732
+ struct hci_dev * hdev ;
733
+ struct mgmt_cp_set_dev_class * cp ;
734
+ u16 dev_id ;
735
+ int err ;
736
+
737
+ cp = (void * ) data ;
738
+ dev_id = get_unaligned_le16 (& cp -> index );
739
+
740
+ BT_DBG ("request for hci%u" , dev_id );
741
+
742
+ hdev = hci_dev_get (dev_id );
743
+ if (!hdev )
744
+ return cmd_status (sk , MGMT_OP_SET_DEV_CLASS , ENODEV );
745
+
746
+ hci_dev_lock_bh (hdev );
747
+
748
+ hdev -> major_class = cp -> major ;
749
+ hdev -> minor_class = cp -> minor ;
750
+
751
+ err = update_class (hdev );
752
+
753
+ if (err == 0 )
754
+ err = index_rsp (sk , MGMT_OP_SET_DEV_CLASS , dev_id );
755
+
756
+ hci_dev_unlock_bh (hdev );
757
+ hci_dev_put (hdev );
758
+
759
+ return err ;
760
+ }
761
+
762
+ static int set_service_cache (struct sock * sk , unsigned char * data , u16 len )
763
+ {
764
+ struct hci_dev * hdev ;
765
+ struct mgmt_cp_set_service_cache * cp ;
766
+ u16 dev_id ;
767
+ int err ;
768
+
769
+ cp = (void * ) data ;
770
+ dev_id = get_unaligned_le16 (& cp -> index );
771
+
772
+ hdev = hci_dev_get (dev_id );
773
+ if (!hdev )
774
+ return cmd_status (sk , MGMT_OP_SET_SERVICE_CACHE , ENODEV );
775
+
776
+ hci_dev_lock_bh (hdev );
777
+
778
+ BT_DBG ("hci%u enable %d" , dev_id , cp -> enable );
779
+
780
+ if (cp -> enable ) {
781
+ set_bit (HCI_SERVICE_CACHE , & hdev -> flags );
782
+ err = 0 ;
783
+ } else {
784
+ clear_bit (HCI_SERVICE_CACHE , & hdev -> flags );
785
+ err = update_class (hdev );
786
+ }
787
+
788
+ if (err == 0 )
789
+ err = index_rsp (sk , MGMT_OP_SET_SERVICE_CACHE , dev_id );
790
+
791
+ hci_dev_unlock_bh (hdev );
792
+ hci_dev_put (hdev );
793
+
794
+ return err ;
795
+ }
796
+
688
797
int mgmt_control (struct sock * sk , struct msghdr * msg , size_t msglen )
689
798
{
690
799
unsigned char * buf ;
@@ -743,6 +852,12 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
743
852
case MGMT_OP_REMOVE_UUID :
744
853
err = remove_uuid (sk , buf + sizeof (* hdr ), len );
745
854
break ;
855
+ case MGMT_OP_SET_DEV_CLASS :
856
+ err = set_dev_class (sk , buf + sizeof (* hdr ), len );
857
+ break ;
858
+ case MGMT_OP_SET_SERVICE_CACHE :
859
+ err = set_service_cache (sk , buf + sizeof (* hdr ), len );
860
+ break ;
746
861
default :
747
862
BT_DBG ("Unknown op %u" , opcode );
748
863
err = cmd_status (sk , opcode , 0x01 );
0 commit comments