* Re: [RFC] Proposal to distinguish address device types
From: Gustavo F. Padovan @ 2011-04-15 18:47 UTC (permalink / raw)
To: Claudio Takahasi; +Cc: johan.hedberg, marcel, linux-bluetooth
In-Reply-To: <1302892422-32206-1-git-send-email-claudio.takahasi@openbossa.org>
Hi Claudio,
* Claudio Takahasi <claudio.takahasi@openbossa.org> [2011-04-15 15:33:42 -0300]:
> Device type is input to decide how to establish the L2CAP connection.
> For LE devices fixed channel ID 4 is set, otherwise PSM should be set
> for basic rate connections. LE public and random constants are misused
> for discovery, however I don't see advantage of defining basic rate and
> LE values only.
>
> Based on jhe/master:
> git://git.kernel.org/pub/scm/linux/kernel/git/jh/linux-2.6.git
>
> Opinions?
> ---
> include/net/bluetooth/bluetooth.h | 6 ++++++
> include/net/bluetooth/hci_core.h | 4 ++--
> include/net/bluetooth/mgmt.h | 1 +
> net/bluetooth/hci_event.c | 16 ++++++++--------
> net/bluetooth/mgmt.c | 5 +++--
> 5 files changed, 20 insertions(+), 12 deletions(-)
>
> diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
> index 4375043..b91eec9 100644
> --- a/include/net/bluetooth/bluetooth.h
> +++ b/include/net/bluetooth/bluetooth.h
> @@ -94,6 +94,12 @@ typedef struct {
> #define BDADDR_ANY (&(bdaddr_t) {{0, 0, 0, 0, 0, 0}})
> #define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff}})
>
> +enum {
> + BDADDR_TYPE_BR = 0,
As we going to differentiate this, can't we separate BR and BR/EDR?
Or maybe not once most of the device today should be BR/EDR.
> + BDADDR_TYPE_LE_PUBLIC,
> + BRADDR_TYPE_LE_RANDOM
> +};
> +
> /* Copy, swap, convert BD Address */
> static inline int bacmp(bdaddr_t *ba1, bdaddr_t *ba2)
> {
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index 8200704..b357346 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -808,8 +808,8 @@ int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status);
> int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status);
> int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer,
> u8 status);
> -int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi,
> - u8 *eir);
> +int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 bdaddr_type,
> + u8 *dev_class, s8 rssi, u8 *eir);
> int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name);
> int mgmt_periodic_inq_complete(u16 index, u8 status);
> int mgmt_exit_periodic_inq_complete(u16 index, u8 status);
> diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
> index 2a70541..c299f6a 100644
> --- a/include/net/bluetooth/mgmt.h
> +++ b/include/net/bluetooth/mgmt.h
> @@ -281,6 +281,7 @@ struct mgmt_ev_local_name_changed {
> #define MGMT_EV_DEVICE_FOUND 0x0012
> struct mgmt_ev_device_found {
> bdaddr_t bdaddr;
> + __u8 bdaddr_type;
> __u8 dev_class[3];
> __s8 rssi;
> __u8 eir[HCI_MAX_EIR_LENGTH];
> diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
> index ded8e0c..997d8f6 100644
> --- a/net/bluetooth/hci_event.c
> +++ b/net/bluetooth/hci_event.c
> @@ -1285,8 +1285,8 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *
> if (!test_bit(HCI_MGMT, &hdev->flags))
> continue;
>
> - mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, 0,
> - NULL);
> + mgmt_device_found(hdev->id, &info->bdaddr, BDADDR_TYPE_BR,
> + info->dev_class, 0, NULL);
>
> if (test_bit(HCI_DISCOVERY, &hdev->flags))
> hci_add_found_device(hdev, &info->bdaddr, 0x00);
> @@ -2257,8 +2257,8 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
> continue;
>
> mgmt_device_found(hdev->id, &info->bdaddr,
> - info->dev_class, info->rssi,
> - NULL);
> + BDADDR_TYPE_BR, info->dev_class,
> + info->rssi, NULL);
>
> if (!test_bit(HCI_DISCOVERY, &hdev->flags))
> continue;
> @@ -2283,8 +2283,8 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
> continue;
>
> mgmt_device_found(hdev->id, &info->bdaddr,
> - info->dev_class, info->rssi,
> - NULL);
> + BDADDR_TYPE_BR, info->dev_class,
> + info->rssi, NULL);
>
> if (!test_bit(HCI_DISCOVERY, &hdev->flags))
> continue;
> @@ -2465,8 +2465,8 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
> if (!test_bit(HCI_MGMT, &hdev->flags))
> continue;
>
> - mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class,
> - info->rssi, info->data);
> + mgmt_device_found(hdev->id, &info->bdaddr, BDADDR_TYPE_BR,
> + info->dev_class, info->rssi, info->data);
>
> if (!test_bit(HCI_DISCOVERY, &hdev->flags))
> continue;
> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
> index 2b20ee9..ad673f2 100644
> --- a/net/bluetooth/mgmt.c
> +++ b/net/bluetooth/mgmt.c
> @@ -2157,14 +2157,15 @@ int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer,
> return err;
> }
>
> -int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi,
> - u8 *eir)
> +int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 bdaddr_type,
> + u8 *dev_class, s8 rssi, u8 *eir)
> {
> struct mgmt_ev_device_found ev;
>
> memset(&ev, 0, sizeof(ev));
>
> bacpy(&ev.bdaddr, bdaddr);
> + ev.bdaddr_type = bdaddr_type;
> memcpy(ev.dev_class, dev_class, sizeof(ev.dev_class));
> ev.rssi = rssi;
Otherwise looks good.
--
Gustavo F. Padovan
http://profusion.mobi
^ permalink raw reply
* [RFC] Proposal to distinguish address device types
From: Claudio Takahasi @ 2011-04-15 18:33 UTC (permalink / raw)
To: johan.hedberg, marcel, linux-bluetooth; +Cc: Claudio Takahasi
Device type is input to decide how to establish the L2CAP connection.
For LE devices fixed channel ID 4 is set, otherwise PSM should be set
for basic rate connections. LE public and random constants are misused
for discovery, however I don't see advantage of defining basic rate and
LE values only.
Based on jhe/master:
git://git.kernel.org/pub/scm/linux/kernel/git/jh/linux-2.6.git
Opinions?
---
include/net/bluetooth/bluetooth.h | 6 ++++++
include/net/bluetooth/hci_core.h | 4 ++--
include/net/bluetooth/mgmt.h | 1 +
net/bluetooth/hci_event.c | 16 ++++++++--------
net/bluetooth/mgmt.c | 5 +++--
5 files changed, 20 insertions(+), 12 deletions(-)
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 4375043..b91eec9 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -94,6 +94,12 @@ typedef struct {
#define BDADDR_ANY (&(bdaddr_t) {{0, 0, 0, 0, 0, 0}})
#define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff}})
+enum {
+ BDADDR_TYPE_BR = 0,
+ BDADDR_TYPE_LE_PUBLIC,
+ BRADDR_TYPE_LE_RANDOM
+};
+
/* Copy, swap, convert BD Address */
static inline int bacmp(bdaddr_t *ba1, bdaddr_t *ba2)
{
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 8200704..b357346 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -808,8 +808,8 @@ int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status);
int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status);
int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer,
u8 status);
-int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi,
- u8 *eir);
+int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 bdaddr_type,
+ u8 *dev_class, s8 rssi, u8 *eir);
int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name);
int mgmt_periodic_inq_complete(u16 index, u8 status);
int mgmt_exit_periodic_inq_complete(u16 index, u8 status);
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 2a70541..c299f6a 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -281,6 +281,7 @@ struct mgmt_ev_local_name_changed {
#define MGMT_EV_DEVICE_FOUND 0x0012
struct mgmt_ev_device_found {
bdaddr_t bdaddr;
+ __u8 bdaddr_type;
__u8 dev_class[3];
__s8 rssi;
__u8 eir[HCI_MAX_EIR_LENGTH];
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index ded8e0c..997d8f6 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1285,8 +1285,8 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *
if (!test_bit(HCI_MGMT, &hdev->flags))
continue;
- mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, 0,
- NULL);
+ mgmt_device_found(hdev->id, &info->bdaddr, BDADDR_TYPE_BR,
+ info->dev_class, 0, NULL);
if (test_bit(HCI_DISCOVERY, &hdev->flags))
hci_add_found_device(hdev, &info->bdaddr, 0x00);
@@ -2257,8 +2257,8 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
continue;
mgmt_device_found(hdev->id, &info->bdaddr,
- info->dev_class, info->rssi,
- NULL);
+ BDADDR_TYPE_BR, info->dev_class,
+ info->rssi, NULL);
if (!test_bit(HCI_DISCOVERY, &hdev->flags))
continue;
@@ -2283,8 +2283,8 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
continue;
mgmt_device_found(hdev->id, &info->bdaddr,
- info->dev_class, info->rssi,
- NULL);
+ BDADDR_TYPE_BR, info->dev_class,
+ info->rssi, NULL);
if (!test_bit(HCI_DISCOVERY, &hdev->flags))
continue;
@@ -2465,8 +2465,8 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
if (!test_bit(HCI_MGMT, &hdev->flags))
continue;
- mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class,
- info->rssi, info->data);
+ mgmt_device_found(hdev->id, &info->bdaddr, BDADDR_TYPE_BR,
+ info->dev_class, info->rssi, info->data);
if (!test_bit(HCI_DISCOVERY, &hdev->flags))
continue;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 2b20ee9..ad673f2 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2157,14 +2157,15 @@ int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer,
return err;
}
-int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi,
- u8 *eir)
+int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 bdaddr_type,
+ u8 *dev_class, s8 rssi, u8 *eir)
{
struct mgmt_ev_device_found ev;
memset(&ev, 0, sizeof(ev));
bacpy(&ev.bdaddr, bdaddr);
+ ev.bdaddr_type = bdaddr_type;
memcpy(ev.dev_class, dev_class, sizeof(ev.dev_class));
ev.rssi = rssi;
--
1.7.4.1
^ permalink raw reply related
* [PATCH 8/8] Bluetooth: Move conn to struct l2cap_chan
From: Gustavo F. Padovan @ 2011-04-15 18:17 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1302891454-10165-8-git-send-email-padovan@profusion.mobi>
There is no need to the socket deal directly with the channel, most of the
time it cares about the channel only.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
include/net/bluetooth/l2cap.h | 7 ++-
net/bluetooth/l2cap_core.c | 92 ++++++++++++++++++-----------------------
net/bluetooth/l2cap_sock.c | 12 +++--
net/bluetooth/rfcomm/core.c | 8 ++-
net/bluetooth/rfcomm/sock.c | 5 +-
5 files changed, 59 insertions(+), 65 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index fd199cd..3de90a9 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -284,6 +284,9 @@ struct srej_list {
struct l2cap_chan {
struct sock *sk;
+
+ struct l2cap_conn *conn;
+
__le16 psm;
__u16 dcid;
__u16 scid;
@@ -385,8 +388,6 @@ struct l2cap_conn {
struct l2cap_pinfo {
struct bt_sock bt;
-
- struct l2cap_conn *conn;
struct l2cap_chan *chan;
};
@@ -447,7 +448,7 @@ int l2cap_init_sockets(void);
void l2cap_cleanup_sockets(void);
void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data);
-void __l2cap_connect_rsp_defer(struct sock *sk);
+void __l2cap_connect_rsp_defer(struct l2cap_chan *chan);
int __l2cap_wait_ack(struct sock *sk);
struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 3ff8840..8680161 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -169,7 +169,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
conn->disc_reason = 0x13;
- l2cap_pi(sk)->conn = conn;
+ chan->conn = conn;
if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
if (conn->hcon->type == LE_LINK) {
@@ -204,7 +204,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
void l2cap_chan_del(struct l2cap_chan *chan, int err)
{
struct sock *sk = chan->sk;
- struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+ struct l2cap_conn *conn = chan->conn;
struct sock *parent = bt_sk(sk)->parent;
l2cap_sock_clear_timer(sk);
@@ -218,7 +218,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
write_unlock_bh(&conn->chan_lock);
__sock_put(sk);
- l2cap_pi(sk)->conn = NULL;
+ chan->conn = NULL;
hci_conn_put(conn->hcon);
}
@@ -296,7 +296,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
/* Service level security */
static inline int l2cap_check_security(struct l2cap_chan *chan)
{
- struct l2cap_conn *conn = l2cap_pi(chan->sk)->conn;
+ struct l2cap_conn *conn = chan->conn;
__u8 auth_type;
auth_type = l2cap_get_auth_type(chan);
@@ -349,7 +349,7 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
struct sk_buff *skb;
struct l2cap_hdr *lh;
struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
- struct l2cap_conn *conn = pi->conn;
+ struct l2cap_conn *conn = chan->conn;
struct sock *sk = (struct sock *)pi;
int count, hlen = L2CAP_HDR_SIZE + 2;
u8 flags;
@@ -394,7 +394,7 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
else
flags = ACL_START;
- hci_send_acl(pi->conn->hcon, skb, flags);
+ hci_send_acl(chan->conn->hcon, skb, flags);
}
static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
@@ -417,8 +417,7 @@ static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
static void l2cap_do_start(struct l2cap_chan *chan)
{
- struct sock *sk = chan->sk;
- struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+ struct l2cap_conn *conn = chan->conn;
if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
@@ -920,12 +919,13 @@ done:
int __l2cap_wait_ack(struct sock *sk)
{
+ struct l2cap_chan *chan = l2cap_pi(sk)->chan;
DECLARE_WAITQUEUE(wait, current);
int err = 0;
int timeo = HZ/5;
add_wait_queue(sk_sleep(sk), &wait);
- while ((l2cap_pi(sk)->chan->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
+ while ((chan->unacked_frames > 0 && chan->conn)) {
set_current_state(TASK_INTERRUPTIBLE);
if (!timeo)
@@ -958,7 +958,7 @@ static void l2cap_monitor_timeout(unsigned long arg)
bh_lock_sock(sk);
if (chan->retry_count >= chan->remote_max_tx) {
- l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, ECONNABORTED);
+ l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
bh_unlock_sock(sk);
return;
}
@@ -1008,8 +1008,7 @@ static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
{
- struct sock *sk = chan->sk;
- struct hci_conn *hcon = l2cap_pi(sk)->conn->hcon;
+ struct hci_conn *hcon = chan->conn->hcon;
u16 flags;
BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
@@ -1045,8 +1044,6 @@ void l2cap_streaming_send(struct l2cap_chan *chan)
static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
{
- struct sock *sk = chan->sk;
- struct l2cap_pinfo *pi = l2cap_pi(sk);
struct sk_buff *skb, *tx_skb;
u16 control, fcs;
@@ -1065,7 +1062,7 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
if (chan->remote_max_tx &&
bt_cb(skb)->retries == chan->remote_max_tx) {
- l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
+ l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
return;
}
@@ -1095,7 +1092,6 @@ int l2cap_ertm_send(struct l2cap_chan *chan)
{
struct sk_buff *skb, *tx_skb;
struct sock *sk = chan->sk;
- struct l2cap_pinfo *pi = l2cap_pi(sk);
u16 control, fcs;
int nsent = 0;
@@ -1106,7 +1102,7 @@ int l2cap_ertm_send(struct l2cap_chan *chan)
if (chan->remote_max_tx &&
bt_cb(skb)->retries == chan->remote_max_tx) {
- l2cap_send_disconn_req(pi->conn, chan, ECONNABORTED);
+ l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
break;
}
@@ -1202,7 +1198,7 @@ static void l2cap_send_srejtail(struct l2cap_chan *chan)
static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb)
{
- struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+ struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
struct sk_buff **frag;
int err, sent = 0;
@@ -1235,7 +1231,7 @@ static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, in
struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
{
struct sock *sk = chan->sk;
- struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+ struct l2cap_conn *conn = chan->conn;
struct sk_buff *skb;
int err, count, hlen = L2CAP_HDR_SIZE + 2;
struct l2cap_hdr *lh;
@@ -1265,7 +1261,7 @@ struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr
struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
{
struct sock *sk = chan->sk;
- struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+ struct l2cap_conn *conn = chan->conn;
struct sk_buff *skb;
int err, count, hlen = L2CAP_HDR_SIZE;
struct l2cap_hdr *lh;
@@ -1294,7 +1290,7 @@ struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *m
struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen)
{
struct sock *sk = chan->sk;
- struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+ struct l2cap_conn *conn = chan->conn;
struct sk_buff *skb;
int err, count, hlen = L2CAP_HDR_SIZE + 2;
struct l2cap_hdr *lh;
@@ -1610,7 +1606,6 @@ static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
{
- struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
struct l2cap_conf_req *req = data;
struct l2cap_conf_rfc rfc = { .mode = chan->mode };
void *ptr = req->data;
@@ -1628,7 +1623,7 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
/* fall through */
default:
- chan->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
+ chan->mode = l2cap_select_mode(rfc.mode, chan->conn->feat_mask);
break;
}
@@ -1638,8 +1633,8 @@ done:
switch (chan->mode) {
case L2CAP_MODE_BASIC:
- if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
- !(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
+ if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) &&
+ !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING))
break;
rfc.mode = L2CAP_MODE_BASIC;
@@ -1660,13 +1655,13 @@ done:
rfc.retrans_timeout = 0;
rfc.monitor_timeout = 0;
rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
- if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
- rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
+ if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
+ rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
(unsigned long) &rfc);
- if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
+ if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
break;
if (chan->fcs == L2CAP_FCS_NONE ||
@@ -1683,13 +1678,13 @@ done:
rfc.retrans_timeout = 0;
rfc.monitor_timeout = 0;
rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
- if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
- rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
+ if (L2CAP_DEFAULT_MAX_PDU_SIZE > chan->conn->mtu - 10)
+ rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
(unsigned long) &rfc);
- if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
+ if (!(chan->conn->feat_mask & L2CAP_FEAT_FCS))
break;
if (chan->fcs == L2CAP_FCS_NONE ||
@@ -1708,7 +1703,6 @@ done:
static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
{
- struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
struct l2cap_conf_rsp *rsp = data;
void *ptr = rsp->data;
void *req = chan->conf_req;
@@ -1768,7 +1762,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
case L2CAP_MODE_ERTM:
if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
chan->mode = l2cap_select_mode(rfc.mode,
- pi->conn->feat_mask);
+ chan->conn->feat_mask);
break;
}
@@ -1813,8 +1807,8 @@ done:
chan->remote_tx_win = rfc.txwin_size;
chan->remote_max_tx = rfc.max_transmit;
- if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
- rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
+ if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
+ rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
@@ -1831,8 +1825,8 @@ done:
break;
case L2CAP_MODE_STREAMING:
- if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
- rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
+ if (le16_to_cpu(rfc.max_pdu_size) > chan->conn->mtu - 10)
+ rfc.max_pdu_size = cpu_to_le16(chan->conn->mtu - 10);
chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
@@ -1942,15 +1936,12 @@ static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result,
return ptr - data;
}
-void __l2cap_connect_rsp_defer(struct sock *sk)
+void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
{
struct l2cap_conn_rsp rsp;
- struct l2cap_conn *conn = l2cap_pi(sk)->conn;
- struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+ struct l2cap_conn *conn = chan->conn;
u8 buf[128];
- sk->sk_state = BT_CONFIG;
-
rsp.scid = cpu_to_le16(chan->dcid);
rsp.dcid = cpu_to_le16(chan->scid);
rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
@@ -2855,7 +2846,6 @@ static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb,
static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
{
- struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
struct sk_buff *_skb;
int err;
@@ -2956,7 +2946,7 @@ drop:
chan->sdu = NULL;
disconnect:
- l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
+ l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
kfree_skb(skb);
return 0;
}
@@ -3017,7 +3007,7 @@ static void l2cap_busy_work(struct work_struct *work)
if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
err = -EBUSY;
- l2cap_send_disconn_req(l2cap_pi(sk)->conn, chan, EBUSY);
+ l2cap_send_disconn_req(chan->conn, chan, EBUSY);
break;
}
@@ -3235,7 +3225,6 @@ static void l2cap_send_srejframe(struct l2cap_chan *chan, u8 tx_seq)
static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_control, struct sk_buff *skb)
{
- struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
u8 tx_seq = __get_txseq(rx_control);
u8 req_seq = __get_reqseq(rx_control);
u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
@@ -3266,7 +3255,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont
/* invalid tx_seq */
if (tx_seq_offset >= chan->tx_win) {
- l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
+ l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
goto drop;
}
@@ -3533,7 +3522,6 @@ static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_cont
static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
{
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
- struct l2cap_pinfo *pi = l2cap_pi(sk);
u16 control;
u8 req_seq;
int len, next_tx_seq_offset, req_seq_offset;
@@ -3557,7 +3545,7 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
len -= 2;
if (len > chan->mps) {
- l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
+ l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
goto drop;
}
@@ -3573,13 +3561,13 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
/* check for invalid req-seq */
if (req_seq_offset > next_tx_seq_offset) {
- l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
+ l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
goto drop;
}
if (__is_iframe(control)) {
if (len < 0) {
- l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
+ l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
goto drop;
}
@@ -3587,7 +3575,7 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
} else {
if (len != 0) {
BT_ERR("%d", len);
- l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
+ l2cap_send_disconn_req(chan->conn, chan, ECONNRESET);
goto drop;
}
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index f5a2773..61d93f6 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -455,8 +455,8 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
break;
}
- cinfo.hci_handle = l2cap_pi(sk)->conn->hcon->handle;
- memcpy(cinfo.dev_class, l2cap_pi(sk)->conn->hcon->dev_class, 3);
+ cinfo.hci_handle = chan->conn->hcon->handle;
+ memcpy(cinfo.dev_class, chan->conn->hcon->dev_class, 3);
len = min_t(unsigned int, len, sizeof(cinfo));
if (copy_to_user(optval, (char *) &cinfo, len))
@@ -690,7 +690,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
}
if (opt == BT_FLUSHABLE_OFF) {
- struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+ struct l2cap_conn *conn = chan->conn;
/* proceed futher only when we have l2cap_conn and
No Flush support in the LM */
if (!conn || !lmp_no_flush_capable(conn->hcon->hdev)) {
@@ -823,7 +823,9 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms
lock_sock(sk);
if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) {
- __l2cap_connect_rsp_defer(sk);
+ sk->sk_state = BT_CONFIG;
+
+ __l2cap_connect_rsp_defer(l2cap_pi(sk)->chan);
release_sock(sk);
return 0;
}
@@ -878,8 +880,8 @@ static void l2cap_sock_cleanup_listen(struct sock *parent)
void __l2cap_sock_close(struct sock *sk, int reason)
{
- struct l2cap_conn *conn = l2cap_pi(sk)->conn;
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+ struct l2cap_conn *conn = chan->conn;
BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index fdd8f5a..121a5c1 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -232,6 +232,8 @@ static int rfcomm_l2sock_create(struct socket **sock)
static inline int rfcomm_check_security(struct rfcomm_dlc *d)
{
struct sock *sk = d->session->sock->sk;
+ struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
+
__u8 auth_type;
switch (d->sec_level) {
@@ -246,8 +248,7 @@ static inline int rfcomm_check_security(struct rfcomm_dlc *d)
break;
}
- return hci_conn_security(l2cap_pi(sk)->conn->hcon, d->sec_level,
- auth_type);
+ return hci_conn_security(conn->hcon, d->sec_level, auth_type);
}
static void rfcomm_session_timeout(unsigned long arg)
@@ -1241,6 +1242,7 @@ static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci)
void rfcomm_dlc_accept(struct rfcomm_dlc *d)
{
struct sock *sk = d->session->sock->sk;
+ struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
BT_DBG("dlc %p", d);
@@ -1254,7 +1256,7 @@ void rfcomm_dlc_accept(struct rfcomm_dlc *d)
rfcomm_dlc_unlock(d);
if (d->role_switch)
- hci_conn_switch_role(l2cap_pi(sk)->conn->hcon, 0x00);
+ hci_conn_switch_role(conn->hcon, 0x00);
rfcomm_send_msc(d->session, 1, d->dlci, d->v24_sig);
}
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 66cc1f0..386cfaf 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -743,6 +743,7 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u
struct sock *sk = sock->sk;
struct sock *l2cap_sk;
struct rfcomm_conninfo cinfo;
+ struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
int len, err = 0;
u32 opt;
@@ -787,8 +788,8 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u
l2cap_sk = rfcomm_pi(sk)->dlc->session->sock->sk;
- cinfo.hci_handle = l2cap_pi(l2cap_sk)->conn->hcon->handle;
- memcpy(cinfo.dev_class, l2cap_pi(l2cap_sk)->conn->hcon->dev_class, 3);
+ cinfo.hci_handle = conn->hcon->handle;
+ memcpy(cinfo.dev_class, conn->hcon->dev_class, 3);
len = min_t(unsigned int, len, sizeof(cinfo));
if (copy_to_user(optval, (char *) &cinfo, len))
--
1.7.5.rc1
^ permalink raw reply related
* [PATCH 7/8] Bluetooth: Move more vars to struct l2cap_chan
From: Gustavo F. Padovan @ 2011-04-15 18:17 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1302891454-10165-7-git-send-email-padovan@profusion.mobi>
In this commit, psm, scid and dcid.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
include/net/bluetooth/l2cap.h | 10 ++--
net/bluetooth/l2cap_core.c | 116 +++++++++++++++++++++--------------------
net/bluetooth/l2cap_sock.c | 26 +++++-----
3 files changed, 77 insertions(+), 75 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 7522835..fd199cd 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -284,6 +284,9 @@ struct srej_list {
struct l2cap_chan {
struct sock *sk;
+ __le16 psm;
+ __u16 dcid;
+ __u16 scid;
__u16 imtu;
__u16 omtu;
@@ -382,9 +385,6 @@ struct l2cap_conn {
struct l2cap_pinfo {
struct bt_sock bt;
- __le16 psm;
- __u16 dcid;
- __u16 scid;
struct l2cap_conn *conn;
struct l2cap_chan *chan;
@@ -450,8 +450,8 @@ void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *d
void __l2cap_connect_rsp_defer(struct sock *sk);
int __l2cap_wait_ack(struct sock *sk);
-struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len);
-struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len);
+struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
+struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen);
int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index c267244..3ff8840 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -80,8 +80,7 @@ static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16
struct l2cap_chan *c;
list_for_each_entry(c, &conn->chan_l, list) {
- struct sock *s = c->sk;
- if (l2cap_pi(s)->dcid == cid)
+ if (c->dcid == cid)
return c;
}
return NULL;
@@ -93,8 +92,7 @@ static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16
struct l2cap_chan *c;
list_for_each_entry(c, &conn->chan_l, list) {
- struct sock *s = c->sk;
- if (l2cap_pi(s)->scid == cid)
+ if (c->scid == cid)
return c;
}
return NULL;
@@ -167,7 +165,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
struct sock *sk = chan->sk;
BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
- l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid);
+ chan->psm, chan->dcid);
conn->disc_reason = 0x13;
@@ -177,22 +175,22 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
if (conn->hcon->type == LE_LINK) {
/* LE connection */
chan->omtu = L2CAP_LE_DEFAULT_MTU;
- l2cap_pi(sk)->scid = L2CAP_CID_LE_DATA;
- l2cap_pi(sk)->dcid = L2CAP_CID_LE_DATA;
+ chan->scid = L2CAP_CID_LE_DATA;
+ chan->dcid = L2CAP_CID_LE_DATA;
} else {
/* Alloc CID for connection-oriented socket */
- l2cap_pi(sk)->scid = l2cap_alloc_cid(conn);
+ chan->scid = l2cap_alloc_cid(conn);
chan->omtu = L2CAP_DEFAULT_MTU;
}
} else if (sk->sk_type == SOCK_DGRAM) {
/* Connectionless socket */
- l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS;
- l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS;
+ chan->scid = L2CAP_CID_CONN_LESS;
+ chan->dcid = L2CAP_CID_CONN_LESS;
chan->omtu = L2CAP_DEFAULT_MTU;
} else {
/* Raw socket can send/recv signalling messages only */
- l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING;
- l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING;
+ chan->scid = L2CAP_CID_SIGNALING;
+ chan->dcid = L2CAP_CID_SIGNALING;
chan->omtu = L2CAP_DEFAULT_MTU;
}
@@ -275,7 +273,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
default:
return HCI_AT_NO_BONDING;
}
- } else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
+ } else if (chan->psm == cpu_to_le16(0x0001)) {
if (chan->sec_level == BT_SECURITY_LOW)
chan->sec_level = BT_SECURITY_SDP;
@@ -383,7 +381,7 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
- lh->cid = cpu_to_le16(pi->dcid);
+ lh->cid = cpu_to_le16(chan->dcid);
put_unaligned_le16(control, skb_put(skb, 2));
if (chan->fcs == L2CAP_FCS_CRC16) {
@@ -429,8 +427,8 @@ static void l2cap_do_start(struct l2cap_chan *chan)
if (l2cap_check_security(chan) &&
__l2cap_no_conn_pending(chan)) {
struct l2cap_conn_req req;
- req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
- req.psm = l2cap_pi(sk)->psm;
+ req.scid = cpu_to_le16(chan->scid);
+ req.psm = chan->psm;
chan->ident = l2cap_get_ident(conn);
chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
@@ -485,8 +483,8 @@ void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, in
del_timer(&chan->ack_timer);
}
- req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
- req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
+ req.dcid = cpu_to_le16(chan->dcid);
+ req.scid = cpu_to_le16(chan->scid);
l2cap_send_cmd(conn, l2cap_get_ident(conn),
L2CAP_DISCONN_REQ, sizeof(req), &req);
@@ -536,8 +534,8 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
continue;
}
- req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
- req.psm = l2cap_pi(sk)->psm;
+ req.scid = cpu_to_le16(chan->scid);
+ req.psm = chan->psm;
chan->ident = l2cap_get_ident(conn);
chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
@@ -548,8 +546,8 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
} else if (sk->sk_state == BT_CONNECT2) {
struct l2cap_conn_rsp rsp;
char buf[128];
- rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
- rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
+ rsp.scid = cpu_to_le16(chan->dcid);
+ rsp.dcid = cpu_to_le16(chan->scid);
if (l2cap_check_security(chan)) {
if (bt_sk(sk)->defer_setup) {
@@ -600,10 +598,12 @@ static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
read_lock(&l2cap_sk_list.lock);
sk_for_each(sk, node, &l2cap_sk_list.head) {
+ struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+
if (state && sk->sk_state != state)
continue;
- if (l2cap_pi(sk)->scid == cid) {
+ if (chan->scid == cid) {
/* Exact match. */
if (!bacmp(&bt_sk(sk)->src, src))
break;
@@ -830,10 +830,12 @@ static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
read_lock(&l2cap_sk_list.lock);
sk_for_each(sk, node, &l2cap_sk_list.head) {
+ struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+
if (state && sk->sk_state != state)
continue;
- if (l2cap_pi(sk)->psm == psm) {
+ if (chan->psm == psm) {
/* Exact match. */
if (!bacmp(&bt_sk(sk)->src, src))
break;
@@ -861,7 +863,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan)
int err;
BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
- l2cap_pi(sk)->psm);
+ chan->psm);
hdev = hci_get_route(dst, src);
if (!hdev)
@@ -871,7 +873,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan)
auth_type = l2cap_get_auth_type(chan);
- if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
+ if (chan->dcid == L2CAP_CID_LE_DATA)
hcon = hci_connect(hdev, LE_LINK, dst,
chan->sec_level, auth_type);
else
@@ -1230,8 +1232,9 @@ static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, in
return sent;
}
-struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
+struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
{
+ struct sock *sk = chan->sk;
struct l2cap_conn *conn = l2cap_pi(sk)->conn;
struct sk_buff *skb;
int err, count, hlen = L2CAP_HDR_SIZE + 2;
@@ -1247,9 +1250,9 @@ struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, s
/* Create L2CAP header */
lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
- lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
+ lh->cid = cpu_to_le16(chan->dcid);
lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
- put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
+ put_unaligned_le16(chan->psm, skb_put(skb, 2));
err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
if (unlikely(err < 0)) {
@@ -1259,8 +1262,9 @@ struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, s
return skb;
}
-struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
+struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
{
+ struct sock *sk = chan->sk;
struct l2cap_conn *conn = l2cap_pi(sk)->conn;
struct sk_buff *skb;
int err, count, hlen = L2CAP_HDR_SIZE;
@@ -1276,7 +1280,7 @@ struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size
/* Create L2CAP header */
lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
- lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
+ lh->cid = cpu_to_le16(chan->dcid);
lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
@@ -1314,7 +1318,7 @@ struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *
/* Create L2CAP header */
lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
- lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
+ lh->cid = cpu_to_le16(chan->dcid);
lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
put_unaligned_le16(control, skb_put(skb, 2));
if (sdulen)
@@ -1696,7 +1700,7 @@ done:
break;
}
- req->dcid = cpu_to_le16(pi->dcid);
+ req->dcid = cpu_to_le16(chan->dcid);
req->flags = cpu_to_le16(0);
return ptr - data;
@@ -1849,7 +1853,7 @@ done:
if (result == L2CAP_CONF_SUCCESS)
chan->conf_state |= L2CAP_CONF_OUTPUT_DONE;
}
- rsp->scid = cpu_to_le16(pi->dcid);
+ rsp->scid = cpu_to_le16(chan->dcid);
rsp->result = cpu_to_le16(result);
rsp->flags = cpu_to_le16(0x0000);
@@ -1858,15 +1862,13 @@ done:
static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result)
{
- struct sock *sk = chan->sk;
- struct l2cap_pinfo *pi = l2cap_pi(sk);
struct l2cap_conf_req *req = data;
void *ptr = req->data;
int type, olen;
unsigned long val;
struct l2cap_conf_rfc rfc;
- BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
+ BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
while (len >= L2CAP_CONF_OPT_SIZE) {
len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
@@ -1920,20 +1922,20 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi
}
}
- req->dcid = cpu_to_le16(pi->dcid);
+ req->dcid = cpu_to_le16(chan->dcid);
req->flags = cpu_to_le16(0x0000);
return ptr - data;
}
-static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
+static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags)
{
struct l2cap_conf_rsp *rsp = data;
void *ptr = rsp->data;
- BT_DBG("sk %p", sk);
+ BT_DBG("chan %p", chan);
- rsp->scid = cpu_to_le16(l2cap_pi(sk)->dcid);
+ rsp->scid = cpu_to_le16(chan->dcid);
rsp->result = cpu_to_le16(result);
rsp->flags = cpu_to_le16(flags);
@@ -1949,8 +1951,8 @@ void __l2cap_connect_rsp_defer(struct sock *sk)
sk->sk_state = BT_CONFIG;
- rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
- rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
+ rsp.scid = cpu_to_le16(chan->dcid);
+ rsp.dcid = cpu_to_le16(chan->scid);
rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
l2cap_send_cmd(conn, chan->ident,
@@ -2084,14 +2086,14 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
l2cap_sock_init(sk, parent);
bacpy(&bt_sk(sk)->src, conn->src);
bacpy(&bt_sk(sk)->dst, conn->dst);
- l2cap_pi(sk)->psm = psm;
- l2cap_pi(sk)->dcid = scid;
+ chan->psm = psm;
+ chan->dcid = scid;
bt_accept_enqueue(parent, sk);
__l2cap_chan_add(conn, chan);
- dcid = l2cap_pi(sk)->scid;
+ dcid = chan->scid;
l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
@@ -2189,7 +2191,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
case L2CAP_CR_SUCCESS:
sk->sk_state = BT_CONFIG;
chan->ident = 0;
- l2cap_pi(sk)->dcid = dcid;
+ chan->dcid = dcid;
chan->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
if (chan->conf_state & L2CAP_CONF_REQ_SENT)
@@ -2269,7 +2271,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
len = cmd_len - sizeof(*req);
if (chan->conf_len + len > sizeof(chan->conf_req)) {
l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
- l2cap_build_conf_rsp(sk, rsp,
+ l2cap_build_conf_rsp(chan, rsp,
L2CAP_CONF_REJECT, flags), rsp);
goto unlock;
}
@@ -2281,7 +2283,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
if (flags & 0x0001) {
/* Incomplete config. Send empty response. */
l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
- l2cap_build_conf_rsp(sk, rsp,
+ l2cap_build_conf_rsp(chan, rsp,
L2CAP_CONF_SUCCESS, 0x0001), rsp);
goto unlock;
}
@@ -2431,8 +2433,8 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
sk = chan->sk;
- rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
- rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
+ rsp.dcid = cpu_to_le16(chan->scid);
+ rsp.scid = cpu_to_le16(chan->dcid);
l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
sk->sk_shutdown = SHUTDOWN_MASK;
@@ -3919,8 +3921,8 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
if (sk->sk_state == BT_CONNECT) {
if (!status) {
struct l2cap_conn_req req;
- req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
- req.psm = l2cap_pi(sk)->psm;
+ req.scid = cpu_to_le16(chan->scid);
+ req.psm = chan->psm;
chan->ident = l2cap_get_ident(conn);
chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
@@ -3944,8 +3946,8 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
result = L2CAP_CR_SEC_BLOCK;
}
- rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
- rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
+ rsp.scid = cpu_to_le16(chan->dcid);
+ rsp.dcid = cpu_to_le16(chan->scid);
rsp.result = cpu_to_le16(result);
rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
@@ -4085,8 +4087,8 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p)
seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
batostr(&bt_sk(sk)->src),
batostr(&bt_sk(sk)->dst),
- sk->sk_state, __le16_to_cpu(pi->psm),
- pi->scid, pi->dcid,
+ sk->sk_state, __le16_to_cpu(chan->psm),
+ chan->scid, chan->dcid,
chan->imtu, chan->omtu, chan->sec_level,
chan->mode);
}
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index eef33b1..f5a2773 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -141,7 +141,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
} else {
/* Save source address */
bacpy(&bt_sk(sk)->src, &la.l2_bdaddr);
- l2cap_pi(sk)->psm = la.l2_psm;
+ chan->psm = la.l2_psm;
chan->sport = la.l2_psm;
sk->sk_state = BT_BOUND;
@@ -151,7 +151,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
}
if (la.l2_cid)
- l2cap_pi(sk)->scid = la.l2_cid;
+ chan->scid = la.l2_cid;
write_unlock_bh(&l2cap_sk_list.lock);
@@ -232,8 +232,8 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
/* Set destination address and psm */
bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr);
- l2cap_pi(sk)->psm = la.l2_psm;
- l2cap_pi(sk)->dcid = la.l2_cid;
+ chan->psm = la.l2_psm;
+ chan->dcid = la.l2_cid;
err = l2cap_chan_connect(l2cap_pi(sk)->chan);
if (err)
@@ -276,7 +276,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
goto done;
}
- if (!l2cap_pi(sk)->psm && !l2cap_pi(sk)->scid) {
+ if (!chan->psm && !chan->scid) {
bdaddr_t *src = &bt_sk(sk)->src;
u16 psm;
@@ -286,7 +286,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
for (psm = 0x1001; psm < 0x1100; psm += 2)
if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) {
- l2cap_pi(sk)->psm = cpu_to_le16(psm);
+ chan->psm = cpu_to_le16(psm);
chan->sport = cpu_to_le16(psm);
err = 0;
break;
@@ -375,13 +375,13 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l
*len = sizeof(struct sockaddr_l2);
if (peer) {
- la->l2_psm = l2cap_pi(sk)->psm;
+ la->l2_psm = chan->psm;
bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst);
- la->l2_cid = cpu_to_le16(l2cap_pi(sk)->dcid);
+ la->l2_cid = cpu_to_le16(chan->dcid);
} else {
la->l2_psm = chan->sport;
bacpy(&la->l2_bdaddr, &bt_sk(sk)->src);
- la->l2_cid = cpu_to_le16(l2cap_pi(sk)->scid);
+ la->l2_cid = cpu_to_le16(chan->scid);
}
return 0;
@@ -737,7 +737,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
/* Connectionless channel */
if (sk->sk_type == SOCK_DGRAM) {
- skb = l2cap_create_connless_pdu(sk, msg, len);
+ skb = l2cap_create_connless_pdu(chan, msg, len);
if (IS_ERR(skb)) {
err = PTR_ERR(skb);
} else {
@@ -756,7 +756,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
}
/* Create a basic PDU */
- skb = l2cap_create_basic_pdu(sk, msg, len);
+ skb = l2cap_create_basic_pdu(chan, msg, len);
if (IS_ERR(skb)) {
err = PTR_ERR(skb);
goto done;
@@ -911,8 +911,8 @@ void __l2cap_sock_close(struct sock *sk, int reason)
else
result = L2CAP_CR_BAD_PSM;
- rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
- rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
+ rsp.scid = cpu_to_le16(chan->dcid);
+ rsp.dcid = cpu_to_le16(chan->scid);
rsp.result = cpu_to_le16(result);
rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
--
1.7.5.rc1
^ permalink raw reply related
* [PATCH 6/8] Bluetooth: Move more channel info to struct l2cap_chan
From: Gustavo F. Padovan @ 2011-04-15 18:17 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1302891454-10165-6-git-send-email-padovan@profusion.mobi>
In this commit, omtu, imtu, flush_to, mode and sport. It also remove the
pi var from l2cap_sock_sendmsg().
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
include/net/bluetooth/l2cap.h | 14 +++---
net/bluetooth/l2cap_core.c | 97 +++++++++++++++++++--------------------
net/bluetooth/l2cap_sock.c | 100 ++++++++++++++++++++++-------------------
net/bluetooth/rfcomm/core.c | 11 +++--
4 files changed, 115 insertions(+), 107 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 02db902..7522835 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -285,6 +285,13 @@ struct srej_list {
struct l2cap_chan {
struct sock *sk;
+ __u16 imtu;
+ __u16 omtu;
+ __u16 flush_to;
+ __u8 mode;
+
+ __le16 sport;
+
__u8 sec_level;
__u8 role_switch;
__u8 force_reliable;
@@ -379,13 +386,6 @@ struct l2cap_pinfo {
__u16 dcid;
__u16 scid;
- __u16 imtu;
- __u16 omtu;
- __u16 flush_to;
- __u8 mode;
-
- __le16 sport;
-
struct l2cap_conn *conn;
struct l2cap_chan *chan;
};
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 5ca6c15..c267244 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -176,24 +176,24 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
if (conn->hcon->type == LE_LINK) {
/* LE connection */
- l2cap_pi(sk)->omtu = L2CAP_LE_DEFAULT_MTU;
+ chan->omtu = L2CAP_LE_DEFAULT_MTU;
l2cap_pi(sk)->scid = L2CAP_CID_LE_DATA;
l2cap_pi(sk)->dcid = L2CAP_CID_LE_DATA;
} else {
/* Alloc CID for connection-oriented socket */
l2cap_pi(sk)->scid = l2cap_alloc_cid(conn);
- l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
+ chan->omtu = L2CAP_DEFAULT_MTU;
}
} else if (sk->sk_type == SOCK_DGRAM) {
/* Connectionless socket */
l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS;
l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS;
- l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
+ chan->omtu = L2CAP_DEFAULT_MTU;
} else {
/* Raw socket can send/recv signalling messages only */
l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING;
l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING;
- l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
+ chan->omtu = L2CAP_DEFAULT_MTU;
}
sock_hold(sk);
@@ -242,7 +242,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
skb_queue_purge(&chan->tx_q);
- if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
+ if (chan->mode == L2CAP_MODE_ERTM) {
struct srej_list *l, *tmp;
del_timer(&chan->retrans_timer);
@@ -479,7 +479,7 @@ void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, in
sk = chan->sk;
- if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
+ if (chan->mode == L2CAP_MODE_ERTM) {
del_timer(&chan->retrans_timer);
del_timer(&chan->monitor_timer);
del_timer(&chan->ack_timer);
@@ -523,7 +523,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
continue;
}
- if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
+ if (!l2cap_mode_supported(chan->mode,
conn->feat_mask)
&& chan->conf_state &
L2CAP_CONF_STATE2_DEVICE) {
@@ -1608,7 +1608,7 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
{
struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
struct l2cap_conf_req *req = data;
- struct l2cap_conf_rfc rfc = { .mode = pi->mode };
+ struct l2cap_conf_rfc rfc = { .mode = chan->mode };
void *ptr = req->data;
BT_DBG("chan %p", chan);
@@ -1616,7 +1616,7 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
if (chan->num_conf_req || chan->num_conf_rsp)
goto done;
- switch (pi->mode) {
+ switch (chan->mode) {
case L2CAP_MODE_STREAMING:
case L2CAP_MODE_ERTM:
if (chan->conf_state & L2CAP_CONF_STATE2_DEVICE)
@@ -1624,15 +1624,15 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
/* fall through */
default:
- pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
+ chan->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
break;
}
done:
- if (pi->imtu != L2CAP_DEFAULT_MTU)
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
+ if (chan->imtu != L2CAP_DEFAULT_MTU)
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
- switch (pi->mode) {
+ switch (chan->mode) {
case L2CAP_MODE_BASIC:
if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
!(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
@@ -1729,7 +1729,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
break;
case L2CAP_CONF_FLUSH_TO:
- pi->flush_to = val;
+ chan->flush_to = val;
break;
case L2CAP_CONF_QOS:
@@ -1759,25 +1759,25 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
if (chan->num_conf_rsp || chan->num_conf_req > 1)
goto done;
- switch (pi->mode) {
+ switch (chan->mode) {
case L2CAP_MODE_STREAMING:
case L2CAP_MODE_ERTM:
if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
- pi->mode = l2cap_select_mode(rfc.mode,
+ chan->mode = l2cap_select_mode(rfc.mode,
pi->conn->feat_mask);
break;
}
- if (pi->mode != rfc.mode)
+ if (chan->mode != rfc.mode)
return -ECONNREFUSED;
break;
}
done:
- if (pi->mode != rfc.mode) {
+ if (chan->mode != rfc.mode) {
result = L2CAP_CONF_UNACCEPT;
- rfc.mode = pi->mode;
+ rfc.mode = chan->mode;
if (chan->num_conf_rsp == 1)
return -ECONNREFUSED;
@@ -1794,10 +1794,10 @@ done:
if (mtu < L2CAP_DEFAULT_MIN_MTU)
result = L2CAP_CONF_UNACCEPT;
else {
- pi->omtu = mtu;
+ chan->omtu = mtu;
chan->conf_state |= L2CAP_CONF_MTU_DONE;
}
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
switch (rfc.mode) {
case L2CAP_MODE_BASIC:
@@ -1843,7 +1843,7 @@ done:
result = L2CAP_CONF_UNACCEPT;
memset(&rfc, 0, sizeof(rfc));
- rfc.mode = pi->mode;
+ rfc.mode = chan->mode;
}
if (result == L2CAP_CONF_SUCCESS)
@@ -1875,16 +1875,16 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi
case L2CAP_CONF_MTU:
if (val < L2CAP_DEFAULT_MIN_MTU) {
*result = L2CAP_CONF_UNACCEPT;
- pi->imtu = L2CAP_DEFAULT_MIN_MTU;
+ chan->imtu = L2CAP_DEFAULT_MIN_MTU;
} else
- pi->imtu = val;
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
+ chan->imtu = val;
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
break;
case L2CAP_CONF_FLUSH_TO:
- pi->flush_to = val;
+ chan->flush_to = val;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
- 2, pi->flush_to);
+ 2, chan->flush_to);
break;
case L2CAP_CONF_RFC:
@@ -1892,7 +1892,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi
memcpy(&rfc, (void *)val, olen);
if ((chan->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
- rfc.mode != pi->mode)
+ rfc.mode != chan->mode)
return -ECONNREFUSED;
chan->fcs = 0;
@@ -1903,10 +1903,10 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi
}
}
- if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
+ if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode)
return -ECONNREFUSED;
- pi->mode = rfc.mode;
+ chan->mode = rfc.mode;
if (*result == L2CAP_CONF_SUCCESS) {
switch (rfc.mode) {
@@ -1967,14 +1967,13 @@ void __l2cap_connect_rsp_defer(struct sock *sk)
static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
{
- struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
int type, olen;
unsigned long val;
struct l2cap_conf_rfc rfc;
BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
- if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
+ if ((chan->mode != L2CAP_MODE_ERTM) && (chan->mode != L2CAP_MODE_STREAMING))
return;
while (len >= L2CAP_CONF_OPT_SIZE) {
@@ -2231,7 +2230,7 @@ static inline void set_default_fcs(struct l2cap_chan *chan)
/* FCS is enabled only in ERTM or streaming mode, if one or both
* sides request it.
*/
- if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
+ if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
chan->fcs = L2CAP_FCS_NONE;
else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV))
chan->fcs = L2CAP_FCS_CRC16;
@@ -2311,7 +2310,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
chan->next_tx_seq = 0;
chan->expected_tx_seq = 0;
skb_queue_head_init(&chan->tx_q);
- if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
+ if (chan->mode == L2CAP_MODE_ERTM)
l2cap_ertm_init(chan);
l2cap_chan_ready(sk);
@@ -2402,7 +2401,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
chan->next_tx_seq = 0;
chan->expected_tx_seq = 0;
skb_queue_head_init(&chan->tx_q);
- if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
+ if (chan->mode == L2CAP_MODE_ERTM)
l2cap_ertm_init(chan);
l2cap_chan_ready(sk);
@@ -2875,7 +2874,7 @@ static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *sk
chan->sdu_len = get_unaligned_le16(skb->data);
- if (chan->sdu_len > pi->imtu)
+ if (chan->sdu_len > chan->imtu)
goto disconnect;
chan->sdu = bt_skb_alloc(chan->sdu_len, GFP_ATOMIC);
@@ -2918,7 +2917,7 @@ static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *sk
if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
chan->partial_sdu_len += skb->len;
- if (chan->partial_sdu_len > pi->imtu)
+ if (chan->partial_sdu_len > chan->imtu)
goto drop;
if (chan->partial_sdu_len != chan->sdu_len)
@@ -3086,7 +3085,6 @@ static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 c
static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u16 control)
{
- struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
struct sk_buff *_skb;
int err = -EINVAL;
@@ -3117,7 +3115,7 @@ static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buf
chan->sdu_len = get_unaligned_le16(skb->data);
skb_pull(skb, 2);
- if (chan->sdu_len > pi->imtu) {
+ if (chan->sdu_len > chan->imtu) {
err = -EMSGSIZE;
break;
}
@@ -3158,7 +3156,7 @@ static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buf
chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
chan->partial_sdu_len += skb->len;
- if (chan->partial_sdu_len > pi->imtu)
+ if (chan->partial_sdu_len > chan->imtu)
goto drop;
if (chan->partial_sdu_len == chan->sdu_len) {
@@ -3624,14 +3622,14 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
if (sk->sk_state != BT_CONNECTED)
goto drop;
- switch (pi->mode) {
+ switch (chan->mode) {
case L2CAP_MODE_BASIC:
/* If socket recv buffers overflows we drop data here
* which is *bad* because L2CAP has to be reliable.
* But we don't have any other choice. L2CAP doesn't
* provide flow control mechanism. */
- if (pi->imtu < skb->len)
+ if (chan->imtu < skb->len)
goto drop;
if (!sock_queue_rcv_skb(sk, skb))
@@ -3677,7 +3675,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
goto done;
default:
- BT_DBG("chan %p: bad mode 0x%2.2x", chan, pi->mode);
+ BT_DBG("chan %p: bad mode 0x%2.2x", chan, chan->mode);
break;
}
@@ -3706,7 +3704,7 @@ static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, str
if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
goto drop;
- if (l2cap_pi(sk)->imtu < skb->len)
+ if (l2cap_pi(sk)->chan->imtu < skb->len)
goto drop;
if (!sock_queue_rcv_skb(sk, skb))
@@ -3736,7 +3734,7 @@ static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct
if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
goto drop;
- if (l2cap_pi(sk)->imtu < skb->len)
+ if (l2cap_pi(sk)->chan->imtu < skb->len)
goto drop;
if (!sock_queue_rcv_skb(sk, skb))
@@ -4019,10 +4017,10 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl
if (chan && chan->sk) {
struct sock *sk = chan->sk;
- if (l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
+ if (chan->imtu < len - L2CAP_HDR_SIZE) {
BT_ERR("Frame exceeding recv MTU (len %d, "
"MTU %d)", len,
- l2cap_pi(sk)->imtu);
+ chan->imtu);
bh_unlock_sock(sk);
l2cap_conn_unreliable(conn, ECOMM);
goto drop;
@@ -4082,14 +4080,15 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p)
sk_for_each(sk, node, &l2cap_sk_list.head) {
struct l2cap_pinfo *pi = l2cap_pi(sk);
+ struct l2cap_chan *chan = pi->chan;
seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
batostr(&bt_sk(sk)->src),
batostr(&bt_sk(sk)->dst),
sk->sk_state, __le16_to_cpu(pi->psm),
pi->scid, pi->dcid,
- pi->imtu, pi->omtu, pi->chan->sec_level,
- pi->mode);
+ chan->imtu, chan->omtu, chan->sec_level,
+ chan->mode);
}
read_unlock_bh(&l2cap_sk_list.lock);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 4ba15b3..eef33b1 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -80,9 +80,13 @@ static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
{
struct sock *sk;
struct hlist_node *node;
- sk_for_each(sk, node, &l2cap_sk_list.head)
- if (l2cap_pi(sk)->sport == psm && !bacmp(&bt_sk(sk)->src, src))
+ sk_for_each(sk, node, &l2cap_sk_list.head) {
+ struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+
+ if (chan->sport == psm && !bacmp(&bt_sk(sk)->src, src))
goto found;
+ }
+
sk = NULL;
found:
return sk;
@@ -138,7 +142,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
/* Save source address */
bacpy(&bt_sk(sk)->src, &la.l2_bdaddr);
l2cap_pi(sk)->psm = la.l2_psm;
- l2cap_pi(sk)->sport = la.l2_psm;
+ chan->sport = la.l2_psm;
sk->sk_state = BT_BOUND;
if (__le16_to_cpu(la.l2_psm) == 0x0001 ||
@@ -159,6 +163,7 @@ done:
static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
{
struct sock *sk = sock->sk;
+ struct l2cap_chan *chan = l2cap_pi(sk)->chan;
struct sockaddr_l2 la;
int len, err = 0;
@@ -183,7 +188,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
goto done;
}
- switch (l2cap_pi(sk)->mode) {
+ switch (chan->mode) {
case L2CAP_MODE_BASIC:
break;
case L2CAP_MODE_ERTM:
@@ -245,6 +250,7 @@ done:
static int l2cap_sock_listen(struct socket *sock, int backlog)
{
struct sock *sk = sock->sk;
+ struct l2cap_chan *chan = l2cap_pi(sk)->chan;
int err = 0;
BT_DBG("sk %p backlog %d", sk, backlog);
@@ -257,7 +263,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
goto done;
}
- switch (l2cap_pi(sk)->mode) {
+ switch (chan->mode) {
case L2CAP_MODE_BASIC:
break;
case L2CAP_MODE_ERTM:
@@ -281,7 +287,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
for (psm = 0x1001; psm < 0x1100; psm += 2)
if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) {
l2cap_pi(sk)->psm = cpu_to_le16(psm);
- l2cap_pi(sk)->sport = cpu_to_le16(psm);
+ chan->sport = cpu_to_le16(psm);
err = 0;
break;
}
@@ -361,6 +367,7 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l
{
struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr;
struct sock *sk = sock->sk;
+ struct l2cap_chan *chan = l2cap_pi(sk)->chan;
BT_DBG("sock %p, sk %p", sock, sk);
@@ -372,7 +379,7 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l
bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst);
la->l2_cid = cpu_to_le16(l2cap_pi(sk)->dcid);
} else {
- la->l2_psm = l2cap_pi(sk)->sport;
+ la->l2_psm = chan->sport;
bacpy(&la->l2_bdaddr, &bt_sk(sk)->src);
la->l2_cid = cpu_to_le16(l2cap_pi(sk)->scid);
}
@@ -399,10 +406,10 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
switch (optname) {
case L2CAP_OPTIONS:
memset(&opts, 0, sizeof(opts));
- opts.imtu = l2cap_pi(sk)->imtu;
- opts.omtu = l2cap_pi(sk)->omtu;
- opts.flush_to = l2cap_pi(sk)->flush_to;
- opts.mode = l2cap_pi(sk)->mode;
+ opts.imtu = chan->imtu;
+ opts.omtu = chan->omtu;
+ opts.flush_to = chan->flush_to;
+ opts.mode = chan->mode;
opts.fcs = chan->fcs;
opts.max_tx = chan->max_tx;
opts.txwin_size = (__u16)chan->tx_win;
@@ -547,10 +554,10 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
break;
}
- opts.imtu = l2cap_pi(sk)->imtu;
- opts.omtu = l2cap_pi(sk)->omtu;
- opts.flush_to = l2cap_pi(sk)->flush_to;
- opts.mode = l2cap_pi(sk)->mode;
+ opts.imtu = chan->imtu;
+ opts.omtu = chan->omtu;
+ opts.flush_to = chan->flush_to;
+ opts.mode = chan->mode;
opts.fcs = chan->fcs;
opts.max_tx = chan->max_tx;
opts.txwin_size = (__u16)chan->tx_win;
@@ -566,8 +573,8 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
break;
}
- l2cap_pi(sk)->mode = opts.mode;
- switch (l2cap_pi(sk)->mode) {
+ chan->mode = opts.mode;
+ switch (chan->mode) {
case L2CAP_MODE_BASIC:
chan->conf_state &= ~L2CAP_CONF_STATE2_DEVICE;
break;
@@ -581,8 +588,8 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
break;
}
- l2cap_pi(sk)->imtu = opts.imtu;
- l2cap_pi(sk)->omtu = opts.omtu;
+ chan->imtu = opts.imtu;
+ chan->omtu = opts.omtu;
chan->fcs = opts.fcs;
chan->max_tx = opts.max_tx;
chan->tx_win = (__u8)opts.txwin_size;
@@ -707,7 +714,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len)
{
struct sock *sk = sock->sk;
- struct l2cap_pinfo *pi = l2cap_pi(sk);
+ struct l2cap_chan *chan = l2cap_pi(sk)->chan;
struct sk_buff *skb;
u16 control;
int err;
@@ -734,16 +741,16 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
if (IS_ERR(skb)) {
err = PTR_ERR(skb);
} else {
- l2cap_do_send(pi->chan, skb);
+ l2cap_do_send(chan, skb);
err = len;
}
goto done;
}
- switch (pi->mode) {
+ switch (chan->mode) {
case L2CAP_MODE_BASIC:
/* Check outgoing MTU */
- if (len > pi->omtu) {
+ if (len > chan->omtu) {
err = -EMSGSIZE;
goto done;
}
@@ -755,52 +762,52 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
goto done;
}
- l2cap_do_send(pi->chan, skb);
+ l2cap_do_send(chan, skb);
err = len;
break;
case L2CAP_MODE_ERTM:
case L2CAP_MODE_STREAMING:
/* Entire SDU fits into one PDU */
- if (len <= pi->chan->remote_mps) {
+ if (len <= chan->remote_mps) {
control = L2CAP_SDU_UNSEGMENTED;
- skb = l2cap_create_iframe_pdu(pi->chan, msg, len,
- control, 0);
+ skb = l2cap_create_iframe_pdu(chan, msg, len, control,
+ 0);
if (IS_ERR(skb)) {
err = PTR_ERR(skb);
goto done;
}
- __skb_queue_tail(&pi->chan->tx_q, skb);
+ __skb_queue_tail(&chan->tx_q, skb);
- if (pi->chan->tx_send_head == NULL)
- pi->chan->tx_send_head = skb;
+ if (chan->tx_send_head == NULL)
+ chan->tx_send_head = skb;
} else {
/* Segment SDU into multiples PDUs */
- err = l2cap_sar_segment_sdu(pi->chan, msg, len);
+ err = l2cap_sar_segment_sdu(chan, msg, len);
if (err < 0)
goto done;
}
- if (pi->mode == L2CAP_MODE_STREAMING) {
- l2cap_streaming_send(pi->chan);
+ if (chan->mode == L2CAP_MODE_STREAMING) {
+ l2cap_streaming_send(chan);
err = len;
break;
}
- if ((pi->chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
- (pi->chan->conn_state & L2CAP_CONN_WAIT_F)) {
+ if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
+ (chan->conn_state & L2CAP_CONN_WAIT_F)) {
err = len;
break;
}
- err = l2cap_ertm_send(pi->chan);
+ err = l2cap_ertm_send(chan);
if (err >= 0)
err = len;
break;
default:
- BT_DBG("bad state %1.1x", pi->mode);
+ BT_DBG("bad state %1.1x", chan->mode);
err = -EBADFD;
}
@@ -929,6 +936,7 @@ void __l2cap_sock_close(struct sock *sk, int reason)
static int l2cap_sock_shutdown(struct socket *sock, int how)
{
struct sock *sk = sock->sk;
+ struct l2cap_chan *chan = l2cap_pi(sk)->chan;
int err = 0;
BT_DBG("sock %p, sk %p", sock, sk);
@@ -938,7 +946,7 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
lock_sock(sk);
if (!sk->sk_shutdown) {
- if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
+ if (chan->mode == L2CAP_MODE_ERTM)
err = __l2cap_wait_ack(sk);
sk->sk_shutdown = SHUTDOWN_MASK;
@@ -995,10 +1003,10 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent)
sk->sk_type = parent->sk_type;
bt_sk(sk)->defer_setup = bt_sk(parent)->defer_setup;
- pi->imtu = l2cap_pi(parent)->imtu;
- pi->omtu = l2cap_pi(parent)->omtu;
+ chan->imtu = pchan->imtu;
+ chan->omtu = pchan->omtu;
chan->conf_state = pchan->conf_state;
- pi->mode = l2cap_pi(parent)->mode;
+ chan->mode = pchan->mode;
chan->fcs = pchan->fcs;
chan->max_tx = pchan->max_tx;
chan->tx_win = pchan->tx_win;
@@ -1007,13 +1015,13 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent)
chan->force_reliable = pchan->force_reliable;
chan->flushable = pchan->flushable;
} else {
- pi->imtu = L2CAP_DEFAULT_MTU;
- pi->omtu = 0;
+ chan->imtu = L2CAP_DEFAULT_MTU;
+ chan->omtu = 0;
if (!disable_ertm && sk->sk_type == SOCK_STREAM) {
- pi->mode = L2CAP_MODE_ERTM;
+ chan->mode = L2CAP_MODE_ERTM;
chan->conf_state |= L2CAP_CONF_STATE2_DEVICE;
} else {
- pi->mode = L2CAP_MODE_BASIC;
+ chan->mode = L2CAP_MODE_BASIC;
}
chan->max_tx = L2CAP_DEFAULT_MAX_TX;
chan->fcs = L2CAP_FCS_CRC16;
@@ -1025,7 +1033,7 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent)
}
/* Default config options */
- pi->flush_to = L2CAP_DEFAULT_FLUSH_TO;
+ chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
}
static struct proto l2cap_proto = {
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 4f728a4..fdd8f5a 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -710,10 +710,10 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
/* Set L2CAP options */
sk = sock->sk;
lock_sock(sk);
- l2cap_pi(sk)->imtu = l2cap_mtu;
+ l2cap_pi(sk)->chan->imtu = l2cap_mtu;
l2cap_pi(sk)->chan->sec_level = sec_level;
if (l2cap_ertm)
- l2cap_pi(sk)->mode = L2CAP_MODE_ERTM;
+ l2cap_pi(sk)->chan->mode = L2CAP_MODE_ERTM;
release_sock(sk);
s = rfcomm_session_add(sock, BT_BOUND);
@@ -1890,7 +1890,8 @@ static inline void rfcomm_accept_connection(struct rfcomm_session *s)
/* We should adjust MTU on incoming sessions.
* L2CAP MTU minus UIH header and FCS. */
- s->mtu = min(l2cap_pi(nsock->sk)->omtu, l2cap_pi(nsock->sk)->imtu) - 5;
+ s->mtu = min(l2cap_pi(nsock->sk)->chan->omtu,
+ l2cap_pi(nsock->sk)->chan->imtu) - 5;
rfcomm_schedule();
} else
@@ -1909,7 +1910,7 @@ static inline void rfcomm_check_connection(struct rfcomm_session *s)
/* We can adjust MTU on outgoing sessions.
* L2CAP MTU minus UIH header and FCS. */
- s->mtu = min(l2cap_pi(sk)->omtu, l2cap_pi(sk)->imtu) - 5;
+ s->mtu = min(l2cap_pi(sk)->chan->omtu, l2cap_pi(sk)->chan->imtu) - 5;
rfcomm_send_sabm(s, 0);
break;
@@ -1992,7 +1993,7 @@ static int rfcomm_add_listener(bdaddr_t *ba)
/* Set L2CAP options */
sk = sock->sk;
lock_sock(sk);
- l2cap_pi(sk)->imtu = l2cap_mtu;
+ l2cap_pi(sk)->chan->imtu = l2cap_mtu;
release_sock(sk);
/* Start listening on the socket */
--
1.7.5.rc1
^ permalink raw reply related
* [PATCH 5/8] Bluetooth: Move more vars to struct l2cap_chan
From: Gustavo F. Padovan @ 2011-04-15 18:17 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1302891454-10165-5-git-send-email-padovan@profusion.mobi>
In this commit all ERTM and Streaming Mode specific vars.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
include/net/bluetooth/l2cap.h | 18 ++++----
net/bluetooth/l2cap_core.c | 100 ++++++++++++++++++++--------------------
net/bluetooth/l2cap_sock.c | 33 +++++++-------
net/bluetooth/rfcomm/core.c | 2 +-
4 files changed, 77 insertions(+), 76 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 684deee..02db902 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -297,6 +297,14 @@ struct l2cap_chan {
__u8 num_conf_req;
__u8 num_conf_rsp;
+ __u8 fcs;
+
+ __u8 tx_win;
+ __u8 max_tx;
+ __u16 retrans_timeout;
+ __u16 monitor_timeout;
+ __u16 mps;
+
__u8 conf_state;
__u16 conn_state;
@@ -376,14 +384,6 @@ struct l2cap_pinfo {
__u16 flush_to;
__u8 mode;
- __u8 fcs;
-
- __u8 tx_win;
- __u8 max_tx;
- __u16 retrans_timeout;
- __u16 monitor_timeout;
- __u16 mps;
-
__le16 sport;
struct l2cap_conn *conn;
@@ -452,7 +452,7 @@ int __l2cap_wait_ack(struct sock *sk);
struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len);
struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len);
-struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen);
+struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen);
int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb);
void l2cap_streaming_send(struct l2cap_chan *chan);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index eca9c9a..5ca6c15 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -359,7 +359,7 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
if (sk->sk_state != BT_CONNECTED)
return;
- if (pi->fcs == L2CAP_FCS_CRC16)
+ if (chan->fcs == L2CAP_FCS_CRC16)
hlen += 2;
BT_DBG("chan %p, control 0x%2.2x", chan, control);
@@ -386,7 +386,7 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
lh->cid = cpu_to_le16(pi->dcid);
put_unaligned_le16(control, skb_put(skb, 2));
- if (pi->fcs == L2CAP_FCS_CRC16) {
+ if (chan->fcs == L2CAP_FCS_CRC16) {
u16 fcs = crc16(0, (u8 *)lh, count - 2);
put_unaligned_le16(fcs, skb_put(skb, 2));
}
@@ -1022,9 +1022,7 @@ void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
void l2cap_streaming_send(struct l2cap_chan *chan)
{
- struct sock *sk = chan->sk;
struct sk_buff *skb;
- struct l2cap_pinfo *pi = l2cap_pi(sk);
u16 control, fcs;
while ((skb = skb_dequeue(&chan->tx_q))) {
@@ -1032,7 +1030,7 @@ void l2cap_streaming_send(struct l2cap_chan *chan)
control |= chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
- if (pi->fcs == L2CAP_FCS_CRC16) {
+ if (chan->fcs == L2CAP_FCS_CRC16) {
fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
put_unaligned_le16(fcs, skb->data + skb->len - 2);
}
@@ -1083,7 +1081,7 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
- if (pi->fcs == L2CAP_FCS_CRC16) {
+ if (chan->fcs == L2CAP_FCS_CRC16) {
fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
}
@@ -1126,7 +1124,7 @@ int l2cap_ertm_send(struct l2cap_chan *chan)
put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
- if (pi->fcs == L2CAP_FCS_CRC16) {
+ if (chan->fcs == L2CAP_FCS_CRC16) {
fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
}
@@ -1289,8 +1287,9 @@ struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size
return skb;
}
-struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen)
+struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen)
{
+ struct sock *sk = chan->sk;
struct l2cap_conn *conn = l2cap_pi(sk)->conn;
struct sk_buff *skb;
int err, count, hlen = L2CAP_HDR_SIZE + 2;
@@ -1304,7 +1303,7 @@ struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, siz
if (sdulen)
hlen += 2;
- if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
+ if (chan->fcs == L2CAP_FCS_CRC16)
hlen += 2;
count = min_t(unsigned int, (conn->mtu - hlen), len);
@@ -1327,7 +1326,7 @@ struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, siz
return ERR_PTR(err);
}
- if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
+ if (chan->fcs == L2CAP_FCS_CRC16)
put_unaligned_le16(0, skb_put(skb, 2));
bt_cb(skb)->retries = 0;
@@ -1336,7 +1335,6 @@ struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, siz
int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
{
- struct sock *sk = chan->sk;
struct sk_buff *skb;
struct sk_buff_head sar_queue;
u16 control;
@@ -1344,7 +1342,7 @@ int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t le
skb_queue_head_init(&sar_queue);
control = L2CAP_SDU_START;
- skb = l2cap_create_iframe_pdu(sk, msg, chan->remote_mps, control, len);
+ skb = l2cap_create_iframe_pdu(chan, msg, chan->remote_mps, control, len);
if (IS_ERR(skb))
return PTR_ERR(skb);
@@ -1363,7 +1361,7 @@ int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t le
buflen = len;
}
- skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
+ skb = l2cap_create_iframe_pdu(chan, msg, buflen, control, 0);
if (IS_ERR(skb)) {
skb_queue_purge(&sar_queue);
return PTR_ERR(skb);
@@ -1653,8 +1651,8 @@ done:
case L2CAP_MODE_ERTM:
rfc.mode = L2CAP_MODE_ERTM;
- rfc.txwin_size = pi->tx_win;
- rfc.max_transmit = pi->max_tx;
+ rfc.txwin_size = chan->tx_win;
+ rfc.max_transmit = chan->max_tx;
rfc.retrans_timeout = 0;
rfc.monitor_timeout = 0;
rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
@@ -1667,10 +1665,10 @@ done:
if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
break;
- if (pi->fcs == L2CAP_FCS_NONE ||
+ if (chan->fcs == L2CAP_FCS_NONE ||
chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
- pi->fcs = L2CAP_FCS_NONE;
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
+ chan->fcs = L2CAP_FCS_NONE;
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
}
break;
@@ -1690,10 +1688,10 @@ done:
if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
break;
- if (pi->fcs == L2CAP_FCS_NONE ||
+ if (chan->fcs == L2CAP_FCS_NONE ||
chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
- pi->fcs = L2CAP_FCS_NONE;
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
+ chan->fcs = L2CAP_FCS_NONE;
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
}
break;
}
@@ -1803,7 +1801,7 @@ done:
switch (rfc.mode) {
case L2CAP_MODE_BASIC:
- pi->fcs = L2CAP_FCS_NONE;
+ chan->fcs = L2CAP_FCS_NONE;
chan->conf_state |= L2CAP_CONF_MODE_DONE;
break;
@@ -1897,7 +1895,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi
rfc.mode != pi->mode)
return -ECONNREFUSED;
- pi->fcs = 0;
+ chan->fcs = 0;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
sizeof(rfc), (unsigned long) &rfc);
@@ -1913,12 +1911,12 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi
if (*result == L2CAP_CONF_SUCCESS) {
switch (rfc.mode) {
case L2CAP_MODE_ERTM:
- pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
- pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
- pi->mps = le16_to_cpu(rfc.max_pdu_size);
+ chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
+ chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
+ chan->mps = le16_to_cpu(rfc.max_pdu_size);
break;
case L2CAP_MODE_STREAMING:
- pi->mps = le16_to_cpu(rfc.max_pdu_size);
+ chan->mps = le16_to_cpu(rfc.max_pdu_size);
}
}
@@ -1967,14 +1965,14 @@ void __l2cap_connect_rsp_defer(struct sock *sk)
chan->num_conf_req++;
}
-static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
+static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
{
- struct l2cap_pinfo *pi = l2cap_pi(sk);
+ struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
int type, olen;
unsigned long val;
struct l2cap_conf_rfc rfc;
- BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
+ BT_DBG("chan %p, rsp %p, len %d", chan, rsp, len);
if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
return;
@@ -1993,12 +1991,12 @@ static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
done:
switch (rfc.mode) {
case L2CAP_MODE_ERTM:
- pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
- pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
- pi->mps = le16_to_cpu(rfc.max_pdu_size);
+ chan->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
+ chan->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
+ chan->mps = le16_to_cpu(rfc.max_pdu_size);
break;
case L2CAP_MODE_STREAMING:
- pi->mps = le16_to_cpu(rfc.max_pdu_size);
+ chan->mps = le16_to_cpu(rfc.max_pdu_size);
}
}
@@ -2226,15 +2224,17 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
return 0;
}
-static inline void set_default_fcs(struct l2cap_pinfo *pi)
+static inline void set_default_fcs(struct l2cap_chan *chan)
{
+ struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
+
/* FCS is enabled only in ERTM or streaming mode, if one or both
* sides request it.
*/
if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
- pi->fcs = L2CAP_FCS_NONE;
+ chan->fcs = L2CAP_FCS_NONE;
else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV))
- pi->fcs = L2CAP_FCS_CRC16;
+ chan->fcs = L2CAP_FCS_CRC16;
}
static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
@@ -2304,7 +2304,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
goto unlock;
if (chan->conf_state & L2CAP_CONF_INPUT_DONE) {
- set_default_fcs(l2cap_pi(sk));
+ set_default_fcs(chan);
sk->sk_state = BT_CONNECTED;
@@ -2354,7 +2354,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
switch (result) {
case L2CAP_CONF_SUCCESS:
- l2cap_conf_rfc_get(sk, rsp->data, len);
+ l2cap_conf_rfc_get(chan, rsp->data, len);
break;
case L2CAP_CONF_UNACCEPT:
@@ -2396,7 +2396,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
chan->conf_state |= L2CAP_CONF_INPUT_DONE;
if (chan->conf_state & L2CAP_CONF_OUTPUT_DONE) {
- set_default_fcs(l2cap_pi(sk));
+ set_default_fcs(chan);
sk->sk_state = BT_CONNECTED;
chan->next_tx_seq = 0;
@@ -2768,12 +2768,12 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn,
kfree_skb(skb);
}
-static int l2cap_check_fcs(struct l2cap_pinfo *pi, struct sk_buff *skb)
+static int l2cap_check_fcs(struct l2cap_chan *chan, struct sk_buff *skb)
{
u16 our_fcs, rcv_fcs;
int hdr_size = L2CAP_HDR_SIZE + 2;
- if (pi->fcs == L2CAP_FCS_CRC16) {
+ if (chan->fcs == L2CAP_FCS_CRC16) {
skb_trim(skb, skb->len - 2);
rcv_fcs = get_unaligned_le16(skb->data + skb->len);
our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
@@ -3240,7 +3240,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont
u8 req_seq = __get_reqseq(rx_control);
u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
int tx_seq_offset, expected_tx_seq_offset;
- int num_to_ack = (pi->tx_win/6) + 1;
+ int num_to_ack = (chan->tx_win/6) + 1;
int err = 0;
BT_DBG("chan %p len %d tx_seq %d rx_control 0x%4.4x", chan, skb->len,
@@ -3265,7 +3265,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont
tx_seq_offset += 64;
/* invalid tx_seq */
- if (tx_seq_offset >= pi->tx_win) {
+ if (tx_seq_offset >= chan->tx_win) {
l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
goto drop;
}
@@ -3547,16 +3547,16 @@ static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
* Receiver will miss it and start proper recovery
* procedures and ask retransmission.
*/
- if (l2cap_check_fcs(pi, skb))
+ if (l2cap_check_fcs(chan, skb))
goto drop;
if (__is_sar_start(control) && __is_iframe(control))
len -= 2;
- if (pi->fcs == L2CAP_FCS_CRC16)
+ if (chan->fcs == L2CAP_FCS_CRC16)
len -= 2;
- if (len > pi->mps) {
+ if (len > chan->mps) {
l2cap_send_disconn_req(pi->conn, chan, ECONNRESET);
goto drop;
}
@@ -3653,16 +3653,16 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
skb_pull(skb, 2);
len = skb->len;
- if (l2cap_check_fcs(pi, skb))
+ if (l2cap_check_fcs(chan, skb))
goto drop;
if (__is_sar_start(control))
len -= 2;
- if (pi->fcs == L2CAP_FCS_CRC16)
+ if (chan->fcs == L2CAP_FCS_CRC16)
len -= 2;
- if (len > pi->mps || len < 0 || __is_sframe(control))
+ if (len > chan->mps || len < 0 || __is_sframe(control))
goto drop;
tx_seq = __get_txseq(control);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 6129556..4ba15b3 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -403,9 +403,9 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
opts.omtu = l2cap_pi(sk)->omtu;
opts.flush_to = l2cap_pi(sk)->flush_to;
opts.mode = l2cap_pi(sk)->mode;
- opts.fcs = l2cap_pi(sk)->fcs;
- opts.max_tx = l2cap_pi(sk)->max_tx;
- opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win;
+ opts.fcs = chan->fcs;
+ opts.max_tx = chan->max_tx;
+ opts.txwin_size = (__u16)chan->tx_win;
len = min_t(unsigned int, len, sizeof(opts));
if (copy_to_user(optval, (char *) &opts, len))
@@ -551,9 +551,9 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
opts.omtu = l2cap_pi(sk)->omtu;
opts.flush_to = l2cap_pi(sk)->flush_to;
opts.mode = l2cap_pi(sk)->mode;
- opts.fcs = l2cap_pi(sk)->fcs;
- opts.max_tx = l2cap_pi(sk)->max_tx;
- opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win;
+ opts.fcs = chan->fcs;
+ opts.max_tx = chan->max_tx;
+ opts.txwin_size = (__u16)chan->tx_win;
len = min_t(unsigned int, sizeof(opts), optlen);
if (copy_from_user((char *) &opts, optval, len)) {
@@ -583,9 +583,9 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
l2cap_pi(sk)->imtu = opts.imtu;
l2cap_pi(sk)->omtu = opts.omtu;
- l2cap_pi(sk)->fcs = opts.fcs;
- l2cap_pi(sk)->max_tx = opts.max_tx;
- l2cap_pi(sk)->tx_win = (__u8)opts.txwin_size;
+ chan->fcs = opts.fcs;
+ chan->max_tx = opts.max_tx;
+ chan->tx_win = (__u8)opts.txwin_size;
break;
case L2CAP_LM:
@@ -764,7 +764,8 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
/* Entire SDU fits into one PDU */
if (len <= pi->chan->remote_mps) {
control = L2CAP_SDU_UNSEGMENTED;
- skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0);
+ skb = l2cap_create_iframe_pdu(pi->chan, msg, len,
+ control, 0);
if (IS_ERR(skb)) {
err = PTR_ERR(skb);
goto done;
@@ -998,9 +999,9 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent)
pi->omtu = l2cap_pi(parent)->omtu;
chan->conf_state = pchan->conf_state;
pi->mode = l2cap_pi(parent)->mode;
- pi->fcs = l2cap_pi(parent)->fcs;
- pi->max_tx = l2cap_pi(parent)->max_tx;
- pi->tx_win = l2cap_pi(parent)->tx_win;
+ chan->fcs = pchan->fcs;
+ chan->max_tx = pchan->max_tx;
+ chan->tx_win = pchan->tx_win;
chan->sec_level = pchan->sec_level;
chan->role_switch = pchan->role_switch;
chan->force_reliable = pchan->force_reliable;
@@ -1014,9 +1015,9 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent)
} else {
pi->mode = L2CAP_MODE_BASIC;
}
- pi->max_tx = L2CAP_DEFAULT_MAX_TX;
- pi->fcs = L2CAP_FCS_CRC16;
- pi->tx_win = L2CAP_DEFAULT_TX_WINDOW;
+ chan->max_tx = L2CAP_DEFAULT_MAX_TX;
+ chan->fcs = L2CAP_FCS_CRC16;
+ chan->tx_win = L2CAP_DEFAULT_TX_WINDOW;
chan->sec_level = BT_SECURITY_LOW;
chan->role_switch = 0;
chan->force_reliable = 0;
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index c997393..4f728a4 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -711,7 +711,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src,
sk = sock->sk;
lock_sock(sk);
l2cap_pi(sk)->imtu = l2cap_mtu;
- l2cap_pi(sk)->sec_level = sec_level;
+ l2cap_pi(sk)->chan->sec_level = sec_level;
if (l2cap_ertm)
l2cap_pi(sk)->mode = L2CAP_MODE_ERTM;
release_sock(sk);
--
1.7.5.rc1
^ permalink raw reply related
* [PATCH 4/8] Bluetooth: Move some more elements to struct l2cap_chan
From: Gustavo F. Padovan @ 2011-04-15 18:17 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1302891454-10165-4-git-send-email-padovan@profusion.mobi>
In this commit sec_level, force_reliable, role_switch and flushable.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
include/net/bluetooth/l2cap.h | 12 ++++---
net/bluetooth/l2cap_core.c | 78 ++++++++++++++++++++++-------------------
net/bluetooth/l2cap_sock.c | 52 +++++++++++++++------------
3 files changed, 77 insertions(+), 65 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index f709350..684deee 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -284,6 +284,12 @@ struct srej_list {
struct l2cap_chan {
struct sock *sk;
+
+ __u8 sec_level;
+ __u8 role_switch;
+ __u8 force_reliable;
+ __u8 flushable;
+
__u8 ident;
__u8 conf_req[64];
@@ -371,10 +377,6 @@ struct l2cap_pinfo {
__u8 mode;
__u8 fcs;
- __u8 sec_level;
- __u8 role_switch;
- __u8 force_reliable;
- __u8 flushable;
__u8 tx_win;
__u8 max_tx;
@@ -452,7 +454,7 @@ struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, s
struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len);
struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen);
int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
-void l2cap_do_send(struct sock *sk, struct sk_buff *skb);
+void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb);
void l2cap_streaming_send(struct l2cap_chan *chan);
int l2cap_ertm_send(struct l2cap_chan *chan);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 05848ee..eca9c9a 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -262,10 +262,12 @@ free:
kfree(chan);
}
-static inline u8 l2cap_get_auth_type(struct sock *sk)
+static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
{
+ struct sock *sk = chan->sk;
+
if (sk->sk_type == SOCK_RAW) {
- switch (l2cap_pi(sk)->sec_level) {
+ switch (chan->sec_level) {
case BT_SECURITY_HIGH:
return HCI_AT_DEDICATED_BONDING_MITM;
case BT_SECURITY_MEDIUM:
@@ -274,15 +276,15 @@ static inline u8 l2cap_get_auth_type(struct sock *sk)
return HCI_AT_NO_BONDING;
}
} else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
- if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
- l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
+ if (chan->sec_level == BT_SECURITY_LOW)
+ chan->sec_level = BT_SECURITY_SDP;
- if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
+ if (chan->sec_level == BT_SECURITY_HIGH)
return HCI_AT_NO_BONDING_MITM;
else
return HCI_AT_NO_BONDING;
} else {
- switch (l2cap_pi(sk)->sec_level) {
+ switch (chan->sec_level) {
case BT_SECURITY_HIGH:
return HCI_AT_GENERAL_BONDING_MITM;
case BT_SECURITY_MEDIUM:
@@ -294,15 +296,14 @@ static inline u8 l2cap_get_auth_type(struct sock *sk)
}
/* Service level security */
-static inline int l2cap_check_security(struct sock *sk)
+static inline int l2cap_check_security(struct l2cap_chan *chan)
{
- struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+ struct l2cap_conn *conn = l2cap_pi(chan->sk)->conn;
__u8 auth_type;
- auth_type = l2cap_get_auth_type(sk);
+ auth_type = l2cap_get_auth_type(chan);
- return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,
- auth_type);
+ return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
}
u8 l2cap_get_ident(struct l2cap_conn *conn)
@@ -425,7 +426,8 @@ static void l2cap_do_start(struct l2cap_chan *chan)
if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
return;
- if (l2cap_check_security(sk) && __l2cap_no_conn_pending(chan)) {
+ if (l2cap_check_security(chan) &&
+ __l2cap_no_conn_pending(chan)) {
struct l2cap_conn_req req;
req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
req.psm = l2cap_pi(sk)->psm;
@@ -515,7 +517,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
if (sk->sk_state == BT_CONNECT) {
struct l2cap_conn_req req;
- if (!l2cap_check_security(sk) ||
+ if (!l2cap_check_security(chan) ||
!__l2cap_no_conn_pending(chan)) {
bh_unlock_sock(sk);
continue;
@@ -549,7 +551,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
- if (l2cap_check_security(sk)) {
+ if (l2cap_check_security(chan)) {
if (bt_sk(sk)->defer_setup) {
struct sock *parent = bt_sk(sk)->parent;
rsp.result = cpu_to_le16(L2CAP_CR_PEND);
@@ -722,7 +724,7 @@ static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
list_for_each_entry(chan, &conn->chan_l, list) {
struct sock *sk = chan->sk;
- if (l2cap_pi(sk)->force_reliable)
+ if (chan->force_reliable)
sk->sk_err = err;
}
@@ -867,14 +869,14 @@ int l2cap_chan_connect(struct l2cap_chan *chan)
hci_dev_lock_bh(hdev);
- auth_type = l2cap_get_auth_type(sk);
+ auth_type = l2cap_get_auth_type(chan);
if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
hcon = hci_connect(hdev, LE_LINK, dst,
- l2cap_pi(sk)->sec_level, auth_type);
+ chan->sec_level, auth_type);
else
hcon = hci_connect(hdev, ACL_LINK, dst,
- l2cap_pi(sk)->sec_level, auth_type);
+ chan->sec_level, auth_type);
if (IS_ERR(hcon)) {
err = PTR_ERR(hcon);
@@ -900,7 +902,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan)
if (sk->sk_type != SOCK_SEQPACKET &&
sk->sk_type != SOCK_STREAM) {
l2cap_sock_clear_timer(sk);
- if (l2cap_check_security(sk))
+ if (l2cap_check_security(chan))
sk->sk_state = BT_CONNECTED;
} else
l2cap_do_start(chan);
@@ -1002,15 +1004,15 @@ static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
del_timer(&chan->retrans_timer);
}
-void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
+void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
{
- struct l2cap_pinfo *pi = l2cap_pi(sk);
- struct hci_conn *hcon = pi->conn->hcon;
+ struct sock *sk = chan->sk;
+ struct hci_conn *hcon = l2cap_pi(sk)->conn->hcon;
u16 flags;
- BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
+ BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
- if (!pi->flushable && lmp_no_flush_capable(hcon->hdev))
+ if (!chan->flushable && lmp_no_flush_capable(hcon->hdev))
flags = ACL_START_NO_FLUSH;
else
flags = ACL_START;
@@ -1035,7 +1037,7 @@ void l2cap_streaming_send(struct l2cap_chan *chan)
put_unaligned_le16(fcs, skb->data + skb->len - 2);
}
- l2cap_do_send(sk, skb);
+ l2cap_do_send(chan, skb);
chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
}
@@ -1086,7 +1088,7 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
}
- l2cap_do_send(sk, tx_skb);
+ l2cap_do_send(chan, tx_skb);
}
int l2cap_ertm_send(struct l2cap_chan *chan)
@@ -1129,7 +1131,7 @@ int l2cap_ertm_send(struct l2cap_chan *chan)
put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
}
- l2cap_do_send(sk, tx_skb);
+ l2cap_do_send(chan, tx_skb);
__mod_retrans_timer();
@@ -2099,7 +2101,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
chan->ident = cmd->ident;
if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
- if (l2cap_check_security(sk)) {
+ if (l2cap_check_security(chan)) {
if (bt_sk(sk)->defer_setup) {
sk->sk_state = BT_CONNECT2;
result = L2CAP_CR_PEND;
@@ -3804,17 +3806,19 @@ static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
/* Find listening sockets and check their link_mode */
read_lock(&l2cap_sk_list.lock);
sk_for_each(sk, node, &l2cap_sk_list.head) {
+ struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+
if (sk->sk_state != BT_LISTEN)
continue;
if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
lm1 |= HCI_LM_ACCEPT;
- if (l2cap_pi(sk)->role_switch)
+ if (chan->role_switch)
lm1 |= HCI_LM_MASTER;
exact++;
} else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
lm2 |= HCI_LM_ACCEPT;
- if (l2cap_pi(sk)->role_switch)
+ if (chan->role_switch)
lm2 |= HCI_LM_MASTER;
}
}
@@ -3866,19 +3870,21 @@ static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
return 0;
}
-static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
+static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
{
+ struct sock *sk = chan->sk;
+
if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
return;
if (encrypt == 0x00) {
- if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
+ if (chan->sec_level == BT_SECURITY_MEDIUM) {
l2cap_sock_clear_timer(sk);
l2cap_sock_set_timer(sk, HZ * 5);
- } else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
+ } else if (chan->sec_level == BT_SECURITY_HIGH)
__l2cap_sock_close(sk, ECONNREFUSED);
} else {
- if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
+ if (chan->sec_level == BT_SECURITY_MEDIUM)
l2cap_sock_clear_timer(sk);
}
}
@@ -3907,7 +3913,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
if (!status && (sk->sk_state == BT_CONNECTED ||
sk->sk_state == BT_CONFIG)) {
- l2cap_check_encryption(sk, encrypt);
+ l2cap_check_encryption(chan, encrypt);
bh_unlock_sock(sk);
continue;
}
@@ -4082,7 +4088,7 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p)
batostr(&bt_sk(sk)->dst),
sk->sk_state, __le16_to_cpu(pi->psm),
pi->scid, pi->dcid,
- pi->imtu, pi->omtu, pi->sec_level,
+ pi->imtu, pi->omtu, pi->chan->sec_level,
pi->mode);
}
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 50437c6..6129556 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -51,7 +51,7 @@ static void l2cap_sock_timeout(unsigned long arg)
if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG)
reason = ECONNREFUSED;
else if (sk->sk_state == BT_CONNECT &&
- l2cap_pi(sk)->sec_level != BT_SECURITY_SDP)
+ l2cap_pi(sk)->chan->sec_level != BT_SECURITY_SDP)
reason = ECONNREFUSED;
else
reason = ETIMEDOUT;
@@ -91,6 +91,7 @@ found:
static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
{
struct sock *sk = sock->sk;
+ struct l2cap_chan *chan = l2cap_pi(sk)->chan;
struct sockaddr_l2 la;
int len, err = 0;
@@ -142,7 +143,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
if (__le16_to_cpu(la.l2_psm) == 0x0001 ||
__le16_to_cpu(la.l2_psm) == 0x0003)
- l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
+ chan->sec_level = BT_SECURITY_SDP;
}
if (la.l2_cid)
@@ -382,6 +383,7 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l
static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
{
struct sock *sk = sock->sk;
+ struct l2cap_chan *chan = l2cap_pi(sk)->chan;
struct l2cap_options opts;
struct l2cap_conninfo cinfo;
int len, err = 0;
@@ -412,7 +414,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
break;
case L2CAP_LM:
- switch (l2cap_pi(sk)->sec_level) {
+ switch (chan->sec_level) {
case BT_SECURITY_LOW:
opt = L2CAP_LM_AUTH;
break;
@@ -428,10 +430,10 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
break;
}
- if (l2cap_pi(sk)->role_switch)
+ if (chan->role_switch)
opt |= L2CAP_LM_MASTER;
- if (l2cap_pi(sk)->force_reliable)
+ if (chan->force_reliable)
opt |= L2CAP_LM_RELIABLE;
if (put_user(opt, (u32 __user *) optval))
@@ -467,6 +469,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
{
struct sock *sk = sock->sk;
+ struct l2cap_chan *chan = l2cap_pi(sk)->chan;
struct bt_security sec;
int len, err = 0;
@@ -491,7 +494,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
break;
}
- sec.level = l2cap_pi(sk)->sec_level;
+ sec.level = chan->sec_level;
len = min_t(unsigned int, len, sizeof(sec));
if (copy_to_user(optval, (char *) &sec, len))
@@ -511,7 +514,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
break;
case BT_FLUSHABLE:
- if (put_user(l2cap_pi(sk)->flushable, (u32 __user *) optval))
+ if (put_user(chan->flushable, (u32 __user *) optval))
err = -EFAULT;
break;
@@ -592,14 +595,14 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
}
if (opt & L2CAP_LM_AUTH)
- l2cap_pi(sk)->sec_level = BT_SECURITY_LOW;
+ chan->sec_level = BT_SECURITY_LOW;
if (opt & L2CAP_LM_ENCRYPT)
- l2cap_pi(sk)->sec_level = BT_SECURITY_MEDIUM;
+ chan->sec_level = BT_SECURITY_MEDIUM;
if (opt & L2CAP_LM_SECURE)
- l2cap_pi(sk)->sec_level = BT_SECURITY_HIGH;
+ chan->sec_level = BT_SECURITY_HIGH;
- l2cap_pi(sk)->role_switch = (opt & L2CAP_LM_MASTER);
- l2cap_pi(sk)->force_reliable = (opt & L2CAP_LM_RELIABLE);
+ chan->role_switch = (opt & L2CAP_LM_MASTER);
+ chan->force_reliable = (opt & L2CAP_LM_RELIABLE);
break;
default:
@@ -614,6 +617,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
+ struct l2cap_chan *chan = l2cap_pi(sk)->chan;
struct bt_security sec;
int len, err = 0;
u32 opt;
@@ -650,7 +654,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
break;
}
- l2cap_pi(sk)->sec_level = sec.level;
+ chan->sec_level = sec.level;
break;
case BT_DEFER_SETUP:
@@ -688,7 +692,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
}
}
- l2cap_pi(sk)->flushable = opt;
+ chan->flushable = opt;
break;
default:
@@ -730,7 +734,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
if (IS_ERR(skb)) {
err = PTR_ERR(skb);
} else {
- l2cap_do_send(sk, skb);
+ l2cap_do_send(pi->chan, skb);
err = len;
}
goto done;
@@ -751,7 +755,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
goto done;
}
- l2cap_do_send(sk, skb);
+ l2cap_do_send(pi->chan, skb);
err = len;
break;
@@ -997,10 +1001,10 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent)
pi->fcs = l2cap_pi(parent)->fcs;
pi->max_tx = l2cap_pi(parent)->max_tx;
pi->tx_win = l2cap_pi(parent)->tx_win;
- pi->sec_level = l2cap_pi(parent)->sec_level;
- pi->role_switch = l2cap_pi(parent)->role_switch;
- pi->force_reliable = l2cap_pi(parent)->force_reliable;
- pi->flushable = l2cap_pi(parent)->flushable;
+ chan->sec_level = pchan->sec_level;
+ chan->role_switch = pchan->role_switch;
+ chan->force_reliable = pchan->force_reliable;
+ chan->flushable = pchan->flushable;
} else {
pi->imtu = L2CAP_DEFAULT_MTU;
pi->omtu = 0;
@@ -1013,10 +1017,10 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent)
pi->max_tx = L2CAP_DEFAULT_MAX_TX;
pi->fcs = L2CAP_FCS_CRC16;
pi->tx_win = L2CAP_DEFAULT_TX_WINDOW;
- pi->sec_level = BT_SECURITY_LOW;
- pi->role_switch = 0;
- pi->force_reliable = 0;
- pi->flushable = BT_FLUSHABLE_OFF;
+ chan->sec_level = BT_SECURITY_LOW;
+ chan->role_switch = 0;
+ chan->force_reliable = 0;
+ chan->flushable = BT_FLUSHABLE_OFF;
}
/* Default config options */
--
1.7.5.rc1
^ permalink raw reply related
* [PATCH 3/8] Bluetooth: Rename l2cap_do_connect() to l2cap_chan_connect()
From: Gustavo F. Padovan @ 2011-04-15 18:17 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1302891454-10165-3-git-send-email-padovan@profusion.mobi>
l2cap_chan_connect() is a much better name and reflects what this
functions is doing (or will do once socket dependence is removed from the
core).
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
include/net/bluetooth/l2cap.h | 2 +-
net/bluetooth/l2cap_core.c | 2 +-
net/bluetooth/l2cap_sock.c | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index b3bb3d4..f709350 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -466,6 +466,6 @@ struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err);
struct l2cap_chan *l2cap_chan_alloc(struct sock *sk);
void l2cap_chan_del(struct l2cap_chan *chan, int err);
-int l2cap_do_connect(struct l2cap_chan *chan);
+int l2cap_chan_connect(struct l2cap_chan *chan);
#endif /* __L2CAP_H */
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index a3aa26b..05848ee 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -847,7 +847,7 @@ static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
return node ? sk : sk1;
}
-int l2cap_do_connect(struct l2cap_chan *chan)
+int l2cap_chan_connect(struct l2cap_chan *chan)
{
struct sock *sk = chan->sk;
bdaddr_t *src = &bt_sk(sk)->src;
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index a29782a..50437c6 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -229,7 +229,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
l2cap_pi(sk)->psm = la.l2_psm;
l2cap_pi(sk)->dcid = la.l2_cid;
- err = l2cap_do_connect(l2cap_pi(sk)->chan);
+ err = l2cap_chan_connect(l2cap_pi(sk)->chan);
if (err)
goto done;
--
1.7.5.rc1
^ permalink raw reply related
* [PATCH 2/8] Bluetooth: Move conf_state to struct l2cap_chan
From: Gustavo F. Padovan @ 2011-04-15 18:17 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1302891454-10165-2-git-send-email-padovan@profusion.mobi>
First move of elements depending on user data.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
include/net/bluetooth/l2cap.h | 3 +-
net/bluetooth/l2cap_core.c | 88 +++++++++++++++++++++--------------------
net/bluetooth/l2cap_sock.c | 10 +++-
3 files changed, 53 insertions(+), 48 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 537e3c1..b3bb3d4 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -291,6 +291,7 @@ struct l2cap_chan {
__u8 num_conf_req;
__u8 num_conf_rsp;
+ __u8 conf_state;
__u16 conn_state;
__u8 next_tx_seq;
@@ -375,8 +376,6 @@ struct l2cap_pinfo {
__u8 force_reliable;
__u8 flushable;
- __u8 conf_state;
-
__u8 tx_win;
__u8 max_tx;
__u16 retrans_timeout;
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 9a60ec0..a3aa26b 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -236,8 +236,8 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
} else
sk->sk_state_change(sk);
- if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE &&
- l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE))
+ if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE &&
+ chan->conf_state & L2CAP_CONF_INPUT_DONE))
goto free;
skb_queue_purge(&chan->tx_q);
@@ -411,9 +411,9 @@ static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
l2cap_send_sframe(chan, control);
}
-static inline int __l2cap_no_conn_pending(struct sock *sk)
+static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
{
- return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
+ return !(chan->conf_state & L2CAP_CONF_CONNECT_PEND);
}
static void l2cap_do_start(struct l2cap_chan *chan)
@@ -425,13 +425,13 @@ static void l2cap_do_start(struct l2cap_chan *chan)
if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
return;
- if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) {
+ if (l2cap_check_security(sk) && __l2cap_no_conn_pending(chan)) {
struct l2cap_conn_req req;
req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
req.psm = l2cap_pi(sk)->psm;
chan->ident = l2cap_get_ident(conn);
- l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
+ chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
sizeof(req), &req);
@@ -516,14 +516,14 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
struct l2cap_conn_req req;
if (!l2cap_check_security(sk) ||
- !__l2cap_no_conn_pending(sk)) {
+ !__l2cap_no_conn_pending(chan)) {
bh_unlock_sock(sk);
continue;
}
if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
conn->feat_mask)
- && l2cap_pi(sk)->conf_state &
+ && chan->conf_state &
L2CAP_CONF_STATE2_DEVICE) {
/* __l2cap_sock_close() calls list_del(chan)
* so release the lock */
@@ -538,7 +538,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
req.psm = l2cap_pi(sk)->psm;
chan->ident = l2cap_get_ident(conn);
- l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
+ chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
sizeof(req), &req);
@@ -569,13 +569,13 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
sizeof(rsp), &rsp);
- if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
+ if (chan->conf_state & L2CAP_CONF_REQ_SENT ||
rsp.result != L2CAP_CR_SUCCESS) {
bh_unlock_sock(sk);
continue;
}
- l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
+ chan->conf_state |= L2CAP_CONF_REQ_SENT;
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
l2cap_build_conf_req(chan, buf), buf);
chan->num_conf_req++;
@@ -1381,10 +1381,11 @@ int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t le
static void l2cap_chan_ready(struct sock *sk)
{
struct sock *parent = bt_sk(sk)->parent;
+ struct l2cap_chan *chan = l2cap_pi(sk)->chan;
BT_DBG("sk %p, parent %p", sk, parent);
- l2cap_pi(sk)->conf_state = 0;
+ chan->conf_state = 0;
l2cap_sock_clear_timer(sk);
if (!parent) {
@@ -1618,7 +1619,7 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
switch (pi->mode) {
case L2CAP_MODE_STREAMING:
case L2CAP_MODE_ERTM:
- if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
+ if (chan->conf_state & L2CAP_CONF_STATE2_DEVICE)
break;
/* fall through */
@@ -1665,7 +1666,7 @@ done:
break;
if (pi->fcs == L2CAP_FCS_NONE ||
- pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
+ chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
pi->fcs = L2CAP_FCS_NONE;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
}
@@ -1688,7 +1689,7 @@ done:
break;
if (pi->fcs == L2CAP_FCS_NONE ||
- pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
+ chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
pi->fcs = L2CAP_FCS_NONE;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
}
@@ -1741,7 +1742,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
case L2CAP_CONF_FCS:
if (val == L2CAP_FCS_NONE)
- pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
+ chan->conf_state |= L2CAP_CONF_NO_FCS_RECV;
break;
@@ -1761,7 +1762,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
switch (pi->mode) {
case L2CAP_MODE_STREAMING:
case L2CAP_MODE_ERTM:
- if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
+ if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
pi->mode = l2cap_select_mode(rfc.mode,
pi->conn->feat_mask);
break;
@@ -1794,14 +1795,14 @@ done:
result = L2CAP_CONF_UNACCEPT;
else {
pi->omtu = mtu;
- pi->conf_state |= L2CAP_CONF_MTU_DONE;
+ chan->conf_state |= L2CAP_CONF_MTU_DONE;
}
l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
switch (rfc.mode) {
case L2CAP_MODE_BASIC:
pi->fcs = L2CAP_FCS_NONE;
- pi->conf_state |= L2CAP_CONF_MODE_DONE;
+ chan->conf_state |= L2CAP_CONF_MODE_DONE;
break;
case L2CAP_MODE_ERTM:
@@ -1818,7 +1819,7 @@ done:
rfc.monitor_timeout =
le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
- pi->conf_state |= L2CAP_CONF_MODE_DONE;
+ chan->conf_state |= L2CAP_CONF_MODE_DONE;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
sizeof(rfc), (unsigned long) &rfc);
@@ -1831,7 +1832,7 @@ done:
chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
- pi->conf_state |= L2CAP_CONF_MODE_DONE;
+ chan->conf_state |= L2CAP_CONF_MODE_DONE;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
sizeof(rfc), (unsigned long) &rfc);
@@ -1846,7 +1847,7 @@ done:
}
if (result == L2CAP_CONF_SUCCESS)
- pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
+ chan->conf_state |= L2CAP_CONF_OUTPUT_DONE;
}
rsp->scid = cpu_to_le16(pi->dcid);
rsp->result = cpu_to_le16(result);
@@ -1855,8 +1856,9 @@ done:
return ptr - data;
}
-static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
+static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result)
{
+ struct sock *sk = chan->sk;
struct l2cap_pinfo *pi = l2cap_pi(sk);
struct l2cap_conf_req *req = data;
void *ptr = req->data;
@@ -1889,7 +1891,7 @@ static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data,
if (olen == sizeof(rfc))
memcpy(&rfc, (void *)val, olen);
- if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
+ if ((chan->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
rfc.mode != pi->mode)
return -ECONNREFUSED;
@@ -1954,10 +1956,10 @@ void __l2cap_connect_rsp_defer(struct sock *sk)
l2cap_send_cmd(conn, chan->ident,
L2CAP_CONN_RSP, sizeof(rsp), &rsp);
- if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
+ if (chan->conf_state & L2CAP_CONF_REQ_SENT)
return;
- l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
+ chan->conf_state |= L2CAP_CONF_REQ_SENT;
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
l2cap_build_conf_req(chan, buf), buf);
chan->num_conf_req++;
@@ -2145,10 +2147,10 @@ sendresp:
L2CAP_INFO_REQ, sizeof(info), &info);
}
- if (chan && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
+ if (chan && !(chan->conf_state & L2CAP_CONF_REQ_SENT) &&
result == L2CAP_CR_SUCCESS) {
u8 buf[128];
- l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
+ chan->conf_state |= L2CAP_CONF_REQ_SENT;
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
l2cap_build_conf_req(chan, buf), buf);
chan->num_conf_req++;
@@ -2189,12 +2191,12 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
sk->sk_state = BT_CONFIG;
chan->ident = 0;
l2cap_pi(sk)->dcid = dcid;
- l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
+ chan->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
- if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
+ if (chan->conf_state & L2CAP_CONF_REQ_SENT)
break;
- l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
+ chan->conf_state |= L2CAP_CONF_REQ_SENT;
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
l2cap_build_conf_req(chan, req), req);
@@ -2202,7 +2204,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
break;
case L2CAP_CR_PEND:
- l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
+ chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
break;
default:
@@ -2229,7 +2231,7 @@ static inline void set_default_fcs(struct l2cap_pinfo *pi)
*/
if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
pi->fcs = L2CAP_FCS_NONE;
- else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
+ else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV))
pi->fcs = L2CAP_FCS_CRC16;
}
@@ -2296,10 +2298,10 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
/* Reset config buffer. */
chan->conf_len = 0;
- if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
+ if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE))
goto unlock;
- if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
+ if (chan->conf_state & L2CAP_CONF_INPUT_DONE) {
set_default_fcs(l2cap_pi(sk));
sk->sk_state = BT_CONNECTED;
@@ -2314,9 +2316,9 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
goto unlock;
}
- if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
+ if (!(chan->conf_state & L2CAP_CONF_REQ_SENT)) {
u8 buf[64];
- l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
+ chan->conf_state |= L2CAP_CONF_REQ_SENT;
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
l2cap_build_conf_req(chan, buf), buf);
chan->num_conf_req++;
@@ -2364,8 +2366,8 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
/* throw out any old stored conf requests */
result = L2CAP_CONF_SUCCESS;
- len = l2cap_parse_conf_rsp(sk, rsp->data,
- len, req, &result);
+ len = l2cap_parse_conf_rsp(chan, rsp->data, len,
+ req, &result);
if (len < 0) {
l2cap_send_disconn_req(conn, chan, ECONNRESET);
goto done;
@@ -2389,9 +2391,9 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
if (flags & 0x01)
goto done;
- l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
+ chan->conf_state |= L2CAP_CONF_INPUT_DONE;
- if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
+ if (chan->conf_state & L2CAP_CONF_OUTPUT_DONE) {
set_default_fcs(l2cap_pi(sk));
sk->sk_state = BT_CONNECTED;
@@ -3898,7 +3900,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
bh_lock_sock(sk);
- if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
+ if (chan->conf_state & L2CAP_CONF_CONNECT_PEND) {
bh_unlock_sock(sk);
continue;
}
@@ -3917,7 +3919,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
req.psm = l2cap_pi(sk)->psm;
chan->ident = l2cap_get_ident(conn);
- l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
+ chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
l2cap_send_cmd(conn, chan->ident,
L2CAP_CONN_REQ, sizeof(req), &req);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index e372457..a29782a 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -528,6 +528,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
+ struct l2cap_chan *chan = l2cap_pi(sk)->chan;
struct l2cap_options opts;
int len, err = 0;
u32 opt;
@@ -565,7 +566,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
l2cap_pi(sk)->mode = opts.mode;
switch (l2cap_pi(sk)->mode) {
case L2CAP_MODE_BASIC:
- l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_STATE2_DEVICE;
+ chan->conf_state &= ~L2CAP_CONF_STATE2_DEVICE;
break;
case L2CAP_MODE_ERTM:
case L2CAP_MODE_STREAMING:
@@ -979,16 +980,19 @@ static void l2cap_sock_destruct(struct sock *sk)
void l2cap_sock_init(struct sock *sk, struct sock *parent)
{
struct l2cap_pinfo *pi = l2cap_pi(sk);
+ struct l2cap_chan *chan = pi->chan;
BT_DBG("sk %p", sk);
if (parent) {
+ struct l2cap_chan *pchan = l2cap_pi(parent)->chan;
+
sk->sk_type = parent->sk_type;
bt_sk(sk)->defer_setup = bt_sk(parent)->defer_setup;
pi->imtu = l2cap_pi(parent)->imtu;
pi->omtu = l2cap_pi(parent)->omtu;
- pi->conf_state = l2cap_pi(parent)->conf_state;
+ chan->conf_state = pchan->conf_state;
pi->mode = l2cap_pi(parent)->mode;
pi->fcs = l2cap_pi(parent)->fcs;
pi->max_tx = l2cap_pi(parent)->max_tx;
@@ -1002,7 +1006,7 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent)
pi->omtu = 0;
if (!disable_ertm && sk->sk_type == SOCK_STREAM) {
pi->mode = L2CAP_MODE_ERTM;
- pi->conf_state |= L2CAP_CONF_STATE2_DEVICE;
+ chan->conf_state |= L2CAP_CONF_STATE2_DEVICE;
} else {
pi->mode = L2CAP_MODE_BASIC;
}
--
1.7.5.rc1
^ permalink raw reply related
* [PATCH 1/8] Bluetooth: Refactor L2CAP channel allocation
From: Gustavo F. Padovan @ 2011-04-15 18:17 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1302891454-10165-1-git-send-email-padovan@profusion.mobi>
If the allocation happens at l2cap_sock_create() will be able to use the
struct l2cap_chan to store channel info that comes from the user via
setsockopt.
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
---
include/net/bluetooth/l2cap.h | 3 ++-
net/bluetooth/l2cap_core.c | 23 +++++++----------------
net/bluetooth/l2cap_sock.c | 11 ++++++++++-
3 files changed, 19 insertions(+), 18 deletions(-)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 7a215a7..537e3c1 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -465,7 +465,8 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent);
struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
int proto, gfp_t prio);
void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err);
+struct l2cap_chan *l2cap_chan_alloc(struct sock *sk);
void l2cap_chan_del(struct l2cap_chan *chan, int err);
-int l2cap_do_connect(struct sock *sk);
+int l2cap_do_connect(struct l2cap_chan *chan);
#endif /* __L2CAP_H */
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index d47de2b..9a60ec0 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -149,7 +149,7 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
return 0;
}
-static struct l2cap_chan *l2cap_chan_alloc(struct sock *sk)
+struct l2cap_chan *l2cap_chan_alloc(struct sock *sk)
{
struct l2cap_chan *chan;
@@ -648,6 +648,8 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
goto clean;
}
+ l2cap_pi(sk)->chan = chan;
+
write_lock_bh(&conn->chan_lock);
hci_conn_hold(conn->hcon);
@@ -661,8 +663,6 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
__l2cap_chan_add(conn, chan);
- l2cap_pi(sk)->chan = chan;
-
l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
sk->sk_state = BT_CONNECTED;
@@ -847,12 +847,12 @@ static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
return node ? sk : sk1;
}
-int l2cap_do_connect(struct sock *sk)
+int l2cap_do_connect(struct l2cap_chan *chan)
{
+ struct sock *sk = chan->sk;
bdaddr_t *src = &bt_sk(sk)->src;
bdaddr_t *dst = &bt_sk(sk)->dst;
struct l2cap_conn *conn;
- struct l2cap_chan *chan;
struct hci_conn *hcon;
struct hci_dev *hdev;
__u8 auth_type;
@@ -888,20 +888,11 @@ int l2cap_do_connect(struct sock *sk)
goto done;
}
- chan = l2cap_chan_alloc(sk);
- if (!chan) {
- hci_conn_put(hcon);
- err = -ENOMEM;
- goto done;
- }
-
/* Update source addr of the socket */
bacpy(src, conn->src);
l2cap_chan_add(conn, chan);
- l2cap_pi(sk)->chan = chan;
-
sk->sk_state = BT_CONNECT;
l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
@@ -2075,6 +2066,8 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
goto response;
}
+ l2cap_pi(sk)->chan = chan;
+
write_lock_bh(&conn->chan_lock);
/* Check if we already have channel with that dcid */
@@ -2097,8 +2090,6 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
__l2cap_chan_add(conn, chan);
- l2cap_pi(sk)->chan = chan;
-
dcid = l2cap_pi(sk)->scid;
l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 473e597..e372457 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -229,7 +229,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
l2cap_pi(sk)->psm = la.l2_psm;
l2cap_pi(sk)->dcid = la.l2_cid;
- err = l2cap_do_connect(sk);
+ err = l2cap_do_connect(l2cap_pi(sk)->chan);
if (err)
goto done;
@@ -1054,6 +1054,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
int kern)
{
struct sock *sk;
+ struct l2cap_chan *chan;
BT_DBG("sock %p", sock);
@@ -1072,6 +1073,14 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
if (!sk)
return -ENOMEM;
+ chan = l2cap_chan_alloc(sk);
+ if (!chan) {
+ l2cap_sock_kill(sk);
+ return -ENOMEM;
+ }
+
+ l2cap_pi(sk)->chan = chan;
+
l2cap_sock_init(sk, NULL);
return 0;
}
--
1.7.5.rc1
^ permalink raw reply related
* [PATCH 0/8] Second round of patches for the l2cap "rewrite"
From: Gustavo F. Padovan @ 2011-04-15 18:17 UTC (permalink / raw)
To: linux-bluetooth
These patches finishes almost all the data separatation bettween an L2CAP
socket and an L2CAP channel. Some missing pieces are:
- New locking system to the l2cap_channel (together with the a new
backlog recv queue implementation).
- Keep the state of the connection on strcut l2cap_chan ( and notify
the socket about changes on the state)
- New ways to retrieve data from bt_sk.
- New list to search for the psm and scid we can accept a connection
or receive data (connectionless case)
Then we need to draw an API to access L2CAP channels from l2cap_sock.c and
RFCOMM, and a notify system for L2CAP core tell its users about new data, state
changes, etc.
Please comment.
Regards,
Gustavo F. Padovan (8):
Bluetooth: Refactor L2CAP channel allocation
Bluetooth: Move conf_state to struct l2cap_chan
Bluetooth: Rename l2cap_do_connect() to l2cap_chan_connect()
Bluetooth: Move some more elements to struct l2cap_chan
Bluetooth: Move more vars to struct l2cap_chan
Bluetooth: Move more channel info to struct l2cap_chan
Bluetooth: Move more vars to struct l2cap_chan
Bluetooth: Move conn to struct l2cap_chan
include/net/bluetooth/l2cap.h | 67 +++---
net/bluetooth/l2cap_core.c | 578 ++++++++++++++++++++---------------------
net/bluetooth/l2cap_sock.c | 236 ++++++++++--------
net/bluetooth/rfcomm/core.c | 21 +-
net/bluetooth/rfcomm/sock.c | 5 +-
5 files changed, 465 insertions(+), 442 deletions(-)
--
1.7.5.rc1
^ permalink raw reply
* [RFC 4/4] hcimgmt: add support for setting pairable mode
From: Vinicius Costa Gomes @ 2011-04-15 17:57 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1302890265-15649-1-git-send-email-vinicius.gomes@openbossa.org>
---
tools/hcimgmt.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 54 insertions(+), 1 deletions(-)
diff --git a/tools/hcimgmt.c b/tools/hcimgmt.c
index 7744344..9998982 100644
--- a/tools/hcimgmt.c
+++ b/tools/hcimgmt.c
@@ -407,6 +407,58 @@ static void cmd_clearkeys(int dev_id, int argc, char **argv)
}
}
+static struct option pairable_options[] = {
+ { "help", 0, 0, 'h' },
+ { 0, 0, 0, 0 }
+};
+
+static const char *pairable_help =
+ "Usage:\n"
+ "\tclearkeys <1|0>\n";
+
+static void cmd_pairable(int dev_id, int argc, char **argv)
+{
+ int opt, dd;
+ ssize_t ret;
+ struct mgmt_mode cp;
+
+ for_each_opt(opt, pairable_options, NULL) {
+ switch (opt) {
+ default:
+ printf("%s", pairable_help);
+ return;
+ }
+ }
+
+ helper_arg(1, 1, &argc, &argv, pairable_help);
+
+ memset(&cp, 0, sizeof(cp));
+
+ dd = hci_open_channel(HCI_DEV_NONE, HCI_CHANNEL_CONTROL);
+ if (dd < 0) {
+ perror("HCI Control socket open failed");
+ exit(1);
+ }
+
+ if (dev_id < 0) {
+ dev_id = hci_get_route(NULL);
+ if (dev_id < 0) {
+ perror("Device is not available");
+ exit(1);
+ }
+ }
+
+ cp.val = (uint8_t) strtol(argv[0], NULL, 0);
+
+ ret = hci_mgmt_cmd(dd, dev_id, MGMT_OP_SET_PAIRABLE, &cp, sizeof(cp),
+ MGMT_EV_CMD_COMPLETE, NULL, 0);
+ if (ret < 0) {
+ fprintf(stderr, "Command failed: %s (%zd)\n",
+ strerror(-ret), -ret);
+ exit(1);
+ }
+}
+
static struct {
char *cmd;
void (*func)(int dev_id, int argc, char **argv);
@@ -417,7 +469,8 @@ static struct {
{ "features", cmd_features, "Control API features" },
{ "info", cmd_info, "Read controller info" },
{ "setiocap", cmd_setiocap, "Set IO Capabilities" },
- { "clearkeys", cmd_clearkeys, "Clear key list" },
+ { "clearkeys", cmd_clearkeys, "Clear key list" },
+ { "pairable", cmd_pairable, "Set pairable mode" },
{ NULL, NULL, 0 }
};
--
1.7.4.3
^ permalink raw reply related
* [RFC 3/4] Add command to clear the link key list via MGMT interface
From: Vinicius Costa Gomes @ 2011-04-15 17:57 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1302890265-15649-1-git-send-email-vinicius.gomes@openbossa.org>
---
tools/hcimgmt.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 51 insertions(+), 0 deletions(-)
diff --git a/tools/hcimgmt.c b/tools/hcimgmt.c
index fc88654..7744344 100644
--- a/tools/hcimgmt.c
+++ b/tools/hcimgmt.c
@@ -357,6 +357,56 @@ static void cmd_setiocap(int dev_id, int argc, char **argv)
}
}
+static struct option clearkeys_options[] = {
+ { "help", 0, 0, 'h' },
+ { 0, 0, 0, 0 }
+};
+
+static const char *clearkeys_help =
+ "Usage:\n"
+ "\tclearkeys\n";
+
+static void cmd_clearkeys(int dev_id, int argc, char **argv)
+{
+ int opt, dd;
+ ssize_t ret;
+ struct mgmt_cp_load_keys cp;
+
+ for_each_opt(opt, clearkeys_options, NULL) {
+ switch (opt) {
+ default:
+ printf("%s", clearkeys_help);
+ return;
+ }
+ }
+
+ helper_arg(0, 0, &argc, &argv, setiocap_help);
+
+ memset(&cp, 0, sizeof(cp));
+
+ dd = hci_open_channel(HCI_DEV_NONE, HCI_CHANNEL_CONTROL);
+ if (dd < 0) {
+ perror("HCI Control socket open failed");
+ exit(1);
+ }
+
+ if (dev_id < 0) {
+ dev_id = hci_get_route(NULL);
+ if (dev_id < 0) {
+ perror("Device is not available");
+ exit(1);
+ }
+ }
+
+ ret = hci_mgmt_cmd(dd, dev_id, MGMT_OP_LOAD_KEYS, &cp, sizeof(cp),
+ MGMT_EV_CMD_COMPLETE, NULL, 0);
+ if (ret < 0) {
+ fprintf(stderr, "Command failed: %s (%zd)\n",
+ strerror(-ret), -ret);
+ exit(1);
+ }
+}
+
static struct {
char *cmd;
void (*func)(int dev_id, int argc, char **argv);
@@ -367,6 +417,7 @@ static struct {
{ "features", cmd_features, "Control API features" },
{ "info", cmd_info, "Read controller info" },
{ "setiocap", cmd_setiocap, "Set IO Capabilities" },
+ { "clearkeys", cmd_clearkeys, "Clear key list" },
{ NULL, NULL, 0 }
};
--
1.7.4.3
^ permalink raw reply related
* [RFC 2/4] hcimgmt: Add command to set IO Capabilities
From: Vinicius Costa Gomes @ 2011-04-15 17:57 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1302890265-15649-1-git-send-email-vinicius.gomes@openbossa.org>
---
tools/hcimgmt.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 80 insertions(+), 0 deletions(-)
diff --git a/tools/hcimgmt.c b/tools/hcimgmt.c
index 99338ed..fc88654 100644
--- a/tools/hcimgmt.c
+++ b/tools/hcimgmt.c
@@ -46,6 +46,31 @@
#define for_each_opt(opt, long, short) while ((opt=getopt_long(argc, argv, short ? short:"+", long, NULL)) != -1)
+static void helper_arg(int min_num_arg, int max_num_arg, int *argc,
+ char ***argv, const char *usage)
+{
+ *argc -= optind;
+ /* too many arguments, but when "max_num_arg < min_num_arg" then no
+ limiting (prefer "max_num_arg=-1" to gen infinity)
+ */
+ if ( (*argc > max_num_arg) && (max_num_arg >= min_num_arg ) ) {
+ fprintf(stderr, "%s: too many arguments (maximal: %i)\n",
+ *argv[0], max_num_arg);
+ printf("%s", usage);
+ exit(1);
+ }
+
+ /* print usage */
+ if (*argc < min_num_arg) {
+ fprintf(stderr, "%s: too few arguments (minimal: %i)\n",
+ *argv[0], min_num_arg);
+ printf("%s", usage);
+ exit(0);
+ }
+
+ *argv += optind;
+}
+
static void usage(void);
/* Display local devices */
@@ -131,6 +156,9 @@ static ssize_t hci_mgmt_cmd(int dd, uint16_t index, uint16_t opcode, void *data,
return -EIO;
}
+ if (rsp == NULL)
+ return 0;
+
/* sizeof(opcode) == 2 */
plen = btohs(hdr.len) - 2;
copied = rsp_len < plen ? plen : rsp_len;
@@ -278,6 +306,57 @@ static void cmd_info(int dev_id, int argc, char **argv)
printf("\n");
}
+static struct option setiocap_options[] = {
+ { "help", 0, 0, 'h' },
+ { 0, 0, 0, 0 }
+};
+
+static const char *setiocap_help =
+ "Usage:\n"
+ "\tsetiocap <value>\n";
+
+static void cmd_setiocap(int dev_id, int argc, char **argv)
+{
+ int opt, dd;
+ ssize_t ret;
+ struct mgmt_cp_set_io_capability cp;
+
+ for_each_opt(opt, setiocap_options, NULL) {
+ switch (opt) {
+ default:
+ printf("%s", setiocap_help);
+ return;
+ }
+ }
+
+ helper_arg(1, 1, &argc, &argv, setiocap_help);
+
+ memset(&cp, 0, sizeof(cp));
+ cp.io_capability = (uint8_t) strtol(argv[0], NULL, 0);
+
+ dd = hci_open_channel(HCI_DEV_NONE, HCI_CHANNEL_CONTROL);
+ if (dd < 0) {
+ perror("HCI Control socket open failed");
+ exit(1);
+ }
+
+ if (dev_id < 0) {
+ dev_id = hci_get_route(NULL);
+ if (dev_id < 0) {
+ perror("Device is not available");
+ exit(1);
+ }
+ }
+
+ ret = hci_mgmt_cmd(dd, dev_id, MGMT_OP_SET_IO_CAPABILITY, &cp, sizeof(cp),
+ MGMT_EV_CMD_COMPLETE, NULL, 0);
+ if (ret < 0) {
+ fprintf(stderr, "Command failed: %s (%zd)\n",
+ strerror(-ret), -ret);
+ exit(1);
+ }
+}
+
static struct {
char *cmd;
void (*func)(int dev_id, int argc, char **argv);
@@ -287,6 +366,7 @@ static struct {
{ "version", cmd_version, "Display version" },
{ "features", cmd_features, "Control API features" },
{ "info", cmd_info, "Read controller info" },
+ { "setiocap", cmd_setiocap, "Set IO Capabilities" },
{ NULL, NULL, 0 }
};
--
1.7.4.3
^ permalink raw reply related
* [RFC 1/4] Add hcimgmt command line test tool
From: Vinicius Costa Gomes @ 2011-04-15 17:57 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Johan Hedberg
In-Reply-To: <1302890265-15649-1-git-send-email-vinicius.gomes@openbossa.org>
From: Johan Hedberg <johan.hedberg@nokia.com>
---
Makefile.tools | 5 +-
tools/hcimgmt.c | 362 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 366 insertions(+), 1 deletions(-)
create mode 100644 tools/hcimgmt.c
diff --git a/Makefile.tools b/Makefile.tools
index 364db37..98fb99c 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -5,7 +5,7 @@ conf_DATA += tools/rfcomm.conf
endif
bin_PROGRAMS += tools/rfcomm tools/l2ping \
- tools/hcitool tools/sdptool tools/ciptool
+ tools/hcitool tools/sdptool tools/ciptool tools/hcimgmt
sbin_PROGRAMS += tools/hciattach tools/hciconfig
@@ -38,6 +38,9 @@ tools_hcitool_SOURCES = tools/hcitool.c src/oui.h src/oui.c \
src/textfile.h src/textfile.c
tools_hcitool_LDADD = lib/libbluetooth.la
+tools_hcimgmt_SOURCES = tools/hcimgmt.c
+tools_hcimgmt_LDADD = lib/libbluetooth.la
+
tools_sdptool_SOURCES = tools/sdptool.c src/sdp-xml.h src/sdp-xml.c
tools_sdptool_LDADD = lib/libbluetooth.la
diff --git a/tools/hcimgmt.c b/tools/hcimgmt.c
new file mode 100644
index 0000000..99338ed
--- /dev/null
+++ b/tools/hcimgmt.c
@@ -0,0 +1,362 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>
+#include <bluetooth/mgmt.h>
+
+#define MGMT_BUF_SIZE 1024
+
+#define for_each_opt(opt, long, short) while ((opt=getopt_long(argc, argv, short ? short:"+", long, NULL)) != -1)
+
+static void usage(void);
+
+/* Display local devices */
+
+static struct option dev_options[] = {
+ { "help", 0, 0, 'h' },
+ {0, 0, 0, 0 }
+};
+
+static int hci_open_channel(int dev_id, unsigned short channel)
+{
+ struct sockaddr_hci a;
+ int dd, err;
+
+ /* Create HCI socket */
+ dd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+ if (dd < 0)
+ return -errno;
+
+ /* Bind socket to the HCI device */
+ memset(&a, 0, sizeof(a));
+ a.hci_family = AF_BLUETOOTH;
+ a.hci_dev = dev_id;
+ a.hci_channel = channel;
+ if (bind(dd, (struct sockaddr *) &a, sizeof(a)) < 0) {
+ err = -errno;
+ goto fail;
+ }
+
+ return dd;
+
+fail:
+ close(dd);
+ return err;
+}
+
+static ssize_t hci_mgmt_cmd(int dd, uint16_t index, uint16_t opcode, void *data,
+ uint16_t len, uint16_t rsp_ev, void *rsp, uint16_t rsp_len)
+{
+ ssize_t ret;
+ size_t copied, plen;
+ struct mgmt_hdr hdr = { htobs(opcode), htobs(index), htobs(len) };
+ struct mgmt_ev_cmd_complete *cc;
+ char buf[MGMT_BUF_SIZE];
+
+ memcpy(buf, &hdr, sizeof(hdr));
+ memcpy(buf + sizeof(hdr), data, len);
+
+ ret = write(dd, buf, sizeof(hdr) + len);
+ if (ret < 0)
+ return -errno;
+
+ ret = read(dd, buf, sizeof(buf));
+ if (ret < 0)
+ return -errno;
+
+ if (ret < (ssize_t) sizeof(struct mgmt_hdr)) {
+ fprintf(stderr,
+ "ret (%zd) != sizeof(struct mgmt_hdr) (%zu)\n",
+ ret, sizeof(struct mgmt_hdr));
+ return -EIO;
+ }
+
+ memcpy(&hdr, buf, sizeof(hdr));
+
+ if (btohs(hdr.len) != ret - sizeof(hdr)) {
+ fprintf(stderr, "hdr.len (%u) != ret - sizeof(hdr) (%zu)\n",
+ btohs(hdr.len), ret - sizeof(hdr));
+ return -EIO;
+ }
+
+ if (btohs(hdr.opcode) != rsp_ev) {
+ fprintf(stderr, "hdr.opcode (%u) != rsp_ev (%u)\n",
+ btohs(hdr.opcode), rsp_ev);
+ return -EIO;
+ }
+
+ cc = (void *) &buf[sizeof(hdr)];
+
+ if (btohs(cc->opcode) != opcode) {
+ fprintf(stderr, "cc.opcode (%u) != opcode (%u)\n",
+ btohs(cc->opcode), opcode);
+ return -EIO;
+ }
+
+ /* sizeof(opcode) == 2 */
+ plen = btohs(hdr.len) - 2;
+ copied = rsp_len < plen ? plen : rsp_len;
+
+ memcpy(rsp, cc->data, copied);
+
+ return copied;
+}
+
+static void print_bytes(uint8_t *bytes, size_t count)
+{
+ size_t i;
+
+ for (i = 0; i < count; i++)
+ printf("%02x ", bytes[i]);
+}
+
+static void cmd_features(int dev_id, int argc, char **argv)
+{
+ int dd;
+ ssize_t ret;
+ struct mgmt_rp_read_features rp;
+
+ dd = hci_open_channel(HCI_DEV_NONE, HCI_CHANNEL_CONTROL);
+ if (dd < 0) {
+ perror("HCI Control socket open failed");
+ exit(1);
+ }
+
+ ret = hci_mgmt_cmd(dd, MGMT_INDEX_NONE, MGMT_OP_READ_FEATURES, NULL, 0,
+ MGMT_EV_CMD_COMPLETE, &rp, sizeof(rp));
+ if (ret < 0) {
+ fprintf(stderr, "Command failed: %s (%zd)\n",
+ strerror(-ret), -ret);
+ exit(1);
+ }
+
+ printf("HCI Control API features: ");
+ print_bytes(rp.features, 8);
+ printf("\n");
+}
+
+static void cmd_version(int dev_id, int argc, char **argv)
+{
+ int dd;
+ ssize_t ret;
+ struct mgmt_rp_read_version rp;
+
+ dd = hci_open_channel(HCI_DEV_NONE, HCI_CHANNEL_CONTROL);
+ if (dd < 0) {
+ perror("HCI Control socket open failed");
+ exit(1);
+ }
+
+ ret = hci_mgmt_cmd(dd, dev_id, MGMT_OP_READ_VERSION, NULL, 0,
+ MGMT_EV_CMD_COMPLETE, &rp, sizeof(rp));
+ if (ret < 0) {
+ fprintf(stderr, "Command failed: %s (%zd)\n",
+ strerror(-ret), -ret);
+ exit(1);
+ }
+
+ printf("HCI Control API version %u.%u\n", rp.version,
+ btohs(rp.revision));
+}
+
+static const char *dev_help =
+ "Usage:\n"
+ "\tdev\n";
+
+static void cmd_dev(int dev_id, int argc, char **argv)
+{
+ int opt, dd, i;
+ ssize_t ret;
+ uint16_t *ptr;
+ struct mgmt_rp_read_index_list rp;
+
+ for_each_opt(opt, dev_options, NULL) {
+ switch (opt) {
+ default:
+ printf("%s", dev_help);
+ return;
+ }
+ }
+
+ dd = hci_open_channel(HCI_DEV_NONE, HCI_CHANNEL_CONTROL);
+ if (dd < 0) {
+ perror("HCI Control socket open failed");
+ exit(1);
+ }
+
+ ret = hci_mgmt_cmd(dd, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST,
+ NULL, 0, MGMT_EV_CMD_COMPLETE, &rp, sizeof(rp));
+ if (ret < 0) {
+ fprintf(stderr, "Failed\n");
+ exit(1);
+ }
+
+ ptr = rp.index;
+ for (i = 0; i < btohs(rp.num_controllers); i++, ptr += 2) {
+ uint16_t index;
+ memcpy(&index, ptr, 2);
+ printf("hci%u ", btohs(index));
+ }
+
+ printf("\n");
+}
+
+static void cmd_info(int dev_id, int argc, char **argv)
+{
+ int dd;
+ uint16_t id;
+ ssize_t ret;
+ char addr[18];
+ struct mgmt_rp_read_info rp;
+
+ dd = hci_open_channel(HCI_DEV_NONE, HCI_CHANNEL_CONTROL);
+ if (dd < 0) {
+ perror("HCI Control socket open failed");
+ exit(1);
+ }
+
+ if (dev_id < 0) {
+ dev_id = hci_get_route(NULL);
+ if (dev_id < 0) {
+ perror("Device is not available");
+ exit(1);
+ }
+ }
+
+ id = (uint16_t) dev_id;
+
+ ret = hci_mgmt_cmd(dd, id, MGMT_OP_READ_INFO, NULL, 0,
+ MGMT_EV_CMD_COMPLETE, &rp, sizeof(rp));
+ if (ret < 0) {
+ fprintf(stderr, "Command failed: %s (%zd)\n",
+ strerror(-ret), -ret);
+ exit(1);
+ }
+
+ ba2str(&rp.bdaddr, addr);
+
+ printf("hci%u type %u addr %s features ", btohs(id), rp.type, addr);
+ print_bytes(rp.features, 8);
+ printf("\n");
+}
+
+static struct {
+ char *cmd;
+ void (*func)(int dev_id, int argc, char **argv);
+ char *doc;
+} command[] = {
+ { "dev", cmd_dev, "Display local devices" },
+ { "version", cmd_version, "Display version" },
+ { "features", cmd_features, "Control API features" },
+ { "info", cmd_info, "Read controller info" },
+ { NULL, NULL, 0 }
+};
+
+static void usage(void)
+{
+ int i;
+
+ printf("hcictl - HCI Control ver %s\n", VERSION);
+ printf("Usage:\n"
+ "\thcictl [options] <command> [command parameters]\n");
+ printf("Options:\n"
+ "\t--help\tDisplay help\n"
+ "\t-i dev\tHCI device\n");
+ printf("Commands:\n");
+ for (i = 0; command[i].cmd; i++)
+ printf("\t%-4s\t%s\n", command[i].cmd,
+ command[i].doc);
+ printf("\n"
+ "For more information on the usage of each command use:\n"
+ "\thcictl <command> --help\n" );
+}
+
+static struct option main_options[] = {
+ { "help", 0, 0, 'h' },
+ { "device", 1, 0, 'i' },
+ { 0, 0, 0, 0 }
+};
+
+int main(int argc, char *argv[])
+{
+ int opt, i, dev_id = -1;
+ bdaddr_t ba;
+
+ while ((opt = getopt_long(argc, argv, "+i:h", main_options,
+ NULL)) != -1) {
+ switch (opt) {
+ case 'i':
+ dev_id = hci_devid(optarg);
+ if (dev_id < 0) {
+ perror("Invalid device");
+ exit(1);
+ }
+ break;
+
+ case 'h':
+ default:
+ usage();
+ exit(0);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+ optind = 0;
+
+ if (argc < 1) {
+ usage();
+ exit(0);
+ }
+
+ if (dev_id != -1 && hci_devba(dev_id, &ba) < 0) {
+ perror("Device is not available");
+ exit(1);
+ }
+
+ for (i = 0; command[i].cmd; i++) {
+ if (strncmp(command[i].cmd, argv[0], strlen(command[1].cmd)))
+ continue;
+ command[i].func(dev_id, argc, argv);
+ break;
+ }
+ return 0;
+}
--
1.7.4.3
^ permalink raw reply related
* [RFC 0/4] hcimgmt: command line tool for mgmt interface
From: Vinicius Costa Gomes @ 2011-04-15 17:57 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
Hi,
When the mgmt interface was first proposed Johan sent a patch
that introduced this tool, I updated it for the current MGMT API
and added a couple new commands.
--
Cheers,
Johan Hedberg (1):
Add hcimgmt command line test tool
Vinicius Costa Gomes (3):
hcimgmt: Add command to set IO Capabilities
Add command to clear the link key list via MGMT interface
hcimgmt: add support for setting pairable mode
Makefile.tools | 5 +-
tools/hcimgmt.c | 546 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 550 insertions(+), 1 deletions(-)
create mode 100644 tools/hcimgmt.c
--
1.7.4.3
^ permalink raw reply
* Re: [PATCH] Fix race condition on gatttool
From: Sheldon Demario @ 2011-04-15 13:29 UTC (permalink / raw)
To: Sheldon Demario, linux-bluetooth
In-Reply-To: <20110414170728.GC7152@jh-x301>
Johan,
On Thu, Apr 14, 2011 at 2:07 PM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> Hi Sheldon,
>
> On Mon, Apr 11, 2011, Sheldon Demario wrote:
>> When the connect_cb() takes too long to be called the event_loop goes to idle
>> state and executes the callback too early
>> ---
>> attrib/gatttool.c | 128 +++++++++++++++++++++++++---------------------------
>> 1 files changed, 62 insertions(+), 66 deletions(-)
>
> Thanks, the patch has been pushed upstream. Could you please fix your
> editor settings so that it doesn't produce lines longer than 74
> characters for git commit messages? I had to manually edit it this time.
For sure. I was using the 80 chars limit.
>
> Johan
>
^ permalink raw reply
* Re: optional support for ERTM mode for certain PSM
From: Gustavo F. Padovan @ 2011-04-15 11:14 UTC (permalink / raw)
To: Suraj Sumangala; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <4DA81E10.60109@Atheros.com>
Hi Suraj,
* Suraj Sumangala <suraj@Atheros.com> [2011-04-15 15:59:36 +0530]:
> Hi Gustavo,
>
> I am working on the L2CAP BQB test cases for ERTM mode and came across
> test cases for PSMs which optionally and mandatorily support ERTM.
>
> As part of BQB qualification, I see two test cases
>
> 1. Mandatory support:
> When tester sends a Config respose with "Un-acceptable parameter" for
> EFC parameter, the IUT is supposed to disconnect the link.
>
> 2. Optional support
>
> When tester sends a Config respose with "Un-acceptable parameter" for
> EFC parameter, the IUT is supposed re-negotiate the connection with the
> EFC parameter provided by Tester.
For mandatory support you have to SOCK_STREAM, in l2test this is the -U
options. Optional support is the default configuration for l2test.
--
Gustavo F. Padovan
http://profusion.mobi
^ permalink raw reply
* [PATCH 3/3] Bluetooth: Ignore key unauthenticated for high security
From: Waldemar Rymarkiewicz @ 2011-04-15 11:06 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Johan Hedberg, Waldemar Rymarkiewicz
In-Reply-To: <1302865617-32704-1-git-send-email-waldemar.rymarkiewicz@tieto.com>
High security level for pre v2.1 devices requires combination link key
authenticated by at least 16 digit PIN code.
It's also necessary to update key_type and pin_length when the key
exists and is sufficently secured for the connection as there will be
no link key notify event in that case.
Signed-off-by: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>
---
net/bluetooth/hci_event.c | 21 +++++++++++++++++----
1 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 5c5e614..337da2b 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2044,11 +2044,24 @@ static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff
}
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
+ if (conn) {
+ if (key->type == HCI_LK_UNAUTH_COMBINATION &&
+ conn->auth_type != 0xff &&
+ (conn->auth_type & 0x01)) {
+ BT_DBG("%s ignoring unauthenticated key", hdev->name);
+ goto not_found;
+ }
- if (key->type == HCI_LK_UNAUTH_COMBINATION && conn &&
- conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
- BT_DBG("%s ignoring unauthenticated key", hdev->name);
- goto not_found;
+ if (key->type == HCI_LK_COMBINATION &&
+ conn->sec_level == BT_SECURITY_HIGH &&
+ conn->pin_length < 16) {
+ BT_DBG("%s ignoring key unauthenticated for high \
+ security", hdev->name);
+ goto not_found;
+ }
+
+ conn->key_type = key->type;
+ conn->pin_length = key->pin_len;
}
bacpy(&cp.bdaddr, &ev->bdaddr);
--
1.7.1
^ permalink raw reply related
* [PATCH 2/3] Bluetooth: Map sec_level to link key requirements
From: Waldemar Rymarkiewicz @ 2011-04-15 11:06 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Johan Hedberg, Waldemar Rymarkiewicz
In-Reply-To: <1302865617-32704-1-git-send-email-waldemar.rymarkiewicz@tieto.com>
Keep the link key type together with connection and use it to
map security level to link key requirements. Authenticate and/or
encrypt connection if the link is insufficiently secure.
Signed-off-by: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>
---
include/net/bluetooth/hci_core.h | 1 +
net/bluetooth/hci_conn.c | 61 +++++++++++++++++++++++++++++++------
net/bluetooth/hci_event.c | 4 ++
3 files changed, 56 insertions(+), 10 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 4093133..02e7256 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -226,6 +226,7 @@ struct hci_conn {
__u16 pkt_type;
__u16 link_policy;
__u32 link_mode;
+ __u8 key_type;
__u8 auth_type;
__u8 sec_level;
__u8 pending_sec_level;
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 7a6f56b..a339845 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -287,6 +287,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
conn->auth_type = HCI_AT_GENERAL_BONDING;
conn->io_capability = hdev->io_capability;
conn->remote_auth = 0xff;
+ conn->key_type = 0xff;
conn->power_save = 1;
conn->disc_timeout = HCI_DISCONN_TIMEOUT;
@@ -535,32 +536,72 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
return 0;
}
+/* Encrypt the the link */
+static void hci_conn_encrypt(struct hci_conn *conn)
+{
+ BT_DBG("conn %p", conn);
+
+ if (!test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
+ struct hci_cp_set_conn_encrypt cp;
+ cp.handle = cpu_to_le16(conn->handle);
+ cp.encrypt = 0x01;
+ hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
+ &cp);
+ }
+}
+
/* Enable security */
int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
{
BT_DBG("conn %p", conn);
+ /* For sdp we don't need the link key. */
if (sec_level == BT_SECURITY_SDP)
return 1;
+ /* For non 2.1 devices and low security level we don't need the link
+ key. */
if (sec_level == BT_SECURITY_LOW &&
(!conn->ssp_mode || !conn->hdev->ssp_mode))
return 1;
- if (conn->link_mode & HCI_LM_ENCRYPT)
- return hci_conn_auth(conn, sec_level, auth_type);
-
+ /* For other security levels we need the link key. */
+ if (!(conn->link_mode & HCI_LM_AUTH))
+ goto auth;
+
+ /* An authenticated combination key has sufficient security for any
+ security level. */
+ if (conn->key_type == HCI_LK_AUTH_COMBINATION)
+ goto encrypt;
+
+ /* An unauthenticated combination key has sufficient security for
+ security level 1 and 2. */
+ if (conn->key_type == HCI_LK_UNAUTH_COMBINATION &&
+ (sec_level == BT_SECURITY_MEDIUM ||
+ sec_level == BT_SECURITY_LOW))
+ goto encrypt;
+
+ /* A combination key has always sufficient security for the security
+ levels 1 or 2. High security level requires the combination key
+ is generated using maximum PIN code length (16).
+ For pre 2.1 units. */
+ if (conn->key_type == HCI_LK_COMBINATION &&
+ (sec_level != BT_SECURITY_HIGH ||
+ conn->pin_length >= 16))
+ goto encrypt;
+
+auth:
if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
return 0;
- if (hci_conn_auth(conn, sec_level, auth_type)) {
- struct hci_cp_set_conn_encrypt cp;
- cp.handle = cpu_to_le16(conn->handle);
- cp.encrypt = 1;
- hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT,
- sizeof(cp), &cp);
- }
+ hci_conn_auth(conn, sec_level, auth_type);
+ return 0;
+
+encrypt:
+ if (conn->link_mode & HCI_LM_ENCRYPT)
+ return 1;
+ hci_conn_encrypt(conn);
return 0;
}
EXPORT_SYMBOL(hci_conn_security);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 36eb062..5c5e614 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2080,6 +2080,10 @@ static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff
hci_conn_hold(conn);
conn->disc_timeout = HCI_DISCONN_TIMEOUT;
pin_len = conn->pin_length;
+
+ if (conn->key_type != HCI_LK_CHANGED_COMBINATION)
+ conn->key_type = ev->key_type;
+
hci_conn_put(conn);
}
--
1.7.1
^ permalink raw reply related
* [PATCH 1/3] Bluetooth: Add definitions for link key types
From: Waldemar Rymarkiewicz @ 2011-04-15 11:06 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Johan Hedberg, Waldemar Rymarkiewicz
In-Reply-To: <1302865617-32704-1-git-send-email-waldemar.rymarkiewicz@tieto.com>
Introduce the link key types defs and use them instead of magic numbers.
Signed-off-by: Waldemar Rymarkiewicz <waldemar.rymarkiewicz@tieto.com>
---
include/net/bluetooth/hci.h | 9 +++++++++
net/bluetooth/hci_core.c | 2 +-
net/bluetooth/hci_event.c | 7 ++++---
3 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 6138e31..e0a3cf1 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -246,6 +246,15 @@ enum {
#define HCI_AT_GENERAL_BONDING 0x04
#define HCI_AT_GENERAL_BONDING_MITM 0x05
+/* Link Key types */
+#define HCI_LK_COMBINATION 0x00
+#define HCI_LK_LOCAL_UNIT 0x01
+#define HCI_LK_REMOTE_UNIT 0x02
+#define HCI_LK_DEBUG_COMBINATION 0x03
+#define HCI_LK_UNAUTH_COMBINATION 0x04
+#define HCI_LK_AUTH_COMBINATION 0x05
+#define HCI_LK_CHANGED_COMBINATION 0x06
+
/* ----- HCI Commands ---- */
#define HCI_OP_NOP 0x0000
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index a80bc1c..cfa5621 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1049,7 +1049,7 @@ int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
if (new_key)
mgmt_new_key(hdev->id, key, old_key_type);
- if (type == 0x06)
+ if (type == HCI_LK_CHANGED_COMBINATION)
key->type = old_key_type;
return 0;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index c7eb073..36eb062 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2037,15 +2037,16 @@ static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff
BT_DBG("%s found key type %u for %s", hdev->name, key->type,
batostr(&ev->bdaddr));
- if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && key->type == 0x03) {
+ if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) &&
+ key->type == HCI_LK_DEBUG_COMBINATION) {
BT_DBG("%s ignoring debug key", hdev->name);
goto not_found;
}
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
- if (key->type == 0x04 && conn && conn->auth_type != 0xff &&
- (conn->auth_type & 0x01)) {
+ if (key->type == HCI_LK_UNAUTH_COMBINATION && conn &&
+ conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
BT_DBG("%s ignoring unauthenticated key", hdev->name);
goto not_found;
}
--
1.7.1
^ permalink raw reply related
* [PATCH 0/3] Handle link key type and security requirements
From: Waldemar Rymarkiewicz @ 2011-04-15 11:06 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Johan Hedberg, Waldemar Rymarkiewicz
Hi,
Please put some comments on these patches. I will test them in next days.
There will be further patches to support 16 digit pin notification to userspace
and rfcomm re-authentication.
Waldek
Waldemar Rymarkiewicz (3):
Bluetooth: Add definitions for link key types
Bluetooth: Map sec_level to link key requirements
Bluetooth: Ignore key unauthenticated for high security
include/net/bluetooth/hci.h | 9 +++++
include/net/bluetooth/hci_core.h | 1 +
net/bluetooth/hci_conn.c | 61 +++++++++++++++++++++++++++++++------
net/bluetooth/hci_core.c | 2 +-
net/bluetooth/hci_event.c | 28 ++++++++++++++---
5 files changed, 85 insertions(+), 16 deletions(-)
^ permalink raw reply
* optional support for ERTM mode for certain PSM
From: Suraj Sumangala @ 2011-04-15 10:29 UTC (permalink / raw)
To: Gustavo F. Padovan; +Cc: linux-bluetooth@vger.kernel.org
Hi Gustavo,
I am working on the L2CAP BQB test cases for ERTM mode and came across
test cases for PSMs which optionally and mandatorily support ERTM.
As part of BQB qualification, I see two test cases
1. Mandatory support:
When tester sends a Config respose with "Un-acceptable parameter" for
EFC parameter, the IUT is supposed to disconnect the link.
2. Optional support
When tester sends a Config respose with "Un-acceptable parameter" for
EFC parameter, the IUT is supposed re-negotiate the connection with the
EFC parameter provided by Tester.
Any idea how both cases can be executed successfully?
Regards
Suraj
^ permalink raw reply
* [PATCH 3/3] Add support for btiotest to returning the key size
From: Vinicius Costa Gomes @ 2011-04-15 0:06 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1302826003-5511-1-git-send-email-vinicius.gomes@openbossa.org>
---
test/btiotest.c | 13 +++++++++++++
1 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/test/btiotest.c b/test/btiotest.c
index c4d8f4f..fdf2234 100644
--- a/test/btiotest.c
+++ b/test/btiotest.c
@@ -135,6 +135,19 @@ static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
printf("imtu=%u, omtu=%u\n", imtu, omtu);
}
+ if (data->type == BT_IO_L2CAP) {
+ uint8_t key_size;
+
+ if (!bt_io_get(io, data->type, &err,
+ BT_IO_OPT_KEY_SIZE, &key_size,
+ BT_IO_OPT_INVALID)) {
+ printf("Unable to get L2CAP Key size: %s\n",
+ err->message);
+ g_clear_error(&err);
+ } else
+ printf("key_size=%u\n", key_size);
+ }
+
if (data->disconn == 0) {
g_io_channel_shutdown(io, TRUE, NULL);
printf("Disconnected\n");
--
1.7.4.3
^ permalink raw reply related
* [PATCH 2/3] Add support for passing the CID to btiotest
From: Vinicius Costa Gomes @ 2011-04-15 0:06 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <1302826003-5511-1-git-send-email-vinicius.gomes@openbossa.org>
---
test/btiotest.c | 11 ++++++++---
1 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/test/btiotest.c b/test/btiotest.c
index c02a25a..c4d8f4f 100644
--- a/test/btiotest.c
+++ b/test/btiotest.c
@@ -225,7 +225,7 @@ static void confirm_cb(GIOChannel *io, gpointer user_data)
}
static void l2cap_connect(const char *src, const char *dst, uint16_t psm,
- gint disconn, gint sec)
+ uint16_t cid, gint disconn, gint sec)
{
struct io_data *data;
GError *err = NULL;
@@ -241,6 +241,7 @@ static void l2cap_connect(const char *src, const char *dst, uint16_t psm,
BT_IO_OPT_SOURCE, src,
BT_IO_OPT_DEST, dst,
BT_IO_OPT_PSM, psm,
+ BT_IO_OPT_CID, cid,
BT_IO_OPT_SEC_LEVEL, sec,
BT_IO_OPT_INVALID);
else
@@ -249,6 +250,7 @@ static void l2cap_connect(const char *src, const char *dst, uint16_t psm,
&err,
BT_IO_OPT_DEST, dst,
BT_IO_OPT_PSM, psm,
+ BT_IO_OPT_CID, cid,
BT_IO_OPT_SEC_LEVEL, sec,
BT_IO_OPT_INVALID);
@@ -466,6 +468,7 @@ static gint opt_disconn = -1;
static gint opt_accept = DEFAULT_ACCEPT_TIMEOUT;
static gint opt_sec = 0;
static gboolean opt_master = FALSE;
+static gint opt_cid = 0;
static GMainLoop *main_loop;
@@ -474,6 +477,8 @@ static GOptionEntry options[] = {
"RFCOMM channel" },
{ "psm", 'p', 0, G_OPTION_ARG_INT, &opt_psm,
"L2CAP PSM" },
+ { "cid", 'j', 0, G_OPTION_ARG_INT, &opt_cid,
+ "L2CAP CID" },
{ "sco", 's', 0, G_OPTION_ARG_NONE, &opt_sco,
"Use SCO" },
{ "defer", 'd', 0, G_OPTION_ARG_NONE, &opt_defer,
@@ -513,9 +518,9 @@ int main(int argc, char *argv[])
printf("accept=%d, reject=%d, discon=%d, defer=%d, sec=%d\n",
opt_accept, opt_reject, opt_disconn, opt_defer, opt_sec);
- if (opt_psm) {
+ if (opt_psm || opt_cid) {
if (argc > 1)
- l2cap_connect(opt_dev, argv[1], opt_psm,
+ l2cap_connect(opt_dev, argv[1], opt_psm, opt_cid,
opt_disconn, opt_sec);
else
l2cap_listen(opt_dev, opt_psm, opt_defer, opt_reject,
--
1.7.4.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox