📄 l2test.c
字号:
/* * * BlueZ - Bluetooth protocol stack for Linux * * Copyright (C) 2000-2001 Qualcomm Incorporated * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com> * Copyright (C) 2002-2005 Marcel Holtmann <marcel@holtmann.org> * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation; * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY * CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, * COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS * SOFTWARE IS DISCLAIMED. * * * $Id: l2test.c,v 1.27 2005/05/19 17:06:50 holtmann Exp $ */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdio.h>#include <errno.h>#include <ctype.h>#include <unistd.h>#include <stdlib.h>#include <getopt.h>#include <syslog.h>#include <signal.h>#include <sys/time.h>#include <sys/poll.h>#include <sys/socket.h>#include <bluetooth/bluetooth.h>#include <bluetooth/hci.h>#include <bluetooth/hci_lib.h>#include <bluetooth/l2cap.h>#define NIBBLE_TO_ASCII(c) ((c) < 0x0a ? (c) + 0x30 : (c) + 0x57)/* Test modes */enum { SEND, RECV, RECONNECT, MULTY, DUMP, CONNECT, CRECV, LSEND, SENDDUMP, LSENDDUMP};static unsigned char *buf;/* Default mtu */static int imtu = 672;static int omtu = 0;/* Default data size */static long data_size = -1;/* Default addr and psm */static bdaddr_t bdaddr;static unsigned short psm = 10;/* Default number of frames to send (-1 = infinite) */static int num_frames = -1;static int flowctl = 0;static int master = 0;static int auth = 0;static int encrypt = 0;static int secure = 0;static int socktype = SOCK_SEQPACKET;static int linger = 0;static int reliable = 0;static float tv2fl(struct timeval tv){ return (float)tv.tv_sec + (float)(tv.tv_usec/1000000.0);}static char *ltoh(unsigned long c, char* s){ int c1; c1 = (c >> 28) & 0x0f; *(s++) = NIBBLE_TO_ASCII (c1); c1 = (c >> 24) & 0x0f; *(s++) = NIBBLE_TO_ASCII (c1); c1 = (c >> 20) & 0x0f; *(s++) = NIBBLE_TO_ASCII (c1); c1 = (c >> 16) & 0x0f; *(s++) = NIBBLE_TO_ASCII (c1); c1 = (c >> 12) & 0x0f; *(s++) = NIBBLE_TO_ASCII (c1); c1 = (c >> 8) & 0x0f; *(s++) = NIBBLE_TO_ASCII (c1); c1 = (c >> 4) & 0x0f; *(s++) = NIBBLE_TO_ASCII (c1); c1 = c & 0x0f; *(s++) = NIBBLE_TO_ASCII (c1); *s = 0; return s;}static char *ctoh(char c, char* s){ char c1; c1 = (c >> 4) & 0x0f; *(s++) = NIBBLE_TO_ASCII (c1); c1 = c & 0x0f; *(s++) = NIBBLE_TO_ASCII (c1); *s = 0; return s;}static void hexdump(char *s, unsigned long l){ char bfr[80]; char *pb; unsigned long i, n = 0; if (l == 0) return; while (n < l) { pb = bfr; pb = ltoh (n, pb); *(pb++) = ':'; *(pb++) = ' '; for (i = 0; i < 16; i++) { if (n + i >= l) { *(pb++) = ' '; *(pb++) = ' '; } else pb = ctoh (*(s + i), pb); *(pb++) = ' '; } *(pb++) = ' '; for (i = 0; i < 16; i++) { if (n + i >= l) break; else *(pb++) = (isprint (*(s + i)) ? *(s + i) : '.'); } *pb = 0; n += 16; s += 16; puts(bfr); }}static int do_connect(char *svr){ struct sockaddr_l2 addr; struct l2cap_options opts; struct l2cap_conninfo conn; socklen_t optlen; int sk, opt; /* Create socket */ sk = socket(PF_BLUETOOTH, socktype, BTPROTO_L2CAP); if (sk < 0) { syslog(LOG_ERR, "Can't create socket: %s (%d)", strerror(errno), errno); return -1; } /* Bind to local address */ memset(&addr, 0, sizeof(addr)); addr.l2_family = AF_BLUETOOTH; bacpy(&addr.l2_bdaddr, &bdaddr); if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { syslog(LOG_ERR, "Can't bind socket: %s (%d)", strerror(errno), errno); goto error; } /* Get default options */ memset(&opts, 0, sizeof(opts)); optlen = sizeof(opts); if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, &optlen) < 0) { syslog(LOG_ERR, "Can't get default L2CAP options: %s (%d)", strerror(errno), errno); goto error; } /* Set new options */ opts.omtu = omtu; opts.imtu = imtu; if (flowctl) opts.mode = 2; if (setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, sizeof(opts)) < 0) { syslog(LOG_ERR, "Can't set L2CAP options: %s (%d)", strerror(errno), errno); goto error; } /* Enable SO_LINGER */ if (linger) { struct linger l = { .l_onoff = 1, .l_linger = linger }; if (setsockopt(sk, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) < 0) { syslog(LOG_ERR, "Can't enable SO_LINGER: %s (%d)", strerror(errno), errno); return -1; } } /* Set link mode */ opt = 0; if (reliable) opt |= L2CAP_LM_RELIABLE; if (setsockopt(sk, SOL_L2CAP, L2CAP_LM, &opt, sizeof(opt)) < 0) { syslog(LOG_ERR, "Can't set L2CAP link mode: %s (%d)", strerror(errno), errno); goto error; } /* Connect to remote device */ memset(&addr, 0, sizeof(addr)); addr.l2_family = AF_BLUETOOTH; str2ba(svr, &addr.l2_bdaddr); addr.l2_psm = htobs(psm); if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0 ) { syslog(LOG_ERR, "Can't connect: %s (%d)", strerror(errno), errno); goto error; } /* Get current options */ memset(&opts, 0, sizeof(opts)); optlen = sizeof(opts); if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, &optlen) < 0) { syslog(LOG_ERR, "Can't get L2CAP options: %s (%d)", strerror(errno), errno); goto error; } /* Get connection information */ memset(&conn, 0, sizeof(conn)); optlen = sizeof(conn); if (getsockopt(sk, SOL_L2CAP, L2CAP_CONNINFO, &conn, &optlen) < 0) { syslog(LOG_ERR, "Can't get L2CAP connection information: %s (%d)", strerror(errno), errno); goto error; } syslog(LOG_INFO, "Connected [imtu %d, omtu %d, flush_to %d, " "mode %d, handle %d, class 0x%02x%02x%02x]", opts.imtu, opts.omtu, opts.flush_to, opts.mode, conn.hci_handle, conn.dev_class[2], conn.dev_class[1], conn.dev_class[0]); if (data_size > opts.omtu) data_size = opts.omtu; return sk;error: close(sk); return -1;}static void do_listen(void (*handler)(int sk)){ struct sockaddr_l2 addr; struct l2cap_options opts; struct l2cap_conninfo conn; socklen_t optlen; int sk, nsk, opt; char ba[18]; /* Create socket */ sk = socket(PF_BLUETOOTH, socktype, BTPROTO_L2CAP); if (sk < 0) { syslog(LOG_ERR, "Can't create socket: %s (%d)", strerror(errno), errno); exit(1); } /* Bind to local address */ addr.l2_family = AF_BLUETOOTH; bacpy(&addr.l2_bdaddr, &bdaddr); addr.l2_psm = htobs(psm); if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { syslog(LOG_ERR, "Can't bind socket: %s (%d)", strerror(errno), errno); goto error; } /* Set link mode */ opt = 0; if (reliable) opt |= L2CAP_LM_RELIABLE; if (master) opt |= L2CAP_LM_MASTER; if (auth) opt |= L2CAP_LM_AUTH; if (encrypt) opt |= L2CAP_LM_ENCRYPT; if (secure) opt |= L2CAP_LM_SECURE; if (opt && setsockopt(sk, SOL_L2CAP, L2CAP_LM, &opt, sizeof(opt)) < 0) { syslog(LOG_ERR, "Can't set L2CAP link mode: %s (%d)", strerror(errno), errno); goto error; } /* Get default options */ memset(&opts, 0, sizeof(opts)); optlen = sizeof(opts); if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, &optlen) < 0) { syslog(LOG_ERR, "Can't get default L2CAP options: %s (%d)", strerror(errno), errno); goto error; } /* Set new options */ opts.imtu = imtu; if (flowctl) opts.mode = 2; if (setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, sizeof(opts)) < 0) { syslog(LOG_ERR, "Can't set L2CAP options: %s (%d)", strerror(errno), errno); goto error; } if (socktype == SOCK_DGRAM) { handler(sk); return; } /* Listen for connections */ if (listen(sk, 10)) { syslog(LOG_ERR, "Can not listen on the socket: %s (%d)", strerror(errno), errno); goto error; } syslog(LOG_INFO, "Waiting for connection on psm %d ...", psm); while(1) { memset(&addr, 0, sizeof(addr)); optlen = sizeof(addr); nsk = accept(sk, (struct sockaddr *) &addr, &optlen); if (nsk < 0) { syslog(LOG_ERR, "Accept failed: %s (%d)", strerror(errno), errno); goto error; } if (fork()) { /* Parent */ close(nsk); continue; } /* Child */ close(sk); /* Get current options */ memset(&opts, 0, sizeof(opts)); optlen = sizeof(opts); if (getsockopt(nsk, SOL_L2CAP, L2CAP_OPTIONS, &opts, &optlen) < 0) { syslog(LOG_ERR, "Can't get L2CAP options: %s (%d)", strerror(errno), errno); close(nsk); goto error; } /* Get connection information */ memset(&conn, 0, sizeof(conn)); optlen = sizeof(conn); if (getsockopt(nsk, SOL_L2CAP, L2CAP_CONNINFO, &conn, &optlen) < 0) { syslog(LOG_ERR, "Can't get L2CAP connection information: %s (%d)", strerror(errno), errno); close(nsk); goto error; } ba2str(&addr.l2_bdaddr, ba); syslog(LOG_INFO, "Connect from %s [imtu %d, omtu %d, flush_to %d, " "mode %d, handle %d, class 0x%02x%02x%02x]", ba, opts.imtu, opts.omtu, opts.flush_to, opts.mode, conn.hci_handle, conn.dev_class[2], conn.dev_class[1], conn.dev_class[0]); /* Enable SO_LINGER */ if (linger) { struct linger l = { .l_onoff = 1, .l_linger = linger }; if (setsockopt(nsk, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) < 0) { syslog(LOG_ERR, "Can't enable SO_LINGER: %s (%d)", strerror(errno), errno); close(nsk); goto error; } } handler(nsk); syslog(LOG_INFO, "Disconnect: %m"); exit(0); } return;error: close(sk); exit(1);}static void dump_mode(int sk){ socklen_t optlen; int opt, len; syslog(LOG_INFO, "Receiving ..."); while (1) { fd_set rset; FD_ZERO(&rset);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -