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; // handle value indication confirms if (packet[0] == ATT_HANDLE_VALUE_CONFIRMATION && att_handle_value_indication_handle){ run_loop_remove_timer(&att_handle_value_indication_timer); uint16_t att_handle = att_handle_value_indication_handle; att_handle_value_indication_handle = 0; att_handle_value_indication_notify_client(0, att_connection.con_handle, att_handle); return; } // check size if (size > sizeof(att_request_buffer)) return; // last request still in processing? if (att_server_state != ATT_SERVER_IDLE) return; // store request att_server_state = ATT_SERVER_REQUEST_RECEIVED; att_request_size = size; memcpy(att_request_buffer, packet, size); att_run(); }
static void att_signed_write_handle_cmac_result(uint8_t hash[8]){ if (att_server_state != ATT_SERVER_W4_SIGNED_WRITE_VALIDATION) return; if (memcmp(hash, &att_request_buffer[att_request_size-8], 8)){ log_info("ATT Signed Write, invalid signature"); att_server_state = ATT_SERVER_IDLE; return; } // update sequence number uint32_t counter_packet = READ_BT_32(att_request_buffer, att_request_size-12); le_device_db_remote_counter_set(att_ir_le_device_db_index, counter_packet+1); att_server_state = ATT_SERVER_REQUEST_RECEIVED_AND_VALIDATED; att_run(); }
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; // handle value indication confirms if (packet[0] == ATT_HANDLE_VALUE_CONFIRMATION && att_handle_value_indication_handle){ run_loop_remove_timer(&att_handle_value_indication_timer); uint16_t att_handle = att_handle_value_indication_handle; att_handle_value_indication_handle = 0; att_handle_value_indication_notify_client(0, att_connection.con_handle, att_handle); return; } // directly process commands // note: signed write cannot be handled directly as authentication needs to be verified if (packet[0] == ATT_WRITE_COMMAND){ att_handle_request(&att_connection, packet, size, 0); return; } // check size if (size > sizeof(att_request_buffer)) { log_info("att_packet_handler: dropping att pdu 0x%02x as size %u > att_request_buffer %u", packet[0], size, (int) sizeof(att_request_buffer)); return; } // last request still in processing? if (att_server_state != ATT_SERVER_IDLE){ log_info("att_packet_handler: skipping att pdu 0x%02x as server not idle (state %u)", packet[0], att_server_state); return; } // store request att_server_state = ATT_SERVER_REQUEST_RECEIVED; att_request_size = size; memcpy(att_request_buffer, packet, size); att_run(); }
static void att_event_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ switch (packet_type) { case HCI_EVENT_PACKET: switch (packet[0]) { case DAEMON_EVENT_HCI_PACKET_SENT: att_run(); break; case HCI_EVENT_LE_META: switch (packet[2]) { case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: // store connection info att_client_addr_type = packet[7]; bt_flip_addr(att_client_address, &packet[8]); // reset connection properties att_connection.con_handle = READ_BT_16(packet, 4); att_connection.mtu = ATT_DEFAULT_MTU; att_connection.max_mtu = l2cap_max_le_mtu(); att_connection.encryption_key_size = 0; att_connection.authenticated = 0; att_connection.authorized = 0; break; default: break; } break; case HCI_EVENT_ENCRYPTION_CHANGE: // check handle if (att_connection.con_handle != READ_BT_16(packet, 3)) break; att_connection.encryption_key_size = sm_encryption_key_size(att_client_addr_type, att_client_address); att_connection.authenticated = sm_authenticated(att_client_addr_type, att_client_address); break; case HCI_EVENT_DISCONNECTION_COMPLETE: att_clear_transaction_queue(&att_connection); att_connection.con_handle = 0; att_handle_value_indication_handle = 0; // reset error state // restart advertising if we have been connected before // -> avoid sending advertise enable a second time before command complete was received att_server_state = ATT_SERVER_IDLE; break; case SM_IDENTITY_RESOLVING_STARTED: log_info("SM_IDENTITY_RESOLVING_STARTED"); att_ir_lookup_active = 1; break; case SM_IDENTITY_RESOLVING_SUCCEEDED: att_ir_lookup_active = 0; att_ir_le_device_db_index = ((sm_event_t*) packet)->le_device_db_index; log_info("SM_IDENTITY_RESOLVING_SUCCEEDED id %u", att_ir_le_device_db_index); att_run(); break; case SM_IDENTITY_RESOLVING_FAILED: log_info("SM_IDENTITY_RESOLVING_FAILED"); att_ir_lookup_active = 0; att_ir_le_device_db_index = -1; att_run(); break; case SM_AUTHORIZATION_RESULT: { sm_event_t * event = (sm_event_t *) packet; if (event->addr_type != att_client_addr_type) break; if (memcmp(event->address, att_client_address, 6) != 0) break; att_connection.authorized = event->authorization_result; att_run(); break; } default: break; } } if (att_client_packet_handler){ att_client_packet_handler(packet_type, channel, packet, size); } }