static void hfp_run_for_context(hfp_connection_t *context){ if (!context) return; if (!rfcomm_can_send_packet_now(context->rfcomm_cid)) return; if (context->command == HFP_CMD_UNKNOWN){ context->ok_pending = 0; context->send_error = 0; context->command = HFP_CMD_NONE; hfp_ag_error(context->rfcomm_cid); return; } if (context->ok_pending){ context->ok_pending = 0; context->command = HFP_CMD_NONE; hfp_ag_ok(context->rfcomm_cid); return; } if (context->send_error){ context->send_error = 0; context->command = HFP_CMD_NONE; hfp_ag_error(context->rfcomm_cid); return; } int done = hfp_ag_run_for_context_service_level_connection(context); if (!done){ done = hfp_ag_run_for_context_service_level_connection_queries(context); } if (!done){ done = incoming_call_state_machine(context); } if (!done){ done = hfp_ag_run_for_audio_connection(context); } if (context->command == HFP_CMD_NONE && !done){ log_info("context->command == HFP_CMD_NONE"); switch(context->state){ case HFP_W2_DISCONNECT_RFCOMM: context->state = HFP_W4_RFCOMM_DISCONNECTED; rfcomm_disconnect_internal(context->rfcomm_cid); break; default: break; } } if (done){ context->command = HFP_CMD_NONE; } }
static void send_packet(){ int err = rfcomm_send_internal(rfcomm_cid, (uint8_t*) test_data, test_data_len); if (err){ printf("rfcomm_send_internal -> error 0X%02x", err); return; } if (data_to_send < test_data_len){ rfcomm_disconnect_internal(rfcomm_cid); rfcomm_cid = 0; state = DONE; printf("SPP Streamer: enough data send, closing DLC\n"); return; } data_to_send -= test_data_len; }
void hfp_run_for_context(hfp_connection_t *context){ if (!context) return; if (!rfcomm_can_send_packet_now(context->rfcomm_cid)) return; // printf("AG hfp_run_for_context 1 state %d, command %d\n", context->state, context->command); if (context->send_ok){ hfp_ag_ok(context->rfcomm_cid); context->send_ok = 0; return; } if (context->send_error){ hfp_ag_error(context->rfcomm_cid); context->send_error = 0; return; } int done; if (!rfcomm_can_send_packet_now(context->rfcomm_cid)) return; hfp_ag_run_for_context_service_level_connection(context); if (!rfcomm_can_send_packet_now(context->rfcomm_cid)) return; done = hfp_ag_run_for_context_service_level_connection_queries(context); if (!rfcomm_can_send_packet_now(context->rfcomm_cid) || done) return; done = hfp_ag_run_for_context_codecs_connection(context); if (context->command == HFP_CMD_NONE){ switch(context->state){ case HFP_W2_DISCONNECT_RFCOMM: // printf("rfcomm_disconnect_internal cid 0x%02x\n", context->rfcomm_cid); context->state = HFP_W4_RFCOMM_DISCONNECTED; rfcomm_disconnect_internal(context->rfcomm_cid); break; default: break; } } context->command = HFP_CMD_NONE; }
static int btstack_command_handler(connection_t *connection, uint8_t *packet, uint16_t size){ bd_addr_t addr; uint16_t cid; uint16_t psm; uint16_t service_channel; uint16_t mtu; uint8_t reason; uint8_t rfcomm_channel; uint8_t rfcomm_credits; uint32_t service_record_handle; client_state_t *client; uint16_t serviceSearchPatternLen; uint16_t attributeIDListLen; // BTstack internal commands - 16 Bit OpCode, 8 Bit ParamLen, Params... switch (READ_CMD_OCF(packet)){ case BTSTACK_GET_STATE: log_info("BTSTACK_GET_STATE"); hci_emit_state(); break; case BTSTACK_SET_POWER_MODE: log_info("BTSTACK_SET_POWER_MODE %u", packet[3]); // track client power requests client = client_for_connection(connection); if (!client) break; client->power_mode = packet[3]; // handle merged state if (!clients_require_power_on()){ start_power_off_timer(); } else if (!power_management_sleep) { stop_power_off_timer(); hci_power_control(HCI_POWER_ON); } break; case BTSTACK_GET_VERSION: log_info("BTSTACK_GET_VERSION"); hci_emit_btstack_version(); break; #ifdef USE_BLUETOOL case BTSTACK_SET_SYSTEM_BLUETOOTH_ENABLED: log_info("BTSTACK_SET_SYSTEM_BLUETOOTH_ENABLED %u", packet[3]); iphone_system_bt_set_enabled(packet[3]); hci_emit_system_bluetooth_enabled(iphone_system_bt_enabled()); break; case BTSTACK_GET_SYSTEM_BLUETOOTH_ENABLED: log_info("BTSTACK_GET_SYSTEM_BLUETOOTH_ENABLED"); hci_emit_system_bluetooth_enabled(iphone_system_bt_enabled()); break; #else case BTSTACK_SET_SYSTEM_BLUETOOTH_ENABLED: case BTSTACK_GET_SYSTEM_BLUETOOTH_ENABLED: hci_emit_system_bluetooth_enabled(0); break; #endif case BTSTACK_SET_DISCOVERABLE: log_info("BTSTACK_SET_DISCOVERABLE discoverable %u)", packet[3]); // track client discoverable requests client = client_for_connection(connection); if (!client) break; client->discoverable = packet[3]; // merge state hci_discoverable_control(clients_require_discoverable()); break; case BTSTACK_SET_BLUETOOTH_ENABLED: log_info("BTSTACK_SET_BLUETOOTH_ENABLED: %u\n", packet[3]); if (packet[3]) { // global enable global_enable = 1; hci_power_control(HCI_POWER_ON); } else { global_enable = 0; clients_clear_power_request(); hci_power_control(HCI_POWER_OFF); } break; case L2CAP_CREATE_CHANNEL_MTU: bt_flip_addr(addr, &packet[3]); psm = READ_BT_16(packet, 9); mtu = READ_BT_16(packet, 11); l2cap_create_channel_internal( connection, NULL, addr, psm, mtu); break; case L2CAP_CREATE_CHANNEL: bt_flip_addr(addr, &packet[3]); psm = READ_BT_16(packet, 9); l2cap_create_channel_internal( connection, NULL, addr, psm, 150); // until r865 break; case L2CAP_DISCONNECT: cid = READ_BT_16(packet, 3); reason = packet[5]; l2cap_disconnect_internal(cid, reason); break; case L2CAP_REGISTER_SERVICE: psm = READ_BT_16(packet, 3); mtu = READ_BT_16(packet, 5); l2cap_register_service_internal(connection, NULL, psm, mtu); break; case L2CAP_UNREGISTER_SERVICE: psm = READ_BT_16(packet, 3); l2cap_unregister_service_internal(connection, psm); break; case L2CAP_ACCEPT_CONNECTION: cid = READ_BT_16(packet, 3); l2cap_accept_connection_internal(cid); break; case L2CAP_DECLINE_CONNECTION: cid = READ_BT_16(packet, 3); reason = packet[7]; l2cap_decline_connection_internal(cid, reason); break; case RFCOMM_CREATE_CHANNEL: bt_flip_addr(addr, &packet[3]); rfcomm_channel = packet[9]; rfcomm_create_channel_internal( connection, &addr, rfcomm_channel ); break; case RFCOMM_CREATE_CHANNEL_WITH_CREDITS: bt_flip_addr(addr, &packet[3]); rfcomm_channel = packet[9]; rfcomm_credits = packet[10]; rfcomm_create_channel_with_initial_credits_internal( connection, &addr, rfcomm_channel, rfcomm_credits ); break; case RFCOMM_DISCONNECT: cid = READ_BT_16(packet, 3); reason = packet[5]; rfcomm_disconnect_internal(cid); break; case RFCOMM_REGISTER_SERVICE: rfcomm_channel = packet[3]; mtu = READ_BT_16(packet, 4); rfcomm_register_service_internal(connection, rfcomm_channel, mtu); break; case RFCOMM_REGISTER_SERVICE_WITH_CREDITS: rfcomm_channel = packet[3]; mtu = READ_BT_16(packet, 4); rfcomm_credits = packet[6]; rfcomm_register_service_with_initial_credits_internal(connection, rfcomm_channel, mtu, rfcomm_credits); break; case RFCOMM_UNREGISTER_SERVICE: service_channel = READ_BT_16(packet, 3); rfcomm_unregister_service_internal(service_channel); break; case RFCOMM_ACCEPT_CONNECTION: cid = READ_BT_16(packet, 3); rfcomm_accept_connection_internal(cid); break; case RFCOMM_DECLINE_CONNECTION: cid = READ_BT_16(packet, 3); reason = packet[7]; rfcomm_decline_connection_internal(cid); break; case RFCOMM_GRANT_CREDITS: cid = READ_BT_16(packet, 3); rfcomm_credits = packet[5]; rfcomm_grant_credits(cid, rfcomm_credits); break; case RFCOMM_PERSISTENT_CHANNEL: { if (remote_device_db) { // enforce \0 packet[3+248] = 0; rfcomm_channel = remote_device_db->persistent_rfcomm_channel((char*)&packet[3]); } else { // NOTE: hack for non-iOS platforms rfcomm_channel = rfcomm_channel_generator++; } log_info("RFCOMM_EVENT_PERSISTENT_CHANNEL %u", rfcomm_channel); uint8_t event[4]; event[0] = RFCOMM_EVENT_PERSISTENT_CHANNEL; event[1] = sizeof(event) - 2; event[2] = 0; event[3] = rfcomm_channel; hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event)); socket_connection_send_packet(connection, HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event)); break; } case SDP_REGISTER_SERVICE_RECORD: log_info("SDP_REGISTER_SERVICE_RECORD size %u\n", size); sdp_register_service_internal(connection, &packet[3]); break; case SDP_UNREGISTER_SERVICE_RECORD: service_record_handle = READ_BT_32(packet, 3); log_info("SDP_UNREGISTER_SERVICE_RECORD handle 0x%x ", service_record_handle); sdp_unregister_service_internal(connection, service_record_handle); break; case SDP_CLIENT_QUERY_RFCOMM_SERVICES: bt_flip_addr(addr, &packet[3]); serviceSearchPatternLen = de_get_len(&packet[9]); memcpy(serviceSearchPattern, &packet[9], serviceSearchPatternLen); sdp_query_rfcomm_register_callback(handle_sdp_rfcomm_service_result, connection); sdp_query_rfcomm_channel_and_name_for_search_pattern(addr, serviceSearchPattern); break; case SDP_CLIENT_QUERY_SERVICES: bt_flip_addr(addr, &packet[3]); sdp_parser_init(); sdp_parser_register_callback(handle_sdp_client_query_result); serviceSearchPatternLen = de_get_len(&packet[9]); memcpy(serviceSearchPattern, &packet[9], serviceSearchPatternLen); attributeIDListLen = de_get_len(&packet[9+serviceSearchPatternLen]); memcpy(attributeIDList, &packet[9+serviceSearchPatternLen], attributeIDListLen); sdp_client_query(addr, (uint8_t*)&serviceSearchPattern[0], (uint8_t*)&attributeIDList[0]); // sdp_general_query_for_uuid(addr, 0x1002); break; default: log_error("Error: command %u not implemented\n:", READ_CMD_OCF(packet)); break; } // verbose log info on command before dumped command unknown to PacketLogger or Wireshark hci_dump_packet( HCI_COMMAND_DATA_PACKET, 1, packet, size); return 0; }
static void hsp_run(void){ if (!rfcomm_can_send_packet_now(rfcomm_cid)) return; if (wait_ok) return; if (hsp_release_audio_connection){ 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_internal(rfcomm_cid); return; } if (hsp_establish_audio_connection){ 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){ 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_query_rfcomm_channel_and_name_for_uuid(remote, SDP_Headset_AG); break; case HSP_AUDIO_CONNECTION_ESTABLISHED: case HSP_RFCOMM_CONNECTION_ESTABLISHED: if (hs_microphone_gain >= 0){ 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){ 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_internal(rfcomm_cid); break; default: 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; } }
void hfp_run_for_context(hfp_connection_t *context) { // printf(" hfp_run_for_context \n"); if (!context) return; if (!rfcomm_can_send_packet_now(context->rfcomm_cid)) return; //printf(" hfp_run_for_context 1 state %d, command %d\n", context->state, context->command); if (context->state == HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) { if (context->send_ok) { hfp_ag_ok(context->rfcomm_cid); context->send_ok = 0; return; } if (context->send_error) { hfp_ag_error(context->rfcomm_cid); context->send_error = 0; return; } if (context->enable_status_update_for_ag_indicators) { int i; for (i = 0; i < context->ag_indicators_nr; i++) { if (context->ag_indicators[i].enabled == 0) continue; if (context->ag_indicators[i].status_changed == 0) continue; hfp_ag_transfer_ag_indicators_status_cmd(context->rfcomm_cid, context->ag_indicators[i]); context->ag_indicators[i].status_changed = 0; return; } } if (context->enable_extended_audio_gateway_error_report) { if (context->extended_audio_gateway_error) { hfp_ag_report_extended_audio_gateway_error(context->rfcomm_cid, context->extended_audio_gateway_error); context->extended_audio_gateway_error = 0; return; } } } if (context->state == HFP_AUDIO_CONNECTION_ESTABLISHED) { // TODO } switch(context->command) { // START codec setup case HFP_CMD_TRIGGER_CODEC_CONNECTION_SETUP: if (!hfp_ag_choose_codec(context)) { hfp_ag_error(context->rfcomm_cid); break; } switch (context->state) { case HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED: // hfp_ag_ok(context->rfcomm_cid); context->negotiated_codec = hfp_ag_choose_codec(context); hfp_ag_cmd_confirm_codec(context->rfcomm_cid, context->negotiated_codec); context->state = HFP_SLE_W4_EXCHANGE_COMMON_CODEC; break; default: hfp_ag_error(context->rfcomm_cid); break; } break; case HFP_CMD_CONFIRM_COMMON_CODEC: hfp_ag_ok(context->rfcomm_cid); context->state = HFP_CODECS_CONNECTION_ESTABLISHED; break; // END codec setup case HFP_CMD_SUPPORTED_FEATURES: switch(context->state) { case HFP_W4_EXCHANGE_SUPPORTED_FEATURES: hfp_ag_exchange_supported_features_cmd(context->rfcomm_cid); if (has_codec_negotiation_feature(context)) { context->state = HFP_W4_NOTIFY_ON_CODECS; break; } context->state = HFP_W4_RETRIEVE_INDICATORS; break; default: break; } break; case HFP_CMD_AVAILABLE_CODECS: switch(context->state) { case HFP_W4_NOTIFY_ON_CODECS: hfp_ag_retrieve_codec_cmd(context->rfcomm_cid); context->state = HFP_W4_RETRIEVE_INDICATORS; break; default: break; } break; case HFP_CMD_INDICATOR: switch(context->state) { case HFP_W4_RETRIEVE_INDICATORS: if (context->retrieve_ag_indicators == 0) break; hfp_ag_retrieve_indicators_cmd(context->rfcomm_cid, context); context->state = HFP_W4_RETRIEVE_INDICATORS_STATUS; break; case HFP_W4_RETRIEVE_INDICATORS_STATUS: if (context->retrieve_ag_indicators_status == 0) break; hfp_ag_retrieve_indicators_status_cmd(context->rfcomm_cid); context->state = HFP_W4_ENABLE_INDICATORS_STATUS_UPDATE; break; default: break; } break; case HFP_CMD_ENABLE_INDICATOR_STATUS_UPDATE: switch(context->state) { case HFP_W4_ENABLE_INDICATORS_STATUS_UPDATE: hfp_ag_toggle_indicator_status_update_cmd(context->rfcomm_cid, 1); if (has_call_waiting_and_3way_calling_feature(context)) { context->state = HFP_W4_RETRIEVE_CAN_HOLD_CALL; break; } if (has_hf_indicators_feature(context)) { context->state = HFP_W4_LIST_GENERIC_STATUS_INDICATORS; break; } context->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED; hfp_emit_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, 0); break; case HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED: // TODO break; default: break; } break; case HFP_CMD_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES: switch(context->state) { case HFP_W4_RETRIEVE_CAN_HOLD_CALL: hfp_ag_retrieve_can_hold_call_cmd(context->rfcomm_cid); if (has_hf_indicators_feature(context)) { context->state = HFP_W4_LIST_GENERIC_STATUS_INDICATORS; break; } context->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED; hfp_emit_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, 0); break; default: break; } break; case HFP_CMD_GENERIC_STATUS_INDICATOR: switch(context->state) { case HFP_W4_LIST_GENERIC_STATUS_INDICATORS: if (context->list_generic_status_indicators == 0) break; hfp_ag_list_supported_generic_status_indicators_cmd(context->rfcomm_cid); context->state = HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS; context->list_generic_status_indicators = 0; break; case HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS: if (context->retrieve_generic_status_indicators == 0) break; hfp_ag_retrieve_supported_generic_status_indicators_cmd(context->rfcomm_cid); context->state = HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS; context->retrieve_generic_status_indicators = 0; break; case HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS: if (context->retrieve_generic_status_indicators_state == 0) break; hfp_ag_retrieve_initital_supported_generic_status_indicators_cmd(context->rfcomm_cid); context->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED; context->retrieve_generic_status_indicators_state = 0; hfp_emit_event(hfp_callback, HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED, 0); break; default: break; } break; case HFP_CMD_QUERY_OPERATOR_SELECTION: if (context->state != HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED) break; if (context->operator_name_format == 1) { if (context->network_operator.format != 0) { hfp_ag_error(context->rfcomm_cid); break; } hfp_ag_ok(context->rfcomm_cid); context->operator_name_format = 0; break; } if (context->operator_name == 1) { hfp_ag_report_network_operator_name_cmd(context->rfcomm_cid, context->network_operator); context->operator_name = 0; break; } break; case HFP_CMD_NONE: switch(context->state) { case HFP_W2_DISCONNECT_RFCOMM: // printf("rfcomm_disconnect_internal cid 0x%02x\n", context->rfcomm_cid); context->state = HFP_W4_RFCOMM_DISCONNECTED; rfcomm_disconnect_internal(context->rfcomm_cid); break; default: break; } break; default: break; } // done context->command = HFP_CMD_NONE; }
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; }