bluetooth: updated bluetooth stack
This commit is contained in:
parent
4da1d6cab6
commit
64b3392b72
@ -58,6 +58,18 @@ config BT_HCIUART_BCSP
|
||||
|
||||
Say Y here to compile support for HCI BCSP protocol.
|
||||
|
||||
config BT_HCIUART_ATH3K
|
||||
bool "Atheros AR300x serial support"
|
||||
depends on BT_HCIUART
|
||||
help
|
||||
HCIATH3K (HCI Atheros AR300x) is a serial protocol for
|
||||
communication between host and Atheros AR300x Bluetooth devices.
|
||||
This protocol enables AR300x chips to be enabled with
|
||||
power management support.
|
||||
Enable this if you have Atheros AR300x serial Bluetooth device.
|
||||
|
||||
Say Y here to compile support for HCI UART ATH3K protocol.
|
||||
|
||||
config BT_HCIUART_LL
|
||||
bool "HCILL protocol support"
|
||||
depends on BT_HCIUART
|
||||
@ -195,5 +207,16 @@ config BT_MRVL_SDIO
|
||||
Say Y here to compile support for Marvell BT-over-SDIO driver
|
||||
into the kernel or say M to compile it as module.
|
||||
|
||||
endmenu
|
||||
config BT_ATH3K
|
||||
tristate "Atheros firmware download driver"
|
||||
depends on BT_HCIBTUSB
|
||||
select FW_LOADER
|
||||
help
|
||||
Bluetooth firmware download driver.
|
||||
This driver loads the firmware into the Atheros Bluetooth
|
||||
chipset.
|
||||
|
||||
Say Y here to compile support for "Atheros firmware download driver"
|
||||
into the kernel or say M to compile it as module (ath3k).
|
||||
|
||||
endmenu
|
||||
|
@ -15,6 +15,7 @@ obj-$(CONFIG_BT_HCIBTUART) += btuart_cs.o
|
||||
obj-$(CONFIG_BT_HCIBTUSB) += btusb.o
|
||||
obj-$(CONFIG_BT_HCIBTSDIO) += btsdio.o
|
||||
|
||||
obj-$(CONFIG_BT_ATH3K) += ath3k.o
|
||||
obj-$(CONFIG_BT_MRVL) += btmrvl.o
|
||||
obj-$(CONFIG_BT_MRVL_SDIO) += btmrvl_sdio.o
|
||||
|
||||
@ -25,4 +26,5 @@ hci_uart-y := hci_ldisc.o
|
||||
hci_uart-$(CONFIG_BT_HCIUART_H4) += hci_h4.o
|
||||
hci_uart-$(CONFIG_BT_HCIUART_BCSP) += hci_bcsp.o
|
||||
hci_uart-$(CONFIG_BT_HCIUART_LL) += hci_ll.o
|
||||
hci_uart-$(CONFIG_BT_HCIUART_ATH3K) += hci_ath.o
|
||||
hci_uart-objs := $(hci_uart-y)
|
||||
|
@ -39,7 +39,7 @@
|
||||
|
||||
#define VERSION "1.2"
|
||||
|
||||
static struct usb_device_id bcm203x_table[] = {
|
||||
static const struct usb_device_id bcm203x_table[] = {
|
||||
/* Broadcom Blutonium (BCM2033) */
|
||||
{ USB_DEVICE(0x0a5c, 0x2033) },
|
||||
|
||||
@ -224,7 +224,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
|
||||
|
||||
BT_DBG("firmware data %p size %zu", firmware->data, firmware->size);
|
||||
|
||||
data->fw_data = kmalloc(firmware->size, GFP_KERNEL);
|
||||
data->fw_data = kmemdup(firmware->data, firmware->size, GFP_KERNEL);
|
||||
if (!data->fw_data) {
|
||||
BT_ERR("Can't allocate memory for firmware image");
|
||||
release_firmware(firmware);
|
||||
@ -234,7 +234,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(data->fw_data, firmware->data, firmware->size);
|
||||
data->fw_size = firmware->size;
|
||||
data->fw_sent = 0;
|
||||
|
||||
|
@ -703,7 +703,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||
|
||||
data->hdev = hdev;
|
||||
|
||||
hdev->type = HCI_USB;
|
||||
hdev->bus = HCI_USB;
|
||||
hdev->driver_data = data;
|
||||
SET_HCIDEV_DEV(hdev, &intf->dev);
|
||||
|
||||
|
@ -37,9 +37,8 @@
|
||||
#include <linux/wait.h>
|
||||
|
||||
#include <linux/skbuff.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <pcmcia/cs_types.h>
|
||||
#include <pcmcia/cs.h>
|
||||
#include <pcmcia/cistpl.h>
|
||||
#include <pcmcia/ciscode.h>
|
||||
@ -65,7 +64,6 @@ MODULE_LICENSE("GPL");
|
||||
|
||||
typedef struct bluecard_info_t {
|
||||
struct pcmcia_device *p_dev;
|
||||
dev_node_t node;
|
||||
|
||||
struct hci_dev *hdev;
|
||||
|
||||
@ -161,7 +159,7 @@ static void bluecard_detach(struct pcmcia_device *p_dev);
|
||||
static void bluecard_activity_led_timeout(u_long arg)
|
||||
{
|
||||
bluecard_info_t *info = (bluecard_info_t *)arg;
|
||||
unsigned int iobase = info->p_dev->io.BasePort1;
|
||||
unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
|
||||
if (!test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
|
||||
return;
|
||||
@ -178,7 +176,7 @@ static void bluecard_activity_led_timeout(u_long arg)
|
||||
|
||||
static void bluecard_enable_activity_led(bluecard_info_t *info)
|
||||
{
|
||||
unsigned int iobase = info->p_dev->io.BasePort1;
|
||||
unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
|
||||
if (!test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
|
||||
return;
|
||||
@ -234,7 +232,7 @@ static void bluecard_write_wakeup(bluecard_info_t *info)
|
||||
}
|
||||
|
||||
do {
|
||||
register unsigned int iobase = info->p_dev->io.BasePort1;
|
||||
register unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
register unsigned int offset;
|
||||
register unsigned char command;
|
||||
register unsigned long ready_bit;
|
||||
@ -381,7 +379,7 @@ static void bluecard_receive(bluecard_info_t *info, unsigned int offset)
|
||||
return;
|
||||
}
|
||||
|
||||
iobase = info->p_dev->io.BasePort1;
|
||||
iobase = info->p_dev->resource[0]->start;
|
||||
|
||||
if (test_bit(XMIT_SENDING_READY, &(info->tx_state)))
|
||||
bluecard_enable_activity_led(info);
|
||||
@ -503,12 +501,14 @@ static irqreturn_t bluecard_interrupt(int irq, void *dev_inst)
|
||||
unsigned int iobase;
|
||||
unsigned char reg;
|
||||
|
||||
BUG_ON(!info->hdev);
|
||||
if (!info || !info->hdev)
|
||||
/* our irq handler is shared */
|
||||
return IRQ_NONE;
|
||||
|
||||
if (!test_bit(CARD_READY, &(info->hw_state)))
|
||||
return IRQ_HANDLED;
|
||||
|
||||
iobase = info->p_dev->io.BasePort1;
|
||||
iobase = info->p_dev->resource[0]->start;
|
||||
|
||||
spin_lock(&(info->lock));
|
||||
|
||||
@ -622,7 +622,7 @@ static int bluecard_hci_flush(struct hci_dev *hdev)
|
||||
static int bluecard_hci_open(struct hci_dev *hdev)
|
||||
{
|
||||
bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data);
|
||||
unsigned int iobase = info->p_dev->io.BasePort1;
|
||||
unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
|
||||
if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
|
||||
bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE);
|
||||
@ -642,7 +642,7 @@ static int bluecard_hci_open(struct hci_dev *hdev)
|
||||
static int bluecard_hci_close(struct hci_dev *hdev)
|
||||
{
|
||||
bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data);
|
||||
unsigned int iobase = info->p_dev->io.BasePort1;
|
||||
unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
|
||||
if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
|
||||
return 0;
|
||||
@ -709,7 +709,7 @@ static int bluecard_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned l
|
||||
|
||||
static int bluecard_open(bluecard_info_t *info)
|
||||
{
|
||||
unsigned int iobase = info->p_dev->io.BasePort1;
|
||||
unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
struct hci_dev *hdev;
|
||||
unsigned char id;
|
||||
|
||||
@ -734,7 +734,7 @@ static int bluecard_open(bluecard_info_t *info)
|
||||
|
||||
info->hdev = hdev;
|
||||
|
||||
hdev->type = HCI_PCCARD;
|
||||
hdev->bus = HCI_PCCARD;
|
||||
hdev->driver_data = info;
|
||||
SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
|
||||
|
||||
@ -828,7 +828,7 @@ static int bluecard_open(bluecard_info_t *info)
|
||||
|
||||
static int bluecard_close(bluecard_info_t *info)
|
||||
{
|
||||
unsigned int iobase = info->p_dev->io.BasePort1;
|
||||
unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
struct hci_dev *hdev = info->hdev;
|
||||
|
||||
if (!hdev)
|
||||
@ -865,14 +865,6 @@ static int bluecard_probe(struct pcmcia_device *link)
|
||||
info->p_dev = link;
|
||||
link->priv = info;
|
||||
|
||||
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
|
||||
link->io.NumPorts1 = 8;
|
||||
link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
|
||||
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
|
||||
|
||||
link->irq.Handler = bluecard_interrupt;
|
||||
link->irq.Instance = info;
|
||||
|
||||
link->conf.Attributes = CONF_ENABLE_IRQ;
|
||||
link->conf.IntType = INT_MEMORY_AND_IO;
|
||||
|
||||
@ -895,39 +887,32 @@ static int bluecard_config(struct pcmcia_device *link)
|
||||
int i, n;
|
||||
|
||||
link->conf.ConfigIndex = 0x20;
|
||||
link->io.NumPorts1 = 64;
|
||||
link->io.IOAddrLines = 6;
|
||||
|
||||
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
|
||||
link->resource[0]->end = 64;
|
||||
link->io_lines = 6;
|
||||
|
||||
for (n = 0; n < 0x400; n += 0x40) {
|
||||
link->io.BasePort1 = n ^ 0x300;
|
||||
i = pcmcia_request_io(link, &link->io);
|
||||
link->resource[0]->start = n ^ 0x300;
|
||||
i = pcmcia_request_io(link);
|
||||
if (i == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i != 0) {
|
||||
cs_error(link, RequestIO, i);
|
||||
if (i != 0)
|
||||
goto failed;
|
||||
}
|
||||
|
||||
i = pcmcia_request_irq(link, &link->irq);
|
||||
if (i != 0) {
|
||||
cs_error(link, RequestIRQ, i);
|
||||
link->irq.AssignedIRQ = 0;
|
||||
}
|
||||
i = pcmcia_request_irq(link, bluecard_interrupt);
|
||||
if (i != 0)
|
||||
goto failed;
|
||||
|
||||
i = pcmcia_request_configuration(link, &link->conf);
|
||||
if (i != 0) {
|
||||
cs_error(link, RequestConfiguration, i);
|
||||
if (i != 0)
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (bluecard_open(info) != 0)
|
||||
goto failed;
|
||||
|
||||
strcpy(info->node.dev_name, info->hdev->name);
|
||||
link->dev_node = &info->node;
|
||||
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
|
@ -62,7 +62,7 @@ struct hci_vendor_hdr {
|
||||
__u8 type;
|
||||
__le16 snum;
|
||||
__le16 dlen;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
static int bpa10x_recv(struct hci_dev *hdev, int queue, void *buf, int count)
|
||||
{
|
||||
@ -469,7 +469,7 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
hdev->type = HCI_USB;
|
||||
hdev->bus = HCI_USB;
|
||||
hdev->driver_data = data;
|
||||
|
||||
data->hdev = hdev;
|
||||
|
@ -45,7 +45,6 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
#include <pcmcia/cs_types.h>
|
||||
#include <pcmcia/cs.h>
|
||||
#include <pcmcia/cistpl.h>
|
||||
#include <pcmcia/ciscode.h>
|
||||
@ -72,7 +71,6 @@ MODULE_FIRMWARE("BT3CPCC.bin");
|
||||
|
||||
typedef struct bt3c_info_t {
|
||||
struct pcmcia_device *p_dev;
|
||||
dev_node_t node;
|
||||
|
||||
struct hci_dev *hdev;
|
||||
|
||||
@ -190,7 +188,7 @@ static void bt3c_write_wakeup(bt3c_info_t *info)
|
||||
return;
|
||||
|
||||
do {
|
||||
register unsigned int iobase = info->p_dev->io.BasePort1;
|
||||
register unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
register struct sk_buff *skb;
|
||||
register int len;
|
||||
|
||||
@ -228,7 +226,7 @@ static void bt3c_receive(bt3c_info_t *info)
|
||||
return;
|
||||
}
|
||||
|
||||
iobase = info->p_dev->io.BasePort1;
|
||||
iobase = info->p_dev->resource[0]->start;
|
||||
|
||||
avail = bt3c_read(iobase, 0x7006);
|
||||
//printk("bt3c_cs: receiving %d bytes\n", avail);
|
||||
@ -345,9 +343,11 @@ static irqreturn_t bt3c_interrupt(int irq, void *dev_inst)
|
||||
int iir;
|
||||
irqreturn_t r = IRQ_NONE;
|
||||
|
||||
BUG_ON(!info->hdev);
|
||||
if (!info || !info->hdev)
|
||||
/* our irq handler is shared */
|
||||
return IRQ_NONE;
|
||||
|
||||
iobase = info->p_dev->io.BasePort1;
|
||||
iobase = info->p_dev->resource[0]->start;
|
||||
|
||||
spin_lock(&(info->lock));
|
||||
|
||||
@ -480,7 +480,7 @@ static int bt3c_load_firmware(bt3c_info_t *info, const unsigned char *firmware,
|
||||
unsigned int iobase, size, addr, fcs, tmp;
|
||||
int i, err = 0;
|
||||
|
||||
iobase = info->p_dev->io.BasePort1;
|
||||
iobase = info->p_dev->resource[0]->start;
|
||||
|
||||
/* Reset */
|
||||
bt3c_io_write(iobase, 0x8040, 0x0404);
|
||||
@ -580,7 +580,7 @@ static int bt3c_open(bt3c_info_t *info)
|
||||
|
||||
info->hdev = hdev;
|
||||
|
||||
hdev->type = HCI_PCCARD;
|
||||
hdev->bus = HCI_PCCARD;
|
||||
hdev->driver_data = info;
|
||||
SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
|
||||
|
||||
@ -657,13 +657,8 @@ static int bt3c_probe(struct pcmcia_device *link)
|
||||
info->p_dev = link;
|
||||
link->priv = info;
|
||||
|
||||
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
|
||||
link->io.NumPorts1 = 8;
|
||||
link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
|
||||
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
|
||||
|
||||
link->irq.Handler = bt3c_interrupt;
|
||||
link->irq.Instance = info;
|
||||
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
|
||||
link->resource[0]->end = 8;
|
||||
|
||||
link->conf.Attributes = CONF_ENABLE_IRQ;
|
||||
link->conf.IntType = INT_MEMORY_AND_IO;
|
||||
@ -688,14 +683,14 @@ static int bt3c_check_config(struct pcmcia_device *p_dev,
|
||||
{
|
||||
unsigned long try = (unsigned long) priv_data;
|
||||
|
||||
p_dev->io_lines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
|
||||
|
||||
if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
|
||||
p_dev->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
|
||||
if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
|
||||
(cf->io.win[0].base != 0)) {
|
||||
p_dev->io.BasePort1 = cf->io.win[0].base;
|
||||
p_dev->io.IOAddrLines = (try == 0) ? 16 :
|
||||
cf->io.flags & CISTPL_IO_LINES_MASK;
|
||||
if (!pcmcia_request_io(p_dev, &p_dev->io))
|
||||
p_dev->resource[0]->start = cf->io.win[0].base;
|
||||
if (!pcmcia_request_io(p_dev))
|
||||
return 0;
|
||||
}
|
||||
return -ENODEV;
|
||||
@ -712,9 +707,9 @@ static int bt3c_check_config_notpicky(struct pcmcia_device *p_dev,
|
||||
|
||||
if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
|
||||
for (j = 0; j < 5; j++) {
|
||||
p_dev->io.BasePort1 = base[j];
|
||||
p_dev->io.IOAddrLines = base[j] ? 16 : 3;
|
||||
if (!pcmcia_request_io(p_dev, &p_dev->io))
|
||||
p_dev->resource[0]->start = base[j];
|
||||
p_dev->io_lines = base[j] ? 16 : 3;
|
||||
if (!pcmcia_request_io(p_dev))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -740,28 +735,20 @@ static int bt3c_config(struct pcmcia_device *link)
|
||||
goto found_port;
|
||||
|
||||
BT_ERR("No usable port range found");
|
||||
cs_error(link, RequestIO, -ENODEV);
|
||||
goto failed;
|
||||
|
||||
found_port:
|
||||
i = pcmcia_request_irq(link, &link->irq);
|
||||
if (i != 0) {
|
||||
cs_error(link, RequestIRQ, i);
|
||||
link->irq.AssignedIRQ = 0;
|
||||
}
|
||||
i = pcmcia_request_irq(link, &bt3c_interrupt);
|
||||
if (i != 0)
|
||||
goto failed;
|
||||
|
||||
i = pcmcia_request_configuration(link, &link->conf);
|
||||
if (i != 0) {
|
||||
cs_error(link, RequestConfiguration, i);
|
||||
if (i != 0)
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (bt3c_open(info) != 0)
|
||||
goto failed;
|
||||
|
||||
strcpy(info->node.dev_name, info->hdev->name);
|
||||
link->dev_node = &info->node;
|
||||
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
|
@ -19,6 +19,7 @@
|
||||
**/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
@ -26,10 +27,10 @@
|
||||
#include "btmrvl_drv.h"
|
||||
|
||||
struct btmrvl_debugfs_data {
|
||||
struct dentry *root_dir, *config_dir, *status_dir;
|
||||
struct dentry *config_dir;
|
||||
struct dentry *status_dir;
|
||||
|
||||
/* config */
|
||||
struct dentry *drvdbg;
|
||||
struct dentry *psmode;
|
||||
struct dentry *pscmd;
|
||||
struct dentry *hsmode;
|
||||
@ -215,7 +216,7 @@ static const struct file_operations btmrvl_gpiogap_fops = {
|
||||
static ssize_t btmrvl_hscmd_write(struct file *file, const char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct btmrvl_private *priv = (struct btmrvl_private *) file->private_data;
|
||||
struct btmrvl_private *priv = file->private_data;
|
||||
char buf[16];
|
||||
long result, ret;
|
||||
|
||||
@ -364,6 +365,9 @@ void btmrvl_debugfs_init(struct hci_dev *hdev)
|
||||
struct btmrvl_private *priv = hdev->driver_data;
|
||||
struct btmrvl_debugfs_data *dbg;
|
||||
|
||||
if (!hdev->debugfs)
|
||||
return;
|
||||
|
||||
dbg = kzalloc(sizeof(*dbg), GFP_KERNEL);
|
||||
priv->debugfs_data = dbg;
|
||||
|
||||
@ -372,9 +376,7 @@ void btmrvl_debugfs_init(struct hci_dev *hdev)
|
||||
return;
|
||||
}
|
||||
|
||||
dbg->root_dir = debugfs_create_dir("btmrvl", NULL);
|
||||
|
||||
dbg->config_dir = debugfs_create_dir("config", dbg->root_dir);
|
||||
dbg->config_dir = debugfs_create_dir("config", hdev->debugfs);
|
||||
|
||||
dbg->psmode = debugfs_create_file("psmode", 0644, dbg->config_dir,
|
||||
hdev->driver_data, &btmrvl_psmode_fops);
|
||||
@ -389,7 +391,7 @@ void btmrvl_debugfs_init(struct hci_dev *hdev)
|
||||
dbg->hscfgcmd = debugfs_create_file("hscfgcmd", 0644, dbg->config_dir,
|
||||
hdev->driver_data, &btmrvl_hscfgcmd_fops);
|
||||
|
||||
dbg->status_dir = debugfs_create_dir("status", dbg->root_dir);
|
||||
dbg->status_dir = debugfs_create_dir("status", hdev->debugfs);
|
||||
dbg->curpsmode = debugfs_create_file("curpsmode", 0444,
|
||||
dbg->status_dir,
|
||||
hdev->driver_data,
|
||||
@ -426,7 +428,5 @@ void btmrvl_debugfs_remove(struct hci_dev *hdev)
|
||||
debugfs_remove(dbg->txdnldready);
|
||||
debugfs_remove(dbg->status_dir);
|
||||
|
||||
debugfs_remove(dbg->root_dir);
|
||||
|
||||
kfree(dbg);
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/slab.h>
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
|
||||
#define BTM_HEADER_LEN 4
|
||||
@ -41,6 +42,8 @@ struct btmrvl_device {
|
||||
void *card;
|
||||
struct hci_dev *hcidev;
|
||||
|
||||
u8 dev_type;
|
||||
|
||||
u8 tx_dnld_rdy;
|
||||
|
||||
u8 psmode;
|
||||
@ -73,6 +76,7 @@ struct btmrvl_private {
|
||||
int (*hw_host_to_card) (struct btmrvl_private *priv,
|
||||
u8 *payload, u16 nb);
|
||||
int (*hw_wakeup_firmware) (struct btmrvl_private *priv);
|
||||
int (*hw_process_int_status) (struct btmrvl_private *priv);
|
||||
spinlock_t driver_lock; /* spinlock used by driver */
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
void *debugfs_data;
|
||||
@ -87,8 +91,11 @@ struct btmrvl_private {
|
||||
#define BT_CMD_HOST_SLEEP_ENABLE 0x5A
|
||||
#define BT_CMD_MODULE_CFG_REQ 0x5B
|
||||
|
||||
/* Sub-commands: Module Bringup/Shutdown Request */
|
||||
/* Sub-commands: Module Bringup/Shutdown Request/Response */
|
||||
#define MODULE_BRINGUP_REQ 0xF1
|
||||
#define MODULE_BROUGHT_UP 0x00
|
||||
#define MODULE_ALREADY_UP 0x0C
|
||||
|
||||
#define MODULE_SHUTDOWN_REQ 0xF2
|
||||
|
||||
#define BT_EVENT_POWER_STATE 0x20
|
||||
@ -112,16 +119,17 @@ struct btmrvl_cmd {
|
||||
__le16 ocf_ogf;
|
||||
u8 length;
|
||||
u8 data[4];
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
struct btmrvl_event {
|
||||
u8 ec; /* event counter */
|
||||
u8 length;
|
||||
u8 data[4];
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
/* Prototype of global function */
|
||||
|
||||
int btmrvl_register_hdev(struct btmrvl_private *priv);
|
||||
struct btmrvl_private *btmrvl_add_card(void *card);
|
||||
int btmrvl_remove_card(struct btmrvl_private *priv);
|
||||
|
||||
@ -131,6 +139,7 @@ void btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb);
|
||||
int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb);
|
||||
|
||||
int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd);
|
||||
int btmrvl_enable_ps(struct btmrvl_private *priv);
|
||||
int btmrvl_prepare_command(struct btmrvl_private *priv);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
@ -66,7 +66,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
|
||||
{
|
||||
struct btmrvl_adapter *adapter = priv->adapter;
|
||||
struct btmrvl_event *event;
|
||||
u8 ret = 0;
|
||||
int ret = 0;
|
||||
|
||||
event = (struct btmrvl_event *) skb->data;
|
||||
if (event->ec != 0xff) {
|
||||
@ -112,8 +112,17 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
|
||||
case BT_CMD_MODULE_CFG_REQ:
|
||||
if (priv->btmrvl_dev.sendcmdflag &&
|
||||
event->data[1] == MODULE_BRINGUP_REQ) {
|
||||
BT_DBG("EVENT:%s", (event->data[2]) ?
|
||||
"Bring-up failed" : "Bring-up succeed");
|
||||
BT_DBG("EVENT:%s",
|
||||
((event->data[2] == MODULE_BROUGHT_UP) ||
|
||||
(event->data[2] == MODULE_ALREADY_UP)) ?
|
||||
"Bring-up succeed" : "Bring-up failed");
|
||||
|
||||
if (event->length > 3)
|
||||
priv->btmrvl_dev.dev_type = event->data[3];
|
||||
else
|
||||
priv->btmrvl_dev.dev_type = HCI_BREDR;
|
||||
|
||||
BT_DBG("dev_type: %d", priv->btmrvl_dev.dev_type);
|
||||
} else if (priv->btmrvl_dev.sendcmdflag &&
|
||||
event->data[1] == MODULE_SHUTDOWN_REQ) {
|
||||
BT_DBG("EVENT:%s", (event->data[2]) ?
|
||||
@ -189,6 +198,38 @@ int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btmrvl_send_module_cfg_cmd);
|
||||
|
||||
int btmrvl_enable_ps(struct btmrvl_private *priv)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct btmrvl_cmd *cmd;
|
||||
|
||||
skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
|
||||
if (skb == NULL) {
|
||||
BT_ERR("No free skb");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
|
||||
cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF,
|
||||
BT_CMD_AUTO_SLEEP_MODE));
|
||||
cmd->length = 1;
|
||||
|
||||
if (priv->btmrvl_dev.psmode)
|
||||
cmd->data[0] = BT_PS_ENABLE;
|
||||
else
|
||||
cmd->data[0] = BT_PS_DISABLE;
|
||||
|
||||
bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
|
||||
|
||||
skb->dev = (void *) priv->btmrvl_dev.hcidev;
|
||||
skb_queue_head(&priv->adapter->tx_queue, skb);
|
||||
|
||||
BT_DBG("Queue PSMODE Command:%d", cmd->data[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btmrvl_enable_ps);
|
||||
|
||||
static int btmrvl_enable_hs(struct btmrvl_private *priv)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
@ -258,28 +299,7 @@ int btmrvl_prepare_command(struct btmrvl_private *priv)
|
||||
|
||||
if (priv->btmrvl_dev.pscmd) {
|
||||
priv->btmrvl_dev.pscmd = 0;
|
||||
|
||||
skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
|
||||
if (skb == NULL) {
|
||||
BT_ERR("No free skb");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
|
||||
cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_AUTO_SLEEP_MODE));
|
||||
cmd->length = 1;
|
||||
|
||||
if (priv->btmrvl_dev.psmode)
|
||||
cmd->data[0] = BT_PS_ENABLE;
|
||||
else
|
||||
cmd->data[0] = BT_PS_DISABLE;
|
||||
|
||||
bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
|
||||
|
||||
skb->dev = (void *) priv->btmrvl_dev.hcidev;
|
||||
skb_queue_head(&priv->adapter->tx_queue, skb);
|
||||
|
||||
BT_DBG("Queue PSMODE Command:%d", cmd->data[0]);
|
||||
btmrvl_enable_ps(priv);
|
||||
}
|
||||
|
||||
if (priv->btmrvl_dev.hscmd) {
|
||||
@ -482,14 +502,17 @@ static int btmrvl_service_main_thread(void *data)
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
if (adapter->int_count) {
|
||||
adapter->int_count = 0;
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
priv->hw_process_int_status(priv);
|
||||
} else if (adapter->ps_state == PS_SLEEP &&
|
||||
!skb_queue_empty(&adapter->tx_queue)) {
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
adapter->wakeup_tries++;
|
||||
priv->hw_wakeup_firmware(priv);
|
||||
continue;
|
||||
} else {
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
|
||||
if (adapter->ps_state == PS_SLEEP)
|
||||
continue;
|
||||
@ -511,12 +534,63 @@ static int btmrvl_service_main_thread(void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct btmrvl_private *btmrvl_add_card(void *card)
|
||||
int btmrvl_register_hdev(struct btmrvl_private *priv)
|
||||
{
|
||||
struct hci_dev *hdev = NULL;
|
||||
struct btmrvl_private *priv;
|
||||
int ret;
|
||||
|
||||
hdev = hci_alloc_dev();
|
||||
if (!hdev) {
|
||||
BT_ERR("Can not allocate HCI device");
|
||||
goto err_hdev;
|
||||
}
|
||||
|
||||
priv->btmrvl_dev.hcidev = hdev;
|
||||
hdev->driver_data = priv;
|
||||
|
||||
hdev->bus = HCI_SDIO;
|
||||
hdev->open = btmrvl_open;
|
||||
hdev->close = btmrvl_close;
|
||||
hdev->flush = btmrvl_flush;
|
||||
hdev->send = btmrvl_send_frame;
|
||||
hdev->destruct = btmrvl_destruct;
|
||||
hdev->ioctl = btmrvl_ioctl;
|
||||
hdev->owner = THIS_MODULE;
|
||||
|
||||
btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
|
||||
|
||||
hdev->dev_type = priv->btmrvl_dev.dev_type;
|
||||
|
||||
ret = hci_register_dev(hdev);
|
||||
if (ret < 0) {
|
||||
BT_ERR("Can not register HCI device");
|
||||
goto err_hci_register_dev;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
btmrvl_debugfs_init(hdev);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
err_hci_register_dev:
|
||||
hci_free_dev(hdev);
|
||||
|
||||
err_hdev:
|
||||
/* Stop the thread servicing the interrupts */
|
||||
kthread_stop(priv->main_thread.task);
|
||||
|
||||
btmrvl_free_adapter(priv);
|
||||
kfree(priv);
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btmrvl_register_hdev);
|
||||
|
||||
struct btmrvl_private *btmrvl_add_card(void *card)
|
||||
{
|
||||
struct btmrvl_private *priv;
|
||||
|
||||
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv) {
|
||||
BT_ERR("Can not allocate priv");
|
||||
@ -531,12 +605,6 @@ struct btmrvl_private *btmrvl_add_card(void *card)
|
||||
|
||||
btmrvl_init_adapter(priv);
|
||||
|
||||
hdev = hci_alloc_dev();
|
||||
if (!hdev) {
|
||||
BT_ERR("Can not allocate HCI device");
|
||||
goto err_hdev;
|
||||
}
|
||||
|
||||
BT_DBG("Starting kthread...");
|
||||
priv->main_thread.priv = priv;
|
||||
spin_lock_init(&priv->driver_lock);
|
||||
@ -545,43 +613,11 @@ struct btmrvl_private *btmrvl_add_card(void *card)
|
||||
priv->main_thread.task = kthread_run(btmrvl_service_main_thread,
|
||||
&priv->main_thread, "btmrvl_main_service");
|
||||
|
||||
priv->btmrvl_dev.hcidev = hdev;
|
||||
priv->btmrvl_dev.card = card;
|
||||
|
||||
hdev->driver_data = priv;
|
||||
|
||||
priv->btmrvl_dev.tx_dnld_rdy = true;
|
||||
|
||||
hdev->type = HCI_SDIO;
|
||||
hdev->open = btmrvl_open;
|
||||
hdev->close = btmrvl_close;
|
||||
hdev->flush = btmrvl_flush;
|
||||
hdev->send = btmrvl_send_frame;
|
||||
hdev->destruct = btmrvl_destruct;
|
||||
hdev->ioctl = btmrvl_ioctl;
|
||||
hdev->owner = THIS_MODULE;
|
||||
|
||||
ret = hci_register_dev(hdev);
|
||||
if (ret < 0) {
|
||||
BT_ERR("Can not register HCI device");
|
||||
goto err_hci_register_dev;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
btmrvl_debugfs_init(hdev);
|
||||
#endif
|
||||
|
||||
return priv;
|
||||
|
||||
err_hci_register_dev:
|
||||
/* Stop the thread servicing the interrupts */
|
||||
kthread_stop(priv->main_thread.task);
|
||||
|
||||
hci_free_dev(hdev);
|
||||
|
||||
err_hdev:
|
||||
btmrvl_free_adapter(priv);
|
||||
|
||||
err_adapter:
|
||||
kfree(priv);
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
**/
|
||||
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/mmc/sdio_ids.h>
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
@ -46,6 +47,7 @@
|
||||
* module_exit function is called.
|
||||
*/
|
||||
static u8 user_rmmod;
|
||||
static u8 sdio_ireg;
|
||||
|
||||
static const struct btmrvl_sdio_device btmrvl_sdio_sd6888 = {
|
||||
.helper = "sd8688_helper.bin",
|
||||
@ -82,10 +84,10 @@ static int btmrvl_sdio_read_fw_status(struct btmrvl_sdio_card *card, u16 *dat)
|
||||
*dat = 0;
|
||||
|
||||
fws0 = sdio_readb(card->func, CARD_FW_STATUS0_REG, &ret);
|
||||
if (ret)
|
||||
return -EIO;
|
||||
|
||||
if (!ret)
|
||||
fws1 = sdio_readb(card->func, CARD_FW_STATUS1_REG, &ret);
|
||||
|
||||
fws1 = sdio_readb(card->func, CARD_FW_STATUS1_REG, &ret);
|
||||
if (ret)
|
||||
return -EIO;
|
||||
|
||||
@ -215,7 +217,7 @@ static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card)
|
||||
|
||||
tmphlprbufsz = ALIGN_SZ(BTM_UPLD_SIZE, BTSDIO_DMA_ALIGN);
|
||||
|
||||
tmphlprbuf = kmalloc(tmphlprbufsz, GFP_KERNEL);
|
||||
tmphlprbuf = kzalloc(tmphlprbufsz, GFP_KERNEL);
|
||||
if (!tmphlprbuf) {
|
||||
BT_ERR("Unable to allocate buffer for helper."
|
||||
" Terminating download");
|
||||
@ -223,8 +225,6 @@ static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card)
|
||||
goto done;
|
||||
}
|
||||
|
||||
memset(tmphlprbuf, 0, tmphlprbufsz);
|
||||
|
||||
helperbuf = (u8 *) ALIGN_ADDR(tmphlprbuf, BTSDIO_DMA_ALIGN);
|
||||
|
||||
/* Perform helper data transfer */
|
||||
@ -317,7 +317,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
|
||||
BT_DBG("Downloading FW image (%d bytes)", firmwarelen);
|
||||
|
||||
tmpfwbufsz = ALIGN_SZ(BTM_UPLD_SIZE, BTSDIO_DMA_ALIGN);
|
||||
tmpfwbuf = kmalloc(tmpfwbufsz, GFP_KERNEL);
|
||||
tmpfwbuf = kzalloc(tmpfwbufsz, GFP_KERNEL);
|
||||
if (!tmpfwbuf) {
|
||||
BT_ERR("Unable to allocate buffer for firmware."
|
||||
" Terminating download");
|
||||
@ -325,8 +325,6 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
|
||||
goto done;
|
||||
}
|
||||
|
||||
memset(tmpfwbuf, 0, tmpfwbufsz);
|
||||
|
||||
/* Ensure aligned firmware buffer */
|
||||
fwbuf = (u8 *) ALIGN_ADDR(tmpfwbuf, BTSDIO_DMA_ALIGN);
|
||||
|
||||
@ -535,7 +533,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
|
||||
break;
|
||||
|
||||
default:
|
||||
BT_ERR("Unknow packet type:%d", type);
|
||||
BT_ERR("Unknown packet type:%d", type);
|
||||
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, payload,
|
||||
blksz * buf_block_len);
|
||||
|
||||
@ -554,78 +552,79 @@ exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int btmrvl_sdio_get_int_status(struct btmrvl_private *priv, u8 * ireg)
|
||||
static int btmrvl_sdio_process_int_status(struct btmrvl_private *priv)
|
||||
{
|
||||
int ret;
|
||||
u8 sdio_ireg = 0;
|
||||
ulong flags;
|
||||
u8 ireg;
|
||||
struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
|
||||
|
||||
*ireg = 0;
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
ireg = sdio_ireg;
|
||||
sdio_ireg = 0;
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
|
||||
sdio_ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret);
|
||||
if (ret) {
|
||||
BT_ERR("sdio_readb: read int status register failed");
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (sdio_ireg != 0) {
|
||||
/*
|
||||
* DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
|
||||
* Clear the interrupt status register and re-enable the
|
||||
* interrupt.
|
||||
*/
|
||||
BT_DBG("sdio_ireg = 0x%x", sdio_ireg);
|
||||
|
||||
sdio_writeb(card->func, ~(sdio_ireg) & (DN_LD_HOST_INT_STATUS |
|
||||
UP_LD_HOST_INT_STATUS),
|
||||
HOST_INTSTATUS_REG, &ret);
|
||||
if (ret) {
|
||||
BT_ERR("sdio_writeb: clear int status register "
|
||||
"failed");
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (sdio_ireg & DN_LD_HOST_INT_STATUS) {
|
||||
sdio_claim_host(card->func);
|
||||
if (ireg & DN_LD_HOST_INT_STATUS) {
|
||||
if (priv->btmrvl_dev.tx_dnld_rdy)
|
||||
BT_DBG("tx_done already received: "
|
||||
" int_status=0x%x", sdio_ireg);
|
||||
" int_status=0x%x", ireg);
|
||||
else
|
||||
priv->btmrvl_dev.tx_dnld_rdy = true;
|
||||
}
|
||||
|
||||
if (sdio_ireg & UP_LD_HOST_INT_STATUS)
|
||||
if (ireg & UP_LD_HOST_INT_STATUS)
|
||||
btmrvl_sdio_card_to_host(priv);
|
||||
|
||||
*ireg = sdio_ireg;
|
||||
sdio_release_host(card->func);
|
||||
|
||||
ret = 0;
|
||||
|
||||
done:
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void btmrvl_sdio_interrupt(struct sdio_func *func)
|
||||
{
|
||||
struct btmrvl_private *priv;
|
||||
struct hci_dev *hcidev;
|
||||
struct btmrvl_sdio_card *card;
|
||||
ulong flags;
|
||||
u8 ireg = 0;
|
||||
int ret;
|
||||
|
||||
card = sdio_get_drvdata(func);
|
||||
if (card && card->priv) {
|
||||
priv = card->priv;
|
||||
hcidev = priv->btmrvl_dev.hcidev;
|
||||
|
||||
if (btmrvl_sdio_get_int_status(priv, &ireg))
|
||||
BT_ERR("reading HOST_INT_STATUS_REG failed");
|
||||
else
|
||||
BT_DBG("HOST_INT_STATUS_REG %#x", ireg);
|
||||
|
||||
btmrvl_interrupt(priv);
|
||||
if (!card || !card->priv) {
|
||||
BT_ERR("sbi_interrupt(%p) card or priv is "
|
||||
"NULL, card=%p\n", func, card);
|
||||
return;
|
||||
}
|
||||
|
||||
priv = card->priv;
|
||||
|
||||
ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret);
|
||||
if (ret) {
|
||||
BT_ERR("sdio_readb: read int status register failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ireg != 0) {
|
||||
/*
|
||||
* DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
|
||||
* Clear the interrupt status register and re-enable the
|
||||
* interrupt.
|
||||
*/
|
||||
BT_DBG("ireg = 0x%x", ireg);
|
||||
|
||||
sdio_writeb(card->func, ~(ireg) & (DN_LD_HOST_INT_STATUS |
|
||||
UP_LD_HOST_INT_STATUS),
|
||||
HOST_INTSTATUS_REG, &ret);
|
||||
if (ret) {
|
||||
BT_ERR("sdio_writeb: clear int status register failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
sdio_ireg |= ireg;
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
|
||||
btmrvl_interrupt(priv);
|
||||
}
|
||||
|
||||
static int btmrvl_sdio_register_dev(struct btmrvl_sdio_card *card)
|
||||
@ -808,6 +807,7 @@ static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv,
|
||||
|
||||
exit:
|
||||
sdio_release_host(card->func);
|
||||
kfree(tmpbuf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -928,8 +928,16 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
|
||||
/* Initialize the interface specific function pointers */
|
||||
priv->hw_host_to_card = btmrvl_sdio_host_to_card;
|
||||
priv->hw_wakeup_firmware = btmrvl_sdio_wakeup_fw;
|
||||
priv->hw_process_int_status = btmrvl_sdio_process_int_status;
|
||||
|
||||
btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
|
||||
if (btmrvl_register_hdev(priv)) {
|
||||
BT_ERR("Register hdev failed!");
|
||||
ret = -ENODEV;
|
||||
goto disable_host_int;
|
||||
}
|
||||
|
||||
priv->btmrvl_dev.psmode = 1;
|
||||
btmrvl_enable_ps(priv);
|
||||
|
||||
return 0;
|
||||
|
||||
@ -973,7 +981,7 @@ static struct sdio_driver bt_mrvl_sdio = {
|
||||
.remove = btmrvl_sdio_remove,
|
||||
};
|
||||
|
||||
static int btmrvl_sdio_init_module(void)
|
||||
static int __init btmrvl_sdio_init_module(void)
|
||||
{
|
||||
if (sdio_register_driver(&bt_mrvl_sdio) != 0) {
|
||||
BT_ERR("SDIO Driver Registration Failed");
|
||||
@ -986,7 +994,7 @@ static int btmrvl_sdio_init_module(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void btmrvl_sdio_exit_module(void)
|
||||
static void __exit btmrvl_sdio_exit_module(void)
|
||||
{
|
||||
/* Set the flag as user is removing this module. */
|
||||
user_rmmod = 1;
|
||||
@ -1001,3 +1009,5 @@ MODULE_AUTHOR("Marvell International Ltd.");
|
||||
MODULE_DESCRIPTION("Marvell BT-over-SDIO driver ver " VERSION);
|
||||
MODULE_VERSION(VERSION);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_FIRMWARE("sd8688_helper.bin");
|
||||
MODULE_FIRMWARE("sd8688.bin");
|
||||
|
@ -326,7 +326,7 @@ static int btsdio_probe(struct sdio_func *func,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
hdev->type = HCI_SDIO;
|
||||
hdev->bus = HCI_SDIO;
|
||||
hdev->driver_data = data;
|
||||
|
||||
data->hdev = hdev;
|
||||
|
@ -41,7 +41,6 @@
|
||||
#include <asm/system.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <pcmcia/cs_types.h>
|
||||
#include <pcmcia/cs.h>
|
||||
#include <pcmcia/cistpl.h>
|
||||
#include <pcmcia/ciscode.h>
|
||||
@ -67,7 +66,6 @@ MODULE_LICENSE("GPL");
|
||||
|
||||
typedef struct btuart_info_t {
|
||||
struct pcmcia_device *p_dev;
|
||||
dev_node_t node;
|
||||
|
||||
struct hci_dev *hdev;
|
||||
|
||||
@ -144,7 +142,7 @@ static void btuart_write_wakeup(btuart_info_t *info)
|
||||
}
|
||||
|
||||
do {
|
||||
register unsigned int iobase = info->p_dev->io.BasePort1;
|
||||
register unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
register struct sk_buff *skb;
|
||||
register int len;
|
||||
|
||||
@ -185,7 +183,7 @@ static void btuart_receive(btuart_info_t *info)
|
||||
return;
|
||||
}
|
||||
|
||||
iobase = info->p_dev->io.BasePort1;
|
||||
iobase = info->p_dev->resource[0]->start;
|
||||
|
||||
do {
|
||||
info->hdev->stat.byte_rx++;
|
||||
@ -295,9 +293,11 @@ static irqreturn_t btuart_interrupt(int irq, void *dev_inst)
|
||||
int iir, lsr;
|
||||
irqreturn_t r = IRQ_NONE;
|
||||
|
||||
BUG_ON(!info->hdev);
|
||||
if (!info || !info->hdev)
|
||||
/* our irq handler is shared */
|
||||
return IRQ_NONE;
|
||||
|
||||
iobase = info->p_dev->io.BasePort1;
|
||||
iobase = info->p_dev->resource[0]->start;
|
||||
|
||||
spin_lock(&(info->lock));
|
||||
|
||||
@ -354,7 +354,7 @@ static void btuart_change_speed(btuart_info_t *info, unsigned int speed)
|
||||
return;
|
||||
}
|
||||
|
||||
iobase = info->p_dev->io.BasePort1;
|
||||
iobase = info->p_dev->resource[0]->start;
|
||||
|
||||
spin_lock_irqsave(&(info->lock), flags);
|
||||
|
||||
@ -478,7 +478,7 @@ static int btuart_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned lon
|
||||
static int btuart_open(btuart_info_t *info)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int iobase = info->p_dev->io.BasePort1;
|
||||
unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
struct hci_dev *hdev;
|
||||
|
||||
spin_lock_init(&(info->lock));
|
||||
@ -498,7 +498,7 @@ static int btuart_open(btuart_info_t *info)
|
||||
|
||||
info->hdev = hdev;
|
||||
|
||||
hdev->type = HCI_PCCARD;
|
||||
hdev->bus = HCI_PCCARD;
|
||||
hdev->driver_data = info;
|
||||
SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
|
||||
|
||||
@ -548,7 +548,7 @@ static int btuart_open(btuart_info_t *info)
|
||||
static int btuart_close(btuart_info_t *info)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int iobase = info->p_dev->io.BasePort1;
|
||||
unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
struct hci_dev *hdev = info->hdev;
|
||||
|
||||
if (!hdev)
|
||||
@ -586,13 +586,8 @@ static int btuart_probe(struct pcmcia_device *link)
|
||||
info->p_dev = link;
|
||||
link->priv = info;
|
||||
|
||||
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
|
||||
link->io.NumPorts1 = 8;
|
||||
link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
|
||||
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
|
||||
|
||||
link->irq.Handler = btuart_interrupt;
|
||||
link->irq.Instance = info;
|
||||
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
|
||||
link->resource[0]->end = 8;
|
||||
|
||||
link->conf.Attributes = CONF_ENABLE_IRQ;
|
||||
link->conf.IntType = INT_MEMORY_AND_IO;
|
||||
@ -617,14 +612,14 @@ static int btuart_check_config(struct pcmcia_device *p_dev,
|
||||
{
|
||||
int *try = priv_data;
|
||||
|
||||
p_dev->io_lines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
|
||||
|
||||
if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
|
||||
p_dev->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
|
||||
if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
|
||||
(cf->io.win[0].base != 0)) {
|
||||
p_dev->io.BasePort1 = cf->io.win[0].base;
|
||||
p_dev->io.IOAddrLines = (*try == 0) ? 16 :
|
||||
cf->io.flags & CISTPL_IO_LINES_MASK;
|
||||
if (!pcmcia_request_io(p_dev, &p_dev->io))
|
||||
p_dev->resource[0]->start = cf->io.win[0].base;
|
||||
if (!pcmcia_request_io(p_dev))
|
||||
return 0;
|
||||
}
|
||||
return -ENODEV;
|
||||
@ -641,9 +636,9 @@ static int btuart_check_config_notpicky(struct pcmcia_device *p_dev,
|
||||
|
||||
if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
|
||||
for (j = 0; j < 5; j++) {
|
||||
p_dev->io.BasePort1 = base[j];
|
||||
p_dev->io.IOAddrLines = base[j] ? 16 : 3;
|
||||
if (!pcmcia_request_io(p_dev, &p_dev->io))
|
||||
p_dev->resource[0]->start = base[j];
|
||||
p_dev->io_lines = base[j] ? 16 : 3;
|
||||
if (!pcmcia_request_io(p_dev))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -669,28 +664,20 @@ static int btuart_config(struct pcmcia_device *link)
|
||||
goto found_port;
|
||||
|
||||
BT_ERR("No usable port range found");
|
||||
cs_error(link, RequestIO, -ENODEV);
|
||||
goto failed;
|
||||
|
||||
found_port:
|
||||
i = pcmcia_request_irq(link, &link->irq);
|
||||
if (i != 0) {
|
||||
cs_error(link, RequestIRQ, i);
|
||||
link->irq.AssignedIRQ = 0;
|
||||
}
|
||||
i = pcmcia_request_irq(link, btuart_interrupt);
|
||||
if (i != 0)
|
||||
goto failed;
|
||||
|
||||
i = pcmcia_request_configuration(link, &link->conf);
|
||||
if (i != 0) {
|
||||
cs_error(link, RequestConfiguration, i);
|
||||
if (i != 0)
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (btuart_open(info) != 0)
|
||||
goto failed;
|
||||
|
||||
strcpy(info->node.dev_name, info->hdev->name);
|
||||
link->dev_node = &info->node;
|
||||
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
|
@ -59,6 +59,9 @@ static struct usb_device_id btusb_table[] = {
|
||||
/* Generic Bluetooth USB device */
|
||||
{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
|
||||
|
||||
/* Apple iMac11,1 */
|
||||
{ USB_DEVICE(0x05ac, 0x8215) },
|
||||
|
||||
/* AVM BlueFRITZ! USB v2.0 */
|
||||
{ USB_DEVICE(0x057c, 0x3800) },
|
||||
|
||||
@ -146,6 +149,7 @@ static struct usb_device_id blacklist_table[] = {
|
||||
#define BTUSB_BULK_RUNNING 1
|
||||
#define BTUSB_ISOC_RUNNING 2
|
||||
#define BTUSB_SUSPENDING 3
|
||||
#define BTUSB_DID_ISO_RESUME 4
|
||||
|
||||
struct btusb_data {
|
||||
struct hci_dev *hdev;
|
||||
@ -179,7 +183,6 @@ struct btusb_data {
|
||||
unsigned int sco_num;
|
||||
int isoc_altsetting;
|
||||
int suspend_count;
|
||||
int did_iso_resume:1;
|
||||
};
|
||||
|
||||
static int inc_tx(struct btusb_data *data)
|
||||
@ -807,7 +810,7 @@ static void btusb_work(struct work_struct *work)
|
||||
int err;
|
||||
|
||||
if (hdev->conn_hash.sco_num > 0) {
|
||||
if (!data->did_iso_resume) {
|
||||
if (!test_bit(BTUSB_DID_ISO_RESUME, &data->flags)) {
|
||||
err = usb_autopm_get_interface(data->isoc);
|
||||
if (err < 0) {
|
||||
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
|
||||
@ -815,7 +818,7 @@ static void btusb_work(struct work_struct *work)
|
||||
return;
|
||||
}
|
||||
|
||||
data->did_iso_resume = 1;
|
||||
set_bit(BTUSB_DID_ISO_RESUME, &data->flags);
|
||||
}
|
||||
if (data->isoc_altsetting != 2) {
|
||||
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
|
||||
@ -836,10 +839,8 @@ static void btusb_work(struct work_struct *work)
|
||||
usb_kill_anchored_urbs(&data->isoc_anchor);
|
||||
|
||||
__set_isoc_interface(hdev, 0);
|
||||
if (data->did_iso_resume) {
|
||||
data->did_iso_resume = 0;
|
||||
if (test_and_clear_bit(BTUSB_DID_ISO_RESUME, &data->flags))
|
||||
usb_autopm_put_interface(data->isoc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -939,7 +940,7 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
hdev->type = HCI_USB;
|
||||
hdev->bus = HCI_USB;
|
||||
hdev->driver_data = data;
|
||||
|
||||
data->hdev = hdev;
|
||||
@ -1067,7 +1068,7 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
|
||||
return 0;
|
||||
|
||||
spin_lock_irq(&data->txlock);
|
||||
if (!(interface_to_usbdev(intf)->auto_pm && data->tx_in_flight)) {
|
||||
if (!((message.event & PM_EVENT_AUTO) && data->tx_in_flight)) {
|
||||
set_bit(BTUSB_SUSPENDING, &data->flags);
|
||||
spin_unlock_irq(&data->txlock);
|
||||
} else {
|
||||
|
@ -41,7 +41,6 @@
|
||||
#include <asm/system.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <pcmcia/cs_types.h>
|
||||
#include <pcmcia/cs.h>
|
||||
#include <pcmcia/cistpl.h>
|
||||
#include <pcmcia/ciscode.h>
|
||||
@ -67,7 +66,6 @@ MODULE_LICENSE("GPL");
|
||||
|
||||
typedef struct dtl1_info_t {
|
||||
struct pcmcia_device *p_dev;
|
||||
dev_node_t node;
|
||||
|
||||
struct hci_dev *hdev;
|
||||
|
||||
@ -105,7 +103,7 @@ typedef struct {
|
||||
u8 type;
|
||||
u8 zero;
|
||||
u16 len;
|
||||
} __attribute__ ((packed)) nsh_t; /* Nokia Specific Header */
|
||||
} __packed nsh_t; /* Nokia Specific Header */
|
||||
|
||||
#define NSHL 4 /* Nokia Specific Header Length */
|
||||
|
||||
@ -151,7 +149,7 @@ static void dtl1_write_wakeup(dtl1_info_t *info)
|
||||
}
|
||||
|
||||
do {
|
||||
register unsigned int iobase = info->p_dev->io.BasePort1;
|
||||
register unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
register struct sk_buff *skb;
|
||||
register int len;
|
||||
|
||||
@ -216,7 +214,7 @@ static void dtl1_receive(dtl1_info_t *info)
|
||||
return;
|
||||
}
|
||||
|
||||
iobase = info->p_dev->io.BasePort1;
|
||||
iobase = info->p_dev->resource[0]->start;
|
||||
|
||||
do {
|
||||
info->hdev->stat.byte_rx++;
|
||||
@ -299,9 +297,11 @@ static irqreturn_t dtl1_interrupt(int irq, void *dev_inst)
|
||||
int iir, lsr;
|
||||
irqreturn_t r = IRQ_NONE;
|
||||
|
||||
BUG_ON(!info->hdev);
|
||||
if (!info || !info->hdev)
|
||||
/* our irq handler is shared */
|
||||
return IRQ_NONE;
|
||||
|
||||
iobase = info->p_dev->io.BasePort1;
|
||||
iobase = info->p_dev->resource[0]->start;
|
||||
|
||||
spin_lock(&(info->lock));
|
||||
|
||||
@ -461,7 +461,7 @@ static int dtl1_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long
|
||||
static int dtl1_open(dtl1_info_t *info)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int iobase = info->p_dev->io.BasePort1;
|
||||
unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
struct hci_dev *hdev;
|
||||
|
||||
spin_lock_init(&(info->lock));
|
||||
@ -483,7 +483,7 @@ static int dtl1_open(dtl1_info_t *info)
|
||||
|
||||
info->hdev = hdev;
|
||||
|
||||
hdev->type = HCI_PCCARD;
|
||||
hdev->bus = HCI_PCCARD;
|
||||
hdev->driver_data = info;
|
||||
SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
|
||||
|
||||
@ -508,7 +508,8 @@ static int dtl1_open(dtl1_info_t *info)
|
||||
outb(UART_LCR_WLEN8, iobase + UART_LCR); /* Reset DLAB */
|
||||
outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase + UART_MCR);
|
||||
|
||||
info->ri_latch = inb(info->p_dev->io.BasePort1 + UART_MSR) & UART_MSR_RI;
|
||||
info->ri_latch = inb(info->p_dev->resource[0]->start + UART_MSR)
|
||||
& UART_MSR_RI;
|
||||
|
||||
/* Turn on interrupts */
|
||||
outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER);
|
||||
@ -533,7 +534,7 @@ static int dtl1_open(dtl1_info_t *info)
|
||||
static int dtl1_close(dtl1_info_t *info)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int iobase = info->p_dev->io.BasePort1;
|
||||
unsigned int iobase = info->p_dev->resource[0]->start;
|
||||
struct hci_dev *hdev = info->hdev;
|
||||
|
||||
if (!hdev)
|
||||
@ -571,13 +572,8 @@ static int dtl1_probe(struct pcmcia_device *link)
|
||||
info->p_dev = link;
|
||||
link->priv = info;
|
||||
|
||||
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
|
||||
link->io.NumPorts1 = 8;
|
||||
link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
|
||||
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
|
||||
|
||||
link->irq.Handler = dtl1_interrupt;
|
||||
link->irq.Instance = info;
|
||||
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
|
||||
link->resource[0]->end = 8;
|
||||
|
||||
link->conf.Attributes = CONF_ENABLE_IRQ;
|
||||
link->conf.IntType = INT_MEMORY_AND_IO;
|
||||
@ -601,14 +597,13 @@ static int dtl1_confcheck(struct pcmcia_device *p_dev,
|
||||
unsigned int vcc,
|
||||
void *priv_data)
|
||||
{
|
||||
if ((cf->io.nwin == 1) && (cf->io.win[0].len > 8)) {
|
||||
p_dev->io.BasePort1 = cf->io.win[0].base;
|
||||
p_dev->io.NumPorts1 = cf->io.win[0].len; /*yo */
|
||||
p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
|
||||
if (!pcmcia_request_io(p_dev, &p_dev->io))
|
||||
return 0;
|
||||
}
|
||||
return -ENODEV;
|
||||
if ((cf->io.nwin != 1) || (cf->io.win[0].len <= 8))
|
||||
return -ENODEV;
|
||||
|
||||
p_dev->resource[0]->start = cf->io.win[0].base;
|
||||
p_dev->resource[0]->end = cf->io.win[0].len; /*yo */
|
||||
p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK;
|
||||
return pcmcia_request_io(p_dev);
|
||||
}
|
||||
|
||||
static int dtl1_config(struct pcmcia_device *link)
|
||||
@ -617,28 +612,21 @@ static int dtl1_config(struct pcmcia_device *link)
|
||||
int i;
|
||||
|
||||
/* Look for a generic full-sized window */
|
||||
link->io.NumPorts1 = 8;
|
||||
link->resource[0]->end = 8;
|
||||
if (pcmcia_loop_config(link, dtl1_confcheck, NULL) < 0)
|
||||
goto failed;
|
||||
|
||||
i = pcmcia_request_irq(link, &link->irq);
|
||||
if (i != 0) {
|
||||
cs_error(link, RequestIRQ, i);
|
||||
link->irq.AssignedIRQ = 0;
|
||||
}
|
||||
i = pcmcia_request_irq(link, dtl1_interrupt);
|
||||
if (i != 0)
|
||||
goto failed;
|
||||
|
||||
i = pcmcia_request_configuration(link, &link->conf);
|
||||
if (i != 0) {
|
||||
cs_error(link, RequestConfiguration, i);
|
||||
if (i != 0)
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (dtl1_open(info) != 0)
|
||||
goto failed;
|
||||
|
||||
strcpy(info->node.dev_name, info->hdev->name);
|
||||
link->dev_node = &info->node;
|
||||
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
|
@ -244,7 +244,7 @@ static struct sk_buff *bcsp_prepare_pkt(struct bcsp_struct *bcsp, u8 *data,
|
||||
if (rel) {
|
||||
hdr[0] |= 0x80 + bcsp->msgq_txseq;
|
||||
BT_DBG("Sending packet with seqno %u", bcsp->msgq_txseq);
|
||||
bcsp->msgq_txseq = ++(bcsp->msgq_txseq) & 0x07;
|
||||
bcsp->msgq_txseq = (bcsp->msgq_txseq + 1) & 0x07;
|
||||
}
|
||||
|
||||
if (bcsp->use_crc)
|
||||
@ -739,7 +739,7 @@ static struct hci_uart_proto bcsp = {
|
||||
.flush = bcsp_flush
|
||||
};
|
||||
|
||||
int bcsp_init(void)
|
||||
int __init bcsp_init(void)
|
||||
{
|
||||
int err = hci_uart_register_proto(&bcsp);
|
||||
|
||||
@ -751,7 +751,7 @@ int bcsp_init(void)
|
||||
return err;
|
||||
}
|
||||
|
||||
int bcsp_deinit(void)
|
||||
int __exit bcsp_deinit(void)
|
||||
{
|
||||
return hci_uart_unregister_proto(&bcsp);
|
||||
}
|
||||
|
@ -210,11 +210,10 @@ static int hci_uart_close(struct hci_dev *hdev)
|
||||
static int hci_uart_send_frame(struct sk_buff *skb)
|
||||
{
|
||||
struct hci_dev* hdev = (struct hci_dev *) skb->dev;
|
||||
struct tty_struct *tty;
|
||||
struct hci_uart *hu;
|
||||
|
||||
if (!hdev) {
|
||||
BT_ERR("Frame for uknown device (hdev=NULL)");
|
||||
BT_ERR("Frame for unknown device (hdev=NULL)");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@ -222,7 +221,6 @@ static int hci_uart_send_frame(struct sk_buff *skb)
|
||||
return -EBUSY;
|
||||
|
||||
hu = (struct hci_uart *) hdev->driver_data;
|
||||
tty = hu->tty;
|
||||
|
||||
BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len);
|
||||
|
||||
@ -383,7 +381,7 @@ static int hci_uart_register_dev(struct hci_uart *hu)
|
||||
|
||||
hu->hdev = hdev;
|
||||
|
||||
hdev->type = HCI_UART;
|
||||
hdev->bus = HCI_UART;
|
||||
hdev->driver_data = hu;
|
||||
|
||||
hdev->open = hci_uart_open;
|
||||
@ -397,6 +395,9 @@ static int hci_uart_register_dev(struct hci_uart *hu)
|
||||
if (!reset)
|
||||
set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
|
||||
|
||||
if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags))
|
||||
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
|
||||
|
||||
if (hci_register_dev(hdev) < 0) {
|
||||
BT_ERR("Can't register HCI device");
|
||||
hci_free_dev(hdev);
|
||||
@ -477,6 +478,15 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
|
||||
return hu->hdev->id;
|
||||
return -EUNATCH;
|
||||
|
||||
case HCIUARTSETFLAGS:
|
||||
if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
|
||||
return -EBUSY;
|
||||
hu->hdev_flags = arg;
|
||||
break;
|
||||
|
||||
case HCIUARTGETFLAGS:
|
||||
return hu->hdev_flags;
|
||||
|
||||
default:
|
||||
err = n_tty_ioctl_helper(tty, file, cmd, arg);
|
||||
break;
|
||||
@ -542,6 +552,9 @@ static int __init hci_uart_init(void)
|
||||
#ifdef CONFIG_BT_HCIUART_LL
|
||||
ll_init();
|
||||
#endif
|
||||
#ifdef CONFIG_BT_HCIUART_ATH3K
|
||||
ath_init();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -559,6 +572,9 @@ static void __exit hci_uart_exit(void)
|
||||
#ifdef CONFIG_BT_HCIUART_LL
|
||||
ll_deinit();
|
||||
#endif
|
||||
#ifdef CONFIG_BT_HCIUART_ATH3K
|
||||
ath_deinit();
|
||||
#endif
|
||||
|
||||
/* Release tty registration of line discipline */
|
||||
if ((err = tty_unregister_ldisc(N_HCI)))
|
||||
|
@ -31,15 +31,20 @@
|
||||
#define HCIUARTSETPROTO _IOW('U', 200, int)
|
||||
#define HCIUARTGETPROTO _IOR('U', 201, int)
|
||||
#define HCIUARTGETDEVICE _IOR('U', 202, int)
|
||||
#define HCIUARTSETFLAGS _IOW('U', 203, int)
|
||||
#define HCIUARTGETFLAGS _IOR('U', 204, int)
|
||||
|
||||
/* UART protocols */
|
||||
#define HCI_UART_MAX_PROTO 5
|
||||
#define HCI_UART_MAX_PROTO 6
|
||||
|
||||
#define HCI_UART_H4 0
|
||||
#define HCI_UART_BCSP 1
|
||||
#define HCI_UART_3WIRE 2
|
||||
#define HCI_UART_H4DS 3
|
||||
#define HCI_UART_LL 4
|
||||
#define HCI_UART_ATH3K 5
|
||||
|
||||
#define HCI_UART_RAW_DEVICE 0
|
||||
|
||||
struct hci_uart;
|
||||
|
||||
@ -57,6 +62,7 @@ struct hci_uart {
|
||||
struct tty_struct *tty;
|
||||
struct hci_dev *hdev;
|
||||
unsigned long flags;
|
||||
unsigned long hdev_flags;
|
||||
|
||||
struct hci_uart_proto *proto;
|
||||
void *priv;
|
||||
@ -66,7 +72,7 @@ struct hci_uart {
|
||||
spinlock_t rx_lock;
|
||||
};
|
||||
|
||||
/* HCI_UART flag bits */
|
||||
/* HCI_UART proto flag bits */
|
||||
#define HCI_UART_PROTO_SET 0
|
||||
|
||||
/* TX states */
|
||||
@ -91,3 +97,8 @@ int bcsp_deinit(void);
|
||||
int ll_init(void);
|
||||
int ll_deinit(void);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_HCIUART_ATH3K
|
||||
int ath_init(void);
|
||||
int ath_deinit(void);
|
||||
#endif
|
||||
|
@ -41,8 +41,6 @@
|
||||
|
||||
#define VERSION "1.3"
|
||||
|
||||
static int minor = MISC_DYNAMIC_MINOR;
|
||||
|
||||
struct vhci_data {
|
||||
struct hci_dev *hdev;
|
||||
|
||||
@ -159,7 +157,7 @@ static inline ssize_t vhci_put_user(struct vhci_data *data,
|
||||
break;
|
||||
|
||||
case HCI_SCODATA_PKT:
|
||||
data->hdev->stat.cmd_tx++;
|
||||
data->hdev->stat.sco_tx++;
|
||||
break;
|
||||
};
|
||||
|
||||
@ -218,12 +216,6 @@ static unsigned int vhci_poll(struct file *file, poll_table *wait)
|
||||
return POLLOUT | POLLWRNORM;
|
||||
}
|
||||
|
||||
static int vhci_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int vhci_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct vhci_data *data;
|
||||
@ -244,7 +236,7 @@ static int vhci_open(struct inode *inode, struct file *file)
|
||||
|
||||
data->hdev = hdev;
|
||||
|
||||
hdev->type = HCI_VIRTUAL;
|
||||
hdev->bus = HCI_VIRTUAL;
|
||||
hdev->driver_data = data;
|
||||
|
||||
hdev->open = vhci_open_dev;
|
||||
@ -284,10 +276,10 @@ static int vhci_release(struct inode *inode, struct file *file)
|
||||
}
|
||||
|
||||
static const struct file_operations vhci_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = vhci_read,
|
||||
.write = vhci_write,
|
||||
.poll = vhci_poll,
|
||||
.ioctl = vhci_ioctl,
|
||||
.open = vhci_open,
|
||||
.release = vhci_release,
|
||||
};
|
||||
@ -302,18 +294,12 @@ static int __init vhci_init(void)
|
||||
{
|
||||
BT_INFO("Virtual HCI driver ver %s", VERSION);
|
||||
|
||||
if (misc_register(&vhci_miscdev) < 0) {
|
||||
BT_ERR("Can't register misc device with minor %d", minor);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return misc_register(&vhci_miscdev);
|
||||
}
|
||||
|
||||
static void __exit vhci_exit(void)
|
||||
{
|
||||
if (misc_deregister(&vhci_miscdev) < 0)
|
||||
BT_ERR("Can't unregister misc device with minor %d", minor);
|
||||
misc_deregister(&vhci_miscdev);
|
||||
}
|
||||
|
||||
module_init(vhci_init);
|
||||
|
@ -43,7 +43,7 @@
|
||||
#define HCI_NOTIFY_CONN_DEL 2
|
||||
#define HCI_NOTIFY_VOICE_SETTING 3
|
||||
|
||||
/* HCI device types */
|
||||
/* HCI bus types */
|
||||
#define HCI_VIRTUAL 0
|
||||
#define HCI_USB 1
|
||||
#define HCI_PCCARD 2
|
||||
@ -52,6 +52,10 @@
|
||||
#define HCI_PCI 5
|
||||
#define HCI_SDIO 6
|
||||
|
||||
/* HCI controller types */
|
||||
#define HCI_BREDR 0x00
|
||||
#define HCI_80211 0x01
|
||||
|
||||
/* HCI device quirks */
|
||||
enum {
|
||||
HCI_QUIRK_NO_RESET,
|
||||
@ -96,6 +100,9 @@ enum {
|
||||
#define HCISETACLMTU _IOW('H', 227, int)
|
||||
#define HCISETSCOMTU _IOW('H', 228, int)
|
||||
|
||||
#define HCIBLOCKADDR _IOW('H', 230, int)
|
||||
#define HCIUNBLOCKADDR _IOW('H', 231, int)
|
||||
|
||||
#define HCIINQUIRY _IOR('H', 240, int)
|
||||
|
||||
/* HCI timeouts */
|
||||
@ -229,7 +236,7 @@ struct hci_cp_inquiry {
|
||||
__u8 lap[3];
|
||||
__u8 length;
|
||||
__u8 num_rsp;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_INQUIRY_CANCEL 0x0402
|
||||
|
||||
@ -243,81 +250,81 @@ struct hci_cp_create_conn {
|
||||
__u8 pscan_mode;
|
||||
__le16 clock_offset;
|
||||
__u8 role_switch;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_DISCONNECT 0x0406
|
||||
struct hci_cp_disconnect {
|
||||
__le16 handle;
|
||||
__u8 reason;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_ADD_SCO 0x0407
|
||||
struct hci_cp_add_sco {
|
||||
__le16 handle;
|
||||
__le16 pkt_type;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_CREATE_CONN_CANCEL 0x0408
|
||||
struct hci_cp_create_conn_cancel {
|
||||
bdaddr_t bdaddr;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_ACCEPT_CONN_REQ 0x0409
|
||||
struct hci_cp_accept_conn_req {
|
||||
bdaddr_t bdaddr;
|
||||
__u8 role;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_REJECT_CONN_REQ 0x040a
|
||||
struct hci_cp_reject_conn_req {
|
||||
bdaddr_t bdaddr;
|
||||
__u8 reason;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_LINK_KEY_REPLY 0x040b
|
||||
struct hci_cp_link_key_reply {
|
||||
bdaddr_t bdaddr;
|
||||
__u8 link_key[16];
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_LINK_KEY_NEG_REPLY 0x040c
|
||||
struct hci_cp_link_key_neg_reply {
|
||||
bdaddr_t bdaddr;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_PIN_CODE_REPLY 0x040d
|
||||
struct hci_cp_pin_code_reply {
|
||||
bdaddr_t bdaddr;
|
||||
__u8 pin_len;
|
||||
__u8 pin_code[16];
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_PIN_CODE_NEG_REPLY 0x040e
|
||||
struct hci_cp_pin_code_neg_reply {
|
||||
bdaddr_t bdaddr;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_CHANGE_CONN_PTYPE 0x040f
|
||||
struct hci_cp_change_conn_ptype {
|
||||
__le16 handle;
|
||||
__le16 pkt_type;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_AUTH_REQUESTED 0x0411
|
||||
struct hci_cp_auth_requested {
|
||||
__le16 handle;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_SET_CONN_ENCRYPT 0x0413
|
||||
struct hci_cp_set_conn_encrypt {
|
||||
__le16 handle;
|
||||
__u8 encrypt;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_CHANGE_CONN_LINK_KEY 0x0415
|
||||
struct hci_cp_change_conn_link_key {
|
||||
__le16 handle;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_REMOTE_NAME_REQ 0x0419
|
||||
struct hci_cp_remote_name_req {
|
||||
@ -325,28 +332,28 @@ struct hci_cp_remote_name_req {
|
||||
__u8 pscan_rep_mode;
|
||||
__u8 pscan_mode;
|
||||
__le16 clock_offset;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_REMOTE_NAME_REQ_CANCEL 0x041a
|
||||
struct hci_cp_remote_name_req_cancel {
|
||||
bdaddr_t bdaddr;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_READ_REMOTE_FEATURES 0x041b
|
||||
struct hci_cp_read_remote_features {
|
||||
__le16 handle;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_READ_REMOTE_EXT_FEATURES 0x041c
|
||||
struct hci_cp_read_remote_ext_features {
|
||||
__le16 handle;
|
||||
__u8 page;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_READ_REMOTE_VERSION 0x041d
|
||||
struct hci_cp_read_remote_version {
|
||||
__le16 handle;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_SETUP_SYNC_CONN 0x0428
|
||||
struct hci_cp_setup_sync_conn {
|
||||
@ -357,7 +364,7 @@ struct hci_cp_setup_sync_conn {
|
||||
__le16 voice_setting;
|
||||
__u8 retrans_effort;
|
||||
__le16 pkt_type;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_ACCEPT_SYNC_CONN_REQ 0x0429
|
||||
struct hci_cp_accept_sync_conn_req {
|
||||
@ -368,13 +375,13 @@ struct hci_cp_accept_sync_conn_req {
|
||||
__le16 content_format;
|
||||
__u8 retrans_effort;
|
||||
__le16 pkt_type;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_REJECT_SYNC_CONN_REQ 0x042a
|
||||
struct hci_cp_reject_sync_conn_req {
|
||||
bdaddr_t bdaddr;
|
||||
__u8 reason;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_SNIFF_MODE 0x0803
|
||||
struct hci_cp_sniff_mode {
|
||||
@ -383,59 +390,59 @@ struct hci_cp_sniff_mode {
|
||||
__le16 min_interval;
|
||||
__le16 attempt;
|
||||
__le16 timeout;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_EXIT_SNIFF_MODE 0x0804
|
||||
struct hci_cp_exit_sniff_mode {
|
||||
__le16 handle;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_ROLE_DISCOVERY 0x0809
|
||||
struct hci_cp_role_discovery {
|
||||
__le16 handle;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
struct hci_rp_role_discovery {
|
||||
__u8 status;
|
||||
__le16 handle;
|
||||
__u8 role;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_SWITCH_ROLE 0x080b
|
||||
struct hci_cp_switch_role {
|
||||
bdaddr_t bdaddr;
|
||||
__u8 role;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_READ_LINK_POLICY 0x080c
|
||||
struct hci_cp_read_link_policy {
|
||||
__le16 handle;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
struct hci_rp_read_link_policy {
|
||||
__u8 status;
|
||||
__le16 handle;
|
||||
__le16 policy;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_WRITE_LINK_POLICY 0x080d
|
||||
struct hci_cp_write_link_policy {
|
||||
__le16 handle;
|
||||
__le16 policy;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
struct hci_rp_write_link_policy {
|
||||
__u8 status;
|
||||
__le16 handle;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_READ_DEF_LINK_POLICY 0x080e
|
||||
struct hci_rp_read_def_link_policy {
|
||||
__u8 status;
|
||||
__le16 policy;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_WRITE_DEF_LINK_POLICY 0x080f
|
||||
struct hci_cp_write_def_link_policy {
|
||||
__le16 policy;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_SNIFF_SUBRATE 0x0811
|
||||
struct hci_cp_sniff_subrate {
|
||||
@ -443,12 +450,12 @@ struct hci_cp_sniff_subrate {
|
||||
__le16 max_latency;
|
||||
__le16 min_remote_timeout;
|
||||
__le16 min_local_timeout;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_SET_EVENT_MASK 0x0c01
|
||||
struct hci_cp_set_event_mask {
|
||||
__u8 mask[8];
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_RESET 0x0c03
|
||||
|
||||
@ -457,7 +464,7 @@ struct hci_cp_set_event_flt {
|
||||
__u8 flt_type;
|
||||
__u8 cond_type;
|
||||
__u8 condition[0];
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
/* Filter types */
|
||||
#define HCI_FLT_CLEAR_ALL 0x00
|
||||
@ -476,13 +483,13 @@ struct hci_cp_set_event_flt {
|
||||
#define HCI_OP_WRITE_LOCAL_NAME 0x0c13
|
||||
struct hci_cp_write_local_name {
|
||||
__u8 name[248];
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_READ_LOCAL_NAME 0x0c14
|
||||
struct hci_rp_read_local_name {
|
||||
__u8 status;
|
||||
__u8 name[248];
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_WRITE_CA_TIMEOUT 0x0c16
|
||||
|
||||
@ -510,23 +517,23 @@ struct hci_rp_read_local_name {
|
||||
struct hci_rp_read_class_of_dev {
|
||||
__u8 status;
|
||||
__u8 dev_class[3];
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_WRITE_CLASS_OF_DEV 0x0c24
|
||||
struct hci_cp_write_class_of_dev {
|
||||
__u8 dev_class[3];
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_READ_VOICE_SETTING 0x0c25
|
||||
struct hci_rp_read_voice_setting {
|
||||
__u8 status;
|
||||
__le16 voice_setting;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_WRITE_VOICE_SETTING 0x0c26
|
||||
struct hci_cp_write_voice_setting {
|
||||
__le16 voice_setting;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_HOST_BUFFER_SIZE 0x0c33
|
||||
struct hci_cp_host_buffer_size {
|
||||
@ -534,18 +541,18 @@ struct hci_cp_host_buffer_size {
|
||||
__u8 sco_mtu;
|
||||
__le16 acl_max_pkt;
|
||||
__le16 sco_max_pkt;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_READ_SSP_MODE 0x0c55
|
||||
struct hci_rp_read_ssp_mode {
|
||||
__u8 status;
|
||||
__u8 mode;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_WRITE_SSP_MODE 0x0c56
|
||||
struct hci_cp_write_ssp_mode {
|
||||
__u8 mode;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_READ_LOCAL_VERSION 0x1001
|
||||
struct hci_rp_read_local_version {
|
||||
@ -555,19 +562,19 @@ struct hci_rp_read_local_version {
|
||||
__u8 lmp_ver;
|
||||
__le16 manufacturer;
|
||||
__le16 lmp_subver;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_READ_LOCAL_COMMANDS 0x1002
|
||||
struct hci_rp_read_local_commands {
|
||||
__u8 status;
|
||||
__u8 commands[64];
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_READ_LOCAL_FEATURES 0x1003
|
||||
struct hci_rp_read_local_features {
|
||||
__u8 status;
|
||||
__u8 features[8];
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_READ_LOCAL_EXT_FEATURES 0x1004
|
||||
struct hci_rp_read_local_ext_features {
|
||||
@ -575,7 +582,7 @@ struct hci_rp_read_local_ext_features {
|
||||
__u8 page;
|
||||
__u8 max_page;
|
||||
__u8 features[8];
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_READ_BUFFER_SIZE 0x1005
|
||||
struct hci_rp_read_buffer_size {
|
||||
@ -584,13 +591,13 @@ struct hci_rp_read_buffer_size {
|
||||
__u8 sco_mtu;
|
||||
__le16 acl_max_pkt;
|
||||
__le16 sco_max_pkt;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_READ_BD_ADDR 0x1009
|
||||
struct hci_rp_read_bd_addr {
|
||||
__u8 status;
|
||||
bdaddr_t bdaddr;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
/* ---- HCI Events ---- */
|
||||
#define HCI_EV_INQUIRY_COMPLETE 0x01
|
||||
@ -603,7 +610,7 @@ struct inquiry_info {
|
||||
__u8 pscan_mode;
|
||||
__u8 dev_class[3];
|
||||
__le16 clock_offset;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_CONN_COMPLETE 0x03
|
||||
struct hci_ev_conn_complete {
|
||||
@ -612,54 +619,54 @@ struct hci_ev_conn_complete {
|
||||
bdaddr_t bdaddr;
|
||||
__u8 link_type;
|
||||
__u8 encr_mode;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_CONN_REQUEST 0x04
|
||||
struct hci_ev_conn_request {
|
||||
bdaddr_t bdaddr;
|
||||
__u8 dev_class[3];
|
||||
__u8 link_type;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_DISCONN_COMPLETE 0x05
|
||||
struct hci_ev_disconn_complete {
|
||||
__u8 status;
|
||||
__le16 handle;
|
||||
__u8 reason;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_AUTH_COMPLETE 0x06
|
||||
struct hci_ev_auth_complete {
|
||||
__u8 status;
|
||||
__le16 handle;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_REMOTE_NAME 0x07
|
||||
struct hci_ev_remote_name {
|
||||
__u8 status;
|
||||
bdaddr_t bdaddr;
|
||||
__u8 name[248];
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_ENCRYPT_CHANGE 0x08
|
||||
struct hci_ev_encrypt_change {
|
||||
__u8 status;
|
||||
__le16 handle;
|
||||
__u8 encrypt;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_CHANGE_LINK_KEY_COMPLETE 0x09
|
||||
struct hci_ev_change_link_key_complete {
|
||||
__u8 status;
|
||||
__le16 handle;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_REMOTE_FEATURES 0x0b
|
||||
struct hci_ev_remote_features {
|
||||
__u8 status;
|
||||
__le16 handle;
|
||||
__u8 features[8];
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_REMOTE_VERSION 0x0c
|
||||
struct hci_ev_remote_version {
|
||||
@ -668,7 +675,7 @@ struct hci_ev_remote_version {
|
||||
__u8 lmp_ver;
|
||||
__le16 manufacturer;
|
||||
__le16 lmp_subver;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_QOS_SETUP_COMPLETE 0x0d
|
||||
struct hci_qos {
|
||||
@ -677,38 +684,38 @@ struct hci_qos {
|
||||
__u32 peak_bandwidth;
|
||||
__u32 latency;
|
||||
__u32 delay_variation;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
struct hci_ev_qos_setup_complete {
|
||||
__u8 status;
|
||||
__le16 handle;
|
||||
struct hci_qos qos;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_CMD_COMPLETE 0x0e
|
||||
struct hci_ev_cmd_complete {
|
||||
__u8 ncmd;
|
||||
__le16 opcode;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_CMD_STATUS 0x0f
|
||||
struct hci_ev_cmd_status {
|
||||
__u8 status;
|
||||
__u8 ncmd;
|
||||
__le16 opcode;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_ROLE_CHANGE 0x12
|
||||
struct hci_ev_role_change {
|
||||
__u8 status;
|
||||
bdaddr_t bdaddr;
|
||||
__u8 role;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_NUM_COMP_PKTS 0x13
|
||||
struct hci_ev_num_comp_pkts {
|
||||
__u8 num_hndl;
|
||||
/* variable length part */
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_MODE_CHANGE 0x14
|
||||
struct hci_ev_mode_change {
|
||||
@ -716,44 +723,44 @@ struct hci_ev_mode_change {
|
||||
__le16 handle;
|
||||
__u8 mode;
|
||||
__le16 interval;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_PIN_CODE_REQ 0x16
|
||||
struct hci_ev_pin_code_req {
|
||||
bdaddr_t bdaddr;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_LINK_KEY_REQ 0x17
|
||||
struct hci_ev_link_key_req {
|
||||
bdaddr_t bdaddr;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_LINK_KEY_NOTIFY 0x18
|
||||
struct hci_ev_link_key_notify {
|
||||
bdaddr_t bdaddr;
|
||||
__u8 link_key[16];
|
||||
__u8 key_type;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_CLOCK_OFFSET 0x1c
|
||||
struct hci_ev_clock_offset {
|
||||
__u8 status;
|
||||
__le16 handle;
|
||||
__le16 clock_offset;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_PKT_TYPE_CHANGE 0x1d
|
||||
struct hci_ev_pkt_type_change {
|
||||
__u8 status;
|
||||
__le16 handle;
|
||||
__le16 pkt_type;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_PSCAN_REP_MODE 0x20
|
||||
struct hci_ev_pscan_rep_mode {
|
||||
bdaddr_t bdaddr;
|
||||
__u8 pscan_rep_mode;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_INQUIRY_RESULT_WITH_RSSI 0x22
|
||||
struct inquiry_info_with_rssi {
|
||||
@ -763,7 +770,7 @@ struct inquiry_info_with_rssi {
|
||||
__u8 dev_class[3];
|
||||
__le16 clock_offset;
|
||||
__s8 rssi;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
struct inquiry_info_with_rssi_and_pscan_mode {
|
||||
bdaddr_t bdaddr;
|
||||
__u8 pscan_rep_mode;
|
||||
@ -772,7 +779,7 @@ struct inquiry_info_with_rssi_and_pscan_mode {
|
||||
__u8 dev_class[3];
|
||||
__le16 clock_offset;
|
||||
__s8 rssi;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_REMOTE_EXT_FEATURES 0x23
|
||||
struct hci_ev_remote_ext_features {
|
||||
@ -781,7 +788,7 @@ struct hci_ev_remote_ext_features {
|
||||
__u8 page;
|
||||
__u8 max_page;
|
||||
__u8 features[8];
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_SYNC_CONN_COMPLETE 0x2c
|
||||
struct hci_ev_sync_conn_complete {
|
||||
@ -794,7 +801,7 @@ struct hci_ev_sync_conn_complete {
|
||||
__le16 rx_pkt_len;
|
||||
__le16 tx_pkt_len;
|
||||
__u8 air_mode;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_SYNC_CONN_CHANGED 0x2d
|
||||
struct hci_ev_sync_conn_changed {
|
||||
@ -804,7 +811,7 @@ struct hci_ev_sync_conn_changed {
|
||||
__u8 retrans_window;
|
||||
__le16 rx_pkt_len;
|
||||
__le16 tx_pkt_len;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_SNIFF_SUBRATE 0x2e
|
||||
struct hci_ev_sniff_subrate {
|
||||
@ -814,7 +821,7 @@ struct hci_ev_sniff_subrate {
|
||||
__le16 max_rx_latency;
|
||||
__le16 max_remote_timeout;
|
||||
__le16 max_local_timeout;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_EXTENDED_INQUIRY_RESULT 0x2f
|
||||
struct extended_inquiry_info {
|
||||
@ -825,37 +832,37 @@ struct extended_inquiry_info {
|
||||
__le16 clock_offset;
|
||||
__s8 rssi;
|
||||
__u8 data[240];
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_IO_CAPA_REQUEST 0x31
|
||||
struct hci_ev_io_capa_request {
|
||||
bdaddr_t bdaddr;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_SIMPLE_PAIR_COMPLETE 0x36
|
||||
struct hci_ev_simple_pair_complete {
|
||||
__u8 status;
|
||||
bdaddr_t bdaddr;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_REMOTE_HOST_FEATURES 0x3d
|
||||
struct hci_ev_remote_host_features {
|
||||
bdaddr_t bdaddr;
|
||||
__u8 features[8];
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
/* Internal events generated by Bluetooth stack */
|
||||
#define HCI_EV_STACK_INTERNAL 0xfd
|
||||
struct hci_ev_stack_internal {
|
||||
__u16 type;
|
||||
__u8 data[0];
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_SI_DEVICE 0x01
|
||||
struct hci_ev_si_device {
|
||||
__u16 event;
|
||||
__u16 dev_id;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_SI_SECURITY 0x02
|
||||
struct hci_ev_si_security {
|
||||
@ -863,7 +870,7 @@ struct hci_ev_si_security {
|
||||
__u16 proto;
|
||||
__u16 subproto;
|
||||
__u8 incoming;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
/* ---- HCI Packet structures ---- */
|
||||
#define HCI_COMMAND_HDR_SIZE 3
|
||||
@ -874,22 +881,22 @@ struct hci_ev_si_security {
|
||||
struct hci_command_hdr {
|
||||
__le16 opcode; /* OCF & OGF */
|
||||
__u8 plen;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
struct hci_event_hdr {
|
||||
__u8 evt;
|
||||
__u8 plen;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
struct hci_acl_hdr {
|
||||
__le16 handle; /* Handle & Flags(PB, BC) */
|
||||
__le16 dlen;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
struct hci_sco_hdr {
|
||||
__le16 handle;
|
||||
__u8 dlen;
|
||||
} __attribute__ ((packed));
|
||||
} __packed;
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/skbuff.h>
|
||||
|
@ -70,7 +70,8 @@ struct hci_dev {
|
||||
char name[8];
|
||||
unsigned long flags;
|
||||
__u16 id;
|
||||
__u8 type;
|
||||
__u8 bus;
|
||||
__u8 dev_type;
|
||||
bdaddr_t bdaddr;
|
||||
__u8 dev_name[248];
|
||||
__u8 dev_class[3];
|
||||
|
@ -796,7 +796,7 @@ int hci_get_dev_info(void __user *arg)
|
||||
|
||||
strcpy(di.name, hdev->name);
|
||||
di.bdaddr = hdev->bdaddr;
|
||||
di.type = hdev->type;
|
||||
di.type = hdev->bus;
|
||||
di.flags = hdev->flags;
|
||||
di.pkt_type = hdev->pkt_type;
|
||||
di.acl_mtu = hdev->acl_mtu;
|
||||
@ -868,8 +868,8 @@ int hci_register_dev(struct hci_dev *hdev)
|
||||
struct list_head *head = &hci_dev_list, *p;
|
||||
int i, id = 0;
|
||||
|
||||
BT_DBG("%p name %s type %d owner %p", hdev, hdev->name,
|
||||
hdev->type, hdev->owner);
|
||||
BT_DBG("%p name %s bus %d owner %p", hdev, hdev->name,
|
||||
hdev->bus, hdev->owner);
|
||||
|
||||
if (!hdev->open || !hdev->close || !hdev->destruct)
|
||||
return -EINVAL;
|
||||
@ -945,7 +945,7 @@ int hci_unregister_dev(struct hci_dev *hdev)
|
||||
{
|
||||
int i;
|
||||
|
||||
BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
|
||||
BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
|
||||
|
||||
write_lock_bh(&hci_dev_list_lock);
|
||||
list_del(&hdev->list);
|
||||
|
@ -166,9 +166,9 @@ void hci_conn_del_sysfs(struct hci_conn *conn)
|
||||
queue_work(bt_workq, &conn->work_del);
|
||||
}
|
||||
|
||||
static inline char *host_typetostr(int type)
|
||||
static inline char *host_bustostr(int bus)
|
||||
{
|
||||
switch (type) {
|
||||
switch (bus) {
|
||||
case HCI_VIRTUAL:
|
||||
return "VIRTUAL";
|
||||
case HCI_USB:
|
||||
@ -188,10 +188,10 @@ static inline char *host_typetostr(int type)
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t show_type(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
static ssize_t show_bus(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct hci_dev *hdev = dev_get_drvdata(dev);
|
||||
return sprintf(buf, "%s\n", host_typetostr(hdev->type));
|
||||
return sprintf(buf, "%s\n", host_bustostr(hdev->bus));
|
||||
}
|
||||
|
||||
static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
@ -355,7 +355,7 @@ static ssize_t store_sniff_min_interval(struct device *dev, struct device_attrib
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(type, S_IRUGO, show_type, NULL);
|
||||
static DEVICE_ATTR(bus, S_IRUGO, show_bus, NULL);
|
||||
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
|
||||
static DEVICE_ATTR(class, S_IRUGO, show_class, NULL);
|
||||
static DEVICE_ATTR(address, S_IRUGO, show_address, NULL);
|
||||
@ -373,7 +373,7 @@ static DEVICE_ATTR(sniff_min_interval, S_IRUGO | S_IWUSR,
|
||||
show_sniff_min_interval, store_sniff_min_interval);
|
||||
|
||||
static struct attribute *bt_host_attrs[] = {
|
||||
&dev_attr_type.attr,
|
||||
&dev_attr_bus.attr,
|
||||
&dev_attr_name.attr,
|
||||
&dev_attr_class.attr,
|
||||
&dev_attr_address.attr,
|
||||
@ -414,7 +414,7 @@ int hci_register_sysfs(struct hci_dev *hdev)
|
||||
struct device *dev = &hdev->dev;
|
||||
int err;
|
||||
|
||||
BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
|
||||
BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
|
||||
|
||||
dev->type = &bt_host;
|
||||
dev->class = bt_class;
|
||||
@ -433,7 +433,7 @@ int hci_register_sysfs(struct hci_dev *hdev)
|
||||
|
||||
void hci_unregister_sysfs(struct hci_dev *hdev)
|
||||
{
|
||||
BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
|
||||
BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
|
||||
|
||||
device_del(&hdev->dev);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user