summaryrefslogtreecommitdiffstats
path: root/usr.sbin/bluetooth/l2control
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/bluetooth/l2control')
-rw-r--r--usr.sbin/bluetooth/l2control/Makefile11
-rw-r--r--usr.sbin/bluetooth/l2control/Makefile.depend19
-rw-r--r--usr.sbin/bluetooth/l2control/l2cap.c314
-rw-r--r--usr.sbin/bluetooth/l2control/l2control.897
-rw-r--r--usr.sbin/bluetooth/l2control/l2control.c221
-rw-r--r--usr.sbin/bluetooth/l2control/l2control.h49
6 files changed, 711 insertions, 0 deletions
diff --git a/usr.sbin/bluetooth/l2control/Makefile b/usr.sbin/bluetooth/l2control/Makefile
new file mode 100644
index 0000000..8f17e02
--- /dev/null
+++ b/usr.sbin/bluetooth/l2control/Makefile
@@ -0,0 +1,11 @@
+# $Id: Makefile,v 1.7 2003/08/14 20:06:22 max Exp $
+# $FreeBSD$
+
+PROG= l2control
+MAN= l2control.8
+SRCS= l2cap.c l2control.c
+WARNS?= 2
+
+LIBADD= bluetooth
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/bluetooth/l2control/Makefile.depend b/usr.sbin/bluetooth/l2control/Makefile.depend
new file mode 100644
index 0000000..5d21038
--- /dev/null
+++ b/usr.sbin/bluetooth/l2control/Makefile.depend
@@ -0,0 +1,19 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ gnu/lib/libgcc \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libbluetooth \
+ lib/libc \
+ lib/libcompiler_rt \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/usr.sbin/bluetooth/l2control/l2cap.c b/usr.sbin/bluetooth/l2control/l2cap.c
new file mode 100644
index 0000000..44009ef
--- /dev/null
+++ b/usr.sbin/bluetooth/l2control/l2cap.c
@@ -0,0 +1,314 @@
+/*
+ * l2cap.c
+ *
+ * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: l2cap.c,v 1.5 2003/05/16 19:52:37 max Exp $
+ * $FreeBSD$
+ */
+
+#include <sys/ioctl.h>
+#define L2CAP_SOCKET_CHECKED
+#include <bluetooth.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "l2control.h"
+
+#define SIZE(x) (sizeof((x))/sizeof((x)[0]))
+
+/* Print BDADDR */
+static char *
+bdaddrpr(bdaddr_t const *ba)
+{
+ extern int numeric_bdaddr;
+ static char str[24];
+ struct hostent *he = NULL;
+
+ if (memcmp(ba, NG_HCI_BDADDR_ANY, sizeof(*ba)) == 0) {
+ str[0] = '*';
+ str[1] = 0;
+
+ return (str);
+ }
+
+ if (!numeric_bdaddr &&
+ (he = bt_gethostbyaddr((char *)ba, sizeof(*ba), AF_BLUETOOTH)) != NULL) {
+ strlcpy(str, he->h_name, sizeof(str));
+
+ return (str);
+ }
+
+ bt_ntoa(ba, str);
+
+ return (str);
+} /* bdaddrpr */
+
+/* Send read_node_flags command to the node */
+static int
+l2cap_read_node_flags(int s, int argc, char **argv)
+{
+ struct ng_btsocket_l2cap_raw_node_flags r;
+
+ memset(&r, 0, sizeof(r));
+ if (ioctl(s, SIOC_L2CAP_NODE_GET_FLAGS, &r, sizeof(r)) < 0)
+ return (ERROR);
+
+ fprintf(stdout, "Connectionless traffic flags:\n");
+ fprintf(stdout, "\tSDP: %s\n",
+ (r.flags & NG_L2CAP_CLT_SDP_DISABLED)? "disabled" : "enabled");
+ fprintf(stdout, "\tRFCOMM: %s\n",
+ (r.flags & NG_L2CAP_CLT_RFCOMM_DISABLED)? "disabled":"enabled");
+ fprintf(stdout, "\tTCP: %s\n",
+ (r.flags & NG_L2CAP_CLT_TCP_DISABLED)? "disabled" : "enabled");
+
+ return (OK);
+} /* l2cap_read_node_flags */
+
+/* Send read_debug_level command to the node */
+static int
+l2cap_read_debug_level(int s, int argc, char **argv)
+{
+ struct ng_btsocket_l2cap_raw_node_debug r;
+
+ memset(&r, 0, sizeof(r));
+ if (ioctl(s, SIOC_L2CAP_NODE_GET_DEBUG, &r, sizeof(r)) < 0)
+ return (ERROR);
+
+ fprintf(stdout, "Debug level: %d\n", r.debug);
+
+ return (OK);
+} /* l2cap_read_debug_level */
+
+/* Send write_debug_level command to the node */
+static int
+l2cap_write_debug_level(int s, int argc, char **argv)
+{
+ struct ng_btsocket_l2cap_raw_node_debug r;
+
+ memset(&r, 0, sizeof(r));
+ switch (argc) {
+ case 1:
+ r.debug = atoi(argv[0]);
+ break;
+
+ default:
+ return (USAGE);
+ }
+
+ if (ioctl(s, SIOC_L2CAP_NODE_SET_DEBUG, &r, sizeof(r)) < 0)
+ return (ERROR);
+
+ return (OK);
+} /* l2cap_write_debug_level */
+
+/* Send read_connection_list command to the node */
+static int
+l2cap_read_connection_list(int s, int argc, char **argv)
+{
+ static char const * const state[] = {
+ /* NG_L2CAP_CON_CLOSED */ "CLOSED",
+ /* NG_L2CAP_W4_LP_CON_CFM */ "W4_LP_CON_CFM",
+ /* NG_L2CAP_CON_OPEN */ "OPEN"
+ };
+#define con_state2str(x) ((x) >= SIZE(state)? "UNKNOWN" : state[(x)])
+
+ struct ng_btsocket_l2cap_raw_con_list r;
+ int n, error = OK;
+
+ memset(&r, 0, sizeof(r));
+ r.num_connections = NG_L2CAP_MAX_CON_NUM;
+ r.connections = calloc(NG_L2CAP_MAX_CON_NUM,
+ sizeof(ng_l2cap_node_con_ep));
+ if (r.connections == NULL) {
+ errno = ENOMEM;
+ return (ERROR);
+ }
+
+ if (ioctl(s, SIOC_L2CAP_NODE_GET_CON_LIST, &r, sizeof(r)) < 0) {
+ error = ERROR;
+ goto out;
+ }
+
+ fprintf(stdout, "L2CAP connections:\n");
+ fprintf(stdout,
+"Remote BD_ADDR Handle Flags Pending State\n");
+ for (n = 0; n < r.num_connections; n++) {
+ fprintf(stdout,
+ "%-17.17s " \
+ "%6d " \
+ "%c%c%c%c%c " \
+ "%7d " \
+ "%s\n",
+ bdaddrpr(&r.connections[n].remote),
+ r.connections[n].con_handle,
+ ((r.connections[n].flags & NG_L2CAP_CON_OUTGOING)? 'O' : 'I'),
+ ((r.connections[n].flags & NG_L2CAP_CON_LP_TIMO)? 'L' : ' '),
+ ((r.connections[n].flags & NG_L2CAP_CON_AUTO_DISCON_TIMO)? 'D' : ' '),
+ ((r.connections[n].flags & NG_L2CAP_CON_TX)? 'T' : ' '),
+ ((r.connections[n].flags & NG_L2CAP_CON_RX)? 'R' : ' '),
+ r.connections[n].pending,
+ con_state2str(r.connections[n].state));
+ }
+out:
+ free(r.connections);
+
+ return (error);
+} /* l2cap_read_connection_list */
+
+/* Send read_channel_list command to the node */
+static int
+l2cap_read_channel_list(int s, int argc, char **argv)
+{
+ static char const * const state[] = {
+ /* NG_L2CAP_CLOSED */ "CLOSED",
+ /* NG_L2CAP_W4_L2CAP_CON_RSP */ "W4_L2CAP_CON_RSP",
+ /* NG_L2CAP_W4_L2CA_CON_RSP */ "W4_L2CA_CON_RSP",
+ /* NG_L2CAP_CONFIG */ "CONFIG",
+ /* NG_L2CAP_OPEN */ "OPEN",
+ /* NG_L2CAP_W4_L2CAP_DISCON_RSP */ "W4_L2CAP_DISCON_RSP",
+ /* NG_L2CAP_W4_L2CA_DISCON_RSP */ "W4_L2CA_DISCON_RSP"
+ };
+#define ch_state2str(x) ((x) >= SIZE(state)? "UNKNOWN" : state[(x)])
+
+ struct ng_btsocket_l2cap_raw_chan_list r;
+ int n, error = OK;
+
+ memset(&r, 0, sizeof(r));
+ r.num_channels = NG_L2CAP_MAX_CHAN_NUM;
+ r.channels = calloc(NG_L2CAP_MAX_CHAN_NUM,
+ sizeof(ng_l2cap_node_chan_ep));
+ if (r.channels == NULL) {
+ errno = ENOMEM;
+ return (ERROR);
+ }
+
+ if (ioctl(s, SIOC_L2CAP_NODE_GET_CHAN_LIST, &r, sizeof(r)) < 0) {
+ error = ERROR;
+ goto out;
+ }
+
+ fprintf(stdout, "L2CAP channels:\n");
+ fprintf(stdout,
+"Remote BD_ADDR SCID/ DCID PSM IMTU/ OMTU State\n");
+ for (n = 0; n < r.num_channels; n++) {
+ fprintf(stdout,
+ "%-17.17s " \
+ "%5d/%5d %5d " \
+ "%5d/%5d " \
+ "%s\n",
+ bdaddrpr(&r.channels[n].remote),
+ r.channels[n].scid, r.channels[n].dcid,
+ r.channels[n].psm, r.channels[n].imtu,
+ r.channels[n].omtu,
+ ch_state2str(r.channels[n].state));
+ }
+out:
+ free(r.channels);
+
+ return (error);
+} /* l2cap_read_channel_list */
+
+/* Send read_auto_disconnect_timeout command to the node */
+static int
+l2cap_read_auto_disconnect_timeout(int s, int argc, char **argv)
+{
+ struct ng_btsocket_l2cap_raw_auto_discon_timo r;
+
+ memset(&r, 0, sizeof(r));
+ if (ioctl(s, SIOC_L2CAP_NODE_GET_AUTO_DISCON_TIMO, &r, sizeof(r)) < 0)
+ return (ERROR);
+
+ if (r.timeout != 0)
+ fprintf(stdout, "Auto disconnect timeout: %d sec\n", r.timeout);
+ else
+ fprintf(stdout, "Auto disconnect disabled\n");
+
+ return (OK);
+} /* l2cap_read_auto_disconnect_timeout */
+
+/* Send write_auto_disconnect_timeout command to the node */
+static int
+l2cap_write_auto_disconnect_timeout(int s, int argc, char **argv)
+{
+ struct ng_btsocket_l2cap_raw_auto_discon_timo r;
+
+ memset(&r, 0, sizeof(r));
+ switch (argc) {
+ case 1:
+ r.timeout = atoi(argv[0]);
+ break;
+
+ default:
+ return (USAGE);
+ }
+
+ if (ioctl(s, SIOC_L2CAP_NODE_SET_AUTO_DISCON_TIMO, &r, sizeof(r)) < 0)
+ return (ERROR);
+
+ return (OK);
+} /* l2cap_write_auto_disconnect_timeout */
+
+struct l2cap_command l2cap_commands[] = {
+{
+"read_node_flags",
+"Get L2CAP node flags",
+&l2cap_read_node_flags
+},
+{
+"read_debug_level",
+"Get L2CAP node debug level",
+&l2cap_read_debug_level
+},
+{
+"write_debug_level <level>",
+"Set L2CAP node debug level",
+&l2cap_write_debug_level
+},
+{
+"read_connection_list",
+"Read list of the L2CAP connections",
+&l2cap_read_connection_list
+},
+{
+"read_channel_list",
+"Read list of the L2CAP channels",
+&l2cap_read_channel_list
+},
+{
+"read_auto_disconnect_timeout",
+"Get L2CAP node auto disconnect timeout (in sec)",
+&l2cap_read_auto_disconnect_timeout
+},
+{
+"write_auto_disconnect_timeout <timeout>",
+"Set L2CAP node auto disconnect timeout (in sec)",
+&l2cap_write_auto_disconnect_timeout
+},
+{
+NULL,
+}};
+
diff --git a/usr.sbin/bluetooth/l2control/l2control.8 b/usr.sbin/bluetooth/l2control/l2control.8
new file mode 100644
index 0000000..5974167
--- /dev/null
+++ b/usr.sbin/bluetooth/l2control/l2control.8
@@ -0,0 +1,97 @@
+.\" Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: l2control.8,v 1.5 2003/05/21 00:53:00 max Exp $
+.\" $FreeBSD$
+.\"
+.Dd April 9, 2011
+.Dt L2CONTROL 8
+.Os
+.Sh NAME
+.Nm l2control
+.Nd L2CAP configuration utility
+.Sh SYNOPSIS
+.Nm
+.Op Fl hn
+.Fl a Ar local
+.Ar command
+.Op Ar parameters ...
+.Sh DESCRIPTION
+The
+.Nm
+utility connects to the local device with the specified BD_ADDR or name
+and attempts to send the specified command.
+The
+.Nm
+utility will print results to the standard output and error messages to
+the standard error output.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl a Ar local
+Connect to the local device with the specified BD_ADDR or name.
+Example:
+.Fl a Li 00:01:02:03:04:05
+or
+.Fl a Li bt_device .
+.It Fl h
+Display usage message and exit.
+.It Fl n
+Show Bluetooth addresses as numbers.
+Normally
+.Nm
+attempts to resolve Bluetooth addresses, and display them symbolically.
+.It Ar command
+One of the supported commands (see below).
+The special command
+.Cm help
+can be used to obtain a list of all supported commands.
+To get more information about a specific command use
+.Cm help Ar command .
+.It Ar parameters
+One or more optional space separated command parameters.
+.El
+.Sh COMMANDS
+The currently supported node commands in
+.Nm
+are:
+.Pp
+.Bl -tag -width "Write_Auto_Disconnect_Timeout" -offset indent -compact
+.It Cm Read_Node_Flags
+.It Cm Read_Debug_Level
+.It Cm Write_Debug_Level
+.It Cm Read_Connection_List
+.It Cm Read_Channel_List
+.It Cm Read_Auto_Disconnect_Timeout
+.It Cm Write_Auto_Disconnect_Timeout
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh SEE ALSO
+.Xr netgraph 3 ,
+.Xr netgraph 4 ,
+.Xr ng_l2cap 4 ,
+.Xr l2ping 8
+.Sh AUTHORS
+.An Maksim Yevmenkin Aq Mt emax@FreeBSD.org
diff --git a/usr.sbin/bluetooth/l2control/l2control.c b/usr.sbin/bluetooth/l2control/l2control.c
new file mode 100644
index 0000000..87ec237
--- /dev/null
+++ b/usr.sbin/bluetooth/l2control/l2control.c
@@ -0,0 +1,221 @@
+/*
+ * l2control.c
+ *
+ * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: l2control.c,v 1.6 2003/09/05 00:38:25 max Exp $
+ * $FreeBSD$
+ */
+
+#include <assert.h>
+#define L2CAP_SOCKET_CHECKED
+#include <bluetooth.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "l2control.h"
+
+/* Prototypes */
+static int do_l2cap_command (bdaddr_p, int, char **);
+static struct l2cap_command * find_l2cap_command (char const *,
+ struct l2cap_command *);
+static void print_l2cap_command (struct l2cap_command *);
+static void usage (void);
+
+/* Main */
+
+int numeric_bdaddr = 0;
+
+int
+main(int argc, char *argv[])
+{
+ int n;
+ bdaddr_t bdaddr;
+
+ memset(&bdaddr, 0, sizeof(bdaddr));
+
+ /* Process command line arguments */
+ while ((n = getopt(argc, argv, "a:nh")) != -1) {
+ switch (n) {
+ case 'a':
+ if (!bt_aton(optarg, &bdaddr)) {
+ struct hostent *he = NULL;
+
+ if ((he = bt_gethostbyname(optarg)) == NULL)
+ errx(1, "%s: %s", optarg, hstrerror(h_errno));
+
+ memcpy(&bdaddr, he->h_addr, sizeof(bdaddr));
+ }
+ break;
+
+ case 'n':
+ numeric_bdaddr = 1;
+ break;
+
+ case 'h':
+ default:
+ usage();
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (*argv == NULL)
+ usage();
+
+ return (do_l2cap_command(&bdaddr, argc, argv));
+} /* main */
+
+/* Execute commands */
+static int
+do_l2cap_command(bdaddr_p bdaddr, int argc, char **argv)
+{
+ char *cmd = argv[0];
+ struct l2cap_command *c = NULL;
+ struct sockaddr_l2cap sa;
+ int s, e, help;
+
+ help = 0;
+ if (strcasecmp(cmd, "help") == 0) {
+ argc --;
+ argv ++;
+
+ if (argc <= 0) {
+ fprintf(stdout, "Supported commands:\n");
+ print_l2cap_command(l2cap_commands);
+ fprintf(stdout, "\nFor more information use " \
+ "'help command'\n");
+
+ return (OK);
+ }
+
+ help = 1;
+ cmd = argv[0];
+ }
+
+ c = find_l2cap_command(cmd, l2cap_commands);
+ if (c == NULL) {
+ fprintf(stdout, "Unknown command: \"%s\"\n", cmd);
+ return (ERROR);
+ }
+
+ if (!help) {
+ if (memcmp(bdaddr, NG_HCI_BDADDR_ANY, sizeof(*bdaddr)) == 0)
+ usage();
+
+ memset(&sa, 0, sizeof(sa));
+ sa.l2cap_len = sizeof(sa);
+ sa.l2cap_family = AF_BLUETOOTH;
+ memcpy(&sa.l2cap_bdaddr, bdaddr, sizeof(sa.l2cap_bdaddr));
+
+ s = socket(PF_BLUETOOTH, SOCK_RAW, BLUETOOTH_PROTO_L2CAP);
+ if (s < 0)
+ err(1, "Could not create socket");
+
+ if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0)
+ err(2,
+"Could not bind socket, bdaddr=%s", bt_ntoa(&sa.l2cap_bdaddr, NULL));
+
+ e = 0x0ffff;
+ if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &e, sizeof(e)) < 0)
+ err(3, "Coult not setsockopt(RCVBUF, %d)", e);
+
+ e = (c->handler)(s, -- argc, ++ argv);
+
+ close(s);
+ } else
+ e = USAGE;
+
+ switch (e) {
+ case OK:
+ case FAILED:
+ break;
+
+ case ERROR:
+ fprintf(stdout, "Could not execute command \"%s\". %s\n",
+ cmd, strerror(errno));
+ break;
+
+ case USAGE:
+ fprintf(stdout, "Usage: %s\n%s\n", c->command, c->description);
+ break;
+
+ default: assert(0); break;
+ }
+
+ return (e);
+} /* do_l2cap_command */
+
+/* Try to find command in specified category */
+static struct l2cap_command *
+find_l2cap_command(char const *command, struct l2cap_command *category)
+{
+ struct l2cap_command *c = NULL;
+
+ for (c = category; c->command != NULL; c++) {
+ char *c_end = strchr(c->command, ' ');
+
+ if (c_end != NULL) {
+ int len = c_end - c->command;
+
+ if (strncasecmp(command, c->command, len) == 0)
+ return (c);
+ } else if (strcasecmp(command, c->command) == 0)
+ return (c);
+ }
+
+ return (NULL);
+} /* find_l2cap_command */
+
+/* Print commands in specified category */
+static void
+print_l2cap_command(struct l2cap_command *category)
+{
+ struct l2cap_command *c = NULL;
+
+ for (c = category; c->command != NULL; c++)
+ fprintf(stdout, "\t%s\n", c->command);
+} /* print_l2cap_command */
+
+/* Usage */
+static void
+usage(void)
+{
+ fprintf(stderr, "Usage: l2control [-hn] -a local cmd [params ..]\n");
+ fprintf(stderr, "Where:\n");
+ fprintf(stderr, " -a local Specify local device to connect to\n");
+ fprintf(stderr, " -h Display this message\n");
+ fprintf(stderr, " -n Show addresses as numbers\n");
+ fprintf(stderr, " cmd Supported command " \
+ "(see l2control help)\n");
+ fprintf(stderr, " params Optional command parameters\n");
+ exit(255);
+} /* usage */
+
diff --git a/usr.sbin/bluetooth/l2control/l2control.h b/usr.sbin/bluetooth/l2control/l2control.h
new file mode 100644
index 0000000..43d4561
--- /dev/null
+++ b/usr.sbin/bluetooth/l2control/l2control.h
@@ -0,0 +1,49 @@
+/*
+ * l2control.h
+ *
+ * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: l2control.h,v 1.1 2002/11/24 20:22:41 max Exp $
+ * $FreeBSD$
+ */
+
+#ifndef _L2CONTROL_H_
+#define _L2CONTROL_H_
+
+#define OK 0 /* everything was OK */
+#define ERROR 1 /* could not execute command */
+#define FAILED 2 /* error was reported */
+#define USAGE 3 /* invalid parameters */
+
+struct l2cap_command {
+ char const *command;
+ char const *description;
+ int (*handler)(int, int, char **);
+};
+
+extern struct l2cap_command l2cap_commands[];
+
+#endif /* _L2CONTROL_H_ */
+
OpenPOWER on IntegriCloud