Commit 2112bb15 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 9552d6bc 7a0987ce
...@@ -97,6 +97,7 @@ ...@@ -97,6 +97,7 @@
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci.h> #include <net/bluetooth/hci.h>
#include <net/bluetooth/rfcomm.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/usbdevice_fs.h> #include <linux/usbdevice_fs.h>
...@@ -4264,6 +4265,15 @@ static int do_blkgetsize64(unsigned int fd, unsigned int cmd, ...@@ -4264,6 +4265,15 @@ static int do_blkgetsize64(unsigned int fd, unsigned int cmd,
return sys_ioctl(fd, BLKGETSIZE64, arg); return sys_ioctl(fd, BLKGETSIZE64, arg);
} }
/* Bluetooth ioctls */
#define HCIUARTSETPROTO _IOW('U', 200, int)
#define HCIUARTGETPROTO _IOR('U', 201, int)
#define BNEPCONNADD _IOW('B', 200, int)
#define BNEPCONNDEL _IOW('B', 201, int)
#define BNEPGETCONNLIST _IOR('B', 210, int)
#define BNEPGETCONNINFO _IOR('B', 211, int)
struct ioctl_trans { struct ioctl_trans {
unsigned int cmd; unsigned int cmd;
unsigned int handler; unsigned int handler;
...@@ -4956,6 +4966,17 @@ COMPATIBLE_IOCTL(HCISETLINKMODE) ...@@ -4956,6 +4966,17 @@ COMPATIBLE_IOCTL(HCISETLINKMODE)
COMPATIBLE_IOCTL(HCISETACLMTU) COMPATIBLE_IOCTL(HCISETACLMTU)
COMPATIBLE_IOCTL(HCISETSCOMTU) COMPATIBLE_IOCTL(HCISETSCOMTU)
COMPATIBLE_IOCTL(HCIINQUIRY) COMPATIBLE_IOCTL(HCIINQUIRY)
COMPATIBLE_IOCTL(HCIUARTSETPROTO)
COMPATIBLE_IOCTL(HCIUARTGETPROTO)
COMPATIBLE_IOCTL(RFCOMMCREATEDEV)
COMPATIBLE_IOCTL(RFCOMMRELEASEDEV)
COMPATIBLE_IOCTL(RFCOMMGETDEVLIST)
COMPATIBLE_IOCTL(RFCOMMGETDEVINFO)
COMPATIBLE_IOCTL(RFCOMMSTEALDLC)
COMPATIBLE_IOCTL(BNEPCONNADD)
COMPATIBLE_IOCTL(BNEPCONNDEL)
COMPATIBLE_IOCTL(BNEPGETCONNLIST)
COMPATIBLE_IOCTL(BNEPGETCONNINFO)
/* Misc. */ /* Misc. */
COMPATIBLE_IOCTL(0x41545900) /* ATYIO_CLKR */ COMPATIBLE_IOCTL(0x41545900) /* ATYIO_CLKR */
COMPATIBLE_IOCTL(0x41545901) /* ATYIO_CLKW */ COMPATIBLE_IOCTL(0x41545901) /* ATYIO_CLKW */
......
menu "Bluetooth device drivers" menu "Bluetooth device drivers"
depends on BT!=n depends on BT
config BT_HCIUSB config BT_HCIUSB
tristate "HCI USB driver" tristate "HCI USB driver"
...@@ -52,11 +52,19 @@ config BT_HCIUART_BCSP ...@@ -52,11 +52,19 @@ config BT_HCIUART_BCSP
help help
BCSP (BlueCore Serial Protocol) is serial protocol for communication BCSP (BlueCore Serial Protocol) is serial protocol for communication
between Bluetooth device and host. This protocol is required for non between Bluetooth device and host. This protocol is required for non
USB Bluetooth devices based on CSR BlueCore chip, including PCMCIA and USB Bluetooth devices based on CSR BlueCore chip, including PCMCIA and
CF cards. CF cards.
Say Y here to compile support for HCI BCSP protocol. 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 config BT_HCIDTL1
tristate "HCI DTL1 (PC Card) driver" tristate "HCI DTL1 (PC Card) driver"
depends on PCMCIA && BT depends on PCMCIA && BT
...@@ -64,8 +72,8 @@ config BT_HCIDTL1 ...@@ -64,8 +72,8 @@ config BT_HCIDTL1
Bluetooth HCI DTL1 (PC Card) driver. Bluetooth HCI DTL1 (PC Card) driver.
This driver provides support for Bluetooth PCMCIA devices with This driver provides support for Bluetooth PCMCIA devices with
Nokia DTL1 interface: Nokia DTL1 interface:
Nokia Bluetooth Card Nokia Bluetooth Card
Socket Bluetooth CF Card Socket Bluetooth CF Card
Say Y here to compile support for HCI DTL1 devices into the Say Y here to compile support for HCI DTL1 devices into the
kernel or say M to compile it as module (dtl1_cs.o). kernel or say M to compile it as module (dtl1_cs.o).
...@@ -73,12 +81,12 @@ config BT_HCIDTL1 ...@@ -73,12 +81,12 @@ config BT_HCIDTL1
config BT_HCIBT3C config BT_HCIBT3C
tristate "HCI BT3C (PC Card) driver" tristate "HCI BT3C (PC Card) driver"
depends on PCMCIA && BT depends on PCMCIA && BT
---help--- help
Bluetooth HCI BT3C (PC Card) driver. Bluetooth HCI BT3C (PC Card) driver.
This driver provides support for Bluetooth PCMCIA devices with This driver provides support for Bluetooth PCMCIA devices with
3Com BT3C interface: 3Com BT3C interface:
3Com Bluetooth Card (3CRWB6096) 3Com Bluetooth Card (3CRWB6096)
HP Bluetooth Card HP Bluetooth Card
The HCI BT3C driver uses external firmware loader program provided in The HCI BT3C driver uses external firmware loader program provided in
the BlueFW package. For more information, see <http://bluez.sf.net>. the BlueFW package. For more information, see <http://bluez.sf.net>.
...@@ -93,12 +101,28 @@ config BT_HCIBLUECARD ...@@ -93,12 +101,28 @@ config BT_HCIBLUECARD
Bluetooth HCI BlueCard (PC Card) driver. Bluetooth HCI BlueCard (PC Card) driver.
This driver provides support for Bluetooth PCMCIA devices with This driver provides support for Bluetooth PCMCIA devices with
Anycom BlueCard interface: Anycom BlueCard interface:
Anycom Bluetooth PC Card Anycom Bluetooth PC Card
Anycom Bluetooth CF Card Anycom Bluetooth CF Card
Say Y here to compile support for HCI BlueCard devices into the Say Y here to compile support for HCI BlueCard devices into the
kernel or say M to compile it as module (bluecard_cs.o). 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 config BT_HCIVHCI
tristate "HCI VHCI (Virtual HCI device) driver" tristate "HCI VHCI (Virtual HCI device) driver"
depends on BT depends on BT
......
...@@ -8,6 +8,7 @@ obj-$(CONFIG_BT_HCIUART) += hci_uart.o ...@@ -8,6 +8,7 @@ obj-$(CONFIG_BT_HCIUART) += hci_uart.o
obj-$(CONFIG_BT_HCIDTL1) += dtl1_cs.o obj-$(CONFIG_BT_HCIDTL1) += dtl1_cs.o
obj-$(CONFIG_BT_HCIBT3C) += bt3c_cs.o obj-$(CONFIG_BT_HCIBT3C) += bt3c_cs.o
obj-$(CONFIG_BT_HCIBLUECARD) += bluecard_cs.o obj-$(CONFIG_BT_HCIBLUECARD) += bluecard_cs.o
obj-$(CONFIG_BT_HCIBTUART) += btuart_cs.o
hci_uart-y := hci_ldisc.o hci_uart-y := hci_ldisc.o
hci_uart-$(CONFIG_BT_HCIUART_H4) += hci_h4.o hci_uart-$(CONFIG_BT_HCIUART_H4) += hci_h4.o
......
...@@ -789,6 +789,8 @@ int bluecard_open(bluecard_info_t *info) ...@@ -789,6 +789,8 @@ int bluecard_open(bluecard_info_t *info)
hdev->destruct = bluecard_hci_destruct; hdev->destruct = bluecard_hci_destruct;
hdev->ioctl = bluecard_hci_ioctl; hdev->ioctl = bluecard_hci_ioctl;
hdev->owner = THIS_MODULE;
if (hci_register_dev(hdev) < 0) { if (hci_register_dev(hdev) < 0) {
printk(KERN_WARNING "bluecard_cs: Can't register HCI device %s.\n", hdev->name); printk(KERN_WARNING "bluecard_cs: Can't register HCI device %s.\n", hdev->name);
return -ENODEV; return -ENODEV;
...@@ -1002,8 +1004,6 @@ void bluecard_config(dev_link_t *link) ...@@ -1002,8 +1004,6 @@ void bluecard_config(dev_link_t *link)
goto failed; goto failed;
} }
MOD_INC_USE_COUNT;
if (bluecard_open(info) != 0) if (bluecard_open(info) != 0)
goto failed; goto failed;
...@@ -1029,8 +1029,6 @@ void bluecard_release(u_long arg) ...@@ -1029,8 +1029,6 @@ void bluecard_release(u_long arg)
if (link->state & DEV_PRESENT) if (link->state & DEV_PRESENT)
bluecard_close(info); bluecard_close(info);
MOD_DEC_USE_COUNT;
link->dev = NULL; link->dev = NULL;
CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseConfiguration, link->handle);
......
...@@ -593,6 +593,8 @@ int bt3c_open(bt3c_info_t *info) ...@@ -593,6 +593,8 @@ int bt3c_open(bt3c_info_t *info)
hdev->destruct = bt3c_hci_destruct; hdev->destruct = bt3c_hci_destruct;
hdev->ioctl = bt3c_hci_ioctl; hdev->ioctl = bt3c_hci_ioctl;
hdev->owner = THIS_MODULE;
if (hci_register_dev(hdev) < 0) { if (hci_register_dev(hdev) < 0) {
printk(KERN_WARNING "bt3c_cs: Can't register HCI device %s.\n", hdev->name); printk(KERN_WARNING "bt3c_cs: Can't register HCI device %s.\n", hdev->name);
return -ENODEV; return -ENODEV;
...@@ -835,8 +837,6 @@ void bt3c_config(dev_link_t *link) ...@@ -835,8 +837,6 @@ void bt3c_config(dev_link_t *link)
goto failed; goto failed;
} }
MOD_INC_USE_COUNT;
if (bt3c_open(info) != 0) if (bt3c_open(info) != 0)
goto failed; goto failed;
...@@ -862,8 +862,6 @@ void bt3c_release(u_long arg) ...@@ -862,8 +862,6 @@ void bt3c_release(u_long arg)
if (link->state & DEV_PRESENT) if (link->state & DEV_PRESENT)
bt3c_close(info); bt3c_close(info);
MOD_DEC_USE_COUNT;
link->dev = NULL; link->dev = NULL;
CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseConfiguration, link->handle);
......
This diff is collapsed.
...@@ -520,6 +520,8 @@ int dtl1_open(dtl1_info_t *info) ...@@ -520,6 +520,8 @@ int dtl1_open(dtl1_info_t *info)
hdev->destruct = dtl1_hci_destruct; hdev->destruct = dtl1_hci_destruct;
hdev->ioctl = dtl1_hci_ioctl; hdev->ioctl = dtl1_hci_ioctl;
hdev->owner = THIS_MODULE;
if (hci_register_dev(hdev) < 0) { if (hci_register_dev(hdev) < 0) {
printk(KERN_WARNING "dtl1_cs: Can't register HCI device %s.\n", hdev->name); printk(KERN_WARNING "dtl1_cs: Can't register HCI device %s.\n", hdev->name);
return -ENODEV; return -ENODEV;
...@@ -747,8 +749,6 @@ void dtl1_config(dev_link_t *link) ...@@ -747,8 +749,6 @@ void dtl1_config(dev_link_t *link)
goto failed; goto failed;
} }
MOD_INC_USE_COUNT;
if (dtl1_open(info) != 0) if (dtl1_open(info) != 0)
goto failed; goto failed;
...@@ -774,8 +774,6 @@ void dtl1_release(u_long arg) ...@@ -774,8 +774,6 @@ void dtl1_release(u_long arg)
if (link->state & DEV_PRESENT) if (link->state & DEV_PRESENT)
dtl1_close(info); dtl1_close(info);
MOD_DEC_USE_COUNT;
link->dev = NULL; link->dev = NULL;
CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseConfiguration, link->handle);
......
...@@ -250,8 +250,6 @@ static void hci_uart_destruct(struct hci_dev *hdev) ...@@ -250,8 +250,6 @@ static void hci_uart_destruct(struct hci_dev *hdev)
hu = (struct hci_uart *) hdev->driver_data; hu = (struct hci_uart *) hdev->driver_data;
kfree(hu); kfree(hu);
MOD_DEC_USE_COUNT;
} }
/* ------ LDISC part ------ */ /* ------ LDISC part ------ */
...@@ -290,8 +288,7 @@ static int hci_uart_tty_open(struct tty_struct *tty) ...@@ -290,8 +288,7 @@ static int hci_uart_tty_open(struct tty_struct *tty)
if (tty->driver.flush_buffer) if (tty->driver.flush_buffer)
tty->driver.flush_buffer(tty); tty->driver.flush_buffer(tty);
MOD_INC_USE_COUNT;
return 0; return 0;
} }
...@@ -317,8 +314,6 @@ static void hci_uart_tty_close(struct tty_struct *tty) ...@@ -317,8 +314,6 @@ static void hci_uart_tty_close(struct tty_struct *tty)
hu->proto->close(hu); hu->proto->close(hu);
hci_unregister_dev(hdev); hci_unregister_dev(hdev);
} }
MOD_DEC_USE_COUNT;
} }
} }
...@@ -411,11 +406,13 @@ static int hci_uart_register_dev(struct hci_uart *hu) ...@@ -411,11 +406,13 @@ static int hci_uart_register_dev(struct hci_uart *hu)
hdev->send = hci_uart_send_frame; hdev->send = hci_uart_send_frame;
hdev->destruct = hci_uart_destruct; hdev->destruct = hci_uart_destruct;
hdev->owner = THIS_MODULE;
if (hci_register_dev(hdev) < 0) { if (hci_register_dev(hdev) < 0) {
BT_ERR("Can't register HCI device %s", hdev->name); BT_ERR("Can't register HCI device %s", hdev->name);
return -ENODEV; return -ENODEV;
} }
MOD_INC_USE_COUNT;
return 0; return 0;
} }
......
...@@ -207,18 +207,15 @@ static int hci_usb_open(struct hci_dev *hdev) ...@@ -207,18 +207,15 @@ static int hci_usb_open(struct hci_dev *hdev)
if (test_and_set_bit(HCI_RUNNING, &hdev->flags)) if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
return 0; return 0;
MOD_INC_USE_COUNT;
write_lock_irqsave(&husb->completion_lock, flags); write_lock_irqsave(&husb->completion_lock, flags);
err = hci_usb_enable_intr(husb); err = hci_usb_enable_intr(husb);
if (!err) { if (!err) {
for (i = 0; i < HCI_MAX_BULK_RX; i++) for (i = 0; i < HCI_MAX_BULK_RX; i++)
hci_usb_rx_submit(husb, NULL); hci_usb_rx_submit(husb, NULL);
} else { } else
clear_bit(HCI_RUNNING, &hdev->flags); clear_bit(HCI_RUNNING, &hdev->flags);
MOD_DEC_USE_COUNT;
}
write_unlock_irqrestore(&husb->completion_lock, flags); write_unlock_irqrestore(&husb->completion_lock, flags);
return err; return err;
...@@ -271,8 +268,6 @@ static int hci_usb_close(struct hci_dev *hdev) ...@@ -271,8 +268,6 @@ static int hci_usb_close(struct hci_dev *hdev)
hci_usb_flush(hdev); hci_usb_flush(hdev);
write_unlock_irqrestore(&husb->completion_lock, flags); write_unlock_irqrestore(&husb->completion_lock, flags);
MOD_DEC_USE_COUNT;
return 0; return 0;
} }
...@@ -758,6 +753,8 @@ int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) ...@@ -758,6 +753,8 @@ int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
hdev->send = hci_usb_send_frame; hdev->send = hci_usb_send_frame;
hdev->destruct = hci_usb_destruct; hdev->destruct = hci_usb_destruct;
hdev->owner = THIS_MODULE;
if (hci_register_dev(hdev) < 0) { if (hci_register_dev(hdev) < 0) {
BT_ERR("Can't register HCI device"); BT_ERR("Can't register HCI device");
goto probe_error; goto probe_error;
......
...@@ -84,8 +84,6 @@ static void hci_vhci_destruct(struct hci_dev *hdev) ...@@ -84,8 +84,6 @@ static void hci_vhci_destruct(struct hci_dev *hdev)
vhci = (struct hci_vhci_struct *) hdev->driver_data; vhci = (struct hci_vhci_struct *) hdev->driver_data;
kfree(vhci); kfree(vhci);
MOD_DEC_USE_COUNT;
} }
static int hci_vhci_send_frame(struct sk_buff *skb) static int hci_vhci_send_frame(struct sk_buff *skb)
...@@ -288,11 +286,12 @@ static int hci_vhci_chr_open(struct inode *inode, struct file * file) ...@@ -288,11 +286,12 @@ static int hci_vhci_chr_open(struct inode *inode, struct file * file)
hdev->send = hci_vhci_send_frame; hdev->send = hci_vhci_send_frame;
hdev->destruct = hci_vhci_destruct; hdev->destruct = hci_vhci_destruct;
hdev->owner = THIS_MODULE;
if (hci_register_dev(hdev) < 0) { if (hci_register_dev(hdev) < 0) {
kfree(hci_vhci); kfree(hci_vhci);
return -EBUSY; return -EBUSY;
} }
MOD_INC_USE_COUNT;
file->private_data = hci_vhci; file->private_data = hci_vhci;
return 0; return 0;
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#define HCI_PCCARD 2 #define HCI_PCCARD 2
#define HCI_UART 3 #define HCI_UART 3
#define HCI_RS232 4 #define HCI_RS232 4
#define HCI_PCI 5
/* HCI device flags */ /* HCI device flags */
enum { enum {
......
...@@ -118,6 +118,8 @@ struct hci_dev { ...@@ -118,6 +118,8 @@ struct hci_dev {
struct proc_dir_entry *proc; struct proc_dir_entry *proc;
#endif #endif
struct module *owner;
int (*open)(struct hci_dev *hdev); int (*open)(struct hci_dev *hdev);
int (*close)(struct hci_dev *hdev); int (*close)(struct hci_dev *hdev);
int (*flush)(struct hci_dev *hdev); int (*flush)(struct hci_dev *hdev);
...@@ -299,12 +301,30 @@ static inline void hci_sched_tx(struct hci_dev *hdev) ...@@ -299,12 +301,30 @@ static inline void hci_sched_tx(struct hci_dev *hdev)
} }
/* ----- HCI Devices ----- */ /* ----- HCI Devices ----- */
static inline void hci_dev_put(struct hci_dev *d) static inline void __hci_dev_put(struct hci_dev *d)
{ {
if (atomic_dec_and_test(&d->refcnt)) if (atomic_dec_and_test(&d->refcnt))
d->destruct(d); d->destruct(d);
} }
#define hci_dev_hold(d) atomic_inc(&d->refcnt)
static inline void hci_dev_put(struct hci_dev *d)
{
__hci_dev_put(d);
module_put(d->owner);
}
static inline struct hci_dev *__hci_dev_hold(struct hci_dev *d)
{
atomic_inc(&d->refcnt);
return d;
}
static inline struct hci_dev *hci_dev_hold(struct hci_dev *d)
{
if (try_module_get(d->owner))
return __hci_dev_hold(d);
return NULL;
}
#define hci_dev_lock(d) spin_lock(&d->lock) #define hci_dev_lock(d) spin_lock(&d->lock)
#define hci_dev_unlock(d) spin_unlock(&d->lock) #define hci_dev_unlock(d) spin_unlock(&d->lock)
......
...@@ -224,6 +224,8 @@ struct l2cap_pinfo { ...@@ -224,6 +224,8 @@ struct l2cap_pinfo {
__u8 ident; __u8 ident;
__u16 sport;
struct l2cap_conn *conn; struct l2cap_conn *conn;
struct sock *next_c; struct sock *next_c;
struct sock *prev_c; struct sock *prev_c;
......
...@@ -7,7 +7,7 @@ menu "Bluetooth support" ...@@ -7,7 +7,7 @@ menu "Bluetooth support"
config BT config BT
tristate "Bluetooth subsystem support" tristate "Bluetooth subsystem support"
---help--- help
Bluetooth is low-cost, low-power, short-range wireless technology. Bluetooth is low-cost, low-power, short-range wireless technology.
It was designed as a replacement for cables and other short-range It was designed as a replacement for cables and other short-range
technologies like IrDA. Bluetooth operates in personal area range technologies like IrDA. Bluetooth operates in personal area range
...@@ -15,12 +15,12 @@ config BT ...@@ -15,12 +15,12 @@ config BT
Bluetooth can be found at <http://www.bluetooth.com/>. Bluetooth can be found at <http://www.bluetooth.com/>.
Linux Bluetooth subsystem consist of several layers: Linux Bluetooth subsystem consist of several layers:
Bluetooth Core (HCI device and connection manager, scheduler) Bluetooth Core (HCI device and connection manager, scheduler)
HCI Device drivers (interface to the hardware) HCI Device drivers (interface to the hardware)
L2CAP Module (L2CAP protocol) L2CAP Module (L2CAP protocol)
SCO Module (SCO links) SCO Module (SCO links)
RFCOMM Module (RFCOMM protocol) RFCOMM Module (RFCOMM protocol)
BNEP Module (BNEP protocol) BNEP Module (BNEP protocol)
Say Y here to enable Linux Bluetooth support and to build Bluetooth Core Say Y here to enable Linux Bluetooth support and to build Bluetooth Core
layer. layer.
......
config BT_BNEP config BT_BNEP
tristate "BNEP protocol support" tristate "BNEP protocol support"
depends on BT_L2CAP depends on BT && BT_L2CAP
---help--- help
BNEP (Bluetooth Network Encapsulation Protocol) is Ethernet BNEP (Bluetooth Network Encapsulation Protocol) is Ethernet
emulation layer on top of Bluetooth. BNEP is required for Bluetooth emulation layer on top of Bluetooth. BNEP is required for Bluetooth
PAN (Personal Area Network). PAN (Personal Area Network).
......
...@@ -111,25 +111,25 @@ struct bnep_ext_hdr { ...@@ -111,25 +111,25 @@ struct bnep_ext_hdr {
__u8 data[0]; __u8 data[0];
} __attribute__((packed)); } __attribute__((packed));
// Ioctl interface /* BNEP ioctl defines */
#define BNEPCONADD 1 #define BNEPCONNADD _IOW('B', 200, int)
#define BNEPCONDEL 2 #define BNEPCONNDEL _IOW('B', 201, int)
#define BNEPGETCONLIST 3 #define BNEPGETCONNLIST _IOR('B', 210, int)
#define BNEPGETCONINFO 4 #define BNEPGETCONNINFO _IOR('B', 211, int)
struct bnep_conadd_req { struct bnep_connadd_req {
int sock; // Connected socket int sock; // Connected socket
__u32 flags; __u32 flags;
__u16 role; __u16 role;
char device[16]; // Name of the Ethernet device char device[16]; // Name of the Ethernet device
}; };
struct bnep_condel_req { struct bnep_conndel_req {
__u32 flags; __u32 flags;
__u8 dst[ETH_ALEN]; __u8 dst[ETH_ALEN];
}; };
struct bnep_coninfo { struct bnep_conninfo {
__u32 flags; __u32 flags;
__u16 role; __u16 role;
__u16 state; __u16 state;
...@@ -137,9 +137,9 @@ struct bnep_coninfo { ...@@ -137,9 +137,9 @@ struct bnep_coninfo {
char device[16]; char device[16];
}; };
struct bnep_conlist_req { struct bnep_connlist_req {
__u32 cnum; __u32 cnum;
struct bnep_coninfo *ci; struct bnep_conninfo *ci;
}; };
struct bnep_proto_filter { struct bnep_proto_filter {
...@@ -147,10 +147,10 @@ struct bnep_proto_filter { ...@@ -147,10 +147,10 @@ struct bnep_proto_filter {
__u16 end; __u16 end;
}; };
int bnep_add_connection(struct bnep_conadd_req *req, struct socket *sock); int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock);
int bnep_del_connection(struct bnep_condel_req *req); int bnep_del_connection(struct bnep_conndel_req *req);
int bnep_get_conlist(struct bnep_conlist_req *req); int bnep_get_connlist(struct bnep_connlist_req *req);
int bnep_get_coninfo(struct bnep_coninfo *ci); int bnep_get_conninfo(struct bnep_conninfo *ci);
// BNEP sessions // BNEP sessions
struct bnep_session { struct bnep_session {
......
...@@ -128,18 +128,17 @@ static int bnep_send_rsp(struct bnep_session *s, u8 ctrl, u16 resp) ...@@ -128,18 +128,17 @@ static int bnep_send_rsp(struct bnep_session *s, u8 ctrl, u16 resp)
return bnep_send(s, &rsp, sizeof(rsp)); 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; int n;
data = (void *) skb->data; if (len < 2)
if (!skb_pull(skb, 2))
return -EILSEQ; return -EILSEQ;
n = ntohs(get_unaligned(data)); n = ntohs(get_unaligned(data));
data++; len -= 2;
data = (void *) skb->data; if (len < n)
if (!skb_pull(skb, n))
return -EILSEQ; return -EILSEQ;
BT_DBG("filter len %d", n); BT_DBG("filter len %d", n);
...@@ -170,18 +169,17 @@ static int bnep_ctrl_set_netfilter(struct bnep_session *s, struct sk_buff *skb) ...@@ -170,18 +169,17 @@ static int bnep_ctrl_set_netfilter(struct bnep_session *s, struct sk_buff *skb)
return 0; 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; int n;
data = (void *) skb->data; if (len < 2)
if (!skb_pull(skb, 2))
return -EILSEQ; return -EILSEQ;
n = ntohs(get_unaligned((u16 *) data));
data = (void *) skb->data; n = ntohs(get_unaligned((u16 *) data));
if (!skb_pull(skb, n)) data += 2; len -= 2;
if (len < n)
return -EILSEQ; return -EILSEQ;
BT_DBG("filter len %d", n); BT_DBG("filter len %d", n);
...@@ -225,12 +223,13 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, struct sk_buff *skb) ...@@ -225,12 +223,13 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, struct sk_buff *skb)
return 0; 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; int err = 0;
u8 cmd = *(u8 *) skb->data;
skb_pull(skb, 1); data++; len--;
switch (cmd) { switch (cmd) {
case BNEP_CMD_NOT_UNDERSTOOD: case BNEP_CMD_NOT_UNDERSTOOD:
case BNEP_SETUP_CONN_REQ: case BNEP_SETUP_CONN_REQ:
...@@ -239,13 +238,13 @@ static int bnep_rx_control(struct bnep_session *s, struct sk_buff *skb) ...@@ -239,13 +238,13 @@ static int bnep_rx_control(struct bnep_session *s, struct sk_buff *skb)
case BNEP_FILTER_MULTI_ADDR_RSP: case BNEP_FILTER_MULTI_ADDR_RSP:
/* Ignore these for now */ /* Ignore these for now */
break; break;
case BNEP_FILTER_NET_TYPE_SET: case BNEP_FILTER_NET_TYPE_SET:
err = bnep_ctrl_set_netfilter(s, skb); err = bnep_ctrl_set_netfilter(s, data, len);
break; break;
case BNEP_FILTER_MULTI_ADDR_SET: case BNEP_FILTER_MULTI_ADDR_SET:
err = bnep_ctrl_set_mcfilter(s, skb); err = bnep_ctrl_set_mcfilter(s, data, len);
break; break;
default: { default: {
...@@ -274,16 +273,19 @@ static int bnep_rx_extension(struct bnep_session *s, struct sk_buff *skb) ...@@ -274,16 +273,19 @@ static int bnep_rx_extension(struct bnep_session *s, struct sk_buff *skb)
} }
BT_DBG("type 0x%x len %d", h->type, h->len); BT_DBG("type 0x%x len %d", h->type, h->len);
switch (h->type & BNEP_TYPE_MASK) { switch (h->type & BNEP_TYPE_MASK) {
case BNEP_EXT_CONTROL: case BNEP_EXT_CONTROL:
err = bnep_rx_control(s, skb); bnep_rx_control(s, skb->data, skb->len);
break; break;
default: default:
/* Unknown extension */ /* Unknown extension, skip it. */
if (!skb_pull(skb, h->len)) break;
err = -EILSEQ; }
if (!skb_pull(skb, h->len)) {
err = -EILSEQ;
break; break;
} }
} while (!err && (h->type & BNEP_EXT_HEADER)); } while (!err && (h->type & BNEP_EXT_HEADER));
...@@ -315,7 +317,7 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb) ...@@ -315,7 +317,7 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
goto badframe; goto badframe;
if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) { if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) {
bnep_rx_control(s, skb); bnep_rx_control(s, skb->data, skb->len);
kfree_skb(skb); kfree_skb(skb);
return 0; return 0;
} }
...@@ -529,7 +531,7 @@ static int bnep_session(void *arg) ...@@ -529,7 +531,7 @@ static int bnep_session(void *arg)
return 0; return 0;
} }
int bnep_add_connection(struct bnep_conadd_req *req, struct socket *sock) int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
{ {
struct net_device *dev; struct net_device *dev;
struct bnep_session *s, *ss; struct bnep_session *s, *ss;
...@@ -620,7 +622,7 @@ int bnep_add_connection(struct bnep_conadd_req *req, struct socket *sock) ...@@ -620,7 +622,7 @@ int bnep_add_connection(struct bnep_conadd_req *req, struct socket *sock)
return err; return err;
} }
int bnep_del_connection(struct bnep_condel_req *req) int bnep_del_connection(struct bnep_conndel_req *req)
{ {
struct bnep_session *s; struct bnep_session *s;
int err = 0; int err = 0;
...@@ -645,7 +647,7 @@ int bnep_del_connection(struct bnep_condel_req *req) ...@@ -645,7 +647,7 @@ int bnep_del_connection(struct bnep_condel_req *req)
return err; return err;
} }
static void __bnep_copy_ci(struct bnep_coninfo *ci, struct bnep_session *s) static void __bnep_copy_ci(struct bnep_conninfo *ci, struct bnep_session *s)
{ {
memcpy(ci->dst, s->eh.h_source, ETH_ALEN); memcpy(ci->dst, s->eh.h_source, ETH_ALEN);
strcpy(ci->device, s->dev.name); strcpy(ci->device, s->dev.name);
...@@ -654,7 +656,7 @@ static void __bnep_copy_ci(struct bnep_coninfo *ci, struct bnep_session *s) ...@@ -654,7 +656,7 @@ static void __bnep_copy_ci(struct bnep_coninfo *ci, struct bnep_session *s)
ci->role = s->role; ci->role = s->role;
} }
int bnep_get_conlist(struct bnep_conlist_req *req) int bnep_get_connlist(struct bnep_connlist_req *req)
{ {
struct list_head *p; struct list_head *p;
int err = 0, n = 0; int err = 0, n = 0;
...@@ -663,7 +665,7 @@ int bnep_get_conlist(struct bnep_conlist_req *req) ...@@ -663,7 +665,7 @@ int bnep_get_conlist(struct bnep_conlist_req *req)
list_for_each(p, &bnep_session_list) { list_for_each(p, &bnep_session_list) {
struct bnep_session *s; struct bnep_session *s;
struct bnep_coninfo ci; struct bnep_conninfo ci;
s = list_entry(p, struct bnep_session, list); s = list_entry(p, struct bnep_session, list);
...@@ -685,7 +687,7 @@ int bnep_get_conlist(struct bnep_conlist_req *req) ...@@ -685,7 +687,7 @@ int bnep_get_conlist(struct bnep_conlist_req *req)
return err; return err;
} }
int bnep_get_coninfo(struct bnep_coninfo *ci) int bnep_get_conninfo(struct bnep_conninfo *ci)
{ {
struct bnep_session *s; struct bnep_session *s;
int err = 0; int err = 0;
......
...@@ -73,17 +73,17 @@ static int bnep_sock_release(struct socket *sock) ...@@ -73,17 +73,17 @@ static int bnep_sock_release(struct socket *sock)
static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{ {
struct bnep_conlist_req cl; struct bnep_connlist_req cl;
struct bnep_conadd_req ca; struct bnep_connadd_req ca;
struct bnep_condel_req cd; struct bnep_conndel_req cd;
struct bnep_coninfo ci; struct bnep_conninfo ci;
struct socket *nsock; struct socket *nsock;
int err; int err;
BT_DBG("cmd %x arg %lx", cmd, arg); BT_DBG("cmd %x arg %lx", cmd, arg);
switch (cmd) { switch (cmd) {
case BNEPCONADD: case BNEPCONNADD:
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN))
return -EACCES; return -EACCES;
...@@ -106,7 +106,7 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long ...@@ -106,7 +106,7 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
return err; return err;
case BNEPCONDEL: case BNEPCONNDEL:
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN))
return -EACCES; return -EACCES;
...@@ -115,24 +115,24 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long ...@@ -115,24 +115,24 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
return bnep_del_connection(&cd); return bnep_del_connection(&cd);
case BNEPGETCONLIST: case BNEPGETCONNLIST:
if (copy_from_user(&cl, (void *) arg, sizeof(cl))) if (copy_from_user(&cl, (void *) arg, sizeof(cl)))
return -EFAULT; return -EFAULT;
if (cl.cnum <= 0) if (cl.cnum <= 0)
return -EINVAL; return -EINVAL;
err = bnep_get_conlist(&cl); err = bnep_get_connlist(&cl);
if (!err && copy_to_user((void *) arg, &cl, sizeof(cl))) if (!err && copy_to_user((void *) arg, &cl, sizeof(cl)))
return -EFAULT; return -EFAULT;
return err; return err;
case BNEPGETCONINFO: case BNEPGETCONNINFO:
if (copy_from_user(&ci, (void *) arg, sizeof(ci))) if (copy_from_user(&ci, (void *) arg, sizeof(ci)))
return -EFAULT; return -EFAULT;
err = bnep_get_coninfo(&ci); err = bnep_get_conninfo(&ci);
if (!err && copy_to_user((void *) arg, &ci, sizeof(ci))) if (!err && copy_to_user((void *) arg, &ci, sizeof(ci)))
return -EFAULT; return -EFAULT;
......
...@@ -218,8 +218,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) ...@@ -218,8 +218,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
read_lock_bh(&hci_dev_list_lock); read_lock_bh(&hci_dev_list_lock);
list_for_each(p, &hci_dev_list) { list_for_each(p, &hci_dev_list) {
struct hci_dev *d; struct hci_dev *d = list_entry(p, struct hci_dev, list);
d = list_entry(p, struct hci_dev, list);
if (!test_bit(HCI_UP, &d->flags)) if (!test_bit(HCI_UP, &d->flags))
continue; continue;
...@@ -241,7 +240,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) ...@@ -241,7 +240,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
} }
if (hdev) if (hdev)
hci_dev_hold(hdev); hdev = hci_dev_hold(hdev);
read_unlock_bh(&hci_dev_list_lock); read_unlock_bh(&hci_dev_list_lock);
return hdev; return hdev;
......
...@@ -287,10 +287,10 @@ static void hci_encrypt_req(struct hci_dev *hdev, unsigned long opt) ...@@ -287,10 +287,10 @@ static void hci_encrypt_req(struct hci_dev *hdev, unsigned long opt)
} }
/* Get HCI device by index. /* Get HCI device by index.
* Device is locked on return. */ * Device is held on return. */
struct hci_dev *hci_dev_get(int index) struct hci_dev *hci_dev_get(int index)
{ {
struct hci_dev *hdev; struct hci_dev *hdev = NULL;
struct list_head *p; struct list_head *p;
BT_DBG("%d", index); BT_DBG("%d", index);
...@@ -300,14 +300,12 @@ struct hci_dev *hci_dev_get(int index) ...@@ -300,14 +300,12 @@ struct hci_dev *hci_dev_get(int index)
read_lock(&hci_dev_list_lock); read_lock(&hci_dev_list_lock);
list_for_each(p, &hci_dev_list) { list_for_each(p, &hci_dev_list) {
hdev = list_entry(p, struct hci_dev, list); struct hci_dev *d = list_entry(p, struct hci_dev, list);
if (hdev->id == index) { if (d->id == index) {
hci_dev_hold(hdev); hdev = hci_dev_hold(d);
goto done; break;
} }
} }
hdev = NULL;
done:
read_unlock(&hci_dev_list_lock); read_unlock(&hci_dev_list_lock);
return hdev; return hdev;
} }
...@@ -483,6 +481,7 @@ int hci_dev_open(__u16 dev) ...@@ -483,6 +481,7 @@ int hci_dev_open(__u16 dev)
} }
if (!ret) { if (!ret) {
hci_dev_hold(hdev);
set_bit(HCI_UP, &hdev->flags); set_bit(HCI_UP, &hdev->flags);
hci_notify(hdev, HCI_DEV_UP); hci_notify(hdev, HCI_DEV_UP);
} else { } else {
...@@ -567,6 +566,8 @@ static int hci_dev_do_close(struct hci_dev *hdev) ...@@ -567,6 +566,8 @@ static int hci_dev_do_close(struct hci_dev *hdev)
hdev->flags = 0; hdev->flags = 0;
hci_req_unlock(hdev); hci_req_unlock(hdev);
hci_dev_put(hdev);
return 0; return 0;
} }
...@@ -718,7 +719,7 @@ int hci_get_dev_list(unsigned long arg) ...@@ -718,7 +719,7 @@ int hci_get_dev_list(unsigned long arg)
if (!dev_num) if (!dev_num)
return -EINVAL; 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)) if (verify_area(VERIFY_WRITE, (void *) arg, size))
return -EFAULT; return -EFAULT;
...@@ -739,7 +740,7 @@ int hci_get_dev_list(unsigned long arg) ...@@ -739,7 +740,7 @@ int hci_get_dev_list(unsigned long arg)
read_unlock_bh(&hci_dev_list_lock); read_unlock_bh(&hci_dev_list_lock);
dl->dev_num = n; 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); copy_to_user((void *) arg, dl, size);
kfree(dl); kfree(dl);
...@@ -790,7 +791,7 @@ int hci_register_dev(struct hci_dev *hdev) ...@@ -790,7 +791,7 @@ int hci_register_dev(struct hci_dev *hdev)
struct list_head *head = &hci_dev_list, *p; struct list_head *head = &hci_dev_list, *p;
int id = 0; int id = 0;
BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); BT_DBG("%p name %s type %d owner %p", hdev, hdev->name, hdev->type, hdev->owner);
if (!hdev->open || !hdev->close || !hdev->destruct) if (!hdev->open || !hdev->close || !hdev->destruct)
return -EINVAL; return -EINVAL;
...@@ -834,8 +835,6 @@ int hci_register_dev(struct hci_dev *hdev) ...@@ -834,8 +835,6 @@ int hci_register_dev(struct hci_dev *hdev)
atomic_set(&hdev->promisc, 0); atomic_set(&hdev->promisc, 0);
MOD_INC_USE_COUNT;
write_unlock_bh(&hci_dev_list_lock); write_unlock_bh(&hci_dev_list_lock);
hci_dev_proc_init(hdev); hci_dev_proc_init(hdev);
...@@ -862,9 +861,7 @@ int hci_unregister_dev(struct hci_dev *hdev) ...@@ -862,9 +861,7 @@ int hci_unregister_dev(struct hci_dev *hdev)
hci_notify(hdev, HCI_DEV_UNREG); hci_notify(hdev, HCI_DEV_UNREG);
hci_run_hotplug(hdev->name, "unregister"); hci_run_hotplug(hdev->name, "unregister");
hci_dev_put(hdev); __hci_dev_put(hdev);
MOD_DEC_USE_COUNT;
return 0; return 0;
} }
......
...@@ -73,7 +73,7 @@ static struct hci_sec_filter hci_sec_filter = { ...@@ -73,7 +73,7 @@ static struct hci_sec_filter hci_sec_filter = {
/* OGF_LINK_POLICY */ /* OGF_LINK_POLICY */
{ 0x1200, 0x0, 0x0, 0x0 }, { 0x1200, 0x0, 0x0, 0x0 },
/* OGF_HOST_CTL */ /* OGF_HOST_CTL */
{ 0x80100000, 0xa, 0x0, 0x0 }, { 0x80100000, 0x2a, 0x0, 0x0 },
/* OGF_INFO_PARAM */ /* OGF_INFO_PARAM */
{ 0x22a, 0x0, 0x0, 0x0 } { 0x22a, 0x0, 0x0, 0x0 }
} }
......
...@@ -186,69 +186,12 @@ static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, stru ...@@ -186,69 +186,12 @@ static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, stru
write_unlock(&l->lock); 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 ---- */ /* ---- Socket interface ---- */
static struct sock *__l2cap_get_sock_by_addr(u16 psm, bdaddr_t *src) static struct sock *__l2cap_get_sock_by_addr(u16 psm, bdaddr_t *src)
{ {
struct sock *sk; struct sock *sk;
for (sk = l2cap_sk_list.head; sk; sk = sk->next) { for (sk = l2cap_sk_list.head; sk; sk = sk->next) {
if (l2cap_pi(sk)->psm == psm && if (l2cap_pi(sk)->sport == psm && !bacmp(&bt_sk(sk)->src, src))
!bacmp(&bt_sk(sk)->src, src))
break; break;
} }
return sk; return sk;
...@@ -437,7 +380,10 @@ static int l2cap_sock_create(struct socket *sock, int protocol) ...@@ -437,7 +380,10 @@ static int l2cap_sock_create(struct socket *sock, int protocol)
if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_DGRAM && sock->type != SOCK_RAW) if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_DGRAM && sock->type != SOCK_RAW)
return -ESOCKTNOSUPPORT; return -ESOCKTNOSUPPORT;
if (sock->type == SOCK_RAW && !capable(CAP_NET_RAW))
return -EPERM;
sock->ops = &l2cap_sock_ops; sock->ops = &l2cap_sock_ops;
sk = l2cap_sock_alloc(sock, protocol, GFP_KERNEL); sk = l2cap_sock_alloc(sock, protocol, GFP_KERNEL);
...@@ -472,7 +418,8 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_ ...@@ -472,7 +418,8 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_
} else { } else {
/* Save source address */ /* Save source address */
bacpy(&bt_sk(sk)->src, &la->l2_bdaddr); bacpy(&bt_sk(sk)->src, &la->l2_bdaddr);
l2cap_pi(sk)->psm = la->l2_psm; l2cap_pi(sk)->psm = la->l2_psm;
l2cap_pi(sk)->sport = la->l2_psm;
sk->state = BT_BOUND; sk->state = BT_BOUND;
} }
write_unlock_bh(&l2cap_sk_list.lock); write_unlock_bh(&l2cap_sk_list.lock);
...@@ -482,6 +429,62 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_ ...@@ -482,6 +429,62 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_
return err; 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) static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
{ {
struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr; 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 ...@@ -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); bacpy(&bt_sk(sk)->dst, &la->l2_bdaddr);
l2cap_pi(sk)->psm = la->l2_psm; l2cap_pi(sk)->psm = la->l2_psm;
if ((err = l2cap_connect(sk))) if ((err = l2cap_do_connect(sk)))
goto done; goto done;
wait: wait:
...@@ -2074,7 +2077,7 @@ static int __init l2cap_proc_init(void) ...@@ -2074,7 +2077,7 @@ static int __init l2cap_proc_init(void)
static void __init l2cap_proc_cleanup(void) static void __init l2cap_proc_cleanup(void)
{ {
return 0; return;
} }
#endif /* CONFIG_PROC_FS */ #endif /* CONFIG_PROC_FS */
......
config BT_RFCOMM config BT_RFCOMM
tristate "RFCOMM protocol support" tristate "RFCOMM protocol support"
depends on BT_L2CAP depends on BT && BT_L2CAP
help help
RFCOMM provides connection oriented stream transport. RFCOMM RFCOMM provides connection oriented stream transport. RFCOMM
support is required for Dialup Networking, OBEX and other Bluetooth support is required for Dialup Networking, OBEX and other Bluetooth
......
...@@ -263,7 +263,7 @@ static void rfcomm_dlc_unlink(struct rfcomm_dlc *d) ...@@ -263,7 +263,7 @@ static void rfcomm_dlc_unlink(struct rfcomm_dlc *d)
rfcomm_session_put(s); rfcomm_session_put(s);
} }
static struct rfcomm_dlc *rfcomm_dlc_get(struct rfcomm_session *s, int dlci) static struct rfcomm_dlc *rfcomm_dlc_get(struct rfcomm_session *s, u8 dlci)
{ {
struct rfcomm_dlc *d; struct rfcomm_dlc *d;
struct list_head *p; struct list_head *p;
...@@ -279,7 +279,8 @@ static struct rfcomm_dlc *rfcomm_dlc_get(struct rfcomm_session *s, int dlci) ...@@ -279,7 +279,8 @@ static struct rfcomm_dlc *rfcomm_dlc_get(struct rfcomm_session *s, int dlci)
static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, u8 channel) static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, u8 channel)
{ {
struct rfcomm_session *s; struct rfcomm_session *s;
int err = 0, dlci = __dlci(0, channel); u8 dlci = __dlci(0, channel);
int err = 0;
BT_DBG("dlc %p state %ld %s %s channel %d dlci %d", BT_DBG("dlc %p state %ld %s %s channel %d dlci %d",
d, d->state, batostr(src), batostr(dst), channel, dlci); d, d->state, batostr(src), batostr(dst), channel, dlci);
...@@ -923,7 +924,7 @@ static void rfcomm_make_uih(struct sk_buff *skb, u8 addr) ...@@ -923,7 +924,7 @@ static void rfcomm_make_uih(struct sk_buff *skb, u8 addr)
} }
/* ---- RFCOMM frame reception ---- */ /* ---- RFCOMM frame reception ---- */
static int rfcomm_recv_ua(struct rfcomm_session *s, int dlci) static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci)
{ {
BT_DBG("session %p state %ld dlci %d", s, s->state, dlci); BT_DBG("session %p state %ld dlci %d", s, s->state, dlci);
...@@ -964,7 +965,7 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, int dlci) ...@@ -964,7 +965,7 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, int dlci)
return 0; return 0;
} }
static int rfcomm_recv_dm(struct rfcomm_session *s, int dlci) static int rfcomm_recv_dm(struct rfcomm_session *s, u8 dlci)
{ {
int err = 0; int err = 0;
...@@ -994,7 +995,7 @@ static int rfcomm_recv_dm(struct rfcomm_session *s, int dlci) ...@@ -994,7 +995,7 @@ static int rfcomm_recv_dm(struct rfcomm_session *s, int dlci)
return 0; return 0;
} }
static int rfcomm_recv_disc(struct rfcomm_session *s, int dlci) static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci)
{ {
int err = 0; int err = 0;
...@@ -1030,10 +1031,10 @@ static int rfcomm_recv_disc(struct rfcomm_session *s, int dlci) ...@@ -1030,10 +1031,10 @@ static int rfcomm_recv_disc(struct rfcomm_session *s, int dlci)
return 0; return 0;
} }
static int rfcomm_recv_sabm(struct rfcomm_session *s, int dlci) static int rfcomm_recv_sabm(struct rfcomm_session *s, u8 dlci)
{ {
struct rfcomm_dlc *d; struct rfcomm_dlc *d;
int channel; u8 channel;
BT_DBG("session %p state %ld dlci %d", s, s->state, dlci); BT_DBG("session %p state %ld dlci %d", s, s->state, dlci);
...@@ -1116,7 +1117,7 @@ static int rfcomm_recv_pn(struct rfcomm_session *s, int cr, struct sk_buff *skb) ...@@ -1116,7 +1117,7 @@ static int rfcomm_recv_pn(struct rfcomm_session *s, int cr, struct sk_buff *skb)
{ {
struct rfcomm_pn *pn = (void *) skb->data; struct rfcomm_pn *pn = (void *) skb->data;
struct rfcomm_dlc *d; struct rfcomm_dlc *d;
int dlci = pn->dlci; u8 dlci = pn->dlci;
BT_DBG("session %p state %ld dlci %d", s, s->state, dlci); BT_DBG("session %p state %ld dlci %d", s, s->state, dlci);
...@@ -1141,7 +1142,7 @@ static int rfcomm_recv_pn(struct rfcomm_session *s, int cr, struct sk_buff *skb) ...@@ -1141,7 +1142,7 @@ static int rfcomm_recv_pn(struct rfcomm_session *s, int cr, struct sk_buff *skb)
} }
} }
} else { } else {
int channel = __srv_channel(dlci); u8 channel = __srv_channel(dlci);
if (!cr) if (!cr)
return 0; return 0;
...@@ -1167,7 +1168,7 @@ static int rfcomm_recv_pn(struct rfcomm_session *s, int cr, struct sk_buff *skb) ...@@ -1167,7 +1168,7 @@ static int rfcomm_recv_pn(struct rfcomm_session *s, int cr, struct sk_buff *skb)
static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_buff *skb) static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_buff *skb)
{ {
struct rfcomm_rpn *rpn = (void *) skb->data; struct rfcomm_rpn *rpn = (void *) skb->data;
int dlci = __get_dlci(rpn->dlci); u8 dlci = __get_dlci(rpn->dlci);
u8 bit_rate = 0; u8 bit_rate = 0;
u8 data_bits = 0; u8 data_bits = 0;
...@@ -1257,7 +1258,7 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb ...@@ -1257,7 +1258,7 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb
{ {
struct rfcomm_msc *msc = (void *) skb->data; struct rfcomm_msc *msc = (void *) skb->data;
struct rfcomm_dlc *d; struct rfcomm_dlc *d;
int dlci = __get_dlci(msc->dlci); u8 dlci = __get_dlci(msc->dlci);
BT_DBG("dlci %d cr %d v24 0x%x", dlci, cr, msc->v24_sig); BT_DBG("dlci %d cr %d v24 0x%x", dlci, cr, msc->v24_sig);
...@@ -1312,6 +1313,9 @@ static int rfcomm_recv_mcc(struct rfcomm_session *s, struct sk_buff *skb) ...@@ -1312,6 +1313,9 @@ static int rfcomm_recv_mcc(struct rfcomm_session *s, struct sk_buff *skb)
rfcomm_send_test(s, 0, skb->data, skb->len); rfcomm_send_test(s, 0, skb->data, skb->len);
break; break;
case RFCOMM_NSC:
break;
default: default:
BT_ERR("Unknown control type 0x%02x", type); BT_ERR("Unknown control type 0x%02x", type);
rfcomm_send_nsc(s, cr, type); rfcomm_send_nsc(s, cr, type);
...@@ -1320,7 +1324,7 @@ static int rfcomm_recv_mcc(struct rfcomm_session *s, struct sk_buff *skb) ...@@ -1320,7 +1324,7 @@ static int rfcomm_recv_mcc(struct rfcomm_session *s, struct sk_buff *skb)
return 0; return 0;
} }
static int rfcomm_recv_data(struct rfcomm_session *s, int dlci, int pf, struct sk_buff *skb) static int rfcomm_recv_data(struct rfcomm_session *s, u8 dlci, int pf, struct sk_buff *skb)
{ {
struct rfcomm_dlc *d; struct rfcomm_dlc *d;
...@@ -1442,7 +1446,7 @@ static inline int rfcomm_process_tx(struct rfcomm_dlc *d) ...@@ -1442,7 +1446,7 @@ static inline int rfcomm_process_tx(struct rfcomm_dlc *d)
/* Send pending MSC */ /* Send pending MSC */
if (test_and_clear_bit(RFCOMM_MSC_PENDING, &d->flags)) 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) { if (d->credits) {
/* CFC enabled. /* CFC enabled.
...@@ -1831,7 +1835,7 @@ static int __init rfcomm_proc_init(void) ...@@ -1831,7 +1835,7 @@ static int __init rfcomm_proc_init(void)
static void __init rfcomm_proc_cleanup(void) static void __init rfcomm_proc_cleanup(void)
{ {
return 0; return;
} }
#endif /* CONFIG_PROC_FS */ #endif /* CONFIG_PROC_FS */
......
...@@ -112,7 +112,7 @@ static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err) ...@@ -112,7 +112,7 @@ static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err)
} }
/* ---- Socket functions ---- */ /* ---- Socket functions ---- */
static struct sock *__rfcomm_get_sock_by_addr(int channel, bdaddr_t *src) static struct sock *__rfcomm_get_sock_by_addr(u8 channel, bdaddr_t *src)
{ {
struct sock *sk; struct sock *sk;
...@@ -128,7 +128,7 @@ static struct sock *__rfcomm_get_sock_by_addr(int channel, bdaddr_t *src) ...@@ -128,7 +128,7 @@ static struct sock *__rfcomm_get_sock_by_addr(int channel, bdaddr_t *src)
/* Find socket with channel and source bdaddr. /* Find socket with channel and source bdaddr.
* Returns closest match. * Returns closest match.
*/ */
static struct sock *__rfcomm_get_sock_by_channel(int state, __u16 channel, bdaddr_t *src) static struct sock *__rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *src)
{ {
struct sock *sk, *sk1 = NULL; struct sock *sk, *sk1 = NULL;
...@@ -151,7 +151,7 @@ static struct sock *__rfcomm_get_sock_by_channel(int state, __u16 channel, bdadd ...@@ -151,7 +151,7 @@ static struct sock *__rfcomm_get_sock_by_channel(int state, __u16 channel, bdadd
/* Find socket with given address (channel, src). /* Find socket with given address (channel, src).
* Returns locked socket */ * Returns locked socket */
static inline struct sock *rfcomm_get_sock_by_channel(int state, __u16 channel, bdaddr_t *src) static inline struct sock *rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *src)
{ {
struct sock *s; struct sock *s;
read_lock(&rfcomm_sk_list.lock); read_lock(&rfcomm_sk_list.lock);
...@@ -851,7 +851,7 @@ static int __init rfcomm_sock_proc_init(void) ...@@ -851,7 +851,7 @@ static int __init rfcomm_sock_proc_init(void)
static void __init rfcomm_sock_proc_cleanup(void) static void __init rfcomm_sock_proc_cleanup(void)
{ {
return 0; return;
} }
#endif /* CONFIG_PROC_FS */ #endif /* CONFIG_PROC_FS */
......
...@@ -442,7 +442,7 @@ static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb) ...@@ -442,7 +442,7 @@ static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb)
struct tty_struct *tty; struct tty_struct *tty;
if (!dev || !(tty = dev->tty)) { if (!dev || !(tty = dev->tty)) {
kfree(skb); kfree_skb(skb);
return; return;
} }
...@@ -669,12 +669,12 @@ static int rfcomm_tty_set_modem_status(uint cmd, struct rfcomm_dlc *dlc, uint st ...@@ -669,12 +669,12 @@ static int rfcomm_tty_set_modem_status(uint cmd, struct rfcomm_dlc *dlc, uint st
else else
rfcomm_dlc_get_modem_status(dlc, &v24_sig); rfcomm_dlc_get_modem_status(dlc, &v24_sig);
mask = (status & TIOCM_DSR) ? RFCOMM_V24_RTC : 0 | mask = ((status & TIOCM_DSR) ? RFCOMM_V24_RTC : 0) |
(status & TIOCM_DTR) ? RFCOMM_V24_RTC : 0 | ((status & TIOCM_DTR) ? RFCOMM_V24_RTC : 0) |
(status & TIOCM_RTS) ? RFCOMM_V24_RTR : 0 | ((status & TIOCM_RTS) ? RFCOMM_V24_RTR : 0) |
(status & TIOCM_CTS) ? RFCOMM_V24_RTR : 0 | ((status & TIOCM_CTS) ? RFCOMM_V24_RTR : 0) |
(status & TIOCM_RI) ? RFCOMM_V24_IC : 0 | ((status & TIOCM_RI) ? RFCOMM_V24_IC : 0) |
(status & TIOCM_CD) ? RFCOMM_V24_DV : 0; ((status & TIOCM_CD) ? RFCOMM_V24_DV : 0);
if (cmd == TIOCMBIC) if (cmd == TIOCMBIC)
v24_sig &= ~mask; v24_sig &= ~mask;
...@@ -854,7 +854,7 @@ static struct tty_driver rfcomm_tty_driver = { ...@@ -854,7 +854,7 @@ static struct tty_driver rfcomm_tty_driver = {
#ifdef CONFIG_DEVFS_FS #ifdef CONFIG_DEVFS_FS
.name = "bluetooth/rfcomm/%d", .name = "bluetooth/rfcomm/%d",
#else #else
.name = "rfcomm%d", .name = "rfcomm",
#endif #endif
.major = RFCOMM_TTY_MAJOR, .major = RFCOMM_TTY_MAJOR,
.minor_start = RFCOMM_TTY_MINOR, .minor_start = RFCOMM_TTY_MINOR,
......
...@@ -698,7 +698,7 @@ int sco_sock_getsockopt(struct socket *sock, int level, int optname, char *optva ...@@ -698,7 +698,7 @@ int sco_sock_getsockopt(struct socket *sock, int level, int optname, char *optva
opts.mtu = sco_pi(sk)->conn->mtu; opts.mtu = sco_pi(sk)->conn->mtu;
BT_INFO("mtu %d", opts.mtu); BT_DBG("mtu %d", opts.mtu);
len = min_t(unsigned int, len, sizeof(opts)); len = min_t(unsigned int, len, sizeof(opts));
if (copy_to_user(optval, (char *)&opts, len)) if (copy_to_user(optval, (char *)&opts, len))
...@@ -962,7 +962,7 @@ static int __init sco_proc_init(void) ...@@ -962,7 +962,7 @@ static int __init sco_proc_init(void)
static void __init sco_proc_cleanup(void) static void __init sco_proc_cleanup(void)
{ {
return 0; return;
} }
#endif /* CONFIG_PROC_FS */ #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