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

📄 core.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	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;	}	if (session->hid) {		vendor  = session->hid->vendor;		product = session->hid->product;	}	daemonize("khidpd_%04x%04x", vendor, product);	set_user_nice(current, -15);	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 (session->input) {		input_unregister_device(session->input);		session->input = NULL;	}	if (session->hid) {		if (session->hid->claimed & HID_CLAIMED_INPUT)			hidinput_disconnect(session->hid);		hid_free_device(session->hid);	}	fput(session->intr_sock->file);	wait_event_timeout(*(ctrl_sk->sk_sleep),		(ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500));	fput(session->ctrl_sock->file);	__hidp_unlink_session(session);	up_write(&hidp_session_sem);	kfree(session);	return 0;}static struct device *hidp_get_device(struct hidp_session *session){	bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src;	bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst;	struct hci_dev *hdev;	struct hci_conn *conn;	hdev = hci_get_route(dst, src);	if (!hdev)		return NULL;	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);	hci_dev_put(hdev);	return conn ? &conn->dev : NULL;}static inline int hidp_setup_input(struct hidp_session *session, struct hidp_connadd_req *req){	struct input_dev *input = session->input;	int i;	input_set_drvdata(input, 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_MASK(EV_KEY) | BIT_MASK(EV_REL);		input->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |			BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);		input->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);		input->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_SIDE) |			BIT_MASK(BTN_EXTRA);		input->relbit[0] |= BIT_MASK(REL_WHEEL);	}	input->dev.parent = hidp_get_device(session);	input->event = hidp_input_event;	return input_register_device(input);}static int hidp_open(struct hid_device *hid){	return 0;}static void hidp_close(struct hid_device *hid){}static const struct {	__u16 idVendor;	__u16 idProduct;	unsigned quirks;} hidp_blacklist[] = {	/* Apple wireless Mighty Mouse */	{ 0x05ac, 0x030c, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL },	{ }	/* Terminating entry */};static void hidp_setup_quirks(struct hid_device *hid){	unsigned int n;	for (n = 0; hidp_blacklist[n].idVendor; n++)		if (hidp_blacklist[n].idVendor == le16_to_cpu(hid->vendor) &&				hidp_blacklist[n].idProduct == le16_to_cpu(hid->product))			hid->quirks = hidp_blacklist[n].quirks;}static inline void hidp_setup_hid(struct hidp_session *session, struct hidp_connadd_req *req){	struct hid_device *hid = session->hid;	struct hid_report *report;	bdaddr_t src, dst;	baswap(&src, &bt_sk(session->ctrl_sock->sk)->src);	baswap(&dst, &bt_sk(session->ctrl_sock->sk)->dst);	hid->driver_data = session;	hid->country = req->country;	hid->bus     = BUS_BLUETOOTH;	hid->vendor  = req->vendor;	hid->product = req->product;	hid->version = req->version;	strncpy(hid->name, req->name, 128);	strncpy(hid->phys, batostr(&src), 64);	strncpy(hid->uniq, batostr(&dst), 64);	hid->dev = hidp_get_device(session);	hid->hid_open  = hidp_open;	hid->hid_close = hidp_close;	hid->hidinput_input_event = hidp_hidinput_event;	hidp_setup_quirks(hid);	list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list)		hidp_send_report(session, report);	list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list)		hidp_send_report(session, report);	if (hidinput_connect(hid) == 0)		hid->claimed |= HID_CLAIMED_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 = kzalloc(sizeof(struct hidp_session), GFP_KERNEL);	if (!session)		return -ENOMEM;	BT_DBG("rd_data %p rd_size %d", req->rd_data, req->rd_size);	if (req->rd_size > 0) {		unsigned char *buf = kmalloc(req->rd_size, GFP_KERNEL);		if (!buf) {			kfree(session);			return -ENOMEM;		}		if (copy_from_user(buf, req->rd_data, req->rd_size)) {			kfree(buf);			kfree(session);			return -EFAULT;		}		session->hid = hid_parse_report(buf, req->rd_size);		kfree(buf);		if (!session->hid) {			kfree(session);			return -EINVAL;		}	}	if (!session->hid) {		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) {		err = hidp_setup_input(session, req);		if (err < 0)			goto failed;	}	if (session->hid)		hidp_setup_hid(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);	if (session->hid)		hid_free_device(session->hid);	input_free_device(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 + -