Upgrade bluez5_37 :Merge the code from private
[platform/upstream/bluez.git] / tools / bnep-tester.c
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2014  Intel Corporation. All rights reserved.
6  *
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdlib.h>
29 #include <stdint.h>
30 #include <unistd.h>
31 #include <errno.h>
32 #include <stdbool.h>
33
34 #include <glib.h>
35
36 #include "lib/bluetooth.h"
37 #include "lib/bnep.h"
38 #include "lib/mgmt.h"
39
40 #include "monitor/bt.h"
41 #include "emulator/bthost.h"
42 #include "emulator/hciemu.h"
43
44 #include "src/shared/tester.h"
45 #include "src/shared/mgmt.h"
46
47 struct test_data {
48         struct mgmt *mgmt;
49         uint16_t mgmt_index;
50         struct hciemu *hciemu;
51         enum hciemu_type hciemu_type;
52         const void *test_data;
53         unsigned int io_id;
54         uint16_t conn_handle;
55 };
56
57 struct rfcomm_client_data {
58         uint8_t server_channel;
59         uint8_t client_channel;
60         int expected_connect_err;
61         const uint8_t *send_data;
62         const uint8_t *read_data;
63         uint16_t data_len;
64 };
65
66 struct rfcomm_server_data {
67         uint8_t server_channel;
68         uint8_t client_channel;
69         bool expected_status;
70         const uint8_t *send_data;
71         const uint8_t *read_data;
72         uint16_t data_len;
73 };
74
75 static void mgmt_debug(const char *str, void *user_data)
76 {
77         const char *prefix = user_data;
78
79         tester_print("%s%s", prefix, str);
80 }
81
82 static void read_info_callback(uint8_t status, uint16_t length,
83                                         const void *param, void *user_data)
84 {
85         struct test_data *data = tester_get_data();
86         const struct mgmt_rp_read_info *rp = param;
87         char addr[18];
88         uint16_t manufacturer;
89         uint32_t supported_settings, current_settings;
90
91         tester_print("Read Info callback");
92         tester_print("  Status: 0x%02x", status);
93
94         if (status || !param) {
95                 tester_pre_setup_failed();
96                 return;
97         }
98
99         ba2str(&rp->bdaddr, addr);
100         manufacturer = btohs(rp->manufacturer);
101         supported_settings = btohl(rp->supported_settings);
102         current_settings = btohl(rp->current_settings);
103
104         tester_print("  Address: %s", addr);
105         tester_print("  Version: 0x%02x", rp->version);
106         tester_print("  Manufacturer: 0x%04x", manufacturer);
107         tester_print("  Supported settings: 0x%08x", supported_settings);
108         tester_print("  Current settings: 0x%08x", current_settings);
109         tester_print("  Class: 0x%02x%02x%02x",
110                         rp->dev_class[2], rp->dev_class[1], rp->dev_class[0]);
111         tester_print("  Name: %s", rp->name);
112         tester_print("  Short name: %s", rp->short_name);
113
114         if (strcmp(hciemu_get_address(data->hciemu), addr)) {
115                 tester_pre_setup_failed();
116                 return;
117         }
118
119         tester_pre_setup_complete();
120 }
121
122 static void index_added_callback(uint16_t index, uint16_t length,
123                                         const void *param, void *user_data)
124 {
125         struct test_data *data = tester_get_data();
126
127         tester_print("Index Added callback");
128         tester_print("  Index: 0x%04x", index);
129
130         data->mgmt_index = index;
131
132         mgmt_send(data->mgmt, MGMT_OP_READ_INFO, data->mgmt_index, 0, NULL,
133                                         read_info_callback, NULL, NULL);
134 }
135
136 static void index_removed_callback(uint16_t index, uint16_t length,
137                                         const void *param, void *user_data)
138 {
139         struct test_data *data = tester_get_data();
140
141         tester_print("Index Removed callback");
142         tester_print("  Index: 0x%04x", index);
143
144         if (index != data->mgmt_index)
145                 return;
146
147         mgmt_unregister_index(data->mgmt, data->mgmt_index);
148
149         mgmt_unref(data->mgmt);
150         data->mgmt = NULL;
151
152         tester_post_teardown_complete();
153 }
154
155 static void read_index_list_callback(uint8_t status, uint16_t length,
156                                         const void *param, void *user_data)
157 {
158         struct test_data *data = tester_get_data();
159
160         tester_print("Read Index List callback");
161         tester_print("  Status: 0x%02x", status);
162
163         if (status || !param) {
164                 tester_pre_setup_failed();
165                 return;
166         }
167
168         mgmt_register(data->mgmt, MGMT_EV_INDEX_ADDED, MGMT_INDEX_NONE,
169                                         index_added_callback, NULL, NULL);
170
171         mgmt_register(data->mgmt, MGMT_EV_INDEX_REMOVED, MGMT_INDEX_NONE,
172                                         index_removed_callback, NULL, NULL);
173
174         data->hciemu = hciemu_new(data->hciemu_type);
175         if (!data->hciemu) {
176                 tester_warn("Failed to setup HCI emulation");
177                 tester_pre_setup_failed();
178         }
179
180         tester_print("New hciemu instance created");
181 }
182
183 static void test_pre_setup(const void *test_data)
184 {
185         struct test_data *data = tester_get_data();
186
187         data->mgmt = mgmt_new_default();
188         if (!data->mgmt) {
189                 tester_warn("Failed to setup management interface");
190                 tester_pre_setup_failed();
191                 return;
192         }
193
194         if (tester_use_debug())
195                 mgmt_set_debug(data->mgmt, mgmt_debug, "mgmt: ", NULL);
196
197         mgmt_send(data->mgmt, MGMT_OP_READ_INDEX_LIST, MGMT_INDEX_NONE, 0, NULL,
198                                         read_index_list_callback, NULL, NULL);
199 }
200
201 static void test_post_teardown(const void *test_data)
202 {
203         struct test_data *data = tester_get_data();
204
205         if (data->io_id > 0) {
206                 g_source_remove(data->io_id);
207                 data->io_id = 0;
208         }
209
210         hciemu_unref(data->hciemu);
211         data->hciemu = NULL;
212 }
213
214 static void test_data_free(void *test_data)
215 {
216         struct test_data *data = test_data;
217
218         free(data);
219 }
220
221 static void client_connectable_complete(uint16_t opcode, uint8_t status,
222                                         const void *param, uint8_t len,
223                                         void *user_data)
224 {
225         switch (opcode) {
226         case BT_HCI_CMD_WRITE_SCAN_ENABLE:
227                 break;
228         default:
229                 return;
230         }
231
232         tester_print("Client set connectable status 0x%02x", status);
233
234         if (status)
235                 tester_setup_failed();
236         else
237                 tester_setup_complete();
238 }
239
240 static void setup_powered_client_callback(uint8_t status, uint16_t length,
241                                         const void *param, void *user_data)
242 {
243         struct test_data *data = tester_get_data();
244         struct bthost *bthost;
245
246         if (status != MGMT_STATUS_SUCCESS) {
247                 tester_setup_failed();
248                 return;
249         }
250
251         tester_print("Controller powered on");
252
253         bthost = hciemu_client_get_host(data->hciemu);
254         bthost_set_cmd_complete_cb(bthost, client_connectable_complete, data);
255         bthost_write_scan_enable(bthost, 0x03);
256 }
257
258 static void setup_powered_client(const void *test_data)
259 {
260         struct test_data *data = tester_get_data();
261         unsigned char param[] = { 0x01 };
262
263         tester_print("Powering on controller");
264
265         mgmt_send(data->mgmt, MGMT_OP_SET_POWERED, data->mgmt_index,
266                         sizeof(param), param, setup_powered_client_callback,
267                         NULL, NULL);
268 }
269
270 static void test_basic(const void *test_data)
271 {
272         int sk;
273
274         sk = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_BNEP);
275         if (sk < 0) {
276                 tester_warn("Can't create socket: %s (%d)", strerror(errno),
277                                                                         errno);
278                 tester_test_failed();
279                 return;
280         }
281
282         close(sk);
283
284         tester_test_passed();
285 }
286
287 #define test_bnep(name, data, setup, func) \
288         do { \
289                 struct test_data *user; \
290                 user = malloc(sizeof(struct test_data)); \
291                 if (!user) \
292                         break; \
293                 user->hciemu_type = HCIEMU_TYPE_BREDR; \
294                 user->test_data = data; \
295                 user->io_id = 0; \
296                 tester_add_full(name, data, \
297                                 test_pre_setup, setup, func, NULL, \
298                                 test_post_teardown, 2, user, test_data_free); \
299         } while (0)
300
301 int main(int argc, char *argv[])
302 {
303         tester_init(&argc, &argv);
304
305         test_bnep("Basic BNEP Socket - Success", NULL,
306                                         setup_powered_client, test_basic);
307
308         return tester_run();
309 }