xref: /linux/drivers/hid/hid-hyperv.c (revision f4cdf7ca9a1fdcca413157df19753f388a5a224e)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *  Copyright (c) 2009, Citrix Systems, Inc.
4  *  Copyright (c) 2010, Microsoft Corporation.
5  *  Copyright (c) 2011, Novell Inc.
6  */
7 #include <linux/init.h>
8 #include <linux/module.h>
9 #include <linux/device.h>
10 #include <linux/completion.h>
11 #include <linux/input.h>
12 #include <linux/hid.h>
13 #include <linux/hiddev.h>
14 #include <linux/hyperv.h>
15 
16 #if IS_ENABLED(CONFIG_HID_HYPERV_MOUSE_KUNIT_TEST)
17 #include <kunit/test.h>
18 #endif
19 
20 struct hv_input_dev_info {
21 	unsigned int size;
22 	unsigned short vendor;
23 	unsigned short product;
24 	unsigned short version;
25 	unsigned short reserved[11];
26 };
27 
28 /*
29  * Current version
30  *
31  * History:
32  * Beta, RC < 2008/1/22        1,0
33  * RC > 2008/1/22              2,0
34  */
35 #define SYNTHHID_INPUT_VERSION_MAJOR	2
36 #define SYNTHHID_INPUT_VERSION_MINOR	0
37 #define SYNTHHID_INPUT_VERSION		(SYNTHHID_INPUT_VERSION_MINOR | \
38 					 (SYNTHHID_INPUT_VERSION_MAJOR << 16))
39 
40 
41 #pragma pack(push, 1)
42 /*
43  * Message types in the synthetic input protocol
44  */
45 enum synthhid_msg_type {
46 	SYNTH_HID_PROTOCOL_REQUEST,
47 	SYNTH_HID_PROTOCOL_RESPONSE,
48 	SYNTH_HID_INITIAL_DEVICE_INFO,
49 	SYNTH_HID_INITIAL_DEVICE_INFO_ACK,
50 	SYNTH_HID_INPUT_REPORT,
51 	SYNTH_HID_MAX
52 };
53 
54 /*
55  * Basic message structures.
56  */
57 struct synthhid_msg_hdr {
58 	enum synthhid_msg_type type;
59 	u32 size;
60 };
61 
62 union synthhid_version {
63 	struct {
64 		u16 minor_version;
65 		u16 major_version;
66 	};
67 	u32 version;
68 };
69 
70 /*
71  * Protocol messages
72  */
73 struct synthhid_protocol_request {
74 	struct synthhid_msg_hdr header;
75 	union synthhid_version version_requested;
76 };
77 
78 struct synthhid_protocol_response {
79 	struct synthhid_msg_hdr header;
80 	union synthhid_version version_requested;
81 	unsigned char approved;
82 };
83 
84 struct synthhid_device_info {
85 	struct synthhid_msg_hdr header;
86 	struct hv_input_dev_info hid_dev_info;
87 	struct hid_descriptor hid_descriptor;
88 };
89 
90 struct synthhid_device_info_ack {
91 	struct synthhid_msg_hdr header;
92 	unsigned char reserved;
93 };
94 
95 struct synthhid_input_report {
96 	struct synthhid_msg_hdr header;
97 	char buffer[];
98 };
99 
100 #pragma pack(pop)
101 
102 #define INPUTVSC_SEND_RING_BUFFER_SIZE	VMBUS_RING_SIZE(36 * 1024)
103 #define INPUTVSC_RECV_RING_BUFFER_SIZE	VMBUS_RING_SIZE(36 * 1024)
104 
105 
106 enum pipe_prot_msg_type {
107 	PIPE_MESSAGE_INVALID,
108 	PIPE_MESSAGE_DATA,
109 	PIPE_MESSAGE_MAXIMUM
110 };
111 
112 
113 struct pipe_prt_msg {
114 	enum pipe_prot_msg_type type;
115 	u32 size;
116 	char data[];
117 };
118 
119 struct  mousevsc_prt_msg {
120 	enum pipe_prot_msg_type type;
121 	u32 size;
122 	union {
123 		struct synthhid_protocol_request request;
124 		struct synthhid_protocol_response response;
125 		struct synthhid_device_info_ack ack;
126 	};
127 };
128 
129 /*
130  * Represents an mousevsc device
131  */
132 struct mousevsc_dev {
133 	struct hv_device	*device;
134 	bool			init_complete;
135 	bool			connected;
136 	struct mousevsc_prt_msg	protocol_req;
137 	struct mousevsc_prt_msg	protocol_resp;
138 	/* Synchronize the request/response if needed */
139 	struct completion	wait_event;
140 	int			dev_info_status;
141 
142 	struct hid_descriptor	*hid_desc;
143 	unsigned char		*report_desc;
144 	u32			report_desc_size;
145 	struct hv_input_dev_info hid_dev_info;
146 	struct hid_device       *hid_device;
147 	u8			input_buf[HID_MAX_BUFFER_SIZE];
148 };
149 
150 
151 static struct mousevsc_dev *mousevsc_alloc_device(struct hv_device *device)
152 {
153 	struct mousevsc_dev *input_dev;
154 
155 	input_dev = kzalloc_obj(struct mousevsc_dev);
156 
157 	if (!input_dev)
158 		return NULL;
159 
160 	input_dev->device = device;
161 	hv_set_drvdata(device, input_dev);
162 	init_completion(&input_dev->wait_event);
163 	input_dev->init_complete = false;
164 
165 	return input_dev;
166 }
167 
168 static void mousevsc_free_device(struct mousevsc_dev *device)
169 {
170 	kfree(device->hid_desc);
171 	kfree(device->report_desc);
172 	hv_set_drvdata(device->device, NULL);
173 	kfree(device);
174 }
175 
176 static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device,
177 					    struct synthhid_device_info *device_info,
178 					    u32 device_info_size)
179 {
180 	int ret = 0;
181 	struct hid_descriptor *desc;
182 	struct mousevsc_prt_msg ack;
183 	size_t desc_offset;
184 	size_t desc_size;
185 
186 	input_device->dev_info_status = -ENOMEM;
187 
188 	if (device_info_size < sizeof(*device_info)) {
189 		input_device->dev_info_status = -EINVAL;
190 		goto cleanup;
191 	}
192 
193 	input_device->hid_dev_info = device_info->hid_dev_info;
194 	desc = &device_info->hid_descriptor;
195 	desc_offset = offsetof(struct synthhid_device_info, hid_descriptor);
196 	desc_size = device_info_size - desc_offset;
197 	if (desc->bLength == 0)
198 		goto cleanup;
199 	if (desc->bLength < sizeof(*desc) || desc->bLength > desc_size) {
200 		input_device->dev_info_status = -EINVAL;
201 		goto cleanup;
202 	}
203 
204 	/* The pointer is not NULL when we resume from hibernation */
205 	kfree(input_device->hid_desc);
206 	input_device->hid_desc = kmemdup(desc, desc->bLength, GFP_ATOMIC);
207 
208 	if (!input_device->hid_desc)
209 		goto cleanup;
210 
211 	input_device->report_desc_size = le16_to_cpu(
212 					desc->rpt_desc.wDescriptorLength);
213 	if (input_device->report_desc_size == 0) {
214 		input_device->dev_info_status = -EINVAL;
215 		goto cleanup;
216 	}
217 	if (input_device->report_desc_size > desc_size - desc->bLength) {
218 		input_device->dev_info_status = -EINVAL;
219 		goto cleanup;
220 	}
221 
222 	/* The pointer is not NULL when we resume from hibernation */
223 	kfree(input_device->report_desc);
224 	input_device->report_desc = kzalloc(input_device->report_desc_size,
225 					  GFP_ATOMIC);
226 
227 	if (!input_device->report_desc) {
228 		input_device->dev_info_status = -ENOMEM;
229 		goto cleanup;
230 	}
231 
232 	memcpy(input_device->report_desc,
233 	       ((unsigned char *)desc) + desc->bLength,
234 	       le16_to_cpu(desc->rpt_desc.wDescriptorLength));
235 
236 	/* Send the ack */
237 	memset(&ack, 0, sizeof(struct mousevsc_prt_msg));
238 
239 	ack.type = PIPE_MESSAGE_DATA;
240 	ack.size = sizeof(struct synthhid_device_info_ack);
241 
242 	ack.ack.header.type = SYNTH_HID_INITIAL_DEVICE_INFO_ACK;
243 	ack.ack.header.size = 1;
244 	ack.ack.reserved = 0;
245 
246 	if (IS_ENABLED(CONFIG_HID_HYPERV_MOUSE_KUNIT_TEST) &&
247 	    !input_device->device) {
248 		ret = 0;
249 	} else {
250 		ret = vmbus_sendpacket(input_device->device->channel,
251 				       &ack,
252 				       sizeof(struct pipe_prt_msg) +
253 				       sizeof(struct synthhid_device_info_ack),
254 				       (unsigned long)&ack,
255 				       VM_PKT_DATA_INBAND,
256 				       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
257 	}
258 
259 	if (!ret)
260 		input_device->dev_info_status = 0;
261 
262 cleanup:
263 	complete(&input_device->wait_event);
264 
265 	return;
266 }
267 
268 static void mousevsc_on_receive(struct hv_device *device,
269 				struct vmpacket_descriptor *packet)
270 {
271 	struct pipe_prt_msg *pipe_msg;
272 	struct synthhid_msg_hdr *hid_msg_hdr;
273 	struct mousevsc_dev *input_dev = hv_get_drvdata(device);
274 	struct synthhid_input_report *input_report;
275 	size_t len;
276 
277 	pipe_msg = (struct pipe_prt_msg *)((unsigned long)packet +
278 						(packet->offset8 << 3));
279 
280 	if (pipe_msg->type != PIPE_MESSAGE_DATA)
281 		return;
282 
283 	hid_msg_hdr = (struct synthhid_msg_hdr *)pipe_msg->data;
284 
285 	switch (hid_msg_hdr->type) {
286 	case SYNTH_HID_PROTOCOL_RESPONSE:
287 		len = struct_size(pipe_msg, data, pipe_msg->size);
288 
289 		/*
290 		 * While it will be impossible for us to protect against
291 		 * malicious/buggy hypervisor/host, add a check here to
292 		 * ensure we don't corrupt memory.
293 		 */
294 		if (WARN_ON(len > sizeof(struct mousevsc_prt_msg)))
295 			break;
296 
297 		memcpy(&input_dev->protocol_resp, pipe_msg, len);
298 		complete(&input_dev->wait_event);
299 		break;
300 
301 	case SYNTH_HID_INITIAL_DEVICE_INFO:
302 		if (WARN_ON_ONCE(pipe_msg->size <
303 				 sizeof(struct synthhid_device_info)))
304 			break;
305 
306 		/*
307 		 * Parse out the device info into device attr,
308 		 * hid desc and report desc
309 		 */
310 		mousevsc_on_receive_device_info(input_dev,
311 						(struct synthhid_device_info *)pipe_msg->data,
312 						pipe_msg->size);
313 		break;
314 	case SYNTH_HID_INPUT_REPORT:
315 		input_report =
316 			(struct synthhid_input_report *)pipe_msg->data;
317 		if (!input_dev->init_complete)
318 			break;
319 
320 		len = min(input_report->header.size,
321 			  (u32)sizeof(input_dev->input_buf));
322 		memcpy(input_dev->input_buf, input_report->buffer, len);
323 		hid_input_report(input_dev->hid_device, HID_INPUT_REPORT,
324 				 input_dev->input_buf, len, 1);
325 
326 		pm_wakeup_hard_event(&input_dev->device->device);
327 
328 		break;
329 	default:
330 		pr_err("unsupported hid msg type - type %d len %d\n",
331 		       hid_msg_hdr->type, hid_msg_hdr->size);
332 		break;
333 	}
334 
335 }
336 
337 static void mousevsc_on_channel_callback(void *context)
338 {
339 	struct hv_device *device = context;
340 	struct vmpacket_descriptor *desc;
341 
342 	foreach_vmbus_pkt(desc, device->channel) {
343 		switch (desc->type) {
344 		case VM_PKT_COMP:
345 			break;
346 
347 		case VM_PKT_DATA_INBAND:
348 			mousevsc_on_receive(device, desc);
349 			break;
350 
351 		default:
352 			pr_err("Unhandled packet type %d, tid %llx len %d\n",
353 			       desc->type, desc->trans_id, desc->len8 * 8);
354 			break;
355 		}
356 	}
357 }
358 
359 static int mousevsc_connect_to_vsp(struct hv_device *device)
360 {
361 	int ret = 0;
362 	unsigned long t;
363 	struct mousevsc_dev *input_dev = hv_get_drvdata(device);
364 	struct mousevsc_prt_msg *request;
365 	struct mousevsc_prt_msg *response;
366 
367 	reinit_completion(&input_dev->wait_event);
368 
369 	request = &input_dev->protocol_req;
370 	memset(request, 0, sizeof(struct mousevsc_prt_msg));
371 
372 	request->type = PIPE_MESSAGE_DATA;
373 	request->size = sizeof(struct synthhid_protocol_request);
374 	request->request.header.type = SYNTH_HID_PROTOCOL_REQUEST;
375 	request->request.header.size = sizeof(unsigned int);
376 	request->request.version_requested.version = SYNTHHID_INPUT_VERSION;
377 
378 	ret = vmbus_sendpacket(device->channel, request,
379 				sizeof(struct pipe_prt_msg) +
380 				sizeof(struct synthhid_protocol_request),
381 				(unsigned long)request,
382 				VM_PKT_DATA_INBAND,
383 				VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
384 	if (ret)
385 		goto cleanup;
386 
387 	t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ);
388 	if (!t) {
389 		ret = -ETIMEDOUT;
390 		goto cleanup;
391 	}
392 
393 	response = &input_dev->protocol_resp;
394 
395 	if (!response->response.approved) {
396 		pr_err("synthhid protocol request failed (version %d)\n",
397 		       SYNTHHID_INPUT_VERSION);
398 		ret = -ENODEV;
399 		goto cleanup;
400 	}
401 
402 	t = wait_for_completion_timeout(&input_dev->wait_event, 5*HZ);
403 	if (!t) {
404 		ret = -ETIMEDOUT;
405 		goto cleanup;
406 	}
407 
408 	/*
409 	 * We should have gotten the device attr, hid desc and report
410 	 * desc at this point
411 	 */
412 	ret = input_dev->dev_info_status;
413 
414 cleanup:
415 	return ret;
416 }
417 
418 static int mousevsc_hid_parse(struct hid_device *hid)
419 {
420 	struct hv_device *dev = hid_get_drvdata(hid);
421 	struct mousevsc_dev *input_dev = hv_get_drvdata(dev);
422 
423 	return hid_parse_report(hid, input_dev->report_desc,
424 				input_dev->report_desc_size);
425 }
426 
427 static int mousevsc_hid_open(struct hid_device *hid)
428 {
429 	return 0;
430 }
431 
432 static int mousevsc_hid_start(struct hid_device *hid)
433 {
434 	return 0;
435 }
436 
437 static void mousevsc_hid_close(struct hid_device *hid)
438 {
439 }
440 
441 static void mousevsc_hid_stop(struct hid_device *hid)
442 {
443 }
444 
445 static int mousevsc_hid_raw_request(struct hid_device *hid,
446 				    unsigned char report_num,
447 				    __u8 *buf, size_t len,
448 				    unsigned char rtype,
449 				    int reqtype)
450 {
451 	return 0;
452 }
453 
454 static int mousevsc_hid_probe(struct hid_device *hid_dev, const struct hid_device_id *id)
455 {
456 	int ret;
457 
458 	ret = hid_parse(hid_dev);
459 	if (ret) {
460 		hid_err(hid_dev, "parse failed\n");
461 		return ret;
462 	}
463 
464 	ret = hid_hw_start(hid_dev, HID_CONNECT_HIDINPUT | HID_CONNECT_HIDDEV);
465 	if (ret) {
466 		hid_err(hid_dev, "hw start failed\n");
467 		return ret;
468 	}
469 
470 	return 0;
471 }
472 
473 static const struct hid_ll_driver mousevsc_ll_driver = {
474 	.parse = mousevsc_hid_parse,
475 	.open = mousevsc_hid_open,
476 	.close = mousevsc_hid_close,
477 	.start = mousevsc_hid_start,
478 	.stop = mousevsc_hid_stop,
479 	.raw_request = mousevsc_hid_raw_request,
480 };
481 
482 static const struct hid_device_id mousevsc_devices[] = {
483 	{ HID_DEVICE(BUS_VIRTUAL, HID_GROUP_ANY, 0x045E, 0x0621) },
484 	{ }
485 };
486 
487 static struct hid_driver mousevsc_hid_driver = {
488 	.name = "hid-hyperv",
489 	.id_table = mousevsc_devices,
490 	.probe = mousevsc_hid_probe,
491 };
492 
493 static int mousevsc_probe(struct hv_device *device,
494 			const struct hv_vmbus_device_id *dev_id)
495 {
496 	int ret;
497 	struct mousevsc_dev *input_dev;
498 	struct hid_device *hid_dev;
499 
500 	input_dev = mousevsc_alloc_device(device);
501 
502 	if (!input_dev)
503 		return -ENOMEM;
504 
505 	ret = vmbus_open(device->channel,
506 		INPUTVSC_SEND_RING_BUFFER_SIZE,
507 		INPUTVSC_RECV_RING_BUFFER_SIZE,
508 		NULL,
509 		0,
510 		mousevsc_on_channel_callback,
511 		device
512 		);
513 
514 	if (ret)
515 		goto probe_err0;
516 
517 	ret = mousevsc_connect_to_vsp(device);
518 
519 	if (ret)
520 		goto probe_err1;
521 
522 	/* workaround SA-167 */
523 	if (input_dev->report_desc[14] == 0x25)
524 		input_dev->report_desc[14] = 0x29;
525 
526 	hid_dev = hid_allocate_device();
527 	if (IS_ERR(hid_dev)) {
528 		ret = PTR_ERR(hid_dev);
529 		goto probe_err1;
530 	}
531 
532 	hid_dev->ll_driver = &mousevsc_ll_driver;
533 	hid_dev->bus = BUS_VIRTUAL;
534 	hid_dev->vendor = input_dev->hid_dev_info.vendor;
535 	hid_dev->product = input_dev->hid_dev_info.product;
536 	hid_dev->version = input_dev->hid_dev_info.version;
537 	input_dev->hid_device = hid_dev;
538 
539 	sprintf(hid_dev->name, "%s", "Microsoft Vmbus HID-compliant Mouse");
540 
541 	hid_set_drvdata(hid_dev, device);
542 
543 	ret = hid_add_device(hid_dev);
544 	if (ret)
545 		goto probe_err2;
546 
547 	device_init_wakeup(&device->device, true);
548 
549 	input_dev->connected = true;
550 	input_dev->init_complete = true;
551 
552 	return ret;
553 
554 probe_err2:
555 	hid_destroy_device(hid_dev);
556 
557 probe_err1:
558 	vmbus_close(device->channel);
559 
560 probe_err0:
561 	mousevsc_free_device(input_dev);
562 
563 	return ret;
564 }
565 
566 
567 static void mousevsc_remove(struct hv_device *dev)
568 {
569 	struct mousevsc_dev *input_dev = hv_get_drvdata(dev);
570 
571 	device_init_wakeup(&dev->device, false);
572 	vmbus_close(dev->channel);
573 	hid_hw_stop(input_dev->hid_device);
574 	hid_destroy_device(input_dev->hid_device);
575 	mousevsc_free_device(input_dev);
576 }
577 
578 static int mousevsc_suspend(struct hv_device *dev)
579 {
580 	vmbus_close(dev->channel);
581 
582 	return 0;
583 }
584 
585 static int mousevsc_resume(struct hv_device *dev)
586 {
587 	int ret;
588 
589 	ret = vmbus_open(dev->channel,
590 			 INPUTVSC_SEND_RING_BUFFER_SIZE,
591 			 INPUTVSC_RECV_RING_BUFFER_SIZE,
592 			 NULL, 0,
593 			 mousevsc_on_channel_callback,
594 			 dev);
595 	if (ret)
596 		return ret;
597 
598 	ret = mousevsc_connect_to_vsp(dev);
599 	return ret;
600 }
601 
602 static const struct hv_vmbus_device_id id_table[] = {
603 	/* Mouse guid */
604 	{ HV_MOUSE_GUID, },
605 	{ },
606 };
607 
608 MODULE_DEVICE_TABLE(vmbus, id_table);
609 
610 static struct  hv_driver mousevsc_drv = {
611 	.name = KBUILD_MODNAME,
612 	.id_table = id_table,
613 	.probe = mousevsc_probe,
614 	.remove = mousevsc_remove,
615 	.suspend = mousevsc_suspend,
616 	.resume = mousevsc_resume,
617 	.driver = {
618 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
619 	},
620 };
621 
622 static int __init mousevsc_init(void)
623 {
624 	int ret;
625 
626 	ret = hid_register_driver(&mousevsc_hid_driver);
627 	if (ret)
628 		return ret;
629 
630 	ret = vmbus_driver_register(&mousevsc_drv);
631 	if (ret)
632 		hid_unregister_driver(&mousevsc_hid_driver);
633 
634 	return ret;
635 }
636 
637 static void __exit mousevsc_exit(void)
638 {
639 	vmbus_driver_unregister(&mousevsc_drv);
640 	hid_unregister_driver(&mousevsc_hid_driver);
641 }
642 
643 MODULE_LICENSE("GPL");
644 MODULE_DESCRIPTION("Microsoft Hyper-V Synthetic HID Driver");
645 
646 #if IS_ENABLED(CONFIG_HID_HYPERV_MOUSE_KUNIT_TEST)
647 static struct mousevsc_dev *mousevsc_kunit_alloc_dev(struct kunit *test)
648 {
649 	struct mousevsc_dev *input_dev;
650 
651 	input_dev = kunit_kzalloc(test, sizeof(*input_dev), GFP_KERNEL);
652 	if (!input_dev)
653 		return NULL;
654 
655 	init_completion(&input_dev->wait_event);
656 
657 	return input_dev;
658 }
659 
660 static void mousevsc_device_info_zero_blength(struct kunit *test)
661 {
662 	struct synthhid_device_info *info;
663 	struct mousevsc_dev *input_dev;
664 
665 	input_dev = mousevsc_kunit_alloc_dev(test);
666 	KUNIT_ASSERT_NOT_NULL(test, input_dev);
667 	info = kunit_kzalloc(test, sizeof(*info), GFP_KERNEL);
668 	KUNIT_ASSERT_NOT_NULL(test, info);
669 
670 	info->hid_descriptor.bLength = 0;
671 
672 	mousevsc_on_receive_device_info(input_dev, info, sizeof(*info));
673 
674 	KUNIT_EXPECT_EQ(test, input_dev->dev_info_status, -ENOMEM);
675 }
676 
677 static void mousevsc_device_info_valid_descriptor(struct kunit *test)
678 {
679 	struct synthhid_device_info *info;
680 	struct mousevsc_dev *input_dev;
681 	u8 *report;
682 
683 	input_dev = mousevsc_kunit_alloc_dev(test);
684 	KUNIT_ASSERT_NOT_NULL(test, input_dev);
685 	info = kunit_kzalloc(test, sizeof(*info) + 4, GFP_KERNEL);
686 	KUNIT_ASSERT_NOT_NULL(test, info);
687 
688 	info->hid_descriptor.bLength = sizeof(struct hid_descriptor);
689 	info->hid_descriptor.rpt_desc.wDescriptorLength = cpu_to_le16(4);
690 	report = ((u8 *)&info->hid_descriptor) + info->hid_descriptor.bLength;
691 	memset(report, 0x42, 4);
692 
693 	mousevsc_on_receive_device_info(input_dev, info, sizeof(*info) + 4);
694 
695 	KUNIT_EXPECT_EQ(test, input_dev->dev_info_status, 0);
696 	KUNIT_EXPECT_EQ(test, input_dev->report_desc_size, 4);
697 	KUNIT_EXPECT_MEMEQ(test, input_dev->report_desc, report, 4);
698 
699 	kfree(input_dev->hid_desc);
700 	kfree(input_dev->report_desc);
701 }
702 
703 static void mousevsc_device_info_report_desc_oob(struct kunit *test)
704 {
705 	struct synthhid_device_info *info;
706 	struct mousevsc_dev *input_dev;
707 	u8 *report;
708 
709 	input_dev = mousevsc_kunit_alloc_dev(test);
710 	KUNIT_ASSERT_NOT_NULL(test, input_dev);
711 	info = kunit_kzalloc(test, sizeof(*info) + 8, GFP_KERNEL);
712 	KUNIT_ASSERT_NOT_NULL(test, info);
713 
714 	info->hid_descriptor.bLength = sizeof(struct hid_descriptor);
715 	info->hid_descriptor.rpt_desc.wDescriptorLength = cpu_to_le16(64);
716 	report = ((u8 *)&info->hid_descriptor) + info->hid_descriptor.bLength;
717 	memset(report, 0x42, 8);
718 
719 	mousevsc_on_receive_device_info(input_dev, info, sizeof(*info) + 8);
720 
721 	KUNIT_EXPECT_EQ(test, input_dev->dev_info_status, -EINVAL);
722 
723 	kfree(input_dev->hid_desc);
724 }
725 
726 static struct kunit_case mousevsc_test_cases[] = {
727 	KUNIT_CASE(mousevsc_device_info_zero_blength),
728 	KUNIT_CASE(mousevsc_device_info_valid_descriptor),
729 	KUNIT_CASE(mousevsc_device_info_report_desc_oob),
730 	{}
731 };
732 
733 static struct kunit_suite mousevsc_test_suite = {
734 	.name = "hid_hyperv_mouse",
735 	.test_cases = mousevsc_test_cases,
736 };
737 
738 kunit_test_suite(mousevsc_test_suite);
739 #endif
740 
741 module_init(mousevsc_init);
742 module_exit(mousevsc_exit);
743