Skip to content

Commit b4a221e

Browse files
apusakaholtmann
authored andcommitted
Bluetooth: advmon offload MSFT add rssi support
MSFT needs rssi parameter for monitoring advertisement packet, therefore we should supply them from mgmt. This adds a new opcode to add advertisement monitor with rssi parameters. Signed-off-by: Archie Pusaka <apusaka@chromium.org> Reviewed-by: Manish Mandlik <mmandlik@chromium.org> Reviewed-by: Miao-chen Chou <mcchou@chromium.org> Reviewed-by: Yun-Hao Chung <howardchung@google.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
1 parent 7f9f2c3 commit b4a221e

File tree

3 files changed

+178
-72
lines changed

3 files changed

+178
-72
lines changed

include/net/bluetooth/hci_core.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,17 @@ struct adv_pattern {
250250
__u8 value[HCI_MAX_AD_LENGTH];
251251
};
252252

253+
struct adv_rssi_thresholds {
254+
__s8 low_threshold;
255+
__s8 high_threshold;
256+
__u16 low_threshold_timeout;
257+
__u16 high_threshold_timeout;
258+
__u8 sampling_period;
259+
};
260+
253261
struct adv_monitor {
254262
struct list_head patterns;
263+
struct adv_rssi_thresholds rssi;
255264
bool active;
256265
__u16 handle;
257266
};

include/net/bluetooth/mgmt.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,22 @@ struct mgmt_rp_add_ext_adv_data {
821821
__u8 instance;
822822
} __packed;
823823

824+
struct mgmt_adv_rssi_thresholds {
825+
__s8 high_threshold;
826+
__le16 high_threshold_timeout;
827+
__s8 low_threshold;
828+
__le16 low_threshold_timeout;
829+
__u8 sampling_period;
830+
} __packed;
831+
832+
#define MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI 0x0056
833+
struct mgmt_cp_add_adv_patterns_monitor_rssi {
834+
struct mgmt_adv_rssi_thresholds rssi;
835+
__u8 pattern_count;
836+
struct mgmt_adv_pattern patterns[];
837+
} __packed;
838+
#define MGMT_ADD_ADV_PATTERNS_MONITOR_RSSI_SIZE 8
839+
824840
#define MGMT_EV_CMD_COMPLETE 0x0001
825841
struct mgmt_ev_cmd_complete {
826842
__le16 opcode;

net/bluetooth/mgmt.c

Lines changed: 153 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -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

129130
static 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

43224263
unlock:
43234264
hci_dev_unlock(hdev);
43244265

43254266
failed:
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

43304408
static 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

82478328
void mgmt_index_added(struct hci_dev *hdev)

0 commit comments

Comments
 (0)