From 5bcdc61f0f3f1765382a1840cdd52a8237bd4246 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 cca20365f85a272c284fc91e901a7da6180ca876 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 a65910bda38..e386498b347 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -118,6 +118,18 @@ int bt_err(const char *fmt, ...); #define BT_ERR(fmt, ...) bt_err(fmt "\n", ##__VA_ARGS__) #define BT_DBG(fmt, ...) pr_debug(fmt "\n", ##__VA_ARGS__) +#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 d47e523c9d8..15da4460f24 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -176,6 +176,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 @@ -458,6 +460,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 db1c5df4522..096ac5ec898 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -296,6 +296,7 @@ struct hci_conn { __u8 type; bool out; __u8 attempt; + __u8 no_autoretry; __u8 dev_class[3]; __u8 features[8]; __u16 interval; @@ -333,6 +334,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); @@ -561,7 +564,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); @@ -571,7 +575,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 5238b6b3ea6..c91f6d90793 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -42,6 +42,7 @@ #include #include +#include static void hci_le_connect(struct hci_conn *conn) { @@ -146,16 +147,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 = true; 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); } @@ -164,22 +170,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 = true; 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); } @@ -360,7 +379,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; @@ -389,13 +409,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; } @@ -513,7 +532,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; @@ -578,6 +599,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)) { set_bit(HCI_CONN_POWER_SAVE, &acl->flags); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 1266f78fa8e..fe1f6f39160 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1824,6 +1824,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"); @@ -2933,9 +2934,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 6f9c25b633a..25dd22767ce 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1219,10 +1219,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 506628876f3..09d027de88b 100644 --- a/net/bluetooth/lib.c +++ b/net/bluetooth/lib.c @@ -138,6 +138,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 4bb03b11112..93a19683702 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1892,10 +1892,10 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, 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 f6ab1290796..33d88ebd063 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -177,6 +177,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; @@ -195,12 +196,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); @@ -401,12 +405,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 = { @@ -660,13 +678,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; @@ -736,18 +786,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 c480d6f6de40ca6eddae262b5f462153dbd567c5 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 15da4460f24..ac91fbd3bc0 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -1436,6 +1436,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 c91f6d90793..6226dc4e9ef 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -948,8 +948,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 adf961596806b476e96f3c141c18d364b005edbb 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 f974961754c..659b1c5cbcd 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c @@ -723,7 +723,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 e593120f64d6dfed8a4919922ad50b940ad43914 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 8ed89a175d7..4d53e8b9830 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 961f14635e3589d262af5dcdc596cbb5bc24aea7 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 fe1f6f39160..334b51a4d75 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1852,9 +1852,12 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk &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