1c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky/*
2b8707600fd45e0cda31654fc7b2932f29b28d1a1Marcel Holtmann *
3b8707600fd45e0cda31654fc7b2932f29b28d1a1Marcel Holtmann *  BlueZ - Bluetooth protocol stack for Linux
4b8707600fd45e0cda31654fc7b2932f29b28d1a1Marcel Holtmann *
5b8707600fd45e0cda31654fc7b2932f29b28d1a1Marcel Holtmann *  Copyright (C) 2000-2001  Qualcomm Incorporated
6b8707600fd45e0cda31654fc7b2932f29b28d1a1Marcel Holtmann *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
79184e2eeb7b97371c6b83b747c8984e2340d2b47Marcel Holtmann *  Copyright (C) 2002-2010  Marcel Holtmann <marcel@holtmann.org>
8b8707600fd45e0cda31654fc7b2932f29b28d1a1Marcel Holtmann *
9b8707600fd45e0cda31654fc7b2932f29b28d1a1Marcel Holtmann *
10b8707600fd45e0cda31654fc7b2932f29b28d1a1Marcel Holtmann *  This program is free software; you can redistribute it and/or modify
11632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann *  it under the terms of the GNU General Public License as published by
12632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann *  the Free Software Foundation; either version 2 of the License, or
13632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann *  (at your option) any later version.
14b8707600fd45e0cda31654fc7b2932f29b28d1a1Marcel Holtmann *
15632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann *  This program is distributed in the hope that it will be useful,
16632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann *  GNU General Public License for more details.
19b8707600fd45e0cda31654fc7b2932f29b28d1a1Marcel Holtmann *
20632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann *  You should have received a copy of the GNU General Public License
21632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann *  along with this program; if not, write to the Free Software
22632a9432774ff3a0c6e556e8f32a565b38890767Marcel Holtmann *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
23b8707600fd45e0cda31654fc7b2932f29b28d1a1Marcel Holtmann *
24c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky */
25c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
26b8707600fd45e0cda31654fc7b2932f29b28d1a1Marcel Holtmann#ifdef HAVE_CONFIG_H
27b8707600fd45e0cda31654fc7b2932f29b28d1a1Marcel Holtmann#include <config.h>
28b8707600fd45e0cda31654fc7b2932f29b28d1a1Marcel Holtmann#endif
29b8707600fd45e0cda31654fc7b2932f29b28d1a1Marcel Holtmann
30c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky#include <stdio.h>
31c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky#include <errno.h>
321f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann#include <ctype.h>
33da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann#include <fcntl.h>
3414be8b04824df3f5a9bd7b713646a9120e2b2454Marcel Holtmann#include <unistd.h>
3514be8b04824df3f5a9bd7b713646a9120e2b2454Marcel Holtmann#include <stdlib.h>
365481f007aa304a6f5f4531a243e146f9075dc17fMarcel Holtmann#include <getopt.h>
3714be8b04824df3f5a9bd7b713646a9120e2b2454Marcel Holtmann#include <syslog.h>
38c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky#include <signal.h>
391f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann#include <sys/time.h>
4077f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann#include <sys/poll.h>
412199bc76c668f92e14fcaa4bc16fd4674f728bc1Marcel Holtmann#include <sys/ioctl.h>
42c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky#include <sys/socket.h>
43c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
4404c8ddd5a5d720e75144755d071e2331c979d1edMax Krasnyansky#include <bluetooth/bluetooth.h>
4552d36be0bf2610739f04786d18df80db23e9cf6bMarcel Holtmann#include <bluetooth/hci.h>
4652d36be0bf2610739f04786d18df80db23e9cf6bMarcel Holtmann#include <bluetooth/hci_lib.h>
4704c8ddd5a5d720e75144755d071e2331c979d1edMax Krasnyansky#include <bluetooth/l2cap.h>
48c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
4914be8b04824df3f5a9bd7b713646a9120e2b2454Marcel Holtmann#define NIBBLE_TO_ASCII(c)  ((c) < 0x0a ? (c) + 0x30 : (c) + 0x57)
501f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann
51c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky/* Test modes */
52c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyanskyenum {
53c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	SEND,
54c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	RECV,
55c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	RECONNECT,
56c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	MULTY,
57c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	DUMP,
5804c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky	CONNECT,
5904c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky	CRECV,
601f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	LSEND,
611f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	SENDDUMP,
62329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	LSENDDUMP,
63a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan	LSENDRECV,
64a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan	CSENDRECV,
6522fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann	INFOREQ,
6622fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann	PAIRING,
67c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky};
68c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
693c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmannstatic unsigned char *buf;
70c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
71c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky/* Default mtu */
723c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmannstatic int imtu = 672;
733c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmannstatic int omtu = 0;
74c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
7533874cd97071383ca45b09a0fcb51b888002b0d9Gustavo F. Padovan/* Default FCS option */
7633874cd97071383ca45b09a0fcb51b888002b0d9Gustavo F. Padovanstatic int fcs = 0x01;
7733874cd97071383ca45b09a0fcb51b888002b0d9Gustavo F. Padovan
78449367e8dab5fadc49f97c72a6837120e889cdc4Gustavo F. Padovan/* Default Transmission Window */
79449367e8dab5fadc49f97c72a6837120e889cdc4Gustavo F. Padovanstatic int txwin_size = 63;
80449367e8dab5fadc49f97c72a6837120e889cdc4Gustavo F. Padovan
81449367e8dab5fadc49f97c72a6837120e889cdc4Gustavo F. Padovan/* Default Max Transmission */
82449367e8dab5fadc49f97c72a6837120e889cdc4Gustavo F. Padovanstatic int max_transmit = 3;
83449367e8dab5fadc49f97c72a6837120e889cdc4Gustavo F. Padovan
84c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky/* Default data size */
8577f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmannstatic long data_size = -1;
8641e30382f9a83f41da700465de274266c60248b4Marcel Holtmannstatic long buffer_size = 2048;
87c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
88c5eab04d6572dee0885a512bfd4ad7f7a33b57c0Gustavo F. Padovan/* Default addr and psm and cid */
893c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmannstatic bdaddr_t bdaddr;
90cd09d807d3060f4b269602276504a8380ab1a2c1Gustavo F. Padovanstatic unsigned short psm = 0x1011;
91c5eab04d6572dee0885a512bfd4ad7f7a33b57c0Gustavo F. Padovanstatic unsigned short cid = 0;
92c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
937715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann/* Default number of frames to send (-1 = infinite) */
947715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmannstatic int num_frames = -1;
9533a6d8d6bc6bf30a37a92ef40353e6426beeb59bMarcel Holtmann
96b357f1d3900bca5575e88fcfc160945c6088608cMarcel Holtmann/* Default number of consecutive frames before the delay */
97b357f1d3900bca5575e88fcfc160945c6088608cMarcel Holtmannstatic int count = 1;
98b357f1d3900bca5575e88fcfc160945c6088608cMarcel Holtmann
99b357f1d3900bca5575e88fcfc160945c6088608cMarcel Holtmann/* Default delay after sending count number of frames */
100b357f1d3900bca5575e88fcfc160945c6088608cMarcel Holtmannstatic unsigned long delay = 0;
101b357f1d3900bca5575e88fcfc160945c6088608cMarcel Holtmann
102da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmannstatic char *filename = NULL;
103da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann
1048e34afe9cc4dada1c34126a9723f76d4a6705707Marcel Holtmannstatic int rfcmode = 0;
1053c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmannstatic int master = 0;
1063c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmannstatic int auth = 0;
1073c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmannstatic int encrypt = 0;
1083c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmannstatic int secure = 0;
1093c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmannstatic int socktype = SOCK_SEQPACKET;
1103c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmannstatic int linger = 0;
1113c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmannstatic int reliable = 0;
1125b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmannstatic int timestamp = 0;
1139e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmannstatic int defer_setup = 0;
114c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
1153c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmannstatic float tv2fl(struct timeval tv)
116c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{
117c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	return (float)tv.tv_sec + (float)(tv.tv_usec/1000000.0);
118c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky}
119c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
1203c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmannstatic char *ltoh(unsigned long c, char* s)
1211f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann{
1221f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	int c1;
1231f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann
1241f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	c1     = (c >> 28) & 0x0f;
1251f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	*(s++) = NIBBLE_TO_ASCII (c1);
1261f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	c1     = (c >> 24) & 0x0f;
1271f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	*(s++) = NIBBLE_TO_ASCII (c1);
1281f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	c1     = (c >> 20) & 0x0f;
1291f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	*(s++) = NIBBLE_TO_ASCII (c1);
1301f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	c1     = (c >> 16) & 0x0f;
1311f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	*(s++) = NIBBLE_TO_ASCII (c1);
1321f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	c1     = (c >> 12) & 0x0f;
1331f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	*(s++) = NIBBLE_TO_ASCII (c1);
1341f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	c1     = (c >>  8) & 0x0f;
1351f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	*(s++) = NIBBLE_TO_ASCII (c1);
1361f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	c1     = (c >>  4) & 0x0f;
1371f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	*(s++) = NIBBLE_TO_ASCII (c1);
1381f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	c1     = c & 0x0f;
1391f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	*(s++) = NIBBLE_TO_ASCII (c1);
1401f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	*s     = 0;
14114be8b04824df3f5a9bd7b713646a9120e2b2454Marcel Holtmann	return s;
1421f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann}
1431f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann
1443c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmannstatic char *ctoh(char c, char* s)
1451f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann{
1461f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	char c1;
1471f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann
1481f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	c1     = (c >> 4) & 0x0f;
1491f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	*(s++) = NIBBLE_TO_ASCII (c1);
1501f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	c1     = c & 0x0f;
1511f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	*(s++) = NIBBLE_TO_ASCII (c1);
1521f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	*s     = 0;
15314be8b04824df3f5a9bd7b713646a9120e2b2454Marcel Holtmann	return s;
1541f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann}
1551f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann
1561f422e5f2b343d35a8c77ce4be16f74b2819b2bfMarcel Holtmannstatic void hexdump(unsigned char *s, unsigned long l)
1571f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann{
1581f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	char bfr[80];
1591f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	char *pb;
1601f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	unsigned long i, n = 0;
1613c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmann
1621f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	if (l == 0)
1631f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann		return;
1643c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmann
1651f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	while (n < l) {
1661f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann		pb = bfr;
1671f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann		pb = ltoh (n, pb);
1681f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann		*(pb++) = ':';
1691f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann		*(pb++) = ' ';
1701f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann		for (i = 0; i < 16; i++) {
1711f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann			if (n + i >= l) {
1721f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann				*(pb++) = ' ';
1731f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann				*(pb++) = ' ';
1741f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann			} else
1751f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann				pb = ctoh (*(s + i), pb);
1761f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann			*(pb++) = ' ';
1771f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann		}
1781f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann		*(pb++) = ' ';
1791f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann		for (i = 0; i < 16; i++) {
1801f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann			if (n + i >= l)
1811f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann				break;
1821f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann			else
1831f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann				*(pb++) = (isprint (*(s + i)) ? *(s + i) : '.');
1841f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann		}
1853c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmann		*pb = 0;
1861f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann		n += 16;
1871f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann		s += 16;
1881f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann		puts(bfr);
1891f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann	}
1901f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann}
1911f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann
1923c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmannstatic int do_connect(char *svr)
193c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{
1947715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	struct sockaddr_l2 addr;
195c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	struct l2cap_options opts;
1969e6e37723b8d8798ed9ba58734fd3022fdf49dc2Marcel Holtmann	struct l2cap_conninfo conn;
1977715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	socklen_t optlen;
1987715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	int sk, opt;
199c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
2007715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	/* Create socket */
2017715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	sk = socket(PF_BLUETOOTH, socktype, BTPROTO_L2CAP);
2027715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	if (sk < 0) {
2037715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		syslog(LOG_ERR, "Can't create socket: %s (%d)",
2047715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann							strerror(errno), errno);
205c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		return -1;
206c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
207c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
2087715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	/* Bind to local address */
2097715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	memset(&addr, 0, sizeof(addr));
2107715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	addr.l2_family = AF_BLUETOOTH;
2117715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	bacpy(&addr.l2_bdaddr, &bdaddr);
2127715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann
2137715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
2147715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		syslog(LOG_ERR, "Can't bind socket: %s (%d)",
2157715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann							strerror(errno), errno);
2167715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		goto error;
217c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
218c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
219c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	/* Get default options */
220bbda499067067aefc8e642a2784d247ac0331eaeMarcel Holtmann	memset(&opts, 0, sizeof(opts));
2217715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	optlen = sizeof(opts);
2227715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann
2237715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, &optlen) < 0) {
2247715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		syslog(LOG_ERR, "Can't get default L2CAP options: %s (%d)",
2257715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann							strerror(errno), errno);
2267715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		goto error;
227c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
228c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
229c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	/* Set new options */
230c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	opts.omtu = omtu;
231c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	opts.imtu = imtu;
2325261de27f3d5463febf4d7dfa3a7e417ba0d4df5Gustavo F. Padovan	opts.mode = rfcmode;
2337715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann
23433874cd97071383ca45b09a0fcb51b888002b0d9Gustavo F. Padovan	opts.fcs = fcs;
235449367e8dab5fadc49f97c72a6837120e889cdc4Gustavo F. Padovan	opts.txwin_size = txwin_size;
236449367e8dab5fadc49f97c72a6837120e889cdc4Gustavo F. Padovan	opts.max_tx = max_transmit;
23733874cd97071383ca45b09a0fcb51b888002b0d9Gustavo F. Padovan
2387715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	if (setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, sizeof(opts)) < 0) {
2397715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		syslog(LOG_ERR, "Can't set L2CAP options: %s (%d)",
2407715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann							strerror(errno), errno);
2417715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		goto error;
242c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
243c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
2442199bc76c668f92e14fcaa4bc16fd4674f728bc1Marcel Holtmann#if 0
2455b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann	/* Enable SO_TIMESTAMP */
2465b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann	if (timestamp) {
2475b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann		int t = 1;
2485b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann
2495b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann		if (setsockopt(sk, SOL_SOCKET, SO_TIMESTAMP, &t, sizeof(t)) < 0) {
2505b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann			syslog(LOG_ERR, "Can't enable SO_TIMESTAMP: %s (%d)",
2515b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann							strerror(errno), errno);
2525b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann			goto error;
2535b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann		}
2545b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann	}
2552199bc76c668f92e14fcaa4bc16fd4674f728bc1Marcel Holtmann#endif
2565b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann
25779cc4e4e2d74be3f1445203b1fdb844caa1cb009Max Krasnyansky	/* Enable SO_LINGER */
25879cc4e4e2d74be3f1445203b1fdb844caa1cb009Max Krasnyansky	if (linger) {
25979cc4e4e2d74be3f1445203b1fdb844caa1cb009Max Krasnyansky		struct linger l = { .l_onoff = 1, .l_linger = linger };
2607715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann
2617715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		if (setsockopt(sk, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) < 0) {
26214be8b04824df3f5a9bd7b713646a9120e2b2454Marcel Holtmann			syslog(LOG_ERR, "Can't enable SO_LINGER: %s (%d)",
2637715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann							strerror(errno), errno);
2645b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann			goto error;
26579cc4e4e2d74be3f1445203b1fdb844caa1cb009Max Krasnyansky		}
26679cc4e4e2d74be3f1445203b1fdb844caa1cb009Max Krasnyansky	}
26779cc4e4e2d74be3f1445203b1fdb844caa1cb009Max Krasnyansky
268f6557046863c041920180d232c8f0a63bb2faf3cMarcel Holtmann	/* Set link mode */
269f6557046863c041920180d232c8f0a63bb2faf3cMarcel Holtmann	opt = 0;
270f6557046863c041920180d232c8f0a63bb2faf3cMarcel Holtmann	if (reliable)
27114be8b04824df3f5a9bd7b713646a9120e2b2454Marcel Holtmann		opt |= L2CAP_LM_RELIABLE;
27206e4d41372a9f005b05cc2f4a09924f18bf6f6d7Marcel Holtmann	if (master)
27306e4d41372a9f005b05cc2f4a09924f18bf6f6d7Marcel Holtmann		opt |= L2CAP_LM_MASTER;
27406e4d41372a9f005b05cc2f4a09924f18bf6f6d7Marcel Holtmann	if (auth)
27506e4d41372a9f005b05cc2f4a09924f18bf6f6d7Marcel Holtmann		opt |= L2CAP_LM_AUTH;
27606e4d41372a9f005b05cc2f4a09924f18bf6f6d7Marcel Holtmann	if (encrypt)
27706e4d41372a9f005b05cc2f4a09924f18bf6f6d7Marcel Holtmann		opt |= L2CAP_LM_ENCRYPT;
27806e4d41372a9f005b05cc2f4a09924f18bf6f6d7Marcel Holtmann	if (secure)
27906e4d41372a9f005b05cc2f4a09924f18bf6f6d7Marcel Holtmann		opt |= L2CAP_LM_SECURE;
280f6557046863c041920180d232c8f0a63bb2faf3cMarcel Holtmann
2817715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	if (setsockopt(sk, SOL_L2CAP, L2CAP_LM, &opt, sizeof(opt)) < 0) {
2827715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		syslog(LOG_ERR, "Can't set L2CAP link mode: %s (%d)",
2837715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann							strerror(errno), errno);
2847715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		goto error;
285f6557046863c041920180d232c8f0a63bb2faf3cMarcel Holtmann	}
286f6557046863c041920180d232c8f0a63bb2faf3cMarcel Holtmann
2877715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	/* Connect to remote device */
2887715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	memset(&addr, 0, sizeof(addr));
2897715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	addr.l2_family = AF_BLUETOOTH;
2907715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	str2ba(svr, &addr.l2_bdaddr);
291c5eab04d6572dee0885a512bfd4ad7f7a33b57c0Gustavo F. Padovan	if (cid)
292c5eab04d6572dee0885a512bfd4ad7f7a33b57c0Gustavo F. Padovan		addr.l2_cid = htobs(cid);
293c5eab04d6572dee0885a512bfd4ad7f7a33b57c0Gustavo F. Padovan	else if (psm)
294c5eab04d6572dee0885a512bfd4ad7f7a33b57c0Gustavo F. Padovan		addr.l2_psm = htobs(psm);
295c5eab04d6572dee0885a512bfd4ad7f7a33b57c0Gustavo F. Padovan	else
296c5eab04d6572dee0885a512bfd4ad7f7a33b57c0Gustavo F. Padovan		goto error;
2977715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann
2987715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0 ) {
2997715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		syslog(LOG_ERR, "Can't connect: %s (%d)",
3007715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann							strerror(errno), errno);
3017715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		goto error;
302c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
303c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
3047715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	/* Get current options */
305bbda499067067aefc8e642a2784d247ac0331eaeMarcel Holtmann	memset(&opts, 0, sizeof(opts));
3067715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	optlen = sizeof(opts);
3077715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann
3087715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, &optlen) < 0) {
3097715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		syslog(LOG_ERR, "Can't get L2CAP options: %s (%d)",
3107715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann							strerror(errno), errno);
3117715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		goto error;
312c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
313c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
3147715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	/* Get connection information */
3159e6e37723b8d8798ed9ba58734fd3022fdf49dc2Marcel Holtmann	memset(&conn, 0, sizeof(conn));
3167715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	optlen = sizeof(conn);
3177715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann
3187715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	if (getsockopt(sk, SOL_L2CAP, L2CAP_CONNINFO, &conn, &optlen) < 0) {
3197715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		syslog(LOG_ERR, "Can't get L2CAP connection information: %s (%d)",
3207715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann							strerror(errno), errno);
3217715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		goto error;
3229e6e37723b8d8798ed9ba58734fd3022fdf49dc2Marcel Holtmann	}
3239e6e37723b8d8798ed9ba58734fd3022fdf49dc2Marcel Holtmann
3247715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	syslog(LOG_INFO, "Connected [imtu %d, omtu %d, flush_to %d, "
3257715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann				"mode %d, handle %d, class 0x%02x%02x%02x]",
3269e6e37723b8d8798ed9ba58734fd3022fdf49dc2Marcel Holtmann		opts.imtu, opts.omtu, opts.flush_to, opts.mode, conn.hci_handle,
3279e6e37723b8d8798ed9ba58734fd3022fdf49dc2Marcel Holtmann		conn.dev_class[2], conn.dev_class[1], conn.dev_class[0]);
328c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
32941e30382f9a83f41da700465de274266c60248b4Marcel Holtmann	omtu = (opts.omtu > buffer_size) ? buffer_size : opts.omtu;
33041e30382f9a83f41da700465de274266c60248b4Marcel Holtmann	imtu = (opts.imtu > buffer_size) ? buffer_size : opts.imtu;
33172a919e9b1ae03645a63e27dfa6f4190ade6c924Marcel Holtmann
3327715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	return sk;
3337715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann
3347715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmannerror:
3357715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	close(sk);
3367715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	return -1;
337c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky}
338c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
3393c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmannstatic void do_listen(void (*handler)(int sk))
340c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{
3417715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	struct sockaddr_l2 addr;
342c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	struct l2cap_options opts;
343d198227a6d76b6fb6bff050e6fda9f2e4ffc4544Marcel Holtmann	struct l2cap_conninfo conn;
3447715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	socklen_t optlen;
3457715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	int sk, nsk, opt;
3463c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmann	char ba[18];
347c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
3487715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	/* Create socket */
3497715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	sk = socket(PF_BLUETOOTH, socktype, BTPROTO_L2CAP);
3507715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	if (sk < 0) {
3517715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		syslog(LOG_ERR, "Can't create socket: %s (%d)",
3527715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann							strerror(errno), errno);
353c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		exit(1);
354c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
355c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
3567715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	/* Bind to local address */
3574296b2cda59e00a559caa988c81598605cdfcf0fMarcel Holtmann	memset(&addr, 0, sizeof(addr));
3587715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	addr.l2_family = AF_BLUETOOTH;
3597715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	bacpy(&addr.l2_bdaddr, &bdaddr);
360c5eab04d6572dee0885a512bfd4ad7f7a33b57c0Gustavo F. Padovan	if (cid)
361c5eab04d6572dee0885a512bfd4ad7f7a33b57c0Gustavo F. Padovan		addr.l2_cid = htobs(cid);
362c5eab04d6572dee0885a512bfd4ad7f7a33b57c0Gustavo F. Padovan	else if (psm)
363c5eab04d6572dee0885a512bfd4ad7f7a33b57c0Gustavo F. Padovan		addr.l2_psm = htobs(psm);
364c5eab04d6572dee0885a512bfd4ad7f7a33b57c0Gustavo F. Padovan	else
365c5eab04d6572dee0885a512bfd4ad7f7a33b57c0Gustavo F. Padovan		goto error;
3667715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann
3677715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
3687715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		syslog(LOG_ERR, "Can't bind socket: %s (%d)",
3697715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann							strerror(errno), errno);
3707715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		goto error;
371c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
372c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
37370516886fef2e6c208d3e48332cc2c6c4b4d964cMax Krasnyansky	/* Set link mode */
37470516886fef2e6c208d3e48332cc2c6c4b4d964cMax Krasnyansky	opt = 0;
375f6557046863c041920180d232c8f0a63bb2faf3cMarcel Holtmann	if (reliable)
376f6557046863c041920180d232c8f0a63bb2faf3cMarcel Holtmann		opt |= L2CAP_LM_RELIABLE;
37770516886fef2e6c208d3e48332cc2c6c4b4d964cMax Krasnyansky	if (master)
37852d36be0bf2610739f04786d18df80db23e9cf6bMarcel Holtmann		opt |= L2CAP_LM_MASTER;
37970516886fef2e6c208d3e48332cc2c6c4b4d964cMax Krasnyansky	if (auth)
38052d36be0bf2610739f04786d18df80db23e9cf6bMarcel Holtmann		opt |= L2CAP_LM_AUTH;
38170516886fef2e6c208d3e48332cc2c6c4b4d964cMax Krasnyansky	if (encrypt)
38252d36be0bf2610739f04786d18df80db23e9cf6bMarcel Holtmann		opt |= L2CAP_LM_ENCRYPT;
38352d36be0bf2610739f04786d18df80db23e9cf6bMarcel Holtmann	if (secure)
38452d36be0bf2610739f04786d18df80db23e9cf6bMarcel Holtmann		opt |= L2CAP_LM_SECURE;
38570516886fef2e6c208d3e48332cc2c6c4b4d964cMax Krasnyansky
3867715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	if (opt && setsockopt(sk, SOL_L2CAP, L2CAP_LM, &opt, sizeof(opt)) < 0) {
3877715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		syslog(LOG_ERR, "Can't set L2CAP link mode: %s (%d)",
3887715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann							strerror(errno), errno);
3897715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		goto error;
390c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
391c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
392c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	/* Get default options */
3937715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	memset(&opts, 0, sizeof(opts));
3947715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	optlen = sizeof(opts);
3957715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann
3967715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, &optlen) < 0) {
3977715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		syslog(LOG_ERR, "Can't get default L2CAP options: %s (%d)",
3987715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann							strerror(errno), errno);
3997715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		goto error;
400c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
401c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
402c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	/* Set new options */
40311d24685fbd0b32c19bab01c0644dd9d5ea25315Marcel Holtmann	opts.omtu = omtu;
404c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	opts.imtu = imtu;
4058e34afe9cc4dada1c34126a9723f76d4a6705707Marcel Holtmann	if (rfcmode > 0)
4068e34afe9cc4dada1c34126a9723f76d4a6705707Marcel Holtmann		opts.mode = rfcmode;
4077715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann
40833874cd97071383ca45b09a0fcb51b888002b0d9Gustavo F. Padovan	opts.fcs = fcs;
409449367e8dab5fadc49f97c72a6837120e889cdc4Gustavo F. Padovan	opts.txwin_size = txwin_size;
410449367e8dab5fadc49f97c72a6837120e889cdc4Gustavo F. Padovan	opts.max_tx = max_transmit;
41133874cd97071383ca45b09a0fcb51b888002b0d9Gustavo F. Padovan
4127715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	if (setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, sizeof(opts)) < 0) {
4137715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		syslog(LOG_ERR, "Can't set L2CAP options: %s (%d)",
4147715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann							strerror(errno), errno);
4157715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		goto error;
416c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
417c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
41870516886fef2e6c208d3e48332cc2c6c4b4d964cMax Krasnyansky	if (socktype == SOCK_DGRAM) {
4197715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		handler(sk);
42070516886fef2e6c208d3e48332cc2c6c4b4d964cMax Krasnyansky		return;
42170516886fef2e6c208d3e48332cc2c6c4b4d964cMax Krasnyansky	}
422c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
4239e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann	/* Enable deferred setup */
4249e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann	opt = defer_setup;
4259e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann
4269e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann	if (opt && setsockopt(sk, SOL_BLUETOOTH, BT_DEFER_SETUP,
4279e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann						&opt, sizeof(opt)) < 0) {
4289e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann		syslog(LOG_ERR, "Can't enable deferred setup : %s (%d)",
4299e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann							strerror(errno), errno);
4309e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann		goto error;
4319e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann	}
4329e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann
4337715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	/* Listen for connections */
4347715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	if (listen(sk, 10)) {
4357715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		syslog(LOG_ERR, "Can not listen on the socket: %s (%d)",
4367715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann							strerror(errno), errno);
4377715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		goto error;
438c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
439c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
440b4ccc4c8dec3b4421f5f644424103eb0274d446aMarcel Holtmann	/* Check for socket address */
441b4ccc4c8dec3b4421f5f644424103eb0274d446aMarcel Holtmann	memset(&addr, 0, sizeof(addr));
442b4ccc4c8dec3b4421f5f644424103eb0274d446aMarcel Holtmann	optlen = sizeof(addr);
443b4ccc4c8dec3b4421f5f644424103eb0274d446aMarcel Holtmann
444b4ccc4c8dec3b4421f5f644424103eb0274d446aMarcel Holtmann	if (getsockname(sk, (struct sockaddr *) &addr, &optlen) < 0) {
445b4ccc4c8dec3b4421f5f644424103eb0274d446aMarcel Holtmann		syslog(LOG_ERR, "Can't get socket name: %s (%d)",
446b4ccc4c8dec3b4421f5f644424103eb0274d446aMarcel Holtmann							strerror(errno), errno);
447b4ccc4c8dec3b4421f5f644424103eb0274d446aMarcel Holtmann		goto error;
448b4ccc4c8dec3b4421f5f644424103eb0274d446aMarcel Holtmann	}
449b4ccc4c8dec3b4421f5f644424103eb0274d446aMarcel Holtmann
450b4ccc4c8dec3b4421f5f644424103eb0274d446aMarcel Holtmann	psm = btohs(addr.l2_psm);
451c5eab04d6572dee0885a512bfd4ad7f7a33b57c0Gustavo F. Padovan	cid = btohs(addr.l2_cid);
452b4ccc4c8dec3b4421f5f644424103eb0274d446aMarcel Holtmann
4537715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	syslog(LOG_INFO, "Waiting for connection on psm %d ...", psm);
454c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
4559e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann	while (1) {
4567715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		memset(&addr, 0, sizeof(addr));
4577715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		optlen = sizeof(addr);
4587715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann
4597715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		nsk = accept(sk, (struct sockaddr *) &addr, &optlen);
4607715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		if (nsk < 0) {
4617715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann			syslog(LOG_ERR, "Accept failed: %s (%d)",
4627715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann							strerror(errno), errno);
4637715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann			goto error;
464c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		}
46514be8b04824df3f5a9bd7b713646a9120e2b2454Marcel Holtmann		if (fork()) {
466c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			/* Parent */
4677715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann			close(nsk);
468c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			continue;
469c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		}
470c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		/* Child */
4717715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		close(sk);
472c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
4737715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		/* Get current options */
474d198227a6d76b6fb6bff050e6fda9f2e4ffc4544Marcel Holtmann		memset(&opts, 0, sizeof(opts));
4757715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		optlen = sizeof(opts);
4767715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann
4777715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		if (getsockopt(nsk, SOL_L2CAP, L2CAP_OPTIONS, &opts, &optlen) < 0) {
4787715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann			syslog(LOG_ERR, "Can't get L2CAP options: %s (%d)",
4797715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann							strerror(errno), errno);
4809e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann			if (!defer_setup) {
4819e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann				close(nsk);
4829e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann				goto error;
4839e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann			}
484d198227a6d76b6fb6bff050e6fda9f2e4ffc4544Marcel Holtmann		}
485d198227a6d76b6fb6bff050e6fda9f2e4ffc4544Marcel Holtmann
4867715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		/* Get connection information */
487d198227a6d76b6fb6bff050e6fda9f2e4ffc4544Marcel Holtmann		memset(&conn, 0, sizeof(conn));
4887715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		optlen = sizeof(conn);
4897715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann
4907715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		if (getsockopt(nsk, SOL_L2CAP, L2CAP_CONNINFO, &conn, &optlen) < 0) {
4917715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann			syslog(LOG_ERR, "Can't get L2CAP connection information: %s (%d)",
4927715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann							strerror(errno), errno);
4939e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann			if (!defer_setup) {
4949e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann				close(nsk);
4959e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann				goto error;
4969e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann			}
497c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		}
498c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
4997715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		ba2str(&addr.l2_bdaddr, ba);
5007715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		syslog(LOG_INFO, "Connect from %s [imtu %d, omtu %d, flush_to %d, "
50154c95138efbc91165d50ee0e3e1fd906493bf68fMarcel Holtmann					"mode %d, handle %d, class 0x%02x%02x%02x]",
502d198227a6d76b6fb6bff050e6fda9f2e4ffc4544Marcel Holtmann			ba, opts.imtu, opts.omtu, opts.flush_to, opts.mode, conn.hci_handle,
503d198227a6d76b6fb6bff050e6fda9f2e4ffc4544Marcel Holtmann			conn.dev_class[2], conn.dev_class[1], conn.dev_class[0]);
504c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
50541e30382f9a83f41da700465de274266c60248b4Marcel Holtmann		omtu = (opts.omtu > buffer_size) ? buffer_size : opts.omtu;
50641e30382f9a83f41da700465de274266c60248b4Marcel Holtmann		imtu = (opts.imtu > buffer_size) ? buffer_size : opts.imtu;
50741e30382f9a83f41da700465de274266c60248b4Marcel Holtmann
5082199bc76c668f92e14fcaa4bc16fd4674f728bc1Marcel Holtmann#if 0
5095b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann		/* Enable SO_TIMESTAMP */
5105b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann		if (timestamp) {
5115b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann			int t = 1;
5125b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann
5139e198552165e2e473a9cb6792a70fe85fecbc987Marcel Holtmann			if (setsockopt(nsk, SOL_SOCKET, SO_TIMESTAMP, &t, sizeof(t)) < 0) {
5145b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann				syslog(LOG_ERR, "Can't enable SO_TIMESTAMP: %s (%d)",
5155b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann							strerror(errno), errno);
5165b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann				goto error;
5175b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann			}
5185b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann		}
5192199bc76c668f92e14fcaa4bc16fd4674f728bc1Marcel Holtmann#endif
5205b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann
52179cc4e4e2d74be3f1445203b1fdb844caa1cb009Max Krasnyansky		/* Enable SO_LINGER */
52279cc4e4e2d74be3f1445203b1fdb844caa1cb009Max Krasnyansky		if (linger) {
52379cc4e4e2d74be3f1445203b1fdb844caa1cb009Max Krasnyansky			struct linger l = { .l_onoff = 1, .l_linger = linger };
5247715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann
5257715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann			if (setsockopt(nsk, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) < 0) {
52614be8b04824df3f5a9bd7b713646a9120e2b2454Marcel Holtmann				syslog(LOG_ERR, "Can't enable SO_LINGER: %s (%d)",
5277715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann							strerror(errno), errno);
5287715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann				close(nsk);
5297715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann				goto error;
53079cc4e4e2d74be3f1445203b1fdb844caa1cb009Max Krasnyansky			}
53179cc4e4e2d74be3f1445203b1fdb844caa1cb009Max Krasnyansky		}
53279cc4e4e2d74be3f1445203b1fdb844caa1cb009Max Krasnyansky
5339e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann		/* Handle deferred setup */
5349e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann		if (defer_setup) {
5359e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann			syslog(LOG_INFO, "Waiting for %d seconds",
5369e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann							abs(defer_setup) - 1);
5379e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann			sleep(abs(defer_setup) - 1);
5389e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann
5399e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann			if (defer_setup < 0) {
5409e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann				close(nsk);
5419e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann				goto error;
5429e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann			}
5439e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann		}
5449e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann
5457715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		handler(nsk);
546c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
54714be8b04824df3f5a9bd7b713646a9120e2b2454Marcel Holtmann		syslog(LOG_INFO, "Disconnect: %m");
548c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		exit(0);
549c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
5507715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann
5517715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	return;
5527715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann
5537715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmannerror:
5547715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	close(sk);
5557715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	exit(1);
556c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky}
557c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
5587715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmannstatic void dump_mode(int sk)
559c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{
5607715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	socklen_t optlen;
5617715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	int opt, len;
562c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
56341e30382f9a83f41da700465de274266c60248b4Marcel Holtmann	if (data_size < 0)
56441e30382f9a83f41da700465de274266c60248b4Marcel Holtmann		data_size = imtu;
56541e30382f9a83f41da700465de274266c60248b4Marcel Holtmann
5669e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann	if (defer_setup) {
5679e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann		len = read(sk, buf, sizeof(buf));
5689e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann		if (len < 0)
5699e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann			syslog(LOG_ERR, "Initial read error: %s (%d)",
5709e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann						strerror(errno), errno);
5719e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann		else
5729e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann			syslog(LOG_INFO, "Initial bytes %d", len);
5739e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann	}
5749e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann
57570516886fef2e6c208d3e48332cc2c6c4b4d964cMax Krasnyansky	syslog(LOG_INFO, "Receiving ...");
576d774efc2f8cc21d599cacc933ea26e0d63e91365Max Krasnyansky	while (1) {
577d774efc2f8cc21d599cacc933ea26e0d63e91365Max Krasnyansky		fd_set rset;
5783c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmann
579d774efc2f8cc21d599cacc933ea26e0d63e91365Max Krasnyansky		FD_ZERO(&rset);
5807715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		FD_SET(sk, &rset);
58114be8b04824df3f5a9bd7b713646a9120e2b2454Marcel Holtmann
5827715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		if (select(sk + 1, &rset, NULL, NULL, NULL) < 0)
583d774efc2f8cc21d599cacc933ea26e0d63e91365Max Krasnyansky			return;
584d774efc2f8cc21d599cacc933ea26e0d63e91365Max Krasnyansky
5857715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		if (!FD_ISSET(sk, &rset))
586d774efc2f8cc21d599cacc933ea26e0d63e91365Max Krasnyansky			continue;
587d774efc2f8cc21d599cacc933ea26e0d63e91365Max Krasnyansky
5887715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		len = read(sk, buf, data_size);
589f6557046863c041920180d232c8f0a63bb2faf3cMarcel Holtmann		if (len <= 0) {
590f6557046863c041920180d232c8f0a63bb2faf3cMarcel Holtmann			if (len < 0) {
591f6557046863c041920180d232c8f0a63bb2faf3cMarcel Holtmann				if (reliable && (errno == ECOMM)) {
5927715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann					syslog(LOG_INFO, "L2CAP Error ECOMM - clearing error and continuing.");
5937715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann					optlen = sizeof(opt);
5947715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann					if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &opt, &optlen) < 0) {
5957715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann						syslog(LOG_ERR, "Couldn't getsockopt(SO_ERROR): %s (%d)",
5963c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmann							strerror(errno), errno);
597f6557046863c041920180d232c8f0a63bb2faf3cMarcel Holtmann						return;
598f6557046863c041920180d232c8f0a63bb2faf3cMarcel Holtmann					}
599f6557046863c041920180d232c8f0a63bb2faf3cMarcel Holtmann					continue;
600f6557046863c041920180d232c8f0a63bb2faf3cMarcel Holtmann				} else {
6017715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann					syslog(LOG_ERR, "Read error: %s(%d)",
6027715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann							strerror(errno), errno);
603f6557046863c041920180d232c8f0a63bb2faf3cMarcel Holtmann				}
604f6557046863c041920180d232c8f0a63bb2faf3cMarcel Holtmann			}
605d774efc2f8cc21d599cacc933ea26e0d63e91365Max Krasnyansky			return;
606f6557046863c041920180d232c8f0a63bb2faf3cMarcel Holtmann		}
607d774efc2f8cc21d599cacc933ea26e0d63e91365Max Krasnyansky
6087715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann		syslog(LOG_INFO, "Recevied %d bytes", len);
6091f422e5f2b343d35a8c77ce4be16f74b2819b2bfMarcel Holtmann		hexdump(buf, len);
610d774efc2f8cc21d599cacc933ea26e0d63e91365Max Krasnyansky	}
611c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky}
612c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
6137715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmannstatic void recv_mode(int sk)
614c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{
61577f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann	struct timeval tv_beg, tv_end, tv_diff;
61677f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann	struct pollfd p;
6172199bc76c668f92e14fcaa4bc16fd4674f728bc1Marcel Holtmann	char ts[30];
618c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	long total;
619c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	uint32_t seq;
6207715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	socklen_t optlen;
6219e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann	int opt, len;
6229e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann
62341e30382f9a83f41da700465de274266c60248b4Marcel Holtmann	if (data_size < 0)
62441e30382f9a83f41da700465de274266c60248b4Marcel Holtmann		data_size = imtu;
62541e30382f9a83f41da700465de274266c60248b4Marcel Holtmann
6269e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann	if (defer_setup) {
6279e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann		len = read(sk, buf, sizeof(buf));
6289e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann		if (len < 0)
6299e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann			syslog(LOG_ERR, "Initial read error: %s (%d)",
6309e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann						strerror(errno), errno);
6319e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann		else
6329e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann			syslog(LOG_INFO, "Initial bytes %d", len);
6339e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann	}
634c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
6352199bc76c668f92e14fcaa4bc16fd4674f728bc1Marcel Holtmann	syslog(LOG_INFO, "Receiving ...");
6362199bc76c668f92e14fcaa4bc16fd4674f728bc1Marcel Holtmann
6372199bc76c668f92e14fcaa4bc16fd4674f728bc1Marcel Holtmann	memset(ts, 0, sizeof(ts));
638c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
63977f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann	p.fd = sk;
64077f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann	p.events = POLLIN | POLLERR | POLLHUP;
64177f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann
642c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	seq = 0;
643c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	while (1) {
64414be8b04824df3f5a9bd7b713646a9120e2b2454Marcel Holtmann		gettimeofday(&tv_beg, NULL);
645c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		total = 0;
646c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		while (total < data_size) {
647c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			uint32_t sq;
648c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			uint16_t l;
6499e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann			int i;
65077f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann
65177f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann			p.revents = 0;
65277f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann			if (poll(&p, 1, -1) <= 0)
65377f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann				return;
65477f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann
65577f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann			if (p.revents & (POLLERR | POLLHUP))
65677f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann				return;
65777f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann
65877f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann			len = recv(sk, buf, data_size, 0);
65977f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann			if (len < 0) {
66077f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann				if (reliable && (errno == ECOMM)) {
66177f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann					syslog(LOG_INFO, "L2CAP Error ECOMM - clearing error and continuing.\n");
66277f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann					optlen = sizeof(opt);
66377f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann					if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &opt, &optlen) < 0) {
66477f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann						syslog(LOG_ERR, "Couldn't getsockopt(SO_ERROR): %s (%d)",
6653c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmann							strerror(errno), errno);
66677f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann						return;
667f6557046863c041920180d232c8f0a63bb2faf3cMarcel Holtmann					}
66877f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann					continue;
66977f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann				} else {
67077f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann					syslog(LOG_ERR, "Read failed: %s (%d)",
67177f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann						strerror(errno), errno);
672f6557046863c041920180d232c8f0a63bb2faf3cMarcel Holtmann				}
673c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			}
674c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
67577f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann			if (len < 6)
67677f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann				break;
67777f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann
6782199bc76c668f92e14fcaa4bc16fd4674f728bc1Marcel Holtmann			if (timestamp) {
6792199bc76c668f92e14fcaa4bc16fd4674f728bc1Marcel Holtmann				struct timeval tv;
6802199bc76c668f92e14fcaa4bc16fd4674f728bc1Marcel Holtmann
6812199bc76c668f92e14fcaa4bc16fd4674f728bc1Marcel Holtmann				if (ioctl(sk, SIOCGSTAMP, &tv) < 0) {
6822199bc76c668f92e14fcaa4bc16fd4674f728bc1Marcel Holtmann					timestamp = 0;
6832199bc76c668f92e14fcaa4bc16fd4674f728bc1Marcel Holtmann					memset(ts, 0, sizeof(ts));
6842199bc76c668f92e14fcaa4bc16fd4674f728bc1Marcel Holtmann				} else {
6852199bc76c668f92e14fcaa4bc16fd4674f728bc1Marcel Holtmann					sprintf(ts, "[%ld.%ld] ",
6862199bc76c668f92e14fcaa4bc16fd4674f728bc1Marcel Holtmann							tv.tv_sec, tv.tv_usec);
6872199bc76c668f92e14fcaa4bc16fd4674f728bc1Marcel Holtmann				}
6882199bc76c668f92e14fcaa4bc16fd4674f728bc1Marcel Holtmann			}
6892199bc76c668f92e14fcaa4bc16fd4674f728bc1Marcel Holtmann
690c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			/* Check sequence */
69114be8b04824df3f5a9bd7b713646a9120e2b2454Marcel Holtmann			sq = btohl(*(uint32_t *) buf);
692c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			if (seq != sq) {
693c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky				syslog(LOG_INFO, "seq missmatch: %d -> %d", seq, sq);
694c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky				seq = sq;
695c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			}
696c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			seq++;
6973c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmann
698c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			/* Check length */
69914be8b04824df3f5a9bd7b713646a9120e2b2454Marcel Holtmann			l = btohs(*(uint16_t *) (buf + 4));
70077f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann			if (len != l) {
70177f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann				syslog(LOG_INFO, "size missmatch: %d -> %d", len, l);
702c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky				continue;
703c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			}
7043c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmann
7053c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmann			/* Verify data */
70677f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann			for (i = 6; i < len; i++) {
707c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky				if (buf[i] != 0x7f)
708c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky					syslog(LOG_INFO, "data missmatch: byte %d 0x%2.2x", i, buf[i]);
709c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			}
710c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
71177f2ea7f02d5981deab6ec22d05570e06d46836eMarcel Holtmann			total += len;
712c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		}
71314be8b04824df3f5a9bd7b713646a9120e2b2454Marcel Holtmann		gettimeofday(&tv_end, NULL);
714c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
71514be8b04824df3f5a9bd7b713646a9120e2b2454Marcel Holtmann		timersub(&tv_end, &tv_beg, &tv_diff);
716c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
7172199bc76c668f92e14fcaa4bc16fd4674f728bc1Marcel Holtmann		syslog(LOG_INFO,"%s%ld bytes in %.2f sec, %.2f kB/s", ts, total,
7183c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmann			tv2fl(tv_diff), (float)(total / tv2fl(tv_diff) ) / 1024.0);
719c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
720c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky}
721c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
722da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmannstatic void do_send(int sk)
723c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{
724c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	uint32_t seq;
725f213783e7d4068268187310251fedc546b9f212fMarcel Holtmann	int i, fd, len, buflen, size, sent;
726c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
727893ddcab14bb2b5309ba0f181a5a9941a2d28661Max Krasnyansky	syslog(LOG_INFO, "Sending ...");
728c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
72941e30382f9a83f41da700465de274266c60248b4Marcel Holtmann	if (data_size < 0)
73041e30382f9a83f41da700465de274266c60248b4Marcel Holtmann		data_size = omtu;
73141e30382f9a83f41da700465de274266c60248b4Marcel Holtmann
732da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann	if (filename) {
733da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann		fd = open(filename, O_RDONLY);
734da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann		if (fd < 0) {
735da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann			syslog(LOG_ERR, "Open failed: %s (%d)",
736da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann							strerror(errno), errno);
737da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann			exit(1);
738da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann		}
739f213783e7d4068268187310251fedc546b9f212fMarcel Holtmann
740f213783e7d4068268187310251fedc546b9f212fMarcel Holtmann		sent = 0;
741f213783e7d4068268187310251fedc546b9f212fMarcel Holtmann		size = read(fd, buf, data_size);
742f213783e7d4068268187310251fedc546b9f212fMarcel Holtmann		while (size > 0) {
743f213783e7d4068268187310251fedc546b9f212fMarcel Holtmann			buflen = (size > omtu) ? omtu : size;
744f213783e7d4068268187310251fedc546b9f212fMarcel Holtmann
745f213783e7d4068268187310251fedc546b9f212fMarcel Holtmann			len = send(sk, buf + sent, buflen, 0);
746f213783e7d4068268187310251fedc546b9f212fMarcel Holtmann
747f213783e7d4068268187310251fedc546b9f212fMarcel Holtmann			sent += len;
748f213783e7d4068268187310251fedc546b9f212fMarcel Holtmann			size -= len;
749f213783e7d4068268187310251fedc546b9f212fMarcel Holtmann		}
750da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann		return;
751da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann	} else {
752da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann		for (i = 6; i < data_size; i++)
753da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann			buf[i] = 0x7f;
754da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann	}
755c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
756c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	seq = 0;
757893ddcab14bb2b5309ba0f181a5a9941a2d28661Max Krasnyansky	while ((num_frames == -1) || (num_frames-- > 0)) {
758b2d7fd8c8e1c7948169726639675d462bd83e50eMarcel Holtmann		*(uint32_t *) buf = htobl(seq);
75914be8b04824df3f5a9bd7b713646a9120e2b2454Marcel Holtmann		*(uint16_t *) (buf + 4) = htobs(data_size);
760b2d7fd8c8e1c7948169726639675d462bd83e50eMarcel Holtmann		seq++;
7613c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmann
762f213783e7d4068268187310251fedc546b9f212fMarcel Holtmann		sent = 0;
763f213783e7d4068268187310251fedc546b9f212fMarcel Holtmann		size = data_size;
764f213783e7d4068268187310251fedc546b9f212fMarcel Holtmann		while (size > 0) {
765f213783e7d4068268187310251fedc546b9f212fMarcel Holtmann			buflen = (size > omtu) ? omtu : size;
766f213783e7d4068268187310251fedc546b9f212fMarcel Holtmann
767f213783e7d4068268187310251fedc546b9f212fMarcel Holtmann			len = send(sk, buf, buflen, 0);
768f213783e7d4068268187310251fedc546b9f212fMarcel Holtmann			if (len < 0 || len != buflen) {
769f213783e7d4068268187310251fedc546b9f212fMarcel Holtmann				syslog(LOG_ERR, "Send failed: %s (%d)",
770da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann							strerror(errno), errno);
771f213783e7d4068268187310251fedc546b9f212fMarcel Holtmann				exit(1);
772f213783e7d4068268187310251fedc546b9f212fMarcel Holtmann			}
773f213783e7d4068268187310251fedc546b9f212fMarcel Holtmann
774f213783e7d4068268187310251fedc546b9f212fMarcel Holtmann			sent += len;
775f213783e7d4068268187310251fedc546b9f212fMarcel Holtmann			size -= len;
776c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		}
777b357f1d3900bca5575e88fcfc160945c6088608cMarcel Holtmann
778e6673071212596bc54fb5bffff72b0c3a8275071Marcel Holtmann		if (num_frames && delay && count && !(seq % count))
779b357f1d3900bca5575e88fcfc160945c6088608cMarcel Holtmann			usleep(delay);
780c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
781da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann}
782da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann
783da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmannstatic void send_mode(int sk)
784da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann{
785da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann	do_send(sk);
786893ddcab14bb2b5309ba0f181a5a9941a2d28661Max Krasnyansky
787893ddcab14bb2b5309ba0f181a5a9941a2d28661Max Krasnyansky	syslog(LOG_INFO, "Closing channel ...");
7887715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	if (shutdown(sk, SHUT_RDWR) < 0)
78914be8b04824df3f5a9bd7b713646a9120e2b2454Marcel Holtmann		syslog(LOG_INFO, "Close failed: %m");
790893ddcab14bb2b5309ba0f181a5a9941a2d28661Max Krasnyansky	else
791893ddcab14bb2b5309ba0f181a5a9941a2d28661Max Krasnyansky		syslog(LOG_INFO, "Done");
792c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky}
793c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
7947715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmannstatic void senddump_mode(int sk)
7951f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann{
796da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann	do_send(sk);
7971f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann
7987715ad4f56e82c9eb4cf75020b1f3039d06ce115Marcel Holtmann	dump_mode(sk);
7991f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann}
8001f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann
801a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovanstatic void send_and_recv_mode(int sk)
802a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan{
803a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan	int flags;
804a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan
805a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan	if ((flags = fcntl(sk, F_GETFL, 0)) < 0)
806a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan		flags = 0;
807a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan	fcntl(sk, F_SETFL, flags | O_NONBLOCK);
808a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan
809a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan	/* fork for duplex channel */
810a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan	if (fork())
811a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan		send_mode(sk);
812a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan	else
813a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan		recv_mode(sk);
814a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan	return;
815a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan}
816a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan
8173c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmannstatic void reconnect_mode(char *svr)
818c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{
81939654da8de5f5d3f9888cb2d4d576993414642ecMarcel Holtmann	while (1) {
82039654da8de5f5d3f9888cb2d4d576993414642ecMarcel Holtmann		int sk = do_connect(svr);
82139654da8de5f5d3f9888cb2d4d576993414642ecMarcel Holtmann		close(sk);
822c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
823c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky}
824c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
8253c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmannstatic void connect_mode(char *svr)
826c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{
82772a919e9b1ae03645a63e27dfa6f4190ade6c924Marcel Holtmann	struct pollfd p;
82839654da8de5f5d3f9888cb2d4d576993414642ecMarcel Holtmann	int sk;
82939654da8de5f5d3f9888cb2d4d576993414642ecMarcel Holtmann
83039654da8de5f5d3f9888cb2d4d576993414642ecMarcel Holtmann	if ((sk = do_connect(svr)) < 0)
831c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		exit(1);
83239654da8de5f5d3f9888cb2d4d576993414642ecMarcel Holtmann
83372a919e9b1ae03645a63e27dfa6f4190ade6c924Marcel Holtmann	p.fd = sk;
83472a919e9b1ae03645a63e27dfa6f4190ade6c924Marcel Holtmann	p.events = POLLERR | POLLHUP;
83572a919e9b1ae03645a63e27dfa6f4190ade6c924Marcel Holtmann
83672a919e9b1ae03645a63e27dfa6f4190ade6c924Marcel Holtmann	while (1) {
83772a919e9b1ae03645a63e27dfa6f4190ade6c924Marcel Holtmann		p.revents = 0;
83835e9349ffc53950c4b78fba9537a50cdb6e5fd7aMarcel Holtmann		if (poll(&p, 1, 500))
83972a919e9b1ae03645a63e27dfa6f4190ade6c924Marcel Holtmann			break;
84072a919e9b1ae03645a63e27dfa6f4190ade6c924Marcel Holtmann	}
84172a919e9b1ae03645a63e27dfa6f4190ade6c924Marcel Holtmann
84272a919e9b1ae03645a63e27dfa6f4190ade6c924Marcel Holtmann	syslog(LOG_INFO, "Disconnected");
84372a919e9b1ae03645a63e27dfa6f4190ade6c924Marcel Holtmann
84472a919e9b1ae03645a63e27dfa6f4190ade6c924Marcel Holtmann	close(sk);
845c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky}
846c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
8470effff5f4fe0fac9a986bb01dc547a99772d1bfaMarcel Holtmannstatic void multi_connect_mode(int argc, char *argv[])
848c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{
8490effff5f4fe0fac9a986bb01dc547a99772d1bfaMarcel Holtmann	int i, n, sk;
8500effff5f4fe0fac9a986bb01dc547a99772d1bfaMarcel Holtmann
85189d41e2e6c81aa5c30f2fa699cc4654eb174627cMax Krasnyansky	while (1) {
8520effff5f4fe0fac9a986bb01dc547a99772d1bfaMarcel Holtmann		for (n = 0; n < argc; n++) {
8530effff5f4fe0fac9a986bb01dc547a99772d1bfaMarcel Holtmann			for (i = 0; i < count; i++) {
8540effff5f4fe0fac9a986bb01dc547a99772d1bfaMarcel Holtmann				if (fork())
8550effff5f4fe0fac9a986bb01dc547a99772d1bfaMarcel Holtmann					continue;
8560effff5f4fe0fac9a986bb01dc547a99772d1bfaMarcel Holtmann
8570effff5f4fe0fac9a986bb01dc547a99772d1bfaMarcel Holtmann				/* Child */
8580effff5f4fe0fac9a986bb01dc547a99772d1bfaMarcel Holtmann				sk = do_connect(argv[n]);
8590effff5f4fe0fac9a986bb01dc547a99772d1bfaMarcel Holtmann				usleep(500);
8600effff5f4fe0fac9a986bb01dc547a99772d1bfaMarcel Holtmann				close(sk);
8610effff5f4fe0fac9a986bb01dc547a99772d1bfaMarcel Holtmann				exit(0);
8620effff5f4fe0fac9a986bb01dc547a99772d1bfaMarcel Holtmann			}
863c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		}
8640effff5f4fe0fac9a986bb01dc547a99772d1bfaMarcel Holtmann		sleep(4);
865c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
866c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky}
867c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
868329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmannstatic void info_request(char *svr)
869329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann{
870329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	unsigned char buf[48];
871329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	l2cap_cmd_hdr *cmd = (l2cap_cmd_hdr *) buf;
872329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	l2cap_info_req *req = (l2cap_info_req *) (buf + L2CAP_CMD_HDR_SIZE);
873329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	l2cap_info_rsp *rsp = (l2cap_info_rsp *) (buf + L2CAP_CMD_HDR_SIZE);
874329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	uint16_t mtu;
8756f220b305be27d1aea0cdd24b5a615c6b91e9cbfMarcel Holtmann	uint32_t channels, mask = 0x0000;
876329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	struct sockaddr_l2 addr;
877329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	int sk, err;
878329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann
879329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	sk = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_L2CAP);
880329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	if (sk < 0) {
881329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		perror("Can't create socket");
882329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		return;
883329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	}
884329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann
885329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	memset(&addr, 0, sizeof(addr));
886329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	addr.l2_family = AF_BLUETOOTH;
887329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	bacpy(&addr.l2_bdaddr, &bdaddr);
888329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann
889329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
890329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		perror("Can't bind socket");
891329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		goto failed;
892329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	}
893329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann
894329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	memset(&addr, 0, sizeof(addr));
895329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	addr.l2_family = AF_BLUETOOTH;
896329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	str2ba(svr, &addr.l2_bdaddr);
897329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann
898329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0 ) {
899329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		perror("Can't connect socket");
900329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		goto failed;
901329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	}
902329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann
903329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	memset(buf, 0, sizeof(buf));
904329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	cmd->code  = L2CAP_INFO_REQ;
90549d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann	cmd->ident = 141;
906329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	cmd->len   = htobs(2);
907329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	req->type  = htobs(0x0001);
908329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann
909329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	if (send(sk, buf, L2CAP_CMD_HDR_SIZE + L2CAP_INFO_REQ_SIZE, 0) < 0) {
910329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		perror("Can't send info request");
911329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		goto failed;
912329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	}
913329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann
914329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	err = recv(sk, buf, L2CAP_CMD_HDR_SIZE + L2CAP_INFO_RSP_SIZE + 2, 0);
915329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	if (err < 0) {
916329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		perror("Can't receive info response");
917329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		goto failed;
918329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	}
919329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann
920329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	switch (btohs(rsp->result)) {
921329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	case 0x0000:
9226432bf4db31b26943889958263e61c6255f0f15bMarcel Holtmann		memcpy(&mtu, rsp->data, sizeof(mtu));
9236432bf4db31b26943889958263e61c6255f0f15bMarcel Holtmann		printf("Connectionless MTU size is %d\n", btohs(mtu));
924329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		break;
925329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	case 0x0001:
926329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		printf("Connectionless MTU is not supported\n");
927329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		break;
928329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	}
929329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann
930329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	memset(buf, 0, sizeof(buf));
931329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	cmd->code  = L2CAP_INFO_REQ;
93249d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann	cmd->ident = 142;
933329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	cmd->len   = htobs(2);
934329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	req->type  = htobs(0x0002);
935329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann
936329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	if (send(sk, buf, L2CAP_CMD_HDR_SIZE + L2CAP_INFO_REQ_SIZE, 0) < 0) {
937329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		perror("Can't send info request");
938329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		goto failed;
939329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	}
940329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann
941329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	err = recv(sk, buf, L2CAP_CMD_HDR_SIZE + L2CAP_INFO_RSP_SIZE + 4, 0);
942329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	if (err < 0) {
943329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		perror("Can't receive info response");
944329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		goto failed;
945329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	}
946329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann
947329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	switch (btohs(rsp->result)) {
948329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	case 0x0000:
9496432bf4db31b26943889958263e61c6255f0f15bMarcel Holtmann		memcpy(&mask, rsp->data, sizeof(mask));
9506432bf4db31b26943889958263e61c6255f0f15bMarcel Holtmann		printf("Extended feature mask is 0x%04x\n", btohl(mask));
951329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		if (mask & 0x01)
952329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann			printf("  Flow control mode\n");
953329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		if (mask & 0x02)
954329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann			printf("  Retransmission mode\n");
955329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		if (mask & 0x04)
956329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann			printf("  Bi-directional QoS\n");
9573fb63ab3bf9e6c1d474d3779992feb1f464cef42Gustavo F. Padovan		if (mask & 0x08)
9583fb63ab3bf9e6c1d474d3779992feb1f464cef42Gustavo F. Padovan			printf("  Enhanced Retransmission mode\n");
9593fb63ab3bf9e6c1d474d3779992feb1f464cef42Gustavo F. Padovan		if (mask & 0x10)
9603fb63ab3bf9e6c1d474d3779992feb1f464cef42Gustavo F. Padovan			printf("  Streaming mode\n");
9613fb63ab3bf9e6c1d474d3779992feb1f464cef42Gustavo F. Padovan		if (mask & 0x20)
9623fb63ab3bf9e6c1d474d3779992feb1f464cef42Gustavo F. Padovan			printf("  FCS Option\n");
9639fca3da026d6af49ec93b98ec3479b21b58da83dMarcel Holtmann		if (mask & 0x40)
9649fca3da026d6af49ec93b98ec3479b21b58da83dMarcel Holtmann			printf("  Extended Flow Specification\n");
9659fca3da026d6af49ec93b98ec3479b21b58da83dMarcel Holtmann		if (mask & 0x80)
9669fca3da026d6af49ec93b98ec3479b21b58da83dMarcel Holtmann			printf("  Fixed Channels\n");
9679fca3da026d6af49ec93b98ec3479b21b58da83dMarcel Holtmann		if (mask & 0x0100)
9689fca3da026d6af49ec93b98ec3479b21b58da83dMarcel Holtmann			printf("  Extended Window Size\n");
9699fca3da026d6af49ec93b98ec3479b21b58da83dMarcel Holtmann		if (mask & 0x0200)
9709fca3da026d6af49ec93b98ec3479b21b58da83dMarcel Holtmann			printf("  Unicast Connectionless Data Reception\n");
971329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		break;
972329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	case 0x0001:
973329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		printf("Extended feature mask is not supported\n");
974329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		break;
975329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	}
976329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann
97749d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann	if (!(mask & 0x80))
97849d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann		goto failed;
97949d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann
98049d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann	memset(buf, 0, sizeof(buf));
98149d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann	cmd->code  = L2CAP_INFO_REQ;
98249d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann	cmd->ident = 143;
98349d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann	cmd->len   = htobs(2);
98449d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann	req->type  = htobs(0x0003);
98549d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann
98649d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann	if (send(sk, buf, L2CAP_CMD_HDR_SIZE + L2CAP_INFO_REQ_SIZE, 0) < 0) {
98749d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann		perror("Can't send info request");
98849d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann		goto failed;
98949d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann	}
99049d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann
99149d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann	err = recv(sk, buf, L2CAP_CMD_HDR_SIZE + L2CAP_INFO_RSP_SIZE + 8, 0);
99249d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann	if (err < 0) {
99349d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann		perror("Can't receive info response");
99449d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann		goto failed;
99549d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann	}
99649d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann
99749d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann	switch (btohs(rsp->result)) {
99849d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann	case 0x0000:
9996432bf4db31b26943889958263e61c6255f0f15bMarcel Holtmann		memcpy(&channels, rsp->data, sizeof(channels));
10006432bf4db31b26943889958263e61c6255f0f15bMarcel Holtmann		printf("Fixed channels list is 0x%04x\n", btohl(channels));
1001218672a1b1928266933d3cdabe5a942e34c7cd9cLuiz Augusto von Dentz		break;
100249d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann	case 0x0001:
100349d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann		printf("Fixed channels list is not supported\n");
100449d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann		break;
100549d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann	}
100649d0b0513690beec7038ac118ab95988961d7d2dMarcel Holtmann
1007329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmannfailed:
1008329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann	close(sk);
1009329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann}
1010329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann
101122fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmannstatic void do_pairing(char *svr)
101222fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann{
101322fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann	struct sockaddr_l2 addr;
101422fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann	int sk, opt;
101522fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann
101622fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann	sk = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_L2CAP);
101722fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann	if (sk < 0) {
101822fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann		perror("Can't create socket");
101922fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann		return;
102022fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann	}
102122fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann
102222fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann	memset(&addr, 0, sizeof(addr));
102322fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann	addr.l2_family = AF_BLUETOOTH;
102422fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann	bacpy(&addr.l2_bdaddr, &bdaddr);
102522fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann
102622fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann	if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
102722fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann		perror("Can't bind socket");
102822fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann		goto failed;
102922fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann	}
103022fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann
10317b5212174affc3834d32b68b07370810f9592cb1Marcel Holtmann	if (secure)
10327b5212174affc3834d32b68b07370810f9592cb1Marcel Holtmann		opt = L2CAP_LM_SECURE;
10337b5212174affc3834d32b68b07370810f9592cb1Marcel Holtmann	else
10347b5212174affc3834d32b68b07370810f9592cb1Marcel Holtmann		opt = L2CAP_LM_ENCRYPT;
103522fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann
103622fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann	if (setsockopt(sk, SOL_L2CAP, L2CAP_LM, &opt, sizeof(opt)) < 0) {
103722fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann		perror("Can't set link mode");
103822fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann		goto failed;
103922fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann	}
104022fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann
104122fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann	memset(&addr, 0, sizeof(addr));
104222fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann	addr.l2_family = AF_BLUETOOTH;
104322fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann	str2ba(svr, &addr.l2_bdaddr);
104422fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann
104522fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann	if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0 ) {
104622fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann		perror("Can't connect socket");
104722fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann		goto failed;
104822fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann	}
104922fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann
105022fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann	printf("Pairing successful\n");
105122fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann
105222fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmannfailed:
105322fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann	close(sk);
105422fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann}
105522fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann
10563c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmannstatic void usage(void)
1057c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{
1058c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	printf("l2test - L2CAP testing\n"
1059c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		"Usage:\n");
1060aba9dc216df7ddacbaa10d9e25c7aba05ab28afbMax Krasnyansky	printf("\tl2test <mode> [options] [bdaddr]\n");
1061c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	printf("Modes:\n"
106204c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky		"\t-r listen and receive\n"
106304c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky		"\t-w listen and send\n"
106496209b933e9b3b9c93701e15e4a9590f859cc8c6Stephen Crane		"\t-d listen and dump incoming data\n"
10651f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann		"\t-x listen, then send, then dump incoming data\n"
1066a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan		"\t-t listen, then send and receive at the same time\n"
1067a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan		"\t-q connect, then send and receive at the same time\n"
106804c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky		"\t-s connect and send\n"
106904c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky		"\t-u connect and receive\n"
107004c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky		"\t-n connect and be silent\n"
10711f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann		"\t-y connect, then send, then dump incoming data\n"
107204c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky		"\t-c connect, disconnect, connect, ...\n"
1073329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		"\t-m multiple connects\n"
107422fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann		"\t-p trigger dedicated bonding\n"
1075329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		"\t-z information request\n");
107604c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky
1077aba9dc216df7ddacbaa10d9e25c7aba05ab28afbMax Krasnyansky	printf("Options:\n"
1078c5eab04d6572dee0885a512bfd4ad7f7a33b57c0Gustavo F. Padovan		"\t[-b bytes] [-i device] [-P psm] [-J cid]\n"
10793c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmann		"\t[-I imtu] [-O omtu]\n"
108079cc4e4e2d74be3f1445203b1fdb844caa1cb009Max Krasnyansky		"\t[-L seconds] enable SO_LINGER\n"
108111e2f9bf390d828b45e26a8a1c00f503efc342c4Marcel Holtmann		"\t[-W seconds] enable deferred setup\n"
1082da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann		"\t[-B filename] use data packets from file\n"
1083da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann		"\t[-N num] send num frames (default = infinite)\n"
1084b357f1d3900bca5575e88fcfc160945c6088608cMarcel Holtmann		"\t[-C num] send num frames before delay (default = 1)\n"
1085e6673071212596bc54fb5bffff72b0c3a8275071Marcel Holtmann		"\t[-D milliseconds] delay after sending num frames (default = 0)\n"
10868e34afe9cc4dada1c34126a9723f76d4a6705707Marcel Holtmann		"\t[-X mode] select retransmission/flow-control mode\n"
108711e2f9bf390d828b45e26a8a1c00f503efc342c4Marcel Holtmann		"\t[-F fcs] use CRC16 check (default = 1)\n"
1088449367e8dab5fadc49f97c72a6837120e889cdc4Gustavo F. Padovan		"\t[-Q num] Max Transmit value (default = 3)\n"
1089449367e8dab5fadc49f97c72a6837120e889cdc4Gustavo F. Padovan		"\t[-Z size] Transmission Window size (default = 63)\n"
1090f6557046863c041920180d232c8f0a63bb2faf3cMarcel Holtmann		"\t[-R] reliable mode\n"
10916ba87383b2047862686d04db85a4b7e0d1f243aeMarcel Holtmann		"\t[-G] use connectionless channel (datagram)\n"
1092c5c6abdf4c2cedfb8ed7977d34222927076698f4Gustavo F. Padovan		"\t[-U] use sock stream\n"
109317990fc4315e60ba6a3ffd59ea8781f2c1647cfcStephen Crane		"\t[-A] request authentication\n"
1094aba9dc216df7ddacbaa10d9e25c7aba05ab28afbMax Krasnyansky		"\t[-E] request encryption\n"
109552d36be0bf2610739f04786d18df80db23e9cf6bMarcel Holtmann		"\t[-S] secure connection\n"
10965b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann		"\t[-M] become master\n"
10975b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann		"\t[-T] enable timestamps\n");
1098c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky}
1099c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
1100da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmannint main(int argc, char *argv[])
1101c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky{
1102c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	struct sigaction sa;
1103917543004017da0f09304844c578b59ca4a1802bMarcel Holtmann	int opt, sk, mode = RECV, need_addr = 0;
110452d36be0bf2610739f04786d18df80db23e9cf6bMarcel Holtmann
110552d36be0bf2610739f04786d18df80db23e9cf6bMarcel Holtmann	bacpy(&bdaddr, BDADDR_ANY);
110652d36be0bf2610739f04786d18df80db23e9cf6bMarcel Holtmann
1107c5eab04d6572dee0885a512bfd4ad7f7a33b57c0Gustavo F. Padovan	while ((opt=getopt(argc,argv,"rdscuwmntqxyzpb:i:P:I:O:J:B:N:L:W:C:D:X:F:Q:Z:RUGAESMT")) != EOF) {
1108c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		switch(opt) {
1109c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		case 'r':
1110c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			mode = RECV;
1111c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			break;
11123c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmann
1113c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		case 's':
1114c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			mode = SEND;
111504c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky			need_addr = 1;
111604c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky			break;
111704c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky
111804c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky		case 'w':
111904c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky			mode = LSEND;
112004c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky			break;
112104c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky
112204c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky		case 'u':
112304c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky			mode = CRECV;
112404c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky			need_addr = 1;
1125c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			break;
1126c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
1127c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		case 'd':
1128c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			mode = DUMP;
1129c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			break;
1130c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
1131c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		case 'c':
1132c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			mode = RECONNECT;
113304c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky			need_addr = 1;
1134c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			break;
1135c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
1136c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		case 'n':
1137c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			mode = CONNECT;
113804c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky			need_addr = 1;
1139c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			break;
1140c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
1141c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		case 'm':
1142c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			mode = MULTY;
114304c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky			need_addr = 1;
1144c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			break;
1145c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
1146a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan		case 't':
1147a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan			mode = LSENDRECV;
1148a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan			break;
1149a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan
1150a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan		case 'q':
1151a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan			mode = CSENDRECV;
1152a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan			need_addr = 1;
1153a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan			break;
1154a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan
11551f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann		case 'x':
11561f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann			mode = LSENDDUMP;
11571f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann			break;
11581f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann
11591f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann		case 'y':
11601f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann			mode = SENDDUMP;
11611f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann			break;
11621f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann
1163329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		case 'z':
1164329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann			mode = INFOREQ;
1165329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann			need_addr = 1;
1166329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann			break;
1167329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann
116822fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann		case 'p':
116922fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann			mode = PAIRING;
117022fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann			need_addr = 1;
117122fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann			break;
117222fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann
1173329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		case 'b':
1174329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann			data_size = atoi(optarg);
1175329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann			break;
1176329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann
117752d36be0bf2610739f04786d18df80db23e9cf6bMarcel Holtmann		case 'i':
117852d36be0bf2610739f04786d18df80db23e9cf6bMarcel Holtmann			if (!strncasecmp(optarg, "hci", 3))
117952d36be0bf2610739f04786d18df80db23e9cf6bMarcel Holtmann				hci_devba(atoi(optarg + 3), &bdaddr);
118052d36be0bf2610739f04786d18df80db23e9cf6bMarcel Holtmann			else
118152d36be0bf2610739f04786d18df80db23e9cf6bMarcel Holtmann				str2ba(optarg, &bdaddr);
1182c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			break;
1183c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
1184c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		case 'P':
1185c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			psm = atoi(optarg);
1186c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			break;
1187c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
1188c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		case 'I':
1189c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			imtu = atoi(optarg);
1190c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			break;
1191c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
1192c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		case 'O':
1193c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			omtu = atoi(optarg);
1194c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			break;
1195c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
119679cc4e4e2d74be3f1445203b1fdb844caa1cb009Max Krasnyansky		case 'L':
119779cc4e4e2d74be3f1445203b1fdb844caa1cb009Max Krasnyansky			linger = atoi(optarg);
119879cc4e4e2d74be3f1445203b1fdb844caa1cb009Max Krasnyansky			break;
119979cc4e4e2d74be3f1445203b1fdb844caa1cb009Max Krasnyansky
120011e2f9bf390d828b45e26a8a1c00f503efc342c4Marcel Holtmann		case 'W':
12019e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann			defer_setup = atoi(optarg);
12029e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann			break;
12039e7fdeca25a58d1e778a6b706c937628def76d7aMarcel Holtmann
1204da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann		case 'B':
1205da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann			filename = strdup(optarg);
1206da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann			break;
1207da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann
1208da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann		case 'N':
1209da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann			num_frames = atoi(optarg);
1210da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann			break;
1211da1911d8ae3753dc2bb925c48c8ee07c2ba93903Marcel Holtmann
1212b357f1d3900bca5575e88fcfc160945c6088608cMarcel Holtmann		case 'C':
1213b357f1d3900bca5575e88fcfc160945c6088608cMarcel Holtmann			count = atoi(optarg);
1214b357f1d3900bca5575e88fcfc160945c6088608cMarcel Holtmann			break;
1215b357f1d3900bca5575e88fcfc160945c6088608cMarcel Holtmann
1216b357f1d3900bca5575e88fcfc160945c6088608cMarcel Holtmann		case 'D':
1217e6673071212596bc54fb5bffff72b0c3a8275071Marcel Holtmann			delay = atoi(optarg) * 1000;
1218b357f1d3900bca5575e88fcfc160945c6088608cMarcel Holtmann			break;
1219b357f1d3900bca5575e88fcfc160945c6088608cMarcel Holtmann
12208e34afe9cc4dada1c34126a9723f76d4a6705707Marcel Holtmann		case 'X':
1221493b4ab0bfe0aa13fbcd8970b3cc1b1d78782d51Marcel Holtmann			if (strcasecmp(optarg, "ertm") == 0)
1222493b4ab0bfe0aa13fbcd8970b3cc1b1d78782d51Marcel Holtmann				rfcmode = L2CAP_MODE_ERTM;
1223493b4ab0bfe0aa13fbcd8970b3cc1b1d78782d51Marcel Holtmann			else
1224493b4ab0bfe0aa13fbcd8970b3cc1b1d78782d51Marcel Holtmann				rfcmode = atoi(optarg);
12258e34afe9cc4dada1c34126a9723f76d4a6705707Marcel Holtmann			break;
12268e34afe9cc4dada1c34126a9723f76d4a6705707Marcel Holtmann
122711e2f9bf390d828b45e26a8a1c00f503efc342c4Marcel Holtmann		case 'F':
122811e2f9bf390d828b45e26a8a1c00f503efc342c4Marcel Holtmann			fcs = atoi(optarg);
122911e2f9bf390d828b45e26a8a1c00f503efc342c4Marcel Holtmann			break;
123011e2f9bf390d828b45e26a8a1c00f503efc342c4Marcel Holtmann
1231f6557046863c041920180d232c8f0a63bb2faf3cMarcel Holtmann		case 'R':
1232f6557046863c041920180d232c8f0a63bb2faf3cMarcel Holtmann			reliable = 1;
1233f6557046863c041920180d232c8f0a63bb2faf3cMarcel Holtmann			break;
1234f6557046863c041920180d232c8f0a63bb2faf3cMarcel Holtmann
1235c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		case 'M':
1236c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			master = 1;
1237c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			break;
1238c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
1239c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		case 'A':
1240c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			auth = 1;
1241c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			break;
1242c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
1243c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		case 'E':
1244c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			encrypt = 1;
1245c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			break;
1246c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
124752d36be0bf2610739f04786d18df80db23e9cf6bMarcel Holtmann		case 'S':
124852d36be0bf2610739f04786d18df80db23e9cf6bMarcel Holtmann			secure = 1;
124952d36be0bf2610739f04786d18df80db23e9cf6bMarcel Holtmann			break;
125052d36be0bf2610739f04786d18df80db23e9cf6bMarcel Holtmann
12516ba87383b2047862686d04db85a4b7e0d1f243aeMarcel Holtmann		case 'G':
125270516886fef2e6c208d3e48332cc2c6c4b4d964cMax Krasnyansky			socktype = SOCK_DGRAM;
125370516886fef2e6c208d3e48332cc2c6c4b4d964cMax Krasnyansky			break;
125470516886fef2e6c208d3e48332cc2c6c4b4d964cMax Krasnyansky
1255c5c6abdf4c2cedfb8ed7977d34222927076698f4Gustavo F. Padovan		case 'U':
1256c5c6abdf4c2cedfb8ed7977d34222927076698f4Gustavo F. Padovan			socktype = SOCK_STREAM;
1257c5c6abdf4c2cedfb8ed7977d34222927076698f4Gustavo F. Padovan			break;
1258c5c6abdf4c2cedfb8ed7977d34222927076698f4Gustavo F. Padovan
12595b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann		case 'T':
12605b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann			timestamp = 1;
12615b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann			break;
12625b675858211437ea5d42ca49bbfbe15aeece65a9Marcel Holtmann
1263449367e8dab5fadc49f97c72a6837120e889cdc4Gustavo F. Padovan		case 'Q':
1264449367e8dab5fadc49f97c72a6837120e889cdc4Gustavo F. Padovan			max_transmit = atoi(optarg);
1265449367e8dab5fadc49f97c72a6837120e889cdc4Gustavo F. Padovan			break;
1266449367e8dab5fadc49f97c72a6837120e889cdc4Gustavo F. Padovan
1267449367e8dab5fadc49f97c72a6837120e889cdc4Gustavo F. Padovan		case 'Z':
1268449367e8dab5fadc49f97c72a6837120e889cdc4Gustavo F. Padovan			txwin_size = atoi(optarg);
1269449367e8dab5fadc49f97c72a6837120e889cdc4Gustavo F. Padovan			break;
1270449367e8dab5fadc49f97c72a6837120e889cdc4Gustavo F. Padovan
1271c5eab04d6572dee0885a512bfd4ad7f7a33b57c0Gustavo F. Padovan		case 'J':
1272c5eab04d6572dee0885a512bfd4ad7f7a33b57c0Gustavo F. Padovan			cid = atoi(optarg);
1273c5eab04d6572dee0885a512bfd4ad7f7a33b57c0Gustavo F. Padovan			break;
1274c5eab04d6572dee0885a512bfd4ad7f7a33b57c0Gustavo F. Padovan
1275c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		default:
1276c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			usage();
1277c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			exit(1);
1278c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		}
1279c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
1280c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
128104c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky	if (need_addr && !(argc - optind)) {
1282c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		usage();
1283c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		exit(1);
1284c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
1285c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
1286f213783e7d4068268187310251fedc546b9f212fMarcel Holtmann	if (data_size < 0)
128741e30382f9a83f41da700465de274266c60248b4Marcel Holtmann		buffer_size = (omtu > imtu) ? omtu : imtu;
128841e30382f9a83f41da700465de274266c60248b4Marcel Holtmann	else
128941e30382f9a83f41da700465de274266c60248b4Marcel Holtmann		buffer_size = data_size;
1290a5fcb1982de75e464c1c41a660975c5d8ab4b47bMarcel Holtmann
129141e30382f9a83f41da700465de274266c60248b4Marcel Holtmann	if (!(buf = malloc(buffer_size))) {
1292c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		perror("Can't allocate data buffer");
1293c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		exit(1);
1294c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
1295c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
1296c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	memset(&sa, 0, sizeof(sa));
1297c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	sa.sa_handler = SIG_IGN;
1298c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	sa.sa_flags   = SA_NOCLDSTOP;
1299c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	sigaction(SIGCHLD, &sa, NULL);
1300c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
1301c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	openlog("l2test", LOG_PERROR | LOG_PID, LOG_LOCAL0);
1302c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
13033c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmann	switch (mode) {
1304c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		case RECV:
1305c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			do_listen(recv_mode);
1306c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			break;
1307c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
130804c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky		case CRECV:
1309917543004017da0f09304844c578b59ca4a1802bMarcel Holtmann			sk = do_connect(argv[optind]);
1310917543004017da0f09304844c578b59ca4a1802bMarcel Holtmann			if (sk < 0)
131104c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky				exit(1);
1312917543004017da0f09304844c578b59ca4a1802bMarcel Holtmann			recv_mode(sk);
131304c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky			break;
131404c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky
1315c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		case DUMP:
1316c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			do_listen(dump_mode);
1317c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			break;
1318c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
1319c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		case SEND:
1320917543004017da0f09304844c578b59ca4a1802bMarcel Holtmann			sk = do_connect(argv[optind]);
1321917543004017da0f09304844c578b59ca4a1802bMarcel Holtmann			if (sk < 0)
132204c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky				exit(1);
1323917543004017da0f09304844c578b59ca4a1802bMarcel Holtmann			send_mode(sk);
132404c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky			break;
132504c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky
132604c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky		case LSEND:
132704c60e71e4b19ca904a5ea158a9e28297855350dMax Krasnyansky			do_listen(send_mode);
1328c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			break;
1329c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
1330c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		case RECONNECT:
1331c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			reconnect_mode(argv[optind]);
1332c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			break;
1333c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
1334c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		case MULTY:
13350effff5f4fe0fac9a986bb01dc547a99772d1bfaMarcel Holtmann			multi_connect_mode(argc - optind, argv + optind);
1336c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			break;
1337c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
1338c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky		case CONNECT:
1339c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			connect_mode(argv[optind]);
1340c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky			break;
13411f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann
13421f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann		case SENDDUMP:
1343917543004017da0f09304844c578b59ca4a1802bMarcel Holtmann			sk = do_connect(argv[optind]);
1344917543004017da0f09304844c578b59ca4a1802bMarcel Holtmann			if (sk < 0)
13451f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann				exit(1);
1346917543004017da0f09304844c578b59ca4a1802bMarcel Holtmann			senddump_mode(sk);
13471f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann			break;
13481f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann
13491f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann		case LSENDDUMP:
13501f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann			do_listen(senddump_mode);
13511f882b1b0f5c381c63c34c8558e13068868198b6Marcel Holtmann			break;
1352329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann
1353a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan		case LSENDRECV:
1354a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan			do_listen(send_and_recv_mode);
1355a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan			break;
1356a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan
1357a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan		case CSENDRECV:
1358a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan			sk = do_connect(argv[optind]);
1359a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan			if (sk < 0)
1360a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan				exit(1);
1361a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan
1362a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan			send_and_recv_mode(sk);
1363a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan			break;
1364a43d90eeb9522da483892d60bfc1054c02756fd4Gustavo F. Padovan
1365329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann		case INFOREQ:
1366329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann			info_request(argv[optind]);
1367329237dde23a9f692590f0075340ea085f8f3b35Marcel Holtmann			exit(0);
136822fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann
136922fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann		case PAIRING:
137022fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann			do_pairing(argv[optind]);
137122fdd674937bb927a00b35b84cca66dda76c6fd5Marcel Holtmann			exit(0);
1372c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	}
13733c967ce42aee827ff36622c7b70cbd65ef6dd900Marcel Holtmann
1374c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	syslog(LOG_INFO, "Exit");
1375c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
1376c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	closelog();
1377c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky
1378c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky	return 0;
1379c98b2f82a4e532ca61592b08e3ad60749eb9f8dMax Krasnyansky}
1380