@@ -16,6 +16,7 @@
#include <stdarg.h>
#include <stdlib.h>
+#include <stdbool.h>
#include <unistd.h>
#include <errno.h>
#include <poll.h>
@@ -71,6 +72,9 @@ struct set_opts {
uint16_t voice;
struct bt_iso_qos qos;
struct bt_iso_base base;
+ uint8_t bc_sid;
+ uint8_t bc_num_bis;
+ uint8_t bc_bis[ISO_MAX_NUM_BIS];
};
struct connect {
@@ -771,21 +775,47 @@ static int sco_bind(int sock, const bdaddr_t *src, GError **err)
}
static int iso_bind(int sock, const bdaddr_t *src, uint8_t src_type,
- GError **err)
+ const bdaddr_t *dst, uint8_t dst_type,
+ uint8_t bc_sid, uint8_t num_bis,
+ uint8_t *bis, GError **err)
{
- struct sockaddr_iso addr;
+ struct sockaddr_iso *addr = NULL;
+ size_t addr_len;
+ int ret = 0;
- memset(&addr, 0, sizeof(addr));
- addr.iso_family = AF_BLUETOOTH;
- bacpy(&addr.iso_bdaddr, src);
- addr.iso_bdaddr_type = src_type;
+ if (num_bis)
+ addr_len = sizeof(*addr) + sizeof(*addr->iso_bc);
+ else
+ addr_len = sizeof(*addr);
+
+ addr = malloc(addr_len);
+
+ if (!addr)
+ return -ENOMEM;
+
+ memset(addr, 0, addr_len);
+ addr->iso_family = AF_BLUETOOTH;
+ bacpy(&addr->iso_bdaddr, src);
+ addr->iso_bdaddr_type = src_type;
- if (!bind(sock, (struct sockaddr *) &addr, sizeof(addr)))
- return 0;
+ if (num_bis) {
+ bacpy(&addr->iso_bc->bc_bdaddr, dst);
+ addr->iso_bc->bc_bdaddr_type = dst_type;
+ addr->iso_bc->bc_sid = bc_sid;
+ addr->iso_bc->bc_num_bis = num_bis;
+ memcpy(addr->iso_bc->bc_bis, bis,
+ addr->iso_bc->bc_num_bis);
+ }
+
+ if (!bind(sock, (struct sockaddr *)addr, addr_len))
+ goto done;
+ ret = -errno;
ERROR_FAILED(err, "iso_bind", errno);
- return -errno;
+done:
+ free(addr);
+ return ret;
}
static int sco_connect(int sock, const bdaddr_t *dst)
@@ -980,6 +1010,16 @@ static gboolean parse_set_opts(struct set_opts *opts, GError **err,
case BT_IO_OPT_BASE:
opts->base = *va_arg(args, struct bt_iso_base *);
break;
+ case BT_IO_OPT_ISO_BC_SID:
+ opts->bc_sid = va_arg(args, int);
+ break;
+ case BT_IO_OPT_ISO_BC_NUM_BIS:
+ opts->bc_num_bis = va_arg(args, int);
+ break;
+ case BT_IO_OPT_ISO_BC_BIS:
+ memcpy(opts->bc_bis, va_arg(args, uint8_t *),
+ opts->bc_num_bis);
+ break;
case BT_IO_OPT_INVALID:
case BT_IO_OPT_KEY_SIZE:
case BT_IO_OPT_SOURCE_CHANNEL:
@@ -1305,6 +1345,9 @@ parse_opts:
case BT_IO_OPT_VOICE:
case BT_IO_OPT_QOS:
case BT_IO_OPT_BASE:
+ case BT_IO_OPT_ISO_BC_SID:
+ case BT_IO_OPT_ISO_BC_NUM_BIS:
+ case BT_IO_OPT_ISO_BC_BIS:
default:
g_set_error(err, BT_IO_ERROR, EINVAL,
"Unknown option %d", opt);
@@ -1460,6 +1503,9 @@ static gboolean rfcomm_get(int sock, GError **err, BtIOOption opt1,
case BT_IO_OPT_VOICE:
case BT_IO_OPT_QOS:
case BT_IO_OPT_BASE:
+ case BT_IO_OPT_ISO_BC_SID:
+ case BT_IO_OPT_ISO_BC_NUM_BIS:
+ case BT_IO_OPT_ISO_BC_BIS:
case BT_IO_OPT_INVALID:
default:
g_set_error(err, BT_IO_ERROR, EINVAL,
@@ -1571,6 +1617,9 @@ static gboolean sco_get(int sock, GError **err, BtIOOption opt1, va_list args)
case BT_IO_OPT_VOICE:
case BT_IO_OPT_QOS:
case BT_IO_OPT_BASE:
+ case BT_IO_OPT_ISO_BC_SID:
+ case BT_IO_OPT_ISO_BC_NUM_BIS:
+ case BT_IO_OPT_ISO_BC_BIS:
case BT_IO_OPT_INVALID:
default:
g_set_error(err, BT_IO_ERROR, EINVAL,
@@ -1660,6 +1709,9 @@ static gboolean iso_get(int sock, GError **err, BtIOOption opt1, va_list args)
case BT_IO_OPT_FLUSHABLE:
case BT_IO_OPT_PRIORITY:
case BT_IO_OPT_VOICE:
+ case BT_IO_OPT_ISO_BC_SID:
+ case BT_IO_OPT_ISO_BC_NUM_BIS:
+ case BT_IO_OPT_ISO_BC_BIS:
case BT_IO_OPT_INVALID:
default:
g_set_error(err, BT_IO_ERROR, EINVAL,
@@ -1836,7 +1888,11 @@ static GIOChannel *create_io(gboolean server, struct set_opts *opts,
ERROR_FAILED(err, "socket(SEQPACKET, ISO)", errno);
return NULL;
}
- if (iso_bind(sock, &opts->src, opts->src_type, err) < 0)
+
+ if (iso_bind(sock, &opts->src, opts->src_type,
+ &opts->dst, opts->dst_type,
+ opts->bc_sid, opts->bc_num_bis,
+ opts->bc_bis, err) < 0)
goto failed;
if (!iso_set_qos(sock, &opts->qos, err))
goto failed;
@@ -46,7 +46,10 @@ typedef enum {
BT_IO_OPT_VOICE,
BT_IO_OPT_PHY,
BT_IO_OPT_QOS,
- BT_IO_OPT_BASE
+ BT_IO_OPT_BASE,
+ BT_IO_OPT_ISO_BC_SID,
+ BT_IO_OPT_ISO_BC_NUM_BIS,
+ BT_IO_OPT_ISO_BC_BIS,
} BtIOOption;
typedef enum {