VirtualBox

source: vbox/trunk/src/VBox/Devices/Input/UsbMouse.cpp@ 47796

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

Devices/Input: reverting r88027 as several guests did not like it.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 87.4 KB
Line 
1/** @file
2 * UsbMouse - USB Human Interface Device Emulation (Mouse).
3 */
4
5/*
6 * Copyright (C) 2007-2012 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 */
16
17/*******************************************************************************
18* Header Files *
19*******************************************************************************/
20#define LOG_GROUP LOG_GROUP_USB_MOUSE
21#include <VBox/vmm/pdmusb.h>
22#include <VBox/log.h>
23#include <VBox/err.h>
24#include <iprt/assert.h>
25#include <iprt/critsect.h>
26#include <iprt/mem.h>
27#include <iprt/semaphore.h>
28#include <iprt/string.h>
29#include <iprt/uuid.h>
30#include "VBoxDD.h"
31
32
33/*******************************************************************************
34* Defined Constants And Macros *
35*******************************************************************************/
36/** @name USB HID string IDs
37 * @{ */
38#define USBHID_STR_ID_MANUFACTURER 1
39#define USBHID_STR_ID_PRODUCT_M 2
40#define USBHID_STR_ID_PRODUCT_T 3
41#define USBHID_STR_ID_PRODUCT_MT 4
42/** @} */
43
44/** @name USB HID specific descriptor types
45 * @{ */
46#define DT_IF_HID_DESCRIPTOR 0x21
47#define DT_IF_HID_REPORT 0x22
48/** @} */
49
50/** @name USB HID vendor and product IDs
51 * @{ */
52#define VBOX_USB_VENDOR 0x80EE
53#define USBHID_PID_MOUSE 0x0020
54#define USBHID_PID_TABLET 0x0021
55#define USBHID_PID_MULTI_TOUCH 0x0022
56/** @} */
57
58/*******************************************************************************
59* Structures and Typedefs *
60*******************************************************************************/
61
62/**
63 * The USB HID request state.
64 */
65typedef enum USBHIDREQSTATE
66{
67 /** Invalid status. */
68 USBHIDREQSTATE_INVALID = 0,
69 /** Ready to receive a new read request. */
70 USBHIDREQSTATE_READY,
71 /** Have (more) data for the host. */
72 USBHIDREQSTATE_DATA_TO_HOST,
73 /** Waiting to supply status information to the host. */
74 USBHIDREQSTATE_STATUS,
75 /** The end of the valid states. */
76 USBHIDREQSTATE_END
77} USBHIDREQSTATE;
78
79/**
80 * The device reporting mode.
81 * @todo Use an interface instead of an enum and switches.
82 */
83typedef enum USBHIDMODE
84{
85 /** Relative. */
86 USBHIDMODE_RELATIVE = 0,
87 /** Absolute. */
88 USBHIDMODE_ABSOLUTE,
89 /** Multi-touch. */
90 USBHIDMODE_MULTI_TOUCH
91} USBHIDMODE;
92
93
94/**
95 * Endpoint status data.
96 */
97typedef struct USBHIDEP
98{
99 bool fHalted;
100} USBHIDEP;
101/** Pointer to the endpoint status. */
102typedef USBHIDEP *PUSBHIDEP;
103
104
105/**
106 * A URB queue.
107 */
108typedef struct USBHIDURBQUEUE
109{
110 /** The head pointer. */
111 PVUSBURB pHead;
112 /** Where to insert the next entry. */
113 PVUSBURB *ppTail;
114} USBHIDURBQUEUE;
115/** Pointer to a URB queue. */
116typedef USBHIDURBQUEUE *PUSBHIDURBQUEUE;
117/** Pointer to a const URB queue. */
118typedef USBHIDURBQUEUE const *PCUSBHIDURBQUEUE;
119
120
121/**
122 * Mouse movement accumulator.
123 */
124typedef struct USBHIDM_ACCUM
125{
126 union
127 {
128 struct
129 {
130 uint32_t fButtons;
131 int32_t dx;
132 int32_t dy;
133 int32_t dz;
134 } Relative;
135 struct
136 {
137 uint32_t x;
138 uint32_t y;
139 uint32_t fButtons;
140 } Absolute;
141 } u;
142} USBHIDM_ACCUM, *PUSBHIDM_ACCUM;
143
144#define MT_CONTACTS_PER_REPORT 5
145
146#define MT_CONTACT_MAX_COUNT 10
147
148#define MT_CONTACT_F_IN_CONTACT 0x01
149#define MT_CONTACT_F_IN_RANGE 0x02
150
151#define MT_CONTACT_S_ACTIVE 0x01 /* Contact must be reported to the guest. */
152#define MT_CONTACT_S_CANCELLED 0x02 /* Contact loss must be reported to the guest. */
153#define MT_CONTACT_S_REUSED 0x04 /* Report contact loss for the oldId and then new contact for the id. */
154#define MT_CONTACT_S_DIRTY 0x08 /* Temporary flag used to track already processed elements. */
155
156typedef struct MTCONTACT
157{
158 uint16_t x;
159 uint16_t y;
160 uint8_t id;
161 uint8_t flags;
162 uint8_t status;
163 uint8_t oldId; /* Valid only if MT_CONTACT_S_REUSED is set. */
164} MTCONTACT;
165
166
167/**
168 * The USB HID instance data.
169 */
170typedef struct USBHID
171{
172 /** Pointer back to the PDM USB Device instance structure. */
173 PPDMUSBINS pUsbIns;
174 /** Critical section protecting the device state. */
175 RTCRITSECT CritSect;
176
177 /** The current configuration.
178 * (0 - default, 1 - the one supported configuration, i.e configured.) */
179 uint8_t bConfigurationValue;
180 /** Endpoint 0 is the default control pipe, 1 is the dev->host interrupt one. */
181 USBHIDEP aEps[2];
182 /** The state of the HID (state machine).*/
183 USBHIDREQSTATE enmState;
184
185 /** Pointer movement accumulator. */
186 USBHIDM_ACCUM PtrDelta;
187
188 /** Pending to-host queue.
189 * The URBs waiting here are waiting for data to become available.
190 */
191 USBHIDURBQUEUE ToHostQueue;
192
193 /** Done queue
194 * The URBs stashed here are waiting to be reaped. */
195 USBHIDURBQUEUE DoneQueue;
196 /** Signalled when adding an URB to the done queue and fHaveDoneQueueWaiter
197 * is set. */
198 RTSEMEVENT hEvtDoneQueue;
199
200 /** Someone is waiting on the done queue. */
201 bool fHaveDoneQueueWaiter;
202 /** If device has pending changes. */
203 bool fHasPendingChanges;
204 /** Is this a relative, absolute or multi-touch pointing device? */
205 USBHIDMODE enmMode;
206 /** Tablet coordinate shift factor for old and broken operating systems. */
207 uint8_t u8CoordShift;
208
209 /**
210 * Mouse port - LUN#0.
211 *
212 * @implements PDMIBASE
213 * @implements PDMIMOUSEPORT
214 */
215 struct
216 {
217 /** The base interface for the mouse port. */
218 PDMIBASE IBase;
219 /** The mouse port base interface. */
220 PDMIMOUSEPORT IPort;
221
222 /** The base interface of the attached mouse driver. */
223 R3PTRTYPE(PPDMIBASE) pDrvBase;
224 /** The mouse interface of the attached mouse driver. */
225 R3PTRTYPE(PPDMIMOUSECONNECTOR) pDrv;
226 } Lun0;
227
228 MTCONTACT aCurrentContactState[MT_CONTACT_MAX_COUNT];
229 MTCONTACT aReportingContactState[MT_CONTACT_MAX_COUNT];
230 uint32_t u32LastTouchScanTime;
231 bool fTouchReporting;
232 bool fTouchStateUpdated;
233} USBHID;
234/** Pointer to the USB HID instance data. */
235typedef USBHID *PUSBHID;
236
237#pragma pack(1)
238/**
239 * The USB HID report structure for relative device.
240 */
241typedef struct USBHIDM_REPORT
242{
243 uint8_t fButtons;
244 int8_t dx;
245 int8_t dy;
246 int8_t dz;
247} USBHIDM_REPORT, *PUSBHIDM_REPORT;
248
249/**
250 * The USB HID report structure for absolute device.
251 */
252
253typedef struct USBHIDT_REPORT
254{
255 uint8_t fButtons;
256 uint8_t padding;
257 uint16_t x;
258 uint16_t y;
259} USBHIDT_REPORT, *PUSBHIDT_REPORT;
260
261/**
262 * The combined USB HID report union for relative and absolute
263 * devices.
264 */
265typedef union USBHIDTM_REPORT
266{
267 USBHIDM_REPORT m;
268 USBHIDT_REPORT t;
269} USBHIDTM_REPORT, *PUSBHIDTM_REPORT;
270
271/**
272 * The USB HID report structure for the multi-touch device.
273 */
274typedef struct USBHIDMT_REPORT
275{
276 uint8_t idReport;
277 uint8_t cContacts;
278 struct
279 {
280 uint8_t fContact;
281 uint8_t cContact;
282 uint16_t x;
283 uint16_t y;
284 } aContacts[MT_CONTACTS_PER_REPORT];
285 uint32_t u32ScanTime;
286} USBHIDMT_REPORT, *PUSBHIDMT_REPORT;
287
288typedef struct USBHIDMT_REPORT_POINTER
289{
290 uint8_t idReport;
291 uint8_t fButtons;
292 uint16_t x;
293 uint16_t y;
294} USBHIDMT_REPORT_POINTER;
295#pragma pack()
296
297/*******************************************************************************
298* Global Variables *
299*******************************************************************************/
300static const PDMUSBDESCCACHESTRING g_aUsbHidStrings_en_US[] =
301{
302 { USBHID_STR_ID_MANUFACTURER, "VirtualBox" },
303 { USBHID_STR_ID_PRODUCT_M, "USB Mouse" },
304 { USBHID_STR_ID_PRODUCT_T, "USB Tablet" },
305 { USBHID_STR_ID_PRODUCT_MT, "USB Multi-Touch" },
306};
307
308static const PDMUSBDESCCACHELANG g_aUsbHidLanguages[] =
309{
310 { 0x0409, RT_ELEMENTS(g_aUsbHidStrings_en_US), g_aUsbHidStrings_en_US }
311};
312
313static const VUSBDESCENDPOINTEX g_aUsbHidMEndpointDescs[] =
314{
315 {
316 {
317 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
318 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
319 /* .bEndpointAddress = */ 0x81 /* ep=1, in */,
320 /* .bmAttributes = */ 3 /* interrupt */,
321 /* .wMaxPacketSize = */ 4,
322 /* .bInterval = */ 10,
323 },
324 /* .pvMore = */ NULL,
325 /* .pvClass = */ NULL,
326 /* .cbClass = */ 0
327 },
328};
329
330static const VUSBDESCENDPOINTEX g_aUsbHidTEndpointDescs[] =
331{
332 {
333 {
334 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
335 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
336 /* .bEndpointAddress = */ 0x81 /* ep=1, in */,
337 /* .bmAttributes = */ 3 /* interrupt */,
338 /* .wMaxPacketSize = */ 6,
339 /* .bInterval = */ 10,
340 },
341 /* .pvMore = */ NULL,
342 /* .pvClass = */ NULL,
343 /* .cbClass = */ 0
344 },
345};
346
347static const VUSBDESCENDPOINTEX g_aUsbHidMTEndpointDescs[] =
348{
349 {
350 {
351 /* .bLength = */ sizeof(VUSBDESCENDPOINT),
352 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
353 /* .bEndpointAddress = */ 0x81 /* ep=1, in */,
354 /* .bmAttributes = */ 3 /* interrupt */,
355 /* .wMaxPacketSize = */ 64,
356 /* .bInterval = */ 10,
357 },
358 /* .pvMore = */ NULL,
359 /* .pvClass = */ NULL,
360 /* .cbClass = */ 0
361 },
362};
363
364/* HID report descriptor (mouse). */
365static const uint8_t g_UsbHidMReportDesc[] =
366{
367 /* Usage Page */ 0x05, 0x01, /* Generic Desktop */
368 /* Usage */ 0x09, 0x02, /* Mouse */
369 /* Collection */ 0xA1, 0x01, /* Application */
370 /* Usage */ 0x09, 0x01, /* Pointer */
371 /* Collection */ 0xA1, 0x00, /* Physical */
372 /* Usage Page */ 0x05, 0x09, /* Button */
373 /* Usage Minimum */ 0x19, 0x01, /* Button 1 */
374 /* Usage Maximum */ 0x29, 0x05, /* Button 5 */
375 /* Logical Minimum */ 0x15, 0x00, /* 0 */
376 /* Logical Maximum */ 0x25, 0x01, /* 1 */
377 /* Report Count */ 0x95, 0x05, /* 5 */
378 /* Report Size */ 0x75, 0x01, /* 1 */
379 /* Input */ 0x81, 0x02, /* Data, Value, Absolute, Bit field */
380 /* Report Count */ 0x95, 0x01, /* 1 */
381 /* Report Size */ 0x75, 0x03, /* 3 (padding bits) */
382 /* Input */ 0x81, 0x03, /* Constant, Value, Absolute, Bit field */
383 /* Usage Page */ 0x05, 0x01, /* Generic Desktop */
384 /* Usage */ 0x09, 0x30, /* X */
385 /* Usage */ 0x09, 0x31, /* Y */
386 /* Usage */ 0x09, 0x38, /* Z (wheel) */
387 /* Logical Minimum */ 0x15, 0x81, /* -127 */
388 /* Logical Maximum */ 0x25, 0x7F, /* +127 */
389 /* Report Size */ 0x75, 0x08, /* 8 */
390 /* Report Count */ 0x95, 0x03, /* 3 */
391 /* Input */ 0x81, 0x06, /* Data, Value, Relative, Bit field */
392 /* End Collection */ 0xC0,
393 /* End Collection */ 0xC0,
394};
395
396/* HID report descriptor (tablet). */
397/* NB: The layout is far from random. Having the buttons and Z axis grouped
398 * together avoids alignment issues. Also, if X/Y is reported first, followed
399 * by buttons/Z, Windows gets phantom Z movement. That is likely a bug in Windows
400 * as OS X shows no such problem. When X/Y is reported last, Windows behaves
401 * properly.
402 */
403#define REPORTID_MOUSE 1
404#define REPORTID_MAX_COUNT 2
405
406static const uint8_t g_UsbHidTReportDesc[] =
407{
408 /* Usage Page */ 0x05, 0x01, /* Generic Desktop */
409 /* Usage */ 0x09, 0x02, /* Mouse */
410 /* Collection */ 0xA1, 0x01, /* Application */
411 /* Usage */ 0x09, 0x01, /* Pointer */
412 /* Collection */ 0xA1, 0x00, /* Physical */
413 /* Usage Page */ 0x05, 0x09, /* Button */
414 /* Usage Minimum */ 0x19, 0x01, /* Button 1 */
415 /* Usage Maximum */ 0x29, 0x05, /* Button 5 */
416 /* Logical Minimum */ 0x15, 0x00, /* 0 */
417 /* Logical Maximum */ 0x25, 0x01, /* 1 */
418 /* Report Count */ 0x95, 0x05, /* 5 */
419 /* Report Size */ 0x75, 0x01, /* 1 */
420 /* Input */ 0x81, 0x02, /* Data, Value, Absolute, Bit field */
421 /* Report Count */ 0x95, 0x01, /* 1 */
422 /* Report Size */ 0x75, 0x03, /* 3 (padding bits) */
423 /* Input */ 0x81, 0x03, /* Constant, Value, Absolute, Bit field */
424 /* Report Size */ 0x75, 0x08, /* 8 (padding byte) */
425 /* Report Count */ 0x95, 0x01, /* 1 */
426 /* Input */ 0x81, 0x03, /* Constant, Value, Absolute, Bit field */
427 /* Usage Page */ 0x05, 0x01, /* Generic Desktop */
428 /* Usage */ 0x09, 0x30, /* X */
429 /* Usage */ 0x09, 0x31, /* Y */
430 /* Logical Minimum */ 0x15, 0x00, /* 0 */
431 /* Logical Maximum */ 0x26, 0xFF,0x7F,/* 0x7fff */
432 /* Physical Minimum */ 0x35, 0x00, /* 0 */
433 /* Physical Maximum */ 0x46, 0xFF,0x7F,/* 0x7fff */
434 /* Report Size */ 0x75, 0x10, /* 16 */
435 /* Report Count */ 0x95, 0x02, /* 2 */
436 /* Input */ 0x81, 0x02, /* Data, Value, Absolute, Bit field */
437 /* End Collection */ 0xC0,
438 /* End Collection */ 0xC0,
439};
440
441/*
442 * Multi-touch device implementation based on "Windows Pointer Device Data Delivery Protocol"
443 * specification.
444 */
445
446#define REPORTID_TOUCH_POINTER 1
447#define REPORTID_TOUCH_EVENT 2
448#define REPORTID_TOUCH_MAX_COUNT 3
449#define REPORTID_TOUCH_QABLOB 4
450#define REPORTID_TOUCH_DEVCONFIG 5
451
452static const uint8_t g_UsbHidMTReportDesc[] =
453{
454/* Usage Page (Digitizer) */ 0x05, 0x0D,
455/* Usage (Touch Screen) */ 0x09, 0x04,
456/* Collection (Application) */ 0xA1, 0x01,
457/* Report ID */ 0x85, REPORTID_TOUCH_EVENT,
458/* Usage Page (Digitizer) */ 0x05, 0x0D,
459/* Usage (Contact count) */ 0x09, 0x54,
460/* Report Size (8) */ 0x75, 0x08,
461/* Logical Minimum (0) */ 0x15, 0x00,
462/* Logical Maximum (12) */ 0x25, 0x0C,
463/* Report Count (1) */ 0x95, 0x01,
464/* Input (Var) */ 0x81, 0x02,
465
466/* MT_CONTACTS_PER_REPORT structs u8TipSwitch, u8ContactIdentifier, u16X, u16Y */
467/* 1 of 5 */
468/* Usage (Finger) */ 0x09, 0x22,
469/* Collection (Logical) */ 0xA1, 0x02,
470/* Usage (Tip Switch) */ 0x09, 0x42,
471/* Logical Minimum (0) */ 0x15, 0x00,
472/* Logical Maximum (1) */ 0x25, 0x01,
473/* Report Size (1) */ 0x75, 0x01,
474/* Report Count (1) */ 0x95, 0x01,
475/* Input (Var) */ 0x81, 0x02,
476
477/* Usage (In Range) */ 0x09, 0x32,
478/* Logical Minimum (0) */ 0x15, 0x00,
479/* Logical Maximum (1) */ 0x25, 0x01,
480/* Report Size (1) */ 0x75, 0x01,
481/* Report Count (1) */ 0x95, 0x01,
482/* Input (Var) */ 0x81, 0x02,
483
484/* Report Count (6) */ 0x95, 0x06,
485/* Input (Cnst,Var) */ 0x81, 0x03,
486
487/* Report Size (8) */ 0x75, 0x08,
488/* Usage (Contact identifier) */ 0x09, 0x51,
489/* Report Count (1) */ 0x95, 0x01,
490/* Logical Minimum (0) */ 0x15, 0x00,
491/* Logical Maximum (32) */ 0x25, 0x20,
492/* Input (Var) */ 0x81, 0x02,
493
494/* Usage Page (Generic Desktop) */ 0x05, 0x01,
495/* Logical Maximum (32K) */ 0x26, 0xFF, 0x7F,
496/* Report Size (16) */ 0x75, 0x10,
497/* Usage (X) */ 0x09, 0x30,
498/* Input (Var) */ 0x81, 0x02,
499
500/* Usage (Y) */ 0x09, 0x31,
501/* Input (Var) */ 0x81, 0x02,
502/* End Collection */ 0xC0,
503/* 2 of 5 */
504/* Usage Page (Digitizer) */ 0x05, 0x0D,
505/* Usage (Finger) */ 0x09, 0x22,
506/* Collection (Logical) */ 0xA1, 0x02,
507/* Usage (Tip Switch) */ 0x09, 0x42,
508/* Logical Minimum (0) */ 0x15, 0x00,
509/* Logical Maximum (1) */ 0x25, 0x01,
510/* Report Size (1) */ 0x75, 0x01,
511/* Report Count (1) */ 0x95, 0x01,
512/* Input (Var) */ 0x81, 0x02,
513/* Usage (In Range) */ 0x09, 0x32,
514/* Logical Minimum (0) */ 0x15, 0x00,
515/* Logical Maximum (1) */ 0x25, 0x01,
516/* Report Size (1) */ 0x75, 0x01,
517/* Report Count (1) */ 0x95, 0x01,
518/* Input (Var) */ 0x81, 0x02,
519/* Report Count (6) */ 0x95, 0x06,
520/* Input (Cnst,Var) */ 0x81, 0x03,
521/* Report Size (8) */ 0x75, 0x08,
522/* Usage (Contact identifier) */ 0x09, 0x51,
523/* Report Count (1) */ 0x95, 0x01,
524/* Logical Minimum (0) */ 0x15, 0x00,
525/* Logical Maximum (32) */ 0x25, 0x20,
526/* Input (Var) */ 0x81, 0x02,
527/* Usage Page (Generic Desktop) */ 0x05, 0x01,
528/* Logical Maximum (32K) */ 0x26, 0xFF, 0x7F,
529/* Report Size (16) */ 0x75, 0x10,
530/* Usage (X) */ 0x09, 0x30,
531/* Input (Var) */ 0x81, 0x02,
532/* Usage (Y) */ 0x09, 0x31,
533/* Input (Var) */ 0x81, 0x02,
534/* End Collection */ 0xC0,
535/* 3 of 5 */
536/* Usage Page (Digitizer) */ 0x05, 0x0D,
537/* Usage (Finger) */ 0x09, 0x22,
538/* Collection (Logical) */ 0xA1, 0x02,
539/* Usage (Tip Switch) */ 0x09, 0x42,
540/* Logical Minimum (0) */ 0x15, 0x00,
541/* Logical Maximum (1) */ 0x25, 0x01,
542/* Report Size (1) */ 0x75, 0x01,
543/* Report Count (1) */ 0x95, 0x01,
544/* Input (Var) */ 0x81, 0x02,
545/* Usage (In Range) */ 0x09, 0x32,
546/* Logical Minimum (0) */ 0x15, 0x00,
547/* Logical Maximum (1) */ 0x25, 0x01,
548/* Report Size (1) */ 0x75, 0x01,
549/* Report Count (1) */ 0x95, 0x01,
550/* Input (Var) */ 0x81, 0x02,
551/* Report Count (6) */ 0x95, 0x06,
552/* Input (Cnst,Var) */ 0x81, 0x03,
553/* Report Size (8) */ 0x75, 0x08,
554/* Usage (Contact identifier) */ 0x09, 0x51,
555/* Report Count (1) */ 0x95, 0x01,
556/* Logical Minimum (0) */ 0x15, 0x00,
557/* Logical Maximum (32) */ 0x25, 0x20,
558/* Input (Var) */ 0x81, 0x02,
559/* Usage Page (Generic Desktop) */ 0x05, 0x01,
560/* Logical Maximum (32K) */ 0x26, 0xFF, 0x7F,
561/* Report Size (16) */ 0x75, 0x10,
562/* Usage (X) */ 0x09, 0x30,
563/* Input (Var) */ 0x81, 0x02,
564/* Usage (Y) */ 0x09, 0x31,
565/* Input (Var) */ 0x81, 0x02,
566/* End Collection */ 0xC0,
567/* 4 of 5 */
568/* Usage Page (Digitizer) */ 0x05, 0x0D,
569/* Usage (Finger) */ 0x09, 0x22,
570/* Collection (Logical) */ 0xA1, 0x02,
571/* Usage (Tip Switch) */ 0x09, 0x42,
572/* Logical Minimum (0) */ 0x15, 0x00,
573/* Logical Maximum (1) */ 0x25, 0x01,
574/* Report Size (1) */ 0x75, 0x01,
575/* Report Count (1) */ 0x95, 0x01,
576/* Input (Var) */ 0x81, 0x02,
577/* Usage (In Range) */ 0x09, 0x32,
578/* Logical Minimum (0) */ 0x15, 0x00,
579/* Logical Maximum (1) */ 0x25, 0x01,
580/* Report Size (1) */ 0x75, 0x01,
581/* Report Count (1) */ 0x95, 0x01,
582/* Input (Var) */ 0x81, 0x02,
583/* Report Count (6) */ 0x95, 0x06,
584/* Input (Cnst,Var) */ 0x81, 0x03,
585/* Report Size (8) */ 0x75, 0x08,
586/* Usage (Contact identifier) */ 0x09, 0x51,
587/* Report Count (1) */ 0x95, 0x01,
588/* Logical Minimum (0) */ 0x15, 0x00,
589/* Logical Maximum (32) */ 0x25, 0x20,
590/* Input (Var) */ 0x81, 0x02,
591/* Usage Page (Generic Desktop) */ 0x05, 0x01,
592/* Logical Maximum (32K) */ 0x26, 0xFF, 0x7F,
593/* Report Size (16) */ 0x75, 0x10,
594/* Usage (X) */ 0x09, 0x30,
595/* Input (Var) */ 0x81, 0x02,
596/* Usage (Y) */ 0x09, 0x31,
597/* Input (Var) */ 0x81, 0x02,
598/* End Collection */ 0xC0,
599/* 5 of 5 */
600/* Usage Page (Digitizer) */ 0x05, 0x0D,
601/* Usage (Finger) */ 0x09, 0x22,
602/* Collection (Logical) */ 0xA1, 0x02,
603/* Usage (Tip Switch) */ 0x09, 0x42,
604/* Logical Minimum (0) */ 0x15, 0x00,
605/* Logical Maximum (1) */ 0x25, 0x01,
606/* Report Size (1) */ 0x75, 0x01,
607/* Report Count (1) */ 0x95, 0x01,
608/* Input (Var) */ 0x81, 0x02,
609/* Usage (In Range) */ 0x09, 0x32,
610/* Logical Minimum (0) */ 0x15, 0x00,
611/* Logical Maximum (1) */ 0x25, 0x01,
612/* Report Size (1) */ 0x75, 0x01,
613/* Report Count (1) */ 0x95, 0x01,
614/* Input (Var) */ 0x81, 0x02,
615/* Report Count (6) */ 0x95, 0x06,
616/* Input (Cnst,Var) */ 0x81, 0x03,
617/* Report Size (8) */ 0x75, 0x08,
618/* Usage (Contact identifier) */ 0x09, 0x51,
619/* Report Count (1) */ 0x95, 0x01,
620/* Logical Minimum (0) */ 0x15, 0x00,
621/* Logical Maximum (32) */ 0x25, 0x20,
622/* Input (Var) */ 0x81, 0x02,
623/* Usage Page (Generic Desktop) */ 0x05, 0x01,
624/* Logical Maximum (32K) */ 0x26, 0xFF, 0x7F,
625/* Report Size (16) */ 0x75, 0x10,
626/* Usage (X) */ 0x09, 0x30,
627/* Input (Var) */ 0x81, 0x02,
628/* Usage (Y) */ 0x09, 0x31,
629/* Input (Var) */ 0x81, 0x02,
630/* End Collection */ 0xC0,
631
632/* Note: "Scan time" usage is required for all touch devices (in 100microseconds units). */
633/* Usage Page (Digitizer) */ 0x05, 0x0D,
634/* Logical Minimum (0) */ 0x17, 0x00, 0x00, 0x00, 0x00,
635/* Logical Maximum (2147483647) */ 0x27, 0xFF, 0xFF, 0xFF, 0x7F,
636/* Report Size (32) */ 0x75, 0x20,
637/* Report Count (1) */ 0x95, 0x01,
638/* Unit Exponent (0) */ 0x55, 0x00,
639/* Unit (None) */ 0x65, 0x00,
640/* Usage (Scan time) */ 0x09, 0x56,
641/* Input (Var) */ 0x81, 0x02,
642
643/* Report ID */ 0x85, REPORTID_TOUCH_MAX_COUNT,
644/* Usage (Contact count maximum) */ 0x09, 0x55,
645/* Usage (Device identifier) */ 0x09, 0x53,
646/* Report Size (8) */ 0x75, 0x08,
647/* Report Count (2) */ 0x95, 0x02,
648/* Logical Maximum (255) */ 0x26, 0xFF, 0x00,
649/* Feature (Var) */ 0xB1, 0x02,
650
651/* Usage Page (Vendor-Defined 1) */ 0x06, 0x00, 0xFF,
652/* Usage (QA blob) */ 0x09, 0xC5,
653/* Report ID */ 0x85, REPORTID_TOUCH_QABLOB,
654/* Logical Minimum (0) */ 0x15, 0x00,
655/* Logical Maximum (255) */ 0x26, 0xFF, 0x00,
656/* Report Size (8) */ 0x75, 0x08,
657/* Report Count (256) */ 0x96, 0x00, 0x01,
658/* Feature (Var) */ 0xB1, 0x02,
659/* End Collection */ 0xC0,
660
661/* Note: the pointer report is required by specification:
662 * "The report descriptor for a multiple input device must include at least
663 * one top-level collection for the primary device and a separate top-level
664 * collection for the mouse."
665 */
666/* Usage Page (Generic Desktop) */ 0x05, 0x01,
667/* Usage (Pointer) */ 0x09, 0x01,
668/* Collection (Application) */ 0xA1, 0x01,
669/* Report ID */ 0x85, REPORTID_TOUCH_POINTER,
670/* Usage (Pointer) */ 0x09, 0x01,
671/* Collection (Logical) */ 0xA1, 0x02,
672/* Usage Page (Button) */ 0x05, 0x09,
673/* Usage Minimum (Button 1) */ 0x19, 0x01,
674/* Usage Maximum (Button 2) */ 0x29, 0x02,
675/* Logical Minimum (0) */ 0x15, 0x00,
676/* Logical Maximum (1) */ 0x25, 0x01,
677/* Report Count (2) */ 0x95, 0x02,
678/* Report Size (1) */ 0x75, 0x01,
679/* Input (Var) */ 0x81, 0x02,
680/* Report Count (1) */ 0x95, 0x01,
681/* Report Size (6) */ 0x75, 0x06,
682/* Input (Cnst,Ary,Abs) */ 0x81, 0x01,
683/* Usage Page (Generic Desktop) */ 0x05, 0x01,
684/* Usage (X) */ 0x09, 0x30,
685/* Usage (Y) */ 0x09, 0x31,
686/* Logical Minimum (0) */ 0x16, 0x00, 0x00,
687/* Logical Maximum (32K) */ 0x26, 0xFF, 0x7F,
688/* Physical Minimum (0) */ 0x36, 0x00, 0x00,
689/* Physical Maximum (32K) */ 0x46, 0xFF, 0x7F,
690/* Unit (None) */ 0x66, 0x00, 0x00,
691/* Report Size (16) */ 0x75, 0x10,
692/* Report Count (2) */ 0x95, 0x02,
693/* Input (Var) */ 0x81, 0x02,
694/* End Collection */ 0xC0,
695/* End Collection */ 0xC0,
696
697/* Usage Page (Digitizer) */ 0x05, 0x0D,
698/* Usage (Device configuration) */ 0x09, 0x0E,
699/* Collection (Application) */ 0xA1, 0x01,
700/* Report ID */ 0x85, REPORTID_TOUCH_DEVCONFIG,
701/* Usage (Device settings) */ 0x09, 0x23,
702/* Collection (Logical) */ 0xA1, 0x02,
703/* Usage (Device mode) */ 0x09, 0x52,
704/* Usage (Device identifier) */ 0x09, 0x53,
705/* Logical Minimum (0) */ 0x15, 0x00,
706/* Logical Maximum (10) */ 0x25, 0x0A,
707/* Report Size (8) */ 0x75, 0x08,
708/* Report Count (2) */ 0x95, 0x02,
709/* Feature (Var) */ 0xB1, 0x02,
710/* End Collection */ 0xC0,
711/* End Collection */ 0xC0
712};
713
714/** @todo Do these really have to all be duplicated three times? */
715/* Additional HID class interface descriptor. */
716static const uint8_t g_UsbHidMIfHidDesc[] =
717{
718 /* .bLength = */ 0x09,
719 /* .bDescriptorType = */ 0x21, /* HID */
720 /* .bcdHID = */ 0x10, 0x01, /* 1.1 */
721 /* .bCountryCode = */ 0,
722 /* .bNumDescriptors = */ 1,
723 /* .bDescriptorType = */ 0x22, /* Report */
724 /* .wDescriptorLength = */ sizeof(g_UsbHidMReportDesc), 0x00
725};
726
727/* Additional HID class interface descriptor. */
728static const uint8_t g_UsbHidTIfHidDesc[] =
729{
730 /* .bLength = */ 0x09,
731 /* .bDescriptorType = */ 0x21, /* HID */
732 /* .bcdHID = */ 0x10, 0x01, /* 1.1 */
733 /* .bCountryCode = */ 0,
734 /* .bNumDescriptors = */ 1,
735 /* .bDescriptorType = */ 0x22, /* Report */
736 /* .wDescriptorLength = */ sizeof(g_UsbHidTReportDesc), 0x00
737};
738
739/* Additional HID class interface descriptor. */
740static const uint8_t g_UsbHidMTIfHidDesc[] =
741{
742 /* .bLength = */ 0x09,
743 /* .bDescriptorType = */ 0x21, /* HID */
744 /* .bcdHID = */ 0x10, 0x02, /* 2.1 */
745 /* .bCountryCode = */ 0,
746 /* .bNumDescriptors = */ 1,
747 /* .bDescriptorType = */ 0x22, /* Report */
748 /* .wDescriptorLength = */ (uint8_t)(sizeof(g_UsbHidMTReportDesc) & 0xFF),
749 (uint8_t)((sizeof(g_UsbHidMTReportDesc) >> 8) & 0xFF)
750};
751
752static const VUSBDESCINTERFACEEX g_UsbHidMInterfaceDesc =
753{
754 {
755 /* .bLength = */ sizeof(VUSBDESCINTERFACE),
756 /* .bDescriptorType = */ VUSB_DT_INTERFACE,
757 /* .bInterfaceNumber = */ 0,
758 /* .bAlternateSetting = */ 0,
759 /* .bNumEndpoints = */ 1,
760 /* .bInterfaceClass = */ 3 /* HID */,
761 /* .bInterfaceSubClass = */ 1 /* Boot Interface */,
762 /* .bInterfaceProtocol = */ 2 /* Mouse */,
763 /* .iInterface = */ 0
764 },
765 /* .pvMore = */ NULL,
766 /* .pvClass = */ &g_UsbHidMIfHidDesc,
767 /* .cbClass = */ sizeof(g_UsbHidMIfHidDesc),
768 &g_aUsbHidMEndpointDescs[0],
769 /* .pIAD = */ NULL,
770 /* .cbIAD = */ 0
771};
772
773static const VUSBDESCINTERFACEEX g_UsbHidTInterfaceDesc =
774{
775 {
776 /* .bLength = */ sizeof(VUSBDESCINTERFACE),
777 /* .bDescriptorType = */ VUSB_DT_INTERFACE,
778 /* .bInterfaceNumber = */ 0,
779 /* .bAlternateSetting = */ 0,
780 /* .bNumEndpoints = */ 1,
781 /* .bInterfaceClass = */ 3 /* HID */,
782 /* .bInterfaceSubClass = */ 0 /* No subclass - no boot interface. */,
783 /* .bInterfaceProtocol = */ 0 /* No protocol - no boot interface. */,
784 /* .iInterface = */ 0
785 },
786 /* .pvMore = */ NULL,
787 /* .pvClass = */ &g_UsbHidTIfHidDesc,
788 /* .cbClass = */ sizeof(g_UsbHidTIfHidDesc),
789 &g_aUsbHidTEndpointDescs[0],
790 /* .pIAD = */ NULL,
791 /* .cbIAD = */ 0
792};
793
794static const VUSBDESCINTERFACEEX g_UsbHidMTInterfaceDesc =
795{
796 {
797 /* .bLength = */ sizeof(VUSBDESCINTERFACE),
798 /* .bDescriptorType = */ VUSB_DT_INTERFACE,
799 /* .bInterfaceNumber = */ 0,
800 /* .bAlternateSetting = */ 0,
801 /* .bNumEndpoints = */ 1,
802 /* .bInterfaceClass = */ 3 /* HID */,
803 /* .bInterfaceSubClass = */ 0 /* No subclass - no boot interface. */,
804 /* .bInterfaceProtocol = */ 0 /* No protocol - no boot interface. */,
805 /* .iInterface = */ 0
806 },
807 /* .pvMore = */ NULL,
808 /* .pvClass = */ &g_UsbHidMTIfHidDesc,
809 /* .cbClass = */ sizeof(g_UsbHidMTIfHidDesc),
810 &g_aUsbHidMTEndpointDescs[0],
811 /* .pIAD = */ NULL,
812 /* .cbIAD = */ 0
813};
814
815static const VUSBINTERFACE g_aUsbHidMInterfaces[] =
816{
817 { &g_UsbHidMInterfaceDesc, /* .cSettings = */ 1 },
818};
819
820static const VUSBINTERFACE g_aUsbHidTInterfaces[] =
821{
822 { &g_UsbHidTInterfaceDesc, /* .cSettings = */ 1 },
823};
824
825static const VUSBINTERFACE g_aUsbHidMTInterfaces[] =
826{
827 { &g_UsbHidMTInterfaceDesc, /* .cSettings = */ 1 },
828};
829
830static const VUSBDESCCONFIGEX g_UsbHidMConfigDesc =
831{
832 {
833 /* .bLength = */ sizeof(VUSBDESCCONFIG),
834 /* .bDescriptorType = */ VUSB_DT_CONFIG,
835 /* .wTotalLength = */ 0 /* recalculated on read */,
836 /* .bNumInterfaces = */ RT_ELEMENTS(g_aUsbHidMInterfaces),
837 /* .bConfigurationValue =*/ 1,
838 /* .iConfiguration = */ 0,
839 /* .bmAttributes = */ RT_BIT(7),
840 /* .MaxPower = */ 50 /* 100mA */
841 },
842 NULL, /* pvMore */
843 &g_aUsbHidMInterfaces[0],
844 NULL /* pvOriginal */
845};
846
847static const VUSBDESCCONFIGEX g_UsbHidTConfigDesc =
848{
849 {
850 /* .bLength = */ sizeof(VUSBDESCCONFIG),
851 /* .bDescriptorType = */ VUSB_DT_CONFIG,
852 /* .wTotalLength = */ 0 /* recalculated on read */,
853 /* .bNumInterfaces = */ RT_ELEMENTS(g_aUsbHidTInterfaces),
854 /* .bConfigurationValue =*/ 1,
855 /* .iConfiguration = */ 0,
856 /* .bmAttributes = */ RT_BIT(7),
857 /* .MaxPower = */ 50 /* 100mA */
858 },
859 NULL, /* pvMore */
860 &g_aUsbHidTInterfaces[0],
861 NULL /* pvOriginal */
862};
863
864static const VUSBDESCCONFIGEX g_UsbHidMTConfigDesc =
865{
866 {
867 /* .bLength = */ sizeof(VUSBDESCCONFIG),
868 /* .bDescriptorType = */ VUSB_DT_CONFIG,
869 /* .wTotalLength = */ 0 /* recalculated on read */,
870 /* .bNumInterfaces = */ RT_ELEMENTS(g_aUsbHidMTInterfaces),
871 /* .bConfigurationValue =*/ 1,
872 /* .iConfiguration = */ 0,
873 /* .bmAttributes = */ RT_BIT(7),
874 /* .MaxPower = */ 50 /* 100mA */
875 },
876 NULL, /* pvMore */
877 &g_aUsbHidMTInterfaces[0],
878 NULL /* pvOriginal */
879};
880
881static const VUSBDESCDEVICE g_UsbHidMDeviceDesc =
882{
883 /* .bLength = */ sizeof(g_UsbHidMDeviceDesc),
884 /* .bDescriptorType = */ VUSB_DT_DEVICE,
885 /* .bcdUsb = */ 0x110, /* 1.1 */
886 /* .bDeviceClass = */ 0 /* Class specified in the interface desc. */,
887 /* .bDeviceSubClass = */ 0 /* Subclass specified in the interface desc. */,
888 /* .bDeviceProtocol = */ 0 /* Protocol specified in the interface desc. */,
889 /* .bMaxPacketSize0 = */ 8,
890 /* .idVendor = */ VBOX_USB_VENDOR,
891 /* .idProduct = */ USBHID_PID_MOUSE,
892 /* .bcdDevice = */ 0x0100, /* 1.0 */
893 /* .iManufacturer = */ USBHID_STR_ID_MANUFACTURER,
894 /* .iProduct = */ USBHID_STR_ID_PRODUCT_M,
895 /* .iSerialNumber = */ 0,
896 /* .bNumConfigurations = */ 1
897};
898
899static const VUSBDESCDEVICE g_UsbHidTDeviceDesc =
900{
901 /* .bLength = */ sizeof(g_UsbHidTDeviceDesc),
902 /* .bDescriptorType = */ VUSB_DT_DEVICE,
903 /* .bcdUsb = */ 0x110, /* 1.1 */
904 /* .bDeviceClass = */ 0 /* Class specified in the interface desc. */,
905 /* .bDeviceSubClass = */ 0 /* Subclass specified in the interface desc. */,
906 /* .bDeviceProtocol = */ 0 /* Protocol specified in the interface desc. */,
907 /* .bMaxPacketSize0 = */ 8,
908 /* .idVendor = */ VBOX_USB_VENDOR,
909 /* .idProduct = */ USBHID_PID_TABLET,
910 /* .bcdDevice = */ 0x0100, /* 1.0 */
911 /* .iManufacturer = */ USBHID_STR_ID_MANUFACTURER,
912 /* .iProduct = */ USBHID_STR_ID_PRODUCT_T,
913 /* .iSerialNumber = */ 0,
914 /* .bNumConfigurations = */ 1
915};
916
917static const VUSBDESCDEVICE g_UsbHidMTDeviceDesc =
918{
919 /* .bLength = */ sizeof(g_UsbHidMTDeviceDesc),
920 /* .bDescriptorType = */ VUSB_DT_DEVICE,
921 /* .bcdUsb = */ 0x110, /* 1.1 */
922 /* .bDeviceClass = */ 0 /* Class specified in the interface desc. */,
923 /* .bDeviceSubClass = */ 0 /* Subclass specified in the interface desc. */,
924 /* .bDeviceProtocol = */ 0 /* Protocol specified in the interface desc. */,
925 /* .bMaxPacketSize0 = */ 8,
926 /* .idVendor = */ VBOX_USB_VENDOR,
927 /* .idProduct = */ USBHID_PID_MULTI_TOUCH,
928 /* .bcdDevice = */ 0x0100, /* 1.0 */
929 /* .iManufacturer = */ USBHID_STR_ID_MANUFACTURER,
930 /* .iProduct = */ USBHID_STR_ID_PRODUCT_MT,
931 /* .iSerialNumber = */ 0,
932 /* .bNumConfigurations = */ 1
933};
934
935static const PDMUSBDESCCACHE g_UsbHidMDescCache =
936{
937 /* .pDevice = */ &g_UsbHidMDeviceDesc,
938 /* .paConfigs = */ &g_UsbHidMConfigDesc,
939 /* .paLanguages = */ g_aUsbHidLanguages,
940 /* .cLanguages = */ RT_ELEMENTS(g_aUsbHidLanguages),
941 /* .fUseCachedDescriptors = */ true,
942 /* .fUseCachedStringsDescriptors = */ true
943};
944
945static const PDMUSBDESCCACHE g_UsbHidTDescCache =
946{
947 /* .pDevice = */ &g_UsbHidTDeviceDesc,
948 /* .paConfigs = */ &g_UsbHidTConfigDesc,
949 /* .paLanguages = */ g_aUsbHidLanguages,
950 /* .cLanguages = */ RT_ELEMENTS(g_aUsbHidLanguages),
951 /* .fUseCachedDescriptors = */ true,
952 /* .fUseCachedStringsDescriptors = */ true
953};
954
955static const PDMUSBDESCCACHE g_UsbHidMTDescCache =
956{
957 /* .pDevice = */ &g_UsbHidMTDeviceDesc,
958 /* .paConfigs = */ &g_UsbHidMTConfigDesc,
959 /* .paLanguages = */ g_aUsbHidLanguages,
960 /* .cLanguages = */ RT_ELEMENTS(g_aUsbHidLanguages),
961 /* .fUseCachedDescriptors = */ true,
962 /* .fUseCachedStringsDescriptors = */ true
963};
964
965
966/*******************************************************************************
967* Internal Functions *
968*******************************************************************************/
969
970/**
971 * Initializes an URB queue.
972 *
973 * @param pQueue The URB queue.
974 */
975static void usbHidQueueInit(PUSBHIDURBQUEUE pQueue)
976{
977 pQueue->pHead = NULL;
978 pQueue->ppTail = &pQueue->pHead;
979}
980
981
982
983/**
984 * Inserts an URB at the end of the queue.
985 *
986 * @param pQueue The URB queue.
987 * @param pUrb The URB to insert.
988 */
989DECLINLINE(void) usbHidQueueAddTail(PUSBHIDURBQUEUE pQueue, PVUSBURB pUrb)
990{
991 pUrb->Dev.pNext = NULL;
992 *pQueue->ppTail = pUrb;
993 pQueue->ppTail = &pUrb->Dev.pNext;
994}
995
996
997/**
998 * Unlinks the head of the queue and returns it.
999 *
1000 * @returns The head entry.
1001 * @param pQueue The URB queue.
1002 */
1003DECLINLINE(PVUSBURB) usbHidQueueRemoveHead(PUSBHIDURBQUEUE pQueue)
1004{
1005 PVUSBURB pUrb = pQueue->pHead;
1006 if (pUrb)
1007 {
1008 PVUSBURB pNext = pUrb->Dev.pNext;
1009 pQueue->pHead = pNext;
1010 if (!pNext)
1011 pQueue->ppTail = &pQueue->pHead;
1012 else
1013 pUrb->Dev.pNext = NULL;
1014 }
1015 return pUrb;
1016}
1017
1018
1019/**
1020 * Removes an URB from anywhere in the queue.
1021 *
1022 * @returns true if found, false if not.
1023 * @param pQueue The URB queue.
1024 * @param pUrb The URB to remove.
1025 */
1026DECLINLINE(bool) usbHidQueueRemove(PUSBHIDURBQUEUE pQueue, PVUSBURB pUrb)
1027{
1028 PVUSBURB pCur = pQueue->pHead;
1029 if (pCur == pUrb)
1030 {
1031 pQueue->pHead = pUrb->Dev.pNext;
1032 if (!pUrb->Dev.pNext)
1033 pQueue->ppTail = &pQueue->pHead;
1034 }
1035 else
1036 {
1037 while (pCur)
1038 {
1039 if (pCur->Dev.pNext == pUrb)
1040 {
1041 pCur->Dev.pNext = pUrb->Dev.pNext;
1042 break;
1043 }
1044 pCur = pCur->Dev.pNext;
1045 }
1046 if (!pCur)
1047 return false;
1048 if (!pUrb->Dev.pNext)
1049 pQueue->ppTail = &pCur->Dev.pNext;
1050 }
1051 pUrb->Dev.pNext = NULL;
1052 return true;
1053}
1054
1055
1056/**
1057 * Checks if the queue is empty or not.
1058 *
1059 * @returns true if it is, false if it isn't.
1060 * @param pQueue The URB queue.
1061 */
1062DECLINLINE(bool) usbHidQueueIsEmpty(PCUSBHIDURBQUEUE pQueue)
1063{
1064 return pQueue->pHead == NULL;
1065}
1066
1067
1068/**
1069 * Links an URB into the done queue.
1070 *
1071 * @param pThis The HID instance.
1072 * @param pUrb The URB.
1073 */
1074static void usbHidLinkDone(PUSBHID pThis, PVUSBURB pUrb)
1075{
1076 usbHidQueueAddTail(&pThis->DoneQueue, pUrb);
1077
1078 if (pThis->fHaveDoneQueueWaiter)
1079 {
1080 int rc = RTSemEventSignal(pThis->hEvtDoneQueue);
1081 AssertRC(rc);
1082 }
1083}
1084
1085
1086
1087/**
1088 * Completes the URB with a stalled state, halting the pipe.
1089 */
1090static int usbHidCompleteStall(PUSBHID pThis, PUSBHIDEP pEp, PVUSBURB pUrb, const char *pszWhy)
1091{
1092 LogRelFlow(("usbHidCompleteStall/#%u: pUrb=%p:%s: %s\n",
1093 pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc, pszWhy));
1094
1095 pUrb->enmStatus = VUSBSTATUS_STALL;
1096
1097 /** @todo figure out if the stall is global or pipe-specific or both. */
1098 if (pEp)
1099 pEp->fHalted = true;
1100 else
1101 {
1102 pThis->aEps[0].fHalted = true;
1103 pThis->aEps[1].fHalted = true;
1104 }
1105
1106 usbHidLinkDone(pThis, pUrb);
1107 return VINF_SUCCESS;
1108}
1109
1110
1111/**
1112 * Completes the URB with a OK state.
1113 */
1114static int usbHidCompleteOk(PUSBHID pThis, PVUSBURB pUrb, size_t cbData)
1115{
1116 LogRelFlow(("usbHidCompleteOk/#%u: pUrb=%p:%s cbData=%#zx\n",
1117 pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc, cbData));
1118
1119 pUrb->enmStatus = VUSBSTATUS_OK;
1120 pUrb->cbData = (uint32_t)cbData;
1121
1122 usbHidLinkDone(pThis, pUrb);
1123 return VINF_SUCCESS;
1124}
1125
1126
1127/**
1128 * Reset worker for usbHidUsbReset, usbHidUsbSetConfiguration and
1129 * usbHidHandleDefaultPipe.
1130 *
1131 * @returns VBox status code.
1132 * @param pThis The HID instance.
1133 * @param pUrb Set when usbHidHandleDefaultPipe is the
1134 * caller.
1135 * @param fSetConfig Set when usbHidUsbSetConfiguration is the
1136 * caller.
1137 */
1138static int usbHidResetWorker(PUSBHID pThis, PVUSBURB pUrb, bool fSetConfig)
1139{
1140 /*
1141 * Wait for the any command currently executing to complete before
1142 * resetting. (We cannot cancel its execution.) How we do this depends
1143 * on the reset method.
1144 */
1145
1146 /*
1147 * Reset the device state.
1148 */
1149 pThis->enmState = USBHIDREQSTATE_READY;
1150 pThis->fHasPendingChanges = false;
1151 pThis->fTouchStateUpdated = false;
1152
1153 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aEps); i++)
1154 pThis->aEps[i].fHalted = false;
1155
1156 if (!pUrb && !fSetConfig) /* (only device reset) */
1157 pThis->bConfigurationValue = 0; /* default */
1158
1159 /*
1160 * Ditch all pending URBs.
1161 */
1162 PVUSBURB pCurUrb;
1163 while ((pCurUrb = usbHidQueueRemoveHead(&pThis->ToHostQueue)) != NULL)
1164 {
1165 pCurUrb->enmStatus = VUSBSTATUS_CRC;
1166 usbHidLinkDone(pThis, pCurUrb);
1167 }
1168
1169 if (pUrb)
1170 return usbHidCompleteOk(pThis, pUrb, 0);
1171 return VINF_SUCCESS;
1172}
1173
1174static int8_t clamp_i8(int32_t val)
1175{
1176 if (val > 127) {
1177 val = 127;
1178 } else if (val < -127) {
1179 val = -127;
1180 }
1181 return val;
1182}
1183
1184/**
1185 * Create a USB HID report report based on the currently accumulated data.
1186 */
1187static size_t usbHidFillReport(PUSBHIDTM_REPORT pReport,
1188 PUSBHIDM_ACCUM pAccumulated, USBHIDMODE enmMode)
1189{
1190 size_t cbCopy;
1191
1192 switch (enmMode)
1193 {
1194 case USBHIDMODE_ABSOLUTE:
1195 pReport->t.fButtons = pAccumulated->u.Absolute.fButtons;
1196 pReport->t.padding = 0;
1197 pReport->t.x = pAccumulated->u.Absolute.x;
1198 pReport->t.y = pAccumulated->u.Absolute.y;
1199
1200 cbCopy = sizeof(pReport->t);
1201 LogRel3(("Abs event, x=%d, y=%d, fButtons=%02x, report size %d\n",
1202 pReport->t.x, pReport->t.y, pReport->t.fButtons,
1203 cbCopy));
1204 break;
1205 case USBHIDMODE_RELATIVE:
1206 pReport->m.fButtons = pAccumulated->u.Relative.fButtons;
1207 pReport->m.dx = clamp_i8(pAccumulated->u.Relative.dx);
1208 pReport->m.dy = clamp_i8(pAccumulated->u.Relative.dy);
1209 pReport->m.dz = clamp_i8(pAccumulated->u.Relative.dz);
1210
1211 cbCopy = sizeof(pReport->m);
1212 LogRel3(("Rel event, dx=%d, dy=%d, dz=%d, fButtons=%02x, report size %d\n",
1213 pReport->m.dx, pReport->m.dy, pReport->m.dz,
1214 pReport->m.fButtons, cbCopy));
1215 break;
1216 default:
1217 AssertFailed(); /* Unexpected here. */
1218 cbCopy = 0;
1219 break;
1220 }
1221
1222 /* Clear the accumulated movement. */
1223 RT_ZERO(*pAccumulated);
1224
1225 return cbCopy;
1226}
1227
1228DECLINLINE(MTCONTACT *) usbHidFindMTContact(MTCONTACT *paContacts, size_t cContacts,
1229 uint8_t u8Mask, uint8_t u8Value)
1230{
1231 size_t i;
1232 for (i = 0; i < cContacts; i++)
1233 {
1234 if ((paContacts[i].status & u8Mask) == u8Value)
1235 {
1236 return &paContacts[i];
1237 }
1238 }
1239
1240 return NULL;
1241}
1242
1243static int usbHidSendMultiTouchReport(PUSBHID pThis, PVUSBURB pUrb)
1244{
1245 uint8_t i;
1246 MTCONTACT *pRepContact;
1247 MTCONTACT *pCurContact;
1248
1249 /* Number of contacts to be reported. In hybrid mode the first report contains
1250 * total number of contacts and subsequent reports contain 0.
1251 */
1252 uint8_t cContacts = 0;
1253
1254 Assert(pThis->fHasPendingChanges);
1255
1256 if (!pThis->fTouchReporting)
1257 {
1258 pThis->fTouchReporting = true;
1259 pThis->fTouchStateUpdated = false;
1260
1261 /* Update the reporting state with the new current state.
1262 * Also mark all active contacts in reporting state as dirty,
1263 * that is they must be reported to the guest.
1264 */
1265 for (i = 0; i < MT_CONTACT_MAX_COUNT; i++)
1266 {
1267 pRepContact = &pThis->aReportingContactState[i];
1268 pCurContact = &pThis->aCurrentContactState[i];
1269
1270 if (pCurContact->status & MT_CONTACT_S_ACTIVE)
1271 {
1272 if (pCurContact->status & MT_CONTACT_S_REUSED)
1273 {
1274 pCurContact->status &= ~MT_CONTACT_S_REUSED;
1275
1276 /* Keep x,y. Will report lost contact at this point. */
1277 pRepContact->id = pCurContact->oldId;
1278 pRepContact->flags = 0;
1279 pRepContact->status = MT_CONTACT_S_REUSED;
1280 }
1281 else if (pThis->aCurrentContactState[i].status & MT_CONTACT_S_CANCELLED)
1282 {
1283 pCurContact->status &= ~(MT_CONTACT_S_CANCELLED | MT_CONTACT_S_ACTIVE);
1284
1285 /* Keep x,y. Will report lost contact at this point. */
1286 pRepContact->id = pCurContact->id;
1287 pRepContact->flags = 0;
1288 pRepContact->status = 0;
1289 }
1290 else
1291 {
1292 if (pCurContact->flags == 0)
1293 {
1294 pCurContact->status &= ~MT_CONTACT_S_ACTIVE; /* Contact disapeared. */
1295 }
1296
1297 pRepContact->x = pCurContact->x;
1298 pRepContact->y = pCurContact->y;
1299 pRepContact->id = pCurContact->id;
1300 pRepContact->flags = pCurContact->flags;
1301 pRepContact->status = 0;
1302 }
1303
1304 cContacts++;
1305
1306 pRepContact->status |= MT_CONTACT_S_DIRTY;
1307 }
1308 else
1309 {
1310 pRepContact->status = 0;
1311 }
1312 }
1313 }
1314
1315 /* Report current state. */
1316 USBHIDMT_REPORT *p = (USBHIDMT_REPORT *)&pUrb->abData[0];
1317 RT_ZERO(*p);
1318
1319 p->idReport = REPORTID_TOUCH_EVENT;
1320 p->cContacts = cContacts;
1321
1322 uint8_t iReportedContact;
1323 for (iReportedContact = 0; iReportedContact < MT_CONTACTS_PER_REPORT; iReportedContact++)
1324 {
1325 /* Find the next not reported contact. */
1326 pRepContact = usbHidFindMTContact(pThis->aReportingContactState, RT_ELEMENTS(pThis->aReportingContactState),
1327 MT_CONTACT_S_DIRTY, MT_CONTACT_S_DIRTY);
1328
1329 if (!pRepContact)
1330 {
1331 LogRel3(("usbHid: no more touch contacts to report\n"));
1332 break;
1333 }
1334
1335 if (pRepContact->status & MT_CONTACT_S_REUSED)
1336 {
1337 /* Do not clear DIRTY flag for contacts which were reused.
1338 * Because two reports must be generated:
1339 * one for old contact off, and the second for new contact on.
1340 */
1341 pRepContact->status &= ~MT_CONTACT_S_REUSED;
1342 }
1343 else
1344 {
1345 pRepContact->status &= ~MT_CONTACT_S_DIRTY;
1346 }
1347
1348 p->aContacts[iReportedContact].fContact = pRepContact->flags;
1349 p->aContacts[iReportedContact].cContact = pRepContact->id;
1350 p->aContacts[iReportedContact].x = pRepContact->x >> pThis->u8CoordShift;
1351 p->aContacts[iReportedContact].y = pRepContact->y >> pThis->u8CoordShift;
1352 }
1353
1354 p->u32ScanTime = pThis->u32LastTouchScanTime * 10;
1355
1356 Assert(iReportedContact > 0);
1357
1358 /* Reset TouchReporting if all contacts reported. */
1359 pRepContact = usbHidFindMTContact(pThis->aReportingContactState, RT_ELEMENTS(pThis->aReportingContactState),
1360 MT_CONTACT_S_DIRTY, MT_CONTACT_S_DIRTY);
1361
1362 if (!pRepContact)
1363 {
1364 LogRel3(("usbHid: all touch contacts reported\n"));
1365 pThis->fTouchReporting = false;
1366 pThis->fHasPendingChanges = pThis->fTouchStateUpdated;
1367 }
1368 else
1369 {
1370 pThis->fHasPendingChanges = true;
1371 }
1372
1373 LogRel3(("usbHid: reporting touch contact:\n%.*Rhxd\n", sizeof(USBHIDMT_REPORT), p));
1374 return usbHidCompleteOk(pThis, pUrb, sizeof(USBHIDMT_REPORT));
1375}
1376
1377/**
1378 * Sends a state report to the host if there is a pending URB.
1379 */
1380static int usbHidSendReport(PUSBHID pThis)
1381{
1382 PVUSBURB pUrb = usbHidQueueRemoveHead(&pThis->ToHostQueue);
1383
1384 if (pThis->enmMode == USBHIDMODE_MULTI_TOUCH)
1385 {
1386 /* This device uses a different reporting method and fHasPendingChanges maintenance. */
1387 if (pUrb)
1388 return usbHidSendMultiTouchReport(pThis, pUrb);
1389 return VINF_SUCCESS;
1390 }
1391
1392 if (pUrb)
1393 {
1394 PUSBHIDTM_REPORT pReport = (PUSBHIDTM_REPORT)&pUrb->abData[0];
1395 size_t cbCopy;
1396
1397 cbCopy = usbHidFillReport(pReport, &pThis->PtrDelta, pThis->enmMode);
1398 pThis->fHasPendingChanges = false;
1399 return usbHidCompleteOk(pThis, pUrb, cbCopy);
1400 }
1401 else
1402 {
1403 LogRelFlow(("No available URB for USB mouse\n"));
1404 pThis->fHasPendingChanges = true;
1405 }
1406 return VINF_EOF;
1407}
1408
1409/**
1410 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
1411 */
1412static DECLCALLBACK(void *) usbHidMouseQueryInterface(PPDMIBASE pInterface, const char *pszIID)
1413{
1414 PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IBase);
1415 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->Lun0.IBase);
1416 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUSEPORT, &pThis->Lun0.IPort);
1417 return NULL;
1418}
1419
1420/**
1421 * @interface_method_impl{PDMIMOUSEPORT,pfnPutEvent}
1422 */
1423static DECLCALLBACK(int) usbHidMousePutEvent(PPDMIMOUSEPORT pInterface,
1424 int32_t dx, int32_t dy, int32_t dz,
1425 int32_t dw, uint32_t fButtons)
1426{
1427 PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort);
1428 RTCritSectEnter(&pThis->CritSect);
1429
1430 /* Accumulate movement - the events from the front end may arrive
1431 * at a much higher rate than USB can handle.
1432 */
1433 pThis->PtrDelta.u.Relative.fButtons = fButtons;
1434 pThis->PtrDelta.u.Relative.dx += dx;
1435 pThis->PtrDelta.u.Relative.dy += dy;
1436 pThis->PtrDelta.u.Relative.dz -= dz; /* Inverted! */
1437
1438 /* Send a report if possible. */
1439 usbHidSendReport(pThis);
1440
1441 RTCritSectLeave(&pThis->CritSect);
1442 return VINF_SUCCESS;
1443}
1444
1445/**
1446 * @interface_method_impl{PDMIMOUSEPORT,pfnPutEventAbs}
1447 */
1448static DECLCALLBACK(int) usbHidMousePutEventAbs(PPDMIMOUSEPORT pInterface,
1449 uint32_t x, uint32_t y,
1450 int32_t dz, int32_t dw,
1451 uint32_t fButtons)
1452{
1453 PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort);
1454 RTCritSectEnter(&pThis->CritSect);
1455
1456 Assert(pThis->enmMode == USBHIDMODE_ABSOLUTE);
1457
1458 /* Accumulate movement - the events from the front end may arrive
1459 * at a much higher rate than USB can handle. Probably not a real issue
1460 * when only the Z axis is relative (X/Y movement isn't technically
1461 * accumulated and only the last value is used).
1462 */
1463 pThis->PtrDelta.u.Absolute.fButtons = fButtons;
1464 pThis->PtrDelta.u.Absolute.x = x >> pThis->u8CoordShift;
1465 pThis->PtrDelta.u.Absolute.y = y >> pThis->u8CoordShift;
1466
1467 /* Send a report if possible. */
1468 usbHidSendReport(pThis);
1469
1470 RTCritSectLeave(&pThis->CritSect);
1471 return VINF_SUCCESS;
1472}
1473
1474/**
1475 * @interface_method_impl{PDMIMOUSEPORT,pfnPutEventMultiTouch}
1476 */
1477static DECLCALLBACK(int) usbHidMousePutEventMultiTouch(PPDMIMOUSEPORT pInterface,
1478 uint8_t cContacts,
1479 const uint64_t *pau64Contacts,
1480 uint32_t u32ScanTime)
1481{
1482 uint8_t i;
1483 uint8_t j;
1484
1485 /* Make a copy of new contacts */
1486 MTCONTACT *paNewContacts = (MTCONTACT *)RTMemTmpAlloc(sizeof(MTCONTACT) * cContacts);
1487 if (!paNewContacts)
1488 return VERR_NO_MEMORY;
1489
1490 for (i = 0; i < cContacts; i++)
1491 {
1492 uint32_t u32Lo = RT_LO_U32(pau64Contacts[i]);
1493 uint32_t u32Hi = RT_HI_U32(pau64Contacts[i]);
1494 paNewContacts[i].x = (uint16_t)u32Lo;
1495 paNewContacts[i].y = (uint16_t)(u32Lo >> 16);
1496 paNewContacts[i].id = RT_BYTE1(u32Hi);
1497 paNewContacts[i].flags = RT_BYTE2(u32Hi) & (MT_CONTACT_F_IN_CONTACT | MT_CONTACT_F_IN_RANGE);
1498 paNewContacts[i].status = MT_CONTACT_S_DIRTY;
1499 paNewContacts[i].oldId = 0; /* Not used. */
1500 if (paNewContacts[i].flags & MT_CONTACT_F_IN_CONTACT)
1501 {
1502 paNewContacts[i].flags |= MT_CONTACT_F_IN_RANGE;
1503 }
1504 }
1505
1506 PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort);
1507 MTCONTACT *pCurContact = NULL;
1508 MTCONTACT *pNewContact = NULL;
1509
1510 RTCritSectEnter(&pThis->CritSect);
1511
1512 Assert(pThis->enmMode == USBHIDMODE_MULTI_TOUCH);
1513
1514 /* Maintain a state of all current contacts.
1515 * Intr URBs will be completed according to the state.
1516 */
1517
1518 /* Mark all existing contacts as dirty. */
1519 for (i = 0; i < RT_ELEMENTS(pThis->aCurrentContactState); i++)
1520 pThis->aCurrentContactState[i].status |= MT_CONTACT_S_DIRTY;
1521
1522 /* Update existing contacts and mark new contacts. */
1523 for (i = 0; i < cContacts; i++)
1524 {
1525 pNewContact = &paNewContacts[i];
1526
1527 /* Find existing contact with the same id. */
1528 pCurContact = NULL;
1529 for (j = 0; j < RT_ELEMENTS(pThis->aCurrentContactState); j++)
1530 {
1531 if ( (pThis->aCurrentContactState[j].status & MT_CONTACT_S_ACTIVE) != 0
1532 && pThis->aCurrentContactState[j].id == pNewContact->id)
1533 {
1534 pCurContact = &pThis->aCurrentContactState[j];
1535 break;
1536 }
1537 }
1538
1539 if (pCurContact)
1540 {
1541 pNewContact->status &= ~MT_CONTACT_S_DIRTY;
1542
1543 pCurContact->x = pNewContact->x;
1544 pCurContact->y = pNewContact->y;
1545 if (pCurContact->flags == 0) /* Contact disappeared already. */
1546 {
1547 if ((pCurContact->status & MT_CONTACT_S_REUSED) == 0)
1548 {
1549 pCurContact->status |= MT_CONTACT_S_REUSED; /* Report to the guest that the contact not in touch. */
1550 pCurContact->oldId = pCurContact->id;
1551 }
1552 }
1553 pCurContact->flags = pNewContact->flags;
1554 pCurContact->status &= ~MT_CONTACT_S_DIRTY;
1555 }
1556 }
1557
1558 /* Append new contacts (the dirty one in the paNewContacts). */
1559 for (i = 0; i < cContacts; i++)
1560 {
1561 pNewContact = &paNewContacts[i];
1562
1563 if (pNewContact->status & MT_CONTACT_S_DIRTY)
1564 {
1565 /* It is a new contact, copy is to one of not ACTIVE or not updated existing contacts. */
1566 pCurContact = usbHidFindMTContact(pThis->aCurrentContactState, RT_ELEMENTS(pThis->aCurrentContactState),
1567 MT_CONTACT_S_ACTIVE, 0);
1568
1569 if (pCurContact)
1570 {
1571 *pCurContact = *pNewContact;
1572 pCurContact->status = MT_CONTACT_S_ACTIVE; /* Reset status. */
1573 }
1574 else
1575 {
1576 /* Dirty existing contacts can be reused. */
1577 pCurContact = usbHidFindMTContact(pThis->aCurrentContactState, RT_ELEMENTS(pThis->aCurrentContactState),
1578 MT_CONTACT_S_ACTIVE | MT_CONTACT_S_DIRTY,
1579 MT_CONTACT_S_ACTIVE | MT_CONTACT_S_DIRTY);
1580
1581 if (pCurContact)
1582 {
1583 pCurContact->x = pNewContact->x;
1584 pCurContact->y = pNewContact->y;
1585 if ((pCurContact->status & MT_CONTACT_S_REUSED) == 0)
1586 {
1587 pCurContact->status |= MT_CONTACT_S_REUSED; /* Report to the guest that the contact not in touch. */
1588 pCurContact->oldId = pCurContact->id;
1589 }
1590 pCurContact->flags = pNewContact->flags;
1591 pCurContact->status &= ~MT_CONTACT_S_DIRTY;
1592 }
1593 else
1594 {
1595 LogRel3(("usbHid: dropped new contact: %d,%d id %d flags %RX8 status %RX8 oldId %d\n",
1596 pNewContact->x,
1597 pNewContact->y,
1598 pNewContact->id,
1599 pNewContact->flags,
1600 pNewContact->status,
1601 pNewContact->oldId
1602 ));
1603 }
1604 }
1605 }
1606 }
1607
1608 /* Mark still dirty existing contacts as cancelled, because a new set of contacts does not include them. */
1609 for (i = 0; i < RT_ELEMENTS(pThis->aCurrentContactState); i++)
1610 {
1611 pCurContact = &pThis->aCurrentContactState[i];
1612 if (pCurContact->status & MT_CONTACT_S_DIRTY)
1613 {
1614 pCurContact->status |= MT_CONTACT_S_CANCELLED;
1615 pCurContact->status &= ~MT_CONTACT_S_DIRTY;
1616 }
1617 }
1618
1619 pThis->u32LastTouchScanTime = u32ScanTime;
1620
1621 LogRel3(("usbHid: scanTime (ms): %d\n", pThis->u32LastTouchScanTime));
1622 for (i = 0; i < RT_ELEMENTS(pThis->aCurrentContactState); i++)
1623 {
1624 LogRel3(("usbHid: contact state[%d]: %d,%d id %d flags %RX8 status %RX8 oldId %d\n",
1625 i,
1626 pThis->aCurrentContactState[i].x,
1627 pThis->aCurrentContactState[i].y,
1628 pThis->aCurrentContactState[i].id,
1629 pThis->aCurrentContactState[i].flags,
1630 pThis->aCurrentContactState[i].status,
1631 pThis->aCurrentContactState[i].oldId
1632 ));
1633 }
1634
1635 pThis->fTouchStateUpdated = true;
1636 pThis->fHasPendingChanges = true;
1637
1638 /* Send a report if possible. */
1639 usbHidSendReport(pThis);
1640
1641 RTCritSectLeave(&pThis->CritSect);
1642
1643 RTMemTmpFree(paNewContacts);
1644 return VINF_SUCCESS;
1645}
1646
1647/**
1648 * @copydoc PDMUSBREG::pfnUrbReap
1649 */
1650static DECLCALLBACK(PVUSBURB) usbHidUrbReap(PPDMUSBINS pUsbIns, RTMSINTERVAL cMillies)
1651{
1652 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
1653
1654 RTCritSectEnter(&pThis->CritSect);
1655
1656 PVUSBURB pUrb = usbHidQueueRemoveHead(&pThis->DoneQueue);
1657 if (!pUrb && cMillies)
1658 {
1659 /* Wait */
1660 pThis->fHaveDoneQueueWaiter = true;
1661 RTCritSectLeave(&pThis->CritSect);
1662
1663 RTSemEventWait(pThis->hEvtDoneQueue, cMillies);
1664
1665 RTCritSectEnter(&pThis->CritSect);
1666 pThis->fHaveDoneQueueWaiter = false;
1667
1668 pUrb = usbHidQueueRemoveHead(&pThis->DoneQueue);
1669 }
1670
1671 RTCritSectLeave(&pThis->CritSect);
1672
1673 if (pUrb)
1674 LogRelFlow(("usbHidUrbReap/#%u: pUrb=%p:%s\n", pUsbIns->iInstance, pUrb,
1675 pUrb->pszDesc));
1676 return pUrb;
1677}
1678
1679
1680/**
1681 * @copydoc PDMUSBREG::pfnUrbCancel
1682 */
1683static DECLCALLBACK(int) usbHidUrbCancel(PPDMUSBINS pUsbIns, PVUSBURB pUrb)
1684{
1685 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
1686 LogRelFlow(("usbHidUrbCancel/#%u: pUrb=%p:%s\n", pUsbIns->iInstance, pUrb,
1687 pUrb->pszDesc));
1688 RTCritSectEnter(&pThis->CritSect);
1689
1690 /*
1691 * Remove the URB from the to-host queue and move it onto the done queue.
1692 */
1693 if (usbHidQueueRemove(&pThis->ToHostQueue, pUrb))
1694 usbHidLinkDone(pThis, pUrb);
1695
1696 RTCritSectLeave(&pThis->CritSect);
1697 return VINF_SUCCESS;
1698}
1699
1700
1701/**
1702 * Handles request sent to the inbound (device to host) interrupt pipe. This is
1703 * rather different from bulk requests because an interrupt read URB may complete
1704 * after arbitrarily long time.
1705 */
1706static int usbHidHandleIntrDevToHost(PUSBHID pThis, PUSBHIDEP pEp, PVUSBURB pUrb)
1707{
1708 /*
1709 * Stall the request if the pipe is halted.
1710 */
1711 if (RT_UNLIKELY(pEp->fHalted))
1712 return usbHidCompleteStall(pThis, NULL, pUrb, "Halted pipe");
1713
1714 /*
1715 * Deal with the URB according to the state.
1716 */
1717 switch (pThis->enmState)
1718 {
1719 /*
1720 * We've data left to transfer to the host.
1721 */
1722 case USBHIDREQSTATE_DATA_TO_HOST:
1723 {
1724 AssertFailed();
1725 LogRelFlow(("usbHidHandleIntrDevToHost: Entering STATUS\n"));
1726 return usbHidCompleteOk(pThis, pUrb, 0);
1727 }
1728
1729 /*
1730 * Status transfer.
1731 */
1732 case USBHIDREQSTATE_STATUS:
1733 {
1734 AssertFailed();
1735 LogRelFlow(("usbHidHandleIntrDevToHost: Entering READY\n"));
1736 pThis->enmState = USBHIDREQSTATE_READY;
1737 return usbHidCompleteOk(pThis, pUrb, 0);
1738 }
1739
1740 case USBHIDREQSTATE_READY:
1741 usbHidQueueAddTail(&pThis->ToHostQueue, pUrb);
1742 LogRelFlow(("usbHidHandleIntrDevToHost: Added %p:%s to the queue\n",
1743 pUrb, pUrb->pszDesc));
1744 /* If a report is pending, send it right away. */
1745 if (pThis->fHasPendingChanges)
1746 usbHidSendReport(pThis);
1747 return VINF_SUCCESS;
1748
1749 /*
1750 * Bad states, stall.
1751 */
1752 default:
1753 LogRelFlow(("usbHidHandleIntrDevToHost: enmState=%d cbData=%#x\n",
1754 pThis->enmState, pUrb->cbData));
1755 return usbHidCompleteStall(pThis, NULL, pUrb, "Really bad state (D2H)!");
1756 }
1757}
1758
1759#define GET_REPORT 0x01
1760#define GET_IDLE 0x02
1761#define GET_PROTOCOL 0x03
1762#define SET_REPORT 0x09
1763#define SET_IDLE 0x0A
1764#define SET_PROTOCOL 0x0B
1765
1766static uint8_t sau8QASampleBlob[256] =
1767{
1768 0xfc, 0x28, 0xfe, 0x84, 0x40, 0xcb, 0x9a, 0x87,
1769 0x0d, 0xbe, 0x57, 0x3c, 0xb6, 0x70, 0x09, 0x88,
1770 0x07, 0x97, 0x2d, 0x2b, 0xe3, 0x38, 0x34, 0xb6,
1771 0x6c, 0xed, 0xb0, 0xf7, 0xe5, 0x9c, 0xf6, 0xc2,
1772 0x2e, 0x84, 0x1b, 0xe8, 0xb4, 0x51, 0x78, 0x43,
1773 0x1f, 0x28, 0x4b, 0x7c, 0x2d, 0x53, 0xaf, 0xfc,
1774 0x47, 0x70, 0x1b, 0x59, 0x6f, 0x74, 0x43, 0xc4,
1775 0xf3, 0x47, 0x18, 0x53, 0x1a, 0xa2, 0xa1, 0x71,
1776 0xc7, 0x95, 0x0e, 0x31, 0x55, 0x21, 0xd3, 0xb5,
1777 0x1e, 0xe9, 0x0c, 0xba, 0xec, 0xb8, 0x89, 0x19,
1778 0x3e, 0xb3, 0xaf, 0x75, 0x81, 0x9d, 0x53, 0xb9,
1779 0x41, 0x57, 0xf4, 0x6d, 0x39, 0x25, 0x29, 0x7c,
1780 0x87, 0xd9, 0xb4, 0x98, 0x45, 0x7d, 0xa7, 0x26,
1781 0x9c, 0x65, 0x3b, 0x85, 0x68, 0x89, 0xd7, 0x3b,
1782 0xbd, 0xff, 0x14, 0x67, 0xf2, 0x2b, 0xf0, 0x2a,
1783 0x41, 0x54, 0xf0, 0xfd, 0x2c, 0x66, 0x7c, 0xf8,
1784 0xc0, 0x8f, 0x33, 0x13, 0x03, 0xf1, 0xd3, 0xc1,
1785 0x0b, 0x89, 0xd9, 0x1b, 0x62, 0xcd, 0x51, 0xb7,
1786 0x80, 0xb8, 0xaf, 0x3a, 0x10, 0xc1, 0x8a, 0x5b,
1787 0xe8, 0x8a, 0x56, 0xf0, 0x8c, 0xaa, 0xfa, 0x35,
1788 0xe9, 0x42, 0xc4, 0xd8, 0x55, 0xc3, 0x38, 0xcc,
1789 0x2b, 0x53, 0x5c, 0x69, 0x52, 0xd5, 0xc8, 0x73,
1790 0x02, 0x38, 0x7c, 0x73, 0xb6, 0x41, 0xe7, 0xff,
1791 0x05, 0xd8, 0x2b, 0x79, 0x9a, 0xe2, 0x34, 0x60,
1792 0x8f, 0xa3, 0x32, 0x1f, 0x09, 0x78, 0x62, 0xbc,
1793 0x80, 0xe3, 0x0f, 0xbd, 0x65, 0x20, 0x08, 0x13,
1794 0xc1, 0xe2, 0xee, 0x53, 0x2d, 0x86, 0x7e, 0xa7,
1795 0x5a, 0xc5, 0xd3, 0x7d, 0x98, 0xbe, 0x31, 0x48,
1796 0x1f, 0xfb, 0xda, 0xaf, 0xa2, 0xa8, 0x6a, 0x89,
1797 0xd6, 0xbf, 0xf2, 0xd3, 0x32, 0x2a, 0x9a, 0xe4,
1798 0xcf, 0x17, 0xb7, 0xb8, 0xf4, 0xe1, 0x33, 0x08,
1799 0x24, 0x8b, 0xc4, 0x43, 0xa5, 0xe5, 0x24, 0xc2
1800};
1801
1802static int usbHidRequestClass(PUSBHID pThis, PUSBHIDEP pEp, PVUSBURB pUrb)
1803{
1804 PVUSBSETUP pSetup = (PVUSBSETUP)&pUrb->abData[0];
1805
1806 if (pThis->enmMode != USBHIDMODE_MULTI_TOUCH)
1807 {
1808 LogRelFlow(("usbHid: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n",
1809 pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue,
1810 pSetup->wIndex, pSetup->wLength));
1811 return usbHidCompleteStall(pThis, pEp, pUrb, "Unsupported class req");
1812 }
1813
1814 int rc = VINF_SUCCESS;
1815
1816 switch (pSetup->bRequest)
1817 {
1818 case SET_REPORT:
1819 case GET_REPORT:
1820 {
1821 uint8_t u8ReportType = RT_HI_U8(pSetup->wValue);
1822 uint8_t u8ReportID = RT_LO_U8(pSetup->wValue);
1823 LogRelFlow(("usbHid: %s: type %d, ID %d, data\n%.*Rhxd\n",
1824 pSetup->bRequest == GET_REPORT? "GET_REPORT": "SET_REPORT",
1825 u8ReportType, u8ReportID,
1826 pUrb->cbData - sizeof(VUSBSETUP), &pUrb->abData[sizeof(VUSBSETUP)]));
1827 if (pSetup->bRequest == GET_REPORT)
1828 {
1829 uint32_t cbData = 0; /* 0 means that the report is unsupported. */
1830
1831 if (u8ReportType == 1 && u8ReportID == REPORTID_TOUCH_POINTER)
1832 {
1833 USBHIDMT_REPORT_POINTER *p = (USBHIDMT_REPORT_POINTER *)&pUrb->abData[sizeof(VUSBSETUP)];
1834 /* The actual state should be reported here. */
1835 p->idReport = REPORTID_TOUCH_POINTER;
1836 p->fButtons = 0;
1837 p->x = 0;
1838 p->y = 0;
1839 cbData = sizeof(USBHIDMT_REPORT_POINTER);
1840 }
1841 else if (u8ReportType == 1 && u8ReportID == REPORTID_TOUCH_EVENT)
1842 {
1843 USBHIDMT_REPORT *p = (USBHIDMT_REPORT *)&pUrb->abData[sizeof(VUSBSETUP)];
1844 /* The actual state should be reported here. */
1845 RT_ZERO(*p);
1846 p->idReport = REPORTID_TOUCH_EVENT;
1847 cbData = sizeof(USBHIDMT_REPORT);
1848 }
1849 else if (u8ReportType == 3 && u8ReportID == REPORTID_TOUCH_MAX_COUNT)
1850 {
1851 pUrb->abData[sizeof(VUSBSETUP) + 0] = REPORTID_TOUCH_MAX_COUNT;
1852 pUrb->abData[sizeof(VUSBSETUP) + 1] = MT_CONTACT_MAX_COUNT; /* Contact count maximum. */
1853 pUrb->abData[sizeof(VUSBSETUP) + 2] = 0; /* Device identifier */
1854 cbData = 3;
1855 }
1856 else if (u8ReportType == 3 && u8ReportID == REPORTID_TOUCH_QABLOB)
1857 {
1858 uint32_t cbLeft = pUrb->cbData;
1859 pUrb->abData[sizeof(VUSBSETUP) + 0] = REPORTID_TOUCH_QABLOB; /* Report Id. */
1860 memcpy(&pUrb->abData[sizeof(VUSBSETUP) + 1],
1861 sau8QASampleBlob, sizeof(sau8QASampleBlob));
1862 cbData = sizeof(sau8QASampleBlob) + 1;
1863 }
1864 else if (u8ReportType == 3 && u8ReportID == REPORTID_TOUCH_DEVCONFIG)
1865 {
1866 pUrb->abData[sizeof(VUSBSETUP) + 0] = REPORTID_TOUCH_DEVCONFIG;
1867 pUrb->abData[sizeof(VUSBSETUP) + 1] = 2; /* Device mode:
1868 * "HID touch device supporting contact
1869 * identifier and contact count maximum."
1870 */
1871 pUrb->abData[sizeof(VUSBSETUP) + 2] = 0; /* Device identifier */
1872 cbData = 3;
1873 }
1874
1875 if (cbData > 0)
1876 {
1877 rc = usbHidCompleteOk(pThis, pUrb, sizeof(VUSBSETUP) + cbData);
1878 }
1879 else
1880 {
1881 rc = usbHidCompleteStall(pThis, pEp, pUrb, "Unsupported GET_REPORT MT");
1882 }
1883 }
1884 else
1885 {
1886 /* SET_REPORT */
1887 rc = usbHidCompleteOk(pThis, pUrb, pUrb->cbData);
1888 }
1889 } break;
1890 default:
1891 {
1892 LogRelFlow(("usbHid: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n",
1893 pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue,
1894 pSetup->wIndex, pSetup->wLength));
1895 rc = usbHidCompleteStall(pThis, pEp, pUrb, "Unsupported class req MT");
1896 }
1897 }
1898
1899 return rc;
1900}
1901
1902/**
1903 * Handles request sent to the default control pipe.
1904 */
1905static int usbHidHandleDefaultPipe(PUSBHID pThis, PUSBHIDEP pEp, PVUSBURB pUrb)
1906{
1907 PVUSBSETUP pSetup = (PVUSBSETUP)&pUrb->abData[0];
1908 AssertReturn(pUrb->cbData >= sizeof(*pSetup), VERR_VUSB_FAILED_TO_QUEUE_URB);
1909
1910 if ((pSetup->bmRequestType & VUSB_REQ_MASK) == VUSB_REQ_STANDARD)
1911 {
1912 switch (pSetup->bRequest)
1913 {
1914 case VUSB_REQ_GET_DESCRIPTOR:
1915 {
1916 switch (pSetup->bmRequestType)
1917 {
1918 case VUSB_TO_DEVICE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
1919 {
1920 switch (pSetup->wValue >> 8)
1921 {
1922 case VUSB_DT_STRING:
1923 LogRelFlow(("usbHid: GET_DESCRIPTOR DT_STRING wValue=%#x wIndex=%#x\n",
1924 pSetup->wValue, pSetup->wIndex));
1925 break;
1926 default:
1927 LogRelFlow(("usbHid: GET_DESCRIPTOR, huh? wValue=%#x wIndex=%#x\n",
1928 pSetup->wValue, pSetup->wIndex));
1929 break;
1930 }
1931 break;
1932 }
1933
1934 case VUSB_TO_INTERFACE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
1935 {
1936 switch (pSetup->wValue >> 8)
1937 {
1938 uint32_t cbCopy;
1939 uint32_t cbDesc;
1940 const uint8_t *pDesc;
1941
1942 case DT_IF_HID_DESCRIPTOR:
1943 {
1944 switch (pThis->enmMode)
1945 {
1946 case USBHIDMODE_ABSOLUTE:
1947 cbDesc = sizeof(g_UsbHidTIfHidDesc);
1948 pDesc = (const uint8_t *)&g_UsbHidTIfHidDesc;
1949 break;
1950 case USBHIDMODE_RELATIVE:
1951 cbDesc = sizeof(g_UsbHidMIfHidDesc);
1952 pDesc = (const uint8_t *)&g_UsbHidMIfHidDesc;
1953 break;
1954 case USBHIDMODE_MULTI_TOUCH:
1955 cbDesc = sizeof(g_UsbHidMTIfHidDesc);
1956 pDesc = (const uint8_t *)&g_UsbHidMTIfHidDesc;
1957 break;
1958 default:
1959 cbDesc = 0;
1960 pDesc = 0;
1961 break;
1962 }
1963 /* Returned data is written after the setup message. */
1964 cbCopy = pUrb->cbData - sizeof(*pSetup);
1965 cbCopy = RT_MIN(cbCopy, cbDesc);
1966 LogRelFlow(("usbHidMouse: GET_DESCRIPTOR DT_IF_HID_DESCRIPTOR wValue=%#x wIndex=%#x cbCopy=%#x\n",
1967 pSetup->wValue, pSetup->wIndex,
1968 cbCopy));
1969 memcpy(&pUrb->abData[sizeof(*pSetup)], pDesc, cbCopy);
1970 return usbHidCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
1971 }
1972
1973 case DT_IF_HID_REPORT:
1974 {
1975 switch (pThis->enmMode)
1976 {
1977 case USBHIDMODE_ABSOLUTE:
1978 cbDesc = sizeof(g_UsbHidTReportDesc);
1979 pDesc = (const uint8_t *)&g_UsbHidTReportDesc;
1980 break;
1981 case USBHIDMODE_RELATIVE:
1982 cbDesc = sizeof(g_UsbHidMReportDesc);
1983 pDesc = (const uint8_t *)&g_UsbHidMReportDesc;
1984 break;
1985 case USBHIDMODE_MULTI_TOUCH:
1986 cbDesc = sizeof(g_UsbHidMTReportDesc);
1987 pDesc = (const uint8_t *)&g_UsbHidMTReportDesc;
1988 break;
1989 default:
1990 cbDesc = 0;
1991 pDesc = 0;
1992 break;
1993 }
1994 /* Returned data is written after the setup message. */
1995 cbCopy = pUrb->cbData - sizeof(*pSetup);
1996 cbCopy = RT_MIN(cbCopy, cbDesc);
1997 LogRelFlow(("usbHid: GET_DESCRIPTOR DT_IF_HID_REPORT wValue=%#x wIndex=%#x cbCopy=%#x\n",
1998 pSetup->wValue, pSetup->wIndex,
1999 cbCopy));
2000 memcpy(&pUrb->abData[sizeof(*pSetup)], pDesc, cbCopy);
2001 return usbHidCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup));
2002 }
2003
2004 default:
2005 LogRelFlow(("usbHid: GET_DESCRIPTOR, huh? wValue=%#x wIndex=%#x\n",
2006 pSetup->wValue, pSetup->wIndex));
2007 break;
2008 }
2009 break;
2010 }
2011
2012 default:
2013 LogRelFlow(("usbHid: Bad GET_DESCRIPTOR req: bmRequestType=%#x\n",
2014 pSetup->bmRequestType));
2015 return usbHidCompleteStall(pThis, pEp, pUrb, "Bad GET_DESCRIPTOR");
2016 }
2017 break;
2018 }
2019
2020 case VUSB_REQ_GET_STATUS:
2021 {
2022 uint16_t wRet = 0;
2023
2024 if (pSetup->wLength != 2)
2025 {
2026 LogRelFlow(("usbHid: Bad GET_STATUS req: wLength=%#x\n",
2027 pSetup->wLength));
2028 break;
2029 }
2030 Assert(pSetup->wValue == 0);
2031 switch (pSetup->bmRequestType)
2032 {
2033 case VUSB_TO_DEVICE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
2034 {
2035 Assert(pSetup->wIndex == 0);
2036 LogRelFlow(("usbHid: GET_STATUS (device)\n"));
2037 wRet = 0; /* Not self-powered, no remote wakeup. */
2038 memcpy(&pUrb->abData[sizeof(*pSetup)], &wRet, sizeof(wRet));
2039 return usbHidCompleteOk(pThis, pUrb, sizeof(wRet) + sizeof(*pSetup));
2040 }
2041
2042 case VUSB_TO_INTERFACE | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
2043 {
2044 if (pSetup->wIndex == 0)
2045 {
2046 memcpy(&pUrb->abData[sizeof(*pSetup)], &wRet, sizeof(wRet));
2047 return usbHidCompleteOk(pThis, pUrb, sizeof(wRet) + sizeof(*pSetup));
2048 }
2049 else
2050 {
2051 LogRelFlow(("usbHid: GET_STATUS (interface) invalid, wIndex=%#x\n",
2052 pSetup->wIndex));
2053 }
2054 break;
2055 }
2056
2057 case VUSB_TO_ENDPOINT | VUSB_REQ_STANDARD | VUSB_DIR_TO_HOST:
2058 {
2059 if (pSetup->wIndex < RT_ELEMENTS(pThis->aEps))
2060 {
2061 wRet = pThis->aEps[pSetup->wIndex].fHalted ? 1 : 0;
2062 memcpy(&pUrb->abData[sizeof(*pSetup)], &wRet, sizeof(wRet));
2063 return usbHidCompleteOk(pThis, pUrb, sizeof(wRet) + sizeof(*pSetup));
2064 }
2065 else
2066 {
2067 LogRelFlow(("usbHid: GET_STATUS (endpoint) invalid, wIndex=%#x\n",
2068 pSetup->wIndex));
2069 }
2070 break;
2071 }
2072
2073 default:
2074 LogRelFlow(("usbHid: Bad GET_STATUS req: bmRequestType=%#x\n",
2075 pSetup->bmRequestType));
2076 return usbHidCompleteStall(pThis, pEp, pUrb, "Bad GET_STATUS");
2077 }
2078 break;
2079 }
2080
2081 case VUSB_REQ_CLEAR_FEATURE:
2082 break;
2083 }
2084
2085 /** @todo implement this. */
2086 LogRelFlow(("usbHid: Implement standard request: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n",
2087 pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue,
2088 pSetup->wIndex, pSetup->wLength));
2089
2090 usbHidCompleteStall(pThis, pEp, pUrb, "TODO: standard request stuff");
2091 }
2092 else if ((pSetup->bmRequestType & VUSB_REQ_MASK) == VUSB_REQ_CLASS)
2093 {
2094 /* Only VUSB_TO_INTERFACE is allowed. */
2095 if ((pSetup->bmRequestType & VUSB_RECIP_MASK) == VUSB_TO_INTERFACE)
2096 {
2097 return usbHidRequestClass(pThis, pEp, pUrb);
2098 }
2099
2100 LogRelFlow(("usbHid: invalid recipient of class req: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n",
2101 pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue,
2102 pSetup->wIndex, pSetup->wLength));
2103 return usbHidCompleteStall(pThis, pEp, pUrb, "Invalid recip");
2104 }
2105 else
2106 {
2107 LogRelFlow(("usbHid: Unknown control msg: bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n",
2108 pSetup->bmRequestType, pSetup->bRequest, pSetup->wValue,
2109 pSetup->wIndex, pSetup->wLength));
2110 return usbHidCompleteStall(pThis, pEp, pUrb, "Unknown control msg");
2111 }
2112
2113 return VINF_SUCCESS;
2114}
2115
2116
2117/**
2118 * @copydoc PDMUSBREG::pfnUrbQueue
2119 */
2120static DECLCALLBACK(int) usbHidQueue(PPDMUSBINS pUsbIns, PVUSBURB pUrb)
2121{
2122 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
2123 LogRelFlow(("usbHidQueue/#%u: pUrb=%p:%s EndPt=%#x\n", pUsbIns->iInstance,
2124 pUrb, pUrb->pszDesc, pUrb->EndPt));
2125 RTCritSectEnter(&pThis->CritSect);
2126
2127 /*
2128 * Parse on a per end-point basis.
2129 */
2130 int rc;
2131 switch (pUrb->EndPt)
2132 {
2133 case 0:
2134 rc = usbHidHandleDefaultPipe(pThis, &pThis->aEps[0], pUrb);
2135 break;
2136
2137 case 0x81:
2138 AssertFailed();
2139 case 0x01:
2140 rc = usbHidHandleIntrDevToHost(pThis, &pThis->aEps[1], pUrb);
2141 break;
2142
2143 default:
2144 AssertMsgFailed(("EndPt=%d\n", pUrb->EndPt));
2145 rc = VERR_VUSB_FAILED_TO_QUEUE_URB;
2146 break;
2147 }
2148
2149 RTCritSectLeave(&pThis->CritSect);
2150 return rc;
2151}
2152
2153
2154/**
2155 * @copydoc PDMUSBREG::pfnUsbClearHaltedEndpoint
2156 */
2157static DECLCALLBACK(int) usbHidUsbClearHaltedEndpoint(PPDMUSBINS pUsbIns, unsigned uEndpoint)
2158{
2159 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
2160 LogRelFlow(("usbHidUsbClearHaltedEndpoint/#%u: uEndpoint=%#x\n",
2161 pUsbIns->iInstance, uEndpoint));
2162
2163 if ((uEndpoint & ~0x80) < RT_ELEMENTS(pThis->aEps))
2164 {
2165 RTCritSectEnter(&pThis->CritSect);
2166 pThis->aEps[(uEndpoint & ~0x80)].fHalted = false;
2167 RTCritSectLeave(&pThis->CritSect);
2168 }
2169
2170 return VINF_SUCCESS;
2171}
2172
2173
2174/**
2175 * @copydoc PDMUSBREG::pfnUsbSetInterface
2176 */
2177static DECLCALLBACK(int) usbHidUsbSetInterface(PPDMUSBINS pUsbIns, uint8_t bInterfaceNumber, uint8_t bAlternateSetting)
2178{
2179 LogRelFlow(("usbHidUsbSetInterface/#%u: bInterfaceNumber=%u bAlternateSetting=%u\n",
2180 pUsbIns->iInstance, bInterfaceNumber, bAlternateSetting));
2181 Assert(bAlternateSetting == 0);
2182 return VINF_SUCCESS;
2183}
2184
2185
2186/**
2187 * @copydoc PDMUSBREG::pfnUsbSetConfiguration
2188 */
2189static DECLCALLBACK(int) usbHidUsbSetConfiguration(PPDMUSBINS pUsbIns, uint8_t bConfigurationValue,
2190 const void *pvOldCfgDesc, const void *pvOldIfState, const void *pvNewCfgDesc)
2191{
2192 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
2193 LogRelFlow(("usbHidUsbSetConfiguration/#%u: bConfigurationValue=%u\n",
2194 pUsbIns->iInstance, bConfigurationValue));
2195 Assert(bConfigurationValue == 1);
2196 RTCritSectEnter(&pThis->CritSect);
2197
2198 /*
2199 * If the same config is applied more than once, it's a kind of reset.
2200 */
2201 if (pThis->bConfigurationValue == bConfigurationValue)
2202 usbHidResetWorker(pThis, NULL, true /*fSetConfig*/); /** @todo figure out the exact difference */
2203 pThis->bConfigurationValue = bConfigurationValue;
2204
2205 /*
2206 * Set received event type to absolute or relative.
2207 */
2208 pThis->Lun0.pDrv->pfnReportModes(pThis->Lun0.pDrv,
2209 pThis->enmMode == USBHIDMODE_RELATIVE,
2210 pThis->enmMode == USBHIDMODE_ABSOLUTE,
2211 pThis->enmMode == USBHIDMODE_MULTI_TOUCH);
2212
2213 RTCritSectLeave(&pThis->CritSect);
2214 return VINF_SUCCESS;
2215}
2216
2217
2218/**
2219 * @copydoc PDMUSBREG::pfnUsbGetDescriptorCache
2220 */
2221static DECLCALLBACK(PCPDMUSBDESCCACHE) usbHidUsbGetDescriptorCache(PPDMUSBINS pUsbIns)
2222{
2223 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
2224 LogRelFlow(("usbHidUsbGetDescriptorCache/#%u:\n", pUsbIns->iInstance));
2225 switch (pThis->enmMode)
2226 {
2227 case USBHIDMODE_ABSOLUTE:
2228 return &g_UsbHidTDescCache;
2229 case USBHIDMODE_RELATIVE:
2230 return &g_UsbHidMDescCache;
2231 case USBHIDMODE_MULTI_TOUCH:
2232 return &g_UsbHidMTDescCache;
2233 default:
2234 return NULL;
2235 }
2236}
2237
2238
2239/**
2240 * @copydoc PDMUSBREG::pfnUsbReset
2241 */
2242static DECLCALLBACK(int) usbHidUsbReset(PPDMUSBINS pUsbIns, bool fResetOnLinux)
2243{
2244 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
2245 LogRelFlow(("usbHidUsbReset/#%u:\n", pUsbIns->iInstance));
2246 RTCritSectEnter(&pThis->CritSect);
2247
2248 int rc = usbHidResetWorker(pThis, NULL, false /*fSetConfig*/);
2249
2250 RTCritSectLeave(&pThis->CritSect);
2251 return rc;
2252}
2253
2254
2255/**
2256 * @copydoc PDMUSBREG::pfnDestruct
2257 */
2258static void usbHidDestruct(PPDMUSBINS pUsbIns)
2259{
2260 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
2261 LogRelFlow(("usbHidDestruct/#%u:\n", pUsbIns->iInstance));
2262
2263 if (RTCritSectIsInitialized(&pThis->CritSect))
2264 {
2265 RTCritSectEnter(&pThis->CritSect);
2266 RTCritSectLeave(&pThis->CritSect);
2267 RTCritSectDelete(&pThis->CritSect);
2268 }
2269
2270 if (pThis->hEvtDoneQueue != NIL_RTSEMEVENT)
2271 {
2272 RTSemEventDestroy(pThis->hEvtDoneQueue);
2273 pThis->hEvtDoneQueue = NIL_RTSEMEVENT;
2274 }
2275}
2276
2277
2278/**
2279 * @copydoc PDMUSBREG::pfnConstruct
2280 */
2281static DECLCALLBACK(int) usbHidConstruct(PPDMUSBINS pUsbIns, int iInstance, PCFGMNODE pCfg, PCFGMNODE pCfgGlobal)
2282{
2283 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
2284 char szMode[64];
2285 LogRelFlow(("usbHidConstruct/#%u:\n", iInstance));
2286
2287 /*
2288 * Perform the basic structure initialization first so the destructor
2289 * will not misbehave.
2290 */
2291 pThis->pUsbIns = pUsbIns;
2292 pThis->hEvtDoneQueue = NIL_RTSEMEVENT;
2293 usbHidQueueInit(&pThis->ToHostQueue);
2294 usbHidQueueInit(&pThis->DoneQueue);
2295
2296 int rc = RTCritSectInit(&pThis->CritSect);
2297 AssertRCReturn(rc, rc);
2298
2299 rc = RTSemEventCreate(&pThis->hEvtDoneQueue);
2300 AssertRCReturn(rc, rc);
2301
2302 /*
2303 * Validate and read the configuration.
2304 */
2305 rc = CFGMR3ValidateConfig(pCfg, "/", "Mode|CoordShift", "Config", "UsbHid", iInstance);
2306 if (RT_FAILURE(rc))
2307 return rc;
2308 rc = CFGMR3QueryStringDef(pCfg, "Mode", szMode, sizeof(szMode), "relative");
2309 if (RT_FAILURE(rc))
2310 return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("HID failed to query settings"));
2311 if (!RTStrCmp(szMode, "relative"))
2312 pThis->enmMode = USBHIDMODE_RELATIVE;
2313 else if (!RTStrCmp(szMode, "absolute"))
2314 pThis->enmMode = USBHIDMODE_ABSOLUTE;
2315 else if (!RTStrCmp(szMode, "multitouch"))
2316 pThis->enmMode = USBHIDMODE_MULTI_TOUCH;
2317 else
2318 return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS,
2319 N_("Invalid HID device mode"));
2320
2321 LogRelFlow(("usbHidConstruct/#%u: mode '%s'\n", iInstance, szMode));
2322
2323 pThis->Lun0.IBase.pfnQueryInterface = usbHidMouseQueryInterface;
2324 pThis->Lun0.IPort.pfnPutEvent = usbHidMousePutEvent;
2325 pThis->Lun0.IPort.pfnPutEventAbs = usbHidMousePutEventAbs;
2326 pThis->Lun0.IPort.pfnPutEventMultiTouch = usbHidMousePutEventMultiTouch;
2327
2328 /*
2329 * Attach the mouse driver.
2330 */
2331 rc = PDMUsbHlpDriverAttach(pUsbIns, 0 /*iLun*/, &pThis->Lun0.IBase, &pThis->Lun0.pDrvBase, "Mouse Port");
2332 if (RT_FAILURE(rc))
2333 return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("HID failed to attach mouse driver"));
2334
2335 pThis->Lun0.pDrv = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pDrvBase, PDMIMOUSECONNECTOR);
2336 if (!pThis->Lun0.pDrv)
2337 return PDMUsbHlpVMSetError(pUsbIns, VERR_PDM_MISSING_INTERFACE, RT_SRC_POS, N_("HID failed to query mouse interface"));
2338
2339 rc = CFGMR3QueryU8Def(pCfg, "CoordShift", &pThis->u8CoordShift, 1);
2340 if (RT_FAILURE(rc))
2341 return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("HID failed to query shift factor"));
2342
2343 return VINF_SUCCESS;
2344}
2345
2346
2347/**
2348 * The USB Human Interface Device (HID) Mouse registration record.
2349 */
2350const PDMUSBREG g_UsbHidMou =
2351{
2352 /* u32Version */
2353 PDM_USBREG_VERSION,
2354 /* szName */
2355 "HidMouse",
2356 /* pszDescription */
2357 "USB HID Mouse.",
2358 /* fFlags */
2359 0,
2360 /* cMaxInstances */
2361 ~0U,
2362 /* cbInstance */
2363 sizeof(USBHID),
2364 /* pfnConstruct */
2365 usbHidConstruct,
2366 /* pfnDestruct */
2367 usbHidDestruct,
2368 /* pfnVMInitComplete */
2369 NULL,
2370 /* pfnVMPowerOn */
2371 NULL,
2372 /* pfnVMReset */
2373 NULL,
2374 /* pfnVMSuspend */
2375 NULL,
2376 /* pfnVMResume */
2377 NULL,
2378 /* pfnVMPowerOff */
2379 NULL,
2380 /* pfnHotPlugged */
2381 NULL,
2382 /* pfnHotUnplugged */
2383 NULL,
2384 /* pfnDriverAttach */
2385 NULL,
2386 /* pfnDriverDetach */
2387 NULL,
2388 /* pfnQueryInterface */
2389 NULL,
2390 /* pfnUsbReset */
2391 usbHidUsbReset,
2392 /* pfnUsbGetDescriptorCache */
2393 usbHidUsbGetDescriptorCache,
2394 /* pfnUsbSetConfiguration */
2395 usbHidUsbSetConfiguration,
2396 /* pfnUsbSetInterface */
2397 usbHidUsbSetInterface,
2398 /* pfnUsbClearHaltedEndpoint */
2399 usbHidUsbClearHaltedEndpoint,
2400 /* pfnUrbNew */
2401 NULL/*usbHidUrbNew*/,
2402 /* pfnUrbQueue */
2403 usbHidQueue,
2404 /* pfnUrbCancel */
2405 usbHidUrbCancel,
2406 /* pfnUrbReap */
2407 usbHidUrbReap,
2408 /* u32TheEnd */
2409 PDM_USBREG_VERSION
2410};
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