⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sock.c

📁 Linux嵌入式平台蓝牙协议栈软件
💻 C
📖 第 1 页 / 共 2 页
字号:
		}	}	set_current_state(TASK_RUNNING);	remove_wait_queue(sk->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, &bt_sk(sk)->dst);	else		bacpy(&sa->rc_bdaddr, &bt_sk(sk)->src);	*len = sizeof(struct sockaddr_rc);	return 0;}static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock,			       struct msghdr *msg, size_t len){	struct sock *sk = sock->sk;	struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc;	struct sk_buff *skb;	int err;	int sent = 0;	if (msg->msg_flags & MSG_OOB)		return -EOPNOTSUPP;	if (sk->sk_shutdown & SEND_SHUTDOWN)		return -EPIPE;	BT_DBG("sock %p, sk %p", sock, sk);	lock_sock(sk);	while (len) {		size_t size = min_t(size_t, 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->sk_sleep, &wait);	for (;;) {		set_current_state(TASK_INTERRUPTIBLE);		if (skb_queue_len(&sk->sk_receive_queue) || sk->sk_err || (sk->sk_shutdown & RCV_SHUTDOWN) ||				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->sk_sleep, &wait);	return timeo;}static int rfcomm_sock_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 %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->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 = 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->sk_receive_queue, skb);			if (!copied)				copied = -EFAULT;			break;		}		copied += chunk;		size   -= chunk;		if (!(flags & MSG_PEEK)) {			atomic_sub(chunk, &sk->sk_rmem_alloc);			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:	if (atomic_read(&sk->sk_rmem_alloc) <= (sk->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 __user *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 __user *optval, int __user *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_BT_RFCOMM_TTY	err = rfcomm_dev_ioctl(sk, cmd, (void __user *)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->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;	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 channel */	parent = rfcomm_get_sock_by_channel(BT_LISTEN, channel, &src);	if (!parent)		return 0;	/* Check for backlog size */	if (parent->sk_ack_backlog > parent->sk_max_ack_backlog) {		BT_DBG("backlog full %d", parent->sk_ack_backlog); 		goto done;	}	sk = rfcomm_sock_alloc(NULL, BTPROTO_RFCOMM, GFP_ATOMIC);	if (!sk)		goto done;	rfcomm_sock_init(sk, parent);	bacpy(&bt_sk(sk)->src, &src);	bacpy(&bt_sk(sk)->dst, &dst);	rfcomm_pi(sk)->channel = channel;	sk->sk_state = BT_CONFIG;	bt_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 ---- */#ifdef CONFIG_PROC_FSstatic void *rfcomm_seq_start(struct seq_file *seq, loff_t *pos){	struct sock *sk;	struct hlist_node *node;	loff_t l = *pos;	read_lock_bh(&rfcomm_sk_list.lock);	sk_for_each(sk, node, &rfcomm_sk_list.head)		if (!l--)			return sk;	return NULL;}static void *rfcomm_seq_next(struct seq_file *seq, void *e, loff_t *pos){	struct sock *sk = e;	(*pos)++;	return sk_next(sk);}static void rfcomm_seq_stop(struct seq_file *seq, void *e){	read_unlock_bh(&rfcomm_sk_list.lock);}static int  rfcomm_seq_show(struct seq_file *seq, void *e){	struct sock *sk = e;	seq_printf(seq, "%s %s %d %d\n",			batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst),			sk->sk_state, rfcomm_pi(sk)->channel);	return 0;}static struct seq_operations rfcomm_seq_ops = {	.start  = rfcomm_seq_start,	.next   = rfcomm_seq_next,	.stop   = rfcomm_seq_stop,	.show   = rfcomm_seq_show };static int rfcomm_seq_open(struct inode *inode, struct file *file){	return seq_open(file, &rfcomm_seq_ops);}static struct file_operations rfcomm_seq_fops = {	.owner	 = THIS_MODULE,	.open    = rfcomm_seq_open,	.read    = seq_read,	.llseek  = seq_lseek,	.release = seq_release,};static int  __init rfcomm_sock_proc_init(void){        struct proc_dir_entry *p = create_proc_entry("sock", S_IRUGO, proc_bt_rfcomm);        if (!p)                return -ENOMEM;        p->proc_fops = &rfcomm_seq_fops;        return 0;}static void __exit rfcomm_sock_proc_cleanup(void){        remove_proc_entry("sock", proc_bt_rfcomm);}#else /* CONFIG_PROC_FS */static int  __init rfcomm_sock_proc_init(void){        return 0;}static void __exit rfcomm_sock_proc_cleanup(void){        return;}#endif /* CONFIG_PROC_FS */static struct proto_ops rfcomm_sock_ops = {	.family		= PF_BLUETOOTH,	.owner		= THIS_MODULE,	.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		= bt_sock_poll,	.socketpair	= sock_no_socketpair,	.mmap		= sock_no_mmap};static struct net_proto_family rfcomm_sock_family_ops = {	.family		= PF_BLUETOOTH,	.owner		= THIS_MODULE,	.create		= rfcomm_sock_create};int  __init rfcomm_init_sockets(void){	int err;	if ((err = bt_sock_register(BTPROTO_RFCOMM, &rfcomm_sock_family_ops))) {		BT_ERR("RFCOMM socket layer registration failed. %d", err);		return err;	}	rfcomm_sock_proc_init();	BT_INFO("RFCOMM socket layer initialized");	return 0;}void __exit rfcomm_cleanup_sockets(void){	int err;	rfcomm_sock_proc_cleanup();	/* Unregister socket, protocol and notifier */	if ((err = bt_sock_unregister(BTPROTO_RFCOMM)))		BT_ERR("RFCOMM socket layer unregistration failed. %d", err);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -