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 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 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 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 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 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 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 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 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 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 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 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