Commit 4523ef76 authored by Maksim Krasnyanskiy's avatar Maksim Krasnyanskiy Committed by Maksim Krasnyanskiy

Bluetooth USB driver update.

Remove firmware loading support, it's handled in hotplug.
Other minor fixes.
parent e4c609fe
......@@ -26,15 +26,6 @@ CONFIG_BLUEZ_HCIUSB
Say Y here to compile support for Bluetooth USB devices into the
kernel or say M to compile it as module (hci_usb.o).
HCI USB firmware download support
CONFIG_BLUEZ_USB_FW_LOAD
Firmware download support for Bluetooth USB devices.
This support is required for devices like Broadcom BCM2033.
HCI USB driver uses external firmware downloader program provided
in BlueFW package.
For more information, see <http://bluez.sf.net/>.
HCI USB zero packet support
CONFIG_BLUEZ_USB_ZERO_PACKET
Support for USB zero packets.
......
......@@ -3,7 +3,6 @@ comment 'Bluetooth device drivers'
dep_tristate 'HCI USB driver' CONFIG_BLUEZ_HCIUSB $CONFIG_BLUEZ $CONFIG_USB
if [ "$CONFIG_BLUEZ_HCIUSB" != "n" ]; then
bool ' Firmware download support' CONFIG_BLUEZ_USB_FW_LOAD
bool ' USB zero packet support' CONFIG_BLUEZ_USB_ZERO_PACKET
fi
......
......@@ -28,9 +28,9 @@
* Copyright (c) 2000 Greg Kroah-Hartman <greg@kroah.com>
* Copyright (c) 2000 Mark Douglas Corner <mcorner@umich.edu>
*
* $Id: hci_usb.c,v 1.6 2002/04/17 17:37:20 maxk Exp $
* $Id: hci_usb.c,v 1.8 2002/07/18 17:23:09 maxk Exp $
*/
#define VERSION "2.0"
#define VERSION "2.1"
#include <linux/config.h>
#include <linux/module.h>
......@@ -73,7 +73,7 @@
static struct usb_driver hci_usb_driver;
static struct usb_device_id usb_bluetooth_ids [] = {
static struct usb_device_id bluetooth_ids[] = {
/* Generic Bluetooth USB device */
{ USB_DEVICE_INFO(HCI_DEV_CLASS, HCI_DEV_SUBCLASS, HCI_DEV_PROTOCOL) },
......@@ -83,7 +83,14 @@ static struct usb_device_id usb_bluetooth_ids [] = {
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, usb_bluetooth_ids);
MODULE_DEVICE_TABLE (usb, bluetooth_ids);
static struct usb_device_id ignore_ids[] = {
/* Broadcom BCM2033 without firmware */
{ USB_DEVICE(0x0a5c, 0x2033) },
{ } /* Terminating entry */
};
static void hci_usb_interrupt(struct urb *urb);
static void hci_usb_rx_complete(struct urb *urb);
......@@ -193,22 +200,26 @@ static int hci_usb_open(struct hci_dev *hdev)
{
struct hci_usb *husb = (struct hci_usb *) hdev->driver_data;
int i, err;
long flags;
unsigned long flags;
BT_DBG("%s", hdev->name);
if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
return 0;
MOD_INC_USE_COUNT;
write_lock_irqsave(&husb->completion_lock, flags);
err = hci_usb_enable_intr(husb);
if (!err) {
for (i = 0; i < HCI_MAX_BULK_TX; i++)
for (i = 0; i < HCI_MAX_BULK_RX; i++)
hci_usb_rx_submit(husb, NULL);
} else
} else {
clear_bit(HCI_RUNNING, &hdev->flags);
MOD_DEC_USE_COUNT;
}
write_unlock_irqrestore(&husb->completion_lock, flags);
return err;
}
......@@ -246,7 +257,7 @@ static inline void hci_usb_unlink_urbs(struct hci_usb *husb)
static int hci_usb_close(struct hci_dev *hdev)
{
struct hci_usb *husb = (struct hci_usb *) hdev->driver_data;
long flags;
unsigned long flags;
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
return 0;
......@@ -260,6 +271,8 @@ static int hci_usb_close(struct hci_dev *hdev)
hci_usb_flush(hdev);
write_unlock_irqrestore(&husb->completion_lock, flags);
MOD_DEC_USE_COUNT;
return 0;
}
......@@ -587,78 +600,11 @@ static void hci_usb_destruct(struct hci_dev *hdev)
husb = (struct hci_usb *) hdev->driver_data;
kfree(husb);
MOD_DEC_USE_COUNT;
}
#ifdef CONFIG_BLUEZ_USB_FW_LOAD
/* Support for user mode Bluetooth USB firmware loader */
#define FW_LOADER "/sbin/bluefw"
static int errno;
static int hci_usb_fw_exec(void *dev)
{
char *envp[] = { "HOME=/", "TERM=linux",
"PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
char *argv[] = { FW_LOADER, dev, NULL };
int err;
err = exec_usermodehelper(FW_LOADER, argv, envp);
if (err)
BT_ERR("failed to exec %s %s", FW_LOADER, (char *)dev);
return err;
}
static int hci_usb_fw_load(struct usb_device *udev)
int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
sigset_t tmpsig;
char dev[16];
pid_t pid;
int result;
/* Check if root fs is mounted */
if (!current->fs->root) {
BT_ERR("root fs not mounted");
return -EPERM;
}
sprintf(dev, "%3.3d/%3.3d", udev->bus->busnum, udev->devnum);
pid = kernel_thread(hci_usb_fw_exec, (void *)dev, 0);
if (pid < 0) {
BT_ERR("fork failed, errno %d\n", -pid);
return pid;
}
/* Block signals, everything but SIGKILL/SIGSTOP */
spin_lock_irq(&current->sig->siglock);
tmpsig = current->blocked;
siginitsetinv(&current->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP));
recalc_sigpending();
spin_unlock_irq(&current->sig->siglock);
result = waitpid(pid, NULL, __WCLONE);
/* Allow signals again */
spin_lock_irq(&current->sig->siglock);
current->blocked = tmpsig;
recalc_sigpending();
spin_unlock_irq(&current->sig->siglock);
if (result != pid) {
BT_ERR("waitpid failed pid %d errno %d\n", pid, -result);
return -result;
}
return 0;
}
#endif /* CONFIG_BLUEZ_USB_FW_LOAD */
static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(intf);
struct usb_device *udev = interface_to_usbdev(intf);
struct usb_endpoint_descriptor *bulk_out_ep[HCI_MAX_IFACE_NUM];
struct usb_endpoint_descriptor *isoc_out_ep[HCI_MAX_IFACE_NUM];
struct usb_endpoint_descriptor *bulk_in_ep[HCI_MAX_IFACE_NUM];
......@@ -673,15 +619,13 @@ static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id
BT_DBG("intf %p", intf);
/* Check our black list */
if (usb_match_id(intf, ignore_ids))
return -EIO;
/* Check number of endpoints */
if (intf->altsetting[0].bNumEndpoints < 3)
return -ENODEV;
MOD_INC_USE_COUNT;
#ifdef CONFIG_BLUEZ_USB_FW_LOAD
hci_usb_fw_load(udev);
#endif
return -EIO;
memset(bulk_out_ep, 0, sizeof(bulk_out_ep));
memset(isoc_out_ep, 0, sizeof(isoc_out_ep));
......@@ -802,7 +746,6 @@ static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id
kfree(husb);
done:
MOD_DEC_USE_COUNT;
return -EIO;
}
......@@ -811,9 +754,9 @@ static void hci_usb_disconnect(struct usb_interface *intf)
struct hci_usb *husb = dev_get_drvdata(&intf->dev);
struct hci_dev *hdev;
dev_set_drvdata(&intf->dev, NULL);
if (!husb)
return;
dev_set_drvdata(&intf->dev, NULL);
hdev = &husb->hdev;
BT_DBG("%s", hdev->name);
......@@ -828,10 +771,10 @@ static void hci_usb_disconnect(struct usb_interface *intf)
}
static struct usb_driver hci_usb_driver = {
.name = "hci_usb",
.probe = hci_usb_probe,
.disconnect = hci_usb_disconnect,
.id_table = usb_bluetooth_ids,
.name = "hci_usb",
.probe = hci_usb_probe,
.disconnect = hci_usb_disconnect,
.id_table = bluetooth_ids
};
int hci_usb_init(void)
......
......@@ -55,8 +55,8 @@ struct hci_usb {
__u8 intr_ep;
__u8 intr_interval;
struct urb * intr_urb;
struct sk_buff * intr_skb;
struct urb *intr_urb;
struct sk_buff *intr_skb;
rwlock_t completion_lock;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment