Commit e3b4ac5d 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 eae9061b 221ce12d
...@@ -113,12 +113,15 @@ static struct usb_device_id blacklist_ids[] = { ...@@ -113,12 +113,15 @@ static struct usb_device_id blacklist_ids[] = {
/* ISSC Bluetooth Adapter v3.1 */ /* ISSC Bluetooth Adapter v3.1 */
{ USB_DEVICE(0x1131, 0x1001), .driver_info = HCI_RESET }, { USB_DEVICE(0x1131, 0x1001), .driver_info = HCI_RESET },
/* RTX Telecom based adapter with buggy SCO support */
{ USB_DEVICE(0x0400, 0x0807), .driver_info = HCI_BROKEN_ISOC },
/* Digianswer devices */ /* Digianswer devices */
{ USB_DEVICE(0x08fd, 0x0001), .driver_info = HCI_DIGIANSWER }, { USB_DEVICE(0x08fd, 0x0001), .driver_info = HCI_DIGIANSWER },
{ USB_DEVICE(0x08fd, 0x0002), .driver_info = HCI_IGNORE }, { USB_DEVICE(0x08fd, 0x0002), .driver_info = HCI_IGNORE },
/* RTX Telecom based adapter with buggy SCO support */ /* CSR BlueCore Bluetooth Sniffer */
{ USB_DEVICE(0x0400, 0x0807), .driver_info = HCI_BROKEN_ISOC }, { USB_DEVICE(0x0a12, 0x0002), .driver_info = HCI_SNIFFER },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
...@@ -969,6 +972,11 @@ static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id ...@@ -969,6 +972,11 @@ static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id
if (reset || id->driver_info & HCI_RESET) if (reset || id->driver_info & HCI_RESET)
set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks); set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks);
if (id->driver_info & HCI_SNIFFER) {
if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997)
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
}
if (hci_register_dev(hdev) < 0) { if (hci_register_dev(hdev) < 0) {
BT_ERR("Can't register HCI device"); BT_ERR("Can't register HCI device");
hci_free_dev(hdev); hci_free_dev(hdev);
......
...@@ -31,7 +31,8 @@ ...@@ -31,7 +31,8 @@
#define HCI_IGNORE 0x01 #define HCI_IGNORE 0x01
#define HCI_RESET 0x02 #define HCI_RESET 0x02
#define HCI_DIGIANSWER 0x04 #define HCI_DIGIANSWER 0x04
#define HCI_BROKEN_ISOC 0x08 #define HCI_SNIFFER 0x08
#define HCI_BROKEN_ISOC 0x10
#define HCI_MAX_IFACE_NUM 3 #define HCI_MAX_IFACE_NUM 3
......
...@@ -53,7 +53,8 @@ ...@@ -53,7 +53,8 @@
/* HCI device quirks */ /* HCI device quirks */
enum { enum {
HCI_QUIRK_RESET_ON_INIT HCI_QUIRK_RESET_ON_INIT,
HCI_QUIRK_RAW_DEVICE
}; };
/* HCI device flags */ /* HCI device flags */
...@@ -576,6 +577,13 @@ struct hci_ev_rmt_version { ...@@ -576,6 +577,13 @@ struct hci_ev_rmt_version {
__u16 lmp_subver; __u16 lmp_subver;
} __attribute__ ((packed)); } __attribute__ ((packed));
#define HCI_EV_CLOCK_OFFSET 0x01C
struct hci_ev_clock_offset {
__u8 status;
__u16 handle;
__u16 clock_offset;
} __attribute__ ((packed));
/* Internal events generated by Bluetooth stack */ /* Internal events generated by Bluetooth stack */
#define HCI_EV_STACK_INTERNAL 0xFD #define HCI_EV_STACK_INTERNAL 0xFD
struct hci_ev_stack_internal { struct hci_ev_stack_internal {
......
...@@ -226,7 +226,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) ...@@ -226,7 +226,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
list_for_each(p, &hci_dev_list) { list_for_each(p, &hci_dev_list) {
struct hci_dev *d = list_entry(p, struct hci_dev, list); struct hci_dev *d = list_entry(p, struct hci_dev, list);
if (!test_bit(HCI_UP, &d->flags)) if (!test_bit(HCI_UP, &d->flags) || test_bit(HCI_RAW, &d->flags))
continue; continue;
/* Simple routing: /* Simple routing:
......
...@@ -457,6 +457,9 @@ int hci_dev_open(__u16 dev) ...@@ -457,6 +457,9 @@ int hci_dev_open(__u16 dev)
goto done; goto done;
} }
if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
set_bit(HCI_RAW, &hdev->flags);
if (hdev->open(hdev)) { if (hdev->open(hdev)) {
ret = -EIO; ret = -EIO;
goto done; goto done;
...@@ -532,9 +535,11 @@ static int hci_dev_do_close(struct hci_dev *hdev) ...@@ -532,9 +535,11 @@ static int hci_dev_do_close(struct hci_dev *hdev)
/* Reset device */ /* Reset device */
skb_queue_purge(&hdev->cmd_q); skb_queue_purge(&hdev->cmd_q);
atomic_set(&hdev->cmd_cnt, 1); atomic_set(&hdev->cmd_cnt, 1);
if (!test_bit(HCI_RAW, &hdev->flags)) {
set_bit(HCI_INIT, &hdev->flags); set_bit(HCI_INIT, &hdev->flags);
__hci_request(hdev, hci_reset_req, 0, HZ/4); __hci_request(hdev, hci_reset_req, 0, HZ/4);
clear_bit(HCI_INIT, &hdev->flags); clear_bit(HCI_INIT, &hdev->flags);
}
/* Kill cmd task */ /* Kill cmd task */
tasklet_kill(&hdev->cmd_task); tasklet_kill(&hdev->cmd_task);
...@@ -604,6 +609,7 @@ int hci_dev_reset(__u16 dev) ...@@ -604,6 +609,7 @@ int hci_dev_reset(__u16 dev)
atomic_set(&hdev->cmd_cnt, 1); atomic_set(&hdev->cmd_cnt, 1);
hdev->acl_cnt = 0; hdev->sco_cnt = 0; hdev->acl_cnt = 0; hdev->sco_cnt = 0;
if (!test_bit(HCI_RAW, &hdev->flags))
ret = __hci_request(hdev, hci_reset_req, 0, HCI_INIT_TIMEOUT); ret = __hci_request(hdev, hci_reset_req, 0, HCI_INIT_TIMEOUT);
done: done:
...@@ -1192,10 +1198,12 @@ static inline void hci_sched_acl(struct hci_dev *hdev) ...@@ -1192,10 +1198,12 @@ static inline void hci_sched_acl(struct hci_dev *hdev)
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
if (!test_bit(HCI_RAW, &hdev->flags)) {
/* ACL tx timeout must be longer than maximum /* ACL tx timeout must be longer than maximum
* link supervision timeout (40.9 seconds) */ * link supervision timeout (40.9 seconds) */
if (!hdev->acl_cnt && (jiffies - hdev->acl_last_tx) > (HZ * 45)) if (!hdev->acl_cnt && (jiffies - hdev->acl_last_tx) > (HZ * 45))
hci_acl_tx_to(hdev); hci_acl_tx_to(hdev);
}
while (hdev->acl_cnt && (conn = hci_low_sent(hdev, ACL_LINK, &quote))) { while (hdev->acl_cnt && (conn = hci_low_sent(hdev, ACL_LINK, &quote))) {
while (quote-- && (skb = skb_dequeue(&conn->data_q))) { while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
......
...@@ -818,6 +818,30 @@ static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff ...@@ -818,6 +818,30 @@ static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff
{ {
} }
/* Clock Offset */
static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_clock_offset *ev = (struct hci_ev_clock_offset *) 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 && !ev->status) {
struct inquiry_entry *ie;
if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) {
ie->data.clock_offset = ev->clock_offset;
ie->timestamp = jiffies;
}
}
hci_dev_unlock(hdev);
}
void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
{ {
struct hci_event_hdr *hdr = (struct hci_event_hdr *) skb->data; struct hci_event_hdr *hdr = (struct hci_event_hdr *) skb->data;
...@@ -886,6 +910,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -886,6 +910,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
hci_link_key_notify_evt(hdev, skb); hci_link_key_notify_evt(hdev, skb);
break; break;
case HCI_EV_CLOCK_OFFSET:
hci_clock_offset_evt(hdev, skb);
break;
case HCI_EV_CMD_STATUS: case HCI_EV_CMD_STATUS:
cs = (struct hci_ev_cmd_status *) skb->data; cs = (struct hci_ev_cmd_status *) skb->data;
skb_pull(skb, sizeof(cs)); skb_pull(skb, sizeof(cs));
......
...@@ -179,6 +179,9 @@ static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsign ...@@ -179,6 +179,9 @@ static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsign
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN))
return -EACCES; return -EACCES;
if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
return -EPERM;
if (arg) if (arg)
set_bit(HCI_RAW, &hdev->flags); set_bit(HCI_RAW, &hdev->flags);
else else
......
...@@ -770,7 +770,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms ...@@ -770,7 +770,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
return -EOPNOTSUPP; return -EOPNOTSUPP;
/* Check outgoing MTU */ /* Check outgoing MTU */
if (len > l2cap_pi(sk)->omtu) if (sk->sk_type != SOCK_RAW && len > l2cap_pi(sk)->omtu)
return -EINVAL; return -EINVAL;
lock_sock(sk); lock_sock(sk);
......
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