Exemplo n.º 1
0
int l2cap_send_prepared_connectionless(uint16_t handle, uint16_t cid, uint16_t len){
    
    if (!hci_can_send_packet_now(HCI_ACL_DATA_PACKET)){
        log_info("l2cap_send_prepared_to_handle cid %u, cannot send\n", cid);
        return BTSTACK_ACL_BUFFERS_FULL;
    }
    
    log_debug("l2cap_send_prepared_to_handle cid %u, handle %u\n", cid, handle);
    
    uint8_t *acl_buffer = hci_get_outgoing_acl_packet_buffer();
    
    // 0 - Connection handle : PB=10 : BC=00 
    bt_store_16(acl_buffer, 0, handle | (2 << 12) | (0 << 14));
    // 2 - ACL length
    bt_store_16(acl_buffer, 2,  len + 4);
    // 4 - L2CAP packet length
    bt_store_16(acl_buffer, 4,  len + 0);
    // 6 - L2CAP channel DEST
    bt_store_16(acl_buffer, 6, cid);    
    // send
    int err = hci_send_acl_packet(acl_buffer, len+8);
    
    l2cap_hand_out_credits();

    return err;
}
Exemplo n.º 2
0
static void att_try_respond(void){
    if (!att_response_size) return;
    if (!att_response_handle) return;
    if (!hci_can_send_packet_now(HCI_ACL_DATA_PACKET)) return;
    
    // update state before sending packet
    uint16_t size = att_response_size;
    att_response_size = 0;
    l2cap_send_connectionless(att_response_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, att_response_buffer, size);
}
Exemplo n.º 3
0
int l2cap_send_connectionless(uint16_t handle, uint16_t cid, uint8_t *data, uint16_t len){
    
    if (!hci_can_send_packet_now(HCI_ACL_DATA_PACKET)){
        log_info("l2cap_send_internal cid %u, cannot send\n", cid);
        return BTSTACK_ACL_BUFFERS_FULL;
    }
    
    uint8_t *acl_buffer = hci_get_outgoing_acl_packet_buffer();
    
    memcpy(&acl_buffer[8], data, len);
    
    return l2cap_send_prepared_connectionless(handle, cid, len);
}
Exemplo n.º 4
0
int l2cap_send_signaling_packet(hci_con_handle_t handle, L2CAP_SIGNALING_COMMANDS cmd, uint8_t identifier, ...){

    if (!hci_can_send_packet_now(HCI_ACL_DATA_PACKET)){
        log_info("l2cap_send_signaling_packet, cannot send\n");
        return BTSTACK_ACL_BUFFERS_FULL;
    }
    
    // log_info("l2cap_send_signaling_packet type %u\n", cmd);
    uint8_t *acl_buffer = hci_get_outgoing_acl_packet_buffer();
    va_list argptr;
    va_start(argptr, identifier);
    uint16_t len = l2cap_create_signaling_internal(acl_buffer, handle, cmd, identifier, argptr);
    va_end(argptr);
    // log_info("l2cap_send_signaling_packet con %u!\n", handle);
    return hci_send_acl_packet(acl_buffer, len);
}
Exemplo n.º 5
0
int l2cap_send_prepared(uint16_t local_cid, uint16_t len){
    
    if (!hci_can_send_packet_now(HCI_ACL_DATA_PACKET)){
        log_info("l2cap_send_internal cid %u, cannot send\n", local_cid);
        return BTSTACK_ACL_BUFFERS_FULL;
    }
    
    l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid);
    if (!channel) {
        log_error("l2cap_send_internal no channel for cid %u\n", local_cid);
        return -1;   // TODO: define error
    }

    if (channel->packets_granted == 0){
        log_error("l2cap_send_internal cid %u, no credits!\n", local_cid);
        return -1;  // TODO: define error
    }
    
    --channel->packets_granted;

    log_debug("l2cap_send_internal cid %u, handle %u, 1 credit used, credits left %u;\n",
                  local_cid, channel->handle, channel->packets_granted);
    
    uint8_t *acl_buffer = hci_get_outgoing_acl_packet_buffer();

    // 0 - Connection handle : PB=10 : BC=00 
    bt_store_16(acl_buffer, 0, channel->handle | (2 << 12) | (0 << 14));
    // 2 - ACL length
    bt_store_16(acl_buffer, 2,  len + 4);
    // 4 - L2CAP packet length
    bt_store_16(acl_buffer, 4,  len + 0);
    // 6 - L2CAP channel DEST
    bt_store_16(acl_buffer, 6, channel->remote_cid);    
    // send
    int err = hci_send_acl_packet(acl_buffer, len+8);
    
    l2cap_hand_out_credits();
    
    return err;
}
Exemplo n.º 6
0
Arquivo: hci.c Projeto: ajsb85/ioio
void hci_run(){
        
    hci_connection_t * connection;
    linked_item_t * it;
    
    if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;

    // global/non-connection oriented commands
    
    // decline incoming connections
    if (hci_stack.decline_reason){
        uint8_t reason = hci_stack.decline_reason;
        hci_stack.decline_reason = 0;
        hci_send_cmd(&hci_reject_connection_request, hci_stack.decline_addr, reason);
    }

    if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;

    // send scan enable
    if (hci_stack.new_scan_enable_value != 0xff){
        hci_send_cmd(&hci_write_scan_enable, hci_stack.new_scan_enable_value);
        hci_stack.new_scan_enable_value = 0xff;
    }
    
    // send pending HCI commands
    for (it = (linked_item_t *) hci_stack.connections; it ; it = it->next){

        if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;

        connection = (hci_connection_t *) it;
        
        if (connection->state == RECEIVED_CONNECTION_REQUEST){
            log_info("sending hci_accept_connection_request\n");
            hci_send_cmd(&hci_accept_connection_request, connection->address, 1);
            connection->state = ACCEPTED_CONNECTION_REQUEST;
        }

        if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;
        
        if (connection->authentication_flags & HANDLE_LINK_KEY_REQUEST){
            link_key_t link_key;
            log_info("responding to link key request\n");
            if ( hci_stack.remote_device_db->get_link_key( &connection->address, &link_key)){
               hci_send_cmd(&hci_link_key_request_reply, connection->address, &link_key);
            } else {
               hci_send_cmd(&hci_link_key_request_negative_reply, connection->address);
            }
            connection->authentication_flags &= ~HANDLE_LINK_KEY_REQUEST;
        }
    }

    if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;
        
    switch (hci_stack.state){
        case HCI_STATE_INITIALIZING:
            // log_info("hci_init: substate %u\n", hci_stack.substate);
            if (hci_stack.substate % 2) {
                // odd: waiting for command completion
                return;
            }
            switch (hci_stack.substate >> 1){
                case 0: // RESET
                    hci_send_cmd(&hci_reset);
                    if (hci_stack.config == 0 || ((hci_uart_config_t *)hci_stack.config)->baudrate_main == 0){
                        // skip baud change
                        hci_stack.substate = 4; // >> 1 = 2
                    }
                    break;
                case 1: // SEND BAUD CHANGE
                    hci_stack.control->baudrate_cmd(hci_stack.config, ((hci_uart_config_t *)hci_stack.config)->baudrate_main, hci_stack.hci_packet_buffer);
                    hci_send_cmd_packet(hci_stack.hci_packet_buffer, 3 + hci_stack.hci_packet_buffer[2]);
                    break;
                case 2: // LOCAL BAUD CHANGE
                    hci_stack.hci_transport->set_baudrate(((hci_uart_config_t *)hci_stack.config)->baudrate_main);
                    hci_stack.substate += 2;
                    // break missing here for fall through
                    
                case 3:
                    // custom initialization
                    if (hci_stack.control && hci_stack.control->next_cmd){
                        int valid_cmd = (*hci_stack.control->next_cmd)(hci_stack.config, hci_stack.hci_packet_buffer);
                        if (valid_cmd){
                            int size = 3 + hci_stack.hci_packet_buffer[2];
                            hci_stack.hci_transport->send_packet(HCI_COMMAND_DATA_PACKET, hci_stack.hci_packet_buffer, size);
                            hci_stack.substate = 4; // more init commands
                            break;
                        }
                        log_info("hci_run: init script done\n\r");
                    }
                    // otherwise continue
                    hci_send_cmd(&hci_read_bd_addr);
                    break;
                case 4:
                    hci_send_cmd(&hci_read_buffer_size);
                    break;
                case 5:
                    // ca. 15 sec
                    hci_send_cmd(&hci_write_page_timeout, 0x6000);
                    break;
                case 6:
                    hci_send_cmd(&hci_write_scan_enable, 2 | hci_stack.discoverable); // page scan
                    break;
                case 7:
#ifndef EMBEDDED
                {
                    char hostname[30];
                    gethostname(hostname, 30);
                    hostname[29] = '\0';
                    hci_send_cmd(&hci_write_local_name, hostname);
                    break;
                }
                case 8:
#ifdef USE_BLUETOOL
                    hci_send_cmd(&hci_write_class_of_device, 0x007a020c); // Smartphone
                    break;
                    
                case 9:
#endif
#endif
                    // done.
                    hci_stack.state = HCI_STATE_WORKING;
                    hci_emit_state();
                    break;
                default:
                    break;
            }
            hci_stack.substate++;
            break;
            
        case HCI_STATE_HALTING:

            log_info("HCI_STATE_HALTING\n");
            // close all open connections
            connection =  (hci_connection_t *) hci_stack.connections;
            if (connection){
                
                // send disconnect
                if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;
                
                log_info("HCI_STATE_HALTING, connection %p, handle %u\n", connection, (uint16_t)connection->con_handle);
                hci_send_cmd(&hci_disconnect, connection->con_handle, 0x13);  // remote closed connection

                // send disconnected event right away - causes higher layer connections to get closed, too.
                hci_shutdown_connection(connection);
                return;
            }
            log_info("HCI_STATE_HALTING, calling off\n");
            
            // switch mode
            hci_power_control_off();
            
            log_info("HCI_STATE_HALTING, emitting state\n");
            hci_emit_state();
            log_info("HCI_STATE_HALTING, done\n");
            break;
            
        case HCI_STATE_FALLING_ASLEEP:
            switch(hci_stack.substate) {
                case 0:
                    log_info("HCI_STATE_FALLING_ASLEEP\n");
                    // close all open connections
                    connection =  (hci_connection_t *) hci_stack.connections;

#if defined(USE_POWERMANAGEMENT) && defined(USE_BLUETOOL)
                    // don't close connections, if H4 supports power management
                    if (bt_control_iphone_power_management_enabled()){
                        connection = NULL;
                    }
#endif
                    if (connection){
                        
                        // send disconnect
                        if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;

                        log_info("HCI_STATE_FALLING_ASLEEP, connection %p, handle %u\n", connection, (uint16_t)connection->con_handle);
                        hci_send_cmd(&hci_disconnect, connection->con_handle, 0x13);  // remote closed connection
                        
                        // send disconnected event right away - causes higher layer connections to get closed, too.
                        hci_shutdown_connection(connection);
                        return;
                    }
                    
                    // disable page and inquiry scan
                    if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;
                    
                    log_info("HCI_STATE_HALTING, disabling inq & page scans\n");
                    hci_send_cmd(&hci_write_scan_enable, 0); // none
                    
                    // continue in next sub state
                    hci_stack.substate++;
                    break;
                case 1:
                    // wait for command complete "hci_write_scan_enable" in event_handler();
                    break;
                case 2:
                    log_info("HCI_STATE_HALTING, calling sleep\n");
#if defined(USE_POWERMANAGEMENT) && defined(USE_BLUETOOL)
                    // don't actually go to sleep, if H4 supports power management
                    if (bt_control_iphone_power_management_enabled()){
                        // SLEEP MODE reached
                        hci_stack.state = HCI_STATE_SLEEPING; 
                        hci_emit_state();
                        break;
                    }
#endif
                    // switch mode
                    hci_power_control_sleep();  // changes hci_stack.state to SLEEP
                    hci_emit_state();
                    break;
                    
                default:
                    break;
            }
            break;
            
        default:
            break;
    }
}
Exemplo n.º 7
0
void l2cap_event_handler( uint8_t *packet, uint16_t size ){
    
    bd_addr_t address;
    hci_con_handle_t handle;
    l2cap_channel_t * channel;
    linked_item_t *it;
    int hci_con_used;
    
    switch(packet[0]){
            
        // handle connection complete events
        case HCI_EVENT_CONNECTION_COMPLETE:
            bt_flip_addr(address, &packet[5]);
            if (packet[2] == 0){
                handle = READ_BT_16(packet, 3);
                l2cap_handle_connection_success_for_addr(address, handle);
            } else {
                l2cap_handle_connection_failed_for_addr(address, packet[2]);
            }
            break;
            
        // handle successful create connection cancel command
        case HCI_EVENT_COMMAND_COMPLETE:
            if ( COMMAND_COMPLETE_EVENT(packet, hci_create_connection_cancel) ) {
                if (packet[5] == 0){
                    bt_flip_addr(address, &packet[6]);
                    // CONNECTION TERMINATED BY LOCAL HOST (0X16)
                    l2cap_handle_connection_failed_for_addr(address, 0x16);
                }
            }
            l2cap_run();    // try sending signaling packets first
            break;
            
        case HCI_EVENT_COMMAND_STATUS:
            l2cap_run();    // try sending signaling packets first
            break;
            
        // handle disconnection complete events
        case HCI_EVENT_DISCONNECTION_COMPLETE:
            // send l2cap disconnect events for all channels on this handle
            handle = READ_BT_16(packet, 3);
            it = (linked_item_t *) &l2cap_channels;
            while (it->next){
                l2cap_channel_t * channel = (l2cap_channel_t *) it->next;
                if ( channel->handle == handle ){
                    // update prev item before free'ing next element - don't call l2cap_finalize_channel_close
                    it->next = it->next->next;
                    l2cap_emit_channel_closed(channel);
                    btstack_memory_l2cap_channel_free(channel);
                } else {
                    it = it->next;
                }
            }
            break;
            
        case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS:
            l2cap_run();    // try sending signaling packets first
            l2cap_hand_out_credits();
            break;
            
        // HCI Connection Timeouts
        case L2CAP_EVENT_TIMEOUT_CHECK:
            handle = READ_BT_16(packet, 2);
            if (hci_authentication_active_for_handle(handle)) break;
            hci_con_used = 0;
            for (it = (linked_item_t *) l2cap_channels; it ; it = it->next){
                channel = (l2cap_channel_t *) it;
                if (channel->handle == handle) {
                    hci_con_used = 1;
                }
            }
            if (hci_con_used) break;
            if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) break;
            hci_send_cmd(&hci_disconnect, handle, 0x13); // remote closed connection             
            break;

        case DAEMON_EVENT_HCI_PACKET_SENT:
            for (it = (linked_item_t *) l2cap_channels; it ; it = it->next){
                channel = (l2cap_channel_t *) it;
                if (channel->packet_handler) {
                    (* (channel->packet_handler))(HCI_EVENT_PACKET, channel->local_cid, packet, size);
                } 
            }
            if (attribute_protocol_packet_handler) {
                (*attribute_protocol_packet_handler)(HCI_EVENT_PACKET, 0, packet, size);
            }
            if (security_protocol_packet_handler) {
                (*security_protocol_packet_handler)(HCI_EVENT_PACKET, 0, packet, size);
            }
            break;
            
        default:
            break;
    }
    
    // pass on
    (*packet_handler)(NULL, HCI_EVENT_PACKET, 0, packet, size);
}
Exemplo n.º 8
0
// MARK: L2CAP_RUN
// process outstanding signaling tasks
void l2cap_run(void){
    
    // check pending signaling responses
    while (signaling_responses_pending){
        
        if (!hci_can_send_packet_now(HCI_ACL_DATA_PACKET)) break;
        
        hci_con_handle_t handle = signaling_responses[0].handle;
        uint8_t sig_id = signaling_responses[0].sig_id;
        uint16_t infoType = signaling_responses[0].data;    // INFORMATION_REQUEST
        uint16_t result   = signaling_responses[0].data;    // CONNECTION_REQUEST
        
        switch (signaling_responses[0].code){
            case CONNECTION_REQUEST:
                l2cap_send_signaling_packet(handle, CONNECTION_RESPONSE, sig_id, 0, 0, result, 0);
                break;
            case ECHO_REQUEST:
                l2cap_send_signaling_packet(handle, ECHO_RESPONSE, sig_id, 0, NULL);
                break;
            case INFORMATION_REQUEST:
                if (infoType == 2) {
                    uint32_t features = 0;
                    // extended features request supported, however no features present
                    l2cap_send_signaling_packet(handle, INFORMATION_RESPONSE, sig_id, infoType, 0, 4, &features);
                } else {
                    // all other types are not supported
                    l2cap_send_signaling_packet(handle, INFORMATION_RESPONSE, sig_id, infoType, 1, 0, NULL);
                }
                break;
            default:
                // should not happen
                break;
        }
        
        // remove first item
        signaling_responses_pending--;
        int i;
        for (i=0; i < signaling_responses_pending; i++){
            memcpy(&signaling_responses[i], &signaling_responses[i+1], sizeof(l2cap_signaling_response_t));
        }
    }
    
    uint8_t  config_options[4];
    linked_item_t *it;
    linked_item_t *next;
    for (it = (linked_item_t *) l2cap_channels; it ; it = next){
        next = it->next;    // cache next item as current item might get freed

        if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) break;
        if (!hci_can_send_packet_now(HCI_ACL_DATA_PACKET)) break;
        
        l2cap_channel_t * channel = (l2cap_channel_t *) it;
        
        // log_info("l2cap_run: state %u, var 0x%02x\n", channel->state, channel->state_var);
        
        
        switch (channel->state){

            case L2CAP_STATE_WILL_SEND_CREATE_CONNECTION:
                // send connection request - set state first
                channel->state = L2CAP_STATE_WAIT_CONNECTION_COMPLETE;
                // BD_ADDR, Packet_Type, Page_Scan_Repetition_Mode, Reserved, Clock_Offset, Allow_Role_Switch
                hci_send_cmd(&hci_create_connection, channel->address, hci_usable_acl_packet_types(), 0, 0, 0, 1); 
                break;
                
            case L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_DECLINE:
                l2cap_send_signaling_packet(channel->handle, CONNECTION_RESPONSE, channel->remote_sig_id, 0, 0, channel->reason, 0);
                // discard channel - l2cap_finialize_channel_close without sending l2cap close event
                linked_list_remove(&l2cap_channels, (linked_item_t *) channel); // -- remove from list
                btstack_memory_l2cap_channel_free(channel); 
                break;
                
            case L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_ACCEPT:
                channel->state = L2CAP_STATE_CONFIG;
                channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_REQ);
                l2cap_send_signaling_packet(channel->handle, CONNECTION_RESPONSE, channel->remote_sig_id, channel->local_cid, channel->remote_cid, 0, 0);
                break;
                
            case L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST:
                // success, start l2cap handshake
                channel->local_sig_id = l2cap_next_sig_id();
                channel->state = L2CAP_STATE_WAIT_CONNECT_RSP;
                l2cap_send_signaling_packet( channel->handle, CONNECTION_REQUEST, channel->local_sig_id, channel->psm, channel->local_cid);                   
                break;
            
            case L2CAP_STATE_CONFIG:
                if (channel->state_var & L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP){
                    channelStateVarClearFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_RSP);
                    channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SENT_CONF_RSP);
                    l2cap_send_signaling_packet(channel->handle, CONFIGURE_RESPONSE, channel->remote_sig_id, channel->remote_cid, 0, 0, 0, NULL);
                }
                else if (channel->state_var & L2CAP_CHANNEL_STATE_VAR_SEND_CONF_REQ){
                    channelStateVarClearFlag(channel, L2CAP_CHANNEL_STATE_VAR_SEND_CONF_REQ);
                    channelStateVarSetFlag(channel, L2CAP_CHANNEL_STATE_VAR_SENT_CONF_REQ);
                    channel->local_sig_id = l2cap_next_sig_id();
                    config_options[0] = 1; // MTU
                    config_options[1] = 2; // len param
                    bt_store_16( (uint8_t*)&config_options, 2, channel->local_mtu);
                    l2cap_send_signaling_packet(channel->handle, CONFIGURE_REQUEST, channel->local_sig_id, channel->remote_cid, 0, 4, &config_options);
                }
                if (l2cap_channel_ready_for_open(channel)){
                    channel->state = L2CAP_STATE_OPEN;
                    l2cap_emit_channel_opened(channel, 0);  // success
                    l2cap_emit_credits(channel, 1);
                }
                break;

            case L2CAP_STATE_WILL_SEND_DISCONNECT_RESPONSE:
                l2cap_send_signaling_packet( channel->handle, DISCONNECTION_RESPONSE, channel->remote_sig_id, channel->local_cid, channel->remote_cid);   
                l2cap_finialize_channel_close(channel);  // -- remove from list
                break;
                
            case L2CAP_STATE_WILL_SEND_DISCONNECT_REQUEST:
                channel->local_sig_id = l2cap_next_sig_id();
                channel->state = L2CAP_STATE_WAIT_DISCONNECT;
                l2cap_send_signaling_packet( channel->handle, DISCONNECTION_REQUEST, channel->local_sig_id, channel->remote_cid, channel->local_cid);   
                break;
            default:
                break;
        }
    }
}
Exemplo n.º 9
0
int  l2cap_can_send_packet_now(uint16_t local_cid){
    l2cap_channel_t *channel = l2cap_get_channel_for_local_cid(local_cid);
    if (!channel) return 0;
    if (!channel->packets_granted) return 0;
    return hci_can_send_packet_now(HCI_ACL_DATA_PACKET);
}
Exemplo n.º 10
0
static void sm_run(void){

    // assert that we can send either one
    if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;
    if (!hci_can_send_packet_now(HCI_ACL_DATA_PACKET)) return;

    switch (sm_state_responding){
        case SM_STATE_C1_GET_RANDOM_A:
        case SM_STATE_C1_GET_RANDOM_B:
            hci_send_cmd(&hci_le_rand);
            sm_state_responding++;
            return;
        case SM_STATE_C1_GET_ENC_A:
        case SM_STATE_C1_GET_ENC_B:
            break;
        case SM_STATE_C1_SEND: {
            uint8_t buffer[17];
            buffer[0] = SM_CODE_PAIRING_CONFIRM;
            memcpy(&buffer[1], sm_s_confirm, 16);
            l2cap_send_connectionless(sm_response_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer));
            sm_state_responding = SM_STATE_IDLE;
            return;
        }
        default:
            break;
    }

    // send security manager packet
    if (sm_response_size){
        uint16_t size = sm_response_size;
        sm_response_size = 0;
        l2cap_send_connectionless(sm_response_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) sm_response_buffer, size);
    }
    // send security request
    if (sm_send_security_request){
        sm_send_security_request = 0;
        uint8_t buffer[2];
        buffer[0] = SM_CODE_SECURITY_REQUEST;
        buffer[1] = SM_AUTHREQ_BONDING;
        l2cap_send_connectionless(sm_response_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer));
        return;
    }
    if (sm_send_encryption_information){
        sm_send_encryption_information = 0;
        uint8_t buffer[17];
        buffer[0] = SM_CODE_ENCRYPTION_INFORMATION;
        memcpy(&buffer[1], sm_s_ltk, 16);
        l2cap_send_connectionless(sm_response_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer));
        return;
    }
    if (sm_send_master_identification){
        sm_send_master_identification = 0;
        uint8_t buffer[11];
        buffer[0] = SM_CODE_MASTER_IDENTIFICATION;
        bt_store_16(buffer, 1, sm_s_ediv);
        memcpy(&buffer[3],sm_s_rand,8); 
        l2cap_send_connectionless(sm_response_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer));
        return;
    }
    if (sm_send_identity_information){
        sm_send_identity_information = 0;
        uint8_t buffer[17];
        buffer[0] = SM_CODE_IDENTITY_INFORMATION;
        memcpy(&buffer[1], sm_s_irk, 16);
        l2cap_send_connectionless(sm_response_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer));
        return;
    }
    if (sm_send_identity_address_information ){
        sm_send_identity_address_information = 0;
        uint8_t buffer[8];
        buffer[0] = SM_CODE_IDENTITY_ADDRESS_INFORMATION;
        buffer[1] = sm_s_addr_type;
        BD_ADDR_COPY(&buffer[2], sm_s_address);
        l2cap_send_connectionless(sm_response_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer));
        return;
    }
    if (sm_send_signing_identification){
        sm_send_signing_identification = 0;
        uint8_t buffer[17];
        buffer[0] = SM_CODE_SIGNING_INFORMATION;
        memcpy(&buffer[1], sm_s_csrk, 16);
        l2cap_send_connectionless(sm_response_handle, L2CAP_CID_SECURITY_MANAGER_PROTOCOL, (uint8_t*) buffer, sizeof(buffer));
        return;
    }
}
Exemplo n.º 11
0
static void gap_run(){
    // make sure we can send one packet
    if (todos == 0 || !hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;

    printf("todo %x\n", todos);
    if (todos & DISABLE_ADVERTISEMENTS){
        todos &= ~DISABLE_ADVERTISEMENTS;
        advertisements_enabled = 0;
        printf("GAP_RUN: disable advertisements\n");
        hci_send_cmd(&hci_le_set_advertise_enable, 0);
        return;
    }

    if (todos & SET_ADVERTISEMENT_DATA){
        todos &= ~SET_ADVERTISEMENT_DATA;
        
        uint8_t adv_data[] = { 
            2, 0x1, 0x2,
            3, 0x03, 0xf0, 0xff,
            14, 0x09, 'M','e', 't', 'e', 'o', 'r', 'L', 'E', ' ', 'X','X','X','X','\0'
        };

        const char* addr = (const char*)system_getserial();
        sprintf((char*)&adv_data[18], "%02X%02X", addr[4], addr[5]);
        printf("GAP_RUN: set advertisement data\n");
        hexdump(adv_data, sizeof(adv_data));
        hci_send_cmd(&hci_le_set_advertising_data, sizeof(adv_data) - 1, adv_data);
        return;
    }    

    if (todos & SET_ADVERTISEMENT_PARAMS){
        todos &= ~SET_ADVERTISEMENT_PARAMS;
        uint8_t adv_type;
        if (advertisements_enabled)
            adv_type = 0x00;
        else
            adv_type = 0x02;
        bd_addr_t null_addr;
        memset(null_addr, 0, 6);
        uint16_t adv_int_min = 0x808;
        uint16_t adv_int_max = 0x808;
        switch (adv_type){
            case 0:
            case 2:
            case 3:
                hci_send_cmd(&hci_le_set_advertising_parameters, adv_int_min, adv_int_max, adv_type, 0, 0, &null_addr, 0x07, 0x00);
                break;
        }
        return;
    }    

    if (todos & SET_SCAN_RESPONSE_DATA){
        uint8_t scan_data[] = {
            2, 0x1, 0x2,
            2, 0x11, 3,
            17, 0x15, 0xD0, 0x00, 0x2D, 0x12, 0x1E, 0x4B, 0x0F, 0xA4, 0x99, 0x4E, 0xCE, 0xB5, 0x31, 0xF4, 0x05, 0x79
        };

        printf("GAP_RUN: set scan response data\n");
        todos &= ~SET_SCAN_RESPONSE_DATA;

        hci_send_cmd(&hci_le_set_scan_response_data, sizeof(scan_data), scan_data);
        return;
    }    

    if (todos & ENABLE_ADVERTISEMENTS){
        printf("GAP_RUN: enable advertisements\n");
        todos &= ~ENABLE_ADVERTISEMENTS;
        advertisements_enabled = 1;
        hci_send_cmd(&hci_le_set_advertise_enable, 1);
        return;
    }
}