Commit 323cdc72 authored by David S. Miller's avatar David S. Miller

Merge http://linux-mh.bkbits.net/bluetooth-2.6

into nuts.davemloft.net:/disk1/BK/net-2.6
parents 4f96d0aa cc9d9e46
...@@ -457,6 +457,11 @@ P: Marcel Holtmann ...@@ -457,6 +457,11 @@ P: Marcel Holtmann
M: marcel@holtmann.org M: marcel@holtmann.org
S: Maintained S: Maintained
BLUETOOTH HCI BPA10X DRIVER
P: Marcel Holtmann
M: marcel@holtmann.org
S: Maintained
BLUETOOTH HCI BFUSB DRIVER BLUETOOTH HCI BFUSB DRIVER
P: Marcel Holtmann P: Marcel Holtmann
M: marcel@holtmann.org M: marcel@holtmann.org
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/wait.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -289,8 +290,9 @@ static void bluecard_write_wakeup(bluecard_info_t *info) ...@@ -289,8 +290,9 @@ static void bluecard_write_wakeup(bluecard_info_t *info)
clear_bit(ready_bit, &(info->tx_state)); clear_bit(ready_bit, &(info->tx_state));
if (skb->pkt_type & 0x80) { if (skb->pkt_type & 0x80) {
DECLARE_WAIT_QUEUE_HEAD(wq);
DEFINE_WAIT(wait);
wait_queue_head_t wait;
unsigned char baud_reg; unsigned char baud_reg;
switch (skb->pkt_type) { switch (skb->pkt_type) {
...@@ -311,8 +313,9 @@ static void bluecard_write_wakeup(bluecard_info_t *info) ...@@ -311,8 +313,9 @@ static void bluecard_write_wakeup(bluecard_info_t *info)
} }
/* Wait until the command reaches the baseband */ /* Wait until the command reaches the baseband */
init_waitqueue_head(&wait); prepare_to_wait(&wq, &wait, TASK_INTERRUPTIBLE);
interruptible_sleep_on_timeout(&wait, HZ / 10); schedule_timeout(HZ/10);
finish_wait(&wq, &wait);
/* Set baud on baseband */ /* Set baud on baseband */
info->ctrl_reg &= ~0x03; info->ctrl_reg &= ~0x03;
...@@ -324,8 +327,9 @@ static void bluecard_write_wakeup(bluecard_info_t *info) ...@@ -324,8 +327,9 @@ static void bluecard_write_wakeup(bluecard_info_t *info)
outb(info->ctrl_reg, iobase + REG_CONTROL); outb(info->ctrl_reg, iobase + REG_CONTROL);
/* Wait before the next HCI packet can be send */ /* Wait before the next HCI packet can be send */
interruptible_sleep_on_timeout(&wait, HZ); prepare_to_wait(&wq, &wait, TASK_INTERRUPTIBLE);
schedule_timeout(HZ);
finish_wait(&wq, &wait);
} }
if (len == skb->len) { if (len == skb->len) {
......
...@@ -888,7 +888,7 @@ static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id ...@@ -888,7 +888,7 @@ static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id
isoc_ifnum = 1; isoc_ifnum = 1;
#ifdef CONFIG_BT_HCIUSB_SCO #ifdef CONFIG_BT_HCIUSB_SCO
if (isoc && !(id->driver_info & HCI_BROKEN_ISOC)) if (isoc && !(id->driver_info & (HCI_BROKEN_ISOC | HCI_SNIFFER)))
isoc_iface = usb_ifnum_to_if(udev, isoc_ifnum); isoc_iface = usb_ifnum_to_if(udev, isoc_ifnum);
if (isoc_iface) { if (isoc_iface) {
......
...@@ -217,7 +217,8 @@ void hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data); ...@@ -217,7 +217,8 @@ void hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data);
/* ----- HCI Connections ----- */ /* ----- HCI Connections ----- */
enum { enum {
HCI_CONN_AUTH_PEND, HCI_CONN_AUTH_PEND,
HCI_CONN_ENCRYPT_PEND HCI_CONN_ENCRYPT_PEND,
HCI_CONN_RSWITCH_PEND
}; };
static inline void hci_conn_hash_init(struct hci_dev *hdev) static inline void hci_conn_hash_init(struct hci_dev *hdev)
...@@ -290,6 +291,7 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *src); ...@@ -290,6 +291,7 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *src);
int hci_conn_auth(struct hci_conn *conn); int hci_conn_auth(struct hci_conn *conn);
int hci_conn_encrypt(struct hci_conn *conn); int hci_conn_encrypt(struct hci_conn *conn);
int hci_conn_change_link_key(struct hci_conn *conn); int hci_conn_change_link_key(struct hci_conn *conn);
int hci_conn_switch_role(struct hci_conn *conn, uint8_t role);
static inline void hci_conn_set_timer(struct hci_conn *conn, unsigned long timeout) static inline void hci_conn_set_timer(struct hci_conn *conn, unsigned long timeout)
{ {
...@@ -515,6 +517,8 @@ struct hci_cb { ...@@ -515,6 +517,8 @@ struct hci_cb {
void (*auth_cfm) (struct hci_conn *conn, __u8 status); void (*auth_cfm) (struct hci_conn *conn, __u8 status);
void (*encrypt_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt); void (*encrypt_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt);
void (*key_change_cfm) (struct hci_conn *conn, __u8 status);
void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role);
}; };
static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status) static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
...@@ -547,6 +551,32 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encr ...@@ -547,6 +551,32 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encr
read_unlock_bh(&hci_cb_list_lock); read_unlock_bh(&hci_cb_list_lock);
} }
static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)
{
struct list_head *p;
read_lock_bh(&hci_cb_list_lock);
list_for_each(p, &hci_cb_list) {
struct hci_cb *cb = list_entry(p, struct hci_cb, list);
if (cb->key_change_cfm)
cb->key_change_cfm(conn, status);
}
read_unlock_bh(&hci_cb_list_lock);
}
static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status, __u8 role)
{
struct list_head *p;
read_lock_bh(&hci_cb_list_lock);
list_for_each(p, &hci_cb_list) {
struct hci_cb *cb = list_entry(p, struct hci_cb, list);
if (cb->role_switch_cfm)
cb->role_switch_cfm(conn, status, role);
}
read_unlock_bh(&hci_cb_list_lock);
}
int hci_register_cb(struct hci_cb *hcb); int hci_register_cb(struct hci_cb *hcb);
int hci_unregister_cb(struct hci_cb *hcb); int hci_unregister_cb(struct hci_cb *hcb);
......
...@@ -348,6 +348,24 @@ int hci_conn_change_link_key(struct hci_conn *conn) ...@@ -348,6 +348,24 @@ int hci_conn_change_link_key(struct hci_conn *conn)
} }
EXPORT_SYMBOL(hci_conn_change_link_key); EXPORT_SYMBOL(hci_conn_change_link_key);
/* Switch role */
int hci_conn_switch_role(struct hci_conn *conn, uint8_t role)
{
BT_DBG("conn %p", conn);
if (!role && conn->link_mode & HCI_LM_MASTER)
return 1;
if (!test_and_set_bit(HCI_CONN_RSWITCH_PEND, &conn->pend)) {
struct hci_cp_switch_role cp;
bacpy(&cp.bdaddr, &conn->dst);
cp.role = role;
hci_send_cmd(conn->hdev, OGF_LINK_POLICY, OCF_SWITCH_ROLE, sizeof(cp), &cp);
}
return 0;
}
EXPORT_SYMBOL(hci_conn_switch_role);
/* Drop all connection on the device */ /* Drop all connection on the device */
void hci_conn_hash_flush(struct hci_dev *hdev) void hci_conn_hash_flush(struct hci_dev *hdev)
{ {
......
...@@ -718,17 +718,20 @@ static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb ...@@ -718,17 +718,20 @@ static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb
BT_DBG("%s status %d", hdev->name, ev->status); BT_DBG("%s status %d", hdev->name, ev->status);
if (ev->status)
return;
hci_dev_lock(hdev); hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
if (conn) { if (conn) {
if (ev->role) if (!ev->status) {
conn->link_mode &= ~HCI_LM_MASTER; if (ev->role)
else conn->link_mode &= ~HCI_LM_MASTER;
conn->link_mode |= HCI_LM_MASTER; else
conn->link_mode |= HCI_LM_MASTER;
}
clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
hci_role_switch_cfm(conn, ev->status, ev->role);
} }
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
...@@ -749,6 +752,7 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s ...@@ -749,6 +752,7 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
if (conn) { if (conn) {
if (!ev->status) if (!ev->status)
conn->link_mode |= HCI_LM_AUTH; conn->link_mode |= HCI_LM_AUTH;
clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
hci_auth_cfm(conn, ev->status); hci_auth_cfm(conn, ev->status);
...@@ -790,6 +794,7 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff * ...@@ -790,6 +794,7 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *
else else
conn->link_mode &= ~HCI_LM_ENCRYPT; conn->link_mode &= ~HCI_LM_ENCRYPT;
} }
clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
hci_encrypt_cfm(conn, ev->status, ev->encrypt); hci_encrypt_cfm(conn, ev->status, ev->encrypt);
...@@ -801,6 +806,25 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff * ...@@ -801,6 +806,25 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *
/* Change Connection Link Key Complete */ /* Change Connection Link Key Complete */
static inline void hci_change_conn_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) static inline void hci_change_conn_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{ {
struct hci_ev_change_conn_link_key_complete *ev = (struct hci_ev_change_conn_link_key_complete *) skb->data;
struct hci_conn *conn = NULL;
__u16 handle = __le16_to_cpu(ev->handle);
BT_DBG("%s status %d", hdev->name, ev->status);
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, handle);
if (conn) {
if (!ev->status)
conn->link_mode |= HCI_LM_SECURE;
clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
hci_key_change_cfm(conn, ev->status);
}
hci_dev_unlock(hdev);
} }
/* Pin Code Request*/ /* Pin Code Request*/
......
...@@ -55,7 +55,7 @@ static ssize_t show_inquiry_cache(struct class_device *cdev, char *buf) ...@@ -55,7 +55,7 @@ static ssize_t show_inquiry_cache(struct class_device *cdev, char *buf)
batostr(&bdaddr), batostr(&bdaddr),
data->pscan_rep_mode, data->pscan_period_mode, data->pscan_mode, data->pscan_rep_mode, data->pscan_period_mode, data->pscan_mode,
data->dev_class[2], data->dev_class[1], data->dev_class[0], data->dev_class[2], data->dev_class[1], data->dev_class[0],
data->clock_offset, data->rssi, e->timestamp); __le16_to_cpu(data->clock_offset), data->rssi, e->timestamp);
} }
hci_dev_unlock_bh(hdev); hci_dev_unlock_bh(hdev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment