All of lore.kernel.org
 help / color / mirror / Atom feed
From: Marcel Holtmann <marcel@holtmann.org>
To: Tedd Ho-Jeong An <tedd.an@intel.com>
Cc: linux-bluetooth <linux-bluetooth@vger.kernel.org>,
	johan.hedberg@intel.com, albert.o.ho@intel.com,
	tedd.hj.an@gmail.com
Subject: Re: [RFC 1/2] Bluetooth: Add driver extension for vendor specific init
Date: Thu, 04 Oct 2012 12:20:13 +0200	[thread overview]
Message-ID: <1349346013.27233.28.camel@aeonflux> (raw)
In-Reply-To: <39660287.XHkFNqYcyS@tedd-ubuntu>

Hi Tedd,

> This patch provides an extension of btusb to support device vendor
> can implement their own module to execute the vendor specific
> device initialization before the stack sends generic BT device
> initialization.
> 
> Signed-off-by: Tedd Ho-Jeong An <tedd.an@intel.com>
> ---
>  drivers/bluetooth/btusb.c        |  191 +++++++++++++++++++++++++-------------
>  drivers/bluetooth/btusb.h        |   53 +++++++++++
>  include/net/bluetooth/hci_core.h |   10 ++
>  net/bluetooth/hci_core.c         |   15 ++-
>  4 files changed, 204 insertions(+), 65 deletions(-)
>  create mode 100644 drivers/bluetooth/btusb.h
> 
> diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> index f637c25..afa1558 100644
> --- a/drivers/bluetooth/btusb.c
> +++ b/drivers/bluetooth/btusb.c
> @@ -26,6 +26,7 @@
>  
>  #include <net/bluetooth/bluetooth.h>
>  #include <net/bluetooth/hci_core.h>
> +#include "btusb.h"
>  
>  #define VERSION "0.6"
>  
> @@ -39,14 +40,59 @@ static bool reset = 1;
>  
>  static struct usb_driver btusb_driver;
>  
> -#define BTUSB_IGNORE		0x01
> -#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
> -#define BTUSB_ATH3012		0x80
> +/*
> + * Create btusb_driver_info struct for each driver_info flags used by
> + * blacklist since vendor's btusb driver will return btusb_driver_info struct.
> + */
> +
> +/*
> + * if the device is set to this, this menas that the device is generic and
> + * doesn't require any vendor specific handling
> + */
> +static const struct btusb_driver_info generic = {
> +	.description	= "BTUSB Generic",
> +	.flags		= BTUSB_GENERIC,
> +};
> +
> +static const struct btusb_driver_info ignore = {
> +	.description	= "BTUSB Ignore",
> +	.flags		= BTUSB_IGNORE,
> +};

I like the effort, but I think you went a little bit too far here. For
these simple ones, we can easily keep our simple blacklist. It keeps the
code more readable than this part. But I do appreciate the attempt in
unifying this.

> +
> +static const struct btusb_driver_info digianswer = {
> +	.description	= "BTUSB DIGIANSWER",
> +	.flags		= BTUSB_DIGIANSWER,
> +};
> +
> +static const struct btusb_driver_info csr = {
> +	.description	= "BTUSB CSR",
> +	.flags		= BTUSB_CSR,
> +};
> +
> +static const struct btusb_driver_info sniffer = {
> +	.description	= "BTUSB Sniffer",
> +	.flags		= BTUSB_SNIFFER,
> +};
> +
> +static const struct btusb_driver_info bcm92035 = {
> +	.description	= "BTUSB BCM92035",
> +	.flags		= BTUSB_BCM92035,
> +};
> +
> +static const struct btusb_driver_info broken_isoc = {
> +	.description	= "BTUSB Broken ISOC",
> +	.flags		= BTUSB_BROKEN_ISOC,
> +};
> +
> +static const struct btusb_driver_info wrong_sco_mtu = {
> +	.description	= "BTUSB Wrong SCO MTU",
> +	.flags		= BTUSB_WRONG_SCO_MTU,
> +};
> +
> +static const struct btusb_driver_info ath3012 = {
> +	.description	= "BTUSB Ath3012",
> +	.flags		= BTUSB_ATH3012,
> +};
>  
>  static struct usb_device_id btusb_table[] = {
>  	/* Generic Bluetooth USB device */
> @@ -105,90 +151,89 @@ static struct usb_device_id btusb_table[] = {
>  
>  	{ }	/* Terminating entry */
>  };
> -
>  MODULE_DEVICE_TABLE(usb, btusb_table);
>  
>  static struct usb_device_id blacklist_table[] = {
>  	/* CSR BlueCore devices */
> -	{ USB_DEVICE(0x0a12, 0x0001), .driver_info = BTUSB_CSR },
> +	{ USB_DEVICE(0x0a12, 0x0001), .driver_info = (unsigned long) &csr },

Keep the blacklist_table as it is. The important table to modify is
btusb_table and use a common driver_info that will be shared between
drivers.

That would also make it simple to just add BTUSB_IGNORE or a new
BTUSB_VENDOR flag to call out the drivers that have a separate driver
with a vendor init function, but would match the Bluetooth general USB
descriptors.

Then over time, we can move the BTUSB_BCM92035 for example into its
separate driver. And also deal with cleaning up all the other Broadcom
specialties.

>  
>  	/* Broadcom BCM2033 without firmware */
> -	{ USB_DEVICE(0x0a5c, 0x2033), .driver_info = BTUSB_IGNORE },
> +	{ USB_DEVICE(0x0a5c, 0x2033), .driver_info = (unsigned long) &ignore },
>  
>  	/* Atheros 3011 with sflash firmware */
> -	{ USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
> -	{ USB_DEVICE(0x0cf3, 0xe019), .driver_info = BTUSB_IGNORE },
> -	{ USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE },
> -	{ USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
> -	{ USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
> +	{ USB_DEVICE(0x0cf3, 0x3002), .driver_info = (unsigned long) &ignore },
> +	{ USB_DEVICE(0x0cf3, 0xe019), .driver_info = (unsigned long) &ignore },
> +	{ USB_DEVICE(0x13d3, 0x3304), .driver_info = (unsigned long) &ignore },
> +	{ USB_DEVICE(0x0930, 0x0215), .driver_info = (unsigned long) &ignore },
> +	{ USB_DEVICE(0x0489, 0xe03d), .driver_info = (unsigned long) &ignore },
>  
>  	/* Atheros AR9285 Malbec with sflash firmware */
> -	{ USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
> +	{ USB_DEVICE(0x03f0, 0x311d), .driver_info = (unsigned long) &ignore },
>  
>  	/* Atheros 3012 with sflash firmware */
> -	{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
> -	{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
> -	{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
> -	{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
> -	{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
> -	{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
> -	{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
> +	{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = (unsigned long) &ath3012 },
> +	{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = (unsigned long) &ath3012 },
> +	{ USB_DEVICE(0x13d3, 0x3375), .driver_info = (unsigned long) &ath3012 },
> +	{ USB_DEVICE(0x04ca, 0x3005), .driver_info = (unsigned long) &ath3012 },
> +	{ USB_DEVICE(0x13d3, 0x3362), .driver_info = (unsigned long) &ath3012 },
> +	{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = (unsigned long) &ath3012 },
> +	{ USB_DEVICE(0x0930, 0x0219), .driver_info = (unsigned long) &ath3012 },
>  
>  	/* Atheros AR5BBU12 with sflash firmware */
> -	{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
> +	{ USB_DEVICE(0x0489, 0xe02c), .driver_info = (unsigned long) &ignore },
>  
>  	/* Atheros AR5BBU12 with sflash firmware */
> -	{ USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
> +	{ USB_DEVICE(0x0489, 0xe03c), .driver_info = (unsigned long) &ath3012 },
>  
>  	/* Broadcom BCM2035 */
> -	{ USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
> -	{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
> -	{ USB_DEVICE(0x0a5c, 0x2009), .driver_info = BTUSB_BCM92035 },
> +	{ USB_DEVICE(0x0a5c, 0x2035), .driver_info = (unsigned long) &wrong_sco_mtu },
> +	{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = (unsigned long) &wrong_sco_mtu },
> +	{ USB_DEVICE(0x0a5c, 0x2009), .driver_info = (unsigned long) &bcm92035 },
>  
>  	/* Broadcom BCM2045 */
> -	{ USB_DEVICE(0x0a5c, 0x2039), .driver_info = BTUSB_WRONG_SCO_MTU },
> -	{ USB_DEVICE(0x0a5c, 0x2101), .driver_info = BTUSB_WRONG_SCO_MTU },
> +	{ USB_DEVICE(0x0a5c, 0x2039), .driver_info = (unsigned long) &wrong_sco_mtu },
> +	{ USB_DEVICE(0x0a5c, 0x2101), .driver_info = (unsigned long) &wrong_sco_mtu },
>  
>  	/* IBM/Lenovo ThinkPad with Broadcom chip */
> -	{ USB_DEVICE(0x0a5c, 0x201e), .driver_info = BTUSB_WRONG_SCO_MTU },
> -	{ USB_DEVICE(0x0a5c, 0x2110), .driver_info = BTUSB_WRONG_SCO_MTU },
> +	{ USB_DEVICE(0x0a5c, 0x201e), .driver_info = (unsigned long) &wrong_sco_mtu },
> +	{ USB_DEVICE(0x0a5c, 0x2110), .driver_info = (unsigned long) &wrong_sco_mtu },
>  
>  	/* HP laptop with Broadcom chip */
> -	{ USB_DEVICE(0x03f0, 0x171d), .driver_info = BTUSB_WRONG_SCO_MTU },
> +	{ USB_DEVICE(0x03f0, 0x171d), .driver_info = (unsigned long) &wrong_sco_mtu },
>  
>  	/* Dell laptop with Broadcom chip */
> -	{ USB_DEVICE(0x413c, 0x8126), .driver_info = BTUSB_WRONG_SCO_MTU },
> +	{ USB_DEVICE(0x413c, 0x8126), .driver_info = (unsigned long) &wrong_sco_mtu },
>  
>  	/* Dell Wireless 370 and 410 devices */
> -	{ USB_DEVICE(0x413c, 0x8152), .driver_info = BTUSB_WRONG_SCO_MTU },
> -	{ USB_DEVICE(0x413c, 0x8156), .driver_info = BTUSB_WRONG_SCO_MTU },
> +	{ USB_DEVICE(0x413c, 0x8152), .driver_info = (unsigned long) &wrong_sco_mtu },
> +	{ USB_DEVICE(0x413c, 0x8156), .driver_info = (unsigned long) &wrong_sco_mtu },
>  
>  	/* 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 },
> +	{ USB_DEVICE(0x050d, 0x0012), .driver_info = (unsigned long) &wrong_sco_mtu },
> +	{ USB_DEVICE(0x050d, 0x0013), .driver_info = (unsigned long) &wrong_sco_mtu },
>  
>  	/* Asus WL-BTD202 device */
> -	{ USB_DEVICE(0x0b05, 0x1715), .driver_info = BTUSB_WRONG_SCO_MTU },
> +	{ USB_DEVICE(0x0b05, 0x1715), .driver_info = (unsigned long) &wrong_sco_mtu },
>  
>  	/* Kensington Bluetooth USB adapter */
> -	{ USB_DEVICE(0x047d, 0x105e), .driver_info = BTUSB_WRONG_SCO_MTU },
> +	{ USB_DEVICE(0x047d, 0x105e), .driver_info = (unsigned long) &wrong_sco_mtu },
>  
>  	/* 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 },
> +	{ USB_DEVICE(0x0400, 0x0807), .driver_info = (unsigned long) &broken_isoc },
> +	{ USB_DEVICE(0x0400, 0x080a), .driver_info = (unsigned long) &broken_isoc },
>  
>  	/* CONWISE Technology based adapters with buggy SCO support */
> -	{ USB_DEVICE(0x0e5e, 0x6622), .driver_info = BTUSB_BROKEN_ISOC },
> +	{ USB_DEVICE(0x0e5e, 0x6622), .driver_info = (unsigned long) &broken_isoc },
>  
>  	/* Digianswer devices */
> -	{ USB_DEVICE(0x08fd, 0x0001), .driver_info = BTUSB_DIGIANSWER },
> -	{ USB_DEVICE(0x08fd, 0x0002), .driver_info = BTUSB_IGNORE },
> +	{ USB_DEVICE(0x08fd, 0x0001), .driver_info = (unsigned long) &digianswer },
> +	{ USB_DEVICE(0x08fd, 0x0002), .driver_info = (unsigned long) &ignore },
>  
>  	/* CSR BlueCore Bluetooth Sniffer */
> -	{ USB_DEVICE(0x0a12, 0x0002), .driver_info = BTUSB_SNIFFER },
> +	{ USB_DEVICE(0x0a12, 0x0002), .driver_info = (unsigned long) &sniffer },
>  
>  	/* Frontline ComProbe Bluetooth Sniffer */
> -	{ USB_DEVICE(0x16d3, 0x0002), .driver_info = BTUSB_SNIFFER },
> +	{ USB_DEVICE(0x16d3, 0x0002), .driver_info = (unsigned long) &sniffer },
>  
>  	{ }	/* Terminating entry */
>  };
> @@ -910,12 +955,12 @@ static void btusb_waker(struct work_struct *work)
>  	usb_autopm_put_interface(data->intf);
>  }
>  
> -static int btusb_probe(struct usb_interface *intf,
> -				const struct usb_device_id *id)
> +int btusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
>  {
>  	struct usb_endpoint_descriptor *ep_desc;
>  	struct btusb_data *data;
>  	struct hci_dev *hdev;
> +	struct btusb_driver_info *info;
>  	int i, err;
>  
>  	BT_DBG("intf %p id %p", intf, id);
> @@ -931,19 +976,28 @@ static int btusb_probe(struct usb_interface *intf,
>  			id = match;
>  	}
>  
> -	if (id->driver_info == BTUSB_IGNORE)
> +	/*
> +	 * Make sure the driver_info is not null or 0 because the code below
> +	 * need to access the flags
> +	 */
> +	if (!id->driver_info)
> +		info = (struct btusb_driver_info *) &generic;
> +	else
> +		info = (struct btusb_driver_info *) id->driver_info;
> +
> +	if (info->flags == BTUSB_IGNORE)
>  		return -ENODEV;
>  
> -	if (ignore_dga && id->driver_info & BTUSB_DIGIANSWER)
> +	if (ignore_dga && (info->flags & BTUSB_DIGIANSWER))
>  		return -ENODEV;
>  
> -	if (ignore_csr && id->driver_info & BTUSB_CSR)
> +	if (ignore_csr && (info->flags & BTUSB_CSR))
>  		return -ENODEV;
>  
> -	if (ignore_sniffer && id->driver_info & BTUSB_SNIFFER)
> +	if (ignore_sniffer && (info->flags & BTUSB_SNIFFER))
>  		return -ENODEV;
>  
> -	if (id->driver_info & BTUSB_ATH3012) {
> +	if (info->flags & BTUSB_ATH3012) {
>  		struct usb_device *udev = interface_to_usbdev(intf);
>  
>  		/* Old firmware would otherwise let ath3k driver load
> @@ -1012,26 +1066,30 @@ static int btusb_probe(struct usb_interface *intf,
>  	hdev->send     = btusb_send_frame;
>  	hdev->notify   = btusb_notify;
>  
> +	/* vendor specific device initialization routines */
> +	hdev->vsdev_init = info->vsdev_init;
> +	hdev->vsdev_event = info->vsdev_event;
> +
>  	/* Interface numbers are hardcoded in the specification */
>  	data->isoc = usb_ifnum_to_if(data->udev, 1);
>  
>  	if (!reset)
>  		set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
>  
> -	if (force_scofix || id->driver_info & BTUSB_WRONG_SCO_MTU) {
> +	if (force_scofix || (info->flags & BTUSB_WRONG_SCO_MTU)) {
>  		if (!disable_scofix)
>  			set_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks);
>  	}
>  
> -	if (id->driver_info & BTUSB_BROKEN_ISOC)
> +	if (info->flags & BTUSB_BROKEN_ISOC)
>  		data->isoc = NULL;
>  
> -	if (id->driver_info & BTUSB_DIGIANSWER) {
> +	if (info->flags & BTUSB_DIGIANSWER) {
>  		data->cmdreq_type = USB_TYPE_VENDOR;
>  		set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
>  	}
>  
> -	if (id->driver_info & BTUSB_CSR) {
> +	if (info->flags & BTUSB_CSR) {
>  		struct usb_device *udev = data->udev;
>  
>  		/* Old firmware would otherwise execute USB reset */
> @@ -1039,7 +1097,7 @@ static int btusb_probe(struct usb_interface *intf,
>  			set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
>  	}
>  
> -	if (id->driver_info & BTUSB_SNIFFER) {
> +	if (info->flags & BTUSB_SNIFFER) {
>  		struct usb_device *udev = data->udev;
>  
>  		/* New sniffer firmware has crippled HCI interface */
> @@ -1049,7 +1107,7 @@ static int btusb_probe(struct usb_interface *intf,
>  		data->isoc = NULL;
>  	}
>  
> -	if (id->driver_info & BTUSB_BCM92035) {
> +	if (info->flags & BTUSB_BCM92035) {
>  		unsigned char cmd[] = { 0x3b, 0xfc, 0x01, 0x00 };
>  		struct sk_buff *skb;
>  
> @@ -1079,8 +1137,9 @@ static int btusb_probe(struct usb_interface *intf,
>  
>  	return 0;
>  }
> +EXPORT_SYMBOL_GPL(btusb_probe);
>  
> -static void btusb_disconnect(struct usb_interface *intf)
> +void btusb_disconnect(struct usb_interface *intf)
>  {
>  	struct btusb_data *data = usb_get_intfdata(intf);
>  	struct hci_dev *hdev;
> @@ -1105,9 +1164,10 @@ static void btusb_disconnect(struct usb_interface *intf)
>  
>  	hci_free_dev(hdev);
>  }
> +EXPORT_SYMBOL_GPL(btusb_disconnect);
>  
>  #ifdef CONFIG_PM
> -static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
> +int btusb_suspend(struct usb_interface *intf, pm_message_t message)
>  {
>  	struct btusb_data *data = usb_get_intfdata(intf);
>  
> @@ -1133,6 +1193,7 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
>  
>  	return 0;
>  }
> +EXPORT_SYMBOL_GPL(btusb_suspend);
>  
>  static void play_deferred(struct btusb_data *data)
>  {
> @@ -1149,7 +1210,7 @@ static void play_deferred(struct btusb_data *data)
>  	usb_scuttle_anchored_urbs(&data->deferred);
>  }
>  
> -static int btusb_resume(struct usb_interface *intf)
> +int btusb_resume(struct usb_interface *intf)
>  {
>  	struct btusb_data *data = usb_get_intfdata(intf);
>  	struct hci_dev *hdev = data->hdev;
> @@ -1205,8 +1266,10 @@ done:
>  
>  	return err;
>  }
> +EXPORT_SYMBOL_GPL(btusb_resume);
>  #endif
>  
> +
>  static struct usb_driver btusb_driver = {
>  	.name		= "btusb",
>  	.probe		= btusb_probe,
> diff --git a/drivers/bluetooth/btusb.h b/drivers/bluetooth/btusb.h
> new file mode 100644
> index 0000000..c26a845
> --- /dev/null
> +++ b/drivers/bluetooth/btusb.h
> @@ -0,0 +1,53 @@
> +/*
> + *
> + *  Generic Bluetooth USB driver
> + *
> + *  Copyright (C) 2005-2008  Marcel Holtmann <marcel@holtmann.org>
> + *
> + *
> + *  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
> + *
> + */
> +#ifndef _BTUSB_H
> +#define _BTUSB_H
> +
> +struct btusb_driver_info {
> +	char	*description;
> +	int	flags;
> +#define BTUSB_GENERIC		0x00
> +#define BTUSB_IGNORE		0x01
> +#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
> +#define BTUSB_ATH3012		0x80
> +
> +	/* entry point for vendor specific device initialization */
> +	int	(*vsdev_init)(struct hci_dev *hdev);

Keep it simple. Call this (*setup).
> +
> +	/* event handler during vendor specific device initiation phase */
> +	void	(*vsdev_event)(struct hci_dev *hdev, struct sk_buff *skb);

And this just (*event).

I am still curious if we would need the event part at all when using HCI
command handling with callbacks, but I know at least that CSR is not
following the HCI specification for command + event, so it might be a
good idea.

> +};
> +
> +extern int btusb_probe(struct usb_interface *, const struct usb_device_id *);
> +extern void btusb_disconnect(struct usb_interface *);
> +#ifdef CONFIG_PM
> +extern int btusb_suspend(struct usb_interface *, pm_message_t);
> +extern int btusb_resume(struct usb_interface *);
> +#endif
> +
> +#endif /* _BTUSB_H */
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index 6a3337e..4af601d 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -275,6 +275,16 @@ struct hci_dev {
>  	int (*send)(struct sk_buff *skb);
>  	void (*notify)(struct hci_dev *hdev, unsigned int evt);
>  	int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg);
> +
> +	/*
> +	 * TODO: Added following members for vendor specific initialization to
> +	 * make the bluetooth.ko transparent to the interface.
> +	 * These members are set by the vendor provided driver
> +	 */
> +	int			vsdev_init_done;

For this, please use dev_flags. No need waste space with another
variable.

> +	void			*vsdev_priv_data;
> +	int (*vsdev_init)(struct hci_dev *hdev);
> +	void (*vsdev_event)(struct hci_dev *hdev, struct sk_buff *skb);
>  };

Rather like vendor_setup and vendor_event here. I do not even want to
know what vs stands for ;)

Hope we are not getting into trouble with driver id tables normally
being const.

>  
>  struct hci_conn {
> diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> index e407051..80aa13f 100644
> --- a/net/bluetooth/hci_core.c
> +++ b/net/bluetooth/hci_core.c
> @@ -685,6 +685,15 @@ int hci_dev_open(__u16 dev)
>  		set_bit(HCI_INIT, &hdev->flags);
>  		hdev->init_last_cmd = 0;
>  
> +		/* vendor specific device initialization */
> +		if (hdev->vsdev_init) {
> +			ret = hdev->vsdev_init(hdev);
> +			hdev->vsdev_init_done = 1;
> +			hdev->vsdev_event = NULL;
> +			if (ret < 0)
> +				goto done;
> +		}
> +

Do you really want to do this on every hciconfig hci0 up? I assumed this
is a one time task. So you might better look at hci_power_on() for this.

Is a HCI_Reset command unloading the firmware patches.

>  		ret = __hci_request(hdev, hci_init_req, 0, HCI_INIT_TIMEOUT);
>  
>  		if (lmp_host_le_capable(hdev))
> @@ -2119,6 +2128,7 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param)
>  
>  	return 0;
>  }
> +EXPORT_SYMBOL(hci_send_cmd);
>  
>  /* Get data from the previously sent command */
>  void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode)
> @@ -2800,7 +2810,10 @@ static void hci_rx_work(struct work_struct *work)
>  		switch (bt_cb(skb)->pkt_type) {
>  		case HCI_EVENT_PKT:
>  			BT_DBG("%s Event packet", hdev->name);
> -			hci_event_packet(hdev, skb);
> +			if (hdev->vsdev_event && !hdev->vsdev_init_done)
> +				hdev->vsdev_event(hdev, skb);
> +			else
> +				hci_event_packet(hdev, skb);
>  			break;

Not going through hci_event_packet is a bad idea. That will screw over
the flow control handling for commands.

Regards

Marcel



  reply	other threads:[~2012-10-04 10:20 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-09-22  1:59 [RFC 1/2] Bluetooth: Add driver extension for vendor specific init Tedd Ho-Jeong An
2012-10-04 10:20 ` Marcel Holtmann [this message]
2012-10-24  8:27   ` Ho, Albert O
2012-10-24 15:18     ` Marcel Holtmann
2012-10-25  6:38       ` Ho, Albert O

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1349346013.27233.28.camel@aeonflux \
    --to=marcel@holtmann.org \
    --cc=albert.o.ho@intel.com \
    --cc=johan.hedberg@intel.com \
    --cc=linux-bluetooth@vger.kernel.org \
    --cc=tedd.an@intel.com \
    --cc=tedd.hj.an@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.