Skip to content

Commit 95118dd

Browse files
Vudentzholtmann
authored andcommitted
Bluetooth: hci_event: Use of a function table to handle LE subevents
This change the use of switch statement to a function table which is easier to extend and can include min/max length of each subevent. Signed-off-by: Luiz Augusto von Dentz <[email protected]> Signed-off-by: Marcel Holtmann <[email protected]>
1 parent 3e54c58 commit 95118dd

File tree

1 file changed

+122
-125
lines changed

1 file changed

+122
-125
lines changed

net/bluetooth/hci_event.c

Lines changed: 122 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -5969,16 +5969,12 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
59695969
hci_dev_unlock(hdev);
59705970
}
59715971

5972-
static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
5972+
static void hci_le_conn_complete_evt(struct hci_dev *hdev, void *data,
5973+
struct sk_buff *skb)
59735974
{
5974-
struct hci_ev_le_conn_complete *ev;
5975-
5976-
ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_CONN_COMPLETE,
5977-
sizeof(*ev));
5978-
if (!ev)
5979-
return;
5975+
struct hci_ev_le_conn_complete *ev = data;
59805976

5981-
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
5977+
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
59825978

59835979
le_conn_complete_evt(hdev, ev->status, &ev->bdaddr, ev->bdaddr_type,
59845980
NULL, ev->role, le16_to_cpu(ev->handle),
@@ -5987,17 +5983,12 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
59875983
le16_to_cpu(ev->supervision_timeout));
59885984
}
59895985

5990-
static void hci_le_enh_conn_complete_evt(struct hci_dev *hdev,
5986+
static void hci_le_enh_conn_complete_evt(struct hci_dev *hdev, void *data,
59915987
struct sk_buff *skb)
59925988
{
5993-
struct hci_ev_le_enh_conn_complete *ev;
5989+
struct hci_ev_le_enh_conn_complete *ev = data;
59945990

5995-
ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_ENHANCED_CONN_COMPLETE,
5996-
sizeof(*ev));
5997-
if (!ev)
5998-
return;
5999-
6000-
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
5991+
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
60015992

60025993
le_conn_complete_evt(hdev, ev->status, &ev->bdaddr, ev->bdaddr_type,
60035994
&ev->local_rpa, ev->role, le16_to_cpu(ev->handle),
@@ -6006,18 +5997,14 @@ static void hci_le_enh_conn_complete_evt(struct hci_dev *hdev,
60065997
le16_to_cpu(ev->supervision_timeout));
60075998
}
60085999

6009-
static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, struct sk_buff *skb)
6000+
static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, void *data,
6001+
struct sk_buff *skb)
60106002
{
6011-
struct hci_evt_le_ext_adv_set_term *ev;
6003+
struct hci_evt_le_ext_adv_set_term *ev = data;
60126004
struct hci_conn *conn;
60136005
struct adv_info *adv, *n;
60146006

6015-
ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_EXT_ADV_SET_TERM,
6016-
sizeof(*ev));
6017-
if (!ev)
6018-
return;
6019-
6020-
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
6007+
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
60216008

60226009
adv = hci_find_adv_instance(hdev, ev->handle);
60236010

@@ -6075,18 +6062,13 @@ static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, struct sk_buff *skb)
60756062
}
60766063
}
60776064

6078-
static void hci_le_conn_update_complete_evt(struct hci_dev *hdev,
6065+
static void hci_le_conn_update_complete_evt(struct hci_dev *hdev, void *data,
60796066
struct sk_buff *skb)
60806067
{
6081-
struct hci_ev_le_conn_update_complete *ev;
6068+
struct hci_ev_le_conn_update_complete *ev = data;
60826069
struct hci_conn *conn;
60836070

6084-
ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_CONN_UPDATE_COMPLETE,
6085-
sizeof(*ev));
6086-
if (!ev)
6087-
return;
6088-
6089-
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
6071+
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
60906072

60916073
if (ev->status)
60926074
return;
@@ -6402,14 +6384,10 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
64026384
clear_pending_adv_report(hdev);
64036385
}
64046386

6405-
static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
6387+
static void hci_le_adv_report_evt(struct hci_dev *hdev, void *data,
6388+
struct sk_buff *skb)
64066389
{
6407-
struct hci_ev_le_advertising_report *ev;
6408-
6409-
ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_ADVERTISING_REPORT,
6410-
sizeof(*ev));
6411-
if (!ev)
6412-
return;
6390+
struct hci_ev_le_advertising_report *ev = data;
64136391

