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

📄 ksock_single.c

📁 蓝牙的各种编程接口和各种按理介绍,还有一些例子和说明
💻 C
字号:
static int errno;#define __KERNEL_SYSCALLS__#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/signal.h>#include <linux/init.h>#include <linux/wait.h>#include <linux/smp_lock.h>#include <linux/net.h>#include <net/sock.h>#include <asm/unistd.h>#include <asm/uaccess.h>#include <net/bluetooth/bluetooth.h>#include <net/bluetooth/l2cap.h>#define VERSION "0.1"#define LISTENER  0#define DATACONN  1struct session {	struct list_head list;	struct socket   *sock;	wait_queue_t     wait;	unsigned int     type;	unsigned long   state;	atomic_t       killed;};static LIST_HEAD(session_list);static DECLARE_WAIT_QUEUE_HEAD(worker_wait);static atomic_t terminate, running;static struct session *ksock_add_session(struct socket *sock, int type){	struct session *s = kmalloc(sizeof(*s), GFP_KERNEL);	if (!s)		return NULL;		memset(s, 0, sizeof(*s));	init_waitqueue_entry(&s->wait, current);	add_wait_queue(sock->sk->sleep, &s->wait);	s->sock  = sock;	s->type  = type;	s->state = 0; 	list_add(&s->list, &session_list);	/* Do not increment module usage count for listeting sessions. 	 * Otherwise we won't be able to unload the module. */	if (type != LISTENER)		MOD_INC_USE_COUNT;	return s;}static inline int ksock_del_session(struct session *s){	struct socket *sock = s->sock;	int type = s->type;		list_del(&s->list);	remove_wait_queue(sock->sk->sleep, &s->wait);	sock_release(sock);	kfree(s);	if (type != LISTENER)		MOD_DEC_USE_COUNT;	return 0;}static void ksock_kill_sessions(void){	struct list_head *p, *n;	list_for_each_safe(p, n, &session_list)		ksock_del_session(list_entry(p, struct session, list));}static inline void ksock_process_data(struct session *s){	struct socket *sock = s->sock;	struct sock *sk = sock->sk;	struct sk_buff *skb;	struct msghdr msg;		memset(&msg, 0, sizeof(msg));	msg.msg_iovlen = 1;	/* Get data directly from socket receive queue without copying it.	 * And echo it back. */	while ((skb = skb_dequeue(&sk->receive_queue))) {		struct iovec iv = { skb->data, skb->len };		BT_INFO("Session %p received %d bytes", s, skb->len);	        msg.msg_iov = &iv;		sock->ops->sendmsg(sock, &msg, skb->len, NULL);				kfree_skb(skb);	}	if (sk->state != BT_CONNECTED)		ksock_del_session(s);}static inline void ksock_accept_connection(struct session *s){	struct socket *sock = s->sock, *nsock;	int err;	/* Fast check for a new connection.	 * Avoids unnesesary socket allocations. */	if (list_empty(&bluez_pi(sock->sk)->accept_q))		return;	nsock = sock_alloc();	if (!nsock)		return;                        	nsock->type = sock->type;	nsock->ops  = sock->ops;		err = sock->ops->accept(sock, nsock, O_NONBLOCK);	if (err < 0) {		sock_release(nsock);		return;	}	ksock_add_session(nsock, DATACONN);}static inline void ksock_process_sessions(void){	struct list_head *p, *n;	list_for_each_safe(p, n, &session_list) {		struct session *s;		s = list_entry(p, struct session, list);		if (atomic_read(&s->killed))			ksock_del_session(s);			if (s->type == LISTENER)			ksock_accept_connection(s);		else				ksock_process_data(s);	}}static void ksock_worker(void){	BT_INFO("");	daemonize(); reparent_to_init();	set_fs(KERNEL_DS);		while (!atomic_read(&terminate)) {		set_current_state(TASK_INTERRUPTIBLE);		/* Process stuff */ 		ksock_process_sessions();		/* Done. Let's sleep. 		 * Incomming connections and data will wake us up. */		schedule();	}	set_current_state(TASK_RUNNING);	return;}static int ksock_add_listener(bdaddr_t *ba, int psm){	struct sockaddr_l2 addr;	struct l2cap_options opts;	struct socket *sock;	int    size, err = 0;		BT_INFO("psm %d", psm);	/* Create socket */	err = sock_create(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP, &sock);	if (err < 0) { 		BT_ERR("Create socket failed %d", err);		return err;	}	/* Bind socket */	bacpy(&addr.l2_bdaddr, ba);	addr.l2_family = AF_BLUETOOTH;	addr.l2_psm    = htobs(psm);	err = sock->ops->bind(sock, (struct sockaddr *) &addr, sizeof(addr));	if (err < 0) {		BT_ERR("Bind failed %d", err);		goto failed;	}        /* Set L2CAP options */	size = sizeof(opts);	sock->ops->getsockopt(sock, SOL_L2CAP, L2CAP_OPTIONS, (void *)&opts, &size);		opts.imtu = 1024;	sock->ops->setsockopt(sock, SOL_L2CAP, L2CAP_OPTIONS, (void *)&opts, size);		/* Start listening on the socket */	err = sock->ops->listen(sock, 10);	if (err) {		BT_ERR("Listen failed %d", err);		goto failed;	}	/* Add listening session */	if (!ksock_add_session(sock, LISTENER))		goto failed;		return 0;failed:	sock_release(sock);	return err;}static int ksock_run(void *unused){	DECLARE_WAITQUEUE(wait, current);		atomic_inc(&running);	daemonize();	sigfillset(&current->blocked);	set_fs(KERNEL_DS);	sprintf(current->comm, "ksock");		BT_INFO("");	/* Listen on PSM 11 and 12 */	ksock_add_listener(BDADDR_ANY, 11);	ksock_add_listener(BDADDR_ANY, 12);	add_wait_queue(&worker_wait, &wait);	ksock_worker();	remove_wait_queue(&worker_wait, &wait);	ksock_kill_sessions();	atomic_dec(&running);	return 0;}int __init ksock_init(void){	kernel_thread(ksock_run, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);	return 0;}void ksock_cleanup(void){	/* Terminate working thread.	 * ie. Set terminate flag and wake it up */	atomic_inc(&terminate);	wake_up_interruptible(&worker_wait);	/* Wait until worker is running */	while (atomic_read(&running))		schedule();		return;}module_init(ksock_init);module_exit(ksock_cleanup);MODULE_AUTHOR("Maxim Krasnyansky <maxk@qualcomm.com>");MODULE_DESCRIPTION("L2CAP kernel sockets example ver " VERSION);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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