mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
bluetooth: Revert drivers back to 3.0 framework
Undo driver changes that conflict with the BT core code under net/bluetooth from 3.0
This commit is contained in:
parent
7433537fe2
commit
0389df18a8
22 changed files with 417 additions and 278 deletions
|
@ -188,7 +188,7 @@ config BT_MRVL
|
||||||
The core driver to support Marvell Bluetooth devices.
|
The core driver to support Marvell Bluetooth devices.
|
||||||
|
|
||||||
This driver is required if you want to support
|
This driver is required if you want to support
|
||||||
Marvell Bluetooth devices, such as 8688/8787/8797.
|
Marvell Bluetooth devices, such as 8688/8787.
|
||||||
|
|
||||||
Say Y here to compile Marvell Bluetooth driver
|
Say Y here to compile Marvell Bluetooth driver
|
||||||
into the kernel or say M to compile it as module.
|
into the kernel or say M to compile it as module.
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
#include <net/bluetooth/bluetooth.h>
|
#include <net/bluetooth/bluetooth.h>
|
||||||
|
|
||||||
#define VERSION "1.0"
|
#define VERSION "1.0"
|
||||||
#define ATH3K_FIRMWARE "ath3k-1.fw"
|
|
||||||
|
|
||||||
#define ATH3K_DNLOAD 0x01
|
#define ATH3K_DNLOAD 0x01
|
||||||
#define ATH3K_GETSTATE 0x05
|
#define ATH3K_GETSTATE 0x05
|
||||||
|
@ -63,20 +62,12 @@ static struct usb_device_id ath3k_table[] = {
|
||||||
|
|
||||||
/* Atheros AR3011 with sflash firmware*/
|
/* Atheros AR3011 with sflash firmware*/
|
||||||
{ USB_DEVICE(0x0CF3, 0x3002) },
|
{ USB_DEVICE(0x0CF3, 0x3002) },
|
||||||
{ USB_DEVICE(0x13d3, 0x3304) },
|
|
||||||
{ USB_DEVICE(0x0930, 0x0215) },
|
|
||||||
{ USB_DEVICE(0x0489, 0xE03D) },
|
|
||||||
|
|
||||||
/* Atheros AR9285 Malbec with sflash firmware */
|
/* Atheros AR9285 Malbec with sflash firmware */
|
||||||
{ USB_DEVICE(0x03F0, 0x311D) },
|
{ USB_DEVICE(0x03F0, 0x311D) },
|
||||||
|
|
||||||
/* Atheros AR3012 with sflash firmware*/
|
/* Atheros AR3012 with sflash firmware*/
|
||||||
{ USB_DEVICE(0x0CF3, 0x3004) },
|
{ USB_DEVICE(0x0CF3, 0x3004) },
|
||||||
{ USB_DEVICE(0x0CF3, 0x311D) },
|
|
||||||
{ USB_DEVICE(0x13d3, 0x3375) },
|
|
||||||
{ USB_DEVICE(0x04CA, 0x3005) },
|
|
||||||
{ USB_DEVICE(0x13d3, 0x3362) },
|
|
||||||
{ USB_DEVICE(0x0CF3, 0xE004) },
|
|
||||||
|
|
||||||
/* Atheros AR5BBU12 with sflash firmware */
|
/* Atheros AR5BBU12 with sflash firmware */
|
||||||
{ USB_DEVICE(0x0489, 0xE02C) },
|
{ USB_DEVICE(0x0489, 0xE02C) },
|
||||||
|
@ -93,11 +84,6 @@ static struct usb_device_id ath3k_blist_tbl[] = {
|
||||||
|
|
||||||
/* Atheros AR3012 with sflash firmware*/
|
/* Atheros AR3012 with sflash firmware*/
|
||||||
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
|
{ 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 },
|
|
||||||
|
|
||||||
{ } /* Terminating entry */
|
{ } /* Terminating entry */
|
||||||
};
|
};
|
||||||
|
@ -117,7 +103,7 @@ static int ath3k_load_firmware(struct usb_device *udev,
|
||||||
|
|
||||||
pipe = usb_sndctrlpipe(udev, 0);
|
pipe = usb_sndctrlpipe(udev, 0);
|
||||||
|
|
||||||
send_buf = kmalloc(BULK_SIZE, GFP_KERNEL);
|
send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC);
|
||||||
if (!send_buf) {
|
if (!send_buf) {
|
||||||
BT_ERR("Can't allocate memory chunk for firmware");
|
BT_ERR("Can't allocate memory chunk for firmware");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -188,7 +174,7 @@ static int ath3k_load_fwfile(struct usb_device *udev,
|
||||||
|
|
||||||
count = firmware->size;
|
count = firmware->size;
|
||||||
|
|
||||||
send_buf = kmalloc(BULK_SIZE, GFP_KERNEL);
|
send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC);
|
||||||
if (!send_buf) {
|
if (!send_buf) {
|
||||||
BT_ERR("Can't allocate memory chunk for firmware");
|
BT_ERR("Can't allocate memory chunk for firmware");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -412,15 +398,9 @@ static int ath3k_probe(struct usb_interface *intf,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = request_firmware(&firmware, ATH3K_FIRMWARE, &udev->dev);
|
if (request_firmware(&firmware, "ath3k-1.fw", &udev->dev) < 0) {
|
||||||
if (ret < 0) {
|
BT_ERR("Error loading firmware");
|
||||||
if (ret == -ENOENT)
|
return -EIO;
|
||||||
BT_ERR("Firmware file \"%s\" not found",
|
|
||||||
ATH3K_FIRMWARE);
|
|
||||||
else
|
|
||||||
BT_ERR("Firmware file \"%s\" request failed (err=%d)",
|
|
||||||
ATH3K_FIRMWARE, ret);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ath3k_load_firmware(udev, firmware);
|
ret = ath3k_load_firmware(udev, firmware);
|
||||||
|
@ -441,10 +421,22 @@ static struct usb_driver ath3k_driver = {
|
||||||
.id_table = ath3k_table,
|
.id_table = ath3k_table,
|
||||||
};
|
};
|
||||||
|
|
||||||
module_usb_driver(ath3k_driver);
|
static int __init ath3k_init(void)
|
||||||
|
{
|
||||||
|
BT_INFO("Atheros AR30xx firmware driver ver %s", VERSION);
|
||||||
|
return usb_register(&ath3k_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit ath3k_exit(void)
|
||||||
|
{
|
||||||
|
usb_deregister(&ath3k_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(ath3k_init);
|
||||||
|
module_exit(ath3k_exit);
|
||||||
|
|
||||||
MODULE_AUTHOR("Atheros Communications");
|
MODULE_AUTHOR("Atheros Communications");
|
||||||
MODULE_DESCRIPTION("Atheros AR30xx firmware driver");
|
MODULE_DESCRIPTION("Atheros AR30xx firmware driver");
|
||||||
MODULE_VERSION(VERSION);
|
MODULE_VERSION(VERSION);
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_FIRMWARE(ATH3K_FIRMWARE);
|
MODULE_FIRMWARE("ath3k-1.fw");
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
|
||||||
#include <linux/atomic.h>
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
@ -66,7 +65,6 @@ struct bcm203x_data {
|
||||||
unsigned long state;
|
unsigned long state;
|
||||||
|
|
||||||
struct work_struct work;
|
struct work_struct work;
|
||||||
atomic_t shutdown;
|
|
||||||
|
|
||||||
struct urb *urb;
|
struct urb *urb;
|
||||||
unsigned char *buffer;
|
unsigned char *buffer;
|
||||||
|
@ -99,7 +97,6 @@ static void bcm203x_complete(struct urb *urb)
|
||||||
|
|
||||||
data->state = BCM203X_SELECT_MEMORY;
|
data->state = BCM203X_SELECT_MEMORY;
|
||||||
|
|
||||||
/* use workqueue to have a small delay */
|
|
||||||
schedule_work(&data->work);
|
schedule_work(&data->work);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -158,10 +155,7 @@ static void bcm203x_work(struct work_struct *work)
|
||||||
struct bcm203x_data *data =
|
struct bcm203x_data *data =
|
||||||
container_of(work, struct bcm203x_data, work);
|
container_of(work, struct bcm203x_data, work);
|
||||||
|
|
||||||
if (atomic_read(&data->shutdown))
|
if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0)
|
||||||
return;
|
|
||||||
|
|
||||||
if (usb_submit_urb(data->urb, GFP_KERNEL) < 0)
|
|
||||||
BT_ERR("Can't submit URB");
|
BT_ERR("Can't submit URB");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,7 +243,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
|
||||||
|
|
||||||
usb_set_intfdata(intf, data);
|
usb_set_intfdata(intf, data);
|
||||||
|
|
||||||
/* use workqueue to have a small delay */
|
|
||||||
schedule_work(&data->work);
|
schedule_work(&data->work);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -261,9 +254,6 @@ static void bcm203x_disconnect(struct usb_interface *intf)
|
||||||
|
|
||||||
BT_DBG("intf %p", intf);
|
BT_DBG("intf %p", intf);
|
||||||
|
|
||||||
atomic_inc(&data->shutdown);
|
|
||||||
cancel_work_sync(&data->work);
|
|
||||||
|
|
||||||
usb_kill_urb(data->urb);
|
usb_kill_urb(data->urb);
|
||||||
|
|
||||||
usb_set_intfdata(intf, NULL);
|
usb_set_intfdata(intf, NULL);
|
||||||
|
@ -281,7 +271,26 @@ static struct usb_driver bcm203x_driver = {
|
||||||
.id_table = bcm203x_table,
|
.id_table = bcm203x_table,
|
||||||
};
|
};
|
||||||
|
|
||||||
module_usb_driver(bcm203x_driver);
|
static int __init bcm203x_init(void)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
BT_INFO("Broadcom Blutonium firmware driver ver %s", VERSION);
|
||||||
|
|
||||||
|
err = usb_register(&bcm203x_driver);
|
||||||
|
if (err < 0)
|
||||||
|
BT_ERR("Failed to register USB driver");
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit bcm203x_exit(void)
|
||||||
|
{
|
||||||
|
usb_deregister(&bcm203x_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(bcm203x_init);
|
||||||
|
module_exit(bcm203x_exit);
|
||||||
|
|
||||||
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
|
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
|
||||||
MODULE_DESCRIPTION("Broadcom Blutonium firmware driver ver " VERSION);
|
MODULE_DESCRIPTION("Broadcom Blutonium firmware driver ver " VERSION);
|
||||||
|
|
|
@ -411,7 +411,7 @@ unlock:
|
||||||
|
|
||||||
static int bfusb_open(struct hci_dev *hdev)
|
static int bfusb_open(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct bfusb_data *data = hci_get_drvdata(hdev);
|
struct bfusb_data *data = hdev->driver_data;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int i, err;
|
int i, err;
|
||||||
|
|
||||||
|
@ -437,7 +437,7 @@ static int bfusb_open(struct hci_dev *hdev)
|
||||||
|
|
||||||
static int bfusb_flush(struct hci_dev *hdev)
|
static int bfusb_flush(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct bfusb_data *data = hci_get_drvdata(hdev);
|
struct bfusb_data *data = hdev->driver_data;
|
||||||
|
|
||||||
BT_DBG("hdev %p bfusb %p", hdev, data);
|
BT_DBG("hdev %p bfusb %p", hdev, data);
|
||||||
|
|
||||||
|
@ -448,7 +448,7 @@ static int bfusb_flush(struct hci_dev *hdev)
|
||||||
|
|
||||||
static int bfusb_close(struct hci_dev *hdev)
|
static int bfusb_close(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct bfusb_data *data = hci_get_drvdata(hdev);
|
struct bfusb_data *data = hdev->driver_data;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
BT_DBG("hdev %p bfusb %p", hdev, data);
|
BT_DBG("hdev %p bfusb %p", hdev, data);
|
||||||
|
@ -483,7 +483,7 @@ static int bfusb_send_frame(struct sk_buff *skb)
|
||||||
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
data = hci_get_drvdata(hdev);
|
data = hdev->driver_data;
|
||||||
|
|
||||||
switch (bt_cb(skb)->pkt_type) {
|
switch (bt_cb(skb)->pkt_type) {
|
||||||
case HCI_COMMAND_PKT:
|
case HCI_COMMAND_PKT:
|
||||||
|
@ -544,6 +544,15 @@ static int bfusb_send_frame(struct sk_buff *skb)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bfusb_destruct(struct hci_dev *hdev)
|
||||||
|
{
|
||||||
|
struct bfusb_data *data = hdev->driver_data;
|
||||||
|
|
||||||
|
BT_DBG("hdev %p bfusb %p", hdev, data);
|
||||||
|
|
||||||
|
kfree(data);
|
||||||
|
}
|
||||||
|
|
||||||
static int bfusb_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
|
static int bfusb_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
return -ENOIOCTLCMD;
|
return -ENOIOCTLCMD;
|
||||||
|
@ -559,23 +568,22 @@ static int bfusb_load_firmware(struct bfusb_data *data,
|
||||||
|
|
||||||
BT_INFO("BlueFRITZ! USB loading firmware");
|
BT_INFO("BlueFRITZ! USB loading firmware");
|
||||||
|
|
||||||
buf = kmalloc(BFUSB_MAX_BLOCK_SIZE + 3, GFP_KERNEL);
|
|
||||||
if (!buf) {
|
|
||||||
BT_ERR("Can't allocate memory chunk for firmware");
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
pipe = usb_sndctrlpipe(data->udev, 0);
|
pipe = usb_sndctrlpipe(data->udev, 0);
|
||||||
|
|
||||||
if (usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION,
|
if (usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION,
|
||||||
0, 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT) < 0) {
|
0, 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT) < 0) {
|
||||||
BT_ERR("Can't change to loading configuration");
|
BT_ERR("Can't change to loading configuration");
|
||||||
kfree(buf);
|
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->udev->toggle[0] = data->udev->toggle[1] = 0;
|
data->udev->toggle[0] = data->udev->toggle[1] = 0;
|
||||||
|
|
||||||
|
buf = kmalloc(BFUSB_MAX_BLOCK_SIZE + 3, GFP_ATOMIC);
|
||||||
|
if (!buf) {
|
||||||
|
BT_ERR("Can't allocate memory chunk for firmware");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
pipe = usb_sndbulkpipe(data->udev, data->bulk_out_ep);
|
pipe = usb_sndbulkpipe(data->udev, data->bulk_out_ep);
|
||||||
|
|
||||||
while (count) {
|
while (count) {
|
||||||
|
@ -696,15 +704,18 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||||
data->hdev = hdev;
|
data->hdev = hdev;
|
||||||
|
|
||||||
hdev->bus = HCI_USB;
|
hdev->bus = HCI_USB;
|
||||||
hci_set_drvdata(hdev, data);
|
hdev->driver_data = data;
|
||||||
SET_HCIDEV_DEV(hdev, &intf->dev);
|
SET_HCIDEV_DEV(hdev, &intf->dev);
|
||||||
|
|
||||||
hdev->open = bfusb_open;
|
hdev->open = bfusb_open;
|
||||||
hdev->close = bfusb_close;
|
hdev->close = bfusb_close;
|
||||||
hdev->flush = bfusb_flush;
|
hdev->flush = bfusb_flush;
|
||||||
hdev->send = bfusb_send_frame;
|
hdev->send = bfusb_send_frame;
|
||||||
|
hdev->destruct = bfusb_destruct;
|
||||||
hdev->ioctl = bfusb_ioctl;
|
hdev->ioctl = bfusb_ioctl;
|
||||||
|
|
||||||
|
hdev->owner = THIS_MODULE;
|
||||||
|
|
||||||
if (hci_register_dev(hdev) < 0) {
|
if (hci_register_dev(hdev) < 0) {
|
||||||
BT_ERR("Can't register HCI device");
|
BT_ERR("Can't register HCI device");
|
||||||
hci_free_dev(hdev);
|
hci_free_dev(hdev);
|
||||||
|
@ -739,9 +750,10 @@ static void bfusb_disconnect(struct usb_interface *intf)
|
||||||
|
|
||||||
bfusb_close(hdev);
|
bfusb_close(hdev);
|
||||||
|
|
||||||
hci_unregister_dev(hdev);
|
if (hci_unregister_dev(hdev) < 0)
|
||||||
|
BT_ERR("Can't unregister HCI device %s", hdev->name);
|
||||||
|
|
||||||
hci_free_dev(hdev);
|
hci_free_dev(hdev);
|
||||||
kfree(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct usb_driver bfusb_driver = {
|
static struct usb_driver bfusb_driver = {
|
||||||
|
@ -751,7 +763,26 @@ static struct usb_driver bfusb_driver = {
|
||||||
.id_table = bfusb_table,
|
.id_table = bfusb_table,
|
||||||
};
|
};
|
||||||
|
|
||||||
module_usb_driver(bfusb_driver);
|
static int __init bfusb_init(void)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
BT_INFO("BlueFRITZ! USB driver ver %s", VERSION);
|
||||||
|
|
||||||
|
err = usb_register(&bfusb_driver);
|
||||||
|
if (err < 0)
|
||||||
|
BT_ERR("Failed to register BlueFRITZ! USB driver");
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit bfusb_exit(void)
|
||||||
|
{
|
||||||
|
usb_deregister(&bfusb_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(bfusb_init);
|
||||||
|
module_exit(bfusb_exit);
|
||||||
|
|
||||||
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
|
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
|
||||||
MODULE_DESCRIPTION("BlueFRITZ! USB driver ver " VERSION);
|
MODULE_DESCRIPTION("BlueFRITZ! USB driver ver " VERSION);
|
||||||
|
|
|
@ -561,7 +561,7 @@ static irqreturn_t bluecard_interrupt(int irq, void *dev_inst)
|
||||||
|
|
||||||
static int bluecard_hci_set_baud_rate(struct hci_dev *hdev, int baud)
|
static int bluecard_hci_set_baud_rate(struct hci_dev *hdev, int baud)
|
||||||
{
|
{
|
||||||
bluecard_info_t *info = hci_get_drvdata(hdev);
|
bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data);
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
|
|
||||||
/* Ericsson baud rate command */
|
/* Ericsson baud rate command */
|
||||||
|
@ -609,7 +609,7 @@ static int bluecard_hci_set_baud_rate(struct hci_dev *hdev, int baud)
|
||||||
|
|
||||||
static int bluecard_hci_flush(struct hci_dev *hdev)
|
static int bluecard_hci_flush(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
bluecard_info_t *info = hci_get_drvdata(hdev);
|
bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data);
|
||||||
|
|
||||||
/* Drop TX queue */
|
/* Drop TX queue */
|
||||||
skb_queue_purge(&(info->txq));
|
skb_queue_purge(&(info->txq));
|
||||||
|
@ -620,7 +620,7 @@ static int bluecard_hci_flush(struct hci_dev *hdev)
|
||||||
|
|
||||||
static int bluecard_hci_open(struct hci_dev *hdev)
|
static int bluecard_hci_open(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
bluecard_info_t *info = hci_get_drvdata(hdev);
|
bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data);
|
||||||
unsigned int iobase = info->p_dev->resource[0]->start;
|
unsigned int iobase = info->p_dev->resource[0]->start;
|
||||||
|
|
||||||
if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
|
if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
|
||||||
|
@ -640,7 +640,7 @@ static int bluecard_hci_open(struct hci_dev *hdev)
|
||||||
|
|
||||||
static int bluecard_hci_close(struct hci_dev *hdev)
|
static int bluecard_hci_close(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
bluecard_info_t *info = hci_get_drvdata(hdev);
|
bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data);
|
||||||
unsigned int iobase = info->p_dev->resource[0]->start;
|
unsigned int iobase = info->p_dev->resource[0]->start;
|
||||||
|
|
||||||
if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
|
if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
|
||||||
|
@ -667,7 +667,7 @@ static int bluecard_hci_send_frame(struct sk_buff *skb)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
info = hci_get_drvdata(hdev);
|
info = (bluecard_info_t *)(hdev->driver_data);
|
||||||
|
|
||||||
switch (bt_cb(skb)->pkt_type) {
|
switch (bt_cb(skb)->pkt_type) {
|
||||||
case HCI_COMMAND_PKT:
|
case HCI_COMMAND_PKT:
|
||||||
|
@ -691,6 +691,11 @@ static int bluecard_hci_send_frame(struct sk_buff *skb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void bluecard_hci_destruct(struct hci_dev *hdev)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int bluecard_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
|
static int bluecard_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
return -ENOIOCTLCMD;
|
return -ENOIOCTLCMD;
|
||||||
|
@ -729,15 +734,18 @@ static int bluecard_open(bluecard_info_t *info)
|
||||||
info->hdev = hdev;
|
info->hdev = hdev;
|
||||||
|
|
||||||
hdev->bus = HCI_PCCARD;
|
hdev->bus = HCI_PCCARD;
|
||||||
hci_set_drvdata(hdev, info);
|
hdev->driver_data = info;
|
||||||
SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
|
SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
|
||||||
|
|
||||||
hdev->open = bluecard_hci_open;
|
hdev->open = bluecard_hci_open;
|
||||||
hdev->close = bluecard_hci_close;
|
hdev->close = bluecard_hci_close;
|
||||||
hdev->flush = bluecard_hci_flush;
|
hdev->flush = bluecard_hci_flush;
|
||||||
hdev->send = bluecard_hci_send_frame;
|
hdev->send = bluecard_hci_send_frame;
|
||||||
|
hdev->destruct = bluecard_hci_destruct;
|
||||||
hdev->ioctl = bluecard_hci_ioctl;
|
hdev->ioctl = bluecard_hci_ioctl;
|
||||||
|
|
||||||
|
hdev->owner = THIS_MODULE;
|
||||||
|
|
||||||
id = inb(iobase + 0x30);
|
id = inb(iobase + 0x30);
|
||||||
|
|
||||||
if ((id & 0x0f) == 0x02)
|
if ((id & 0x0f) == 0x02)
|
||||||
|
@ -836,7 +844,9 @@ static int bluecard_close(bluecard_info_t *info)
|
||||||
/* Turn FPGA off */
|
/* Turn FPGA off */
|
||||||
outb(0x80, iobase + 0x30);
|
outb(0x80, iobase + 0x30);
|
||||||
|
|
||||||
hci_unregister_dev(hdev);
|
if (hci_unregister_dev(hdev) < 0)
|
||||||
|
BT_ERR("Can't unregister HCI device %s", hdev->name);
|
||||||
|
|
||||||
hci_free_dev(hdev);
|
hci_free_dev(hdev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -920,7 +930,7 @@ static void bluecard_release(struct pcmcia_device *link)
|
||||||
pcmcia_disable_device(link);
|
pcmcia_disable_device(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct pcmcia_device_id bluecard_ids[] = {
|
static struct pcmcia_device_id bluecard_ids[] = {
|
||||||
PCMCIA_DEVICE_PROD_ID12("BlueCard", "LSE041", 0xbaf16fbf, 0x657cc15e),
|
PCMCIA_DEVICE_PROD_ID12("BlueCard", "LSE041", 0xbaf16fbf, 0x657cc15e),
|
||||||
PCMCIA_DEVICE_PROD_ID12("BTCFCARD", "LSE139", 0xe3987764, 0x2524b59c),
|
PCMCIA_DEVICE_PROD_ID12("BTCFCARD", "LSE139", 0xe3987764, 0x2524b59c),
|
||||||
PCMCIA_DEVICE_PROD_ID12("WSS", "LSE039", 0x0a0736ec, 0x24e6dfab),
|
PCMCIA_DEVICE_PROD_ID12("WSS", "LSE039", 0x0a0736ec, 0x24e6dfab),
|
||||||
|
|
|
@ -66,7 +66,7 @@ struct hci_vendor_hdr {
|
||||||
|
|
||||||
static int bpa10x_recv(struct hci_dev *hdev, int queue, void *buf, int count)
|
static int bpa10x_recv(struct hci_dev *hdev, int queue, void *buf, int count)
|
||||||
{
|
{
|
||||||
struct bpa10x_data *data = hci_get_drvdata(hdev);
|
struct bpa10x_data *data = hdev->driver_data;
|
||||||
|
|
||||||
BT_DBG("%s queue %d buffer %p count %d", hdev->name,
|
BT_DBG("%s queue %d buffer %p count %d", hdev->name,
|
||||||
queue, buf, count);
|
queue, buf, count);
|
||||||
|
@ -189,7 +189,7 @@ done:
|
||||||
static void bpa10x_rx_complete(struct urb *urb)
|
static void bpa10x_rx_complete(struct urb *urb)
|
||||||
{
|
{
|
||||||
struct hci_dev *hdev = urb->context;
|
struct hci_dev *hdev = urb->context;
|
||||||
struct bpa10x_data *data = hci_get_drvdata(hdev);
|
struct bpa10x_data *data = hdev->driver_data;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
BT_DBG("%s urb %p status %d count %d", hdev->name,
|
BT_DBG("%s urb %p status %d count %d", hdev->name,
|
||||||
|
@ -219,7 +219,7 @@ static void bpa10x_rx_complete(struct urb *urb)
|
||||||
|
|
||||||
static inline int bpa10x_submit_intr_urb(struct hci_dev *hdev)
|
static inline int bpa10x_submit_intr_urb(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct bpa10x_data *data = hci_get_drvdata(hdev);
|
struct bpa10x_data *data = hdev->driver_data;
|
||||||
struct urb *urb;
|
struct urb *urb;
|
||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
unsigned int pipe;
|
unsigned int pipe;
|
||||||
|
@ -260,7 +260,7 @@ static inline int bpa10x_submit_intr_urb(struct hci_dev *hdev)
|
||||||
|
|
||||||
static inline int bpa10x_submit_bulk_urb(struct hci_dev *hdev)
|
static inline int bpa10x_submit_bulk_urb(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct bpa10x_data *data = hci_get_drvdata(hdev);
|
struct bpa10x_data *data = hdev->driver_data;
|
||||||
struct urb *urb;
|
struct urb *urb;
|
||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
unsigned int pipe;
|
unsigned int pipe;
|
||||||
|
@ -301,7 +301,7 @@ static inline int bpa10x_submit_bulk_urb(struct hci_dev *hdev)
|
||||||
|
|
||||||
static int bpa10x_open(struct hci_dev *hdev)
|
static int bpa10x_open(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct bpa10x_data *data = hci_get_drvdata(hdev);
|
struct bpa10x_data *data = hdev->driver_data;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
BT_DBG("%s", hdev->name);
|
BT_DBG("%s", hdev->name);
|
||||||
|
@ -329,7 +329,7 @@ error:
|
||||||
|
|
||||||
static int bpa10x_close(struct hci_dev *hdev)
|
static int bpa10x_close(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct bpa10x_data *data = hci_get_drvdata(hdev);
|
struct bpa10x_data *data = hdev->driver_data;
|
||||||
|
|
||||||
BT_DBG("%s", hdev->name);
|
BT_DBG("%s", hdev->name);
|
||||||
|
|
||||||
|
@ -343,7 +343,7 @@ static int bpa10x_close(struct hci_dev *hdev)
|
||||||
|
|
||||||
static int bpa10x_flush(struct hci_dev *hdev)
|
static int bpa10x_flush(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct bpa10x_data *data = hci_get_drvdata(hdev);
|
struct bpa10x_data *data = hdev->driver_data;
|
||||||
|
|
||||||
BT_DBG("%s", hdev->name);
|
BT_DBG("%s", hdev->name);
|
||||||
|
|
||||||
|
@ -355,7 +355,7 @@ static int bpa10x_flush(struct hci_dev *hdev)
|
||||||
static int bpa10x_send_frame(struct sk_buff *skb)
|
static int bpa10x_send_frame(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct hci_dev *hdev = (struct hci_dev *) skb->dev;
|
struct hci_dev *hdev = (struct hci_dev *) skb->dev;
|
||||||
struct bpa10x_data *data = hci_get_drvdata(hdev);
|
struct bpa10x_data *data = hdev->driver_data;
|
||||||
struct usb_ctrlrequest *dr;
|
struct usb_ctrlrequest *dr;
|
||||||
struct urb *urb;
|
struct urb *urb;
|
||||||
unsigned int pipe;
|
unsigned int pipe;
|
||||||
|
@ -432,6 +432,17 @@ static int bpa10x_send_frame(struct sk_buff *skb)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bpa10x_destruct(struct hci_dev *hdev)
|
||||||
|
{
|
||||||
|
struct bpa10x_data *data = hdev->driver_data;
|
||||||
|
|
||||||
|
BT_DBG("%s", hdev->name);
|
||||||
|
|
||||||
|
kfree_skb(data->rx_skb[0]);
|
||||||
|
kfree_skb(data->rx_skb[1]);
|
||||||
|
kfree(data);
|
||||||
|
}
|
||||||
|
|
||||||
static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||||
{
|
{
|
||||||
struct bpa10x_data *data;
|
struct bpa10x_data *data;
|
||||||
|
@ -459,7 +470,7 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
|
||||||
}
|
}
|
||||||
|
|
||||||
hdev->bus = HCI_USB;
|
hdev->bus = HCI_USB;
|
||||||
hci_set_drvdata(hdev, data);
|
hdev->driver_data = data;
|
||||||
|
|
||||||
data->hdev = hdev;
|
data->hdev = hdev;
|
||||||
|
|
||||||
|
@ -469,6 +480,9 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
|
||||||
hdev->close = bpa10x_close;
|
hdev->close = bpa10x_close;
|
||||||
hdev->flush = bpa10x_flush;
|
hdev->flush = bpa10x_flush;
|
||||||
hdev->send = bpa10x_send_frame;
|
hdev->send = bpa10x_send_frame;
|
||||||
|
hdev->destruct = bpa10x_destruct;
|
||||||
|
|
||||||
|
hdev->owner = THIS_MODULE;
|
||||||
|
|
||||||
set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
|
set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
|
||||||
|
|
||||||
|
@ -498,9 +512,6 @@ static void bpa10x_disconnect(struct usb_interface *intf)
|
||||||
hci_unregister_dev(data->hdev);
|
hci_unregister_dev(data->hdev);
|
||||||
|
|
||||||
hci_free_dev(data->hdev);
|
hci_free_dev(data->hdev);
|
||||||
kfree_skb(data->rx_skb[0]);
|
|
||||||
kfree_skb(data->rx_skb[1]);
|
|
||||||
kfree(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct usb_driver bpa10x_driver = {
|
static struct usb_driver bpa10x_driver = {
|
||||||
|
@ -510,7 +521,20 @@ static struct usb_driver bpa10x_driver = {
|
||||||
.id_table = bpa10x_table,
|
.id_table = bpa10x_table,
|
||||||
};
|
};
|
||||||
|
|
||||||
module_usb_driver(bpa10x_driver);
|
static int __init bpa10x_init(void)
|
||||||
|
{
|
||||||
|
BT_INFO("Digianswer Bluetooth USB driver ver %s", VERSION);
|
||||||
|
|
||||||
|
return usb_register(&bpa10x_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit bpa10x_exit(void)
|
||||||
|
{
|
||||||
|
usb_deregister(&bpa10x_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(bpa10x_init);
|
||||||
|
module_exit(bpa10x_exit);
|
||||||
|
|
||||||
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
|
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
|
||||||
MODULE_DESCRIPTION("Digianswer Bluetooth USB driver ver " VERSION);
|
MODULE_DESCRIPTION("Digianswer Bluetooth USB driver ver " VERSION);
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include <linux/serial.h>
|
#include <linux/serial.h>
|
||||||
#include <linux/serial_reg.h>
|
#include <linux/serial_reg.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
|
#include <asm/system.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
|
@ -388,7 +389,7 @@ static irqreturn_t bt3c_interrupt(int irq, void *dev_inst)
|
||||||
|
|
||||||
static int bt3c_hci_flush(struct hci_dev *hdev)
|
static int bt3c_hci_flush(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
bt3c_info_t *info = hci_get_drvdata(hdev);
|
bt3c_info_t *info = (bt3c_info_t *)(hdev->driver_data);
|
||||||
|
|
||||||
/* Drop TX queue */
|
/* Drop TX queue */
|
||||||
skb_queue_purge(&(info->txq));
|
skb_queue_purge(&(info->txq));
|
||||||
|
@ -427,7 +428,7 @@ static int bt3c_hci_send_frame(struct sk_buff *skb)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
info = hci_get_drvdata(hdev);
|
info = (bt3c_info_t *) (hdev->driver_data);
|
||||||
|
|
||||||
switch (bt_cb(skb)->pkt_type) {
|
switch (bt_cb(skb)->pkt_type) {
|
||||||
case HCI_COMMAND_PKT:
|
case HCI_COMMAND_PKT:
|
||||||
|
@ -455,6 +456,11 @@ static int bt3c_hci_send_frame(struct sk_buff *skb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void bt3c_hci_destruct(struct hci_dev *hdev)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int bt3c_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
|
static int bt3c_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
return -ENOIOCTLCMD;
|
return -ENOIOCTLCMD;
|
||||||
|
@ -574,15 +580,18 @@ static int bt3c_open(bt3c_info_t *info)
|
||||||
info->hdev = hdev;
|
info->hdev = hdev;
|
||||||
|
|
||||||
hdev->bus = HCI_PCCARD;
|
hdev->bus = HCI_PCCARD;
|
||||||
hci_set_drvdata(hdev, info);
|
hdev->driver_data = info;
|
||||||
SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
|
SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
|
||||||
|
|
||||||
hdev->open = bt3c_hci_open;
|
hdev->open = bt3c_hci_open;
|
||||||
hdev->close = bt3c_hci_close;
|
hdev->close = bt3c_hci_close;
|
||||||
hdev->flush = bt3c_hci_flush;
|
hdev->flush = bt3c_hci_flush;
|
||||||
hdev->send = bt3c_hci_send_frame;
|
hdev->send = bt3c_hci_send_frame;
|
||||||
|
hdev->destruct = bt3c_hci_destruct;
|
||||||
hdev->ioctl = bt3c_hci_ioctl;
|
hdev->ioctl = bt3c_hci_ioctl;
|
||||||
|
|
||||||
|
hdev->owner = THIS_MODULE;
|
||||||
|
|
||||||
/* Load firmware */
|
/* Load firmware */
|
||||||
err = request_firmware(&firmware, "BT3CPCC.bin", &info->p_dev->dev);
|
err = request_firmware(&firmware, "BT3CPCC.bin", &info->p_dev->dev);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
|
@ -627,7 +636,9 @@ static int bt3c_close(bt3c_info_t *info)
|
||||||
|
|
||||||
bt3c_hci_close(hdev);
|
bt3c_hci_close(hdev);
|
||||||
|
|
||||||
hci_unregister_dev(hdev);
|
if (hci_unregister_dev(hdev) < 0)
|
||||||
|
BT_ERR("Can't unregister HCI device %s", hdev->name);
|
||||||
|
|
||||||
hci_free_dev(hdev);
|
hci_free_dev(hdev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -750,7 +761,7 @@ static void bt3c_release(struct pcmcia_device *link)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const struct pcmcia_device_id bt3c_ids[] = {
|
static struct pcmcia_device_id bt3c_ids[] = {
|
||||||
PCMCIA_DEVICE_PROD_ID13("3COM", "Bluetooth PC Card", 0xefce0a31, 0xd4ce9b02),
|
PCMCIA_DEVICE_PROD_ID13("3COM", "Bluetooth PC Card", 0xefce0a31, 0xd4ce9b02),
|
||||||
PCMCIA_DEVICE_NULL
|
PCMCIA_DEVICE_NULL
|
||||||
};
|
};
|
||||||
|
|
|
@ -45,6 +45,12 @@ struct btmrvl_debugfs_data {
|
||||||
struct dentry *txdnldready;
|
struct dentry *txdnldready;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int btmrvl_open_generic(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
file->private_data = inode->i_private;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t btmrvl_hscfgcmd_write(struct file *file,
|
static ssize_t btmrvl_hscfgcmd_write(struct file *file,
|
||||||
const char __user *ubuf, size_t count, loff_t *ppos)
|
const char __user *ubuf, size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
|
@ -58,8 +64,6 @@ static ssize_t btmrvl_hscfgcmd_write(struct file *file,
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
ret = strict_strtol(buf, 10, &result);
|
ret = strict_strtol(buf, 10, &result);
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
priv->btmrvl_dev.hscfgcmd = result;
|
priv->btmrvl_dev.hscfgcmd = result;
|
||||||
|
|
||||||
|
@ -87,7 +91,7 @@ static ssize_t btmrvl_hscfgcmd_read(struct file *file, char __user *userbuf,
|
||||||
static const struct file_operations btmrvl_hscfgcmd_fops = {
|
static const struct file_operations btmrvl_hscfgcmd_fops = {
|
||||||
.read = btmrvl_hscfgcmd_read,
|
.read = btmrvl_hscfgcmd_read,
|
||||||
.write = btmrvl_hscfgcmd_write,
|
.write = btmrvl_hscfgcmd_write,
|
||||||
.open = simple_open,
|
.open = btmrvl_open_generic,
|
||||||
.llseek = default_llseek,
|
.llseek = default_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -104,8 +108,6 @@ static ssize_t btmrvl_psmode_write(struct file *file, const char __user *ubuf,
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
ret = strict_strtol(buf, 10, &result);
|
ret = strict_strtol(buf, 10, &result);
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
priv->btmrvl_dev.psmode = result;
|
priv->btmrvl_dev.psmode = result;
|
||||||
|
|
||||||
|
@ -128,7 +130,7 @@ static ssize_t btmrvl_psmode_read(struct file *file, char __user *userbuf,
|
||||||
static const struct file_operations btmrvl_psmode_fops = {
|
static const struct file_operations btmrvl_psmode_fops = {
|
||||||
.read = btmrvl_psmode_read,
|
.read = btmrvl_psmode_read,
|
||||||
.write = btmrvl_psmode_write,
|
.write = btmrvl_psmode_write,
|
||||||
.open = simple_open,
|
.open = btmrvl_open_generic,
|
||||||
.llseek = default_llseek,
|
.llseek = default_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -145,8 +147,6 @@ static ssize_t btmrvl_pscmd_write(struct file *file, const char __user *ubuf,
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
ret = strict_strtol(buf, 10, &result);
|
ret = strict_strtol(buf, 10, &result);
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
priv->btmrvl_dev.pscmd = result;
|
priv->btmrvl_dev.pscmd = result;
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ static ssize_t btmrvl_pscmd_read(struct file *file, char __user *userbuf,
|
||||||
static const struct file_operations btmrvl_pscmd_fops = {
|
static const struct file_operations btmrvl_pscmd_fops = {
|
||||||
.read = btmrvl_pscmd_read,
|
.read = btmrvl_pscmd_read,
|
||||||
.write = btmrvl_pscmd_write,
|
.write = btmrvl_pscmd_write,
|
||||||
.open = simple_open,
|
.open = btmrvl_open_generic,
|
||||||
.llseek = default_llseek,
|
.llseek = default_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -191,8 +191,6 @@ static ssize_t btmrvl_gpiogap_write(struct file *file, const char __user *ubuf,
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
ret = strict_strtol(buf, 16, &result);
|
ret = strict_strtol(buf, 16, &result);
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
priv->btmrvl_dev.gpio_gap = result;
|
priv->btmrvl_dev.gpio_gap = result;
|
||||||
|
|
||||||
|
@ -215,7 +213,7 @@ static ssize_t btmrvl_gpiogap_read(struct file *file, char __user *userbuf,
|
||||||
static const struct file_operations btmrvl_gpiogap_fops = {
|
static const struct file_operations btmrvl_gpiogap_fops = {
|
||||||
.read = btmrvl_gpiogap_read,
|
.read = btmrvl_gpiogap_read,
|
||||||
.write = btmrvl_gpiogap_write,
|
.write = btmrvl_gpiogap_write,
|
||||||
.open = simple_open,
|
.open = btmrvl_open_generic,
|
||||||
.llseek = default_llseek,
|
.llseek = default_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -232,8 +230,6 @@ static ssize_t btmrvl_hscmd_write(struct file *file, const char __user *ubuf,
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
ret = strict_strtol(buf, 10, &result);
|
ret = strict_strtol(buf, 10, &result);
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
priv->btmrvl_dev.hscmd = result;
|
priv->btmrvl_dev.hscmd = result;
|
||||||
if (priv->btmrvl_dev.hscmd) {
|
if (priv->btmrvl_dev.hscmd) {
|
||||||
|
@ -259,7 +255,7 @@ static ssize_t btmrvl_hscmd_read(struct file *file, char __user *userbuf,
|
||||||
static const struct file_operations btmrvl_hscmd_fops = {
|
static const struct file_operations btmrvl_hscmd_fops = {
|
||||||
.read = btmrvl_hscmd_read,
|
.read = btmrvl_hscmd_read,
|
||||||
.write = btmrvl_hscmd_write,
|
.write = btmrvl_hscmd_write,
|
||||||
.open = simple_open,
|
.open = btmrvl_open_generic,
|
||||||
.llseek = default_llseek,
|
.llseek = default_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -276,8 +272,6 @@ static ssize_t btmrvl_hsmode_write(struct file *file, const char __user *ubuf,
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
ret = strict_strtol(buf, 10, &result);
|
ret = strict_strtol(buf, 10, &result);
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
priv->btmrvl_dev.hsmode = result;
|
priv->btmrvl_dev.hsmode = result;
|
||||||
|
|
||||||
|
@ -299,7 +293,7 @@ static ssize_t btmrvl_hsmode_read(struct file *file, char __user * userbuf,
|
||||||
static const struct file_operations btmrvl_hsmode_fops = {
|
static const struct file_operations btmrvl_hsmode_fops = {
|
||||||
.read = btmrvl_hsmode_read,
|
.read = btmrvl_hsmode_read,
|
||||||
.write = btmrvl_hsmode_write,
|
.write = btmrvl_hsmode_write,
|
||||||
.open = simple_open,
|
.open = btmrvl_open_generic,
|
||||||
.llseek = default_llseek,
|
.llseek = default_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -317,7 +311,7 @@ static ssize_t btmrvl_curpsmode_read(struct file *file, char __user *userbuf,
|
||||||
|
|
||||||
static const struct file_operations btmrvl_curpsmode_fops = {
|
static const struct file_operations btmrvl_curpsmode_fops = {
|
||||||
.read = btmrvl_curpsmode_read,
|
.read = btmrvl_curpsmode_read,
|
||||||
.open = simple_open,
|
.open = btmrvl_open_generic,
|
||||||
.llseek = default_llseek,
|
.llseek = default_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -335,7 +329,7 @@ static ssize_t btmrvl_psstate_read(struct file *file, char __user * userbuf,
|
||||||
|
|
||||||
static const struct file_operations btmrvl_psstate_fops = {
|
static const struct file_operations btmrvl_psstate_fops = {
|
||||||
.read = btmrvl_psstate_read,
|
.read = btmrvl_psstate_read,
|
||||||
.open = simple_open,
|
.open = btmrvl_open_generic,
|
||||||
.llseek = default_llseek,
|
.llseek = default_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -353,7 +347,7 @@ static ssize_t btmrvl_hsstate_read(struct file *file, char __user *userbuf,
|
||||||
|
|
||||||
static const struct file_operations btmrvl_hsstate_fops = {
|
static const struct file_operations btmrvl_hsstate_fops = {
|
||||||
.read = btmrvl_hsstate_read,
|
.read = btmrvl_hsstate_read,
|
||||||
.open = simple_open,
|
.open = btmrvl_open_generic,
|
||||||
.llseek = default_llseek,
|
.llseek = default_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -372,13 +366,13 @@ static ssize_t btmrvl_txdnldready_read(struct file *file, char __user *userbuf,
|
||||||
|
|
||||||
static const struct file_operations btmrvl_txdnldready_fops = {
|
static const struct file_operations btmrvl_txdnldready_fops = {
|
||||||
.read = btmrvl_txdnldready_read,
|
.read = btmrvl_txdnldready_read,
|
||||||
.open = simple_open,
|
.open = btmrvl_open_generic,
|
||||||
.llseek = default_llseek,
|
.llseek = default_llseek,
|
||||||
};
|
};
|
||||||
|
|
||||||
void btmrvl_debugfs_init(struct hci_dev *hdev)
|
void btmrvl_debugfs_init(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct btmrvl_private *priv = hci_get_drvdata(hdev);
|
struct btmrvl_private *priv = hdev->driver_data;
|
||||||
struct btmrvl_debugfs_data *dbg;
|
struct btmrvl_debugfs_data *dbg;
|
||||||
|
|
||||||
if (!hdev->debugfs)
|
if (!hdev->debugfs)
|
||||||
|
@ -395,34 +389,36 @@ void btmrvl_debugfs_init(struct hci_dev *hdev)
|
||||||
dbg->config_dir = debugfs_create_dir("config", hdev->debugfs);
|
dbg->config_dir = debugfs_create_dir("config", hdev->debugfs);
|
||||||
|
|
||||||
dbg->psmode = debugfs_create_file("psmode", 0644, dbg->config_dir,
|
dbg->psmode = debugfs_create_file("psmode", 0644, dbg->config_dir,
|
||||||
priv, &btmrvl_psmode_fops);
|
hdev->driver_data, &btmrvl_psmode_fops);
|
||||||
dbg->pscmd = debugfs_create_file("pscmd", 0644, dbg->config_dir,
|
dbg->pscmd = debugfs_create_file("pscmd", 0644, dbg->config_dir,
|
||||||
priv, &btmrvl_pscmd_fops);
|
hdev->driver_data, &btmrvl_pscmd_fops);
|
||||||
dbg->gpiogap = debugfs_create_file("gpiogap", 0644, dbg->config_dir,
|
dbg->gpiogap = debugfs_create_file("gpiogap", 0644, dbg->config_dir,
|
||||||
priv, &btmrvl_gpiogap_fops);
|
hdev->driver_data, &btmrvl_gpiogap_fops);
|
||||||
dbg->hsmode = debugfs_create_file("hsmode", 0644, dbg->config_dir,
|
dbg->hsmode = debugfs_create_file("hsmode", 0644, dbg->config_dir,
|
||||||
priv, &btmrvl_hsmode_fops);
|
hdev->driver_data, &btmrvl_hsmode_fops);
|
||||||
dbg->hscmd = debugfs_create_file("hscmd", 0644, dbg->config_dir,
|
dbg->hscmd = debugfs_create_file("hscmd", 0644, dbg->config_dir,
|
||||||
priv, &btmrvl_hscmd_fops);
|
hdev->driver_data, &btmrvl_hscmd_fops);
|
||||||
dbg->hscfgcmd = debugfs_create_file("hscfgcmd", 0644, dbg->config_dir,
|
dbg->hscfgcmd = debugfs_create_file("hscfgcmd", 0644, dbg->config_dir,
|
||||||
priv, &btmrvl_hscfgcmd_fops);
|
hdev->driver_data, &btmrvl_hscfgcmd_fops);
|
||||||
|
|
||||||
dbg->status_dir = debugfs_create_dir("status", hdev->debugfs);
|
dbg->status_dir = debugfs_create_dir("status", hdev->debugfs);
|
||||||
dbg->curpsmode = debugfs_create_file("curpsmode", 0444,
|
dbg->curpsmode = debugfs_create_file("curpsmode", 0444,
|
||||||
dbg->status_dir, priv,
|
dbg->status_dir,
|
||||||
&btmrvl_curpsmode_fops);
|
hdev->driver_data,
|
||||||
|
&btmrvl_curpsmode_fops);
|
||||||
dbg->psstate = debugfs_create_file("psstate", 0444, dbg->status_dir,
|
dbg->psstate = debugfs_create_file("psstate", 0444, dbg->status_dir,
|
||||||
priv, &btmrvl_psstate_fops);
|
hdev->driver_data, &btmrvl_psstate_fops);
|
||||||
dbg->hsstate = debugfs_create_file("hsstate", 0444, dbg->status_dir,
|
dbg->hsstate = debugfs_create_file("hsstate", 0444, dbg->status_dir,
|
||||||
priv, &btmrvl_hsstate_fops);
|
hdev->driver_data, &btmrvl_hsstate_fops);
|
||||||
dbg->txdnldready = debugfs_create_file("txdnldready", 0444,
|
dbg->txdnldready = debugfs_create_file("txdnldready", 0444,
|
||||||
dbg->status_dir, priv,
|
dbg->status_dir,
|
||||||
&btmrvl_txdnldready_fops);
|
hdev->driver_data,
|
||||||
|
&btmrvl_txdnldready_fops);
|
||||||
}
|
}
|
||||||
|
|
||||||
void btmrvl_debugfs_remove(struct hci_dev *hdev)
|
void btmrvl_debugfs_remove(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct btmrvl_private *priv = hci_get_drvdata(hdev);
|
struct btmrvl_private *priv = hdev->driver_data;
|
||||||
struct btmrvl_debugfs_data *dbg = priv->debugfs_data;
|
struct btmrvl_debugfs_data *dbg = priv->debugfs_data;
|
||||||
|
|
||||||
if (!dbg)
|
if (!dbg)
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
* this warranty disclaimer.
|
* this warranty disclaimer.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#include <linux/module.h>
|
|
||||||
|
|
||||||
#include <net/bluetooth/bluetooth.h>
|
#include <net/bluetooth/bluetooth.h>
|
||||||
#include <net/bluetooth/hci_core.h>
|
#include <net/bluetooth/hci_core.h>
|
||||||
|
|
||||||
|
@ -387,6 +385,10 @@ static int btmrvl_ioctl(struct hci_dev *hdev,
|
||||||
return -ENOIOCTLCMD;
|
return -ENOIOCTLCMD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void btmrvl_destruct(struct hci_dev *hdev)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static int btmrvl_send_frame(struct sk_buff *skb)
|
static int btmrvl_send_frame(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct hci_dev *hdev = (struct hci_dev *) skb->dev;
|
struct hci_dev *hdev = (struct hci_dev *) skb->dev;
|
||||||
|
@ -394,13 +396,12 @@ static int btmrvl_send_frame(struct sk_buff *skb)
|
||||||
|
|
||||||
BT_DBG("type=%d, len=%d", skb->pkt_type, skb->len);
|
BT_DBG("type=%d, len=%d", skb->pkt_type, skb->len);
|
||||||
|
|
||||||
if (!hdev) {
|
if (!hdev || !hdev->driver_data) {
|
||||||
BT_ERR("Frame for unknown HCI device");
|
BT_ERR("Frame for unknown HCI device");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv = hci_get_drvdata(hdev);
|
priv = (struct btmrvl_private *) hdev->driver_data;
|
||||||
|
|
||||||
if (!test_bit(HCI_RUNNING, &hdev->flags)) {
|
if (!test_bit(HCI_RUNNING, &hdev->flags)) {
|
||||||
BT_ERR("Failed testing HCI_RUNING, flags=%lx", hdev->flags);
|
BT_ERR("Failed testing HCI_RUNING, flags=%lx", hdev->flags);
|
||||||
print_hex_dump_bytes("data: ", DUMP_PREFIX_OFFSET,
|
print_hex_dump_bytes("data: ", DUMP_PREFIX_OFFSET,
|
||||||
|
@ -431,7 +432,7 @@ static int btmrvl_send_frame(struct sk_buff *skb)
|
||||||
|
|
||||||
static int btmrvl_flush(struct hci_dev *hdev)
|
static int btmrvl_flush(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct btmrvl_private *priv = hci_get_drvdata(hdev);
|
struct btmrvl_private *priv = hdev->driver_data;
|
||||||
|
|
||||||
skb_queue_purge(&priv->adapter->tx_queue);
|
skb_queue_purge(&priv->adapter->tx_queue);
|
||||||
|
|
||||||
|
@ -440,7 +441,7 @@ static int btmrvl_flush(struct hci_dev *hdev)
|
||||||
|
|
||||||
static int btmrvl_close(struct hci_dev *hdev)
|
static int btmrvl_close(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct btmrvl_private *priv = hci_get_drvdata(hdev);
|
struct btmrvl_private *priv = hdev->driver_data;
|
||||||
|
|
||||||
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
|
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -472,6 +473,8 @@ static int btmrvl_service_main_thread(void *data)
|
||||||
|
|
||||||
init_waitqueue_entry(&wait, current);
|
init_waitqueue_entry(&wait, current);
|
||||||
|
|
||||||
|
current->flags |= PF_NOFREEZE;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
add_wait_queue(&thread->wait_q, &wait);
|
add_wait_queue(&thread->wait_q, &wait);
|
||||||
|
|
||||||
|
@ -543,14 +546,16 @@ int btmrvl_register_hdev(struct btmrvl_private *priv)
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->btmrvl_dev.hcidev = hdev;
|
priv->btmrvl_dev.hcidev = hdev;
|
||||||
hci_set_drvdata(hdev, priv);
|
hdev->driver_data = priv;
|
||||||
|
|
||||||
hdev->bus = HCI_SDIO;
|
hdev->bus = HCI_SDIO;
|
||||||
hdev->open = btmrvl_open;
|
hdev->open = btmrvl_open;
|
||||||
hdev->close = btmrvl_close;
|
hdev->close = btmrvl_close;
|
||||||
hdev->flush = btmrvl_flush;
|
hdev->flush = btmrvl_flush;
|
||||||
hdev->send = btmrvl_send_frame;
|
hdev->send = btmrvl_send_frame;
|
||||||
|
hdev->destruct = btmrvl_destruct;
|
||||||
hdev->ioctl = btmrvl_ioctl;
|
hdev->ioctl = btmrvl_ioctl;
|
||||||
|
hdev->owner = THIS_MODULE;
|
||||||
|
|
||||||
btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
|
btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
|
|
||||||
#include <linux/mmc/sdio_ids.h>
|
#include <linux/mmc/sdio_ids.h>
|
||||||
#include <linux/mmc/sdio_func.h>
|
#include <linux/mmc/sdio_func.h>
|
||||||
#include <linux/module.h>
|
|
||||||
|
|
||||||
#include <net/bluetooth/bluetooth.h>
|
#include <net/bluetooth/bluetooth.h>
|
||||||
#include <net/bluetooth/hci_core.h>
|
#include <net/bluetooth/hci_core.h>
|
||||||
|
@ -65,7 +64,7 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8688 = {
|
||||||
.io_port_1 = 0x01,
|
.io_port_1 = 0x01,
|
||||||
.io_port_2 = 0x02,
|
.io_port_2 = 0x02,
|
||||||
};
|
};
|
||||||
static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = {
|
static const struct btmrvl_sdio_card_reg btmrvl_reg_8787 = {
|
||||||
.cfg = 0x00,
|
.cfg = 0x00,
|
||||||
.host_int_mask = 0x02,
|
.host_int_mask = 0x02,
|
||||||
.host_intstatus = 0x03,
|
.host_intstatus = 0x03,
|
||||||
|
@ -82,7 +81,7 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = {
|
||||||
.io_port_2 = 0x7a,
|
.io_port_2 = 0x7a,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
|
static const struct btmrvl_sdio_device btmrvl_sdio_sd6888 = {
|
||||||
.helper = "sd8688_helper.bin",
|
.helper = "sd8688_helper.bin",
|
||||||
.firmware = "sd8688.bin",
|
.firmware = "sd8688.bin",
|
||||||
.reg = &btmrvl_reg_8688,
|
.reg = &btmrvl_reg_8688,
|
||||||
|
@ -92,27 +91,17 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
|
||||||
static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
|
static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
|
||||||
.helper = NULL,
|
.helper = NULL,
|
||||||
.firmware = "mrvl/sd8787_uapsta.bin",
|
.firmware = "mrvl/sd8787_uapsta.bin",
|
||||||
.reg = &btmrvl_reg_87xx,
|
.reg = &btmrvl_reg_8787,
|
||||||
.sd_blksz_fw_dl = 256,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
|
|
||||||
.helper = NULL,
|
|
||||||
.firmware = "mrvl/sd8797_uapsta.bin",
|
|
||||||
.reg = &btmrvl_reg_87xx,
|
|
||||||
.sd_blksz_fw_dl = 256,
|
.sd_blksz_fw_dl = 256,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct sdio_device_id btmrvl_sdio_ids[] = {
|
static const struct sdio_device_id btmrvl_sdio_ids[] = {
|
||||||
/* Marvell SD8688 Bluetooth device */
|
/* Marvell SD8688 Bluetooth device */
|
||||||
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9105),
|
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9105),
|
||||||
.driver_data = (unsigned long) &btmrvl_sdio_sd8688 },
|
.driver_data = (unsigned long) &btmrvl_sdio_sd6888 },
|
||||||
/* Marvell SD8787 Bluetooth device */
|
/* Marvell SD8787 Bluetooth device */
|
||||||
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A),
|
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A),
|
||||||
.driver_data = (unsigned long) &btmrvl_sdio_sd8787 },
|
.driver_data = (unsigned long) &btmrvl_sdio_sd8787 },
|
||||||
/* Marvell SD8797 Bluetooth device */
|
|
||||||
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A),
|
|
||||||
.driver_data = (unsigned long) &btmrvl_sdio_sd8797 },
|
|
||||||
|
|
||||||
{ } /* Terminating entry */
|
{ } /* Terminating entry */
|
||||||
};
|
};
|
||||||
|
@ -1086,4 +1075,3 @@ MODULE_LICENSE("GPL v2");
|
||||||
MODULE_FIRMWARE("sd8688_helper.bin");
|
MODULE_FIRMWARE("sd8688_helper.bin");
|
||||||
MODULE_FIRMWARE("sd8688.bin");
|
MODULE_FIRMWARE("sd8688.bin");
|
||||||
MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
|
MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
|
||||||
MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");
|
|
||||||
|
|
|
@ -189,7 +189,7 @@ static void btsdio_interrupt(struct sdio_func *func)
|
||||||
|
|
||||||
static int btsdio_open(struct hci_dev *hdev)
|
static int btsdio_open(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct btsdio_data *data = hci_get_drvdata(hdev);
|
struct btsdio_data *data = hdev->driver_data;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
BT_DBG("%s", hdev->name);
|
BT_DBG("%s", hdev->name);
|
||||||
|
@ -225,7 +225,7 @@ release:
|
||||||
|
|
||||||
static int btsdio_close(struct hci_dev *hdev)
|
static int btsdio_close(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct btsdio_data *data = hci_get_drvdata(hdev);
|
struct btsdio_data *data = hdev->driver_data;
|
||||||
|
|
||||||
BT_DBG("%s", hdev->name);
|
BT_DBG("%s", hdev->name);
|
||||||
|
|
||||||
|
@ -246,7 +246,7 @@ static int btsdio_close(struct hci_dev *hdev)
|
||||||
|
|
||||||
static int btsdio_flush(struct hci_dev *hdev)
|
static int btsdio_flush(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct btsdio_data *data = hci_get_drvdata(hdev);
|
struct btsdio_data *data = hdev->driver_data;
|
||||||
|
|
||||||
BT_DBG("%s", hdev->name);
|
BT_DBG("%s", hdev->name);
|
||||||
|
|
||||||
|
@ -258,7 +258,7 @@ static int btsdio_flush(struct hci_dev *hdev)
|
||||||
static int btsdio_send_frame(struct sk_buff *skb)
|
static int btsdio_send_frame(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct hci_dev *hdev = (struct hci_dev *) skb->dev;
|
struct hci_dev *hdev = (struct hci_dev *) skb->dev;
|
||||||
struct btsdio_data *data = hci_get_drvdata(hdev);
|
struct btsdio_data *data = hdev->driver_data;
|
||||||
|
|
||||||
BT_DBG("%s", hdev->name);
|
BT_DBG("%s", hdev->name);
|
||||||
|
|
||||||
|
@ -289,6 +289,15 @@ static int btsdio_send_frame(struct sk_buff *skb)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void btsdio_destruct(struct hci_dev *hdev)
|
||||||
|
{
|
||||||
|
struct btsdio_data *data = hdev->driver_data;
|
||||||
|
|
||||||
|
BT_DBG("%s", hdev->name);
|
||||||
|
|
||||||
|
kfree(data);
|
||||||
|
}
|
||||||
|
|
||||||
static int btsdio_probe(struct sdio_func *func,
|
static int btsdio_probe(struct sdio_func *func,
|
||||||
const struct sdio_device_id *id)
|
const struct sdio_device_id *id)
|
||||||
{
|
{
|
||||||
|
@ -321,7 +330,7 @@ static int btsdio_probe(struct sdio_func *func,
|
||||||
}
|
}
|
||||||
|
|
||||||
hdev->bus = HCI_SDIO;
|
hdev->bus = HCI_SDIO;
|
||||||
hci_set_drvdata(hdev, data);
|
hdev->driver_data = data;
|
||||||
|
|
||||||
if (id->class == SDIO_CLASS_BT_AMP)
|
if (id->class == SDIO_CLASS_BT_AMP)
|
||||||
hdev->dev_type = HCI_AMP;
|
hdev->dev_type = HCI_AMP;
|
||||||
|
@ -336,6 +345,9 @@ static int btsdio_probe(struct sdio_func *func,
|
||||||
hdev->close = btsdio_close;
|
hdev->close = btsdio_close;
|
||||||
hdev->flush = btsdio_flush;
|
hdev->flush = btsdio_flush;
|
||||||
hdev->send = btsdio_send_frame;
|
hdev->send = btsdio_send_frame;
|
||||||
|
hdev->destruct = btsdio_destruct;
|
||||||
|
|
||||||
|
hdev->owner = THIS_MODULE;
|
||||||
|
|
||||||
err = hci_register_dev(hdev);
|
err = hci_register_dev(hdev);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
|
@ -366,7 +378,6 @@ static void btsdio_remove(struct sdio_func *func)
|
||||||
hci_unregister_dev(hdev);
|
hci_unregister_dev(hdev);
|
||||||
|
|
||||||
hci_free_dev(hdev);
|
hci_free_dev(hdev);
|
||||||
kfree(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct sdio_driver btsdio_driver = {
|
static struct sdio_driver btsdio_driver = {
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include <linux/serial.h>
|
#include <linux/serial.h>
|
||||||
#include <linux/serial_reg.h>
|
#include <linux/serial_reg.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
|
#include <asm/system.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
|
||||||
#include <pcmcia/cistpl.h>
|
#include <pcmcia/cistpl.h>
|
||||||
|
@ -396,7 +397,7 @@ static void btuart_change_speed(btuart_info_t *info, unsigned int speed)
|
||||||
|
|
||||||
static int btuart_hci_flush(struct hci_dev *hdev)
|
static int btuart_hci_flush(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
btuart_info_t *info = hci_get_drvdata(hdev);
|
btuart_info_t *info = (btuart_info_t *)(hdev->driver_data);
|
||||||
|
|
||||||
/* Drop TX queue */
|
/* Drop TX queue */
|
||||||
skb_queue_purge(&(info->txq));
|
skb_queue_purge(&(info->txq));
|
||||||
|
@ -434,7 +435,7 @@ static int btuart_hci_send_frame(struct sk_buff *skb)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
info = hci_get_drvdata(hdev);
|
info = (btuart_info_t *)(hdev->driver_data);
|
||||||
|
|
||||||
switch (bt_cb(skb)->pkt_type) {
|
switch (bt_cb(skb)->pkt_type) {
|
||||||
case HCI_COMMAND_PKT:
|
case HCI_COMMAND_PKT:
|
||||||
|
@ -458,6 +459,11 @@ static int btuart_hci_send_frame(struct sk_buff *skb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void btuart_hci_destruct(struct hci_dev *hdev)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int btuart_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
|
static int btuart_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
return -ENOIOCTLCMD;
|
return -ENOIOCTLCMD;
|
||||||
|
@ -492,15 +498,18 @@ static int btuart_open(btuart_info_t *info)
|
||||||
info->hdev = hdev;
|
info->hdev = hdev;
|
||||||
|
|
||||||
hdev->bus = HCI_PCCARD;
|
hdev->bus = HCI_PCCARD;
|
||||||
hci_set_drvdata(hdev, info);
|
hdev->driver_data = info;
|
||||||
SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
|
SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
|
||||||
|
|
||||||
hdev->open = btuart_hci_open;
|
hdev->open = btuart_hci_open;
|
||||||
hdev->close = btuart_hci_close;
|
hdev->close = btuart_hci_close;
|
||||||
hdev->flush = btuart_hci_flush;
|
hdev->flush = btuart_hci_flush;
|
||||||
hdev->send = btuart_hci_send_frame;
|
hdev->send = btuart_hci_send_frame;
|
||||||
|
hdev->destruct = btuart_hci_destruct;
|
||||||
hdev->ioctl = btuart_hci_ioctl;
|
hdev->ioctl = btuart_hci_ioctl;
|
||||||
|
|
||||||
|
hdev->owner = THIS_MODULE;
|
||||||
|
|
||||||
spin_lock_irqsave(&(info->lock), flags);
|
spin_lock_irqsave(&(info->lock), flags);
|
||||||
|
|
||||||
/* Reset UART */
|
/* Reset UART */
|
||||||
|
@ -556,7 +565,9 @@ static int btuart_close(btuart_info_t *info)
|
||||||
|
|
||||||
spin_unlock_irqrestore(&(info->lock), flags);
|
spin_unlock_irqrestore(&(info->lock), flags);
|
||||||
|
|
||||||
hci_unregister_dev(hdev);
|
if (hci_unregister_dev(hdev) < 0)
|
||||||
|
BT_ERR("Can't unregister HCI device %s", hdev->name);
|
||||||
|
|
||||||
hci_free_dev(hdev);
|
hci_free_dev(hdev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -678,7 +689,7 @@ static void btuart_release(struct pcmcia_device *link)
|
||||||
pcmcia_disable_device(link);
|
pcmcia_disable_device(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct pcmcia_device_id btuart_ids[] = {
|
static struct pcmcia_device_id btuart_ids[] = {
|
||||||
/* don't use this driver. Use serial_cs + hci_uart instead */
|
/* don't use this driver. Use serial_cs + hci_uart instead */
|
||||||
PCMCIA_DEVICE_NULL
|
PCMCIA_DEVICE_NULL
|
||||||
};
|
};
|
||||||
|
|
|
@ -37,13 +37,13 @@
|
||||||
|
|
||||||
#define VERSION "0.6"
|
#define VERSION "0.6"
|
||||||
|
|
||||||
static bool ignore_dga;
|
static int ignore_dga;
|
||||||
static bool ignore_csr;
|
static int ignore_csr;
|
||||||
static bool ignore_sniffer;
|
static int ignore_sniffer;
|
||||||
static bool disable_scofix;
|
static int disable_scofix;
|
||||||
static bool force_scofix;
|
static int force_scofix;
|
||||||
|
|
||||||
static bool reset = 1;
|
static int reset = 1;
|
||||||
|
|
||||||
static struct usb_driver btusb_driver;
|
static struct usb_driver btusb_driver;
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ static struct usb_device_id btusb_table[] = {
|
||||||
{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
|
{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
|
||||||
|
|
||||||
/* Broadcom SoftSailing reporting vendor specific */
|
/* Broadcom SoftSailing reporting vendor specific */
|
||||||
{ USB_DEVICE(0x0a5c, 0x21e1) },
|
{ USB_DEVICE(0x05ac, 0x21e1) },
|
||||||
|
|
||||||
/* Apple MacBookPro 7,1 */
|
/* Apple MacBookPro 7,1 */
|
||||||
{ USB_DEVICE(0x05ac, 0x8213) },
|
{ USB_DEVICE(0x05ac, 0x8213) },
|
||||||
|
@ -100,17 +100,6 @@ static struct usb_device_id btusb_table[] = {
|
||||||
/* Canyon CN-BTU1 with HID interfaces */
|
/* Canyon CN-BTU1 with HID interfaces */
|
||||||
{ USB_DEVICE(0x0c10, 0x0000) },
|
{ USB_DEVICE(0x0c10, 0x0000) },
|
||||||
|
|
||||||
/* Broadcom BCM20702A0 */
|
|
||||||
{ USB_DEVICE(0x0489, 0xe042) },
|
|
||||||
{ USB_DEVICE(0x0a5c, 0x21e3) },
|
|
||||||
{ USB_DEVICE(0x0a5c, 0x21e6) },
|
|
||||||
{ USB_DEVICE(0x0a5c, 0x21e8) },
|
|
||||||
{ USB_DEVICE(0x0a5c, 0x21f3) },
|
|
||||||
{ USB_DEVICE(0x413c, 0x8197) },
|
|
||||||
|
|
||||||
/* Foxconn - Hon Hai */
|
|
||||||
{ USB_DEVICE(0x0489, 0xe033) },
|
|
||||||
|
|
||||||
{ } /* Terminating entry */
|
{ } /* Terminating entry */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -125,20 +114,12 @@ static struct usb_device_id blacklist_table[] = {
|
||||||
|
|
||||||
/* Atheros 3011 with sflash firmware */
|
/* Atheros 3011 with sflash firmware */
|
||||||
{ USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
|
{ USB_DEVICE(0x0cf3, 0x3002), .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 },
|
|
||||||
|
|
||||||
/* Atheros AR9285 Malbec with sflash firmware */
|
/* Atheros AR9285 Malbec with sflash firmware */
|
||||||
{ USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
|
{ USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
|
||||||
|
|
||||||
/* Atheros 3012 with sflash firmware */
|
/* Atheros 3012 with sflash firmware */
|
||||||
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
|
{ 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 },
|
|
||||||
|
|
||||||
/* Atheros AR5BBU12 with sflash firmware */
|
/* Atheros AR5BBU12 with sflash firmware */
|
||||||
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
|
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
|
||||||
|
@ -255,7 +236,7 @@ static int inc_tx(struct btusb_data *data)
|
||||||
static void btusb_intr_complete(struct urb *urb)
|
static void btusb_intr_complete(struct urb *urb)
|
||||||
{
|
{
|
||||||
struct hci_dev *hdev = urb->context;
|
struct hci_dev *hdev = urb->context;
|
||||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
struct btusb_data *data = hdev->driver_data;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
BT_DBG("%s urb %p status %d count %d", hdev->name,
|
BT_DBG("%s urb %p status %d count %d", hdev->name,
|
||||||
|
@ -283,9 +264,7 @@ static void btusb_intr_complete(struct urb *urb)
|
||||||
|
|
||||||
err = usb_submit_urb(urb, GFP_ATOMIC);
|
err = usb_submit_urb(urb, GFP_ATOMIC);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
/* -EPERM: urb is being killed;
|
if (err != -EPERM)
|
||||||
* -ENODEV: device got disconnected */
|
|
||||||
if (err != -EPERM && err != -ENODEV)
|
|
||||||
BT_ERR("%s urb %p failed to resubmit (%d)",
|
BT_ERR("%s urb %p failed to resubmit (%d)",
|
||||||
hdev->name, urb, -err);
|
hdev->name, urb, -err);
|
||||||
usb_unanchor_urb(urb);
|
usb_unanchor_urb(urb);
|
||||||
|
@ -294,7 +273,7 @@ static void btusb_intr_complete(struct urb *urb)
|
||||||
|
|
||||||
static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)
|
static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)
|
||||||
{
|
{
|
||||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
struct btusb_data *data = hdev->driver_data;
|
||||||
struct urb *urb;
|
struct urb *urb;
|
||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
unsigned int pipe;
|
unsigned int pipe;
|
||||||
|
@ -329,8 +308,7 @@ static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)
|
||||||
|
|
||||||
err = usb_submit_urb(urb, mem_flags);
|
err = usb_submit_urb(urb, mem_flags);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
if (err != -EPERM && err != -ENODEV)
|
BT_ERR("%s urb %p submission failed (%d)",
|
||||||
BT_ERR("%s urb %p submission failed (%d)",
|
|
||||||
hdev->name, urb, -err);
|
hdev->name, urb, -err);
|
||||||
usb_unanchor_urb(urb);
|
usb_unanchor_urb(urb);
|
||||||
}
|
}
|
||||||
|
@ -343,7 +321,7 @@ static int btusb_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)
|
||||||
static void btusb_bulk_complete(struct urb *urb)
|
static void btusb_bulk_complete(struct urb *urb)
|
||||||
{
|
{
|
||||||
struct hci_dev *hdev = urb->context;
|
struct hci_dev *hdev = urb->context;
|
||||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
struct btusb_data *data = hdev->driver_data;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
BT_DBG("%s urb %p status %d count %d", hdev->name,
|
BT_DBG("%s urb %p status %d count %d", hdev->name,
|
||||||
|
@ -371,9 +349,7 @@ static void btusb_bulk_complete(struct urb *urb)
|
||||||
|
|
||||||
err = usb_submit_urb(urb, GFP_ATOMIC);
|
err = usb_submit_urb(urb, GFP_ATOMIC);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
/* -EPERM: urb is being killed;
|
if (err != -EPERM)
|
||||||
* -ENODEV: device got disconnected */
|
|
||||||
if (err != -EPERM && err != -ENODEV)
|
|
||||||
BT_ERR("%s urb %p failed to resubmit (%d)",
|
BT_ERR("%s urb %p failed to resubmit (%d)",
|
||||||
hdev->name, urb, -err);
|
hdev->name, urb, -err);
|
||||||
usb_unanchor_urb(urb);
|
usb_unanchor_urb(urb);
|
||||||
|
@ -382,7 +358,7 @@ static void btusb_bulk_complete(struct urb *urb)
|
||||||
|
|
||||||
static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags)
|
static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags)
|
||||||
{
|
{
|
||||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
struct btusb_data *data = hdev->driver_data;
|
||||||
struct urb *urb;
|
struct urb *urb;
|
||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
unsigned int pipe;
|
unsigned int pipe;
|
||||||
|
@ -415,8 +391,7 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags)
|
||||||
|
|
||||||
err = usb_submit_urb(urb, mem_flags);
|
err = usb_submit_urb(urb, mem_flags);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
if (err != -EPERM && err != -ENODEV)
|
BT_ERR("%s urb %p submission failed (%d)",
|
||||||
BT_ERR("%s urb %p submission failed (%d)",
|
|
||||||
hdev->name, urb, -err);
|
hdev->name, urb, -err);
|
||||||
usb_unanchor_urb(urb);
|
usb_unanchor_urb(urb);
|
||||||
}
|
}
|
||||||
|
@ -429,7 +404,7 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags)
|
||||||
static void btusb_isoc_complete(struct urb *urb)
|
static void btusb_isoc_complete(struct urb *urb)
|
||||||
{
|
{
|
||||||
struct hci_dev *hdev = urb->context;
|
struct hci_dev *hdev = urb->context;
|
||||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
struct btusb_data *data = hdev->driver_data;
|
||||||
int i, err;
|
int i, err;
|
||||||
|
|
||||||
BT_DBG("%s urb %p status %d count %d", hdev->name,
|
BT_DBG("%s urb %p status %d count %d", hdev->name,
|
||||||
|
@ -464,16 +439,14 @@ static void btusb_isoc_complete(struct urb *urb)
|
||||||
|
|
||||||
err = usb_submit_urb(urb, GFP_ATOMIC);
|
err = usb_submit_urb(urb, GFP_ATOMIC);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
/* -EPERM: urb is being killed;
|
if (err != -EPERM)
|
||||||
* -ENODEV: device got disconnected */
|
|
||||||
if (err != -EPERM && err != -ENODEV)
|
|
||||||
BT_ERR("%s urb %p failed to resubmit (%d)",
|
BT_ERR("%s urb %p failed to resubmit (%d)",
|
||||||
hdev->name, urb, -err);
|
hdev->name, urb, -err);
|
||||||
usb_unanchor_urb(urb);
|
usb_unanchor_urb(urb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void __fill_isoc_descriptor(struct urb *urb, int len, int mtu)
|
static void inline __fill_isoc_descriptor(struct urb *urb, int len, int mtu)
|
||||||
{
|
{
|
||||||
int i, offset = 0;
|
int i, offset = 0;
|
||||||
|
|
||||||
|
@ -496,7 +469,7 @@ static inline void __fill_isoc_descriptor(struct urb *urb, int len, int mtu)
|
||||||
|
|
||||||
static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)
|
static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)
|
||||||
{
|
{
|
||||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
struct btusb_data *data = hdev->driver_data;
|
||||||
struct urb *urb;
|
struct urb *urb;
|
||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
unsigned int pipe;
|
unsigned int pipe;
|
||||||
|
@ -522,10 +495,15 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)
|
||||||
|
|
||||||
pipe = usb_rcvisocpipe(data->udev, data->isoc_rx_ep->bEndpointAddress);
|
pipe = usb_rcvisocpipe(data->udev, data->isoc_rx_ep->bEndpointAddress);
|
||||||
|
|
||||||
usb_fill_int_urb(urb, data->udev, pipe, buf, size, btusb_isoc_complete,
|
urb->dev = data->udev;
|
||||||
hdev, data->isoc_rx_ep->bInterval);
|
urb->pipe = pipe;
|
||||||
|
urb->context = hdev;
|
||||||
|
urb->complete = btusb_isoc_complete;
|
||||||
|
urb->interval = data->isoc_rx_ep->bInterval;
|
||||||
|
|
||||||
urb->transfer_flags = URB_FREE_BUFFER | URB_ISO_ASAP;
|
urb->transfer_flags = URB_FREE_BUFFER | URB_ISO_ASAP;
|
||||||
|
urb->transfer_buffer = buf;
|
||||||
|
urb->transfer_buffer_length = size;
|
||||||
|
|
||||||
__fill_isoc_descriptor(urb, size,
|
__fill_isoc_descriptor(urb, size,
|
||||||
le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize));
|
le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize));
|
||||||
|
@ -534,8 +512,7 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)
|
||||||
|
|
||||||
err = usb_submit_urb(urb, mem_flags);
|
err = usb_submit_urb(urb, mem_flags);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
if (err != -EPERM && err != -ENODEV)
|
BT_ERR("%s urb %p submission failed (%d)",
|
||||||
BT_ERR("%s urb %p submission failed (%d)",
|
|
||||||
hdev->name, urb, -err);
|
hdev->name, urb, -err);
|
||||||
usb_unanchor_urb(urb);
|
usb_unanchor_urb(urb);
|
||||||
}
|
}
|
||||||
|
@ -549,7 +526,7 @@ static void btusb_tx_complete(struct urb *urb)
|
||||||
{
|
{
|
||||||
struct sk_buff *skb = urb->context;
|
struct sk_buff *skb = urb->context;
|
||||||
struct hci_dev *hdev = (struct hci_dev *) skb->dev;
|
struct hci_dev *hdev = (struct hci_dev *) skb->dev;
|
||||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
struct btusb_data *data = hdev->driver_data;
|
||||||
|
|
||||||
BT_DBG("%s urb %p status %d count %d", hdev->name,
|
BT_DBG("%s urb %p status %d count %d", hdev->name,
|
||||||
urb, urb->status, urb->actual_length);
|
urb, urb->status, urb->actual_length);
|
||||||
|
@ -596,7 +573,7 @@ done:
|
||||||
|
|
||||||
static int btusb_open(struct hci_dev *hdev)
|
static int btusb_open(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
struct btusb_data *data = hdev->driver_data;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
BT_DBG("%s", hdev->name);
|
BT_DBG("%s", hdev->name);
|
||||||
|
@ -646,7 +623,7 @@ static void btusb_stop_traffic(struct btusb_data *data)
|
||||||
|
|
||||||
static int btusb_close(struct hci_dev *hdev)
|
static int btusb_close(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
struct btusb_data *data = hdev->driver_data;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
BT_DBG("%s", hdev->name);
|
BT_DBG("%s", hdev->name);
|
||||||
|
@ -676,7 +653,7 @@ failed:
|
||||||
|
|
||||||
static int btusb_flush(struct hci_dev *hdev)
|
static int btusb_flush(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
struct btusb_data *data = hdev->driver_data;
|
||||||
|
|
||||||
BT_DBG("%s", hdev->name);
|
BT_DBG("%s", hdev->name);
|
||||||
|
|
||||||
|
@ -688,7 +665,7 @@ static int btusb_flush(struct hci_dev *hdev)
|
||||||
static int btusb_send_frame(struct sk_buff *skb)
|
static int btusb_send_frame(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct hci_dev *hdev = (struct hci_dev *) skb->dev;
|
struct hci_dev *hdev = (struct hci_dev *) skb->dev;
|
||||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
struct btusb_data *data = hdev->driver_data;
|
||||||
struct usb_ctrlrequest *dr;
|
struct usb_ctrlrequest *dr;
|
||||||
struct urb *urb;
|
struct urb *urb;
|
||||||
unsigned int pipe;
|
unsigned int pipe;
|
||||||
|
@ -782,23 +759,31 @@ skip_waking:
|
||||||
|
|
||||||
err = usb_submit_urb(urb, GFP_ATOMIC);
|
err = usb_submit_urb(urb, GFP_ATOMIC);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
if (err != -EPERM && err != -ENODEV)
|
BT_ERR("%s urb %p submission failed", hdev->name, urb);
|
||||||
BT_ERR("%s urb %p submission failed (%d)",
|
|
||||||
hdev->name, urb, -err);
|
|
||||||
kfree(urb->setup_packet);
|
kfree(urb->setup_packet);
|
||||||
usb_unanchor_urb(urb);
|
usb_unanchor_urb(urb);
|
||||||
} else {
|
} else {
|
||||||
usb_mark_last_busy(data->udev);
|
usb_mark_last_busy(data->udev);
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
|
||||||
usb_free_urb(urb);
|
usb_free_urb(urb);
|
||||||
|
|
||||||
|
done:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void btusb_destruct(struct hci_dev *hdev)
|
||||||
|
{
|
||||||
|
struct btusb_data *data = hdev->driver_data;
|
||||||
|
|
||||||
|
BT_DBG("%s", hdev->name);
|
||||||
|
|
||||||
|
kfree(data);
|
||||||
|
}
|
||||||
|
|
||||||
static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
|
static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
|
||||||
{
|
{
|
||||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
struct btusb_data *data = hdev->driver_data;
|
||||||
|
|
||||||
BT_DBG("%s evt %d", hdev->name, evt);
|
BT_DBG("%s evt %d", hdev->name, evt);
|
||||||
|
|
||||||
|
@ -808,9 +793,9 @@ static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
|
static int inline __set_isoc_interface(struct hci_dev *hdev, int altsetting)
|
||||||
{
|
{
|
||||||
struct btusb_data *data = hci_get_drvdata(hdev);
|
struct btusb_data *data = hdev->driver_data;
|
||||||
struct usb_interface *intf = data->isoc;
|
struct usb_interface *intf = data->isoc;
|
||||||
struct usb_endpoint_descriptor *ep_desc;
|
struct usb_endpoint_descriptor *ep_desc;
|
||||||
int i, err;
|
int i, err;
|
||||||
|
@ -998,7 +983,7 @@ static int btusb_probe(struct usb_interface *intf,
|
||||||
}
|
}
|
||||||
|
|
||||||
hdev->bus = HCI_USB;
|
hdev->bus = HCI_USB;
|
||||||
hci_set_drvdata(hdev, data);
|
hdev->driver_data = data;
|
||||||
|
|
||||||
data->hdev = hdev;
|
data->hdev = hdev;
|
||||||
|
|
||||||
|
@ -1008,8 +993,11 @@ static int btusb_probe(struct usb_interface *intf,
|
||||||
hdev->close = btusb_close;
|
hdev->close = btusb_close;
|
||||||
hdev->flush = btusb_flush;
|
hdev->flush = btusb_flush;
|
||||||
hdev->send = btusb_send_frame;
|
hdev->send = btusb_send_frame;
|
||||||
|
hdev->destruct = btusb_destruct;
|
||||||
hdev->notify = btusb_notify;
|
hdev->notify = btusb_notify;
|
||||||
|
|
||||||
|
hdev->owner = THIS_MODULE;
|
||||||
|
|
||||||
/* Interface numbers are hardcoded in the specification */
|
/* Interface numbers are hardcoded in the specification */
|
||||||
data->isoc = usb_ifnum_to_if(data->udev, 1);
|
data->isoc = usb_ifnum_to_if(data->udev, 1);
|
||||||
|
|
||||||
|
@ -1091,6 +1079,9 @@ static void btusb_disconnect(struct usb_interface *intf)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
hdev = data->hdev;
|
hdev = data->hdev;
|
||||||
|
|
||||||
|
__hci_dev_hold(hdev);
|
||||||
|
|
||||||
usb_set_intfdata(data->intf, NULL);
|
usb_set_intfdata(data->intf, NULL);
|
||||||
|
|
||||||
if (data->isoc)
|
if (data->isoc)
|
||||||
|
@ -1103,8 +1094,9 @@ static void btusb_disconnect(struct usb_interface *intf)
|
||||||
else if (data->isoc)
|
else if (data->isoc)
|
||||||
usb_driver_release_interface(&btusb_driver, data->isoc);
|
usb_driver_release_interface(&btusb_driver, data->isoc);
|
||||||
|
|
||||||
|
__hci_dev_put(hdev);
|
||||||
|
|
||||||
hci_free_dev(hdev);
|
hci_free_dev(hdev);
|
||||||
kfree(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
|
@ -1118,7 +1110,7 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
spin_lock_irq(&data->txlock);
|
spin_lock_irq(&data->txlock);
|
||||||
if (!(PMSG_IS_AUTO(message) && data->tx_in_flight)) {
|
if (!((message.event & PM_EVENT_AUTO) && data->tx_in_flight)) {
|
||||||
set_bit(BTUSB_SUSPENDING, &data->flags);
|
set_bit(BTUSB_SUSPENDING, &data->flags);
|
||||||
spin_unlock_irq(&data->txlock);
|
spin_unlock_irq(&data->txlock);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1220,7 +1212,20 @@ static struct usb_driver btusb_driver = {
|
||||||
.supports_autosuspend = 1,
|
.supports_autosuspend = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
module_usb_driver(btusb_driver);
|
static int __init btusb_init(void)
|
||||||
|
{
|
||||||
|
BT_INFO("Generic Bluetooth USB driver ver %s", VERSION);
|
||||||
|
|
||||||
|
return usb_register(&btusb_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit btusb_exit(void)
|
||||||
|
{
|
||||||
|
usb_deregister(&btusb_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(btusb_init);
|
||||||
|
module_exit(btusb_exit);
|
||||||
|
|
||||||
module_param(ignore_dga, bool, 0644);
|
module_param(ignore_dga, bool, 0644);
|
||||||
MODULE_PARM_DESC(ignore_dga, "Ignore devices with id 08fd:0001");
|
MODULE_PARM_DESC(ignore_dga, "Ignore devices with id 08fd:0001");
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
#include <net/bluetooth/hci.h>
|
#include <net/bluetooth/hci.h>
|
||||||
|
|
||||||
#include <linux/ti_wilink_st.h>
|
#include <linux/ti_wilink_st.h>
|
||||||
#include <linux/module.h>
|
|
||||||
|
|
||||||
/* Bluetooth Driver Version */
|
/* Bluetooth Driver Version */
|
||||||
#define VERSION "1.0"
|
#define VERSION "1.0"
|
||||||
|
@ -125,13 +124,6 @@ static long st_receive(void *priv_data, struct sk_buff *skb)
|
||||||
/* ------- Interfaces to HCI layer ------ */
|
/* ------- Interfaces to HCI layer ------ */
|
||||||
/* protocol structure registered with shared transport */
|
/* protocol structure registered with shared transport */
|
||||||
static struct st_proto_s ti_st_proto[MAX_BT_CHNL_IDS] = {
|
static struct st_proto_s ti_st_proto[MAX_BT_CHNL_IDS] = {
|
||||||
{
|
|
||||||
.chnl_id = HCI_EVENT_PKT, /* HCI Events */
|
|
||||||
.hdr_len = sizeof(struct hci_event_hdr),
|
|
||||||
.offset_len_in_hdr = offsetof(struct hci_event_hdr, plen),
|
|
||||||
.len_size = 1, /* sizeof(plen) in struct hci_event_hdr */
|
|
||||||
.reserve = 8,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
.chnl_id = HCI_ACLDATA_PKT, /* ACL */
|
.chnl_id = HCI_ACLDATA_PKT, /* ACL */
|
||||||
.hdr_len = sizeof(struct hci_acl_hdr),
|
.hdr_len = sizeof(struct hci_acl_hdr),
|
||||||
|
@ -146,6 +138,13 @@ static struct st_proto_s ti_st_proto[MAX_BT_CHNL_IDS] = {
|
||||||
.len_size = 1, /* sizeof(dlen) in struct hci_sco_hdr */
|
.len_size = 1, /* sizeof(dlen) in struct hci_sco_hdr */
|
||||||
.reserve = 8,
|
.reserve = 8,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.chnl_id = HCI_EVENT_PKT, /* HCI Events */
|
||||||
|
.hdr_len = sizeof(struct hci_event_hdr),
|
||||||
|
.offset_len_in_hdr = offsetof(struct hci_event_hdr, plen),
|
||||||
|
.len_size = 1, /* sizeof(plen) in struct hci_event_hdr */
|
||||||
|
.reserve = 8,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Called from HCI core to initialize the device */
|
/* Called from HCI core to initialize the device */
|
||||||
|
@ -161,7 +160,7 @@ static int ti_st_open(struct hci_dev *hdev)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
/* provide contexts for callbacks from ST */
|
/* provide contexts for callbacks from ST */
|
||||||
hst = hci_get_drvdata(hdev);
|
hst = hdev->driver_data;
|
||||||
|
|
||||||
for (i = 0; i < MAX_BT_CHNL_IDS; i++) {
|
for (i = 0; i < MAX_BT_CHNL_IDS; i++) {
|
||||||
ti_st_proto[i].priv_data = hst;
|
ti_st_proto[i].priv_data = hst;
|
||||||
|
@ -236,12 +235,12 @@ done:
|
||||||
static int ti_st_close(struct hci_dev *hdev)
|
static int ti_st_close(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
int err, i;
|
int err, i;
|
||||||
struct ti_st *hst = hci_get_drvdata(hdev);
|
struct ti_st *hst = hdev->driver_data;
|
||||||
|
|
||||||
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
|
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (i = MAX_BT_CHNL_IDS-1; i >= 0; i--) {
|
for (i = 0; i < MAX_BT_CHNL_IDS; i++) {
|
||||||
err = st_unregister(&ti_st_proto[i]);
|
err = st_unregister(&ti_st_proto[i]);
|
||||||
if (err)
|
if (err)
|
||||||
BT_ERR("st_unregister(%d) failed with error %d",
|
BT_ERR("st_unregister(%d) failed with error %d",
|
||||||
|
@ -264,7 +263,7 @@ static int ti_st_send_frame(struct sk_buff *skb)
|
||||||
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
hst = hci_get_drvdata(hdev);
|
hst = hdev->driver_data;
|
||||||
|
|
||||||
/* Prepend skb with frame type */
|
/* Prepend skb with frame type */
|
||||||
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
|
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
|
||||||
|
@ -291,6 +290,14 @@ static int ti_st_send_frame(struct sk_buff *skb)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ti_st_destruct(struct hci_dev *hdev)
|
||||||
|
{
|
||||||
|
BT_DBG("%s", hdev->name);
|
||||||
|
/* do nothing here, since platform remove
|
||||||
|
* would free the hdev->driver_data
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
static int bt_ti_probe(struct platform_device *pdev)
|
static int bt_ti_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
static struct ti_st *hst;
|
static struct ti_st *hst;
|
||||||
|
@ -312,11 +319,13 @@ static int bt_ti_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
hst->hdev = hdev;
|
hst->hdev = hdev;
|
||||||
hdev->bus = HCI_UART;
|
hdev->bus = HCI_UART;
|
||||||
hci_set_drvdata(hdev, hst);
|
hdev->driver_data = hst;
|
||||||
hdev->open = ti_st_open;
|
hdev->open = ti_st_open;
|
||||||
hdev->close = ti_st_close;
|
hdev->close = ti_st_close;
|
||||||
hdev->flush = NULL;
|
hdev->flush = NULL;
|
||||||
hdev->send = ti_st_send_frame;
|
hdev->send = ti_st_send_frame;
|
||||||
|
hdev->destruct = ti_st_destruct;
|
||||||
|
hdev->owner = THIS_MODULE;
|
||||||
|
|
||||||
err = hci_register_dev(hdev);
|
err = hci_register_dev(hdev);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include <linux/serial.h>
|
#include <linux/serial.h>
|
||||||
#include <linux/serial_reg.h>
|
#include <linux/serial_reg.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
|
#include <asm/system.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
|
||||||
#include <pcmcia/cistpl.h>
|
#include <pcmcia/cistpl.h>
|
||||||
|
@ -82,6 +83,9 @@ typedef struct dtl1_info_t {
|
||||||
|
|
||||||
|
|
||||||
static int dtl1_config(struct pcmcia_device *link);
|
static int dtl1_config(struct pcmcia_device *link);
|
||||||
|
static void dtl1_release(struct pcmcia_device *link);
|
||||||
|
|
||||||
|
static void dtl1_detach(struct pcmcia_device *p_dev);
|
||||||
|
|
||||||
|
|
||||||
/* Transmit states */
|
/* Transmit states */
|
||||||
|
@ -363,7 +367,7 @@ static int dtl1_hci_open(struct hci_dev *hdev)
|
||||||
|
|
||||||
static int dtl1_hci_flush(struct hci_dev *hdev)
|
static int dtl1_hci_flush(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
dtl1_info_t *info = hci_get_drvdata(hdev);
|
dtl1_info_t *info = (dtl1_info_t *)(hdev->driver_data);
|
||||||
|
|
||||||
/* Drop TX queue */
|
/* Drop TX queue */
|
||||||
skb_queue_purge(&(info->txq));
|
skb_queue_purge(&(info->txq));
|
||||||
|
@ -395,7 +399,7 @@ static int dtl1_hci_send_frame(struct sk_buff *skb)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
info = hci_get_drvdata(hdev);
|
info = (dtl1_info_t *)(hdev->driver_data);
|
||||||
|
|
||||||
switch (bt_cb(skb)->pkt_type) {
|
switch (bt_cb(skb)->pkt_type) {
|
||||||
case HCI_COMMAND_PKT:
|
case HCI_COMMAND_PKT:
|
||||||
|
@ -438,6 +442,11 @@ static int dtl1_hci_send_frame(struct sk_buff *skb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void dtl1_hci_destruct(struct hci_dev *hdev)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int dtl1_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
|
static int dtl1_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
return -ENOIOCTLCMD;
|
return -ENOIOCTLCMD;
|
||||||
|
@ -474,15 +483,18 @@ static int dtl1_open(dtl1_info_t *info)
|
||||||
info->hdev = hdev;
|
info->hdev = hdev;
|
||||||
|
|
||||||
hdev->bus = HCI_PCCARD;
|
hdev->bus = HCI_PCCARD;
|
||||||
hci_set_drvdata(hdev, info);
|
hdev->driver_data = info;
|
||||||
SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
|
SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
|
||||||
|
|
||||||
hdev->open = dtl1_hci_open;
|
hdev->open = dtl1_hci_open;
|
||||||
hdev->close = dtl1_hci_close;
|
hdev->close = dtl1_hci_close;
|
||||||
hdev->flush = dtl1_hci_flush;
|
hdev->flush = dtl1_hci_flush;
|
||||||
hdev->send = dtl1_hci_send_frame;
|
hdev->send = dtl1_hci_send_frame;
|
||||||
|
hdev->destruct = dtl1_hci_destruct;
|
||||||
hdev->ioctl = dtl1_hci_ioctl;
|
hdev->ioctl = dtl1_hci_ioctl;
|
||||||
|
|
||||||
|
hdev->owner = THIS_MODULE;
|
||||||
|
|
||||||
spin_lock_irqsave(&(info->lock), flags);
|
spin_lock_irqsave(&(info->lock), flags);
|
||||||
|
|
||||||
/* Reset UART */
|
/* Reset UART */
|
||||||
|
@ -539,7 +551,9 @@ static int dtl1_close(dtl1_info_t *info)
|
||||||
|
|
||||||
spin_unlock_irqrestore(&(info->lock), flags);
|
spin_unlock_irqrestore(&(info->lock), flags);
|
||||||
|
|
||||||
hci_unregister_dev(hdev);
|
if (hci_unregister_dev(hdev) < 0)
|
||||||
|
BT_ERR("Can't unregister HCI device %s", hdev->name);
|
||||||
|
|
||||||
hci_free_dev(hdev);
|
hci_free_dev(hdev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -567,8 +581,8 @@ static void dtl1_detach(struct pcmcia_device *link)
|
||||||
{
|
{
|
||||||
dtl1_info_t *info = link->priv;
|
dtl1_info_t *info = link->priv;
|
||||||
|
|
||||||
dtl1_close(info);
|
dtl1_release(link);
|
||||||
pcmcia_disable_device(link);
|
|
||||||
kfree(info);
|
kfree(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -607,11 +621,22 @@ static int dtl1_config(struct pcmcia_device *link)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
failed:
|
failed:
|
||||||
dtl1_detach(link);
|
dtl1_release(link);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct pcmcia_device_id dtl1_ids[] = {
|
|
||||||
|
static void dtl1_release(struct pcmcia_device *link)
|
||||||
|
{
|
||||||
|
dtl1_info_t *info = link->priv;
|
||||||
|
|
||||||
|
dtl1_close(info);
|
||||||
|
|
||||||
|
pcmcia_disable_device(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct pcmcia_device_id dtl1_ids[] = {
|
||||||
PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-1", 0xe1bfdd64, 0xe168480d),
|
PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-1", 0xe1bfdd64, 0xe168480d),
|
||||||
PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-4", 0xe1bfdd64, 0x9102bc82),
|
PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-4", 0xe1bfdd64, 0x9102bc82),
|
||||||
PCMCIA_DEVICE_PROD_ID12("Socket", "CF", 0xb38bcc2e, 0x44ebf863),
|
PCMCIA_DEVICE_PROD_ID12("Socket", "CF", 0xb38bcc2e, 0x44ebf863),
|
||||||
|
|
|
@ -112,7 +112,7 @@ static int ath_open(struct hci_uart *hu)
|
||||||
|
|
||||||
BT_DBG("hu %p", hu);
|
BT_DBG("hu %p", hu);
|
||||||
|
|
||||||
ath = kzalloc(sizeof(*ath), GFP_KERNEL);
|
ath = kzalloc(sizeof(*ath), GFP_ATOMIC);
|
||||||
if (!ath)
|
if (!ath)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
|
|
@ -49,8 +49,8 @@
|
||||||
|
|
||||||
#define VERSION "0.3"
|
#define VERSION "0.3"
|
||||||
|
|
||||||
static bool txcrc = 1;
|
static int txcrc = 1;
|
||||||
static bool hciextn = 1;
|
static int hciextn = 1;
|
||||||
|
|
||||||
#define BCSP_TXWINSIZE 4
|
#define BCSP_TXWINSIZE 4
|
||||||
|
|
||||||
|
@ -692,7 +692,7 @@ static int bcsp_open(struct hci_uart *hu)
|
||||||
|
|
||||||
BT_DBG("hu %p", hu);
|
BT_DBG("hu %p", hu);
|
||||||
|
|
||||||
bcsp = kzalloc(sizeof(*bcsp), GFP_KERNEL);
|
bcsp = kzalloc(sizeof(*bcsp), GFP_ATOMIC);
|
||||||
if (!bcsp)
|
if (!bcsp)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,7 @@ static int h4_open(struct hci_uart *hu)
|
||||||
|
|
||||||
BT_DBG("hu %p", hu);
|
BT_DBG("hu %p", hu);
|
||||||
|
|
||||||
h4 = kzalloc(sizeof(*h4), GFP_KERNEL);
|
h4 = kzalloc(sizeof(*h4), GFP_ATOMIC);
|
||||||
if (!h4)
|
if (!h4)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,8 @@
|
||||||
|
|
||||||
#define VERSION "2.2"
|
#define VERSION "2.2"
|
||||||
|
|
||||||
|
static bool reset = 0;
|
||||||
|
|
||||||
static struct hci_uart_proto *hup[HCI_UART_MAX_PROTO];
|
static struct hci_uart_proto *hup[HCI_UART_MAX_PROTO];
|
||||||
|
|
||||||
int hci_uart_register_proto(struct hci_uart_proto *p)
|
int hci_uart_register_proto(struct hci_uart_proto *p)
|
||||||
|
@ -172,7 +174,7 @@ static int hci_uart_open(struct hci_dev *hdev)
|
||||||
/* Reset device */
|
/* Reset device */
|
||||||
static int hci_uart_flush(struct hci_dev *hdev)
|
static int hci_uart_flush(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct hci_uart *hu = hci_get_drvdata(hdev);
|
struct hci_uart *hu = (struct hci_uart *) hdev->driver_data;
|
||||||
struct tty_struct *tty = hu->tty;
|
struct tty_struct *tty = hu->tty;
|
||||||
|
|
||||||
BT_DBG("hdev %p tty %p", hdev, tty);
|
BT_DBG("hdev %p tty %p", hdev, tty);
|
||||||
|
@ -218,7 +220,7 @@ static int hci_uart_send_frame(struct sk_buff *skb)
|
||||||
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
hu = hci_get_drvdata(hdev);
|
hu = (struct hci_uart *) hdev->driver_data;
|
||||||
|
|
||||||
BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len);
|
BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len);
|
||||||
|
|
||||||
|
@ -229,6 +231,15 @@ static int hci_uart_send_frame(struct sk_buff *skb)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void hci_uart_destruct(struct hci_dev *hdev)
|
||||||
|
{
|
||||||
|
if (!hdev)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BT_DBG("%s", hdev->name);
|
||||||
|
kfree(hdev->driver_data);
|
||||||
|
}
|
||||||
|
|
||||||
/* ------ LDISC part ------ */
|
/* ------ LDISC part ------ */
|
||||||
/* hci_uart_tty_open
|
/* hci_uart_tty_open
|
||||||
*
|
*
|
||||||
|
@ -299,14 +310,12 @@ static void hci_uart_tty_close(struct tty_struct *tty)
|
||||||
hci_uart_close(hdev);
|
hci_uart_close(hdev);
|
||||||
|
|
||||||
if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
|
if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
|
||||||
|
hu->proto->close(hu);
|
||||||
if (hdev) {
|
if (hdev) {
|
||||||
hci_unregister_dev(hdev);
|
hci_unregister_dev(hdev);
|
||||||
hci_free_dev(hdev);
|
hci_free_dev(hdev);
|
||||||
}
|
}
|
||||||
hu->proto->close(hu);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kfree(hu);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,6 +359,7 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty)
|
||||||
*/
|
*/
|
||||||
static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count)
|
static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
struct hci_uart *hu = (void *)tty->disc_data;
|
struct hci_uart *hu = (void *)tty->disc_data;
|
||||||
|
|
||||||
if (!hu || tty != hu->tty)
|
if (!hu || tty != hu->tty)
|
||||||
|
@ -359,8 +369,9 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *f
|
||||||
return;
|
return;
|
||||||
|
|
||||||
spin_lock(&hu->rx_lock);
|
spin_lock(&hu->rx_lock);
|
||||||
hu->proto->recv(hu, (void *) data, count);
|
ret = hu->proto->recv(hu, (void *) data, count);
|
||||||
hu->hdev->stat.byte_rx += count;
|
if (ret > 0)
|
||||||
|
hu->hdev->stat.byte_rx += count;
|
||||||
spin_unlock(&hu->rx_lock);
|
spin_unlock(&hu->rx_lock);
|
||||||
|
|
||||||
tty_unthrottle(tty);
|
tty_unthrottle(tty);
|
||||||
|
@ -382,25 +393,23 @@ static int hci_uart_register_dev(struct hci_uart *hu)
|
||||||
hu->hdev = hdev;
|
hu->hdev = hdev;
|
||||||
|
|
||||||
hdev->bus = HCI_UART;
|
hdev->bus = HCI_UART;
|
||||||
hci_set_drvdata(hdev, hu);
|
hdev->driver_data = hu;
|
||||||
|
|
||||||
hdev->open = hci_uart_open;
|
hdev->open = hci_uart_open;
|
||||||
hdev->close = hci_uart_close;
|
hdev->close = hci_uart_close;
|
||||||
hdev->flush = hci_uart_flush;
|
hdev->flush = hci_uart_flush;
|
||||||
hdev->send = hci_uart_send_frame;
|
hdev->send = hci_uart_send_frame;
|
||||||
|
hdev->destruct = hci_uart_destruct;
|
||||||
hdev->parent = hu->tty->dev;
|
hdev->parent = hu->tty->dev;
|
||||||
|
|
||||||
|
hdev->owner = THIS_MODULE;
|
||||||
|
|
||||||
|
if (!reset)
|
||||||
|
set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
|
||||||
|
|
||||||
if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags))
|
if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags))
|
||||||
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
|
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
|
||||||
|
|
||||||
if (!test_bit(HCI_UART_RESET_ON_INIT, &hu->hdev_flags))
|
|
||||||
set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
|
|
||||||
|
|
||||||
if (test_bit(HCI_UART_CREATE_AMP, &hu->hdev_flags))
|
|
||||||
hdev->dev_type = HCI_AMP;
|
|
||||||
else
|
|
||||||
hdev->dev_type = HCI_BREDR;
|
|
||||||
|
|
||||||
if (hci_register_dev(hdev) < 0) {
|
if (hci_register_dev(hdev) < 0) {
|
||||||
BT_ERR("Can't register HCI device");
|
BT_ERR("Can't register HCI device");
|
||||||
hci_free_dev(hdev);
|
hci_free_dev(hdev);
|
||||||
|
@ -587,6 +596,9 @@ static void __exit hci_uart_exit(void)
|
||||||
module_init(hci_uart_init);
|
module_init(hci_uart_init);
|
||||||
module_exit(hci_uart_exit);
|
module_exit(hci_uart_exit);
|
||||||
|
|
||||||
|
module_param(reset, bool, 0644);
|
||||||
|
MODULE_PARM_DESC(reset, "Send HCI reset command on initialization");
|
||||||
|
|
||||||
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
|
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
|
||||||
MODULE_DESCRIPTION("Bluetooth HCI UART driver ver " VERSION);
|
MODULE_DESCRIPTION("Bluetooth HCI UART driver ver " VERSION);
|
||||||
MODULE_VERSION(VERSION);
|
MODULE_VERSION(VERSION);
|
||||||
|
|
|
@ -125,7 +125,7 @@ static int ll_open(struct hci_uart *hu)
|
||||||
|
|
||||||
BT_DBG("hu %p", hu);
|
BT_DBG("hu %p", hu);
|
||||||
|
|
||||||
ll = kzalloc(sizeof(*ll), GFP_KERNEL);
|
ll = kzalloc(sizeof(*ll), GFP_ATOMIC);
|
||||||
if (!ll)
|
if (!ll)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@ -207,7 +207,7 @@ static void ll_device_want_to_wakeup(struct hci_uart *hu)
|
||||||
/*
|
/*
|
||||||
* This state means that both the host and the BRF chip
|
* This state means that both the host and the BRF chip
|
||||||
* have simultaneously sent a wake-up-indication packet.
|
* have simultaneously sent a wake-up-indication packet.
|
||||||
* Traditionally, in this case, receiving a wake-up-indication
|
* Traditionaly, in this case, receiving a wake-up-indication
|
||||||
* was enough and an additional wake-up-ack wasn't needed.
|
* was enough and an additional wake-up-ack wasn't needed.
|
||||||
* This has changed with the BRF6350, which does require an
|
* This has changed with the BRF6350, which does require an
|
||||||
* explicit wake-up-ack. Other BRF versions, which do not
|
* explicit wake-up-ack. Other BRF versions, which do not
|
||||||
|
|
|
@ -45,8 +45,6 @@
|
||||||
#define HCI_UART_ATH3K 5
|
#define HCI_UART_ATH3K 5
|
||||||
|
|
||||||
#define HCI_UART_RAW_DEVICE 0
|
#define HCI_UART_RAW_DEVICE 0
|
||||||
#define HCI_UART_RESET_ON_INIT 1
|
|
||||||
#define HCI_UART_CREATE_AMP 2
|
|
||||||
|
|
||||||
struct hci_uart;
|
struct hci_uart;
|
||||||
|
|
||||||
|
|
|
@ -41,8 +41,6 @@
|
||||||
|
|
||||||
#define VERSION "1.3"
|
#define VERSION "1.3"
|
||||||
|
|
||||||
static bool amp;
|
|
||||||
|
|
||||||
struct vhci_data {
|
struct vhci_data {
|
||||||
struct hci_dev *hdev;
|
struct hci_dev *hdev;
|
||||||
|
|
||||||
|
@ -61,7 +59,7 @@ static int vhci_open_dev(struct hci_dev *hdev)
|
||||||
|
|
||||||
static int vhci_close_dev(struct hci_dev *hdev)
|
static int vhci_close_dev(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct vhci_data *data = hci_get_drvdata(hdev);
|
struct vhci_data *data = hdev->driver_data;
|
||||||
|
|
||||||
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
|
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -73,7 +71,7 @@ static int vhci_close_dev(struct hci_dev *hdev)
|
||||||
|
|
||||||
static int vhci_flush(struct hci_dev *hdev)
|
static int vhci_flush(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct vhci_data *data = hci_get_drvdata(hdev);
|
struct vhci_data *data = hdev->driver_data;
|
||||||
|
|
||||||
skb_queue_purge(&data->readq);
|
skb_queue_purge(&data->readq);
|
||||||
|
|
||||||
|
@ -93,7 +91,7 @@ static int vhci_send_frame(struct sk_buff *skb)
|
||||||
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
data = hci_get_drvdata(hdev);
|
data = hdev->driver_data;
|
||||||
|
|
||||||
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
|
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
|
||||||
skb_queue_tail(&data->readq, skb);
|
skb_queue_tail(&data->readq, skb);
|
||||||
|
@ -103,6 +101,11 @@ static int vhci_send_frame(struct sk_buff *skb)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vhci_destruct(struct hci_dev *hdev)
|
||||||
|
{
|
||||||
|
kfree(hdev->driver_data);
|
||||||
|
}
|
||||||
|
|
||||||
static inline ssize_t vhci_get_user(struct vhci_data *data,
|
static inline ssize_t vhci_get_user(struct vhci_data *data,
|
||||||
const char __user *buf, size_t count)
|
const char __user *buf, size_t count)
|
||||||
{
|
{
|
||||||
|
@ -234,15 +237,15 @@ static int vhci_open(struct inode *inode, struct file *file)
|
||||||
data->hdev = hdev;
|
data->hdev = hdev;
|
||||||
|
|
||||||
hdev->bus = HCI_VIRTUAL;
|
hdev->bus = HCI_VIRTUAL;
|
||||||
hci_set_drvdata(hdev, data);
|
hdev->driver_data = data;
|
||||||
|
|
||||||
if (amp)
|
|
||||||
hdev->dev_type = HCI_AMP;
|
|
||||||
|
|
||||||
hdev->open = vhci_open_dev;
|
hdev->open = vhci_open_dev;
|
||||||
hdev->close = vhci_close_dev;
|
hdev->close = vhci_close_dev;
|
||||||
hdev->flush = vhci_flush;
|
hdev->flush = vhci_flush;
|
||||||
hdev->send = vhci_send_frame;
|
hdev->send = vhci_send_frame;
|
||||||
|
hdev->destruct = vhci_destruct;
|
||||||
|
|
||||||
|
hdev->owner = THIS_MODULE;
|
||||||
|
|
||||||
if (hci_register_dev(hdev) < 0) {
|
if (hci_register_dev(hdev) < 0) {
|
||||||
BT_ERR("Can't register HCI device");
|
BT_ERR("Can't register HCI device");
|
||||||
|
@ -261,11 +264,13 @@ static int vhci_release(struct inode *inode, struct file *file)
|
||||||
struct vhci_data *data = file->private_data;
|
struct vhci_data *data = file->private_data;
|
||||||
struct hci_dev *hdev = data->hdev;
|
struct hci_dev *hdev = data->hdev;
|
||||||
|
|
||||||
hci_unregister_dev(hdev);
|
if (hci_unregister_dev(hdev) < 0) {
|
||||||
|
BT_ERR("Can't unregister HCI device %s", hdev->name);
|
||||||
|
}
|
||||||
|
|
||||||
hci_free_dev(hdev);
|
hci_free_dev(hdev);
|
||||||
|
|
||||||
file->private_data = NULL;
|
file->private_data = NULL;
|
||||||
kfree(data);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -301,9 +306,6 @@ static void __exit vhci_exit(void)
|
||||||
module_init(vhci_init);
|
module_init(vhci_init);
|
||||||
module_exit(vhci_exit);
|
module_exit(vhci_exit);
|
||||||
|
|
||||||
module_param(amp, bool, 0644);
|
|
||||||
MODULE_PARM_DESC(amp, "Create AMP controller device");
|
|
||||||
|
|
||||||
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
|
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
|
||||||
MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION);
|
MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION);
|
||||||
MODULE_VERSION(VERSION);
|
MODULE_VERSION(VERSION);
|
||||||
|
|
Loading…
Reference in a new issue