static void hsp_run(void){ int err; if (hs_ring_received){ hs_ring_received = 0; hs_send_button_press = 1; } if (hs_ok_received){ hs_ok_received = 0; } if (hs_send_button_press){ int err = 0; if (hsp_state == HSP_W4_USER_ACTION){ err = send_str_over_rfcomm(rfcomm_cid, HSP_HS_AT_CKPD); } else { err = send_str_over_rfcomm(rfcomm_cid, HSP_HS_BUTTON_PRESS); } if (!err) hs_send_button_press = 0; 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_W2_CONNECT_SCO: hsp_state = HSP_W4_SCO_CONNECTED; break; case HSP_W2_DISCONNECT_SCO: hsp_state = HSP_W4_SCO_DISCONNECTED; break; case HSP_ACTIVE: if (hs_ok_received) break; if (hs_microphone_gain >= 0){ char buffer[20]; sprintf(buffer, "%s=%d\r\n", HSP_HS_MICROPHONE_GAIN, hs_microphone_gain); err = send_str_over_rfcomm(rfcomm_cid, buffer); if (!err) 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); err = send_str_over_rfcomm(rfcomm_cid, buffer); if (!err) hs_speaker_gain = -1; break; } break; default: break; } }
void hfp_establish_service_level_connection(bd_addr_t bd_addr, uint16_t service_uuid){ hfp_connection_t * context = provide_hfp_connection_context_for_bd_addr(bd_addr); log_info("hfp_connect %s, context %p", bd_addr_to_str(bd_addr), context); if (!context) { log_error("hfp_establish_service_level_connection for addr %s failed", bd_addr_to_str(bd_addr)); return; } switch (context->state){ case HFP_W2_DISCONNECT_RFCOMM: context->state = HFP_SERVICE_LEVEL_CONNECTION_ESTABLISHED; return; case HFP_W4_RFCOMM_DISCONNECTED: context->state = HFP_W4_RFCOMM_DISCONNECTED_AND_RESTART; return; case HFP_IDLE: memcpy(context->remote_addr, bd_addr, 6); context->state = HFP_W4_SDP_QUERY_COMPLETE; connection_doing_sdp_query = context; context->service_uuid = service_uuid; sdp_query_rfcomm_channel_and_name_for_uuid(context->remote_addr, service_uuid); break; default: break; } }
static void packet_handler(void* connection, uint8_t packet_type, uint16_t channel, uint8_t* packet, uint16_t size) { bd_addr_t event_addr; uint16_t mtu; int ret; switch (packet_type) { case RFCOMM_DATA_PACKET: printf("Received RFCOMM data on channel id %u, size %u\n", channel, size); hexdump(packet, size); rfcomm_send_internal(local_spp_channel, packet, size); // Simple ECHO break; case HCI_EVENT_PACKET: switch (packet[0]) { case BTSTACK_EVENT_STATE: // bt stack activated, get started if (packet[2] == HCI_STATE_WORKING){ // Inquiry SDP at first sdp_query_rfcomm_channel_and_name_for_uuid(remote_addr, 0x1101/*0x1002*/); // 0x1101 is the UUID for SPP } break; case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE: // data: event(8), len(8), status (8), address (48), handle(16), server channel(8), rfcomm_cid(16), max frame size(16) if (packet[2]) { printf("RFCOMM channel open failed, status %u\n", packet[2]); } else { local_spp_channel = READ_BT_16(packet, 12); mtu = READ_BT_16(packet, 14); printf( "RFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u\n", local_spp_channel, mtu); } break; case HCI_EVENT_DISCONNECTION_COMPLETE: printf("[bluetooth] Connection closed\n"); break; default: break; } break; default: break; } }
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ if (packet_type != HCI_EVENT_PACKET) return; uint8_t event = packet[0]; switch (event) { case BTSTACK_EVENT_STATE: // bt stack activated, get started if (packet[2] == HCI_STATE_WORKING){ // sdp_query_rfcomm_channel_and_name_for_uuid(remote, 0x1101/*0x1002*/); // 0x1101 is the UUID for SPP sdp_query_rfcomm_channel_and_name_for_uuid(remote, 0x1002); // 0x1101 is the UUID for SPP } break; default: break; } }
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ printf("packet_handler type %u, packet[0] %x\n", packet_type, packet[0]); if (packet_type != HCI_EVENT_PACKET) return; uint8_t event = packet[0]; switch (event) { case BTSTACK_EVENT_STATE: // bt stack activated, get started if (packet[2] == HCI_STATE_WORKING){ sdp_query_rfcomm_channel_and_name_for_uuid(remote, 0x1002); } break; default: break; } }
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ // printf("packet_handler type %u, packet[0] %x\n", packet_type, packet[0]); if (packet_type != HCI_EVENT_PACKET) return; uint8_t event = packet[0]; switch (event) { case BTSTACK_EVENT_STATE: // bt stack activated, get started if (packet[2] == HCI_STATE_WORKING){ sdp_query_rfcomm_channel_and_name_for_uuid(remote, SDP_PublicBrowseGroup); } break; case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE: // data: event(8), len(8), status (8), address (48), handle(16), server channel(8), rfcomm_cid(16), max frame size(16) if (packet[2]) { printf("RFCOMM channel open failed, status %u\n", packet[2]); } else { // data: event(8), len(8), status (8), address (48), handle (16), server channel(8), rfcomm_cid(16), max frame size(16) rfcomm_cid = READ_BT_16(packet, 12); mtu = READ_BT_16(packet, 14); printf("RFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u\n", rfcomm_cid, mtu); if ((test_data_len > mtu)) { test_data_len = mtu; } if (rfcomm_can_send_packet_now(rfcomm_cid)) send_packet(); break; } break; case DAEMON_EVENT_HCI_PACKET_SENT: case RFCOMM_EVENT_CREDITS: if (rfcomm_can_send_packet_now(rfcomm_cid)) send_packet(); break; default: break; } }
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; } }
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; }