/* LISTING_START(packetHandler): Packet Handler */ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ switch (packet_type) { case HCI_EVENT_PACKET: switch (hci_event_packet_get_type(packet)) { case SM_EVENT_JUST_WORKS_REQUEST: printf("Just Works requested\n"); sm_just_works_confirm(sm_event_just_works_request_get_handle(packet)); break; case SM_EVENT_NUMERIC_COMPARISON_REQUEST: printf("Confirming numeric comparison: %u\n", sm_event_numeric_comparison_request_get_passkey(packet)); sm_numeric_comparison_confirm(sm_event_passkey_display_number_get_handle(packet)); break; case SM_EVENT_PASSKEY_DISPLAY_NUMBER: printf("Display Passkey: %u\n", sm_event_passkey_display_number_get_passkey(packet)); break; } break; } }
static void att_event_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ UNUSED(channel); // ok: there is no channel UNUSED(size); // ok: handling own l2cap events att_server_t * att_server; hci_con_handle_t con_handle; switch (packet_type) { case HCI_EVENT_PACKET: switch (hci_event_packet_get_type(packet)) { case HCI_EVENT_LE_META: switch (packet[2]) { case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: con_handle = little_endian_read_16(packet, 4); att_server = att_server_for_handle(con_handle); if (!att_server) break; // store connection info att_server->peer_addr_type = packet[7]; reverse_bd_addr(&packet[8], att_server->peer_address); att_server->connection.con_handle = con_handle; // reset connection properties att_server->state = ATT_SERVER_IDLE; att_server->connection.mtu = ATT_DEFAULT_MTU; att_server->connection.max_mtu = l2cap_max_le_mtu(); if (att_server->connection.max_mtu > ATT_REQUEST_BUFFER_SIZE){ att_server->connection.max_mtu = ATT_REQUEST_BUFFER_SIZE; } att_server->connection.encryption_key_size = 0; att_server->connection.authenticated = 0; att_server->connection.authorized = 0; // workaround: identity resolving can already be complete, at least store result att_server->ir_le_device_db_index = sm_le_device_index(con_handle); att_server->pairing_active = 0; break; default: break; } break; case HCI_EVENT_ENCRYPTION_CHANGE: case HCI_EVENT_ENCRYPTION_KEY_REFRESH_COMPLETE: // check handle con_handle = little_endian_read_16(packet, 3); att_server = att_server_for_handle(con_handle); if (!att_server) break; att_server->connection.encryption_key_size = gap_encryption_key_size(con_handle); att_server->connection.authenticated = gap_authenticated(con_handle); if (hci_event_packet_get_type(packet) == HCI_EVENT_ENCRYPTION_CHANGE){ // restore CCC values when encrypted if (hci_event_encryption_change_get_encryption_enabled(packet)){ att_server_persistent_ccc_restore(att_server); } } break; case HCI_EVENT_DISCONNECTION_COMPLETE: // check handle con_handle = hci_event_disconnection_complete_get_connection_handle(packet); att_server = att_server_for_handle(con_handle); if (!att_server) break; att_clear_transaction_queue(&att_server->connection); att_server->connection.con_handle = 0; att_server->value_indication_handle = 0; // reset error state att_server->pairing_active = 0; att_server->state = ATT_SERVER_IDLE; break; // Identity Resolving case SM_EVENT_IDENTITY_RESOLVING_STARTED: con_handle = sm_event_identity_resolving_started_get_handle(packet); att_server = att_server_for_handle(con_handle); if (!att_server) break; log_info("SM_EVENT_IDENTITY_RESOLVING_STARTED"); att_server->ir_lookup_active = 1; break; case SM_EVENT_IDENTITY_RESOLVING_SUCCEEDED: con_handle = sm_event_identity_created_get_handle(packet); att_server = att_server_for_handle(con_handle); if (!att_server) return; att_server->ir_lookup_active = 0; att_server->ir_le_device_db_index = sm_event_identity_resolving_succeeded_get_index(packet); log_info("SM_EVENT_IDENTITY_RESOLVING_SUCCEEDED"); att_run_for_context(att_server); break; case SM_EVENT_IDENTITY_RESOLVING_FAILED: con_handle = sm_event_identity_resolving_failed_get_handle(packet); att_server = att_server_for_handle(con_handle); if (!att_server) break; log_info("SM_EVENT_IDENTITY_RESOLVING_FAILED"); att_server->ir_lookup_active = 0; att_server->ir_le_device_db_index = -1; att_run_for_context(att_server); break; // Pairing started - delete stored CCC values // - assumes pairing indicates either new device or re-pairing, in both cases there should be no stored CCC values // - assumes that all events have the con handle as the first field case SM_EVENT_JUST_WORKS_REQUEST: case SM_EVENT_PASSKEY_DISPLAY_NUMBER: case SM_EVENT_PASSKEY_INPUT_NUMBER: case SM_EVENT_NUMERIC_COMPARISON_REQUEST: con_handle = sm_event_just_works_request_get_handle(packet); att_server = att_server_for_handle(con_handle); if (!att_server) break; att_server->pairing_active = 1; log_info("SM Pairing started"); if (att_server->ir_le_device_db_index < 0) break; att_server_persistent_ccc_clear(att_server); // index not valid anymore att_server->ir_le_device_db_index = -1; break; // Bonding completed case SM_EVENT_IDENTITY_CREATED: con_handle = sm_event_identity_created_get_handle(packet); att_server = att_server_for_handle(con_handle); if (!att_server) return; att_server->pairing_active = 0; att_server->ir_le_device_db_index = sm_event_identity_created_get_index(packet); att_run_for_context(att_server); break; // Pairing complete (with/without bonding=storing of pairing information) case SM_EVENT_PAIRING_COMPLETE: con_handle = sm_event_pairing_complete_get_handle(packet); att_server = att_server_for_handle(con_handle); if (!att_server) return; att_server->pairing_active = 0; att_run_for_context(att_server); break; // Authorization case SM_EVENT_AUTHORIZATION_RESULT: { con_handle = sm_event_authorization_result_get_handle(packet); att_server = att_server_for_handle(con_handle); if (!att_server) break; att_server->connection.authorized = sm_event_authorization_result_get_authorization_result(packet); att_dispatch_server_request_can_send_now_event(con_handle); break; } default: break; } break; default: break; } }