]> www.wagner.pp.ru Git - oss/btcli.git/commitdiff
Initial import
authorVictor Wagner <vitus@wagner.pp.ru>
Sun, 27 Jul 2008 14:01:49 +0000 (14:01 +0000)
committerVictor Wagner <vitus@wagner.pp.ru>
Sun, 27 Jul 2008 14:01:49 +0000 (14:01 +0000)
bluenet/bluenet [new file with mode: 0755]
bluenet/btnet-client [new file with mode: 0644]
bluenet/btnet-server [new file with mode: 0644]
btpasskey/Makefile [new file with mode: 0644]
btpasskey/btpasskey.1 [new file with mode: 0644]
btpasskey/btpasskey.c [new file with mode: 0644]
scripts/btls [new file with mode: 0644]
scripts/btmode [new file with mode: 0755]
scripts/listmodes [new file with mode: 0644]

diff --git a/bluenet/bluenet b/bluenet/bluenet
new file mode 100755 (executable)
index 0000000..ce212fa
--- /dev/null
@@ -0,0 +1,50 @@
+#!/bin/sh
+case "$1" in
+on) 
+       # ðÏÉÓË ÔÏÞËÉ ÄÏÓÔÕÐÁ × /etc/bluetooth/NAP
+       while read address; do
+         echo "Trying access point $address"
+         if sdptool search --bdaddr $address NAP | grep -q "Service Name"; then
+               pand -c $address -d NAP --devup /usr/local/sbin/btnet-client
+               exit
+         fi
+         done </etc/bluetooth/NAP
+         echo "No active network access point found" 1>&2
+         exit 1
+;;
+[0-9A-F][0-9A-F]:*)
+       role=${2:-"NAP"}
+       pand -c $1 -d $role --devup  /usr/local/sbin/btnet-client
+;;
+off)
+       ifdown bnep0
+       pand -K
+;;
+master)
+# ×ÁÒÉÁÎÔ ÒÁÂÏÔÙ ÎÏÕÔÂÕËÁ ÓÅÒ×ÅÒÏÍ ad-hoc ÓÅÔÉ
+       role=${2:-"GN"}
+       PAN_BRIDGE=btgn0
+       # üËÓÐÏÒÔÉÒÕÅÍ ÉÍÑ briget ÄÌÑ ÉÓÐÏÌØÚÏ×ÁÎÉÑ btnet-server ÓËÒÉÐÔÏÍ
+       export PAN_BRIGE
+       # óÏÚÄÁÅÍ bridge ÎÁ ËÏÔÏÒÏÍ ÂÕÄÅÔ ×ÉÓÅÔØ dhcp ÓÅÒ×ÅÒ
+       brctl addbr $PAN_BRIDGE
+       ifconfig btgn0 10.0.0.1 netmask 255.255.255.0 broacast 10.0.0.255
+       # úÄÅÓØ ÎÁÄÏ ÂÙ ÐÒÏ×ÅÒÉÔØ ÚÁÐÕÝÅÎÎÏÓÔØ dnsmasq É ÅÇÏ ÓÌÅÇËÁ
+       # ÐÅÒÅËÏÎÆÉÇÕÒÉÒÏ×ÁÔØ. îÏ Õ ÍÅÎÑ ÏΠ×ÓÅ ÒÁ×ÎÏ ÚÁÐÕÝÅΠÉ
+       # ÓËÏÎÆÉÇÕÒÉÒÏ×ÁΠÔÁË, ÞÔÏ É ÔÁË ÒÁÂÏÔÁÅÔ.
+       # úÁ ÉÓËÌÀÞÅÎÉÅÍ ÔÏÇÏ ÞÔÏ ÏÔÄÁÅÔ default gateway É × ÒÅÖÉÍÅ NAP
+       # É × ÒÅÖÉÍÅ GN
+       
+       # åÓÌÉ ÍÙ ÒÁÂÏÔÁÅÍ NAP, ×ËÌÀÞÁÅÍ ÆÏÒ×ÁÒÄÉÎÇ
+       if [ "$role" = "NAP" ]; then
+               echo 1> /proc/sys/net/ipv4/ip_forward
+       fi
+       # úÁÐÕÓËÁÅÍ pand × ÒÅÖÉÍÅ ÐÒÉÅÍÁ
+       pand --listen --role $role --devup /usr/local/sbin/btnet-server 
+       ;;
+*)
+       echo "use $0 on|off|master [GN|NAP]|address [GN|NAP]" >&2
+       exit 1
+       ;;
+esac
+
diff --git a/bluenet/btnet-client b/bluenet/btnet-client
new file mode 100644 (file)
index 0000000..5d46343
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+logger -p daemon.info "btnet-client[$$] Connected to PAN access point $2 interface $1" 
+ifup $1
diff --git a/bluenet/btnet-server b/bluenet/btnet-server
new file mode 100644 (file)
index 0000000..c504415
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/sh
+logger -p daemon.info "btnet-server[$$]: Machine $2 is connected to our net inetface $1"
+if [ -z "$PAN_BRIDGE" ]; then
+       logger -p daemon.error "btnet-client[$#]: PAN_BRIDGE variable is absent. Is pand started from bluenet script?"
+       exit 1
+fi     
+brctl add $PAN_BRIDGE $1
+ifconfig $1 0.0.0.0
+
diff --git a/btpasskey/Makefile b/btpasskey/Makefile
new file mode 100644 (file)
index 0000000..21380db
--- /dev/null
@@ -0,0 +1,8 @@
+# this Makefile is for building btcli it depends on pkg-config libdbus-1-dev (and build-essential) packages 
+btpasskey: btpasskey.c
+       $(CC) `pkg-config --libs --cflags dbus-1`  -g -DDBUS_API_SUBJECT_TO_CHANGE -DVERSION="\"1.1\"" -o btpasskey btpasskey.c 
+
+install: btpasskey
+       install -m 755 -o root btpasskey /usr/bin 
+       install -m 644 -o root btpasskey.1 /usr/share/man/man1
+
diff --git a/btpasskey/btpasskey.1 b/btpasskey/btpasskey.1
new file mode 100644 (file)
index 0000000..3dbd6c8
--- /dev/null
@@ -0,0 +1,67 @@
+.TH BTPASSKEY "1" "November 2007" "btpasskey 1.0" "User Commands"
+.SH NAME
+btpasskey\- waits for D-Bus signal and request passkey from stdin
+.SH SYNOPSIS
+.B btpasskey
+[\fB--path\fR \fIagent-path\fI]
+.SH DESCRIPTION
+.PP
+.B btpasskey
+is a command line utility to enter passkeys during bluetooth pairing
+process. When started it just sits and waits for D-BUS message from
+bluez bluetooth stack. 
+.PP
+When message recieved, it prints out name and bluetooth address of the
+device requesting connection and expects numeric passkey to be entered
+from stdin. Passkey entry should be finished by hitting Return key.
+.PP
+Entering empty passkey (just hitting enter) causes 
+.B btpasskey
+to refuse answer to recieved message, which typically means cancelling
+bluetooth connection, unless another passkey agent is listening on
+system message bus.
+.PP
+.B btpasskey
+is intended to run from some more sophisticated user interface, so it
+uses unbuffered input/output. If another application starts it
+redirecting stdin and stdout to pipes, application may expect complete 
+message to be read before 
+.B btpasswd
+blocks waiting for input.
+.SH OPTIONS
+.TP
+.BI "--path, -p " agent-path
+Specify D-BUS path for agent, other than default.
+.TP
+.B --discoverable, -d
+Turn default adapter into discoverable mode while program is running and waiting for pairing request
+.TP
+.BI "--pair, -P " address
+Initiate pairing with device with specified address.
+.TP 
+.BI "--remove, -r " address
+Instead of waiting for pairing request and ask user for passkey, just remove bonding with specified device and exit. This operation may be needed if device was prevoisly paired with this computer, then was paired with another computer and forgot link key. In this case we need to remove link key from our computer before pairing once again.
+.TP 
+.B --help, -h
+Displays brief usage message.
+.TP
+.B --version, -V
+Displays program version.
+.SH SIGNALS
+.TP
+.B SIGINT
+Closes D-BUS connection and terminates
+.TP
+.B SIGTERM
+Closes D-BUS connection and terminates
+.TP
+.B SIGPIPE
+Closes D-BUS connection and terminates
+.SH BUGS
+Doesn't properly handle org.bluez.PasskeyAgent.Cancel method, when is blocked on reading from stdin.
+.PP
+All mode changes and pairing operations (-d,-P,-r) work only with default Bluetooth adapter. There is no way to specify other adapter to operate with.
+.SH AUTHOR
+Victor B. Wagner <vitus@wagner.pp.ru>
+
+
diff --git a/btpasskey/btpasskey.c b/btpasskey/btpasskey.c
new file mode 100644 (file)
index 0000000..4c5e1b5
--- /dev/null
@@ -0,0 +1,515 @@
+/*
+ *
+ *  btpasskey 1.0 Copyright (c) 2007 Victor Wagner
+ *
+ *  Based on example passkey-agent.c program from
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2005-2006  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 as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <getopt.h>
+#include <string.h>
+
+#include <dbus/dbus.h>
+
+#define INTERFACE "org.bluez.Security"
+char*  resolve_bluetooth_name(DBusConnection *conn,const char *adapter,const char *btaddress)  
+{
+       DBusMessage *msg;
+       DBusPendingCall *pending;
+       char *name;
+       static char namebuf[256];
+       DBusError err;
+       msg = dbus_message_new_method_call("org.bluez",
+       adapter, "org.bluez.Adapter","GetRemoteName");
+       if (NULL==msg) 
+       {
+               fprintf(stderr,"dbus_message_new_method_call error\n");
+               exit(1);
+       }
+       dbus_message_append_args(msg,DBUS_TYPE_STRING,btaddress,DBUS_TYPE_INVALID);
+
+       if (!dbus_connection_send_with_reply(conn, msg, &pending,-1)
+        || NULL==pending) 
+       {
+               fprintf(stderr,"Error sending message to system bus\n");
+               exit(1);
+       }
+        dbus_connection_flush(conn);
+       dbus_message_unref(msg);
+       dbus_pending_call_block(pending);
+       msg = dbus_pending_call_steal_reply(pending);
+       if (NULL == msg)
+       {
+               fprintf(stderr,"Error getting call result\n");
+               exit(1);
+       }
+       dbus_pending_call_unref(pending);
+       dbus_error_init(&err);
+       if (!dbus_message_get_args(msg,&err,DBUS_TYPE_STRING,&name,DBUS_TYPE_INVALID)) 
+       {
+               fprintf(stderr,"Error parsing name request result\n");
+               exit(1);
+       }
+       if (!dbus_error_is_set(&err)) 
+       {
+               strcpy(namebuf,name);
+       }
+       else 
+       {
+               fprintf(stderr,"DBus error %s: %s\n",err.name,
+               err.message);
+               namebuf[0]=0;
+       }
+       dbus_error_free(&err);
+       dbus_message_unref(msg);
+       return namebuf;
+          
+               
+}
+
+static volatile sig_atomic_t __io_canceled = 0;
+static volatile sig_atomic_t __io_terminated = 0;
+
+static void sig_term(int sig)
+{
+       __io_canceled = 1;
+}
+
+static DBusHandlerResult agent_filter(DBusConnection *conn,
+                                               DBusMessage *msg, void *data)
+{
+       const char *name, *old, *new;
+
+       if (!dbus_message_is_signal(msg, DBUS_INTERFACE_DBUS, "NameOwnerChanged"))
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+       if (!dbus_message_get_args(msg, NULL,
+                       DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &old,
+                               DBUS_TYPE_STRING, &new, DBUS_TYPE_INVALID)) {
+               fprintf(stderr, "Invalid arguments for NameOwnerChanged signal");
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+       }
+
+       if (!strcmp(name, "org.bluez") && *new == '\0') {
+               fprintf(stderr, "Passkey service has been terminated\n");
+               __io_terminated = 1;
+       }
+
+       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static DBusHandlerResult request_message(DBusConnection *conn,
+                                               DBusMessage *msg, void *data)
+{
+       DBusMessage *reply;
+       const char *path, *address;
+       char passbuf[24], *c,*dname; 
+       char *passkey = passbuf;
+       int ok=0;
+       
+
+       if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &path,
+                       DBUS_TYPE_STRING, &address, DBUS_TYPE_INVALID)) {
+               fprintf(stderr, "Invalid arguments for passkey Request method");
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+       }
+       dname = resolve_bluetooth_name(conn,path,address);
+       if (!dname) dname = "";
+       while (!ok) {
+               printf("Pass key requested for device \"%s\" (%s)\nEnter passkey: ",dname,address);
+               fgets(passkey,sizeof(passbuf),stdin);
+               for (c=passkey;*c && *c!='\n'; c++) {
+                       if (!isdigit(*c)) {
+                               printf("Invalid passkey. Retry, please\n");                             break;
+                       }       
+               }       
+               if (*c=='\n') *c=0;
+               if (!*c && c>passkey) ok=1;
+               if (c==passkey) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+       }
+       reply = dbus_message_new_method_return(msg);
+       if (!reply) {
+               fprintf(stderr, "Can't create reply message\n");
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+       }
+
+       dbus_message_append_args(reply, DBUS_TYPE_STRING, &passkey,
+                                       DBUS_TYPE_INVALID);
+
+       dbus_connection_send(conn, reply, NULL);
+
+       dbus_connection_flush(conn);
+
+       dbus_message_unref(reply);
+
+       return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult release_message(DBusConnection *conn,
+                                               DBusMessage *msg, void *data)
+{
+       DBusMessage *reply;
+
+       if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_INVALID)) {
+               fprintf(stderr, "Invalid arguments for passkey Release method");
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+       }
+
+       reply = dbus_message_new_method_return(msg);
+       if (!reply) {
+               fprintf(stderr, "Can't create reply message\n");
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+       }
+
+       dbus_message_append_args(reply, DBUS_TYPE_INVALID);
+
+       dbus_connection_send(conn, reply, NULL);
+
+       dbus_connection_flush(conn);
+
+       dbus_message_unref(reply);
+
+       if (!__io_canceled)
+               fprintf(stderr, "Passkey service has been released\n");
+
+       __io_terminated = 1;
+
+       return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult agent_message(DBusConnection *conn,
+                                               DBusMessage *msg, void *data)
+{
+       if (dbus_message_is_method_call(msg, "org.bluez.PasskeyAgent", "Request"))
+               return request_message(conn, msg, data);
+
+       if (dbus_message_is_method_call(msg, "org.bluez.PasskeyAgent", "Release"))
+               return release_message(conn, msg, data);
+
+       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static const DBusObjectPathVTable agent_table = {
+       .message_function = agent_message,
+};
+
+static int register_agent(DBusConnection *conn, const char *agent_path)
+{
+       DBusMessage *msg, *reply;
+       DBusError err;
+       const char *path, *method;
+
+       if (!dbus_connection_register_object_path(conn, agent_path,
+                                                       &agent_table, NULL)) {
+               fprintf(stderr, "Can't register path object path for agent\n");
+               return -1;
+       }
+
+       path = "/org/bluez";
+       method = "RegisterDefaultPasskeyAgent";
+       msg = dbus_message_new_method_call("org.bluez", path, INTERFACE, method);
+       if (!msg) {
+               fprintf(stderr, "Can't allocate new method call\n");
+               return -1;
+       }
+
+       dbus_message_append_args(msg, DBUS_TYPE_STRING, &agent_path,
+                                                       DBUS_TYPE_INVALID);
+
+       dbus_error_init(&err);
+
+       reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err);
+
+       dbus_message_unref(msg);
+
+       if (!reply) {
+               fprintf(stderr, "Can't register passkey agent\n");
+               if (dbus_error_is_set(&err)) {
+                       fprintf(stderr, "%s\n", err.message);
+                       dbus_error_free(&err);
+               }
+               return -1;
+       }
+
+       dbus_message_unref(reply);
+
+       dbus_connection_flush(conn);
+
+       return 0;
+}
+
+static int unregister_agent(DBusConnection *conn, const char *agent_path)
+{
+       DBusMessage *msg, *reply;
+       DBusError err;
+       const char *path, *method;
+
+       path = "/org/bluez";
+       method = "UnregisterDefaultPasskeyAgent";
+
+       msg = dbus_message_new_method_call("org.bluez", path, INTERFACE, method);
+       if (!msg) {
+               fprintf(stderr, "Can't allocate new method call\n");
+               dbus_connection_unref(conn);
+               exit(1);
+       }
+
+       dbus_message_append_args(msg, DBUS_TYPE_STRING, &agent_path,
+                                                       DBUS_TYPE_INVALID);
+
+       dbus_error_init(&err);
+
+       reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err);
+
+       dbus_message_unref(msg);
+
+       if (!reply) {
+               fprintf(stderr, "Can't unregister passkey agent\n");
+               if (dbus_error_is_set(&err)) {
+                       fprintf(stderr, "%s\n", err.message);
+                       dbus_error_free(&err);
+               }
+               return -1;
+       }
+
+       dbus_message_unref(reply);
+
+       dbus_connection_flush(conn);
+
+       dbus_connection_unregister_object_path(conn, agent_path);
+
+       return 0;
+}
+/* Gets default bluetooth adapter name */
+char *get_default_adapter(DBusConnection *conn)
+{
+       DBusMessage *msg, *reply;
+       char *result=NULL;
+       DBusError err;
+
+       msg = dbus_message_new_method_call("org.bluez", "/org/bluez","org.bluez.Manager", "DefaultAdapter");
+       dbus_error_init(&err);
+       reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err);
+       dbus_message_get_args(reply,&err,DBUS_TYPE_STRING,&result,DBUS_TYPE_INVALID);
+       if (dbus_error_is_set(&err))
+       {
+               fprintf(stderr,"Error getting default adapter: %s\n",err.message);
+               dbus_error_free(&err);
+               exit(1);
+       }       
+       dbus_message_unref(msg);
+       result=strdup(result);
+       dbus_message_unref(reply);
+       return result;
+}
+
+
+/* Finishes pending call without retriving anything */
+static void finish_pending_call(DBusPendingCall *pending, void *user_data)
+{
+       dbus_pending_call_unref(pending);
+}
+/*Calls specified method of org.bluez.Adapter interface with one or zero 
+ * string arguments. If wait for reply is specified, waits, and if 
+ * method is not void,
+ * returns string result
+ */
+char *adapter_call(DBusConnection *conn, char *adapter,const char *method,
+   const char *argument, int wait_reply) {
+       DBusMessage *msg, *reply;
+       char *result=NULL;
+       DBusError err;
+       msg = dbus_message_new_method_call("org.bluez", adapter,"org.bluez.Adapter", method);
+       if (argument !=NULL) 
+               dbus_message_append_args(msg, DBUS_TYPE_STRING, &argument,
+                       DBUS_TYPE_INVALID);
+                                                       
+       if (wait_reply) {
+               dbus_error_init(&err);
+               reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err);
+               dbus_message_get_args(reply,&err,DBUS_TYPE_STRING,&result,DBUS_TYPE_INVALID);
+               if (result) 
+                       result=strdup(result);
+               dbus_message_unref(reply);
+       } else {
+               DBusPendingCall *pending;
+               dbus_connection_send_with_reply(conn,msg,&pending,-1);
+               dbus_pending_call_set_notify(pending,finish_pending_call,
+                       NULL,NULL);
+                       
+       }
+       dbus_message_unref(msg);
+       return result;
+}
+
+static void usage(const char *progname)
+{
+       printf("Bluetooth passkey agent ver %s\n\n", VERSION);
+
+       printf("Usage:\n"
+               "\t%s [options]\n"
+               "\n",progname);
+       printf("Options:\n"
+       "\t -p, --path agent-path - set D-Bus object path for agent\n"
+       "\t -d, --discoverable - switch default adapter into discoverable\n" 
+       "\t\tmode whie waiting for pairing request\n"
+       "\t -P, --pair address - initiate pairing with specified address\n"
+       "\t -r, --remove address - remove pairing with specified device and exit\n");
+}
+
+static struct option main_options[] = {
+       { "path",       1, 0, 'p' },
+       { "help",       0, 0, 'h' },
+       { "version", 0, 0, 'V'}, 
+       { "discoverable",0,0,'d' },
+       { "pair",1,0,'P' },
+       { "remove",1,0,'r'},
+       { 0, 0, 0, 0 }
+};
+
+int main(int argc, char *argv[])
+{
+       struct sigaction sa;
+       DBusConnection *conn;
+       char match_string[128], default_path[128], *agent_path = NULL;
+       char *saved_mode=NULL;
+       char *default_adapter=NULL,*pair_address=NULL, *remove_bonding=NULL;
+       int opt,set_mode=0;
+
+       snprintf(default_path, sizeof(default_path),
+                               "/org/bluez/passkey_agent_%d", getpid());
+
+       while ((opt = getopt_long(argc, argv, "p:r:P:hVd", main_options, NULL)) != EOF) {
+               switch(opt) {
+               case 'p':
+                       if (optarg[0] != '/') {
+                               fprintf(stderr, "Invalid path\n");
+                               exit(1);
+                       }
+                       agent_path = strdup(optarg);
+                       break;
+               case 'd': set_mode=1;
+                       break;
+               case 'P': pair_address=optarg;
+                       break;
+               case 'r' : remove_bonding=optarg;       
+                       break;
+               case 'h':
+                       usage(argv[0]);
+
+                       exit(0);
+               case 'V':
+                       printf("btpasskey " VERSION " Copyright (c) 2007-2008, Victor Wagner\n");
+               default:
+                       fprintf(stderr,"Invalid option -%c. Use %s --help\n",
+                       opt,argv[0]);
+
+                       exit(1);
+               }
+       }
+
+
+
+       if (!agent_path)
+               agent_path = strdup(default_path);
+
+       conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
+       if (!conn) {
+               fprintf(stderr, "Can't get on system bus");
+               exit(1);
+       }
+       if (set_mode || pair_address|| remove_bonding)
+       {
+       /* With these options we need default adapter to interact */
+               default_adapter = get_default_adapter(conn);
+       }       
+       if (remove_bonding) 
+       {
+               adapter_call(conn,default_adapter,"RemoveBonding",remove_bonding,0);
+               dbus_connection_unref(conn);
+               exit(0);
+       }
+
+       if (register_agent(conn, agent_path) < 0) {
+               dbus_connection_unref(conn);
+               exit(1);
+       }
+
+       if (!dbus_connection_add_filter(conn, agent_filter, NULL, NULL))
+               fprintf(stderr, "Can't add signal filter");
+
+       snprintf(match_string, sizeof(match_string),
+                       "interface=%s,member=NameOwnerChanged,arg0=%s",
+                                       DBUS_INTERFACE_DBUS, "org.bluez");
+
+       dbus_bus_add_match(conn, match_string, NULL);
+
+       memset(&sa, 0, sizeof(sa));
+       sa.sa_flags   = SA_NOCLDSTOP;
+       sa.sa_handler = sig_term;
+       sigaction(SIGTERM, &sa, NULL);
+       sigaction(SIGINT,  &sa, NULL);
+       sigaction(SIGPIPE,  &sa, NULL);
+       setvbuf(stdin,NULL,_IONBF,0);
+       setvbuf(stdout,NULL,_IONBF,0); 
+       if (isatty(fileno(stdout))) 
+               printf("Waiting for passkey request. Press Ctrl-C to interrupt\n");
+       if (set_mode) {
+               saved_mode=adapter_call(conn,default_adapter,"GetMode",NULL,1);
+               if (strcmp(saved_mode,"discoverable")==0) 
+               { /* Already in discoverable state nothing to do*/
+                       free(saved_mode);
+                       saved_mode=NULL;
+                }
+                else
+                {
+                   adapter_call(conn,default_adapter,"SetMode","discoverable",1);
+                }
+       }
+       if (pair_address) {
+               adapter_call(conn,default_adapter,"CreateBonding", pair_address,0);
+       }
+       while (!__io_canceled && !__io_terminated) {
+               if (dbus_connection_read_write_dispatch(conn, 100) != TRUE)
+                       break;
+       }
+
+       if (!__io_terminated)
+               unregister_agent(conn, agent_path);
+
+       if (saved_mode) {
+               adapter_call(conn,default_adapter,"SetMode",saved_mode,1);
+               free(saved_mode);
+       }       
+       dbus_connection_unref(conn);
+       if (default_adapter) free(default_adapter);
+
+       return 0;
+}
diff --git a/scripts/btls b/scripts/btls
new file mode 100644 (file)
index 0000000..3581fc5
--- /dev/null
@@ -0,0 +1 @@
+dbus-send --system --type=method_call --print-reply --dest=org.bluez /org/bluez/hci0 org.bluez.Adapter.ListRemoteDevices
diff --git a/scripts/btmode b/scripts/btmode
new file mode 100755 (executable)
index 0000000..c607164
--- /dev/null
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+set -- `getopt lha: "$@"`
+if [ $? -ne 0 ]; then
+       echo "run $0 -h for help" 1>&2
+       exit 1  
+fi     
+while [ "$1" != "--" ]; do
+case "$1" in
+-l) # List adapters
+       dbus-send --system --type=method_call --print-reply --dest=org.bluez\
+       /org/bluez org.bluez.Manager.ListAdapters|sed -n 's/^ *string "\/org\/bluez\/\([^"]\+\)".*$/\1/p'
+       exit 0
+       ;;
+-a)    # get adapter from command line 
+       shift
+       adapter="/org/bluez/$1"
+       shift
+       ;;
+-h)    echo "Usage $0  [ -a adapter ] [ -l ] [mode]"
+       echo "without mode argument lists mode for specified (or default) adapter"
+       echo "with mode argument (one of connectable discoverable off) sets"
+       echo "with -l list available adapters"
+       exit
+esac   
+done
+shift
+if [ -z "$adapter" ];  then
+       adapter=`dbus-send --system --type=method_call  --print-reply \
+       --dest=org.bluez /org/bluez org.bluez.Manager.DefaultAdapter  |sed \
+       -n 's/^ *string "\([^"]\+\)".*$/\1/p'` 
+       [ -z "$adapter" ] && exit 1
+fi
+if [ -z "$1" ]; then
+       dbus-send --system --type=method_call  --print-reply \
+       --dest=org.bluez $adapter org.bluez.Adapter.GetMode  |sed \
+       -n 's/^ *string "\([^"]\+\)".*$/\1/p' 
+else
+       dbus-send --system --type=method_call  --print-reply \
+       --dest=org.bluez $adapter org.bluez.Adapter.SetMode string:$1 |grep -v  "method return"
+       #|sed \
+       #-n 's/^ *string "\([^"]\+\)".*$/\1/p' 
+
+fi     
+
+
+
+
diff --git a/scripts/listmodes b/scripts/listmodes
new file mode 100644 (file)
index 0000000..fa4ac6b
--- /dev/null
@@ -0,0 +1,3 @@
+
+dbus-send --system --type=method_call  --print-reply \
+       --dest=org.bluez /org/bluez/hci0 org.bluez.Adapter.ListAvailableModes