Commit 2df06ce5 authored by Marcel Holtmann's avatar Marcel Holtmann

Merge bk://linux.bkbits.net/linux-2.5

into hostme.bitkeeper.com:/ua/repos/l/linux-bt/bt-2.5
parents f52d1d03 dbb5f15d
......@@ -13,11 +13,18 @@ config BT_HCIUSB
Say Y here to compile support for Bluetooth USB devices into the
kernel or say M to compile it as module (hci_usb).
config BT_USB_SCO
bool "SCO over HCI USB support"
depends on BT_HCIUSB
help
This option enables the SCO support in the HCI USB driver. You need this
to transmit voice data with your Bluetooth USB device.
Say Y here to compile support for SCO over HCI USB.
config BT_USB_ZERO_PACKET
bool "USB zero packet support"
depends on BT_HCIUSB
help
Support for USB zero packets.
This option is provided only as a work around for buggy Bluetooth USB
devices. Do _not_ enable it unless you know for sure that your device
requires zero packets.
......
......@@ -1075,36 +1075,29 @@ int bluecard_event(event_t event, int priority, event_callback_args_t *args)
return 0;
}
/* ======================== Module initialization ======================== */
int __init init_bluecard_cs(void)
static struct pcmcia_driver bluecard_driver = {
.owner = THIS_MODULE,
.drv = {
.name = "bluecard_cs",
},
.attach = bluecard_attach,
.detach = bluecard_detach,
};
static int __init init_bluecard_cs(void)
{
servinfo_t serv;
int err;
CardServices(GetCardServicesInfo, &serv);
if (serv.Revision != CS_RELEASE_CODE) {
printk(KERN_NOTICE "bluecard_cs: Card Services release does not match!\n");
return -1;
}
err = register_pccard_driver(&dev_info, &bluecard_attach, &bluecard_detach);
return err;
return pcmcia_register_driver(&bluecard_driver);
}
void __exit exit_bluecard_cs(void)
static void __exit exit_bluecard_cs(void)
{
unregister_pccard_driver(&dev_info);
pcmcia_unregister_driver(&bluecard_driver);
/* XXX: this really needs to move into generic code.. */
while (dev_list != NULL)
bluecard_detach(dev_list);
}
module_init(init_bluecard_cs);
module_exit(exit_bluecard_cs);
......@@ -861,36 +861,29 @@ int bt3c_event(event_t event, int priority, event_callback_args_t *args)
return 0;
}
/* ======================== Module initialization ======================== */
int __init init_bt3c_cs(void)
static struct pcmcia_driver bt3c_driver = {
.owner = THIS_MODULE,
.drv = {
.name = "bt3c_cs",
},
.attach = bt3c_attach,
.detach = bt3c_detach,
};
static int __init init_bt3c_cs(void)
{
servinfo_t serv;
int err;
CardServices(GetCardServicesInfo, &serv);
if (serv.Revision != CS_RELEASE_CODE) {
printk(KERN_NOTICE "bt3c_cs: Card Services release does not match!\n");
return -1;
}
err = register_pccard_driver(&dev_info, &bt3c_attach, &bt3c_detach);
return err;
return pcmcia_register_driver(&bt3c_driver);
}
void __exit exit_bt3c_cs(void)
static void __exit exit_bt3c_cs(void)
{
unregister_pccard_driver(&dev_info);
pcmcia_unregister_driver(&bt3c_driver);
/* XXX: this really needs to move into generic code.. */
while (dev_list != NULL)
bt3c_detach(dev_list);
}
module_init(init_bt3c_cs);
module_exit(exit_bt3c_cs);
......@@ -868,36 +868,29 @@ int btuart_event(event_t event, int priority, event_callback_args_t *args)
return 0;
}
/* ======================== Module initialization ======================== */
int __init init_btuart_cs(void)
static struct pcmcia_driver btuart_driver = {
.owner = THIS_MODULE,
.drv = {
.name = "btuart_cs",
},
.attach = btuart_attach,
.detach = btuart_detach,
};
static int __init init_btuart_cs(void)
{
servinfo_t serv;
int err;
CardServices(GetCardServicesInfo, &serv);
if (serv.Revision != CS_RELEASE_CODE) {
printk(KERN_NOTICE "btuart_cs: Card Services release does not match!\n");
return -1;
}
err = register_pccard_driver(&dev_info, &btuart_attach, &btuart_detach);
return err;
return pcmcia_register_driver(&btuart_driver);
}
void __exit exit_btuart_cs(void)
static void __exit exit_btuart_cs(void)
{
unregister_pccard_driver(&dev_info);
pcmcia_unregister_driver(&btuart_driver);
/* XXX: this really needs to move into generic code.. */
while (dev_list != NULL)
btuart_detach(dev_list);
}
module_init(init_btuart_cs);
module_exit(exit_btuart_cs);
......@@ -820,36 +820,29 @@ int dtl1_event(event_t event, int priority, event_callback_args_t *args)
return 0;
}
/* ======================== Module initialization ======================== */
int __init init_dtl1_cs(void)
static struct pcmcia_driver dtl1_driver = {
.owner = THIS_MODULE,
.drv = {
.name = "dtl1_cs",
},
.attach = dtl1_attach,
.detach = dtl1_detach,
};
static int __init init_dtl1_cs(void)
{
servinfo_t serv;
int err;
CardServices(GetCardServicesInfo, &serv);
if (serv.Revision != CS_RELEASE_CODE) {
printk(KERN_NOTICE "dtl1_cs: Card Services release does not match!\n");
return -1;
}
err = register_pccard_driver(&dev_info, &dtl1_attach, &dtl1_detach);
return err;
return pcmcia_register_driver(&dtl1_driver);
}
void __exit exit_dtl1_cs(void)
static void __exit exit_dtl1_cs(void)
{
unregister_pccard_driver(&dev_info);
pcmcia_unregister_driver(&dtl1_driver);
/* XXX: this really needs to move into generic code.. */
while (dev_list != NULL)
dtl1_detach(dev_list);
}
module_init(init_dtl1_cs);
module_exit(exit_dtl1_cs);
This diff is collapsed.
/*
BlueZ - Bluetooth protocol stack for Linux
HCI USB driver for Linux Bluetooth protocol stack (BlueZ)
Copyright (C) 2000-2001 Qualcomm Incorporated
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
Copyright (C) 2003 Maxim Krasnyansky <maxk@qualcomm.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation;
......@@ -40,40 +41,96 @@
#define HCI_MAX_BULK_TX 4
#define HCI_MAX_BULK_RX 1
#define HCI_MAX_ISOC_FRAMES 10
struct _urb_queue {
struct list_head head;
spinlock_t lock;
};
struct _urb {
struct list_head list;
struct _urb_queue *queue;
int type;
void *priv;
struct urb urb;
};
struct _urb *_urb_alloc(int isoc, int gfp);
static inline void _urb_free(struct _urb *_urb)
{
kfree(_urb);
}
static inline void _urb_queue_init(struct _urb_queue *q)
{
INIT_LIST_HEAD(&q->head);
spin_lock_init(&q->lock);
}
static inline void _urb_queue_head(struct _urb_queue *q, struct _urb *_urb)
{
unsigned long flags;
spin_lock_irqsave(&q->lock, flags);
list_add(&_urb->list, &q->head); _urb->queue = q;
spin_unlock_irqrestore(&q->lock, flags);
}
static inline void _urb_queue_tail(struct _urb_queue *q, struct _urb *_urb)
{
unsigned long flags;
spin_lock_irqsave(&q->lock, flags);
list_add_tail(&_urb->list, &q->head); _urb->queue = q;
spin_unlock_irqrestore(&q->lock, flags);
}
static inline void _urb_unlink(struct _urb *_urb)
{
struct _urb_queue *q = _urb->queue;
unsigned long flags;
if (q) {
spin_lock_irqsave(&q->lock, flags);
list_del(&_urb->list); _urb->queue = NULL;
spin_unlock_irqrestore(&q->lock, flags);
}
}
struct _urb *_urb_dequeue(struct _urb_queue *q);
#ifndef container_of
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#endif
struct hci_usb {
struct hci_dev hdev;
unsigned long state;
struct usb_device *udev;
struct usb_interface *isoc_iface;
__u8 bulk_out_ep;
__u8 bulk_in_ep;
__u8 isoc_out_ep;
__u8 isoc_in_ep;
struct usb_host_endpoint *bulk_in_ep;
struct usb_host_endpoint *bulk_out_ep;
struct usb_host_endpoint *intr_in_ep;
struct usb_interface *isoc_iface;
struct usb_host_endpoint *isoc_out_ep;
struct usb_host_endpoint *isoc_in_ep;
__u8 intr_ep;
__u8 intr_interval;
struct urb *intr_urb;
struct sk_buff *intr_skb;
struct sk_buff_head transmit_q[4];
struct sk_buff *reassembly[4]; // Reassembly buffers
rwlock_t completion_lock;
struct sk_buff_head cmd_q; // TX Commands
struct sk_buff_head acl_q; // TX ACLs
struct sk_buff_head pending_q; // Pending requests
struct sk_buff_head completed_q; // Completed requests
};
struct hci_usb_scb {
struct urb *urb;
int intr_len;
atomic_t pending_tx[4]; // Number of pending requests
struct _urb_queue pending_q[4]; // Pending requests
struct _urb_queue completed_q[4]; // Completed requests
};
/* States */
#define HCI_USB_TX_PROCESS 1
#define HCI_USB_TX_WAKEUP 2
#define HCI_USB_CTRL_TX 3
#endif /* __KERNEL__ */
......@@ -262,7 +262,7 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *src);
int hci_conn_auth(struct hci_conn *conn);
int hci_conn_encrypt(struct hci_conn *conn);
static inline void hci_conn_set_timer(struct hci_conn *conn, long timeout)
static inline void hci_conn_set_timer(struct hci_conn *conn, unsigned long timeout)
{
mod_timer(&conn->timer, jiffies + timeout);
}
......@@ -280,8 +280,12 @@ static inline void hci_conn_hold(struct hci_conn *conn)
static inline void hci_conn_put(struct hci_conn *conn)
{
if (atomic_dec_and_test(&conn->refcnt) && conn->out)
hci_conn_set_timer(conn, HCI_DISCONN_TIMEOUT);
if (atomic_dec_and_test(&conn->refcnt)) {
if (conn->type == SCO_LINK)
hci_conn_set_timer(conn, HZ / 100);
else if (conn->out)
hci_conn_set_timer(conn, HCI_DISCONN_TIMEOUT);
}
}
/* ----- HCI tasks ----- */
......
......@@ -146,6 +146,11 @@ struct rfcomm_rpn {
u16 param_mask;
} __attribute__ ((packed));
struct rfcomm_rls {
u8 dlci;
u8 status;
} __attribute__ ((packed));
struct rfcomm_msc {
u8 dlci;
u8 v24_sig;
......
......@@ -71,6 +71,7 @@ void hci_acl_connect(struct hci_conn *conn)
memset(&cp, 0, sizeof(cp));
bacpy(&cp.bdaddr, &conn->dst);
cp.pscan_rep_mode = 0x01;
if ((ie = inquiry_cache_lookup(hdev, &conn->dst)) &&
inquiry_entry_age(ie) <= INQUIRY_ENTRY_AGE_MAX) {
......
......@@ -1788,7 +1788,7 @@ static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
if (sk->state != BT_LISTEN)
continue;
if (!bacmp(&bt_sk(sk)->src, bdaddr)) {
if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
lm1 |= (HCI_LM_ACCEPT | l2cap_pi(sk)->link_mode);
exact++;
} else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
......
......@@ -798,6 +798,33 @@ static int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci,
return rfcomm_send_frame(s, buf, ptr - buf);
}
static int rfcomm_send_rls(struct rfcomm_session *s, int cr, u8 dlci, u8 status)
{
struct rfcomm_hdr *hdr;
struct rfcomm_mcc *mcc;
struct rfcomm_rls *rls;
u8 buf[16], *ptr = buf;
BT_DBG("%p cr %d status 0x%x", s, cr, status);
hdr = (void *) ptr; ptr += sizeof(*hdr);
hdr->addr = __addr(s->initiator, 0);
hdr->ctrl = __ctrl(RFCOMM_UIH, 0);
hdr->len = __len8(sizeof(*mcc) + sizeof(*rls));
mcc = (void *) ptr; ptr += sizeof(*mcc);
mcc->type = __mcc_type(cr, RFCOMM_RLS);
mcc->len = __len8(sizeof(*rls));
rls = (void *) ptr; ptr += sizeof(*rls);
rls->dlci = __addr(1, dlci);
rls->status = status;
*ptr = __fcs(buf); ptr++;
return rfcomm_send_frame(s, buf, ptr - buf);
}
static int rfcomm_send_msc(struct rfcomm_session *s, int cr, u8 dlci, u8 v24_sig)
{
struct rfcomm_hdr *hdr;
......@@ -1229,6 +1256,26 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
return 0;
}
static int rfcomm_recv_rls(struct rfcomm_session *s, int cr, struct sk_buff *skb)
{
struct rfcomm_rls *rls = (void *) skb->data;
u8 dlci = __get_dlci(rls->dlci);
BT_DBG("dlci %d cr %d status 0x%x", dlci, cr, rls->status);
if (!cr)
return 0;
/* FIXME: We should probably do something with this
information here. But for now it's sufficient just
to reply -- Bluetooth 1.1 says it's mandatory to
recognise and respond to RLS */
rfcomm_send_rls(s, 0, dlci, rls->status);
return 0;
}
static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb)
{
struct rfcomm_msc *msc = (void *) skb->data;
......@@ -1279,6 +1326,10 @@ static int rfcomm_recv_mcc(struct rfcomm_session *s, struct sk_buff *skb)
rfcomm_recv_rpn(s, cr, len, skb);
break;
case RFCOMM_RLS:
rfcomm_recv_rls(s, cr, skb);
break;
case RFCOMM_MSC:
rfcomm_recv_msc(s, cr, skb);
break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment