Code synchronization with latest tizen 4.0 codes
[platform/core/connectivity/bluetooth-frwk.git] / test / gatt-test / bluetooth-gatt-test.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *              http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 /**
19  * @file       bluetooth-gatt-test.c
20  * @brief      This is the source file for bluetooth framework test suite.
21  */
22
23 #include <stdio.h>
24 #include <errno.h>
25 #include <ctype.h>
26 #include <fcntl.h>
27 #include <unistd.h>
28 #include <stdint.h>
29 #include <string.h>
30 #include <glib.h>
31 #include "bluetooth-api.h"
32
33
34 #define PRT(format, args...) printf("%s:%d() "format, __FUNCTION__, __LINE__, ##args)
35 #define TC_PRT(format, args...) PRT(format"\n", ##args)
36
37 #define TC_PASS 1
38 #define TC_FAIL 0
39
40 GMainLoop *main_loop = NULL;
41
42 typedef struct {
43         const char *tc_name;
44         int tc_code;
45 } tc_table_t;
46
47 tc_table_t tc_table[] = {
48         {"Send alert to remote le device"               , 1},
49         {"Set Link loss alert"          , 2},
50
51         /* -----------------------------------------*/
52         {"Finish"                                       , 0x00ff},
53         {NULL                                   , 0x0000},
54
55 };
56
57 #define tc_result(success, tc_index) \
58         TC_PRT("Test case [%d - %s] %s", tc_table[tc_index].tc_code, tc_table[tc_index].tc_name, ((success == TC_PASS) ? "Success" : "Failed"));
59
60 char *g_alert_char_handle = NULL;
61 guint8 g_alert_level = 0;
62
63 #define IMMEDIATE_ALERT_UUID    "00001802-0000-1000-8000-00805f9b34fb"
64 #define LINK_LOSS_UUID          "00001803-0000-1000-8000-00805f9b34fb"
65 #define ALERT_LEVEL_CHR_UUID    "2a06"
66
67 #define BD_ADDR_FILE "/opt/remote-bd"
68
69 void tc_usage_print(void)
70 {
71         int i = 0;
72
73         while (tc_table[i].tc_name) {
74                 if (tc_table[i].tc_code != 0x00ff) {
75                         TC_PRT("Key %d : usage %s", tc_table[i].tc_code,
76                                                         tc_table[i].tc_name);
77                 } else {
78                         TC_PRT("Key %d : usage %s\n\n", 0x00ff,
79                                                         tc_table[i].tc_name);
80                 }
81
82                 i++;
83         }
84 }
85
86 static void convert_addr_string_to_addr_type(bluetooth_device_address_t *addr,
87                                                         const char *address)
88 {
89         char *ptr1, *ptr2, *ptr3, *ptr4, *ptr5;
90
91         if (!address || !addr)
92                 return;
93
94         addr->addr[0] = strtol(address, &ptr5, 16);
95         addr->addr[1] = strtol(ptr5 + 1, &ptr4, 16);
96         addr->addr[2] = strtol(ptr4 + 1, &ptr3, 16);
97         addr->addr[3] = strtol(ptr3 + 1, &ptr2, 16);
98         addr->addr[4] = strtol(ptr2 + 1, &ptr1, 16);
99         addr->addr[5] = strtol(ptr1 + 1, NULL, 16);
100 }
101
102 char * get_bd_from_file(char *filename)
103 {
104         int fd;
105         char *buf;
106
107         if ((fd = open(filename, O_RDONLY)) < 0) {
108                 perror("Can't open file");
109                 return NULL;
110         }
111
112         buf = g_malloc0(20);
113         /* Fix : NULL_RETURNS */
114         if (buf == NULL) {
115                 close(fd);
116                 return NULL;
117         }
118
119         if (read(fd, buf, 17) < 17) {
120                 perror("Can't load firmware");
121                 g_free(buf);
122                 close(fd);
123                 return NULL;
124         }
125
126         close(fd);
127
128         return buf;
129 }
130
131 static void __accept_bdaddress(bluetooth_device_address_t *device_address)
132 {
133         char str_address[20] = {0};
134         char *addr;
135
136         addr = get_bd_from_file(BD_ADDR_FILE);
137         if (addr) {
138                 TC_PRT("Remote bd adress from file: %s", addr);
139                 convert_addr_string_to_addr_type(device_address, addr);
140                 g_free(addr);
141                 return;
142         }
143
144         TC_PRT("Enter bd address: ");
145         int ret = 0;
146         ret = scanf("%s", str_address);
147         if (ret < 0)
148                 TC_PRT("Some read error");
149         TC_PRT("You have entered bd address %s\n", str_address);
150         convert_addr_string_to_addr_type(device_address, str_address);
151 }
152
153 static void __accept_alert_level()
154 {
155         TC_PRT("Enter alert level \n 0 - no alert 1 - mild alert 2 - High alert : ");
156         int ret = 0;
157         ret = scanf("%c", &g_alert_level);
158         if (ret < 0)
159                 TC_PRT("Some read error");
160         TC_PRT("You have selected alert level %hu ", g_alert_level);
161 }
162
163 int test_input_callback(void *data)
164 {
165         int ret = 0;
166         int test_id = (int)data;
167         bluetooth_device_address_t device_address;
168         bt_gatt_service_property_t service;
169
170         switch (test_id) {
171         case 0x00ff:
172                 TC_PRT("Finished");
173                 g_main_loop_quit(main_loop);
174                 break;
175         case 1:
176                 TC_PRT("Immediate Alert");
177                 __accept_bdaddress(&device_address);
178
179                 __accept_alert_level();
180
181                 if (g_alert_char_handle) {
182                         if (bluetooth_gatt_set_characteristics_value(g_alert_char_handle,
183                                                 &g_alert_level, 1) != BLUETOOTH_ERROR_NONE)
184                                 TC_PRT("Set char val failed");
185
186                         return 0;
187                 }
188
189                 ret = bluetooth_gatt_get_service_from_uuid(&device_address,
190                                                         IMMEDIATE_ALERT_UUID,
191                                                         &service);
192                 if (ret != BLUETOOTH_ERROR_NONE) {
193                         TC_PRT(" bluetooth_gatt_get_service_from_uuid FAILED");
194                         return 0;
195                 }
196
197                 ret = bluetooth_gatt_get_char_from_uuid(service.handle,
198                                                         ALERT_LEVEL_CHR_UUID);
199                 if (ret != BLUETOOTH_ERROR_NONE) {
200                         TC_PRT(" bluetooth_gatt_get_char_from_uuid FAILED");
201                         return 0;
202                 }
203
204                 break;
205         case 2:
206                 TC_PRT("Proximity Link loss alert");
207                 __accept_bdaddress(&device_address);
208
209                 __accept_alert_level();
210
211                 /* TODO */
212                 break;
213         default:
214                 break;
215         }
216
217         return 0;
218 }
219
220 void startup()
221 {
222         TC_PRT("bluetooth framework TC startup");
223
224         dbus_threads_init_default();
225
226         main_loop = g_main_loop_new(NULL, FALSE);
227 }
228
229 void cleanup()
230 {
231         TC_PRT("bluetooth framework TC cleanup");
232         if (main_loop != NULL)
233                 g_main_loop_unref(main_loop);
234 }
235
236 static void __handle_alert_char(char *char_handle,
237                                         bt_gatt_char_property_t *char_pty)
238 {
239         if (char_pty->val == NULL)
240                 TC_PRT("Read only char");
241         else
242                 TC_PRT("Current Alert level [%d]", char_pty->val[0]);
243
244         g_alert_char_handle = g_strdup(char_handle);
245
246         if (bluetooth_gatt_set_characteristics_value(char_handle,
247                                 &g_alert_level, 1) != BLUETOOTH_ERROR_NONE)
248                 TC_PRT("Set char val failed");
249
250 }
251
252 static gboolean __handle_char(char *char_handle,
253                                         bt_gatt_char_property_t *char_pty)
254 {
255         TC_PRT("char uuid %s", char_pty->uuid);
256
257         if (g_strstr_len(char_pty->uuid, -1, ALERT_LEVEL_CHR_UUID) != NULL) {
258                 TC_PRT("Alert char recieved");
259                 __handle_alert_char(char_handle, char_pty);
260                 return TRUE;
261         } /* Add else if for other chars*/
262
263         return FALSE;
264 }
265
266 void bt_event_callback(int event, bluetooth_event_param_t* param,
267                                                         void *user_data)
268 {
269         TC_PRT(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
270         TC_PRT("bt event callback 0x%04x", event);
271         switch (event) {
272         case BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID:
273         {
274                 TC_PRT("BLUETOOTH_EVENT_GATT_GET_CHAR_FROM_UUID");
275                 if (param->result != 0) {
276                         TC_PRT("Failed!!!");
277                         return;
278                 }
279                 bt_gatt_char_property_t *char_pty = param->param_data;
280
281                 __handle_char(char_pty->handle, char_pty);
282
283         }
284         break;
285         default:
286                 TC_PRT("received event [0x%04x]", event);
287                 break;
288         }
289         TC_PRT("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
290 }
291
292 static gboolean key_event_cb(GIOChannel *chan, GIOCondition cond, gpointer data)
293 {
294         char buf[10] = {0};
295         unsigned int len = 0;
296         int test_id;
297
298         if (g_io_channel_read_chars(chan, buf, sizeof(buf),
299                         &len, NULL) ==  G_IO_STATUS_ERROR) {
300                 printf("IO Channel read error");
301                 return FALSE;
302         }
303         printf("%s\n", buf);
304         tc_usage_print();
305
306         test_id = atoi(buf);
307
308         if (test_id)
309                 g_idle_add(test_input_callback, (void*)test_id);
310
311         return TRUE;
312 }
313
314 int main()
315 {
316         int ret_val;
317         GIOChannel *key_io;
318
319         startup();
320
321         /* Register callback function */
322         TC_PRT("TC : %s", tc_table[0].tc_name);
323         ret_val = bluetooth_register_callback(bt_event_callback, NULL);
324         if (ret_val >= BLUETOOTH_ERROR_NONE) {
325                 TC_PRT("bluetooth_register_callback returned Success");
326                 tc_result(TC_PASS, 0);
327         } else {
328                 TC_PRT("bluetooth_register_callback returned failiure [0x%04x]", ret_val);
329                 tc_result(TC_FAIL, 0);
330                 return 0;
331         }
332
333         ret_val = bluetooth_check_adapter();
334         if (ret_val < BLUETOOTH_ERROR_NONE) {
335                 TC_PRT("bluetooth_check_adapter returned failiure [0x%04x]", ret_val);
336                 tc_result(TC_FAIL, 3);
337         } else {
338                 TC_PRT("BT state [0x%04x]", ret_val);
339                 tc_result(TC_PASS, 3);
340         }
341
342         key_io = g_io_channel_unix_new(fileno(stdin));
343
344         g_io_add_watch(key_io, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
345                         key_event_cb, NULL);
346         g_io_channel_unref(key_io);
347
348         g_main_loop_run(main_loop);
349
350         cleanup();
351         return 0;
352 }