VirtualBox

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

Last change on this file since 50962 was 50962, checked in by vboxsync, 11 years ago

Send HID usage codes rather than XT scan codes to keyboard devices, with conversion in driver. See #6026.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 50.0 KB
Line 
1/* $Id: UsbKbd.cpp 50962 2014-04-03 13:58:47Z vboxsync $ */
2/** @file
3 * UsbKbd - USB Human Interface Device Emulation, Keyboard.
4 */
5
6/*
7 * Copyright (C) 2007-2012 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/*******************************************************************************
19* Header Files *
20*******************************************************************************/
21#define LOG_GROUP LOG_GROUP_USB_KBD
22#include <VBox/vmm/pdmusb.h>
23#include <VBox/log.h>
24#include <VBox/err.h>
25#include <iprt/assert.h>
26#include <iprt/critsect.h>
27#include <iprt/mem.h>
28#include <iprt/semaphore.h>
29#include <iprt/string.h>
30#include <iprt/uuid.h>
31#include "VBoxDD.h"
32
33
34/*******************************************************************************
35* Defined Constants And Macros *
36*******************************************************************************/
37/** @name USB HID string IDs
38 * @{ */
39#define USBHID_STR_ID_MANUFACTURER 1
40#define USBHID_STR_ID_PRODUCT 2
41/** @} */
42
43/** @name USB HID specific descriptor types
44 * @{ */
45#define DT_IF_HID_DESCRIPTOR 0x21
46#define DT_IF_HID_REPORT 0x22
47/** @} */
48
49/** @name USB HID vendor and product IDs
50 * @{ */
51#define VBOX_USB_VENDOR 0x80EE
52#define USBHID_PID_KEYBOARD 0x0010
53/** @} */
54
55/** @name USB HID class specific requests
56 * @{ */
57#define HID_REQ_GET_REPORT 0x01
58#define HID_REQ_GET_IDLE 0x02
59#define HID_REQ_SET_REPORT 0x09
60#define HID_REQ_SET_IDLE 0x0A
61/** @} */
62
63/** @name USB HID additional constants
64 * @{ */
65/** The highest USB usage code reported by the VBox emulated keyboard */
66#define VBOX_USB_MAX_USAGE_CODE 0xE7
67/** The size of an array needed to store all USB usage codes */
68#define VBOX_USB_USAGE_ARRAY_SIZE (VBOX_USB_MAX_USAGE_CODE + 1)
69#define USBHID_USAGE_ROLL_OVER 1
70/** The usage code of the first modifier key. */
71#define USBHID_MODIFIER_FIRST 0xE0
72/** The usage code of the last modifier key. */
73#define USBHID_MODIFIER_LAST 0xE7
74/** @} */
75
76/*******************************************************************************
77* Structures and Typedefs *
78*******************************************************************************/
79
80/**
81 * The USB HID request state.
82 */
83typedef enum USBHIDREQSTATE
84{
85 /** Invalid status. */
86 USBHIDREQSTATE_INVALID = 0,
87 /** Ready to receive a new read request. */
88 USBHIDREQSTATE_READY,
89 /** Have (more) data for the host. */
90 USBHIDREQSTATE_DATA_TO_HOST,
91 /** Waiting to supply status information to the host. */
92 USBHIDREQSTATE_STATUS,
93 /** The end of the valid states. */
94 USBHIDREQSTATE_END
95} USBHIDREQSTATE;
96
97
98/**
99 * Endpoint status data.
100 */
101typedef struct USBHIDEP
102{
103 bool fHalted;
104} USBHIDEP;
105/** Pointer to the endpoint status. */
106typedef USBHIDEP *PUSBHIDEP;
107
108
109/**
110 * A URB queue.
111 */
112typedef struct USBHIDURBQUEUE
113{
114 /** The head pointer. */
115 PVUSBURB pHead;
116 /** Where to insert the next entry. */
117 PVUSBURB *ppTail;
118} USBHIDURBQUEUE;
119/** Pointer to a URB queue. */
120typedef USBHIDURBQUEUE *PUSBHIDURBQUEUE;
121/** Pointer to a const URB queue. */
122typedef USBHIDURBQUEUE const *PCUSBHIDURBQUEUE;
123
124
125/**
126 * The USB HID report structure for regular keys.
127 */
128typedef struct USBHIDK_REPORT
129{
130 uint8_t ShiftState; /**< Modifier keys bitfield */
131 uint8_t Reserved; /**< Currently unused */
132 uint8_t aKeys[6]; /**< Normal keys */
133} USBHIDK_REPORT, *PUSBHIDK_REPORT;
134
135/**
136 * The USB HID instance data.
137 */
138typedef struct USBHID
139{
140 /** Pointer back to the PDM USB Device instance structure. */
141 PPDMUSBINS pUsbIns;
142 /** Critical section protecting the device state. */
143 RTCRITSECT CritSect;
144
145 /** The current configuration.
146 * (0 - default, 1 - the one supported configuration, i.e configured.) */
147 uint8_t bConfigurationValue;
148 /** USB HID Idle value..
149 * (0 - only report state change, !=0 - report in bIdle * 4ms intervals.) */
150 uint8_t bIdle;
151 /** Endpoint 0 is the default control pipe, 1 is the dev->host interrupt one. */
152 USBHIDEP aEps[2];
153 /** The state of the HID (state machine).*/
154 USBHIDREQSTATE enmState;
155
156 /** Pending to-host queue.
157 * The URBs waiting here are waiting for data to become available.
158 */
159 USBHIDURBQUEUE ToHostQueue;
160
161 /** Done queue
162 * The URBs stashed here are waiting to be reaped. */
163 USBHIDURBQUEUE DoneQueue;
164 /** Signalled when adding an URB to the done queue and fHaveDoneQueueWaiter
165 * is set. */
166 RTSEMEVENT hEvtDoneQueue;
167 /** Someone is waiting on the done queue. */
168 bool fHaveDoneQueueWaiter;
169 /** If device has pending changes. */
170 bool fHasPendingChanges;
171 /** Keypresses which have not yet been reported. A workaround for the
172 * problem of keys being released before the keypress could be reported. */
173 uint8_t abUnreportedKeys[VBOX_USB_USAGE_ARRAY_SIZE];
174 /** Currently depressed keys */
175 uint8_t abDepressedKeys[VBOX_USB_USAGE_ARRAY_SIZE];
176
177 /**
178 * Keyboard port - LUN#0.
179 *
180 * @implements PDMIBASE
181 * @implements PDMIKEYBOARDPORT
182 */
183 struct
184 {
185 /** The base interface for the keyboard port. */
186 PDMIBASE IBase;
187 /** The keyboard port base interface. */
188 PDMIKEYBOARDPORT IPort;
189
190 /** The base interface of the attached keyboard driver. */
191 R3PTRTYPE(PPDMIBASE) pDrvBase;
192 /** The keyboard interface of the attached keyboard driver. */
193 R3PTRTYPE(PPDMIKEYBOARDCONNECTOR) pDrv;
194 } Lun0;
195} USBHID;
196/** Pointer to the USB HID instance data. */
197typedef USBHID *PUSBHID;
198
199/*******************************************************************************
200* Global Variables *
201*******************************************************************************/
202static const PDMUSBDESCCACHESTRING g_aUsbHidStrings_en_US[] =
203{
204 { USBHID_STR_ID_MANUFACTURER, "VirtualBox" },
205 { USBHID_STR_ID_PRODUCT, "USB Keyboard" },
206};
207
208static const PDMUSBDESCCACHELANG g_aUsbHidLanguages[] =
209{
210 { 0x0409, RT_ELEMENTS(g_aUsbHidStrings_en_US), g_aUsbHidStrings_en_US }
211};
212
213static const VUSBDESCENDPOINTEX g_aUsbHidEndpointDescs[] =
214{
215 {
216 {
217 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
218 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
219 /* .bEndpointAddress = */ 0x81 /* ep=1, in */,
220 /* .bmAttributes = */ 3 /* interrupt */,
221 /* .wMaxPacketSize = */ 8,
222 /* .bInterval = */ 10,
223 },
224 /* .pvMore = */ NULL,
225 /* .pvClass = */ NULL,
226 /* .cbClass = */ 0
227 },
228};
229
230/** HID report descriptor. */
231static const uint8_t g_UsbHidReportDesc[] =
232{
233 /* Usage Page */ 0x05, 0x01, /* Generic Desktop */
234 /* Usage */ 0x09, 0x06, /* Keyboard */
235 /* Collection */ 0xA1, 0x01, /* Application */
236 /* Usage Page */ 0x05, 0x07, /* Keyboard */
237 /* Usage Minimum */ 0x19, 0xE0, /* Left Ctrl Key */
238 /* Usage Maximum */ 0x29, 0xE7, /* Right GUI Key */
239 /* Logical Minimum */ 0x15, 0x00, /* 0 */
240 /* Logical Maximum */ 0x25, 0x01, /* 1 */
241 /* Report Count */ 0x95, 0x08, /* 8 */
242 /* Report Size */ 0x75, 0x01, /* 1 */
243 /* Input */ 0x81, 0x02, /* Data, Value, Absolute, Bit field */
244 /* Report Count */ 0x95, 0x01, /* 1 */
245 /* Report Size */ 0x75, 0x08, /* 8 (padding bits) */
246 /* Input */ 0x81, 0x01, /* Constant, Array, Absolute, Bit field */
247 /* Report Count */ 0x95, 0x05, /* 5 */
248 /* Report Size */ 0x75, 0x01, /* 1 */
249 /* Usage Page */ 0x05, 0x08, /* LEDs */
250 /* Usage Minimum */ 0x19, 0x01, /* Num Lock */
251 /* Usage Maximum */ 0x29, 0x05, /* Kana */
252 /* Output */ 0x91, 0x02, /* Data, Value, Absolute, Non-volatile,Bit field */
253 /* Report Count */ 0x95, 0x01, /* 1 */
254 /* Report Size */ 0x75, 0x03, /* 3 */
255 /* Output */ 0x91, 0x01, /* Constant, Value, Absolute, Non-volatile, Bit field */
256 /* Report Count */ 0x95, 0x06, /* 6 */
257 /* Report Size */ 0x75, 0x08, /* 8 */
258 /* Logical Minimum */ 0x15, 0x00, /* 0 */
259 /* Logical Maximum */ 0x26, 0xFF,0x00,/* 255 */
260 /* Usage Page */ 0x05, 0x07, /* Keyboard */
261 /* Usage Minimum */ 0x19, 0x00, /* 0 */
262 /* Usage Maximum */ 0x29, 0xFF, /* 255 */
263 /* Input */ 0x81, 0x00, /* Data, Array, Absolute, Bit field */
264 /* End Collection */ 0xC0,
265};
266
267/** Additional HID class interface descriptor. */
268static const uint8_t g_UsbHidIfHidDesc[] =
269{
270 /* .bLength = */ 0x09,
271 /* .bDescriptorType = */ 0x21, /* HID */
272 /* .bcdHID = */ 0x10, 0x01, /* 1.1 */
273 /* .bCountryCode = */ 0x0D, /* International (ISO) */
274 /* .bNumDescriptors = */ 1,
275 /* .bDescriptorType = */ 0x22, /* Report */
276 /* .wDescriptorLength = */ sizeof(g_UsbHidReportDesc), 0x00
277};
278
279static const VUSBDESCINTERFACEEX g_UsbHidInterfaceDesc =
280{
281 {
282 /* .bLength = */ sizeof(VUSBDESCINTERFACE),
283 /* .bDescriptorType = */ VUSB_DT_INTERFACE,
284 /* .bInterfaceNumber = */ 0,
285 /* .bAlternateSetting = */ 0,
286 /* .bNumEndpoints = */ 1,
287 /* .bInterfaceClass = */ 3 /* HID */,
288 /* .bInterfaceSubClass = */ 1 /* Boot Interface */,
289 /* .bInterfaceProtocol = */ 1 /* Keyboard */,
290 /* .iInterface = */ 0
291 },
292 /* .pvMore = */ NULL,
293 /* .pvClass = */ &g_UsbHidIfHidDesc,
294 /* .cbClass = */ sizeof(g_UsbHidIfHidDesc),
295 &g_aUsbHidEndpointDescs[0],
296 /* .pIAD = */ NULL,
297 /* .cbIAD = */ 0
298};
299
300static const VUSBINTERFACE g_aUsbHidInterfaces[] =
301{
302 { &g_UsbHidInterfaceDesc, /* .cSettings = */ 1 },
303};
304
305static const VUSBDESCCONFIGEX g_UsbHidConfigDesc =
306{
307 {
308 /* .bLength = */ sizeof(VUSBDESCCONFIG),
309 /* .bDescriptorType = */ VUSB_DT_CONFIG,
310 /* .wTotalLength = */ 0 /* recalculated on read */,
311 /* .bNumInterfaces = */ RT_ELEMENTS(g_aUsbHidInterfaces),
312 /* .bConfigurationValue =*/ 1,
313 /* .iConfiguration = */ 0,
314 /* .bmAttributes = */ RT_BIT(7),
315 /* .MaxPower = */ 50 /* 100mA */
316 },
317 NULL, /* pvMore */
318 &g_aUsbHidInterfaces[0],
319 NULL /* pvOriginal */
320};
321
322static const VUSBDESCDEVICE g_UsbHidDeviceDesc =
323{
324 /* .bLength = */ sizeof(g_UsbHidDeviceDesc),
325 /* .bDescriptorType = */ VUSB_DT_DEVICE,
326 /* .bcdUsb = */ 0x110, /* 1.1 */
327 /* .bDeviceClass = */ 0 /* Class specified in the interface desc. */,
328 /* .bDeviceSubClass = */ 0 /* Subclass specified in the interface desc. */,
329 /* .bDeviceProtocol = */ 0 /* Protocol specified in the interface desc. */,
330 /* .bMaxPacketSize0 = */ 8,
331 /* .idVendor = */ VBOX_USB_VENDOR,
332 /* .idProduct = */ USBHID_PID_KEYBOARD,
333 /* .bcdDevice = */ 0x0100, /* 1.0 */
334 /* .iManufacturer = */ USBHID_STR_ID_MANUFACTURER,
335 /* .iProduct = */ USBHID_STR_ID_PRODUCT,
336 /* .iSerialNumber = */ 0,
337 /* .bNumConfigurations = */ 1
338};
339
340static const PDMUSBDESCCACHE g_UsbHidDescCache =
341{
342 /* .pDevice = */ &g_UsbHidDeviceDesc,
343 /* .paConfigs = */ &g_UsbHidConfigDesc,
344 /* .paLanguages = */ g_aUsbHidLanguages,
345 /* .cLanguages = */ RT_ELEMENTS(g_aUsbHidLanguages),
346 /* .fUseCachedDescriptors = */ true,
347 /* .fUseCachedStringsDescriptors = */ true
348};
349
350
351/*******************************************************************************
352* Internal Functions *
353*******************************************************************************/
354
355
356/**
357 * Initializes an URB queue.
358 *
359 * @param pQueue The URB queue.
360 */
361static void usbHidQueueInit(PUSBHIDURBQUEUE pQueue)
362{
363 pQueue->pHead = NULL;
364 pQueue->ppTail = &pQueue->pHead;
365}
366
367/**
368 * Inserts an URB at the end of the queue.
369 *
370 * @param pQueue The URB queue.
371 * @param pUrb The URB to insert.
372 */
373DECLINLINE(void) usbHidQueueAddTail(PUSBHIDURBQUEUE pQueue, PVUSBURB pUrb)
374{
375 pUrb->Dev.pNext = NULL;
376 *pQueue->ppTail = pUrb;
377 pQueue->ppTail = &pUrb->Dev.pNext;
378}
379
380
381/**
382 * Unlinks the head of the queue and returns it.
383 *
384 * @returns The head entry.
385 * @param pQueue The URB queue.
386 */
387DECLINLINE(PVUSBURB) usbHidQueueRemoveHead(PUSBHIDURBQUEUE pQueue)
388{
389 PVUSBURB pUrb = pQueue->pHead;
390 if (pUrb)
391 {
392 PVUSBURB pNext = pUrb->Dev.pNext;
393 pQueue->pHead = pNext;
394 if (!pNext)
395 pQueue->ppTail = &pQueue->pHead;
396 else
397 pUrb->Dev.pNext = NULL;
398 }
399 return pUrb;
400}
401
402
403/**
404 * Removes an URB from anywhere in the queue.
405 *
406 * @returns true if found, false if not.
407 * @param pQueue The URB queue.
408 * @param pUrb The URB to remove.
409 */
410DECLINLINE(bool) usbHidQueueRemove(PUSBHIDURBQUEUE pQueue, PVUSBURB pUrb)
411{
412 PVUSBURB pCur = pQueue->pHead;
413 if (pCur == pUrb)
414 pQueue->pHead = pUrb->Dev.pNext;
415 else
416 {
417 while (pCur)
418 {
419 if (pCur->Dev.pNext == pUrb)
420 {
421 pCur->Dev.pNext = pUrb->Dev.pNext;
422 break;
423 }
424 pCur = pCur->Dev.pNext;
425 }
426 if (!pCur)
427 return false;
428 }
429 if (!pUrb->Dev.pNext)
430 pQueue->ppTail = &pQueue->pHead;
431 return true;
432}
433
434
435/**
436 * Checks if the queue is empty or not.
437 *
438 * @returns true if it is, false if it isn't.
439 * @param pQueue The URB queue.
440 */
441DECLINLINE(bool) usbHidQueueIsEmpty(PCUSBHIDURBQUEUE pQueue)
442{
443 return pQueue->pHead == NULL;
444}
445
446
447/**
448 * Links an URB into the done queue.
449 *
450 * @param pThis The HID instance.
451 * @param pUrb The URB.
452 */
453static void usbHidLinkDone(PUSBHID pThis, PVUSBURB pUrb)
454{
455 usbHidQueueAddTail(&pThis->DoneQueue, pUrb);
456
457 if (pThis->fHaveDoneQueueWaiter)
458 {
459 int rc = RTSemEventSignal(pThis->hEvtDoneQueue);
460 AssertRC(rc);
461 }
462}
463
464
465
466/**
467 * Completes the URB with a stalled state, halting the pipe.
468 */
469static int usbHidCompleteStall(PUSBHID pThis, PUSBHIDEP pEp, PVUSBURB pUrb, const char *pszWhy)
470{
471 Log(("usbHidCompleteStall/#%u: pUrb=%p:%s: %s\n", pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc, pszWhy));
472
473 pUrb->enmStatus = VUSBSTATUS_STALL;
474
475 /** @todo figure out if the stall is global or pipe-specific or both. */
476 if (pEp)
477 pEp->fHalted = true;
478 else
479 {
480 pThis->aEps[0].fHalted = true;
481 pThis->aEps[1].fHalted = true;
482 }
483
484 usbHidLinkDone(pThis, pUrb);
485 return VINF_SUCCESS;
486}
487
488
489/**
490 * Completes the URB with a OK state.
491 */
492static int usbHidCompleteOk(PUSBHID pThis, PVUSBURB pUrb, size_t cbData)
493{
494 Log(("usbHidCompleteOk/#%u: pUrb=%p:%s cbData=%#zx\n", pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc, cbData));
495
496 pUrb->enmStatus = VUSBSTATUS_OK;
497 pUrb->cbData = (uint32_t)cbData;
498
499 usbHidLinkDone(pThis, pUrb);
500 return VINF_SUCCESS;
501}
502
503
504/**
505 * Reset worker for usbHidUsbReset, usbHidUsbSetConfiguration and
506 * usbHidHandleDefaultPipe.
507 *
508 * @returns VBox status code.
509 * @param pThis The HID instance.
510 * @param pUrb Set when usbHidHandleDefaultPipe is the
511 * caller.
512 * @param fSetConfig Set when usbHidUsbSetConfiguration is the
513 * caller.
514 */
515static int usbHidResetWorker(PUSBHID pThis, PVUSBURB pUrb, bool fSetConfig)
516{
517 /*
518 * Deactivate the keyboard.
519 */
520 pThis->Lun0.pDrv->pfnSetActive(pThis->Lun0.pDrv, false);
521
522 /*
523 * Reset the device state.
524 */
525 pThis->enmState = USBHIDREQSTATE_READY;
526 pThis->bIdle = 0;
527 pThis->fHasPendingChanges = false;
528
529 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aEps); i++)
530 pThis->aEps[i].fHalted = false;
531
532 if (!pUrb && !fSetConfig) /* (only device reset) */
533 pThis->bConfigurationValue = 0; /* default */
534
535 /*
536 * Ditch all pending URBs.
537 */
538 PVUSBURB pCurUrb;
539 while ((pCurUrb = usbHidQueueRemoveHead(&pThis->ToHostQueue)) != NULL)
540 {
541 pCurUrb->enmStatus = VUSBSTATUS_CRC;
542 usbHidLinkDone(pThis, pCurUrb);
543 }
544
545 if (pUrb)
546 return usbHidCompleteOk(pThis, pUrb, 0);
547 return VINF_SUCCESS;
548}
549
550#ifdef DEBUG
551# define HEX_DIGIT(x) (((x) < 0xa) ? ((x) + '0') : ((x) - 0xa + 'a'))
552static void usbHidComputePressed(PUSBHIDK_REPORT pReport, char* pszBuf, unsigned cbBuf)
553{
554 unsigned offBuf = 0;
555 unsigned i;
556 for (i = 0; i < RT_ELEMENTS(pReport->aKeys); ++i)
557 {
558 uint8_t uCode = pReport->aKeys[i];
559 if (uCode != 0)
560 {
561 if (offBuf + 4 >= cbBuf)
562 break;
563 pszBuf[offBuf++] = HEX_DIGIT(uCode >> 4);
564 pszBuf[offBuf++] = HEX_DIGIT(uCode & 0xf);
565 pszBuf[offBuf++] = ' ';
566 }
567 }
568 pszBuf[offBuf++] = '\0';
569}
570# undef HEX_DIGIT
571#endif
572
573/**
574 * Returns true if the usage code corresponds to a keyboard modifier key
575 * (left or right ctrl, shift, alt or GUI). The usage codes for these keys
576 * are the range 0xe0 to 0xe7.
577 */
578static bool usbHidUsageCodeIsModifier(uint8_t u8Usage)
579{
580 return u8Usage >= USBHID_MODIFIER_FIRST && u8Usage <= USBHID_MODIFIER_LAST;
581}
582
583/**
584 * Convert a USB HID usage code to a keyboard modifier flag. The arithmetic
585 * is simple: the modifier keys have usage codes from 0xe0 to 0xe7, and the
586 * lower nibble is the bit number of the flag.
587 */
588static uint8_t usbHidModifierToFlag(uint8_t u8Usage)
589{
590 Assert(usbHidUsageCodeIsModifier(u8Usage));
591 return RT_BIT(u8Usage & 0xf);
592}
593
594/**
595 * Create a USB HID keyboard report based on a vector of keys which have been
596 * pressed since the last report was created (so that we don't miss keys that
597 * are only pressed briefly) and a vector of currently depressed keys.
598 * The keys in the report aKeys array are in increasing order (important for
599 * the test case).
600 */
601static int usbHidFillReport(PUSBHIDK_REPORT pReport,
602 uint8_t *pabUnreportedKeys,
603 uint8_t *pabDepressedKeys)
604{
605 int rc = false;
606 unsigned iBuf = 0;
607 RT_ZERO(*pReport);
608 for (unsigned iKey = 0; iKey < VBOX_USB_USAGE_ARRAY_SIZE; ++iKey)
609 {
610 AssertReturn(iBuf <= RT_ELEMENTS(pReport->aKeys),
611 VERR_INTERNAL_ERROR);
612 if (pabUnreportedKeys[iKey] || pabDepressedKeys[iKey])
613 {
614 if (usbHidUsageCodeIsModifier(iKey))
615 pReport->ShiftState |= usbHidModifierToFlag(iKey);
616 else if (iBuf == RT_ELEMENTS(pReport->aKeys))
617 {
618 /* The USB HID spec says that the entire vector should be
619 * set to ErrorRollOver on overflow. We don't mind if this
620 * path is taken several times for one report. */
621 for (unsigned iBuf2 = 0;
622 iBuf2 < RT_ELEMENTS(pReport->aKeys); ++iBuf2)
623 pReport->aKeys[iBuf2] = USBHID_USAGE_ROLL_OVER;
624 }
625 else
626 {
627 pReport->aKeys[iBuf] = iKey;
628 ++iBuf;
629 /* More Korean keyboard hackery: Give the caller a hint that
630 * a key release event needs reporting.
631 */
632 if (iKey == 0x90 || iKey == 0x91)
633 rc = true;
634 }
635 /* Avoid "hanging" keys: If a key is unreported but no longer
636 * depressed, we'll need to report the key-up state, too.
637 */
638 if (pabUnreportedKeys[iKey] && !pabDepressedKeys[iKey])
639 rc = true;
640
641 pabUnreportedKeys[iKey] = 0;
642 }
643 }
644 return rc;
645}
646
647#ifdef DEBUG
648/** Test data for testing usbHidFillReport(). The format is:
649 * - Unreported keys (zero terminated array)
650 * - Depressed keys (zero terminated array)
651 * - Expected shift state in the report (single byte inside array)
652 * - Expected keys buffer contents (array of six bytes)
653 */
654static const uint8_t testUsbHidFillReportData[][4][10] = {
655 /* Just unreported, no modifiers */
656 {{4, 9, 0}, {0}, {0}, {4, 9, 0, 0, 0, 0}},
657 /* Just unreported, one modifier */
658 {{4, 9, 0xe2, 0}, {0}, {4}, {4, 9, 0, 0, 0, 0}},
659 /* Just unreported, two modifiers */
660 {{4, 9, 0xe2, 0xe4, 0}, {0}, {20}, {4, 9, 0, 0, 0, 0}},
661 /* Just depressed, no modifiers */
662 {{0}, {7, 20, 0}, {0}, {7, 20, 0, 0, 0, 0}},
663 /* Just depressed, one modifier */
664 {{0}, {7, 20, 0xe3, 0}, {8}, {7, 20, 0, 0, 0, 0}},
665 /* Just depressed, two modifiers */
666 {{0}, {7, 20, 0xe3, 0xe6, 0}, {72}, {7, 20, 0, 0, 0, 0}},
667 /* Unreported and depressed, no overlap, no modifiers */
668 {{5, 10, 0}, {8, 21, 0}, {0}, {5, 8, 10, 21, 0, 0}},
669 /* Unreported and depressed, one overlap, no modifiers */
670 {{5, 10, 0}, {8, 10, 21, 0}, {0}, {5, 8, 10, 21, 0, 0}},
671 /* Unreported and depressed, no overlap, non-overlapping modifiers */
672 {{5, 10, 0xe2, 0xe4, 0}, {8, 21, 0xe3, 0xe6, 0}, {92},
673 {5, 8, 10, 21, 0, 0}},
674 /* Unreported and depressed, one overlap, non-overlapping modifiers */
675 {{5, 10, 21, 0xe2, 0xe4, 0}, {8, 21, 0xe3, 0xe6, 0}, {92},
676 {5, 8, 10, 21, 0, 0}},
677 /* Unreported and depressed, no overlap, overlapping modifiers */
678 {{5, 10, 0xe2, 0xe4, 0}, {8, 21, 0xe3, 0xe4, 0}, {28},
679 {5, 8, 10, 21, 0, 0}},
680 /* Unreported and depressed, one overlap, overlapping modifiers */
681 {{5, 10, 0xe2, 0xe4, 0}, {5, 8, 21, 0xe3, 0xe4, 0}, {28},
682 {5, 8, 10, 21, 0, 0}},
683 /* Just too many unreported, no modifiers */
684 {{4, 9, 11, 12, 16, 18, 20, 0}, {0}, {0}, {1, 1, 1, 1, 1, 1}},
685 /* Just too many unreported, two modifiers */
686 {{4, 9, 11, 12, 16, 18, 20, 0xe2, 0xe4, 0}, {0}, {20},
687 {1, 1, 1, 1, 1, 1}},
688 /* Just too many depressed, no modifiers */
689 {{0}, {7, 20, 22, 25, 27, 29, 34, 0}, {0}, {1, 1, 1, 1, 1, 1}},
690 /* Just too many depressed, two modifiers */
691 {{0}, {7, 20, 22, 25, 27, 29, 34, 0xe3, 0xe5, 0}, {40},
692 {1, 1, 1, 1, 1, 1}},
693 /* Too many unreported and depressed, no overlap, no modifiers */
694 {{5, 10, 12, 13, 0}, {8, 9, 21, 0}, {0}, {1, 1, 1, 1, 1, 1}},
695 /* Eight unreported and depressed total, one overlap, no modifiers */
696 {{5, 10, 12, 13, 0}, {8, 10, 21, 22, 0}, {0}, {1, 1, 1, 1, 1, 1}},
697 /* Seven unreported and depressed total, one overlap, no modifiers */
698 {{5, 10, 12, 13, 0}, {8, 10, 21, 0}, {0}, {5, 8, 10, 12, 13, 21}},
699 /* Too many unreported and depressed, no overlap, two modifiers */
700 {{5, 10, 12, 13, 0xe2, 0}, {8, 9, 21, 0xe4, 0}, {20},
701 {1, 1, 1, 1, 1, 1}},
702 /* Eight unreported and depressed total, one overlap, two modifiers */
703 {{5, 10, 12, 13, 0xe1, 0}, {8, 10, 21, 22, 0xe2, 0}, {6},
704 {1, 1, 1, 1, 1, 1}},
705 /* Seven unreported and depressed total, one overlap, two modifiers */
706 {{5, 10, 12, 13, 0xe2, 0}, {8, 10, 21, 0xe3, 0}, {12},
707 {5, 8, 10, 12, 13, 21}}
708};
709
710/** Test case for usbHidFillReport() */
711class testUsbHidFillReport
712{
713 USBHIDK_REPORT mReport;
714 uint8_t mabUnreportedKeys[VBOX_USB_USAGE_ARRAY_SIZE];
715 uint8_t mabDepressedKeys[VBOX_USB_USAGE_ARRAY_SIZE];
716 const uint8_t (*mTests)[4][10];
717
718 void doTest(unsigned cTest, const uint8_t *paiUnreportedKeys,
719 const uint8_t *paiDepressedKeys, uint8_t aExpShiftState,
720 const uint8_t *pabExpKeys)
721 {
722 RT_ZERO(mReport);
723 RT_ZERO(mabUnreportedKeys);
724 RT_ZERO(mabDepressedKeys);
725 for (unsigned i = 0; paiUnreportedKeys[i] != 0; ++i)
726 mabUnreportedKeys[paiUnreportedKeys[i]] = 1;
727 for (unsigned i = 0; paiDepressedKeys[i] != 0; ++i)
728 mabUnreportedKeys[paiDepressedKeys[i]] = 1;
729 int rc = usbHidFillReport(&mReport, mabUnreportedKeys, mabDepressedKeys);
730 AssertMsgRC(rc, ("test %u\n", cTest));
731 AssertMsg(mReport.ShiftState == aExpShiftState, ("test %u\n", cTest));
732 for (unsigned i = 0; i < RT_ELEMENTS(mReport.aKeys); ++i)
733 AssertMsg(mReport.aKeys[i] == pabExpKeys[i], ("test %u\n", cTest));
734 }
735
736public:
737 testUsbHidFillReport(void) : mTests(&testUsbHidFillReportData[0])
738 {
739 for (unsigned i = 0; i < RT_ELEMENTS(testUsbHidFillReportData); ++i)
740 doTest(i, mTests[i][0], mTests[i][1], mTests[i][2][0],
741 mTests[i][3]);
742 }
743};
744
745static testUsbHidFillReport gsTestUsbHidFillReport;
746#endif
747
748/**
749 * Handles a SET_REPORT request sent to the default control pipe. Note
750 * that unrecognized requests are ignored without reporting an error.
751 */
752static void usbHidSetReport(PUSBHID pThis, PVUSBURB pUrb)
753{
754 PVUSBSETUP pSetup = (PVUSBSETUP)&pUrb->abData[0];
755 Assert(pSetup->bRequest == HID_REQ_SET_REPORT);
756
757 /* The LED report is the 3rd report, ID 0 (-> wValue 0x200). */
758 if (pSetup->wIndex == 0 && pSetup->wLength == 1 && pSetup->wValue == 0x200)
759 {
760 PDMKEYBLEDS enmLeds = PDMKEYBLEDS_NONE;
761 uint8_t u8LEDs = pUrb->abData[sizeof(*pSetup)];
762 LogFlowFunc(("Setting keybooard LEDs to u8LEDs=%02X\n", u8LEDs));
763
764 /* Translate LED state to PDM format and send upstream. */
765 if (u8LEDs & 0x01)
766 enmLeds = (PDMKEYBLEDS)(enmLeds | PDMKEYBLEDS_NUMLOCK);
767 if (u8LEDs & 0x02)
768 enmLeds = (PDMKEYBLEDS)(enmLeds | PDMKEYBLEDS_CAPSLOCK);
769 if (u8LEDs & 0x04)
770 enmLeds = (PDMKEYBLEDS)(enmLeds | PDMKEYBLEDS_SCROLLLOCK);
771
772 pThis->Lun0.pDrv->pfnLedStatusChange(pThis->Lun0.pDrv, enmLeds);
773 }
774}
775
776/**
777 * Sends a state report to the host if there is a pending URB.
778 */
779static int usbHidSendReport(PUSBHID pThis)
780{
781 PVUSBURB pUrb = usbHidQueueRemoveHead(&pThis->ToHostQueue);
782 if (pUrb)
783 {
784 PUSBHIDK_REPORT pReport = (PUSBHIDK_REPORT)&pUrb->abData[0];
785
786 int again = usbHidFillReport(pReport, pThis->abUnreportedKeys,
787 pThis->abDepressedKeys);
788 if (again)
789 pThis->fHasPendingChanges = true;
790 else
791 pThis->fHasPendingChanges = false;
792 return usbHidCompleteOk(pThis, pUrb, sizeof(*pReport));
793 }
794 else
795 {
796 Log2(("No available URB for USB kbd\n"));
797 pThis->fHasPendingChanges = true;
798 }
799 return VINF_EOF;
800}
801
802/**
803 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
804 */
805static DECLCALLBACK(void *) usbHidKeyboardQueryInterface(PPDMIBASE pInterface, const char *pszIID)
806{
807 PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IBase);
808 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->Lun0.IBase);
809 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIKEYBOARDPORT, &pThis->Lun0.IPort);
810 return NULL;
811}
812
813/* See the PS2K device. */
814#define KRSP_BAT_FAIL 0xFC /* Also a 'release keys' signal. */
815
816/**
817 * Keyboard event handler.
818 *
819 * @returns VBox status code.
820 * @param pInterface Pointer to the keyboard port interface (KBDState::Keyboard.IPort).
821 * @param u32UsageCode The key usage ID.
822 */
823static DECLCALLBACK(int) usbHidKeyboardPutEvent(PPDMIKEYBOARDPORT pInterface, uint32_t u32UsageCode)
824{
825 PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort);
826 uint8_t u8HidCode;
827 int fKeyDown;
828 bool fHaveEvent = true;
829
830 RTCritSectEnter(&pThis->CritSect);
831
832 if (RT_UNLIKELY(u32UsageCode == KRSP_BAT_FAIL))
833 {
834 /* Clear all currently depressed and unreported keys. */
835 RT_ZERO(pThis->abDepressedKeys);
836 RT_ZERO(pThis->abUnreportedKeys);
837 usbHidSendReport(pThis);
838 }
839 else
840 {
841 fKeyDown = !(u32UsageCode & 0x80000000);
842 u8HidCode = u32UsageCode & 0xFF;
843 AssertReturn(u8HidCode <= VBOX_USB_MAX_USAGE_CODE, VERR_INTERNAL_ERROR);
844
845 LogFlowFunc(("key %s: 0x%x\n", fKeyDown ? "down" : "up", u8HidCode));
846
847 if (fKeyDown)
848 {
849 /* Due to host key repeat, we can get key events for keys which are
850 * already depressed. */
851 if (!pThis->abDepressedKeys[u8HidCode])
852 {
853 pThis->abUnreportedKeys[u8HidCode] = 1;
854
855 /* If a non-modifier key is being marked as unreported, also set
856 * all currently depressed modifer keys as unreported. This avoids
857 * problems where a simulated key sequence is sent too fast and
858 * by the time the key is reported, some previously reported
859 * modifiers are already released. This helps ensure that the guest
860 * sees the entire modifier(s)+key sequence in a single report.
861 */
862 if (!usbHidUsageCodeIsModifier(u8HidCode))
863 {
864 int iModKey;
865
866 for (iModKey = USBHID_MODIFIER_FIRST; iModKey <= USBHID_MODIFIER_LAST; ++iModKey)
867 if (pThis->abDepressedKeys[iModKey])
868 pThis->abUnreportedKeys[iModKey] = 1;
869 }
870 }
871 else
872 fHaveEvent = false;
873 pThis->abDepressedKeys[u8HidCode] = 1;
874 }
875 else
876 {
877 /* For stupid Korean keyboards, we have to fake a key up/down sequence
878 * because they only send break codes for Hangul/Hanja keys.
879 */
880 if (u8HidCode == 0x90 || u8HidCode == 0x91)
881 pThis->abUnreportedKeys[u8HidCode] = 1;
882 pThis->abDepressedKeys[u8HidCode] = 0;
883 }
884
885
886 /* Send a report if the host is already waiting for it. */
887 if (fHaveEvent)
888 usbHidSendReport(pThis);
889 }
890
891 RTCritSectLeave(&pThis->CritSect);
892
893 return VINF_SUCCESS;
894}
895
896/**
897 * @copydoc PDMUSBREG::pfnUrbReap
898 */
899static DECLCALLBACK(PVUSBURB) usbHidUrbReap(PPDMUSBINS pUsbIns, RTMSINTERVAL cMillies)
900{
901 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
902 //LogFlow(("usbHidUrbReap/#%u: cMillies=%u\n", pUsbIns->iInstance, cMillies));
903
904 RTCritSectEnter(&pThis->CritSect);
905
906 PVUSBURB pUrb = usbHidQueueRemoveHead(&pThis->DoneQueue);
907 if (!pUrb && cMillies)
908 {
909 /* Wait */
910 pThis->fHaveDoneQueueWaiter = true;
911 RTCritSectLeave(&pThis->CritSect);
912
913 RTSemEventWait(pThis->hEvtDoneQueue, cMillies);
914
915 RTCritSectEnter(&pThis->CritSect);
916 pThis->fHaveDoneQueueWaiter = false;
917
918 pUrb = usbHidQueueRemoveHead(&pThis->DoneQueue);
919 }
920
921 RTCritSectLeave(&pThis->CritSect);
922
923 if (pUrb)
924 Log(("usbHidUrbReap/#%u: pUrb=%p:%s\n", pUsbIns->iInstance, pUrb, pUrb->pszDesc));
925 return pUrb;
926}
927
928
929/**
930 * @copydoc PDMUSBREG::pfnWakeup
931 */
932static DECLCALLBACK(int) usbHidWakeup(PPDMUSBINS pUsbIns)
933{
934 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
935
936 return RTSemEventSignal(pThis->hEvtDoneQueue);
937}
938
939
940/**
941 * @copydoc PDMUSBREG::pfnUrbCancel
942 */
943static DECLCALLBACK(int) usbHidUrbCancel(PPDMUSBINS pUsbIns, PVUSBURB pUrb)
944{
945 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
946 LogFlow(("usbHidUrbCancel/#%u: pUrb=%p:%s\n", pUsbIns->iInstance, pUrb, pUrb->pszDesc));
947 RTCritSectEnter(&pThis->CritSect);
948
949 /*
950 * Remove the URB from the to-host queue and move it onto the done queue.
951 */
952 if (usbHidQueueRemove(&pThis->ToHostQueue, pUrb))
953 usbHidLinkDone(pThis, pUrb);
954
955 RTCritSectLeave(&pThis->CritSect);
956 return VINF_SUCCESS;
957}
958
959
960/**
961 * Handles request sent to the inbound (device to host) interrupt pipe. This is
962 * rather different from bulk requests because an interrupt read URB may complete
963 * after arbitrarily long time.
964 */
965static int usbHidHandleIntrDevToHost(PUSBHID pThis, PUSBHIDEP pEp, PVUSBURB pUrb)
966{
967 /*
968 * Stall the request if the pipe is halted.
969 */
970 if (RT_UNLIKELY(pEp->fHalted))
971 return usbHidCompleteStall(pThis, NULL, pUrb, "Halted pipe");
972
973 /*
974 * Deal with the URB according to the state.
975 */
976 switch (pThis->enmState)
977 {
978 /*
979 * We've data left to transfer to the host.
980 */
981 case USBHIDREQSTATE_DATA_TO_HOST:
982 {
983 AssertFailed();
984 Log(("usbHidHandleIntrDevToHost: Entering STATUS\n"));
985 return usbHidCompleteOk(pThis, pUrb, 0);
986 }
987
988 /*
989 * Status transfer.
990 */
991 case USBHIDREQSTATE_STATUS:
992 {
993 AssertFailed();
994 Log(("usbHidHandleIntrDevToHost: Entering READY\n"));
995 pThis->enmState = USBHIDREQSTATE_READY;
996 return usbHidCompleteOk(pThis, pUrb, 0);
997 }
998
999 case USBHIDREQSTATE_READY:
1000 usbHidQueueAddTail(&pThis->ToHostQueue, pUrb);
1001 /* If device was not set idle, send the current report right away. */
1002 if (pThis->bIdle != 0 || pThis->fHasPendingChanges)
1003 usbHidSendReport(pThis);
1004 LogFlow(("usbHidHandleIntrDevToHost: Sent report via %p:%s\n", pUrb, pUrb->pszDesc));
1005 return VINF_SUCCESS;
1006
1007 /*
1008 * Bad states, stall.
1009 */
1010 default:
1011 Log(("usbHidHandleIntrDevToHost: enmState=%d cbData=%#x\n", pThis->enmState, pUrb->cbData));
1012 return usbHidCompleteStall(pThis, NULL, pUrb, "Really bad state (D2H)!");
1013 }
1014}
1015
1016
1017/**
1018 * Handles request sent to the default control pipe.
1019 */
1020static int usbHidHandleDefaultPipe(PUSBHID pThis, PUSBHIDEP pEp, PVUSBURB pUrb)
1021{
1022 PVUSBSETUP pSetup = (PVUSBSETUP)&pUrb->abData[0];
1023 LogFlow(("usbHidHandleDefaultPipe: cbData=%d\n", pUrb->cbData));
1024
1025 AssertReturn(pUrb->cbData >= sizeof(*pSetup), VERR_VUSB_FAILED_TO_QUEUE_URB);
1026
1027 if ((pSetup->bmRequestType & VUSB_REQ_MASK) == VUSB_REQ_STANDARD)
1028 {
1029 switch (pSetup->bRequest)
1030 {
1031 case VUSB_REQ_GET_DESCRIPTOR:
1032 {
1033 switch (pSetup->bmRequestType)
1034 {
1035 case VUSB_TO_DEVICE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
1036 {
1037 switch (pSetup->wValue >> 8)
1038 {
1039 case VUSB_DT_STRING:
1040 Log(("usbHid: GET_DESCRIPTOR DT_STRING wValue=%#x wIndex=%#x\n", pSetup->wValue, pSetup->wIndex));
1041 break;
1042 default:
1043 Log(("usbHid: GET_DESCRIPTOR, huh? wValue=%#x wIndex=%#x\n", pSetup->wValue, pSetup->wIndex));
1044 break;
1045 }
1046 break;
1047 }
1048
1049 case VUSB_TO_INTERFACE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
1050 {
1051 switch (pSetup->wValue >> 8)
1052 {
1053 case DT_IF_HID_DESCRIPTOR:
1054 {
1055 uint32_t cbCopy;
1056
1057 /* Returned data is written after the setup message. */
1058 cbCopy = pUrb->cbData - sizeof(*pSetup);
1059 cbCopy = RT_MIN(cbCopy, sizeof(g_UsbHidIfHidDesc));
1060 Log(("usbHidKbd: GET_DESCRIPTOR DT_IF_HID_DESCRIPTOR wValue=%#x wIndex=%#x cbCopy=%#x\n", pSetup->wValue, pSetup->wIndex, cbCopy));
1061 memcpy(&pUrb->abData[sizeof(*pSetup)], &g_UsbHidIfHidDesc, cbCopy);
1062 return usbHidCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
1063 }
1064
1065 case DT_IF_HID_REPORT:
1066 {
1067 uint32_t cbCopy;
1068
1069 /* Returned data is written after the setup message. */
1070 cbCopy = pUrb->cbData - sizeof(*pSetup);
1071 cbCopy = RT_MIN(cbCopy, sizeof(g_UsbHidReportDesc));
1072 Log(("usbHid: GET_DESCRIPTOR DT_IF_HID_REPORT wValue=%#x wIndex=%#x cbCopy=%#x\n", pSetup->wValue, pSetup->wIndex, cbCopy));
1073 memcpy(&pUrb->abData[sizeof(*pSetup)], &g_UsbHidReportDesc, cbCopy);
1074 return usbHidCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
1075 }
1076
1077 default:
1078 Log(("usbHid: GET_DESCRIPTOR, huh? wValue=%#x wIndex=%#x\n", pSetup->wValue, pSetup->wIndex));
1079 break;
1080 }
1081 break;
1082 }
1083
1084 default:
1085 Log(("usbHid: Bad GET_DESCRIPTOR req: bmRequestType=%#x\n", pSetup->bmRequestType));
1086 return usbHidCompleteStall(pThis, pEp, pUrb, "Bad GET_DESCRIPTOR");
1087 }
1088 break;
1089 }
1090
1091 case VUSB_REQ_GET_STATUS:
1092 {
1093 uint16_t wRet = 0;
1094
1095 if (pSetup->wLength != 2)
1096 {
1097 Log(("usbHid: Bad GET_STATUS req: wLength=%#x\n", pSetup->wLength));
1098 break;
1099 }
1100 Assert(pSetup->wValue == 0);
1101 switch (pSetup->bmRequestType)
1102 {
1103 case VUSB_TO_DEVICE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
1104 {
1105 Assert(pSetup->wIndex == 0);
1106 Log(("usbHid: GET_STATUS (device)\n"));
1107 wRet = 0; /* Not self-powered, no remote wakeup. */
1108 memcpy(&pUrb->abData[sizeof(*pSetup)], &wRet, sizeof(wRet));
1109 return usbHidCompleteOk(pThis, pUrb, sizeof(wRet) + sizeof(*pSetup));
1110 }
1111
1112 case VUSB_TO_INTERFACE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
1113 {
1114 if (pSetup->wIndex == 0)
1115 {
1116 memcpy(&pUrb->abData[sizeof(*pSetup)], &wRet, sizeof(wRet));
1117 return usbHidCompleteOk(pThis, pUrb, sizeof(wRet) + sizeof(*pSetup));
1118 }
1119 else
1120 {
1121 Log(("usbHid: GET_STATUS (interface) invalid, wIndex=%#x\n", pSetup->wIndex));
1122 }
1123 break;
1124 }
1125
1126 case VUSB_TO_ENDPOINT | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
1127 {
1128 if (pSetup->wIndex < RT_ELEMENTS(pThis->aEps))
1129 {
1130 wRet = pThis->aEps[pSetup->wIndex].fHalted ? 1 : 0;
1131 memcpy(&pUrb->abData[sizeof(*pSetup)], &wRet, sizeof(wRet));
1132 return usbHidCompleteOk(pThis, pUrb, sizeof(wRet) + sizeof(*pSetup));
1133 }
1134 else
1135 {
1136 Log(("usbHid: GET_STATUS (endpoint) invalid, wIndex=%#x\n", pSetup->wIndex));
1137 }
1138 break;
1139 }
1140
1141 default:
1142 Log(("usbHid: Bad GET_STATUS req: bmRequestType=%#x\n", pSetup->bmRequestType));
1143 return usbHidCompleteStall(pThis, pEp, pUrb, "Bad GET_STATUS");
1144 }
1145 break;
1146 }
1147
1148 case VUSB_REQ_CLEAR_FEATURE:
1149 break;
1150 }
1151
1152 /** @todo implement this. */
1153 Log(("usbHid: Implement standard request: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n",
1154 pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue, pSetup->wIndex, pSetup->wLength));
1155
1156 usbHidCompleteStall(pThis, pEp, pUrb, "TODO: standard request stuff");
1157 }
1158 else if ((pSetup->bmRequestType & VUSB_REQ_MASK) == VUSB_REQ_CLASS)
1159 {
1160 switch (pSetup->bRequest)
1161 {
1162 case HID_REQ_SET_IDLE:
1163 {
1164 switch (pSetup->bmRequestType)
1165 {
1166 case VUSB_TO_INTERFACE | VUSB_REQ_CLASS | VUSB_DIR_TO_DEVICE:
1167 {
1168 Log(("usbHid: SET_IDLE wValue=%#x wIndex=%#x\n", pSetup->wValue, pSetup->wIndex));
1169 pThis->bIdle = pSetup->wValue >> 8;
1170 /* Consider 24ms to mean zero for keyboards (see IOUSBHIDDriver) */
1171 if (pThis->bIdle == 6) pThis->bIdle = 0;
1172 return usbHidCompleteOk(pThis, pUrb, 0);
1173 }
1174 break;
1175 }
1176 break;
1177 }
1178 case HID_REQ_GET_IDLE:
1179 {
1180 switch (pSetup->bmRequestType)
1181 {
1182 case VUSB_TO_INTERFACE | VUSB_REQ_CLASS | VUSB_DIR_TO_HOST:
1183 {
1184 Log(("usbHid: GET_IDLE wValue=%#x wIndex=%#x, returning %#x\n", pSetup->wValue, pSetup->wIndex, pThis->bIdle));
1185 pUrb->abData[sizeof(*pSetup)] = pThis->bIdle;
1186 return usbHidCompleteOk(pThis, pUrb, 1);
1187 }
1188 break;
1189 }
1190 break;
1191 }
1192 case HID_REQ_SET_REPORT:
1193 {
1194 switch (pSetup->bmRequestType)
1195 {
1196 case VUSB_TO_INTERFACE | VUSB_REQ_CLASS | VUSB_DIR_TO_DEVICE:
1197 {
1198 Log(("usbHid: SET_REPORT wValue=%#x wIndex=%#x wLength=%#x\n", pSetup->wValue, pSetup->wIndex, pSetup->wLength));
1199 usbHidSetReport(pThis, pUrb);
1200 return usbHidCompleteOk(pThis, pUrb, 0);
1201 }
1202 break;
1203 }
1204 break;
1205 }
1206 }
1207 Log(("usbHid: Unimplemented class request: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n",
1208 pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue, pSetup->wIndex, pSetup->wLength));
1209
1210 usbHidCompleteStall(pThis, pEp, pUrb, "TODO: class request stuff");
1211 }
1212 else
1213 {
1214 Log(("usbHid: Unknown control msg: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n",
1215 pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue, pSetup->wIndex, pSetup->wLength));
1216 return usbHidCompleteStall(pThis, pEp, pUrb, "Unknown control msg");
1217 }
1218
1219 return VINF_SUCCESS;
1220}
1221
1222
1223/**
1224 * @copydoc PDMUSBREG::pfnUrbQueue
1225 */
1226static DECLCALLBACK(int) usbHidQueue(PPDMUSBINS pUsbIns, PVUSBURB pUrb)
1227{
1228 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
1229 LogFlow(("usbHidQueue/#%u: pUrb=%p:%s EndPt=%#x\n", pUsbIns->iInstance, pUrb, pUrb->pszDesc, pUrb->EndPt));
1230 RTCritSectEnter(&pThis->CritSect);
1231
1232 /*
1233 * Parse on a per end-point basis.
1234 */
1235 int rc;
1236 switch (pUrb->EndPt)
1237 {
1238 case 0:
1239 rc = usbHidHandleDefaultPipe(pThis, &pThis->aEps[0], pUrb);
1240 break;
1241
1242 case 0x81:
1243 AssertFailed();
1244 case 0x01:
1245 rc = usbHidHandleIntrDevToHost(pThis, &pThis->aEps[1], pUrb);
1246 break;
1247
1248 default:
1249 AssertMsgFailed(("EndPt=%d\n", pUrb->EndPt));
1250 rc = VERR_VUSB_FAILED_TO_QUEUE_URB;
1251 break;
1252 }
1253
1254 RTCritSectLeave(&pThis->CritSect);
1255 return rc;
1256}
1257
1258
1259/**
1260 * @copydoc PDMUSBREG::pfnUsbClearHaltedEndpoint
1261 */
1262static DECLCALLBACK(int) usbHidUsbClearHaltedEndpoint(PPDMUSBINS pUsbIns, unsigned uEndpoint)
1263{
1264 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
1265 LogFlow(("usbHidUsbClearHaltedEndpoint/#%u: uEndpoint=%#x\n", pUsbIns->iInstance, uEndpoint));
1266
1267 if ((uEndpoint & ~0x80) < RT_ELEMENTS(pThis->aEps))
1268 {
1269 RTCritSectEnter(&pThis->CritSect);
1270 pThis->aEps[(uEndpoint & ~0x80)].fHalted = false;
1271 RTCritSectLeave(&pThis->CritSect);
1272 }
1273
1274 return VINF_SUCCESS;
1275}
1276
1277
1278/**
1279 * @copydoc PDMUSBREG::pfnUsbSetInterface
1280 */
1281static DECLCALLBACK(int) usbHidUsbSetInterface(PPDMUSBINS pUsbIns, uint8_t bInterfaceNumber, uint8_t bAlternateSetting)
1282{
1283 LogFlow(("usbHidUsbSetInterface/#%u: bInterfaceNumber=%u bAlternateSetting=%u\n", pUsbIns->iInstance, bInterfaceNumber, bAlternateSetting));
1284 Assert(bAlternateSetting == 0);
1285 return VINF_SUCCESS;
1286}
1287
1288
1289/**
1290 * @copydoc PDMUSBREG::pfnUsbSetConfiguration
1291 */
1292static DECLCALLBACK(int) usbHidUsbSetConfiguration(PPDMUSBINS pUsbIns, uint8_t bConfigurationValue,
1293 const void *pvOldCfgDesc, const void *pvOldIfState, const void *pvNewCfgDesc)
1294{
1295 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
1296 LogFlow(("usbHidUsbSetConfiguration/#%u: bConfigurationValue=%u\n", pUsbIns->iInstance, bConfigurationValue));
1297 Assert(bConfigurationValue == 1);
1298 RTCritSectEnter(&pThis->CritSect);
1299
1300 /*
1301 * If the same config is applied more than once, it's a kind of reset.
1302 */
1303 if (pThis->bConfigurationValue == bConfigurationValue)
1304 usbHidResetWorker(pThis, NULL, true /*fSetConfig*/); /** @todo figure out the exact difference */
1305 pThis->bConfigurationValue = bConfigurationValue;
1306
1307 /*
1308 * Tell the other end that the keyboard is now enabled and wants
1309 * to receive keystrokes.
1310 */
1311 pThis->Lun0.pDrv->pfnSetActive(pThis->Lun0.pDrv, true);
1312
1313 RTCritSectLeave(&pThis->CritSect);
1314 return VINF_SUCCESS;
1315}
1316
1317
1318/**
1319 * @copydoc PDMUSBREG::pfnUsbGetDescriptorCache
1320 */
1321static DECLCALLBACK(PCPDMUSBDESCCACHE) usbHidUsbGetDescriptorCache(PPDMUSBINS pUsbIns)
1322{
1323 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
1324 LogFlow(("usbHidUsbGetDescriptorCache/#%u:\n", pUsbIns->iInstance));
1325 return &g_UsbHidDescCache;
1326}
1327
1328
1329/**
1330 * @copydoc PDMUSBREG::pfnUsbReset
1331 */
1332static DECLCALLBACK(int) usbHidUsbReset(PPDMUSBINS pUsbIns, bool fResetOnLinux)
1333{
1334 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
1335 LogFlow(("usbHidUsbReset/#%u:\n", pUsbIns->iInstance));
1336 RTCritSectEnter(&pThis->CritSect);
1337
1338 int rc = usbHidResetWorker(pThis, NULL, false /*fSetConfig*/);
1339
1340 RTCritSectLeave(&pThis->CritSect);
1341 return rc;
1342}
1343
1344
1345/**
1346 * @copydoc PDMUSBREG::pfnDestruct
1347 */
1348static void usbHidDestruct(PPDMUSBINS pUsbIns)
1349{
1350 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
1351 LogFlow(("usbHidDestruct/#%u:\n", pUsbIns->iInstance));
1352
1353 if (RTCritSectIsInitialized(&pThis->CritSect))
1354 {
1355 /* Let whoever runs in this critical section complete. */
1356 RTCritSectEnter(&pThis->CritSect);
1357 RTCritSectLeave(&pThis->CritSect);
1358 RTCritSectDelete(&pThis->CritSect);
1359 }
1360
1361 if (pThis->hEvtDoneQueue != NIL_RTSEMEVENT)
1362 {
1363 RTSemEventDestroy(pThis->hEvtDoneQueue);
1364 pThis->hEvtDoneQueue = NIL_RTSEMEVENT;
1365 }
1366}
1367
1368
1369/**
1370 * @copydoc PDMUSBREG::pfnConstruct
1371 */
1372static DECLCALLBACK(int) usbHidConstruct(PPDMUSBINS pUsbIns, int iInstance, PCFGMNODE pCfg, PCFGMNODE pCfgGlobal)
1373{
1374 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
1375 Log(("usbHidConstruct/#%u:\n", iInstance));
1376
1377 /*
1378 * Perform the basic structure initialization first so the destructor
1379 * will not misbehave.
1380 */
1381 pThis->pUsbIns = pUsbIns;
1382 pThis->hEvtDoneQueue = NIL_RTSEMEVENT;
1383 usbHidQueueInit(&pThis->ToHostQueue);
1384 usbHidQueueInit(&pThis->DoneQueue);
1385
1386 int rc = RTCritSectInit(&pThis->CritSect);
1387 AssertRCReturn(rc, rc);
1388
1389 rc = RTSemEventCreate(&pThis->hEvtDoneQueue);
1390 AssertRCReturn(rc, rc);
1391
1392 /*
1393 * Validate and read the configuration.
1394 */
1395 rc = CFGMR3ValidateConfig(pCfg, "/", "", "", "UsbHid", iInstance);
1396 if (RT_FAILURE(rc))
1397 return rc;
1398
1399 pThis->Lun0.IBase.pfnQueryInterface = usbHidKeyboardQueryInterface;
1400 pThis->Lun0.IPort.pfnPutEventHid = usbHidKeyboardPutEvent;
1401
1402 /*
1403 * Attach the keyboard driver.
1404 */
1405 rc = PDMUsbHlpDriverAttach(pUsbIns, 0 /*iLun*/, &pThis->Lun0.IBase, &pThis->Lun0.pDrvBase, "Keyboard Port");
1406 if (RT_FAILURE(rc))
1407 return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("HID failed to attach keyboard driver"));
1408
1409 pThis->Lun0.pDrv = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pDrvBase, PDMIKEYBOARDCONNECTOR);
1410 if (!pThis->Lun0.pDrv)
1411 return PDMUsbHlpVMSetError(pUsbIns, VERR_PDM_MISSING_INTERFACE, RT_SRC_POS, N_("HID failed to query keyboard interface"));
1412
1413 return VINF_SUCCESS;
1414}
1415
1416
1417/**
1418 * The USB Human Interface Device (HID) Keyboard registration record.
1419 */
1420const PDMUSBREG g_UsbHidKbd =
1421{
1422 /* u32Version */
1423 PDM_USBREG_VERSION,
1424 /* szName */
1425 "HidKeyboard",
1426 /* pszDescription */
1427 "USB HID Keyboard.",
1428 /* fFlags */
1429 0,
1430 /* cMaxInstances */
1431 ~0U,
1432 /* cbInstance */
1433 sizeof(USBHID),
1434 /* pfnConstruct */
1435 usbHidConstruct,
1436 /* pfnDestruct */
1437 usbHidDestruct,
1438 /* pfnVMInitComplete */
1439 NULL,
1440 /* pfnVMPowerOn */
1441 NULL,
1442 /* pfnVMReset */
1443 NULL,
1444 /* pfnVMSuspend */
1445 NULL,
1446 /* pfnVMResume */
1447 NULL,
1448 /* pfnVMPowerOff */
1449 NULL,
1450 /* pfnHotPlugged */
1451 NULL,
1452 /* pfnHotUnplugged */
1453 NULL,
1454 /* pfnDriverAttach */
1455 NULL,
1456 /* pfnDriverDetach */
1457 NULL,
1458 /* pfnQueryInterface */
1459 NULL,
1460 /* pfnUsbReset */
1461 usbHidUsbReset,
1462 /* pfnUsbGetDescriptorCache */
1463 usbHidUsbGetDescriptorCache,
1464 /* pfnUsbSetConfiguration */
1465 usbHidUsbSetConfiguration,
1466 /* pfnUsbSetInterface */
1467 usbHidUsbSetInterface,
1468 /* pfnUsbClearHaltedEndpoint */
1469 usbHidUsbClearHaltedEndpoint,
1470 /* pfnUrbNew */
1471 NULL/*usbHidUrbNew*/,
1472 /* pfnUrbQueue */
1473 usbHidQueue,
1474 /* pfnUrbCancel */
1475 usbHidUrbCancel,
1476 /* pfnUrbReap */
1477 usbHidUrbReap,
1478 /* pfnWakeup */
1479 usbHidWakeup,
1480 /* u32TheEnd */
1481 PDM_USBREG_VERSION
1482};
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette