Tizen 2.0 Release
[profile/ivi/bluetooth.git] / test / bt_chat_client.c
1 /*
2  * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
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 #include <bluetooth.h>
19 #include <dlog.h>
20 #include <glib.h>
21 #include <string.h>
22
23 #ifdef LOG_TAG
24 #undef LOG_TAG
25 #endif
26 #define LOG_TAG "BT_CHAT_CLIENT"
27
28 /**
29  *   Variables
30  **/
31 static GMainLoop* g_mainloop = NULL;
32 static bt_adapter_state_e bt_state = BT_ADAPTER_DISABLED;
33 static int socket_fd = -1;
34 static char* bt_address = NULL;
35 static char* server_name = "chat_server";
36 static char quit_command[5] = "Quit";
37 static int bonding_state = BT_ERROR_OPERATION_FAILED;
38
39
40 /**
41  *   Callback functions
42  **/
43 gboolean timeout_func(gpointer data)
44 {
45         LOGE("[%s] Callback: Timeout.", __FUNCTION__);
46         g_main_loop_quit((GMainLoop*)data);
47         return FALSE;
48 }
49
50 void bt_state_changed_impl(int result, bt_adapter_state_e adapter_state, void* user_data)
51 {
52         if(adapter_state == BT_ADAPTER_ENABLED)
53         {
54                 if(result == BT_ERROR_NONE)
55                 {
56                         LOGI("[%s] Callback: BT was enabled successfully.", __FUNCTION__);
57                         bt_state = BT_ADAPTER_ENABLED;
58                 }
59                 else
60                 {
61                         LOGE("[%s] Callback: Failed to enable BT.", __FUNCTION__);
62                 }
63         }
64
65         if(g_mainloop)
66         {
67                 g_main_loop_quit(g_mainloop);
68         }
69 }
70
71 void bt_socket_connection_state_changed_impl(int result, bt_socket_connection_state_e connection_state,
72         bt_socket_connection_s *connection, void *user_data)
73 {
74         if(result == BT_ERROR_NONE)
75         {
76                 LOGI("[%s] Callback: Result is BT_ERROR_NONE.", __FUNCTION__);
77         }
78         else
79         {
80                 LOGI("[%s] Callback: Result is not BT_ERROR_NONE.", __FUNCTION__);
81         }
82
83         if(connection_state == BT_SOCKET_CONNECTED)
84         {
85                 LOGI("[%s] Callback: Connected.", __FUNCTION__);
86                 if(result == BT_ERROR_NONE && connection != NULL)
87                 {
88                         socket_fd = connection->socket_fd;
89                         LOGI("[%s] Callback: Socket of connection - %d.", __FUNCTION__, socket_fd);
90                         LOGI("[%s] Callback: Role of connection - %d.", __FUNCTION__, connection->local_role);
91                         LOGI("[%s] Callback: Address of connection - %s.", __FUNCTION__, connection->remote_address);
92
93                         if(bt_socket_send_data(socket_fd, quit_command, strlen(quit_command)) == BT_ERROR_NONE)
94                         {
95                                 LOGI("[%s] Callback: Send quit command.", __FUNCTION__);
96                         }
97                         else
98                         {
99                                 LOGE("[%s] Callback: bt_socket_send_data() failed.", __FUNCTION__);
100                                 if(g_mainloop)
101                                 {
102                                         g_main_loop_quit(g_mainloop);
103                                 }
104                         }
105                 }
106                 else
107                 {
108                         LOGI("[%s] Callback: Failed to connect", __FUNCTION__);
109                         if(g_mainloop)
110                         {
111                                 g_main_loop_quit(g_mainloop);
112                         }
113                 }
114         }
115         else
116         {
117                 LOGI("[%s] Callback: Disconnected.", __FUNCTION__);
118         }
119 }
120
121 void bt_socket_data_received_impl(bt_socket_received_data_s *data, void *user_data)
122 {
123         if(socket_fd == data->socket_fd)
124         {
125                 if(data->data_size > 0)
126                 {
127                         if(!strncmp(data->data, quit_command, data->data_size))
128                         {
129                                 LOGI("[%s] Callback: Quit command.", __FUNCTION__);
130                                 if(g_mainloop)
131                                 {
132                                         g_main_loop_quit(g_mainloop);
133                                 }
134                         }
135                 }
136                 else
137                 {
138                         LOGE("[%s] Callback: No data.", __FUNCTION__);
139                 }
140         }
141         else
142         {
143                 LOGI("[%s] Callback: Another socket - %d.", __FUNCTION__, data->socket_fd);
144         }
145 }
146
147 bool bt_adapter_bonded_device_impl(bt_device_info_s *device_info, void *user_data)
148 {
149         int i = 0;
150         if(device_info != NULL)
151         {
152                 if(device_info->remote_name != NULL && !strcmp(device_info->remote_name, (char*)user_data))
153                 {
154                         LOGI("[%s] Callback: chat_server is found in bonded list.", __FUNCTION__);
155                         if( device_info->remote_address != NULL )
156                         {
157                                 LOGI("[%s] Callback: Address of chat_server - %s.", __FUNCTION__, device_info->remote_address);
158                                 bt_address = strdup(device_info->remote_address);
159                                 LOGI("[%s] Callback: The number of service_count - %d.", __FUNCTION__, device_info->service_count);
160                                 if(device_info->service_count <= 0)
161                                 {
162                                         bonding_state = BT_ERROR_SERVICE_SEARCH_FAILED;
163                                 }
164                                 else
165                                 {
166                                         bonding_state = BT_ERROR_NONE;
167                                         for(i=0; i<device_info->service_count; i++)
168                                         {
169                                                 LOGI("[%s] Callback: service[%d] - %s", __FUNCTION__, i+1, device_info->service_uuid[i]);
170                                         }
171                                         LOGI("[%s] Callback: is_bonded - %d.", __FUNCTION__, device_info->is_bonded);
172                                         LOGI("[%s] Callback: is_connected - %d.", __FUNCTION__, device_info->is_connected);
173                                         LOGI("[%s] Callback: is_authorized - %d.", __FUNCTION__, device_info->is_authorized);
174                                 }
175                         }
176                         else
177                         {
178                                 LOGE("[%s] Callback: Address of chat_server is NULL.", __FUNCTION__);
179                         }
180
181                         return false;
182                 }
183         }
184
185         return true;
186 }
187
188 void bt_adapter_device_discovery_state_changed_impl(int result, bt_adapter_device_discovery_state_e discovery_state,
189         bt_adapter_device_discovery_info_s *discovery_info, void *user_data)
190 {
191         if(discovery_state == BT_ADAPTER_DEVICE_DISCOVERY_FOUND)
192         {
193                 if(discovery_info->remote_address != NULL && !strcmp(discovery_info->remote_name, server_name))
194                 {
195                         LOGI("[%s] Callback: chat_server is found.", __FUNCTION__);
196                         LOGI("[%s] Callback: Address of chat_server - %s.", __FUNCTION__, discovery_info->remote_address);
197                         LOGI("[%s] Callback: Device major class - %d.", __FUNCTION__, discovery_info->bt_class.major_device_class);
198                         LOGI("[%s] Callback: Device minor class - %d.", __FUNCTION__, discovery_info->bt_class.minor_device_class);
199                         LOGI("[%s] Callback: Service major class - %d.", __FUNCTION__, discovery_info->bt_class.major_service_class_mask);
200                         bt_address = strdup(discovery_info->remote_address);
201                         LOGI("[%s] Callback: is_bonded - %d.", __FUNCTION__, discovery_info->is_bonded);
202                         bt_adapter_stop_device_discovery();
203                 }
204                 else
205                 {
206                         LOGE("[%s] Callback: Another device is found.", __FUNCTION__);
207                 }
208         }
209         else if(discovery_state == BT_ADAPTER_DEVICE_DISCOVERY_FINISHED)
210         {
211                 LOGI("[%s] Callback: device discovery finished.", __FUNCTION__);
212                 if(g_mainloop)
213                 {
214                         g_main_loop_quit(g_mainloop);
215                 }
216         }
217 }
218
219 void bt_device_bond_created_impl(int result, bt_device_info_s *device_info, void *user_data)
220 {
221         if(device_info != NULL && !strcmp(device_info->remote_address, bt_address))
222         {
223                 bonding_state = result;
224                 if(result == BT_ERROR_NONE)
225                 {
226                         LOGI("[%s] Callback: A bond with chat_server is created.", __FUNCTION__);
227                         LOGI("[%s] Callback: The number of service - %d.", __FUNCTION__, device_info->service_count);
228
229                         int i = 0;
230                         for(i=0; i<device_info->service_count; i++)
231                         {
232                                 LOGI("[%s] Callback: service[%d] - %s", __FUNCTION__, i+1, device_info->service_uuid[i]);
233                         }
234                         LOGI("[%s] Callback: is_bonded - %d.", __FUNCTION__, device_info->is_bonded);
235                         LOGI("[%s] Callback: is_connected - %d.", __FUNCTION__, device_info->is_connected);
236                 }
237                 else
238                 {
239                         LOGE("[%s] Callback: Creating a bond is failed.", __FUNCTION__);
240                 }
241         }
242         else
243         {
244                 LOGE("[%s] Callback: A bond with another device is created.", __FUNCTION__);
245         }
246
247         if(g_mainloop)
248         {
249                 g_main_loop_quit(g_mainloop);
250         }
251 }
252
253 void bt_device_service_searched_impl(int result, bt_device_sdp_info_s* sdp_info, void* user_data)
254 {
255         if(sdp_info != NULL && !strcmp(sdp_info->remote_address, bt_address))
256         {
257                 bonding_state = result;
258                 if(result == BT_ERROR_NONE)
259                 {
260                         LOGI("[%s] Callback: Services of chat_service are found.", __FUNCTION__);
261                         LOGI("[%s] Callback: The number of service - %d.", __FUNCTION__, sdp_info->service_count);
262
263                         int i = 0;
264                         for(i = 0; i < sdp_info->service_count; i++)
265                         {
266                                 LOGI("[%s] Callback: service[%d] - %s", __FUNCTION__, i+1, sdp_info->service_uuid[i]);
267                         }
268                 }
269         }
270         else
271         {
272                 LOGE("[%s] Callback: Services of another device are found.", __FUNCTION__);
273         }
274
275         if(g_mainloop)
276         {
277                 g_main_loop_quit(g_mainloop);
278         }
279 }
280
281
282
283
284 int main()
285 {
286         g_mainloop = g_main_loop_new(NULL, FALSE);
287         const char* my_uuid="11011101-0000-1000-8000-00805F9B34FB";
288         int timeout_id = -1;
289
290         LOGI("[%s] Client starts.", __FUNCTION__);
291
292         if(bt_initialize() != BT_ERROR_NONE)
293         {
294                 LOGE("[%s] bt_initialize() failed.", __FUNCTION__);
295                 return -1;
296         }
297
298         if(bt_adapter_get_state(&bt_state) != BT_ERROR_NONE)
299         {
300                 LOGE("[%s] bt_adapter_get_state() failed.", __FUNCTION__);
301                 return -1;
302         }
303
304         //      Enable BT
305         if(bt_state == BT_ADAPTER_DISABLED)
306         {
307                 if(bt_adapter_set_state_changed_cb(bt_state_changed_impl, NULL) != BT_ERROR_NONE)
308                 {
309                         LOGE("[%s] bt_adapter_set_state_changed_cb() failed.", __FUNCTION__);
310                         return -1;
311                 }
312
313                 if(bt_adapter_enable() == BT_ERROR_NONE)
314                 {
315                         LOGI("[%s] bt_adapter_state_changed_cb will be called.", __FUNCTION__);
316                         timeout_id = g_timeout_add (60000, timeout_func, g_mainloop);
317                         g_main_loop_run(g_mainloop);
318                         g_source_remove(timeout_id);
319                 }
320                 else
321                 {
322                         LOGE("[%s] bt_adapter_enable() failed.", __FUNCTION__);
323                         return -1;
324                 }
325         }
326         else
327         {
328                 LOGI("[%s] BT was already enabled.", __FUNCTION__);
329         }
330
331         //      Device discovery
332         if(bt_state == BT_ADAPTER_ENABLED)
333         {
334                 if(bt_adapter_foreach_bonded_device(bt_adapter_bonded_device_impl, server_name) != BT_ERROR_NONE)
335                 {
336                         LOGE("[%s] bt_adapter_foreach_bonded_device() failed.", __FUNCTION__);
337                         return -1;
338                 }
339
340                 if(bt_address == NULL)
341                 {
342                         if(bt_adapter_set_device_discovery_state_changed_cb(bt_adapter_device_discovery_state_changed_impl, NULL)
343                                 != BT_ERROR_NONE )
344                         {
345                                 LOGE("[%s] bt_adapter_set_device_discovery_state_changed_cb() failed.", __FUNCTION__);
346                                 return -1;
347                         }
348
349                         if(bt_adapter_start_device_discovery() == BT_ERROR_NONE)
350                         {
351                                 LOGI("[%s] bt_adapter_device_discovery_state_changed_cb will be called.", __FUNCTION__);
352                                 g_main_loop_run(g_mainloop);
353                         }
354                         else
355                         {
356                                 LOGE("[%s] bt_adapter_start_device_discovery() failed.", __FUNCTION__);
357                                 return -1;
358                         }
359                 }
360                 else
361                 {
362                         LOGI("[%s] chat_server is found in bonded device list.", __FUNCTION__);
363                 }
364         }
365         else
366         {
367                 LOGE("[%s] BT is not enabled.", __FUNCTION__);
368                 return -1;
369         }
370
371         // Create bond with a server
372         if(bonding_state == BT_ERROR_SERVICE_SEARCH_FAILED)
373         {
374                 if(bt_device_set_service_searched_cb(bt_device_service_searched_impl, NULL) != BT_ERROR_NONE)
375                 {
376                         LOGE("[%s] bt_device_set_service_searched_cb() failed.", __FUNCTION__);
377                         return -1;
378                 }
379
380                 if(bt_device_start_service_search(bt_address) == BT_ERROR_NONE)
381                 {
382                         LOGI("[%s] bt_device_service_searched_cb will be called.", __FUNCTION__);
383                         g_main_loop_run(g_mainloop);
384                 }
385                 else
386                 {
387                         LOGE("[%s] bt_device_start_service_search() failed.", __FUNCTION__);
388                         return -1;
389                 }
390         }
391         else if(bonding_state != BT_ERROR_NONE)
392         {
393                 if(bt_device_set_bond_created_cb(bt_device_bond_created_impl, NULL) != BT_ERROR_NONE)
394                 {
395                         LOGE("[%s] bt_device_set_bond_created_cb() failed.", __FUNCTION__);
396                         return -1;
397                 }
398
399                 if(bt_device_create_bond(bt_address) == BT_ERROR_NONE)
400                 {
401                         LOGI("[%s] bt_device_bond_created_cb will be called.", __FUNCTION__);
402                         g_main_loop_run(g_mainloop);
403                 }
404                 else
405                 {
406                         LOGE("[%s] bt_device_create_bond() failed.", __FUNCTION__);
407                         return -1;
408                 }
409         }
410
411         //      Connecting socket as a client
412         if( bonding_state == BT_ERROR_NONE )
413         {
414                 if( bt_socket_set_connection_state_changed_cb(bt_socket_connection_state_changed_impl, NULL) != BT_ERROR_NONE )
415                 {
416                         LOGE("[%s] bt_socket_set_connection_state_changed_cb() failed.", __FUNCTION__);
417                         return -1;
418                 }
419
420                 if( bt_socket_set_data_received_cb(bt_socket_data_received_impl, NULL) != BT_ERROR_NONE )
421                 {
422                         LOGE("[%s] bt_socket_set_data_received_cb() failed.", __FUNCTION__);
423                         return -1;
424                 }
425
426                 if( bt_socket_connect_rfcomm(bt_address, my_uuid) == BT_ERROR_NONE )
427                 {
428                         LOGI("[%s] bt_socket_connection_state_changed_cb will be called.", __FUNCTION__);
429                         g_main_loop_run(g_mainloop);
430                 }
431                 else
432                 {
433                         LOGE("[%s] bt_socket_connect_rfcomm() failed.", __FUNCTION__);
434                         return -1;
435                 }
436
437                 if( bt_socket_disconnect_rfcomm(socket_fd) != BT_ERROR_NONE )
438                 {
439                         LOGE("[%s] bt_socket_disconnect_rfcomm() failed.", __FUNCTION__);
440                         return -1;
441                 }
442         }
443         else
444         {
445                 LOGE("[%s] Bond is not created.", __FUNCTION__);
446                 return -1;
447         }
448
449         bt_deinitialize();
450
451         LOGI("[%s] Client ends.", __FUNCTION__);
452         return 0;
453 }