Commit 8feb324f authored by Linus Torvalds's avatar Linus Torvalds

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

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 204048de 2d6ed781
......@@ -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;
......@@ -215,10 +220,9 @@ static inline void rfcomm_schedule(uint event)
{
if (!rfcomm_thread)
return;
//set_bit(event, &rfcomm_event);
if (!test_and_set_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event))
wake_up_process(rfcomm_thread);
set_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event);
wake_up_process(rfcomm_thread);
}
extern struct semaphore rfcomm_sem;
......
......@@ -321,6 +321,7 @@ int bt_sock_w4_connect(struct sock *sk, int flags)
}
struct net_proto_family bt_sock_family_ops = {
.owner = THIS_MODULE,
.family = PF_BLUETOOTH,
.create = bt_sock_create,
};
......
......@@ -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) {
......
......@@ -161,8 +161,6 @@ static int hci_sock_release(struct socket *sock)
skb_queue_purge(&sk->write_queue);
sock_put(sk);
MOD_DEC_USE_COUNT;
return 0;
}
......@@ -591,8 +589,6 @@ static int hci_sock_create(struct socket *sock, int protocol)
sk->state = BT_OPEN;
bt_sock_link(&hci_sk_list, sk);
MOD_INC_USE_COUNT;
return 0;
}
......
......@@ -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;
......@@ -1432,9 +1483,9 @@ static inline int rfcomm_process_tx(struct rfcomm_dlc *d)
d->rx_credits = d->credits;
}
} else {
/* CFC disabled.
/* CFC disabled.
* Give ourselves some credits */
d->tx_credits = RFCOMM_MAX_CREDITS;
d->tx_credits = 5;
}
if (test_bit(RFCOMM_TX_THROTTLED, &d->flags))
......@@ -1600,7 +1651,7 @@ static void rfcomm_worker(void)
BT_DBG("");
while (!atomic_read(&terminate)) {
if (!test_and_clear_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event)) {
if (!test_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event)) {
/* No pending events. Let's sleep.
* Incomming connections and data will wake us up. */
set_current_state(TASK_INTERRUPTIBLE);
......@@ -1608,6 +1659,7 @@ static void rfcomm_worker(void)
}
/* Process stuff */
clear_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event);
rfcomm_process_sessions();
}
set_current_state(TASK_RUNNING);
......
......@@ -72,7 +72,6 @@ struct rfcomm_dev {
struct tasklet_struct wakeup_task;
atomic_t wmem_alloc;
unsigned int sndbuf;
};
static LIST_HEAD(rfcomm_dev_list);
......@@ -200,8 +199,6 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
dev->flags = req->flags &
((1 << RFCOMM_RELEASE_ONHUP) | (1 << RFCOMM_REUSE_DLC));
dev->sndbuf = RFCOMM_MAX_CREDITS * RFCOMM_DEFAULT_MTU * 10;
init_waitqueue_head(&dev->wait);
tasklet_init(&dev->wakeup_task, rfcomm_tty_wakeup, (unsigned long) dev);
......@@ -238,6 +235,13 @@ static void rfcomm_dev_del(struct rfcomm_dev *dev)
}
/* ---- Send buffer ---- */
static inline unsigned int rfcomm_room(struct rfcomm_dlc *dlc)
{
/* We can't let it be zero, because we don't get a callback
when tx_credits becomes nonzero, hence we'd never wake up */
return dlc->mtu * (dlc->tx_credits?:1);
}
static void rfcomm_wfree(struct sk_buff *skb)
{
struct rfcomm_dev *dev = (void *) skb->sk;
......@@ -257,7 +261,7 @@ static inline void rfcomm_set_owner_w(struct sk_buff *skb, struct rfcomm_dev *de
static struct sk_buff *rfcomm_wmalloc(struct rfcomm_dev *dev, unsigned long size, int priority)
{
if (atomic_read(&dev->wmem_alloc) < dev->sndbuf) {
if (atomic_read(&dev->wmem_alloc) < rfcomm_room(dev->dlc)) {
struct sk_buff *skb = alloc_skb(size, priority);
if (skb) {
rfcomm_set_owner_w(skb, dev);
......@@ -651,11 +655,14 @@ static int rfcomm_tty_write(struct tty_struct *tty, int from_user, const unsigne
static int rfcomm_tty_write_room(struct tty_struct *tty)
{
struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
struct rfcomm_dlc *dlc = dev->dlc;
int room;
BT_DBG("tty %p", tty);
return dlc->mtu * (dlc->tx_credits ? : 10);
room = rfcomm_room(dev->dlc) - atomic_read(&dev->wmem_alloc);
if (room < 0)
room = 0;
return room;
}
static int rfcomm_tty_set_modem_status(uint cmd, struct rfcomm_dlc *dlc, uint status)
......@@ -849,6 +856,8 @@ static struct termios *rfcomm_tty_termios[RFCOMM_TTY_PORTS];
static struct termios *rfcomm_tty_termios_locked[RFCOMM_TTY_PORTS];
static struct tty_driver rfcomm_tty_driver = {
.owner = THIS_MODULE,
.magic = TTY_DRIVER_MAGIC,
.driver_name = "rfcomm",
#ifdef CONFIG_DEVFS_FS
......
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