Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/holtmann/bluetooth-2.6
This commit is contained in:
@ -51,7 +51,7 @@
|
||||
#define BT_DBG(D...)
|
||||
#endif
|
||||
|
||||
#define VERSION "1.8"
|
||||
#define VERSION "1.10"
|
||||
|
||||
static int disable_cfc = 0;
|
||||
static int channel_mtu = -1;
|
||||
@ -228,6 +228,21 @@ static int rfcomm_l2sock_create(struct socket **sock)
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline int rfcomm_check_link_mode(struct rfcomm_dlc *d)
|
||||
{
|
||||
struct sock *sk = d->session->sock->sk;
|
||||
|
||||
if (d->link_mode & (RFCOMM_LM_ENCRYPT | RFCOMM_LM_SECURE)) {
|
||||
if (!hci_conn_encrypt(l2cap_pi(sk)->conn->hcon))
|
||||
return 1;
|
||||
} else if (d->link_mode & RFCOMM_LM_AUTH) {
|
||||
if (!hci_conn_auth(l2cap_pi(sk)->conn->hcon))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---- RFCOMM DLCs ---- */
|
||||
static void rfcomm_dlc_timeout(unsigned long arg)
|
||||
{
|
||||
@ -369,15 +384,23 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
|
||||
d->addr = __addr(s->initiator, dlci);
|
||||
d->priority = 7;
|
||||
|
||||
d->state = BT_CONFIG;
|
||||
d->state = BT_CONFIG;
|
||||
rfcomm_dlc_link(s, d);
|
||||
|
||||
d->out = 1;
|
||||
|
||||
d->mtu = s->mtu;
|
||||
d->cfc = (s->cfc == RFCOMM_CFC_UNKNOWN) ? 0 : s->cfc;
|
||||
|
||||
if (s->state == BT_CONNECTED)
|
||||
rfcomm_send_pn(s, 1, d);
|
||||
if (s->state == BT_CONNECTED) {
|
||||
if (rfcomm_check_link_mode(d))
|
||||
set_bit(RFCOMM_AUTH_PENDING, &d->flags);
|
||||
else
|
||||
rfcomm_send_pn(s, 1, d);
|
||||
}
|
||||
|
||||
rfcomm_dlc_set_timer(d, RFCOMM_CONN_TIMEOUT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1144,21 +1167,6 @@ static int rfcomm_recv_disc(struct rfcomm_session *s, u8 dlci)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int rfcomm_check_link_mode(struct rfcomm_dlc *d)
|
||||
{
|
||||
struct sock *sk = d->session->sock->sk;
|
||||
|
||||
if (d->link_mode & (RFCOMM_LM_ENCRYPT | RFCOMM_LM_SECURE)) {
|
||||
if (!hci_conn_encrypt(l2cap_pi(sk)->conn->hcon))
|
||||
return 1;
|
||||
} else if (d->link_mode & RFCOMM_LM_AUTH) {
|
||||
if (!hci_conn_auth(l2cap_pi(sk)->conn->hcon))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rfcomm_dlc_accept(struct rfcomm_dlc *d)
|
||||
{
|
||||
struct sock *sk = d->session->sock->sk;
|
||||
@ -1203,10 +1211,8 @@ static int rfcomm_recv_sabm(struct rfcomm_session *s, u8 dlci)
|
||||
if (rfcomm_check_link_mode(d)) {
|
||||
set_bit(RFCOMM_AUTH_PENDING, &d->flags);
|
||||
rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rfcomm_dlc_accept(d);
|
||||
} else
|
||||
rfcomm_dlc_accept(d);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1221,10 +1227,8 @@ static int rfcomm_recv_sabm(struct rfcomm_session *s, u8 dlci)
|
||||
if (rfcomm_check_link_mode(d)) {
|
||||
set_bit(RFCOMM_AUTH_PENDING, &d->flags);
|
||||
rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rfcomm_dlc_accept(d);
|
||||
} else
|
||||
rfcomm_dlc_accept(d);
|
||||
} else {
|
||||
rfcomm_send_dm(s, dlci);
|
||||
}
|
||||
@ -1457,8 +1461,12 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb
|
||||
clear_bit(RFCOMM_TX_THROTTLED, &d->flags);
|
||||
|
||||
rfcomm_dlc_lock(d);
|
||||
|
||||
d->remote_v24_sig = msc->v24_sig;
|
||||
|
||||
if (d->modem_status)
|
||||
d->modem_status(d, msc->v24_sig);
|
||||
|
||||
rfcomm_dlc_unlock(d);
|
||||
|
||||
rfcomm_send_msc(s, 0, dlci, msc->v24_sig);
|
||||
@ -1634,7 +1642,11 @@ static void rfcomm_process_connect(struct rfcomm_session *s)
|
||||
d = list_entry(p, struct rfcomm_dlc, list);
|
||||
if (d->state == BT_CONFIG) {
|
||||
d->mtu = s->mtu;
|
||||
rfcomm_send_pn(s, 1, d);
|
||||
if (rfcomm_check_link_mode(d)) {
|
||||
set_bit(RFCOMM_AUTH_PENDING, &d->flags);
|
||||
rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT);
|
||||
} else
|
||||
rfcomm_send_pn(s, 1, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1707,7 +1719,11 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s)
|
||||
|
||||
if (test_and_clear_bit(RFCOMM_AUTH_ACCEPT, &d->flags)) {
|
||||
rfcomm_dlc_clear_timer(d);
|
||||
rfcomm_dlc_accept(d);
|
||||
if (d->out) {
|
||||
rfcomm_send_pn(s, 1, d);
|
||||
rfcomm_dlc_set_timer(d, RFCOMM_CONN_TIMEOUT);
|
||||
} else
|
||||
rfcomm_dlc_accept(d);
|
||||
if (d->link_mode & RFCOMM_LM_SECURE) {
|
||||
struct sock *sk = s->sock->sk;
|
||||
hci_conn_change_link_key(l2cap_pi(sk)->conn->hcon);
|
||||
@ -1715,7 +1731,10 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s)
|
||||
continue;
|
||||
} else if (test_and_clear_bit(RFCOMM_AUTH_REJECT, &d->flags)) {
|
||||
rfcomm_dlc_clear_timer(d);
|
||||
rfcomm_send_dm(s, d->dlci);
|
||||
if (!d->out)
|
||||
rfcomm_send_dm(s, d->dlci);
|
||||
else
|
||||
d->state = BT_CLOSED;
|
||||
__rfcomm_dlc_close(d, ECONNREFUSED);
|
||||
continue;
|
||||
}
|
||||
@ -1724,7 +1743,7 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s)
|
||||
continue;
|
||||
|
||||
if ((d->state == BT_CONNECTED || d->state == BT_DISCONN) &&
|
||||
d->mscex == RFCOMM_MSCEX_OK)
|
||||
d->mscex == RFCOMM_MSCEX_OK)
|
||||
rfcomm_process_tx(d);
|
||||
}
|
||||
}
|
||||
@ -1952,7 +1971,8 @@ static void rfcomm_auth_cfm(struct hci_conn *conn, u8 status)
|
||||
list_for_each_safe(p, n, &s->dlcs) {
|
||||
d = list_entry(p, struct rfcomm_dlc, list);
|
||||
|
||||
if (d->link_mode & (RFCOMM_LM_ENCRYPT | RFCOMM_LM_SECURE))
|
||||
if ((d->link_mode & (RFCOMM_LM_ENCRYPT | RFCOMM_LM_SECURE)) &&
|
||||
!(conn->link_mode & HCI_LM_ENCRYPT) && !status)
|
||||
continue;
|
||||
|
||||
if (!test_and_clear_bit(RFCOMM_AUTH_PENDING, &d->flags))
|
||||
@ -1986,6 +2006,14 @@ static void rfcomm_encrypt_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
|
||||
list_for_each_safe(p, n, &s->dlcs) {
|
||||
d = list_entry(p, struct rfcomm_dlc, list);
|
||||
|
||||
if ((d->link_mode & (RFCOMM_LM_ENCRYPT | RFCOMM_LM_SECURE)) &&
|
||||
(d->state == BT_CONNECTED ||
|
||||
d->state == BT_CONFIG) &&
|
||||
!status && encrypt == 0x00) {
|
||||
__rfcomm_dlc_close(d, ECONNREFUSED);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!test_and_clear_bit(RFCOMM_AUTH_PENDING, &d->flags))
|
||||
continue;
|
||||
|
||||
|
@ -307,13 +307,13 @@ static struct sock *rfcomm_sock_alloc(struct net *net, struct socket *sock, int
|
||||
sk->sk_destruct = rfcomm_sock_destruct;
|
||||
sk->sk_sndtimeo = RFCOMM_CONN_TIMEOUT;
|
||||
|
||||
sk->sk_sndbuf = RFCOMM_MAX_CREDITS * RFCOMM_DEFAULT_MTU * 10;
|
||||
sk->sk_rcvbuf = RFCOMM_MAX_CREDITS * RFCOMM_DEFAULT_MTU * 10;
|
||||
sk->sk_sndbuf = RFCOMM_MAX_CREDITS * RFCOMM_DEFAULT_MTU * 10;
|
||||
sk->sk_rcvbuf = RFCOMM_MAX_CREDITS * RFCOMM_DEFAULT_MTU * 10;
|
||||
|
||||
sock_reset_flag(sk, SOCK_ZAPPED);
|
||||
|
||||
sk->sk_protocol = proto;
|
||||
sk->sk_state = BT_OPEN;
|
||||
sk->sk_state = BT_OPEN;
|
||||
|
||||
bt_sock_link(&rfcomm_sk_list, sk);
|
||||
|
||||
@ -411,6 +411,8 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a
|
||||
bacpy(&bt_sk(sk)->dst, &sa->rc_bdaddr);
|
||||
rfcomm_pi(sk)->channel = sa->rc_channel;
|
||||
|
||||
d->link_mode = rfcomm_pi(sk)->link_mode;
|
||||
|
||||
err = rfcomm_dlc_open(d, &bt_sk(sk)->src, &sa->rc_bdaddr, sa->rc_channel);
|
||||
if (!err)
|
||||
err = bt_sock_wait_state(sk, BT_CONNECTED,
|
||||
@ -686,6 +688,8 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
|
||||
copied += chunk;
|
||||
size -= chunk;
|
||||
|
||||
sock_recv_timestamp(msg, sk, skb);
|
||||
|
||||
if (!(flags & MSG_PEEK)) {
|
||||
atomic_sub(chunk, &sk->sk_rmem_alloc);
|
||||
|
||||
@ -791,15 +795,20 @@ static int rfcomm_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned lon
|
||||
struct sock *sk = sock->sk;
|
||||
int err;
|
||||
|
||||
lock_sock(sk);
|
||||
BT_DBG("sk %p cmd %x arg %lx", sk, cmd, arg);
|
||||
|
||||
err = bt_sock_ioctl(sock, cmd, arg);
|
||||
|
||||
if (err == -ENOIOCTLCMD) {
|
||||
#ifdef CONFIG_BT_RFCOMM_TTY
|
||||
err = rfcomm_dev_ioctl(sk, cmd, (void __user *)arg);
|
||||
lock_sock(sk);
|
||||
err = rfcomm_dev_ioctl(sk, cmd, (void __user *) arg);
|
||||
release_sock(sk);
|
||||
#else
|
||||
err = -EOPNOTSUPP;
|
||||
err = -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
|
||||
release_sock(sk);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -75,6 +75,8 @@ struct rfcomm_dev {
|
||||
struct device *tty_dev;
|
||||
|
||||
atomic_t wmem_alloc;
|
||||
|
||||
struct sk_buff_head pending;
|
||||
};
|
||||
|
||||
static LIST_HEAD(rfcomm_dev_list);
|
||||
@ -262,13 +264,34 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
|
||||
init_waitqueue_head(&dev->wait);
|
||||
tasklet_init(&dev->wakeup_task, rfcomm_tty_wakeup, (unsigned long) dev);
|
||||
|
||||
skb_queue_head_init(&dev->pending);
|
||||
|
||||
rfcomm_dlc_lock(dlc);
|
||||
|
||||
if (req->flags & (1 << RFCOMM_REUSE_DLC)) {
|
||||
struct sock *sk = dlc->owner;
|
||||
struct sk_buff *skb;
|
||||
|
||||
BUG_ON(!sk);
|
||||
|
||||
rfcomm_dlc_throttle(dlc);
|
||||
|
||||
while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
|
||||
skb_orphan(skb);
|
||||
skb_queue_tail(&dev->pending, skb);
|
||||
atomic_sub(skb->len, &sk->sk_rmem_alloc);
|
||||
}
|
||||
}
|
||||
|
||||
dlc->data_ready = rfcomm_dev_data_ready;
|
||||
dlc->state_change = rfcomm_dev_state_change;
|
||||
dlc->modem_status = rfcomm_dev_modem_status;
|
||||
|
||||
dlc->owner = dev;
|
||||
dev->dlc = dlc;
|
||||
|
||||
rfcomm_dev_modem_status(dlc, dlc->remote_v24_sig);
|
||||
|
||||
rfcomm_dlc_unlock(dlc);
|
||||
|
||||
/* It's safe to call __module_get() here because socket already
|
||||
@ -537,11 +560,16 @@ static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb)
|
||||
struct rfcomm_dev *dev = dlc->owner;
|
||||
struct tty_struct *tty;
|
||||
|
||||
if (!dev || !(tty = dev->tty)) {
|
||||
if (!dev) {
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(tty = dev->tty) || !skb_queue_empty(&dev->pending)) {
|
||||
skb_queue_tail(&dev->pending, skb);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("dlc %p tty %p len %d", dlc, tty, skb->len);
|
||||
|
||||
tty_insert_flip_string(tty, skb->data, skb->len);
|
||||
@ -625,6 +653,30 @@ static void rfcomm_tty_wakeup(unsigned long arg)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void rfcomm_tty_copy_pending(struct rfcomm_dev *dev)
|
||||
{
|
||||
struct tty_struct *tty = dev->tty;
|
||||
struct sk_buff *skb;
|
||||
int inserted = 0;
|
||||
|
||||
if (!tty)
|
||||
return;
|
||||
|
||||
BT_DBG("dev %p tty %p", dev, tty);
|
||||
|
||||
rfcomm_dlc_lock(dev->dlc);
|
||||
|
||||
while ((skb = skb_dequeue(&dev->pending))) {
|
||||
inserted += tty_insert_flip_string(tty, skb->data, skb->len);
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
rfcomm_dlc_unlock(dev->dlc);
|
||||
|
||||
if (inserted > 0)
|
||||
tty_flip_buffer_push(tty);
|
||||
}
|
||||
|
||||
static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
|
||||
{
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
@ -689,6 +741,10 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
|
||||
if (err == 0)
|
||||
device_move(dev->tty_dev, rfcomm_get_device(dev));
|
||||
|
||||
rfcomm_tty_copy_pending(dev);
|
||||
|
||||
rfcomm_dlc_unthrottle(dev->dlc);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1121,6 +1177,7 @@ int rfcomm_init_ttys(void)
|
||||
rfcomm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
|
||||
rfcomm_tty_driver->init_termios = tty_std_termios;
|
||||
rfcomm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
|
||||
rfcomm_tty_driver->init_termios.c_lflag &= ~ICANON;
|
||||
tty_set_operations(rfcomm_tty_driver, &rfcomm_ops);
|
||||
|
||||
if (tty_register_driver(rfcomm_tty_driver)) {
|
||||
|
Reference in New Issue
Block a user