static int hfp_ag_run_for_audio_connection(hfp_connection_t * context){ if (context->state < HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED || context->state > HFP_W2_DISCONNECT_SCO) return 0; if (context->state == HFP_AUDIO_CONNECTION_ESTABLISHED && context->release_audio_connection){ context->state = HFP_W4_SCO_DISCONNECTED; context->release_audio_connection = 0; gap_disconnect(context->sco_handle); return 1; } if (context->state == HFP_AUDIO_CONNECTION_ESTABLISHED) return 0; // run codecs exchange int done = codecs_exchange_state_machine(context); if (done) return done; // printf(" -> State machine: Audio Connection\n"); if (context->codecs_state != HFP_CODECS_EXCHANGED) return done; if (context->establish_audio_connection){ context->state = HFP_W4_SCO_CONNECTED; context->establish_audio_connection = 0; hci_send_cmd(&hci_setup_synchronous_connection, context->con_handle, 8000, 8000, 0xFFFF, hci_get_sco_voice_setting(), 0xFF, 0x003F); return 1; } return 0; }
static void stdin_process(char buffer){ switch (buffer){ case 'c': printf("Creating L2CAP Connection to %s, PSM SDP\n", bd_addr_to_str(remote)); if (l2cap_ertm){ l2cap_create_ertm_channel(packet_handler, remote, BLUETOOTH_PROTOCOL_SDP, &ertm_config, ertm_buffer, sizeof(ertm_buffer), &local_cid); } else { l2cap_create_channel(packet_handler, remote, BLUETOOTH_PROTOCOL_SDP, 100, &local_cid); } break; case 'b': printf("Set channel busy\n"); l2cap_ertm_set_busy(local_cid); break; case 'B': printf("Set channel ready\n"); l2cap_ertm_set_ready(local_cid); break; case 's': printf("Send some L2CAP Data\n"); l2cap_send(local_cid, (uint8_t *) "0123456789", 10); break; case 'S': printf("Send more L2CAP Data\n"); l2cap_send(local_cid, (uint8_t *) "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789", 100); break; case 'd': printf("L2CAP Channel Closed\n"); l2cap_disconnect(local_cid, 0); break; case 'e': printf("L2CAP Enhanced Retransmission Mode (ERTM) optional\n"); l2cap_ertm = 1; ertm_config.ertm_mandatory = 0; break; case 'E': printf("L2CAP Enhanced Retransmission Mode (ERTM) mandatory\n"); l2cap_ertm = 1; ertm_config.ertm_mandatory = 1; break; case 'p': printf("Send L2CAP ECHO Request\n"); l2cap_send_echo_request(handle, (uint8_t *) "Hello World!", 13); break; case 't': printf("Disconnect ACL handle\n"); gap_disconnect(handle); break; case '\n': case '\r': break; default: show_usage(); break; } }
void handle_gatt_client_event(le_event_t * event){ le_service_t service; le_characteristic_t characteristic; switch(state){ case TC_W4_SERVICE_RESULT: switch(event->type){ case GATT_SERVICE_QUERY_RESULT: service = ((le_service_event_t *) event)->service; dump_service(&service); services[service_count++] = service; break; case GATT_QUERY_COMPLETE: state = TC_W4_CHARACTERISTIC_RESULT; service_index = 0; printf("\ntest client - CHARACTERISTIC for SERVICE "); printUUID128(service.uuid128); printf("\n"); gatt_client_discover_characteristics_for_service(gc_handle, &services[service_index]); break; default: break; } break; case TC_W4_CHARACTERISTIC_RESULT: switch(event->type){ case GATT_CHARACTERISTIC_QUERY_RESULT: characteristic = ((le_characteristic_event_t *) event)->characteristic; dump_characteristic(&characteristic); break; case GATT_QUERY_COMPLETE: if (service_index < service_count) { state = TC_W4_CHARACTERISTIC_RESULT; service = services[service_index++]; printf("\ntest client - CHARACTERISTIC for SERVICE "); printUUID128(service.uuid128); printf(", [0x%04x-0x%04x]\n", service.start_group_handle, service.end_group_handle); gatt_client_discover_characteristics_for_service(gc_handle, &service); break; } state = TC_W4_DISCONNECT; service_index = 0; gap_disconnect(gc_handle); break; default: break; } break; default: break; } }
static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ UNUSED(packet_type); UNUSED(channel); UNUSED(size); gatt_client_service_t service; gatt_client_characteristic_t characteristic; switch(hci_event_packet_get_type(packet)){ case GATT_EVENT_SERVICE_QUERY_RESULT:\ gatt_event_service_query_result_get_service(packet, &service); dump_service(&service); services[service_count++] = service; break; case GATT_EVENT_CHARACTERISTIC_QUERY_RESULT: gatt_event_characteristic_query_result_get_characteristic(packet, &characteristic); dump_characteristic(&characteristic); break; case GATT_EVENT_QUERY_COMPLETE: if (search_services){ // GATT_EVENT_QUERY_COMPLETE of search services service_index = 0; printf("\nGATT browser - CHARACTERISTIC for SERVICE %s\n", uuid128_to_str(service.uuid128)); search_services = 0; gatt_client_discover_characteristics_for_service(handle_gatt_client_event, connection_handler, &services[service_index]); } else { // GATT_EVENT_QUERY_COMPLETE of search characteristics if (service_index < service_count) { service = services[service_index++]; printf("\nGATT browser - CHARACTERISTIC for SERVICE %s, [0x%04x-0x%04x]\n", uuid128_to_str(service.uuid128), service.start_group_handle, service.end_group_handle); gatt_client_discover_characteristics_for_service(handle_gatt_client_event, connection_handler, &service); break; } service_index = 0; gap_disconnect(connection_handler); } break; default: break; } }
static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ UNUSED(packet_type); UNUSED(channel); UNUSED(size); int status; char message[30]; 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, &le_counter_service); break; case GATT_EVENT_QUERY_COMPLETE: if (packet[4] != 0){ printf("SERVICE_QUERY_RESULT - Error status %x.\n", packet[4]); gap_disconnect(connection_handle); break; } state = TC_W4_CHARACTERISTIC_RESULT; printf("Search for counter characteristic.\n"); gatt_client_discover_characteristics_for_service_by_uuid128(handle_gatt_client_event, connection_handle, &le_counter_service, le_counter_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, &le_counter_characteristic); break; case GATT_EVENT_QUERY_COMPLETE: if (packet[4] != 0){ printf("CHARACTERISTIC_QUERY_RESULT - Error status %x.\n", packet[4]); gap_disconnect(connection_handle); break; } state = TC_W4_SUBSCRIBED; printf("Configure counter for notify.\n"); status = gatt_client_write_client_characteristic_configuration(handle_gatt_client_event, connection_handle, &le_counter_characteristic, GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION); break; default: break; } break; case TC_W4_SUBSCRIBED: switch(hci_event_packet_get_type(packet)){ case GATT_EVENT_QUERY_COMPLETE: // register handler for notifications state = TC_SUBSCRIBED; printf("Subscribed, start listening\n"); gatt_client_listen_for_characteristic_value_updates(¬ification_listener, handle_gatt_client_event, connection_handle, &le_counter_characteristic); break; default: break; } break; case TC_SUBSCRIBED: switch(hci_event_packet_get_type(packet)){ case GATT_EVENT_NOTIFICATION: memset(message, 0, sizeof(message)); memcpy(message, gatt_event_notification_get_value(packet), gatt_event_notification_get_value_length(packet)); printf("COUNTER: %s\n", message); log_info("COUNTER: %s", message); break; default: break; } default: break; } fflush(stdout); }
static void user_command(char cmd){ switch (cmd){ case 'a': memcpy(device_addr, pts_addr, 6); printf("Establish HFP service level connection to PTS module %s...\n", bd_addr_to_str(device_addr)); hfp_ag_establish_service_level_connection(device_addr); break; case 'A': printf("Release HFP service level connection.\n"); hfp_ag_release_service_level_connection(device_addr); break; case 'Z': printf("Release HFP service level connection to %s...\n", bd_addr_to_str(device_addr)); hfp_ag_release_service_level_connection(device_addr); break; case 'b': printf("Establish Audio connection %s...\n", bd_addr_to_str(device_addr)); hfp_ag_establish_audio_connection(device_addr); break; case 'B': printf("Release Audio connection.\n"); hfp_ag_release_audio_connection(device_addr); break; case 'c': printf("Simulate incoming call from 1234567\n"); current_call_exists_a = 1; current_call_status_a = HFP_ENHANCED_CALL_STATUS_INCOMING; current_call_dir = HFP_ENHANCED_CALL_DIR_INCOMING; hfp_ag_set_clip(129, "1234567"); hfp_ag_incoming_call(); break; case 'm': printf("Simulate incoming call from 7654321\n"); current_call_exists_b = 1; current_call_status_b = HFP_ENHANCED_CALL_STATUS_INCOMING; current_call_dir = HFP_ENHANCED_CALL_DIR_INCOMING; hfp_ag_set_clip(129, "7654321"); hfp_ag_incoming_call(); break; case 'C': printf("Simulate terminate call\n"); hfp_ag_call_dropped(); break; case 'd': printf("Report AG failure\n"); hfp_ag_report_extended_audio_gateway_error_result_code(device_addr, HFP_CME_ERROR_AG_FAILURE); break; case 'e': printf("Answer call on AG\n"); if (current_call_status_a == HFP_ENHANCED_CALL_STATUS_INCOMING){ current_call_status_a = HFP_ENHANCED_CALL_STATUS_ACTIVE; } if (current_call_status_b == HFP_ENHANCED_CALL_STATUS_INCOMING){ current_call_status_b = HFP_ENHANCED_CALL_STATUS_ACTIVE; current_call_status_a = HFP_ENHANCED_CALL_STATUS_HELD; } hfp_ag_answer_incoming_call(); break; case 'E': printf("Reject call on AG\n"); hfp_ag_terminate_call(); break; case 'f': printf("Disable cellular network\n"); hfp_ag_set_registration_status(0); break; case 'F': printf("Enable cellular network\n"); hfp_ag_set_registration_status(1); break; case 'g': printf("Set signal strength to 0\n"); hfp_ag_set_signal_strength(0); break; case 'G': printf("Set signal strength to 5\n"); hfp_ag_set_signal_strength(5); break; case 'h': printf("Disable roaming\n"); hfp_ag_set_roaming_status(0); break; case 'H': printf("Enable roaming\n"); hfp_ag_set_roaming_status(1); break; case 'i': printf("Set battery level to 3\n"); hfp_ag_set_battery_level(3); break; case 'I': printf("Set battery level to 5\n"); hfp_ag_set_battery_level(5); break; case 'j': printf("Answering call on remote side\n"); hfp_ag_outgoing_call_established(); break; case 'r': printf("Disable in-band ring tone\n"); hfp_ag_set_use_in_band_ring_tone(0); break; case 'k': printf("Memory 1 cleared\n"); memory_1_enabled = 0; break; case 'K': printf("Memory 1 set\n"); memory_1_enabled = 1; break; case 'l': printf("Last dialed number cleared\n"); last_number_exists = 0; break; case 'L': printf("Last dialed number set\n"); last_number_exists = 1; break; case 'n': printf("Disable Voice Recognition\n"); hfp_ag_activate_voice_recognition(device_addr, 0); break; case 'N': printf("Enable Voice Recognition\n"); hfp_ag_activate_voice_recognition(device_addr, 1); break; case 'o': printf("Set speaker gain to 0 (minimum)\n"); hfp_ag_set_speaker_gain(device_addr, 0); break; case 'O': printf("Set speaker gain to 9 (default)\n"); hfp_ag_set_speaker_gain(device_addr, 9); break; case 'p': printf("Set speaker gain to 12 (higher)\n"); hfp_ag_set_speaker_gain(device_addr, 12); break; case 'P': printf("Set speaker gain to 15 (maximum)\n"); hfp_ag_set_speaker_gain(device_addr, 15); break; case 'q': printf("Set microphone gain to 0\n"); hfp_ag_set_microphone_gain(device_addr, 0); break; case 'Q': printf("Set microphone gain to 9\n"); hfp_ag_set_microphone_gain(device_addr, 9); break; case 's': printf("Set microphone gain to 12\n"); hfp_ag_set_microphone_gain(device_addr, 12); break; case 'S': printf("Set microphone gain to 15\n"); hfp_ag_set_microphone_gain(device_addr, 15); break; case 'R': printf("Enable in-band ring tone\n"); hfp_ag_set_use_in_band_ring_tone(1); break; case 't': printf("Terminate HCI connection.\n"); gap_disconnect(handle); break; case 'u': printf("Join held call\n"); current_call_mpty = HFP_ENHANCED_CALL_MPTY_CONFERENCE_CALL; hfp_ag_join_held_call(); break; case 'v': printf("Starting inquiry scan..\n"); // hci_send_cmd(&hci_inquiry, HCI_INQUIRY_LAP, INQUIRY_INTERVAL, 0); break; case 'w': printf("AG: Put incoming call on hold (Response and Hold)\n"); hfp_ag_hold_incoming_call(); break; case 'x': printf("AG: Accept held incoming call (Response and Hold)\n"); hfp_ag_accept_held_incoming_call(); break; case 'X': printf("AG: Reject held incoming call (Response and Hold)\n"); hfp_ag_reject_held_incoming_call(); break; default: break; } }
static void user_command(char cmd){ switch (cmd){ case '#': case '-': case '+': case '*': printf("DTMF Code: %c\n", cmd); hfp_hf_send_dtmf_code(device_addr, cmd); break; case 'a': printf("Establish Service level connection to device with Bluetooth address %s...\n", bd_addr_to_str(device_addr)); hfp_hf_establish_service_level_connection(device_addr); break; case 'A': printf("Release Service level connection.\n"); hfp_hf_release_service_level_connection(device_addr); break; case 'b': printf("Establish Audio connection to device with Bluetooth address %s...\n", bd_addr_to_str(device_addr)); hfp_hf_establish_audio_connection(device_addr); break; case 'B': printf("Release Audio service level connection.\n"); hfp_hf_release_audio_connection(device_addr); break; case 'C': printf("Enable registration status update for all AG indicators.\n"); hfp_hf_enable_status_update_for_all_ag_indicators(device_addr); case 'c': printf("Disable registration status update for all AG indicators.\n"); hfp_hf_disable_status_update_for_all_ag_indicators(device_addr); break; case 'D': printf("Set HFP AG registration status update for individual indicators (0111111).\n"); hfp_hf_set_status_update_for_individual_ag_indicators(device_addr, 63); break; case 'd': printf("Query network operator.\n"); hfp_hf_query_operator_selection(device_addr); break; case 'E': printf("Enable reporting of the extended AG error result code.\n"); hfp_hf_enable_report_extended_audio_gateway_error_result_code(device_addr); break; case 'e': printf("Disable reporting of the extended AG error result code.\n"); hfp_hf_disable_report_extended_audio_gateway_error_result_code(device_addr); break; case 'f': printf("Answer incoming call.\n"); hfp_hf_answer_incoming_call(device_addr); break; case 'F': printf("Hangup call.\n"); hfp_hf_terminate_call(device_addr); break; case 'G': printf("Reject incoming call.\n"); hfp_hf_reject_incoming_call(device_addr); break; case 'g': printf("Query operator.\n"); hfp_hf_query_operator_selection(device_addr); break; case 't': printf("Terminate HCI connection.\n"); gap_disconnect(handle); break; case 'i': printf("Dial 1234567\n"); hfp_hf_dial_number(device_addr, (char *)"1234567"); break; case 'I': printf("Dial 7654321\n"); hfp_hf_dial_number(device_addr, (char *)"7654321"); break; case 'j': printf("Dial #1\n"); hfp_hf_dial_memory(device_addr, 1); break; case 'J': printf("Dial #99\n"); hfp_hf_dial_memory(device_addr, 99); break; case 'k': printf("Deactivate call waiting notification\n"); hfp_hf_deactivate_call_waiting_notification(device_addr); break; case 'K': printf("Activate call waiting notification\n"); hfp_hf_activate_call_waiting_notification(device_addr); break; case 'l': printf("Deactivate calling line notification\n"); hfp_hf_deactivate_calling_line_notification(device_addr); break; case 'L': printf("Activate calling line notification\n"); hfp_hf_activate_calling_line_notification(device_addr); break; case 'm': printf("Deactivate echo canceling and noise reduction\n"); hfp_hf_deactivate_echo_canceling_and_noise_reduction(device_addr); break; case 'M': printf("Activate echo canceling and noise reduction\n"); hfp_hf_activate_echo_canceling_and_noise_reduction(device_addr); break; case 'n': printf("Deactivate voice recognition\n"); hfp_hf_deactivate_voice_recognition_notification(device_addr); break; case 'N': printf("Activate voice recognition\n"); hfp_hf_activate_voice_recognition_notification(device_addr); break; case 'o': printf("Set speaker gain to 0 (minimum)\n"); hfp_hf_set_speaker_gain(device_addr, 0); break; case 'O': printf("Set speaker gain to 9 (default)\n"); hfp_hf_set_speaker_gain(device_addr, 9); break; case 'p': printf("Set speaker gain to 12 (higher)\n"); hfp_hf_set_speaker_gain(device_addr, 12); break; case 'P': printf("Set speaker gain to 15 (maximum)\n"); hfp_hf_set_speaker_gain(device_addr, 15); break; case 'q': printf("Set microphone gain to 0\n"); hfp_hf_set_microphone_gain(device_addr, 0); break; case 'Q': printf("Set microphone gain to 9\n"); hfp_hf_set_microphone_gain(device_addr, 9); break; case 's': printf("Set microphone gain to 12\n"); hfp_hf_set_microphone_gain(device_addr, 12); break; case 'S': printf("Set microphone gain to 15\n"); hfp_hf_set_microphone_gain(device_addr, 15); break; case 'u': printf("Send 'user busy' (Three-Way Call 0)\n"); hfp_hf_user_busy(device_addr); break; case 'U': printf("End active call and accept waiting/held call (Three-Way Call 1)\n"); hfp_hf_end_active_and_accept_other(device_addr); break; case 'v': printf("Swap active call and hold/waiting call (Three-Way Call 2)\n"); hfp_hf_swap_calls(device_addr); break; case 'V': printf("Join hold call (Three-Way Call 3)\n"); hfp_hf_join_held_call(device_addr); break; case 'w': printf("Connect calls (Three-Way Call 4)\n"); hfp_hf_connect_calls(device_addr); break; case 'W': printf("Redial\n"); hfp_hf_redial_last_number(device_addr); break; case 'x': printf("Request phone number for voice tag\n"); hfp_hf_request_phone_number_for_voice_tag(device_addr); break; case 'X': printf("Query current call status\n"); hfp_hf_query_current_call_status(device_addr); break; case 'y': printf("Release call with index 2\n"); hfp_hf_release_call_with_index(device_addr, 2); break; case 'Y': printf("Private consulation with call 2\n"); hfp_hf_private_consultation_with_call(device_addr, 2); break; case '[': printf("Query Response and Hold status (RHH ?)\n"); hfp_hf_rrh_query_status(device_addr); break; case ']': printf("Place call in a response and held state (RHH 0)\n"); hfp_hf_rrh_hold_call(device_addr); break; case '{': printf("Accept held call (RHH 1)\n"); hfp_hf_rrh_accept_held_call(device_addr); break; case '}': printf("Reject held call (RHH 2)\n"); hfp_hf_rrh_reject_held_call(device_addr); break; case '?': printf("Query Subscriber Number\n"); hfp_hf_query_subscriber_number(device_addr); break; case '!': printf("Update HF indicator with assigned number 1 (HFI)\n"); hfp_hf_set_hf_indicator(device_addr, 1, 1); break; default: printf("HF: undefined user command\n"); break; } }
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; } }
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 int stdin_process(struct data_source *ds){ read(ds->fd, &cmd, 1); switch (cmd){ case 'a': memcpy(device_addr, pts_addr, 6); log_info("USER:\'%c\'", cmd); printf("Establish HFP service level connection to PTS module %s...\n", bd_addr_to_str(device_addr)); hfp_ag_establish_service_level_connection(device_addr); break; case 'A': log_info("USER:\'%c\'", cmd); printf("Release HFP service level connection.\n"); hfp_ag_release_service_level_connection(device_addr); break; case 'z': memcpy(device_addr, speaker_addr, 6); log_info("USER:\'%c\'", cmd); printf("Establish HFP service level connection to %s...\n", bd_addr_to_str(device_addr)); hfp_ag_establish_service_level_connection(device_addr); break; case 'Z': log_info("USER:\'%c\'", cmd); printf("Release HFP service level connection to %s...\n", bd_addr_to_str(device_addr)); hfp_ag_release_service_level_connection(device_addr); break; case 'b': log_info("USER:\'%c\'", cmd); printf("Establish Audio connection %s...\n", bd_addr_to_str(device_addr)); hfp_ag_establish_audio_connection(device_addr); break; case 'B': log_info("USER:\'%c\'", cmd); printf("Release Audio connection.\n"); hfp_ag_release_audio_connection(device_addr); break; case 'c': log_info("USER:\'%c\'", cmd); printf("Simulate incoming call from 1234567\n"); hfp_ag_set_clip(129, "1234567"); hfp_ag_incoming_call(); break; case 'm': log_info("USER:\'%c\'", cmd); printf("Simulate incoming call from 7654321\n"); hfp_ag_set_clip(129, "7654321"); hfp_ag_incoming_call(); break; case 'C': log_info("USER:\'%c\'", cmd); printf("Simulate terminate call\n"); hfp_ag_call_dropped(); break; case 'd': log_info("USER:\'%c\'", cmd); printf("Report AG failure\n"); hfp_ag_report_extended_audio_gateway_error_result_code(device_addr, HFP_CME_ERROR_AG_FAILURE); break; case 'e': log_info("USER:\'%c\'", cmd); printf("Answer call on AG\n"); hfp_ag_answer_incoming_call(); break; case 'E': log_info("USER:\'%c\'", cmd); printf("Reject call on AG\n"); hfp_ag_terminate_call(); break; case 'f': log_info("USER:\'%c\'", cmd); printf("Disable cellular network\n"); hfp_ag_set_registration_status(0); break; case 'F': log_info("USER:\'%c\'", cmd); printf("Enable cellular network\n"); hfp_ag_set_registration_status(1); break; case 'g': log_info("USER:\'%c\'", cmd); printf("Set signal strength to 0\n"); hfp_ag_set_signal_strength(0); break; case 'G': log_info("USER:\'%c\'", cmd); printf("Set signal strength to 5\n"); hfp_ag_set_signal_strength(5); break; case 'h': log_info("USER:\'%c\'", cmd); printf("Disable roaming\n"); hfp_ag_set_roaming_status(0); break; case 'H': log_info("USER:\'%c\'", cmd); printf("Enable roaming\n"); hfp_ag_set_roaming_status(1); break; case 'i': log_info("USER:\'%c\'", cmd); printf("Set battery level to 3\n"); hfp_ag_set_battery_level(3); break; case 'I': log_info("USER:\'%c\'", cmd); printf("Set battery level to 5\n"); hfp_ag_set_battery_level(5); break; case 'j': log_info("USER:\'%c\'", cmd); printf("Answering call on remote side\n"); hfp_ag_outgoing_call_established(); break; case 'r': log_info("USER:\'%c\'", cmd); printf("Disable in-band ring tone\n"); hfp_ag_set_use_in_band_ring_tone(0); break; case 'k': log_info("USER:\'%c\'", cmd); printf("Memory 1 cleared\n"); memory_1_enabled = 0; break; case 'K': log_info("USER:\'%c\'", cmd); printf("Memory 1 set\n"); memory_1_enabled = 1; break; case 'l': log_info("USER:\'%c\'", cmd); printf("Last dialed number cleared\n"); hfp_ag_clear_last_dialed_number(); break; case 'L': log_info("USER:\'%c\'", cmd); printf("Outgoing call connected, ringing\n"); hfp_ag_outgoing_call_ringing(); break; case 'n': log_info("USER:\'%c\'", cmd); printf("Disable Voice Recognition\n"); hfp_ag_activate_voice_recognition(device_addr, 0); break; case 'N': log_info("USER:\'%c\'", cmd); printf("Enable Voice Recognition\n"); hfp_ag_activate_voice_recognition(device_addr, 1); break; case 'o': log_info("USER:\'%c\'", cmd); printf("Set speaker gain to 0 (minimum)\n"); hfp_ag_set_speaker_gain(device_addr, 0); break; case 'O': log_info("USER:\'%c\'", cmd); printf("Set speaker gain to 9 (default)\n"); hfp_ag_set_speaker_gain(device_addr, 9); break; case 'p': log_info("USER:\'%c\'", cmd); printf("Set speaker gain to 12 (higher)\n"); hfp_ag_set_speaker_gain(device_addr, 12); break; case 'P': log_info("USER:\'%c\'", cmd); printf("Set speaker gain to 15 (maximum)\n"); hfp_ag_set_speaker_gain(device_addr, 15); break; case 'q': log_info("USER:\'%c\'", cmd); printf("Set microphone gain to 0\n"); hfp_ag_set_microphone_gain(device_addr, 0); break; case 'Q': log_info("USER:\'%c\'", cmd); printf("Set microphone gain to 9\n"); hfp_ag_set_microphone_gain(device_addr, 9); break; case 's': log_info("USER:\'%c\'", cmd); printf("Set microphone gain to 12\n"); hfp_ag_set_microphone_gain(device_addr, 12); break; case 'S': log_info("USER:\'%c\'", cmd); printf("Set microphone gain to 15\n"); hfp_ag_set_microphone_gain(device_addr, 15); break; case 'R': log_info("USER:\'%c\'", cmd); printf("Enable in-band ring tone\n"); hfp_ag_set_use_in_band_ring_tone(1); break; case 't': log_info("USER:\'%c\'", cmd); printf("Terminate HCI connection.\n"); gap_disconnect(handle); break; case 'u': log_info("USER:\'%c\'", cmd); printf("Join held call\n"); hfp_ag_join_held_call(); break; case 'v': start_scan(); break; case 'w': log_info("USER:\'%c\'", cmd); printf("AG: Put incoming call on hold (Response and Hold)\n"); hfp_ag_hold_incoming_call(); break; case 'x': log_info("USER:\'%c\'", cmd); printf("AG: Accept held incoming call (Response and Hold)\n"); hfp_ag_accept_held_incoming_call(); break; case 'X': log_info("USER:\'%c\'", cmd); printf("AG: Reject held incoming call (Response and Hold)\n"); hfp_ag_reject_held_incoming_call(); break; default: show_usage(); break; } return 0; }
int stdin_process(struct data_source *ds){ char buffer; read(ds->fd, &buffer, 1); // passkey input if (ui_digits_for_passkey){ if (buffer < '0' || buffer > '9') return 0; printf("%c", buffer); fflush(stdout); ui_passkey = ui_passkey * 10 + buffer - '0'; ui_digits_for_passkey--; if (ui_digits_for_passkey == 0){ printf("\nSending Passkey '%06u'\n", ui_passkey); hci_send_cmd(&hci_user_passkey_request_reply, remote, ui_passkey); } return 0; } if (ui_chars_for_pin){ printf("%c", buffer); fflush(stdout); if (buffer == '\n'){ printf("\nSending Pin '%s'\n", ui_pin); hci_send_cmd(&hci_pin_code_request_reply, remote, ui_pin_offset, ui_pin); } else { ui_pin[ui_pin_offset++] = buffer; } return 0; } switch (buffer){ case 'c': gap_connectable = 0; hci_connectable_control(0); show_usage(); break; case 'C': gap_connectable = 1; hci_connectable_control(1); show_usage(); break; case 'd': gap_discoverable = 0; hci_discoverable_control(0); show_usage(); break; case 'D': gap_discoverable = 1; hci_discoverable_control(1); show_usage(); break; case 'b': gap_bondable = 0; // gap_set_bondable_mode(0); update_auth_req(); show_usage(); break; case 'B': gap_bondable = 1; // gap_set_bondable_mode(1); update_auth_req(); show_usage(); break; case 'm': gap_mitm_protection = 0; update_auth_req(); show_usage(); break; case 'M': gap_mitm_protection = 1; update_auth_req(); show_usage(); break; case '<': gap_dedicated_bonding_mode = 0; update_auth_req(); show_usage(); break; case '>': gap_dedicated_bonding_mode = 1; update_auth_req(); show_usage(); break; case 'e': gap_io_capabilities = "IO_CAPABILITY_DISPLAY_ONLY"; hci_ssp_set_io_capability(IO_CAPABILITY_DISPLAY_ONLY); show_usage(); break; case 'f': gap_io_capabilities = "IO_CAPABILITY_DISPLAY_YES_NO"; hci_ssp_set_io_capability(IO_CAPABILITY_DISPLAY_YES_NO); show_usage(); break; case 'g': gap_io_capabilities = "IO_CAPABILITY_NO_INPUT_NO_OUTPUT"; hci_ssp_set_io_capability(IO_CAPABILITY_NO_INPUT_NO_OUTPUT); show_usage(); break; case 'h': gap_io_capabilities = "IO_CAPABILITY_KEYBOARD_ONLY"; hci_ssp_set_io_capability(IO_CAPABILITY_KEYBOARD_ONLY); show_usage(); break; case 'i': start_scan(); break; case 'j': printf("Start dedicated bonding to %s using MITM %u\n", bd_addr_to_str(remote), gap_mitm_protection); gap_dedicated_bonding(remote, gap_mitm_protection); break; case 'z': printf("Start dedicated bonding to %s using legacy pairing\n", bd_addr_to_str(remote)); gap_dedicated_bonding(remote, gap_mitm_protection); break; case 'y': printf("Disabling SSP for this session\n"); hci_send_cmd(&hci_write_simple_pairing_mode, 0); break; case 'k': printf("Start SDP query for SPP service\n"); sdp_query_rfcomm_channel_and_name_for_uuid(remote_rfcomm, 0x1101); break; case 't': printf("Terminate connection with handle 0x%04x\n", handle); hci_send_cmd(&hci_disconnect, handle, 0x13); // remote closed connection break; case 'p': printf("Creating HCI Connection to %s\n", bd_addr_to_str(remote)); hci_send_cmd(&hci_create_connection, remote, hci_usable_acl_packet_types(), 0, 0, 0, 1); break; // printf("Creating L2CAP Connection to %s, PSM SDP\n", bd_addr_to_str(remote)); // l2cap_create_channel_internal(NULL, packet_handler, remote, PSM_SDP, 100); // break; // case 'u': // printf("Creating L2CAP Connection to %s, PSM 3\n", bd_addr_to_str(remote)); // l2cap_create_channel_internal(NULL, packet_handler, remote, 3, 100); // break; case 'q': printf("Send L2CAP Data\n"); l2cap_send_internal(local_cid, (uint8_t *) "0123456789", 10); break; case 'r': printf("Send L2CAP ECHO Request\n"); l2cap_send_echo_request(handle, (uint8_t *) "Hello World!", 13); break; case 's': printf("L2CAP Channel Closed\n"); l2cap_disconnect_internal(local_cid, 0); break; case 'x': printf("Outgoing L2CAP Channels to SDP will also require SSP\n"); l2cap_require_security_level_2_for_outgoing_sdp(); break; case 'l': printf("Creating RFCOMM Channel to %s #%u\n", bd_addr_to_str(remote_rfcomm), rfcomm_channel_nr); rfcomm_create_channel_internal(NULL, remote_rfcomm, rfcomm_channel_nr); break; case 'n': printf("Send RFCOMM Data\n"); // mtu < 60 rfcomm_send_internal(rfcomm_channel_id, (uint8_t *) "012345678901234567890123456789012345678901234567890123456789", mtu); break; case 'u': printf("Sending RLS indicating framing error\n"); // mtu < 60 rfcomm_send_local_line_status(rfcomm_channel_id, 9); break; case 'v': printf("Sending RPN CMD to select 115200 baud\n"); // mtu < 60 rfcomm_send_port_configuration(rfcomm_channel_id, RPN_BAUD_115200, RPN_DATA_BITS_8, RPN_STOP_BITS_1_0, RPN_PARITY_NONE, 0); break; case 'w': printf("Sending RPN REQ to query remote port settings\n"); // mtu < 60 rfcomm_query_port_configuration(rfcomm_channel_id); break; case 'o': printf("RFCOMM Channel Closed\n"); rfcomm_disconnect_internal(rfcomm_channel_id); rfcomm_channel_id = 0; break; case '+': printf("Initiate SSP on current connection\n"); gap_request_security_level(handle, LEVEL_2); break; case '*': printf("Sending SSP User Confirmation for %s\n", bd_addr_to_str(remote)); hci_send_cmd(&hci_user_confirmation_request_reply, remote); break; case '=': printf("Deleting Link Key for %s\n", bd_addr_to_str(remote)); hci_drop_link_key_for_bd_addr(remote); break; case 'U': printf("Sending UCD data on handle 0x%04x\n", handle); send_ucd_packet(); break; case 'Q': printf("Closing HCI Connection to handle 0x%04x\n", handle); gap_disconnect(handle); break; default: show_usage(); break; } return 0; }
static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ UNUSED(packet_type); UNUSED(channel); UNUSED(size); uint16_t mtu; switch(state){ case TC_W4_SERVICE_RESULT: switch(hci_event_packet_get_type(packet)){ case GATT_EVENT_SERVICE_QUERY_RESULT: // store service (we expect only one) gatt_event_service_query_result_get_service(packet, &le_streamer_service); break; case GATT_EVENT_QUERY_COMPLETE: if (packet[4] != 0){ printf("SERVICE_QUERY_RESULT - Error status %x.\n", packet[4]); gap_disconnect(connection_handle); break; } // service query complete, look for characteristic state = TC_W4_CHARACTERISTIC_RX_RESULT; printf("Search for LE Streamer RX characteristic.\n"); gatt_client_discover_characteristics_for_service_by_uuid128(handle_gatt_client_event, connection_handle, &le_streamer_service, le_streamer_characteristic_rx_uuid); break; default: break; } break; case TC_W4_CHARACTERISTIC_RX_RESULT: switch(hci_event_packet_get_type(packet)){ case GATT_EVENT_CHARACTERISTIC_QUERY_RESULT: gatt_event_characteristic_query_result_get_characteristic(packet, &le_streamer_characteristic_rx); break; case GATT_EVENT_QUERY_COMPLETE: if (packet[4] != 0){ printf("CHARACTERISTIC_QUERY_RESULT - Error status %x.\n", packet[4]); gap_disconnect(connection_handle); break; } // rx characteristiic found, look for tx characteristic state = TC_W4_CHARACTERISTIC_TX_RESULT; printf("Search for LE Streamer TX characteristic.\n"); gatt_client_discover_characteristics_for_service_by_uuid128(handle_gatt_client_event, connection_handle, &le_streamer_service, le_streamer_characteristic_tx_uuid); break; default: break; } break; case TC_W4_CHARACTERISTIC_TX_RESULT: switch(hci_event_packet_get_type(packet)){ case GATT_EVENT_CHARACTERISTIC_QUERY_RESULT: gatt_event_characteristic_query_result_get_characteristic(packet, &le_streamer_characteristic_tx); break; case GATT_EVENT_QUERY_COMPLETE: if (packet[4] != 0){ printf("CHARACTERISTIC_QUERY_RESULT - Error status %x.\n", packet[4]); gap_disconnect(connection_handle); break; } // register handler for notifications listener_registered = 1; gatt_client_listen_for_characteristic_value_updates(¬ification_listener, handle_gatt_client_event, connection_handle, &le_streamer_characteristic_tx); // setup tracking le_streamer_connection.name = 'A'; le_streamer_connection.test_data_len = ATT_DEFAULT_MTU - 3; test_reset(&le_streamer_connection); gatt_client_get_mtu(connection_handle, &mtu); le_streamer_connection.test_data_len = btstack_min(mtu - 3, sizeof(le_streamer_connection.test_data)); printf("%c: ATT MTU = %u => use test data of len %u\n", le_streamer_connection.name, mtu, le_streamer_connection.test_data_len); // enable notifications #if (TEST_MODE & TEST_MODE_ENABLE_NOTIFICATIONS) printf("Start streaming - enable notify on test characteristic.\n"); state = TC_W4_ENABLE_NOTIFICATIONS_COMPLETE; gatt_client_write_client_characteristic_configuration(handle_gatt_client_event, connection_handle, &le_streamer_characteristic_tx, GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION); break; #endif state = TC_W4_TEST_DATA; #if (TEST_MODE & TEST_MODE_WRITE_WITHOUT_RESPONSE) printf("Start streaming - request can send now.\n"); gatt_client_request_can_write_without_response_event(handle_gatt_client_event, connection_handle); #endif break; default: break; } break; case TC_W4_ENABLE_NOTIFICATIONS_COMPLETE: switch(hci_event_packet_get_type(packet)){ case GATT_EVENT_QUERY_COMPLETE: printf("Notifications enabled, status %02x\n", gatt_event_query_complete_get_status(packet)); state = TC_W4_TEST_DATA; #if (TEST_MODE & TEST_MODE_WRITE_WITHOUT_RESPONSE) printf("Start streaming - request can send now.\n"); gatt_client_request_can_write_without_response_event(handle_gatt_client_event, connection_handle); #endif break; default: break; } break; case TC_W4_TEST_DATA: switch(hci_event_packet_get_type(packet)){ case GATT_EVENT_NOTIFICATION: test_track_data(&le_streamer_connection, gatt_event_notification_get_value_length(packet)); break; case GATT_EVENT_QUERY_COMPLETE: break; case GATT_EVENT_CAN_WRITE_WITHOUT_RESPONSE: streamer(&le_streamer_connection); break; default: printf("Unknown packet type %x\n", hci_event_packet_get_type(packet)); break; } break; default: printf("error\n"); break; } }