示例#1
0
int ad_data_contains_uuid16(uint8_t ad_len, uint8_t * ad_data, uint16_t uuid16){
    ad_context_t context;
    for (ad_iterator_init(&context, ad_len, ad_data) ; ad_iterator_has_more(&context) ; ad_iterator_next(&context)){
        uint8_t data_type = ad_iterator_get_data_type(&context);
        uint8_t data_len  = ad_iterator_get_data_len(&context);
        uint8_t * data    = ad_iterator_get_data(&context);
        
        int i;
        uint8_t ad_uuid128[16], uuid128_bt[16];
                
        switch (data_type){
            case IncompleteList16:
            case CompleteList16:
                for (i=0; i<data_len; i+=2){
                    uint16_t uuid = little_endian_read_16(data, i);
                    if ( uuid == uuid16 ) return 1;
                }
                break;
            case IncompleteList128:
            case CompleteList128:
                uuid_add_bluetooth_prefix(ad_uuid128, uuid16);
                reverse_128(ad_uuid128, uuid128_bt);
            
                for (i=0; i<data_len; i+=16){
                    if (memcmp(uuid128_bt, &data[i], 16) == 0) return 1;
                }
                break;
            default:
                break;
        }  
    }
    return 0;
}
示例#2
0
static btstack_chipset_result_t chipset_next_command(uint8_t * hci_cmd_buffer){

    if (init_script_offset >= init_script_size) {
        return BTSTACK_CHIPSET_DONE;
    }

    // init script is stored with the HCI Command Packet Type
    init_script_offset++;
    // copy command header
    memcpy(&hci_cmd_buffer[0], (uint8_t *) &init_script[init_script_offset], 3); 
    init_script_offset += 3;
    int payload_len = hci_cmd_buffer[2];
    // copy command payload
    memcpy(&hci_cmd_buffer[3], (uint8_t *) &init_script[init_script_offset], payload_len);

    // support for on-the-fly configuration updates
    update_init_script_command(hci_cmd_buffer);

    init_script_offset += payload_len;

    // support for warm boot command
    uint16_t varid = little_endian_read_16(hci_cmd_buffer, 10);
    if (varid == 0x4002){
        return BTSTACK_CHIPSET_WARMSTART_REQUIRED;
    }

    return BTSTACK_CHIPSET_VALID_COMMAND; 
}
示例#3
0
static void h4_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type) {
    if (hci_transport_h4->ds->fd == 0) return;

    // read up to bytes_to_read data in
    ssize_t bytes_read = mtk_bt_read(hci_transport_h4->ds->fd, &hci_packet_in[0], sizeof(hci_packet_in));

    if (bytes_read == 0) return;

    // iterate over packets
    uint16_t pos = 0;
    while (pos < bytes_read) {
        uint16_t packet_len;
        switch(hci_packet_in[pos]){
            case HCI_EVENT_PACKET:
                packet_len = hci_packet_in[pos+2] + 3;
                break;
            case HCI_ACL_DATA_PACKET:
                 packet_len = little_endian_read_16(hci_packet_in, pos + 3) + 5;
                 break;
            default:
                log_error("h4_process: invalid packet type 0x%02x\n", hci_packet_in[pos]);
                return;
        }

        packet_handler(hci_packet_in[pos], &hci_packet_in[pos+1], packet_len-1);
        pos += packet_len;
    }
}
示例#4
0
static void ancs_chunk_parser_handle_byte(uint8_t data){
    ancs_notification_buffer[ancs_bytes_received++] = data;
    if (ancs_bytes_received < ancs_bytes_needed) return;
    switch (chunk_parser_state){
        case W4_ATTRIBUTE_ID:
            ancs_attribute_id   = ancs_notification_buffer[ancs_bytes_received-1];
            ancs_bytes_received = 0;
            ancs_bytes_needed   = 2;
            chunk_parser_state  = W4_ATTRIBUTE_LEN;
            break;
        case W4_ATTRIBUTE_LEN:
            ancs_attribute_len  = little_endian_read_16(ancs_notification_buffer, ancs_bytes_received-2);
            ancs_bytes_received = 0;
            ancs_bytes_needed   = ancs_attribute_len;
            if (ancs_attribute_len == 0) {
                ancs_bytes_needed   = 1;
                chunk_parser_state  = W4_ATTRIBUTE_ID;
                break;
            }
            chunk_parser_state  = W4_ATTRIBUTE_COMPLETE;
            break;
        case W4_ATTRIBUTE_COMPLETE:
            ancs_notification_buffer[ancs_bytes_received] = 0;
            notify_client_text(ANCS_SUBEVENT_CLIENT_NOTIFICATION);
            ancs_bytes_received = 0;
            ancs_bytes_needed   = 1;
            chunk_parser_state  = W4_ATTRIBUTE_ID;
            break;
    }
}
示例#5
0
int ad_data_contains_uuid16(uint8_t ad_len, const uint8_t * ad_data, uint16_t uuid16){
    ad_context_t context;
    for (ad_iterator_init(&context, ad_len, ad_data) ; ad_iterator_has_more(&context) ; ad_iterator_next(&context)){
        uint8_t data_type    = ad_iterator_get_data_type(&context);
        uint8_t data_len     = ad_iterator_get_data_len(&context);
        const uint8_t * data = ad_iterator_get_data(&context);
        
        int i;
        uint8_t ad_uuid128[16], uuid128_bt[16];
                
        switch (data_type){
            case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS:
            case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS:
                for (i=0; i<data_len; i+=2){
                    uint16_t uuid = little_endian_read_16(data, i);
                    if ( uuid == uuid16 ) return 1;
                }
                break;
            case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS:
            case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS:
                uuid_add_bluetooth_prefix(ad_uuid128, uuid16);
                reverse_128(ad_uuid128, uuid128_bt);
            
                for (i=0; i<data_len; i+=16){
                    if (memcmp(uuid128_bt, &data[i], 16) == 0) return 1;
                }
                break;
            default:
                break;
        }  
    }
    return 0;
}
示例#6
0
static void att_run_for_context(att_server_t * att_server){
    switch (att_server->state){
        case ATT_SERVER_REQUEST_RECEIVED:

            // wait until pairing is complete
            if (att_server->pairing_active) break;

#ifdef ENABLE_LE_SIGNED_WRITE
            if (att_server->request_buffer[0] == ATT_SIGNED_WRITE_COMMAND){
                log_info("ATT Signed Write!");
                if (!sm_cmac_ready()) {
                    log_info("ATT Signed Write, sm_cmac engine not ready. Abort");
                    att_server->state = ATT_SERVER_IDLE;
                    return;
                }  
                if (att_server->request_size < (3 + 12)) {
                    log_info("ATT Signed Write, request to short. Abort.");
                    att_server->state = ATT_SERVER_IDLE;
                    return;
                }
                if (att_server->ir_lookup_active){
                    return;
                }
                if (att_server->ir_le_device_db_index < 0){
                    log_info("ATT Signed Write, CSRK not available");
                    att_server->state = ATT_SERVER_IDLE;
                    return;
                }

                // check counter
                uint32_t counter_packet = little_endian_read_32(att_server->request_buffer, att_server->request_size-12);
                uint32_t counter_db     = le_device_db_remote_counter_get(att_server->ir_le_device_db_index);
                log_info("ATT Signed Write, DB counter %"PRIu32", packet counter %"PRIu32, counter_db, counter_packet);
                if (counter_packet < counter_db){
                    log_info("ATT Signed Write, db reports higher counter, abort");
                    att_server->state = ATT_SERVER_IDLE;
                    return;
                }

                // signature is { sequence counter, secure hash }
                sm_key_t csrk;
                le_device_db_remote_csrk_get(att_server->ir_le_device_db_index, csrk);
                att_server->state = ATT_SERVER_W4_SIGNED_WRITE_VALIDATION;
                log_info("Orig Signature: ");
                log_info_hexdump( &att_server->request_buffer[att_server->request_size-8], 8);
                uint16_t attribute_handle = little_endian_read_16(att_server->request_buffer, 1);
                sm_cmac_signed_write_start(csrk, att_server->request_buffer[0], attribute_handle, att_server->request_size - 15, &att_server->request_buffer[3], counter_packet, att_signed_write_handle_cmac_result);
                return;
            } 
#endif
            // move on
            att_server->state = ATT_SERVER_REQUEST_RECEIVED_AND_VALIDATED;
            att_dispatch_server_request_can_send_now_event(att_server->connection.con_handle);
            break;

        default:
            break;
    }   
}
示例#7
0
// set requested baud rate
static void update_init_script_command(uint8_t *hci_cmd_buffer){
    uint16_t varid = little_endian_read_16(hci_cmd_buffer, 10);
    if (varid != 0x7003) return;
    uint16_t key = little_endian_read_16(hci_cmd_buffer, 14);
    log_info("csr: pskey 0x%04x", key);
    if (key != 0x01ea) return;

    // check for baud rate
    if (!hci_transport_config_uart) return;
    uint32_t baudrate = hci_transport_config_uart->baudrate_main;
    if (baudrate == 0){
        baudrate = hci_transport_config_uart->baudrate_init;
    }
    // uint32_t is stored as 2 x uint16_t with most important 16 bits first
    little_endian_store_16(hci_cmd_buffer, 20, baudrate >> 16);
    little_endian_store_16(hci_cmd_buffer, 22, baudrate &  0xffff);
}
示例#8
0
文件: main.c 项目: AubrCool/btstack
static void local_version_information_callback(uint8_t * packet){
    printf("Local version information:\n");
    uint16_t hci_version    = little_endian_read_16(packet, 4);
    uint16_t hci_revision   = little_endian_read_16(packet, 6);
    uint16_t lmp_version    = little_endian_read_16(packet, 8);
    uint16_t manufacturer   = little_endian_read_16(packet, 10);
    uint16_t lmp_subversion = little_endian_read_16(packet, 12);
    printf("- HCI Version  0x%04x\n", hci_version);
    printf("- HCI Revision 0x%04x\n", hci_revision);
    printf("- LMP Version  0x%04x\n", lmp_version);
    printf("- LMP Revision 0x%04x\n", lmp_subversion);
    printf("- Manufacturer 0x%04x\n", manufacturer);
    switch (manufacturer){
        case COMPANY_ID_CAMBRIDGE_SILICON_RADIO:
            printf("Cambridge Silicon Radio CSR chipset.\n");
            use_fast_uart();
            hci_set_chipset(btstack_chipset_csr_instance());
            break;
        case COMPANY_ID_TEXAS_INSTRUMENTS_INC: 
            printf("Texas Instruments - CC256x compatible chipset.\n");
            use_fast_uart();
            hci_set_chipset(btstack_chipset_cc256x_instance());
#ifdef ENABLE_EHCILL
            printf("eHCILL enabled.\n");
#endif
            break;
        case COMPANY_ID_BROADCOM_CORPORATION:   
            printf("Broadcom chipset. Not supported yet\n");
            // hci_set_chipset(btstack_chipset_bcm_instance());
            break;
        case COMPANY_ID_ST_MICROELECTRONICS:   
            printf("ST Microelectronics - using STLC2500d driver.\n");
            use_fast_uart();
            hci_set_chipset(btstack_chipset_stlc2500d_instance());
            break;
        case COMPANY_ID_EM_MICROELECTRONICS_MARIN:
            printf("EM Microelectronics - using EM9301 driver.\n");
            hci_set_chipset(btstack_chipset_em9301_instance());
            break;
        default:
            printf("Unknown manufacturer / manufacturer not supported yet.\n");
            break;
    }
}
示例#9
0
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
    if (packet_type != HCI_EVENT_PACKET) return;
    uint8_t event = hci_event_packet_get_type(packet);
    switch (event) {
        case BTSTACK_EVENT_STATE:
            // bt stack activated, get started 
            if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING){
                printf("SDP Query for RFCOMM services on %s started\n", bd_addr_to_str(remote));
                sdp_client_query_rfcomm_channel_and_name_for_uuid(&handle_query_rfcomm_event, remote, SDP_PublicBrowseGroup);
            }
            break;
        case RFCOMM_EVENT_CHANNEL_OPENED:
            // data: event(8), len(8), status (8), address (48), handle(16), server channel(8), rfcomm_cid(16), max frame size(16)
            if (packet[2]) {
                state = DONE;
                printf("RFCOMM channel open failed, status %u\n", packet[2]);
            } else {
                // data: event(8), len(8), status (8), address (48), handle (16), server channel(8), rfcomm_cid(16), max frame size(16)
                state = SENDING;
                rfcomm_cid = little_endian_read_16(packet, 12);
                mtu = little_endian_read_16(packet, 14);
                printf("RFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u\n", rfcomm_cid, mtu);
                if ((test_data_len > mtu)) {
                    test_data_len = mtu;
                }
                test_reset();
                rfcomm_request_can_send_now_event(rfcomm_cid);
                break;
            }
            break;
        case RFCOMM_EVENT_CAN_SEND_NOW:
            send_packet();
            break;
        case RFCOMM_EVENT_CHANNEL_CLOSED:
            if (state != DONE) {
                printf("RFCOMM_EVENT_CHANNEL_CLOSED received before all test data was sent\n");
                state = DONE;
            }
            break;
        default:
            break;
    }
}
示例#10
0
static int battery_service_write_callback(hci_con_handle_t con_handle, uint16_t attribute_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size){
	UNUSED(con_handle);
	UNUSED(transaction_mode);
	UNUSED(offset);
	UNUSED(buffer_size);

	if (attribute_handle == battery_value_handle_client_configuration){
		battery_value_client_configuration = little_endian_read_16(buffer, 0);
	}
	return 0;
}
示例#11
0
文件: main.c 项目: notmikeb/btstack
static void local_version_information_handler(uint8_t * packet){
    printf("Local version information:\n");
    uint16_t hci_version    = packet[6];
    uint16_t hci_revision   = little_endian_read_16(packet, 7);
    uint16_t lmp_version    = packet[9];
    uint16_t manufacturer   = little_endian_read_16(packet, 10);
    uint16_t lmp_subversion = little_endian_read_16(packet, 12);
    printf("- HCI Version  0x%04x\n", hci_version);
    printf("- HCI Revision 0x%04x\n", hci_revision);
    printf("- LMP Version  0x%04x\n", lmp_version);
    printf("- LMP Revision 0x%04x\n", lmp_subversion);
    printf("- Manufacturer 0x%04x\n", manufacturer);
    switch (manufacturer){
        case BLUETOOTH_COMPANY_ID_CAMBRIDGE_SILICON_RADIO:
            printf("Cambridge Silicon Radio CSR chipset.\n");
            use_fast_uart();
            hci_set_chipset(btstack_chipset_csr_instance());
            break;
        case BLUETOOTH_COMPANY_ID_TEXAS_INSTRUMENTS_INC: 
            printf("Texas Instruments - CC256x compatible chipset.\n");
            use_fast_uart();
            hci_set_chipset(btstack_chipset_cc256x_instance());
            break;
        case BLUETOOTH_COMPANY_ID_BROADCOM_CORPORATION:   
            printf("Broadcom chipset. Not supported by posix-h5 port, please use port/posix-h5-bcm\n");
            exit(10);
            break;
        case BLUETOOTH_COMPANY_ID_ST_MICROELECTRONICS:   
            printf("ST Microelectronics - using STLC2500d driver.\n");
            use_fast_uart();
            hci_set_chipset(btstack_chipset_stlc2500d_instance());
            break;
        case BLUETOOTH_COMPANY_ID_EM_MICROELECTRONIC_MARIN_SA:
            printf("EM Microelectronics - using EM9301 driver.\n");
            hci_set_chipset(btstack_chipset_em9301_instance());
            break;
        default:
            printf("Unknown manufacturer / manufacturer not supported yet.\n");
            break;
    }
}
示例#12
0
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){

    bd_addr_t event_addr;
    uint16_t psm;

    if (packet_type != HCI_EVENT_PACKET) return;

    switch (packet[0]) {
        case BTSTACK_EVENT_STATE:
            // bt stack activated, get started 
            if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING){
                printf("BTstack L2CAP Test Ready\n");
                show_usage();
            }
            break;
        case L2CAP_EVENT_CHANNEL_OPENED:
            // inform about new l2cap connection
            reverse_bd_addr(&packet[3], event_addr);
            psm = little_endian_read_16(packet, 11); 
            local_cid = little_endian_read_16(packet, 13); 
            handle = little_endian_read_16(packet, 9);
            if (packet[2] == 0) {
                printf("Channel successfully opened: %s, handle 0x%02x, psm 0x%02x, local cid 0x%02x, remote cid 0x%02x\n",
                       bd_addr_to_str(event_addr), handle, psm, local_cid,  little_endian_read_16(packet, 15));
            } else {
                printf("L2CAP connection to device %s failed. status code %u\n", bd_addr_to_str(event_addr), packet[2]);
            }
            break;
        case L2CAP_EVENT_INCOMING_CONNECTION: {
            uint16_t l2cap_cid  = little_endian_read_16(packet, 12);
            printf("L2CAP Accepting incoming connection request\n"); 
            l2cap_accept_connection(l2cap_cid);
            break;
        }


        default:
            break;
    }
}
示例#13
0
esp_err_t esp_eddystone_decode(const uint8_t* buf, uint8_t len, esp_eddystone_result_t* res)
{
    static uint8_t pos=0;
    while(res->common.srv_data_type != EDDYSTONE_SERVICE_UUID) 
    {
        pos++;
        uint8_t ad_type = buf[pos++];
        switch(ad_type) 
        {
            case ESP_BLE_AD_TYPE_FLAG: {
                res->common.flags = buf[pos++];
                break;
            }
            case ESP_BLE_AD_TYPE_16SRV_CMPL: {
                uint16_t uuid = little_endian_read_16(buf, pos);
                if(uuid != EDDYSTONE_SERVICE_UUID) {
                    return -1; 
                }
                res->common.srv_uuid = uuid;
                pos += 2;
                break;
            }
            case ESP_BLE_AD_TYPE_SERVICE_DATA: {
                uint16_t type = little_endian_read_16(buf, pos);
                pos += 2;
                uint8_t frame_type = buf[pos++];
                if(type != EDDYSTONE_SERVICE_UUID || !(frame_type == EDDYSTONE_FRAME_TYPE_UID || frame_type == EDDYSTONE_FRAME_TYPE_URL || 
                   frame_type == EDDYSTONE_FRAME_TYPE_TLM)) {
                    return -1;
                }
                res->common.srv_data_type = type;
                res->common.frame_type = frame_type;
                break;
            }
            default:
                break;
        }
    }
    return esp_eddystone_get_inform(buf+pos, len-pos, res);
}
示例#14
0
int wav_reader_open(const char * filepath){
    wav_reader_fd = open(filepath, O_RDONLY); 
    if (!wav_reader_fd) {
        log_error("Can't open file %s", filepath);
        return 1;
    }

    uint8_t buf[40];
    __read(wav_reader_fd, buf, sizeof(buf));

    int num_channels = little_endian_read_16(buf, 22);
    int block_align = little_endian_read_16(buf, 32);
    if (num_channels != 1 && num_channels != 2) {
        log_error("Unexpected num channels %d", num_channels);
        return 1;
    }
    bytes_per_sample = block_align/num_channels;
    if (bytes_per_sample > 2){
        bytes_per_sample = bytes_per_sample/8;
    }
    return 0;
}
示例#15
0
文件: main.c 项目: notmikeb/btstack
static void transport_deliver_packets(void){
    xSemaphoreTake(ring_buffer_mutex, portMAX_DELAY);
    while (btstack_ring_buffer_bytes_available(&hci_ringbuffer)){
        uint32_t number_read;
        uint8_t len_tag[2];
        btstack_ring_buffer_read(&hci_ringbuffer, len_tag, 2, &number_read);
        uint32_t len = little_endian_read_16(len_tag, 0);
        btstack_ring_buffer_read(&hci_ringbuffer, hci_receive_buffer, len, &number_read);
        xSemaphoreGive(ring_buffer_mutex);
        transport_packet_handler(hci_receive_buffer[0], &hci_receive_buffer[1], len-1);
        xSemaphoreTake(ring_buffer_mutex, portMAX_DELAY);
    }
    xSemaphoreGive(ring_buffer_mutex);
}
示例#16
0
static void packet_handler(uint8_t * event, uint16_t event_size){
    // printf("Packet handler event 0x%02x\n", event[0]);
    switch (event[0]) {
        case BTSTACK_EVENT_STATE:
            if (event[2] != HCI_STATE_WORKING) break;
            show_usage();
            break;
        case HCI_EVENT_HSP_META:
            switch (event[2]) { 
                case HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE:
                    if (event[3] == 0){
                        sco_handle = little_endian_read_16(event, 4);
                        printf("Audio connection established with SCO handle 0x%04x.\n", sco_handle);
                    } else {
                        printf("Audio connection establishment failed with status %u\n", event[3]);
                        sco_handle = 0;
                    }
                    break;
                case HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE:
                    if (event[3] == 0){
                        printf("Audio connection released.\n\n");
                        sco_handle = 0;    
                    } else {
                        printf("Audio connection releasing failed with status %u\n", event[3]);
                    }
                    break;
                case HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED:
                    printf("Received microphone gain change %d\n", event[3]);
                    break;
                case HSP_SUBEVENT_SPEAKER_GAIN_CHANGED:
                    printf("Received speaker gain change %d\n", event[3]);
                    break;
                case HSP_SUBEVENT_RING:
                    printf("HS: RING RING!\n");
                    break;
                case HSP_SUBEVENT_AG_INDICATION:
                    memset(hs_cmd_buffer, 0, sizeof(hs_cmd_buffer));
                    int size = event[3] <= sizeof(hs_cmd_buffer)? event[3] : sizeof(hs_cmd_buffer); 
                    memcpy(hs_cmd_buffer, &event[4], size - 1);
                    printf("Received custom indication: \"%s\". \nExit code or call hsp_hs_send_result.\n", hs_cmd_buffer);
                    break;
                default:
                    printf("event not handled %u\n", event[2]);
                    break;
            }
            break;
        default:
            break;
    }
}
示例#17
0
int wav_reader_read_int16(int num_samples, int16_t * data){
    if (!wav_reader_fd) return 1;
    int i;
    int bytes_read = 0;  
    for (i=0; i<num_samples; i++){
        uint8_t buf[2];
        bytes_read +=__read(wav_reader_fd, &buf, 2);
        data[i] = little_endian_read_16(buf, 0);  
    }
    if (bytes_read == num_samples*bytes_per_sample) {
        return 0;
    } else {
        return 1;
    }
}
示例#18
0
void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
    uint16_t aHandle;
    bd_addr_t event_address;
    switch (packet_type) {
        case HCI_EVENT_PACKET:
            switch (packet[0]) {
                case SM_EVENT_PASSKEY_INPUT_NUMBER: 
                    // store peer address for input
                    printf("\nGAP Bonding: Enter 6 digit passkey: '");
                    fflush(stdout);
                    break;

                case SM_EVENT_PASSKEY_DISPLAY_NUMBER:
                    printf("\nGAP Bonding: Display Passkey '%06u\n", little_endian_read_32(packet, 11));
                    break;

                case SM_EVENT_PASSKEY_DISPLAY_CANCEL: 
                    printf("\nGAP Bonding: Display cancel\n");
                    break;

                case SM_EVENT_JUST_WORKS_REQUEST:
                    // auto-authorize connection if requested
                    sm_just_works_confirm(little_endian_read_16(packet, 2));
                    printf("Just Works request confirmed\n");
                    break;

                case SM_EVENT_AUTHORIZATION_REQUEST:
                    // auto-authorize connection if requested
                    sm_authorization_grant(little_endian_read_16(packet, 2));
                    break;

                default:
                    break;
            }
    }
}
示例#19
0
// write requests
static int att_write_callback(hci_con_handle_t con_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size){
    // ignore cancel sent for new connections
    if (transaction_mode == ATT_TRANSACTION_MODE_CANCEL) return 0;
    // find characteristic for handle
    switch (att_handle){
        case ATT_CHARACTERISTIC_0000FF11_0000_1000_8000_00805F9B34FB_01_CLIENT_CONFIGURATION_HANDLE:
            le_notification_enabled = little_endian_read_16(buffer, 0) == GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION;
            att_con_handle = con_handle;
            return 0;
        case ATT_CHARACTERISTIC_0000FF11_0000_1000_8000_00805F9B34FB_01_VALUE_HANDLE:
            printf("Write on test characteristic: ");
            printf_hexdump(buffer, buffer_size);
            return 0;
        default:
            printf("WRITE Callback, handle %04x, mode %u, offset %u, data: ", con_handle, transaction_mode, offset);
            printf_hexdump(buffer, buffer_size);
            return 0;
    }
}
示例#20
0
static int att_server_write_callback(hci_con_handle_t con_handle, uint16_t attribute_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size){
    switch (transaction_mode){
        case ATT_TRANSACTION_MODE_VALIDATE:
            return att_validate_prepared_write(con_handle);
        case ATT_TRANSACTION_MODE_EXECUTE:
        case ATT_TRANSACTION_MODE_CANCEL:
            att_notify_write_callbacks(con_handle, transaction_mode);
            return 0;
        default:
            break;
    }

    // track CCC writes
    if (att_is_persistent_ccc(attribute_handle) && offset == 0 && buffer_size == 2){
        att_server_persistent_ccc_write(con_handle, attribute_handle, little_endian_read_16(buffer, 0));
    }

    att_write_callback_t callback = att_server_write_callback_for_handle(attribute_handle);
    if (!callback) return 0;
    return (*callback)(con_handle, attribute_handle, transaction_mode, offset, buffer, buffer_size);
}
示例#21
0
static void sco_demo_receive_CVSD(uint8_t * packet, uint16_t size){
    if (!num_samples_to_write) return;

    int16_t audio_frame_out[128];    // 

    if (size > sizeof(audio_frame_out)){
        printf("sco_demo_receive_CVSD: SCO packet larger than local output buffer - dropping data.\n");
        return;
    }

#if defined(SCO_WAV_FILENAME) || defined(USE_PORTAUDIO)
    const int audio_bytes_read = size - 3;
    const int num_samples = audio_bytes_read / CVSD_BYTES_PER_FRAME;

    // convert into host endian
    int16_t audio_frame_in[128];
    int i;
    for (i=0;i<num_samples;i++){
        audio_frame_in[i] = little_endian_read_16(packet, 3 + i * 2);
    }

    btstack_cvsd_plc_process_data(&cvsd_plc_state, audio_frame_in, num_samples, audio_frame_out);
#endif

#ifdef SCO_WAV_FILENAME
    // Samples in CVSD SCO packet are in little endian, ready for wav files (take shortcut)
    const int samples_to_write = btstack_min(num_samples, num_samples_to_write);
    wav_writer_write_le_int16(samples_to_write, audio_frame_out);
    num_samples_to_write -= samples_to_write;
    if (num_samples_to_write == 0){
        wav_writer_close();
    }
#endif

#ifdef USE_PORTAUDIO
    btstack_ring_buffer_write(&pa_output_ring_buffer, (uint8_t *)audio_frame_out, audio_bytes_read);
#endif
}
示例#22
0
static wiced_result_t h4_rx_worker_receive_packet(void * arg){

#ifdef WICED_BT_UART_MANUAL_CTS_RTS
    platform_gpio_output_low(wiced_bt_uart_pins[WICED_BT_PIN_UART_RTS]);
#endif

    while (1){
        rx_worker_read_pos = 0;
        h4_rx_worker_receive_bytes(1);
        switch (hci_packet[0]){
            case HCI_EVENT_PACKET:
                h4_rx_worker_receive_bytes(HCI_EVENT_HEADER_SIZE);
                h4_rx_worker_receive_bytes(hci_packet[2]);
                break;
            case HCI_ACL_DATA_PACKET:
                h4_rx_worker_receive_bytes(HCI_ACL_HEADER_SIZE);
                h4_rx_worker_receive_bytes(little_endian_read_16( hci_packet, 3));
                break;
            case HCI_SCO_DATA_PACKET:
                h4_rx_worker_receive_bytes(HCI_SCO_HEADER_SIZE);
                h4_rx_worker_receive_bytes(hci_packet[3]);
                break;
            default:
                // try again
                log_error("h4_rx_worker_receive_packet: invalid packet type 0x%02x", hci_packet[0]);
                continue;
        }

#ifdef WICED_BT_UART_MANUAL_CTS_RTS
        platform_gpio_output_high(wiced_bt_uart_pins[WICED_BT_PIN_UART_RTS]);
#endif

        // deliver packet on main thread
        btstack_run_loop_wiced_execute_code_on_main_thread(&h4_main_deliver_packet, NULL);
        return WICED_SUCCESS;
    }
}
示例#23
0
static void handle_hci_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){

    UNUSED(packet_type);
    UNUSED(channel);
    UNUSED(size);

    int connection_encrypted;

    // handle connect / disconncet events first
    switch (hci_event_packet_get_type(packet)) {
        case HCI_EVENT_LE_META:
            switch (packet[2]) {
                case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
                    gc_handle = little_endian_read_16(packet, 4);
                    log_info("Connection handle 0x%04x, request encryption", gc_handle);

                    // we need to be paired to enable notifications
                    tc_state = TC_W4_ENCRYPTED_CONNECTION;
                    sm_send_security_request(gc_handle);
                    break;
                default:
                    break;
            }
            return;

        case HCI_EVENT_ENCRYPTION_CHANGE: 
            if (gc_handle != little_endian_read_16(packet, 3)) return;
            connection_encrypted = packet[5];
            log_info("Encryption state change: %u", connection_encrypted);
            if (!connection_encrypted) return;
            if (tc_state != TC_W4_ENCRYPTED_CONNECTION) return;

            // let's start
            log_info("\nANCS Client - CONNECTED, discover ANCS service");
            tc_state = TC_W4_SERVICE_RESULT;
            gatt_client_discover_primary_services_by_uuid128(handle_hci_event, gc_handle, ancs_service_uuid);
            return;
            
        case HCI_EVENT_DISCONNECTION_COMPLETE:
            if (hci_event_disconnection_complete_get_connection_handle(packet) != gc_handle) break;
            if (tc_state == TC_SUBSCRIBED){
                notify_client_simple(ANCS_SUBEVENT_CLIENT_DISCONNECTED);
            }
            tc_state = TC_IDLE;
            gc_handle = 0;
            return;

        default:
            break;
    }

    gatt_client_characteristic_t characteristic;
    uint8_t *           value;
    uint16_t            value_handle;
    uint16_t            value_length;

    switch(tc_state){
        case TC_W4_SERVICE_RESULT:
            switch(hci_event_packet_get_type(packet)){
                case GATT_EVENT_SERVICE_QUERY_RESULT:
                    gatt_event_service_query_result_get_service(packet, &ancs_service);
                    ancs_service_found = 1;
                    break;
                case GATT_EVENT_QUERY_COMPLETE:
                    if (!ancs_service_found){
                        log_info("ANCS Service not found");
                        tc_state = TC_IDLE;
                        break;
                    }
                    tc_state = TC_W4_CHARACTERISTIC_RESULT;
                    log_info("ANCS Client - Discover characteristics for ANCS SERVICE ");
                    gatt_client_discover_characteristics_for_service(handle_hci_event, gc_handle, &ancs_service);
                    break;
                default:
                    break;
            }
            break;
            
        case TC_W4_CHARACTERISTIC_RESULT:
            switch(hci_event_packet_get_type(packet)){
                case GATT_EVENT_CHARACTERISTIC_QUERY_RESULT:
                    gatt_event_characteristic_query_result_get_characteristic(packet, &characteristic);
                    if (memcmp(characteristic.uuid128, ancs_notification_source_uuid, 16) == 0){
                        log_info("ANCS Notification Source found, attribute handle %u", characteristic.value_handle);
                        ancs_notification_source_characteristic = characteristic;
                        ancs_characteristcs++;
                        break;                        
                    }
                    if (memcmp(characteristic.uuid128, ancs_control_point_uuid, 16) == 0){
                        log_info("ANCS Control Point found, attribute handle %u", characteristic.value_handle);
                        ancs_control_point_characteristic = characteristic;
                        ancs_characteristcs++;
                        break;                        
                    }
                    if (memcmp(characteristic.uuid128, ancs_data_source_uuid, 16) == 0){
                        log_info("ANCS Data Source found, attribute handle %u", characteristic.value_handle);
                        ancs_data_source_characteristic = characteristic;
                        ancs_characteristcs++;
                        break;                        
                    }
                    break;
                case GATT_EVENT_QUERY_COMPLETE:
                    log_info("ANCS Characteristcs count %u", ancs_characteristcs);
                    tc_state = TC_W4_NOTIFICATION_SOURCE_SUBSCRIBED;
                    gatt_client_listen_for_characteristic_value_updates(&ancs_notification_source_notification, &handle_hci_event, gc_handle, &ancs_notification_source_characteristic);
                    gatt_client_write_client_characteristic_configuration(handle_hci_event, gc_handle, &ancs_notification_source_characteristic,
                        GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION);
                    break;
                default:
                    break;
            }
            break;
        case TC_W4_NOTIFICATION_SOURCE_SUBSCRIBED:
            switch(hci_event_packet_get_type(packet)){
                case GATT_EVENT_QUERY_COMPLETE:
                    log_info("ANCS Notification Source subscribed");
                    tc_state = TC_W4_DATA_SOURCE_SUBSCRIBED;
                    gatt_client_listen_for_characteristic_value_updates(&ancs_data_source_notification, &handle_hci_event, gc_handle, &ancs_data_source_characteristic);
                    gatt_client_write_client_characteristic_configuration(handle_hci_event, gc_handle, &ancs_data_source_characteristic,
                        GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION);
                    break;
                default:
                    break;
            }
            break;
        case TC_W4_DATA_SOURCE_SUBSCRIBED:
            switch(hci_event_packet_get_type(packet)){
                case GATT_EVENT_QUERY_COMPLETE:
                    log_info("ANCS Data Source subscribed");
                    tc_state = TC_SUBSCRIBED;
                    notify_client_simple(ANCS_SUBEVENT_CLIENT_CONNECTED);
                    break;
                default:
                    break;
            }
            break;
        case TC_SUBSCRIBED:
            if (hci_event_packet_get_type(packet) != GATT_EVENT_NOTIFICATION && hci_event_packet_get_type(packet) != GATT_EVENT_INDICATION ) break;

            value_handle = little_endian_read_16(packet, 4);
            value_length = little_endian_read_16(packet, 6);
            value = &packet[8];

            log_info("ANCS Notification, value handle %u", value_handle);

            if (value_handle == ancs_data_source_characteristic.value_handle){
                int i;
                for (i=0;i<value_length;i++) {
                    ancs_chunk_parser_handle_byte(value[i]);
                }
            } else if (value_handle == ancs_notification_source_characteristic.value_handle){
                ancs_notification_uid = little_endian_read_32(value, 4);
                log_info("Notification received: EventID %02x, EventFlags %02x, CategoryID %02x, CategoryCount %u, UID %04x",
                    value[0], value[1], value[2], value[3], (int) ancs_notification_uid);
                static uint8_t get_notification_attributes[] = {0, 0,0,0,0,  0,  1,32,0,  2,32,0, 3,32,0, 4, 5};
                little_endian_store_32(get_notification_attributes, 1, ancs_notification_uid);
                ancs_notification_uid = 0;
                ancs_chunk_parser_init();
                gatt_client_write_value_of_characteristic(handle_hci_event, gc_handle, ancs_control_point_characteristic.value_handle, 
                    sizeof(get_notification_attributes), get_notification_attributes);
            } else {
                log_info("Unknown Source: ");
                log_info_hexdump(value , value_length);
            }
            break;
        default:
            break;
    }    
    // app_run();
}
示例#24
0
static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
    UNUSED(channel);
    UNUSED(size);
    bd_addr_t local_addr;
    switch (packet_type) {
        case HCI_EVENT_PACKET:
            switch (packet[0]) {
                case BTSTACK_EVENT_STATE:
                    // bt stack activated, get started
                    if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING){
                        gap_local_bd_addr(local_addr);
                        printf("BD_ADDR: %s\n", bd_addr_to_str(local_addr));
                        // generate OOB data
                        sm_generate_sc_oob_data(sc_local_oob_generated_callback);
                    }
                    break;
                case HCI_EVENT_LE_META:
                    switch (hci_event_le_meta_get_subevent_code(packet)) {
                        case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
                            connection_handle = little_endian_read_16(packet, 4);
                            printf("CONNECTED: Connection handle 0x%04x\n", connection_handle);
                            break;
                        default:
                            break;
                    }
                    break;
                case HCI_EVENT_DISCONNECTION_COMPLETE:
                    break;
                case SM_EVENT_JUST_WORKS_REQUEST:
                    printf("JUST_WORKS_REQUEST\n");
                    break;
                case SM_EVENT_NUMERIC_COMPARISON_REQUEST:
                    printf("NUMERIC_COMPARISON_REQUEST\n");
                    break;
                case SM_EVENT_PASSKEY_INPUT_NUMBER:
                    // display number
                    printf("PASSKEY_INPUT_NUMBER\n");
                    ui_passkey = 0;
                    ui_digits_for_passkey = 6;
                    sm_keypress_notification(connection_handle, SM_KEYPRESS_PASSKEY_ENTRY_STARTED);
                    break;
                case SM_EVENT_PASSKEY_DISPLAY_NUMBER:
                    // display number
                    printf("PASSKEY_DISPLAY_NUMBER: %06u\n", little_endian_read_32(packet, 11));
                    break;
                case SM_EVENT_PASSKEY_DISPLAY_CANCEL: 
                    break;
                case SM_EVENT_AUTHORIZATION_REQUEST:
                    break;
                case SM_EVENT_PAIRING_COMPLETE:
                    printf("\nPAIRING_COMPLETE: %u,%u\n", sm_event_pairing_complete_get_status(packet), sm_event_pairing_complete_get_reason(packet));
                    if (sm_event_pairing_complete_get_status(packet)) break;
                    if (we_are_central){
                        printf("Search for LE Counter service.\n");
                        state = TC_W4_SERVICE_RESULT;
                        gatt_client_discover_primary_services_by_uuid128(handle_gatt_client_event, connection_handle, le_counter_service_uuid);
                    }
                    break;
                case ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE:
                    break;
                case ATT_EVENT_CAN_SEND_NOW:
                    att_server_notify(connection_handle, ATT_CHARACTERISTIC_0000FF11_0000_1000_8000_00805F9B34FB_01_VALUE_HANDLE, (uint8_t *) "Pairing Success!", 16);
                    break;
                default:
                    break;
            }
    }
    fflush(stdout);
}
示例#25
0
/* LISTING_START(GAPLEAdvDataParsing): Parsing advertising data */
static void dump_advertisement_data(const uint8_t * adv_data, uint8_t adv_size){
    ad_context_t context;
    bd_addr_t address;
    uint8_t uuid_128[16];
    for (ad_iterator_init(&context, adv_size, (uint8_t *)adv_data) ; ad_iterator_has_more(&context) ; ad_iterator_next(&context)){
        uint8_t data_type    = ad_iterator_get_data_type(&context);
        uint8_t size         = ad_iterator_get_data_len(&context);
        const uint8_t * data = ad_iterator_get_data(&context);
        
        if (data_type > 0 && data_type < 0x1B){
            printf("    %s: ", ad_types[data_type]);
        } 
        int i;
        // Assigned Numbers GAP
    
        switch (data_type){
            case 0x01: // Flags
                // show only first octet, ignore rest
                for (i=0; i<8;i++){
                    if (data[0] & (1<<i)){
                        printf("%s; ", flags[i]);
                    }

                }
                break;
            case 0x02: // Incomplete List of 16-bit Service Class UUIDs
            case 0x03: // Complete List of 16-bit Service Class UUIDs
            case 0x14: // List of 16-bit Service Solicitation UUIDs
                for (i=0; i<size;i+=2){
                    printf("%02X ", little_endian_read_16(data, i));
                }
                break;
            case 0x04: // Incomplete List of 32-bit Service Class UUIDs
            case 0x05: // Complete List of 32-bit Service Class UUIDs
                for (i=0; i<size;i+=4){
                    printf("%04"PRIX32, little_endian_read_32(data, i));
                }
                break;
            case 0x06: // Incomplete List of 128-bit Service Class UUIDs
            case 0x07: // Complete List of 128-bit Service Class UUIDs
            case 0x15: // List of 128-bit Service Solicitation UUIDs
                reverse_128(data, uuid_128);
                printf("%s", uuid128_to_str(uuid_128));
                break;
            case 0x08: // Shortened Local Name
            case 0x09: // Complete Local Name
                for (i=0; i<size;i++){
                    printf("%c", (char)(data[i]));
                }
                break;
            case 0x0A: // Tx Power Level 
                printf("%d dBm", *(int8_t*)data);
                break;
            case 0x12: // Slave Connection Interval Range 
                printf("Connection Interval Min = %u ms, Max = %u ms", little_endian_read_16(data, 0) * 5/4, little_endian_read_16(data, 2) * 5/4);
                break;
            case 0x16: // Service Data 
                printf_hexdump(data, size);
                break;
            case 0x17: // Public Target Address
            case 0x18: // Random Target Address
                reverse_bd_addr(data, address);
                printf("%s", bd_addr_to_str(address));
                break;
            case 0x19: // Appearance 
                // https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml
                printf("%02X", little_endian_read_16(data, 0) );
                break;
            case 0x1A: // Advertising Interval 
                printf("%u ms", little_endian_read_16(data, 0) * 5/8 );
                break;
            case 0x3D: // 3D Information Data 
                printf_hexdump(data, size);
                break;
            case 0xFF: // Manufacturer Specific Data 
                break;
            case 0x0D: // Class of Device (3B)
            case 0x0E: // Simple Pairing Hash C (16B)
            case 0x0F: // Simple Pairing Randomizer R (16B) 
            case 0x10: // Device ID 
            case 0x11: // Security Manager TK Value (16B)
            default:
                printf("Unknown Advertising Data Type"); 
                break;
        }        
        printf("\n");
    }
    printf("\n");
}
示例#26
0
文件: hsp_hs.c 项目: AubrCool/btstack
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
    // printf("packet_handler type %u, packet[0] %x\n", packet_type, packet[0]);
    if (packet_type == RFCOMM_DATA_PACKET){
        // skip over leading newline
        while (size > 0 && (packet[0] == '\n' || packet[0] == '\r')){
            size--;
            packet++;
        }
        if (strncmp((char *)packet, HSP_AG_RING, strlen(HSP_AG_RING)) == 0){
            emit_ring_event();
        } else if (strncmp((char *)packet, HSP_AG_OK, strlen(HSP_AG_OK)) == 0){
           wait_ok = 0;
        } else if (strncmp((char *)packet, HSP_MICROPHONE_GAIN, strlen(HSP_MICROPHONE_GAIN)) == 0){
            uint8_t gain = (uint8_t)atoi((char*)&packet[strlen(HSP_MICROPHONE_GAIN)]);
            emit_event(HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED, gain);
        
        } else if (strncmp((char *)packet, HSP_SPEAKER_GAIN, strlen(HSP_SPEAKER_GAIN)) == 0){
            uint8_t gain = (uint8_t)atoi((char*)&packet[strlen(HSP_SPEAKER_GAIN)]);
            emit_event(HSP_SUBEVENT_SPEAKER_GAIN_CHANGED, gain);
        } else {
            if (!hsp_hs_callback) return;
            // strip trailing newline
            while (size > 0 && (packet[size-1] == '\n' || packet[size-1] == '\r')){
                size--;
            }
            // add trailing \0
            packet[size] = 0;
            // re-use incoming buffer to avoid reserving large buffers - ugly but efficient
            uint8_t * event = packet - 4;
            event[0] = HCI_EVENT_HSP_META;
            event[1] = size + 2;
            event[2] = HSP_SUBEVENT_AG_INDICATION;
            event[3] = size;
            (*hsp_hs_callback)(HCI_EVENT_PACKET, 0, event, size+4);
        }
        hsp_run();
        return;
    }

    if (packet_type != HCI_EVENT_PACKET) return;
    uint8_t event = hci_event_packet_get_type(packet);
    bd_addr_t event_addr;
    uint16_t handle;

    switch (event) {
        case HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE:{
            if (hsp_state < HSP_RFCOMM_CONNECTION_ESTABLISHED) return;
            int index = 2;
            uint8_t status = packet[index++];
            sco_handle = little_endian_read_16(packet, index);
            index+=2;
            bd_addr_t address; 
            memcpy(address, &packet[index], 6);
            index+=6;
            uint8_t link_type = packet[index++];
            uint8_t transmission_interval = packet[index++];  // measured in slots
            uint8_t retransmission_interval = packet[index++];// measured in slots
            uint16_t rx_packet_length = little_endian_read_16(packet, index); // measured in bytes
            index+=2;
            uint16_t tx_packet_length = little_endian_read_16(packet, index); // measured in bytes
            index+=2;
            uint8_t air_mode = packet[index];

            if (status != 0){
                log_error("(e)SCO Connection failed, status %u", status);
                emit_event_audio_connected(status, sco_handle);
                hsp_state = HSP_RFCOMM_CONNECTION_ESTABLISHED ;
                break;
            }

            switch (link_type){
                case 0x00:
                    log_info("SCO Connection established.");
                    if (transmission_interval != 0) log_error("SCO Connection: transmission_interval not zero: %d.", transmission_interval);
                    if (retransmission_interval != 0) log_error("SCO Connection: retransmission_interval not zero: %d.", retransmission_interval);
                    if (rx_packet_length != 0) log_error("SCO Connection: rx_packet_length not zero: %d.", rx_packet_length);
                    if (tx_packet_length != 0) log_error("SCO Connection: tx_packet_length not zero: %d.", tx_packet_length);
                    break;
                case 0x02:
                    log_info("eSCO Connection established.");
                    break;
                default:
                    log_error("(e)SCO reserved link_type 0x%2x", link_type);
                    break;
            }
            log_info("sco_handle 0x%2x, address %s, transmission_interval %u slots, retransmission_interval %u slots, " 
                 " rx_packet_length %u bytes, tx_packet_length %u bytes, air_mode 0x%2x (0x02 == CVSD)", sco_handle,
                 bd_addr_to_str(address), transmission_interval, retransmission_interval, rx_packet_length, tx_packet_length, air_mode);

            hsp_state = HSP_AUDIO_CONNECTION_ESTABLISHED;
            emit_event_audio_connected(status, sco_handle);
            break;                
        }

        case RFCOMM_EVENT_INCOMING_CONNECTION:
            // data: event (8), len(8), address(48), channel (8), rfcomm_cid (16)
            if (hsp_state != HSP_IDLE) return;

            reverse_bd_addr(&packet[2], event_addr); 
            rfcomm_cid = little_endian_read_16(packet, 9);
            log_info("RFCOMM channel %u requested for %s", packet[8], bd_addr_to_str(event_addr));
            hsp_state = HSP_W4_RFCOMM_CONNECTED;
            rfcomm_accept_connection(rfcomm_cid);
            break;

        case RFCOMM_EVENT_CHANNEL_OPENED:
            // printf("RFCOMM_EVENT_CHANNEL_OPENED packet_handler type %u, packet[0] %x\n", packet_type, packet[0]);
            // data: event(8), len(8), status (8), address (48), handle(16), server channel(8), rfcomm_cid(16), max frame size(16)
            if (hsp_state != HSP_W4_RFCOMM_CONNECTED) return;
            if (packet[2]) {
                log_info("RFCOMM channel open failed, status %u", packet[2]);
                hsp_state = HSP_IDLE;
                hsp_hs_reset_state();
            } else {
                // data: event(8) , len(8), status (8), address (48), handle (16), server channel(8), rfcomm_cid(16), max frame size(16)
                rfcomm_handle = little_endian_read_16(packet, 9);
                rfcomm_cid = little_endian_read_16(packet, 12);
                mtu = little_endian_read_16(packet, 14);
                log_info("RFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u, handle %02x", rfcomm_cid, mtu, rfcomm_handle);
                hsp_state = HSP_RFCOMM_CONNECTION_ESTABLISHED;
            }
            emit_event(HSP_SUBEVENT_RFCOMM_CONNECTION_COMPLETE, packet[2]);
            break;

        case RFCOMM_EVENT_CAN_SEND_NOW:
            hsp_run();
            break;
        
        case HCI_EVENT_DISCONNECTION_COMPLETE:
            handle = little_endian_read_16(packet,3);
            if (handle == sco_handle){
                sco_handle = 0;
                hsp_state = HSP_RFCOMM_CONNECTION_ESTABLISHED;
                emit_event(HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE,0);
                break;
            } 
            if (handle == rfcomm_handle) {
                rfcomm_handle = 0;
                hsp_state = HSP_IDLE;
                emit_event(HSP_SUBEVENT_RFCOMM_DISCONNECTION_COMPLETE,0);
                hsp_hs_reset_state();
            }
            break;

        case RFCOMM_EVENT_CHANNEL_CLOSED:
            hsp_hs_reset_state();
            hsp_hs_callback(HCI_EVENT_PACKET, 0, packet, size);
            break;

        default:
            break;
    }

    hsp_run();
}
static void h4_block_received(void){
    
    read_pos += bytes_to_read;
    
    // act
    switch (h4_state) {
        case H4_W4_PACKET_TYPE:
            switch (hci_packet[0]) {
                case HCI_EVENT_PACKET:
                    h4_state = H4_W4_EVENT_HEADER;
                    bytes_to_read = HCI_EVENT_HEADER_SIZE;
                    break;
                case HCI_ACL_DATA_PACKET:
                    h4_state = H4_W4_ACL_HEADER;
                    bytes_to_read = HCI_ACL_HEADER_SIZE;
                    break;
                case HCI_SCO_DATA_PACKET:
                    h4_state = H4_W4_SCO_HEADER;
                    bytes_to_read = HCI_SCO_HEADER_SIZE;
                    break;
                default:
                    log_error("h4_process: invalid packet type 0x%02x", hci_packet[0]);
                    h4_init_sm();
                    return;
            }
            break;
            
        case H4_W4_EVENT_HEADER:
            bytes_to_read = hci_packet[2];
            if (bytes_to_read == 0) {
                h4_state = H4_PACKET_RECEIVED; 
                break;
            }
            h4_state = H4_W4_PAYLOAD;
            break;
            
        case H4_W4_ACL_HEADER:
            bytes_to_read = little_endian_read_16( hci_packet, 3);
            // check ACL length
            if (HCI_ACL_HEADER_SIZE + bytes_to_read >  HCI_PACKET_BUFFER_SIZE){
                log_error("h4_process: invalid ACL payload len %u - only space for %u", bytes_to_read, HCI_PACKET_BUFFER_SIZE - HCI_ACL_HEADER_SIZE);
                h4_init_sm();
                return;              
            }
            if (bytes_to_read == 0) {
                h4_state = H4_PACKET_RECEIVED; 
                break;
            }
            h4_state = H4_W4_PAYLOAD;
            break;
        
        case H4_W4_SCO_HEADER:
            bytes_to_read = hci_packet[3];
            if (bytes_to_read == 0) {
                h4_state = H4_PACKET_RECEIVED; 
                break;
            }
            h4_state = H4_W4_PAYLOAD;
            break;            

        case H4_W4_PAYLOAD:
            h4_state = H4_PACKET_RECEIVED;
            bytes_to_read = 0;
            // trigger run loop
            btstack_run_loop_embedded_trigger();
            break;
            
        default:
            bytes_to_read = 0;
            break;
    }
    
    // read next block
    if (bytes_to_read) {
        hal_uart_dma_receive_block(&hci_packet[read_pos], bytes_to_read);
    }
}
示例#28
0
/* LISTING_START(packetHandler): Packet Handler */
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)
{
    /* LISTING_PAUSE */
    uint8_t   event;
    bd_addr_t event_addr;
    uint8_t   status;
    uint16_t  l2cap_cid;

    /* LISTING_RESUME */
    switch (packet_type) {
		case HCI_EVENT_PACKET:
            event = hci_event_packet_get_type(packet);
            switch (event) {            
                /* @text When BTSTACK_EVENT_STATE with state HCI_STATE_WORKING
                 * is received and the example is started in client mode, the remote SDP HID query is started.
                 */
                case BTSTACK_EVENT_STATE:
                    if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING){
                        printf("Start SDP HID query for remote HID Device.\n");
                        sdp_client_query_uuid16(&handle_sdp_client_query_result, remote_addr, BLUETOOTH_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE_SERVICE);
                    }
                    break;

                /* LISTING_PAUSE */
                case HCI_EVENT_PIN_CODE_REQUEST:
					// inform about pin code request
                    printf("Pin code request - using '0000'\n");
                    hci_event_pin_code_request_get_bd_addr(packet, event_addr);
                    gap_pin_code_response(event_addr, "0000");
					break;

                case HCI_EVENT_USER_CONFIRMATION_REQUEST:
                    // inform about user confirmation request
                    printf("SSP User Confirmation Request with numeric value '%"PRIu32"'\n", little_endian_read_32(packet, 8));
                    printf("SSP User Confirmation Auto accept\n");
                    break;

                /* LISTING_RESUME */

                case L2CAP_EVENT_CHANNEL_OPENED: 
                    status = packet[2];
                    if (status){
                        printf("L2CAP Connection failed: 0x%02x\n", status);
                        break;
                    }
                    l2cap_cid  = little_endian_read_16(packet, 13);
                    if (!l2cap_cid) break;
                    if (l2cap_cid == l2cap_hid_control_cid){
                        status = l2cap_create_channel(packet_handler, remote_addr, hid_interrupt_psm, 48, &l2cap_hid_interrupt_cid);
                        if (status){
                            printf("Connecting to HID Control failed: 0x%02x\n", status);
                            break;
                        }
                    }                        
                    if (l2cap_cid == l2cap_hid_interrupt_cid){
                        printf("HID Connection established\n");
                    }
                    break;
                default:
                    break;
            }
            break;
        case L2CAP_DATA_PACKET:
            // for now, just dump incoming data
            if (channel == l2cap_hid_interrupt_cid){
                hid_host_handle_interrupt_report(packet,  size);
            } else if (channel == l2cap_hid_control_cid){
                printf("HID Control: ");
                printf_hexdump(packet, size);
            } else {
                break;
            }
        default:
            break;
    }
}
示例#29
0
static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
    int status;
    uint8_t battery_level;

    switch(state){
        case TC_W4_SERVICE_RESULT:
            switch(hci_event_packet_get_type(packet)){
                case GATT_EVENT_SERVICE_QUERY_RESULT:
                    gatt_event_service_query_result_get_service(packet, &battery_service);
                    dump_service(&battery_service);
                    break;
                case GATT_EVENT_QUERY_COMPLETE:
                    if (packet[4] != 0){
                        printf("SERVICE_QUERY_RESULT - Error status %x.\n", packet[4]);
                        add_to_blacklist(report.address);
                        gap_disconnect(connection_handle);
                        break;  
                    } 
                    state = TC_W4_CHARACTERISTIC_RESULT;
                    printf("\nSearch for battery level characteristic.\n");
                    gatt_client_discover_characteristics_for_service_by_uuid16(handle_gatt_client_event, connection_handle, &battery_service, battery_level_characteristic_uuid);
                    break;
                default:
                    break;
            }
            break;
            
        case TC_W4_CHARACTERISTIC_RESULT:
            switch(hci_event_packet_get_type(packet)){
                case GATT_EVENT_CHARACTERISTIC_QUERY_RESULT:
                    gatt_event_characteristic_query_result_get_characteristic(packet, &config_characteristic);
                    dump_characteristic(&config_characteristic);
                    break;
                case GATT_EVENT_QUERY_COMPLETE:
                    if (packet[4] != 0){
                        printf("CHARACTERISTIC_QUERY_RESULT - Error status %x.\n", packet[4]);
                        add_to_blacklist(report.address);
                        gap_disconnect(connection_handle);
                        break;  
                    } 
                    state = TC_W4_BATTERY_DATA;
                    printf("\nConfigure battery level characteristic for notify.\n");
                    status = gatt_client_write_client_characteristic_configuration(handle_gatt_client_event, connection_handle, &config_characteristic, GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION);
                    if (status != 0){
                        printf("\nNotification not supported. Query value of characteristic.\n");
                        gatt_client_read_value_of_characteristic(handle_gatt_client_event, connection_handle, &config_characteristic);
                    }
                    
                    break;
                default:
                    break;
            }
            break;
        case TC_W4_BATTERY_DATA:
            switch(hci_event_packet_get_type(packet)){
                case GATT_EVENT_NOTIFICATION:
                    printf("\nBattery Data:\n");
                    dump_characteristic_value(&packet[8], little_endian_read_16(packet, 6));
                    break;
                case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT:
                        
                        if (gatt_event_characteristic_value_query_result_get_value_length(packet) < 1) break;
                        battery_level = gatt_event_characteristic_value_query_result_get_value(packet)[0];
                        printf("Battry level %d \n", battery_level);
                    break;

                case GATT_EVENT_QUERY_COMPLETE:
                    if (packet[4] != 0){
                        printf("CHARACTERISTIC_VALUE_QUERY_RESULT - Error status %x.\n", packet[4]);
                        break;  
                    }
                    // Use timer if repeated request is needed and notification is not supperted
                    gap_disconnect(connection_handle);
                    break;
                default:
                    printf("Unknown packet type %x\n", hci_event_packet_get_type(packet));
                    break;
            }
            break;

        default:
            printf("error\n");
            break;
    }
    
}
示例#30
0
/* LISTING_START(attWrite): ATT Write */
static int att_write_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size){
    if (att_handle != ATT_CHARACTERISTIC_0000FF11_0000_1000_8000_00805F9B34FB_01_CLIENT_CONFIGURATION_HANDLE) return 0;
    le_notification_enabled = little_endian_read_16(buffer, 0) == GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION;
    con_handle = connection_handle;
    return 0;
}