int stdin_process(struct data_source *ds){ char buffer; read(ds->fd, &buffer, 1); switch (buffer){ case 'c': 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 's': printf("Send L2CAP Data\n"); l2cap_send_internal(local_cid, (uint8_t *) "0123456789", 10); break; case 'e': printf("Send L2CAP ECHO Request\n"); l2cap_send_echo_request(handle, (uint8_t *) "Hello World!", 13); break; case 'd': printf("L2CAP Channel Closed\n"); l2cap_disconnect_internal(local_cid, 0); break; case '\n': case '\r': break; default: show_usage(); break; } return 0; }
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; }
void sdp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ // uint16_t handle; if (packet_type == L2CAP_DATA_PACKET){ uint16_t responseTransactionID = READ_NET_16(packet,1); if ( responseTransactionID != transactionID){ log_error("Missmatching transaction ID, expected %u, found %u.", transactionID, responseTransactionID); return; } if (packet[0] != SDP_ServiceSearchAttributeResponse && packet[0] != SDP_ServiceSearchResponse && packet[0] != SDP_ServiceAttributeResponse){ log_error("Not a valid PDU ID, expected %u, %u or %u, found %u.", SDP_ServiceSearchResponse, SDP_ServiceAttributeResponse, SDP_ServiceSearchAttributeResponse, packet[0]); return; } PDU_ID = packet[0]; log_info("SDP Client :: PDU ID. %u ,%u", PDU_ID, packet[0]); switch (PDU_ID){ #ifdef HAVE_SDP_EXTRA_QUERIES case SDP_ServiceSearchResponse: parse_service_search_response(packet); break; case SDP_ServiceAttributeResponse: parse_service_attribute_response(packet); break; #endif case SDP_ServiceSearchAttributeResponse: parse_service_search_attribute_response(packet); break; default: log_error("SDP Client :: PDU ID invalid. %u ,%u", PDU_ID, packet[0]); return; } // continuation set or DONE? if (continuationStateLen == 0){ log_info("SDP Client Query DONE! "); sdp_client_state = QUERY_COMPLETE; l2cap_disconnect_internal(sdp_cid, 0); // sdp_parser_handle_done(0); return; } // prepare next request and send sdp_client_state = W2_SEND; if (can_send_now(sdp_cid)) send_request(sdp_cid); return; } if (packet_type != HCI_EVENT_PACKET) return; switch(packet[0]){ case L2CAP_EVENT_TIMEOUT_CHECK: log_info("sdp client: L2CAP_EVENT_TIMEOUT_CHECK"); break; case L2CAP_EVENT_CHANNEL_OPENED: if (sdp_client_state != W4_CONNECT) break; // data: event (8), len(8), status (8), address(48), handle (16), psm (16), local_cid(16), remote_cid (16), local_mtu(16), remote_mtu(16) if (packet[2]) { log_error("SDP Client Connection failed."); sdp_parser_handle_done(packet[2]); break; } sdp_cid = channel; mtu = READ_BT_16(packet, 17); // handle = READ_BT_16(packet, 9); log_info("SDP Client Connected, cid %x, mtu %u.", sdp_cid, mtu); sdp_client_state = W2_SEND; if (can_send_now(sdp_cid)) send_request(sdp_cid); break; case L2CAP_EVENT_CREDITS: case DAEMON_EVENT_HCI_PACKET_SENT: if (can_send_now(sdp_cid)) send_request(sdp_cid); break; case L2CAP_EVENT_CHANNEL_CLOSED: { if (sdp_cid != READ_BT_16(packet, 2)) { // log_info("Received L2CAP_EVENT_CHANNEL_CLOSED for cid %x, current cid %x\n", READ_BT_16(packet, 2),sdp_cid); break; } log_info("SDP Client disconnected."); uint8_t status = sdp_client_state == QUERY_COMPLETE ? 0 : SDP_QUERY_INCOMPLETE; sdp_client_state = INIT; sdp_parser_handle_done(status); 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; }