VirtualBox

source: vbox/trunk/src/VBox/Devices/Input/testcase/tstUsbMouse.cpp@ 82968

Last change on this file since 82968 was 82968, checked in by vboxsync, 5 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.3 KB
Line 
1/* $Id: tstUsbMouse.cpp 82968 2020-02-04 10:35:17Z vboxsync $ */
2/** @file
3 * tstUsbMouse.cpp - testcase USB mouse and tablet devices.
4 */
5
6/*
7 * Copyright (C) 2013-2020 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/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#include "VBoxDD.h"
23#include <VBox/vmm/pdmdrv.h>
24#include <iprt/mem.h>
25#include <iprt/rand.h>
26#include <iprt/stream.h>
27#include <iprt/test.h>
28#include <iprt/uuid.h>
29
30
31/*********************************************************************************************************************************
32* Structures and Typedefs *
33*********************************************************************************************************************************/
34/** Test mouse driver structure. */
35typedef struct DRVTSTMOUSE
36{
37 /** The USBHID structure. */
38 struct USBHID *pUsbHid;
39 /** The base interface for the mouse driver. */
40 PDMIBASE IBase;
41 /** Our mouse connector interface. */
42 PDMIMOUSECONNECTOR IConnector;
43 /** The base interface of the attached mouse port. */
44 PPDMIBASE pDrvBase;
45 /** The mouse port interface of the attached mouse port. */
46 PPDMIMOUSEPORT pDrv;
47 /** Is relative mode currently supported? */
48 bool fRel;
49 /** Is absolute mode currently supported? */
50 bool fAbs;
51 /** Is multi-touch mode currently supported? */
52 bool fMT;
53} DRVTSTMOUSE;
54typedef DRVTSTMOUSE *PDRVTSTMOUSE;
55
56
57/*********************************************************************************************************************************
58* Global Variables *
59*********************************************************************************************************************************/
60static PDMUSBHLP g_tstUsbHlp;
61/** Global mouse driver variable.
62 * @todo To be improved some time. */
63static DRVTSTMOUSE g_drvTstMouse;
64
65
66/** @interface_method_impl{PDMUSBHLPR3,pfnVMSetErrorV} */
67static DECLCALLBACK(int) tstVMSetErrorV(PPDMUSBINS pUsbIns, int rc,
68 RT_SRC_POS_DECL, const char *pszFormat,
69 va_list va)
70{
71 RT_NOREF(pUsbIns);
72 RTPrintf("Error: %s:%u:%s:", RT_SRC_POS_ARGS);
73 RTPrintfV(pszFormat, va);
74 return rc;
75}
76
77/** @interface_method_impl{PDMUSBHLPR3,pfnDriverAttach} */
78/** @todo We currently just take the driver interface from the global
79 * variable. This is sufficient for a unit test but still a bit sad. */
80static DECLCALLBACK(int) tstDriverAttach(PPDMUSBINS pUsbIns, RTUINT iLun, PPDMIBASE pBaseInterface,
81 PPDMIBASE *ppBaseInterface, const char *pszDesc)
82{
83 RT_NOREF3(pUsbIns, iLun, pszDesc);
84 g_drvTstMouse.pDrvBase = pBaseInterface;
85 g_drvTstMouse.pDrv = PDMIBASE_QUERY_INTERFACE(pBaseInterface, PDMIMOUSEPORT);
86 *ppBaseInterface = &g_drvTstMouse.IBase;
87 return VINF_SUCCESS;
88}
89
90
91/**
92 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
93 */
94static DECLCALLBACK(void *) tstMouseQueryInterface(PPDMIBASE pInterface,
95 const char *pszIID)
96{
97 PDRVTSTMOUSE pUsbIns = RT_FROM_MEMBER(pInterface, DRVTSTMOUSE, IBase);
98 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pUsbIns->IBase);
99 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUSECONNECTOR, &pUsbIns->IConnector);
100 return NULL;
101}
102
103
104/**
105 * @interface_method_impl{PDMIMOUSECONNECTOR,pfnReportModes}
106 */
107static DECLCALLBACK(void) tstMouseReportModes(PPDMIMOUSECONNECTOR pInterface,
108 bool fRel, bool fAbs, bool fMT)
109{
110 PDRVTSTMOUSE pDrv = RT_FROM_MEMBER(pInterface, DRVTSTMOUSE, IConnector);
111 pDrv->fRel = fRel;
112 pDrv->fAbs = fAbs;
113 pDrv->fMT = fMT;
114}
115
116
117static int tstMouseConstruct(RTTEST hTest, int iInstance, const char *pcszMode,
118 uint8_t u8CoordShift, PPDMUSBINS *ppThis,
119 uint32_t uInstanceVersion = PDM_USBINS_VERSION)
120{
121 size_t cbUsbIns = RT_UOFFSETOF(PDMUSBINS, achInstanceData) + g_UsbHidMou.cbInstance;
122 PPDMUSBINS pUsbIns;
123 int rc = RTTestGuardedAlloc(hTest, cbUsbIns, 1, RTRandU32Ex(0, 1) != 0 /*fHead*/, (void **)&pUsbIns);
124 if (RT_SUCCESS(rc))
125 {
126 RT_BZERO(pUsbIns, cbUsbIns);
127
128 PCFGMNODE pCfg = CFGMR3CreateTree(NULL);
129 if (pCfg)
130 {
131 rc = CFGMR3InsertString(pCfg, "Mode", pcszMode);
132 if (RT_SUCCESS(rc))
133 rc = CFGMR3InsertInteger(pCfg, "CoordShift", u8CoordShift);
134 if (RT_SUCCESS(rc))
135 {
136 g_drvTstMouse.pDrv = NULL;
137 g_drvTstMouse.pDrvBase = NULL;
138 pUsbIns->u32Version = uInstanceVersion;
139 pUsbIns->iInstance = iInstance;
140 pUsbIns->pHlpR3 = &g_tstUsbHlp;
141 pUsbIns->pvInstanceDataR3 = pUsbIns->achInstanceData;
142 rc = g_UsbHidMou.pfnConstruct(pUsbIns, iInstance, pCfg, NULL);
143 if (RT_SUCCESS(rc))
144 {
145 *ppThis = pUsbIns;
146 return rc;
147 }
148 }
149 /* Failure */
150 CFGMR3DestroyTree(pCfg);
151 }
152 }
153 RTTestGuardedFree(hTest, pUsbIns);
154 return rc;
155}
156
157
158static void testConstructAndDestruct(RTTEST hTest)
159{
160 RTTestSub(hTest, "simple construction and destruction");
161
162 /*
163 * Normal check first.
164 */
165 PPDMUSBINS pUsbIns = NULL;
166 RTTEST_CHECK_RC(hTest, tstMouseConstruct(hTest, 0, "relative", 1, &pUsbIns), VINF_SUCCESS);
167 if (pUsbIns)
168 {
169 g_UsbHidMou.pfnDestruct(pUsbIns);
170 RTTestGuardedFree(hTest, pUsbIns);
171 }
172
173 /*
174 * Modify the dev hlp version.
175 */
176 static struct
177 {
178 int rc;
179 uint32_t uInsVersion;
180 uint32_t uHlpVersion;
181 } const s_aVersionTests[] =
182 {
183 { VERR_PDM_USBHLPR3_VERSION_MISMATCH, PDM_USBINS_VERSION, 0 },
184 { VERR_PDM_USBHLPR3_VERSION_MISMATCH, PDM_USBINS_VERSION, PDM_USBHLP_VERSION - PDM_VERSION_MAKE(0, 1, 0) },
185 { VERR_PDM_USBHLPR3_VERSION_MISMATCH, PDM_USBINS_VERSION, PDM_USBHLP_VERSION + PDM_VERSION_MAKE(0, 1, 0) },
186 { VERR_PDM_USBHLPR3_VERSION_MISMATCH, PDM_USBINS_VERSION, PDM_USBHLP_VERSION + PDM_VERSION_MAKE(0, 1, 1) },
187 { VERR_PDM_USBHLPR3_VERSION_MISMATCH, PDM_USBINS_VERSION, PDM_USBHLP_VERSION + PDM_VERSION_MAKE(1, 0, 0) },
188 { VERR_PDM_USBHLPR3_VERSION_MISMATCH, PDM_USBINS_VERSION, PDM_USBHLP_VERSION - PDM_VERSION_MAKE(1, 0, 0) },
189 { VINF_SUCCESS, PDM_USBINS_VERSION, PDM_USBHLP_VERSION + PDM_VERSION_MAKE(0, 0, 1) },
190 { VERR_PDM_USBINS_VERSION_MISMATCH, PDM_USBINS_VERSION - PDM_VERSION_MAKE(0, 1, 0), PDM_USBHLP_VERSION },
191 { VERR_PDM_USBINS_VERSION_MISMATCH, PDM_USBINS_VERSION + PDM_VERSION_MAKE(0, 1, 0), PDM_USBHLP_VERSION },
192 { VERR_PDM_USBINS_VERSION_MISMATCH, PDM_USBINS_VERSION + PDM_VERSION_MAKE(0, 1, 1), PDM_USBHLP_VERSION },
193 { VERR_PDM_USBINS_VERSION_MISMATCH, PDM_USBINS_VERSION + PDM_VERSION_MAKE(1, 0, 0), PDM_USBHLP_VERSION },
194 { VERR_PDM_USBINS_VERSION_MISMATCH, PDM_USBINS_VERSION - PDM_VERSION_MAKE(1, 0, 0), PDM_USBHLP_VERSION },
195 { VINF_SUCCESS, PDM_USBINS_VERSION + PDM_VERSION_MAKE(0, 0, 1), PDM_USBHLP_VERSION },
196 { VINF_SUCCESS,
197 PDM_USBINS_VERSION + PDM_VERSION_MAKE(0, 0, 1), PDM_USBHLP_VERSION + PDM_VERSION_MAKE(0, 0, 1) },
198 };
199 bool const fSavedMayPanic = RTAssertSetMayPanic(false);
200 bool const fSavedQuiet = RTAssertSetQuiet(true);
201 for (unsigned i = 0; i < RT_ELEMENTS(s_aVersionTests); i++)
202 {
203 g_tstUsbHlp.u32Version = g_tstUsbHlp.u32TheEnd = s_aVersionTests[i].uHlpVersion;
204 pUsbIns = NULL;
205 RTTEST_CHECK_RC(hTest, tstMouseConstruct(hTest, 0, "relative", 1, &pUsbIns, s_aVersionTests[i].uInsVersion),
206 s_aVersionTests[i].rc);
207 if (pUsbIns)
208 RTTestGuardedFree(hTest, pUsbIns);
209 }
210 RTAssertSetMayPanic(fSavedMayPanic);
211 RTAssertSetQuiet(fSavedQuiet);
212
213 g_tstUsbHlp.u32Version = g_tstUsbHlp.u32TheEnd = PDM_USBHLP_VERSION;
214}
215
216
217static void testSendPositionRel(RTTEST hTest)
218{
219 PPDMUSBINS pUsbIns = NULL;
220 VUSBURB Urb;
221 RTTestSub(hTest, "sending a relative position event");
222 int rc = tstMouseConstruct(hTest, 0, "relative", 1, &pUsbIns);
223 RT_ZERO(Urb);
224 if (RT_SUCCESS(rc))
225 rc = g_UsbHidMou.pfnUsbReset(pUsbIns, false);
226 if (RT_SUCCESS(rc) && !g_drvTstMouse.pDrv)
227 rc = VERR_PDM_MISSING_INTERFACE;
228 RTTEST_CHECK_RC_OK(hTest, rc);
229 if (RT_SUCCESS(rc))
230 {
231 g_drvTstMouse.pDrv->pfnPutEvent(g_drvTstMouse.pDrv, 123, -16, 1, -1, 3);
232 Urb.EndPt = 0x01;
233 rc = g_UsbHidMou.pfnUrbQueue(pUsbIns, &Urb);
234 }
235 if (RT_SUCCESS(rc))
236 {
237 PVUSBURB pUrb = g_UsbHidMou.pfnUrbReap(pUsbIns, 0);
238 if (pUrb)
239 {
240 if (pUrb == &Urb)
241 {
242 if ( Urb.abData[0] != 3 /* Buttons */
243 || Urb.abData[1] != 123 /* x */
244 || Urb.abData[2] != 240 /* 256 - y */
245 || Urb.abData[3] != 255 /* z */)
246 rc = VERR_GENERAL_FAILURE;
247 }
248 else
249 rc = VERR_GENERAL_FAILURE;
250 }
251 else
252 rc = VERR_GENERAL_FAILURE;
253 }
254 RTTEST_CHECK_RC_OK(hTest, rc);
255 if (pUsbIns)
256 {
257 g_UsbHidMou.pfnDestruct(pUsbIns);
258 RTTestGuardedFree(hTest, pUsbIns);
259 }
260}
261
262
263static void testSendPositionAbs(RTTEST hTest)
264{
265 PPDMUSBINS pUsbIns = NULL;
266 VUSBURB Urb;
267 RTTestSub(hTest, "sending an absolute position event");
268 int rc = tstMouseConstruct(hTest, 0, "absolute", 1, &pUsbIns);
269 RT_ZERO(Urb);
270 if (RT_SUCCESS(rc))
271 {
272 rc = g_UsbHidMou.pfnUsbReset(pUsbIns, false);
273 }
274 if (RT_SUCCESS(rc))
275 {
276 if (g_drvTstMouse.pDrv)
277 g_drvTstMouse.pDrv->pfnPutEventAbs(g_drvTstMouse.pDrv, 300, 200, 1,
278 3, 3);
279 else
280 rc = VERR_PDM_MISSING_INTERFACE;
281 }
282 if (RT_SUCCESS(rc))
283 {
284 Urb.EndPt = 0x01;
285 rc = g_UsbHidMou.pfnUrbQueue(pUsbIns, &Urb);
286 }
287 if (RT_SUCCESS(rc))
288 {
289 PVUSBURB pUrb = g_UsbHidMou.pfnUrbReap(pUsbIns, 0);
290 if (pUrb)
291 {
292 if (pUrb == &Urb)
293 {
294 if ( Urb.abData[0] != 3 /* Buttons */
295 || (int8_t)Urb.abData[1] != -1 /* dz */
296 || (int8_t)Urb.abData[2] != -3 /* dw */
297 || *(uint16_t *)&Urb.abData[4] != 150 /* x >> 1 */
298 || *(uint16_t *)&Urb.abData[6] != 100 /* y >> 1 */)
299 rc = VERR_GENERAL_FAILURE;
300 }
301 else
302 rc = VERR_GENERAL_FAILURE;
303 }
304 else
305 rc = VERR_GENERAL_FAILURE;
306 }
307 RTTEST_CHECK_RC_OK(hTest, rc);
308 if (pUsbIns)
309 {
310 g_UsbHidMou.pfnDestruct(pUsbIns);
311 RTTestGuardedFree(hTest, pUsbIns);
312 }
313}
314
315#if 0
316/** @todo PDM interface was updated. This is not working anymore. */
317static void testSendPositionMT(RTTEST hTest)
318{
319 PPDMUSBINS pUsbIns = NULL;
320 VUSBURB Urb;
321 RTTestSub(hTest, "sending a multi-touch position event");
322 int rc = tstMouseConstruct(hTest, 0, "multitouch", 1, &pUsbIns);
323 RT_ZERO(Urb);
324 if (RT_SUCCESS(rc))
325 {
326 rc = g_UsbHidMou.pfnUsbReset(pUsbIns, false);
327 }
328 if (RT_SUCCESS(rc))
329 {
330 if (g_drvTstMouse.pDrv)
331 g_drvTstMouse.pDrv->pfnPutEventMT(g_drvTstMouse.pDrv, 300, 200, 2,
332 3);
333 else
334 rc = VERR_PDM_MISSING_INTERFACE;
335 }
336 if (RT_SUCCESS(rc))
337 {
338 Urb.EndPt = 0x01;
339 rc = g_UsbHidMou.pfnUrbQueue(pUsbIns, &Urb);
340 }
341 if (RT_SUCCESS(rc))
342 {
343 PVUSBURB pUrb = g_UsbHidMou.pfnUrbReap(pUsbIns, 0);
344 if (pUrb)
345 {
346 if (pUrb == &Urb)
347 {
348 if ( Urb.abData[0] != 1 /* Report ID */
349 || Urb.abData[1] != 3 /* Contact flags */
350 || *(uint16_t *)&Urb.abData[2] != 150 /* x >> 1 */
351 || *(uint16_t *)&Urb.abData[4] != 100 /* y >> 1 */
352 || Urb.abData[6] != 2 /* Contact number */)
353 rc = VERR_GENERAL_FAILURE;
354 }
355 else
356 rc = VERR_GENERAL_FAILURE;
357 }
358 else
359 rc = VERR_GENERAL_FAILURE;
360 }
361 RTTEST_CHECK_RC_OK(hTest, rc);
362 if (pUsbIns)
363 {
364 g_UsbHidMou.pfnDestruct(pUsbIns);
365 RTTestGuardedFree(hTest, pUsbIns);
366 }
367}
368#endif
369
370int main()
371{
372 /*
373 * Init the runtime, test and say hello.
374 */
375 RTTEST hTest;
376 int rc = RTTestInitAndCreate("tstUsbMouse", &hTest);
377 if (rc)
378 return rc;
379 RTTestBanner(hTest);
380 /* Set up our faked PDMUSBHLP interface. */
381 g_tstUsbHlp.u32Version = PDM_USBHLP_VERSION;
382 g_tstUsbHlp.pfnVMSetErrorV = tstVMSetErrorV;
383 g_tstUsbHlp.pfnDriverAttach = tstDriverAttach;
384 g_tstUsbHlp.u32TheEnd = PDM_USBHLP_VERSION;
385 /* Set up our global mouse driver */
386 g_drvTstMouse.IBase.pfnQueryInterface = tstMouseQueryInterface;
387 g_drvTstMouse.IConnector.pfnReportModes = tstMouseReportModes;
388
389 /*
390 * Run the tests.
391 */
392 testConstructAndDestruct(hTest);
393 testSendPositionRel(hTest);
394 testSendPositionAbs(hTest);
395 /* testSendPositionMT(hTest); */
396 return RTTestSummaryAndDestroy(hTest);
397}
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