From 36712f5b775b553861544df1815ba5b353e4dd7d Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 10 Mar 2011 11:32:02 +0100 Subject: bluetooth: Improve BNEP extension headers handling Adds handling of extension headers to BNEP control packets. Adds support for BNEP setup connection request handled in pand. ST-Ericsson Linux next: - ST-Ericsson ID: 328144 ST-Ericsson FOSS-OUT-ID: Trivial Depends-On: Id2cbd106af9b380f63d87ea0b4652ec6cd996fa4 Change-Id: I005e00e2fe934dc19f40533953d5b233676f0d0e Signed-off-by: Andrzej Kaczmarek Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/18117 Reviewed-by: Par-Gunnar HJALMDAHL Reviewed-by: Lukasz RYMANOWSKI Reviewed-by: Henrik POSSUNG --- net/bluetooth/bnep/bnep.h | 2 ++ net/bluetooth/bnep/core.c | 53 +++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/net/bluetooth/bnep/bnep.h b/net/bluetooth/bnep/bnep.h index e7ee5314f39..0545fe0493f 100644 --- a/net/bluetooth/bnep/bnep.h +++ b/net/bluetooth/bnep/bnep.h @@ -166,6 +166,8 @@ struct bnep_session { struct socket *sock; struct net_device *dev; + + unsigned int setup_done; }; void bnep_net_setup(struct net_device *dev); diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index a779ec70332..fe3b9faeb68 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -117,7 +117,8 @@ static inline void bnep_set_default_proto_filter(struct bnep_session *s) } #endif -static int bnep_ctrl_set_netfilter(struct bnep_session *s, __be16 *data, int len) +static int bnep_ctrl_set_netfilter(struct bnep_session *s, __be16 *data, + int len, int *pkt_size) { int n; @@ -133,6 +134,8 @@ static int bnep_ctrl_set_netfilter(struct bnep_session *s, __be16 *data, int len BT_DBG("filter len %d", n); + *pkt_size = 2 + n; + #ifdef CONFIG_BT_BNEP_PROTO_FILTER n /= 4; if (n <= BNEP_MAX_PROTO_FILTERS) { @@ -163,7 +166,8 @@ static int bnep_ctrl_set_netfilter(struct bnep_session *s, __be16 *data, int len return 0; } -static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len) +static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len, + int *pkt_size) { int n; @@ -179,6 +183,8 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len) BT_DBG("filter len %d", n); + *pkt_size = 2 + n; + #ifdef CONFIG_BT_BNEP_MC_FILTER n /= (ETH_ALEN * 2); @@ -224,7 +230,8 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len) return 0; } -static int bnep_rx_control(struct bnep_session *s, void *data, int len) +static int bnep_rx_control(struct bnep_session *s, void *data, int len, + int *pkt_size) { u8 cmd = *(u8 *)data; int err = 0; @@ -232,6 +239,8 @@ static int bnep_rx_control(struct bnep_session *s, void *data, int len) data++; len--; + *pkt_size = 0; + switch (cmd) { case BNEP_CMD_NOT_UNDERSTOOD: case BNEP_SETUP_CONN_RSP: @@ -241,15 +250,27 @@ static int bnep_rx_control(struct bnep_session *s, void *data, int len) break; case BNEP_FILTER_NET_TYPE_SET: - err = bnep_ctrl_set_netfilter(s, data, len); + err = bnep_ctrl_set_netfilter(s, data, len, pkt_size); break; case BNEP_FILTER_MULTI_ADDR_SET: - err = bnep_ctrl_set_mcfilter(s, data, len); + err = bnep_ctrl_set_mcfilter(s, data, len, pkt_size); break; - case BNEP_SETUP_CONN_REQ: - err = bnep_send_rsp(s, BNEP_SETUP_CONN_RSP, BNEP_CONN_NOT_ALLOWED); + case BNEP_SETUP_CONN_REQ: { + u8 uuid_size = *(u8 *)data; + + /* First setup connection should be silently discarded, + * it was already handled when accepting connection. + */ + if (s->setup_done) + err = bnep_send_rsp(s, BNEP_SETUP_CONN_RSP, + BNEP_CONN_NOT_ALLOWED); + else + s->setup_done = 1; + + *pkt_size = 1 + 2 * uuid_size; + } break; default: { @@ -262,6 +283,10 @@ static int bnep_rx_control(struct bnep_session *s, void *data, int len) break; } + if (*pkt_size > 0) + /* Add 1 byte for type field */ + (*pkt_size)++; + return err; } @@ -269,6 +294,7 @@ static int bnep_rx_extension(struct bnep_session *s, struct sk_buff *skb) { struct bnep_ext_hdr *h; int err = 0; + int pkt_size; do { h = (void *) skb->data; @@ -281,7 +307,7 @@ static int bnep_rx_extension(struct bnep_session *s, struct sk_buff *skb) switch (h->type & BNEP_TYPE_MASK) { case BNEP_EXT_CONTROL: - bnep_rx_control(s, skb->data, skb->len); + bnep_rx_control(s, skb->data, skb->len, &pkt_size); break; default: @@ -321,7 +347,16 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb) goto badframe; if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) { - bnep_rx_control(s, skb->data, skb->len); + int pkt_size = 0; + + bnep_rx_control(s, skb->data, skb->len, &pkt_size); + + if (pkt_size > 0 && (type & BNEP_EXT_HEADER)) { + skb_pull(skb, pkt_size); + if (bnep_rx_extension(s, skb) < 0) + goto badframe; + } + kfree_skb(skb); return 0; } -- cgit v1.2.3 From 2b90a9f88fde7954e84203470623beb174cc342c Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 17 Mar 2011 12:17:30 +0100 Subject: bluetooth: Add SCO parameters support for socket Adds ability to setup SCO connection parameters through socket option. ST-Ericsson Linux next: Not tested, ER 256277 ST-Ericsson ID: 256277 ST-Ericsson FOSS-OUT ID: STETL-FOSS-OUT-10137 Change-Id: If859341019fd9f7cc7c0efe95750779e84fac801 Signed-off-by: Andrzej Kaczmarek Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/30136 Reviewed-by: Par-Gunnar HJALMDAHL Tested-by: Par-Gunnar HJALMDAHL Reviewed-by: Srinidhi KASAGAR Signed-off-by: Robert Marklund --- include/net/bluetooth/bluetooth.h | 12 +++++++ include/net/bluetooth/hci.h | 17 ++++++++++ include/net/bluetooth/hci_core.h | 9 +++-- include/net/bluetooth/sco.h | 4 ++- net/bluetooth/hci_conn.c | 47 +++++++++++++++++++------- net/bluetooth/hci_event.c | 6 ++-- net/bluetooth/l2cap_core.c | 4 +-- net/bluetooth/lib.c | 2 ++ net/bluetooth/mgmt.c | 4 +-- net/bluetooth/sco.c | 70 ++++++++++++++++++++++++++++++++++++++- 10 files changed, 152 insertions(+), 23 deletions(-) diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 4a82ca0bb0b..dda8bb18420 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -116,6 +116,18 @@ int bt_printk(const char *level, const char *fmt, ...); #define BT_ERR(fmt, arg...) bt_printk(KERN_ERR, pr_fmt(fmt), ##arg) #define BT_DBG(fmt, arg...) pr_debug(fmt "\n", ##arg) +#define BT_SCO_PARAMETERS 8 +struct bt_sco_parameters { + __u32 tx_bandwidth; + __u32 rx_bandwidth; + __u16 max_latency; + __u16 voice_setting; + __u8 retrans_effort; + __u16 pkt_type; +} __packed; + +#define BT_NO_AUTORETRY 9 + /* Connection and socket states */ enum { BT_CONNECTED = 1, /* Equal to TCP_ESTABLISHED to make net code happy */ diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 00596e816b4..14766899355 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -167,6 +167,8 @@ enum { #define SCO_ESCO_MASK (ESCO_HV1 | ESCO_HV2 | ESCO_HV3) #define EDR_ESCO_MASK (ESCO_2EV3 | ESCO_3EV3 | ESCO_2EV5 | ESCO_3EV5) +#define ALL_ESCO_MASK (SCO_ESCO_MASK | ESCO_EV3 | ESCO_EV4 | ESCO_EV5 | \ + EDR_ESCO_MASK) /* ACL flags */ #define ACL_START_NO_FLUSH 0x00 @@ -430,6 +432,21 @@ struct hci_cp_setup_sync_conn { __le16 pkt_type; } __packed; +/* Air coding format types */ +#define HCI_SYNC_AIR_CODING_CVSD 0x00 +#define HCI_SYNC_AIR_CODING_ULAW 0x01 +#define HCI_SYNC_AIR_CODING_ALAW 0x02 +#define HCI_SYNC_AIR_CODING_TRANSPARENT 0x03 + +/* Max latency constants */ +#define HCI_SYNC_MAX_LATENCY_DONTCARE 0xffff + +/* Retransmission effort constants */ +#define HCI_SYNC_RETRANS_EFFORT_NO 0x00 +#define HCI_SYNC_RETRANS_EFFORT_POWER 0x01 +#define HCI_SYNC_RETRANS_EFFORT_QUALITY 0x02 +#define HCI_SYNC_RETRANS_EFFORT_DONTCARE 0xff + #define HCI_OP_ACCEPT_SYNC_CONN_REQ 0x0429 struct hci_cp_accept_sync_conn_req { bdaddr_t bdaddr; diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 453893b3120..733d5bb6b1e 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -272,6 +272,7 @@ struct hci_conn { __u8 type; __u8 out; __u8 attempt; + __u8 no_autoretry; __u8 dev_class[3]; __u8 features[8]; __u8 ssp_mode; @@ -311,6 +312,8 @@ struct hci_conn { void *sco_data; void *smp_conn; + struct bt_sco_parameters *sco_parameters; + struct hci_conn *link; void (*connect_cfm_cb) (struct hci_conn *conn, u8 status); @@ -515,7 +518,8 @@ void hci_add_sco(struct hci_conn *conn, __u16 handle); void hci_setup_sync(struct hci_conn *conn, __u16 handle); void hci_sco_setup(struct hci_conn *conn, __u8 status); -struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst); +struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, + bdaddr_t *dst); int hci_conn_del(struct hci_conn *conn); void hci_conn_hash_flush(struct hci_dev *hdev); void hci_conn_check_pending(struct hci_dev *hdev); @@ -525,7 +529,8 @@ int hci_chan_del(struct hci_chan *chan); void hci_chan_list_flush(struct hci_conn *conn); struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, - __u8 sec_level, __u8 auth_type); + __u8 sec_level, __u8 auth_type, + struct bt_sco_parameters *sco_parameters); int hci_conn_check_link_mode(struct hci_conn *conn); int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level); int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type); diff --git a/include/net/bluetooth/sco.h b/include/net/bluetooth/sco.h index 1e35c43657c..e6b5a94f7e8 100644 --- a/include/net/bluetooth/sco.h +++ b/include/net/bluetooth/sco.h @@ -72,7 +72,9 @@ struct sco_conn { struct sco_pinfo { struct bt_sock bt; - __u32 flags; + struct bt_sco_parameters param; + __u8 no_autoretry; + struct sco_conn *conn; }; diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 07bc69ed949..963ff2d02cf 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -44,6 +44,7 @@ #include #include +#include static void hci_le_connect(struct hci_conn *conn) { @@ -147,16 +148,21 @@ void hci_add_sco(struct hci_conn *conn, __u16 handle) { struct hci_dev *hdev = conn->hdev; struct hci_cp_add_sco cp; + struct bt_sco_parameters *p = conn->sco_parameters; + __u16 pkt_type; BT_DBG("%p", conn); + /* HCI_Add_SCO_Connection uses shifted bitmask for packet type */ + pkt_type = (p->pkt_type << 5) & conn->pkt_type; + conn->state = BT_CONNECT; conn->out = 1; conn->attempt++; cp.handle = cpu_to_le16(handle); - cp.pkt_type = cpu_to_le16(conn->pkt_type); + cp.pkt_type = cpu_to_le16(pkt_type); hci_send_cmd(hdev, HCI_OP_ADD_SCO, sizeof(cp), &cp); } @@ -165,22 +171,35 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle) { struct hci_dev *hdev = conn->hdev; struct hci_cp_setup_sync_conn cp; + struct bt_sco_parameters *p = conn->sco_parameters; + __u16 voice_setting; + __u16 pkt_type; BT_DBG("%p", conn); + /* + * Combine voice setting using device parameters and air coding + * format set by user. + */ + voice_setting = (hdev->voice_setting & 0xfffc) | + (p->voice_setting & 0x0003); + + /* Bits for EDR packets have inverted logic in BT spec. */ + pkt_type = (p->pkt_type & conn->pkt_type) ^ EDR_ESCO_MASK; + conn->state = BT_CONNECT; conn->out = 1; conn->attempt++; cp.handle = cpu_to_le16(handle); - cp.pkt_type = cpu_to_le16(conn->pkt_type); - cp.tx_bandwidth = cpu_to_le32(0x00001f40); - cp.rx_bandwidth = cpu_to_le32(0x00001f40); - cp.max_latency = cpu_to_le16(0xffff); - cp.voice_setting = cpu_to_le16(hdev->voice_setting); - cp.retrans_effort = 0xff; + cp.tx_bandwidth = cpu_to_le32(p->tx_bandwidth); + cp.rx_bandwidth = cpu_to_le32(p->rx_bandwidth); + cp.max_latency = cpu_to_le16(p->max_latency); + cp.voice_setting = cpu_to_le16(voice_setting); + cp.retrans_effort = p->retrans_effort; + cp.pkt_type = cpu_to_le16(pkt_type); hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp); } @@ -366,7 +385,8 @@ static void hci_conn_auto_accept(unsigned long arg) &conn->dst); } -struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) +struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, + bdaddr_t *dst) { struct hci_conn *conn; @@ -395,13 +415,12 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) break; case SCO_LINK: if (lmp_esco_capable(hdev)) - conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | - (hdev->esco_type & EDR_ESCO_MASK); + conn->pkt_type = hdev->esco_type & SCO_ESCO_MASK; else conn->pkt_type = hdev->pkt_type & SCO_PTYPE_MASK; break; case ESCO_LINK: - conn->pkt_type = hdev->esco_type & ~EDR_ESCO_MASK; + conn->pkt_type = hdev->esco_type; break; } @@ -519,7 +538,9 @@ EXPORT_SYMBOL(hci_get_route); /* Create SCO, ACL or LE connection. * Device _must_ be locked */ -struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type) +struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, + __u8 sec_level, __u8 auth_type, + struct bt_sco_parameters *sco_parameters) { struct hci_conn *acl; struct hci_conn *sco; @@ -584,6 +605,8 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 hci_conn_hold(sco); + sco->sco_parameters = sco_parameters; + if (acl->state == BT_CONNECTED && (sco->state == BT_OPEN || sco->state == BT_CLOSED)) { acl->power_save = 1; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 001307f8105..8357436fb1a 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1645,6 +1645,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); if (!conn) { + /* pkt_type not yet used for incoming connections */ conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); if (!conn) { BT_ERR("No memory for new connection"); @@ -2677,9 +2678,8 @@ static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_bu case 0x1c: /* SCO interval rejected */ case 0x1a: /* Unsupported Remote Feature */ case 0x1f: /* Unspecified error */ - if (conn->out && conn->attempt < 2) { - conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | - (hdev->esco_type & EDR_ESCO_MASK); + if (conn->out && !conn->no_autoretry && conn->attempt < 2) { + conn->pkt_type = hdev->esco_type & SCO_ESCO_MASK; hci_setup_sync(conn, conn->link->handle); goto unlock; } diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 32d338c30e6..f68a1108d25 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1198,10 +1198,10 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *d if (chan->dcid == L2CAP_CID_LE_DATA) hcon = hci_connect(hdev, LE_LINK, dst, - chan->sec_level, auth_type); + chan->sec_level, auth_type, NULL); else hcon = hci_connect(hdev, ACL_LINK, dst, - chan->sec_level, auth_type); + chan->sec_level, auth_type, NULL); if (IS_ERR(hcon)) { err = PTR_ERR(hcon); diff --git a/net/bluetooth/lib.c b/net/bluetooth/lib.c index 86a6bed229d..f9b2dde4c0a 100644 --- a/net/bluetooth/lib.c +++ b/net/bluetooth/lib.c @@ -136,6 +136,8 @@ int bt_to_errno(__u16 code) return EPROTONOSUPPORT; case 0x1b: + case 0x1c: + case 0x1d: return ECONNREFUSED; case 0x19: diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index bc8e59dda78..87389cab147 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1551,10 +1551,10 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len) if (cp->addr.type == MGMT_ADDR_BREDR) conn = hci_connect(hdev, ACL_LINK, &cp->addr.bdaddr, sec_level, - auth_type); + auth_type, NULL); else conn = hci_connect(hdev, LE_LINK, &cp->addr.bdaddr, sec_level, - auth_type); + auth_type, NULL); memset(&rp, 0, sizeof(rp)); bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr); diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 8bf26d1bc5c..ef816b0dda8 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -178,6 +178,7 @@ static int sco_connect(struct sock *sk) { bdaddr_t *src = &bt_sk(sk)->src; bdaddr_t *dst = &bt_sk(sk)->dst; + struct bt_sco_parameters *param = &sco_pi(sk)->param; struct sco_conn *conn; struct hci_conn *hcon; struct hci_dev *hdev; @@ -196,12 +197,15 @@ static int sco_connect(struct sock *sk) else type = SCO_LINK; - hcon = hci_connect(hdev, type, dst, BT_SECURITY_LOW, HCI_AT_NO_BONDING); + hcon = hci_connect(hdev, type, dst, + BT_SECURITY_LOW, HCI_AT_NO_BONDING, param); if (IS_ERR(hcon)) { err = PTR_ERR(hcon); goto done; } + hcon->no_autoretry = sco_pi(sk)->no_autoretry; + conn = sco_conn_add(hcon, 0); if (!conn) { hci_conn_put(hcon); @@ -402,12 +406,26 @@ static void sco_sock_close(struct sock *sk) static void sco_sock_init(struct sock *sk, struct sock *parent) { + struct sco_pinfo *pi = sco_pi(sk); + BT_DBG("sk %p", sk); if (parent) { sk->sk_type = parent->sk_type; security_sk_clone(parent, sk); } + + pi->param.tx_bandwidth = 8000; + pi->param.rx_bandwidth = 8000; + pi->param.max_latency = HCI_SYNC_MAX_LATENCY_DONTCARE; + + /* Only Air Coding Format matters here, other data will be + * overriden by device settings during connection setup. + */ + pi->param.voice_setting = HCI_SYNC_AIR_CODING_CVSD; + + pi->param.retrans_effort = HCI_SYNC_RETRANS_EFFORT_DONTCARE; + pi->param.pkt_type = ALL_ESCO_MASK; } static struct proto sco_proto = { @@ -661,13 +679,45 @@ static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock, static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen) { struct sock *sk = sock->sk; + int len; int err = 0; + struct bt_sco_parameters *param; + u32 opt; BT_DBG("sk %p", sk); + if (level != SOL_BLUETOOTH) + return -ENOPROTOOPT; + lock_sock(sk); switch (optname) { + case BT_SCO_PARAMETERS: + /* We do not support changing SCO parameters during + * connection. + */ + if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) { + err = -EBUSY; + break; + } + + param = &sco_pi(sk)->param; + + len = min_t(unsigned int, sizeof(*param), optlen); + if (copy_from_user((char *) param, optval, len)) + err = -EFAULT; + + break; + + case BT_NO_AUTORETRY: + if (get_user(opt, (u32 __user *) optval)) { + err = -EFAULT; + break; + } + + sco_pi(sk)->no_autoretry = opt; + break; + default: err = -ENOPROTOOPT; break; @@ -737,18 +787,36 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char { struct sock *sk = sock->sk; int len, err = 0; + struct bt_sco_parameters *params; BT_DBG("sk %p", sk); if (level == SOL_SCO) return sco_sock_getsockopt_old(sock, optname, optval, optlen); + if (level != SOL_BLUETOOTH) + return -ENOPROTOOPT; + if (get_user(len, optlen)) return -EFAULT; lock_sock(sk); switch (optname) { + case BT_SCO_PARAMETERS: + params = &sco_pi(sk)->param; + + len = min_t(unsigned int, len, sizeof(*params)); + if (copy_to_user(optval, (char *) params, len)) + err = -EFAULT; + + break; + + case BT_NO_AUTORETRY: + if (put_user(sco_pi(sk)->no_autoretry, (u32 __user *) optval)) + err = -EFAULT; + break; + default: err = -ENOPROTOOPT; break; -- cgit v1.2.3 From 1fb2802cdfe2cb39f59278d482eb298161d3748f Mon Sep 17 00:00:00 2001 From: Lukasz Rymanowski Date: Fri, 9 Dec 2011 13:48:17 +0100 Subject: BT: Add sec_level to auth_conn_info With this patch it is possible to retrieve sec_level from the kernel by user space. This is needed for SAP working on hciops. This patch missed to be added when moving to kernel 3.0 ST-Ericsson ID: 256270 ST-Ericsson FOSS-OUT ID: FOSS-OUT-10060 Change-Id: Ic569db392e6f6ee2e546003dec86cc2d62a1fcd7 Signed-off-by: Lukasz Rymanowski Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/42169 Reviewed-by: Lukasz RYMANOWSKI Tested-by: Lukasz RYMANOWSKI Reviewed-by: Hakan GARDRUP Reviewed-by: Henrik POSSUNG Reviewed-by: Kanak GUPTA --- include/net/bluetooth/hci.h | 1 + net/bluetooth/hci_conn.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 14766899355..9aa8301a71f 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -1394,6 +1394,7 @@ struct hci_conn_info_req { struct hci_auth_info_req { bdaddr_t bdaddr; __u8 type; + __u8 sec_level; }; struct hci_inquiry_req { diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 963ff2d02cf..265f0601c80 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -956,8 +956,10 @@ int hci_get_auth_info(struct hci_dev *hdev, void __user *arg) hci_dev_lock(hdev); conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &req.bdaddr); - if (conn) + if (conn) { req.type = conn->auth_type; + req.sec_level = max(conn->sec_level, conn->pending_sec_level); + } hci_dev_unlock(hdev); if (!conn) -- cgit v1.2.3 From a887ddba8cb80ebdb8708d1fa64268e8c5c4867d Mon Sep 17 00:00:00 2001 From: Kejun ZHOU Date: Fri, 20 Jan 2012 12:15:10 -0700 Subject: snowball: android: Fixing access right for BT Signed-off-by: Kejun ZHOU Committer: Mathieu Poirier --- net/rfkill/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/rfkill/core.c b/net/rfkill/core.c index 354760ebbbd..696e1fb1065 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c @@ -722,7 +722,7 @@ static struct device_attribute rfkill_dev_attrs[] = { __ATTR(type, S_IRUGO, rfkill_type_show, NULL), __ATTR(index, S_IRUGO, rfkill_idx_show, NULL), __ATTR(persistent, S_IRUGO, rfkill_persistent_show, NULL), - __ATTR(state, S_IRUGO|S_IWUSR, rfkill_state_show, rfkill_state_store), + __ATTR(state, S_IRUGO|S_IWUGO, rfkill_state_show, rfkill_state_store), __ATTR(claim, S_IRUGO|S_IWUSR, rfkill_claim_show, rfkill_claim_store), __ATTR(soft, S_IRUGO|S_IWUSR, rfkill_soft_show, rfkill_soft_store), __ATTR(hard, S_IRUGO, rfkill_hard_show, NULL), -- cgit v1.2.3 From 09addacdbf20c7ce61783f21a81f3477e2575a3f Mon Sep 17 00:00:00 2001 From: Johan Bjornstedt Date: Fri, 13 Jan 2012 13:17:59 +0100 Subject: panic: Call notify before kernel is stopped In order for panic_notifier_list to be used it needs to be moved to before we call crash_kexec ST-Ericsson ID: 403009 ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson Linux next: N/A Change-Id: I9adea0902b7a52a18ad2af151823a463e6a420a6 Signed-off-by: Johan Bjornstedt Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/45474 Reviewed-by: QATOOLS Reviewed-by: Magnus TEMPLING Reviewed-by: QABUILD Reviewed-by: QATEST Reviewed-by: Per FRANSSON Reviewed-by: Srinidhi KASAGAR --- kernel/panic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/panic.c b/kernel/panic.c index 80aed44e345..59b7ef6940f 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -101,6 +101,8 @@ void panic(const char *fmt, ...) dump_stack(); #endif + atomic_notifier_call_chain(&panic_notifier_list, 0, buf); + /* * If we have crashed and we have a crash kernel loaded let it handle * everything else. @@ -117,8 +119,6 @@ void panic(const char *fmt, ...) */ smp_send_stop(); - atomic_notifier_call_chain(&panic_notifier_list, 0, buf); - bust_spinlocks(0); if (!panic_blink) -- cgit v1.2.3 From d0e667563b14f68beb40a3fe42bdec63d98e54fb Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 11 Jan 2012 10:59:47 +0100 Subject: Bluetooth: Clear ack_timer when sending ack ack_timer should be cleared when sending ACK to avoid acking I-frames twice. This commit introduces helper function (only send ack, not clearing timer) which is used by l2cap_send_ack and l2cap_ack_timeout. This is to avoid clearing ack timer in timer function. Signed-off-by: Szymon Janc Acked-by: Marcel Holtmann Signed-off-by: Johan Hedberg Conflicts: net/bluetooth/l2cap_core.c Change-Id: I325e7eb6ecb7e228be573b762dedb07f76327dc2 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/45122 Reviewed-by: SZYMON JANC Tested-by: SZYMON JANC Reviewed-by: QABUILD Reviewed-by: Andrzej KACZMAREK Reviewed-by: Kanak GUPTA Reviewed-by: Lukasz RYMANOWSKI Reviewed-by: Anurag GUPTA-1 Reviewed-by: Linus WALLEIJ --- net/bluetooth/l2cap_core.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index f68a1108d25..9dab75d4fea 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1478,7 +1478,7 @@ static int l2cap_retransmit_frames(struct l2cap_chan *chan) return ret; } -static void l2cap_send_ack(struct l2cap_chan *chan) +static void __l2cap_send_ack(struct l2cap_chan *chan) { u32 control = 0; @@ -1498,6 +1498,12 @@ static void l2cap_send_ack(struct l2cap_chan *chan) l2cap_send_sframe(chan, control); } +static void l2cap_send_ack(struct l2cap_chan *chan) +{ + __clear_ack_timer(chan); + __l2cap_send_ack(chan); +} + static void l2cap_send_srejtail(struct l2cap_chan *chan) { struct srej_list *tail; @@ -1988,7 +1994,7 @@ static void l2cap_ack_timeout(struct work_struct *work) BT_DBG("chan %p", chan); lock_sock(chan->sk); - l2cap_send_ack(chan); + __l2cap_send_ack(chan); release_sock(chan->sk); } -- cgit v1.2.3 From 674eff1d2f80f4e34aef047b6e0ea44f225111f8 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 11 Jan 2012 10:59:48 +0100 Subject: Bluetooth: Don't send RNR immediately when entering local busy There is no need to send RNR immediately when entring local busy. Also upper layer might clear local busy condition before ack timer expires saving few cycles for sending RNR. This also prevents sending two RNRs in some cases where sending one would be enough i.e received N I-frame can trigger local busy (sending RNR acking up to N-1 I-frame) and later sending ack (RNR acking up to N I-frame). This was affecting TC_ERM_BV_07_C and TC_ERM_BV_22_C with some non default channel parameters (tx window and receiving buffer sizes). Signed-off-by: Szymon Janc Acked-by: Marcel Holtmann Signed-off-by: Johan Hedberg Conflicts: net/bluetooth/l2cap_core.c Change-Id: I6f6b6f95d6bca4a5361e84e28d7c2740c5b991ae Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/45123 Reviewed-by: SZYMON JANC Tested-by: SZYMON JANC Reviewed-by: QABUILD Reviewed-by: Andrzej KACZMAREK Reviewed-by: Kanak GUPTA Reviewed-by: Lukasz RYMANOWSKI Reviewed-by: Anurag GUPTA-1 Reviewed-by: Linus WALLEIJ --- net/bluetooth/l2cap_core.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 9dab75d4fea..d0ad4325927 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -3719,19 +3719,11 @@ static int l2cap_reassemble_sdu(struct l2cap_chan *chan, struct sk_buff *skb, u3 static void l2cap_ertm_enter_local_busy(struct l2cap_chan *chan) { - u32 control; - BT_DBG("chan %p, Enter local busy", chan); set_bit(CONN_LOCAL_BUSY, &chan->conn_state); - control = __set_reqseq(chan, chan->buffer_seq); - control |= __set_ctrl_super(chan, L2CAP_SUPER_RNR); - l2cap_send_sframe(chan, control); - - set_bit(CONN_RNR_SENT, &chan->conn_state); - - __clear_ack_timer(chan); + __set_ack_timer(chan); } static void l2cap_ertm_exit_local_busy(struct l2cap_chan *chan) @@ -3871,8 +3863,11 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_cont goto drop; } - if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) + if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { + if (!test_bit(CONN_RNR_SENT, &chan->conn_state)) + l2cap_send_ack(chan); goto drop; + } if (tx_seq == chan->expected_tx_seq) goto expected; -- cgit v1.2.3 From 64619c48c2f1cfb7974b0f764a2ac863195cc053 Mon Sep 17 00:00:00 2001 From: Sebastian Chlad Date: Fri, 10 Feb 2012 11:55:14 +0100 Subject: Bluetooth: Set up correct eSCO packet type for incomming connection This patch sets up correct eSCO packet type mask for the incomming connection request. ST-Ericsson ID: 413660 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ice423fe276c184d7350c4940efe1e010f5c3751d Signed-off-by: Sebastian Chlad Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/48491 Reviewed-by: QABUILD Reviewed-by: QATEST Reviewed-by: Jonas ABERG Reviewed-by: Sebastian CHLAD Tested-by: Sebastian CHLAD Reviewed-by: Anurag GUPTA-1 --- net/bluetooth/hci_event.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 8357436fb1a..4c0dfef28ca 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1673,9 +1673,12 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk sizeof(cp), &cp); } else { struct hci_cp_accept_sync_conn_req cp; + __u16 pkt_type; + + pkt_type = conn->pkt_type ^ EDR_ESCO_MASK; bacpy(&cp.bdaddr, &ev->bdaddr); - cp.pkt_type = cpu_to_le16(conn->pkt_type); + cp.pkt_type = cpu_to_le16(pkt_type); cp.tx_bandwidth = cpu_to_le32(0x00001f40); cp.rx_bandwidth = cpu_to_le32(0x00001f40); -- cgit v1.2.3 From 025ddfad021effc8ea256d8aa09ddf3b1b8972e6 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Sun, 19 Feb 2012 12:06:37 +0530 Subject: [ANDROID] logger: hold mutex while removing reader The readers list is traversed under the log->mutex lock (for example from fix_up_readers()), but the deletion of elements from this list is not being done under this lock. ST-Ericsson ID: 418270 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: NA Change-Id: Ib99f2e02b211c17fe54c035e37e648d28be516bb Signed-off-by: Rabin Vincent Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/49546 Reviewed-by: Bibek BASU Tested-by: Bibek BASU --- drivers/staging/android/logger.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/staging/android/logger.c b/drivers/staging/android/logger.c index ffc2d043dd8..a45c3b04fc5 100644 --- a/drivers/staging/android/logger.c +++ b/drivers/staging/android/logger.c @@ -432,7 +432,12 @@ static int logger_release(struct inode *ignored, struct file *file) { if (file->f_mode & FMODE_READ) { struct logger_reader *reader = file->private_data; + struct logger_log *log = reader->log; + + mutex_lock(&log->mutex); list_del(&reader->list); + mutex_unlock(&log->mutex); + kfree(reader); } -- cgit v1.2.3