3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
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.
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.
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
36 #include <sys/ioctl.h>
37 #include <sys/socket.h>
39 #include "lib/bluetooth.h"
41 #include "lib/hci_lib.h"
42 #include "lib/l2cap.h"
44 #include "lib/sdp_lib.h"
47 static volatile sig_atomic_t __io_canceled = 0;
49 static void sig_hup(int sig)
54 static void sig_term(int sig)
59 static char *cmtp_state[] = {
72 static char *cmtp_flagstostr(uint32_t flags)
74 static char str[100] = "";
78 if (flags & (1 << CMTP_LOOPBACK))
79 strcat(str, "loopback");
86 static int get_psm(bdaddr_t *src, bdaddr_t *dst, unsigned short *psm)
89 sdp_list_t *srch, *attrs, *rsp;
94 if (!(s = sdp_connect(src, dst, 0)))
97 sdp_uuid16_create(&svclass, CIP_SVCLASS_ID);
98 srch = sdp_list_append(NULL, &svclass);
100 attr = SDP_ATTR_PROTO_DESC_LIST;
101 attrs = sdp_list_append(NULL, &attr);
103 err = sdp_service_search_attr_req(s, srch, SDP_ATTR_REQ_INDIVIDUAL, attrs, &rsp);
110 for (; rsp; rsp = rsp->next) {
111 sdp_record_t *rec = (sdp_record_t *) rsp->data;
114 if (!sdp_get_access_protos(rec, &protos)) {
115 unsigned short p = sdp_get_proto_port(protos, L2CAP_UUID);
126 static int do_connect(int ctl, int dev_id, bdaddr_t *src, bdaddr_t *dst, unsigned short psm, uint32_t flags)
128 struct cmtp_connadd_req req;
129 struct hci_dev_info di;
130 struct sockaddr_l2 addr;
131 struct l2cap_options opts;
135 hci_devinfo(dev_id, &di);
136 if (!(di.link_policy & HCI_LP_RSWITCH)) {
137 printf("Local device is not accepting role switch\n");
140 if ((sk = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) < 0) {
141 perror("Can't create L2CAP socket");
145 memset(&addr, 0, sizeof(addr));
146 addr.l2_family = AF_BLUETOOTH;
147 bacpy(&addr.l2_bdaddr, src);
149 if (bind(sk, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
150 perror("Can't bind L2CAP socket");
155 memset(&opts, 0, sizeof(opts));
158 if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, &size) < 0) {
159 perror("Can't get L2CAP options");
164 opts.imtu = CMTP_DEFAULT_MTU;
165 opts.omtu = CMTP_DEFAULT_MTU;
166 opts.flush_to = 0xffff;
168 if (setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, sizeof(opts)) < 0) {
169 perror("Can't set L2CAP options");
174 memset(&addr, 0, sizeof(addr));
175 addr.l2_family = AF_BLUETOOTH;
176 bacpy(&addr.l2_bdaddr, dst);
177 addr.l2_psm = htobs(psm);
179 if (connect(sk, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
180 perror("Can't connect L2CAP socket");
188 if (ioctl(ctl, CMTPCONNADD, &req) < 0) {
189 perror("Can't create connection");
196 static void cmd_show(int ctl, bdaddr_t *bdaddr, int argc, char **argv)
198 struct cmtp_connlist_req req;
199 struct cmtp_conninfo ci[16];
206 if (ioctl(ctl, CMTPGETCONNLIST, &req) < 0) {
207 perror("Can't get connection list");
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) : "");
219 static void cmd_search(int ctl, bdaddr_t *bdaddr, int argc, char **argv)
221 inquiry_info *info = NULL;
224 int i, dev_id, num_rsp, length, flags;
228 ba2str(bdaddr, addr);
229 dev_id = hci_devid(addr);
231 dev_id = hci_get_route(NULL);
232 hci_devba(dev_id, &src);
236 length = 8; /* ~10 seconds */
240 printf("Searching ...\n");
242 num_rsp = hci_inquiry(dev_id, length, num_rsp, NULL, &info, flags);
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);
250 printf("\tChecking service for %s\n", addr);
251 if (!get_psm(&src, &dst, &psm))
256 printf("\tConnecting to device %s\n", addr);
257 do_connect(ctl, dev_id, &src, &dst, psm, 0);
263 fprintf(stderr, "\tNo devices in range or visible\n");
267 static void cmd_create(int ctl, bdaddr_t *bdaddr, int argc, char **argv)
277 str2ba(argv[1], &dst);
279 ba2str(bdaddr, addr);
280 dev_id = hci_devid(addr);
282 dev_id = hci_get_route(&dst);
283 hci_devba(dev_id, &src);
288 if (!get_psm(&src, &dst, &psm))
293 do_connect(ctl, dev_id, &src, &dst, psm, 0);
296 static void cmd_release(int ctl, bdaddr_t *bdaddr, int argc, char **argv)
298 struct cmtp_conndel_req req;
299 struct cmtp_connlist_req cl;
300 struct cmtp_conninfo ci[16];
306 if (ioctl(ctl, CMTPGETCONNLIST, &cl) < 0) {
307 perror("Can't get connection list");
315 fprintf(stderr, "You have to specifiy the device address.\n");
319 bacpy(&req.bdaddr, &ci[0].bdaddr);
321 str2ba(argv[1], &req.bdaddr);
323 if (ioctl(ctl, CMTPCONNDEL, &req) < 0) {
324 perror("Can't release connection");
329 static void cmd_loopback(int ctl, bdaddr_t *bdaddr, int argc, char **argv)
331 struct cmtp_conndel_req req;
343 str2ba(argv[1], &dst);
345 ba2str(bdaddr, addr);
346 dev_id = hci_devid(addr);
348 dev_id = hci_get_route(&dst);
349 hci_devba(dev_id, &src);
354 printf("Connecting to %s in loopback mode\n", addr);
357 if (!get_psm(&src, &dst, &psm))
362 sk = do_connect(ctl, dev_id, &src, &dst, psm, (1 << CMTP_LOOPBACK));
364 printf("Press CTRL-C for hangup\n");
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);
372 sa.sa_handler = sig_term;
373 sigaction(SIGTERM, &sa, NULL);
374 sigaction(SIGINT, &sa, NULL);
376 sa.sa_handler = sig_hup;
377 sigaction(SIGHUP, &sa, NULL);
380 sigdelset(&sigs, SIGCHLD);
381 sigdelset(&sigs, SIGPIPE);
382 sigdelset(&sigs, SIGTERM);
383 sigdelset(&sigs, SIGINT);
384 sigdelset(&sigs, SIGHUP);
387 p.events = POLLERR | POLLHUP;
389 while (!__io_canceled) {
391 if (ppoll(&p, 1, NULL, &sigs) > 0)
395 bacpy(&req.bdaddr, &dst);
396 ioctl(ctl, CMTPCONNDEL, &req);
402 void (*func)(int ctl, bdaddr_t *bdaddr, int argc, char **argv);
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 }
414 static void usage(void)
418 printf("ciptool - Bluetooth Common ISDN Access Profile (CIP)\n\n");
421 "\tciptool [options] [command]\n"
425 "\t-i [hciX|bdaddr] Local HCI device or BD Address\n"
426 "\t-h, --help Display help\n"
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 : " ",
437 static struct option main_options[] = {
438 { "help", 0, 0, 'h' },
439 { "device", 1, 0, 'i' },
443 int main(int argc, char *argv[])
448 bacpy(&bdaddr, BDADDR_ANY);
450 while ((opt = getopt_long(argc, argv, "+i:h", main_options, NULL)) != -1) {
453 if (!strncmp(optarg, "hci", 3))
454 hci_devba(atoi(optarg + 3), &bdaddr);
456 str2ba(optarg, &bdaddr);
475 if ((ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_CMTP)) < 0 ) {
476 perror("Can't open CMTP control socket");
480 for (i = 0; command[i].cmd; i++) {
481 if (strncmp(command[i].cmd, argv[0], 4) && strncmp(command[i].alt, argv[0], 4))
483 command[i].func(ctl, &bdaddr, argc, argv);