summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@nokia.com>2009-02-20 00:21:18 +0200
committerJohan Hedberg <johan.hedberg@nokia.com>2009-02-20 00:21:18 +0200
commit3d579217297b23df62123eba7807a66b0b93cd1c (patch)
treecc71cdf31a142a7a2d03b9804acaa6cd16210acc /common
parent9b0acaa2621f6a5db077644d2a5a816017eae4b5 (diff)
Add support for getting connection info
Diffstat (limited to 'common')
-rw-r--r--common/btio.c93
-rw-r--r--common/btio.h2
2 files changed, 95 insertions, 0 deletions
diff --git a/common/btio.c b/common/btio.c
index 727ff624..f9a1507d 100644
--- a/common/btio.c
+++ b/common/btio.c
@@ -680,6 +680,24 @@ static gboolean get_peers(int sock, struct sockaddr *src, struct sockaddr *dst,
return TRUE;
}
+static int l2cap_get_info(int sock, uint16_t *handle, uint8_t *dev_class)
+{
+ struct l2cap_conninfo info;
+ socklen_t len;
+
+ len = sizeof(info);
+ if (getsockopt(sock, SOL_L2CAP, L2CAP_CONNINFO, &info, &len) < 0)
+ return -errno;
+
+ if (handle)
+ *handle = info.hci_handle;
+
+ if (dev_class)
+ memcpy(dev_class, info.dev_class, 3);
+
+ return 0;
+}
+
static gboolean l2cap_get(int sock, GError **err, BtIOOption opt1,
va_list args)
{
@@ -687,6 +705,8 @@ static gboolean l2cap_get(int sock, GError **err, BtIOOption opt1,
struct sockaddr_l2 src, dst;
struct l2cap_options l2o;
int flags;
+ uint8_t dev_class[3];
+ uint16_t handle;
socklen_t len;
len = sizeof(l2o);
@@ -700,6 +720,11 @@ static gboolean l2cap_get(int sock, GError **err, BtIOOption opt1,
(struct sockaddr *) &dst, sizeof(src), err))
return FALSE;
+ if (l2cap_get_info(sock, &handle, dev_class) < 0) {
+ ERROR_FAILED(err, "L2CAP_CONNINFO", errno);
+ return FALSE;
+ }
+
while (opt != BT_IO_OPT_INVALID) {
switch (opt) {
case BT_IO_OPT_SOURCE:
@@ -749,6 +774,12 @@ static gboolean l2cap_get(int sock, GError **err, BtIOOption opt1,
*(va_arg(args, gboolean *)) =
(flags & L2CAP_LM_MASTER) ? TRUE : FALSE;
break;
+ case BT_IO_OPT_HANDLE:
+ *(va_arg(args, uint16_t *)) = handle;
+ break;
+ case BT_IO_OPT_CLASS:
+ memcpy(va_arg(args, uint8_t *), dev_class, 3);
+ break;
default:
g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
"Unknown option %d", opt);
@@ -761,6 +792,24 @@ static gboolean l2cap_get(int sock, GError **err, BtIOOption opt1,
return TRUE;
}
+static int rfcomm_get_info(int sock, uint16_t *handle, uint8_t *dev_class)
+{
+ struct rfcomm_conninfo info;
+ socklen_t len;
+
+ len = sizeof(info);
+ if (getsockopt(sock, SOL_RFCOMM, RFCOMM_CONNINFO, &info, &len) < 0)
+ return -errno;
+
+ if (handle)
+ *handle = info.hci_handle;
+
+ if (dev_class)
+ memcpy(dev_class, info.dev_class, 3);
+
+ return 0;
+}
+
static gboolean rfcomm_get(int sock, GError **err, BtIOOption opt1,
va_list args)
{
@@ -768,11 +817,18 @@ static gboolean rfcomm_get(int sock, GError **err, BtIOOption opt1,
struct sockaddr_rc src, dst;
int flags;
socklen_t len;
+ uint8_t dev_class[3];
+ uint16_t handle;
if (!get_peers(sock, (struct sockaddr *) &src,
(struct sockaddr *) &dst, sizeof(src), err))
return FALSE;
+ if (rfcomm_get_info(sock, &handle, dev_class) < 0) {
+ ERROR_FAILED(err, "RFCOMM_CONNINFO", errno);
+ return FALSE;
+ }
+
while (opt != BT_IO_OPT_INVALID) {
switch (opt) {
case BT_IO_OPT_SOURCE:
@@ -816,6 +872,12 @@ static gboolean rfcomm_get(int sock, GError **err, BtIOOption opt1,
*(va_arg(args, gboolean *)) =
(flags & RFCOMM_LM_MASTER) ? TRUE : FALSE;
break;
+ case BT_IO_OPT_HANDLE:
+ *(va_arg(args, uint16_t *)) = handle;
+ break;
+ case BT_IO_OPT_CLASS:
+ memcpy(va_arg(args, uint8_t *), dev_class, 3);
+ break;
default:
g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
"Unknown option %d", opt);
@@ -828,12 +890,32 @@ static gboolean rfcomm_get(int sock, GError **err, BtIOOption opt1,
return TRUE;
}
+static int sco_get_info(int sock, uint16_t *handle, uint8_t *dev_class)
+{
+ struct sco_conninfo info;
+ socklen_t len;
+
+ len = sizeof(info);
+ if (getsockopt(sock, SOL_SCO, SCO_CONNINFO, &info, &len) < 0)
+ return -errno;
+
+ if (handle)
+ *handle = info.hci_handle;
+
+ if (dev_class)
+ memcpy(dev_class, info.dev_class, 3);
+
+ return 0;
+}
+
static gboolean sco_get(int sock, GError **err, BtIOOption opt1, va_list args)
{
BtIOOption opt = opt1;
struct sockaddr_sco src, dst;
struct sco_options sco_opt;
socklen_t len;
+ uint8_t dev_class[3];
+ uint16_t handle;
len = sizeof(sco_opt);
memset(&sco_opt, 0, len);
@@ -846,6 +928,11 @@ static gboolean sco_get(int sock, GError **err, BtIOOption opt1, va_list args)
(struct sockaddr *) &dst, sizeof(src), err))
return FALSE;
+ if (sco_get_info(sock, &handle, dev_class) < 0) {
+ ERROR_FAILED(err, "RFCOMM_CONNINFO", errno);
+ return FALSE;
+ }
+
while (opt != BT_IO_OPT_INVALID) {
switch (opt) {
case BT_IO_OPT_SOURCE:
@@ -865,6 +952,12 @@ static gboolean sco_get(int sock, GError **err, BtIOOption opt1, va_list args)
case BT_IO_OPT_OMTU:
*(va_arg(args, uint16_t *)) = sco_opt.mtu;
break;
+ case BT_IO_OPT_HANDLE:
+ *(va_arg(args, uint16_t *)) = handle;
+ break;
+ case BT_IO_OPT_CLASS:
+ memcpy(va_arg(args, uint8_t *), dev_class, 3);
+ break;
default:
g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS,
"Unknown option %d", opt);
diff --git a/common/btio.h b/common/btio.h
index 07ebea50..a202da9d 100644
--- a/common/btio.h
+++ b/common/btio.h
@@ -57,6 +57,8 @@ typedef enum {
BT_IO_OPT_OMTU,
BT_IO_OPT_IMTU,
BT_IO_OPT_MASTER,
+ BT_IO_OPT_HANDLE,
+ BT_IO_OPT_CLASS,
BT_IO_OPT_INVALID,
} BtIOOption;