diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c index 67d96b5cbb96..57c48bbf6fe6 100644 --- a/drivers/bluetooth/hci_usb.c +++ b/drivers/bluetooth/hci_usb.c @@ -65,13 +65,15 @@ #endif static int ignore = 0; +static int ignore_csr = 0; +static int ignore_sniffer = 0; static int reset = 0; #ifdef CONFIG_BT_HCIUSB_SCO static int isoc = 2; #endif -#define VERSION "2.8" +#define VERSION "2.9" static struct usb_driver hci_usb_driver; @@ -98,6 +100,9 @@ static struct usb_device_id bluetooth_ids[] = { MODULE_DEVICE_TABLE (usb, bluetooth_ids); static struct usb_device_id blacklist_ids[] = { + /* CSR BlueCore devices */ + { USB_DEVICE(0x0a12, 0x0001), .driver_info = HCI_CSR }, + /* Broadcom BCM2033 without firmware */ { USB_DEVICE(0x0a5c, 0x2033), .driver_info = HCI_IGNORE }, @@ -836,6 +841,12 @@ static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id if (ignore || id->driver_info & HCI_IGNORE) return -ENODEV; + if (ignore_csr && id->driver_info & HCI_CSR) + return -ENODEV; + + if (ignore_sniffer && id->driver_info & HCI_SNIFFER) + return -ENODEV; + if (intf->cur_altsetting->desc.bInterfaceNumber > 0) return -ENODEV; @@ -1061,6 +1072,12 @@ module_exit(hci_usb_exit); module_param(ignore, bool, 0644); MODULE_PARM_DESC(ignore, "Ignore devices from the matching table"); +module_param(ignore_csr, bool, 0644); +MODULE_PARM_DESC(ignore_csr, "Ignore devices with id 0a12:0001"); + +module_param(ignore_sniffer, bool, 0644); +MODULE_PARM_DESC(ignore_sniffer, "Ignore devices with id 0a12:0002"); + module_param(reset, bool, 0644); MODULE_PARM_DESC(reset, "Send HCI reset command on initialization"); diff --git a/drivers/bluetooth/hci_usb.h b/drivers/bluetooth/hci_usb.h index 29936b43d4f8..37100a6ea1a8 100644 --- a/drivers/bluetooth/hci_usb.h +++ b/drivers/bluetooth/hci_usb.h @@ -31,9 +31,10 @@ #define HCI_IGNORE 0x01 #define HCI_RESET 0x02 #define HCI_DIGIANSWER 0x04 -#define HCI_SNIFFER 0x08 -#define HCI_BROKEN_ISOC 0x10 +#define HCI_CSR 0x08 +#define HCI_SNIFFER 0x10 #define HCI_BCM92035 0x20 +#define HCI_BROKEN_ISOC 0x40 #define HCI_MAX_IFACE_NUM 3 diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 371e7d3f2e6f..fa2d12b0579b 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -463,6 +463,17 @@ struct inquiry_info_with_rssi_and_pscan_mode { __s8 rssi; } __attribute__ ((packed)); +#define HCI_EV_EXTENDED_INQUIRY_RESULT 0x2F +struct extended_inquiry_info { + bdaddr_t bdaddr; + __u8 pscan_rep_mode; + __u8 pscan_period_mode; + __u8 dev_class[3]; + __u16 clock_offset; + __s8 rssi; + __u8 data[240]; +} __attribute__ ((packed)); + #define HCI_EV_CONN_COMPLETE 0x03 struct hci_ev_conn_complete { __u8 status; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index d6da0939216d..b61b4e8e36fd 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -558,6 +558,35 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct hci_dev_unlock(hdev); } +/* Extended Inquiry Result */ +static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct inquiry_data data; + struct extended_inquiry_info *info = (struct extended_inquiry_info *) (skb->data + 1); + int num_rsp = *((__u8 *) skb->data); + + BT_DBG("%s num_rsp %d", hdev->name, num_rsp); + + if (!num_rsp) + return; + + hci_dev_lock(hdev); + + for (; num_rsp; num_rsp--) { + bacpy(&data.bdaddr, &info->bdaddr); + data.pscan_rep_mode = info->pscan_rep_mode; + data.pscan_period_mode = info->pscan_period_mode; + data.pscan_mode = 0x00; + memcpy(data.dev_class, info->dev_class, 3); + data.clock_offset = info->clock_offset; + data.rssi = info->rssi; + info++; + hci_inquiry_cache_update(hdev, &data); + } + + hci_dev_unlock(hdev); +} + /* Connect Request */ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) { @@ -940,6 +969,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) hci_inquiry_result_with_rssi_evt(hdev, skb); break; + case HCI_EV_EXTENDED_INQUIRY_RESULT: + hci_extended_inquiry_result_evt(hdev, skb); + break; + case HCI_EV_CONN_REQUEST: hci_conn_request_evt(hdev, skb); break; diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 90e19eb6d3cc..f49e7e938bfb 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -363,6 +363,11 @@ static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr goto done; } + if (sk->sk_type != SOCK_STREAM) { + err = -EINVAL; + goto done; + } + write_lock_bh(&rfcomm_sk_list.lock); if (sa->rc_channel && __rfcomm_get_sock_by_addr(sa->rc_channel, &sa->rc_bdaddr)) { @@ -393,14 +398,18 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a if (addr->sa_family != AF_BLUETOOTH || alen < sizeof(struct sockaddr_rc)) return -EINVAL; - if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) - return -EBADFD; - - if (sk->sk_type != SOCK_STREAM) - return -EINVAL; - lock_sock(sk); + if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) { + err = -EBADFD; + goto done; + } + + if (sk->sk_type != SOCK_STREAM) { + err = -EINVAL; + goto done; + } + sk->sk_state = BT_CONNECT; bacpy(&bt_sk(sk)->dst, &sa->rc_bdaddr); rfcomm_pi(sk)->channel = sa->rc_channel; @@ -410,6 +419,7 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a err = bt_sock_wait_state(sk, BT_CONNECTED, sock_sndtimeo(sk, flags & O_NONBLOCK)); +done: release_sock(sk); return err; } @@ -428,6 +438,11 @@ static int rfcomm_sock_listen(struct socket *sock, int backlog) goto done; } + if (sk->sk_type != SOCK_STREAM) { + err = -EINVAL; + goto done; + } + if (!rfcomm_pi(sk)->channel) { bdaddr_t *src = &bt_sk(sk)->src; u8 channel; @@ -472,6 +487,11 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f goto done; } + if (sk->sk_type != SOCK_STREAM) { + err = -EINVAL; + goto done; + } + timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); BT_DBG("sk %p timeo %ld", sk, timeo);