VirtualBox

source: vbox/trunk/src/VBox/Devices/Input/UsbKbd.cpp

Last change on this file was 99558, checked in by vboxsync, 14 months ago

DevPS2K/UsbKbd: Improved range checks.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 65.2 KB
RevLine 
[27969]1/* $Id: UsbKbd.cpp 99558 2023-04-28 13:54:03Z vboxsync $ */
[26473]2/** @file
[27969]3 * UsbKbd - USB Human Interface Device Emulation, Keyboard.
[26473]4 */
5
6/*
[98103]7 * Copyright (C) 2007-2023 Oracle and/or its affiliates.
[26473]8 *
[96407]9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
[26473]26 */
27
[51546]28/** @page pg_usb_kbd USB Keyboard Device Emulation.
29 *
30 * This module implements a standard USB keyboard which uses the boot
31 * interface. The keyboard sends reports which have room for up to six
32 * normal keys and all standard modifier keys. A report always reflects the
33 * current state of the keyboard and indicates which keys are held down.
34 *
35 * Software normally utilizes the keyboard's interrupt endpoint to request
36 * reports to be sent whenever a state change occurs. However, reports can
37 * also be sent whenever an interrupt transfer is initiated (the keyboard is
38 * not "idle") or requested via the control endpoint (polling).
39 *
40 * Because turnaround on USB is relatively slow, the keyboard often ends up
41 * in a situation where new input arrived but there is no URB available
42 * where a report could be written to. The PDM queue maintained by the
43 * keyboard driver is utilized to provide buffering and hold incoming events
44 * until they can be passed along. The USB keyboard can effectively buffer
45 * up to one event.
46 *
47 * If there is a pending event and a new URB becomes available, a report is
48 * built and the keyboard queue is flushed. This ensures that queued events
49 * are processed as quickly as possible.
50 *
[90697]51 * A second interface with its own interrupt endpoint is used to deliver
52 * additional key events for media and system control keys. This adds
53 * considerable complexity to the emulated device, but unfortunately the
54 * keyboard boot interface is fixed and fairly limited.
[51546]55 *
[90697]56 * The second interface is only exposed if the device is configured in
57 * "extended" mode, with a different USB product ID and different
58 * descriptors. The "basic" mode should be indistinguishable from the original
59 * implementation.
60 *
61 * There are various options available for reporting media keys. We chose
62 * a very basic approach which reports system control keys as a bit-field
63 * (since there are only 3 keys defined) and consumer control keys as just
64 * a single 16-bit value.
65 *
66 * As a consequence, only one consumer control key can be reported as
67 * pressed at any one time. While this may seem limiting, the usefulness of
68 * being able to report e.g. volume-up at the same time as volume-down or
69 * mute is highly questionable.
70 *
71 * System control and consumer control keys are reported in a single
72 * 4-byte report in order to avoid sending multiple separate report types.
73 *
74 * There is a slight complication in that both interfaces are configured
75 * together, but a guest does not necessarily "listen" on both (e.g. EFI).
76 * Since all events come through a single queue, we can't just push back
77 * events for the secondary interface because the entire keyboard would be
78 * blocked. After the device is reset/configured, we drop any events destined
79 * for the secondary interface until a URB is actually queued on the second
80 * interrupt endpoint. Once that happens, we assume the guest will be
81 * receiving data on the second endpoint until the next reset/reconfig.
82 *
[51546]83 * References:
84 *
85 * Device Class Definition for Human Interface Devices (HID), Version 1.11
86 *
87 */
88
[57358]89
90/*********************************************************************************************************************************
91* Header Files *
92*********************************************************************************************************************************/
[27838]93#define LOG_GROUP LOG_GROUP_USB_KBD
[35346]94#include <VBox/vmm/pdmusb.h>
[26473]95#include <VBox/log.h>
96#include <VBox/err.h>
97#include <iprt/assert.h>
98#include <iprt/critsect.h>
99#include <iprt/mem.h>
100#include <iprt/semaphore.h>
101#include <iprt/string.h>
102#include <iprt/uuid.h>
[35353]103#include "VBoxDD.h"
[26473]104
105
[57358]106/*********************************************************************************************************************************
107* Defined Constants And Macros *
108*********************************************************************************************************************************/
[26473]109/** @name USB HID string IDs
110 * @{ */
111#define USBHID_STR_ID_MANUFACTURER 1
112#define USBHID_STR_ID_PRODUCT 2
[90697]113#define USBHID_STR_ID_IF_KBD 3
114#define USBHID_STR_ID_IF_EXT 4
[26473]115/** @} */
116
117/** @name USB HID specific descriptor types
118 * @{ */
[37388]119#define DT_IF_HID_DESCRIPTOR 0x21
[26473]120#define DT_IF_HID_REPORT 0x22
121/** @} */
122
123/** @name USB HID vendor and product IDs
124 * @{ */
125#define VBOX_USB_VENDOR 0x80EE
[90697]126#define USBHID_PID_BAS_KEYBOARD 0x0010
127#define USBHID_PID_EXT_KEYBOARD 0x0011
[26473]128/** @} */
129
130/** @name USB HID class specific requests
131 * @{ */
132#define HID_REQ_GET_REPORT 0x01
133#define HID_REQ_GET_IDLE 0x02
134#define HID_REQ_SET_REPORT 0x09
135#define HID_REQ_SET_IDLE 0x0A
136/** @} */
137
[30507]138/** @name USB HID additional constants
139 * @{ */
140/** The highest USB usage code reported by the VBox emulated keyboard */
[34028]141#define VBOX_USB_MAX_USAGE_CODE 0xE7
142/** The size of an array needed to store all USB usage codes */
143#define VBOX_USB_USAGE_ARRAY_SIZE (VBOX_USB_MAX_USAGE_CODE + 1)
[30507]144#define USBHID_USAGE_ROLL_OVER 1
[44764]145/** The usage code of the first modifier key. */
146#define USBHID_MODIFIER_FIRST 0xE0
147/** The usage code of the last modifier key. */
148#define USBHID_MODIFIER_LAST 0xE7
[30507]149/** @} */
150
[26473]151
[57358]152/*********************************************************************************************************************************
153* Structures and Typedefs *
154*********************************************************************************************************************************/
155
[26473]156/**
[90697]157 * The device mode.
158 */
159typedef enum USBKBDMODE
160{
161 /** Basic keyboard only, backward compatible. */
162 USBKBDMODE_BASIC = 0,
163 /** Extended 2nd interface for consumer control and power. */
164 USBKBDMODE_EXTENDED,
165} USBKBDMODE;
166
167
168/**
[26473]169 * The USB HID request state.
170 */
171typedef enum USBHIDREQSTATE
172{
173 /** Invalid status. */
174 USBHIDREQSTATE_INVALID = 0,
175 /** Ready to receive a new read request. */
176 USBHIDREQSTATE_READY,
177 /** Have (more) data for the host. */
178 USBHIDREQSTATE_DATA_TO_HOST,
179 /** Waiting to supply status information to the host. */
180 USBHIDREQSTATE_STATUS,
181 /** The end of the valid states. */
182 USBHIDREQSTATE_END
183} USBHIDREQSTATE;
184
185
186/**
187 * A URB queue.
188 */
189typedef struct USBHIDURBQUEUE
190{
191 /** The head pointer. */
192 PVUSBURB pHead;
193 /** Where to insert the next entry. */
194 PVUSBURB *ppTail;
195} USBHIDURBQUEUE;
196/** Pointer to a URB queue. */
197typedef USBHIDURBQUEUE *PUSBHIDURBQUEUE;
198/** Pointer to a const URB queue. */
199typedef USBHIDURBQUEUE const *PCUSBHIDURBQUEUE;
200
201
202/**
[90697]203 * Endpoint state.
204 */
205typedef struct USBHIDEP
206{
207 /** Endpoint halt flag.*/
208 bool fHalted;
209} USBHIDEP;
210/** Pointer to the endpoint status. */
211typedef USBHIDEP *PUSBHIDEP;
212
213
214/**
215 * Interface state.
216 */
217typedef struct USBHIDIF
218{
219 /** If interface has pending changes. */
220 bool fHasPendingChanges;
221 /** The state of the HID (state machine).*/
222 USBHIDREQSTATE enmState;
223 /** Pending to-host queue.
224 * The URBs waiting here are waiting for data to become available.
225 */
226 USBHIDURBQUEUE ToHostQueue;
227} USBHIDIF;
228/** Pointer to the endpoint status. */
229typedef USBHIDIF *PUSBHIDIF;
230
231
232/**
[26473]233 * The USB HID report structure for regular keys.
234 */
235typedef struct USBHIDK_REPORT
236{
[27969]237 uint8_t ShiftState; /**< Modifier keys bitfield */
238 uint8_t Reserved; /**< Currently unused */
239 uint8_t aKeys[6]; /**< Normal keys */
[26473]240} USBHIDK_REPORT, *PUSBHIDK_REPORT;
241
[90697]242/* Must match 8-byte packet size. */
243AssertCompile(sizeof(USBHIDK_REPORT) == 8);
244
245
[26473]246/**
[90697]247 * The USB HID report structure for extra keys.
248 */
249typedef struct USBHIDX_REPORT
250{
251 uint16_t uKeyCC; /**< Consumer Control key code */
252 uint8_t uSCKeys; /**< System Control keys bit map */
253 uint8_t Reserved; /**< Unused */
254} USBHIDX_REPORT, *PUSBHIDX_REPORT;
255
256/* Must match 4-byte packet size. */
257AssertCompile(sizeof(USBHIDX_REPORT) == 4);
258
259
260/**
[26473]261 * The USB HID instance data.
262 */
263typedef struct USBHID
264{
265 /** Pointer back to the PDM USB Device instance structure. */
266 PPDMUSBINS pUsbIns;
267 /** Critical section protecting the device state. */
[27969]268 RTCRITSECT CritSect;
[26473]269
270 /** The current configuration.
271 * (0 - default, 1 - the one supported configuration, i.e configured.) */
272 uint8_t bConfigurationValue;
[64368]273 /** USB HID Idle value.
[26473]274 * (0 - only report state change, !=0 - report in bIdle * 4ms intervals.) */
275 uint8_t bIdle;
[90697]276 /** Is this a relative, absolute or multi-touch pointing device? */
277 USBKBDMODE enmMode;
278 /** Endpoint 0 is the default control pipe, 1 is the dev->host interrupt one
279 * for standard keys, 1 is the interrupt EP for extra keys. */
280 USBHIDEP aEps[3];
281 /** Interface 0 is the standard keyboard interface, 1 is the additional
282 * control/media key interface. */
283 USBHIDIF aIfs[2];
[26473]284
285 /** Done queue
286 * The URBs stashed here are waiting to be reaped. */
287 USBHIDURBQUEUE DoneQueue;
288 /** Signalled when adding an URB to the done queue and fHaveDoneQueueWaiter
289 * is set. */
290 RTSEMEVENT hEvtDoneQueue;
291 /** Someone is waiting on the done queue. */
292 bool fHaveDoneQueueWaiter;
[90697]293 /** The guest expects data coming over second endpoint/pipe. */
294 bool fExtPipeActive;
[30507]295 /** Currently depressed keys */
[34028]296 uint8_t abDepressedKeys[VBOX_USB_USAGE_ARRAY_SIZE];
[26473]297
298 /**
299 * Keyboard port - LUN#0.
300 *
301 * @implements PDMIBASE
302 * @implements PDMIKEYBOARDPORT
303 */
304 struct
305 {
306 /** The base interface for the keyboard port. */
307 PDMIBASE IBase;
308 /** The keyboard port base interface. */
309 PDMIKEYBOARDPORT IPort;
310
311 /** The base interface of the attached keyboard driver. */
312 R3PTRTYPE(PPDMIBASE) pDrvBase;
313 /** The keyboard interface of the attached keyboard driver. */
314 R3PTRTYPE(PPDMIKEYBOARDCONNECTOR) pDrv;
315 } Lun0;
316} USBHID;
317/** Pointer to the USB HID instance data. */
318typedef USBHID *PUSBHID;
319
[57358]320
321/*********************************************************************************************************************************
322* Global Variables *
323*********************************************************************************************************************************/
[26473]324static const PDMUSBDESCCACHESTRING g_aUsbHidStrings_en_US[] =
325{
326 { USBHID_STR_ID_MANUFACTURER, "VirtualBox" },
327 { USBHID_STR_ID_PRODUCT, "USB Keyboard" },
[90697]328 { USBHID_STR_ID_IF_KBD, "Keyboard" },
329 { USBHID_STR_ID_IF_EXT, "System Control"},
[26473]330};
331
332static const PDMUSBDESCCACHELANG g_aUsbHidLanguages[] =
333{
334 { 0x0409, RT_ELEMENTS(g_aUsbHidStrings_en_US), g_aUsbHidStrings_en_US }
335};
336
[90697]337static const VUSBDESCENDPOINTEX g_aUsbHidEndpointDescsKbd[] =
[26473]338{
339 {
340 {
341 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
342 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
343 /* .bEndpointAddress = */ 0x81 /* ep=1, in */,
344 /* .bmAttributes = */ 3 /* interrupt */,
345 /* .wMaxPacketSize = */ 8,
346 /* .bInterval = */ 10,
347 },
348 /* .pvMore = */ NULL,
349 /* .pvClass = */ NULL,
350 /* .cbClass = */ 0
351 },
352};
353
[90697]354static const VUSBDESCENDPOINTEX g_aUsbHidEndpointDescsExt[] =
[26473]355{
[90697]356 {
357 {
358 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
359 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
360 /* .bEndpointAddress = */ 0x82 /* ep=2, in */,
361 /* .bmAttributes = */ 3 /* interrupt */,
362 /* .wMaxPacketSize = */ 4,
363 /* .bInterval = */ 10,
364 },
365 /* .pvMore = */ NULL,
366 /* .pvClass = */ NULL,
367 /* .cbClass = */ 0
368 },
369};
370
371/** HID report descriptor for standard keys. */
372static const uint8_t g_UsbHidReportDescKbd[] =
373{
[26473]374 /* Usage Page */ 0x05, 0x01, /* Generic Desktop */
375 /* Usage */ 0x09, 0x06, /* Keyboard */
376 /* Collection */ 0xA1, 0x01, /* Application */
377 /* Usage Page */ 0x05, 0x07, /* Keyboard */
378 /* Usage Minimum */ 0x19, 0xE0, /* Left Ctrl Key */
379 /* Usage Maximum */ 0x29, 0xE7, /* Right GUI Key */
380 /* Logical Minimum */ 0x15, 0x00, /* 0 */
381 /* Logical Maximum */ 0x25, 0x01, /* 1 */
382 /* Report Count */ 0x95, 0x08, /* 8 */
383 /* Report Size */ 0x75, 0x01, /* 1 */
384 /* Input */ 0x81, 0x02, /* Data, Value, Absolute, Bit field */
385 /* Report Count */ 0x95, 0x01, /* 1 */
386 /* Report Size */ 0x75, 0x08, /* 8 (padding bits) */
387 /* Input */ 0x81, 0x01, /* Constant, Array, Absolute, Bit field */
388 /* Report Count */ 0x95, 0x05, /* 5 */
389 /* Report Size */ 0x75, 0x01, /* 1 */
390 /* Usage Page */ 0x05, 0x08, /* LEDs */
391 /* Usage Minimum */ 0x19, 0x01, /* Num Lock */
392 /* Usage Maximum */ 0x29, 0x05, /* Kana */
[90697]393 /* Output */ 0x91, 0x02, /* Data, Value, Absolute, Non-volatile, Bit field */
[26473]394 /* Report Count */ 0x95, 0x01, /* 1 */
395 /* Report Size */ 0x75, 0x03, /* 3 */
396 /* Output */ 0x91, 0x01, /* Constant, Value, Absolute, Non-volatile, Bit field */
397 /* Report Count */ 0x95, 0x06, /* 6 */
398 /* Report Size */ 0x75, 0x08, /* 8 */
399 /* Logical Minimum */ 0x15, 0x00, /* 0 */
[26966]400 /* Logical Maximum */ 0x26, 0xFF,0x00,/* 255 */
[26473]401 /* Usage Page */ 0x05, 0x07, /* Keyboard */
402 /* Usage Minimum */ 0x19, 0x00, /* 0 */
[26948]403 /* Usage Maximum */ 0x29, 0xFF, /* 255 */
[26473]404 /* Input */ 0x81, 0x00, /* Data, Array, Absolute, Bit field */
405 /* End Collection */ 0xC0,
406};
407
[90697]408/** HID report descriptor for extra multimedia/system keys. */
409static const uint8_t g_UsbHidReportDescExt[] =
[26473]410{
[90697]411 /* Usage Page */ 0x05, 0x0C, /* Consumer */
412 /* Usage */ 0x09, 0x01, /* Consumer Control */
413 /* Collection */ 0xA1, 0x01, /* Application */
414
415 /* Usage Page */ 0x05, 0x0C, /* Consumer */
416 /* Usage Minimum */ 0x19, 0x00, /* 0 */
417 /* Usage Maximum */ 0x2A, 0x3C, 0x02, /* 572 */
418 /* Logical Minimum */ 0x15, 0x00, /* 0 */
419 /* Logical Maximum */ 0x26, 0x3C, 0x02, /* 572 */
420 /* Report Count */ 0x95, 0x01, /* 1 */
421 /* Report Size */ 0x75, 0x10, /* 16 */
422 /* Input */ 0x81, 0x80, /* Data, Array, Absolute, Bytes */
423
424 /* Usage Page */ 0x05, 0x01, /* Generic Desktop */
425 /* Usage Minimum */ 0x19, 0x81, /* 129 */
426 /* Usage Maximum */ 0x29, 0x83, /* 131 */
427 /* Logical Minimum */ 0x15, 0x00, /* 0 */
428 /* Logical Maximum */ 0x25, 0x01, /* 1 */
429 /* Report Size */ 0x75, 0x01, /* 1 */
430 /* Report Count */ 0x95, 0x03, /* 3 */
431 /* Input */ 0x81, 0x02, /* Data, Value, Absolute, Bit field */
432 /* Report Count */ 0x95, 0x05, /* 5 */
433 /* Input */ 0x81, 0x01, /* Constant, Array, Absolute, Bit field */
434 /* Report Count */ 0x95, 0x01, /* 1 */
435 /* Report Size */ 0x75, 0x08, /* 8 (padding bits) */
436 /* Input */ 0x81, 0x01, /* Constant, Array, Absolute, Bit field */
437
438 /* End Collection */ 0xC0,
439};
440
441/** Additional HID class interface descriptor for standard keys. */
442static const uint8_t g_UsbHidIfHidDescKbd[] =
443{
[26473]444 /* .bLength = */ 0x09,
445 /* .bDescriptorType = */ 0x21, /* HID */
446 /* .bcdHID = */ 0x10, 0x01, /* 1.1 */
447 /* .bCountryCode = */ 0x0D, /* International (ISO) */
448 /* .bNumDescriptors = */ 1,
449 /* .bDescriptorType = */ 0x22, /* Report */
[90697]450 /* .wDescriptorLength = */ sizeof(g_UsbHidReportDescKbd), 0x00
[26473]451};
452
[90697]453/** Additional HID class interface descriptor for extra keys. */
454static const uint8_t g_UsbHidIfHidDescExt[] =
[26473]455{
[90697]456 /* .bLength = */ 0x09,
457 /* .bDescriptorType = */ 0x21, /* HID */
458 /* .bcdHID = */ 0x10, 0x01, /* 1.1 */
459 /* .bCountryCode = */ 0,
460 /* .bNumDescriptors = */ 1,
461 /* .bDescriptorType = */ 0x22, /* Report */
462 /* .wDescriptorLength = */ sizeof(g_UsbHidReportDescExt), 0x00
463};
464
465/** Standard keyboard interface. */
466static const VUSBDESCINTERFACEEX g_UsbHidInterfaceDescKbd =
467{
[26473]468 {
469 /* .bLength = */ sizeof(VUSBDESCINTERFACE),
470 /* .bDescriptorType = */ VUSB_DT_INTERFACE,
471 /* .bInterfaceNumber = */ 0,
472 /* .bAlternateSetting = */ 0,
473 /* .bNumEndpoints = */ 1,
474 /* .bInterfaceClass = */ 3 /* HID */,
475 /* .bInterfaceSubClass = */ 1 /* Boot Interface */,
476 /* .bInterfaceProtocol = */ 1 /* Keyboard */,
[90697]477 /* .iInterface = */ USBHID_STR_ID_IF_KBD
[26473]478 },
479 /* .pvMore = */ NULL,
[90697]480 /* .pvClass = */ &g_UsbHidIfHidDescKbd,
481 /* .cbClass = */ sizeof(g_UsbHidIfHidDescKbd),
482 &g_aUsbHidEndpointDescsKbd[0],
[43960]483 /* .pIAD = */ NULL,
484 /* .cbIAD = */ 0
[26473]485};
486
[90697]487/** Extra keys (multimedia/system) interface. */
488static const VUSBDESCINTERFACEEX g_UsbHidInterfaceDescExt =
[26473]489{
[90697]490 {
491 /* .bLength = */ sizeof(VUSBDESCINTERFACE),
492 /* .bDescriptorType = */ VUSB_DT_INTERFACE,
493 /* .bInterfaceNumber = */ 1,
494 /* .bAlternateSetting = */ 0,
495 /* .bNumEndpoints = */ 1,
496 /* .bInterfaceClass = */ 3 /* HID */,
497 /* .bInterfaceSubClass = */ 0 /* None */,
498 /* .bInterfaceProtocol = */ 0 /* Unspecified */,
499 /* .iInterface = */ USBHID_STR_ID_IF_EXT
500 },
501 /* .pvMore = */ NULL,
502 /* .pvClass = */ &g_UsbHidIfHidDescExt,
503 /* .cbClass = */ sizeof(g_UsbHidIfHidDescExt),
504 &g_aUsbHidEndpointDescsExt[0],
505 /* .pIAD = */ NULL,
506 /* .cbIAD = */ 0
[26473]507};
508
[90697]509static const VUSBINTERFACE g_aUsbHidBasInterfaces[] =
[26473]510{
[90697]511 { &g_UsbHidInterfaceDescKbd, /* .cSettings = */ 1 },
512};
513
514static const VUSBINTERFACE g_aUsbHidExtInterfaces[] =
515{
516 { &g_UsbHidInterfaceDescKbd, /* .cSettings = */ 1 },
517 { &g_UsbHidInterfaceDescExt, /* .cSettings = */ 1 },
518};
519
520static const VUSBDESCCONFIGEX g_UsbHidBasConfigDesc =
521{
[26473]522 {
523 /* .bLength = */ sizeof(VUSBDESCCONFIG),
524 /* .bDescriptorType = */ VUSB_DT_CONFIG,
525 /* .wTotalLength = */ 0 /* recalculated on read */,
[90697]526 /* .bNumInterfaces = */ RT_ELEMENTS(g_aUsbHidBasInterfaces),
[26473]527 /* .bConfigurationValue =*/ 1,
528 /* .iConfiguration = */ 0,
[90697]529 /* .bmAttributes = */ RT_BIT(7), /* bus-powered */
[26473]530 /* .MaxPower = */ 50 /* 100mA */
531 },
[37388]532 NULL, /* pvMore */
[66989]533 NULL, /* pvClass */
534 0, /* cbClass */
[90697]535 &g_aUsbHidBasInterfaces[0],
[37388]536 NULL /* pvOriginal */
[26473]537};
538
[90697]539static const VUSBDESCCONFIGEX g_UsbHidExtConfigDesc =
[26473]540{
[90697]541 {
542 /* .bLength = */ sizeof(VUSBDESCCONFIG),
543 /* .bDescriptorType = */ VUSB_DT_CONFIG,
544 /* .wTotalLength = */ 0 /* recalculated on read */,
545 /* .bNumInterfaces = */ RT_ELEMENTS(g_aUsbHidExtInterfaces),
546 /* .bConfigurationValue =*/ 1,
547 /* .iConfiguration = */ 0,
548 /* .bmAttributes = */ RT_BIT(7), /* bus-powered */
549 /* .MaxPower = */ 50 /* 100mA */
550 },
551 NULL, /* pvMore */
552 NULL, /* pvClass */
553 0, /* cbClass */
554 &g_aUsbHidExtInterfaces[0],
555 NULL /* pvOriginal */
556};
557
558static const VUSBDESCDEVICE g_UsbHidBasDeviceDesc =
559{
560 /* .bLength = */ sizeof(g_UsbHidBasDeviceDesc),
[26473]561 /* .bDescriptorType = */ VUSB_DT_DEVICE,
562 /* .bcdUsb = */ 0x110, /* 1.1 */
563 /* .bDeviceClass = */ 0 /* Class specified in the interface desc. */,
564 /* .bDeviceSubClass = */ 0 /* Subclass specified in the interface desc. */,
565 /* .bDeviceProtocol = */ 0 /* Protocol specified in the interface desc. */,
566 /* .bMaxPacketSize0 = */ 8,
567 /* .idVendor = */ VBOX_USB_VENDOR,
[90697]568 /* .idProduct = */ USBHID_PID_BAS_KEYBOARD,
[26473]569 /* .bcdDevice = */ 0x0100, /* 1.0 */
570 /* .iManufacturer = */ USBHID_STR_ID_MANUFACTURER,
571 /* .iProduct = */ USBHID_STR_ID_PRODUCT,
572 /* .iSerialNumber = */ 0,
573 /* .bNumConfigurations = */ 1
574};
575
[90697]576static const VUSBDESCDEVICE g_UsbHidExtDeviceDesc =
[26473]577{
[90697]578 /* .bLength = */ sizeof(g_UsbHidExtDeviceDesc),
579 /* .bDescriptorType = */ VUSB_DT_DEVICE,
580 /* .bcdUsb = */ 0x110, /* 1.1 */
581 /* .bDeviceClass = */ 0 /* Class specified in the interface desc. */,
582 /* .bDeviceSubClass = */ 0 /* Subclass specified in the interface desc. */,
583 /* .bDeviceProtocol = */ 0 /* Protocol specified in the interface desc. */,
584 /* .bMaxPacketSize0 = */ 8,
585 /* .idVendor = */ VBOX_USB_VENDOR,
586 /* .idProduct = */ USBHID_PID_EXT_KEYBOARD,
587 /* .bcdDevice = */ 0x0100, /* 1.0 */
588 /* .iManufacturer = */ USBHID_STR_ID_MANUFACTURER,
589 /* .iProduct = */ USBHID_STR_ID_PRODUCT,
590 /* .iSerialNumber = */ 0,
591 /* .bNumConfigurations = */ 1
592};
593
594static const PDMUSBDESCCACHE g_UsbHidBasDescCache =
595{
596 /* .pDevice = */ &g_UsbHidBasDeviceDesc,
597 /* .paConfigs = */ &g_UsbHidBasConfigDesc,
[26473]598 /* .paLanguages = */ g_aUsbHidLanguages,
599 /* .cLanguages = */ RT_ELEMENTS(g_aUsbHidLanguages),
600 /* .fUseCachedDescriptors = */ true,
601 /* .fUseCachedStringsDescriptors = */ true
602};
603
[90697]604static const PDMUSBDESCCACHE g_UsbHidExtDescCache =
605{
606 /* .pDevice = */ &g_UsbHidExtDeviceDesc,
607 /* .paConfigs = */ &g_UsbHidExtConfigDesc,
608 /* .paLanguages = */ g_aUsbHidLanguages,
609 /* .cLanguages = */ RT_ELEMENTS(g_aUsbHidLanguages),
610 /* .fUseCachedDescriptors = */ true,
611 /* .fUseCachedStringsDescriptors = */ true
612};
[26473]613
[89935]614/**
615 * Conversion table for consumer control keys (HID Usage Page 12).
616 * Used to 'compress' the USB HID usage code into a single 8-bit
617 * value. See also PS2CCKeys in the PS/2 keyboard emulation.
618 */
619static const uint16_t aHidCCKeys[] = {
620 0x00B5, /* Scan Next Track */
621 0x00B6, /* Scan Previous Track */
622 0x00B7, /* Stop */
623 0x00CD, /* Play/Pause */
624 0x00E2, /* Mute */
625 0x00E5, /* Bass Boost */
626 0x00E7, /* Loudness */
627 0x00E9, /* Volume Up */
628 0x00EA, /* Volume Down */
629 0x0152, /* Bass Up */
630 0x0153, /* Bass Down */
631 0x0154, /* Treble Up */
632 0x0155, /* Treble Down */
633 0x0183, /* Media Select */
634 0x018A, /* Mail */
635 0x0192, /* Calculator */
636 0x0194, /* My Computer */
637 0x0221, /* WWW Search */
638 0x0223, /* WWW Home */
639 0x0224, /* WWW Back */
640 0x0225, /* WWW Forward */
641 0x0226, /* WWW Stop */
642 0x0227, /* WWW Refresh */
643 0x022A, /* WWW Favorites */
644};
645
646/**
647 * Conversion table for generic desktop control keys (HID Usage Page 1).
648 * Used to 'compress' the USB HID usage code into a single 8-bit
649 * value. See also PS2DCKeys in the PS/2 keyboard emulation.
650 */
651static const uint16_t aHidDCKeys[] = {
652 0x81, /* System Power */
653 0x82, /* System Sleep */
654 0x83, /* System Wake */
655};
656
657#define USBHID_PAGE_DC_START 0xb0
[99558]658#define USBHID_PAGE_DC_END (USBHID_PAGE_DC_START + RT_ELEMENTS(aHidDCKeys) - 1)
[89935]659#define USBHID_PAGE_CC_START 0xc0
[99558]660#define USBHID_PAGE_CC_END (USBHID_PAGE_CC_START + RT_ELEMENTS(aHidCCKeys) - 1)
[89935]661
662AssertCompile(RT_ELEMENTS(aHidCCKeys) <= 0x20); /* Must fit between 0xC0-0xDF. */
663AssertCompile(RT_ELEMENTS(aHidDCKeys) <= 0x10); /* Must fit between 0xB0-0xBF. */
664
665
[57358]666/*********************************************************************************************************************************
667* Internal Functions *
668*********************************************************************************************************************************/
[26473]669
[27890]670
671/**
[89935]672 * Converts a 32-bit USB HID code to an internal 8-bit value.
673 *
674 * @returns 8-bit internal key code/index. -1 if not found.
675 * @param u32HidCode 32-bit USB HID code.
676 */
677static int usbHidToInternalCode(uint32_t u32HidCode)
678{
679 uint8_t u8HidPage;
680 uint16_t u16HidUsage;
681 int iKeyIndex = -1;
682
683 u8HidPage = RT_LOBYTE(RT_HIWORD(u32HidCode));
684 u16HidUsage = RT_LOWORD(u32HidCode);
685
686 if (u8HidPage == USB_HID_KB_PAGE)
687 {
688 if (u16HidUsage <= VBOX_USB_MAX_USAGE_CODE)
689 iKeyIndex = u16HidUsage; /* Direct mapping. */
690 else
691 AssertMsgFailed(("u16HidUsage out of range! (%04X)\n", u16HidUsage));
692 }
693 else if (u8HidPage == USB_HID_CC_PAGE)
694 {
[89937]695 for (unsigned i = 0; i < RT_ELEMENTS(aHidCCKeys); ++i)
[89935]696 if (aHidCCKeys[i] == u16HidUsage)
697 {
698 iKeyIndex = USBHID_PAGE_CC_START + i;
699 break;
700 }
701 AssertMsg(iKeyIndex > -1, ("Unsupported code in USB_HID_CC_PAGE! (%04X)\n", u16HidUsage));
702 }
703 else if (u8HidPage == USB_HID_DC_PAGE)
704 {
[89937]705 for (unsigned i = 0; i < RT_ELEMENTS(aHidDCKeys); ++i)
[90697]706 if (aHidDCKeys[i] == u16HidUsage)
[89935]707 {
708 iKeyIndex = USBHID_PAGE_DC_START + i;
709 break;
710 }
711 AssertMsg(iKeyIndex > -1, ("Unsupported code in USB_HID_DC_PAGE! (%04X)\n", u16HidUsage));
712 }
713 else
714 {
715 AssertMsgFailed(("Unsupported u8HidPage! (%02X)\n", u8HidPage));
716 }
717
718 return iKeyIndex;
719}
720
721
722/**
723 * Converts an internal 8-bit key index back to a 32-bit USB HID code.
724 *
725 * @returns 32-bit USB HID code. Zero if not found.
[89940]726 * @param uKeyCode Internal key code/index.
[89935]727 */
[89937]728static uint32_t usbInternalCodeToHid(unsigned uKeyCode)
[89935]729{
730 uint16_t u16HidUsage;
731 uint32_t u32HidCode = 0;
732
[89937]733 if ((uKeyCode >= USBHID_PAGE_DC_START) && (uKeyCode <= USBHID_PAGE_DC_END))
[89935]734 {
[89937]735 u16HidUsage = aHidDCKeys[uKeyCode - USBHID_PAGE_DC_START];
[89935]736 u32HidCode = RT_MAKE_U32(u16HidUsage, USB_HID_DC_PAGE);
737 }
[89937]738 else if ((uKeyCode >= USBHID_PAGE_CC_START) && (uKeyCode <= USBHID_PAGE_CC_END))
[89935]739 {
[89937]740 u16HidUsage = aHidCCKeys[uKeyCode - USBHID_PAGE_CC_START];
[89935]741 u32HidCode = RT_MAKE_U32(u16HidUsage, USB_HID_CC_PAGE);
742 }
743 else /* Must be the keyboard usage page. */
744 {
[89937]745 if (uKeyCode <= VBOX_USB_MAX_USAGE_CODE)
746 u32HidCode = RT_MAKE_U32(uKeyCode, USB_HID_KB_PAGE);
[89935]747 else
[89937]748 AssertMsgFailed(("uKeyCode out of range! (%u)\n", uKeyCode));
[89935]749 }
750
751 return u32HidCode;
752}
753
754
755/**
[26473]756 * Initializes an URB queue.
757 *
758 * @param pQueue The URB queue.
759 */
760static void usbHidQueueInit(PUSBHIDURBQUEUE pQueue)
761{
762 pQueue->pHead = NULL;
763 pQueue->ppTail = &pQueue->pHead;
764}
765
766/**
767 * Inserts an URB at the end of the queue.
768 *
769 * @param pQueue The URB queue.
770 * @param pUrb The URB to insert.
771 */
772DECLINLINE(void) usbHidQueueAddTail(PUSBHIDURBQUEUE pQueue, PVUSBURB pUrb)
773{
774 pUrb->Dev.pNext = NULL;
775 *pQueue->ppTail = pUrb;
776 pQueue->ppTail = &pUrb->Dev.pNext;
777}
778
779
780/**
781 * Unlinks the head of the queue and returns it.
782 *
783 * @returns The head entry.
784 * @param pQueue The URB queue.
785 */
786DECLINLINE(PVUSBURB) usbHidQueueRemoveHead(PUSBHIDURBQUEUE pQueue)
787{
788 PVUSBURB pUrb = pQueue->pHead;
789 if (pUrb)
790 {
791 PVUSBURB pNext = pUrb->Dev.pNext;
792 pQueue->pHead = pNext;
793 if (!pNext)
794 pQueue->ppTail = &pQueue->pHead;
795 else
796 pUrb->Dev.pNext = NULL;
797 }
798 return pUrb;
799}
800
801
802/**
803 * Removes an URB from anywhere in the queue.
804 *
805 * @returns true if found, false if not.
806 * @param pQueue The URB queue.
807 * @param pUrb The URB to remove.
808 */
809DECLINLINE(bool) usbHidQueueRemove(PUSBHIDURBQUEUE pQueue, PVUSBURB pUrb)
810{
811 PVUSBURB pCur = pQueue->pHead;
812 if (pCur == pUrb)
[90697]813 {
[26473]814 pQueue->pHead = pUrb->Dev.pNext;
[90697]815 if (!pUrb->Dev.pNext)
816 pQueue->ppTail = &pQueue->pHead;
817 }
[26473]818 else
819 {
820 while (pCur)
821 {
822 if (pCur->Dev.pNext == pUrb)
823 {
824 pCur->Dev.pNext = pUrb->Dev.pNext;
825 break;
826 }
827 pCur = pCur->Dev.pNext;
828 }
829 if (!pCur)
830 return false;
[90697]831 if (!pUrb->Dev.pNext)
832 pQueue->ppTail = &pCur->Dev.pNext;
[26473]833 }
[90697]834 pUrb->Dev.pNext = NULL;
[26473]835 return true;
836}
837
838
[63478]839#if 0 /* unused */
[26473]840/**
841 * Checks if the queue is empty or not.
842 *
843 * @returns true if it is, false if it isn't.
844 * @param pQueue The URB queue.
845 */
846DECLINLINE(bool) usbHidQueueIsEmpty(PCUSBHIDURBQUEUE pQueue)
847{
848 return pQueue->pHead == NULL;
849}
[63478]850#endif /* unused */
[26473]851
852
853/**
854 * Links an URB into the done queue.
855 *
856 * @param pThis The HID instance.
857 * @param pUrb The URB.
858 */
859static void usbHidLinkDone(PUSBHID pThis, PVUSBURB pUrb)
860{
861 usbHidQueueAddTail(&pThis->DoneQueue, pUrb);
862
863 if (pThis->fHaveDoneQueueWaiter)
864 {
865 int rc = RTSemEventSignal(pThis->hEvtDoneQueue);
866 AssertRC(rc);
867 }
868}
869
870
871/**
872 * Completes the URB with a stalled state, halting the pipe.
873 */
874static int usbHidCompleteStall(PUSBHID pThis, PUSBHIDEP pEp, PVUSBURB pUrb, const char *pszWhy)
875{
[62885]876 RT_NOREF1(pszWhy);
[26473]877 Log(("usbHidCompleteStall/#%u: pUrb=%p:%s: %s\n", pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc, pszWhy));
878
879 pUrb->enmStatus = VUSBSTATUS_STALL;
880
881 /** @todo figure out if the stall is global or pipe-specific or both. */
882 if (pEp)
883 pEp->fHalted = true;
884 else
885 {
[90697]886 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aEps); i++)
887 pThis->aEps[i].fHalted = true;
[26473]888 }
889
890 usbHidLinkDone(pThis, pUrb);
891 return VINF_SUCCESS;
892}
893
894
895/**
[90697]896 * Completes the URB after device successfully processed it. Optionally copies data
897 * into the URB. May still generate an error if the URB is not big enough.
[26473]898 */
[90697]899static int usbHidCompleteOk(PUSBHID pThis, PVUSBURB pUrb, const void *pSrc, size_t cbSrc)
[26473]900{
[90697]901 Log(("usbHidCompleteOk/#%u: pUrb=%p:%s (cbData=%#x) cbSrc=%#zx\n", pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc, pUrb->cbData, cbSrc));
[26473]902
903 pUrb->enmStatus = VUSBSTATUS_OK;
[90697]904 size_t cbCopy = 0;
905 size_t cbSetup = 0;
[26473]906
[90697]907 if (pSrc) /* Can be NULL if not copying anything. */
908 {
909 Assert(cbSrc);
910 uint8_t *pDst = pUrb->abData;
911
912 /* Returned data is written after the setup message in control URBs. */
913 if (pUrb->enmType == VUSBXFERTYPE_MSG)
914 cbSetup = sizeof(VUSBSETUP);
915
916 Assert(pUrb->cbData >= cbSetup); /* Only triggers if URB is corrupted. */
917
918 if (pUrb->cbData > cbSetup)
919 {
920 /* There is at least one byte of room in the URB. */
921 cbCopy = RT_MIN(pUrb->cbData - cbSetup, cbSrc);
922 memcpy(pDst + cbSetup, pSrc, cbCopy);
923 pUrb->cbData = (uint32_t)(cbCopy + cbSetup);
924 Log(("Copied %zu bytes to pUrb->abData[%zu], source had %zu bytes\n", cbCopy, cbSetup, cbSrc));
925 }
926
927 /* Need to check length differences. If cbSrc is less than what
928 * the URB has space for, it'll be resolved as a short packet. But
929 * if cbSrc is bigger, there is a real problem and the host needs
930 * to see an overrun/babble error.
931 */
932 if (RT_UNLIKELY(cbSrc > cbCopy))
933 pUrb->enmStatus = VUSBSTATUS_DATA_OVERRUN;
934 }
935 else
936 Assert(cbSrc == 0); /* Make up your mind, caller! */
937
[26473]938 usbHidLinkDone(pThis, pUrb);
939 return VINF_SUCCESS;
940}
941
942
943/**
944 * Reset worker for usbHidUsbReset, usbHidUsbSetConfiguration and
[36445]945 * usbHidHandleDefaultPipe.
[26473]946 *
947 * @returns VBox status code.
948 * @param pThis The HID instance.
[36445]949 * @param pUrb Set when usbHidHandleDefaultPipe is the
[26473]950 * caller.
951 * @param fSetConfig Set when usbHidUsbSetConfiguration is the
952 * caller.
953 */
954static int usbHidResetWorker(PUSBHID pThis, PVUSBURB pUrb, bool fSetConfig)
955{
956 /*
[28909]957 * Deactivate the keyboard.
958 */
959 pThis->Lun0.pDrv->pfnSetActive(pThis->Lun0.pDrv, false);
960
961 /*
[26473]962 * Reset the device state.
963 */
964 pThis->bIdle = 0;
[90697]965 pThis->fExtPipeActive = false;
[26473]966
967 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aEps); i++)
968 pThis->aEps[i].fHalted = false;
969
[90697]970 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aIfs); i++)
971 {
972 pThis->aIfs[i].fHasPendingChanges = false;
973 pThis->aIfs[i].enmState = USBHIDREQSTATE_READY;
974 }
975
[26473]976 if (!pUrb && !fSetConfig) /* (only device reset) */
977 pThis->bConfigurationValue = 0; /* default */
978
979 /*
980 * Ditch all pending URBs.
981 */
982 PVUSBURB pCurUrb;
[90697]983 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aIfs); i++)
984 while ((pCurUrb = usbHidQueueRemoveHead(&pThis->aIfs[i].ToHostQueue)) != NULL)
985 {
986 pCurUrb->enmStatus = VUSBSTATUS_CRC;
987 usbHidLinkDone(pThis, pCurUrb);
988 }
[26473]989
990 if (pUrb)
[90697]991 return usbHidCompleteOk(pThis, pUrb, NULL, 0);
[26473]992 return VINF_SUCCESS;
993}
994
995/**
[30507]996 * Returns true if the usage code corresponds to a keyboard modifier key
997 * (left or right ctrl, shift, alt or GUI). The usage codes for these keys
998 * are the range 0xe0 to 0xe7.
999 */
1000static bool usbHidUsageCodeIsModifier(uint8_t u8Usage)
1001{
[44764]1002 return u8Usage >= USBHID_MODIFIER_FIRST && u8Usage <= USBHID_MODIFIER_LAST;
[30507]1003}
1004
1005/**
1006 * Convert a USB HID usage code to a keyboard modifier flag. The arithmetic
1007 * is simple: the modifier keys have usage codes from 0xe0 to 0xe7, and the
1008 * lower nibble is the bit number of the flag.
1009 */
1010static uint8_t usbHidModifierToFlag(uint8_t u8Usage)
1011{
1012 Assert(usbHidUsageCodeIsModifier(u8Usage));
1013 return RT_BIT(u8Usage & 0xf);
1014}
1015
1016/**
[90697]1017 * Returns true if the usage code corresponds to a System Control key.
1018 * The usage codes for these keys are the range 0x81 to 0x83.
1019 */
1020static bool usbHidUsageCodeIsSCKey(uint16_t u16Usage)
1021{
1022 return u16Usage >= 0x81 && u16Usage <= 0x83;
1023}
1024
1025/**
1026 * Convert a USB HID usage code to a system control key mask. The system control
1027 * keys have usage codes from 0x81 to 0x83, and the lower nibble is the bit
1028 * position plus one.
1029 */
1030static uint8_t usbHidSCKeyToMask(uint16_t u16Usage)
1031{
1032 Assert(usbHidUsageCodeIsSCKey(u16Usage));
1033 return RT_BIT((u16Usage & 0xf) - 1);
1034}
1035
1036/**
[51539]1037 * Create a USB HID keyboard report reflecting the current state of the
[90697]1038 * standard keyboard (up/down keys).
[30507]1039 */
[90697]1040static void usbHidBuildReportKbd(PUSBHIDK_REPORT pReport, uint8_t *pabDepressedKeys)
[30507]1041{
1042 unsigned iBuf = 0;
1043 RT_ZERO(*pReport);
[34028]1044 for (unsigned iKey = 0; iKey < VBOX_USB_USAGE_ARRAY_SIZE; ++iKey)
[30507]1045 {
[51539]1046 Assert(iBuf <= RT_ELEMENTS(pReport->aKeys));
1047 if (pabDepressedKeys[iKey])
[30507]1048 {
1049 if (usbHidUsageCodeIsModifier(iKey))
1050 pReport->ShiftState |= usbHidModifierToFlag(iKey);
1051 else if (iBuf == RT_ELEMENTS(pReport->aKeys))
1052 {
1053 /* The USB HID spec says that the entire vector should be
1054 * set to ErrorRollOver on overflow. We don't mind if this
1055 * path is taken several times for one report. */
1056 for (unsigned iBuf2 = 0;
1057 iBuf2 < RT_ELEMENTS(pReport->aKeys); ++iBuf2)
1058 pReport->aKeys[iBuf2] = USBHID_USAGE_ROLL_OVER;
1059 }
1060 else
1061 {
[89935]1062 /* Key index back to 32-bit HID code. */
1063 uint32_t u32HidCode = usbInternalCodeToHid(iKey);
1064 uint8_t u8HidPage = RT_LOBYTE(RT_HIWORD(u32HidCode));
[90697]1065 uint16_t u16HidUsage = RT_LOWORD(u32HidCode);
[89935]1066
1067 if (u8HidPage == USB_HID_KB_PAGE)
1068 {
1069 pReport->aKeys[iBuf] = (uint8_t)u16HidUsage;
1070 ++iBuf;
1071 }
[30507]1072 }
1073 }
1074 }
1075}
1076
1077/**
[90697]1078 * Create a USB HID keyboard report reflecting the current state of the
1079 * consumer control keys. This is very easy as we have a bit mask that fully
1080 * reflects the state of all defined system control keys.
1081 */
1082static void usbHidBuildReportExt(PUSBHIDX_REPORT pReport, uint8_t *pabDepressedKeys)
1083{
1084 RT_ZERO(*pReport);
1085
1086 for (unsigned iKey = 0; iKey < VBOX_USB_USAGE_ARRAY_SIZE; ++iKey)
1087 {
1088 if (pabDepressedKeys[iKey])
1089 {
1090 /* Key index back to 32-bit HID code. */
1091 uint32_t u32HidCode = usbInternalCodeToHid(iKey);
1092 uint8_t u8HidPage = RT_LOBYTE(RT_HIWORD(u32HidCode));
1093 uint16_t u16HidUsage = RT_LOWORD(u32HidCode);
1094
1095 if (u8HidPage == USB_HID_CC_PAGE)
1096 pReport->uKeyCC = u16HidUsage;
1097 else if (u8HidPage == USB_HID_DC_PAGE)
1098 if (usbHidUsageCodeIsSCKey(u16HidUsage))
1099 pReport->uSCKeys |= usbHidSCKeyToMask(u16HidUsage);
1100 }
1101 }
1102}
1103
1104/**
[47675]1105 * Handles a SET_REPORT request sent to the default control pipe. Note
1106 * that unrecognized requests are ignored without reporting an error.
1107 */
1108static void usbHidSetReport(PUSBHID pThis, PVUSBURB pUrb)
1109{
1110 PVUSBSETUP pSetup = (PVUSBSETUP)&pUrb->abData[0];
1111 Assert(pSetup->bRequest == HID_REQ_SET_REPORT);
1112
1113 /* The LED report is the 3rd report, ID 0 (-> wValue 0x200). */
1114 if (pSetup->wIndex == 0 && pSetup->wLength == 1 && pSetup->wValue == 0x200)
1115 {
1116 PDMKEYBLEDS enmLeds = PDMKEYBLEDS_NONE;
1117 uint8_t u8LEDs = pUrb->abData[sizeof(*pSetup)];
1118 LogFlowFunc(("Setting keybooard LEDs to u8LEDs=%02X\n", u8LEDs));
1119
1120 /* Translate LED state to PDM format and send upstream. */
1121 if (u8LEDs & 0x01)
1122 enmLeds = (PDMKEYBLEDS)(enmLeds | PDMKEYBLEDS_NUMLOCK);
1123 if (u8LEDs & 0x02)
1124 enmLeds = (PDMKEYBLEDS)(enmLeds | PDMKEYBLEDS_CAPSLOCK);
1125 if (u8LEDs & 0x04)
1126 enmLeds = (PDMKEYBLEDS)(enmLeds | PDMKEYBLEDS_SCROLLLOCK);
1127
1128 pThis->Lun0.pDrv->pfnLedStatusChange(pThis->Lun0.pDrv, enmLeds);
1129 }
1130}
1131
1132/**
[51539]1133 * Sends a state report to the guest if there is a URB available.
[26473]1134 */
[90697]1135static void usbHidSendReport(PUSBHID pThis, PUSBHIDIF pIf)
[26473]1136{
[90697]1137 PVUSBURB pUrb = usbHidQueueRemoveHead(&pIf->ToHostQueue);
[26473]1138 if (pUrb)
1139 {
[90697]1140 pIf->fHasPendingChanges = false;
1141 if (pIf == &pThis->aIfs[0])
1142 {
1143 USBHIDK_REPORT ReportKbd;
[26473]1144
[90697]1145 usbHidBuildReportKbd(&ReportKbd, pThis->abDepressedKeys);
1146 usbHidCompleteOk(pThis, pUrb, &ReportKbd, sizeof(ReportKbd));
1147 }
1148 else
1149 {
1150 Assert(pIf == &pThis->aIfs[1]);
1151 USBHIDX_REPORT ReportExt;
1152
1153 usbHidBuildReportExt(&ReportExt, pThis->abDepressedKeys);
1154 usbHidCompleteOk(pThis, pUrb, &ReportExt, sizeof(ReportExt));
1155 }
[26473]1156 }
[27838]1157 else
1158 {
[27890]1159 Log2(("No available URB for USB kbd\n"));
[90697]1160 pIf->fHasPendingChanges = true;
[27838]1161 }
[26473]1162}
1163
1164/**
1165 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
1166 */
1167static DECLCALLBACK(void *) usbHidKeyboardQueryInterface(PPDMIBASE pInterface, const char *pszIID)
1168{
1169 PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IBase);
1170 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->Lun0.IBase);
1171 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIKEYBOARDPORT, &pThis->Lun0.IPort);
1172 return NULL;
1173}
1174
1175/**
[82213]1176 * @interface_method_impl{PDMIKEYBOARDPORT,pfnPutEventHid}
[26473]1177 */
[82213]1178static DECLCALLBACK(int) usbHidKeyboardPutEvent(PPDMIKEYBOARDPORT pInterface, uint32_t idUsage)
[26473]1179{
[90697]1180 PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort);
1181 PUSBHIDIF pIf;
[51539]1182 bool fKeyDown;
[27917]1183 bool fHaveEvent = true;
[51539]1184 int rc = VINF_SUCCESS;
[89935]1185 int iKeyCode;
[90697]1186 uint8_t u8HidPage = RT_LOBYTE(RT_HIWORD(idUsage));
[26473]1187
[51539]1188 /* Let's see what we got... */
[89935]1189 fKeyDown = !(idUsage & PDMIKBDPORT_KEY_UP);
[51539]1190
[90697]1191 /* Always respond to USB_HID_KB_PAGE, but quietly drop USB_HID_CC_PAGE/USB_HID_DC_PAGE
1192 * events unless the device is in the extended mode. And drop anything else, too.
1193 */
1194 if (u8HidPage == USB_HID_KB_PAGE)
1195 pIf = &pThis->aIfs[0];
1196 else
1197 {
1198 if ( pThis->fExtPipeActive
1199 && ((u8HidPage == USB_HID_CC_PAGE) || (u8HidPage == USB_HID_DC_PAGE)))
1200 pIf = &pThis->aIfs[1];
1201 else
1202 return VINF_SUCCESS; /* Must consume data to avoid blockage. */
1203 }
1204
[89935]1205 iKeyCode = usbHidToInternalCode(idUsage);
[95427]1206 AssertReturn((iKeyCode > 0 && iKeyCode <= VBOX_USB_MAX_USAGE_CODE) || (idUsage & PDMIKBDPORT_RELEASE_KEYS), VERR_INTERNAL_ERROR);
[89935]1207
[82213]1208 RTCritSectEnter(&pThis->CritSect);
1209
[95427]1210 if (RT_LIKELY(!(idUsage & PDMIKBDPORT_RELEASE_KEYS)))
1211 {
1212 LogFlowFunc(("key %s: %08X (iKeyCode 0x%x)\n", fKeyDown ? "down" : "up", idUsage, iKeyCode));
[51539]1213
[95427]1214 /*
1215 * Due to host key repeat, we can get key events for keys which are
1216 * already depressed. Drop those right here.
1217 */
1218 if (fKeyDown && pThis->abDepressedKeys[iKeyCode])
1219 fHaveEvent = false;
[51539]1220
[95427]1221 /* If there is already a pending event, we won't accept a new one yet. */
1222 if (pIf->fHasPendingChanges && fHaveEvent)
[26473]1223 {
[95427]1224 rc = VERR_TRY_AGAIN;
1225 }
1226 else if (fHaveEvent)
1227 {
[51539]1228 /* Regular key event - update keyboard state. */
1229 if (fKeyDown)
[89935]1230 pThis->abDepressedKeys[iKeyCode] = 1;
[51539]1231 else
[89935]1232 pThis->abDepressedKeys[iKeyCode] = 0;
[95427]1233
1234 /*
1235 * Try sending a report. Note that we already decided to consume the
1236 * event regardless of whether a URB is available or not. If it's not,
1237 * we will simply not accept any further events.
1238 */
1239 usbHidSendReport(pThis, pIf);
[50962]1240 }
[95427]1241 }
1242 else
1243 {
1244 LogFlowFunc(("Release all keys.\n"));
[27890]1245
[95427]1246 /* Clear all currently depressed keys. */
1247 RT_ZERO(pThis->abDepressedKeys);
[26473]1248 }
1249
[27969]1250 RTCritSectLeave(&pThis->CritSect);
[27890]1251
[51539]1252 return rc;
[26473]1253}
1254
1255/**
[62956]1256 * @interface_method_impl{PDMUSBREG,pfnUrbReap}
[26473]1257 */
1258static DECLCALLBACK(PVUSBURB) usbHidUrbReap(PPDMUSBINS pUsbIns, RTMSINTERVAL cMillies)
1259{
1260 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
[27890]1261 //LogFlow(("usbHidUrbReap/#%u: cMillies=%u\n", pUsbIns->iInstance, cMillies));
[26473]1262
[27969]1263 RTCritSectEnter(&pThis->CritSect);
[26473]1264
1265 PVUSBURB pUrb = usbHidQueueRemoveHead(&pThis->DoneQueue);
1266 if (!pUrb && cMillies)
1267 {
1268 /* Wait */
1269 pThis->fHaveDoneQueueWaiter = true;
[27969]1270 RTCritSectLeave(&pThis->CritSect);
[26473]1271
1272 RTSemEventWait(pThis->hEvtDoneQueue, cMillies);
1273
[27969]1274 RTCritSectEnter(&pThis->CritSect);
[26473]1275 pThis->fHaveDoneQueueWaiter = false;
1276
1277 pUrb = usbHidQueueRemoveHead(&pThis->DoneQueue);
1278 }
1279
[27969]1280 RTCritSectLeave(&pThis->CritSect);
[26473]1281
1282 if (pUrb)
1283 Log(("usbHidUrbReap/#%u: pUrb=%p:%s\n", pUsbIns->iInstance, pUrb, pUrb->pszDesc));
1284 return pUrb;
1285}
1286
1287
1288/**
[62956]1289 * @interface_method_impl{PDMUSBREG,pfnWakeup}
[49814]1290 */
1291static DECLCALLBACK(int) usbHidWakeup(PPDMUSBINS pUsbIns)
1292{
1293 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
1294
1295 return RTSemEventSignal(pThis->hEvtDoneQueue);
1296}
1297
1298
1299/**
[62956]1300 * @interface_method_impl{PDMUSBREG,pfnUrbCancel}
[26473]1301 */
1302static DECLCALLBACK(int) usbHidUrbCancel(PPDMUSBINS pUsbIns, PVUSBURB pUrb)
1303{
1304 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
1305 LogFlow(("usbHidUrbCancel/#%u: pUrb=%p:%s\n", pUsbIns->iInstance, pUrb, pUrb->pszDesc));
[27969]1306 RTCritSectEnter(&pThis->CritSect);
[26473]1307
1308 /*
[90697]1309 * Remove the URB from its to-host queue and move it onto the done queue.
[26473]1310 */
[90697]1311 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aIfs); i++)
1312 if (usbHidQueueRemove(&pThis->aIfs[i].ToHostQueue, pUrb))
1313 usbHidLinkDone(pThis, pUrb);
[26473]1314
[27969]1315 RTCritSectLeave(&pThis->CritSect);
[26473]1316 return VINF_SUCCESS;
1317}
1318
1319
1320/**
1321 * Handles request sent to the inbound (device to host) interrupt pipe. This is
1322 * rather different from bulk requests because an interrupt read URB may complete
1323 * after arbitrarily long time.
1324 */
[90697]1325static int usbHidHandleIntrDevToHost(PUSBHID pThis, PUSBHIDEP pEp, PUSBHIDIF pIf, PVUSBURB pUrb)
[26473]1326{
1327 /*
1328 * Stall the request if the pipe is halted.
1329 */
1330 if (RT_UNLIKELY(pEp->fHalted))
1331 return usbHidCompleteStall(pThis, NULL, pUrb, "Halted pipe");
1332
1333 /*
[90697]1334 * Deal with the URB according to the endpoint/interface state.
[26473]1335 */
[90697]1336 switch (pIf->enmState)
[26473]1337 {
1338 /*
1339 * We've data left to transfer to the host.
1340 */
1341 case USBHIDREQSTATE_DATA_TO_HOST:
1342 {
1343 AssertFailed();
1344 Log(("usbHidHandleIntrDevToHost: Entering STATUS\n"));
[90697]1345 return usbHidCompleteOk(pThis, pUrb, NULL, 0);
[26473]1346 }
1347
1348 /*
1349 * Status transfer.
1350 */
1351 case USBHIDREQSTATE_STATUS:
1352 {
1353 AssertFailed();
1354 Log(("usbHidHandleIntrDevToHost: Entering READY\n"));
[90697]1355 pIf->enmState = USBHIDREQSTATE_READY;
1356 return usbHidCompleteOk(pThis, pUrb, NULL, 0);
[26473]1357 }
1358
1359 case USBHIDREQSTATE_READY:
[90697]1360 usbHidQueueAddTail(&pIf->ToHostQueue, pUrb);
[44022]1361 /* If device was not set idle, send the current report right away. */
[90697]1362 if (pThis->bIdle != 0 || pIf->fHasPendingChanges)
[51539]1363 {
[90697]1364 usbHidSendReport(pThis, pIf);
[51539]1365 LogFlow(("usbHidHandleIntrDevToHost: Sent report via %p:%s\n", pUrb, pUrb->pszDesc));
[90697]1366 Assert(!pIf->fHasPendingChanges); /* Since we just got a URB... */
[51539]1367 /* There may be more input queued up. Ask for it now. */
1368 pThis->Lun0.pDrv->pfnFlushQueue(pThis->Lun0.pDrv);
1369 }
[26473]1370 return VINF_SUCCESS;
1371
1372 /*
1373 * Bad states, stall.
1374 */
1375 default:
[90697]1376 Log(("usbHidHandleIntrDevToHost: enmState=%d cbData=%#x\n", pIf->enmState, pUrb->cbData));
[26473]1377 return usbHidCompleteStall(pThis, NULL, pUrb, "Really bad state (D2H)!");
1378 }
1379}
1380
1381
1382/**
1383 * Handles request sent to the default control pipe.
1384 */
1385static int usbHidHandleDefaultPipe(PUSBHID pThis, PUSBHIDEP pEp, PVUSBURB pUrb)
1386{
1387 PVUSBSETUP pSetup = (PVUSBSETUP)&pUrb->abData[0];
[27838]1388 LogFlow(("usbHidHandleDefaultPipe: cbData=%d\n", pUrb->cbData));
1389
[26473]1390 AssertReturn(pUrb->cbData >= sizeof(*pSetup), VERR_VUSB_FAILED_TO_QUEUE_URB);
1391
1392 if ((pSetup->bmRequestType & VUSB_REQ_MASK) == VUSB_REQ_STANDARD)
1393 {
1394 switch (pSetup->bRequest)
1395 {
1396 case VUSB_REQ_GET_DESCRIPTOR:
1397 {
1398 switch (pSetup->bmRequestType)
1399 {
1400 case VUSB_TO_DEVICE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
1401 {
1402 switch (pSetup->wValue >> 8)
1403 {
1404 case VUSB_DT_STRING:
1405 Log(("usbHid: GET_DESCRIPTOR DT_STRING wValue=%#x wIndex=%#x\n", pSetup->wValue, pSetup->wIndex));
1406 break;
1407 default:
1408 Log(("usbHid: GET_DESCRIPTOR, huh? wValue=%#x wIndex=%#x\n", pSetup->wValue, pSetup->wIndex));
1409 break;
1410 }
1411 break;
1412 }
1413
1414 case VUSB_TO_INTERFACE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
1415 {
1416 switch (pSetup->wValue >> 8)
1417 {
[37388]1418 case DT_IF_HID_DESCRIPTOR:
1419 {
[90697]1420 uint32_t cbSrc;
1421 const void *pSrc;
[37388]1422
[90697]1423 if (pSetup->wIndex == 0)
1424 {
1425 cbSrc = RT_MIN(pSetup->wLength, sizeof(g_UsbHidIfHidDescKbd));
1426 pSrc = &g_UsbHidIfHidDescKbd;
1427 }
1428 else
1429 {
1430 cbSrc = RT_MIN(pSetup->wLength, sizeof(g_UsbHidIfHidDescExt));
1431 pSrc = &g_UsbHidIfHidDescExt;
1432 }
1433 Log(("usbHidKbd: GET_DESCRIPTOR DT_IF_HID_DESCRIPTOR wValue=%#x wIndex=%#x cbSrc=%#x\n", pSetup->wValue, pSetup->wIndex, cbSrc));
1434 return usbHidCompleteOk(pThis, pUrb, pSrc, cbSrc);
[37388]1435 }
1436
[26473]1437 case DT_IF_HID_REPORT:
[37388]1438 {
[90697]1439 uint32_t cbSrc;
1440 const void *pSrc;
[26473]1441
1442 /* Returned data is written after the setup message. */
[90697]1443 if (pSetup->wIndex == 0)
1444 {
1445 cbSrc = RT_MIN(pSetup->wLength, sizeof(g_UsbHidReportDescKbd));
1446 pSrc = &g_UsbHidReportDescKbd;
1447 }
1448 else
1449 {
1450 cbSrc = RT_MIN(pSetup->wLength, sizeof(g_UsbHidReportDescExt));
1451 pSrc = &g_UsbHidReportDescExt;
1452 }
1453
1454 Log(("usbHid: GET_DESCRIPTOR DT_IF_HID_REPORT wValue=%#x wIndex=%#x cbSrc=%#x\n", pSetup->wValue, pSetup->wIndex, cbSrc));
1455 return usbHidCompleteOk(pThis, pUrb, pSrc, cbSrc);
[37388]1456 }
1457
[26473]1458 default:
1459 Log(("usbHid: GET_DESCRIPTOR, huh? wValue=%#x wIndex=%#x\n", pSetup->wValue, pSetup->wIndex));
1460 break;
1461 }
1462 break;
1463 }
1464
1465 default:
1466 Log(("usbHid: Bad GET_DESCRIPTOR req: bmRequestType=%#x\n", pSetup->bmRequestType));
1467 return usbHidCompleteStall(pThis, pEp, pUrb, "Bad GET_DESCRIPTOR");
1468 }
1469 break;
1470 }
1471
[26945]1472 case VUSB_REQ_GET_STATUS:
1473 {
1474 uint16_t wRet = 0;
1475
[27129]1476 if (pSetup->wLength != 2)
[26945]1477 {
1478 Log(("usbHid: Bad GET_STATUS req: wLength=%#x\n", pSetup->wLength));
1479 break;
1480 }
1481 Assert(pSetup->wValue == 0);
1482 switch (pSetup->bmRequestType)
1483 {
1484 case VUSB_TO_DEVICE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
1485 {
1486 Assert(pSetup->wIndex == 0);
1487 Log(("usbHid: GET_STATUS (device)\n"));
1488 wRet = 0; /* Not self-powered, no remote wakeup. */
[90697]1489 return usbHidCompleteOk(pThis, pUrb, &wRet, sizeof(wRet));
[26945]1490 }
[27129]1491
[26945]1492 case VUSB_TO_INTERFACE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
1493 {
1494 if (pSetup->wIndex == 0)
1495 {
[90697]1496 return usbHidCompleteOk(pThis, pUrb, &wRet, sizeof(wRet));
[26945]1497 }
[71779]1498 Log(("usbHid: GET_STATUS (interface) invalid, wIndex=%#x\n", pSetup->wIndex));
[26945]1499 break;
1500 }
1501
1502 case VUSB_TO_ENDPOINT | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
1503 {
1504 if (pSetup->wIndex < RT_ELEMENTS(pThis->aEps))
1505 {
1506 wRet = pThis->aEps[pSetup->wIndex].fHalted ? 1 : 0;
[90697]1507 return usbHidCompleteOk(pThis, pUrb, &wRet, sizeof(wRet));
[26945]1508 }
[71779]1509 Log(("usbHid: GET_STATUS (endpoint) invalid, wIndex=%#x\n", pSetup->wIndex));
[26945]1510 break;
1511 }
1512
1513 default:
1514 Log(("usbHid: Bad GET_STATUS req: bmRequestType=%#x\n", pSetup->bmRequestType));
1515 return usbHidCompleteStall(pThis, pEp, pUrb, "Bad GET_STATUS");
1516 }
1517 break;
1518 }
1519
[26473]1520 case VUSB_REQ_CLEAR_FEATURE:
1521 break;
1522 }
1523
1524 /** @todo implement this. */
1525 Log(("usbHid: Implement standard request: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n",
1526 pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue, pSetup->wIndex, pSetup->wLength));
1527
1528 usbHidCompleteStall(pThis, pEp, pUrb, "TODO: standard request stuff");
1529 }
1530 else if ((pSetup->bmRequestType & VUSB_REQ_MASK) == VUSB_REQ_CLASS)
1531 {
1532 switch (pSetup->bRequest)
1533 {
1534 case HID_REQ_SET_IDLE:
1535 {
1536 switch (pSetup->bmRequestType)
1537 {
1538 case VUSB_TO_INTERFACE | VUSB_REQ_CLASS | VUSB_DIR_TO_DEVICE:
1539 {
1540 Log(("usbHid: SET_IDLE wValue=%#x wIndex=%#x\n", pSetup->wValue, pSetup->wIndex));
1541 pThis->bIdle = pSetup->wValue >> 8;
1542 /* Consider 24ms to mean zero for keyboards (see IOUSBHIDDriver) */
1543 if (pThis->bIdle == 6) pThis->bIdle = 0;
[90697]1544 return usbHidCompleteOk(pThis, pUrb, NULL, 0);
[26473]1545 }
1546 break;
1547 }
1548 break;
[26495]1549 }
[26473]1550 case HID_REQ_GET_IDLE:
1551 {
1552 switch (pSetup->bmRequestType)
1553 {
1554 case VUSB_TO_INTERFACE | VUSB_REQ_CLASS | VUSB_DIR_TO_HOST:
1555 {
1556 Log(("usbHid: GET_IDLE wValue=%#x wIndex=%#x, returning %#x\n", pSetup->wValue, pSetup->wIndex, pThis->bIdle));
[90697]1557 return usbHidCompleteOk(pThis, pUrb, &pThis->bIdle, sizeof(pThis->bIdle));
[26473]1558 }
1559 break;
1560 }
1561 break;
[26495]1562 }
[47675]1563 case HID_REQ_SET_REPORT:
1564 {
1565 switch (pSetup->bmRequestType)
1566 {
1567 case VUSB_TO_INTERFACE | VUSB_REQ_CLASS | VUSB_DIR_TO_DEVICE:
1568 {
1569 Log(("usbHid: SET_REPORT wValue=%#x wIndex=%#x wLength=%#x\n", pSetup->wValue, pSetup->wIndex, pSetup->wLength));
1570 usbHidSetReport(pThis, pUrb);
[90697]1571 return usbHidCompleteOk(pThis, pUrb, NULL, 0);
[47675]1572 }
1573 break;
1574 }
1575 break;
1576 }
[26473]1577 }
1578 Log(("usbHid: Unimplemented class request: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n",
1579 pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue, pSetup->wIndex, pSetup->wLength));
1580
1581 usbHidCompleteStall(pThis, pEp, pUrb, "TODO: class request stuff");
1582 }
1583 else
1584 {
1585 Log(("usbHid: Unknown control msg: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n",
1586 pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue, pSetup->wIndex, pSetup->wLength));
1587 return usbHidCompleteStall(pThis, pEp, pUrb, "Unknown control msg");
1588 }
1589
1590 return VINF_SUCCESS;
1591}
1592
1593
1594/**
[62956]1595 * @interface_method_impl{PDMUSBREG,pfnUrbQueue}
[26473]1596 */
[90697]1597static DECLCALLBACK(int) usbHidQueueUrb(PPDMUSBINS pUsbIns, PVUSBURB pUrb)
[26473]1598{
1599 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
1600 LogFlow(("usbHidQueue/#%u: pUrb=%p:%s EndPt=%#x\n", pUsbIns->iInstance, pUrb, pUrb->pszDesc, pUrb->EndPt));
[27969]1601 RTCritSectEnter(&pThis->CritSect);
[26473]1602
1603 /*
[90697]1604 * Parse on a per-endpoint basis.
[26473]1605 */
1606 int rc;
1607 switch (pUrb->EndPt)
1608 {
1609 case 0:
1610 rc = usbHidHandleDefaultPipe(pThis, &pThis->aEps[0], pUrb);
1611 break;
1612
[90697]1613 /* Standard keyboard interface. */
[26473]1614 case 0x81:
1615 AssertFailed();
[69046]1616 RT_FALL_THRU();
[26473]1617 case 0x01:
[90697]1618 rc = usbHidHandleIntrDevToHost(pThis, &pThis->aEps[1], &pThis->aIfs[0], pUrb);
[26473]1619 break;
1620
[90697]1621 /* Extended multimedia/control keys interface. */
1622 case 0x82:
1623 AssertFailed();
1624 RT_FALL_THRU();
1625 case 0x02:
1626 if (pThis->enmMode == USBKBDMODE_EXTENDED)
1627 {
1628 rc = usbHidHandleIntrDevToHost(pThis, &pThis->aEps[2], &pThis->aIfs[1], pUrb);
1629 pThis->fExtPipeActive = true;
1630 break;
1631 }
1632 RT_FALL_THRU();
[26473]1633 default:
1634 AssertMsgFailed(("EndPt=%d\n", pUrb->EndPt));
1635 rc = VERR_VUSB_FAILED_TO_QUEUE_URB;
1636 break;
1637 }
1638
[27969]1639 RTCritSectLeave(&pThis->CritSect);
[26473]1640 return rc;
1641}
1642
1643
1644/**
[62956]1645 * @interface_method_impl{PDMUSBREG,pfnUsbClearHaltedEndpoint}
[26473]1646 */
1647static DECLCALLBACK(int) usbHidUsbClearHaltedEndpoint(PPDMUSBINS pUsbIns, unsigned uEndpoint)
1648{
1649 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
1650 LogFlow(("usbHidUsbClearHaltedEndpoint/#%u: uEndpoint=%#x\n", pUsbIns->iInstance, uEndpoint));
1651
1652 if ((uEndpoint & ~0x80) < RT_ELEMENTS(pThis->aEps))
1653 {
[27969]1654 RTCritSectEnter(&pThis->CritSect);
[26473]1655 pThis->aEps[(uEndpoint & ~0x80)].fHalted = false;
[27969]1656 RTCritSectLeave(&pThis->CritSect);
[26473]1657 }
1658
1659 return VINF_SUCCESS;
1660}
1661
1662
1663/**
[62956]1664 * @interface_method_impl{PDMUSBREG,pfnUsbSetInterface}
[26473]1665 */
1666static DECLCALLBACK(int) usbHidUsbSetInterface(PPDMUSBINS pUsbIns, uint8_t bInterfaceNumber, uint8_t bAlternateSetting)
1667{
[62885]1668 RT_NOREF3(pUsbIns, bInterfaceNumber, bAlternateSetting);
[26473]1669 LogFlow(("usbHidUsbSetInterface/#%u: bInterfaceNumber=%u bAlternateSetting=%u\n", pUsbIns->iInstance, bInterfaceNumber, bAlternateSetting));
1670 Assert(bAlternateSetting == 0);
1671 return VINF_SUCCESS;
1672}
1673
1674
1675/**
[62956]1676 * @interface_method_impl{PDMUSBREG,pfnUsbSetConfiguration}
[26473]1677 */
1678static DECLCALLBACK(int) usbHidUsbSetConfiguration(PPDMUSBINS pUsbIns, uint8_t bConfigurationValue,
1679 const void *pvOldCfgDesc, const void *pvOldIfState, const void *pvNewCfgDesc)
1680{
[62885]1681 RT_NOREF3(pvOldCfgDesc, pvOldIfState, pvNewCfgDesc);
[26473]1682 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
1683 LogFlow(("usbHidUsbSetConfiguration/#%u: bConfigurationValue=%u\n", pUsbIns->iInstance, bConfigurationValue));
1684 Assert(bConfigurationValue == 1);
[27969]1685 RTCritSectEnter(&pThis->CritSect);
[26473]1686
1687 /*
1688 * If the same config is applied more than once, it's a kind of reset.
1689 */
1690 if (pThis->bConfigurationValue == bConfigurationValue)
1691 usbHidResetWorker(pThis, NULL, true /*fSetConfig*/); /** @todo figure out the exact difference */
1692 pThis->bConfigurationValue = bConfigurationValue;
1693
[28909]1694 /*
1695 * Tell the other end that the keyboard is now enabled and wants
1696 * to receive keystrokes.
1697 */
1698 pThis->Lun0.pDrv->pfnSetActive(pThis->Lun0.pDrv, true);
1699
[27969]1700 RTCritSectLeave(&pThis->CritSect);
[26473]1701 return VINF_SUCCESS;
1702}
1703
1704
1705/**
[62956]1706 * @interface_method_impl{PDMUSBREG,pfnUsbGetDescriptorCache}
[26473]1707 */
1708static DECLCALLBACK(PCPDMUSBDESCCACHE) usbHidUsbGetDescriptorCache(PPDMUSBINS pUsbIns)
1709{
[90697]1710 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
1711 LogRelFlow(("usbHidUsbGetDescriptorCache/#%u:\n", pUsbIns->iInstance));
1712 switch (pThis->enmMode)
1713 {
1714 case USBKBDMODE_BASIC:
1715 return &g_UsbHidBasDescCache;
1716 case USBKBDMODE_EXTENDED:
1717 return &g_UsbHidExtDescCache;
1718 default:
1719 return NULL;
1720 }
[26473]1721}
1722
1723
1724/**
[62956]1725 * @interface_method_impl{PDMUSBREG,pfnUsbReset}
[26473]1726 */
1727static DECLCALLBACK(int) usbHidUsbReset(PPDMUSBINS pUsbIns, bool fResetOnLinux)
1728{
[62885]1729 RT_NOREF1(fResetOnLinux);
[26473]1730 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
1731 LogFlow(("usbHidUsbReset/#%u:\n", pUsbIns->iInstance));
[27969]1732 RTCritSectEnter(&pThis->CritSect);
[26473]1733
1734 int rc = usbHidResetWorker(pThis, NULL, false /*fSetConfig*/);
1735
[27969]1736 RTCritSectLeave(&pThis->CritSect);
[26473]1737 return rc;
1738}
1739
1740
1741/**
[62956]1742 * @interface_method_impl{PDMUSBREG,pfnDestruct}
[26473]1743 */
[57393]1744static DECLCALLBACK(void) usbHidDestruct(PPDMUSBINS pUsbIns)
[26473]1745{
[62885]1746 PDMUSB_CHECK_VERSIONS_RETURN_VOID(pUsbIns);
[26473]1747 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
1748 LogFlow(("usbHidDestruct/#%u:\n", pUsbIns->iInstance));
1749
[27969]1750 if (RTCritSectIsInitialized(&pThis->CritSect))
[26473]1751 {
[27969]1752 /* Let whoever runs in this critical section complete. */
1753 RTCritSectEnter(&pThis->CritSect);
1754 RTCritSectLeave(&pThis->CritSect);
1755 RTCritSectDelete(&pThis->CritSect);
[26473]1756 }
1757
1758 if (pThis->hEvtDoneQueue != NIL_RTSEMEVENT)
1759 {
1760 RTSemEventDestroy(pThis->hEvtDoneQueue);
1761 pThis->hEvtDoneQueue = NIL_RTSEMEVENT;
1762 }
1763}
1764
1765
1766/**
[62956]1767 * @interface_method_impl{PDMUSBREG,pfnConstruct}
[26473]1768 */
1769static DECLCALLBACK(int) usbHidConstruct(PPDMUSBINS pUsbIns, int iInstance, PCFGMNODE pCfg, PCFGMNODE pCfgGlobal)
1770{
[62885]1771 RT_NOREF1(pCfgGlobal);
1772 PDMUSB_CHECK_VERSIONS_RETURN(pUsbIns);
[91881]1773 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
1774 PCPDMUSBHLP pHlp = pUsbIns->pHlpR3;
[26473]1775 Log(("usbHidConstruct/#%u:\n", iInstance));
1776
1777 /*
1778 * Perform the basic structure initialization first so the destructor
1779 * will not misbehave.
1780 */
1781 pThis->pUsbIns = pUsbIns;
1782 pThis->hEvtDoneQueue = NIL_RTSEMEVENT;
1783 usbHidQueueInit(&pThis->DoneQueue);
[90697]1784 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aIfs); i++)
1785 usbHidQueueInit(&pThis->aIfs[i].ToHostQueue);
[26473]1786
[27969]1787 int rc = RTCritSectInit(&pThis->CritSect);
[26473]1788 AssertRCReturn(rc, rc);
1789
1790 rc = RTSemEventCreate(&pThis->hEvtDoneQueue);
1791 AssertRCReturn(rc, rc);
1792
1793 /*
1794 * Validate and read the configuration.
1795 */
[91881]1796 rc = pHlp->pfnCFGMValidateConfig(pCfg, "/", "Mode", "Config", "UsbHid", iInstance);
[26473]1797 if (RT_FAILURE(rc))
1798 return rc;
[90697]1799 char szMode[64];
[91881]1800 rc = pHlp->pfnCFGMQueryStringDef(pCfg, "Mode", szMode, sizeof(szMode), "basic");
[90697]1801 if (RT_FAILURE(rc))
1802 return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("HID failed to query settings"));
1803 if (!RTStrCmp(szMode, "basic"))
1804 pThis->enmMode = USBKBDMODE_BASIC;
1805 else if (!RTStrCmp(szMode, "extended"))
1806 pThis->enmMode = USBKBDMODE_EXTENDED;
1807 else
1808 return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS,
1809 N_("Invalid HID mode"));
[26473]1810
1811 pThis->Lun0.IBase.pfnQueryInterface = usbHidKeyboardQueryInterface;
[50962]1812 pThis->Lun0.IPort.pfnPutEventHid = usbHidKeyboardPutEvent;
[26473]1813
1814 /*
1815 * Attach the keyboard driver.
1816 */
[37795]1817 rc = PDMUsbHlpDriverAttach(pUsbIns, 0 /*iLun*/, &pThis->Lun0.IBase, &pThis->Lun0.pDrvBase, "Keyboard Port");
[26473]1818 if (RT_FAILURE(rc))
1819 return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("HID failed to attach keyboard driver"));
1820
[28909]1821 pThis->Lun0.pDrv = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pDrvBase, PDMIKEYBOARDCONNECTOR);
1822 if (!pThis->Lun0.pDrv)
1823 return PDMUsbHlpVMSetError(pUsbIns, VERR_PDM_MISSING_INTERFACE, RT_SRC_POS, N_("HID failed to query keyboard interface"));
1824
[26473]1825 return VINF_SUCCESS;
1826}
1827
1828
1829/**
1830 * The USB Human Interface Device (HID) Keyboard registration record.
1831 */
1832const PDMUSBREG g_UsbHidKbd =
1833{
1834 /* u32Version */
1835 PDM_USBREG_VERSION,
1836 /* szName */
1837 "HidKeyboard",
1838 /* pszDescription */
1839 "USB HID Keyboard.",
1840 /* fFlags */
1841 0,
1842 /* cMaxInstances */
[40282]1843 ~0U,
[26473]1844 /* cbInstance */
1845 sizeof(USBHID),
1846 /* pfnConstruct */
1847 usbHidConstruct,
1848 /* pfnDestruct */
1849 usbHidDestruct,
1850 /* pfnVMInitComplete */
1851 NULL,
1852 /* pfnVMPowerOn */
1853 NULL,
1854 /* pfnVMReset */
1855 NULL,
1856 /* pfnVMSuspend */
1857 NULL,
1858 /* pfnVMResume */
1859 NULL,
1860 /* pfnVMPowerOff */
1861 NULL,
1862 /* pfnHotPlugged */
1863 NULL,
1864 /* pfnHotUnplugged */
1865 NULL,
1866 /* pfnDriverAttach */
1867 NULL,
1868 /* pfnDriverDetach */
1869 NULL,
1870 /* pfnQueryInterface */
1871 NULL,
1872 /* pfnUsbReset */
1873 usbHidUsbReset,
[36322]1874 /* pfnUsbGetDescriptorCache */
[26473]1875 usbHidUsbGetDescriptorCache,
1876 /* pfnUsbSetConfiguration */
1877 usbHidUsbSetConfiguration,
1878 /* pfnUsbSetInterface */
1879 usbHidUsbSetInterface,
1880 /* pfnUsbClearHaltedEndpoint */
1881 usbHidUsbClearHaltedEndpoint,
1882 /* pfnUrbNew */
1883 NULL/*usbHidUrbNew*/,
[36421]1884 /* pfnUrbQueue */
[90697]1885 usbHidQueueUrb,
[26473]1886 /* pfnUrbCancel */
1887 usbHidUrbCancel,
1888 /* pfnUrbReap */
1889 usbHidUrbReap,
[49814]1890 /* pfnWakeup */
1891 usbHidWakeup,
[26473]1892 /* u32TheEnd */
1893 PDM_USBREG_VERSION
1894};
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use