summaryrefslogtreecommitdiffstats
path: root/rfcomm
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2003-01-02 01:50:47 +0000
committerMarcel Holtmann <marcel@holtmann.org>2003-01-02 01:50:47 +0000
commitc9271603f6ae622ee61f4514d97adf8e38f3eef1 (patch)
tree860a06fb6867843e23934bdc2191aed3eab7b1dc /rfcomm
parenteb6639784b6a47684078f28935f5150f26e561ea (diff)
Basic support for listen command
Diffstat (limited to 'rfcomm')
-rw-r--r--rfcomm/main.c149
1 files changed, 134 insertions, 15 deletions
diff --git a/rfcomm/main.c b/rfcomm/main.c
index 0dae70e6..c03f6127 100644
--- a/rfcomm/main.c
+++ b/rfcomm/main.c
@@ -2,7 +2,7 @@
*
* RFCOMM configuration utility
*
- * Copyright (C) 2002 Marcel Holtmann <marcel@holtmann.org>
+ * Copyright (C) 2002-2003 Marcel Holtmann <marcel@holtmann.org>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -30,6 +30,7 @@
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
+#include <termios.h>
#include <sys/poll.h>
#include <sys/param.h>
#include <sys/ioctl.h>
@@ -50,14 +51,14 @@ extern char *optarg;
static char *rfcomm_state[] = {
"unknown",
"connected",
- "clean",
- "bound",
- "listening",
- "connecting",
- "connecting",
- "config",
- "disconnecting",
- "closed"
+ "clean",
+ "bound",
+ "listening",
+ "connecting",
+ "connecting",
+ "config",
+ "disconnecting",
+ "closed"
};
static volatile sig_atomic_t __io_canceled = 0;
@@ -241,6 +242,7 @@ static void cmd_connect(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **arg
{
struct sockaddr_rc laddr, raddr;
struct rfcomm_dev_req req;
+ struct termios ti;
struct sigaction sa;
struct pollfd p;
char dst[18], devname[MAXPATHLEN];
@@ -264,7 +266,7 @@ static void cmd_connect(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **arg
fprintf(stderr, "Can't find a config entry for rfcomm%d\n", dev);
return;
}
-
+
} else {
raddr.rc_family = AF_BLUETOOTH;
str2ba(argv[1], &raddr.rc_bdaddr);
@@ -296,7 +298,7 @@ static void cmd_connect(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **arg
if (getsockname(sk, (struct sockaddr *)&laddr, &alen) < 0) {
perror("Can't get RFCOMM socket name");
close(sk);
- return;
+ return;
}
memset(&req, 0, sizeof(req));
@@ -305,7 +307,7 @@ static void cmd_connect(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **arg
bacpy(&req.src, &laddr.rc_bdaddr);
bacpy(&req.dst, &raddr.rc_bdaddr);
- req.channel = raddr.rc_channel;
+ req.channel = raddr.rc_channel;
if ((dev = ioctl(sk, RFCOMMCREATEDEV, &req)) < 0) {
perror("Can't create RFCOMM TTY");
@@ -318,10 +320,18 @@ static void cmd_connect(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **arg
snprintf(devname, MAXPATHLEN - 1, "/dev/bluetooth/rfcomm/%d", dev);
if ((fd = open(devname, O_RDONLY | O_NOCTTY)) < 0) {
perror("Can't open RFCOMM device");
+ close(sk);
return;
}
}
+ tcflush(fd, TCIOFLUSH);
+
+ cfmakeraw(&ti);
+ tcsetattr(fd, TCSANOW, &ti);
+
+ close(sk);
+
ba2str(&req.dst, dst);
printf("Connected %s to %s on channel %d\n", devname, dst, req.channel);
printf("Press CTRL-C for hangup\n");
@@ -353,6 +363,112 @@ static void cmd_connect(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **arg
close(fd);
}
+static void cmd_listen(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv)
+{
+ struct sockaddr_rc laddr, raddr;
+ struct rfcomm_dev_req req;
+ struct termios ti;
+ char dst[18], devname[MAXPATHLEN];
+ int sk, nsk, fd, alen;
+ int i;
+
+ if (argc < 3) {
+ fprintf(stderr, "No command specified\n");
+ return;
+ }
+
+ laddr.rc_family = AF_BLUETOOTH;
+ bacpy(&laddr.rc_bdaddr, bdaddr);
+
+ if (strncmp(argv[1], "exec", 4) == 0) {
+ laddr.rc_channel = 1;
+ argc -= 2;
+ argv += 2;
+ } else if (strncmp(argv[2], "exec", 4) == 0) {
+ laddr.rc_channel = atoi(argv[1]);
+ argc -= 3;
+ argv += 3;
+ } else {
+ fprintf(stderr, "Unknown syntax\n");
+ return;
+ }
+
+ argv[argc] = NULL;
+
+ if ((sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0) {
+ perror("Can't create RFCOMM socket");
+ return;
+ }
+
+ if (bind(sk, (struct sockaddr *)&laddr, sizeof(laddr)) < 0) {
+ perror("Can't bind RFCOMM socket");
+ close(sk);
+ return;
+ }
+
+ printf("Waiting for connection on channel %d\n", laddr.rc_channel);
+
+ listen(sk, 10);
+
+ alen = sizeof(raddr);
+ nsk = accept(sk, (struct sockaddr *) &raddr, &alen);
+
+ alen = sizeof(laddr);
+ if (getsockname(nsk, (struct sockaddr *)&laddr, &alen) < 0) {
+ perror("Can't get RFCOMM socket name");
+ close(nsk);
+ return;
+ }
+
+ memset(&req, 0, sizeof(req));
+ req.dev_id = dev;
+ req.flags = (1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP);
+
+ bacpy(&req.src, &laddr.rc_bdaddr);
+ bacpy(&req.dst, &raddr.rc_bdaddr);
+ req.channel = raddr.rc_channel;
+
+ if ((dev = ioctl(nsk, RFCOMMCREATEDEV, &req)) < 0) {
+ perror("Can't create RFCOMM TTY");
+ close(sk);
+ return;
+ }
+
+ snprintf(devname, MAXPATHLEN - 1, "/dev/rfcomm%d", dev);
+ if ((fd = open(devname, O_RDONLY | O_NOCTTY)) < 0) {
+ snprintf(devname, MAXPATHLEN - 1, "/dev/bluetooth/rfcomm/%d", dev);
+ if ((fd = open(devname, O_RDONLY | O_NOCTTY)) < 0) {
+ perror("Can't open RFCOMM device");
+ close(sk);
+ return;
+ }
+ }
+
+ tcflush(fd, TCIOFLUSH);
+
+ cfmakeraw(&ti);
+ tcsetattr(fd, TCSANOW, &ti);
+
+ close(sk);
+ close(nsk);
+
+ ba2str(&req.dst, dst);
+ printf("Connection from %s to %s\n", dst, devname);
+
+ for (i = 1; i < argc; i++)
+ if (strcmp(argv[i], "%d") == 0)
+ argv[i] = devname;
+
+ printf("Executing ");
+ for (i = 0; i < argc; i++)
+ printf("%s%s", (i == 0) ? "\"" : " ", argv[i]);
+ printf("\"\n");
+
+ execvp(argv[0], argv);
+
+ close(fd);
+}
+
static void cmd_create(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv)
{
if (strcmp(argv[0], "all") == 0)
@@ -393,8 +509,9 @@ struct {
} command[] = {
{ "bind", "create", cmd_create, "<dev> <bdaddr> [channel]", "Bind device" },
{ "release", "unbind", cmd_release, "<dev>", "Release device" },
+ { "show", "info", cmd_show, "<dev>", "Show device" },
{ "connect", "conn", cmd_connect, "<dev> <bdaddr> [channel]", "Connect device" },
- { "show", "info", cmd_show, 0, "Show device" },
+ { "listen", "server", cmd_listen, "<dev> [channel]", "Listen" },
{ NULL, NULL, NULL, 0, 0 }
};
@@ -447,7 +564,7 @@ int main(int argc, char *argv[])
else
str2ba(optarg, &bdaddr);
break;
-
+
case 'f':
rfcomm_config_file = strdup(optarg);
break;
@@ -483,7 +600,9 @@ int main(int argc, char *argv[])
exit(0);
}
- if (strncmp(argv[1], "rfcomm", 6) == 0)
+ if (strncmp(argv[1], "/dev/rfcomm", 11) == 0)
+ dev_id = atoi(argv[1] + 11);
+ else if (strncmp(argv[1], "rfcomm", 6) == 0)
dev_id = atoi(argv[1] + 6);
else
dev_id = atoi(argv[1]);