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

📄 sock.c

📁 基于liunx的蓝牙协议栈源代码版本為2.13,可以方便的下載和移植!
💻 C
📖 第 1 页 / 共 2 页
字号:
	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 + -