tizen 2.3.1 release
[framework/connectivity/bluez.git] / tools / ciptool.c
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2002-2010  Marcel Holtmann <marcel@holtmann.org>
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 <stdio.h>
29 #include <errno.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <getopt.h>
34 #include <signal.h>
35 #include <poll.h>
36 #include <sys/ioctl.h>
37 #include <sys/socket.h>
38
39 #include "lib/bluetooth.h"
40 #include "lib/hci.h"
41 #include "lib/hci_lib.h"
42 #include "lib/l2cap.h"
43 #include "lib/sdp.h"
44 #include "lib/sdp_lib.h"
45 #include "lib/cmtp.h"
46
47 static volatile sig_atomic_t __io_canceled = 0;
48
49 static void sig_hup(int sig)
50 {
51         return;
52 }
53
54 static void sig_term(int sig)
55 {
56         __io_canceled = 1;
57 }
58
59 static char *cmtp_state[] = {
60         "unknown",
61         "connected",
62         "open",
63         "bound",
64         "listening",
65         "connecting",
66         "connecting",
67         "config",
68         "disconnecting",
69         "closed"
70 };
71
72 static char *cmtp_flagstostr(uint32_t flags)
73 {
74         static char str[100] = "";
75
76         strcat(str, "[");
77
78         if (flags & (1 << CMTP_LOOPBACK))
79                 strcat(str, "loopback");
80
81         strcat(str, "]");
82
83         return str;
84 }
85
86 static int get_psm(bdaddr_t *src, bdaddr_t *dst, unsigned short *psm)
87 {
88         sdp_session_t *s;
89         sdp_list_t *srch, *attrs, *rsp;
90         uuid_t svclass;
91         uint16_t attr;
92         int err;
93
94         if (!(s = sdp_connect(src, dst, 0)))
95                 return -1;
96
97         sdp_uuid16_create(&svclass, CIP_SVCLASS_ID);
98         srch = sdp_list_append(NULL, &svclass);
99
100         attr = SDP_ATTR_PROTO_DESC_LIST;
101         attrs = sdp_list_append(NULL, &attr);
102
103         err = sdp_service_search_attr_req(s, srch, SDP_ATTR_REQ_INDIVIDUAL, attrs, &rsp);
104
105         sdp_close(s);
106
107         if (err)
108                 return 0;
109
110         for (; rsp; rsp = rsp->next) {
111                 sdp_record_t *rec = (sdp_record_t *) rsp->data;
112                 sdp_list_t *protos;
113
114                 if (!sdp_get_access_protos(rec, &protos)) {
115                         unsigned short p = sdp_get_proto_port(protos, L2CAP_UUID);
116                         if (p > 0) {
117                                 *psm = p;
118                                 return 1;
119                         }
120                 }
121         }
122
123         return 0;
124 }
125
126 static int do_connect(int ctl, int dev_id, bdaddr_t *src, bdaddr_t *dst, unsigned short psm, uint32_t flags)
127 {
128         struct cmtp_connadd_req req;
129         struct hci_dev_info di;
130         struct sockaddr_l2 addr;
131         struct l2cap_options opts;
132         socklen_t size;
133         int sk;
134
135         hci_devinfo(dev_id, &di);
136         if (!(di.link_policy & HCI_LP_RSWITCH)) {
137                 printf("Local device is not accepting role switch\n");
138         }
139
140         if ((sk = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) < 0) {
141                 perror("Can't create L2CAP socket");
142                 exit(1);
143         }
144
145         memset(&addr, 0, sizeof(addr));
146         addr.l2_family = AF_BLUETOOTH;
147         bacpy(&addr.l2_bdaddr, src);
148
149         if (bind(sk, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
150                 perror("Can't bind L2CAP socket");
151                 close(sk);
152                 exit(1);
153         }
154
155         memset(&opts, 0, sizeof(opts));
156         size = sizeof(opts);
157
158         if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, &size) < 0) {
159                 perror("Can't get L2CAP options");
160                 close(sk);
161                 exit(1);
162         }
163
164         opts.imtu = CMTP_DEFAULT_MTU;
165         opts.omtu = CMTP_DEFAULT_MTU;
166         opts.flush_to = 0xffff;
167
168         if (setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, sizeof(opts)) < 0) {
169                 perror("Can't set L2CAP options");
170                 close(sk);
171                 exit(1);
172         }
173
174         memset(&addr, 0, sizeof(addr));
175         addr.l2_family = AF_BLUETOOTH;
176         bacpy(&addr.l2_bdaddr, dst);
177         addr.l2_psm = htobs(psm);
178
179         if (connect(sk, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
180                 perror("Can't connect L2CAP socket");
181                 close(sk);
182                 exit(1);
183         }
184
185         req.sock = sk;
186         req.flags = flags;
187
188         if (ioctl(ctl, CMTPCONNADD, &req) < 0) {
189                 perror("Can't create connection");
190                 exit(1);
191         }
192
193         return sk;
194 }
195
196 static void cmd_show(int ctl, bdaddr_t *bdaddr, int argc, char **argv)
197 {
198         struct cmtp_connlist_req req;
199         struct cmtp_conninfo ci[16];
200         char addr[18];
201         unsigned int i;
202
203         req.cnum = 16;
204         req.ci   = ci;
205
206         if (ioctl(ctl, CMTPGETCONNLIST, &req) < 0) {
207                 perror("Can't get connection list");
208                 exit(1);
209         }
210
211         for (i = 0; i < req.cnum; i++) {
212                 ba2str(&ci[i].bdaddr, addr);
213                 printf("%d %s %s %s\n", ci[i].num, addr,
214                         cmtp_state[ci[i].state],
215                         ci[i].flags ? cmtp_flagstostr(ci[i].flags) : "");
216         }
217 }
218
219 static void cmd_search(int ctl, bdaddr_t *bdaddr, int argc, char **argv)
220 {
221         inquiry_info *info = NULL;
222         bdaddr_t src, dst;
223         unsigned short psm;
224         int i, dev_id, num_rsp, length, flags;
225         char addr[18];
226         uint8_t class[3];
227
228         ba2str(bdaddr, addr);
229         dev_id = hci_devid(addr);
230         if (dev_id < 0) {
231                 dev_id = hci_get_route(NULL);
232                 hci_devba(dev_id, &src);
233         } else
234                 bacpy(&src, bdaddr);
235
236         length  = 8;    /* ~10 seconds */
237         num_rsp = 0;
238         flags   = 0;
239
240         printf("Searching ...\n");
241
242         num_rsp = hci_inquiry(dev_id, length, num_rsp, NULL, &info, flags);
243
244         for (i = 0; i < num_rsp; i++) {
245                 memcpy(class, (info+i)->dev_class, 3);
246                 if ((class[1] == 2) && ((class[0] / 4) == 5)) {
247                         bacpy(&dst, &(info+i)->bdaddr);
248                         ba2str(&dst, addr);
249
250                         printf("\tChecking service for %s\n", addr);
251                         if (!get_psm(&src, &dst, &psm))
252                                 continue;
253
254                         bt_free(info);
255
256                         printf("\tConnecting to device %s\n", addr);
257                         do_connect(ctl, dev_id, &src, &dst, psm, 0);
258                         return;
259                 }
260         }
261
262         bt_free(info);
263         fprintf(stderr, "\tNo devices in range or visible\n");
264         exit(1);
265 }
266
267 static void cmd_create(int ctl, bdaddr_t *bdaddr, int argc, char **argv)
268 {
269         bdaddr_t src, dst;
270         unsigned short psm;
271         int dev_id;
272         char addr[18];
273
274         if (argc < 2)
275                 return;
276
277         str2ba(argv[1], &dst);
278
279         ba2str(bdaddr, addr);
280         dev_id = hci_devid(addr);
281         if (dev_id < 0) {
282                 dev_id = hci_get_route(&dst);
283                 hci_devba(dev_id, &src);
284         } else
285                 bacpy(&src, bdaddr);
286
287         if (argc < 3) {
288                 if (!get_psm(&src, &dst, &psm))
289                         psm = 4099;
290         } else
291                 psm = atoi(argv[2]);
292
293         do_connect(ctl, dev_id, &src, &dst, psm, 0);
294 }
295
296 static void cmd_release(int ctl, bdaddr_t *bdaddr, int argc, char **argv)
297 {
298         struct cmtp_conndel_req req;
299         struct cmtp_connlist_req cl;
300         struct cmtp_conninfo ci[16];
301
302         if (argc < 2) {
303                 cl.cnum = 16;
304                 cl.ci   = ci;
305
306                 if (ioctl(ctl, CMTPGETCONNLIST, &cl) < 0) {
307                         perror("Can't get connection list");
308                         exit(1);
309                 }
310
311                 if (cl.cnum == 0)
312                         return;
313
314                 if (cl.cnum != 1) {
315                         fprintf(stderr, "You have to specifiy the device address.\n");
316                         exit(1);
317                 }
318
319                 bacpy(&req.bdaddr, &ci[0].bdaddr);
320         } else
321                 str2ba(argv[1], &req.bdaddr);
322
323         if (ioctl(ctl, CMTPCONNDEL, &req) < 0) {
324                 perror("Can't release connection");
325                 exit(1);
326         }
327 }
328
329 static void cmd_loopback(int ctl, bdaddr_t *bdaddr, int argc, char **argv)
330 {
331         struct cmtp_conndel_req req;
332         struct sigaction sa;
333         struct pollfd p;
334         sigset_t sigs;
335         bdaddr_t src, dst;
336         unsigned short psm;
337         int dev_id, sk;
338         char addr[18];
339
340         if (argc < 2)
341                 return;
342
343         str2ba(argv[1], &dst);
344
345         ba2str(bdaddr, addr);
346         dev_id = hci_devid(addr);
347         if (dev_id < 0) {
348                 dev_id = hci_get_route(&dst);
349                 hci_devba(dev_id, &src);
350         } else
351                 bacpy(&src, bdaddr);
352
353         ba2str(&dst, addr);
354         printf("Connecting to %s in loopback mode\n", addr);
355
356         if (argc < 3) {
357                 if (!get_psm(&src, &dst, &psm))
358                         psm = 4099;
359         } else
360                 psm = atoi(argv[2]);
361
362         sk = do_connect(ctl, dev_id, &src, &dst, psm, (1 << CMTP_LOOPBACK));
363
364         printf("Press CTRL-C for hangup\n");
365
366         memset(&sa, 0, sizeof(sa));
367         sa.sa_flags   = SA_NOCLDSTOP;
368         sa.sa_handler = SIG_IGN;
369         sigaction(SIGCHLD, &sa, NULL);
370         sigaction(SIGPIPE, &sa, NULL);
371
372         sa.sa_handler = sig_term;
373         sigaction(SIGTERM, &sa, NULL);
374         sigaction(SIGINT,  &sa, NULL);
375
376         sa.sa_handler = sig_hup;
377         sigaction(SIGHUP, &sa, NULL);
378
379         sigfillset(&sigs);
380         sigdelset(&sigs, SIGCHLD);
381         sigdelset(&sigs, SIGPIPE);
382         sigdelset(&sigs, SIGTERM);
383         sigdelset(&sigs, SIGINT);
384         sigdelset(&sigs, SIGHUP);
385
386         p.fd = sk;
387         p.events = POLLERR | POLLHUP;
388
389         while (!__io_canceled) {
390                 p.revents = 0;
391                 if (ppoll(&p, 1, NULL, &sigs) > 0)
392                         break;
393         }
394
395         bacpy(&req.bdaddr, &dst);
396         ioctl(ctl, CMTPCONNDEL, &req);
397 }
398
399 static struct {
400         char *cmd;
401         char *alt;
402         void (*func)(int ctl, bdaddr_t *bdaddr, int argc, char **argv);
403         char *opt;
404         char *doc;
405 } command[] = {
406         { "show",     "list",       cmd_show,     0,          "Show remote connections"      },
407         { "search",   "scan",       cmd_search,   0,          "Search for a remote device"   },
408         { "connect",  "create",     cmd_create,   "<bdaddr>", "Connect a remote device"      },
409         { "release",  "disconnect", cmd_release,  "[bdaddr]", "Disconnect the remote device" },
410         { "loopback", "test",       cmd_loopback, "<bdaddr>", "Loopback test of a device"    },
411         { NULL, NULL, NULL, 0, 0 }
412 };
413
414 static void usage(void)
415 {
416         int i;
417
418         printf("ciptool - Bluetooth Common ISDN Access Profile (CIP)\n\n");
419
420         printf("Usage:\n"
421                 "\tciptool [options] [command]\n"
422                 "\n");
423
424         printf("Options:\n"
425                 "\t-i [hciX|bdaddr]   Local HCI device or BD Address\n"
426                 "\t-h, --help         Display help\n"
427                 "\n");
428
429         printf("Commands:\n");
430         for (i = 0; command[i].cmd; i++)
431                 printf("\t%-8s %-10s\t%s\n", command[i].cmd,
432                 command[i].opt ? command[i].opt : " ",
433                 command[i].doc);
434         printf("\n");
435 }
436
437 static struct option main_options[] = {
438         { "help",       0, 0, 'h' },
439         { "device",     1, 0, 'i' },
440         { 0, 0, 0, 0 }
441 };
442
443 int main(int argc, char *argv[])
444 {
445         bdaddr_t bdaddr;
446         int i, opt, ctl;
447
448         bacpy(&bdaddr, BDADDR_ANY);
449
450         while ((opt = getopt_long(argc, argv, "+i:h", main_options, NULL)) != -1) {
451                 switch(opt) {
452                 case 'i':
453                         if (!strncmp(optarg, "hci", 3))
454                                 hci_devba(atoi(optarg + 3), &bdaddr);
455                         else
456                                 str2ba(optarg, &bdaddr);
457                         break;
458                 case 'h':
459                         usage();
460                         exit(0);
461                 default:
462                         exit(0);
463                 }
464         }
465
466         argc -= optind;
467         argv += optind;
468         optind = 0;
469
470         if (argc < 1) {
471                 usage();
472                 return 0;
473         }
474
475         if ((ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_CMTP)) < 0 ) {
476                 perror("Can't open CMTP control socket");
477                 exit(1);
478         }
479
480         for (i = 0; command[i].cmd; i++) {
481                 if (strncmp(command[i].cmd, argv[0], 4) && strncmp(command[i].alt, argv[0], 4))
482                         continue;
483                 command[i].func(ctl, &bdaddr, argc, argv);
484                 close(ctl);
485                 exit(0);
486         }
487
488         usage();
489
490         close(ctl);
491
492         return 0;
493 }