tizen 2.3 release
[framework/connectivity/bluez.git] / tools / rctest.c
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
6  *  Copyright (C) 2002-2010  Marcel Holtmann <marcel@holtmann.org>
7  *
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22  *
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <stdio.h>
30 #include <errno.h>
31 #include <ctype.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34 #include <stdlib.h>
35 #include <getopt.h>
36 #include <syslog.h>
37 #include <signal.h>
38 #include <sys/time.h>
39 #include <sys/ioctl.h>
40 #include <sys/socket.h>
41 #include <sys/stat.h>
42
43 #include <bluetooth/bluetooth.h>
44 #include <bluetooth/hci.h>
45 #include <bluetooth/hci_lib.h>
46 #include <bluetooth/rfcomm.h>
47 #include <bluetooth/sdp.h>
48 #include <bluetooth/sdp_lib.h>
49
50 /* Test modes */
51 enum {
52         SEND,
53         RECV,
54         RECONNECT,
55         MULTY,
56         DUMP,
57         CONNECT,
58         CRECV,
59         LSEND,
60         AUTO,
61 };
62
63 static unsigned char *buf;
64
65 /* Default data size */
66 static long data_size = 127;
67 static long num_frames = -1;
68
69 /* Default number of consecutive frames before the delay */
70 static int count = 1;
71
72 /* Default delay after sending count number of frames */
73 static unsigned long delay = 0;
74
75 /* Default addr and channel */
76 static bdaddr_t bdaddr;
77 static bdaddr_t auto_bdaddr;
78 static uint16_t uuid = 0x0000;
79 static uint8_t channel = 10;
80
81 static char *filename = NULL;
82 static char *savefile = NULL;
83 static int save_fd = -1;
84
85 static int master = 0;
86 static int auth = 0;
87 static int encr = 0;
88 static int secure = 0;
89 static int socktype = SOCK_STREAM;
90 static int linger = 0;
91 static int timestamp = 0;
92 static int defer_setup = 0;
93 static int priority = -1;
94
95 static float tv2fl(struct timeval tv)
96 {
97         return (float)tv.tv_sec + (float)(tv.tv_usec/1000000.0);
98 }
99
100 static uint8_t get_channel(const char *svr, uint16_t uuid)
101 {
102         sdp_session_t *sdp;
103         sdp_list_t *srch, *attrs, *rsp;
104         uuid_t svclass;
105         uint16_t attr;
106         bdaddr_t dst;
107         uint8_t channel = 0;
108         int err;
109
110         str2ba(svr, &dst);
111
112         sdp = sdp_connect(&bdaddr, &dst, SDP_RETRY_IF_BUSY);
113         if (!sdp)
114                 return 0;
115
116         sdp_uuid16_create(&svclass, uuid);
117         srch = sdp_list_append(NULL, &svclass);
118
119         attr = SDP_ATTR_PROTO_DESC_LIST;
120         attrs = sdp_list_append(NULL, &attr);
121
122         err = sdp_service_search_attr_req(sdp, srch,
123                                         SDP_ATTR_REQ_INDIVIDUAL, attrs, &rsp);
124         if (err)
125                 goto done;
126
127         for (; rsp; rsp = rsp->next) {
128                 sdp_record_t *rec = (sdp_record_t *) rsp->data;
129                 sdp_list_t *protos;
130
131                 if (!sdp_get_access_protos(rec, &protos)) {
132                         channel = sdp_get_proto_port(protos, RFCOMM_UUID);
133                         if (channel > 0)
134                                 break;
135                 }
136         }
137
138 done:
139         sdp_close(sdp);
140
141         return channel;
142 }
143
144 static int do_connect(const char *svr)
145 {
146         struct sockaddr_rc addr;
147         struct rfcomm_conninfo conn;
148         socklen_t optlen;
149         int sk, opt;
150
151         if (uuid != 0x0000)
152                 channel = get_channel(svr, uuid);
153
154         if (channel == 0) {
155                 syslog(LOG_ERR, "Can't get channel number");
156                 return -1;
157         }
158
159         /* Create socket */
160         sk = socket(PF_BLUETOOTH, socktype, BTPROTO_RFCOMM);
161         if (sk < 0) {
162                 syslog(LOG_ERR, "Can't create socket: %s (%d)",
163                                                         strerror(errno), errno);
164                 return -1;
165         }
166
167         /* Bind to local address */
168         memset(&addr, 0, sizeof(addr));
169         addr.rc_family = AF_BLUETOOTH;
170
171         if (bacmp(&auto_bdaddr, BDADDR_ANY))
172                 bacpy(&addr.rc_bdaddr, &auto_bdaddr);
173         else
174                 bacpy(&addr.rc_bdaddr, &bdaddr);
175
176         if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
177                 syslog(LOG_ERR, "Can't bind socket: %s (%d)",
178                                                         strerror(errno), errno);
179                 goto error;
180         }
181
182 #if 0
183         /* Enable SO_TIMESTAMP */
184         if (timestamp) {
185                 int t = 1;
186
187                 if (setsockopt(sk, SOL_SOCKET, SO_TIMESTAMP, &t, sizeof(t)) < 0) {
188                         syslog(LOG_ERR, "Can't enable SO_TIMESTAMP: %s (%d)",
189                                                         strerror(errno), errno);
190                         goto error;
191                 }
192         }
193 #endif
194
195         /* Enable SO_LINGER */
196         if (linger) {
197                 struct linger l = { .l_onoff = 1, .l_linger = linger };
198
199                 if (setsockopt(sk, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) < 0) {
200                         syslog(LOG_ERR, "Can't enable SO_LINGER: %s (%d)",
201                                                         strerror(errno), errno);
202                         goto error;
203                 }
204         }
205
206         /* Set link mode */
207         opt = 0;
208         if (master)
209                 opt |= RFCOMM_LM_MASTER;
210         if (auth)
211                 opt |= RFCOMM_LM_AUTH;
212         if (encr)
213                 opt |= RFCOMM_LM_ENCRYPT;
214         if (secure)
215                 opt |= RFCOMM_LM_SECURE;
216
217         if (opt && setsockopt(sk, SOL_RFCOMM, RFCOMM_LM, &opt, sizeof(opt)) < 0) {
218                 syslog(LOG_ERR, "Can't set RFCOMM link mode: %s (%d)",
219                                                         strerror(errno), errno);
220                 goto error;
221         }
222
223         /* Connect to remote device */
224         memset(&addr, 0, sizeof(addr));
225         addr.rc_family = AF_BLUETOOTH;
226         str2ba(svr, &addr.rc_bdaddr);
227         addr.rc_channel = channel;
228
229         if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
230                 syslog(LOG_ERR, "Can't connect: %s (%d)",
231                                                         strerror(errno), errno);
232                 goto error;
233         }
234
235         /* Get connection information */
236         memset(&conn, 0, sizeof(conn));
237         optlen = sizeof(conn);
238
239         if (getsockopt(sk, SOL_RFCOMM, RFCOMM_CONNINFO, &conn, &optlen) < 0) {
240                 syslog(LOG_ERR, "Can't get RFCOMM connection information: %s (%d)",
241                                                         strerror(errno), errno);
242                 //goto error;
243         }
244
245         if (priority > 0 && setsockopt(sk, SOL_SOCKET, SO_PRIORITY, &priority,
246                                                 sizeof(priority)) < 0) {
247                 syslog(LOG_ERR, "Can't set socket priority: %s (%d)",
248                                                         strerror(errno), errno);
249                 goto error;
250         }
251
252         if (getsockopt(sk, SOL_SOCKET, SO_PRIORITY, &opt, &optlen) < 0) {
253                 syslog(LOG_ERR, "Can't get socket priority: %s (%d)",
254                                                         strerror(errno), errno);
255                 goto error;
256         }
257
258         syslog(LOG_INFO, "Connected [handle %d, class 0x%02x%02x%02x, "
259                         "priority %d]", conn.hci_handle, conn.dev_class[2],
260                         conn.dev_class[1], conn.dev_class[0], opt);
261
262         return sk;
263
264 error:
265         close(sk);
266         return -1;
267 }
268
269 static void do_listen(void (*handler)(int sk))
270 {
271         struct sockaddr_rc addr;
272         struct rfcomm_conninfo conn;
273         socklen_t optlen;
274         int sk, nsk, opt;
275         char ba[18];
276
277         /* Create socket */
278         sk = socket(PF_BLUETOOTH, socktype, BTPROTO_RFCOMM);
279         if (sk < 0) {
280                 syslog(LOG_ERR, "Can't create socket: %s (%d)",
281                                                         strerror(errno), errno);
282                 exit(1);
283         }
284
285         /* Bind to local address */
286         memset(&addr, 0, sizeof(addr));
287         addr.rc_family = AF_BLUETOOTH;
288         bacpy(&addr.rc_bdaddr, &bdaddr);
289         addr.rc_channel = channel;
290
291         if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
292                 syslog(LOG_ERR, "Can't bind socket: %s (%d)",
293                                                         strerror(errno), errno);
294                 goto error;
295         }
296
297         /* Set link mode */
298         opt = 0;
299         if (master)
300                 opt |= RFCOMM_LM_MASTER;
301         if (auth)
302                 opt |= RFCOMM_LM_AUTH;
303         if (encr)
304                 opt |= RFCOMM_LM_ENCRYPT;
305         if (secure)
306                 opt |= RFCOMM_LM_SECURE;
307
308         if (opt && setsockopt(sk, SOL_RFCOMM, RFCOMM_LM, &opt, sizeof(opt)) < 0) {
309                 syslog(LOG_ERR, "Can't set RFCOMM link mode: %s (%d)",
310                                                         strerror(errno), errno);
311                 goto error;
312         }
313
314         /* Enable deferred setup */
315         opt = defer_setup;
316
317         if (opt && setsockopt(sk, SOL_BLUETOOTH, BT_DEFER_SETUP,
318                                                 &opt, sizeof(opt)) < 0) {
319                 syslog(LOG_ERR, "Can't enable deferred setup : %s (%d)",
320                                                         strerror(errno), errno);
321                 goto error;
322         }
323
324         /* Listen for connections */
325         if (listen(sk, 10)) {
326                 syslog(LOG_ERR,"Can not listen on the socket: %s (%d)",
327                                                         strerror(errno), errno);
328                 goto error;
329         }
330
331         /* Check for socket address */
332         memset(&addr, 0, sizeof(addr));
333         optlen = sizeof(addr);
334
335         if (getsockname(sk, (struct sockaddr *) &addr, &optlen) < 0) {
336                 syslog(LOG_ERR, "Can't get socket name: %s (%d)",
337                                                         strerror(errno), errno);
338                 goto error;
339         }
340
341         channel = addr.rc_channel;
342
343         syslog(LOG_INFO, "Waiting for connection on channel %d ...", channel);
344
345         while (1) {
346                 memset(&addr, 0, sizeof(addr));
347                 optlen = sizeof(addr);
348
349                 nsk = accept(sk, (struct sockaddr *) &addr, &optlen);
350                 if (nsk < 0) {
351                         syslog(LOG_ERR,"Accept failed: %s (%d)",
352                                                         strerror(errno), errno);
353                         goto error;
354                 }
355                 if (fork()) {
356                         /* Parent */
357                         close(nsk);
358                         continue;
359                 }
360                 /* Child */
361                 close(sk);
362
363                 /* Get connection information */
364                 memset(&conn, 0, sizeof(conn));
365                 optlen = sizeof(conn);
366
367                 if (getsockopt(nsk, SOL_RFCOMM, RFCOMM_CONNINFO, &conn, &optlen) < 0) {
368                         syslog(LOG_ERR, "Can't get RFCOMM connection information: %s (%d)",
369                                                         strerror(errno), errno);
370                         //close(nsk);
371                         //goto error;
372                 }
373
374                 if (priority > 0 && setsockopt(sk, SOL_SOCKET, SO_PRIORITY,
375                                         &priority, sizeof(priority)) < 0) {
376                         syslog(LOG_ERR, "Can't set socket priority: %s (%d)",
377                                                 strerror(errno), errno);
378                         close(nsk);
379                         goto error;
380                 }
381
382                 optlen = sizeof(priority);
383                 if (getsockopt(nsk, SOL_SOCKET, SO_PRIORITY, &opt, &optlen) < 0) {
384                         syslog(LOG_ERR, "Can't get socket priority: %s (%d)",
385                                                         strerror(errno), errno);
386                         goto error;
387                 }
388
389                 ba2str(&addr.rc_bdaddr, ba);
390                 syslog(LOG_INFO, "Connect from %s [handle %d, "
391                                 "class 0x%02x%02x%02x, priority %d]",
392                                 ba, conn.hci_handle, conn.dev_class[2],
393                                 conn.dev_class[1], conn.dev_class[0], opt);
394
395 #if 0
396                 /* Enable SO_TIMESTAMP */
397                 if (timestamp) {
398                         int t = 1;
399
400                         if (setsockopt(nsk, SOL_SOCKET, SO_TIMESTAMP, &t, sizeof(t)) < 0) {
401                                 syslog(LOG_ERR, "Can't enable SO_TIMESTAMP: %s (%d)",
402                                                         strerror(errno), errno);
403                                 goto error;
404                         }
405                 }
406 #endif
407
408                 /* Enable SO_LINGER */
409                 if (linger) {
410                         struct linger l = { .l_onoff = 1, .l_linger = linger };
411
412                         if (setsockopt(nsk, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) < 0) {
413                                 syslog(LOG_ERR, "Can't enable SO_LINGER: %s (%d)",
414                                                         strerror(errno), errno);
415                                 close(nsk);
416                                 goto error;
417                         }
418                 }
419
420                 /* Handle deferred setup */
421                 if (defer_setup) {
422                         syslog(LOG_INFO, "Waiting for %d seconds",
423                                                         abs(defer_setup) - 1);
424                         sleep(abs(defer_setup) - 1);
425
426                         if (defer_setup < 0) {
427                                 close(nsk);
428                                 goto error;
429                         }
430                 }
431
432                 handler(nsk);
433
434                 syslog(LOG_INFO, "Disconnect: %m");
435                 exit(0);
436         }
437
438         return;
439
440 error:
441         close(sk);
442         exit(1);
443 }
444
445 static void dump_mode(int sk)
446 {
447         int len;
448
449         syslog(LOG_INFO, "Receiving ...");
450         while ((len = read(sk, buf, data_size)) > 0)
451                 syslog(LOG_INFO, "Received %d bytes", len);
452 }
453
454 static void save_mode(int sk)
455 {
456         int len, ret;
457         char *b;
458
459         b = malloc(data_size);
460         if (!b) {
461                 syslog(LOG_ERR, "Failed to open file to save recv data");
462                 return;
463         }
464
465         syslog(LOG_INFO, "Receiving ...");
466         while ((len = read(sk, b, data_size)) > 0) {
467                 ret = write(save_fd, b, len);
468                 if (ret < 0)
469                         goto done;
470         }
471
472 done:
473         free(b);
474 }
475
476 static void recv_mode(int sk)
477 {
478         struct timeval tv_beg, tv_end, tv_diff;
479         char ts[30];
480         long total;
481
482         syslog(LOG_INFO, "Receiving ...");
483
484         memset(ts, 0, sizeof(ts));
485
486         while (1) {
487                 gettimeofday(&tv_beg,NULL);
488                 total = 0;
489                 while (total < data_size) {
490                         //uint32_t sq;
491                         //uint16_t l;
492                         int r;
493
494                         if ((r = recv(sk, buf, data_size, 0)) < 0) {
495                                 if (r < 0)
496                                         syslog(LOG_ERR, "Read failed: %s (%d)",
497                                                         strerror(errno), errno);
498                                 return;
499                         }
500
501                         if (timestamp) {
502                                 struct timeval tv;
503
504                                 if (ioctl(sk, SIOCGSTAMP, &tv) < 0) {
505                                         timestamp = 0;
506                                         memset(ts, 0, sizeof(ts));
507                                 } else {
508                                         sprintf(ts, "[%ld.%ld] ",
509                                                         tv.tv_sec, tv.tv_usec);
510                                 }
511                         }
512
513 #if 0
514                         /* Check sequence */
515                         sq = btohl(*(uint32_t *) buf);
516                         if (seq != sq) {
517                                 syslog(LOG_INFO, "seq missmatch: %d -> %d", seq, sq);
518                                 seq = sq;
519                         }
520                         seq++;
521
522                         /* Check length */
523                         l = btohs(*(uint16_t *) (buf + 4));
524                         if (r != l) {
525                                 syslog(LOG_INFO, "size missmatch: %d -> %d", r, l);
526                                 continue;
527                         }
528
529                         /* Verify data */
530                         for (i = 6; i < r; i++) {
531                                 if (buf[i] != 0x7f)
532                                         syslog(LOG_INFO, "data missmatch: byte %d 0x%2.2x", i, buf[i]);
533                         }
534 #endif
535                         total += r;
536                 }
537                 gettimeofday(&tv_end,NULL);
538
539                 timersub(&tv_end,&tv_beg,&tv_diff);
540
541                 syslog(LOG_INFO,"%s%ld bytes in %.2f sec, %.2f kB/s", ts, total,
542                         tv2fl(tv_diff), (float)(total / tv2fl(tv_diff) ) / 1024.0);
543         }
544 }
545
546 static void do_send(int sk)
547 {
548         uint32_t seq;
549         int i, fd, len;
550
551         syslog(LOG_INFO,"Sending ...");
552
553         if (filename) {
554                 fd = open(filename, O_RDONLY);
555                 if (fd < 0) {
556                         syslog(LOG_ERR, "Open failed: %s (%d)",
557                                                         strerror(errno), errno);
558                         exit(1);
559                 }
560                 len = read(fd, buf, data_size);
561                 send(sk, buf, len, 0);
562                 return;
563         } else {
564                 for (i = 6; i < data_size; i++)
565                         buf[i] = 0x7f;
566         }
567
568         seq = 0;
569         while ((num_frames == -1) || (num_frames-- > 0)) {
570                 bt_put_le32(seq, buf);
571                 bt_put_le16(data_size, buf + 4);
572
573                 seq++;
574
575                 if (send(sk, buf, data_size, 0) <= 0) {
576                         syslog(LOG_ERR, "Send failed: %s (%d)",
577                                                         strerror(errno), errno);
578                         exit(1);
579                 }
580
581                 if (num_frames && delay && count && !(seq % count))
582                         usleep(delay);
583         }
584 }
585
586 static void send_mode(int sk)
587 {
588         do_send(sk);
589
590         syslog(LOG_INFO, "Closing channel ...");
591         if (shutdown(sk, SHUT_RDWR) < 0)
592                 syslog(LOG_INFO, "Close failed: %m");
593         else
594                 syslog(LOG_INFO, "Done");
595 }
596
597 static void reconnect_mode(char *svr)
598 {
599         while(1) {
600                 int sk = do_connect(svr);
601                 close(sk);
602         }
603 }
604
605 static void multi_connect_mode(int argc, char *argv[])
606 {
607         int i, n, sk;
608
609         while (1) {
610                 for (n = 0; n < argc; n++) {
611                         for (i = 0; i < count; i++) {
612                                 if (fork())
613                                         continue;
614
615                                 /* Child */
616                                 sk = do_connect(argv[n]);
617                                 usleep(500);
618                                 close(sk);
619                                 exit(0);
620                         }
621                 }
622                 sleep(4);
623         }
624 }
625
626 static void automated_send_recv()
627 {
628         int sk;
629         char device[18];
630
631         if (fork()) {
632                 if (!savefile) {
633                         do_listen(recv_mode);
634                         return;
635                 }
636
637                 save_fd = open(savefile, O_CREAT | O_WRONLY,
638                                                 S_IRUSR | S_IWUSR);
639                 if (save_fd < 0)
640                         syslog(LOG_ERR, "Failed to open file to save data");
641
642                 do_listen(save_mode);
643
644                 close(save_fd);
645         } else {
646                 ba2str(&bdaddr, device);
647
648                 sk = do_connect(device);
649                 if (sk < 0)
650                         exit(1);
651                 send_mode(sk);
652         }
653 }
654
655 static void sig_child_exit(int code)
656 {
657         if (save_fd >= 0)
658                 close(save_fd);
659
660         syslog(LOG_INFO, "Exit");
661         exit(0);
662 }
663
664 static void usage(void)
665 {
666         printf("rctest - RFCOMM testing\n"
667                 "Usage:\n");
668         printf("\trctest <mode> [options] [bdaddr]\n");
669         printf("Modes:\n"
670                 "\t-r listen and receive\n"
671                 "\t-w listen and send\n"
672                 "\t-d listen and dump incoming data\n"
673                 "\t-s connect and send\n"
674                 "\t-u connect and receive\n"
675                 "\t-n connect and be silent\n"
676                 "\t-c connect, disconnect, connect, ...\n"
677                 "\t-m multiple connects\n"
678                 "\t-a automated test (receive hcix as parameter)\n");
679
680         printf("Options:\n"
681                 "\t[-b bytes] [-i device] [-P channel] [-U uuid]\n"
682                 "\t[-L seconds] enabled SO_LINGER option\n"
683                 "\t[-W seconds] enable deferred setup\n"
684                 "\t[-B filename] use data packets from file\n"
685                 "\t[-O filename] save received data to file\n"
686                 "\t[-N num] number of frames to send\n"
687                 "\t[-C num] send num frames before delay (default = 1)\n"
688                 "\t[-D milliseconds] delay after sending num frames (default = 0)\n"
689                 "\t[-Y priority] socket priority\n"
690                 "\t[-A] request authentication\n"
691                 "\t[-E] request encryption\n"
692                 "\t[-S] secure connection\n"
693                 "\t[-M] become master\n"
694                 "\t[-T] enable timestamps\n");
695 }
696
697 int main(int argc, char *argv[])
698 {
699         struct sigaction sa;
700         int opt, sk, mode = RECV, need_addr = 0;
701
702         bacpy(&bdaddr, BDADDR_ANY);
703         bacpy(&auto_bdaddr, BDADDR_ANY);
704
705         while ((opt=getopt(argc,argv,"rdscuwmna:b:i:P:U:B:O:N:MAESL:W:C:D:Y:T")) != EOF) {
706                 switch (opt) {
707                 case 'r':
708                         mode = RECV;
709                         break;
710
711                 case 's':
712                         mode = SEND;
713                         need_addr = 1;
714                         break;
715
716                 case 'w':
717                         mode = LSEND;
718                         break;
719
720                 case 'u':
721                         mode = CRECV;
722                         need_addr = 1;
723                         break;
724
725                 case 'd':
726                         mode = DUMP;
727                         break;
728
729                 case 'c':
730                         mode = RECONNECT;
731                         need_addr = 1;
732                         break;
733
734                 case 'n':
735                         mode = CONNECT;
736                         need_addr = 1;
737                         break;
738
739                 case 'm':
740                         mode = MULTY;
741                         need_addr = 1;
742                         break;
743
744                 case 'a':
745                         mode = AUTO;
746
747                         if (!strncasecmp(optarg, "hci", 3))
748                                 hci_devba(atoi(optarg + 3), &auto_bdaddr);
749                         else
750                                 str2ba(optarg, &auto_bdaddr);
751                         break;
752
753                 case 'b':
754                         data_size = atoi(optarg);
755                         break;
756
757                 case 'i':
758                         if (!strncasecmp(optarg, "hci", 3))
759                                 hci_devba(atoi(optarg + 3), &bdaddr);
760                         else
761                                 str2ba(optarg, &bdaddr);
762                         break;
763
764                 case 'P':
765                         channel = atoi(optarg);
766                         break;
767
768                 case 'U':
769                         if (!strcasecmp(optarg, "spp"))
770                                 uuid = SERIAL_PORT_SVCLASS_ID;
771                         else if (!strncasecmp(optarg, "0x", 2))
772                                 uuid = strtoul(optarg + 2, NULL, 16);
773                         else
774                                 uuid = atoi(optarg);
775                         break;
776
777                 case 'M':
778                         master = 1;
779                         break;
780
781                 case 'A':
782                         auth = 1;
783                         break;
784
785                 case 'E':
786                         encr = 1;
787                         break;
788
789                 case 'S':
790                         secure = 1;
791                         break;
792
793                 case 'L':
794                         linger = atoi(optarg);
795                         break;
796
797                 case 'W':
798                         defer_setup = atoi(optarg);
799                         break;
800
801                 case 'B':
802                         filename = strdup(optarg);
803                         break;
804
805                 case 'O':
806                         savefile = strdup(optarg);
807                         break;
808
809                 case 'N':
810                         num_frames = atoi(optarg);
811                         break;
812
813                 case 'C':
814                         count = atoi(optarg);
815                         break;
816
817                 case 'D':
818                         delay = atoi(optarg) * 1000;
819                         break;
820
821                 case 'Y':
822                         priority = atoi(optarg);
823                         break;
824
825                 case 'T':
826                         timestamp = 1;
827                         break;
828
829                 default:
830                         usage();
831                         exit(1);
832                 }
833         }
834
835         if (need_addr && !(argc - optind)) {
836                 usage();
837                 exit(1);
838         }
839
840         if (!(buf = malloc(data_size))) {
841                 perror("Can't allocate data buffer");
842                 exit(1);
843         }
844
845         memset(&sa, 0, sizeof(sa));
846         if (mode == AUTO)
847                 sa.sa_handler = sig_child_exit;
848         else
849                 sa.sa_handler = SIG_IGN;
850         sa.sa_flags   = SA_NOCLDSTOP;
851         sigaction(SIGCHLD, &sa, NULL);
852
853         openlog("rctest", LOG_PERROR | LOG_PID, LOG_LOCAL0);
854
855         switch (mode) {
856                 case RECV:
857                         do_listen(recv_mode);
858                         break;
859
860                 case CRECV:
861                         sk = do_connect(argv[optind]);
862                         if (sk < 0)
863                                 exit(1);
864                         recv_mode(sk);
865                         break;
866
867                 case DUMP:
868                         do_listen(dump_mode);
869                         break;
870
871                 case SEND:
872                         sk = do_connect(argv[optind]);
873                         if (sk < 0)
874                                 exit(1);
875                         send_mode(sk);
876                         break;
877
878                 case LSEND:
879                         do_listen(send_mode);
880                         break;
881
882                 case RECONNECT:
883                         reconnect_mode(argv[optind]);
884                         break;
885
886                 case MULTY:
887                         multi_connect_mode(argc - optind, argv + optind);
888                         break;
889
890                 case CONNECT:
891                         sk = do_connect(argv[optind]);
892                         if (sk < 0)
893                                 exit(1);
894                         dump_mode(sk);
895                         break;
896
897                 case AUTO:
898                         automated_send_recv();
899                         break;
900         }
901
902         syslog(LOG_INFO, "Exit");
903
904         closelog();
905
906         return 0;
907 }