2007-10-20 14:12:34 +02:00
/*
*
* Generic Bluetooth USB driver
*
2008-08-18 13:23:52 +02:00
* Copyright ( C ) 2005 - 2008 Marcel Holtmann < marcel @ holtmann . org >
2007-10-20 14:12:34 +02:00
*
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*
*/
# include <linux/module.h>
# include <linux/usb.h>
2013-04-19 09:57:43 -07:00
# include <linux/firmware.h>
2007-10-20 14:12:34 +02:00
# include <net/bluetooth/bluetooth.h>
# include <net/bluetooth/hci_core.h>
2009-08-24 23:44:59 +02:00
# define VERSION "0.6"
2008-08-07 22:26:56 +02:00
2012-01-13 09:32:20 +10:30
static bool disable_scofix ;
static bool force_scofix ;
2008-11-30 12:17:26 +01:00
2012-01-13 09:32:20 +10:30
static bool reset = 1 ;
2008-08-07 22:26:56 +02:00
static struct usb_driver btusb_driver ;
# define BTUSB_IGNORE 0x01
2008-11-30 12:17:26 +01:00
# define BTUSB_DIGIANSWER 0x02
# define BTUSB_CSR 0x04
# define BTUSB_SNIFFER 0x08
# define BTUSB_BCM92035 0x10
# define BTUSB_BROKEN_ISOC 0x20
# define BTUSB_WRONG_SCO_MTU 0x40
2011-07-01 14:02:36 +08:00
# define BTUSB_ATH3012 0x80
2013-04-19 09:57:43 -07:00
# define BTUSB_INTEL 0x100
2014-07-06 13:29:58 +02:00
# define BTUSB_INTEL_BOOT 0x200
# define BTUSB_BCM_PATCHRAM 0x400
2014-07-18 14:47:06 -07:00
# define BTUSB_MARVELL 0x800
2015-01-01 17:34:37 -08:00
# define BTUSB_SWAVE 0x1000
2007-10-20 14:12:34 +02:00
2013-10-11 07:46:18 -07:00
static const struct usb_device_id btusb_table [ ] = {
2007-10-20 14:12:34 +02:00
/* Generic Bluetooth USB device */
{ USB_DEVICE_INFO ( 0xe0 , 0x01 , 0x01 ) } ,
2012-08-25 19:28:06 +02:00
/* Apple-specific (Broadcom) devices */
{ USB_VENDOR_AND_INTERFACE_INFO ( 0x05ac , 0xff , 0x01 , 0x01 ) } ,
2013-06-04 21:40:26 +08:00
/* MediaTek MT76x0E */
{ USB_DEVICE ( 0x0e8d , 0x763f ) } ,
2011-09-21 11:41:45 +02:00
/* Broadcom SoftSailing reporting vendor specific */
2012-03-28 16:41:11 -04:00
{ USB_DEVICE ( 0x0a5c , 0x21e1 ) } ,
2011-09-21 11:41:45 +02:00
2010-08-20 16:24:07 +09:00
/* Apple MacBookPro 7,1 */
{ USB_DEVICE ( 0x05ac , 0x8213 ) } ,
2010-07-14 10:29:27 +04:00
/* Apple iMac11,1 */
{ USB_DEVICE ( 0x05ac , 0x8215 ) } ,
2010-08-20 16:24:06 +09:00
/* Apple MacBookPro6,2 */
{ USB_DEVICE ( 0x05ac , 0x8218 ) } ,
2010-11-04 08:04:33 +01:00
/* Apple MacBookAir3,1, MacBookAir3,2 */
{ USB_DEVICE ( 0x05ac , 0x821b ) } ,
2011-09-07 02:28:10 -04:00
/* Apple MacBookAir4,1 */
{ USB_DEVICE ( 0x05ac , 0x821f ) } ,
2011-03-24 14:51:21 -03:00
/* Apple MacBookPro8,2 */
{ USB_DEVICE ( 0x05ac , 0x821a ) } ,
2011-09-04 18:01:42 +02:00
/* Apple MacMini5,1 */
{ USB_DEVICE ( 0x05ac , 0x8281 ) } ,
2008-08-07 22:26:56 +02:00
/* AVM BlueFRITZ! USB v2.0 */
2015-01-01 17:34:37 -08:00
{ USB_DEVICE ( 0x057c , 0x3800 ) , . driver_info = BTUSB_SWAVE } ,
2008-08-07 22:26:56 +02:00
/* Bluetooth Ultraport Module from IBM */
{ USB_DEVICE ( 0x04bf , 0x030a ) } ,
/* ALPS Modules with non-standard id */
{ USB_DEVICE ( 0x044e , 0x3001 ) } ,
{ USB_DEVICE ( 0x044e , 0x3002 ) } ,
/* Ericsson with non-standard id */
{ USB_DEVICE ( 0x0bdb , 0x1002 ) } ,
/* Canyon CN-BTU1 with HID interfaces */
2008-11-30 12:17:26 +01:00
{ USB_DEVICE ( 0x0c10 , 0x0000 ) } ,
2008-08-07 22:26:56 +02:00
2011-11-08 14:30:22 +08:00
/* Broadcom BCM20702A0 */
2014-02-18 18:26:19 +02:00
{ USB_DEVICE ( 0x0489 , 0xe042 ) } ,
{ USB_DEVICE ( 0x04ca , 0x2003 ) } ,
2012-11-09 16:39:48 -07:00
{ USB_DEVICE ( 0x0b05 , 0x17b5 ) } ,
2013-09-02 14:57:51 +03:00
{ USB_DEVICE ( 0x0b05 , 0x17cb ) } ,
2011-11-08 14:30:22 +08:00
{ USB_DEVICE ( 0x413c , 0x8197 ) } ,
2014-11-18 00:46:28 -02:00
{ USB_DEVICE ( 0x13d3 , 0x3404 ) ,
. driver_info = BTUSB_BCM_PATCHRAM } ,
2011-11-08 14:30:22 +08:00
2012-04-13 14:45:55 -04:00
/* Foxconn - Hon Hai */
2014-12-03 19:32:22 +01:00
{ USB_VENDOR_AND_INTERFACE_INFO ( 0x0489 , 0xff , 0x01 , 0x01 ) ,
. driver_info = BTUSB_BCM_PATCHRAM } ,
2012-04-13 14:45:55 -04:00
2014-02-18 18:26:19 +02:00
/* Broadcom devices with vendor specific id */
2014-05-08 15:50:01 -07:00
{ USB_VENDOR_AND_INTERFACE_INFO ( 0x0a5c , 0xff , 0x01 , 0x01 ) ,
. driver_info = BTUSB_BCM_PATCHRAM } ,
2012-08-06 15:36:49 -03:00
2014-07-21 14:02:33 +02:00
/* ASUSTek Computer - Broadcom based */
{ USB_VENDOR_AND_INTERFACE_INFO ( 0x0b05 , 0xff , 0x01 , 0x01 ) } ,
2013-09-21 19:14:43 +01:00
/* Belkin F8065bf - Broadcom based */
{ USB_VENDOR_AND_INTERFACE_INFO ( 0x050d , 0xff , 0x01 , 0x01 ) } ,
2014-02-15 12:01:09 +01:00
/* IMC Networks - Broadcom based */
{ USB_VENDOR_AND_INTERFACE_INFO ( 0x13d3 , 0xff , 0x01 , 0x01 ) } ,
2014-07-06 13:29:58 +02:00
/* Intel Bluetooth USB Bootloader (RAM module) */
2014-07-06 14:53:55 +02:00
{ USB_DEVICE ( 0x8087 , 0x0a5a ) ,
. driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC } ,
2014-07-06 13:29:58 +02:00
2007-10-20 14:12:34 +02:00
{ } /* Terminating entry */
} ;
MODULE_DEVICE_TABLE ( usb , btusb_table ) ;
2013-10-11 07:46:18 -07:00
static const struct usb_device_id blacklist_table [ ] = {
2008-08-07 22:26:56 +02:00
/* CSR BlueCore devices */
{ USB_DEVICE ( 0x0a12 , 0x0001 ) , . driver_info = BTUSB_CSR } ,
/* Broadcom BCM2033 without firmware */
{ USB_DEVICE ( 0x0a5c , 0x2033 ) , . driver_info = BTUSB_IGNORE } ,
2010-11-26 17:35:46 +05:30
/* Atheros 3011 with sflash firmware */
2014-02-18 18:26:19 +02:00
{ USB_DEVICE ( 0x0489 , 0xe027 ) , . driver_info = BTUSB_IGNORE } ,
{ USB_DEVICE ( 0x0489 , 0xe03d ) , . driver_info = BTUSB_IGNORE } ,
{ USB_DEVICE ( 0x0930 , 0x0215 ) , . driver_info = BTUSB_IGNORE } ,
2010-11-26 17:35:46 +05:30
{ USB_DEVICE ( 0x0cf3 , 0x3002 ) , . driver_info = BTUSB_IGNORE } ,
2012-06-08 14:32:50 +02:00
{ USB_DEVICE ( 0x0cf3 , 0xe019 ) , . driver_info = BTUSB_IGNORE } ,
2011-05-09 16:11:16 -07:00
{ USB_DEVICE ( 0x13d3 , 0x3304 ) , . driver_info = BTUSB_IGNORE } ,
2010-11-26 17:35:46 +05:30
2011-01-26 17:10:59 +08:00
/* Atheros AR9285 Malbec with sflash firmware */
{ USB_DEVICE ( 0x03f0 , 0x311d ) , . driver_info = BTUSB_IGNORE } ,
2011-02-11 15:38:53 +05:30
/* Atheros 3012 with sflash firmware */
2014-02-18 18:26:19 +02:00
{ USB_DEVICE ( 0x0489 , 0xe04d ) , . driver_info = BTUSB_ATH3012 } ,
{ USB_DEVICE ( 0x0489 , 0xe04e ) , . driver_info = BTUSB_ATH3012 } ,
{ USB_DEVICE ( 0x0489 , 0xe056 ) , . driver_info = BTUSB_ATH3012 } ,
{ USB_DEVICE ( 0x0489 , 0xe057 ) , . driver_info = BTUSB_ATH3012 } ,
{ USB_DEVICE ( 0x0489 , 0xe05f ) , . driver_info = BTUSB_ATH3012 } ,
2014-10-06 16:31:49 +05:30
{ USB_DEVICE ( 0x0489 , 0xe078 ) , . driver_info = BTUSB_ATH3012 } ,
2014-02-18 18:26:19 +02:00
{ USB_DEVICE ( 0x04c5 , 0x1330 ) , . driver_info = BTUSB_ATH3012 } ,
{ USB_DEVICE ( 0x04ca , 0x3004 ) , . driver_info = BTUSB_ATH3012 } ,
{ USB_DEVICE ( 0x04ca , 0x3005 ) , . driver_info = BTUSB_ATH3012 } ,
{ USB_DEVICE ( 0x04ca , 0x3006 ) , . driver_info = BTUSB_ATH3012 } ,
2014-04-17 11:37:13 -07:00
{ USB_DEVICE ( 0x04ca , 0x3007 ) , . driver_info = BTUSB_ATH3012 } ,
2014-02-18 18:26:19 +02:00
{ USB_DEVICE ( 0x04ca , 0x3008 ) , . driver_info = BTUSB_ATH3012 } ,
{ USB_DEVICE ( 0x04ca , 0x300b ) , . driver_info = BTUSB_ATH3012 } ,
2014-12-09 07:44:51 +02:00
{ USB_DEVICE ( 0x04ca , 0x3010 ) , . driver_info = BTUSB_ATH3012 } ,
2014-02-18 18:26:19 +02:00
{ USB_DEVICE ( 0x0930 , 0x0219 ) , . driver_info = BTUSB_ATH3012 } ,
{ USB_DEVICE ( 0x0930 , 0x0220 ) , . driver_info = BTUSB_ATH3012 } ,
2014-08-08 12:33:56 +01:00
{ USB_DEVICE ( 0x0930 , 0x0227 ) , . driver_info = BTUSB_ATH3012 } ,
2014-02-18 18:26:20 +02:00
{ USB_DEVICE ( 0x0b05 , 0x17d0 ) , . driver_info = BTUSB_ATH3012 } ,
2013-03-15 11:00:39 +08:00
{ USB_DEVICE ( 0x0cf3 , 0x0036 ) , . driver_info = BTUSB_ATH3012 } ,
2011-07-01 14:02:36 +08:00
{ USB_DEVICE ( 0x0cf3 , 0x3004 ) , . driver_info = BTUSB_ATH3012 } ,
2013-03-12 04:41:58 +09:00
{ USB_DEVICE ( 0x0cf3 , 0x3008 ) , . driver_info = BTUSB_ATH3012 } ,
2012-03-14 22:01:21 +02:00
{ USB_DEVICE ( 0x0cf3 , 0x311d ) , . driver_info = BTUSB_ATH3012 } ,
2014-01-16 15:37:11 +01:00
{ USB_DEVICE ( 0x0cf3 , 0x311e ) , . driver_info = BTUSB_ATH3012 } ,
2014-01-16 16:02:58 +01:00
{ USB_DEVICE ( 0x0cf3 , 0x311f ) , . driver_info = BTUSB_ATH3012 } ,
2014-02-18 18:26:19 +02:00
{ USB_DEVICE ( 0x0cf3 , 0x3121 ) , . driver_info = BTUSB_ATH3012 } ,
2013-03-18 23:45:11 +08:00
{ USB_DEVICE ( 0x0cf3 , 0x817a ) , . driver_info = BTUSB_ATH3012 } ,
2014-02-18 18:26:19 +02:00
{ USB_DEVICE ( 0x0cf3 , 0xe003 ) , . driver_info = BTUSB_ATH3012 } ,
2012-04-19 14:53:45 +08:00
{ USB_DEVICE ( 0x0cf3 , 0xe004 ) , . driver_info = BTUSB_ATH3012 } ,
2013-08-30 17:41:40 +08:00
{ USB_DEVICE ( 0x0cf3 , 0xe005 ) , . driver_info = BTUSB_ATH3012 } ,
2014-02-18 18:26:19 +02:00
{ USB_DEVICE ( 0x13d3 , 0x3362 ) , . driver_info = BTUSB_ATH3012 } ,
{ USB_DEVICE ( 0x13d3 , 0x3375 ) , . driver_info = BTUSB_ATH3012 } ,
2012-12-11 11:41:20 +08:00
{ USB_DEVICE ( 0x13d3 , 0x3393 ) , . driver_info = BTUSB_ATH3012 } ,
2013-07-15 09:29:03 +05:30
{ USB_DEVICE ( 0x13d3 , 0x3402 ) , . driver_info = BTUSB_ATH3012 } ,
2014-11-25 20:19:52 +03:00
{ USB_DEVICE ( 0x13d3 , 0x3408 ) , . driver_info = BTUSB_ATH3012 } ,
2014-07-08 19:25:08 +05:30
{ USB_DEVICE ( 0x13d3 , 0x3432 ) , . driver_info = BTUSB_ATH3012 } ,
2011-02-11 15:38:53 +05:30
2011-02-15 10:20:07 +08:00
/* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE ( 0x0489 , 0xe02c ) , . driver_info = BTUSB_IGNORE } ,
2012-05-02 22:33:40 +02:00
/* Atheros AR5BBU12 with sflash firmware */
2012-08-07 19:48:10 +05:30
{ USB_DEVICE ( 0x0489 , 0xe036 ) , . driver_info = BTUSB_ATH3012 } ,
2014-02-18 18:26:19 +02:00
{ USB_DEVICE ( 0x0489 , 0xe03c ) , . driver_info = BTUSB_ATH3012 } ,
2012-05-02 22:33:40 +02:00
2008-08-07 22:26:56 +02:00
/* Broadcom BCM2035 */
2008-11-30 12:17:26 +01:00
{ USB_DEVICE ( 0x0a5c , 0x2009 ) , . driver_info = BTUSB_BCM92035 } ,
2014-02-18 18:26:19 +02:00
{ USB_DEVICE ( 0x0a5c , 0x200a ) , . driver_info = BTUSB_WRONG_SCO_MTU } ,
{ USB_DEVICE ( 0x0a5c , 0x2035 ) , . driver_info = BTUSB_WRONG_SCO_MTU } ,
2008-08-07 22:26:56 +02:00
/* Broadcom BCM2045 */
2008-11-30 12:17:26 +01:00
{ USB_DEVICE ( 0x0a5c , 0x2039 ) , . driver_info = BTUSB_WRONG_SCO_MTU } ,
{ USB_DEVICE ( 0x0a5c , 0x2101 ) , . driver_info = BTUSB_WRONG_SCO_MTU } ,
2008-09-23 00:16:35 +02:00
2008-08-07 22:26:56 +02:00
/* IBM/Lenovo ThinkPad with Broadcom chip */
2008-11-30 12:17:26 +01:00
{ USB_DEVICE ( 0x0a5c , 0x201e ) , . driver_info = BTUSB_WRONG_SCO_MTU } ,
{ USB_DEVICE ( 0x0a5c , 0x2110 ) , . driver_info = BTUSB_WRONG_SCO_MTU } ,
2008-08-07 22:26:56 +02:00
/* HP laptop with Broadcom chip */
2008-11-30 12:17:26 +01:00
{ USB_DEVICE ( 0x03f0 , 0x171d ) , . driver_info = BTUSB_WRONG_SCO_MTU } ,
2008-08-07 22:26:56 +02:00
/* Dell laptop with Broadcom chip */
2008-11-30 12:17:26 +01:00
{ USB_DEVICE ( 0x413c , 0x8126 ) , . driver_info = BTUSB_WRONG_SCO_MTU } ,
2008-08-07 22:26:56 +02:00
2008-11-30 12:17:27 +01:00
/* Dell Wireless 370 and 410 devices */
2008-11-30 12:17:26 +01:00
{ USB_DEVICE ( 0x413c , 0x8152 ) , . driver_info = BTUSB_WRONG_SCO_MTU } ,
2008-11-30 12:17:27 +01:00
{ USB_DEVICE ( 0x413c , 0x8156 ) , . driver_info = BTUSB_WRONG_SCO_MTU } ,
2008-08-07 22:26:56 +02:00
2008-11-30 12:17:26 +01:00
/* Belkin F8T012 and F8T013 devices */
{ USB_DEVICE ( 0x050d , 0x0012 ) , . driver_info = BTUSB_WRONG_SCO_MTU } ,
{ USB_DEVICE ( 0x050d , 0x0013 ) , . driver_info = BTUSB_WRONG_SCO_MTU } ,
2008-08-07 22:26:56 +02:00
2008-11-30 12:17:27 +01:00
/* Asus WL-BTD202 device */
{ USB_DEVICE ( 0x0b05 , 0x1715 ) , . driver_info = BTUSB_WRONG_SCO_MTU } ,
/* Kensington Bluetooth USB adapter */
{ USB_DEVICE ( 0x047d , 0x105e ) , . driver_info = BTUSB_WRONG_SCO_MTU } ,
2008-08-07 22:26:56 +02:00
/* RTX Telecom based adapters with buggy SCO support */
{ USB_DEVICE ( 0x0400 , 0x0807 ) , . driver_info = BTUSB_BROKEN_ISOC } ,
{ USB_DEVICE ( 0x0400 , 0x080a ) , . driver_info = BTUSB_BROKEN_ISOC } ,
/* CONWISE Technology based adapters with buggy SCO support */
{ USB_DEVICE ( 0x0e5e , 0x6622 ) , . driver_info = BTUSB_BROKEN_ISOC } ,
2015-01-01 17:34:37 -08:00
/* Roper Class 1 Bluetooth Dongle (Silicon Wave based) */
{ USB_DEVICE ( 0x1300 , 0x0001 ) , . driver_info = BTUSB_SWAVE } ,
2008-08-07 22:26:56 +02:00
/* Digianswer devices */
{ USB_DEVICE ( 0x08fd , 0x0001 ) , . driver_info = BTUSB_DIGIANSWER } ,
{ USB_DEVICE ( 0x08fd , 0x0002 ) , . driver_info = BTUSB_IGNORE } ,
/* CSR BlueCore Bluetooth Sniffer */
2014-07-07 00:12:04 +02:00
{ USB_DEVICE ( 0x0a12 , 0x0002 ) ,
. driver_info = BTUSB_SNIFFER | BTUSB_BROKEN_ISOC } ,
2008-08-07 22:26:56 +02:00
/* Frontline ComProbe Bluetooth Sniffer */
2014-07-07 00:12:04 +02:00
{ USB_DEVICE ( 0x16d3 , 0x0002 ) ,
. driver_info = BTUSB_SNIFFER | BTUSB_BROKEN_ISOC } ,
2008-08-07 22:26:56 +02:00
2013-04-19 09:57:43 -07:00
/* Intel Bluetooth device */
{ USB_DEVICE ( 0x8087 , 0x07dc ) , . driver_info = BTUSB_INTEL } ,
2013-11-12 13:10:58 -08:00
{ USB_DEVICE ( 0x8087 , 0x0a2a ) , . driver_info = BTUSB_INTEL } ,
2013-04-19 09:57:43 -07:00
2014-07-18 14:47:06 -07:00
/* Marvell device */
{ USB_DEVICE ( 0x1286 , 0x2044 ) , . driver_info = BTUSB_MARVELL } ,
{ USB_DEVICE ( 0x1286 , 0x2046 ) , . driver_info = BTUSB_MARVELL } ,
2007-10-20 14:12:34 +02:00
{ } /* Terminating entry */
} ;
2008-08-18 13:23:52 +02:00
# define BTUSB_MAX_ISOC_FRAMES 10
2007-10-20 14:12:34 +02:00
# define BTUSB_INTR_RUNNING 0
# define BTUSB_BULK_RUNNING 1
2008-08-18 13:23:52 +02:00
# define BTUSB_ISOC_RUNNING 2
2009-08-24 23:44:59 +02:00
# define BTUSB_SUSPENDING 3
2010-07-16 17:20:33 -03:00
# define BTUSB_DID_ISO_RESUME 4
2007-10-20 14:12:34 +02:00
struct btusb_data {
struct hci_dev * hdev ;
struct usb_device * udev ;
2008-09-23 00:16:36 +02:00
struct usb_interface * intf ;
2008-08-18 13:23:52 +02:00
struct usb_interface * isoc ;
2007-10-20 14:12:34 +02:00
unsigned long flags ;
struct work_struct work ;
2009-08-24 23:44:59 +02:00
struct work_struct waker ;
2007-10-20 14:12:34 +02:00
2014-09-16 08:00:29 +02:00
struct usb_anchor deferred ;
2007-10-20 14:12:34 +02:00
struct usb_anchor tx_anchor ;
2014-09-16 08:00:29 +02:00
int tx_in_flight ;
spinlock_t txlock ;
2007-10-20 14:12:34 +02:00
struct usb_anchor intr_anchor ;
struct usb_anchor bulk_anchor ;
2008-08-18 13:23:52 +02:00
struct usb_anchor isoc_anchor ;
2014-09-16 08:00:29 +02:00
spinlock_t rxlock ;
struct sk_buff * evt_skb ;
struct sk_buff * acl_skb ;
struct sk_buff * sco_skb ;
2007-10-20 14:12:34 +02:00
struct usb_endpoint_descriptor * intr_ep ;
struct usb_endpoint_descriptor * bulk_tx_ep ;
struct usb_endpoint_descriptor * bulk_rx_ep ;
2008-08-18 13:23:52 +02:00
struct usb_endpoint_descriptor * isoc_tx_ep ;
struct usb_endpoint_descriptor * isoc_rx_ep ;
2008-11-30 12:17:26 +01:00
__u8 cmdreq_type ;
2009-02-04 17:41:38 +01:00
unsigned int sco_num ;
2008-08-18 13:23:52 +02:00
int isoc_altsetting ;
2008-11-30 12:17:14 +01:00
int suspend_count ;
2014-11-03 05:16:07 +01:00
int ( * recv_bulk ) ( struct btusb_data * data , void * buffer , int count ) ;
2007-10-20 14:12:34 +02:00
} ;
2014-09-16 08:00:29 +02:00
static inline void btusb_free_frags ( struct btusb_data * data )
{
unsigned long flags ;
spin_lock_irqsave ( & data - > rxlock , flags ) ;
kfree_skb ( data - > evt_skb ) ;
data - > evt_skb = NULL ;
kfree_skb ( data - > acl_skb ) ;
data - > acl_skb = NULL ;
kfree_skb ( data - > sco_skb ) ;
data - > sco_skb = NULL ;
spin_unlock_irqrestore ( & data - > rxlock , flags ) ;
}
2014-09-16 05:33:33 +02:00
static int btusb_recv_intr ( struct btusb_data * data , void * buffer , int count )
{
2014-09-16 08:00:29 +02:00
struct sk_buff * skb ;
int err = 0 ;
spin_lock ( & data - > rxlock ) ;
skb = data - > evt_skb ;
while ( count ) {
int len ;
if ( ! skb ) {
skb = bt_skb_alloc ( HCI_MAX_EVENT_SIZE , GFP_ATOMIC ) ;
if ( ! skb ) {
err = - ENOMEM ;
break ;
}
bt_cb ( skb ) - > pkt_type = HCI_EVENT_PKT ;
bt_cb ( skb ) - > expect = HCI_EVENT_HDR_SIZE ;
}
len = min_t ( uint , bt_cb ( skb ) - > expect , count ) ;
memcpy ( skb_put ( skb , len ) , buffer , len ) ;
count - = len ;
buffer + = len ;
bt_cb ( skb ) - > expect - = len ;
if ( skb - > len = = HCI_EVENT_HDR_SIZE ) {
/* Complete event header */
bt_cb ( skb ) - > expect = hci_event_hdr ( skb ) - > plen ;
if ( skb_tailroom ( skb ) < bt_cb ( skb ) - > expect ) {
kfree_skb ( skb ) ;
skb = NULL ;
err = - EILSEQ ;
break ;
}
}
if ( bt_cb ( skb ) - > expect = = 0 ) {
/* Complete frame */
hci_recv_frame ( data - > hdev , skb ) ;
skb = NULL ;
}
}
data - > evt_skb = skb ;
spin_unlock ( & data - > rxlock ) ;
return err ;
2014-09-16 05:33:33 +02:00
}
static int btusb_recv_bulk ( struct btusb_data * data , void * buffer , int count )
{
2014-09-16 08:00:29 +02:00
struct sk_buff * skb ;
int err = 0 ;
spin_lock ( & data - > rxlock ) ;
skb = data - > acl_skb ;
while ( count ) {
int len ;
if ( ! skb ) {
skb = bt_skb_alloc ( HCI_MAX_FRAME_SIZE , GFP_ATOMIC ) ;
if ( ! skb ) {
err = - ENOMEM ;
break ;
}
bt_cb ( skb ) - > pkt_type = HCI_ACLDATA_PKT ;
bt_cb ( skb ) - > expect = HCI_ACL_HDR_SIZE ;
}
len = min_t ( uint , bt_cb ( skb ) - > expect , count ) ;
memcpy ( skb_put ( skb , len ) , buffer , len ) ;
count - = len ;
buffer + = len ;
bt_cb ( skb ) - > expect - = len ;
if ( skb - > len = = HCI_ACL_HDR_SIZE ) {
__le16 dlen = hci_acl_hdr ( skb ) - > dlen ;
/* Complete ACL header */
bt_cb ( skb ) - > expect = __le16_to_cpu ( dlen ) ;
if ( skb_tailroom ( skb ) < bt_cb ( skb ) - > expect ) {
kfree_skb ( skb ) ;
skb = NULL ;
err = - EILSEQ ;
break ;
}
}
if ( bt_cb ( skb ) - > expect = = 0 ) {
/* Complete frame */
hci_recv_frame ( data - > hdev , skb ) ;
skb = NULL ;
}
}
data - > acl_skb = skb ;
spin_unlock ( & data - > rxlock ) ;
return err ;
2014-09-16 05:33:33 +02:00
}
static int btusb_recv_isoc ( struct btusb_data * data , void * buffer , int count )
{
2014-09-16 08:00:29 +02:00
struct sk_buff * skb ;
int err = 0 ;
spin_lock ( & data - > rxlock ) ;
skb = data - > sco_skb ;
while ( count ) {
int len ;
if ( ! skb ) {
skb = bt_skb_alloc ( HCI_MAX_SCO_SIZE , GFP_ATOMIC ) ;
if ( ! skb ) {
err = - ENOMEM ;
break ;
}
bt_cb ( skb ) - > pkt_type = HCI_SCODATA_PKT ;
bt_cb ( skb ) - > expect = HCI_SCO_HDR_SIZE ;
}
len = min_t ( uint , bt_cb ( skb ) - > expect , count ) ;
memcpy ( skb_put ( skb , len ) , buffer , len ) ;
count - = len ;
buffer + = len ;
bt_cb ( skb ) - > expect - = len ;
if ( skb - > len = = HCI_SCO_HDR_SIZE ) {
/* Complete SCO header */
bt_cb ( skb ) - > expect = hci_sco_hdr ( skb ) - > dlen ;
if ( skb_tailroom ( skb ) < bt_cb ( skb ) - > expect ) {
kfree_skb ( skb ) ;
skb = NULL ;
err = - EILSEQ ;
break ;
}
}
if ( bt_cb ( skb ) - > expect = = 0 ) {
/* Complete frame */
hci_recv_frame ( data - > hdev , skb ) ;
skb = NULL ;
}
}
data - > sco_skb = skb ;
spin_unlock ( & data - > rxlock ) ;
return err ;
2014-09-16 05:33:33 +02:00
}
2007-10-20 14:12:34 +02:00
static void btusb_intr_complete ( struct urb * urb )
{
struct hci_dev * hdev = urb - > context ;
2012-02-09 21:58:32 +01:00
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
2007-10-20 14:12:34 +02:00
int err ;
2014-09-16 04:44:50 +02:00
BT_DBG ( " %s urb %p status %d count %d " , hdev - > name , urb , urb - > status ,
urb - > actual_length ) ;
2007-10-20 14:12:34 +02:00
if ( ! test_bit ( HCI_RUNNING , & hdev - > flags ) )
return ;
if ( urb - > status = = 0 ) {
2008-08-18 13:23:52 +02:00
hdev - > stat . byte_rx + = urb - > actual_length ;
2014-09-16 05:33:33 +02:00
if ( btusb_recv_intr ( data , urb - > transfer_buffer ,
urb - > actual_length ) < 0 ) {
2007-10-20 14:12:34 +02:00
BT_ERR ( " %s corrupted event packet " , hdev - > name ) ;
hdev - > stat . err_rx + + ;
}
2014-09-06 14:06:08 -05:00
} else if ( urb - > status = = - ENOENT ) {
/* Avoid suspend failed when usb_kill_urb */
return ;
2007-10-20 14:12:34 +02:00
}
if ( ! test_bit ( BTUSB_INTR_RUNNING , & data - > flags ) )
return ;
2009-08-24 23:44:59 +02:00
usb_mark_last_busy ( data - > udev ) ;
2007-10-20 14:12:34 +02:00
usb_anchor_urb ( urb , & data - > intr_anchor ) ;
err = usb_submit_urb ( urb , GFP_ATOMIC ) ;
if ( err < 0 ) {
2011-08-09 17:16:28 +02:00
/* -EPERM: urb is being killed;
* - ENODEV : device got disconnected */
if ( err ! = - EPERM & & err ! = - ENODEV )
2010-11-30 21:49:08 +01:00
BT_ERR ( " %s urb %p failed to resubmit (%d) " ,
2014-09-16 04:44:50 +02:00
hdev - > name , urb , - err ) ;
2007-10-20 14:12:34 +02:00
usb_unanchor_urb ( urb ) ;
}
}
2008-11-30 12:17:10 +01:00
static int btusb_submit_intr_urb ( struct hci_dev * hdev , gfp_t mem_flags )
2007-10-20 14:12:34 +02:00
{
2012-02-09 21:58:32 +01:00
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
2007-10-20 14:12:34 +02:00
struct urb * urb ;
unsigned char * buf ;
unsigned int pipe ;
int err , size ;
BT_DBG ( " %s " , hdev - > name ) ;
2008-08-18 13:23:52 +02:00
if ( ! data - > intr_ep )
return - ENODEV ;
2008-11-30 12:17:10 +01:00
urb = usb_alloc_urb ( 0 , mem_flags ) ;
2007-10-20 14:12:34 +02:00
if ( ! urb )
return - ENOMEM ;
size = le16_to_cpu ( data - > intr_ep - > wMaxPacketSize ) ;
2008-11-30 12:17:10 +01:00
buf = kmalloc ( size , mem_flags ) ;
2007-10-20 14:12:34 +02:00
if ( ! buf ) {
usb_free_urb ( urb ) ;
return - ENOMEM ;
}
pipe = usb_rcvintpipe ( data - > udev , data - > intr_ep - > bEndpointAddress ) ;
usb_fill_int_urb ( urb , data - > udev , pipe , buf , size ,
2014-09-16 04:44:50 +02:00
btusb_intr_complete , hdev , data - > intr_ep - > bInterval ) ;
2007-10-20 14:12:34 +02:00
urb - > transfer_flags | = URB_FREE_BUFFER ;
usb_anchor_urb ( urb , & data - > intr_anchor ) ;
2008-11-30 12:17:10 +01:00
err = usb_submit_urb ( urb , mem_flags ) ;
2007-10-20 14:12:34 +02:00
if ( err < 0 ) {
2011-10-09 12:12:22 +02:00
if ( err ! = - EPERM & & err ! = - ENODEV )
BT_ERR ( " %s urb %p submission failed (%d) " ,
2014-09-16 04:44:50 +02:00
hdev - > name , urb , - err ) ;
2007-10-20 14:12:34 +02:00
usb_unanchor_urb ( urb ) ;
}
usb_free_urb ( urb ) ;
return err ;
}
static void btusb_bulk_complete ( struct urb * urb )
{
struct hci_dev * hdev = urb - > context ;
2012-02-09 21:58:32 +01:00
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
2007-10-20 14:12:34 +02:00
int err ;
2014-09-16 04:44:50 +02:00
BT_DBG ( " %s urb %p status %d count %d " , hdev - > name , urb , urb - > status ,
urb - > actual_length ) ;
2007-10-20 14:12:34 +02:00
if ( ! test_bit ( HCI_RUNNING , & hdev - > flags ) )
return ;
if ( urb - > status = = 0 ) {
2008-08-18 13:23:52 +02:00
hdev - > stat . byte_rx + = urb - > actual_length ;
2014-11-03 05:16:07 +01:00
if ( data - > recv_bulk ( data , urb - > transfer_buffer ,
2014-09-16 05:33:33 +02:00
urb - > actual_length ) < 0 ) {
2007-10-20 14:12:34 +02:00
BT_ERR ( " %s corrupted ACL packet " , hdev - > name ) ;
hdev - > stat . err_rx + + ;
}
2014-09-06 14:06:08 -05:00
} else if ( urb - > status = = - ENOENT ) {
/* Avoid suspend failed when usb_kill_urb */
return ;
2007-10-20 14:12:34 +02:00
}
if ( ! test_bit ( BTUSB_BULK_RUNNING , & data - > flags ) )
return ;
usb_anchor_urb ( urb , & data - > bulk_anchor ) ;
2009-12-16 19:23:43 +01:00
usb_mark_last_busy ( data - > udev ) ;
2007-10-20 14:12:34 +02:00
err = usb_submit_urb ( urb , GFP_ATOMIC ) ;
if ( err < 0 ) {
2011-08-09 17:16:28 +02:00
/* -EPERM: urb is being killed;
* - ENODEV : device got disconnected */
if ( err ! = - EPERM & & err ! = - ENODEV )
2010-11-30 21:49:08 +01:00
BT_ERR ( " %s urb %p failed to resubmit (%d) " ,
2014-09-16 04:44:50 +02:00
hdev - > name , urb , - err ) ;
2007-10-20 14:12:34 +02:00
usb_unanchor_urb ( urb ) ;
}
}
2008-11-30 12:17:10 +01:00
static int btusb_submit_bulk_urb ( struct hci_dev * hdev , gfp_t mem_flags )
2007-10-20 14:12:34 +02:00
{
2012-02-09 21:58:32 +01:00
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
2007-10-20 14:12:34 +02:00
struct urb * urb ;
unsigned char * buf ;
unsigned int pipe ;
2009-07-02 14:31:59 +05:30
int err , size = HCI_MAX_FRAME_SIZE ;
2007-10-20 14:12:34 +02:00
BT_DBG ( " %s " , hdev - > name ) ;
2008-08-18 13:23:52 +02:00
if ( ! data - > bulk_rx_ep )
return - ENODEV ;
2008-11-30 12:17:10 +01:00
urb = usb_alloc_urb ( 0 , mem_flags ) ;
2007-10-20 14:12:34 +02:00
if ( ! urb )
return - ENOMEM ;
2008-11-30 12:17:10 +01:00
buf = kmalloc ( size , mem_flags ) ;
2007-10-20 14:12:34 +02:00
if ( ! buf ) {
usb_free_urb ( urb ) ;
return - ENOMEM ;
}
pipe = usb_rcvbulkpipe ( data - > udev , data - > bulk_rx_ep - > bEndpointAddress ) ;
2014-09-16 04:44:50 +02:00
usb_fill_bulk_urb ( urb , data - > udev , pipe , buf , size ,
btusb_bulk_complete , hdev ) ;
2007-10-20 14:12:34 +02:00
urb - > transfer_flags | = URB_FREE_BUFFER ;
2009-08-24 23:44:59 +02:00
usb_mark_last_busy ( data - > udev ) ;
2007-10-20 14:12:34 +02:00
usb_anchor_urb ( urb , & data - > bulk_anchor ) ;
2008-11-30 12:17:10 +01:00
err = usb_submit_urb ( urb , mem_flags ) ;
2007-10-20 14:12:34 +02:00
if ( err < 0 ) {
2011-10-09 12:12:22 +02:00
if ( err ! = - EPERM & & err ! = - ENODEV )
BT_ERR ( " %s urb %p submission failed (%d) " ,
2014-09-16 04:44:50 +02:00
hdev - > name , urb , - err ) ;
2007-10-20 14:12:34 +02:00
usb_unanchor_urb ( urb ) ;
}
usb_free_urb ( urb ) ;
return err ;
}
2008-08-18 13:23:52 +02:00
static void btusb_isoc_complete ( struct urb * urb )
{
struct hci_dev * hdev = urb - > context ;
2012-02-09 21:58:32 +01:00
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
2008-08-18 13:23:52 +02:00
int i , err ;
2014-09-16 04:44:50 +02:00
BT_DBG ( " %s urb %p status %d count %d " , hdev - > name , urb , urb - > status ,
urb - > actual_length ) ;
2008-08-18 13:23:52 +02:00
if ( ! test_bit ( HCI_RUNNING , & hdev - > flags ) )
return ;
if ( urb - > status = = 0 ) {
for ( i = 0 ; i < urb - > number_of_packets ; i + + ) {
unsigned int offset = urb - > iso_frame_desc [ i ] . offset ;
unsigned int length = urb - > iso_frame_desc [ i ] . actual_length ;
if ( urb - > iso_frame_desc [ i ] . status )
continue ;
hdev - > stat . byte_rx + = length ;
2014-09-16 05:33:33 +02:00
if ( btusb_recv_isoc ( data , urb - > transfer_buffer + offset ,
length ) < 0 ) {
2008-08-18 13:23:52 +02:00
BT_ERR ( " %s corrupted SCO packet " , hdev - > name ) ;
hdev - > stat . err_rx + + ;
}
}
2014-09-06 14:06:08 -05:00
} else if ( urb - > status = = - ENOENT ) {
/* Avoid suspend failed when usb_kill_urb */
return ;
2008-08-18 13:23:52 +02:00
}
if ( ! test_bit ( BTUSB_ISOC_RUNNING , & data - > flags ) )
return ;
usb_anchor_urb ( urb , & data - > isoc_anchor ) ;
err = usb_submit_urb ( urb , GFP_ATOMIC ) ;
if ( err < 0 ) {
2011-08-09 17:16:28 +02:00
/* -EPERM: urb is being killed;
* - ENODEV : device got disconnected */
if ( err ! = - EPERM & & err ! = - ENODEV )
2010-11-30 21:49:08 +01:00
BT_ERR ( " %s urb %p failed to resubmit (%d) " ,
2014-09-16 04:44:50 +02:00
hdev - > name , urb , - err ) ;
2008-08-18 13:23:52 +02:00
usb_unanchor_urb ( urb ) ;
}
}
2011-01-17 00:09:38 +01:00
static inline void __fill_isoc_descriptor ( struct urb * urb , int len , int mtu )
2008-08-18 13:23:52 +02:00
{
int i , offset = 0 ;
BT_DBG ( " len %d mtu %d " , len , mtu ) ;
for ( i = 0 ; i < BTUSB_MAX_ISOC_FRAMES & & len > = mtu ;
i + + , offset + = mtu , len - = mtu ) {
urb - > iso_frame_desc [ i ] . offset = offset ;
urb - > iso_frame_desc [ i ] . length = mtu ;
}
if ( len & & i < BTUSB_MAX_ISOC_FRAMES ) {
urb - > iso_frame_desc [ i ] . offset = offset ;
urb - > iso_frame_desc [ i ] . length = len ;
i + + ;
}
urb - > number_of_packets = i ;
}
2008-11-30 12:17:10 +01:00
static int btusb_submit_isoc_urb ( struct hci_dev * hdev , gfp_t mem_flags )
2008-08-18 13:23:52 +02:00
{
2012-02-09 21:58:32 +01:00
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
2008-08-18 13:23:52 +02:00
struct urb * urb ;
unsigned char * buf ;
unsigned int pipe ;
int err , size ;
BT_DBG ( " %s " , hdev - > name ) ;
if ( ! data - > isoc_rx_ep )
return - ENODEV ;
2008-11-30 12:17:10 +01:00
urb = usb_alloc_urb ( BTUSB_MAX_ISOC_FRAMES , mem_flags ) ;
2008-08-18 13:23:52 +02:00
if ( ! urb )
return - ENOMEM ;
size = le16_to_cpu ( data - > isoc_rx_ep - > wMaxPacketSize ) *
BTUSB_MAX_ISOC_FRAMES ;
2008-11-30 12:17:10 +01:00
buf = kmalloc ( size , mem_flags ) ;
2008-08-18 13:23:52 +02:00
if ( ! buf ) {
usb_free_urb ( urb ) ;
return - ENOMEM ;
}
pipe = usb_rcvisocpipe ( data - > udev , data - > isoc_rx_ep - > bEndpointAddress ) ;
2011-12-20 18:19:00 -08:00
usb_fill_int_urb ( urb , data - > udev , pipe , buf , size , btusb_isoc_complete ,
2014-09-16 04:44:50 +02:00
hdev , data - > isoc_rx_ep - > bInterval ) ;
2008-08-18 13:23:52 +02:00
2014-09-16 04:44:50 +02:00
urb - > transfer_flags = URB_FREE_BUFFER | URB_ISO_ASAP ;
2008-08-18 13:23:52 +02:00
__fill_isoc_descriptor ( urb , size ,
2014-09-16 04:44:50 +02:00
le16_to_cpu ( data - > isoc_rx_ep - > wMaxPacketSize ) ) ;
2008-08-18 13:23:52 +02:00
usb_anchor_urb ( urb , & data - > isoc_anchor ) ;
2008-11-30 12:17:10 +01:00
err = usb_submit_urb ( urb , mem_flags ) ;
2008-08-18 13:23:52 +02:00
if ( err < 0 ) {
2011-10-09 12:12:22 +02:00
if ( err ! = - EPERM & & err ! = - ENODEV )
BT_ERR ( " %s urb %p submission failed (%d) " ,
2014-09-16 04:44:50 +02:00
hdev - > name , urb , - err ) ;
2008-08-18 13:23:52 +02:00
usb_unanchor_urb ( urb ) ;
}
usb_free_urb ( urb ) ;
return err ;
}
2007-10-20 14:12:34 +02:00
static void btusb_tx_complete ( struct urb * urb )
2009-08-24 23:44:59 +02:00
{
struct sk_buff * skb = urb - > context ;
2014-09-16 04:44:50 +02:00
struct hci_dev * hdev = ( struct hci_dev * ) skb - > dev ;
2012-02-09 21:58:32 +01:00
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
2009-08-24 23:44:59 +02:00
2014-09-16 04:44:50 +02:00
BT_DBG ( " %s urb %p status %d count %d " , hdev - > name , urb , urb - > status ,
urb - > actual_length ) ;
2009-08-24 23:44:59 +02:00
if ( ! test_bit ( HCI_RUNNING , & hdev - > flags ) )
goto done ;
if ( ! urb - > status )
hdev - > stat . byte_tx + = urb - > transfer_buffer_length ;
else
hdev - > stat . err_tx + + ;
done :
spin_lock ( & data - > txlock ) ;
data - > tx_in_flight - - ;
spin_unlock ( & data - > txlock ) ;
kfree ( urb - > setup_packet ) ;
kfree_skb ( skb ) ;
}
static void btusb_isoc_tx_complete ( struct urb * urb )
2007-10-20 14:12:34 +02:00
{
struct sk_buff * skb = urb - > context ;
2014-09-16 04:44:50 +02:00
struct hci_dev * hdev = ( struct hci_dev * ) skb - > dev ;
2007-10-20 14:12:34 +02:00
2014-09-16 04:44:50 +02:00
BT_DBG ( " %s urb %p status %d count %d " , hdev - > name , urb , urb - > status ,
urb - > actual_length ) ;
2007-10-20 14:12:34 +02:00
if ( ! test_bit ( HCI_RUNNING , & hdev - > flags ) )
goto done ;
if ( ! urb - > status )
hdev - > stat . byte_tx + = urb - > transfer_buffer_length ;
else
hdev - > stat . err_tx + + ;
done :
kfree ( urb - > setup_packet ) ;
kfree_skb ( skb ) ;
}
static int btusb_open ( struct hci_dev * hdev )
{
2012-02-09 21:58:32 +01:00
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
2007-10-20 14:12:34 +02:00
int err ;
BT_DBG ( " %s " , hdev - > name ) ;
2009-08-24 23:44:59 +02:00
err = usb_autopm_get_interface ( data - > intf ) ;
if ( err < 0 )
return err ;
data - > intf - > needs_remote_wakeup = 1 ;
2007-10-20 14:12:34 +02:00
if ( test_and_set_bit ( HCI_RUNNING , & hdev - > flags ) )
2009-08-24 23:44:59 +02:00
goto done ;
2007-10-20 14:12:34 +02:00
if ( test_and_set_bit ( BTUSB_INTR_RUNNING , & data - > flags ) )
2009-08-24 23:44:59 +02:00
goto done ;
2007-10-20 14:12:34 +02:00
2008-11-30 12:17:10 +01:00
err = btusb_submit_intr_urb ( hdev , GFP_KERNEL ) ;
2009-02-04 17:41:38 +01:00
if ( err < 0 )
goto failed ;
err = btusb_submit_bulk_urb ( hdev , GFP_KERNEL ) ;
2007-10-20 14:12:34 +02:00
if ( err < 0 ) {
2009-02-04 17:41:38 +01:00
usb_kill_anchored_urbs ( & data - > intr_anchor ) ;
goto failed ;
2007-10-20 14:12:34 +02:00
}
2009-02-04 17:41:38 +01:00
set_bit ( BTUSB_BULK_RUNNING , & data - > flags ) ;
btusb_submit_bulk_urb ( hdev , GFP_KERNEL ) ;
2009-08-24 23:44:59 +02:00
done :
usb_autopm_put_interface ( data - > intf ) ;
2009-02-04 17:41:38 +01:00
return 0 ;
failed :
clear_bit ( BTUSB_INTR_RUNNING , & data - > flags ) ;
clear_bit ( HCI_RUNNING , & hdev - > flags ) ;
2009-08-24 23:44:59 +02:00
usb_autopm_put_interface ( data - > intf ) ;
2007-10-20 14:12:34 +02:00
return err ;
}
2009-08-24 23:44:59 +02:00
static void btusb_stop_traffic ( struct btusb_data * data )
{
usb_kill_anchored_urbs ( & data - > intr_anchor ) ;
usb_kill_anchored_urbs ( & data - > bulk_anchor ) ;
usb_kill_anchored_urbs ( & data - > isoc_anchor ) ;
}
2007-10-20 14:12:34 +02:00
static int btusb_close ( struct hci_dev * hdev )
{
2012-02-09 21:58:32 +01:00
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
2009-08-24 23:44:59 +02:00
int err ;
2007-10-20 14:12:34 +02:00
BT_DBG ( " %s " , hdev - > name ) ;
if ( ! test_and_clear_bit ( HCI_RUNNING , & hdev - > flags ) )
return 0 ;
2008-09-23 00:16:36 +02:00
cancel_work_sync ( & data - > work ) ;
2009-11-11 13:32:29 -08:00
cancel_work_sync ( & data - > waker ) ;
2008-09-23 00:16:36 +02:00
2008-08-18 13:23:52 +02:00
clear_bit ( BTUSB_ISOC_RUNNING , & data - > flags ) ;
2007-10-20 14:12:34 +02:00
clear_bit ( BTUSB_BULK_RUNNING , & data - > flags ) ;
clear_bit ( BTUSB_INTR_RUNNING , & data - > flags ) ;
2009-08-24 23:44:59 +02:00
btusb_stop_traffic ( data ) ;
2014-09-16 08:00:29 +02:00
btusb_free_frags ( data ) ;
2009-08-24 23:44:59 +02:00
err = usb_autopm_get_interface ( data - > intf ) ;
if ( err < 0 )
2009-11-13 14:26:23 +01:00
goto failed ;
2009-08-24 23:44:59 +02:00
data - > intf - > needs_remote_wakeup = 0 ;
usb_autopm_put_interface ( data - > intf ) ;
2007-10-20 14:12:34 +02:00
2009-11-13 14:26:23 +01:00
failed :
usb_scuttle_anchored_urbs ( & data - > deferred ) ;
2007-10-20 14:12:34 +02:00
return 0 ;
}
static int btusb_flush ( struct hci_dev * hdev )
{
2012-02-09 21:58:32 +01:00
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
2007-10-20 14:12:34 +02:00
BT_DBG ( " %s " , hdev - > name ) ;
usb_kill_anchored_urbs ( & data - > tx_anchor ) ;
2014-09-16 08:00:29 +02:00
btusb_free_frags ( data ) ;
2007-10-20 14:12:34 +02:00
return 0 ;
}
2014-09-14 09:11:06 +02:00
static struct urb * alloc_ctrl_urb ( struct hci_dev * hdev , struct sk_buff * skb )
2007-10-20 14:12:34 +02:00
{
2012-02-09 21:58:32 +01:00
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
2007-10-20 14:12:34 +02:00
struct usb_ctrlrequest * dr ;
struct urb * urb ;
unsigned int pipe ;
2014-09-14 09:11:06 +02:00
urb = usb_alloc_urb ( 0 , GFP_KERNEL ) ;
if ( ! urb )
return ERR_PTR ( - ENOMEM ) ;
2007-10-20 14:12:34 +02:00
2014-09-14 09:11:06 +02:00
dr = kmalloc ( sizeof ( * dr ) , GFP_KERNEL ) ;
if ( ! dr ) {
usb_free_urb ( urb ) ;
return ERR_PTR ( - ENOMEM ) ;
}
2007-10-20 14:12:34 +02:00
2014-09-14 09:11:06 +02:00
dr - > bRequestType = data - > cmdreq_type ;
dr - > bRequest = 0 ;
dr - > wIndex = 0 ;
dr - > wValue = 0 ;
dr - > wLength = __cpu_to_le16 ( skb - > len ) ;
2013-10-11 06:19:18 -07:00
2014-09-14 09:11:06 +02:00
pipe = usb_sndctrlpipe ( data - > udev , 0x00 ) ;
2007-10-20 14:12:34 +02:00
2014-09-16 04:44:50 +02:00
usb_fill_control_urb ( urb , data - > udev , pipe , ( void * ) dr ,
2014-09-14 09:11:06 +02:00
skb - > data , skb - > len , btusb_tx_complete , skb ) ;
2007-10-20 14:12:34 +02:00
2014-09-16 04:44:50 +02:00
skb - > dev = ( void * ) hdev ;
2007-10-20 14:12:34 +02:00
2014-09-14 09:11:06 +02:00
return urb ;
}
2007-10-20 14:12:34 +02:00
2014-09-14 09:11:06 +02:00
static struct urb * alloc_bulk_urb ( struct hci_dev * hdev , struct sk_buff * skb )
{
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
struct urb * urb ;
unsigned int pipe ;
2007-10-20 14:12:34 +02:00
2014-09-14 09:11:06 +02:00
if ( ! data - > bulk_tx_ep )
return ERR_PTR ( - ENODEV ) ;
2008-08-18 13:23:52 +02:00
2014-09-14 09:11:06 +02:00
urb = usb_alloc_urb ( 0 , GFP_KERNEL ) ;
if ( ! urb )
return ERR_PTR ( - ENOMEM ) ;
2007-10-20 14:12:34 +02:00
2014-09-14 09:11:06 +02:00
pipe = usb_sndbulkpipe ( data - > udev , data - > bulk_tx_ep - > bEndpointAddress ) ;
2007-10-20 14:12:34 +02:00
2014-09-14 09:11:06 +02:00
usb_fill_bulk_urb ( urb , data - > udev , pipe ,
skb - > data , skb - > len , btusb_tx_complete , skb ) ;
2007-10-20 14:12:34 +02:00
2014-09-16 04:44:50 +02:00
skb - > dev = ( void * ) hdev ;
2007-10-20 14:12:34 +02:00
2014-09-14 09:11:06 +02:00
return urb ;
}
2008-08-18 13:23:52 +02:00
2014-09-14 09:11:06 +02:00
static struct urb * alloc_isoc_urb ( struct hci_dev * hdev , struct sk_buff * skb )
{
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
struct urb * urb ;
unsigned int pipe ;
2008-08-18 13:23:52 +02:00
2014-09-14 09:11:06 +02:00
if ( ! data - > isoc_tx_ep )
return ERR_PTR ( - ENODEV ) ;
2008-08-18 13:23:52 +02:00
2014-09-14 09:11:06 +02:00
urb = usb_alloc_urb ( BTUSB_MAX_ISOC_FRAMES , GFP_KERNEL ) ;
if ( ! urb )
return ERR_PTR ( - ENOMEM ) ;
2008-08-18 13:23:52 +02:00
2014-09-14 09:11:06 +02:00
pipe = usb_sndisocpipe ( data - > udev , data - > isoc_tx_ep - > bEndpointAddress ) ;
2008-08-18 13:23:52 +02:00
2014-09-14 09:11:06 +02:00
usb_fill_int_urb ( urb , data - > udev , pipe ,
skb - > data , skb - > len , btusb_isoc_tx_complete ,
skb , data - > isoc_tx_ep - > bInterval ) ;
2008-08-18 13:23:52 +02:00
2014-09-14 09:11:06 +02:00
urb - > transfer_flags = URB_ISO_ASAP ;
2007-10-20 14:12:34 +02:00
2014-09-14 09:11:06 +02:00
__fill_isoc_descriptor ( urb , skb - > len ,
le16_to_cpu ( data - > isoc_tx_ep - > wMaxPacketSize ) ) ;
2007-10-20 14:12:34 +02:00
2014-09-16 04:44:50 +02:00
skb - > dev = ( void * ) hdev ;
2014-09-14 09:11:06 +02:00
return urb ;
}
static int submit_tx_urb ( struct hci_dev * hdev , struct urb * urb )
{
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
int err ;
2009-08-24 23:44:59 +02:00
2007-10-20 14:12:34 +02:00
usb_anchor_urb ( urb , & data - > tx_anchor ) ;
2014-09-14 08:49:34 +03:00
err = usb_submit_urb ( urb , GFP_KERNEL ) ;
2007-10-20 14:12:34 +02:00
if ( err < 0 ) {
2011-10-09 12:12:16 +02:00
if ( err ! = - EPERM & & err ! = - ENODEV )
BT_ERR ( " %s urb %p submission failed (%d) " ,
2014-09-16 04:44:50 +02:00
hdev - > name , urb , - err ) ;
2007-10-20 14:12:34 +02:00
kfree ( urb - > setup_packet ) ;
usb_unanchor_urb ( urb ) ;
2009-08-24 23:44:59 +02:00
} else {
usb_mark_last_busy ( data - > udev ) ;
2007-10-20 14:12:34 +02:00
}
2011-11-22 09:32:57 +08:00
usb_free_urb ( urb ) ;
2007-10-20 14:12:34 +02:00
return err ;
}
2014-09-14 09:11:06 +02:00
static int submit_or_queue_tx_urb ( struct hci_dev * hdev , struct urb * urb )
{
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
unsigned long flags ;
bool suspending ;
spin_lock_irqsave ( & data - > txlock , flags ) ;
suspending = test_bit ( BTUSB_SUSPENDING , & data - > flags ) ;
if ( ! suspending )
data - > tx_in_flight + + ;
spin_unlock_irqrestore ( & data - > txlock , flags ) ;
if ( ! suspending )
return submit_tx_urb ( hdev , urb ) ;
usb_anchor_urb ( urb , & data - > deferred ) ;
schedule_work ( & data - > waker ) ;
usb_free_urb ( urb ) ;
return 0 ;
}
static int btusb_send_frame ( struct hci_dev * hdev , struct sk_buff * skb )
{
struct urb * urb ;
BT_DBG ( " %s " , hdev - > name ) ;
if ( ! test_bit ( HCI_RUNNING , & hdev - > flags ) )
return - EBUSY ;
switch ( bt_cb ( skb ) - > pkt_type ) {
case HCI_COMMAND_PKT :
urb = alloc_ctrl_urb ( hdev , skb ) ;
if ( IS_ERR ( urb ) )
return PTR_ERR ( urb ) ;
hdev - > stat . cmd_tx + + ;
return submit_or_queue_tx_urb ( hdev , urb ) ;
case HCI_ACLDATA_PKT :
urb = alloc_bulk_urb ( hdev , skb ) ;
if ( IS_ERR ( urb ) )
return PTR_ERR ( urb ) ;
hdev - > stat . acl_tx + + ;
return submit_or_queue_tx_urb ( hdev , urb ) ;
case HCI_SCODATA_PKT :
if ( hci_conn_num ( hdev , SCO_LINK ) < 1 )
return - ENODEV ;
urb = alloc_isoc_urb ( hdev , skb ) ;
if ( IS_ERR ( urb ) )
return PTR_ERR ( urb ) ;
hdev - > stat . sco_tx + + ;
return submit_tx_urb ( hdev , urb ) ;
}
return - EILSEQ ;
}
2007-10-20 14:12:34 +02:00
static void btusb_notify ( struct hci_dev * hdev , unsigned int evt )
{
2012-02-09 21:58:32 +01:00
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
2007-10-20 14:12:34 +02:00
BT_DBG ( " %s evt %d " , hdev - > name , evt ) ;
2013-10-10 09:47:55 -07:00
if ( hci_conn_num ( hdev , SCO_LINK ) ! = data - > sco_num ) {
data - > sco_num = hci_conn_num ( hdev , SCO_LINK ) ;
2009-02-04 17:41:38 +01:00
schedule_work ( & data - > work ) ;
2008-11-30 12:17:12 +01:00
}
2007-10-20 14:12:34 +02:00
}
2011-01-17 00:09:38 +01:00
static inline int __set_isoc_interface ( struct hci_dev * hdev , int altsetting )
2008-08-18 13:23:52 +02:00
{
2012-02-09 21:58:32 +01:00
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
2008-08-18 13:23:52 +02:00
struct usb_interface * intf = data - > isoc ;
struct usb_endpoint_descriptor * ep_desc ;
int i , err ;
if ( ! data - > isoc )
return - ENODEV ;
err = usb_set_interface ( data - > udev , 1 , altsetting ) ;
if ( err < 0 ) {
BT_ERR ( " %s setting interface failed (%d) " , hdev - > name , - err ) ;
return err ;
}
data - > isoc_altsetting = altsetting ;
data - > isoc_tx_ep = NULL ;
data - > isoc_rx_ep = NULL ;
for ( i = 0 ; i < intf - > cur_altsetting - > desc . bNumEndpoints ; i + + ) {
ep_desc = & intf - > cur_altsetting - > endpoint [ i ] . desc ;
if ( ! data - > isoc_tx_ep & & usb_endpoint_is_isoc_out ( ep_desc ) ) {
data - > isoc_tx_ep = ep_desc ;
continue ;
}
if ( ! data - > isoc_rx_ep & & usb_endpoint_is_isoc_in ( ep_desc ) ) {
data - > isoc_rx_ep = ep_desc ;
continue ;
}
}
if ( ! data - > isoc_tx_ep | | ! data - > isoc_rx_ep ) {
BT_ERR ( " %s invalid SCO descriptors " , hdev - > name ) ;
return - ENODEV ;
}
return 0 ;
}
2007-10-20 14:12:34 +02:00
static void btusb_work ( struct work_struct * work )
{
struct btusb_data * data = container_of ( work , struct btusb_data , work ) ;
struct hci_dev * hdev = data - > hdev ;
2012-04-11 08:48:51 +02:00
int new_alts ;
2009-08-24 23:44:59 +02:00
int err ;
2007-10-20 14:12:34 +02:00
2013-10-10 09:47:55 -07:00
if ( data - > sco_num > 0 ) {
2010-07-16 17:20:33 -03:00
if ( ! test_bit ( BTUSB_DID_ISO_RESUME , & data - > flags ) ) {
2011-02-11 13:00:06 +01:00
err = usb_autopm_get_interface ( data - > isoc ? data - > isoc : data - > intf ) ;
2009-08-24 23:44:59 +02:00
if ( err < 0 ) {
clear_bit ( BTUSB_ISOC_RUNNING , & data - > flags ) ;
usb_kill_anchored_urbs ( & data - > isoc_anchor ) ;
return ;
}
2010-07-16 17:20:33 -03:00
set_bit ( BTUSB_DID_ISO_RESUME , & data - > flags ) ;
2009-08-24 23:44:59 +02:00
}
2012-04-11 08:48:51 +02:00
if ( hdev - > voice_setting & 0x0020 ) {
static const int alts [ 3 ] = { 2 , 4 , 5 } ;
2014-09-16 04:44:50 +02:00
2013-10-10 09:47:55 -07:00
new_alts = alts [ data - > sco_num - 1 ] ;
2012-04-11 08:48:51 +02:00
} else {
2013-10-10 09:47:55 -07:00
new_alts = data - > sco_num ;
2012-04-11 08:48:51 +02:00
}
if ( data - > isoc_altsetting ! = new_alts ) {
2008-08-18 13:23:52 +02:00
clear_bit ( BTUSB_ISOC_RUNNING , & data - > flags ) ;
usb_kill_anchored_urbs ( & data - > isoc_anchor ) ;
2012-04-11 08:48:51 +02:00
if ( __set_isoc_interface ( hdev , new_alts ) < 0 )
2008-08-18 13:23:52 +02:00
return ;
}
if ( ! test_and_set_bit ( BTUSB_ISOC_RUNNING , & data - > flags ) ) {
2008-11-30 12:17:10 +01:00
if ( btusb_submit_isoc_urb ( hdev , GFP_KERNEL ) < 0 )
2008-08-18 13:23:52 +02:00
clear_bit ( BTUSB_ISOC_RUNNING , & data - > flags ) ;
else
2008-11-30 12:17:10 +01:00
btusb_submit_isoc_urb ( hdev , GFP_KERNEL ) ;
2008-08-18 13:23:52 +02:00
}
} else {
clear_bit ( BTUSB_ISOC_RUNNING , & data - > flags ) ;
usb_kill_anchored_urbs ( & data - > isoc_anchor ) ;
__set_isoc_interface ( hdev , 0 ) ;
2010-07-16 17:20:33 -03:00
if ( test_and_clear_bit ( BTUSB_DID_ISO_RESUME , & data - > flags ) )
2011-02-11 13:00:06 +01:00
usb_autopm_put_interface ( data - > isoc ? data - > isoc : data - > intf ) ;
2007-10-20 14:12:34 +02:00
}
}
2009-08-24 23:44:59 +02:00
static void btusb_waker ( struct work_struct * work )
{
struct btusb_data * data = container_of ( work , struct btusb_data , waker ) ;
int err ;
err = usb_autopm_get_interface ( data - > intf ) ;
if ( err < 0 )
return ;
usb_autopm_put_interface ( data - > intf ) ;
}
2013-04-10 08:11:35 -07:00
static int btusb_setup_bcm92035 ( struct hci_dev * hdev )
{
struct sk_buff * skb ;
u8 val = 0x00 ;
BT_DBG ( " %s " , hdev - > name ) ;
skb = __hci_cmd_sync ( hdev , 0xfc3b , 1 , & val , HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) )
BT_ERR ( " BCM92035 command failed (%ld) " , - PTR_ERR ( skb ) ) ;
else
kfree_skb ( skb ) ;
return 0 ;
}
2014-01-03 03:02:36 -08:00
static int btusb_setup_csr ( struct hci_dev * hdev )
{
struct hci_rp_read_local_version * rp ;
struct sk_buff * skb ;
int ret ;
BT_DBG ( " %s " , hdev - > name ) ;
skb = __hci_cmd_sync ( hdev , HCI_OP_READ_LOCAL_VERSION , 0 , NULL ,
HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) ) {
BT_ERR ( " Reading local version failed (%ld) " , - PTR_ERR ( skb ) ) ;
return - PTR_ERR ( skb ) ;
}
2014-09-16 04:44:50 +02:00
rp = ( struct hci_rp_read_local_version * ) skb - > data ;
2014-01-03 03:02:36 -08:00
if ( ! rp - > status ) {
if ( le16_to_cpu ( rp - > manufacturer ) ! = 10 ) {
/* Clear the reset quirk since this is not an actual
* early Bluetooth 1.1 device from CSR .
*/
clear_bit ( HCI_QUIRK_RESET_ON_CLOSE , & hdev - > quirks ) ;
/* These fake CSR controllers have all a broken
* stored link key handling and so just disable it .
*/
set_bit ( HCI_QUIRK_BROKEN_STORED_LINK_KEY ,
& hdev - > quirks ) ;
}
}
ret = - bt_to_errno ( rp - > status ) ;
kfree_skb ( skb ) ;
return ret ;
}
2013-04-19 09:57:43 -07:00
struct intel_version {
u8 status ;
u8 hw_platform ;
u8 hw_variant ;
u8 hw_revision ;
u8 fw_variant ;
u8 fw_revision ;
u8 fw_build_num ;
u8 fw_build_ww ;
u8 fw_build_yy ;
u8 fw_patch_num ;
} __packed ;
static const struct firmware * btusb_setup_intel_get_fw ( struct hci_dev * hdev ,
2014-09-16 04:44:50 +02:00
struct intel_version * ver )
2013-04-19 09:57:43 -07:00
{
const struct firmware * fw ;
char fwname [ 64 ] ;
int ret ;
snprintf ( fwname , sizeof ( fwname ) ,
" intel/ibt-hw-%x.%x.%x-fw-%x.%x.%x.%x.%x.bseq " ,
ver - > hw_platform , ver - > hw_variant , ver - > hw_revision ,
ver - > fw_variant , ver - > fw_revision , ver - > fw_build_num ,
ver - > fw_build_ww , ver - > fw_build_yy ) ;
ret = request_firmware ( & fw , fwname , & hdev - > dev ) ;
if ( ret < 0 ) {
if ( ret = = - EINVAL ) {
BT_ERR ( " %s Intel firmware file request failed (%d) " ,
hdev - > name , ret ) ;
return NULL ;
}
BT_ERR ( " %s failed to open Intel firmware file: %s(%d) " ,
hdev - > name , fwname , ret ) ;
/* If the correct firmware patch file is not found, use the
* default firmware patch file instead
*/
snprintf ( fwname , sizeof ( fwname ) , " intel/ibt-hw-%x.%x.bseq " ,
ver - > hw_platform , ver - > hw_variant ) ;
if ( request_firmware ( & fw , fwname , & hdev - > dev ) < 0 ) {
BT_ERR ( " %s failed to open default Intel fw file: %s " ,
hdev - > name , fwname ) ;
return NULL ;
}
}
BT_INFO ( " %s: Intel Bluetooth firmware file: %s " , hdev - > name , fwname ) ;
return fw ;
}
static int btusb_setup_intel_patching ( struct hci_dev * hdev ,
const struct firmware * fw ,
const u8 * * fw_ptr , int * disable_patch )
{
struct sk_buff * skb ;
struct hci_command_hdr * cmd ;
const u8 * cmd_param ;
struct hci_event_hdr * evt = NULL ;
const u8 * evt_param = NULL ;
int remain = fw - > size - ( * fw_ptr - fw - > data ) ;
/* The first byte indicates the types of the patch command or event.
* 0x01 means HCI command and 0x02 is HCI event . If the first bytes
* in the current firmware buffer doesn ' t start with 0x01 or
* the size of remain buffer is smaller than HCI command header ,
* the firmware file is corrupted and it should stop the patching
* process .
*/
if ( remain > HCI_COMMAND_HDR_SIZE & & * fw_ptr [ 0 ] ! = 0x01 ) {
BT_ERR ( " %s Intel fw corrupted: invalid cmd read " , hdev - > name ) ;
return - EINVAL ;
}
( * fw_ptr ) + + ;
remain - - ;
cmd = ( struct hci_command_hdr * ) ( * fw_ptr ) ;
* fw_ptr + = sizeof ( * cmd ) ;
remain - = sizeof ( * cmd ) ;
/* Ensure that the remain firmware data is long enough than the length
* of command parameter . If not , the firmware file is corrupted .
*/
if ( remain < cmd - > plen ) {
BT_ERR ( " %s Intel fw corrupted: invalid cmd len " , hdev - > name ) ;
return - EFAULT ;
}
/* If there is a command that loads a patch in the firmware
* file , then enable the patch upon success , otherwise just
* disable the manufacturer mode , for example patch activation
* is not required when the default firmware patch file is used
* because there are no patch data to load .
*/
if ( * disable_patch & & le16_to_cpu ( cmd - > opcode ) = = 0xfc8e )
* disable_patch = 0 ;
cmd_param = * fw_ptr ;
* fw_ptr + = cmd - > plen ;
remain - = cmd - > plen ;
/* This reads the expected events when the above command is sent to the
* device . Some vendor commands expects more than one events , for
* example command status event followed by vendor specific event .
* For this case , it only keeps the last expected event . so the command
* can be sent with __hci_cmd_sync_ev ( ) which returns the sk_buff of
* last expected event .
*/
while ( remain > HCI_EVENT_HDR_SIZE & & * fw_ptr [ 0 ] = = 0x02 ) {
( * fw_ptr ) + + ;
remain - - ;
evt = ( struct hci_event_hdr * ) ( * fw_ptr ) ;
* fw_ptr + = sizeof ( * evt ) ;
remain - = sizeof ( * evt ) ;
if ( remain < evt - > plen ) {
BT_ERR ( " %s Intel fw corrupted: invalid evt len " ,
hdev - > name ) ;
return - EFAULT ;
}
evt_param = * fw_ptr ;
* fw_ptr + = evt - > plen ;
remain - = evt - > plen ;
}
/* Every HCI commands in the firmware file has its correspond event.
* If event is not found or remain is smaller than zero , the firmware
* file is corrupted .
*/
if ( ! evt | | ! evt_param | | remain < 0 ) {
BT_ERR ( " %s Intel fw corrupted: invalid evt read " , hdev - > name ) ;
return - EFAULT ;
}
skb = __hci_cmd_sync_ev ( hdev , le16_to_cpu ( cmd - > opcode ) , cmd - > plen ,
cmd_param , evt - > evt , HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) ) {
BT_ERR ( " %s sending Intel patch command (0x%4.4x) failed (%ld) " ,
hdev - > name , cmd - > opcode , PTR_ERR ( skb ) ) ;
2013-07-10 10:02:12 +08:00
return PTR_ERR ( skb ) ;
2013-04-19 09:57:43 -07:00
}
/* It ensures that the returned event matches the event data read from
* the firmware file . At fist , it checks the length and then
* the contents of the event .
*/
if ( skb - > len ! = evt - > plen ) {
BT_ERR ( " %s mismatch event length (opcode 0x%4.4x) " , hdev - > name ,
le16_to_cpu ( cmd - > opcode ) ) ;
kfree_skb ( skb ) ;
return - EFAULT ;
}
if ( memcmp ( skb - > data , evt_param , evt - > plen ) ) {
BT_ERR ( " %s mismatch event parameter (opcode 0x%4.4x) " ,
hdev - > name , le16_to_cpu ( cmd - > opcode ) ) ;
kfree_skb ( skb ) ;
return - EFAULT ;
}
kfree_skb ( skb ) ;
return 0 ;
}
2014-07-02 12:06:45 +02:00
# define BDADDR_INTEL (&(bdaddr_t) {{0x00, 0x8b, 0x9e, 0x19, 0x03, 0x00}})
static int btusb_check_bdaddr_intel ( struct hci_dev * hdev )
{
struct sk_buff * skb ;
struct hci_rp_read_bd_addr * rp ;
skb = __hci_cmd_sync ( hdev , HCI_OP_READ_BD_ADDR , 0 , NULL ,
HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) ) {
BT_ERR ( " %s reading Intel device address failed (%ld) " ,
hdev - > name , PTR_ERR ( skb ) ) ;
return PTR_ERR ( skb ) ;
}
if ( skb - > len ! = sizeof ( * rp ) ) {
BT_ERR ( " %s Intel device address length mismatch " , hdev - > name ) ;
kfree_skb ( skb ) ;
return - EIO ;
}
2014-09-16 04:44:50 +02:00
rp = ( struct hci_rp_read_bd_addr * ) skb - > data ;
2014-07-02 12:06:45 +02:00
if ( rp - > status ) {
BT_ERR ( " %s Intel device address result failed (%02x) " ,
hdev - > name , rp - > status ) ;
kfree_skb ( skb ) ;
return - bt_to_errno ( rp - > status ) ;
}
/* For some Intel based controllers, the default Bluetooth device
* address 00 : 03 : 19 : 9 E : 8 B : 00 can be found . These controllers are
* fully operational , but have the danger of duplicate addresses
* and that in turn can cause problems with Bluetooth operation .
*/
2014-07-04 16:54:38 +02:00
if ( ! bacmp ( & rp - > bdaddr , BDADDR_INTEL ) ) {
2014-07-02 12:06:45 +02:00
BT_ERR ( " %s found Intel default device address (%pMR) " ,
hdev - > name , & rp - > bdaddr ) ;
2014-07-04 16:54:38 +02:00
set_bit ( HCI_QUIRK_INVALID_BDADDR , & hdev - > quirks ) ;
}
2014-07-02 12:06:45 +02:00
kfree_skb ( skb ) ;
return 0 ;
}
2013-04-19 09:57:43 -07:00
static int btusb_setup_intel ( struct hci_dev * hdev )
{
struct sk_buff * skb ;
const struct firmware * fw ;
const u8 * fw_ptr ;
int disable_patch ;
struct intel_version * ver ;
const u8 mfg_enable [ ] = { 0x01 , 0x00 } ;
const u8 mfg_disable [ ] = { 0x00 , 0x00 } ;
const u8 mfg_reset_deactivate [ ] = { 0x00 , 0x01 } ;
const u8 mfg_reset_activate [ ] = { 0x00 , 0x02 } ;
BT_DBG ( " %s " , hdev - > name ) ;
/* The controller has a bug with the first HCI command sent to it
* returning number of completed commands as zero . This would stall the
* command processing in the Bluetooth core .
*
* As a workaround , send HCI Reset command first which will reset the
* number of completed commands and allow normal command processing
* from now on .
*/
skb = __hci_cmd_sync ( hdev , HCI_OP_RESET , 0 , NULL , HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) ) {
BT_ERR ( " %s sending initial HCI reset command failed (%ld) " ,
hdev - > name , PTR_ERR ( skb ) ) ;
2013-07-10 10:02:12 +08:00
return PTR_ERR ( skb ) ;
2013-04-19 09:57:43 -07:00
}
kfree_skb ( skb ) ;
/* Read Intel specific controller version first to allow selection of
* which firmware file to load .
*
* The returned information are hardware variant and revision plus
* firmware variant , revision and build number .
*/
skb = __hci_cmd_sync ( hdev , 0xfc05 , 0 , NULL , HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) ) {
BT_ERR ( " %s reading Intel fw version command failed (%ld) " ,
hdev - > name , PTR_ERR ( skb ) ) ;
2013-07-10 10:02:12 +08:00
return PTR_ERR ( skb ) ;
2013-04-19 09:57:43 -07:00
}
if ( skb - > len ! = sizeof ( * ver ) ) {
BT_ERR ( " %s Intel version event length mismatch " , hdev - > name ) ;
kfree_skb ( skb ) ;
return - EIO ;
}
ver = ( struct intel_version * ) skb - > data ;
if ( ver - > status ) {
BT_ERR ( " %s Intel fw version event failed (%02x) " , hdev - > name ,
ver - > status ) ;
kfree_skb ( skb ) ;
return - bt_to_errno ( ver - > status ) ;
}
BT_INFO ( " %s: read Intel version: %02x%02x%02x%02x%02x%02x%02x%02x%02x " ,
hdev - > name , ver - > hw_platform , ver - > hw_variant ,
ver - > hw_revision , ver - > fw_variant , ver - > fw_revision ,
ver - > fw_build_num , ver - > fw_build_ww , ver - > fw_build_yy ,
ver - > fw_patch_num ) ;
/* fw_patch_num indicates the version of patch the device currently
* have . If there is no patch data in the device , it is always 0x00 .
* So , if it is other than 0x00 , no need to patch the deivce again .
*/
if ( ver - > fw_patch_num ) {
BT_INFO ( " %s: Intel device is already patched. patch num: %02x " ,
hdev - > name , ver - > fw_patch_num ) ;
kfree_skb ( skb ) ;
2014-07-02 12:06:45 +02:00
btusb_check_bdaddr_intel ( hdev ) ;
2013-04-19 09:57:43 -07:00
return 0 ;
}
/* Opens the firmware patch file based on the firmware version read
* from the controller . If it fails to open the matching firmware
* patch file , it tries to open the default firmware patch file .
* If no patch file is found , allow the device to operate without
* a patch .
*/
fw = btusb_setup_intel_get_fw ( hdev , ver ) ;
if ( ! fw ) {
kfree_skb ( skb ) ;
2014-07-02 12:06:45 +02:00
btusb_check_bdaddr_intel ( hdev ) ;
2013-04-19 09:57:43 -07:00
return 0 ;
}
fw_ptr = fw - > data ;
/* This Intel specific command enables the manufacturer mode of the
* controller .
*
* Only while this mode is enabled , the driver can download the
* firmware patch data and configuration parameters .
*/
skb = __hci_cmd_sync ( hdev , 0xfc11 , 2 , mfg_enable , HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) ) {
BT_ERR ( " %s entering Intel manufacturer mode failed (%ld) " ,
hdev - > name , PTR_ERR ( skb ) ) ;
release_firmware ( fw ) ;
2013-07-10 10:02:12 +08:00
return PTR_ERR ( skb ) ;
2013-04-19 09:57:43 -07:00
}
if ( skb - > data [ 0 ] ) {
u8 evt_status = skb - > data [ 0 ] ;
2014-09-16 04:44:50 +02:00
2013-04-19 09:57:43 -07:00
BT_ERR ( " %s enable Intel manufacturer mode event failed (%02x) " ,
hdev - > name , evt_status ) ;
kfree_skb ( skb ) ;
release_firmware ( fw ) ;
return - bt_to_errno ( evt_status ) ;
}
kfree_skb ( skb ) ;
disable_patch = 1 ;
/* The firmware data file consists of list of Intel specific HCI
* commands and its expected events . The first byte indicates the
* type of the message , either HCI command or HCI event .
*
* It reads the command and its expected event from the firmware file ,
* and send to the controller . Once __hci_cmd_sync_ev ( ) returns ,
* the returned event is compared with the event read from the firmware
* file and it will continue until all the messages are downloaded to
* the controller .
*
* Once the firmware patching is completed successfully ,
* the manufacturer mode is disabled with reset and activating the
* downloaded patch .
*
* If the firmware patching fails , the manufacturer mode is
* disabled with reset and deactivating the patch .
*
* If the default patch file is used , no reset is done when disabling
* the manufacturer .
*/
while ( fw - > size > fw_ptr - fw - > data ) {
int ret ;
ret = btusb_setup_intel_patching ( hdev , fw , & fw_ptr ,
& disable_patch ) ;
if ( ret < 0 )
goto exit_mfg_deactivate ;
}
release_firmware ( fw ) ;
if ( disable_patch )
goto exit_mfg_disable ;
/* Patching completed successfully and disable the manufacturer mode
* with reset and activate the downloaded firmware patches .
*/
skb = __hci_cmd_sync ( hdev , 0xfc11 , sizeof ( mfg_reset_activate ) ,
mfg_reset_activate , HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) ) {
BT_ERR ( " %s exiting Intel manufacturer mode failed (%ld) " ,
hdev - > name , PTR_ERR ( skb ) ) ;
2013-07-10 10:02:12 +08:00
return PTR_ERR ( skb ) ;
2013-04-19 09:57:43 -07:00
}
kfree_skb ( skb ) ;
BT_INFO ( " %s: Intel Bluetooth firmware patch completed and activated " ,
hdev - > name ) ;
2014-07-02 12:06:45 +02:00
btusb_check_bdaddr_intel ( hdev ) ;
2013-04-19 09:57:43 -07:00
return 0 ;
exit_mfg_disable :
/* Disable the manufacturer mode without reset */
skb = __hci_cmd_sync ( hdev , 0xfc11 , sizeof ( mfg_disable ) , mfg_disable ,
HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) ) {
BT_ERR ( " %s exiting Intel manufacturer mode failed (%ld) " ,
hdev - > name , PTR_ERR ( skb ) ) ;
2013-07-10 10:02:12 +08:00
return PTR_ERR ( skb ) ;
2013-04-19 09:57:43 -07:00
}
kfree_skb ( skb ) ;
BT_INFO ( " %s: Intel Bluetooth firmware patch completed " , hdev - > name ) ;
2014-07-02 12:06:45 +02:00
btusb_check_bdaddr_intel ( hdev ) ;
2013-04-19 09:57:43 -07:00
return 0 ;
exit_mfg_deactivate :
release_firmware ( fw ) ;
/* Patching failed. Disable the manufacturer mode with reset and
* deactivate the downloaded firmware patches .
*/
skb = __hci_cmd_sync ( hdev , 0xfc11 , sizeof ( mfg_reset_deactivate ) ,
mfg_reset_deactivate , HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) ) {
BT_ERR ( " %s exiting Intel manufacturer mode failed (%ld) " ,
hdev - > name , PTR_ERR ( skb ) ) ;
2013-07-10 10:02:12 +08:00
return PTR_ERR ( skb ) ;
2013-04-19 09:57:43 -07:00
}
kfree_skb ( skb ) ;
BT_INFO ( " %s: Intel Bluetooth firmware patch completed and deactivated " ,
hdev - > name ) ;
2014-07-02 12:06:45 +02:00
btusb_check_bdaddr_intel ( hdev ) ;
2013-04-19 09:57:43 -07:00
return 0 ;
}
2014-07-02 11:25:25 +02:00
static int btusb_set_bdaddr_intel ( struct hci_dev * hdev , const bdaddr_t * bdaddr )
{
struct sk_buff * skb ;
long ret ;
skb = __hci_cmd_sync ( hdev , 0xfc31 , 6 , bdaddr , HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) ) {
ret = PTR_ERR ( skb ) ;
BT_ERR ( " %s: changing Intel device address failed (%ld) " ,
2014-09-16 04:44:50 +02:00
hdev - > name , ret ) ;
2014-07-02 11:25:25 +02:00
return ret ;
}
kfree_skb ( skb ) ;
return 0 ;
}
2014-07-18 14:47:06 -07:00
static int btusb_set_bdaddr_marvell ( struct hci_dev * hdev ,
const bdaddr_t * bdaddr )
{
struct sk_buff * skb ;
u8 buf [ 8 ] ;
long ret ;
buf [ 0 ] = 0xfe ;
buf [ 1 ] = sizeof ( bdaddr_t ) ;
memcpy ( buf + 2 , bdaddr , sizeof ( bdaddr_t ) ) ;
skb = __hci_cmd_sync ( hdev , 0xfc22 , sizeof ( buf ) , buf , HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) ) {
ret = PTR_ERR ( skb ) ;
BT_ERR ( " %s: changing Marvell device address failed (%ld) " ,
hdev - > name , ret ) ;
return ret ;
}
kfree_skb ( skb ) ;
return 0 ;
}
2014-07-02 12:38:22 +02:00
# define BDADDR_BCM20702A0 (&(bdaddr_t) {{0x00, 0xa0, 0x02, 0x70, 0x20, 0x00}})
2014-05-08 15:50:01 -07:00
static int btusb_setup_bcm_patchram ( struct hci_dev * hdev )
{
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
struct usb_device * udev = data - > udev ;
char fw_name [ 64 ] ;
const struct firmware * fw ;
const u8 * fw_ptr ;
size_t fw_size ;
const struct hci_command_hdr * cmd ;
const u8 * cmd_param ;
u16 opcode ;
struct sk_buff * skb ;
struct hci_rp_read_local_version * ver ;
2014-07-02 12:38:22 +02:00
struct hci_rp_read_bd_addr * bda ;
2014-05-08 15:50:01 -07:00
long ret ;
snprintf ( fw_name , sizeof ( fw_name ) , " brcm/%s-%04x-%04x.hcd " ,
udev - > product ? udev - > product : " BCM " ,
le16_to_cpu ( udev - > descriptor . idVendor ) ,
le16_to_cpu ( udev - > descriptor . idProduct ) ) ;
ret = request_firmware ( & fw , fw_name , & hdev - > dev ) ;
if ( ret < 0 ) {
2014-07-02 12:38:22 +02:00
BT_INFO ( " %s: BCM: patch %s not found " , hdev - > name , fw_name ) ;
2014-05-08 15:50:01 -07:00
return 0 ;
}
/* Reset */
skb = __hci_cmd_sync ( hdev , HCI_OP_RESET , 0 , NULL , HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) ) {
ret = PTR_ERR ( skb ) ;
BT_ERR ( " %s: HCI_OP_RESET failed (%ld) " , hdev - > name , ret ) ;
goto done ;
}
kfree_skb ( skb ) ;
/* Read Local Version Info */
skb = __hci_cmd_sync ( hdev , HCI_OP_READ_LOCAL_VERSION , 0 , NULL ,
HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) ) {
ret = PTR_ERR ( skb ) ;
BT_ERR ( " %s: HCI_OP_READ_LOCAL_VERSION failed (%ld) " ,
2014-09-16 04:44:50 +02:00
hdev - > name , ret ) ;
2014-05-08 15:50:01 -07:00
goto done ;
}
if ( skb - > len ! = sizeof ( * ver ) ) {
BT_ERR ( " %s: HCI_OP_READ_LOCAL_VERSION event length mismatch " ,
2014-09-16 04:44:50 +02:00
hdev - > name ) ;
2014-05-08 15:50:01 -07:00
kfree_skb ( skb ) ;
ret = - EIO ;
goto done ;
}
2014-09-16 04:44:50 +02:00
ver = ( struct hci_rp_read_local_version * ) skb - > data ;
2014-05-08 15:50:01 -07:00
BT_INFO ( " %s: BCM: patching hci_ver=%02x hci_rev=%04x lmp_ver=%02x "
" lmp_subver=%04x " , hdev - > name , ver - > hci_ver , ver - > hci_rev ,
ver - > lmp_ver , ver - > lmp_subver ) ;
kfree_skb ( skb ) ;
/* Start Download */
skb = __hci_cmd_sync ( hdev , 0xfc2e , 0 , NULL , HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) ) {
ret = PTR_ERR ( skb ) ;
BT_ERR ( " %s: BCM: Download Minidrv command failed (%ld) " ,
2014-09-16 04:44:50 +02:00
hdev - > name , ret ) ;
2014-05-08 15:50:01 -07:00
goto reset_fw ;
}
kfree_skb ( skb ) ;
/* 50 msec delay after Download Minidrv completes */
msleep ( 50 ) ;
fw_ptr = fw - > data ;
fw_size = fw - > size ;
while ( fw_size > = sizeof ( * cmd ) ) {
2014-09-16 04:44:50 +02:00
cmd = ( struct hci_command_hdr * ) fw_ptr ;
2014-05-08 15:50:01 -07:00
fw_ptr + = sizeof ( * cmd ) ;
fw_size - = sizeof ( * cmd ) ;
if ( fw_size < cmd - > plen ) {
BT_ERR ( " %s: BCM: patch %s is corrupted " ,
2014-09-16 04:44:50 +02:00
hdev - > name , fw_name ) ;
2014-05-08 15:50:01 -07:00
ret = - EINVAL ;
goto reset_fw ;
}
cmd_param = fw_ptr ;
fw_ptr + = cmd - > plen ;
fw_size - = cmd - > plen ;
opcode = le16_to_cpu ( cmd - > opcode ) ;
skb = __hci_cmd_sync ( hdev , opcode , cmd - > plen , cmd_param ,
HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) ) {
ret = PTR_ERR ( skb ) ;
BT_ERR ( " %s: BCM: patch command %04x failed (%ld) " ,
2014-09-16 04:44:50 +02:00
hdev - > name , opcode , ret ) ;
2014-05-08 15:50:01 -07:00
goto reset_fw ;
}
kfree_skb ( skb ) ;
}
/* 250 msec delay after Launch Ram completes */
msleep ( 250 ) ;
reset_fw :
/* Reset */
skb = __hci_cmd_sync ( hdev , HCI_OP_RESET , 0 , NULL , HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) ) {
ret = PTR_ERR ( skb ) ;
BT_ERR ( " %s: HCI_OP_RESET failed (%ld) " , hdev - > name , ret ) ;
goto done ;
}
kfree_skb ( skb ) ;
/* Read Local Version Info */
skb = __hci_cmd_sync ( hdev , HCI_OP_READ_LOCAL_VERSION , 0 , NULL ,
HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) ) {
ret = PTR_ERR ( skb ) ;
BT_ERR ( " %s: HCI_OP_READ_LOCAL_VERSION failed (%ld) " ,
2014-09-16 04:44:50 +02:00
hdev - > name , ret ) ;
2014-05-08 15:50:01 -07:00
goto done ;
}
if ( skb - > len ! = sizeof ( * ver ) ) {
BT_ERR ( " %s: HCI_OP_READ_LOCAL_VERSION event length mismatch " ,
2014-09-16 04:44:50 +02:00
hdev - > name ) ;
2014-05-08 15:50:01 -07:00
kfree_skb ( skb ) ;
ret = - EIO ;
goto done ;
}
2014-09-16 04:44:50 +02:00
ver = ( struct hci_rp_read_local_version * ) skb - > data ;
2014-05-08 15:50:01 -07:00
BT_INFO ( " %s: BCM: firmware hci_ver=%02x hci_rev=%04x lmp_ver=%02x "
" lmp_subver=%04x " , hdev - > name , ver - > hci_ver , ver - > hci_rev ,
ver - > lmp_ver , ver - > lmp_subver ) ;
kfree_skb ( skb ) ;
2014-07-02 12:38:22 +02:00
/* Read BD Address */
skb = __hci_cmd_sync ( hdev , HCI_OP_READ_BD_ADDR , 0 , NULL ,
HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) ) {
ret = PTR_ERR ( skb ) ;
BT_ERR ( " %s: HCI_OP_READ_BD_ADDR failed (%ld) " ,
2014-09-16 04:44:50 +02:00
hdev - > name , ret ) ;
2014-07-02 12:38:22 +02:00
goto done ;
}
if ( skb - > len ! = sizeof ( * bda ) ) {
BT_ERR ( " %s: HCI_OP_READ_BD_ADDR event length mismatch " ,
2014-09-16 04:44:50 +02:00
hdev - > name ) ;
2014-07-02 12:38:22 +02:00
kfree_skb ( skb ) ;
ret = - EIO ;
goto done ;
}
2014-09-16 04:44:50 +02:00
bda = ( struct hci_rp_read_bd_addr * ) skb - > data ;
2014-07-02 12:38:22 +02:00
if ( bda - > status ) {
BT_ERR ( " %s: HCI_OP_READ_BD_ADDR error status (%02x) " ,
hdev - > name , bda - > status ) ;
kfree_skb ( skb ) ;
ret = - bt_to_errno ( bda - > status ) ;
goto done ;
}
/* The address 00:20:70:02:A0:00 indicates a BCM20702A0 controller
* with no configured address .
*/
2014-07-04 16:54:39 +02:00
if ( ! bacmp ( & bda - > bdaddr , BDADDR_BCM20702A0 ) ) {
2014-07-02 12:38:22 +02:00
BT_INFO ( " %s: BCM: using default device address (%pMR) " ,
hdev - > name , & bda - > bdaddr ) ;
2014-07-04 16:54:39 +02:00
set_bit ( HCI_QUIRK_INVALID_BDADDR , & hdev - > quirks ) ;
}
2014-07-02 12:38:22 +02:00
kfree_skb ( skb ) ;
2014-05-08 15:50:01 -07:00
done :
release_firmware ( fw ) ;
return ret ;
}
2014-07-02 00:53:48 +02:00
static int btusb_set_bdaddr_bcm ( struct hci_dev * hdev , const bdaddr_t * bdaddr )
{
struct sk_buff * skb ;
long ret ;
skb = __hci_cmd_sync ( hdev , 0xfc01 , 6 , bdaddr , HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) ) {
ret = PTR_ERR ( skb ) ;
BT_ERR ( " %s: BCM: Change address command failed (%ld) " ,
2014-09-16 04:44:50 +02:00
hdev - > name , ret ) ;
2014-07-02 00:53:48 +02:00
return ret ;
}
kfree_skb ( skb ) ;
return 0 ;
}
2014-12-12 10:58:05 -08:00
static int btusb_set_bdaddr_ath3012 ( struct hci_dev * hdev ,
const bdaddr_t * bdaddr )
{
struct sk_buff * skb ;
u8 buf [ 10 ] ;
long ret ;
buf [ 0 ] = 0x01 ;
buf [ 1 ] = 0x01 ;
buf [ 2 ] = 0x00 ;
buf [ 3 ] = sizeof ( bdaddr_t ) ;
memcpy ( buf + 4 , bdaddr , sizeof ( bdaddr_t ) ) ;
skb = __hci_cmd_sync ( hdev , 0xfc0b , sizeof ( buf ) , buf , HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) ) {
ret = PTR_ERR ( skb ) ;
BT_ERR ( " %s: Change address command failed (%ld) " ,
hdev - > name , ret ) ;
return ret ;
}
kfree_skb ( skb ) ;
return 0 ;
}
2007-10-20 14:12:34 +02:00
static int btusb_probe ( struct usb_interface * intf ,
2014-09-16 04:44:50 +02:00
const struct usb_device_id * id )
2007-10-20 14:12:34 +02:00
{
struct usb_endpoint_descriptor * ep_desc ;
struct btusb_data * data ;
struct hci_dev * hdev ;
int i , err ;
BT_DBG ( " intf %p id %p " , intf , id ) ;
2008-08-07 22:26:56 +02:00
/* interface numbers are hardcoded in the spec */
2007-10-20 14:12:34 +02:00
if ( intf - > cur_altsetting - > desc . bInterfaceNumber ! = 0 )
return - ENODEV ;
if ( ! id - > driver_info ) {
const struct usb_device_id * match ;
2014-09-16 04:44:50 +02:00
2007-10-20 14:12:34 +02:00
match = usb_match_id ( intf , blacklist_table ) ;
if ( match )
id = match ;
}
2008-08-07 22:26:56 +02:00
if ( id - > driver_info = = BTUSB_IGNORE )
return - ENODEV ;
2011-07-01 14:02:36 +08:00
if ( id - > driver_info & BTUSB_ATH3012 ) {
struct usb_device * udev = interface_to_usbdev ( intf ) ;
/* Old firmware would otherwise let ath3k driver load
* patch and sysconfig files */
if ( le16_to_cpu ( udev - > descriptor . bcdDevice ) < = 0x0001 )
return - ENODEV ;
}
2012-07-27 12:38:39 +05:30
data = devm_kzalloc ( & intf - > dev , sizeof ( * data ) , GFP_KERNEL ) ;
2007-10-20 14:12:34 +02:00
if ( ! data )
return - ENOMEM ;
for ( i = 0 ; i < intf - > cur_altsetting - > desc . bNumEndpoints ; i + + ) {
ep_desc = & intf - > cur_altsetting - > endpoint [ i ] . desc ;
if ( ! data - > intr_ep & & usb_endpoint_is_int_in ( ep_desc ) ) {
data - > intr_ep = ep_desc ;
continue ;
}
if ( ! data - > bulk_tx_ep & & usb_endpoint_is_bulk_out ( ep_desc ) ) {
data - > bulk_tx_ep = ep_desc ;
continue ;
}
if ( ! data - > bulk_rx_ep & & usb_endpoint_is_bulk_in ( ep_desc ) ) {
data - > bulk_rx_ep = ep_desc ;
continue ;
}
}
2012-07-27 12:38:39 +05:30
if ( ! data - > intr_ep | | ! data - > bulk_tx_ep | | ! data - > bulk_rx_ep )
2007-10-20 14:12:34 +02:00
return - ENODEV ;
2008-11-30 12:17:26 +01:00
data - > cmdreq_type = USB_TYPE_CLASS ;
2007-10-20 14:12:34 +02:00
data - > udev = interface_to_usbdev ( intf ) ;
2008-09-23 00:16:36 +02:00
data - > intf = intf ;
2007-10-20 14:12:34 +02:00
INIT_WORK ( & data - > work , btusb_work ) ;
2009-08-24 23:44:59 +02:00
INIT_WORK ( & data - > waker , btusb_waker ) ;
2014-09-16 08:00:29 +02:00
init_usb_anchor ( & data - > deferred ) ;
init_usb_anchor ( & data - > tx_anchor ) ;
2009-08-24 23:44:59 +02:00
spin_lock_init ( & data - > txlock ) ;
2007-10-20 14:12:34 +02:00
init_usb_anchor ( & data - > intr_anchor ) ;
init_usb_anchor ( & data - > bulk_anchor ) ;
2008-08-18 13:23:52 +02:00
init_usb_anchor ( & data - > isoc_anchor ) ;
2014-09-16 08:00:29 +02:00
spin_lock_init ( & data - > rxlock ) ;
2007-10-20 14:12:34 +02:00
2014-11-03 05:16:07 +01:00
data - > recv_bulk = btusb_recv_bulk ;
2007-10-20 14:12:34 +02:00
hdev = hci_alloc_dev ( ) ;
2012-07-27 12:38:39 +05:30
if ( ! hdev )
2007-10-20 14:12:34 +02:00
return - ENOMEM ;
2010-02-08 15:27:07 +01:00
hdev - > bus = HCI_USB ;
2012-02-09 21:58:32 +01:00
hci_set_drvdata ( hdev , data ) ;
2007-10-20 14:12:34 +02:00
data - > hdev = hdev ;
SET_HCIDEV_DEV ( hdev , & intf - > dev ) ;
2013-04-10 08:11:35 -07:00
hdev - > open = btusb_open ;
hdev - > close = btusb_close ;
hdev - > flush = btusb_flush ;
hdev - > send = btusb_send_frame ;
hdev - > notify = btusb_notify ;
if ( id - > driver_info & BTUSB_BCM92035 )
hdev - > setup = btusb_setup_bcm92035 ;
2007-10-20 14:12:34 +02:00
2014-07-02 00:53:48 +02:00
if ( id - > driver_info & BTUSB_BCM_PATCHRAM ) {
2014-05-08 15:50:01 -07:00
hdev - > setup = btusb_setup_bcm_patchram ;
2014-07-02 00:53:48 +02:00
hdev - > set_bdaddr = btusb_set_bdaddr_bcm ;
2014-11-02 20:52:24 +01:00
set_bit ( HCI_QUIRK_STRICT_DUPLICATE_FILTER , & hdev - > quirks ) ;
2014-07-02 00:53:48 +02:00
}
2014-05-08 15:50:01 -07:00
2014-07-02 11:25:25 +02:00
if ( id - > driver_info & BTUSB_INTEL ) {
2013-04-19 09:57:43 -07:00
hdev - > setup = btusb_setup_intel ;
2014-07-02 11:25:25 +02:00
hdev - > set_bdaddr = btusb_set_bdaddr_intel ;
}
2013-04-19 09:57:43 -07:00
2014-07-18 14:47:06 -07:00
if ( id - > driver_info & BTUSB_MARVELL )
hdev - > set_bdaddr = btusb_set_bdaddr_marvell ;
2015-01-01 17:34:37 -08:00
if ( id - > driver_info & BTUSB_SWAVE )
2014-12-26 04:42:33 +01:00
set_bit ( HCI_QUIRK_BROKEN_LOCAL_COMMANDS , & hdev - > quirks ) ;
2014-07-06 13:29:58 +02:00
if ( id - > driver_info & BTUSB_INTEL_BOOT )
set_bit ( HCI_QUIRK_RAW_DEVICE , & hdev - > quirks ) ;
2014-12-12 10:58:05 -08:00
if ( id - > driver_info & BTUSB_ATH3012 )
hdev - > set_bdaddr = btusb_set_bdaddr_ath3012 ;
2008-11-30 12:17:26 +01:00
/* Interface numbers are hardcoded in the specification */
2008-08-18 13:23:52 +02:00
data - > isoc = usb_ifnum_to_if ( data - > udev , 1 ) ;
2008-11-30 12:17:26 +01:00
if ( ! reset )
2012-05-23 12:35:46 +02:00
set_bit ( HCI_QUIRK_RESET_ON_CLOSE , & hdev - > quirks ) ;
2008-08-07 22:26:56 +02:00
if ( force_scofix | | id - > driver_info & BTUSB_WRONG_SCO_MTU ) {
if ( ! disable_scofix )
set_bit ( HCI_QUIRK_FIXUP_BUFFER_SIZE , & hdev - > quirks ) ;
}
2008-08-18 13:23:52 +02:00
if ( id - > driver_info & BTUSB_BROKEN_ISOC )
data - > isoc = NULL ;
2008-11-30 12:17:26 +01:00
if ( id - > driver_info & BTUSB_DIGIANSWER ) {
data - > cmdreq_type = USB_TYPE_VENDOR ;
2012-05-23 12:35:46 +02:00
set_bit ( HCI_QUIRK_RESET_ON_CLOSE , & hdev - > quirks ) ;
2008-11-30 12:17:26 +01:00
}
if ( id - > driver_info & BTUSB_CSR ) {
struct usb_device * udev = data - > udev ;
2014-01-03 03:02:36 -08:00
u16 bcdDevice = le16_to_cpu ( udev - > descriptor . bcdDevice ) ;
2008-11-30 12:17:26 +01:00
/* Old firmware would otherwise execute USB reset */
2014-01-03 03:02:36 -08:00
if ( bcdDevice < 0x117 )
2012-05-23 12:35:46 +02:00
set_bit ( HCI_QUIRK_RESET_ON_CLOSE , & hdev - > quirks ) ;
2014-01-03 03:02:36 -08:00
/* Fake CSR devices with broken commands */
if ( bcdDevice < = 0x100 )
hdev - > setup = btusb_setup_csr ;
2008-11-30 12:17:26 +01:00
}
2008-08-07 22:26:56 +02:00
if ( id - > driver_info & BTUSB_SNIFFER ) {
2008-08-18 13:23:52 +02:00
struct usb_device * udev = data - > udev ;
2008-08-07 22:26:56 +02:00
2008-11-30 12:17:26 +01:00
/* New sniffer firmware has crippled HCI interface */
2008-08-07 22:26:56 +02:00
if ( le16_to_cpu ( udev - > descriptor . bcdDevice ) > 0x997 )
set_bit ( HCI_QUIRK_RAW_DEVICE , & hdev - > quirks ) ;
}
2014-07-06 14:53:54 +02:00
if ( id - > driver_info & BTUSB_INTEL_BOOT ) {
/* A bug in the bootloader causes that interrupt interface is
* only enabled after receiving SetInterface ( 0 , AltSetting = 0 ) .
*/
err = usb_set_interface ( data - > udev , 0 , 0 ) ;
if ( err < 0 ) {
BT_ERR ( " failed to set interface 0, alt 0 %d " , err ) ;
hci_free_dev ( hdev ) ;
return err ;
}
}
2008-08-18 13:23:52 +02:00
if ( data - > isoc ) {
err = usb_driver_claim_interface ( & btusb_driver ,
2014-09-16 04:44:50 +02:00
data - > isoc , data ) ;
2008-08-18 13:23:52 +02:00
if ( err < 0 ) {
hci_free_dev ( hdev ) ;
return err ;
}
}
2007-10-20 14:12:34 +02:00
err = hci_register_dev ( hdev ) ;
if ( err < 0 ) {
hci_free_dev ( hdev ) ;
return err ;
}
usb_set_intfdata ( intf , data ) ;
return 0 ;
}
static void btusb_disconnect ( struct usb_interface * intf )
{
struct btusb_data * data = usb_get_intfdata ( intf ) ;
struct hci_dev * hdev ;
BT_DBG ( " intf %p " , intf ) ;
if ( ! data )
return ;
hdev = data - > hdev ;
2008-09-23 00:16:36 +02:00
usb_set_intfdata ( data - > intf , NULL ) ;
if ( data - > isoc )
usb_set_intfdata ( data - > isoc , NULL ) ;
2007-10-20 14:12:34 +02:00
hci_unregister_dev ( hdev ) ;
2008-09-23 00:16:36 +02:00
if ( intf = = data - > isoc )
usb_driver_release_interface ( & btusb_driver , data - > intf ) ;
else if ( data - > isoc )
usb_driver_release_interface ( & btusb_driver , data - > isoc ) ;
2014-09-16 08:00:29 +02:00
btusb_free_frags ( data ) ;
2007-10-20 14:12:34 +02:00
hci_free_dev ( hdev ) ;
}
2009-08-24 23:44:59 +02:00
# ifdef CONFIG_PM
2008-11-30 12:17:14 +01:00
static int btusb_suspend ( struct usb_interface * intf , pm_message_t message )
{
struct btusb_data * data = usb_get_intfdata ( intf ) ;
BT_DBG ( " intf %p " , intf ) ;
if ( data - > suspend_count + + )
return 0 ;
2009-08-24 23:44:59 +02:00
spin_lock_irq ( & data - > txlock ) ;
2011-08-19 23:49:48 +02:00
if ( ! ( PMSG_IS_AUTO ( message ) & & data - > tx_in_flight ) ) {
2009-08-24 23:44:59 +02:00
set_bit ( BTUSB_SUSPENDING , & data - > flags ) ;
spin_unlock_irq ( & data - > txlock ) ;
} else {
spin_unlock_irq ( & data - > txlock ) ;
data - > suspend_count - - ;
return - EBUSY ;
}
2008-11-30 12:17:14 +01:00
cancel_work_sync ( & data - > work ) ;
2009-08-24 23:44:59 +02:00
btusb_stop_traffic ( data ) ;
2008-11-30 12:17:14 +01:00
usb_kill_anchored_urbs ( & data - > tx_anchor ) ;
return 0 ;
}
2009-08-24 23:44:59 +02:00
static void play_deferred ( struct btusb_data * data )
{
struct urb * urb ;
int err ;
while ( ( urb = usb_get_from_anchor ( & data - > deferred ) ) ) {
err = usb_submit_urb ( urb , GFP_ATOMIC ) ;
if ( err < 0 )
break ;
data - > tx_in_flight + + ;
}
usb_scuttle_anchored_urbs ( & data - > deferred ) ;
}
2008-11-30 12:17:14 +01:00
static int btusb_resume ( struct usb_interface * intf )
{
struct btusb_data * data = usb_get_intfdata ( intf ) ;
struct hci_dev * hdev = data - > hdev ;
2009-08-24 23:44:59 +02:00
int err = 0 ;
2008-11-30 12:17:14 +01:00
BT_DBG ( " intf %p " , intf ) ;
if ( - - data - > suspend_count )
return 0 ;
if ( ! test_bit ( HCI_RUNNING , & hdev - > flags ) )
2009-08-24 23:44:59 +02:00
goto done ;
2008-11-30 12:17:14 +01:00
if ( test_bit ( BTUSB_INTR_RUNNING , & data - > flags ) ) {
err = btusb_submit_intr_urb ( hdev , GFP_NOIO ) ;
if ( err < 0 ) {
clear_bit ( BTUSB_INTR_RUNNING , & data - > flags ) ;
2009-08-24 23:44:59 +02:00
goto failed ;
2008-11-30 12:17:14 +01:00
}
}
if ( test_bit ( BTUSB_BULK_RUNNING , & data - > flags ) ) {
2009-02-04 17:41:38 +01:00
err = btusb_submit_bulk_urb ( hdev , GFP_NOIO ) ;
if ( err < 0 ) {
2008-11-30 12:17:14 +01:00
clear_bit ( BTUSB_BULK_RUNNING , & data - > flags ) ;
2009-08-24 23:44:59 +02:00
goto failed ;
}
btusb_submit_bulk_urb ( hdev , GFP_NOIO ) ;
2008-11-30 12:17:14 +01:00
}
if ( test_bit ( BTUSB_ISOC_RUNNING , & data - > flags ) ) {
if ( btusb_submit_isoc_urb ( hdev , GFP_NOIO ) < 0 )
clear_bit ( BTUSB_ISOC_RUNNING , & data - > flags ) ;
else
btusb_submit_isoc_urb ( hdev , GFP_NOIO ) ;
}
2009-08-24 23:44:59 +02:00
spin_lock_irq ( & data - > txlock ) ;
play_deferred ( data ) ;
clear_bit ( BTUSB_SUSPENDING , & data - > flags ) ;
spin_unlock_irq ( & data - > txlock ) ;
schedule_work ( & data - > work ) ;
2008-11-30 12:17:14 +01:00
return 0 ;
2009-08-24 23:44:59 +02:00
failed :
usb_scuttle_anchored_urbs ( & data - > deferred ) ;
done :
spin_lock_irq ( & data - > txlock ) ;
clear_bit ( BTUSB_SUSPENDING , & data - > flags ) ;
spin_unlock_irq ( & data - > txlock ) ;
return err ;
2008-11-30 12:17:14 +01:00
}
2009-08-24 23:44:59 +02:00
# endif
2008-11-30 12:17:14 +01:00
2007-10-20 14:12:34 +02:00
static struct usb_driver btusb_driver = {
. name = " btusb " ,
. probe = btusb_probe ,
. disconnect = btusb_disconnect ,
2009-08-24 23:44:59 +02:00
# ifdef CONFIG_PM
2008-11-30 12:17:14 +01:00
. suspend = btusb_suspend ,
. resume = btusb_resume ,
2009-08-24 23:44:59 +02:00
# endif
2007-10-20 14:12:34 +02:00
. id_table = btusb_table ,
2009-08-24 23:44:59 +02:00
. supports_autosuspend = 1 ,
2012-04-23 10:08:51 -07:00
. disable_hub_initiated_lpm = 1 ,
2007-10-20 14:12:34 +02:00
} ;
2011-11-18 09:47:34 -08:00
module_usb_driver ( btusb_driver ) ;
2007-10-20 14:12:34 +02:00
2008-08-07 22:26:56 +02:00
module_param ( disable_scofix , bool , 0644 ) ;
MODULE_PARM_DESC ( disable_scofix , " Disable fixup of wrong SCO buffer size " ) ;
module_param ( force_scofix , bool , 0644 ) ;
MODULE_PARM_DESC ( force_scofix , " Force fixup of wrong SCO buffers size " ) ;
module_param ( reset , bool , 0644 ) ;
MODULE_PARM_DESC ( reset , " Send HCI reset command on initialization " ) ;
2007-10-20 14:12:34 +02:00
MODULE_AUTHOR ( " Marcel Holtmann <marcel@holtmann.org> " ) ;
MODULE_DESCRIPTION ( " Generic Bluetooth USB driver ver " VERSION ) ;
MODULE_VERSION ( VERSION ) ;
MODULE_LICENSE ( " GPL " ) ;