1 /*-
2 * Copyright (c) 2017 Microsoft Corp.
3 * Copyright (c) 2023 Yuri <yuri@aetern.org>
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions, and the following
10 * disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include <sys/param.h>
28 #include <sys/bus.h>
29 #include <sys/cdefs.h>
30 #include <sys/conf.h>
31 #include <sys/kernel.h>
32 #include <sys/lock.h>
33 #include <sys/malloc.h>
34 #include <sys/module.h>
35 #include <sys/mutex.h>
36
37 #include <dev/evdev/input.h>
38
39 #include <dev/hid/hid.h>
40
41 #include <dev/hyperv/include/hyperv.h>
42 #include <dev/hyperv/include/vmbus_xact.h>
43 #include <dev/hyperv/utilities/hv_utilreg.h>
44 #include <dev/hyperv/utilities/vmbus_icreg.h>
45 #include <dev/hyperv/utilities/vmbus_icvar.h>
46
47 #include "hid_if.h"
48 #include "vmbus_if.h"
49
50 #define HV_HID_VER_MAJOR 2
51 #define HV_HID_VER_MINOR 0
52 #define HV_HID_VER (HV_HID_VER_MINOR | (HV_HID_VER_MAJOR) << 16)
53
54 #define HV_BUFSIZ (4 * PAGE_SIZE)
55 #define HV_HID_RINGBUFF_SEND_SZ (10 * PAGE_SIZE)
56 #define HV_HID_RINGBUFF_RECV_SZ (10 * PAGE_SIZE)
57
58 typedef struct {
59 device_t dev;
60 struct mtx mtx;
61 /* vmbus */
62 struct vmbus_channel *hs_chan;
63 struct vmbus_xact_ctx *hs_xact_ctx;
64 uint8_t *buf;
65 int buflen;
66 /* hid */
67 struct hid_device_info hdi;
68 hid_intr_t *intr;
69 bool intr_on;
70 void *intr_ctx;
71 uint8_t *rdesc;
72 } hv_hid_sc;
73
74 typedef enum {
75 SH_PROTO_REQ,
76 SH_PROTO_RESP,
77 SH_DEVINFO,
78 SH_DEVINFO_ACK,
79 SH_INPUT_REPORT,
80 } sh_msg_type;
81
82 typedef struct {
83 sh_msg_type type;
84 uint32_t size;
85 } __packed sh_msg_hdr;
86
87 typedef struct {
88 sh_msg_hdr hdr;
89 char data[];
90 } __packed sh_msg;
91
92 typedef struct {
93 sh_msg_hdr hdr;
94 uint32_t ver;
95 } __packed sh_proto_req;
96
97 typedef struct {
98 sh_msg_hdr hdr;
99 uint32_t ver;
100 uint32_t app;
101 } __packed sh_proto_resp;
102
103 typedef struct {
104 u_int size;
105 u_short vendor;
106 u_short product;
107 u_short version;
108 u_short reserved[11];
109 } __packed sh_devinfo;
110
111 /* Copied from linux/hid.h */
112 typedef struct {
113 uint8_t bDescriptorType;
114 uint16_t wDescriptorLength;
115 } __packed sh_hcdesc;
116
117 typedef struct {
118 uint8_t bLength;
119 uint8_t bDescriptorType;
120 uint16_t bcdHID;
121 uint8_t bCountryCode;
122 uint8_t bNumDescriptors;
123 sh_hcdesc hcdesc[1];
124 } __packed sh_hdesc;
125
126 typedef struct {
127 sh_msg_hdr hdr;
128 sh_devinfo devinfo;
129 sh_hdesc hdesc;
130 } __packed sh_devinfo_resp;
131
132 typedef struct {
133 sh_msg_hdr hdr;
134 uint8_t rsvd;
135 } __packed sh_devinfo_ack;
136
137 typedef struct {
138 sh_msg_hdr hdr;
139 char buffer[];
140 } __packed sh_input_report;
141
142 typedef enum {
143 HV_HID_MSG_INVALID,
144 HV_HID_MSG_DATA,
145 } hv_hid_msg_type;
146
147 typedef struct {
148 hv_hid_msg_type type;
149 uint32_t size;
150 char data[];
151 } hv_hid_pmsg;
152
153 typedef struct {
154 hv_hid_msg_type type;
155 uint32_t size;
156 union {
157 sh_msg msg;
158 sh_proto_req req;
159 sh_proto_resp resp;
160 sh_devinfo_resp dresp;
161 sh_devinfo_ack ack;
162 sh_input_report irep;
163 };
164 } hv_hid_msg;
165
166 #define HV_HID_REQ_SZ (sizeof(hv_hid_pmsg) + sizeof(sh_proto_req))
167 #define HV_HID_RESP_SZ (sizeof(hv_hid_pmsg) + sizeof(sh_proto_resp))
168 #define HV_HID_ACK_SZ (sizeof(hv_hid_pmsg) + sizeof(sh_devinfo_ack))
169
170 /* Somewhat arbitrary, enough to get the devinfo response */
171 #define HV_HID_REQ_MAX 256
172 #define HV_HID_RESP_MAX 256
173
174 static const struct vmbus_ic_desc vmbus_hid_descs[] = {
175 {
176 .ic_guid = { .hv_guid = {
177 0x9e, 0xb6, 0xa8, 0xcf, 0x4a, 0x5b, 0xc0, 0x4c,
178 0xb9, 0x8b, 0x8b, 0xa1, 0xa1, 0xf3, 0xf9, 0x5a} },
179 .ic_desc = "Hyper-V HID device"
180 },
181 VMBUS_IC_DESC_END
182 };
183
184 /* TODO: add GUID support to devmatch(8) to export vmbus_hid_descs directly */
185 const struct {
186 char *guid;
187 } vmbus_hid_descs_pnp[] = {{ "cfa8b69e-5b4a-4cc0-b98b-8ba1a1f3f95a" }};
188
189 static int hv_hid_attach(device_t dev);
190 static int hv_hid_detach(device_t dev);
191
192 static int
hv_hid_connect_vsp(hv_hid_sc * sc)193 hv_hid_connect_vsp(hv_hid_sc *sc)
194 {
195 struct vmbus_xact *xact;
196 hv_hid_msg *req;
197 const hv_hid_msg *resp;
198 size_t resplen;
199 int ret;
200
201 xact = vmbus_xact_get(sc->hs_xact_ctx, HV_HID_REQ_SZ);
202 if (xact == NULL) {
203 device_printf(sc->dev, "no xact for init");
204 return (ENODEV);
205 }
206 req = vmbus_xact_req_data(xact);
207 req->type = HV_HID_MSG_DATA;
208 req->size = sizeof(sh_proto_req);
209 req->req.hdr.type = SH_PROTO_REQ;
210 req->req.hdr.size = sizeof(u_int);
211 req->req.ver = HV_HID_VER;
212
213 vmbus_xact_activate(xact);
214 ret = vmbus_chan_send(sc->hs_chan,
215 VMBUS_CHANPKT_TYPE_INBAND,
216 VMBUS_CHANPKT_FLAG_RC,
217 req, HV_HID_REQ_SZ, (uint64_t)(uintptr_t)xact);
218 if (ret != 0) {
219 device_printf(sc->dev, "failed to send proto req\n");
220 vmbus_xact_deactivate(xact);
221 return (ret);
222 }
223 resp = vmbus_chan_xact_wait(sc->hs_chan, xact, &resplen, true);
224 if (resplen != HV_HID_RESP_SZ || !resp->resp.app) {
225 device_printf(sc->dev, "proto req failed\n");
226 ret = ENODEV;
227 }
228
229 vmbus_xact_put(xact);
230 return (ret);
231 }
232
233 static void
hv_hid_receive(hv_hid_sc * sc,struct vmbus_chanpkt_hdr * pkt)234 hv_hid_receive(hv_hid_sc *sc, struct vmbus_chanpkt_hdr *pkt)
235 {
236 const hv_hid_msg *msg;
237 sh_msg_type msg_type;
238 uint32_t msg_len;
239 void *rdesc;
240
241 msg = VMBUS_CHANPKT_CONST_DATA(pkt);
242 msg_len = VMBUS_CHANPKT_DATALEN(pkt);
243
244 if (msg->type != HV_HID_MSG_DATA)
245 return;
246
247 if (msg_len <= sizeof(hv_hid_pmsg)) {
248 device_printf(sc->dev, "invalid packet length\n");
249 return;
250 }
251 msg_type = msg->msg.hdr.type;
252 switch (msg_type) {
253 case SH_PROTO_RESP: {
254 struct vmbus_xact_ctx *xact_ctx;
255
256 xact_ctx = sc->hs_xact_ctx;
257 if (xact_ctx != NULL) {
258 vmbus_xact_ctx_wakeup(xact_ctx,
259 VMBUS_CHANPKT_CONST_DATA(pkt),
260 VMBUS_CHANPKT_DATALEN(pkt));
261 }
262 break;
263 }
264 case SH_DEVINFO: {
265 struct vmbus_xact *xact;
266 struct hid_device_info *hdi;
267 hv_hid_msg ack;
268 const sh_devinfo *devinfo;
269 const sh_hdesc *hdesc;
270
271 /* Send ack */
272 ack.type = HV_HID_MSG_DATA;
273 ack.size = sizeof(sh_devinfo_ack);
274 ack.ack.hdr.type = SH_DEVINFO_ACK;
275 ack.ack.hdr.size = 1;
276 ack.ack.rsvd = 0;
277
278 xact = vmbus_xact_get(sc->hs_xact_ctx, HV_HID_ACK_SZ);
279 if (xact == NULL)
280 break;
281 vmbus_xact_activate(xact);
282 (void) vmbus_chan_send(sc->hs_chan, VMBUS_CHANPKT_TYPE_INBAND,
283 0, &ack, HV_HID_ACK_SZ, (uint64_t)(uintptr_t)xact);
284 vmbus_xact_deactivate(xact);
285 vmbus_xact_put(xact);
286
287 /* Check for resume from hibernation */
288 if (sc->rdesc != NULL)
289 break;
290
291 /* Parse devinfo response */
292 devinfo = &msg->dresp.devinfo;
293 hdesc = &msg->dresp.hdesc;
294 if (hdesc->bLength == 0)
295 break;
296 hdi = &sc->hdi;
297 memset(hdi, 0, sizeof(*hdi));
298 hdi->rdescsize = le16toh(hdesc->hcdesc[0].wDescriptorLength);
299 if (hdi->rdescsize == 0)
300 break;
301 strlcpy(hdi->name, "Hyper-V", sizeof(hdi->name));
302 hdi->idBus = BUS_VIRTUAL;
303 hdi->idVendor = le16toh(devinfo->vendor);
304 hdi->idProduct = le16toh(devinfo->product);
305 hdi->idVersion = le16toh(devinfo->version);
306 /* Save rdesc copy */
307 rdesc = malloc(hdi->rdescsize, M_DEVBUF, M_WAITOK | M_ZERO);
308 memcpy(rdesc, (const uint8_t *)hdesc + hdesc->bLength,
309 hdi->rdescsize);
310 mtx_lock(&sc->mtx);
311 sc->rdesc = rdesc;
312 wakeup(sc);
313 mtx_unlock(&sc->mtx);
314 break;
315 }
316 case SH_INPUT_REPORT: {
317 mtx_lock(&sc->mtx);
318 if (sc->intr != NULL && sc->intr_on)
319 sc->intr(sc->intr_ctx,
320 __DECONST(void *, msg->irep.buffer),
321 msg->irep.hdr.size);
322 mtx_unlock(&sc->mtx);
323 break;
324 }
325 default:
326 break;
327 }
328 }
329
330 static void
hv_hid_read_channel(struct vmbus_channel * channel,void * ctx)331 hv_hid_read_channel(struct vmbus_channel *channel, void *ctx)
332 {
333 hv_hid_sc *sc;
334 uint8_t *buf;
335 int buflen;
336 int ret;
337
338 sc = ctx;
339 buf = sc->buf;
340 buflen = sc->buflen;
341 for (;;) {
342 struct vmbus_chanpkt_hdr *pkt;
343 int rcvd;
344
345 pkt = (struct vmbus_chanpkt_hdr *)buf;
346 rcvd = buflen;
347 ret = vmbus_chan_recv_pkt(channel, pkt, &rcvd);
348 if (__predict_false(ret == ENOBUFS)) {
349 buflen = sc->buflen * 2;
350 while (buflen < rcvd)
351 buflen *= 2;
352 buf = malloc(buflen, M_DEVBUF, M_WAITOK | M_ZERO);
353 device_printf(sc->dev, "expand recvbuf %d -> %d\n",
354 sc->buflen, buflen);
355 free(sc->buf, M_DEVBUF);
356 sc->buf = buf;
357 sc->buflen = buflen;
358 continue;
359 } else if (__predict_false(ret == EAGAIN)) {
360 /* No more channel packets; done! */
361 break;
362 }
363 KASSERT(ret == 0, ("vmbus_chan_recv_pkt failed: %d", ret));
364
365 switch (pkt->cph_type) {
366 case VMBUS_CHANPKT_TYPE_COMP:
367 case VMBUS_CHANPKT_TYPE_RXBUF:
368 device_printf(sc->dev, "unhandled event: %d\n",
369 pkt->cph_type);
370 break;
371 case VMBUS_CHANPKT_TYPE_INBAND:
372 hv_hid_receive(sc, pkt);
373 break;
374 default:
375 device_printf(sc->dev, "unknown event: %d\n",
376 pkt->cph_type);
377 break;
378 }
379 }
380 }
381
382 static int
hv_hid_probe(device_t dev)383 hv_hid_probe(device_t dev)
384 {
385 device_t bus;
386 const struct vmbus_ic_desc *d;
387
388 if (resource_disabled(device_get_name(dev), 0))
389 return (ENXIO);
390
391 bus = device_get_parent(dev);
392 for (d = vmbus_hid_descs; d->ic_desc != NULL; ++d) {
393 if (VMBUS_PROBE_GUID(bus, dev, &d->ic_guid) == 0) {
394 device_set_desc(dev, d->ic_desc);
395 return (BUS_PROBE_DEFAULT);
396 }
397 }
398
399 return (ENXIO);
400 }
401
402 static int
hv_hid_attach(device_t dev)403 hv_hid_attach(device_t dev)
404 {
405 device_t child;
406 hv_hid_sc *sc;
407 int ret;
408
409 sc = device_get_softc(dev);
410 sc->dev = dev;
411 mtx_init(&sc->mtx, "hvhid lock", NULL, MTX_DEF);
412 sc->hs_chan = vmbus_get_channel(dev);
413 sc->hs_xact_ctx = vmbus_xact_ctx_create(bus_get_dma_tag(dev),
414 HV_HID_REQ_MAX, HV_HID_RESP_MAX, 0);
415 if (sc->hs_xact_ctx == NULL) {
416 ret = ENOMEM;
417 goto out;
418 }
419 sc->buflen = HV_BUFSIZ;
420 sc->buf = malloc(sc->buflen, M_DEVBUF, M_WAITOK | M_ZERO);
421 vmbus_chan_set_readbatch(sc->hs_chan, false);
422 ret = vmbus_chan_open(sc->hs_chan, HV_HID_RINGBUFF_SEND_SZ,
423 HV_HID_RINGBUFF_RECV_SZ, NULL, 0, hv_hid_read_channel, sc);
424 if (ret != 0)
425 goto out;
426 ret = hv_hid_connect_vsp(sc);
427 if (ret != 0)
428 goto out;
429
430 /* Wait until we have devinfo (or arbitrary timeout of 3s) */
431 mtx_lock(&sc->mtx);
432 if (sc->rdesc == NULL)
433 ret = mtx_sleep(sc, &sc->mtx, 0, "hvhid", hz * 3);
434 mtx_unlock(&sc->mtx);
435 if (ret != 0) {
436 ret = ENODEV;
437 goto out;
438 }
439 child = device_add_child(sc->dev, "hidbus", -1);
440 if (child == NULL) {
441 device_printf(sc->dev, "failed to add hidbus\n");
442 ret = ENOMEM;
443 goto out;
444 }
445 device_set_ivars(child, &sc->hdi);
446 bus_attach_children(dev);
447 out:
448 if (ret != 0)
449 hv_hid_detach(dev);
450 return (ret);
451 }
452
453 static int
hv_hid_detach(device_t dev)454 hv_hid_detach(device_t dev)
455 {
456 hv_hid_sc *sc;
457 int ret;
458
459 sc = device_get_softc(dev);
460 ret = device_delete_children(dev);
461 if (ret != 0)
462 return (ret);
463 if (sc->hs_xact_ctx != NULL)
464 vmbus_xact_ctx_destroy(sc->hs_xact_ctx);
465 vmbus_chan_close(vmbus_get_channel(dev));
466 free(sc->buf, M_DEVBUF);
467 free(sc->rdesc, M_DEVBUF);
468 mtx_destroy(&sc->mtx);
469
470 return (0);
471 }
472
473 static void
hv_hid_intr_setup(device_t dev,device_t child __unused,hid_intr_t intr,void * ctx,struct hid_rdesc_info * rdesc)474 hv_hid_intr_setup(device_t dev, device_t child __unused, hid_intr_t intr,
475 void *ctx, struct hid_rdesc_info *rdesc)
476 {
477 hv_hid_sc *sc;
478
479 if (intr == NULL)
480 return;
481
482 sc = device_get_softc(dev);
483 sc->intr = intr;
484 sc->intr_on = false;
485 sc->intr_ctx = ctx;
486 rdesc->rdsize = rdesc->isize;
487 }
488
489 static void
hv_hid_intr_unsetup(device_t dev,device_t child __unused)490 hv_hid_intr_unsetup(device_t dev, device_t child __unused)
491 {
492 hv_hid_sc *sc;
493
494 sc = device_get_softc(dev);
495 sc->intr = NULL;
496 sc->intr_on = false;
497 sc->intr_ctx = NULL;
498 }
499
500 static int
hv_hid_intr_start(device_t dev,device_t child __unused)501 hv_hid_intr_start(device_t dev, device_t child __unused)
502 {
503 hv_hid_sc *sc;
504
505 sc = device_get_softc(dev);
506 mtx_lock(&sc->mtx);
507 sc->intr_on = true;
508 mtx_unlock(&sc->mtx);
509 return (0);
510 }
511
512 static int
hv_hid_intr_stop(device_t dev,device_t child __unused)513 hv_hid_intr_stop(device_t dev, device_t child __unused)
514 {
515 hv_hid_sc *sc;
516
517 sc = device_get_softc(dev);
518 mtx_lock(&sc->mtx);
519 sc->intr_on = false;
520 mtx_unlock(&sc->mtx);
521 return (0);
522 }
523
524 static int
hv_hid_get_rdesc(device_t dev,device_t child __unused,void * buf,hid_size_t len)525 hv_hid_get_rdesc(device_t dev, device_t child __unused, void *buf,
526 hid_size_t len)
527 {
528 hv_hid_sc *sc;
529
530 sc = device_get_softc(dev);
531 if (len < sc->hdi.rdescsize)
532 return (EMSGSIZE);
533 memcpy(buf, sc->rdesc, len);
534 return (0);
535 }
536
537 static device_method_t hv_hid_methods[] = {
538 DEVMETHOD(device_probe, hv_hid_probe),
539 DEVMETHOD(device_attach, hv_hid_attach),
540 DEVMETHOD(device_detach, hv_hid_detach),
541
542 DEVMETHOD(hid_intr_setup, hv_hid_intr_setup),
543 DEVMETHOD(hid_intr_unsetup, hv_hid_intr_unsetup),
544 DEVMETHOD(hid_intr_start, hv_hid_intr_start),
545 DEVMETHOD(hid_intr_stop, hv_hid_intr_stop),
546
547 DEVMETHOD(hid_get_rdesc, hv_hid_get_rdesc),
548 DEVMETHOD_END,
549 };
550
551 static driver_t hv_hid_driver = {
552 .name = "hvhid",
553 .methods = hv_hid_methods,
554 .size = sizeof(hv_hid_sc),
555 };
556
557 DRIVER_MODULE(hv_hid, vmbus, hv_hid_driver, NULL, NULL);
558 MODULE_VERSION(hv_hid, 1);
559 MODULE_DEPEND(hv_hid, hidbus, 1, 1, 1);
560 MODULE_DEPEND(hv_hid, hms, 1, 1, 1);
561 MODULE_DEPEND(hv_hid, vmbus, 1, 1, 1);
562 MODULE_PNP_INFO("Z:classid", vmbus, hv_hid, vmbus_hid_descs_pnp,
563 nitems(vmbus_hid_descs_pnp));
564