mirror of
https://git.kernel.org/pub/scm/bluetooth/bluez.git
synced 2024-11-15 08:14:28 +08:00
gatttool: add support for L2CAP socket connection
Connect using L2CAP by default, and add a --unix/-u option to select the Unix socket (for local testing).
This commit is contained in:
parent
fa7e72f64b
commit
f1d7e6a7a9
@ -27,20 +27,86 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <glib.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/l2cap.h>
|
||||
#include <bluetooth/hci.h>
|
||||
#include <bluetooth/hci_lib.h>
|
||||
|
||||
#define GATT_UNIX_PATH "/var/run/gatt"
|
||||
#define GATT_PSM 27
|
||||
|
||||
static gchar *opt_src = NULL;
|
||||
static gchar *opt_dst = NULL;
|
||||
static int opt_start = 0x0001;
|
||||
static int opt_end = 0xffff;
|
||||
static gboolean opt_unix = FALSE;
|
||||
static gboolean opt_primary = FALSE;
|
||||
static gboolean opt_characteristics = FALSE;
|
||||
static GMainLoop *event_loop;
|
||||
|
||||
static int l2cap_connect(void)
|
||||
{
|
||||
struct sockaddr_l2 addr;
|
||||
bdaddr_t sba, dba;
|
||||
int err, sk;
|
||||
|
||||
/* Remote device */
|
||||
if (opt_dst == NULL) {
|
||||
g_printerr("Remote Bluetooth address required\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
str2ba(opt_dst, &dba);
|
||||
|
||||
/* Local adapter */
|
||||
if (opt_src != NULL) {
|
||||
if (!strncmp(opt_src, "hci", 3))
|
||||
hci_devba(atoi(opt_src + 3), &sba);
|
||||
else
|
||||
str2ba(opt_src, &sba);
|
||||
g_free(opt_src);
|
||||
} else
|
||||
bacpy(&sba, BDADDR_ANY);
|
||||
|
||||
sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
|
||||
if (sk < 0) {
|
||||
err = errno;
|
||||
g_printerr("L2CAP socket create failed: %s(%d)\n", strerror(err), err);
|
||||
return -err;
|
||||
}
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.l2_family = AF_BLUETOOTH;
|
||||
bacpy(&addr.l2_bdaddr, &sba);
|
||||
|
||||
if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
||||
err = errno;
|
||||
g_printerr("L2CAP socket bind failed: %s(%d)\n", strerror(err), err);
|
||||
close(sk);
|
||||
return -err;
|
||||
}
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.l2_family = AF_BLUETOOTH;
|
||||
bacpy(&addr.l2_bdaddr, &dba);
|
||||
addr.l2_psm = htobs(GATT_PSM);
|
||||
|
||||
err = connect(sk, (struct sockaddr *) &addr, sizeof(addr));
|
||||
if (err < 0) {
|
||||
err = errno;
|
||||
g_printerr("L2CAP socket connect failed: %s(%d)\n", strerror(err), err);
|
||||
close(sk);
|
||||
return -err;
|
||||
}
|
||||
|
||||
return sk;
|
||||
}
|
||||
|
||||
static int unix_connect(const char *address)
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
@ -73,12 +139,16 @@ static gboolean primary(gpointer user_data)
|
||||
{
|
||||
int sk;
|
||||
|
||||
/* FIXME: implement option to select between unix/btio socket */
|
||||
sk = unix_connect(GATT_UNIX_PATH);
|
||||
if (opt_unix)
|
||||
sk = unix_connect(GATT_UNIX_PATH);
|
||||
else
|
||||
sk = l2cap_connect();
|
||||
if (sk < 0)
|
||||
return FALSE;
|
||||
goto error;
|
||||
|
||||
/* FIXME: implement "discover all primary services */
|
||||
|
||||
error:
|
||||
g_main_loop_quit(event_loop);
|
||||
|
||||
return FALSE;
|
||||
@ -101,6 +171,8 @@ static GOptionEntry gatt_options[] = {
|
||||
};
|
||||
|
||||
static GOptionEntry options[] = {
|
||||
{ "unix", 'u', 0, G_OPTION_ARG_NONE, &opt_unix,
|
||||
"Connect to server using Unix socket" , NULL },
|
||||
{ "adapter", 'i', 0, G_OPTION_ARG_STRING, &opt_src,
|
||||
"Specify local adapter interface", "hciX" },
|
||||
{ "device", 'b', 0, G_OPTION_ARG_STRING, &opt_dst,
|
||||
|
Loading…
Reference in New Issue
Block a user