Ejemplo n.º 1
0
    void btstack_libusb_device_base::send_notification( std::uint8_t* buffer, std::size_t size )
    {
        log_info( "*ATT-Notification: %i", size );
        hexdump( buffer, size );

        hci_reserve_packet_buffer();
        uint8_t     *acl_buffer      = hci_get_outgoing_packet_buffer();
        std::size_t out_buffer_size  = mtu_size_;

        std::copy( buffer, buffer + size, acl_buffer );

        send_acl_package( acl_buffer, size + hci_header_size );
    }
Ejemplo n.º 2
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();
}
Ejemplo n.º 3
0
static void try_send_sco(void) {
    printf("try send handle %x\n", sco_handle);
    if (!sco_handle) return;
    if (!hci_can_send_sco_packet_now(sco_handle)) {
        printf("try_send_sco, cannot send now\n");
        return;
    }
    const int frames_per_packet = 9;
    hci_reserve_packet_buffer();
    uint8_t * sco_packet = hci_get_outgoing_packet_buffer();
    // set handle + flags
    bt_store_16(sco_packet, 0, sco_handle);
    // set len
    sco_packet[2] = frames_per_packet;
    int i;
    for (i=0; i<frames_per_packet; i++) {
        sco_packet[3+i] = sine[phase];
        phase++;
        if (phase >= TABLE_SIZE) phase = 0;
    }
    hci_send_sco_packet_buffer(3 + frames_per_packet);
}
Ejemplo n.º 4
0
static void try_send_sco(void){
    if (!sco_handle) return;
    if (!hci_can_send_sco_packet_now(sco_handle)) {
        // printf("try_send_sco, cannot send now\n");
        return;
    }
    const int frames_per_packet = 180;
    hci_reserve_packet_buffer();
    uint8_t * sco_packet = hci_get_outgoing_packet_buffer();
    // set handle + flags
    bt_store_16(sco_packet, 0, sco_handle);
    // set len
    sco_packet[2] = frames_per_packet;
    int i;
    for (i=0;i<frames_per_packet;i++){
        sco_packet[3+i] = sine[phase];
        phase++;
        if (phase >= sizeof(sine)) phase = 0;
    }
    hci_send_sco_packet_buffer(3 + frames_per_packet);
    static int count = 0;
    count++;
    if ((count & 15) == 0) printf("Sent %u\n", count);
}
Ejemplo n.º 5
0
    void btstack_libusb_device_base::btstack_packet_handler( std::uint8_t packet_type, std::uint8_t *packet, std::uint16_t size)
    {
        bool no_log = false;

        switch (packet_type) {
            case HCI_EVENT_PACKET:
                log_info( "*HCI_EVENT_PACKET: %i; size: %lu", packet_type, size );

                if ( size >= 2 )
                {
                    const std::uint8_t event_code       = packet[ 0 ];
                    const std::uint8_t parameter_length = packet[ 1 ];
                    packet += 2;

                    if ( parameter_length  + 2 == size )
                    {
                        handle_event( event_code, parameter_length, packet );
                    }
                    else
                    {
                        log_error( "!!unresonable HCI_EVENT_parameter_length: %i; size: %lu plength: %lu", packet_type, size, parameter_length );
                    }
                }
                else
                {
                    log_error( "!!unresonable HCI_EVENT_SIZE: %i; size: %lu", packet_type, size);
                }

                break;
            case HCI_ACL_DATA_PACKET:
                log_info( "*HCI_ACL_DATA_PACKET: %i; size: %lu", packet_type, size );

                if ( size > 8 )
                {
                    hexdump( packet, size );
                    const std::uint16_t hci_length       = read_u16( packet + 2 );
                    const std::uint16_t l2cap_length     = read_u16( packet + 4 );
                    const std::uint16_t l2cap_channel_id = read_u16( packet + 6 );

                    if ( l2cap_channel_id == 0x0004 && l2cap_length == size - 8 && hci_length == size - 4 )
                    {
                        size    -= hci_header_size;
                        packet  += hci_header_size;
                        log_info( "*ATT-Command: %i", size );
                        hexdump( packet, size ), no_log = true;

                        hci_reserve_packet_buffer();
                        uint8_t     *acl_buffer      = hci_get_outgoing_packet_buffer();
                        std::size_t out_buffer_size  = mtu_size_;

                        l2cap_input_( packet, size, acl_buffer + hci_header_size, out_buffer_size );

                        send_acl_package( acl_buffer, out_buffer_size + hci_header_size );
                    }
                }
                break;
            default:
                break;
        }

        if ( !no_log )
            hexdump( packet, size );

        static int init_phase = 0;

        if ( hci_can_send_command_packet_now() && init_phase < 100 )
        {
            if ( init_phase == 0 )
            {
                std::uint8_t      adv_data[ 31 ] = { 0 };
                const std::size_t size           = advertising_data_( adv_data, sizeof( adv_data ) );

                hci_send_cmd( &hci_le_set_advertising_data, size, adv_data );
            }
            else if ( init_phase == 1 )
            {
                hci_send_cmd( &hci_le_set_advertise_enable, 1 );
            }

            ++init_phase;
        }
    }
Ejemplo n.º 6
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
}