64146392
if (!ev->num)
64156393
return;
@@ -6487,14 +6465,10 @@ static u8 ext_evt_type_to_legacy(struct hci_dev *hdev, u16 evt_type)
64876465
return LE_ADV_INVALID;
64886466
}
64896467

6490-
static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
6468+
static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, void *data,
6469+
struct sk_buff *skb)
64916470
{
6492-
struct hci_ev_le_ext_adv_report *ev;
6493-
6494-
ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_EXT_ADV_REPORT,
6495-
sizeof(*ev));
6496-
if (!ev)
6497-
return;
6471+
struct hci_ev_le_ext_adv_report *ev = data;
64986472

64996473
if (!ev->num)
65006474
return;
@@ -6528,18 +6502,13 @@ static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
65286502
hci_dev_unlock(hdev);
65296503
}
65306504

6531-
static void hci_le_remote_feat_complete_evt(struct hci_dev *hdev,
6505+
static void hci_le_remote_feat_complete_evt(struct hci_dev *hdev, void *data,
65326506
struct sk_buff *skb)
65336507
{
6534-
struct hci_ev_le_remote_feat_complete *ev;
6508+
struct hci_ev_le_remote_feat_complete *ev = data;
65356509
struct hci_conn *conn;
65366510

6537-
ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_EXT_ADV_REPORT,
6538-
sizeof(*ev));
6539-
if (!ev)
6540-
return;
6541-
6542-
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
6511+
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
65436512

65446513
hci_dev_lock(hdev);
65456514

@@ -6575,19 +6544,16 @@ static void hci_le_remote_feat_complete_evt(struct hci_dev *hdev,
65756544
hci_dev_unlock(hdev);
65766545
}
65776546

6578-
static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
6547+
static void hci_le_ltk_request_evt(struct hci_dev *hdev, void *data,
6548+
struct sk_buff *skb)
65796549
{
6580-
struct hci_ev_le_ltk_req *ev;
6550+
struct hci_ev_le_ltk_req *ev = data;
65816551
struct hci_cp_le_ltk_reply cp;
65826552
struct hci_cp_le_ltk_neg_reply neg;
65836553
struct hci_conn *conn;
65846554
struct smp_ltk *ltk;
65856555

6586-
ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_LTK_REQ, sizeof(*ev));
6587-
if (!ev)
6588-
return;
6589-
6590-
BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
6556+
bt_dev_dbg(hdev, "handle 0x%4.4x", __le16_to_cpu(ev->handle));
65916557

65926558
hci_dev_lock(hdev);
65936559

@@ -6655,18 +6621,15 @@ static void send_conn_param_neg_reply(struct hci_dev *hdev, u16 handle,
66556621
&cp);
66566622
}
66576623

6658-
static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev,
6624+
static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev, void *data,
66596625
struct sk_buff *skb)
66606626
{
6661-
struct hci_ev_le_remote_conn_param_req *ev;
6627+
struct hci_ev_le_remote_conn_param_req *ev = data;
66626628
struct hci_cp_le_conn_param_req_reply cp;
66636629
struct hci_conn *hcon;
66646630
u16 handle, min, max, latency, timeout;
66656631

6666-
ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_REMOTE_CONN_PARAM_REQ,
6667-
sizeof(*ev));
6668-
if (!ev)
6669-
return;
6632+
bt_dev_dbg(hdev, "handle 0x%4.4x", __le16_to_cpu(ev->handle));
66706633

66716634
handle = le16_to_cpu(ev->handle);
66726635
min = le16_to_cpu(ev->interval_min);
@@ -6718,17 +6681,12 @@ static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev,
67186681
hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_REPLY, sizeof(cp), &cp);
67196682
}
67206683

6721-
static void hci_le_direct_adv_report_evt(struct hci_dev *hdev,
6684+
static void hci_le_direct_adv_report_evt(struct hci_dev *hdev, void *data,
67226685
struct sk_buff *skb)
67236686
{
6724-
struct hci_ev_le_direct_adv_report *ev;
6687+
struct hci_ev_le_direct_adv_report *ev = data;
67256688
int i;
67266689

6727-
ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_DIRECT_ADV_REPORT,
6728-
sizeof(*ev));
6729-
if (!ev)
6730-
return;
6731-
67326690
if (!hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_DIRECT_ADV_REPORT,
67336691
flex_array_size(ev, info, ev->num)))
67346692
return;
@@ -6750,17 +6708,13 @@ static void hci_le_direct_adv_report_evt(struct hci_dev *hdev,
67506708
hci_dev_unlock(hdev);
67516709
}
67526710

