diff options
| author | Johan Hedberg <johan.hedberg@nokia.com> | 2009-02-20 00:21:18 +0200 | 
|---|---|---|
| committer | Johan Hedberg <johan.hedberg@nokia.com> | 2009-02-20 00:21:18 +0200 | 
| commit | 3d579217297b23df62123eba7807a66b0b93cd1c (patch) | |
| tree | cc71cdf31a142a7a2d03b9804acaa6cd16210acc | |
| parent | 9b0acaa2621f6a5db077644d2a5a816017eae4b5 (diff) | |
Add support for getting connection info
| -rw-r--r-- | common/btio.c | 93 | ||||
| -rw-r--r-- | common/btio.h | 2 | ||||
| -rw-r--r-- | test/btiotest.c | 10 | 
3 files changed, 103 insertions, 2 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; diff --git a/test/btiotest.c b/test/btiotest.c index ede8a452..906d3853 100644 --- a/test/btiotest.c +++ b/test/btiotest.c @@ -99,13 +99,18 @@ static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)  	struct io_data *data = user_data;  	GIOCondition cond;  	char addr[18]; +	uint16_t handle; +	uint8_t cls[3];  	if (err) {  		printf("Connecting failed: %s\n", err->message);  		return;  	} -	if (!bt_io_get(io, data->type, &err, BT_IO_OPT_DEST, addr, +	if (!bt_io_get(io, data->type, &err, +			BT_IO_OPT_DEST, addr, +			BT_IO_OPT_HANDLE, &handle, +			BT_IO_OPT_CLASS, cls,  			BT_IO_OPT_INVALID)) {  		printf("Unable to get destination address: %s\n",  								err->message); @@ -113,7 +118,8 @@ static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)  		strcpy(addr, "(unknown)");  	} -	printf("Successfully connected to %s\n", addr); +	printf("Successfully connected to %s. handle=%u, class=%02x%02x%02x\n", +			addr, handle, cls[0], cls[1], cls[2]);  	if (data->type == BT_IO_L2CAP || data->type == BT_IO_SCO) {  		uint16_t omtu, imtu; | 
