From: DoHyun Pyun Date: Thu, 12 Mar 2020 06:49:18 +0000 (+0900) Subject: Add the spp infinite test X-Git-Tag: accepted/tizen/unified/20200316.221052^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8c42129c58d73e0967df4015d7e9a064b28c0b6b;p=platform%2Fcore%2Fapi%2Fbluetooth.git Add the spp infinite test Change-Id: I2e50e5f5e0813d3f9a9610848b83aead5224041c Signed-off-by: DoHyun Pyun --- diff --git a/packaging/capi-network-bluetooth.spec b/packaging/capi-network-bluetooth.spec index 84a3bda..cbb0314 100644 --- a/packaging/capi-network-bluetooth.spec +++ b/packaging/capi-network-bluetooth.spec @@ -43,7 +43,6 @@ Requires: %{name} = %{version}-%{release} %description test This package is C-API test application. - %if 0%{?gcov:1} %package gcov Summary: Network Bluetooth Framework library(gcov) @@ -107,6 +106,9 @@ mkdir -p %{buildroot}%{_datadir}/gcov/obj install -m 0644 gcov-obj/* %{buildroot}%{_datadir}/gcov/obj %endif +mkdir -p %{buildroot}%{_unitdir} +install -m 0644 test/bt_infinite_spp_test_server.service %{buildroot}%{_unitdir}/bt_infinite_spp_test_server.service + %post -p /sbin/ldconfig %postun -p /sbin/ldconfig @@ -122,6 +124,8 @@ install -m 0644 gcov-obj/* %{buildroot}%{_datadir}/gcov/obj %{_bindir}/bt_onoff %{_bindir}/ble_mouse %{_bindir}/hid_keyboard +%{_bindir}/bt_infinite_spp_test +%{_unitdir}/bt_infinite_spp_test_server.service #/etc/smack/accesses.d/capi-network-bluetooth-test.efl %files devel diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 34d5dd4..a8d35f9 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -20,3 +20,4 @@ INSTALL(TARGETS bt_unit_test DESTINATION bin) INSTALL(TARGETS bt_onoff DESTINATION bin) INSTALL(TARGETS ble_mouse DESTINATION bin) INSTALL(TARGETS hid_keyboard DESTINATION bin) +INSTALL(TARGETS bt_infinite_spp_test DESTINATION bin) diff --git a/test/bt_infinite_spp_test.c b/test/bt_infinite_spp_test.c new file mode 100644 index 0000000..97326d8 --- /dev/null +++ b/test/bt_infinite_spp_test.c @@ -0,0 +1,538 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#undef LOG_TAG +#define LOG_TAG "BLUETOOTH_SPP_TEST" + +#define BT_DBG(fmt, args...) \ + SLOGD(fmt, ##args) +#define BT_INFO(fmt, args...) \ + SLOGI(fmt, ##args) +#define BT_ERR(fmt, args...) \ + SLOGE(fmt, ##args) + +typedef enum +{ + BT_SPP_TEST_ROLE_SERVER = 0x00, + BT_SPP_TEST_ROLE_CLIENT, +} bt_spp_test_role_e; + +#define BT_INFINITE_SPP_TEST_REMOTE_ADDRESS_FILE_PATH "/opt/usr/home/owner/media/Downloads/spp_test_addr" +#define BT_INFINITE_SPP_TEST_RESULT_FILE_PATH "/opt/usr/home/owner/media/Downloads/spp_result.log" + +bool __bt_connect_spp(void); +static gboolean __bt_send_data(gpointer user_data); +bool __bt_verify_data(char *data, int data_size); +bool __bt_bond_remote_device(void); +bool __bt_is_paired(void); + +static GMainLoop* g_mainloop = NULL; + +static bt_spp_test_role_e spp_role = BT_SPP_TEST_ROLE_SERVER; +static char remote_addr[18] = {0,}; +static bt_adapter_state_e bt_state = BT_ADAPTER_DISABLED; + +const char *spp_secure_uuid = "fa87c0d0-afac-11de-8a39-0800200c9a66"; +static int server_fd = -1; +static int socket_fd = -1; +static bool is_receive_complete = false; + +static int packet_size = 65536; +static char *buf = NULL; +static int total_count = 32; +static int sent_count = 0; +static int receive_count = 0; +static int receive_index = 0; + +static struct timeval start_time = {0,}; +static struct timeval end_time = {0,}; +static struct timeval diff_time = {0,}; + +static int sum_time_ms = 0; +static int avg_time_ms = 0; +static int total_test_count = 0; + +void __bt_create_log_dump(void) +{ + char *argv[] = {"/usr/bin/crashctl", "dump_log", "normal", NULL}; + execv("/usr/bin/crashctl", argv); + + BT_ERR("Fail to verify data"); + +#if 0 + if (g_mainloop) + g_main_loop_quit(g_mainloop); + else + exit(0); +#endif +} + +static void __bt_socket_data_received_cb(bt_socket_received_data_s *data, void *user_data) +{ + if (data == NULL) { + BT_ERR("data is NULL"); + return; + } + BT_INFO("FD = %d, Buffer len = %d", data->socket_fd, data->data_size); + + if (__bt_verify_data(data->data, data->data_size) == false) + __bt_create_log_dump(); + + if (is_receive_complete == true) + g_idle_add(__bt_send_data, NULL); +} + +static void __bt_device_bond_created_cb(int result, bt_device_info_s *device_info, void *user_data) +{ + if (result != BT_ERROR_NONE) { + BT_ERR("result[0x%X]", result); + return; + } + + if (strcmp(device_info->remote_address, remote_addr) == 0) { + if (__bt_connect_spp() == false) + BT_ERR("__bt_connect_spp() failed."); + } +} + +static bool __bt_adapter_bonded_device_cb(bt_device_info_s *device_info, void *user_data) +{ + bool *is_paired = (bool*)user_data; + + if (strcmp(device_info->remote_address, remote_addr) == 0) { + BT_INFO("remote_addr is exist."); + *is_paired = true; + return false; + } + + return true; +} + +void __bt_adapter_state_changed_cb(int result, bt_adapter_state_e adapter_state, void *user_data) +{ + BT_INFO("result [0x%04x] state = %d", result, adapter_state); + + if (result == BT_ERROR_NONE) { + bt_state = adapter_state; + if (adapter_state == BT_ADAPTER_ENABLED) { + if (__bt_is_paired() == true) + __bt_connect_spp(); + else + __bt_bond_remote_device(); + } + } +} + +void __bt_socket_connection_state_changed_cb(int result, bt_socket_connection_state_e connection_state, bt_socket_connection_s *connection, void *user_data) +{ + if (connection_state == BT_SOCKET_CONNECTED) { + BT_INFO("RFCOMM connected, result [0x%04x] Fd = %d, device add = %s, Role = %s", + result, connection->socket_fd, connection->remote_address, + (connection->local_role == BT_SOCKET_SERVER) ? "SERVER" : "CLIENT"); + + if (connection->socket_fd > 0) { + socket_fd = connection->socket_fd; + if (spp_role == BT_SPP_TEST_ROLE_CLIENT) + g_idle_add(__bt_send_data, NULL); + } else { + BT_ERR("socket_fd is INVALID"); + } + } else { + BT_INFO("RFCOMM disconnected, result [0x%04x] Fd = %d, device add = %s", + result, connection->socket_fd, connection->remote_address); + __bt_create_log_dump(); + } +} + +void __bt_spp_calc_speed(void) +{ + int total_time_ms; + FILE *fp = NULL; + static char str_speed[30] = "\0"; + int speed; + + diff_time.tv_sec = end_time.tv_sec - start_time.tv_sec; + diff_time.tv_usec = end_time.tv_usec - start_time.tv_usec; + + if(diff_time.tv_usec < 0) + { + diff_time.tv_sec = diff_time.tv_sec - 1; + diff_time.tv_usec = diff_time.tv_usec + 1000000; + } + + fp = fopen(BT_INFINITE_SPP_TEST_RESULT_FILE_PATH, "a+"); + /* Fix : NULL_RETURNS */ + if (fp == NULL) { + BT_ERR("Cannot open file: %s\n", BT_INFINITE_SPP_TEST_RESULT_FILE_PATH); + return; + } + total_time_ms = (diff_time.tv_sec * 1000); + total_time_ms += diff_time.tv_usec / 1000; + + speed = (packet_size * total_count * 8) / total_time_ms; + + BT_INFO("%s @ %d kbps", "2MB", speed); + snprintf(str_speed, 30, "%s @ %d kbps", "2MB", speed); + fprintf(fp, "%s\n", str_speed); + + total_test_count++; + sum_time_ms += total_time_ms; + if (total_test_count % 10 == 0) { + avg_time_ms = sum_time_ms / total_test_count; + speed = (packet_size * total_count * 8) / avg_time_ms; + BT_INFO("[AVG(%d times)] %d kbps", total_test_count, speed); + snprintf(str_speed, 30, "[AVG(%d times)] %d kbps", total_test_count, speed); + fprintf(fp, "%s\n", str_speed); + } + + if (total_test_count == 1000) { + sum_time_ms = 0; + avg_time_ms = 0; + total_test_count = 0; + } + + fclose(fp); +} + +void __bt_make_data(void) +{ + int i; + int j; + char w = 0x20; + + memset(buf, 0x00, packet_size); + for (i = 0; i < packet_size / 256; i++) { + for (j = 0; j < 256; j++) { + buf[i * 256 + j] = w; + } + + w++; + if (w > 0x7e) + w = 0x20; + } +} + +bool __bt_verify_data(char *data, int data_size) +{ + int i; + + if (receive_count == 0 && receive_index == 0) + gettimeofday(&start_time, NULL); + + for (i = 0; i < data_size; i++) { + if (data[i] != buf[receive_index]) { + BT_ERR("data error. rcv_cnt=%d, data[%d]=%d, buf[%d]=%d", receive_count, i, data[i], receive_index, buf[receive_index]); + return false; + } + + receive_index++; + if (receive_index == packet_size) { + receive_index = 0; + receive_count++; + + if (receive_count == total_count) + is_receive_complete = true; + } + } + + if (is_receive_complete == true) { + gettimeofday(&end_time, NULL); + __bt_spp_calc_speed(); + receive_count = 0; + receive_index = 0; + } + + return true; +} + +static gboolean __bt_send_data(gpointer user_data) +{ + int ret = BT_ERROR_NONE; + int write = 0; + int state = 0; + struct timeval tv_write_timeout = {0, }; + fd_set wfds; + int fail_count = 0; + + tv_write_timeout.tv_sec = 1; + + is_receive_complete = false; + + if (sent_count == 0) + gettimeofday(&start_time, NULL); + + while (write < packet_size) { + FD_ZERO(&wfds); + FD_SET(socket_fd, &wfds); + state = select(socket_fd + 1, NULL, &wfds, NULL, &tv_write_timeout); + if (state == -1) { + BT_ERR("select() error.[0x%X]", ret); + __bt_create_log_dump(); + return FALSE; + } else { + if (FD_ISSET(socket_fd, &wfds)) { + ret = bt_socket_send_data(socket_fd, buf + write, packet_size - write); + if(ret <= 0) { + BT_ERR("bt_socket_send_data() failed.[0x%X]", ret); + __bt_create_log_dump(); + return FALSE; + } else { + write += ret; + } + fail_count = 0; + } else { + BT_ERR("socket is NOT ready.(fail_count = %d)", fail_count); + if (fail_count++ == 10) { + BT_ERR("__bt_send_data failed."); + __bt_create_log_dump(); + return FALSE; + } + } + } + } + + sent_count++; + if (sent_count == total_count) { + BT_INFO("Last packet."); + gettimeofday(&end_time, NULL); + __bt_spp_calc_speed(); + sent_count = 0; + } else { + return TRUE; + } + + return FALSE; +} + +static bool __bt_adapter_foreach_bonded_device_cb(bt_device_info_s *device_info, void *user_data) +{ + if (device_info != NULL) { + if (bt_device_set_authorization(device_info->remote_address, BT_DEVICE_AUTHORIZED) != BT_ERROR_NONE) + BT_ERR("Fail to authorize"); + } + + return true; +} + +bool __bt_connect_spp(void) +{ + int ret = BT_ERROR_NONE; + + if (spp_role == BT_SPP_TEST_ROLE_SERVER) { + if (bt_adapter_foreach_bonded_device(__bt_adapter_foreach_bonded_device_cb, NULL) != BT_ERROR_NONE) + BT_ERR("Fail to get bonded devices"); + + if (server_fd < 0) { + ret = bt_socket_create_rfcomm(spp_secure_uuid, &server_fd); + if (ret != BT_ERROR_NONE) { + BT_ERR("bt_socket_create_rfcomm() failed.[0x%X]", ret); + return false; + } + } + + ret = bt_socket_listen_and_accept_rfcomm(server_fd, 1); + if (ret != BT_ERROR_NONE) { + BT_ERR("bt_socket_listen_and_accept_rfcomm() failed.[0x%X]", ret); + return false; + } + } else { + ret = bt_socket_connect_rfcomm(remote_addr, spp_secure_uuid); + if (ret != BT_ERROR_NONE) { + BT_ERR("bt_socket_connect_rfcomm() failed.[0x%X]", ret); + bt_socket_destroy_rfcomm(server_fd); + return false; + } + } + + return true; +} + +bool __bt_bond_remote_device(void) +{ + int ret = BT_ERROR_NONE; + + ret = bt_device_set_bond_created_cb(__bt_device_bond_created_cb, NULL); + if (ret != BT_ERROR_NONE) { + BT_ERR("bt_device_set_bond_created_cb() failed.[0x%X]", ret); + return false; + } + + if (spp_role == BT_SPP_TEST_ROLE_CLIENT) { + ret = bt_device_create_bond(remote_addr); + if (ret != BT_ERROR_NONE) { + BT_ERR("bt_device_create_bond() failed.[0x%X]", ret); + return false; + } + } + + return true; +} + +bool __bt_is_paired(void) +{ + int ret = BT_ERROR_NONE; + bool is_paired = false; + + ret = bt_adapter_foreach_bonded_device(__bt_adapter_bonded_device_cb, &is_paired); + if (ret != BT_ERROR_NONE) { + BT_ERR("bt_adapter_foreach_bonded_device() failed.[0x%X]", ret); + return false; + } + + return is_paired; +} + +bool __bt_init(void) +{ + int ret = BT_ERROR_NONE; + + ret = bt_initialize(); + if(ret != BT_ERROR_NONE) { + BT_ERR("bt_initialize() failed.[0x%X]", ret); + return false; + } + + ret = bt_adapter_get_state(&bt_state); + if(ret != BT_ERROR_NONE) { + BT_ERR("bt_adapter_get_state() failed.[0x%X]", ret); + return false; + } + + ret = bt_adapter_set_state_changed_cb(__bt_adapter_state_changed_cb, NULL); + if(ret != BT_ERROR_NONE) { + BT_ERR("bt_adapter_get_state() failed.[0x%X]", ret); + return false; + } + + ret = bt_socket_set_connection_state_changed_cb(__bt_socket_connection_state_changed_cb, NULL); + if (ret != BT_ERROR_NONE) { + BT_ERR("bt_socket_set_connection_state_changed_cb() failed.[0x%X]", ret); + return false; + } + + ret = bt_socket_set_data_received_cb(__bt_socket_data_received_cb, NULL); + if (ret != BT_ERROR_NONE) { + BT_ERR("bt_socket_set_data_received_cb() failed.[0x%X]", ret); + return false; + } + + if (buf == NULL) { + buf = malloc(packet_size); + if (buf == NULL) { + BT_ERR("Out of memory"); + return false; + } + __bt_make_data(); + } + + return true; +} + +void __bt_deinit(void) +{ + int ret = BT_ERROR_NONE; + + if (buf) + free(buf); + + if (server_fd >= 0) + bt_socket_destroy_rfcomm(server_fd); + + ret = bt_socket_unset_data_received_cb(); + if (ret != BT_ERROR_NONE) + BT_ERR("bt_socket_unset_data_received_cb() failed.[0x%X]", ret); + + ret = bt_socket_unset_connection_state_changed_cb(); + if (ret != BT_ERROR_NONE) + BT_ERR("bt_socket_unset_connection_state_changed_cb() failed.[0x%X]", ret); + + ret = bt_device_unset_bond_created_cb(); + if (ret != BT_ERROR_NONE) + BT_ERR("bt_device_unset_bond_created_cb() failed.[0x%X]", ret); + + ret = bt_deinitialize(); + if(ret != BT_ERROR_NONE) + BT_ERR("bt_deinitialize() failed.[0x%X]", ret); +} + +bool __bt_set_remote_address(void) +{ + FILE *fp = NULL; + + if ((fp = fopen(BT_INFINITE_SPP_TEST_REMOTE_ADDRESS_FILE_PATH, "r")) == NULL) { + BT_ERR("remote_addr file is NOT exist."); + return false; + } + + if (fgets(remote_addr, 18, fp) == NULL) { + BT_ERR("remote_addr is INVALID."); + fclose(fp); + return false; + } + + fclose(fp); + return true; +} + +int main(int argc, char *argv[]) +{ + if (argc == 2 && strcmp(argv[1], "client") == 0) + spp_role = BT_SPP_TEST_ROLE_CLIENT; + BT_INFO("SPP test role is %s", spp_role==BT_SPP_TEST_ROLE_SERVER?"SERVER":"CLIENT"); + + if (spp_role == BT_SPP_TEST_ROLE_CLIENT) { + if (__bt_set_remote_address() == false) + return -1; + } + + if (__bt_init() == false) + goto fail; + + if (bt_state == BT_ADAPTER_ENABLED) { + if (spp_role == BT_SPP_TEST_ROLE_SERVER) { + if (bt_adapter_set_visibility(BT_ADAPTER_VISIBILITY_MODE_GENERAL_DISCOVERABLE, 0) != BT_ERROR_NONE) + BT_ERR("Fail to set visibility"); + + __bt_connect_spp(); + } else { + if (__bt_is_paired() == true) { + if (__bt_connect_spp() == false) + goto fail; + } else { + if (__bt_bond_remote_device() == false) + goto fail; + } + } + } + + g_mainloop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(g_mainloop); + +fail: + if (g_mainloop) + g_main_loop_unref(g_mainloop); + + __bt_deinit(); + + return 0; +} diff --git a/test/bt_infinite_spp_test_server.service b/test/bt_infinite_spp_test_server.service new file mode 100644 index 0000000..f622aee --- /dev/null +++ b/test/bt_infinite_spp_test_server.service @@ -0,0 +1,7 @@ +[Unit] +Description=BT SPP test infinitely + +[Service] +Type=oneshot +ExecStart=/usr/bin/bt_infinite_spp_test +RemainAfterExit=yes diff --git a/test/spp_test_addr b/test/spp_test_addr new file mode 100644 index 0000000..5dd70bf --- /dev/null +++ b/test/spp_test_addr @@ -0,0 +1 @@ +E4:FA:ED:75:D7:11