Пример #1
0
static void emit_mtu_exchange_complete(btstack_packet_handler_t packet_handler, hci_con_handle_t con_handle, uint16_t new_mtu){
    if (!packet_handler) return;
    uint8_t packet[6];
    packet[0] = ATT_EVENT_MTU_EXCHANGE_COMPLETE;
    packet[1] = sizeof(packet) - 2;
    little_endian_store_16(packet, 2, con_handle);
    little_endian_store_16(packet, 4, new_mtu);
    packet_handler(HCI_EVENT_PACKET, con_handle, packet, 1);
}
Пример #2
0
// SDP Parser
static void sdp_parser_emit_value_byte(uint8_t event_byte){
    uint8_t event[11];
    event[0] = SDP_EVENT_QUERY_ATTRIBUTE_VALUE;
    event[1] = 9;
    little_endian_store_16(event, 2, record_counter);
    little_endian_store_16(event, 4, attribute_id);
    little_endian_store_16(event, 6, attribute_value_size);
    little_endian_store_16(event, 8, attribute_bytes_delivered);
    event[10] = event_byte;
    (*sdp_parser_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 
}
Пример #3
0
static void notify_client_text(int event_type){
    if (!client_handler) return;
    uint8_t event[7 + sizeof(ancs_notification_buffer) + 1];
    event[0] = HCI_EVENT_ANCS_META;
    event[1] = 5 + ancs_attribute_len;
    event[2] = event_type;
    little_endian_store_16(event, 3, gc_handle);
    little_endian_store_16(event, 5, ancs_attribute_id);
    memcpy(&event[7], ancs_notification_buffer, ancs_attribute_len);
    // we're nice
    event[7+ancs_attribute_len] = 0;
    (*client_handler)(HCI_EVENT_PACKET, 0, event, event[1] + 2);
}
Пример #4
0
static void att_emit_mtu_event(hci_con_handle_t con_handle, uint16_t mtu){
    if (!att_client_packet_handler) return;

    uint8_t event[6];
    int pos = 0;
    event[pos++] = ATT_EVENT_MTU_EXCHANGE_COMPLETE;
    event[pos++] = sizeof(event) - 2;
    little_endian_store_16(event, pos, con_handle);
    pos += 2;
    little_endian_store_16(event, pos, mtu);
    att_dispatch_server_mtu_exchanged(con_handle, mtu);
    (*att_client_packet_handler)(HCI_EVENT_PACKET, 0, &event[0], sizeof(event));
}
Пример #5
0
static void att_handle_value_indication_notify_client(uint8_t status, uint16_t client_handle, uint16_t attribute_handle){
    if (!att_client_packet_handler) return;
    
    uint8_t event[7];
    int pos = 0;
    event[pos++] = ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE;
    event[pos++] = sizeof(event) - 2;
    event[pos++] = status;
    little_endian_store_16(event, pos, client_handle);
    pos += 2;
    little_endian_store_16(event, pos, attribute_handle);
    (*att_client_packet_handler)(HCI_EVENT_PACKET, 0, &event[0], sizeof(event));
}
Пример #6
0
void sdp_parser_handle_service_search(uint8_t * data, uint16_t total_count, uint16_t record_handle_count){
    int i;
    for (i=0;i<record_handle_count;i++){
        record_handle = big_endian_read_32(data, i*4);
        record_counter++;
        uint8_t event[10];
        event[0] = SDP_EVENT_QUERY_SERVICE_RECORD_HANDLE;
        event[1] = 8;
        little_endian_store_16(event, 2, total_count);
        little_endian_store_16(event, 4, record_counter);
        little_endian_store_32(event, 6, record_handle);
        (*sdp_parser_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 
    }        
}
Пример #7
0
static void att_server_persistent_ccc_restore(att_server_t * att_server){
    if (!att_server) return;
    int le_device_index = att_server->ir_le_device_db_index;
    log_info("Restore CCC values of remote %s, le device id %d", bd_addr_to_str(att_server->peer_address), le_device_index);
    // check if bonded
    if (le_device_index < 0) return;
    // get btstack_tlv
    const btstack_tlv_t * tlv_impl = NULL;
    void * tlv_context;
    btstack_tlv_get_instance(&tlv_impl, &tlv_context);
    if (!tlv_impl) return;
    // get all ccc tag
    int index;
    persistent_ccc_entry_t entry;
    for (index=0;index<NVN_NUM_GATT_SERVER_CCC;index++){
        uint32_t tag = att_server_persistent_ccc_tag_for_index(index);
        int len = tlv_impl->get_tag(tlv_context, tag, (uint8_t *) &entry, sizeof(persistent_ccc_entry_t));
        if (len != sizeof(persistent_ccc_entry_t)) continue;
        if (entry.device_index != le_device_index) continue;
        // simulate write callback
        uint16_t attribute_handle = entry.att_handle;
        uint8_t  value[2];
        little_endian_store_16(value, 0, entry.value);
        att_write_callback_t callback = att_server_write_callback_for_handle(attribute_handle);
        if (!callback) continue;
        log_info("CCC Index %u: Set Attribute handle 0x%04x to value 0x%04x", index, attribute_handle, entry.value );
        (*callback)(att_server->connection.con_handle, attribute_handle, ATT_TRANSACTION_MODE_NONE, 0, value, sizeof(value));
    }
}
Пример #8
0
static int host_recv_pkt_cb(uint8_t *data, uint16_t len){

    if (xPortInIsrContext()){
        report_recv_called_from_isr();
        return 0;
    }

    xSemaphoreTake(ring_buffer_mutex, portMAX_DELAY);

    // check space
    uint16_t space = btstack_ring_buffer_bytes_free(&hci_ringbuffer);
    if (space < len){
        xSemaphoreGive(ring_buffer_mutex);
        log_error("transport_recv_pkt_cb packet %u, space %u -> dropping packet", len, space);
        return 0;
    }

    // store size in ringbuffer
    uint8_t len_tag[2];
    little_endian_store_16(len_tag, 0, len);
    btstack_ring_buffer_write(&hci_ringbuffer, len_tag, sizeof(len_tag));

    // store in ringbuffer
    btstack_ring_buffer_write(&hci_ringbuffer, data, len);

    xSemaphoreGive(ring_buffer_mutex);

    // set flag and trigger delivery of packets on main thread
    transport_packets_to_deliver = 1;
    btstack_run_loop_freertos_trigger();
    return 0;
}
Пример #9
0
static void notify_client_simple(int event_type){
    if (!client_handler) return;
    uint8_t event[5];
    event[0] = HCI_EVENT_ANCS_META;
    event[1] = 3;
    event[2] = event_type;
    little_endian_store_16(event, 3, gc_handle);
    (*client_handler)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
Пример #10
0
static void emit_event_audio_connected(uint8_t status, uint16_t handle){
    if (!hsp_hs_callback) return;
    uint8_t event[6];
    event[0] = HCI_EVENT_HSP_META;
    event[1] = sizeof(event) - 2;
    event[2] = HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE;
    event[3] = status;
    little_endian_store_16(event, 4, handle);
    (*hsp_hs_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
Пример #11
0
// 8 kHz samples for CVSD/SCO packets in little endian
static void sco_demo_sine_wave_int16_at_8000_hz_little_endian(unsigned int num_samples, uint8_t * data){
    unsigned int i;
    for (i=0; i < num_samples; i++){
        int16_t sample = sine_int16_at_16000hz[phase];
        little_endian_store_16(data, i * 2, sample);
        // ony use every second sample from 16khz table to get 8khz
        phase += 2;
        if (phase >= (sizeof(sine_int16_at_16000hz) / sizeof(int16_t))){
            phase = 0;
        }
    }
}
Пример #12
0
static void a2dp_streaming_emit_can_send_media_packet_now(btstack_packet_handler_t callback, uint16_t cid, uint8_t seid){
    if (!callback) return;
    uint8_t event[8];
    int pos = 0;
    event[pos++] = HCI_EVENT_A2DP_META;
    event[pos++] = sizeof(event) - 2;
    event[pos++] = A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW;
    little_endian_store_16(event, pos, cid);
    pos += 2;
    event[pos++] = seid;
    (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
Пример #13
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);
}
Пример #14
0
static uint16_t battery_service_read_callback(hci_con_handle_t con_handle, uint16_t attribute_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size){
	UNUSED(offset);
	UNUSED(buffer_size);

	if (attribute_handle == battery_value_handle_value){
		if (buffer) {
			buffer[0] = battery_value;
		}
		return 1;
	}
	if (attribute_handle == battery_value_handle_client_configuration){
		if (buffer){
			little_endian_store_16(buffer, 0, battery_value_client_configuration);
			battery_value_client_configuration_connection = con_handle;
		}
		return 2;
	}
	return 0;
}
Пример #15
0
void sco_demo_send(hci_con_handle_t sco_handle){

    if (!sco_handle) return;
    
    const int sco_packet_length = 24 + 3; // hci_get_sco_packet_length();
    const int sco_payload_length = sco_packet_length - 3;

    hci_reserve_packet_buffer();
    uint8_t * sco_packet = hci_get_outgoing_packet_buffer();
    // set handle + flags
    little_endian_store_16(sco_packet, 0, sco_handle);
    // set len
    sco_packet[2] = sco_payload_length;
    const int frames_per_packet = sco_payload_length;    // for 8-bit data. for 16-bit data it's /2

#if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE
    int i;
    for (i=0;i<frames_per_packet;i++){
        sco_packet[3+i] = sine[phase];
        phase++;
        if (phase >= sizeof(sine)) phase = 0;
    }
#else
#if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII
    memset(&sco_packet[3], phase++, frames_per_packet);
    if (phase > 'z') phase = 'a';
#else
    int j;
    for (j=0;j<frames_per_packet;j++){
        sco_packet[3+j] = phase++;
    }
#endif
#endif
    hci_send_sco_packet_buffer(sco_packet_length);

    // request another send event
    hci_request_sco_can_send_now_event();

    count_sent++;
    if ((count_sent % SCO_REPORT_PERIOD) == 0) sco_report();
}
Пример #16
0
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
    UNUSED(channel);
    UNUSED(size);

    uint8_t signal_identifier;
    uint8_t status;
    uint8_t local_seid;
    uint8_t remote_seid;
    uint16_t cid;
    bd_addr_t address;
    
    if (packet_type != HCI_EVENT_PACKET) return;
    if (hci_event_packet_get_type(packet) != HCI_EVENT_AVDTP_META) return;
    
    switch (packet[2]){
        case AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED:
            avdtp_subevent_signaling_connection_established_get_bd_addr(packet, sc.remote_addr);
            cid = avdtp_subevent_signaling_connection_established_get_avdtp_cid(packet);
            status = avdtp_subevent_signaling_connection_established_get_status(packet);
            if (status != 0){
                log_info("AVDTP_SUBEVENT_SIGNALING_CONNECTION failed status %d ---", status);
                a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, cid, sc.remote_addr, 0, 0, status);
                break;
            }
            
            sc.active_remote_sep = NULL;
            next_remote_sep_index_to_query = 0;
            if (!sc.local_stream_endpoint) {
                app_state = A2DP_CONNECTED;
                uint8_t event[11];
                int pos = 0;
                event[pos++] = HCI_EVENT_A2DP_META;
                event[pos++] = sizeof(event) - 2;
                event[pos++] = A2DP_SUBEVENT_INCOMING_CONNECTION_ESTABLISHED;
                little_endian_store_16(event, pos, cid);
                pos += 2;
                reverse_bd_addr(event+pos, sc.remote_addr);
                pos += 6;
                (*a2dp_source_context.a2dp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
                return;
            }

            app_state = A2DP_W2_DISCOVER_SEPS;
            avdtp_source_discover_stream_endpoints(cid);
            break;
        
        case AVDTP_SUBEVENT_SIGNALING_SEP_FOUND:
            break;

        case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY:{
            if (!sc.local_stream_endpoint) {
                // printf("local seid %d \n", avdtp_subevent_signaling_media_codec_sbc_capability_get_local_seid(packet));
                return;
            }
            uint8_t sampling_frequency = avdtp_choose_sbc_sampling_frequency(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_sampling_frequency_bitmap(packet));
            uint8_t channel_mode = avdtp_choose_sbc_channel_mode(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_channel_mode_bitmap(packet));
            uint8_t block_length = avdtp_choose_sbc_block_length(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_block_length_bitmap(packet));
            uint8_t subbands = avdtp_choose_sbc_subbands(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_subbands_bitmap(packet));
            
            uint8_t allocation_method = avdtp_choose_sbc_allocation_method(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_allocation_method_bitmap(packet));
            uint8_t max_bitpool_value = avdtp_choose_sbc_max_bitpool_value(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_max_bitpool_value(packet));
            uint8_t min_bitpool_value = avdtp_choose_sbc_min_bitpool_value(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_min_bitpool_value(packet));

            sc.local_stream_endpoint->remote_configuration.media_codec.media_codec_information[0] = (sampling_frequency << 4) | channel_mode;
            sc.local_stream_endpoint->remote_configuration.media_codec.media_codec_information[1] = (block_length << 4) | (subbands << 2) | allocation_method;
            sc.local_stream_endpoint->remote_configuration.media_codec.media_codec_information[2] = min_bitpool_value;
            sc.local_stream_endpoint->remote_configuration.media_codec.media_codec_information[3] = max_bitpool_value;

            sc.local_stream_endpoint->remote_configuration_bitmap = store_bit16(sc.local_stream_endpoint->remote_configuration_bitmap, AVDTP_MEDIA_CODEC, 1);
            sc.local_stream_endpoint->remote_configuration.media_codec.media_type = AVDTP_AUDIO;
            sc.local_stream_endpoint->remote_configuration.media_codec.media_codec_type = AVDTP_CODEC_SBC;

            app_state = A2DP_W2_SET_CONFIGURATION;
            break;
        }
        case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY:
            log_info("received non SBC codec. not implemented");
            break;
        
        case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION:{
            // TODO check cid
            sc.sampling_frequency = avdtp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(packet);
            sc.block_length = avdtp_subevent_signaling_media_codec_sbc_configuration_get_block_length(packet);
            sc.subbands = avdtp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet);
            sc.allocation_method = avdtp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet) - 1;
            sc.max_bitpool_value = avdtp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(packet);
            sc.channel_mode = avdtp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet);
            // TODO: deal with reconfigure: avdtp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet);
            break;
        }  
        case AVDTP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW: 
            cid = avdtp_subevent_streaming_can_send_media_packet_now_get_avdtp_cid(packet);
            a2dp_streaming_emit_can_send_media_packet_now(a2dp_source_context.a2dp_callback, cid, 0);
            break;
        
        case AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED:
            avdtp_subevent_streaming_connection_established_get_bd_addr(packet, address);
            status = avdtp_subevent_streaming_connection_established_get_status(packet);
            cid = avdtp_subevent_streaming_connection_established_get_avdtp_cid(packet);
            remote_seid = avdtp_subevent_streaming_connection_established_get_remote_seid(packet);
            local_seid  = avdtp_subevent_streaming_connection_established_get_local_seid(packet);
            if (status != 0){
                log_info("AVDTP_SUBEVENT_STREAMING_CONNECTION could not be established, status %d ---", status);
                a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, cid, address, local_seid, remote_seid, status);
                break;
            }

            app_state = A2DP_STREAMING_OPENED;
            a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, cid, address, local_seid, remote_seid, 0);
            log_info("AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED --- avdtp_cid 0x%02x, local seid %d, remote seid %d", cid, local_seid, remote_seid);
            break;

        case AVDTP_SUBEVENT_SIGNALING_ACCEPT:
            // TODO check cid
            signal_identifier = avdtp_subevent_signaling_accept_get_signal_identifier(packet);
            cid = avdtp_subevent_signaling_accept_get_avdtp_cid(packet);
            log_info("Accepted %d", signal_identifier);
            
            switch (app_state){
                case A2DP_W2_DISCOVER_SEPS:
                    app_state = A2DP_W2_GET_ALL_CAPABILITIES;
                    
                    sc.active_remote_sep = avdtp_source_remote_sep(cid, next_remote_sep_index_to_query++);
                    if (!sc.active_remote_sep) {
                        app_state = A2DP_IDLE; 
                        a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, cid, sc.remote_addr, 0, 0, AVDTP_SEID_DOES_NOT_EXIST);
                        break;
                    }
                    // printf("Query get caps for seid %d\n", sc.active_remote_sep->seid);
                    avdtp_source_get_capabilities(cid, sc.active_remote_sep->seid);
                    break;
                case A2DP_W2_GET_CAPABILITIES:
                case A2DP_W2_GET_ALL_CAPABILITIES:
                    if (next_remote_sep_index_to_query < avdtp_source_remote_seps_num(cid)){
                        sc.active_remote_sep = avdtp_source_remote_sep(cid, next_remote_sep_index_to_query++);
                        // printf("Query get caps for seid %d\n", sc.active_remote_sep->seid);
                        avdtp_source_get_capabilities(cid, sc.active_remote_sep->seid);
                    } else {
                        // printf("No more remote seps found\n");
                        app_state = A2DP_IDLE;
                        a2dp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, cid, sc.remote_addr, 0, 0, AVDTP_SEID_DOES_NOT_EXIST);
                    }
                    break;
                case A2DP_W2_SET_CONFIGURATION:{
                    if (!sc.local_stream_endpoint) return;
                    app_state = A2DP_W2_GET_CONFIGURATION;
                    avdtp_source_set_configuration(cid, avdtp_stream_endpoint_seid(sc.local_stream_endpoint), sc.active_remote_sep->seid, sc.local_stream_endpoint->remote_configuration_bitmap, sc.local_stream_endpoint->remote_configuration);
                    break;
                }
                case A2DP_W2_GET_CONFIGURATION:
                    app_state = A2DP_W2_OPEN_STREAM_WITH_SEID;
                    avdtp_source_get_configuration(cid, sc.active_remote_sep->seid);
                    break;
                case A2DP_W2_OPEN_STREAM_WITH_SEID:{
                    app_state = A2DP_W4_OPEN_STREAM_WITH_SEID;
                    btstack_sbc_encoder_init(&sc.sbc_encoder_state, SBC_MODE_STANDARD, 
                        sc.block_length, sc.subbands, 
                        sc.allocation_method, sc.sampling_frequency, 
                        sc.max_bitpool_value,
                        sc.channel_mode);
                    avdtp_source_open_stream(cid, avdtp_stream_endpoint_seid(sc.local_stream_endpoint), sc.active_remote_sep->seid);
                    break;
                }
                case A2DP_STREAMING_OPENED:
                    if (!a2dp_source_context.a2dp_callback) return;
                    switch (signal_identifier){
                        case  AVDTP_SI_START:{
                            uint8_t event[6];
                            int pos = 0;
                            event[pos++] = HCI_EVENT_A2DP_META;
                            event[pos++] = sizeof(event) - 2;
                            event[pos++] = A2DP_SUBEVENT_STREAM_STARTED;
                            little_endian_store_16(event, pos, cid);
                            pos += 2;
                            event[pos++] = avdtp_stream_endpoint_seid(sc.local_stream_endpoint);
                            (*a2dp_source_context.a2dp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
                            break;
                        }
                        case AVDTP_SI_SUSPEND:{
                            uint8_t event[6];
                            int pos = 0;
                            event[pos++] = HCI_EVENT_A2DP_META;
                            event[pos++] = sizeof(event) - 2;
                            event[pos++] = A2DP_SUBEVENT_STREAM_SUSPENDED;
                            little_endian_store_16(event, pos, cid);
                            pos += 2;
                            event[pos++] = avdtp_stream_endpoint_seid(sc.local_stream_endpoint);
                            (*a2dp_source_context.a2dp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
                            break;
                        }
                        case AVDTP_SI_ABORT:
                        case AVDTP_SI_CLOSE:{
                            uint8_t event[6];
                            int pos = 0;
                            event[pos++] = HCI_EVENT_A2DP_META;
                            event[pos++] = sizeof(event) - 2;
                            event[pos++] = A2DP_SUBEVENT_STREAM_STOPPED;
                            little_endian_store_16(event, pos, cid);
                            pos += 2;
                            log_info("send A2DP_SUBEVENT_STREAM_RELEASED to app");
                            event[pos++] = avdtp_stream_endpoint_seid(sc.local_stream_endpoint);
                            (*a2dp_source_context.a2dp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
                            break;
                        }
                        default:
                            break;
                    }
                    break;
                default:
                    app_state = A2DP_IDLE;
                    break;
            }
            
            break;
        case AVDTP_SUBEVENT_SIGNALING_REJECT:
            app_state = A2DP_IDLE;
            signal_identifier = avdtp_subevent_signaling_reject_get_signal_identifier(packet);
            log_info("Rejected %d", signal_identifier);
            break;
        case AVDTP_SUBEVENT_SIGNALING_GENERAL_REJECT:
            app_state = A2DP_IDLE;
            signal_identifier = avdtp_subevent_signaling_general_reject_get_signal_identifier(packet);
            log_info("Rejected %d", signal_identifier);
            break;
        case AVDTP_SUBEVENT_SIGNALING_CONNECTION_RELEASED:{
            app_state = A2DP_IDLE;
            uint8_t event[6];
            int pos = 0;
            event[pos++] = HCI_EVENT_A2DP_META;
            event[pos++] = sizeof(event) - 2;
            event[pos++] = A2DP_SUBEVENT_SIGNALING_CONNECTION_RELEASED;
            little_endian_store_16(event, pos, avdtp_subevent_streaming_connection_released_get_avdtp_cid(packet));
            pos += 2;
            event[pos++] = avdtp_subevent_streaming_connection_released_get_local_seid(packet);
            (*a2dp_source_context.a2dp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
            break;
        }
        case AVDTP_SUBEVENT_STREAMING_CONNECTION_RELEASED:{
            app_state = A2DP_IDLE;
            uint8_t event[6];
            int pos = 0;
            event[pos++] = HCI_EVENT_A2DP_META;
            event[pos++] = sizeof(event) - 2;
            event[pos++] = A2DP_SUBEVENT_STREAM_RELEASED;
            little_endian_store_16(event, pos, avdtp_subevent_streaming_connection_released_get_avdtp_cid(packet));
            pos += 2;
            event[pos++] = avdtp_subevent_streaming_connection_released_get_local_seid(packet);
            (*a2dp_source_context.a2dp_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event));
            break;
        }
        default:
            app_state = A2DP_IDLE;
            log_info("not implemented");
            break; 
    }
}
Пример #17
0
static void little_endian_fstore_16(FILE *wav_file, uint16_t value){
    uint8_t buf[2];
    little_endian_store_16(buf, 0, value);
    fwrite(&buf, 1, 2, wav_file);
}
Пример #18
0
void hci_dump_packet(uint8_t packet_type, uint8_t in, uint8_t *packet, uint16_t len) {

    if (dump_file < 0) return; // not activated yet

#ifdef HAVE_POSIX_FILE_IO

    // don't grow bigger than max_nr_packets
    if (dump_format != HCI_DUMP_STDOUT && max_nr_packets > 0){
        if (nr_packets >= max_nr_packets){
            lseek(dump_file, 0, SEEK_SET);
            ftruncate(dump_file, 0);
            nr_packets = 0;
        }
        nr_packets++;
    }
    
    // get time
    struct timeval curr_time;
    struct tm* ptm;
    gettimeofday(&curr_time, NULL);
    time_t curr_time_secs = curr_time.tv_sec;

    switch (dump_format){
        case HCI_DUMP_STDOUT: {
            /* Obtain the time of day, and convert it to a tm struct. */
            ptm = localtime (&curr_time_secs);
            /* assert localtime was successful */
            if (!ptm) break;
            /* Format the date and time, down to a single second. */
            strftime (time_string, sizeof (time_string), "[%Y-%m-%d %H:%M:%S", ptm);
            /* Compute milliseconds from microseconds. */
            uint16_t milliseconds = curr_time.tv_usec / 1000;
            /* Print the formatted time, in seconds, followed by a decimal point and the milliseconds. */
            printf ("%s.%03u] ", time_string, milliseconds);
            printf_packet(packet_type, in, packet, len);
            break;
        }
            
        case HCI_DUMP_BLUEZ:
            little_endian_store_16( header_bluez, 0, 1 + len);
            header_bluez[2] = in;
            header_bluez[3] = 0;
            little_endian_store_32( header_bluez, 4, (uint32_t) curr_time.tv_sec);
            little_endian_store_32( header_bluez, 8,            curr_time.tv_usec);
            header_bluez[12] = packet_type;
            write (dump_file, header_bluez, HCIDUMP_HDR_SIZE);
            write (dump_file, packet, len );
            break;
            
        case HCI_DUMP_PACKETLOGGER:
            big_endian_store_32( header_packetlogger, 0, PKTLOG_HDR_SIZE - 4 + len);
            big_endian_store_32( header_packetlogger, 4,  (uint32_t) curr_time.tv_sec);
            big_endian_store_32( header_packetlogger, 8, curr_time.tv_usec);
            switch (packet_type){
                case HCI_COMMAND_DATA_PACKET:
                    header_packetlogger[12] = 0x00;
                    break;
                case HCI_ACL_DATA_PACKET:
                    if (in) {
                        header_packetlogger[12] = 0x03;
                    } else {
                        header_packetlogger[12] = 0x02;
                    }
                    break;
                case HCI_SCO_DATA_PACKET:
                    if (in) {
                        header_packetlogger[12] = 0x09;
                    } else {
                        header_packetlogger[12] = 0x08;
                    }
                    break;
                case HCI_EVENT_PACKET:
                    header_packetlogger[12] = 0x01;
                    break;
                case LOG_MESSAGE_PACKET:
                    header_packetlogger[12] = 0xfc;
                    break;
                default:
                    return;
            }
            write (dump_file, &header_packetlogger, PKTLOG_HDR_SIZE);
            write (dump_file, packet, len );
            break;
            
        default:
            break;
    }
#else

// #ifdef HAVE_EMBEDDED_TICK
//     uint32_t time_ms = btstack_run_loop_embedded_get_time_ms();
//     printf("[%06u] ", time_ms);
// #endif
    printf_packet(packet_type, in, packet, len);

#endif
}
Пример #19
0
void sco_demo_send(hci_con_handle_t sco_handle){

    if (!sco_handle) return;
    
    int sco_packet_length = hci_get_sco_packet_length();
    int sco_payload_length = sco_packet_length - 3;

    hci_reserve_packet_buffer();
    uint8_t * sco_packet = hci_get_outgoing_packet_buffer();
#if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE
#ifdef ENABLE_HFP_WIDE_BAND_SPEECH
    if (negotiated_codec == HFP_CODEC_MSBC){
        // overwrite
        sco_payload_length = 24;
        sco_packet_length = sco_payload_length + 3;

        if (hfp_msbc_num_bytes_in_stream() < sco_payload_length){
            log_error("mSBC stream is empty.");
        }
        hfp_msbc_read_from_stream(sco_packet + 3, sco_payload_length);
        if (msbc_file_out){
            // log outgoing mSBC data for testing
            fwrite(sco_packet + 3, sco_payload_length, 1, msbc_file_out);
        }

        sco_demo_msbc_fill_sine_audio_frame();
    } else
#endif
    {
        const int audio_samples_per_packet = sco_payload_length / CVSD_BYTES_PER_FRAME;  
        sco_demo_sine_wave_int16_at_8000_hz_little_endian(audio_samples_per_packet, &sco_packet[3]);
    }
#endif

#if SCO_DEMO_MODE == SCO_DEMO_MODE_MICROPHONE

#ifdef HAVE_PORTAUDIO
    if (negotiated_codec == HFP_CODEC_MSBC){
        // MSBC

        // overwrite
        sco_payload_length = 24;
        sco_packet_length = sco_payload_length + 3;

        if (pa_input_paused){
            if (btstack_ring_buffer_bytes_available(&pa_input_ring_buffer) >= MSBC_PA_PREBUFFER_BYTES){
                // resume sending
                pa_input_paused = 0;
            }
        }

        if (!pa_input_paused){
            int num_samples = hfp_msbc_num_audio_samples_per_frame();
            if (hfp_msbc_can_encode_audio_frame_now() && btstack_ring_buffer_bytes_available(&pa_input_ring_buffer) >= (num_samples * MSBC_BYTES_PER_FRAME)){
                int16_t sample_buffer[num_samples];
                uint32_t bytes_read;
                btstack_ring_buffer_read(&pa_input_ring_buffer, (uint8_t*) sample_buffer, num_samples * MSBC_BYTES_PER_FRAME, &bytes_read);
                hfp_msbc_encode_audio_frame(sample_buffer);
                num_audio_frames++;
            }
        }

        if (hfp_msbc_num_bytes_in_stream() < sco_payload_length){
            log_error("mSBC stream should not be empty.");
            memset(sco_packet + 3, 0, sco_payload_length);
            pa_input_paused = 1;
        } else {
            hfp_msbc_read_from_stream(sco_packet + 3, sco_payload_length);
            if (msbc_file_out){
                // log outgoing mSBC data for testing
                fwrite(sco_packet + 3, sco_payload_length, 1, msbc_file_out);
            }
        }

    } else {
        // CVSD

        log_info("send: bytes avail %u, free %u, counter %u", btstack_ring_buffer_bytes_available(&pa_input_ring_buffer), btstack_ring_buffer_bytes_free(&pa_input_ring_buffer), pa_input_counter);
        // fill with silence while paused
        int bytes_to_copy = sco_payload_length;
        if (pa_input_paused){
            if (btstack_ring_buffer_bytes_available(&pa_input_ring_buffer) >= CVSD_PA_PREBUFFER_BYTES){
                // resume sending
                pa_input_paused = 0;
            }
        }

        // get data from ringbuffer
        uint16_t pos = 0;
        uint8_t * sample_data = &sco_packet[3];
        if (!pa_input_paused){
            uint32_t bytes_read = 0;
            btstack_ring_buffer_read(&pa_input_ring_buffer, sample_data, bytes_to_copy, &bytes_read);
            // flip 16 on big endian systems
            // @note We don't use (uint16_t *) casts since all sample addresses are odd which causes crahses on some systems
            if (btstack_is_big_endian()){
                int i;
                for (i=0;i<bytes_read;i+=2){
                    uint8_t tmp        = sample_data[i*2];
                    sample_data[i*2]   = sample_data[i*2+1];
                    sample_data[i*2+1] = tmp;
                }
            }
            bytes_to_copy -= bytes_read;
            pos           += bytes_read;
        }

        // fill with 0 if not enough
        if (bytes_to_copy){
            memset(sample_data + pos, 0, bytes_to_copy);
            pa_input_paused = 1;
        }
    }
#else
    // just send '0's
    if (negotiated_codec == HFP_CODEC_MSBC){
        sco_payload_length = 24;
        sco_packet_length = sco_payload_length + 3;
    }
    memset(sco_packet + 3, 0, sco_payload_length);
#endif
#endif

#if SCO_DEMO_MODE == SCO_DEMO_MODE_ASCII
    memset(&sco_packet[3], phase++, sco_payload_length);
    if (phase > 'z') phase = 'a';
#endif
#if SCO_DEMO_MODE == SCO_DEMO_MODE_COUNTER
    int j;
    for (j=0;j<sco_payload_length;j++){
        sco_packet[3+j] = phase++;
    }
#endif
#if SCO_DEMO_MODE == SCO_DEMO_MODE_55
    int j;
    for (j=0;j<sco_payload_length;j++){
        // sco_packet[3+j] = j & 1 ? 0x35 : 0x53;
        sco_packet[3+j] = 0x55;
    }
#endif
#if SCO_DEMO_MODE == SCO_DEMO_MODE_00
    int j;
    for (j=0;j<sco_payload_length;j++){
        sco_packet[3+j] = 0x00;
    }
    // additional hack
    // big_endian_store_16(sco_packet, 5, phase++);
    (void) phase;
#endif

    // test silence
    // memset(sco_packet+3, 0, sco_payload_length);

    // set handle + flags
    little_endian_store_16(sco_packet, 0, sco_handle);
    // set len
    sco_packet[2] = sco_payload_length;
    // finally send packet 
    hci_send_sco_packet_buffer(sco_packet_length);

    // request another send event
    hci_request_sco_can_send_now_event();

    count_sent++;
#if SCO_DEMO_MODE != SCO_DEMO_MODE_55
    if ((count_sent % SCO_REPORT_PERIOD) == 0) sco_report();
#endif
}