Exemple #1
0
uint8_t hci_number_outgoing_packets(hci_con_handle_t handle){
    hci_connection_t * connection = connection_for_handle(handle);
    if (!connection) {
        log_error("hci_number_outgoing_packets connectino for handle %u does not exist!\n", handle);
        return 0;
    }
    return connection->num_acl_packets_sent;
}
Exemple #2
0
int  hci_authentication_active_for_handle(hci_con_handle_t handle){
    hci_connection_t * conn = connection_for_handle(handle);
    if (!conn) return 0;
    if (!conn->authentication_flags) return 0;
    if (conn->authentication_flags & SENT_LINK_KEY_REPLY) return 0;
    if (conn->authentication_flags & RECV_LINK_KEY_NOTIFICATION) return 0;
    return 1;
}
Exemple #3
0
static void l2cap_handle_connection_request(hci_con_handle_t handle, uint8_t sig_id, uint16_t psm, uint16_t source_cid){
    
    log_info("l2cap_handle_connection_request for handle %u, psm %u cid %u\n", handle, psm, source_cid);
    l2cap_service_t *service = l2cap_get_service(psm);
    if (!service) {
        // 0x0002 PSM not supported
        l2cap_register_signaling_response(handle, CONNECTION_REQUEST, sig_id, 0x0002);
        return;
    }
    
    hci_connection_t * hci_connection = connection_for_handle( handle );
    if (!hci_connection) {
        // 
        log_error("no hci_connection for handle %u\n", handle);
        return;
    }
    // alloc structure
    // log_info("l2cap_handle_connection_request register channel\n");
    l2cap_channel_t * channel = (l2cap_channel_t*) btstack_memory_l2cap_channel_get();
    if (!channel){
        // 0x0004 No resources available
        l2cap_register_signaling_response(handle, CONNECTION_REQUEST, sig_id, 0x0004);
        return;
    }
    
    // fill in 
    BD_ADDR_COPY(channel->address, hci_connection->address);
    channel->psm = psm;
    channel->handle = handle;
    channel->connection = service->connection;
    channel->packet_handler = service->packet_handler;
    channel->local_cid  = l2cap_next_local_cid();
    channel->remote_cid = source_cid;
    channel->local_mtu  = service->mtu;
    channel->remote_mtu = L2CAP_DEFAULT_MTU;
    channel->packets_granted = 0;
    channel->remote_sig_id = sig_id; 

    // limit local mtu to max acl packet length
    if (channel->local_mtu > l2cap_max_mtu()) {
        channel->local_mtu = l2cap_max_mtu();
    }
    
    // set initial state
    channel->state = L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT;
    channel->state_var = L2CAP_CHANNEL_STATE_VAR_NONE;
    
    // add to connections list
    linked_list_add(&l2cap_channels, (linked_item_t *) channel);
    
    // emit incoming connection request
    l2cap_emit_connection_request(channel);
}
Exemple #4
0
int hci_send_acl_packet(uint8_t *packet, int size){

    // check for free places on BT module
    if (!hci_number_free_acl_slots()) return BTSTACK_ACL_BUFFERS_FULL;
    
    hci_con_handle_t con_handle = READ_ACL_CONNECTION_HANDLE(packet);
    hci_connection_t *connection = connection_for_handle( con_handle);
    if (!connection) return 0;
    hci_connection_timestamp(connection);
    
    // count packet
    connection->num_acl_packets_sent++;
    // log_info("hci_send_acl_packet - handle %u, sent %u\n", connection->con_handle, connection->num_acl_packets_sent);

    // send packet 
    int err = hci_stack.hci_transport->send_packet(HCI_ACL_DATA_PACKET, packet, size);
    
    return err;
}
Exemple #5
0
static void event_handler(uint8_t *packet, int size){
    bd_addr_t addr;
    uint8_t link_type;
    hci_con_handle_t handle;
    hci_connection_t * conn;
    int i;
        
    switch (packet[0]) {
                        
        case HCI_EVENT_COMMAND_COMPLETE:
            // get num cmd packets
            // log_info("HCI_EVENT_COMMAND_COMPLETE cmds old %u - new %u\n", hci_stack.num_cmd_packets, packet[2]);
            hci_stack.num_cmd_packets = packet[2];
            
            if (COMMAND_COMPLETE_EVENT(packet, hci_read_buffer_size)){
                // from offset 5
                // status 
                // "The HC_ACL_Data_Packet_Length return parameter will be used to determine the size of the L2CAP segments contained in ACL Data Packets"
                hci_stack.acl_data_packet_length = READ_BT_16(packet, 6);
                // ignore: SCO data packet len (8)
                hci_stack.total_num_acl_packets  = packet[9];
                // ignore: total num SCO packets
                if (hci_stack.state == HCI_STATE_INITIALIZING){
                    // determine usable ACL payload size
                    if (HCI_ACL_PAYLOAD_SIZE < hci_stack.acl_data_packet_length){
                        hci_stack.acl_data_packet_length = HCI_ACL_PAYLOAD_SIZE;
                    }
                    // determine usable ACL packet types
                    hci_stack.packet_types = hci_acl_packet_types_for_buffer_size(hci_stack.acl_data_packet_length);
                    
                    log_error("hci_read_buffer_size: used size %u, count %u, packet types %04x\n",
                             hci_stack.acl_data_packet_length, hci_stack.total_num_acl_packets, hci_stack.packet_types); 
                }
            }
            if (COMMAND_COMPLETE_EVENT(packet, hci_write_scan_enable)){
                hci_emit_discoverable_enabled(hci_stack.discoverable);
            }
            break;
            
        case HCI_EVENT_COMMAND_STATUS:
            // get num cmd packets
            // log_info("HCI_EVENT_COMMAND_STATUS cmds - old %u - new %u\n", hci_stack.num_cmd_packets, packet[3]);
            hci_stack.num_cmd_packets = packet[3];
            break;
            
        case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS:
            for (i=0; i<packet[2];i++){
                handle = READ_BT_16(packet, 3 + 2*i);
                uint16_t num_packets = READ_BT_16(packet, 3 + packet[2]*2 + 2*i);
                conn = connection_for_handle(handle);
                if (!conn){
                    log_error("hci_number_completed_packet lists unused con handle %u\n", handle);
                    continue;
                }
                conn->num_acl_packets_sent -= num_packets;
                // log_info("hci_number_completed_packet %u processed for handle %u, outstanding %u\n", num_packets, handle, conn->num_acl_packets_sent);
            }
            break;
            
        case HCI_EVENT_CONNECTION_REQUEST:
            bt_flip_addr(addr, &packet[2]);
            // TODO: eval COD 8-10
            link_type = packet[11];
            log_info("Connection_incoming: %s, type %u\n", bd_addr_to_str(addr), link_type);
            if (link_type == 1) { // ACL
                conn = connection_for_address(addr);
                if (!conn) {
                    conn = create_connection_for_addr(addr);
                }
                if (!conn) {
                    // CONNECTION REJECTED DUE TO LIMITED RESOURCES (0X0D)
                    hci_stack.decline_reason = 0x0d;
                    BD_ADDR_COPY(hci_stack.decline_addr, addr);
                    break;
                }
                conn->state = RECEIVED_CONNECTION_REQUEST;
                hci_run();
            } else {
                // SYNCHRONOUS CONNECTION LIMIT TO A DEVICE EXCEEDED (0X0A)
                hci_stack.decline_reason = 0x0a;
                BD_ADDR_COPY(hci_stack.decline_addr, addr);
            }
            break;
            
        case HCI_EVENT_CONNECTION_COMPLETE:
            // Connection management
            bt_flip_addr(addr, &packet[5]);
            log_info("Connection_complete (status=%u) %s\n", packet[2], bd_addr_to_str(addr));
            conn = connection_for_address(addr);
            if (conn) {
                if (!packet[2]){
                    conn->state = OPEN;
                    conn->con_handle = READ_BT_16(packet, 3);

#ifdef HAVE_TICK
                    // restart timer
                    run_loop_set_timer(&conn->timeout, HCI_CONNECTION_TIMEOUT_MS);
                    run_loop_add_timer(&conn->timeout);
#endif
                    
                    log_info("New connection: handle %u, %s\n", conn->con_handle, bd_addr_to_str(conn->address));
                    
                    hci_emit_nr_connections_changed();
                } else {
                    // connection failed, remove entry
                    linked_list_remove(&hci_stack.connections, (linked_item_t *) conn);
                    btstack_memory_hci_connection_free( conn );
                    
                    // if authentication error, also delete link key
                    if (packet[2] == 0x05) {
                        hci_drop_link_key_for_bd_addr(&addr);
                    }
                }
            }
            break;

        case HCI_EVENT_LINK_KEY_REQUEST:
            log_info("HCI_EVENT_LINK_KEY_REQUEST\n");
            hci_add_connection_flags_for_flipped_bd_addr(&packet[2], RECV_LINK_KEY_REQUEST);
            if (!hci_stack.remote_device_db) break;
            hci_add_connection_flags_for_flipped_bd_addr(&packet[2], HANDLE_LINK_KEY_REQUEST);
            hci_run();
            // request already answered
            return;
            
        case HCI_EVENT_LINK_KEY_NOTIFICATION:
            hci_add_connection_flags_for_flipped_bd_addr(&packet[2], RECV_LINK_KEY_NOTIFICATION);
            if (!hci_stack.remote_device_db) break;
            bt_flip_addr(addr, &packet[2]);
            hci_stack.remote_device_db->put_link_key(&addr, (link_key_t *) &packet[8]);
            // still forward event to allow dismiss of pairing dialog
            break;
            
        case HCI_EVENT_PIN_CODE_REQUEST:
            hci_add_connection_flags_for_flipped_bd_addr(&packet[2], RECV_PIN_CODE_REQUEST);
            break;
            
#ifndef EMBEDDED
        case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE:
            if (!hci_stack.remote_device_db) break;
            if (packet[2]) break; // status not ok
            bt_flip_addr(addr, &packet[3]);
            // fix for invalid remote names - terminate on 0xff
            for (i=0; i<248;i++){
                if (packet[9+i] == 0xff){
                    packet[9+i] = 0;
                    break;
                }
            }
            memset(&device_name, 0, sizeof(device_name_t));
            strncpy((char*) device_name, (char*) &packet[9], 248);
            hci_stack.remote_device_db->put_name(&addr, &device_name);
            break;
            
        case HCI_EVENT_INQUIRY_RESULT:
        case HCI_EVENT_INQUIRY_RESULT_WITH_RSSI:
            if (!hci_stack.remote_device_db) break;
            // first send inq result packet
            hci_stack.packet_handler(HCI_EVENT_PACKET, packet, size);
            // then send cached remote names
            for (i=0; i<packet[2];i++){
                bt_flip_addr(addr, &packet[3+i*6]);
                if (hci_stack.remote_device_db->get_name(&addr, &device_name)){
                    hci_emit_remote_name_cached(&addr, &device_name);
                }
            }
            return;
#endif
            
        case HCI_EVENT_DISCONNECTION_COMPLETE:
            if (!packet[2]){
                handle = READ_BT_16(packet, 3);
                hci_connection_t * conn = connection_for_handle(handle);
                if (conn) {
                    hci_shutdown_connection(conn);
                }
            }
            break;
            
        case HCI_EVENT_HARDWARE_ERROR:
            if(hci_stack.control->hw_error){
                (*hci_stack.control->hw_error)();
            }
            break;

#ifdef HAVE_BLE
        case HCI_EVENT_LE_META:
            switch (packet[2]) {
                case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
                    // Connection management
                    bt_flip_addr(addr, &packet[8]);
                    log_info("LE Connection_complete (status=%u) %s\n", packet[3], bd_addr_to_str(addr));
                    // LE connections are auto-accepted, so just create a connection if there isn't one already
                    conn = connection_for_address(addr);
                    if (packet[3]){
                        if (conn){
                            // outgoing connection failed, remove entry
                            linked_list_remove(&hci_stack.connections, (linked_item_t *) conn);
                            btstack_memory_hci_connection_free( conn );
                        }
                        // if authentication error, also delete link key
                        if (packet[3] == 0x05) {
                            hci_drop_link_key_for_bd_addr(&addr);
                        }
                        break;
                    }
                    if (!conn){
                        conn = create_connection_for_addr(addr);
                    }
                    if (!conn){
                        // no memory
                        break;
                    }

                    conn->state = OPEN;
                    conn->con_handle = READ_BT_16(packet, 4);

                    // TODO: store - role, peer address type, conn_interval, conn_latency, supervision timeout, master clock
                    // restart timer
                    // run_loop_set_timer(&conn->timeout, HCI_CONNECTION_TIMEOUT_MS);
                    // run_loop_add_timer(&conn->timeout);

                    log_info("New connection: handle %u, %s\n", conn->con_handle, bd_addr_to_str(conn->address));

                    hci_emit_nr_connections_changed();
                    break;

        default:
            break;
    }
            break;
#endif

        default:
            break;
    }

    // handle BT initialization
    if (hci_stack.state == HCI_STATE_INITIALIZING){
        // handle H4 synchronization loss on restart
        // if (hci_stack.substate == 1 && packet[0] == HCI_EVENT_HARDWARE_ERROR){
        //    hci_stack.substate = 0;
        // }
        // handle normal init sequence
        if (hci_stack.substate % 2){
            // odd: waiting for event
            if (packet[0] == HCI_EVENT_COMMAND_COMPLETE){
                hci_stack.substate++;
            }
        }
    }
    
    // help with BT sleep
    if (hci_stack.state == HCI_STATE_FALLING_ASLEEP
        && hci_stack.substate == 1
        && COMMAND_COMPLETE_EVENT(packet, hci_write_scan_enable)){
        hci_stack.substate++;
    }
    
    hci_stack.packet_handler(HCI_EVENT_PACKET, packet, size);
	
    // execute main loop
    hci_run();
}
Exemple #6
0
static void acl_handler(uint8_t *packet, int size){

    // get info
    hci_con_handle_t con_handle = READ_ACL_CONNECTION_HANDLE(packet);
    hci_connection_t *conn      = connection_for_handle(con_handle);
    uint8_t  acl_flags          = READ_ACL_FLAGS(packet);
    uint16_t acl_length         = READ_ACL_LENGTH(packet);

    // ignore non-registered handle
    if (!conn){
        log_error( "hci.c: acl_handler called with non-registered handle %u!\n" , con_handle);
        return;
    }
    
    // update idle timestamp
    hci_connection_timestamp(conn);
    
    // handle different packet types
    switch (acl_flags & 0x03) {
            
        case 0x01: // continuation fragment
            
            // sanity check
            if (conn->acl_recombination_pos == 0) {
                log_error( "ACL Cont Fragment but no first fragment for handle 0x%02x\n", con_handle);
                return;
            }
            
            // append fragment payload (header already stored)
            memcpy(&conn->acl_recombination_buffer[conn->acl_recombination_pos], &packet[4], acl_length );
            conn->acl_recombination_pos += acl_length;
            
            // log_error( "ACL Cont Fragment: acl_len %u, combined_len %u, l2cap_len %u\n", acl_length,
            //        conn->acl_recombination_pos, conn->acl_recombination_length);  
            
            // forward complete L2CAP packet if complete. 
            if (conn->acl_recombination_pos >= conn->acl_recombination_length + 4 + 4){ // pos already incl. ACL header
                
                hci_stack.packet_handler(HCI_ACL_DATA_PACKET, conn->acl_recombination_buffer, conn->acl_recombination_pos);
                // reset recombination buffer
                conn->acl_recombination_length = 0;
                conn->acl_recombination_pos = 0;
            }
            break;
            
        case 0x02: { // first fragment
            
            // sanity check
            if (conn->acl_recombination_pos) {
                log_error( "ACL First Fragment but data in buffer for handle 0x%02x\n", con_handle);
                return;
            }

            // peek into L2CAP packet!
            uint16_t l2cap_length = READ_L2CAP_LENGTH( packet );

            // log_error( "ACL First Fragment: acl_len %u, l2cap_len %u\n", acl_length, l2cap_length);

            // compare fragment size to L2CAP packet size
            if (acl_length >= l2cap_length + 4){
                
                // forward fragment as L2CAP packet
                hci_stack.packet_handler(HCI_ACL_DATA_PACKET, packet, acl_length + 4);
            
            } else {
                // store first fragment and tweak acl length for complete package
                memcpy(conn->acl_recombination_buffer, packet, acl_length + 4);
                conn->acl_recombination_pos    = acl_length + 4;
                conn->acl_recombination_length = l2cap_length;
                bt_store_16(conn->acl_recombination_buffer, 2, l2cap_length +4);
            }
            break;
            
        } 
        default:
            log_error( "hci.c: acl_handler called with invalid packet boundary flags %u\n", acl_flags & 0x03);
            return;
    }
    
    // execute main loop
    hci_run();
}