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 ); }
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(); }
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); }
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); }
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; } }
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 }