static pthread_mutex_t commands_pending_response_lock;
static packet_receive_data_t incoming_packets[INBOUND_PACKET_TYPE_COUNT];
+// The hand-off point for data going to a higher layer, set by the higher layer
+static fixed_queue_t *upwards_data_queue;
+
static future_t *shut_down();
static void event_finish_startup(void *context);
thread_post(thread, event_postload, NULL);
}
+static void set_data_queue(fixed_queue_t *queue) {
+ upwards_data_queue = queue;
+}
+
static void transmit_command(
BT_HDR *command,
command_complete_cb complete_callback,
}
static void fragmenter_transmit_finished(BT_HDR *packet, bool all_fragments_sent) {
- if (all_fragments_sent)
+ if (all_fragments_sent) {
buffer_allocator->free(packet);
- else
- data_dispatcher_dispatch(interface.upward_dispatcher, packet->event & MSG_EVT_MASK, packet);
+ } else {
+ // This is kind of a weird case, since we're dispatching a partially sent packet
+ // up to a higher layer.
+ // TODO(zachoverflow): rework upper layer so this isn't necessary.
+ data_dispatcher_dispatch(interface.event_dispatcher, packet->event & MSG_EVT_MASK, packet);
+ }
}
static void command_timed_out(UNUSED_ATTR void *context) {
incoming->buffer->len = incoming->index;
btsnoop->capture(incoming->buffer, true);
- if (type != DATA_TYPE_EVENT || !filter_incoming_event(incoming->buffer)) {
+ if (type != DATA_TYPE_EVENT) {
packet_fragmenter->reassemble_and_dispatch(incoming->buffer);
+ } else if (!filter_incoming_event(incoming->buffer)) {
+ // Dispatch the event by event code
+ uint8_t *stream = incoming->buffer->data;
+ uint8_t event_code;
+ STREAM_TO_UINT8(event_code, stream);
+
+ data_dispatcher_dispatch(
+ interface.event_dispatcher,
+ event_code,
+ incoming->buffer
+ );
}
// We don't control the buffer anymore
// Callback for the fragmenter to dispatch up a completely reassembled packet
static void dispatch_reassembled(BT_HDR *packet) {
- data_dispatcher_dispatch(
- interface.upward_dispatcher,
- packet->event & MSG_EVT_MASK,
- packet
- );
+ // Events should already have been dispatched before this point
+ assert((packet->event & MSG_EVT_MASK) != MSG_HC_TO_STACK_HCI_EVT);
+ assert(upwards_data_queue != NULL);
+
+ if (upwards_data_queue) {
+ fixed_queue_enqueue(upwards_data_queue, packet);
+ } else {
+ LOG_ERROR("%s had no queue to place upwards data packet in. Dropping it on the floor.", __func__);
+ buffer_allocator->free(packet);
+ }
}
// Misc internal functions
// It's probably ok for this to live forever. It's small and
// there's only one instance of the hci interface.
- interface.upward_dispatcher = data_dispatcher_new("hci_layer");
- if (!interface.upward_dispatcher) {
+ interface.event_dispatcher = data_dispatcher_new("hci_layer");
+ if (!interface.event_dispatcher) {
LOG_ERROR("%s could not create upward dispatcher.", __func__);
return;
}
+ interface.set_data_queue = set_data_queue;
interface.transmit_command = transmit_command;
interface.transmit_command_futured = transmit_command_futured;
interface.transmit_downward = transmit_downward;
return;
}
- data_dispatcher_register_default(hci->upward_dispatcher, btu_hci_msg_queue);
+ data_dispatcher_register_default(hci->event_dispatcher, btu_hci_msg_queue);
+ hci->set_data_queue(btu_hci_msg_queue);
#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
bte_load_ble_conf(BTE_BLE_STACK_CONF_FILE);
******************************************************************************/
void bte_main_shutdown()
{
- data_dispatcher_register_default(hci_layer_get_interface()->upward_dispatcher, NULL);
+ data_dispatcher_register_default(hci_layer_get_interface()->event_dispatcher, NULL);
+ hci->set_data_queue(NULL);
fixed_queue_free(btu_hci_msg_queue, NULL);
btu_hci_msg_queue = NULL;