Commit 735fe7c5 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 4749dedc 76762efa
menu "Bluetooth device drivers"
depends on BT!=n
depends on BT
config BT_HCIUSB
tristate "HCI USB driver"
......@@ -57,6 +57,14 @@ config BT_HCIUART_BCSP
Say Y here to compile support for HCI BCSP protocol.
config BT_HCIUART_BCSP_TXCRC
bool "Transmit CRC with every BCSP packet"
depends on BT_HCIUART_BCSP
help
If you say Y here, a 16-bit CRC checksum will be transmitted along with
every BCSP (BlueCore Serial Protocol) packet sent to the Bluetooth chip.
This increases reliability, but slightly reduces efficiency.
config BT_HCIDTL1
tristate "HCI DTL1 (PC Card) driver"
depends on PCMCIA && BT
......@@ -73,7 +81,7 @@ config BT_HCIDTL1
config BT_HCIBT3C
tristate "HCI BT3C (PC Card) driver"
depends on PCMCIA && BT
---help---
help
Bluetooth HCI BT3C (PC Card) driver.
This driver provides support for Bluetooth PCMCIA devices with
3Com BT3C interface:
......@@ -99,6 +107,22 @@ config BT_HCIBLUECARD
Say Y here to compile support for HCI BlueCard devices into the
kernel or say M to compile it as module (bluecard_cs.o).
config BT_HCIBTUART
tristate "HCI UART (PC Card) device driver"
depends on PCMCIA && BT
help
Bluetooth HCI UART (PC Card) driver.
This driver provides support for Bluetooth PCMCIA devices with
an UART interface:
Xircom CreditCard Bluetooth Adapter
Xircom RealPort2 Bluetooth Adapter
Sphinx PICO Card
H-Soft blue+Card
Cyber-blue Compact Flash Card
Say Y here to compile support for HCI UART devices into the
kernel or say M to compile it as module (btuart_cs.o).
config BT_HCIVHCI
tristate "HCI VHCI (Virtual HCI device) driver"
depends on BT
......
......@@ -8,6 +8,7 @@ obj-$(CONFIG_BT_HCIUART) += hci_uart.o
obj-$(CONFIG_BT_HCIDTL1) += dtl1_cs.o
obj-$(CONFIG_BT_HCIBT3C) += bt3c_cs.o
obj-$(CONFIG_BT_HCIBLUECARD) += bluecard_cs.o
obj-$(CONFIG_BT_HCIBTUART) += btuart_cs.o
hci_uart-y := hci_ldisc.o
hci_uart-$(CONFIG_BT_HCIUART_H4) += hci_h4.o
......
This diff is collapsed.
......@@ -48,6 +48,7 @@
#define HCI_PCCARD 2
#define HCI_UART 3
#define HCI_RS232 4
#define HCI_PCI 5
/* HCI device flags */
enum {
......
......@@ -224,6 +224,8 @@ struct l2cap_pinfo {
__u8 ident;
__u16 sport;
struct l2cap_conn *conn;
struct sock *next_c;
struct sock *prev_c;
......
......@@ -7,7 +7,7 @@ menu "Bluetooth support"
config BT
tristate "Bluetooth subsystem support"
---help---
help
Bluetooth is low-cost, low-power, short-range wireless technology.
It was designed as a replacement for cables and other short-range
technologies like IrDA. Bluetooth operates in personal area range
......
config BT_BNEP
tristate "BNEP protocol support"
depends on BT_L2CAP
---help---
depends on BT && BT_L2CAP
help
BNEP (Bluetooth Network Encapsulation Protocol) is Ethernet
emulation layer on top of Bluetooth. BNEP is required for Bluetooth
PAN (Personal Area Network).
......
......@@ -128,18 +128,17 @@ static int bnep_send_rsp(struct bnep_session *s, u8 ctrl, u16 resp)
return bnep_send(s, &rsp, sizeof(rsp));
}
static int bnep_ctrl_set_netfilter(struct bnep_session *s, struct sk_buff *skb)
static int bnep_ctrl_set_netfilter(struct bnep_session *s, u16 *data, int len)
{
u16 *data;
int n;
data = (void *) skb->data;
if (!skb_pull(skb, 2))
if (len < 2)
return -EILSEQ;
n = ntohs(get_unaligned(data));
data++; len -= 2;
data = (void *) skb->data;
if (!skb_pull(skb, n))
if (len < n)
return -EILSEQ;
BT_DBG("filter len %d", n);
......@@ -170,18 +169,17 @@ static int bnep_ctrl_set_netfilter(struct bnep_session *s, struct sk_buff *skb)
return 0;
}
static int bnep_ctrl_set_mcfilter(struct bnep_session *s, struct sk_buff *skb)
static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len)
{
u8 *data;
int n;
data = (void *) skb->data;
if (!skb_pull(skb, 2))
if (len < 2)
return -EILSEQ;
n = ntohs(get_unaligned((u16 *) data));
data += 2; len -= 2;
data = (void *) skb->data;
if (!skb_pull(skb, n))
if (len < n)
return -EILSEQ;
BT_DBG("filter len %d", n);
......@@ -225,11 +223,12 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, struct sk_buff *skb)
return 0;
}
static int bnep_rx_control(struct bnep_session *s, struct sk_buff *skb)
static int bnep_rx_control(struct bnep_session *s, void *data, int len)
{
u8 cmd = *(u8 *)data;
int err = 0;
u8 cmd = *(u8 *) skb->data;
skb_pull(skb, 1);
data++; len--;
switch (cmd) {
case BNEP_CMD_NOT_UNDERSTOOD:
......@@ -241,11 +240,11 @@ static int bnep_rx_control(struct bnep_session *s, struct sk_buff *skb)
break;
case BNEP_FILTER_NET_TYPE_SET:
err = bnep_ctrl_set_netfilter(s, skb);
err = bnep_ctrl_set_netfilter(s, data, len);
break;
case BNEP_FILTER_MULTI_ADDR_SET:
err = bnep_ctrl_set_mcfilter(s, skb);
err = bnep_ctrl_set_mcfilter(s, data, len);
break;
default: {
......@@ -277,12 +276,15 @@ static int bnep_rx_extension(struct bnep_session *s, struct sk_buff *skb)
switch (h->type & BNEP_TYPE_MASK) {
case BNEP_EXT_CONTROL:
err = bnep_rx_control(s, skb);
bnep_rx_control(s, skb->data, skb->len);
break;
default:
/* Unknown extension */
if (!skb_pull(skb, h->len))
/* Unknown extension, skip it. */
break;
}
if (!skb_pull(skb, h->len)) {
err = -EILSEQ;
break;
}
......@@ -315,7 +317,7 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
goto badframe;
if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) {
bnep_rx_control(s, skb);
bnep_rx_control(s, skb->data, skb->len);
kfree_skb(skb);
return 0;
}
......
......@@ -718,7 +718,7 @@ int hci_get_dev_list(unsigned long arg)
if (!dev_num)
return -EINVAL;
size = dev_num * sizeof(struct hci_dev_req) + sizeof(__u16);
size = dev_num * sizeof(*dr) + sizeof(*dl);
if (verify_area(VERIFY_WRITE, (void *) arg, size))
return -EFAULT;
......@@ -739,7 +739,7 @@ int hci_get_dev_list(unsigned long arg)
read_unlock_bh(&hci_dev_list_lock);
dl->dev_num = n;
size = n * sizeof(struct hci_dev_req) + sizeof(__u16);
size = n * sizeof(*dr) + sizeof(*dl);
copy_to_user((void *) arg, dl, size);
kfree(dl);
......
......@@ -186,69 +186,12 @@ static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, stru
write_unlock(&l->lock);
}
int l2cap_connect(struct sock *sk)
{
bdaddr_t *src = &bt_sk(sk)->src;
bdaddr_t *dst = &bt_sk(sk)->dst;
struct l2cap_conn *conn;
struct hci_conn *hcon;
struct hci_dev *hdev;
int err = 0;
BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst), l2cap_pi(sk)->psm);
if (!(hdev = hci_get_route(dst, src)))
return -EHOSTUNREACH;
hci_dev_lock_bh(hdev);
err = -ENOMEM;
hcon = hci_connect(hdev, ACL_LINK, dst);
if (!hcon)
goto done;
conn = l2cap_conn_add(hcon, 0);
if (!conn) {
hci_conn_put(hcon);
goto done;
}
err = 0;
/* Update source addr of the socket */
bacpy(src, conn->src);
l2cap_chan_add(conn, sk, NULL);
sk->state = BT_CONNECT;
l2cap_sock_set_timer(sk, sk->sndtimeo);
if (hcon->state == BT_CONNECTED) {
if (sk->type == SOCK_SEQPACKET) {
struct l2cap_conn_req req;
req.scid = __cpu_to_le16(l2cap_pi(sk)->scid);
req.psm = l2cap_pi(sk)->psm;
l2cap_send_req(conn, L2CAP_CONN_REQ, sizeof(req), &req);
} else {
l2cap_sock_clear_timer(sk);
sk->state = BT_CONNECTED;
}
}
done:
hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return err;
}
/* ---- Socket interface ---- */
static struct sock *__l2cap_get_sock_by_addr(u16 psm, bdaddr_t *src)
{
struct sock *sk;
for (sk = l2cap_sk_list.head; sk; sk = sk->next) {
if (l2cap_pi(sk)->psm == psm &&
!bacmp(&bt_sk(sk)->src, src))
if (l2cap_pi(sk)->sport == psm && !bacmp(&bt_sk(sk)->src, src))
break;
}
return sk;
......@@ -438,6 +381,9 @@ static int l2cap_sock_create(struct socket *sock, int protocol)
if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_DGRAM && sock->type != SOCK_RAW)
return -ESOCKTNOSUPPORT;
if (sock->type == SOCK_RAW && !capable(CAP_NET_RAW))
return -EPERM;
sock->ops = &l2cap_sock_ops;
sk = l2cap_sock_alloc(sock, protocol, GFP_KERNEL);
......@@ -473,6 +419,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_
/* Save source address */
bacpy(&bt_sk(sk)->src, &la->l2_bdaddr);
l2cap_pi(sk)->psm = la->l2_psm;
l2cap_pi(sk)->sport = la->l2_psm;
sk->state = BT_BOUND;
}
write_unlock_bh(&l2cap_sk_list.lock);
......@@ -482,6 +429,62 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_
return err;
}
static int l2cap_do_connect(struct sock *sk)
{
bdaddr_t *src = &bt_sk(sk)->src;
bdaddr_t *dst = &bt_sk(sk)->dst;
struct l2cap_conn *conn;
struct hci_conn *hcon;
struct hci_dev *hdev;
int err = 0;
BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst), l2cap_pi(sk)->psm);
if (!(hdev = hci_get_route(dst, src)))
return -EHOSTUNREACH;
hci_dev_lock_bh(hdev);
err = -ENOMEM;
hcon = hci_connect(hdev, ACL_LINK, dst);
if (!hcon)
goto done;
conn = l2cap_conn_add(hcon, 0);
if (!conn) {
hci_conn_put(hcon);
goto done;
}
err = 0;
/* Update source addr of the socket */
bacpy(src, conn->src);
l2cap_chan_add(conn, sk, NULL);
sk->state = BT_CONNECT;
l2cap_sock_set_timer(sk, sk->sndtimeo);
if (hcon->state == BT_CONNECTED) {
if (sk->type == SOCK_SEQPACKET) {
struct l2cap_conn_req req;
req.scid = __cpu_to_le16(l2cap_pi(sk)->scid);
req.psm = l2cap_pi(sk)->psm;
l2cap_send_req(conn, L2CAP_CONN_REQ, sizeof(req), &req);
} else {
l2cap_sock_clear_timer(sk);
sk->state = BT_CONNECTED;
}
}
done:
hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
return err;
}
static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
{
struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr;
......@@ -527,7 +530,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
bacpy(&bt_sk(sk)->dst, &la->l2_bdaddr);
l2cap_pi(sk)->psm = la->l2_psm;
if ((err = l2cap_connect(sk)))
if ((err = l2cap_do_connect(sk)))
goto done;
wait:
......@@ -2074,7 +2077,7 @@ static int __init l2cap_proc_init(void)
static void __init l2cap_proc_cleanup(void)
{
return 0;
return;
}
#endif /* CONFIG_PROC_FS */
......
config BT_RFCOMM
tristate "RFCOMM protocol support"
depends on BT_L2CAP
depends on BT && BT_L2CAP
help
RFCOMM provides connection oriented stream transport. RFCOMM
support is required for Dialup Networking, OBEX and other Bluetooth
......
......@@ -1312,6 +1312,9 @@ static int rfcomm_recv_mcc(struct rfcomm_session *s, struct sk_buff *skb)
rfcomm_send_test(s, 0, skb->data, skb->len);
break;
case RFCOMM_NSC:
break;
default:
BT_ERR("Unknown control type 0x%02x", type);
rfcomm_send_nsc(s, cr, type);
......@@ -1442,7 +1445,7 @@ static inline int rfcomm_process_tx(struct rfcomm_dlc *d)
/* Send pending MSC */
if (test_and_clear_bit(RFCOMM_MSC_PENDING, &d->flags))
rfcomm_send_msc(d->session, d->dlci, 1, d->v24_sig);
rfcomm_send_msc(d->session, 1, d->dlci, d->v24_sig);
if (d->credits) {
/* CFC enabled.
......@@ -1831,7 +1834,7 @@ static int __init rfcomm_proc_init(void)
static void __init rfcomm_proc_cleanup(void)
{
return 0;
return;
}
#endif /* CONFIG_PROC_FS */
......
......@@ -851,7 +851,7 @@ static int __init rfcomm_sock_proc_init(void)
static void __init rfcomm_sock_proc_cleanup(void)
{
return 0;
return;
}
#endif /* CONFIG_PROC_FS */
......
......@@ -442,7 +442,7 @@ static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb)
struct tty_struct *tty;
if (!dev || !(tty = dev->tty)) {
kfree(skb);
kfree_skb(skb);
return;
}
......@@ -669,12 +669,12 @@ static int rfcomm_tty_set_modem_status(uint cmd, struct rfcomm_dlc *dlc, uint st
else
rfcomm_dlc_get_modem_status(dlc, &v24_sig);
mask = (status & TIOCM_DSR) ? RFCOMM_V24_RTC : 0 |
(status & TIOCM_DTR) ? RFCOMM_V24_RTC : 0 |
(status & TIOCM_RTS) ? RFCOMM_V24_RTR : 0 |
(status & TIOCM_CTS) ? RFCOMM_V24_RTR : 0 |
(status & TIOCM_RI) ? RFCOMM_V24_IC : 0 |
(status & TIOCM_CD) ? RFCOMM_V24_DV : 0;
mask = ((status & TIOCM_DSR) ? RFCOMM_V24_RTC : 0) |
((status & TIOCM_DTR) ? RFCOMM_V24_RTC : 0) |
((status & TIOCM_RTS) ? RFCOMM_V24_RTR : 0) |
((status & TIOCM_CTS) ? RFCOMM_V24_RTR : 0) |
((status & TIOCM_RI) ? RFCOMM_V24_IC : 0) |
((status & TIOCM_CD) ? RFCOMM_V24_DV : 0);
if (cmd == TIOCMBIC)
v24_sig &= ~mask;
......
......@@ -962,7 +962,7 @@ static int __init sco_proc_init(void)
static void __init sco_proc_cleanup(void)
{
return 0;
return;
}
#endif /* CONFIG_PROC_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