diff --git a/nimble/transport/common/hci_h4/include/nimble/transport/hci_h4.h b/nimble/transport/common/hci_h4/include/nimble/transport/hci_h4.h index 6ad083a05f..2378d658f8 100644 --- a/nimble/transport/common/hci_h4/include/nimble/transport/hci_h4.h +++ b/nimble/transport/common/hci_h4/include/nimble/transport/hci_h4.h @@ -43,8 +43,17 @@ struct hci_h4_allocators { extern const struct hci_h4_allocators hci_h4_allocs_from_ll; extern const struct hci_h4_allocators hci_h4_allocs_from_hs; +/** Callback invoked on every frame that the H4 parser sees; it is this + * callback's responsibility to dispatch packets to the transport layer. + */ typedef int (hci_h4_frame_cb)(uint8_t pkt_type, void *data); +/** Callback invoked at the start of every packet that the H4 parser sees, + * to allow a transport to parse custom types of packets that the H4 parser + * may not otherwise understand (for instance, TI eHCILL packets). + */ +typedef uint16_t(hci_h4_packet_cb)(const uint8_t *buf, uint16_t len); + struct hci_h4_sm { uint8_t state; uint8_t pkt_type; @@ -59,12 +68,19 @@ struct hci_h4_sm { const struct hci_h4_allocators *allocs; hci_h4_frame_cb *frame_cb; + hci_h4_packet_cb *packet_cb; }; void hci_h4_sm_init(struct hci_h4_sm *h4sm, const struct hci_h4_allocators *allocs, hci_h4_frame_cb *frame_cb); +/* We do not include this in sm_init to avoid breaking the API for other + * users, but ideally if you need to call this, you will call it immediately + * once, right after sm_init. + */ +void hci_h4_sm_set_packet_cb(struct hci_h4_sm *h4sm, hci_h4_packet_cb *packet_cb); + int hci_h4_sm_rx(struct hci_h4_sm *h4sm, const uint8_t *buf, uint16_t len); #endif /* _HCI_H4_H_ */ diff --git a/nimble/transport/common/hci_h4/src/hci_h4.c b/nimble/transport/common/hci_h4/src/hci_h4.c index fd89154a34..41a29c3f01 100644 --- a/nimble/transport/common/hci_h4/src/hci_h4.c +++ b/nimble/transport/common/hci_h4/src/hci_h4.c @@ -283,6 +283,15 @@ hci_h4_sm_rx(struct hci_h4_sm *h4sm, const uint8_t *buf, uint16_t len) rc = 0; switch (h4sm->state) { case HCI_H4_SM_W4_PKT_TYPE: + if (h4sm->packet_cb) { + /* perhaps the chipset / transport driver wants to inspect + * start-of-packet and consume it on its own? */ + uint16_t consumed = h4sm->packet_cb(ib.buf, ib.len); + if (consumed) { + hci_h4_ib_consume(&ib, consumed); + continue; + } + } hci_h4_frame_start(h4sm, ib.buf[0]); hci_h4_ib_consume(&ib, 1); h4sm->state = HCI_H4_SM_W4_HEADER; @@ -337,3 +346,9 @@ hci_h4_sm_init(struct hci_h4_sm *h4sm, const struct hci_h4_allocators *allocs, h4sm->allocs = allocs; h4sm->frame_cb = frame_cb; } + +void +hci_h4_sm_set_packet_cb(struct hci_h4_sm *h4sm, hci_h4_packet_cb *packet_cb) +{ + h4sm->packet_cb = packet_cb; +}