static void att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size){ if (packet_type != ATT_DATA_PACKET) return; att_response_handle = handle; att_response_size = att_handle_request(&att_connection, packet, size, att_response_buffer); att_try_respond(); }
// enable LE, setup ADV data static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ uint8_t adv_data[] = { 02, 01, 05, 03, 02, 0xf0, 0xff }; sm_run(); switch (packet_type) { case HCI_EVENT_PACKET: switch (packet[0]) { case BTSTACK_EVENT_STATE: // bt stack activated, get started if (packet[2] == HCI_STATE_WORKING) { printf("Working!\n"); hci_send_cmd(&hci_le_set_advertising_data, sizeof(adv_data), adv_data); } break; case DAEMON_EVENT_HCI_PACKET_SENT: att_try_respond(); break; case HCI_EVENT_LE_META: switch (packet[2]) { case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: sm_response_handle = READ_BT_16(packet, 4); sm_m_addr_type = packet[7]; BD_ADDR_COPY(sm_m_address, &packet[8]); // TODO use non-null TK if appropriate sm_reset_tk(); // TODO support private addresses sm_s_addr_type = 0; BD_ADDR_COPY(sm_s_address, hci_local_bd_addr()); // request security sm_send_security_request = 1; // reset connection MTU att_connection.mtu = 23; break; case HCI_SUBEVENT_LE_LONG_TERM_KEY_REQUEST: sm_s1(sm_tk, sm_m_random, sm_m_random, sm_s_ltk); hci_send_cmd(&hci_le_long_term_key_request_reply, READ_BT_16(packet, 3), sm_s_ltk); break; default: break; } break; case HCI_EVENT_ENCRYPTION_CHANGE: // distribute keys as requested by initiator // TODO: handle initiator case here if (sm_key_distribution_set & SM_KEYDIST_ENC_KEY) sm_send_encryption_information = 1; sm_send_master_identification = 1; if (sm_key_distribution_set & SM_KEYDIST_ID_KEY) sm_send_identity_information = 1; sm_send_identity_address_information = 1; if (sm_key_distribution_set & SM_KEYDIST_SIGN) sm_send_signing_identification = 1; break; case HCI_EVENT_DISCONNECTION_COMPLETE: att_response_handle = 0; att_response_size = 0; // restart advertising hci_send_cmd(&hci_le_set_advertise_enable, 1); break; case HCI_EVENT_COMMAND_COMPLETE: if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_advertising_parameters)){ // only needed for BLE Peripheral hci_send_cmd(&hci_le_set_advertising_data, sizeof(adv_data), adv_data); break; } if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_advertising_data)){ // only needed for BLE Peripheral hci_send_cmd(&hci_le_set_scan_response_data, 10, adv_data); break; } if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_scan_response_data)){ // only needed for BLE Peripheral hci_send_cmd(&hci_le_set_advertise_enable, 1); break; } if (COMMAND_COMPLETE_EVENT(packet, hci_le_rand)){ switch (sm_state_responding){ case SM_STATE_C1_W4_RANDOM_A: memcpy(&sm_s_random[0], &packet[6], 8); hci_send_cmd(&hci_le_rand); sm_state_responding++; break; case SM_STATE_C1_W4_RANDOM_B: memcpy(&sm_s_random[8], &packet[6], 8); // calculate s_confirm sm_c1(sm_tk, sm_s_random, sm_preq, sm_pres, sm_m_addr_type, sm_s_addr_type, sm_m_address, sm_s_address, sm_s_confirm); // send data sm_state_responding = SM_STATE_C1_SEND; break; default: break; } break; } } } sm_run(); }
// enable LE, setup ADV data static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ bd_addr_t addr; uint8_t adv_data[] = { 02, 01, 05, 03, 02, 0xf0, 0xff }; switch (packet_type) { case HCI_EVENT_PACKET: switch (packet[0]) { case BTSTACK_EVENT_STATE: // bt stack activated, get started - set local name if (packet[2] == HCI_STATE_WORKING) { printf("Working!\n"); hci_send_cmd(&hci_read_local_supported_features); } break; case DAEMON_EVENT_HCI_PACKET_SENT: att_try_respond(); break; case HCI_EVENT_LE_META: switch (packet[2]) { case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: // reset connection MTU att_connection.mtu = 23; break; default: break; } break; case BTSTACK_EVENT_NR_CONNECTIONS_CHANGED: if (packet[2]) { printf("Connected.\n"); } else { printf("Not connected.\n"); } break; case HCI_EVENT_DISCONNECTION_COMPLETE: att_response_handle =0; att_response_size = 0; // restart advertising hci_send_cmd(&hci_le_set_advertise_enable, 1); break; case HCI_EVENT_COMMAND_COMPLETE: if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr)){ bt_flip_addr(addr, &packet[6]); printf("BD ADDR: %s\n", bd_addr_to_str(addr)); break; } if (COMMAND_COMPLETE_EVENT(packet, hci_read_local_supported_features)){ printf("Local supported features: %04X%04X\n", READ_BT_32(packet, 10), READ_BT_32(packet, 6)); hci_send_cmd(&hci_set_event_mask, 0xffffffff, 0x20001fff); break; } if (COMMAND_COMPLETE_EVENT(packet, hci_set_event_mask)){ hci_send_cmd(&hci_write_le_host_supported, 1, 1); break; } if (COMMAND_COMPLETE_EVENT(packet, hci_write_le_host_supported)){ hci_send_cmd(&hci_le_set_event_mask, 0xffffffff, 0xffffffff); break; } if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_event_mask)){ hci_send_cmd(&hci_le_read_buffer_size); break; } if (COMMAND_COMPLETE_EVENT(packet, hci_le_read_buffer_size)){ printf("LE buffer size: %u, count %u\n", READ_BT_16(packet,6), packet[8]); hci_send_cmd(&hci_le_read_supported_states); break; } if (COMMAND_COMPLETE_EVENT(packet, hci_le_read_supported_states)){ hci_send_cmd(&hci_le_set_advertising_parameters, 0x0400, 0x0800, 0, 0, 0, &addr, 0x07, 0); break; } if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_advertising_parameters)){ hci_send_cmd(&hci_le_set_advertising_data, sizeof(adv_data), adv_data); break; } if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_advertising_data)){ hci_send_cmd(&hci_le_set_scan_response_data, 10, adv_data); break; } if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_scan_response_data)){ hci_send_cmd(&hci_le_set_advertise_enable, 1); break; } if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_advertise_enable)){ hci_discoverable_control(1); break; } } } }