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

📄 core.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	default:		__hidp_send_ctrl_message(session,			HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_UNSUPPORTED_REQUEST, NULL, 0);		break;	}	kfree_skb(skb);}static inline void hidp_recv_intr_frame(struct hidp_session *session, struct sk_buff *skb){	unsigned char hdr;	BT_DBG("session %p skb %p len %d", session, skb, skb->len);	hdr = skb->data[0];	skb_pull(skb, 1);	if (hdr == (HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT)) {		hidp_set_timer(session);		if (session->input)			hidp_input_report(session, skb);	} else {		BT_DBG("Unsupported protocol header 0x%02x", hdr);	}	kfree_skb(skb);}static int hidp_send_frame(struct socket *sock, unsigned char *data, int len){	struct kvec iv = { data, len };	struct msghdr msg;	BT_DBG("sock %p data %p len %d", sock, data, len);	if (!len)		return 0;	memset(&msg, 0, sizeof(msg));	return kernel_sendmsg(sock, &msg, &iv, 1, len);}static void hidp_process_transmit(struct hidp_session *session){	struct sk_buff *skb;	BT_DBG("session %p", session);	while ((skb = skb_dequeue(&session->ctrl_transmit))) {		if (hidp_send_frame(session->ctrl_sock, skb->data, skb->len) < 0) {			skb_queue_head(&session->ctrl_transmit, skb);			break;		}		hidp_set_timer(session);		kfree_skb(skb);	}	while ((skb = skb_dequeue(&session->intr_transmit))) {		if (hidp_send_frame(session->intr_sock, skb->data, skb->len) < 0) {			skb_queue_head(&session->intr_transmit, skb);			break;		}		hidp_set_timer(session);		kfree_skb(skb);	}}static int hidp_session(void *arg){	struct hidp_session *session = arg;	struct sock *ctrl_sk = session->ctrl_sock->sk;	struct sock *intr_sk = session->intr_sock->sk;	struct sk_buff *skb;	int vendor = 0x0000, product = 0x0000;	wait_queue_t ctrl_wait, intr_wait;	BT_DBG("session %p", session);	if (session->input) {		vendor  = session->input->id.vendor;		product = session->input->id.product;	}	daemonize("khidpd_%04x%04x", vendor, product);	set_user_nice(current, -15);	current->flags |= PF_NOFREEZE;	init_waitqueue_entry(&ctrl_wait, current);	init_waitqueue_entry(&intr_wait, current);	add_wait_queue(ctrl_sk->sk_sleep, &ctrl_wait);	add_wait_queue(intr_sk->sk_sleep, &intr_wait);	while (!atomic_read(&session->terminate)) {		set_current_state(TASK_INTERRUPTIBLE);		if (ctrl_sk->sk_state != BT_CONNECTED || intr_sk->sk_state != BT_CONNECTED)			break;		while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) {			skb_orphan(skb);			hidp_recv_ctrl_frame(session, skb);		}		while ((skb = skb_dequeue(&intr_sk->sk_receive_queue))) {			skb_orphan(skb);			hidp_recv_intr_frame(session, skb);		}		hidp_process_transmit(session);		schedule();	}	set_current_state(TASK_RUNNING);	remove_wait_queue(intr_sk->sk_sleep, &intr_wait);	remove_wait_queue(ctrl_sk->sk_sleep, &ctrl_wait);	down_write(&hidp_session_sem);	hidp_del_timer(session);	if (intr_sk->sk_state != BT_CONNECTED)		wait_event_timeout(*(ctrl_sk->sk_sleep), (ctrl_sk->sk_state == BT_CLOSED), HZ);	fput(session->ctrl_sock->file);	wait_event_timeout(*(intr_sk->sk_sleep), (intr_sk->sk_state == BT_CLOSED), HZ);	fput(session->intr_sock->file);	__hidp_unlink_session(session);	if (session->input) {		input_unregister_device(session->input);		session->input = NULL;	}	up_write(&hidp_session_sem);	kfree(session);	return 0;}static inline void hidp_setup_input(struct hidp_session *session, struct hidp_connadd_req *req){	struct input_dev *input = session->input;	int i;	input->private = session;	input->name = "Bluetooth HID Boot Protocol Device";	input->id.bustype = BUS_BLUETOOTH;	input->id.vendor  = req->vendor;	input->id.product = req->product;	input->id.version = req->version;	if (req->subclass & 0x40) {		set_bit(EV_KEY, input->evbit);		set_bit(EV_LED, input->evbit);		set_bit(EV_REP, input->evbit);		set_bit(LED_NUML,    input->ledbit);		set_bit(LED_CAPSL,   input->ledbit);		set_bit(LED_SCROLLL, input->ledbit);		set_bit(LED_COMPOSE, input->ledbit);		set_bit(LED_KANA,    input->ledbit);		for (i = 0; i < sizeof(hidp_keycode); i++)			set_bit(hidp_keycode[i], input->keybit);		clear_bit(0, input->keybit);	}	if (req->subclass & 0x80) {		input->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);		input->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);		input->relbit[0] = BIT(REL_X) | BIT(REL_Y);		input->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA);		input->relbit[0] |= BIT(REL_WHEEL);	}	input->event = hidp_input_event;	input_register_device(input);}int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock){	struct hidp_session *session, *s;	int err;	BT_DBG("");	if (bacmp(&bt_sk(ctrl_sock->sk)->src, &bt_sk(intr_sock->sk)->src) ||			bacmp(&bt_sk(ctrl_sock->sk)->dst, &bt_sk(intr_sock->sk)->dst))		return -ENOTUNIQ;	session = kmalloc(sizeof(struct hidp_session), GFP_KERNEL);	if (!session)		return -ENOMEM;	memset(session, 0, sizeof(struct hidp_session));	session->input = input_allocate_device();	if (!session->input) {		kfree(session);		return -ENOMEM;	}	down_write(&hidp_session_sem);	s = __hidp_get_session(&bt_sk(ctrl_sock->sk)->dst);	if (s && s->state == BT_CONNECTED) {		err = -EEXIST;		goto failed;	}	bacpy(&session->bdaddr, &bt_sk(ctrl_sock->sk)->dst);	session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->omtu, l2cap_pi(ctrl_sock->sk)->imtu);	session->intr_mtu = min_t(uint, l2cap_pi(intr_sock->sk)->omtu, l2cap_pi(intr_sock->sk)->imtu);	BT_DBG("ctrl mtu %d intr mtu %d", session->ctrl_mtu, session->intr_mtu);	session->ctrl_sock = ctrl_sock;	session->intr_sock = intr_sock;	session->state     = BT_CONNECTED;	init_timer(&session->timer);	session->timer.function = hidp_idle_timeout;	session->timer.data     = (unsigned long) session;	skb_queue_head_init(&session->ctrl_transmit);	skb_queue_head_init(&session->intr_transmit);	session->flags   = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);	session->idle_to = req->idle_to;	if (session->input)		hidp_setup_input(session, req);	__hidp_link_session(session);	hidp_set_timer(session);	err = kernel_thread(hidp_session, session, CLONE_KERNEL);	if (err < 0)		goto unlink;	if (session->input) {		hidp_send_ctrl_message(session,			HIDP_TRANS_SET_PROTOCOL | HIDP_PROTO_BOOT, NULL, 0);		session->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE);		session->leds = 0xff;		hidp_input_event(session->input, EV_LED, 0, 0);	}	up_write(&hidp_session_sem);	return 0;unlink:	hidp_del_timer(session);	__hidp_unlink_session(session);	if (session->input) {		input_unregister_device(session->input);		session->input = NULL; /* don't try to free it here */	}failed:	up_write(&hidp_session_sem);	kfree(session->input);	kfree(session);	return err;}int hidp_del_connection(struct hidp_conndel_req *req){	struct hidp_session *session;	int err = 0;	BT_DBG("");	down_read(&hidp_session_sem);	session = __hidp_get_session(&req->bdaddr);	if (session) {		if (req->flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG)) {			hidp_send_ctrl_message(session,				HIDP_TRANS_HID_CONTROL | HIDP_CTRL_VIRTUAL_CABLE_UNPLUG, NULL, 0);		} else {			/* Flush the transmit queues */			skb_queue_purge(&session->ctrl_transmit);			skb_queue_purge(&session->intr_transmit);			/* Kill session thread */			atomic_inc(&session->terminate);			hidp_schedule(session);		}	} else		err = -ENOENT;	up_read(&hidp_session_sem);	return err;}int hidp_get_connlist(struct hidp_connlist_req *req){	struct list_head *p;	int err = 0, n = 0;	BT_DBG("");	down_read(&hidp_session_sem);	list_for_each(p, &hidp_session_list) {		struct hidp_session *session;		struct hidp_conninfo ci;		session = list_entry(p, struct hidp_session, list);		__hidp_copy_session(session, &ci);		if (copy_to_user(req->ci, &ci, sizeof(ci))) {			err = -EFAULT;			break;		}		if (++n >= req->cnum)			break;		req->ci++;	}	req->cnum = n;	up_read(&hidp_session_sem);	return err;}int hidp_get_conninfo(struct hidp_conninfo *ci){	struct hidp_session *session;	int err = 0;	down_read(&hidp_session_sem);	session = __hidp_get_session(&ci->bdaddr);	if (session)		__hidp_copy_session(session, ci);	else		err = -ENOENT;	up_read(&hidp_session_sem);	return err;}static int __init hidp_init(void){	l2cap_load();	BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION);	return hidp_init_sockets();}static void __exit hidp_exit(void){	hidp_cleanup_sockets();}module_init(hidp_init);module_exit(hidp_exit);MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");MODULE_DESCRIPTION("Bluetooth HIDP ver " VERSION);MODULE_VERSION(VERSION);MODULE_LICENSE("GPL");MODULE_ALIAS("bt-proto-6");

⌨️ 快捷键说明

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