5
5
*/
6
6
7
7
#include <linux/ctype.h>
8
+ #include <linux/dmi.h>
8
9
#include <linux/kernel.h>
9
10
#include <linux/module.h>
10
11
#include <linux/init.h>
@@ -750,114 +751,179 @@ static void hid_sensor_custom_dev_if_remove(struct hid_sensor_custom
750
751
751
752
}
752
753
753
- /* luid defined in FW (e.g. ISH). Maybe used to identify sensor. */
754
- static const char * const known_sensor_luid [] = { "020B000000000000" };
754
+ /*
755
+ * Match a known custom sensor.
756
+ * tag and luid is mandatory.
757
+ */
758
+ struct hid_sensor_custom_match {
759
+ const char * tag ;
760
+ const char * luid ;
761
+ const char * model ;
762
+ const char * manufacturer ;
763
+ bool check_dmi ;
764
+ struct dmi_system_id dmi ;
765
+ };
755
766
756
- static int get_luid_table_index (unsigned char * usage_str )
757
- {
758
- int i ;
767
+ /*
768
+ * Custom sensor properties used for matching.
769
+ */
770
+ struct hid_sensor_custom_properties {
771
+ u16 serial_num [HID_CUSTOM_MAX_FEATURE_BYTES ];
772
+ u16 model [HID_CUSTOM_MAX_FEATURE_BYTES ];
773
+ u16 manufacturer [HID_CUSTOM_MAX_FEATURE_BYTES ];
774
+ };
759
775
760
- for (i = 0 ; i < ARRAY_SIZE (known_sensor_luid ); i ++ ) {
761
- if (!strncmp (usage_str , known_sensor_luid [i ],
762
- strlen (known_sensor_luid [i ])))
763
- return i ;
776
+ static const struct hid_sensor_custom_match hid_sensor_custom_known_table [] = {
777
+ /*
778
+ * Intel Integrated Sensor Hub (ISH)
779
+ */
780
+ { /* Intel ISH hinge */
781
+ .tag = "INT" ,
782
+ .luid = "020B000000000000" ,
783
+ .manufacturer = "INTEL" ,
784
+ },
785
+ {}
786
+ };
787
+
788
+ static bool hid_sensor_custom_prop_match_str (const u16 * prop , const char * match ,
789
+ size_t count )
790
+ {
791
+ while (count -- && * prop && * match ) {
792
+ if (* prop != (u16 ) * match )
793
+ return false;
794
+ prop ++ ;
795
+ match ++ ;
764
796
}
765
797
766
- return - ENODEV ;
798
+ return ( count == -1 ) || * prop == ( u16 ) * match ;
767
799
}
768
800
769
- static int get_known_custom_sensor_index (struct hid_sensor_hub_device * hsdev )
801
+ static int hid_sensor_custom_get_prop (struct hid_sensor_hub_device * hsdev ,
802
+ u32 prop_usage_id , size_t prop_size ,
803
+ u16 * prop )
770
804
{
771
- struct hid_sensor_hub_attribute_info sensor_manufacturer = { 0 };
772
- struct hid_sensor_hub_attribute_info sensor_luid_info = { 0 };
773
- int report_size ;
805
+ struct hid_sensor_hub_attribute_info prop_attr = { 0 };
774
806
int ret ;
775
- static u16 w_buf [HID_CUSTOM_MAX_FEATURE_BYTES ];
776
- static char buf [HID_CUSTOM_MAX_FEATURE_BYTES ];
777
- int i ;
778
807
779
- memset (w_buf , 0 , sizeof (w_buf ));
780
- memset (buf , 0 , sizeof (buf ));
808
+ memset (prop , 0 , prop_size );
781
809
782
- /* get manufacturer info */
783
- ret = sensor_hub_input_get_attribute_info (hsdev ,
784
- HID_FEATURE_REPORT , hsdev -> usage ,
785
- HID_USAGE_SENSOR_PROP_MANUFACTURER , & sensor_manufacturer );
810
+ ret = sensor_hub_input_get_attribute_info (hsdev , HID_FEATURE_REPORT ,
811
+ hsdev -> usage , prop_usage_id ,
812
+ & prop_attr );
786
813
if (ret < 0 )
787
814
return ret ;
788
815
789
- report_size =
790
- sensor_hub_get_feature (hsdev , sensor_manufacturer .report_id ,
791
- sensor_manufacturer .index , sizeof (w_buf ),
792
- w_buf );
793
- if (report_size <= 0 ) {
794
- hid_err (hsdev -> hdev ,
795
- "Failed to get sensor manufacturer info %d\n" ,
796
- report_size );
797
- return - ENODEV ;
816
+ ret = sensor_hub_get_feature (hsdev , prop_attr .report_id ,
817
+ prop_attr .index , prop_size , prop );
818
+ if (ret < 0 ) {
819
+ hid_err (hsdev -> hdev , "Failed to get sensor property %08x %d\n" ,
820
+ prop_usage_id , ret );
821
+ return ret ;
798
822
}
799
823
800
- /* convert from wide char to char */
801
- for (i = 0 ; i < ARRAY_SIZE (buf ) - 1 && w_buf [i ]; i ++ )
802
- buf [i ] = (char )w_buf [i ];
824
+ return 0 ;
825
+ }
826
+
827
+ static bool
828
+ hid_sensor_custom_do_match (struct hid_sensor_hub_device * hsdev ,
829
+ const struct hid_sensor_custom_match * match ,
830
+ const struct hid_sensor_custom_properties * prop )
831
+ {
832
+ struct dmi_system_id dmi [] = { match -> dmi , { 0 } };
833
+
834
+ if (!hid_sensor_custom_prop_match_str (prop -> serial_num , "LUID:" , 5 ) ||
835
+ !hid_sensor_custom_prop_match_str (prop -> serial_num + 5 , match -> luid ,
836
+ HID_CUSTOM_MAX_FEATURE_BYTES - 5 ))
837
+ return false;
838
+
839
+ if (match -> model &&
840
+ !hid_sensor_custom_prop_match_str (prop -> model , match -> model ,
841
+ HID_CUSTOM_MAX_FEATURE_BYTES ))
842
+ return false;
843
+
844
+ if (match -> manufacturer &&
845
+ !hid_sensor_custom_prop_match_str (prop -> manufacturer , match -> manufacturer ,
846
+ HID_CUSTOM_MAX_FEATURE_BYTES ))
847
+ return false;
803
848
804
- /* ensure it's ISH sensor */
805
- if (strncmp (buf , "INTEL" , strlen ("INTEL" )))
806
- return - ENODEV ;
849
+ if (match -> check_dmi && !dmi_check_system (dmi ))
850
+ return false;
807
851
808
- memset ( w_buf , 0 , sizeof ( w_buf )) ;
809
- memset ( buf , 0 , sizeof ( buf ));
852
+ return true ;
853
+ }
810
854
811
- /* get real usage id */
812
- ret = sensor_hub_input_get_attribute_info (hsdev ,
813
- HID_FEATURE_REPORT , hsdev -> usage ,
814
- HID_USAGE_SENSOR_PROP_SERIAL_NUM , & sensor_luid_info );
855
+ static int
856
+ hid_sensor_custom_properties_get (struct hid_sensor_hub_device * hsdev ,
857
+ struct hid_sensor_custom_properties * prop )
858
+ {
859
+ int ret ;
860
+
861
+ ret = hid_sensor_custom_get_prop (hsdev ,
862
+ HID_USAGE_SENSOR_PROP_SERIAL_NUM ,
863
+ HID_CUSTOM_MAX_FEATURE_BYTES ,
864
+ prop -> serial_num );
815
865
if (ret < 0 )
816
866
return ret ;
817
867
818
- report_size = sensor_hub_get_feature ( hsdev , sensor_luid_info . report_id ,
819
- sensor_luid_info . index , sizeof ( w_buf ),
820
- w_buf );
821
- if ( report_size <= 0 ) {
822
- hid_err ( hsdev -> hdev , "Failed to get real usage info %d\n" ,
823
- report_size );
824
- return - ENODEV ;
825
- }
868
+ /*
869
+ * Ignore errors on the following model and manufacturer properties.
870
+ * Because these are optional, it is not an error if they are missing.
871
+ */
872
+
873
+ hid_sensor_custom_get_prop ( hsdev , HID_USAGE_SENSOR_PROP_MODEL ,
874
+ HID_CUSTOM_MAX_FEATURE_BYTES ,
875
+ prop -> model );
826
876
827
- /* convert from wide char to char */
828
- for ( i = 0 ; i < ARRAY_SIZE ( buf ) - 1 && w_buf [ i ]; i ++ )
829
- buf [ i ] = ( char ) w_buf [ i ] ;
877
+ hid_sensor_custom_get_prop ( hsdev , HID_USAGE_SENSOR_PROP_MANUFACTURER ,
878
+ HID_CUSTOM_MAX_FEATURE_BYTES ,
879
+ prop -> manufacturer ) ;
830
880
831
- if (strlen (buf ) != strlen (known_sensor_luid [0 ]) + 5 ) {
832
- hid_err (hsdev -> hdev ,
833
- "%s luid length not match %zu != (%zu + 5)\n" , __func__ ,
834
- strlen (buf ), strlen (known_sensor_luid [0 ]));
835
- return - ENODEV ;
881
+ return 0 ;
882
+ }
883
+
884
+ static int
885
+ hid_sensor_custom_get_known (struct hid_sensor_hub_device * hsdev ,
886
+ const struct hid_sensor_custom_match * * known )
887
+ {
888
+ int ret ;
889
+ const struct hid_sensor_custom_match * match =
890
+ hid_sensor_custom_known_table ;
891
+ struct hid_sensor_custom_properties prop ;
892
+
893
+ ret = hid_sensor_custom_properties_get (hsdev , & prop );
894
+ if (ret < 0 )
895
+ return ret ;
896
+
897
+ while (match -> tag ) {
898
+ if (hid_sensor_custom_do_match (hsdev , match , & prop )) {
899
+ * known = match ;
900
+ return 0 ;
901
+ }
902
+ match ++ ;
836
903
}
837
904
838
- /* get table index with luid (not matching 'LUID: ' in luid) */
839
- return get_luid_table_index (& buf [5 ]);
905
+ return - ENODATA ;
840
906
}
841
907
842
908
static struct platform_device *
843
909
hid_sensor_register_platform_device (struct platform_device * pdev ,
844
910
struct hid_sensor_hub_device * hsdev ,
845
- int index )
911
+ const struct hid_sensor_custom_match * match )
846
912
{
847
- char real_usage [HID_SENSOR_USAGE_LENGTH ] = { 0 } ;
913
+ char real_usage [HID_SENSOR_USAGE_LENGTH ];
848
914
struct platform_device * custom_pdev ;
849
915
const char * dev_name ;
850
916
char * c ;
851
917
852
- /* copy real usage id */
853
- memcpy (real_usage , known_sensor_luid [index ], 4 );
918
+ memcpy (real_usage , match -> luid , 4 );
854
919
855
920
/* usage id are all lowcase */
856
921
for (c = real_usage ; * c != '\0' ; c ++ )
857
922
* c = tolower (* c );
858
923
859
- /* HID-SENSOR-INT-REAL_USAGE_ID */
860
- dev_name = kasprintf (GFP_KERNEL , "HID-SENSOR-INT-%s" , real_usage );
924
+ /* HID-SENSOR-TAG-REAL_USAGE_ID */
925
+ dev_name = kasprintf (GFP_KERNEL , "HID-SENSOR-%s-%s" ,
926
+ match -> tag , real_usage );
861
927
if (!dev_name )
862
928
return ERR_PTR (- ENOMEM );
863
929
@@ -873,7 +939,7 @@ static int hid_sensor_custom_probe(struct platform_device *pdev)
873
939
struct hid_sensor_custom * sensor_inst ;
874
940
struct hid_sensor_hub_device * hsdev = pdev -> dev .platform_data ;
875
941
int ret ;
876
- int index ;
942
+ const struct hid_sensor_custom_match * match ;
877
943
878
944
sensor_inst = devm_kzalloc (& pdev -> dev , sizeof (* sensor_inst ),
879
945
GFP_KERNEL );
@@ -888,10 +954,10 @@ static int hid_sensor_custom_probe(struct platform_device *pdev)
888
954
mutex_init (& sensor_inst -> mutex );
889
955
platform_set_drvdata (pdev , sensor_inst );
890
956
891
- index = get_known_custom_sensor_index (hsdev );
892
- if (index >= 0 && index < ARRAY_SIZE ( known_sensor_luid ) ) {
957
+ ret = hid_sensor_custom_get_known (hsdev , & match );
958
+ if (! ret ) {
893
959
sensor_inst -> custom_pdev =
894
- hid_sensor_register_platform_device (pdev , hsdev , index );
960
+ hid_sensor_register_platform_device (pdev , hsdev , match );
895
961
896
962
ret = PTR_ERR_OR_ZERO (sensor_inst -> custom_pdev );
897
963
if (ret ) {
0 commit comments