예제 #1
0
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);
    }
}
예제 #2
0
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;
    }
}