6753-
static void hci_le_phy_update_evt(struct hci_dev *hdev, struct sk_buff *skb)
6711+
static void hci_le_phy_update_evt(struct hci_dev *hdev, void *data,
6712+
struct sk_buff *skb)
67546713
{
6755-
struct hci_ev_le_phy_update_complete *ev;
6714+
struct hci_ev_le_phy_update_complete *ev = data;
67566715
struct hci_conn *conn;
67576716

6758-
ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_PHY_UPDATE_COMPLETE,
6759-
sizeof(*ev));
6760-
if (ev)
6761-
return;
6762-
6763-
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
6717+
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
67646718

67656719
if (ev->status)
67666720
return;
@@ -6778,59 +6732,102 @@ static void hci_le_phy_update_evt(struct hci_dev *hdev, struct sk_buff *skb)
67786732
hci_dev_unlock(hdev);
67796733
}
67806734

6781-
static void hci_le_meta_evt(struct hci_dev *hdev, void *data,
6782-
struct sk_buff *skb)
6783-
{
6784-
struct hci_ev_le_meta *ev = data;
6785-
6786-
switch (ev->subevent) {
6787-
case HCI_EV_LE_CONN_COMPLETE:
6788-
hci_le_conn_complete_evt(hdev, skb);
6789-
break;
6790-
6791-
case HCI_EV_LE_CONN_UPDATE_COMPLETE:
6792-
hci_le_conn_update_complete_evt(hdev, skb);
6793-
break;
6735+
#define HCI_LE_EV_VL(_op, _func, _min_len, _max_len) \
6736+
[_op] = { \
6737+
.func = _func, \
6738+
.min_len = _min_len, \
6739+
.max_len = _max_len, \
6740+
}
67946741

6795-
case HCI_EV_LE_ADVERTISING_REPORT:
6796-
hci_le_adv_report_evt(hdev, skb);
6797-
break;
6742+
#define HCI_LE_EV(_op, _func, _len) \
6743+
HCI_LE_EV_VL(_op, _func, _len, _len)
67986744

6799-
case HCI_EV_LE_REMOTE_FEAT_COMPLETE:
6800-
hci_le_remote_feat_complete_evt(hdev, skb);
6801-
break;
6745+
#define HCI_LE_EV_STATUS(_op, _func) \
6746+
HCI_LE_EV(_op, _func, sizeof(struct hci_ev_status))
68026747

6803-
case HCI_EV_LE_LTK_REQ:
6804-
hci_le_ltk_request_evt(hdev, skb);
6805-
break;
6748+
/* Entries in this table shall have their position according to the subevent
6749+
* opcode they handle so the use of the macros above is recommend since it does
6750+
* attempt to initialize at its proper index using Designated Initializers that
6751+
* way events without a callback function can be ommited.
6752+
*/
6753+
static const struct hci_le_ev {
6754+
void (*func)(struct hci_dev *hdev, void *data, struct sk_buff *skb);
6755+
u16 min_len;
6756+
u16 max_len;
6757+
} hci_le_ev_table[U8_MAX + 1] = {
6758+
/* [0x01 = HCI_EV_LE_CONN_COMPLETE] */
6759+
HCI_LE_EV(HCI_EV_LE_CONN_COMPLETE, hci_le_conn_complete_evt,
6760+
sizeof(struct hci_ev_le_conn_complete)),
6761+
/* [0x02 = HCI_EV_LE_ADVERTISING_REPORT] */
6762+
HCI_LE_EV_VL(HCI_EV_LE_ADVERTISING_REPORT, hci_le_adv_report_evt,
6763+
sizeof(struct hci_ev_le_advertising_report),
6764+
HCI_MAX_EVENT_SIZE),
6765+
/* [0x03 = HCI_EV_LE_CONN_UPDATE_COMPLETE] */
6766+
HCI_LE_EV(HCI_EV_LE_CONN_UPDATE_COMPLETE,
6767+
hci_le_conn_update_complete_evt,
6768+
sizeof(struct hci_ev_le_conn_update_complete)),
6769+
/* [0x04 = HCI_EV_LE_REMOTE_FEAT_COMPLETE] */
6770+
HCI_LE_EV(HCI_EV_LE_REMOTE_FEAT_COMPLETE,
6771+
hci_le_remote_feat_complete_evt,
6772+
sizeof(struct hci_ev_le_remote_feat_complete)),
6773+
/* [0x05 = HCI_EV_LE_LTK_REQ] */
6774+
HCI_LE_EV(HCI_EV_LE_LTK_REQ, hci_le_ltk_request_evt,
6775+
sizeof(struct hci_ev_le_ltk_req)),
6776+
/* [0x06 = HCI_EV_LE_REMOTE_CONN_PARAM_REQ] */
6777+
HCI_LE_EV(HCI_EV_LE_REMOTE_CONN_PARAM_REQ,
6778+
hci_le_remote_conn_param_req_evt,
6779+
sizeof(struct hci_ev_le_remote_conn_param_req)),
6780+
/* [0x0a = HCI_EV_LE_ENHANCED_CONN_COMPLETE] */
6781+
HCI_LE_EV(HCI_EV_LE_ENHANCED_CONN_COMPLETE,
6782+
hci_le_enh_conn_complete_evt,
6783+
sizeof(struct hci_ev_le_enh_conn_complete)),
6784+
/* [0x0b = HCI_EV_LE_DIRECT_ADV_REPORT] */
6785+
HCI_LE_EV_VL(HCI_EV_LE_DIRECT_ADV_REPORT, hci_le_direct_adv_report_evt,
6786+
sizeof(struct hci_ev_le_direct_adv_report),
6787+
HCI_MAX_EVENT_SIZE),
6788+
/* [0x0c = HCI_EV_LE_PHY_UPDATE_COMPLETE] */
6789+
HCI_LE_EV(HCI_EV_LE_PHY_UPDATE_COMPLETE, hci_le_phy_update_evt,
6790+
sizeof(struct hci_ev_le_phy_update_complete)),
6791+
/* [0x0d = HCI_EV_LE_EXT_ADV_REPORT] */
6792+
HCI_LE_EV_VL(HCI_EV_LE_EXT_ADV_REPORT, hci_le_ext_adv_report_evt,
6793+
sizeof(struct hci_ev_le_ext_adv_report),
6794+
HCI_MAX_EVENT_SIZE),
6795+
/* [0x12 = HCI_EV_LE_EXT_ADV_SET_TERM] */
6796+
HCI_LE_EV(HCI_EV_LE_EXT_ADV_SET_TERM, hci_le_ext_adv_term_evt,
6797+
sizeof(struct hci_evt_le_ext_adv_set_term)),
6798+
};
68066799

6807-
case HCI_EV_LE_REMOTE_CONN_PARAM_REQ:
6808-
hci_le_remote_conn_param_req_evt(hdev, skb);
6809-
break;
6800+
static void hci_le_meta_evt(struct hci_dev *hdev, void *data,
6801+
struct sk_buff *skb)
6802+
{
6803+
struct hci_ev_le_meta *ev = data;
6804+
const struct hci_le_ev *subev;
68106805

6811-
case HCI_EV_LE_DIRECT_ADV_REPORT:
6812-
hci_le_direct_adv_report_evt(hdev, skb);
6813-
break;
6806+
bt_dev_dbg(hdev, "subevent 0x%2.2x", ev->subevent);
68146807

6815-
case HCI_EV_LE_PHY_UPDATE_COMPLETE:
6816-
hci_le_phy_update_evt(hdev, skb);
6817-
break;
6808+
subev = &hci_le_ev_table[ev->subevent];
6809+
if (!subev->func)
6810+
return;
68186811

6819-
case HCI_EV_LE_EXT_ADV_REPORT:
6820-
hci_le_ext_adv_report_evt(hdev, skb);
6821-
break;
6812+
if (skb->len < subev->min_len) {
6813+
bt_dev_err(hdev, "unexpected subevent 0x%2.2x length: %u < %u",
6814+
ev->subevent, skb->len, subev->min_len);
6815+
return;
6816+
}
68226817

6823-
case HCI_EV_LE_ENHANCED_CONN_COMPLETE:
6824-
hci_le_enh_conn_complete_evt(hdev, skb);
6825-
break;
6818+
/* Just warn if the length is over max_len size it still be
6819+
* possible to partially parse the event so leave to callback to
6820+
* decide if that is acceptable.
6821+
*/
6822+
if (skb->len > subev->max_len)
6823+
bt_dev_warn(hdev, "unexpected subevent 0x%2.2x length: %u > %u",
6824+
ev->subevent, skb->len, subev->max_len);
68266825

6827-
case HCI_EV_LE_EXT_ADV_SET_TERM:
6828-
hci_le_ext_adv_term_evt(hdev, skb);
6829-
break;
6826+
data = hci_le_ev_skb_pull(hdev, skb, ev->subevent, subev->min_len);
6827+
if (!data)
6828+
return;
68306829

6831-
default:
6832-
break;
6833-
}
6830+
subev->func(hdev, data, skb);
68346831
}
68356832

68366833
static bool hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode,

0 commit comments

Comments
 (0)