btio: Add L2CAP fixed channels support

Add new option BT_IO_OPT_CID to allow listen and connect using a fixed
L2CAP channel for BTIO.
This commit is contained in:
Claudio Takahasi 2010-07-20 18:33:40 -03:00 committed by Marcel Holtmann
parent e4ef929aee
commit 26de869580
2 changed files with 28 additions and 10 deletions

View File

@ -53,6 +53,7 @@ struct set_opts {
int sec_level; int sec_level;
uint8_t channel; uint8_t channel;
uint16_t psm; uint16_t psm;
uint16_t cid;
uint16_t mtu; uint16_t mtu;
uint16_t imtu; uint16_t imtu;
uint16_t omtu; uint16_t omtu;
@ -250,14 +251,19 @@ static void accept_add(GIOChannel *io, BtIOConnect connect, gpointer user_data,
(GDestroyNotify) accept_remove); (GDestroyNotify) accept_remove);
} }
static int l2cap_bind(int sock, const bdaddr_t *src, uint16_t psm, GError **err) static int l2cap_bind(int sock, const bdaddr_t *src, uint16_t psm,
uint16_t cid, GError **err)
{ {
struct sockaddr_l2 addr; struct sockaddr_l2 addr;
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
addr.l2_family = AF_BLUETOOTH; addr.l2_family = AF_BLUETOOTH;
bacpy(&addr.l2_bdaddr, src); bacpy(&addr.l2_bdaddr, src);
addr.l2_psm = htobs(psm);
if (cid)
addr.l2_cid = htobs(cid);
else
addr.l2_psm = htobs(psm);
if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
ERROR_FAILED(err, "l2cap_bind", errno); ERROR_FAILED(err, "l2cap_bind", errno);
@ -267,7 +273,8 @@ static int l2cap_bind(int sock, const bdaddr_t *src, uint16_t psm, GError **err)
return 0; return 0;
} }
static int l2cap_connect(int sock, const bdaddr_t *dst, uint16_t psm) static int l2cap_connect(int sock, const bdaddr_t *dst,
uint16_t psm, uint16_t cid)
{ {
int err; int err;
struct sockaddr_l2 addr; struct sockaddr_l2 addr;
@ -275,7 +282,10 @@ static int l2cap_connect(int sock, const bdaddr_t *dst, uint16_t psm)
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
addr.l2_family = AF_BLUETOOTH; addr.l2_family = AF_BLUETOOTH;
bacpy(&addr.l2_bdaddr, dst); bacpy(&addr.l2_bdaddr, dst);
addr.l2_psm = htobs(psm); if (cid)
addr.l2_cid = htobs(cid);
else
addr.l2_psm = htobs(psm);
err = connect(sock, (struct sockaddr *) &addr, sizeof(addr)); err = connect(sock, (struct sockaddr *) &addr, sizeof(addr));
if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS))
@ -664,6 +674,9 @@ static gboolean parse_set_opts(struct set_opts *opts, GError **err,
case BT_IO_OPT_PSM: case BT_IO_OPT_PSM:
opts->psm = va_arg(args, int); opts->psm = va_arg(args, int);
break; break;
case BT_IO_OPT_CID:
opts->cid = va_arg(args, int);
break;
case BT_IO_OPT_MTU: case BT_IO_OPT_MTU:
opts->mtu = va_arg(args, int); opts->mtu = va_arg(args, int);
opts->imtu = opts->mtu; opts->imtu = opts->mtu;
@ -791,6 +804,10 @@ static gboolean l2cap_get(int sock, GError **err, BtIOOption opt1,
*(va_arg(args, uint16_t *)) = src.l2_psm ? *(va_arg(args, uint16_t *)) = src.l2_psm ?
src.l2_psm : dst.l2_psm; src.l2_psm : dst.l2_psm;
break; break;
case BT_IO_OPT_CID:
*(va_arg(args, uint16_t *)) = src.l2_cid ?
src.l2_cid : dst.l2_cid;
break;
case BT_IO_OPT_OMTU: case BT_IO_OPT_OMTU:
*(va_arg(args, uint16_t *)) = l2o.omtu; *(va_arg(args, uint16_t *)) = l2o.omtu;
break; break;
@ -1133,8 +1150,8 @@ static GIOChannel *create_io(BtIOType type, gboolean server,
ERROR_FAILED(err, "socket(RAW, L2CAP)", errno); ERROR_FAILED(err, "socket(RAW, L2CAP)", errno);
return NULL; return NULL;
} }
if (l2cap_bind(sock, &opts->src, if (l2cap_bind(sock, &opts->src, server ? opts->psm : 0,
server ? opts->psm : 0, err) < 0) opts->cid, err) < 0)
goto failed; goto failed;
if (!l2cap_set(sock, opts->sec_level, 0, 0, 0, -1, err)) if (!l2cap_set(sock, opts->sec_level, 0, 0, 0, -1, err))
goto failed; goto failed;
@ -1145,8 +1162,8 @@ static GIOChannel *create_io(BtIOType type, gboolean server,
ERROR_FAILED(err, "socket(SEQPACKET, L2CAP)", errno); ERROR_FAILED(err, "socket(SEQPACKET, L2CAP)", errno);
return NULL; return NULL;
} }
if (l2cap_bind(sock, &opts->src, if (l2cap_bind(sock, &opts->src, server ? opts->psm : 0,
server ? opts->psm : 0, err) < 0) opts->cid, err) < 0)
goto failed; goto failed;
if (!l2cap_set(sock, opts->sec_level, opts->imtu, opts->omtu, if (!l2cap_set(sock, opts->sec_level, opts->imtu, opts->omtu,
opts->mode, opts->master, err)) opts->mode, opts->master, err))
@ -1219,10 +1236,10 @@ GIOChannel *bt_io_connect(BtIOType type, BtIOConnect connect,
switch (type) { switch (type) {
case BT_IO_L2RAW: case BT_IO_L2RAW:
err = l2cap_connect(sock, &opts.dst, 0); err = l2cap_connect(sock, &opts.dst, 0, opts.cid);
break; break;
case BT_IO_L2CAP: case BT_IO_L2CAP:
err = l2cap_connect(sock, &opts.dst, opts.psm); err = l2cap_connect(sock, &opts.dst, opts.psm, opts.cid);
break; break;
case BT_IO_RFCOMM: case BT_IO_RFCOMM:
err = rfcomm_connect(sock, &opts.dst, opts.channel); err = rfcomm_connect(sock, &opts.dst, opts.channel);

View File

@ -56,6 +56,7 @@ typedef enum {
BT_IO_OPT_SOURCE_CHANNEL, BT_IO_OPT_SOURCE_CHANNEL,
BT_IO_OPT_DEST_CHANNEL, BT_IO_OPT_DEST_CHANNEL,
BT_IO_OPT_PSM, BT_IO_OPT_PSM,
BT_IO_OPT_CID,
BT_IO_OPT_MTU, BT_IO_OPT_MTU,
BT_IO_OPT_OMTU, BT_IO_OPT_OMTU,
BT_IO_OPT_IMTU, BT_IO_OPT_IMTU,