📄 sock.c
字号:
BT_DBG("sk %p timeo %ld", sk, timeo); /* Wait for an incoming connection. (wake-one). */ add_wait_queue_exclusive(sk->sleep, &wait); while (!(nsk = bluez_accept_dequeue(sk, newsock))) { set_current_state(TASK_INTERRUPTIBLE); if (!timeo) { err = -EAGAIN; break; } release_sock(sk); timeo = schedule_timeout(timeo); lock_sock(sk); if (sk->state != BT_LISTEN) { err = -EBADFD; break; } if (signal_pending(current)) { err = sock_intr_errno(timeo); break; } } set_current_state(TASK_RUNNING); remove_wait_queue(sk->sleep, &wait); if (err) goto done; newsock->state = SS_CONNECTED; BT_DBG("new socket %p", nsk);done: release_sock(sk); return err;}static int rfcomm_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer){ struct sockaddr_rc *sa = (struct sockaddr_rc *) addr; struct sock *sk = sock->sk; BT_DBG("sock %p, sk %p", sock, sk); sa->rc_family = AF_BLUETOOTH; sa->rc_channel = rfcomm_pi(sk)->channel; if (peer) bacpy(&sa->rc_bdaddr, &bluez_pi(sk)->dst); else bacpy(&sa->rc_bdaddr, &bluez_pi(sk)->src); *len = sizeof(struct sockaddr_rc); return 0;}static int rfcomm_sock_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm){ struct sock *sk = sock->sk; struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc; struct sk_buff *skb; int err, size; int sent = 0; if (msg->msg_flags & MSG_OOB) return -EOPNOTSUPP; if (sk->shutdown & SEND_SHUTDOWN) return -EPIPE; BT_DBG("sock %p, sk %p", sock, sk); lock_sock(sk); while (len) { size = min_t(uint, len, d->mtu); skb = sock_alloc_send_skb(sk, size + RFCOMM_SKB_RESERVE, msg->msg_flags & MSG_DONTWAIT, &err); if (!skb) break; skb_reserve(skb, RFCOMM_SKB_HEAD_RESERVE); err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); if (err) { kfree_skb(skb); sent = err; break; } err = rfcomm_dlc_send(d, skb); if (err < 0) { kfree_skb(skb); break; } sent += size; len -= size; } release_sock(sk); return sent ? sent : err;}static long rfcomm_sock_data_wait(struct sock *sk, long timeo){ DECLARE_WAITQUEUE(wait, current); add_wait_queue(sk->sleep, &wait); for (;;) { set_current_state(TASK_INTERRUPTIBLE); if (skb_queue_len(&sk->receive_queue) || sk->err || (sk->shutdown & RCV_SHUTDOWN) || signal_pending(current) || !timeo) break; set_bit(SOCK_ASYNC_WAITDATA, &sk->socket->flags); release_sock(sk); timeo = schedule_timeout(timeo); lock_sock(sk); clear_bit(SOCK_ASYNC_WAITDATA, &sk->socket->flags); } __set_current_state(TASK_RUNNING); remove_wait_queue(sk->sleep, &wait); return timeo;}static int rfcomm_sock_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags, struct scm_cookie *scm){ struct sock *sk = sock->sk; int target, err = 0, copied = 0; long timeo; if (flags & MSG_OOB) return -EOPNOTSUPP; msg->msg_namelen = 0; BT_DBG("sk %p size %d", 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->receive_queue); if (!skb) { if (copied >= target) break; if ((err = sock_error(sk)) != 0) break; if (sk->shutdown & RCV_SHUTDOWN) break; err = -EAGAIN; if (!timeo) break; timeo = rfcomm_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->receive_queue, skb); if (!copied) copied = -EFAULT; break; } copied += chunk; size -= chunk; if (!(flags & MSG_PEEK)) { atomic_sub(chunk, &sk->rmem_alloc); skb_pull(skb, chunk); if (skb->len) { skb_queue_head(&sk->receive_queue, skb); break; } kfree_skb(skb); } else { /* put message back and return */ skb_queue_head(&sk->receive_queue, skb); break; } } while (size);out: if (atomic_read(&sk->rmem_alloc) <= (sk->rcvbuf >> 2)) rfcomm_dlc_unthrottle(rfcomm_pi(sk)->dlc); release_sock(sk); return copied ? : err;}static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen){ struct sock *sk = sock->sk; int err = 0; BT_DBG("sk %p", sk); lock_sock(sk); switch (optname) { default: err = -ENOPROTOOPT; break; }; release_sock(sk); return err;}static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen){ struct sock *sk = sock->sk; int len, err = 0; BT_DBG("sk %p", sk); if (get_user(len, optlen)) return -EFAULT; lock_sock(sk); switch (optname) { default: err = -ENOPROTOOPT; break; }; release_sock(sk); return err;}static int rfcomm_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg){ struct sock *sk = sock->sk; int err; lock_sock(sk);#ifdef CONFIG_BLUEZ_RFCOMM_TTY err = rfcomm_dev_ioctl(sk, cmd, arg);#else err = -EOPNOTSUPP;#endif release_sock(sk); 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->shutdown) { sk->shutdown = SHUTDOWN_MASK; __rfcomm_sock_close(sk); if (sk->linger) err = bluez_sock_wait_state(sk, BT_CLOSED, sk->lingertime); } release_sock(sk); return err;}static int rfcomm_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; err = rfcomm_sock_shutdown(sock, 2); sock_orphan(sk); rfcomm_sock_kill(sk); return err;}/* ---- RFCOMM core layer callbacks ---- * * called under rfcomm_lock() */int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc **d){ struct sock *sk, *parent; bdaddr_t src, dst; int result = 0; BT_DBG("session %p channel %d", s, channel); rfcomm_session_getaddr(s, &src, &dst); /* Check if we have socket listening on this channel */ parent = rfcomm_get_sock_by_channel(BT_LISTEN, channel, &src); if (!parent) return 0; /* Check for backlog size */ if (parent->ack_backlog > parent->max_ack_backlog) { BT_DBG("backlog full %d", parent->ack_backlog); goto done; } sk = rfcomm_sock_alloc(NULL, BTPROTO_RFCOMM, GFP_ATOMIC); if (!sk) goto done; rfcomm_sock_init(sk, parent); bacpy(&bluez_pi(sk)->src, &src); bacpy(&bluez_pi(sk)->dst, &dst); rfcomm_pi(sk)->channel = channel; sk->state = BT_CONFIG; bluez_accept_enqueue(parent, sk); /* Accept connection and return socket DLC */ *d = rfcomm_pi(sk)->dlc; result = 1;done: bh_unlock_sock(parent); return result;}/* ---- Proc fs support ---- */int rfcomm_sock_dump(char *buf){ struct bluez_sock_list *list = &rfcomm_sk_list; struct rfcomm_pinfo *pi; struct sock *sk; char *ptr = buf; write_lock_bh(&list->lock); for (sk = list->head; sk; sk = sk->next) { pi = rfcomm_pi(sk); ptr += sprintf(ptr, "sk %s %s %d %d\n", batostr(&bluez_pi(sk)->src), batostr(&bluez_pi(sk)->dst), sk->state, rfcomm_pi(sk)->channel); } write_unlock_bh(&list->lock); return ptr - buf;}static struct proto_ops rfcomm_sock_ops = { family: PF_BLUETOOTH, release: rfcomm_sock_release, bind: rfcomm_sock_bind, connect: rfcomm_sock_connect, listen: rfcomm_sock_listen, accept: rfcomm_sock_accept, getname: rfcomm_sock_getname, sendmsg: rfcomm_sock_sendmsg, recvmsg: rfcomm_sock_recvmsg, shutdown: rfcomm_sock_shutdown, setsockopt: rfcomm_sock_setsockopt, getsockopt: rfcomm_sock_getsockopt, ioctl: rfcomm_sock_ioctl, poll: bluez_sock_poll, socketpair: sock_no_socketpair, mmap: sock_no_mmap};static struct net_proto_family rfcomm_sock_family_ops = { family: PF_BLUETOOTH, create: rfcomm_sock_create};int rfcomm_init_sockets(void){ int err; if ((err = bluez_sock_register(BTPROTO_RFCOMM, &rfcomm_sock_family_ops))) { BT_ERR("Can't register RFCOMM socket layer"); return err; } return 0;}void rfcomm_cleanup_sockets(void){ int err; /* Unregister socket, protocol and notifier */ if ((err = bluez_sock_unregister(BTPROTO_RFCOMM))) BT_ERR("Can't unregister RFCOMM socket layer %d", err);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -