Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 215242
b: refs/heads/master
c: 796c86e
h: refs/heads/master
v: v3
  • Loading branch information
Mat Martineau authored and Gustavo F. Padovan committed Oct 12, 2010
1 parent d262226 commit 70ceb55
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0fba2558cbb3fae3a09147b7d6e18a6204204e0e
refs/heads/master: 796c86eec84ddfd02281c5071838ed1fefda6b90
2 changes: 2 additions & 0 deletions trunk/include/net/bluetooth/bluetooth.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ int bt_sock_unregister(int proto);
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, size_t len, int flags);
int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t len, int flags);
uint bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait);
int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo);
Expand Down
109 changes: 109 additions & 0 deletions trunk/net/bluetooth/af_bluetooth.c
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,115 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
}
EXPORT_SYMBOL(bt_sock_recvmsg);

static long bt_sock_data_wait(struct sock *sk, long timeo)
{
DECLARE_WAITQUEUE(wait, current);

add_wait_queue(sk_sleep(sk), &wait);
for (;;) {
set_current_state(TASK_INTERRUPTIBLE);

if (!skb_queue_empty(&sk->sk_receive_queue))
break;

if (sk->sk_err || (sk->sk_shutdown & RCV_SHUTDOWN))
break;

if (signal_pending(current) || !timeo)
break;

set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
release_sock(sk);
timeo = schedule_timeout(timeo);
lock_sock(sk);
clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
}

__set_current_state(TASK_RUNNING);
remove_wait_queue(sk_sleep(sk), &wait);
return timeo;
}

int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t size, int flags)
{
struct sock *sk = sock->sk;
int err = 0;
size_t target, copied = 0;
long timeo;

if (flags & MSG_OOB)
return -EOPNOTSUPP;

msg->msg_namelen = 0;

BT_DBG("sk %p size %zu", sk, size);

lock_sock(sk);

target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);

do {
struct sk_buff *skb;
int chunk;

skb = skb_dequeue(&sk->sk_receive_queue);
if (!skb) {
if (copied >= target)
break;

if ((err = sock_error(sk)) != 0)
break;
if (sk->sk_shutdown & RCV_SHUTDOWN)
break;

err = -EAGAIN;
if (!timeo)
break;

timeo = bt_sock_data_wait(sk, timeo);

if (signal_pending(current)) {
err = sock_intr_errno(timeo);
goto out;
}
continue;
}

chunk = min_t(unsigned int, skb->len, size);
if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) {
skb_queue_head(&sk->sk_receive_queue, skb);
if (!copied)
copied = -EFAULT;
break;
}
copied += chunk;
size -= chunk;

sock_recv_ts_and_drops(msg, sk, skb);

if (!(flags & MSG_PEEK)) {
skb_pull(skb, chunk);
if (skb->len) {
skb_queue_head(&sk->sk_receive_queue, skb);
break;
}
kfree_skb(skb);

} else {
/* put message back and return */
skb_queue_head(&sk->sk_receive_queue, skb);
break;
}
} while (size);

out:
release_sock(sk);
return copied ? : err;
}
EXPORT_SYMBOL(bt_sock_stream_recvmsg);

static inline unsigned int bt_accept_poll(struct sock *parent)
{
struct list_head *p, *n;
Expand Down

0 comments on commit 70ceb55

Please sign in to comment.