@@ -124,6 +124,7 @@ static const u16 mgmt_commands[] = {
124124 MGMT_OP_REMOVE_ADV_MONITOR ,
125125 MGMT_OP_ADD_EXT_ADV_PARAMS ,
126126 MGMT_OP_ADD_EXT_ADV_DATA ,
127+ MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI ,
127128};
128129
129130static const u16 mgmt_events [] = {
@@ -4225,87 +4226,27 @@ static int read_adv_mon_features(struct sock *sk, struct hci_dev *hdev,
42254226 return err ;
42264227}
42274228
4228- static int add_adv_patterns_monitor (struct sock * sk , struct hci_dev * hdev ,
4229- void * data , u16 len )
4229+ static int __add_adv_patterns_monitor (struct sock * sk , struct hci_dev * hdev ,
4230+ struct adv_monitor * m , u8 status , u16 op )
42304231{
4231- struct mgmt_cp_add_adv_patterns_monitor * cp = data ;
42324232 struct mgmt_rp_add_adv_patterns_monitor rp ;
4233- struct adv_monitor * m = NULL ;
4234- struct adv_pattern * p = NULL ;
4235- unsigned int mp_cnt = 0 , prev_adv_monitors_cnt ;
4236- __u8 cp_ofst = 0 , cp_len = 0 ;
4237- int err , i ;
4238-
4239- BT_DBG ("request for %s" , hdev -> name );
4240-
4241- if (len <= sizeof (* cp ) || cp -> pattern_count == 0 ) {
4242- err = mgmt_cmd_status (sk , hdev -> id ,
4243- MGMT_OP_ADD_ADV_PATTERNS_MONITOR ,
4244- MGMT_STATUS_INVALID_PARAMS );
4245- goto failed ;
4246- }
4247-
4248- m = kmalloc (sizeof (* m ), GFP_KERNEL );
4249- if (!m ) {
4250- err = - ENOMEM ;
4251- goto failed ;
4252- }
4253-
4254- INIT_LIST_HEAD (& m -> patterns );
4255- m -> active = false;
4256-
4257- for (i = 0 ; i < cp -> pattern_count ; i ++ ) {
4258- if (++ mp_cnt > HCI_MAX_ADV_MONITOR_NUM_PATTERNS ) {
4259- err = mgmt_cmd_status (sk , hdev -> id ,
4260- MGMT_OP_ADD_ADV_PATTERNS_MONITOR ,
4261- MGMT_STATUS_INVALID_PARAMS );
4262- goto failed ;
4263- }
4264-
4265- cp_ofst = cp -> patterns [i ].offset ;
4266- cp_len = cp -> patterns [i ].length ;
4267- if (cp_ofst >= HCI_MAX_AD_LENGTH ||
4268- cp_len > HCI_MAX_AD_LENGTH ||
4269- (cp_ofst + cp_len ) > HCI_MAX_AD_LENGTH ) {
4270- err = mgmt_cmd_status (sk , hdev -> id ,
4271- MGMT_OP_ADD_ADV_PATTERNS_MONITOR ,
4272- MGMT_STATUS_INVALID_PARAMS );
4273- goto failed ;
4274- }
4275-
4276- p = kmalloc (sizeof (* p ), GFP_KERNEL );
4277- if (!p ) {
4278- err = - ENOMEM ;
4279- goto failed ;
4280- }
4281-
4282- p -> ad_type = cp -> patterns [i ].ad_type ;
4283- p -> offset = cp -> patterns [i ].offset ;
4284- p -> length = cp -> patterns [i ].length ;
4285- memcpy (p -> value , cp -> patterns [i ].value , p -> length );
4286-
4287- INIT_LIST_HEAD (& p -> list );
4288- list_add (& p -> list , & m -> patterns );
4289- }
4233+ unsigned int prev_adv_monitors_cnt ;
4234+ int err ;
42904235
4291- if (mp_cnt != cp -> pattern_count ) {
4292- err = mgmt_cmd_status (sk , hdev -> id ,
4293- MGMT_OP_ADD_ADV_PATTERNS_MONITOR ,
4294- MGMT_STATUS_INVALID_PARAMS );
4236+ if (status )
42954237 goto failed ;
4296- }
42974238
42984239 hci_dev_lock (hdev );
42994240
43004241 prev_adv_monitors_cnt = hdev -> adv_monitors_cnt ;
43014242
43024243 err = hci_add_adv_monitor (hdev , m );
43034244 if (err ) {
4304- if (err == - ENOSPC ) {
4305- mgmt_cmd_status ( sk , hdev -> id ,
4306- MGMT_OP_ADD_ADV_PATTERNS_MONITOR ,
4307- MGMT_STATUS_NO_RESOURCES ) ;
4308- }
4245+ if (err == - ENOSPC )
4246+ status = MGMT_STATUS_NO_RESOURCES ;
4247+ else
4248+ status = MGMT_STATUS_FAILED ;
4249+
43094250 goto unlock ;
43104251 }
43114252
@@ -4316,15 +4257,152 @@ static int add_adv_patterns_monitor(struct sock *sk, struct hci_dev *hdev,
43164257
43174258 rp .monitor_handle = cpu_to_le16 (m -> handle );
43184259
4319- return mgmt_cmd_complete (sk , hdev -> id , MGMT_OP_ADD_ADV_PATTERNS_MONITOR ,
4260+ return mgmt_cmd_complete (sk , hdev -> id , op ,
43204261 MGMT_STATUS_SUCCESS , & rp , sizeof (rp ));
43214262
43224263unlock :
43234264 hci_dev_unlock (hdev );
43244265
43254266failed :
43264267 hci_free_adv_monitor (m );
4327- return err ;
4268+ return mgmt_cmd_status (sk , hdev -> id , op , status );
4269+ }
4270+
4271+ static void parse_adv_monitor_rssi (struct adv_monitor * m ,
4272+ struct mgmt_adv_rssi_thresholds * rssi )
4273+ {
4274+ if (rssi ) {
4275+ m -> rssi .low_threshold = rssi -> low_threshold ;
4276+ m -> rssi .low_threshold_timeout =
4277+ __le16_to_cpu (rssi -> low_threshold_timeout );
4278+ m -> rssi .high_threshold = rssi -> high_threshold ;
4279+ m -> rssi .high_threshold_timeout =
4280+ __le16_to_cpu (rssi -> high_threshold_timeout );
4281+ m -> rssi .sampling_period = rssi -> sampling_period ;
4282+ } else {
4283+ /* Default values. These numbers are the least constricting
4284+ * parameters for MSFT API to work, so it behaves as if there
4285+ * are no rssi parameter to consider. May need to be changed
4286+ * if other API are to be supported.
4287+ */
4288+ m -> rssi .low_threshold = -127 ;
4289+ m -> rssi .low_threshold_timeout = 60 ;
4290+ m -> rssi .high_threshold = -127 ;
4291+ m -> rssi .high_threshold_timeout = 0 ;
4292+ m -> rssi .sampling_period = 0 ;
4293+ }
4294+ }
4295+
4296+ static u8 parse_adv_monitor_pattern (struct adv_monitor * m , u8 pattern_count ,
4297+ struct mgmt_adv_pattern * patterns )
4298+ {
4299+ u8 offset = 0 , length = 0 ;
4300+ struct adv_pattern * p = NULL ;
4301+ unsigned int mp_cnt = 0 ;
4302+ int i ;
4303+
4304+ for (i = 0 ; i < pattern_count ; i ++ ) {
4305+ if (++ mp_cnt > HCI_MAX_ADV_MONITOR_NUM_PATTERNS )
4306+ return MGMT_STATUS_INVALID_PARAMS ;
4307+
4308+ offset = patterns [i ].offset ;
4309+ length = patterns [i ].length ;
4310+ if (offset >= HCI_MAX_AD_LENGTH ||
4311+ length > HCI_MAX_AD_LENGTH ||
4312+ (offset + length ) > HCI_MAX_AD_LENGTH )
4313+ return MGMT_STATUS_INVALID_PARAMS ;
4314+
4315+ p = kmalloc (sizeof (* p ), GFP_KERNEL );
4316+ if (!p )
4317+ return MGMT_STATUS_NO_RESOURCES ;
4318+
4319+ p -> ad_type = patterns [i ].ad_type ;
4320+ p -> offset = patterns [i ].offset ;
4321+ p -> length = patterns [i ].length ;
4322+ memcpy (p -> value , patterns [i ].value , p -> length );
4323+
4324+ INIT_LIST_HEAD (& p -> list );
4325+ list_add (& p -> list , & m -> patterns );
4326+ }
4327+
4328+ if (mp_cnt != pattern_count )
4329+ return MGMT_STATUS_INVALID_PARAMS ;
4330+
4331+ return MGMT_STATUS_SUCCESS ;
4332+ }
4333+
4334+ static int add_adv_patterns_monitor (struct sock * sk , struct hci_dev * hdev ,
4335+ void * data , u16 len )
4336+ {
4337+ struct mgmt_cp_add_adv_patterns_monitor * cp = data ;
4338+ struct adv_monitor * m = NULL ;
4339+ u8 status = MGMT_STATUS_SUCCESS ;
4340+ size_t expected_size = sizeof (* cp );
4341+
4342+ BT_DBG ("request for %s" , hdev -> name );
4343+
4344+ if (len <= sizeof (* cp )) {
4345+ status = MGMT_STATUS_INVALID_PARAMS ;
4346+ goto done ;
4347+ }
4348+
4349+ expected_size += cp -> pattern_count * sizeof (struct mgmt_adv_pattern );
4350+ if (len != expected_size ) {
4351+ status = MGMT_STATUS_INVALID_PARAMS ;
4352+ goto done ;
4353+ }
4354+
4355+ m = kzalloc (sizeof (* m ), GFP_KERNEL );
4356+ if (!m ) {
4357+ status = MGMT_STATUS_NO_RESOURCES ;
4358+ goto done ;
4359+ }
4360+
4361+ INIT_LIST_HEAD (& m -> patterns );
4362+
4363+ parse_adv_monitor_rssi (m , NULL );
4364+ status = parse_adv_monitor_pattern (m , cp -> pattern_count , cp -> patterns );
4365+
4366+ done :
4367+ return __add_adv_patterns_monitor (sk , hdev , m , status ,
4368+ MGMT_OP_ADD_ADV_PATTERNS_MONITOR );
4369+ }
4370+
4371+ static int add_adv_patterns_monitor_rssi (struct sock * sk , struct hci_dev * hdev ,
4372+ void * data , u16 len )
4373+ {
4374+ struct mgmt_cp_add_adv_patterns_monitor_rssi * cp = data ;
4375+ struct adv_monitor * m = NULL ;
4376+ u8 status = MGMT_STATUS_SUCCESS ;
4377+ size_t expected_size = sizeof (* cp );
4378+
4379+ BT_DBG ("request for %s" , hdev -> name );
4380+
4381+ if (len <= sizeof (* cp )) {
4382+ status = MGMT_STATUS_INVALID_PARAMS ;
4383+ goto done ;
4384+ }
4385+
4386+ expected_size += cp -> pattern_count * sizeof (struct mgmt_adv_pattern );
4387+ if (len != expected_size ) {
4388+ status = MGMT_STATUS_INVALID_PARAMS ;
4389+ goto done ;
4390+ }
4391+
4392+ m = kzalloc (sizeof (* m ), GFP_KERNEL );
4393+ if (!m ) {
4394+ status = MGMT_STATUS_NO_RESOURCES ;
4395+ goto done ;
4396+ }
4397+
4398+ INIT_LIST_HEAD (& m -> patterns );
4399+
4400+ parse_adv_monitor_rssi (m , & cp -> rssi );
4401+ status = parse_adv_monitor_pattern (m , cp -> pattern_count , cp -> patterns );
4402+
4403+ done :
4404+ return __add_adv_patterns_monitor (sk , hdev , m , status ,
4405+ MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI );
43284406}
43294407
43304408static int remove_adv_monitor (struct sock * sk , struct hci_dev * hdev ,
@@ -8242,6 +8320,9 @@ static const struct hci_mgmt_handler mgmt_handlers[] = {
82428320 HCI_MGMT_VAR_LEN },
82438321 { add_ext_adv_data , MGMT_ADD_EXT_ADV_DATA_SIZE ,
82448322 HCI_MGMT_VAR_LEN },
8323+ { add_adv_patterns_monitor_rssi ,
8324+ MGMT_ADD_ADV_PATTERNS_MONITOR_RSSI_SIZE ,
8325+ HCI_MGMT_VAR_LEN },
82458326};
82468327
82478328void mgmt_index_added (struct hci_dev * hdev )
0 commit comments