static void ssp_reply_p(int argc, const char **argv) { bt_bdaddr_t addr; bt_ssp_variant_t var; int accept; int passkey; RETURN_IF_NULL(if_bluetooth); VERIFY_ADDR_ARG(2, &addr); if (argc < 4) { haltest_error("No ssp variant specified\n"); return; } var = str2btsspvariant(argv[3]); if (argc < 5) { haltest_error("No accept value specified\n"); return; } accept = atoi(argv[4]); passkey = 0; if (accept && var == BT_SSP_VARIANT_PASSKEY_ENTRY && argc >= 5) passkey = atoi(argv[4]); EXEC(if_bluetooth->ssp_reply, &addr, var, accept, passkey); }
static void get_report_p(int argc, const char **argv) { bt_bdaddr_t addr; bthh_report_type_t reportType; uint8_t reportId; int bufferSize; RETURN_IF_NULL(if_hh); VERIFY_ADDR_ARG(2, &addr); if (argc < 4) { haltest_error("No report type specified\n"); return; } reportType = str2bthh_report_type_t(argv[3]); if (argc < 5) { haltest_error("No reportId specified\n"); return; } reportId = (uint8_t) atoi(argv[4]); if (argc < 6) { haltest_error("No bufferSize specified\n"); return; } bufferSize = atoi(argv[5]); EXEC(if_hh->get_report, &addr, reportType, reportId, bufferSize); }
static void get_play_status_rsp_p(int argc, const char **argv) { btrc_play_status_t play_status; uint32_t song_len, song_pos; RETURN_IF_NULL(if_rc); if (argc <= 2) { haltest_error("No play status specified"); return; } if (argc <= 3) { haltest_error("No song length specified"); return; } if (argc <= 4) { haltest_error("No song position specified"); return; } play_status = str2btrc_play_status_t(argv[2]); song_len = (uint32_t) atoi(argv[3]); song_pos = (uint32_t) atoi(argv[4]); EXEC(if_rc->get_play_status_rsp, play_status, song_len, song_pos); }
static void connect_channel_p(int argc, const char **argv) { uint32_t app_id, mdep_cfg_index; int channel_id = -1; bt_bdaddr_t bd_addr; RETURN_IF_NULL(if_hl); if (argc <= 2) { haltest_error("No app id is specified"); return; } VERIFY_ADDR_ARG(3, &bd_addr); if (argc <= 4) { haltest_error("No mdep cfg index is specified"); return; } app_id = (uint32_t) atoi(argv[2]); mdep_cfg_index = (uint32_t) atoi(argv[4]); EXEC(if_hl->connect_channel, app_id, &bd_addr, mdep_cfg_index, &channel_id); }
static void init_p(int argc, const char **argv) { int err; const hw_module_t *module; hw_device_t *device; err = hw_get_module(BT_HARDWARE_MODULE_ID, &module); if (err) { haltest_error("he_get_module returned %d\n", err); return; } err = module->methods->open(module, BT_HARDWARE_MODULE_ID, &device); if (err) { haltest_error("module->methods->open returned %d\n", err); return; } if_bluetooth = ((bluetooth_device_t *) device)->get_bluetooth_interface(); if (!if_bluetooth) { haltest_error("get_bluetooth_interface returned NULL\n"); return; } EXEC(if_bluetooth->init, &bt_callbacks); }
static void connect_p(int argc, const char **argv) { bt_bdaddr_t addr; int local_role; int remote_role; RETURN_IF_NULL(if_pan); VERIFY_ADDR_ARG(2, &addr); /* local role */ if (argc < 4) { haltest_error("No local mode specified\n"); return; } local_role = str2btpan_role_t(argv[3]); if (local_role == -1) local_role = atoi(argv[3]); /* remote role */ if (argc < 5) { haltest_error("No remote mode specified\n"); return; } remote_role = str2btpan_role_t(argv[4]); if (remote_role == -1) remote_role = atoi(argv[4]); EXEC(if_pan->connect, &addr, local_role, remote_role); }
/* perform specified call related action */ static void handle_call_action_p(int argc, const char **argv) { bthf_client_call_action_t action; int index = 0; RETURN_IF_NULL(if_hf_client); /* action */ if (argc <= 2) { haltest_error("No action specified\n"); return; } action = str2bthf_client_call_action_t(argv[2]); /* call index */ if (action == BTHF_CLIENT_CALL_ACTION_CHLD_1x || action == BTHF_CLIENT_CALL_ACTION_CHLD_2x) { if (argc <= 3) { haltest_error("No call index specified\n"); return; } index = atoi(argv[3]); } EXEC(if_hf_client->handle_call_action, action, index); }
static void gatts_add_characteristic_p(int argc, const char *argv[]) { int server_if; int service_handle; int properties; int permissions; bt_uuid_t uuid; RETURN_IF_NULL(if_gatt); VERIFY_SERVER_IF(2, server_if); VERIFY_SERVICE_HANDLE(3, service_handle); VERIFY_UUID(4, &uuid); /* properties */ if (argc <= 5) { haltest_error("No properties specified\n"); return; } properties = atoi(argv[5]); /* permissions */ if (argc <= 6) { haltest_error("No permissions specified\n"); return; } permissions = atoi(argv[6]); EXEC(if_gatt->server->add_characteristic, server_if, service_handle, &uuid, properties, permissions); }
static void open_output_stream_p(int argc, const char **argv) { int err; RETURN_IF_NULL(if_audio); pthread_mutex_lock(&state_mutex); if (current_state == STATE_PLAYING) { haltest_error("Already playing!\n"); pthread_mutex_unlock(&state_mutex); return; } pthread_mutex_unlock(&state_mutex); err = if_audio->open_output_stream(if_audio, 0, AUDIO_DEVICE_OUT_ALL_A2DP, AUDIO_OUTPUT_FLAG_NONE, NULL, &stream_out); if (err < 0) { haltest_error("open output stream returned %d\n", err); return; } buffer_size = stream_out->common.get_buffer_size(&stream_out->common); if (buffer_size == 0) haltest_error("Invalid buffer size received!\n"); else haltest_info("Using buffer size: %zu\n", buffer_size); }
static void listen_p(int argc, const char **argv) { btsock_type_t type; const char *service_name; bt_uuid_t service_uuid; int channel; int sock_fd = -1; int flags; RETURN_IF_NULL(if_sock); /* Socket type */ if (argc < 3) { haltest_error("No socket type specified\n"); return; } type = str2btsock_type_t(argv[2]); if ((int) type == -1) type = atoi(argv[2]); /* service name */ if (argc < 4) { haltest_error("No service name specified\n"); return; } service_name = argv[3]; /* uuid */ if (argc < 5) { haltest_error("No uuid specified\n"); return; } str2bt_uuid_t(argv[4], &service_uuid); /* channel */ channel = argc > 5 ? atoi(argv[5]) : 0; /* flags */ flags = argc > 6 ? atoi(argv[6]) : 0; if (listen_fd_count >= MAX_LISTEN_FD) { haltest_error("Max (%d) listening sockets exceeded\n", listen_fd_count); return; } EXEC(if_sock->listen, type, service_name, &service_uuid.uu[0], channel, &sock_fd, flags); if (sock_fd > 0) { int channel = 0; int ret = read(sock_fd, &channel, 4); if (ret != 4) haltest_info("Read channel failed\n"); haltest_info("Channel returned from first read %d\n", channel); listen_fd[listen_fd_count++] = sock_fd; poll_register_fd(sock_fd, POLLIN, client_connected); } }
static void connect_p(int argc, const char **argv) { bt_bdaddr_t addr; btsock_type_t type; bt_uuid_t uuid; int channel; int sock_fd = -1; int flags; /* Address */ if (argc <= 2) { haltest_error("No address specified\n"); return; } str2bt_bdaddr_t(argv[2], &addr); /* Socket type */ if (argc <= 3) { haltest_error("No socket type specified\n"); return; } type = str2btsock_type_t(argv[3]); if ((int) type == -1) type = atoi(argv[3]); /* uuid */ if (argc <= 4) { haltest_error("No uuid specified\n"); return; } str2bt_uuid_t(argv[4], &uuid); /* channel */ if (argc <= 5) { haltest_error("No channel specified\n"); return; } channel = atoi(argv[5]); /* flags */ flags = argc <= 6 ? 0 : atoi(argv[6]); RETURN_IF_NULL(if_sock); EXEC(if_sock->connect, &addr, type, &uuid.uu[0], channel, &sock_fd, flags); if (sock_fd > 0) { int channel = 0; int ret = read(sock_fd, &channel, 4); if (ret != 4) haltest_info("Read channel failed\n"); haltest_info("Channel returned from first read %d\n", channel); listen_fd[listen_fd_count++] = sock_fd; poll_register_fd(sock_fd, POLLIN, receive_sock_connect_signal); } }
/* * This function read from fd socket information about * incoming connection and starts monitoring new connection * on file descriptor read from fd. */ static void read_accepted(int fd) { int ret; struct msghdr msg; struct iovec iv; char cmsgbuf[CMSG_SPACE(1)]; struct cmsghdr *cmsgptr; sock_connect_signal_t cs; int accepted_fd = -1; char addr_str[MAX_ADDR_STR_LEN]; memset(&msg, 0, sizeof(msg)); memset(&iv, 0, sizeof(iv)); memset(cmsgbuf, 0, sizeof(cmsgbuf)); iv.iov_base = &cs; iv.iov_len = sizeof(cs); msg.msg_iov = &iv; msg.msg_iovlen = 1; msg.msg_control = cmsgbuf; msg.msg_controllen = sizeof(cmsgbuf); do { ret = recvmsg(fd, &msg, MSG_NOSIGNAL); } while (ret < 0 && errno == EINTR); if (ret < 16 || (msg.msg_flags & (MSG_CTRUNC | MSG_OOB | MSG_ERRQUEUE)) != 0) haltest_error("Failed to accept connection\n"); for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) { int count; if (cmsgptr->cmsg_level != SOL_SOCKET || cmsgptr->cmsg_type != SCM_RIGHTS) continue; memcpy(&accepted_fd, CMSG_DATA(cmsgptr), sizeof(accepted_fd)); count = ((cmsgptr->cmsg_len - CMSG_LEN(0)) / sizeof(int)); if (count != 1) haltest_error("Failed to accept descriptors count=%d\n", count); break; } haltest_info("Incoming connection from %s channel %d status=%d fd=%d\n", bt_bdaddr_t2str(&cs.bd_addr, addr_str), cs.channel, cs.status, accepted_fd); poll_register_fd(accepted_fd, POLLIN, receive_from_client); }
static void phone_state_change_p(int argc, const char **argv) { int num_active; int num_held; bthf_call_state_t call_setup_state; const char *number; bthf_call_addrtype_t type; RETURN_IF_NULL(if_hf); /* num_active */ if (argc <= 2) { haltest_error("No num_active specified\n"); return; } num_active = atoi(argv[2]); /* num_held */ if (argc <= 3) { haltest_error("No num_held specified\n"); return; } num_held = atoi(argv[3]); /* setup state */ if (argc <= 4) { haltest_error("No call setup state specified\n"); return; } call_setup_state = str2bthf_call_state_t(argv[4]); /* number */ if (argc <= 5) { haltest_error("No number specified\n"); return; } number = argv[5]; /* call mpty type */ if (argc <= 6) { haltest_error("No address type specified\n"); return; } type = str2bthf_call_addrtype_t(argv[6]); EXEC(if_hf->phone_state_change, num_active, num_held, call_setup_state, number, type); }
/* * This function read from fd socket information about * connected socket */ static void receive_sock_connect_signal(struct pollfd *pollfd) { sock_connect_signal_t cs; char addr_str[MAX_ADDR_STR_LEN]; if (pollfd->revents & POLLIN) { int ret; poll_unregister_fd(pollfd->fd, receive_sock_connect_signal); ret = read(pollfd->fd, &cs, sizeof(cs)); if (ret != sizeof(cs)) { haltest_info("Read on connect return %d\n", ret); return; } haltest_info("Connection to %s channel %d status=%d\n", bt_bdaddr_t2str(&cs.bd_addr, addr_str), cs.channel, cs.status); if (cs.status == 0) poll_register_fd(pollfd->fd, POLLIN, receive_from_client); } if (pollfd->revents & POLLHUP) { haltest_error("Disconnected fd=%d revents=0x%X\n", pollfd->fd, pollfd->revents); poll_unregister_fd(pollfd->fd, receive_sock_connect_signal); } }
static void gatts_send_indication_p(int argc, const char *argv[]) { int server_if; int attr_handle; int conn_id; int confirm; char data[200]; int len = 0; RETURN_IF_NULL(if_gatt); VERIFY_SERVER_IF(2, server_if); VERIFY_HANDLE(3, attr_handle); VERIFY_CONN_ID(4, conn_id); /* confirm */ if (argc <= 5) { haltest_error("No transport specified\n"); return; } confirm = atoi(argv[5]); if (argc > 6) { len = strlen(argv[6]); scan_field(argv[6], len, (uint8_t *) data, sizeof(data)); } EXEC(if_gatt->server->send_indication, server_if, attr_handle, conn_id, len, confirm, data); }
static void test_command_p(int argc, const char **argv) { int command; int i; bt_bdaddr_t bd_addr; bt_uuid_t uuid; btgatt_test_params_t params = { .bda1 = &bd_addr, .uuid1 = &uuid }; uint16_t *u = ¶ms.u1; RETURN_IF_NULL(if_gatt); /* command */ if (argc <= 2) { haltest_error("No command specified\n"); return; } command = atoi(argv[2]); VERIFY_ADDR_ARG(3, &bd_addr); VERIFY_UUID(4, &uuid); for (i = 5; i < argc; i++) VERIFY_TEST_ARG(i, *u++); EXEC(if_gatt->client->test_command, command, ¶ms); }
static void play_p(int argc, const char **argv) { const char *fname = NULL; FILE *in = NULL; RETURN_IF_NULL(if_audio); RETURN_IF_NULL(stream_out); if (argc < 3) { haltest_error("Invalid audio file path.\n"); haltest_info("Using sound generator.\n"); } else { fname = argv[2]; in = fopen(fname, "r"); if (in == NULL) { haltest_error("Cannot open file: %s\n", fname); return; } haltest_info("Playing file: %s\n", fname); } if (buffer_size == 0) { haltest_error("Invalid buffer size. Was stream_out opened?\n"); goto fail; } pthread_mutex_lock(&state_mutex); if (current_state != STATE_STOPPED) { haltest_error("Already playing or stream suspended!\n"); pthread_mutex_unlock(&state_mutex); goto fail; } pthread_mutex_unlock(&state_mutex); if (pthread_create(&play_thread, NULL, playback_thread, in) != 0) { haltest_error("Cannot create playback thread!\n"); goto fail; } return; fail: if (in) fclose(in); }
static void write_descriptor_p(int argc, const char **argv) { int conn_id; btgatt_srvc_id_t srvc_id; btgatt_gatt_id_t char_id; btgatt_descr_id_t descr_id; int write_type; int len; int auth_req = 0; uint8_t value[200] = {0}; RETURN_IF_NULL(if_gatt); VERIFY_CONN_ID(2, conn_id); VERIFY_SRVC_ID(3, &srvc_id); VERIFY_CHAR_ID(4, &char_id); VERIFY_DESCR_ID(5, &descr_id); /* write type */ if (argc <= 6) { haltest_error("No write type specified\n"); return; } write_type = atoi(argv[6]); /* value */ if (argc <= 7) { haltest_error("No value specified\n"); return; } /* len in chars */ if (strncmp(argv[7], "0X", 2) && strncmp(argv[7], "0x", 2)) { haltest_error("Value must be hex string"); return; } len = fill_buffer(argv[7] + 2, value, sizeof(value)); /* auth_req */ if (argc > 8) auth_req = atoi(argv[8]); EXEC(if_gatt->client->write_descriptor, conn_id, &srvc_id, &char_id, &descr_id, write_type, len, auth_req, (char *) value); }
static void source_p(int argc, const char **argv) { if (argc < 2) { haltest_error("No file specified"); return; } process_file(argv[1]); }
static void gatts_send_response_p(int argc, const char *argv[]) { int conn_id; int trans_id; int status; btgatt_response_t data; memset(&data, 0, sizeof(data)); RETURN_IF_NULL(if_gatt); VERIFY_CONN_ID(2, conn_id); VERIFY_TRANS_ID(3, trans_id); VERIFY_STATUS(4, status); VERIFY_HANDLE(5, data.attr_value.handle); VERIFY_OFFSET(6, data.attr_value.offset); data.attr_value.auth_req = 0; data.attr_value.len = 0; if (argc > 7) { const char *str; if (strncmp(argv[7], "0X", 2) && strncmp(argv[7], "0x", 2)) { haltest_error("Value must be hex string"); return; } str = argv[7] + 2; data.attr_value.len = fill_buffer(str, data.attr_value.value, sizeof(data.attr_value.value)); if (data.attr_value.len == 0) { haltest_error("Failed to parse response value"); return; } } haltest_info("conn_id %d, trans_id %d, status %d", conn_id, trans_id, status); EXEC(if_gatt->server->send_response, conn_id, trans_id, status, &data); }
static void write_descriptor_p(int argc, const char **argv) { int conn_id; btgatt_srvc_id_t srvc_id; btgatt_gatt_id_t char_id; btgatt_descr_id_t descr_id; int write_type; int len; int auth_req = 0; uint8_t value[200] = {0}; RETURN_IF_NULL(if_gatt); VERIFY_CONN_ID(2, conn_id); VERIFY_SRVC_ID(3, &srvc_id); VERIFY_CHAR_ID(4, &char_id); VERIFY_DESCR_ID(5, &descr_id); /* write type */ if (argc <= 6) { haltest_error("No write type specified\n"); return; } write_type = atoi(argv[6]); /* value */ if (argc <= 7) { haltest_error("No value specified\n"); return; } /* len in chars */ len = strlen(argv[7]); scan_field(argv[7], len, value, sizeof(value)); /* len in bytes converted from ascii chars */ len = (len + 1) / 2; /* auth_req */ if (argc > 8) auth_req = atoi(argv[8]); EXEC(if_gatt->client->write_descriptor, conn_id, &srvc_id, &char_id, &descr_id, write_type, len, auth_req, (char *) value); }
static void process_file(const char *name) { int fd = open(name, O_RDONLY); if (fd < 0) { haltest_error("Can't open file: %s for reading\n", name); return; } if (fd_stack_pointer >= 10) { haltest_error("To many open files\n"); close(fd); return; } fd_stack[fd_stack_pointer++] = fd; poll_unregister_fd(fd_stack[fd_stack_pointer - 2], stdin_handler); poll_register_fd(fd_stack[fd_stack_pointer - 1], POLLIN, stdin_handler); }
static void get_profile_interface_p(int argc, const char **argv) { const char *id; const void **pif = NULL; RETURN_IF_NULL(if_bluetooth); if (argc <= 2) { haltest_error("No interface specified\n"); return; } id = argv[2]; if (strcmp(BT_PROFILE_HANDSFREE_ID, id) == 0) pif = (const void **) &if_hf; else if (strcmp(BT_PROFILE_ADVANCED_AUDIO_ID, id) == 0) pif = (const void **) &if_av; else if (strcmp(BT_PROFILE_HEALTH_ID, id) == 0) pif = (const void **) &if_hl; else if (strcmp(BT_PROFILE_SOCKETS_ID, id) == 0) pif = (const void **) &if_sock; else if (strcmp(BT_PROFILE_HIDHOST_ID, id) == 0) pif = (const void **) &if_hh; else if (strcmp(BT_PROFILE_PAN_ID, id) == 0) pif = (const void **) &if_pan; else if (strcmp(BT_PROFILE_AV_RC_ID, id) == 0) pif = (const void **) &if_rc; else if (strcmp(BT_PROFILE_GATT_ID, id) == 0) pif = (const void **) &if_gatt; #ifdef BLUEZ_EXTENSIONS else if (strcmp(BT_PROFILE_HANDSFREE_CLIENT_ID, id) == 0) pif = (const void **) &if_hf_client; #endif else haltest_error("%s is not correct for get_profile_interface\n", id); if (pif != NULL) { *pif = if_bluetooth->get_profile_interface(id); haltest_info("get_profile_interface(%s) : %p\n", id, *pif); } }
/* place a call with number a number */ static void dial_p(int argc, const char **argv) { RETURN_IF_NULL(if_hf_client); /* number string */ if (argc <= 2) { haltest_error("No number specified\n"); return; } EXEC(if_hf_client->dial, argv[2]); }
/* place a call with number specified by location (speed dial) */ static void dial_memory_p(int argc, const char **argv) { RETURN_IF_NULL(if_hf_client); /* memory index */ if (argc <= 2) { haltest_error("No memory index specified\n"); return; } EXEC(if_hf_client->dial_memory, atoi(argv[2])); }
static void set_parameters_p(int argc, const char **argv) { RETURN_IF_NULL(if_audio); RETURN_IF_NULL(stream_out); if (argc < 3) { haltest_error("No key=value; pairs given.\n"); return; } stream_out->common.set_parameters(&stream_out->common, argv[2]); }
static void init_p(int argc, const char **argv) { int err; const hw_module_t *module; audio_hw_device_t *device; err = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, AUDIO_HARDWARE_MODULE_ID_A2DP, &module); if (err) { haltest_error("hw_get_module_by_class returned %d\n", err); return; } err = audio_hw_device_open(module, &device); if (err) { haltest_error("audio_hw_device_open returned %d\n", err); return; } if_audio = device; }
static void formatted_at_response_p(int argc, const char **argv) { RETURN_IF_NULL(if_hf); /* response */ if (argc <= 2) { haltest_error("No response specified\n"); return; } EXEC(if_hf->formatted_at_response, argv[2]); }
static void set_report_p(int argc, const char **argv) { bt_bdaddr_t addr; bthh_report_type_t reportType; RETURN_IF_NULL(if_hh); VERIFY_ADDR_ARG(2, &addr); if (argc <= 3) { haltest_error("No report type specified\n"); return; } reportType = str2bthh_report_type_t(argv[3]); if (argc <= 4) { haltest_error("No report specified\n"); return; } EXEC(if_hh->set_report, &addr, reportType, (char *) argv[4]); }
static void device_status_notification_p(int argc, const char **argv) { bthf_network_state_t ntk_state; bthf_service_type_t svc_type; int signal; int batt_chg; RETURN_IF_NULL(if_hf); /* network state */ if (argc <= 2) { haltest_error("No network state specified\n"); return; } ntk_state = str2bthf_network_state_t(argv[2]); /* service type */ if (argc <= 3) { haltest_error("No service type specified\n"); return; } svc_type = str2bthf_service_type_t(argv[3]); /* signal */ if (argc <= 4) { haltest_error("No signal specified\n"); return; } signal = atoi(argv[4]); /* batt_chg */ if (argc <= 5) { haltest_error("No batt_chg specified\n"); return; } batt_chg = atoi(argv[5]); EXEC(if_hf->device_status_notification, ntk_state, svc_type, signal, batt_chg); }