summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilippe Langlais <philippe.langlais@stericsson.com>2012-04-06 11:11:36 +0200
committerPhilippe Langlais <philippe.langlais@stericsson.com>2012-04-06 11:11:36 +0200
commitbb14f8e91a4d2bdb8643f6f166299ada8d015377 (patch)
treef212dc9be4f26684bd06bfd138444282b457949a
parent180bbb1528515d262ae4bcb7244379b8dcfc9674 (diff)
parent025ddfad021effc8ea256d8aa09ddf3b1b8972e6 (diff)
Merge topic branch 'other' into integration-linux-ux500-3.3
-rw-r--r--drivers/staging/android/logger.c5
-rw-r--r--include/net/bluetooth/bluetooth.h12
-rw-r--r--include/net/bluetooth/hci.h18
-rw-r--r--include/net/bluetooth/hci_core.h9
-rw-r--r--include/net/bluetooth/sco.h4
-rw-r--r--kernel/panic.c4
-rw-r--r--net/bluetooth/bnep/bnep.h2
-rw-r--r--net/bluetooth/bnep/core.c53
-rw-r--r--net/bluetooth/hci_conn.c51
-rw-r--r--net/bluetooth/hci_event.c11
-rw-r--r--net/bluetooth/l2cap_core.c29
-rw-r--r--net/bluetooth/lib.c2
-rw-r--r--net/bluetooth/mgmt.c4
-rw-r--r--net/bluetooth/sco.c70
-rw-r--r--net/rfkill/core.c2
15 files changed, 227 insertions, 49 deletions
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);
}
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..9aa8301a71f 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;
@@ -1377,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/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/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)
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;
}
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 07bc69ed949..265f0601c80 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -44,6 +44,7 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/sco.h>
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;
@@ -933,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)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 001307f8105..4c0dfef28ca 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");
@@ -1672,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);
@@ -2677,9 +2681,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..d0ad4325927 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);
@@ -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);
}
@@ -3713,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)
@@ -3865,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;
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;
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),