VirtualBox

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

Last change on this file since 70607 was 69500, checked in by vboxsync, 7 years ago

*: scm --update-copyright-year

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