Commit 2157c296 authored by Maksim Krasnyanskiy's avatar Maksim Krasnyanskiy

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

into qualcomm.com:/home/kernel/bt-2.5
parents eb40c469 385b4ccc
......@@ -131,7 +131,7 @@ void bt_sock_link(struct bt_sock_list *l, struct sock *s);
void bt_sock_unlink(struct bt_sock_list *l, struct sock *s);
int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len, int flags);
uint bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait);
int bt_sock_w4_connect(struct sock *sk, int flags);
int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo);
void bt_accept_enqueue(struct sock *parent, struct sock *sk);
struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock);
......
......@@ -27,7 +27,7 @@
*
* $Id: af_bluetooth.c,v 1.3 2002/04/17 17:37:15 maxk Exp $
*/
#define VERSION "2.2"
#define VERSION "2.3"
#include <linux/config.h>
#include <linux/module.h>
......@@ -272,39 +272,35 @@ unsigned int bt_sock_poll(struct file * file, struct socket *sock, poll_table *w
return mask;
}
int bt_sock_w4_connect(struct sock *sk, int flags)
int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)
{
DECLARE_WAITQUEUE(wait, current);
long timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
int err = 0;
BT_DBG("sk %p", sk);
add_wait_queue(sk->sk_sleep, &wait);
while (sk->sk_state != BT_CONNECTED) {
while (sk->sk_state != state) {
set_current_state(TASK_INTERRUPTIBLE);
if (!timeo) {
err = -EAGAIN;
break;
}
if (signal_pending(current)) {
err = sock_intr_errno(timeo);
break;
}
release_sock(sk);
timeo = schedule_timeout(timeo);
lock_sock(sk);
err = 0;
if (sk->sk_state == BT_CONNECTED)
break;
if (sk->sk_err) {
err = sock_error(sk);
break;
}
if (signal_pending(current)) {
err = sock_intr_errno(timeo);
break;
}
}
set_current_state(TASK_RUNNING);
remove_wait_queue(sk->sk_sleep, &wait);
......
......@@ -290,7 +290,7 @@ static void __l2cap_sock_close(struct sock *sk, int reason)
struct l2cap_disconn_req req;
sk->sk_state = BT_DISCONN;
l2cap_sock_set_timer(sk, HZ * 5);
l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
req.dcid = __cpu_to_le16(l2cap_pi(sk)->dcid);
req.scid = __cpu_to_le16(l2cap_pi(sk)->scid);
......@@ -315,11 +315,9 @@ static void __l2cap_sock_close(struct sock *sk, int reason)
static void l2cap_sock_close(struct sock *sk)
{
l2cap_sock_clear_timer(sk);
lock_sock(sk);
__l2cap_sock_close(sk, ECONNRESET);
release_sock(sk);
l2cap_sock_kill(sk);
}
......@@ -531,8 +529,8 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
goto done;
wait:
err = bt_sock_w4_connect(sk, flags);
err = bt_sock_wait_state(sk, BT_CONNECTED,
sock_sndtimeo(sk, flags & O_NONBLOCK));
done:
release_sock(sk);
return err;
......@@ -832,32 +830,39 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
static int l2cap_sock_shutdown(struct socket *sock, int how)
{
struct sock *sk = sock->sk;
int err = 0;
BT_DBG("sock %p, sk %p", sock, sk);
if (!sk) return 0;
l2cap_sock_clear_timer(sk);
lock_sock(sk);
if (!sk->sk_shutdown) {
sk->sk_shutdown = SHUTDOWN_MASK;
__l2cap_sock_close(sk, ECONNRESET);
release_sock(sk);
l2cap_sock_clear_timer(sk);
__l2cap_sock_close(sk, 0);
return 0;
if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
}
release_sock(sk);
return err;
}
static int l2cap_sock_release(struct socket *sock)
{
struct sock *sk = sock->sk;
int err;
BT_DBG("sock %p, sk %p", sock, sk);
if (!sk) return 0;
err = l2cap_sock_shutdown(sock, 2);
sock_orphan(sk);
l2cap_sock_close(sk);
return 0;
l2cap_sock_kill(sk);
return err;
}
/* ---- L2CAP channels ---- */
......@@ -982,9 +987,11 @@ static void l2cap_chan_del(struct sock *sk, int err)
}
sk->sk_state = BT_CLOSED;
sk->sk_err = err;
sk->sk_zapped = 1;
if (err)
sk->sk_err = err;
if (parent)
parent->sk_data_ready(parent, 0);
else
......@@ -1591,7 +1598,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, scid)))
return 0;
l2cap_chan_del(sk, ECONNABORTED);
l2cap_chan_del(sk, 0);
bh_unlock_sock(sk);
l2cap_sock_kill(sk);
......
......@@ -280,13 +280,13 @@ static struct rfcomm_dlc *rfcomm_dlc_get(struct rfcomm_session *s, u8 dlci)
static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, u8 channel)
{
struct rfcomm_session *s;
u8 dlci = __dlci(0, channel);
int err = 0;
u8 dlci;
BT_DBG("dlc %p state %ld %s %s channel %d dlci %d",
d, d->state, batostr(src), batostr(dst), channel, dlci);
BT_DBG("dlc %p state %ld %s %s channel %d",
d, d->state, batostr(src), batostr(dst), channel);
if (dlci < 1 || dlci > 62)
if (channel < 1 || channel > 30)
return -EINVAL;
if (d->state != BT_OPEN && d->state != BT_CLOSED)
......@@ -299,6 +299,8 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
return err;
}
dlci = __dlci(!s->initiator, channel);
/* Check if DLCI already exists */
if (rfcomm_dlc_get(s, dlci))
return -EBUSY;
......@@ -715,7 +717,7 @@ static int rfcomm_send_nsc(struct rfcomm_session *s, int cr, u8 type)
hdr->len = __len8(sizeof(*mcc) + 1);
mcc = (void *) ptr; ptr += sizeof(*mcc);
mcc->type = __mcc_type(s->initiator, RFCOMM_NSC);
mcc->type = __mcc_type(cr, RFCOMM_NSC);
mcc->len = __len8(1);
/* Type that we didn't like */
......@@ -741,7 +743,7 @@ static int rfcomm_send_pn(struct rfcomm_session *s, int cr, struct rfcomm_dlc *d
hdr->len = __len8(sizeof(*mcc) + sizeof(*pn));
mcc = (void *) ptr; ptr += sizeof(*mcc);
mcc->type = __mcc_type(s->initiator, RFCOMM_PN);
mcc->type = __mcc_type(cr, RFCOMM_PN);
mcc->len = __len8(sizeof(*pn));
pn = (void *) ptr; ptr += sizeof(*pn);
......@@ -850,7 +852,7 @@ static int rfcomm_send_msc(struct rfcomm_session *s, int cr, u8 dlci, u8 v24_sig
msc = (void *) ptr; ptr += sizeof(*msc);
msc->dlci = __addr(1, dlci);
msc->v24_sig = v24_sig;
msc->v24_sig = v24_sig | 0x01;
*ptr = __fcs(buf); ptr++;
......@@ -1085,6 +1087,8 @@ static int rfcomm_recv_sabm(struct rfcomm_session *s, u8 dlci)
d->state = BT_CONNECTED;
d->state_change(d, 0);
rfcomm_dlc_unlock(d);
rfcomm_send_msc(s, 1, dlci, d->v24_sig);
} else {
rfcomm_send_dm(s, dlci);
}
......@@ -1207,6 +1211,14 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
}
/* check for sane values: ignore/accept bit_rate, 8 bits, 1 stop bit, no parity,
no flow control lines, normal XON/XOFF chars */
if (rpn->param_mask & RFCOMM_RPN_PM_BITRATE) {
bit_rate = rpn->bit_rate;
if (bit_rate != RFCOMM_RPN_BR_115200) {
BT_DBG("RPN bit rate mismatch 0x%x", bit_rate);
bit_rate = RFCOMM_RPN_BR_115200;
rpn_mask ^= RFCOMM_RPN_PM_BITRATE;
}
}
if (rpn->param_mask & RFCOMM_RPN_PM_DATA) {
data_bits = __get_rpn_data_bits(rpn->line_settings);
if (data_bits != RFCOMM_RPN_DATA_8) {
......@@ -1232,22 +1244,25 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
}
}
if (rpn->param_mask & RFCOMM_RPN_PM_FLOW) {
if (rpn->flow_ctrl != RFCOMM_RPN_FLOW_NONE) {
BT_DBG("RPN flow ctrl mismatch 0x%x", rpn->flow_ctrl);
flow_ctrl = rpn->flow_ctrl;
if (flow_ctrl != RFCOMM_RPN_FLOW_NONE) {
BT_DBG("RPN flow ctrl mismatch 0x%x", flow_ctrl);
flow_ctrl = RFCOMM_RPN_FLOW_NONE;
rpn_mask ^= RFCOMM_RPN_PM_FLOW;
}
}
if (rpn->param_mask & RFCOMM_RPN_PM_XON) {
if (rpn->xon_char != RFCOMM_RPN_XON_CHAR) {
BT_DBG("RPN XON char mismatch 0x%x", rpn->xon_char);
xon_char = rpn->xon_char;
if (xon_char != RFCOMM_RPN_XON_CHAR) {
BT_DBG("RPN XON char mismatch 0x%x", xon_char);
xon_char = RFCOMM_RPN_XON_CHAR;
rpn_mask ^= RFCOMM_RPN_PM_XON;
}
}
if (rpn->param_mask & RFCOMM_RPN_PM_XOFF) {
if (rpn->xoff_char != RFCOMM_RPN_XOFF_CHAR) {
BT_DBG("RPN XOFF char mismatch 0x%x", rpn->xoff_char);
xoff_char = rpn->xoff_char;
if (xoff_char != RFCOMM_RPN_XOFF_CHAR) {
BT_DBG("RPN XOFF char mismatch 0x%x", xoff_char);
xoff_char = RFCOMM_RPN_XOFF_CHAR;
rpn_mask ^= RFCOMM_RPN_PM_XOFF;
}
......
......@@ -193,8 +193,10 @@ static void rfcomm_sock_cleanup_listen(struct sock *parent)
BT_DBG("parent %p", parent);
/* Close not yet accepted dlcs */
while ((sk = bt_accept_dequeue(parent, NULL)))
while ((sk = bt_accept_dequeue(parent, NULL))) {
rfcomm_sock_close(sk);
rfcomm_sock_kill(sk);
}
parent->sk_state = BT_CLOSED;
parent->sk_zapped = 1;
......@@ -216,15 +218,10 @@ static void rfcomm_sock_kill(struct sock *sk)
sock_put(sk);
}
/* Close socket.
* Must be called on unlocked socket.
*/
static void rfcomm_sock_close(struct sock *sk)
static void __rfcomm_sock_close(struct sock *sk)
{
struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc;
lock_sock(sk);
BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
switch (sk->sk_state) {
......@@ -241,11 +238,17 @@ static void rfcomm_sock_close(struct sock *sk)
default:
sk->sk_zapped = 1;
break;
};
}
}
/* Close socket.
* Must be called on unlocked socket.
*/
static void rfcomm_sock_close(struct sock *sk)
{
lock_sock(sk);
__rfcomm_sock_close(sk);
release_sock(sk);
rfcomm_sock_kill(sk);
}
static void rfcomm_sock_init(struct sock *sk, struct sock *parent)
......@@ -375,7 +378,8 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a
err = rfcomm_dlc_open(d, &bt_sk(sk)->src, &sa->rc_bdaddr, sa->rc_channel);
if (!err)
err = bt_sock_w4_connect(sk, flags);
err = bt_sock_wait_state(sk, BT_CONNECTED,
sock_sndtimeo(sk, flags & O_NONBLOCK));
release_sock(sk);
return err;
......@@ -559,9 +563,6 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
int target, err = 0, copied = 0;
long timeo;
if (sk->sk_state != BT_CONNECTED)
return -EINVAL;
if (flags & MSG_OOB)
return -EOPNOTSUPP;
......@@ -636,23 +637,6 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
return copied ? : err;
}
static int rfcomm_sock_shutdown(struct socket *sock, int how)
{
struct sock *sk = sock->sk;
BT_DBG("sock %p, sk %p", sock, sk);
if (!sk) return 0;
lock_sock(sk);
sk->sk_shutdown = SHUTDOWN_MASK;
if (sk->sk_state == BT_CONNECTED)
rfcomm_dlc_close(rfcomm_pi(sk)->dlc, 0);
release_sock(sk);
return 0;
}
static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen)
{
struct sock *sk = sock->sk;
......@@ -711,19 +695,42 @@ static int rfcomm_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned lon
return err;
}
static int rfcomm_sock_shutdown(struct socket *sock, int how)
{
struct sock *sk = sock->sk;
int err = 0;
BT_DBG("sock %p, sk %p", sock, sk);
if (!sk) return 0;
lock_sock(sk);
if (!sk->sk_shutdown) {
sk->sk_shutdown = SHUTDOWN_MASK;
__rfcomm_sock_close(sk);
if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
}
release_sock(sk);
return err;
}
static int rfcomm_sock_release(struct socket *sock)
{
struct sock *sk = sock->sk;
int err;
BT_DBG("sock %p, sk %p", sock, sk);
if (!sk)
return 0;
sock_orphan(sk);
rfcomm_sock_close(sk);
err = rfcomm_sock_shutdown(sock, 2);
return 0;
sock_orphan(sk);
rfcomm_sock_kill(sk);
return err;
}
/* ---- RFCOMM core layer callbacks ----
......
......@@ -354,8 +354,10 @@ static void sco_sock_cleanup_listen(struct sock *parent)
BT_DBG("parent %p", parent);
/* Close not yet accepted channels */
while ((sk = bt_accept_dequeue(parent, NULL)))
while ((sk = bt_accept_dequeue(parent, NULL))) {
sco_sock_close(sk);
sco_sock_kill(sk);
}
parent->sk_state = BT_CLOSED;
parent->sk_zapped = 1;
......@@ -524,7 +526,8 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen
if ((err = sco_connect(sk)))
goto done;
err = bt_sock_w4_connect(sk, flags);
err = bt_sock_wait_state(sk, BT_CONNECTED,
sock_sndtimeo(sk, flags & O_NONBLOCK));
done:
release_sock(sk);
......@@ -728,16 +731,24 @@ int sco_sock_getsockopt(struct socket *sock, int level, int optname, char *optva
static int sco_sock_release(struct socket *sock)
{
struct sock *sk = sock->sk;
int err = 0;
BT_DBG("sock %p, sk %p", sock, sk);
if (!sk)
return 0;
sock_orphan(sk);
sco_sock_close(sk);
return 0;
if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) {
lock_sock(sk);
err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
release_sock(sk);
}
sock_orphan(sk);
sco_sock_kill(sk);
return err;
}
static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent)
......
......@@ -77,6 +77,6 @@ EXPORT_SYMBOL(bt_sock_recvmsg);
EXPORT_SYMBOL(bt_sock_poll);
EXPORT_SYMBOL(bt_accept_enqueue);
EXPORT_SYMBOL(bt_accept_dequeue);
EXPORT_SYMBOL(bt_sock_w4_connect);
EXPORT_SYMBOL(bt_sock_wait_state);
EXPORT_SYMBOL(proc_bt);
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