2007-10-20 16:12:34 +04:00
/*
*
* Generic Bluetooth USB driver
*
2008-08-18 15:23:52 +04:00
* Copyright ( C ) 2005 - 2008 Marcel Holtmann < marcel @ holtmann . org >
2007-10-20 16:12:34 +04: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 20:57:43 +04:00
# include <linux/firmware.h>
2015-04-16 23:09:55 +03:00
# include <asm/unaligned.h>
2007-10-20 16:12:34 +04:00
# include <net/bluetooth/bluetooth.h>
# include <net/bluetooth/hci_core.h>
2015-04-06 10:52:12 +03:00
# include "btintel.h"
2015-04-06 08:52:11 +03:00
# include "btbcm.h"
2015-05-14 11:49:09 +03:00
# include "btrtl.h"
2015-04-06 08:52:11 +03:00
2015-04-06 08:52:16 +03:00
# define VERSION "0.8"
2008-08-08 00:26:56 +04:00
2012-01-13 03:02:20 +04:00
static bool disable_scofix ;
static bool force_scofix ;
2008-11-30 14:17:26 +03:00
2012-01-13 03:02:20 +04:00
static bool reset = 1 ;
2008-08-08 00:26:56 +04:00
static struct usb_driver btusb_driver ;
# define BTUSB_IGNORE 0x01
2008-11-30 14:17:26 +03: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 10:02:36 +04:00
# define BTUSB_ATH3012 0x80
2013-04-19 20:57:43 +04:00
# define BTUSB_INTEL 0x100
2014-07-06 15:29:58 +04:00
# define BTUSB_INTEL_BOOT 0x200
# define BTUSB_BCM_PATCHRAM 0x400
2014-07-19 01:47:06 +04:00
# define BTUSB_MARVELL 0x800
2015-01-02 04:34:37 +03:00
# define BTUSB_SWAVE 0x1000
2015-01-27 08:33:48 +03:00
# define BTUSB_INTEL_NEW 0x2000
2015-01-29 07:27:34 +03:00
# define BTUSB_AMP 0x4000
2015-02-16 02:07:33 +03:00
# define BTUSB_QCA_ROME 0x8000
2015-03-22 17:52:38 +03:00
# define BTUSB_BCM_APPLE 0x10000
2015-04-16 23:09:55 +03:00
# define BTUSB_REALTEK 0x20000
2007-10-20 16:12:34 +04:00
2013-10-11 18:46:18 +04:00
static const struct usb_device_id btusb_table [ ] = {
2007-10-20 16:12:34 +04:00
/* Generic Bluetooth USB device */
{ USB_DEVICE_INFO ( 0xe0 , 0x01 , 0x01 ) } ,
2015-01-29 07:27:34 +03:00
/* Generic Bluetooth AMP device */
{ USB_DEVICE_INFO ( 0xe0 , 0x01 , 0x04 ) , . driver_info = BTUSB_AMP } ,
2012-08-25 21:28:06 +04:00
/* Apple-specific (Broadcom) devices */
2015-03-22 17:52:38 +03:00
{ USB_VENDOR_AND_INTERFACE_INFO ( 0x05ac , 0xff , 0x01 , 0x01 ) ,
. driver_info = BTUSB_BCM_APPLE } ,
2012-08-25 21:28:06 +04:00
2013-06-04 17:40:26 +04:00
/* MediaTek MT76x0E */
{ USB_DEVICE ( 0x0e8d , 0x763f ) } ,
2011-09-21 13:41:45 +04:00
/* Broadcom SoftSailing reporting vendor specific */
2012-03-29 00:41:11 +04:00
{ USB_DEVICE ( 0x0a5c , 0x21e1 ) } ,
2011-09-21 13:41:45 +04:00
2010-08-20 11:24:07 +04: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 11:24:06 +04:00
/* Apple MacBookPro6,2 */
{ USB_DEVICE ( 0x05ac , 0x8218 ) } ,
2010-11-04 10:04:33 +03:00
/* Apple MacBookAir3,1, MacBookAir3,2 */
{ USB_DEVICE ( 0x05ac , 0x821b ) } ,
2011-09-07 10:28:10 +04:00
/* Apple MacBookAir4,1 */
{ USB_DEVICE ( 0x05ac , 0x821f ) } ,
2011-03-24 20:51:21 +03:00
/* Apple MacBookPro8,2 */
{ USB_DEVICE ( 0x05ac , 0x821a ) } ,
2011-09-04 20:01:42 +04:00
/* Apple MacMini5,1 */
{ USB_DEVICE ( 0x05ac , 0x8281 ) } ,
2008-08-08 00:26:56 +04:00
/* AVM BlueFRITZ! USB v2.0 */
2015-01-02 04:34:37 +03:00
{ USB_DEVICE ( 0x057c , 0x3800 ) , . driver_info = BTUSB_SWAVE } ,
2008-08-08 00:26:56 +04: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 14:17:26 +03:00
{ USB_DEVICE ( 0x0c10 , 0x0000 ) } ,
2008-08-08 00:26:56 +04:00
2011-11-08 10:30:22 +04:00
/* Broadcom BCM20702A0 */
{ USB_DEVICE ( 0x413c , 0x8197 ) } ,
2015-01-27 07:35:32 +03:00
/* Broadcom BCM20702B0 (Dynex/Insignia) */
{ USB_DEVICE ( 0x19ff , 0x0239 ) , . driver_info = BTUSB_BCM_PATCHRAM } ,
2012-04-13 22:45:55 +04:00
/* Foxconn - Hon Hai */
2014-12-03 21:32:22 +03:00
{ USB_VENDOR_AND_INTERFACE_INFO ( 0x0489 , 0xff , 0x01 , 0x01 ) ,
. driver_info = BTUSB_BCM_PATCHRAM } ,
2012-04-13 22:45:55 +04:00
2015-02-02 20:50:14 +03:00
/* Lite-On Technology - Broadcom based */
{ USB_VENDOR_AND_INTERFACE_INFO ( 0x04ca , 0xff , 0x01 , 0x01 ) ,
. driver_info = BTUSB_BCM_PATCHRAM } ,
2014-02-18 20:26:19 +04:00
/* Broadcom devices with vendor specific id */
2014-05-09 02:50:01 +04:00
{ USB_VENDOR_AND_INTERFACE_INFO ( 0x0a5c , 0xff , 0x01 , 0x01 ) ,
. driver_info = BTUSB_BCM_PATCHRAM } ,
2012-08-06 22:36:49 +04:00
2014-07-21 16:02:33 +04:00
/* ASUSTek Computer - Broadcom based */
2015-01-17 07:29:12 +03:00
{ USB_VENDOR_AND_INTERFACE_INFO ( 0x0b05 , 0xff , 0x01 , 0x01 ) ,
. driver_info = BTUSB_BCM_PATCHRAM } ,
2014-07-21 16:02:33 +04:00
2013-09-21 22:14:43 +04:00
/* Belkin F8065bf - Broadcom based */
2015-03-28 01:11:41 +03:00
{ USB_VENDOR_AND_INTERFACE_INFO ( 0x050d , 0xff , 0x01 , 0x01 ) ,
. driver_info = BTUSB_BCM_PATCHRAM } ,
2013-09-21 22:14:43 +04:00
2014-02-15 15:01:09 +04:00
/* IMC Networks - Broadcom based */
2015-03-28 01:11:41 +03:00
{ USB_VENDOR_AND_INTERFACE_INFO ( 0x13d3 , 0xff , 0x01 , 0x01 ) ,
. driver_info = BTUSB_BCM_PATCHRAM } ,
2014-02-15 15:01:09 +04:00
2014-07-06 15:29:58 +04:00
/* Intel Bluetooth USB Bootloader (RAM module) */
2014-07-06 16:53:55 +04:00
{ USB_DEVICE ( 0x8087 , 0x0a5a ) ,
. driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC } ,
2014-07-06 15:29:58 +04:00
2007-10-20 16:12:34 +04:00
{ } /* Terminating entry */
} ;
MODULE_DEVICE_TABLE ( usb , btusb_table ) ;
2013-10-11 18:46:18 +04:00
static const struct usb_device_id blacklist_table [ ] = {
2008-08-08 00:26:56 +04: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 15:05:46 +03:00
/* Atheros 3011 with sflash firmware */
2014-02-18 20:26:19 +04:00
{ USB_DEVICE ( 0x0489 , 0xe027 ) , . driver_info = BTUSB_IGNORE } ,
{ USB_DEVICE ( 0x0489 , 0xe03d ) , . driver_info = BTUSB_IGNORE } ,
2015-02-13 22:05:11 +03:00
{ USB_DEVICE ( 0x04f2 , 0xaff1 ) , . driver_info = BTUSB_IGNORE } ,
2014-02-18 20:26:19 +04:00
{ USB_DEVICE ( 0x0930 , 0x0215 ) , . driver_info = BTUSB_IGNORE } ,
2010-11-26 15:05:46 +03:00
{ USB_DEVICE ( 0x0cf3 , 0x3002 ) , . driver_info = BTUSB_IGNORE } ,
2012-06-08 16:32:50 +04:00
{ USB_DEVICE ( 0x0cf3 , 0xe019 ) , . driver_info = BTUSB_IGNORE } ,
2011-05-10 03:11:16 +04:00
{ USB_DEVICE ( 0x13d3 , 0x3304 ) , . driver_info = BTUSB_IGNORE } ,
2010-11-26 15:05:46 +03:00
2011-01-26 12:10:59 +03:00
/* Atheros AR9285 Malbec with sflash firmware */
{ USB_DEVICE ( 0x03f0 , 0x311d ) , . driver_info = BTUSB_IGNORE } ,
2011-02-11 13:08:53 +03:00
/* Atheros 3012 with sflash firmware */
2014-02-18 20:26:19 +04: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 15:01:49 +04:00
{ USB_DEVICE ( 0x0489 , 0xe078 ) , . driver_info = BTUSB_ATH3012 } ,
2014-02-18 20:26:19 +04: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 22:37:13 +04:00
{ USB_DEVICE ( 0x04ca , 0x3007 ) , . driver_info = BTUSB_ATH3012 } ,
2014-02-18 20:26:19 +04:00
{ USB_DEVICE ( 0x04ca , 0x3008 ) , . driver_info = BTUSB_ATH3012 } ,
{ USB_DEVICE ( 0x04ca , 0x300b ) , . driver_info = BTUSB_ATH3012 } ,
2014-12-09 08:44:51 +03:00
{ USB_DEVICE ( 0x04ca , 0x3010 ) , . driver_info = BTUSB_ATH3012 } ,
2014-02-18 20:26:19 +04:00
{ USB_DEVICE ( 0x0930 , 0x0219 ) , . driver_info = BTUSB_ATH3012 } ,
{ USB_DEVICE ( 0x0930 , 0x0220 ) , . driver_info = BTUSB_ATH3012 } ,
2014-08-08 15:33:56 +04:00
{ USB_DEVICE ( 0x0930 , 0x0227 ) , . driver_info = BTUSB_ATH3012 } ,
2014-02-18 20:26:20 +04:00
{ USB_DEVICE ( 0x0b05 , 0x17d0 ) , . driver_info = BTUSB_ATH3012 } ,
2013-03-15 07:00:39 +04:00
{ USB_DEVICE ( 0x0cf3 , 0x0036 ) , . driver_info = BTUSB_ATH3012 } ,
2011-07-01 10:02:36 +04:00
{ USB_DEVICE ( 0x0cf3 , 0x3004 ) , . driver_info = BTUSB_ATH3012 } ,
2013-03-11 23:41:58 +04:00
{ USB_DEVICE ( 0x0cf3 , 0x3008 ) , . driver_info = BTUSB_ATH3012 } ,
2012-03-15 00:01:21 +04:00
{ USB_DEVICE ( 0x0cf3 , 0x311d ) , . driver_info = BTUSB_ATH3012 } ,
2014-01-16 18:37:11 +04:00
{ USB_DEVICE ( 0x0cf3 , 0x311e ) , . driver_info = BTUSB_ATH3012 } ,
2014-01-16 19:02:58 +04:00
{ USB_DEVICE ( 0x0cf3 , 0x311f ) , . driver_info = BTUSB_ATH3012 } ,
2014-02-18 20:26:19 +04:00
{ USB_DEVICE ( 0x0cf3 , 0x3121 ) , . driver_info = BTUSB_ATH3012 } ,
2013-03-18 19:45:11 +04:00
{ USB_DEVICE ( 0x0cf3 , 0x817a ) , . driver_info = BTUSB_ATH3012 } ,
2014-02-18 20:26:19 +04:00
{ USB_DEVICE ( 0x0cf3 , 0xe003 ) , . driver_info = BTUSB_ATH3012 } ,
2012-04-19 10:53:45 +04:00
{ USB_DEVICE ( 0x0cf3 , 0xe004 ) , . driver_info = BTUSB_ATH3012 } ,
2013-08-30 13:41:40 +04:00
{ USB_DEVICE ( 0x0cf3 , 0xe005 ) , . driver_info = BTUSB_ATH3012 } ,
2014-02-18 20:26:19 +04:00
{ USB_DEVICE ( 0x13d3 , 0x3362 ) , . driver_info = BTUSB_ATH3012 } ,
{ USB_DEVICE ( 0x13d3 , 0x3375 ) , . driver_info = BTUSB_ATH3012 } ,
2012-12-11 07:41:20 +04:00
{ USB_DEVICE ( 0x13d3 , 0x3393 ) , . driver_info = BTUSB_ATH3012 } ,
2013-07-15 07:59:03 +04:00
{ USB_DEVICE ( 0x13d3 , 0x3402 ) , . driver_info = BTUSB_ATH3012 } ,
2014-11-25 20:19:52 +03:00
{ USB_DEVICE ( 0x13d3 , 0x3408 ) , . driver_info = BTUSB_ATH3012 } ,
2015-01-18 00:16:51 +03:00
{ USB_DEVICE ( 0x13d3 , 0x3423 ) , . driver_info = BTUSB_ATH3012 } ,
2014-07-08 17:55:08 +04:00
{ USB_DEVICE ( 0x13d3 , 0x3432 ) , . driver_info = BTUSB_ATH3012 } ,
2011-02-11 13:08:53 +03:00
2011-02-15 05:20:07 +03:00
/* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE ( 0x0489 , 0xe02c ) , . driver_info = BTUSB_IGNORE } ,
2012-05-03 00:33:40 +04:00
/* Atheros AR5BBU12 with sflash firmware */
2012-08-07 18:18:10 +04:00
{ USB_DEVICE ( 0x0489 , 0xe036 ) , . driver_info = BTUSB_ATH3012 } ,
2014-02-18 20:26:19 +04:00
{ USB_DEVICE ( 0x0489 , 0xe03c ) , . driver_info = BTUSB_ATH3012 } ,
2012-05-03 00:33:40 +04:00
2015-02-16 02:07:33 +03:00
/* QCA ROME chipset */
2015-03-17 09:56:04 +03:00
{ USB_DEVICE ( 0x0cf3 , 0xe300 ) , . driver_info = BTUSB_QCA_ROME } ,
{ USB_DEVICE ( 0x0cf3 , 0xe360 ) , . driver_info = BTUSB_QCA_ROME } ,
2015-02-16 02:07:33 +03:00
2008-08-08 00:26:56 +04:00
/* Broadcom BCM2035 */
2008-11-30 14:17:26 +03:00
{ USB_DEVICE ( 0x0a5c , 0x2009 ) , . driver_info = BTUSB_BCM92035 } ,
2014-02-18 20:26:19 +04:00
{ USB_DEVICE ( 0x0a5c , 0x200a ) , . driver_info = BTUSB_WRONG_SCO_MTU } ,
{ USB_DEVICE ( 0x0a5c , 0x2035 ) , . driver_info = BTUSB_WRONG_SCO_MTU } ,
2008-08-08 00:26:56 +04:00
/* Broadcom BCM2045 */
2008-11-30 14:17:26 +03:00
{ USB_DEVICE ( 0x0a5c , 0x2039 ) , . driver_info = BTUSB_WRONG_SCO_MTU } ,
{ USB_DEVICE ( 0x0a5c , 0x2101 ) , . driver_info = BTUSB_WRONG_SCO_MTU } ,
2008-09-23 02:16:35 +04:00
2008-08-08 00:26:56 +04:00
/* IBM/Lenovo ThinkPad with Broadcom chip */
2008-11-30 14:17:26 +03:00
{ USB_DEVICE ( 0x0a5c , 0x201e ) , . driver_info = BTUSB_WRONG_SCO_MTU } ,
{ USB_DEVICE ( 0x0a5c , 0x2110 ) , . driver_info = BTUSB_WRONG_SCO_MTU } ,
2008-08-08 00:26:56 +04:00
/* HP laptop with Broadcom chip */
2008-11-30 14:17:26 +03:00
{ USB_DEVICE ( 0x03f0 , 0x171d ) , . driver_info = BTUSB_WRONG_SCO_MTU } ,
2008-08-08 00:26:56 +04:00
/* Dell laptop with Broadcom chip */
2008-11-30 14:17:26 +03:00
{ USB_DEVICE ( 0x413c , 0x8126 ) , . driver_info = BTUSB_WRONG_SCO_MTU } ,
2008-08-08 00:26:56 +04:00
2008-11-30 14:17:27 +03:00
/* Dell Wireless 370 and 410 devices */
2008-11-30 14:17:26 +03:00
{ USB_DEVICE ( 0x413c , 0x8152 ) , . driver_info = BTUSB_WRONG_SCO_MTU } ,
2008-11-30 14:17:27 +03:00
{ USB_DEVICE ( 0x413c , 0x8156 ) , . driver_info = BTUSB_WRONG_SCO_MTU } ,
2008-08-08 00:26:56 +04:00
2008-11-30 14:17:26 +03: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-08 00:26:56 +04:00
2008-11-30 14:17:27 +03: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-08 00:26:56 +04: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-02 04:34:37 +03:00
/* Roper Class 1 Bluetooth Dongle (Silicon Wave based) */
{ USB_DEVICE ( 0x1300 , 0x0001 ) , . driver_info = BTUSB_SWAVE } ,
2008-08-08 00:26:56 +04: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 02:12:04 +04:00
{ USB_DEVICE ( 0x0a12 , 0x0002 ) ,
. driver_info = BTUSB_SNIFFER | BTUSB_BROKEN_ISOC } ,
2008-08-08 00:26:56 +04:00
/* Frontline ComProbe Bluetooth Sniffer */
2014-07-07 02:12:04 +04:00
{ USB_DEVICE ( 0x16d3 , 0x0002 ) ,
. driver_info = BTUSB_SNIFFER | BTUSB_BROKEN_ISOC } ,
2008-08-08 00:26:56 +04:00
2015-01-29 06:41:42 +03:00
/* Marvell Bluetooth devices */
{ USB_DEVICE ( 0x1286 , 0x2044 ) , . driver_info = BTUSB_MARVELL } ,
{ USB_DEVICE ( 0x1286 , 0x2046 ) , . driver_info = BTUSB_MARVELL } ,
2015-01-29 06:41:43 +03:00
/* Intel Bluetooth devices */
2015-02-23 02:41:18 +03:00
{ USB_DEVICE ( 0x8087 , 0x07da ) , . driver_info = BTUSB_CSR } ,
2013-04-19 20:57:43 +04:00
{ USB_DEVICE ( 0x8087 , 0x07dc ) , . driver_info = BTUSB_INTEL } ,
2013-11-13 01:10:58 +04:00
{ USB_DEVICE ( 0x8087 , 0x0a2a ) , . driver_info = BTUSB_INTEL } ,
2015-01-27 08:33:48 +03:00
{ USB_DEVICE ( 0x8087 , 0x0a2b ) , . driver_info = BTUSB_INTEL_NEW } ,
2013-04-19 20:57:43 +04:00
2015-01-29 06:41:43 +03:00
/* Other Intel Bluetooth devices */
{ USB_VENDOR_AND_INTERFACE_INFO ( 0x8087 , 0xe0 , 0x01 , 0x01 ) ,
. driver_info = BTUSB_IGNORE } ,
2014-07-19 01:47:06 +04:00
2015-04-16 23:09:55 +03:00
/* Realtek Bluetooth devices */
{ USB_VENDOR_AND_INTERFACE_INFO ( 0x0bda , 0xe0 , 0x01 , 0x01 ) ,
. driver_info = BTUSB_REALTEK } ,
/* Additional Realtek 8723AE Bluetooth devices */
{ USB_DEVICE ( 0x0930 , 0x021d ) , . driver_info = BTUSB_REALTEK } ,
{ USB_DEVICE ( 0x13d3 , 0x3394 ) , . driver_info = BTUSB_REALTEK } ,
/* Additional Realtek 8723BE Bluetooth devices */
{ USB_DEVICE ( 0x0489 , 0xe085 ) , . driver_info = BTUSB_REALTEK } ,
{ USB_DEVICE ( 0x0489 , 0xe08b ) , . driver_info = BTUSB_REALTEK } ,
{ USB_DEVICE ( 0x13d3 , 0x3410 ) , . driver_info = BTUSB_REALTEK } ,
{ USB_DEVICE ( 0x13d3 , 0x3416 ) , . driver_info = BTUSB_REALTEK } ,
{ USB_DEVICE ( 0x13d3 , 0x3459 ) , . driver_info = BTUSB_REALTEK } ,
/* Additional Realtek 8821AE Bluetooth devices */
{ USB_DEVICE ( 0x0b05 , 0x17dc ) , . driver_info = BTUSB_REALTEK } ,
{ USB_DEVICE ( 0x13d3 , 0x3414 ) , . driver_info = BTUSB_REALTEK } ,
{ USB_DEVICE ( 0x13d3 , 0x3458 ) , . driver_info = BTUSB_REALTEK } ,
{ USB_DEVICE ( 0x13d3 , 0x3461 ) , . driver_info = BTUSB_REALTEK } ,
{ USB_DEVICE ( 0x13d3 , 0x3462 ) , . driver_info = BTUSB_REALTEK } ,
2007-10-20 16:12:34 +04:00
{ } /* Terminating entry */
} ;
2008-08-18 15:23:52 +04:00
# define BTUSB_MAX_ISOC_FRAMES 10
2007-10-20 16:12:34 +04:00
# define BTUSB_INTR_RUNNING 0
# define BTUSB_BULK_RUNNING 1
2008-08-18 15:23:52 +04:00
# define BTUSB_ISOC_RUNNING 2
2009-08-25 01:44:59 +04:00
# define BTUSB_SUSPENDING 3
2010-07-17 00:20:33 +04:00
# define BTUSB_DID_ISO_RESUME 4
2015-01-27 08:33:48 +03:00
# define BTUSB_BOOTLOADER 5
# define BTUSB_DOWNLOADING 6
2015-01-28 12:58:40 +03:00
# define BTUSB_FIRMWARE_LOADED 7
2015-01-27 08:33:48 +03:00
# define BTUSB_FIRMWARE_FAILED 8
2015-01-28 12:58:40 +03:00
# define BTUSB_BOOTING 9
2007-10-20 16:12:34 +04:00
struct btusb_data {
struct hci_dev * hdev ;
struct usb_device * udev ;
2008-09-23 02:16:36 +04:00
struct usb_interface * intf ;
2008-08-18 15:23:52 +04:00
struct usb_interface * isoc ;
2007-10-20 16:12:34 +04:00
unsigned long flags ;
struct work_struct work ;
2009-08-25 01:44:59 +04:00
struct work_struct waker ;
2007-10-20 16:12:34 +04:00
2014-09-16 10:00:29 +04:00
struct usb_anchor deferred ;
2007-10-20 16:12:34 +04:00
struct usb_anchor tx_anchor ;
2014-09-16 10:00:29 +04:00
int tx_in_flight ;
spinlock_t txlock ;
2007-10-20 16:12:34 +04:00
struct usb_anchor intr_anchor ;
struct usb_anchor bulk_anchor ;
2008-08-18 15:23:52 +04:00
struct usb_anchor isoc_anchor ;
2014-09-16 10:00:29 +04:00
spinlock_t rxlock ;
struct sk_buff * evt_skb ;
struct sk_buff * acl_skb ;
struct sk_buff * sco_skb ;
2007-10-20 16:12:34 +04:00
struct usb_endpoint_descriptor * intr_ep ;
struct usb_endpoint_descriptor * bulk_tx_ep ;
struct usb_endpoint_descriptor * bulk_rx_ep ;
2008-08-18 15:23:52 +04:00
struct usb_endpoint_descriptor * isoc_tx_ep ;
struct usb_endpoint_descriptor * isoc_rx_ep ;
2008-11-30 14:17:26 +03:00
__u8 cmdreq_type ;
2015-01-29 07:27:34 +03:00
__u8 cmdreq ;
2008-11-30 14:17:26 +03:00
2009-02-04 19:41:38 +03:00
unsigned int sco_num ;
2008-08-18 15:23:52 +04:00
int isoc_altsetting ;
2008-11-30 14:17:14 +03:00
int suspend_count ;
2014-11-03 07:16:07 +03:00
2015-01-13 00:51:10 +03:00
int ( * recv_event ) ( struct hci_dev * hdev , struct sk_buff * skb ) ;
2014-11-03 07:16:07 +03:00
int ( * recv_bulk ) ( struct btusb_data * data , void * buffer , int count ) ;
2015-02-16 02:06:14 +03:00
int ( * setup_on_usb ) ( struct hci_dev * hdev ) ;
2007-10-20 16:12:34 +04:00
} ;
2014-09-16 10:00:29 +04: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 07:33:33 +04:00
static int btusb_recv_intr ( struct btusb_data * data , void * buffer , int count )
{
2014-09-16 10:00:29 +04: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 */
2015-01-13 00:51:10 +03:00
data - > recv_event ( data - > hdev , skb ) ;
2014-09-16 10:00:29 +04:00
skb = NULL ;
}
}
data - > evt_skb = skb ;
spin_unlock ( & data - > rxlock ) ;
return err ;
2014-09-16 07:33:33 +04:00
}
static int btusb_recv_bulk ( struct btusb_data * data , void * buffer , int count )
{
2014-09-16 10:00:29 +04: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 07:33:33 +04:00
}
static int btusb_recv_isoc ( struct btusb_data * data , void * buffer , int count )
{
2014-09-16 10:00:29 +04: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 07:33:33 +04:00
}
2007-10-20 16:12:34 +04:00
static void btusb_intr_complete ( struct urb * urb )
{
struct hci_dev * hdev = urb - > context ;
2012-02-10 00:58:32 +04:00
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
2007-10-20 16:12:34 +04:00
int err ;
2014-09-16 06:44:50 +04:00
BT_DBG ( " %s urb %p status %d count %d " , hdev - > name , urb , urb - > status ,
urb - > actual_length ) ;
2007-10-20 16:12:34 +04:00
if ( ! test_bit ( HCI_RUNNING , & hdev - > flags ) )
return ;
if ( urb - > status = = 0 ) {
2008-08-18 15:23:52 +04:00
hdev - > stat . byte_rx + = urb - > actual_length ;
2014-09-16 07:33:33 +04:00
if ( btusb_recv_intr ( data , urb - > transfer_buffer ,
urb - > actual_length ) < 0 ) {
2007-10-20 16:12:34 +04:00
BT_ERR ( " %s corrupted event packet " , hdev - > name ) ;
hdev - > stat . err_rx + + ;
}
2014-09-06 23:06:08 +04:00
} else if ( urb - > status = = - ENOENT ) {
/* Avoid suspend failed when usb_kill_urb */
return ;
2007-10-20 16:12:34 +04:00
}
if ( ! test_bit ( BTUSB_INTR_RUNNING , & data - > flags ) )
return ;
2009-08-25 01:44:59 +04:00
usb_mark_last_busy ( data - > udev ) ;
2007-10-20 16:12:34 +04:00
usb_anchor_urb ( urb , & data - > intr_anchor ) ;
err = usb_submit_urb ( urb , GFP_ATOMIC ) ;
if ( err < 0 ) {
2011-08-09 19:16:28 +04:00
/* -EPERM: urb is being killed;
* - ENODEV : device got disconnected */
if ( err ! = - EPERM & & err ! = - ENODEV )
2010-11-30 23:49:08 +03:00
BT_ERR ( " %s urb %p failed to resubmit (%d) " ,
2014-09-16 06:44:50 +04:00
hdev - > name , urb , - err ) ;
2007-10-20 16:12:34 +04:00
usb_unanchor_urb ( urb ) ;
}
}
2008-11-30 14:17:10 +03:00
static int btusb_submit_intr_urb ( struct hci_dev * hdev , gfp_t mem_flags )
2007-10-20 16:12:34 +04:00
{
2012-02-10 00:58:32 +04:00
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
2007-10-20 16:12:34 +04:00
struct urb * urb ;
unsigned char * buf ;
unsigned int pipe ;
int err , size ;
BT_DBG ( " %s " , hdev - > name ) ;
2008-08-18 15:23:52 +04:00
if ( ! data - > intr_ep )
return - ENODEV ;
2008-11-30 14:17:10 +03:00
urb = usb_alloc_urb ( 0 , mem_flags ) ;
2007-10-20 16:12:34 +04:00
if ( ! urb )
return - ENOMEM ;
size = le16_to_cpu ( data - > intr_ep - > wMaxPacketSize ) ;
2008-11-30 14:17:10 +03:00
buf = kmalloc ( size , mem_flags ) ;
2007-10-20 16:12:34 +04: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 06:44:50 +04:00
btusb_intr_complete , hdev , data - > intr_ep - > bInterval ) ;
2007-10-20 16:12:34 +04:00
urb - > transfer_flags | = URB_FREE_BUFFER ;
usb_anchor_urb ( urb , & data - > intr_anchor ) ;
2008-11-30 14:17:10 +03:00
err = usb_submit_urb ( urb , mem_flags ) ;
2007-10-20 16:12:34 +04:00
if ( err < 0 ) {
2011-10-09 14:12:22 +04:00
if ( err ! = - EPERM & & err ! = - ENODEV )
BT_ERR ( " %s urb %p submission failed (%d) " ,
2014-09-16 06:44:50 +04:00
hdev - > name , urb , - err ) ;
2007-10-20 16:12:34 +04: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-10 00:58:32 +04:00
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
2007-10-20 16:12:34 +04:00
int err ;
2014-09-16 06:44:50 +04:00
BT_DBG ( " %s urb %p status %d count %d " , hdev - > name , urb , urb - > status ,
urb - > actual_length ) ;
2007-10-20 16:12:34 +04:00
if ( ! test_bit ( HCI_RUNNING , & hdev - > flags ) )
return ;
if ( urb - > status = = 0 ) {
2008-08-18 15:23:52 +04:00
hdev - > stat . byte_rx + = urb - > actual_length ;
2014-11-03 07:16:07 +03:00
if ( data - > recv_bulk ( data , urb - > transfer_buffer ,
2014-09-16 07:33:33 +04:00
urb - > actual_length ) < 0 ) {
2007-10-20 16:12:34 +04:00
BT_ERR ( " %s corrupted ACL packet " , hdev - > name ) ;
hdev - > stat . err_rx + + ;
}
2014-09-06 23:06:08 +04:00
} else if ( urb - > status = = - ENOENT ) {
/* Avoid suspend failed when usb_kill_urb */
return ;
2007-10-20 16:12:34 +04:00
}
if ( ! test_bit ( BTUSB_BULK_RUNNING , & data - > flags ) )
return ;
usb_anchor_urb ( urb , & data - > bulk_anchor ) ;
2009-12-16 21:23:43 +03:00
usb_mark_last_busy ( data - > udev ) ;
2007-10-20 16:12:34 +04:00
err = usb_submit_urb ( urb , GFP_ATOMIC ) ;
if ( err < 0 ) {
2011-08-09 19:16:28 +04:00
/* -EPERM: urb is being killed;
* - ENODEV : device got disconnected */
if ( err ! = - EPERM & & err ! = - ENODEV )
2010-11-30 23:49:08 +03:00
BT_ERR ( " %s urb %p failed to resubmit (%d) " ,
2014-09-16 06:44:50 +04:00
hdev - > name , urb , - err ) ;
2007-10-20 16:12:34 +04:00
usb_unanchor_urb ( urb ) ;
}
}
2008-11-30 14:17:10 +03:00
static int btusb_submit_bulk_urb ( struct hci_dev * hdev , gfp_t mem_flags )
2007-10-20 16:12:34 +04:00
{
2012-02-10 00:58:32 +04:00
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
2007-10-20 16:12:34 +04:00
struct urb * urb ;
unsigned char * buf ;
unsigned int pipe ;
2009-07-02 13:01:59 +04:00
int err , size = HCI_MAX_FRAME_SIZE ;
2007-10-20 16:12:34 +04:00
BT_DBG ( " %s " , hdev - > name ) ;
2008-08-18 15:23:52 +04:00
if ( ! data - > bulk_rx_ep )
return - ENODEV ;
2008-11-30 14:17:10 +03:00
urb = usb_alloc_urb ( 0 , mem_flags ) ;
2007-10-20 16:12:34 +04:00
if ( ! urb )
return - ENOMEM ;
2008-11-30 14:17:10 +03:00
buf = kmalloc ( size , mem_flags ) ;
2007-10-20 16:12:34 +04:00
if ( ! buf ) {
usb_free_urb ( urb ) ;
return - ENOMEM ;
}
pipe = usb_rcvbulkpipe ( data - > udev , data - > bulk_rx_ep - > bEndpointAddress ) ;
2014-09-16 06:44:50 +04:00
usb_fill_bulk_urb ( urb , data - > udev , pipe , buf , size ,
btusb_bulk_complete , hdev ) ;
2007-10-20 16:12:34 +04:00
urb - > transfer_flags | = URB_FREE_BUFFER ;
2009-08-25 01:44:59 +04:00
usb_mark_last_busy ( data - > udev ) ;
2007-10-20 16:12:34 +04:00
usb_anchor_urb ( urb , & data - > bulk_anchor ) ;
2008-11-30 14:17:10 +03:00
err = usb_submit_urb ( urb , mem_flags ) ;
2007-10-20 16:12:34 +04:00
if ( err < 0 ) {
2011-10-09 14:12:22 +04:00
if ( err ! = - EPERM & & err ! = - ENODEV )
BT_ERR ( " %s urb %p submission failed (%d) " ,
2014-09-16 06:44:50 +04:00
hdev - > name , urb , - err ) ;
2007-10-20 16:12:34 +04:00
usb_unanchor_urb ( urb ) ;
}
usb_free_urb ( urb ) ;
return err ;
}
2008-08-18 15:23:52 +04:00
static void btusb_isoc_complete ( struct urb * urb )
{
struct hci_dev * hdev = urb - > context ;
2012-02-10 00:58:32 +04:00
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
2008-08-18 15:23:52 +04:00
int i , err ;
2014-09-16 06:44:50 +04:00
BT_DBG ( " %s urb %p status %d count %d " , hdev - > name , urb , urb - > status ,
urb - > actual_length ) ;
2008-08-18 15:23:52 +04: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 07:33:33 +04:00
if ( btusb_recv_isoc ( data , urb - > transfer_buffer + offset ,
length ) < 0 ) {
2008-08-18 15:23:52 +04:00
BT_ERR ( " %s corrupted SCO packet " , hdev - > name ) ;
hdev - > stat . err_rx + + ;
}
}
2014-09-06 23:06:08 +04:00
} else if ( urb - > status = = - ENOENT ) {
/* Avoid suspend failed when usb_kill_urb */
return ;
2008-08-18 15:23:52 +04: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 19:16:28 +04:00
/* -EPERM: urb is being killed;
* - ENODEV : device got disconnected */
if ( err ! = - EPERM & & err ! = - ENODEV )
2010-11-30 23:49:08 +03:00
BT_ERR ( " %s urb %p failed to resubmit (%d) " ,
2014-09-16 06:44:50 +04:00
hdev - > name , urb , - err ) ;
2008-08-18 15:23:52 +04:00
usb_unanchor_urb ( urb ) ;
}
}
2011-01-17 02:09:38 +03:00
static inline void __fill_isoc_descriptor ( struct urb * urb , int len , int mtu )
2008-08-18 15:23:52 +04: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 14:17:10 +03:00
static int btusb_submit_isoc_urb ( struct hci_dev * hdev , gfp_t mem_flags )
2008-08-18 15:23:52 +04:00
{
2012-02-10 00:58:32 +04:00
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
2008-08-18 15:23:52 +04: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 14:17:10 +03:00
urb = usb_alloc_urb ( BTUSB_MAX_ISOC_FRAMES , mem_flags ) ;
2008-08-18 15:23:52 +04:00
if ( ! urb )
return - ENOMEM ;
size = le16_to_cpu ( data - > isoc_rx_ep - > wMaxPacketSize ) *
BTUSB_MAX_ISOC_FRAMES ;
2008-11-30 14:17:10 +03:00
buf = kmalloc ( size , mem_flags ) ;
2008-08-18 15:23:52 +04:00
if ( ! buf ) {
usb_free_urb ( urb ) ;
return - ENOMEM ;
}
pipe = usb_rcvisocpipe ( data - > udev , data - > isoc_rx_ep - > bEndpointAddress ) ;
2011-12-21 06:19:00 +04:00
usb_fill_int_urb ( urb , data - > udev , pipe , buf , size , btusb_isoc_complete ,
2014-09-16 06:44:50 +04:00
hdev , data - > isoc_rx_ep - > bInterval ) ;
2008-08-18 15:23:52 +04:00
2014-09-16 06:44:50 +04:00
urb - > transfer_flags = URB_FREE_BUFFER | URB_ISO_ASAP ;
2008-08-18 15:23:52 +04:00
__fill_isoc_descriptor ( urb , size ,
2014-09-16 06:44:50 +04:00
le16_to_cpu ( data - > isoc_rx_ep - > wMaxPacketSize ) ) ;
2008-08-18 15:23:52 +04:00
usb_anchor_urb ( urb , & data - > isoc_anchor ) ;
2008-11-30 14:17:10 +03:00
err = usb_submit_urb ( urb , mem_flags ) ;
2008-08-18 15:23:52 +04:00
if ( err < 0 ) {
2011-10-09 14:12:22 +04:00
if ( err ! = - EPERM & & err ! = - ENODEV )
BT_ERR ( " %s urb %p submission failed (%d) " ,
2014-09-16 06:44:50 +04:00
hdev - > name , urb , - err ) ;
2008-08-18 15:23:52 +04:00
usb_unanchor_urb ( urb ) ;
}
usb_free_urb ( urb ) ;
return err ;
}
2007-10-20 16:12:34 +04:00
static void btusb_tx_complete ( struct urb * urb )
2009-08-25 01:44:59 +04:00
{
struct sk_buff * skb = urb - > context ;
2014-09-16 06:44:50 +04:00
struct hci_dev * hdev = ( struct hci_dev * ) skb - > dev ;
2012-02-10 00:58:32 +04:00
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
2009-08-25 01:44:59 +04:00
2014-09-16 06:44:50 +04:00
BT_DBG ( " %s urb %p status %d count %d " , hdev - > name , urb , urb - > status ,
urb - > actual_length ) ;
2009-08-25 01:44:59 +04: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 16:12:34 +04:00
{
struct sk_buff * skb = urb - > context ;
2014-09-16 06:44:50 +04:00
struct hci_dev * hdev = ( struct hci_dev * ) skb - > dev ;
2007-10-20 16:12:34 +04:00
2014-09-16 06:44:50 +04:00
BT_DBG ( " %s urb %p status %d count %d " , hdev - > name , urb , urb - > status ,
urb - > actual_length ) ;
2007-10-20 16:12:34 +04: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-10 00:58:32 +04:00
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
2007-10-20 16:12:34 +04:00
int err ;
BT_DBG ( " %s " , hdev - > name ) ;
2015-02-16 02:06:14 +03:00
/* Patching USB firmware files prior to starting any URBs of HCI path
* It is more safe to use USB bulk channel for downloading USB patch
*/
if ( data - > setup_on_usb ) {
err = data - > setup_on_usb ( hdev ) ;
2015-04-17 00:15:50 +03:00
if ( err < 0 )
2015-02-16 02:06:14 +03:00
return err ;
}
2009-08-25 01:44:59 +04:00
err = usb_autopm_get_interface ( data - > intf ) ;
if ( err < 0 )
return err ;
data - > intf - > needs_remote_wakeup = 1 ;
2007-10-20 16:12:34 +04:00
if ( test_and_set_bit ( HCI_RUNNING , & hdev - > flags ) )
2009-08-25 01:44:59 +04:00
goto done ;
2007-10-20 16:12:34 +04:00
if ( test_and_set_bit ( BTUSB_INTR_RUNNING , & data - > flags ) )
2009-08-25 01:44:59 +04:00
goto done ;
2007-10-20 16:12:34 +04:00
2008-11-30 14:17:10 +03:00
err = btusb_submit_intr_urb ( hdev , GFP_KERNEL ) ;
2009-02-04 19:41:38 +03:00
if ( err < 0 )
goto failed ;
err = btusb_submit_bulk_urb ( hdev , GFP_KERNEL ) ;
2007-10-20 16:12:34 +04:00
if ( err < 0 ) {
2009-02-04 19:41:38 +03:00
usb_kill_anchored_urbs ( & data - > intr_anchor ) ;
goto failed ;
2007-10-20 16:12:34 +04:00
}
2009-02-04 19:41:38 +03:00
set_bit ( BTUSB_BULK_RUNNING , & data - > flags ) ;
btusb_submit_bulk_urb ( hdev , GFP_KERNEL ) ;
2009-08-25 01:44:59 +04:00
done :
usb_autopm_put_interface ( data - > intf ) ;
2009-02-04 19:41:38 +03:00
return 0 ;
failed :
clear_bit ( BTUSB_INTR_RUNNING , & data - > flags ) ;
clear_bit ( HCI_RUNNING , & hdev - > flags ) ;
2009-08-25 01:44:59 +04:00
usb_autopm_put_interface ( data - > intf ) ;
2007-10-20 16:12:34 +04:00
return err ;
}
2009-08-25 01:44:59 +04: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 16:12:34 +04:00
static int btusb_close ( struct hci_dev * hdev )
{
2012-02-10 00:58:32 +04:00
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
2009-08-25 01:44:59 +04:00
int err ;
2007-10-20 16:12:34 +04:00
BT_DBG ( " %s " , hdev - > name ) ;
if ( ! test_and_clear_bit ( HCI_RUNNING , & hdev - > flags ) )
return 0 ;
2008-09-23 02:16:36 +04:00
cancel_work_sync ( & data - > work ) ;
2009-11-12 00:32:29 +03:00
cancel_work_sync ( & data - > waker ) ;
2008-09-23 02:16:36 +04:00
2008-08-18 15:23:52 +04:00
clear_bit ( BTUSB_ISOC_RUNNING , & data - > flags ) ;
2007-10-20 16:12:34 +04:00
clear_bit ( BTUSB_BULK_RUNNING , & data - > flags ) ;
clear_bit ( BTUSB_INTR_RUNNING , & data - > flags ) ;
2009-08-25 01:44:59 +04:00
btusb_stop_traffic ( data ) ;
2014-09-16 10:00:29 +04:00
btusb_free_frags ( data ) ;
2009-08-25 01:44:59 +04:00
err = usb_autopm_get_interface ( data - > intf ) ;
if ( err < 0 )
2009-11-13 16:26:23 +03:00
goto failed ;
2009-08-25 01:44:59 +04:00
data - > intf - > needs_remote_wakeup = 0 ;
usb_autopm_put_interface ( data - > intf ) ;
2007-10-20 16:12:34 +04:00
2009-11-13 16:26:23 +03:00
failed :
usb_scuttle_anchored_urbs ( & data - > deferred ) ;
2007-10-20 16:12:34 +04:00
return 0 ;
}
static int btusb_flush ( struct hci_dev * hdev )
{
2012-02-10 00:58:32 +04:00
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
2007-10-20 16:12:34 +04:00
BT_DBG ( " %s " , hdev - > name ) ;
usb_kill_anchored_urbs ( & data - > tx_anchor ) ;
2014-09-16 10:00:29 +04:00
btusb_free_frags ( data ) ;
2007-10-20 16:12:34 +04:00
return 0 ;
}
2014-09-14 11:11:06 +04:00
static struct urb * alloc_ctrl_urb ( struct hci_dev * hdev , struct sk_buff * skb )
2007-10-20 16:12:34 +04:00
{
2012-02-10 00:58:32 +04:00
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
2007-10-20 16:12:34 +04:00
struct usb_ctrlrequest * dr ;
struct urb * urb ;
unsigned int pipe ;
2014-09-14 11:11:06 +04:00
urb = usb_alloc_urb ( 0 , GFP_KERNEL ) ;
if ( ! urb )
return ERR_PTR ( - ENOMEM ) ;
2007-10-20 16:12:34 +04:00
2014-09-14 11:11:06 +04:00
dr = kmalloc ( sizeof ( * dr ) , GFP_KERNEL ) ;
if ( ! dr ) {
usb_free_urb ( urb ) ;
return ERR_PTR ( - ENOMEM ) ;
}
2007-10-20 16:12:34 +04:00
2014-09-14 11:11:06 +04:00
dr - > bRequestType = data - > cmdreq_type ;
2015-01-29 07:27:34 +03:00
dr - > bRequest = data - > cmdreq ;
2014-09-14 11:11:06 +04:00
dr - > wIndex = 0 ;
dr - > wValue = 0 ;
dr - > wLength = __cpu_to_le16 ( skb - > len ) ;
2013-10-11 17:19:18 +04:00
2014-09-14 11:11:06 +04:00
pipe = usb_sndctrlpipe ( data - > udev , 0x00 ) ;
2007-10-20 16:12:34 +04:00
2014-09-16 06:44:50 +04:00
usb_fill_control_urb ( urb , data - > udev , pipe , ( void * ) dr ,
2014-09-14 11:11:06 +04:00
skb - > data , skb - > len , btusb_tx_complete , skb ) ;
2007-10-20 16:12:34 +04:00
2014-09-16 06:44:50 +04:00
skb - > dev = ( void * ) hdev ;
2007-10-20 16:12:34 +04:00
2014-09-14 11:11:06 +04:00
return urb ;
}
2007-10-20 16:12:34 +04:00
2014-09-14 11:11:06 +04: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 16:12:34 +04:00
2014-09-14 11:11:06 +04:00
if ( ! data - > bulk_tx_ep )
return ERR_PTR ( - ENODEV ) ;
2008-08-18 15:23:52 +04:00
2014-09-14 11:11:06 +04:00
urb = usb_alloc_urb ( 0 , GFP_KERNEL ) ;
if ( ! urb )
return ERR_PTR ( - ENOMEM ) ;
2007-10-20 16:12:34 +04:00
2014-09-14 11:11:06 +04:00
pipe = usb_sndbulkpipe ( data - > udev , data - > bulk_tx_ep - > bEndpointAddress ) ;
2007-10-20 16:12:34 +04:00
2014-09-14 11:11:06 +04:00
usb_fill_bulk_urb ( urb , data - > udev , pipe ,
skb - > data , skb - > len , btusb_tx_complete , skb ) ;
2007-10-20 16:12:34 +04:00
2014-09-16 06:44:50 +04:00
skb - > dev = ( void * ) hdev ;
2007-10-20 16:12:34 +04:00
2014-09-14 11:11:06 +04:00
return urb ;
}
2008-08-18 15:23:52 +04:00
2014-09-14 11:11:06 +04: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 15:23:52 +04:00
2014-09-14 11:11:06 +04:00
if ( ! data - > isoc_tx_ep )
return ERR_PTR ( - ENODEV ) ;
2008-08-18 15:23:52 +04:00
2014-09-14 11:11:06 +04:00
urb = usb_alloc_urb ( BTUSB_MAX_ISOC_FRAMES , GFP_KERNEL ) ;
if ( ! urb )
return ERR_PTR ( - ENOMEM ) ;
2008-08-18 15:23:52 +04:00
2014-09-14 11:11:06 +04:00
pipe = usb_sndisocpipe ( data - > udev , data - > isoc_tx_ep - > bEndpointAddress ) ;
2008-08-18 15:23:52 +04:00
2014-09-14 11:11:06 +04: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 15:23:52 +04:00
2014-09-14 11:11:06 +04:00
urb - > transfer_flags = URB_ISO_ASAP ;
2007-10-20 16:12:34 +04:00
2014-09-14 11:11:06 +04:00
__fill_isoc_descriptor ( urb , skb - > len ,
le16_to_cpu ( data - > isoc_tx_ep - > wMaxPacketSize ) ) ;
2007-10-20 16:12:34 +04:00
2014-09-16 06:44:50 +04:00
skb - > dev = ( void * ) hdev ;
2014-09-14 11:11:06 +04: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-25 01:44:59 +04:00
2007-10-20 16:12:34 +04:00
usb_anchor_urb ( urb , & data - > tx_anchor ) ;
2014-09-14 09:49:34 +04:00
err = usb_submit_urb ( urb , GFP_KERNEL ) ;
2007-10-20 16:12:34 +04:00
if ( err < 0 ) {
2011-10-09 14:12:16 +04:00
if ( err ! = - EPERM & & err ! = - ENODEV )
BT_ERR ( " %s urb %p submission failed (%d) " ,
2014-09-16 06:44:50 +04:00
hdev - > name , urb , - err ) ;
2007-10-20 16:12:34 +04:00
kfree ( urb - > setup_packet ) ;
usb_unanchor_urb ( urb ) ;
2009-08-25 01:44:59 +04:00
} else {
usb_mark_last_busy ( data - > udev ) ;
2007-10-20 16:12:34 +04:00
}
2011-11-22 05:32:57 +04:00
usb_free_urb ( urb ) ;
2007-10-20 16:12:34 +04:00
return err ;
}
2014-09-14 11:11:06 +04: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 16:12:34 +04:00
static void btusb_notify ( struct hci_dev * hdev , unsigned int evt )
{
2012-02-10 00:58:32 +04:00
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
2007-10-20 16:12:34 +04:00
BT_DBG ( " %s evt %d " , hdev - > name , evt ) ;
2013-10-10 20:47:55 +04:00
if ( hci_conn_num ( hdev , SCO_LINK ) ! = data - > sco_num ) {
data - > sco_num = hci_conn_num ( hdev , SCO_LINK ) ;
2009-02-04 19:41:38 +03:00
schedule_work ( & data - > work ) ;
2008-11-30 14:17:12 +03:00
}
2007-10-20 16:12:34 +04:00
}
2011-01-17 02:09:38 +03:00
static inline int __set_isoc_interface ( struct hci_dev * hdev , int altsetting )
2008-08-18 15:23:52 +04:00
{
2012-02-10 00:58:32 +04:00
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
2008-08-18 15:23:52 +04: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 16:12:34 +04: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 10:48:51 +04:00
int new_alts ;
2009-08-25 01:44:59 +04:00
int err ;
2007-10-20 16:12:34 +04:00
2013-10-10 20:47:55 +04:00
if ( data - > sco_num > 0 ) {
2010-07-17 00:20:33 +04:00
if ( ! test_bit ( BTUSB_DID_ISO_RESUME , & data - > flags ) ) {
2011-02-11 15:00:06 +03:00
err = usb_autopm_get_interface ( data - > isoc ? data - > isoc : data - > intf ) ;
2009-08-25 01:44:59 +04:00
if ( err < 0 ) {
clear_bit ( BTUSB_ISOC_RUNNING , & data - > flags ) ;
usb_kill_anchored_urbs ( & data - > isoc_anchor ) ;
return ;
}
2010-07-17 00:20:33 +04:00
set_bit ( BTUSB_DID_ISO_RESUME , & data - > flags ) ;
2009-08-25 01:44:59 +04:00
}
2012-04-11 10:48:51 +04:00
if ( hdev - > voice_setting & 0x0020 ) {
static const int alts [ 3 ] = { 2 , 4 , 5 } ;
2014-09-16 06:44:50 +04:00
2013-10-10 20:47:55 +04:00
new_alts = alts [ data - > sco_num - 1 ] ;
2012-04-11 10:48:51 +04:00
} else {
2013-10-10 20:47:55 +04:00
new_alts = data - > sco_num ;
2012-04-11 10:48:51 +04:00
}
if ( data - > isoc_altsetting ! = new_alts ) {
2008-08-18 15:23:52 +04:00
clear_bit ( BTUSB_ISOC_RUNNING , & data - > flags ) ;
usb_kill_anchored_urbs ( & data - > isoc_anchor ) ;
2012-04-11 10:48:51 +04:00
if ( __set_isoc_interface ( hdev , new_alts ) < 0 )
2008-08-18 15:23:52 +04:00
return ;
}
if ( ! test_and_set_bit ( BTUSB_ISOC_RUNNING , & data - > flags ) ) {
2008-11-30 14:17:10 +03:00
if ( btusb_submit_isoc_urb ( hdev , GFP_KERNEL ) < 0 )
2008-08-18 15:23:52 +04:00
clear_bit ( BTUSB_ISOC_RUNNING , & data - > flags ) ;
else
2008-11-30 14:17:10 +03:00
btusb_submit_isoc_urb ( hdev , GFP_KERNEL ) ;
2008-08-18 15:23:52 +04:00
}
} else {
clear_bit ( BTUSB_ISOC_RUNNING , & data - > flags ) ;
usb_kill_anchored_urbs ( & data - > isoc_anchor ) ;
__set_isoc_interface ( hdev , 0 ) ;
2010-07-17 00:20:33 +04:00
if ( test_and_clear_bit ( BTUSB_DID_ISO_RESUME , & data - > flags ) )
2011-02-11 15:00:06 +03:00
usb_autopm_put_interface ( data - > isoc ? data - > isoc : data - > intf ) ;
2007-10-20 16:12:34 +04:00
}
}
2009-08-25 01:44:59 +04: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 ) ;
}
2015-02-24 03:16:47 +03:00
static struct sk_buff * btusb_read_local_version ( struct hci_dev * hdev )
{
struct sk_buff * skb ;
skb = __hci_cmd_sync ( hdev , HCI_OP_READ_LOCAL_VERSION , 0 , NULL ,
HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) ) {
BT_ERR ( " %s: HCI_OP_READ_LOCAL_VERSION failed (%ld) " ,
hdev - > name , PTR_ERR ( skb ) ) ;
return skb ;
}
if ( skb - > len ! = sizeof ( struct hci_rp_read_local_version ) ) {
BT_ERR ( " %s: HCI_OP_READ_LOCAL_VERSION event length mismatch " ,
hdev - > name ) ;
kfree_skb ( skb ) ;
return ERR_PTR ( - EIO ) ;
}
return skb ;
}
2013-04-10 19:11:35 +04: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 15:02:36 +04: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 ) ;
2015-02-24 03:16:47 +03:00
skb = btusb_read_local_version ( hdev ) ;
if ( IS_ERR ( skb ) )
2014-01-03 15:02:36 +04:00
return - PTR_ERR ( skb ) ;
2014-09-16 06:44:50 +04:00
rp = ( struct hci_rp_read_local_version * ) skb - > data ;
2014-01-03 15:02:36 +04: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 20:57:43 +04:00
static const struct firmware * btusb_setup_intel_get_fw ( struct hci_dev * hdev ,
2014-09-16 06:44:50 +04:00
struct intel_version * ver )
2013-04-19 20:57:43 +04: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 06:02:12 +04:00
return PTR_ERR ( skb ) ;
2013-04-19 20:57:43 +04: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 ;
}
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 06:02:12 +04:00
return PTR_ERR ( skb ) ;
2013-04-19 20:57:43 +04: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 06:02:12 +04:00
return PTR_ERR ( skb ) ;
2013-04-19 20:57:43 +04: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 ;
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 ) ;
2015-04-06 10:52:12 +03:00
btintel_check_bdaddr ( hdev ) ;
2013-04-19 20:57:43 +04: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 ) ;
2015-04-06 10:52:12 +03:00
btintel_check_bdaddr ( hdev ) ;
2013-04-19 20:57:43 +04: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 06:02:12 +04:00
return PTR_ERR ( skb ) ;
2013-04-19 20:57:43 +04:00
}
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 06:02:12 +04:00
return PTR_ERR ( skb ) ;
2013-04-19 20:57:43 +04:00
}
kfree_skb ( skb ) ;
BT_INFO ( " %s: Intel Bluetooth firmware patch completed and activated " ,
hdev - > name ) ;
2015-04-06 10:52:12 +03:00
btintel_check_bdaddr ( hdev ) ;
2013-04-19 20:57:43 +04: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 06:02:12 +04:00
return PTR_ERR ( skb ) ;
2013-04-19 20:57:43 +04:00
}
kfree_skb ( skb ) ;
BT_INFO ( " %s: Intel Bluetooth firmware patch completed " , hdev - > name ) ;
2014-07-02 14:06:45 +04:00
2015-04-06 10:52:12 +03:00
btintel_check_bdaddr ( hdev ) ;
2013-04-19 20:57:43 +04: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 06:02:12 +04:00
return PTR_ERR ( skb ) ;
2013-04-19 20:57:43 +04:00
}
kfree_skb ( skb ) ;
BT_INFO ( " %s: Intel Bluetooth firmware patch completed and deactivated " ,
hdev - > name ) ;
2015-04-06 10:52:12 +03:00
btintel_check_bdaddr ( hdev ) ;
2013-04-19 20:57:43 +04:00
return 0 ;
}
2015-01-27 08:33:48 +03:00
static int inject_cmd_complete ( struct hci_dev * hdev , __u16 opcode )
{
struct sk_buff * skb ;
struct hci_event_hdr * hdr ;
struct hci_ev_cmd_complete * evt ;
skb = bt_skb_alloc ( sizeof ( * hdr ) + sizeof ( * evt ) + 1 , GFP_ATOMIC ) ;
if ( ! skb )
return - ENOMEM ;
hdr = ( struct hci_event_hdr * ) skb_put ( skb , sizeof ( * hdr ) ) ;
hdr - > evt = HCI_EV_CMD_COMPLETE ;
hdr - > plen = sizeof ( * evt ) + 1 ;
evt = ( struct hci_ev_cmd_complete * ) skb_put ( skb , sizeof ( * evt ) ) ;
evt - > ncmd = 0x01 ;
evt - > opcode = cpu_to_le16 ( opcode ) ;
* skb_put ( skb , 1 ) = 0x00 ;
bt_cb ( skb ) - > pkt_type = HCI_EVENT_PKT ;
return hci_recv_frame ( hdev , skb ) ;
}
static int btusb_recv_bulk_intel ( struct btusb_data * data , void * buffer ,
int count )
{
/* When the device is in bootloader mode, then it can send
* events via the bulk endpoint . These events are treated the
* same way as the ones received from the interrupt endpoint .
*/
if ( test_bit ( BTUSB_BOOTLOADER , & data - > flags ) )
return btusb_recv_intr ( data , buffer , count ) ;
return btusb_recv_bulk ( data , buffer , count ) ;
}
2015-04-09 10:35:19 +03:00
static void btusb_intel_bootup ( struct btusb_data * data , const void * ptr ,
unsigned int len )
{
const struct intel_bootup * evt = ptr ;
if ( len ! = sizeof ( * evt ) )
return ;
if ( test_and_clear_bit ( BTUSB_BOOTING , & data - > flags ) ) {
smp_mb__after_atomic ( ) ;
wake_up_bit ( & data - > flags , BTUSB_BOOTING ) ;
}
}
static void btusb_intel_secure_send_result ( struct btusb_data * data ,
const void * ptr , unsigned int len )
{
const struct intel_secure_send_result * evt = ptr ;
if ( len ! = sizeof ( * evt ) )
return ;
if ( evt - > result )
set_bit ( BTUSB_FIRMWARE_FAILED , & data - > flags ) ;
if ( test_and_clear_bit ( BTUSB_DOWNLOADING , & data - > flags ) & &
test_bit ( BTUSB_FIRMWARE_LOADED , & data - > flags ) ) {
smp_mb__after_atomic ( ) ;
wake_up_bit ( & data - > flags , BTUSB_DOWNLOADING ) ;
}
}
2015-01-27 08:33:48 +03:00
static int btusb_recv_event_intel ( struct hci_dev * hdev , struct sk_buff * skb )
{
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
if ( test_bit ( BTUSB_BOOTLOADER , & data - > flags ) ) {
struct hci_event_hdr * hdr = ( void * ) skb - > data ;
2015-04-09 10:35:19 +03:00
if ( skb - > len > HCI_EVENT_HDR_SIZE & & hdr - > evt = = 0xff & &
hdr - > plen > 0 ) {
const void * ptr = skb - > data + HCI_EVENT_HDR_SIZE + 1 ;
unsigned int len = skb - > len - HCI_EVENT_HDR_SIZE - 1 ;
switch ( skb - > data [ 2 ] ) {
case 0x02 :
/* When switching to the operational firmware
* the device sends a vendor specific event
* indicating that the bootup completed .
*/
btusb_intel_bootup ( data , ptr , len ) ;
break ;
case 0x06 :
/* When the firmware loading completes the
* device sends out a vendor specific event
* indicating the result of the firmware
* loading .
*/
btusb_intel_secure_send_result ( data , ptr , len ) ;
break ;
2015-01-30 11:58:55 +03:00
}
2015-01-27 08:33:48 +03:00
}
}
return hci_recv_frame ( hdev , skb ) ;
}
static int btusb_send_frame_intel ( struct hci_dev * hdev , struct sk_buff * skb )
{
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
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 :
if ( test_bit ( BTUSB_BOOTLOADER , & data - > flags ) ) {
struct hci_command_hdr * cmd = ( void * ) skb - > data ;
__u16 opcode = le16_to_cpu ( cmd - > opcode ) ;
/* When in bootloader mode and the command 0xfc09
* is received , it needs to be send down the
* bulk endpoint . So allocate a bulk URB instead .
*/
if ( opcode = = 0xfc09 )
urb = alloc_bulk_urb ( hdev , skb ) ;
else
urb = alloc_ctrl_urb ( hdev , skb ) ;
/* When the 0xfc01 command is issued to boot into
* the operational firmware , it will actually not
* send a command complete event . To keep the flow
* control working inject that event here .
*/
if ( opcode = = 0xfc01 )
inject_cmd_complete ( hdev , opcode ) ;
} else {
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 ;
}
static int btusb_intel_secure_send ( struct hci_dev * hdev , u8 fragment_type ,
u32 plen , const void * param )
{
while ( plen > 0 ) {
struct sk_buff * skb ;
u8 cmd_param [ 253 ] , fragment_len = ( plen > 252 ) ? 252 : plen ;
cmd_param [ 0 ] = fragment_type ;
memcpy ( cmd_param + 1 , param , fragment_len ) ;
skb = __hci_cmd_sync ( hdev , 0xfc09 , fragment_len + 1 ,
cmd_param , HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) )
return PTR_ERR ( skb ) ;
kfree_skb ( skb ) ;
plen - = fragment_len ;
param + = fragment_len ;
}
return 0 ;
}
static void btusb_intel_version_info ( struct hci_dev * hdev ,
struct intel_version * ver )
{
const char * variant ;
switch ( ver - > fw_variant ) {
case 0x06 :
variant = " Bootloader " ;
break ;
case 0x23 :
variant = " Firmware " ;
break ;
default :
return ;
}
BT_INFO ( " %s: %s revision %u.%u build %u week %u %u " , hdev - > name ,
variant , ver - > fw_revision > > 4 , ver - > fw_revision & 0x0f ,
ver - > fw_build_num , ver - > fw_build_ww , 2000 + ver - > fw_build_yy ) ;
}
static int btusb_setup_intel_new ( struct hci_dev * hdev )
{
static const u8 reset_param [ ] = { 0x00 , 0x01 , 0x00 , 0x01 ,
0x00 , 0x08 , 0x04 , 0x00 } ;
struct btusb_data * data = hci_get_drvdata ( hdev ) ;
struct sk_buff * skb ;
struct intel_version * ver ;
struct intel_boot_params * params ;
const struct firmware * fw ;
const u8 * fw_ptr ;
char fwname [ 64 ] ;
ktime_t calltime , delta , rettime ;
unsigned long long duration ;
int err ;
BT_DBG ( " %s " , hdev - > name ) ;
calltime = ktime_get ( ) ;
/* Read the Intel version information to determine if the device
* is in bootloader mode or if it already has operational firmware
* loaded .
*/
skb = __hci_cmd_sync ( hdev , 0xfc05 , 0 , NULL , HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) ) {
BT_ERR ( " %s: Reading Intel version information failed (%ld) " ,
hdev - > name , PTR_ERR ( skb ) ) ;
return PTR_ERR ( skb ) ;
}
if ( skb - > len ! = sizeof ( * ver ) ) {
BT_ERR ( " %s: Intel version event size mismatch " , hdev - > name ) ;
kfree_skb ( skb ) ;
return - EILSEQ ;
}
ver = ( struct intel_version * ) skb - > data ;
/* The hardware platform number has a fixed value of 0x37 and
* for now only accept this single value .
*/
if ( ver - > hw_platform ! = 0x37 ) {
BT_ERR ( " %s: Unsupported Intel hardware platform (%u) " ,
hdev - > name , ver - > hw_platform ) ;
kfree_skb ( skb ) ;
return - EINVAL ;
}
/* At the moment only the hardware variant iBT 3.0 (LnP/SfP) is
* supported by this firmware loading method . This check has been
* put in place to ensure correct forward compatibility options
* when newer hardware variants come along .
*/
if ( ver - > hw_variant ! = 0x0b ) {
BT_ERR ( " %s: Unsupported Intel hardware variant (%u) " ,
hdev - > name , ver - > hw_variant ) ;
kfree_skb ( skb ) ;
return - EINVAL ;
}
btusb_intel_version_info ( hdev , ver ) ;
/* The firmware variant determines if the device is in bootloader
* mode or is running operational firmware . The value 0x06 identifies
* the bootloader and the value 0x23 identifies the operational
* firmware .
*
* When the operational firmware is already present , then only
* the check for valid Bluetooth device address is needed . This
* determines if the device will be added as configured or
* unconfigured controller .
*
* It is not possible to use the Secure Boot Parameters in this
* case since that command is only available in bootloader mode .
*/
if ( ver - > fw_variant = = 0x23 ) {
kfree_skb ( skb ) ;
clear_bit ( BTUSB_BOOTLOADER , & data - > flags ) ;
2015-04-06 10:52:12 +03:00
btintel_check_bdaddr ( hdev ) ;
2015-01-27 08:33:48 +03:00
return 0 ;
}
/* If the device is not in bootloader mode, then the only possible
* choice is to return an error and abort the device initialization .
*/
if ( ver - > fw_variant ! = 0x06 ) {
BT_ERR ( " %s: Unsupported Intel firmware variant (%u) " ,
hdev - > name , ver - > fw_variant ) ;
kfree_skb ( skb ) ;
return - ENODEV ;
}
kfree_skb ( skb ) ;
/* Read the secure boot parameters to identify the operating
* details of the bootloader .
*/
skb = __hci_cmd_sync ( hdev , 0xfc0d , 0 , NULL , HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) ) {
BT_ERR ( " %s: Reading Intel boot parameters failed (%ld) " ,
hdev - > name , PTR_ERR ( skb ) ) ;
return PTR_ERR ( skb ) ;
}
if ( skb - > len ! = sizeof ( * params ) ) {
BT_ERR ( " %s: Intel boot parameters size mismatch " , hdev - > name ) ;
kfree_skb ( skb ) ;
return - EILSEQ ;
}
params = ( struct intel_boot_params * ) skb - > data ;
BT_INFO ( " %s: Device revision is %u " , hdev - > name ,
le16_to_cpu ( params - > dev_revid ) ) ;
BT_INFO ( " %s: Secure boot is %s " , hdev - > name ,
params - > secure_boot ? " enabled " : " disabled " ) ;
BT_INFO ( " %s: Minimum firmware build %u week %u %u " , hdev - > name ,
params - > min_fw_build_nn , params - > min_fw_build_cw ,
2000 + params - > min_fw_build_yy ) ;
/* It is required that every single firmware fragment is acknowledged
* with a command complete event . If the boot parameters indicate
* that this bootloader does not send them , then abort the setup .
*/
if ( params - > limited_cce ! = 0x00 ) {
BT_ERR ( " %s: Unsupported Intel firmware loading method (%u) " ,
hdev - > name , params - > limited_cce ) ;
kfree_skb ( skb ) ;
return - EINVAL ;
}
/* If the OTP has no valid Bluetooth device address, then there will
* also be no valid address for the operational firmware .
*/
if ( ! bacmp ( & params - > otp_bdaddr , BDADDR_ANY ) ) {
BT_INFO ( " %s: No device address configured " , hdev - > name ) ;
set_bit ( HCI_QUIRK_INVALID_BDADDR , & hdev - > quirks ) ;
}
/* With this Intel bootloader only the hardware variant and device
* revision information are used to select the right firmware .
*
* Currently this bootloader support is limited to hardware variant
* iBT 3.0 ( LnP / SfP ) which is identified by the value 11 ( 0x0b ) .
*/
snprintf ( fwname , sizeof ( fwname ) , " intel/ibt-11-%u.sfi " ,
le16_to_cpu ( params - > dev_revid ) ) ;
err = request_firmware ( & fw , fwname , & hdev - > dev ) ;
if ( err < 0 ) {
BT_ERR ( " %s: Failed to load Intel firmware file (%d) " ,
hdev - > name , err ) ;
kfree_skb ( skb ) ;
return err ;
}
BT_INFO ( " %s: Found device firmware: %s " , hdev - > name , fwname ) ;
kfree_skb ( skb ) ;
if ( fw - > size < 644 ) {
BT_ERR ( " %s: Invalid size of firmware file (%zu) " ,
hdev - > name , fw - > size ) ;
err = - EBADF ;
goto done ;
}
set_bit ( BTUSB_DOWNLOADING , & data - > flags ) ;
/* Start the firmware download transaction with the Init fragment
* represented by the 128 bytes of CSS header .
*/
err = btusb_intel_secure_send ( hdev , 0x00 , 128 , fw - > data ) ;
if ( err < 0 ) {
BT_ERR ( " %s: Failed to send firmware header (%d) " ,
hdev - > name , err ) ;
goto done ;
}
/* Send the 256 bytes of public key information from the firmware
* as the PKey fragment .
*/
err = btusb_intel_secure_send ( hdev , 0x03 , 256 , fw - > data + 128 ) ;
if ( err < 0 ) {
BT_ERR ( " %s: Failed to send firmware public key (%d) " ,
hdev - > name , err ) ;
goto done ;
}
/* Send the 256 bytes of signature information from the firmware
* as the Sign fragment .
*/
err = btusb_intel_secure_send ( hdev , 0x02 , 256 , fw - > data + 388 ) ;
if ( err < 0 ) {
BT_ERR ( " %s: Failed to send firmware signature (%d) " ,
hdev - > name , err ) ;
goto done ;
}
fw_ptr = fw - > data + 644 ;
while ( fw_ptr - fw - > data < fw - > size ) {
struct hci_command_hdr * cmd = ( void * ) fw_ptr ;
u8 cmd_len ;
cmd_len = sizeof ( * cmd ) + cmd - > plen ;
/* Send each command from the firmware data buffer as
* a single Data fragment .
*/
err = btusb_intel_secure_send ( hdev , 0x01 , cmd_len , fw_ptr ) ;
if ( err < 0 ) {
BT_ERR ( " %s: Failed to send firmware data (%d) " ,
hdev - > name , err ) ;
goto done ;
}
fw_ptr + = cmd_len ;
}
2015-01-28 12:58:40 +03:00
set_bit ( BTUSB_FIRMWARE_LOADED , & data - > flags ) ;
2015-01-30 11:58:54 +03:00
BT_INFO ( " %s: Waiting for firmware download to complete " , hdev - > name ) ;
2015-01-27 08:33:48 +03:00
/* Before switching the device into operational mode and with that
* booting the loaded firmware , wait for the bootloader notification
* that all fragments have been successfully received .
*
2015-01-30 11:58:54 +03:00
* When the event processing receives the notification , then the
* BTUSB_DOWNLOADING flag will be cleared .
*
* The firmware loading should not take longer than 5 seconds
* and thus just timeout if that happens and fail the setup
* of this device .
2015-01-27 08:33:48 +03:00
*/
2015-02-14 10:33:35 +03:00
err = wait_on_bit_timeout ( & data - > flags , BTUSB_DOWNLOADING ,
TASK_INTERRUPTIBLE ,
msecs_to_jiffies ( 5000 ) ) ;
2015-01-30 11:58:54 +03:00
if ( err = = 1 ) {
BT_ERR ( " %s: Firmware loading interrupted " , hdev - > name ) ;
err = - EINTR ;
goto done ;
}
2015-01-27 08:33:48 +03:00
2015-01-30 11:58:54 +03:00
if ( err ) {
BT_ERR ( " %s: Firmware loading timeout " , hdev - > name ) ;
err = - ETIMEDOUT ;
goto done ;
2015-01-27 08:33:48 +03:00
}
if ( test_bit ( BTUSB_FIRMWARE_FAILED , & data - > flags ) ) {
BT_ERR ( " %s: Firmware loading failed " , hdev - > name ) ;
err = - ENOEXEC ;
goto done ;
}
rettime = ktime_get ( ) ;
delta = ktime_sub ( rettime , calltime ) ;
duration = ( unsigned long long ) ktime_to_ns ( delta ) > > 10 ;
BT_INFO ( " %s: Firmware loaded in %llu usecs " , hdev - > name , duration ) ;
done :
release_firmware ( fw ) ;
if ( err < 0 )
return err ;
calltime = ktime_get ( ) ;
set_bit ( BTUSB_BOOTING , & data - > flags ) ;
skb = __hci_cmd_sync ( hdev , 0xfc01 , sizeof ( reset_param ) , reset_param ,
HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) )
return PTR_ERR ( skb ) ;
kfree_skb ( skb ) ;
/* The bootloader will not indicate when the device is ready. This
* is done by the operational firmware sending bootup notification .
2015-01-30 11:58:55 +03:00
*
* Booting into operational firmware should not take longer than
* 1 second . However if that happens , then just fail the setup
* since something went wrong .
2015-01-27 08:33:48 +03:00
*/
2015-01-30 11:58:55 +03:00
BT_INFO ( " %s: Waiting for device to boot " , hdev - > name ) ;
2015-01-27 08:33:48 +03:00
2015-02-14 10:33:35 +03:00
err = wait_on_bit_timeout ( & data - > flags , BTUSB_BOOTING ,
TASK_INTERRUPTIBLE ,
msecs_to_jiffies ( 1000 ) ) ;
2015-01-27 08:33:48 +03:00
2015-01-30 11:58:55 +03:00
if ( err = = 1 ) {
BT_ERR ( " %s: Device boot interrupted " , hdev - > name ) ;
return - EINTR ;
}
2015-01-27 08:33:48 +03:00
2015-01-30 11:58:55 +03:00
if ( err ) {
BT_ERR ( " %s: Device boot timeout " , hdev - > name ) ;
return - ETIMEDOUT ;
2015-01-27 08:33:48 +03:00
}
rettime = ktime_get ( ) ;
delta = ktime_sub ( rettime , calltime ) ;
duration = ( unsigned long long ) ktime_to_ns ( delta ) > > 10 ;
BT_INFO ( " %s: Device booted in %llu usecs " , hdev - > name , duration ) ;
clear_bit ( BTUSB_BOOTLOADER , & data - > flags ) ;
return 0 ;
}
2015-01-28 22:09:56 +03:00
static void btusb_hw_error_intel ( struct hci_dev * hdev , u8 code )
{
struct sk_buff * skb ;
u8 type = 0x00 ;
BT_ERR ( " %s: Hardware error 0x%2.2x " , hdev - > name , code ) ;
skb = __hci_cmd_sync ( hdev , HCI_OP_RESET , 0 , NULL , HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) ) {
BT_ERR ( " %s: Reset after hardware error failed (%ld) " ,
hdev - > name , PTR_ERR ( skb ) ) ;
return ;
}
kfree_skb ( skb ) ;
skb = __hci_cmd_sync ( hdev , 0xfc22 , 1 , & type , HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) ) {
BT_ERR ( " %s: Retrieving Intel exception info failed (%ld) " ,
hdev - > name , PTR_ERR ( skb ) ) ;
return ;
}
if ( skb - > len ! = 13 ) {
BT_ERR ( " %s: Exception info size mismatch " , hdev - > name ) ;
kfree_skb ( skb ) ;
return ;
}
BT_ERR ( " %s: Exception info %s " , hdev - > name , ( char * ) ( skb - > data + 1 ) ) ;
kfree_skb ( skb ) ;
}
2015-02-13 20:20:52 +03:00
static int btusb_shutdown_intel ( struct hci_dev * hdev )
{
struct sk_buff * skb ;
long ret ;
/* Some platforms have an issue with BT LED when the interface is
* down or BT radio is turned off , which takes 5 seconds to BT LED
* goes off . This command turns off the BT LED immediately .
*/
skb = __hci_cmd_sync ( hdev , 0xfc3f , 0 , NULL , HCI_INIT_TIMEOUT ) ;
if ( IS_ERR ( skb ) ) {
ret = PTR_ERR ( skb ) ;
BT_ERR ( " %s: turning off Intel device LED failed (%ld) " ,
hdev - > name , ret ) ;
return ret ;
}
kfree_skb ( skb ) ;
return 0 ;
}
2014-07-19 01:47:06 +04: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-12-12 21:58:05 +03: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 ;
}
2015-02-16 02:07:33 +03:00
# define QCA_DFU_PACKET_LEN 4096
# define QCA_GET_TARGET_VERSION 0x09
# define QCA_CHECK_STATUS 0x05
# define QCA_DFU_DOWNLOAD 0x01
# define QCA_SYSCFG_UPDATED 0x40
# define QCA_PATCH_UPDATED 0x80
# define QCA_DFU_TIMEOUT 3000
struct qca_version {
__le32 rom_version ;
__le32 patch_version ;
__le32 ram_version ;
__le32 ref_clock ;
__u8 reserved [ 4 ] ;
} __packed ;
struct qca_rampatch_version {
__le16 rom_version ;
__le16 patch_version ;
} __packed ;
struct qca_device_info {
2015-03-11 02:34:58 +03:00
u32 rom_version ;
u8 rampatch_hdr ; /* length of header in rampatch */
u8 nvm_hdr ; /* length of header in NVM */
u8 ver_offset ; /* offset of version structure in rampatch */
2015-02-16 02:07:33 +03:00
} ;
static const struct qca_device_info qca_devices_table [ ] = {
{ 0x00000100 , 20 , 4 , 10 } , /* Rome 1.0 */
{ 0x00000101 , 20 , 4 , 10 } , /* Rome 1.1 */
2015-05-21 05:24:27 +03:00
{ 0x00000200 , 28 , 4 , 18 } , /* Rome 2.0 */
2015-02-16 02:07:33 +03:00
{ 0x00000201 , 28 , 4 , 18 } , /* Rome 2.1 */
{ 0x00000300 , 28 , 4 , 18 } , /* Rome 3.0 */
{ 0x00000302 , 28 , 4 , 18 } , /* Rome 3.2 */
} ;
static int btusb_qca_send_vendor_req ( struct hci_dev * hdev , u8 request ,
void * data , u16 size )
{
struct btusb_data * btdata = hci_get_drvdata ( hdev ) ;
struct usb_device * udev = btdata - > udev ;
int pipe , err ;
u8 * buf ;
buf = kmalloc ( size , GFP_KERNEL ) ;
if ( ! buf )
return - ENOMEM ;
/* Found some of USB hosts have IOT issues with ours so that we should
* not wait until HCI layer is ready .
*/
pipe = usb_rcvctrlpipe ( udev , 0 ) ;
err = usb_control_msg ( udev , pipe , request , USB_TYPE_VENDOR | USB_DIR_IN ,
0 , 0 , buf , size , USB_CTRL_SET_TIMEOUT ) ;
if ( err < 0 ) {
BT_ERR ( " %s: Failed to access otp area (%d) " , hdev - > name , err ) ;
goto done ;
}
memcpy ( data , buf , size ) ;
done :
kfree ( buf ) ;
return err ;
}
static int btusb_setup_qca_download_fw ( struct hci_dev * hdev ,
const struct firmware * firmware ,
size_t hdr_size )
{
struct btusb_data * btdata = hci_get_drvdata ( hdev ) ;
struct usb_device * udev = btdata - > udev ;
size_t count , size , sent = 0 ;
int pipe , len , err ;
u8 * buf ;
buf = kmalloc ( QCA_DFU_PACKET_LEN , GFP_KERNEL ) ;
if ( ! buf )
return - ENOMEM ;
count = firmware - > size ;
size = min_t ( size_t , count , hdr_size ) ;
memcpy ( buf , firmware - > data , size ) ;
/* USB patches should go down to controller through USB path
* because binary format fits to go down through USB channel .
* USB control path is for patching headers and USB bulk is for
* patch body .
*/
pipe = usb_sndctrlpipe ( udev , 0 ) ;
err = usb_control_msg ( udev , pipe , QCA_DFU_DOWNLOAD , USB_TYPE_VENDOR ,
0 , 0 , buf , size , USB_CTRL_SET_TIMEOUT ) ;
if ( err < 0 ) {
BT_ERR ( " %s: Failed to send headers (%d) " , hdev - > name , err ) ;
goto done ;
}
sent + = size ;
count - = size ;
while ( count ) {
size = min_t ( size_t , count , QCA_DFU_PACKET_LEN ) ;
memcpy ( buf , firmware - > data + sent , size ) ;
pipe = usb_sndbulkpipe ( udev , 0x02 ) ;
err = usb_bulk_msg ( udev , pipe , buf , size , & len ,
QCA_DFU_TIMEOUT ) ;
if ( err < 0 ) {
BT_ERR ( " %s: Failed to send body at %zd of %zd (%d) " ,
hdev - > name , sent , firmware - > size , err ) ;
break ;
}
if ( size ! = len ) {
BT_ERR ( " %s: Failed to get bulk buffer " , hdev - > name ) ;
err = - EILSEQ ;
break ;
}
sent + = size ;
count - = size ;
}
done :
kfree ( buf ) ;
return err ;
}
static int btusb_setup_qca_load_rampatch ( struct hci_dev * hdev ,
struct qca_version * ver ,
const struct qca_device_info * info )
{
struct qca_rampatch_version * rver ;
const struct firmware * fw ;
2015-03-11 02:34:58 +03:00
u32 ver_rom , ver_patch ;
u16 rver_rom , rver_patch ;
2015-02-16 02:07:33 +03:00
char fwname [ 64 ] ;
int err ;
2015-03-11 02:34:58 +03:00
ver_rom = le32_to_cpu ( ver - > rom_version ) ;
ver_patch = le32_to_cpu ( ver - > patch_version ) ;
snprintf ( fwname , sizeof ( fwname ) , " qca/rampatch_usb_%08x.bin " , ver_rom ) ;
2015-02-16 02:07:33 +03:00
err = request_firmware ( & fw , fwname , & hdev - > dev ) ;
if ( err ) {
BT_ERR ( " %s: failed to request rampatch file: %s (%d) " ,
hdev - > name , fwname , err ) ;
return err ;
}
BT_INFO ( " %s: using rampatch file: %s " , hdev - > name , fwname ) ;
2015-03-11 02:34:58 +03:00
2015-02-16 02:07:33 +03:00
rver = ( struct qca_rampatch_version * ) ( fw - > data + info - > ver_offset ) ;
2015-03-11 02:34:58 +03:00
rver_rom = le16_to_cpu ( rver - > rom_version ) ;
rver_patch = le16_to_cpu ( rver - > patch_version ) ;
2015-02-16 02:07:33 +03:00
BT_INFO ( " %s: QCA: patch rome 0x%x build 0x%x, firmware rome 0x%x "
2015-03-11 02:34:58 +03:00
" build 0x%x " , hdev - > name , rver_rom , rver_patch , ver_rom ,
ver_patch ) ;
2015-02-16 02:07:33 +03:00
2015-03-11 02:34:58 +03:00
if ( rver_rom ! = ver_rom | | rver_patch < = ver_patch ) {
2015-02-16 02:07:33 +03:00
BT_ERR ( " %s: rampatch file version did not match with firmware " ,
hdev - > name ) ;
err = - EINVAL ;
goto done ;
}
err = btusb_setup_qca_download_fw ( hdev , fw , info - > rampatch_hdr ) ;
done :
release_firmware ( fw ) ;
return err ;
}
static int btusb_setup_qca_load_nvm ( struct hci_dev * hdev ,
struct qca_version * ver ,
const struct qca_device_info * info )
{
const struct firmware * fw ;
char fwname [ 64 ] ;
int err ;
snprintf ( fwname , sizeof ( fwname ) , " qca/nvm_usb_%08x.bin " ,
le32_to_cpu ( ver - > rom_version ) ) ;
err = request_firmware ( & fw , fwname , & hdev - > dev ) ;
if ( err ) {
BT_ERR ( " %s: failed to request NVM file: %s (%d) " ,
hdev - > name , fwname , err ) ;
return err ;
}
BT_INFO ( " %s: using NVM file: %s " , hdev - > name , fwname ) ;
err = btusb_setup_qca_download_fw ( hdev , fw , info - > nvm_hdr ) ;
release_firmware ( fw ) ;
return err ;
}
static int btusb_setup_qca ( struct hci_dev * hdev )
{
const struct qca_device_info * info = NULL ;
struct qca_version ver ;
2015-03-11 02:34:58 +03:00
u32 ver_rom ;
2015-02-16 02:07:33 +03:00
u8 status ;
int i , err ;
err = btusb_qca_send_vendor_req ( hdev , QCA_GET_TARGET_VERSION , & ver ,
2015-04-17 00:15:50 +03:00
sizeof ( ver ) ) ;
2015-02-16 02:07:33 +03:00
if ( err < 0 )
return err ;
2015-03-11 02:34:58 +03:00
ver_rom = le32_to_cpu ( ver . rom_version ) ;
2015-02-16 02:07:33 +03:00
for ( i = 0 ; i < ARRAY_SIZE ( qca_devices_table ) ; i + + ) {
2015-03-11 02:34:58 +03:00
if ( ver_rom = = qca_devices_table [ i ] . rom_version )
2015-02-16 02:07:33 +03:00
info = & qca_devices_table [ i ] ;
}
if ( ! info ) {
BT_ERR ( " %s: don't support firmware rome 0x%x " , hdev - > name ,
2015-03-11 02:34:58 +03:00
ver_rom ) ;
2015-02-16 02:07:33 +03:00
return - ENODEV ;
}
err = btusb_qca_send_vendor_req ( hdev , QCA_CHECK_STATUS , & status ,
sizeof ( status ) ) ;
if ( err < 0 )
return err ;
if ( ! ( status & QCA_PATCH_UPDATED ) ) {
err = btusb_setup_qca_load_rampatch ( hdev , & ver , info ) ;
if ( err < 0 )
return err ;
}
if ( ! ( status & QCA_SYSCFG_UPDATED ) ) {
err = btusb_setup_qca_load_nvm ( hdev , & ver , info ) ;
if ( err < 0 )
return err ;
}
return 0 ;
}
2007-10-20 16:12:34 +04:00
static int btusb_probe ( struct usb_interface * intf ,
2014-09-16 06:44:50 +04:00
const struct usb_device_id * id )
2007-10-20 16:12:34 +04: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-08 00:26:56 +04:00
/* interface numbers are hardcoded in the spec */
2007-10-20 16:12:34 +04:00
if ( intf - > cur_altsetting - > desc . bInterfaceNumber ! = 0 )
return - ENODEV ;
if ( ! id - > driver_info ) {
const struct usb_device_id * match ;
2014-09-16 06:44:50 +04:00
2007-10-20 16:12:34 +04:00
match = usb_match_id ( intf , blacklist_table ) ;
if ( match )
id = match ;
}
2008-08-08 00:26:56 +04:00
if ( id - > driver_info = = BTUSB_IGNORE )
return - ENODEV ;
2011-07-01 10:02:36 +04: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 11:08:39 +04:00
data = devm_kzalloc ( & intf - > dev , sizeof ( * data ) , GFP_KERNEL ) ;
2007-10-20 16:12:34 +04: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 11:08:39 +04:00
if ( ! data - > intr_ep | | ! data - > bulk_tx_ep | | ! data - > bulk_rx_ep )
2007-10-20 16:12:34 +04:00
return - ENODEV ;
2015-01-29 07:27:34 +03:00
if ( id - > driver_info & BTUSB_AMP ) {
data - > cmdreq_type = USB_TYPE_CLASS | 0x01 ;
data - > cmdreq = 0x2b ;
} else {
data - > cmdreq_type = USB_TYPE_CLASS ;
data - > cmdreq = 0x00 ;
}
2008-11-30 14:17:26 +03:00
2007-10-20 16:12:34 +04:00
data - > udev = interface_to_usbdev ( intf ) ;
2008-09-23 02:16:36 +04:00
data - > intf = intf ;
2007-10-20 16:12:34 +04:00
INIT_WORK ( & data - > work , btusb_work ) ;
2009-08-25 01:44:59 +04:00
INIT_WORK ( & data - > waker , btusb_waker ) ;
2014-09-16 10:00:29 +04:00
init_usb_anchor ( & data - > deferred ) ;
init_usb_anchor ( & data - > tx_anchor ) ;
2009-08-25 01:44:59 +04:00
spin_lock_init ( & data - > txlock ) ;
2007-10-20 16:12:34 +04:00
init_usb_anchor ( & data - > intr_anchor ) ;
init_usb_anchor ( & data - > bulk_anchor ) ;
2008-08-18 15:23:52 +04:00
init_usb_anchor ( & data - > isoc_anchor ) ;
2014-09-16 10:00:29 +04:00
spin_lock_init ( & data - > rxlock ) ;
2007-10-20 16:12:34 +04:00
2015-01-27 08:33:48 +03:00
if ( id - > driver_info & BTUSB_INTEL_NEW ) {
data - > recv_event = btusb_recv_event_intel ;
data - > recv_bulk = btusb_recv_bulk_intel ;
set_bit ( BTUSB_BOOTLOADER , & data - > flags ) ;
} else {
data - > recv_event = hci_recv_frame ;
data - > recv_bulk = btusb_recv_bulk ;
}
2014-11-03 07:16:07 +03:00
2007-10-20 16:12:34 +04:00
hdev = hci_alloc_dev ( ) ;
2012-07-27 11:08:39 +04:00
if ( ! hdev )
2007-10-20 16:12:34 +04:00
return - ENOMEM ;
2010-02-08 17:27:07 +03:00
hdev - > bus = HCI_USB ;
2012-02-10 00:58:32 +04:00
hci_set_drvdata ( hdev , data ) ;
2007-10-20 16:12:34 +04:00
2015-01-29 07:27:34 +03:00
if ( id - > driver_info & BTUSB_AMP )
hdev - > dev_type = HCI_AMP ;
else
hdev - > dev_type = HCI_BREDR ;
2007-10-20 16:12:34 +04:00
data - > hdev = hdev ;
SET_HCIDEV_DEV ( hdev , & intf - > dev ) ;
2013-04-10 19:11:35 +04: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 16:12:34 +04:00
2015-04-06 08:52:14 +03:00
# ifdef CONFIG_BT_HCIBTUSB_BCM
2014-07-02 02:53:48 +04:00
if ( id - > driver_info & BTUSB_BCM_PATCHRAM ) {
2015-04-06 08:52:14 +03:00
hdev - > setup = btbcm_setup_patchram ;
2015-04-06 08:52:11 +03:00
hdev - > set_bdaddr = btbcm_set_bdaddr ;
2014-07-02 02:53:48 +04:00
}
2014-05-09 02:50:01 +04:00
2015-04-06 08:52:15 +03:00
if ( id - > driver_info & BTUSB_BCM_APPLE )
2015-04-06 08:52:14 +03:00
hdev - > setup = btbcm_setup_apple ;
# endif
2015-03-22 17:52:38 +03:00
2014-07-02 13:25:25 +04:00
if ( id - > driver_info & BTUSB_INTEL ) {
2013-04-19 20:57:43 +04:00
hdev - > setup = btusb_setup_intel ;
2015-02-13 20:20:52 +03:00
hdev - > shutdown = btusb_shutdown_intel ;
2015-04-06 10:52:12 +03:00
hdev - > set_bdaddr = btintel_set_bdaddr ;
2015-01-31 05:55:58 +03:00
set_bit ( HCI_QUIRK_STRICT_DUPLICATE_FILTER , & hdev - > quirks ) ;
2015-03-17 19:04:16 +03:00
set_bit ( HCI_QUIRK_SIMULTANEOUS_DISCOVERY , & hdev - > quirks ) ;
2014-07-02 13:25:25 +04:00
}
2013-04-19 20:57:43 +04:00
2015-01-27 08:33:48 +03:00
if ( id - > driver_info & BTUSB_INTEL_NEW ) {
hdev - > send = btusb_send_frame_intel ;
hdev - > setup = btusb_setup_intel_new ;
2015-01-28 22:09:56 +03:00
hdev - > hw_error = btusb_hw_error_intel ;
2015-04-06 10:52:12 +03:00
hdev - > set_bdaddr = btintel_set_bdaddr ;
2015-02-02 10:57:18 +03:00
set_bit ( HCI_QUIRK_STRICT_DUPLICATE_FILTER , & hdev - > quirks ) ;
2015-01-27 08:33:48 +03:00
}
2014-07-19 01:47:06 +04:00
if ( id - > driver_info & BTUSB_MARVELL )
hdev - > set_bdaddr = btusb_set_bdaddr_marvell ;
2015-01-03 10:35:20 +03:00
if ( id - > driver_info & BTUSB_SWAVE ) {
set_bit ( HCI_QUIRK_FIXUP_INQUIRY_MODE , & hdev - > quirks ) ;
2014-12-26 06:42:33 +03:00
set_bit ( HCI_QUIRK_BROKEN_LOCAL_COMMANDS , & hdev - > quirks ) ;
2015-01-03 10:35:20 +03:00
}
2014-12-26 06:42:33 +03:00
2014-07-06 15:29:58 +04:00
if ( id - > driver_info & BTUSB_INTEL_BOOT )
set_bit ( HCI_QUIRK_RAW_DEVICE , & hdev - > quirks ) ;
2015-01-29 21:38:34 +03:00
if ( id - > driver_info & BTUSB_ATH3012 ) {
2014-12-12 21:58:05 +03:00
hdev - > set_bdaddr = btusb_set_bdaddr_ath3012 ;
2015-03-17 19:04:15 +03:00
set_bit ( HCI_QUIRK_SIMULTANEOUS_DISCOVERY , & hdev - > quirks ) ;
2015-01-29 21:38:34 +03:00
set_bit ( HCI_QUIRK_STRICT_DUPLICATE_FILTER , & hdev - > quirks ) ;
}
2014-12-12 21:58:05 +03:00
2015-02-16 02:07:33 +03:00
if ( id - > driver_info & BTUSB_QCA_ROME ) {
data - > setup_on_usb = btusb_setup_qca ;
hdev - > set_bdaddr = btusb_set_bdaddr_ath3012 ;
}
2015-05-14 11:49:09 +03:00
# ifdef CONFIG_BT_HCIBTUSB_RTL
2015-04-16 23:09:55 +03:00
if ( id - > driver_info & BTUSB_REALTEK )
2015-05-14 11:49:09 +03:00
hdev - > setup = btrtl_setup_realtek ;
# endif
2015-04-16 23:09:55 +03:00
2015-01-29 07:27:34 +03:00
if ( id - > driver_info & BTUSB_AMP ) {
/* AMP controllers do not support SCO packets */
data - > isoc = NULL ;
} else {
/* Interface numbers are hardcoded in the specification */
data - > isoc = usb_ifnum_to_if ( data - > udev , 1 ) ;
}
2008-08-18 15:23:52 +04:00
2008-11-30 14:17:26 +03:00
if ( ! reset )
2012-05-23 14:35:46 +04:00
set_bit ( HCI_QUIRK_RESET_ON_CLOSE , & hdev - > quirks ) ;
2008-08-08 00:26:56 +04: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 15:23:52 +04:00
if ( id - > driver_info & BTUSB_BROKEN_ISOC )
data - > isoc = NULL ;
2008-11-30 14:17:26 +03:00
if ( id - > driver_info & BTUSB_DIGIANSWER ) {
data - > cmdreq_type = USB_TYPE_VENDOR ;
2012-05-23 14:35:46 +04:00
set_bit ( HCI_QUIRK_RESET_ON_CLOSE , & hdev - > quirks ) ;
2008-11-30 14:17:26 +03:00
}
if ( id - > driver_info & BTUSB_CSR ) {
struct usb_device * udev = data - > udev ;
2014-01-03 15:02:36 +04:00
u16 bcdDevice = le16_to_cpu ( udev - > descriptor . bcdDevice ) ;
2008-11-30 14:17:26 +03:00
/* Old firmware would otherwise execute USB reset */
2014-01-03 15:02:36 +04:00
if ( bcdDevice < 0x117 )
2012-05-23 14:35:46 +04:00
set_bit ( HCI_QUIRK_RESET_ON_CLOSE , & hdev - > quirks ) ;
2014-01-03 15:02:36 +04:00
/* Fake CSR devices with broken commands */
if ( bcdDevice < = 0x100 )
hdev - > setup = btusb_setup_csr ;
2015-03-17 19:04:17 +03:00
set_bit ( HCI_QUIRK_SIMULTANEOUS_DISCOVERY , & hdev - > quirks ) ;
2008-11-30 14:17:26 +03:00
}
2008-08-08 00:26:56 +04:00
if ( id - > driver_info & BTUSB_SNIFFER ) {
2008-08-18 15:23:52 +04:00
struct usb_device * udev = data - > udev ;
2008-08-08 00:26:56 +04:00
2008-11-30 14:17:26 +03:00
/* New sniffer firmware has crippled HCI interface */
2008-08-08 00:26:56 +04:00
if ( le16_to_cpu ( udev - > descriptor . bcdDevice ) > 0x997 )
set_bit ( HCI_QUIRK_RAW_DEVICE , & hdev - > quirks ) ;
}
2014-07-06 16:53:54 +04: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 15:23:52 +04:00
if ( data - > isoc ) {
err = usb_driver_claim_interface ( & btusb_driver ,
2014-09-16 06:44:50 +04:00
data - > isoc , data ) ;
2008-08-18 15:23:52 +04:00
if ( err < 0 ) {
hci_free_dev ( hdev ) ;
return err ;
}
}
2007-10-20 16:12:34 +04: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 02:16:36 +04:00
usb_set_intfdata ( data - > intf , NULL ) ;
if ( data - > isoc )
usb_set_intfdata ( data - > isoc , NULL ) ;
2007-10-20 16:12:34 +04:00
hci_unregister_dev ( hdev ) ;
2008-09-23 02:16:36 +04: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 ) ;
2007-10-20 16:12:34 +04:00
hci_free_dev ( hdev ) ;
}
2009-08-25 01:44:59 +04:00
# ifdef CONFIG_PM
2008-11-30 14:17:14 +03: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-25 01:44:59 +04:00
spin_lock_irq ( & data - > txlock ) ;
2011-08-20 01:49:48 +04:00
if ( ! ( PMSG_IS_AUTO ( message ) & & data - > tx_in_flight ) ) {
2009-08-25 01:44:59 +04: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 14:17:14 +03:00
cancel_work_sync ( & data - > work ) ;
2009-08-25 01:44:59 +04:00
btusb_stop_traffic ( data ) ;
2008-11-30 14:17:14 +03:00
usb_kill_anchored_urbs ( & data - > tx_anchor ) ;
return 0 ;
}
2009-08-25 01:44:59 +04: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 14:17:14 +03: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-25 01:44:59 +04:00
int err = 0 ;
2008-11-30 14:17:14 +03:00
BT_DBG ( " intf %p " , intf ) ;
if ( - - data - > suspend_count )
return 0 ;
if ( ! test_bit ( HCI_RUNNING , & hdev - > flags ) )
2009-08-25 01:44:59 +04:00
goto done ;
2008-11-30 14:17:14 +03: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-25 01:44:59 +04:00
goto failed ;
2008-11-30 14:17:14 +03:00
}
}
if ( test_bit ( BTUSB_BULK_RUNNING , & data - > flags ) ) {
2009-02-04 19:41:38 +03:00
err = btusb_submit_bulk_urb ( hdev , GFP_NOIO ) ;
if ( err < 0 ) {
2008-11-30 14:17:14 +03:00
clear_bit ( BTUSB_BULK_RUNNING , & data - > flags ) ;
2009-08-25 01:44:59 +04:00
goto failed ;
}
btusb_submit_bulk_urb ( hdev , GFP_NOIO ) ;
2008-11-30 14:17:14 +03: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-25 01:44:59 +04: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 14:17:14 +03:00
return 0 ;
2009-08-25 01:44:59 +04: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 14:17:14 +03:00
}
2009-08-25 01:44:59 +04:00
# endif
2008-11-30 14:17:14 +03:00
2007-10-20 16:12:34 +04:00
static struct usb_driver btusb_driver = {
. name = " btusb " ,
. probe = btusb_probe ,
. disconnect = btusb_disconnect ,
2009-08-25 01:44:59 +04:00
# ifdef CONFIG_PM
2008-11-30 14:17:14 +03:00
. suspend = btusb_suspend ,
. resume = btusb_resume ,
2009-08-25 01:44:59 +04:00
# endif
2007-10-20 16:12:34 +04:00
. id_table = btusb_table ,
2009-08-25 01:44:59 +04:00
. supports_autosuspend = 1 ,
2012-04-23 21:08:51 +04:00
. disable_hub_initiated_lpm = 1 ,
2007-10-20 16:12:34 +04:00
} ;
2011-11-18 21:47:34 +04:00
module_usb_driver ( btusb_driver ) ;
2007-10-20 16:12:34 +04:00
2008-08-08 00:26:56 +04: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 16:12:34 +04:00
MODULE_AUTHOR ( " Marcel Holtmann <marcel@holtmann.org> " ) ;
MODULE_DESCRIPTION ( " Generic Bluetooth USB driver ver " VERSION ) ;
MODULE_VERSION ( VERSION ) ;
MODULE_LICENSE ( " GPL " ) ;