static void gap_run(){ if (!hci_can_send_command_packet_now()) return; if (todos & SET_ADVERTISEMENT_DATA){ printf("GAP_RUN: set advertisement data\n"); todos &= ~SET_ADVERTISEMENT_DATA; hci_send_cmd(&hci_le_set_advertising_data, adv_data_len, adv_data); return; } if (todos & SET_ADVERTISEMENT_PARAMS){ todos &= ~SET_ADVERTISEMENT_PARAMS; uint8_t adv_type = 0; // default bd_addr_t null_addr; memset(null_addr, 0, 6); uint16_t adv_int_min = 0x0030; uint16_t adv_int_max = 0x0030; hci_send_cmd(&hci_le_set_advertising_parameters, adv_int_min, adv_int_max, adv_type, 0, 0, &null_addr, 0x07, 0x00); return; } if (todos & ENABLE_ADVERTISEMENTS){ printf("GAP_RUN: enable advertisements\n"); todos &= ~ENABLE_ADVERTISEMENTS; hci_send_cmd(&hci_le_set_advertise_enable, 1); return; } }
static void gap_run(){ if (!hci_can_send_command_packet_now()) return; if (todos & DISABLE_ADVERTISEMENTS){ todos &= ~DISABLE_ADVERTISEMENTS; printf("GAP_RUN: disable advertisements\n"); advertisements_enabled = 0; hci_send_cmd(&hci_le_set_advertise_enable, 0); return; } if (todos & SET_ADVERTISEMENT_DATA){ printf("GAP_RUN: set advertisement data\n"); todos &= ~SET_ADVERTISEMENT_DATA; hci_send_cmd(&hci_le_set_advertising_data, adv_data_len, adv_data); return; } if (todos & SET_ADVERTISEMENT_PARAMS){ todos &= ~SET_ADVERTISEMENT_PARAMS; uint8_t adv_type = gap_adv_type(); bd_addr_t null_addr; memset(null_addr, 0, 6); uint16_t adv_int_min = 0x800; uint16_t adv_int_max = 0x800; switch (adv_type){ case 0: case 2: case 3: hci_send_cmd(&hci_le_set_advertising_parameters, adv_int_min, adv_int_max, adv_type, gap_random, 0, &null_addr, 0x07, 0x00); break; case 1: case 4: hci_send_cmd(&hci_le_set_advertising_parameters, adv_int_min, adv_int_max, adv_type, gap_random, tester_address_type, &tester_address, 0x07, 0x00); break; } return; } if (todos & SET_SCAN_RESPONSE_DATA){ printf("GAP_RUN: set scan response data\n"); todos &= ~SET_SCAN_RESPONSE_DATA; hci_send_cmd(&hci_le_set_scan_response_data, adv_data_len, adv_data); // hack for menu if ((todos & ENABLE_ADVERTISEMENTS) == 0) show_usage(); return; } if (todos & ENABLE_ADVERTISEMENTS){ printf("GAP_RUN: enable advertisements\n"); todos &= ~ENABLE_ADVERTISEMENTS; advertisements_enabled = 1; hci_send_cmd(&hci_le_set_advertise_enable, 1); show_usage(); return; } }
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; } }
static void hsp_run(void){ int err; if (ag_send_ok){ ag_send_ok = 0; err = hsp_ag_send_str_over_rfcomm(rfcomm_cid, HSP_AG_OK); if (err){ ag_send_ok = 1; } return; } if (ag_send_error){ ag_send_error = 0; err = hsp_ag_send_str_over_rfcomm(rfcomm_cid, HSP_AG_ERROR); if (err) { ag_send_error = 1; } return; } switch (hsp_state){ case HSP_SDP_QUERY_RFCOMM_CHANNEL: hsp_state = HSP_W4_SDP_QUERY_COMPLETE; log_info("Start SDP query %s, 0x%02x", bd_addr_to_str(remote), SDP_HSP); sdp_query_rfcomm_channel_and_name_for_uuid(remote, SDP_HSP); break; case HSP_W4_RING_ANSWER: if (ag_ring){ ag_ring = 0; err = hsp_ag_send_str_over_rfcomm(rfcomm_cid, HSP_AG_RING); if (err) { ag_ring = 1; } break; } if (!ag_num_button_press_received) break; ag_send_ok = 0; ag_num_button_press_received = 0; hsp_state = HSP_W2_CONNECT_SCO; err = hsp_ag_send_str_over_rfcomm(rfcomm_cid, HSP_AG_OK); if (err) { hsp_state = HSP_W4_RING_ANSWER; ag_num_button_press_received = 1; } break; case HSP_W2_CONNECT_SCO: if (!hci_can_send_command_packet_now()) break; hsp_state = HSP_W4_SCO_CONNECTED; hci_send_cmd(&hci_setup_synchronous_connection, rfcomm_handle, 8000, 8000, 0xFFFF, hci_get_sco_voice_setting(), 0xFF, 0x003F); break; case HSP_W2_DISCONNECT_SCO: ag_num_button_press_received = 0; hsp_state = HSP_W4_SCO_DISCONNECTED; gap_disconnect(sco_handle); break; case HSP_W2_DISCONNECT_RFCOMM: hsp_state = HSP_W4_RFCOMM_DISCONNECTED; rfcomm_disconnect_internal(rfcomm_cid); break; case HSP_ACTIVE: if (ag_microphone_gain >= 0){ int gain = ag_microphone_gain; ag_microphone_gain = -1; char buffer[10]; sprintf(buffer, "%s=%d\r\n", HSP_MICROPHONE_GAIN, gain); err = hsp_ag_send_str_over_rfcomm(rfcomm_cid, buffer); if (err) { ag_microphone_gain = gain; } break; } if (ag_speaker_gain >= 0){ int gain = ag_speaker_gain; ag_speaker_gain = -1; char buffer[10]; sprintf(buffer, "%s=%d\r\n", HSP_SPEAKER_GAIN, gain); err = hsp_ag_send_str_over_rfcomm(rfcomm_cid, buffer); if (err) { ag_speaker_gain = gain; } break; } break; default: break; } }
static void hsp_run(void){ if (wait_ok) return; if (hs_accept_sco_connection && hci_can_send_command_packet_now()){ hs_accept_sco_connection = 0; log_info("HSP: sending hci_accept_connection_request."); // remote supported feature eSCO is set if link type is eSCO // eSCO: S4 - max latency == transmission interval = 0x000c == 12 ms, uint16_t max_latency; uint8_t retransmission_effort; uint16_t packet_types; if (hci_remote_esco_supported(rfcomm_handle)){ max_latency = 0x000c; retransmission_effort = 0x02; packet_types = 0x388; } else { max_latency = 0xffff; retransmission_effort = 0xff; packet_types = 0x003f; } uint16_t sco_voice_setting = hci_get_sco_voice_setting(); log_info("HFP: sending hci_accept_connection_request, sco_voice_setting %02x", sco_voice_setting); hci_send_cmd(&hci_accept_synchronous_connection, remote, 8000, 8000, max_latency, sco_voice_setting, retransmission_effort, packet_types); return; } if (hsp_release_audio_connection){ if (!rfcomm_can_send_packet_now(rfcomm_cid)) { rfcomm_request_can_send_now_event(rfcomm_cid); return; } hsp_release_audio_connection = 0; wait_ok = 1; hsp_hs_send_str_over_rfcomm(rfcomm_cid, HSP_HS_AT_CKPD); return; } if (hsp_disconnect_rfcomm){ hsp_disconnect_rfcomm = 0; hsp_establish_audio_connection = 0; rfcomm_disconnect(rfcomm_cid); return; } if (hsp_establish_audio_connection){ if (!rfcomm_can_send_packet_now(rfcomm_cid)) { rfcomm_request_can_send_now_event(rfcomm_cid); return; } hsp_establish_audio_connection = 0; wait_ok = 1; hsp_hs_send_str_over_rfcomm(rfcomm_cid, HSP_HS_AT_CKPD); return; } if (hs_send_button_press){ if (!rfcomm_can_send_packet_now(rfcomm_cid)) { rfcomm_request_can_send_now_event(rfcomm_cid); return; } hs_send_button_press = 0; wait_ok = 1; hsp_hs_send_str_over_rfcomm(rfcomm_cid, HSP_HS_AT_CKPD); return; } switch (hsp_state){ case HSP_SDP_QUERY_RFCOMM_CHANNEL: hsp_state = HSP_W4_SDP_QUERY_COMPLETE; sdp_client_query_rfcomm_channel_and_name_for_uuid(&handle_query_rfcomm_event, remote, BLUETOOTH_SERVICE_CLASS_HEADSET_AUDIO_GATEWAY_AG); break; case HSP_AUDIO_CONNECTION_ESTABLISHED: case HSP_RFCOMM_CONNECTION_ESTABLISHED: if (hs_microphone_gain >= 0){ if (!rfcomm_can_send_packet_now(rfcomm_cid)) { rfcomm_request_can_send_now_event(rfcomm_cid); return; } char buffer[20]; sprintf(buffer, "%s=%d\r\n", HSP_HS_MICROPHONE_GAIN, hs_microphone_gain); hsp_hs_send_str_over_rfcomm(rfcomm_cid, buffer); hs_microphone_gain = -1; break; } if (hs_speaker_gain >= 0){ if (!rfcomm_can_send_packet_now(rfcomm_cid)) { rfcomm_request_can_send_now_event(rfcomm_cid); return; } char buffer[20]; sprintf(buffer, "%s=%d\r\n", HSP_HS_SPEAKER_GAIN, hs_speaker_gain); hsp_hs_send_str_over_rfcomm(rfcomm_cid, buffer); hs_speaker_gain = -1; break; } break; case HSP_W4_RFCOMM_DISCONNECTED: rfcomm_disconnect(rfcomm_cid); break; default: break; } }