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