summaryrefslogtreecommitdiff
path: root/src/VBox/Devices/Input/testcase
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/Input/testcase')
-rw-r--r--src/VBox/Devices/Input/testcase/Makefile.kmk34
-rw-r--r--src/VBox/Devices/Input/testcase/tstUsbMouse.cpp329
2 files changed, 363 insertions, 0 deletions
diff --git a/src/VBox/Devices/Input/testcase/Makefile.kmk b/src/VBox/Devices/Input/testcase/Makefile.kmk
new file mode 100644
index 00000000..48e59399
--- /dev/null
+++ b/src/VBox/Devices/Input/testcase/Makefile.kmk
@@ -0,0 +1,34 @@
+# $Id: Makefile.kmk $
+## @file
+# Sub-makefile for input test cases.
+#
+
+#
+# Copyright (C) 2013 Oracle Corporation
+#
+# This file is part of VirtualBox Open Source Edition (OSE), as
+# available from http://www.virtualbox.org. This file is free software;
+# you can redistribute it and/or modify it under the terms of the GNU
+# General Public License (GPL) as published by the Free Software
+# Foundation, in version 2 as it comes in the "COPYING" file of the
+# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+#
+
+SUB_DEPTH = ../../../..
+include $(KBUILD_PATH)/subheader.kmk
+
+if defined(VBOX_WITH_TESTCASES) && !defined(VBOX_ONLY_ADDITIONS) && !defined(VBOX_ONLY_SDK)
+ PROGRAMS += tstUsbMouse
+endif
+tstUsbMouse_TEMPLATE = VBOXR3TSTEXE
+tstUsbMouse_DEFS = VBOX_WITH_VUSB
+tstUsbMouse_INCS = \
+ ../../build
+tstUsbMouse_LIBS = $(LIB_VMM)
+tstUsbMouse_SOURCES = \
+ tstUsbMouse.cpp \
+ ../UsbMouse.cpp
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
diff --git a/src/VBox/Devices/Input/testcase/tstUsbMouse.cpp b/src/VBox/Devices/Input/testcase/tstUsbMouse.cpp
new file mode 100644
index 00000000..8b733c4b
--- /dev/null
+++ b/src/VBox/Devices/Input/testcase/tstUsbMouse.cpp
@@ -0,0 +1,329 @@
+/* $Id: tstUsbMouse.cpp $ */
+/** @file
+ * tstUsbMouse.cpp - testcase USB mouse and tablet devices.
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#include "VBoxDD.h"
+#include <VBox/vmm/pdmdrv.h>
+#include <iprt/alloc.h>
+#include <iprt/stream.h>
+#include <iprt/test.h>
+#include <iprt/uuid.h>
+
+/** Test mouse driver structure. */
+typedef struct DRVTSTMOUSE
+{
+ /** The USBHID structure. */
+ struct USBHID *pUsbHid;
+ /** The base interface for the mouse driver. */
+ PDMIBASE IBase;
+ /** Our mouse connector interface. */
+ PDMIMOUSECONNECTOR IConnector;
+ /** The base interface of the attached mouse port. */
+ PPDMIBASE pDrvBase;
+ /** The mouse port interface of the attached mouse port. */
+ PPDMIMOUSEPORT pDrv;
+ /** Is relative mode currently supported? */
+ bool fRel;
+ /** Is absolute mode currently supported? */
+ bool fAbs;
+ /** Is multi-touch mode currently supported? */
+ bool fMT;
+} DRVTSTMOUSE, *PDRVTSTMOUSE;
+
+
+/** Global mouse driver variable.
+ * @todo To be improved some time. */
+static DRVTSTMOUSE s_drvTstMouse;
+
+
+/** @interface_method_impl{PDMUSBHLPR3,pfnVMSetErrorV} */
+static DECLCALLBACK(int) tstVMSetErrorV(PPDMUSBINS pUsbIns, int rc,
+ RT_SRC_POS_DECL, const char *pszFormat,
+ va_list va)
+{
+ NOREF(pUsbIns);
+ RTPrintf("Error: %s:%u:%s:", RT_SRC_POS_ARGS);
+ RTPrintfV(pszFormat, va);
+ return rc;
+}
+
+/** @interface_method_impl{PDMUSBHLPR3,pfnDriverAttach} */
+/** @todo We currently just take the driver interface from the global
+ * variable. This is sufficient for a unit test but still a bit sad. */
+static DECLCALLBACK(int) tstDriverAttach(PPDMUSBINS pUsbIns, RTUINT iLun,
+ PPDMIBASE pBaseInterface,
+ PPDMIBASE *ppBaseInterface,
+ const char *pszDesc)
+{
+ NOREF(iLun);
+ NOREF(pszDesc);
+ s_drvTstMouse.pDrvBase = pBaseInterface;
+ s_drvTstMouse.pDrv = PDMIBASE_QUERY_INTERFACE(pBaseInterface,
+ PDMIMOUSEPORT);
+ *ppBaseInterface = &s_drvTstMouse.IBase;
+ return VINF_SUCCESS;
+}
+
+
+static PDMUSBHLP s_tstUsbHlp;
+
+
+/**
+ * @interface_method_impl{PDMIBASE,pfnQueryInterface}
+ */
+static DECLCALLBACK(void *) tstMouseQueryInterface(PPDMIBASE pInterface,
+ const char *pszIID)
+{
+ PDRVTSTMOUSE pThis = RT_FROM_MEMBER(pInterface, DRVTSTMOUSE, IBase);
+ PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
+ PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUSECONNECTOR, &pThis->IConnector);
+ return NULL;
+}
+
+
+/**
+ * @interface_method_impl{PDMIMOUSECONNECTOR,pfnReportModes}
+ */
+static DECLCALLBACK(void) tstMouseReportModes(PPDMIMOUSECONNECTOR pInterface,
+ bool fRel, bool fAbs, bool fMT)
+{
+ PDRVTSTMOUSE pDrv = RT_FROM_MEMBER(pInterface, DRVTSTMOUSE, IConnector);
+ pDrv->fRel = fRel;
+ pDrv->fAbs = fAbs;
+ pDrv->fMT = fMT;
+}
+
+
+static int tstMouseConstruct(int iInstance, const char *pcszMode,
+ uint8_t u8CoordShift, PPDMUSBINS *ppThis)
+{
+ int rc = VERR_NO_MEMORY;
+ PPDMUSBINS pThis = (PPDMUSBINS)RTMemAllocZ( sizeof(*pThis)
+ + g_UsbHidMou.cbInstance);
+ PCFGMNODE pCfg = NULL;
+ if (pThis)
+ pCfg = CFGMR3CreateTree(NULL);
+ if (pCfg)
+ rc = CFGMR3InsertString(pCfg, "Mode", pcszMode);
+ if (RT_SUCCESS(rc))
+ rc = CFGMR3InsertInteger(pCfg, "CoordShift", u8CoordShift);
+ if (RT_SUCCESS(rc))
+ {
+ s_drvTstMouse.pDrv = NULL;
+ s_drvTstMouse.pDrvBase = NULL;
+ pThis->iInstance = iInstance;
+ pThis->pHlpR3 = &s_tstUsbHlp;
+ rc = g_UsbHidMou.pfnConstruct(pThis, iInstance, pCfg, NULL);
+ if (RT_SUCCESS(rc))
+ {
+ *ppThis = pThis;
+ return rc;
+ }
+ }
+ /* Failure */
+ if (pCfg)
+ CFGMR3DestroyTree(pCfg);
+ if (pThis)
+ RTMemFree(pThis);
+ return rc;
+}
+
+
+static void testConstructAndDestruct(RTTEST hTest)
+{
+ PPDMUSBINS pThis;
+ RTTestSub(hTest, "simple construction and destruction");
+ int rc = tstMouseConstruct(0, "relative", 1, &pThis);
+ RTTEST_CHECK_RC_OK(hTest, rc);
+ if (pThis)
+ g_UsbHidMou.pfnDestruct(pThis);
+}
+
+
+static void testSendPositionRel(RTTEST hTest)
+{
+ PPDMUSBINS pThis = NULL;
+ VUSBURB Urb;
+ RTTestSub(hTest, "sending a relative position event");
+ int rc = tstMouseConstruct(0, "relative", 1, &pThis);
+ RT_ZERO(Urb);
+ if (RT_SUCCESS(rc))
+ rc = g_UsbHidMou.pfnUsbReset(pThis, false);
+ if (RT_SUCCESS(rc) && !s_drvTstMouse.pDrv)
+ rc = VERR_PDM_MISSING_INTERFACE;
+ RTTEST_CHECK_RC_OK(hTest, rc);
+ if (RT_SUCCESS(rc))
+ {
+ s_drvTstMouse.pDrv->pfnPutEvent(s_drvTstMouse.pDrv, 123, -16, 1, -1, 3);
+ Urb.EndPt = 0x01;
+ rc = g_UsbHidMou.pfnUrbQueue(pThis, &Urb);
+ }
+ if (RT_SUCCESS(rc))
+ {
+ PVUSBURB pUrb = g_UsbHidMou.pfnUrbReap(pThis, 0);
+ if (pUrb)
+ {
+ if (pUrb == &Urb)
+ {
+ if ( Urb.abData[0] != 3 /* Buttons */
+ || Urb.abData[1] != 123 /* x */
+ || Urb.abData[2] != 240 /* 256 - y */
+ || Urb.abData[3] != 255 /* z */)
+ rc = VERR_GENERAL_FAILURE;
+ }
+ else
+ rc = VERR_GENERAL_FAILURE;
+ }
+ else
+ rc = VERR_GENERAL_FAILURE;
+ }
+ RTTEST_CHECK_RC_OK(hTest, rc);
+ if (pThis)
+ g_UsbHidMou.pfnDestruct(pThis);
+}
+
+
+static void testSendPositionAbs(RTTEST hTest)
+{
+ PPDMUSBINS pThis = NULL;
+ VUSBURB Urb;
+ RTTestSub(hTest, "sending an absolute position event");
+ int rc = tstMouseConstruct(0, "absolute", 1, &pThis);
+ RT_ZERO(Urb);
+ if (RT_SUCCESS(rc))
+ {
+ rc = g_UsbHidMou.pfnUsbReset(pThis, false);
+ }
+ if (RT_SUCCESS(rc))
+ {
+ if (s_drvTstMouse.pDrv)
+ s_drvTstMouse.pDrv->pfnPutEventAbs(s_drvTstMouse.pDrv, 300, 200, 1,
+ 3, 3);
+ else
+ rc = VERR_PDM_MISSING_INTERFACE;
+ }
+ if (RT_SUCCESS(rc))
+ {
+ Urb.EndPt = 0x01;
+ rc = g_UsbHidMou.pfnUrbQueue(pThis, &Urb);
+ }
+ if (RT_SUCCESS(rc))
+ {
+ PVUSBURB pUrb = g_UsbHidMou.pfnUrbReap(pThis, 0);
+ if (pUrb)
+ {
+ if (pUrb == &Urb)
+ {
+ if ( Urb.abData[0] != 3 /* Buttons */
+ || (int8_t)Urb.abData[1] != -1 /* dz */
+ || (int8_t)Urb.abData[2] != -3 /* dw */
+ || *(uint16_t *)&Urb.abData[4] != 150 /* x >> 1 */
+ || *(uint16_t *)&Urb.abData[6] != 100 /* y >> 1 */)
+ rc = VERR_GENERAL_FAILURE;
+ }
+ else
+ rc = VERR_GENERAL_FAILURE;
+ }
+ else
+ rc = VERR_GENERAL_FAILURE;
+ }
+ RTTEST_CHECK_RC_OK(hTest, rc);
+ if (pThis)
+ g_UsbHidMou.pfnDestruct(pThis);
+}
+
+#if 0
+/** @todo PDM interface was updated. This is not working anymore. */
+static void testSendPositionMT(RTTEST hTest)
+{
+ PPDMUSBINS pThis = NULL;
+ VUSBURB Urb;
+ RTTestSub(hTest, "sending a multi-touch position event");
+ int rc = tstMouseConstruct(0, "multitouch", 1, &pThis);
+ RT_ZERO(Urb);
+ if (RT_SUCCESS(rc))
+ {
+ rc = g_UsbHidMou.pfnUsbReset(pThis, false);
+ }
+ if (RT_SUCCESS(rc))
+ {
+ if (s_drvTstMouse.pDrv)
+ s_drvTstMouse.pDrv->pfnPutEventMT(s_drvTstMouse.pDrv, 300, 200, 2,
+ 3);
+ else
+ rc = VERR_PDM_MISSING_INTERFACE;
+ }
+ if (RT_SUCCESS(rc))
+ {
+ Urb.EndPt = 0x01;
+ rc = g_UsbHidMou.pfnUrbQueue(pThis, &Urb);
+ }
+ if (RT_SUCCESS(rc))
+ {
+ PVUSBURB pUrb = g_UsbHidMou.pfnUrbReap(pThis, 0);
+ if (pUrb)
+ {
+ if (pUrb == &Urb)
+ {
+ if ( Urb.abData[0] != 1 /* Report ID */
+ || Urb.abData[1] != 3 /* Contact flags */
+ || *(uint16_t *)&Urb.abData[2] != 150 /* x >> 1 */
+ || *(uint16_t *)&Urb.abData[4] != 100 /* y >> 1 */
+ || Urb.abData[6] != 2 /* Contact number */)
+ rc = VERR_GENERAL_FAILURE;
+ }
+ else
+ rc = VERR_GENERAL_FAILURE;
+ }
+ else
+ rc = VERR_GENERAL_FAILURE;
+ }
+ RTTEST_CHECK_RC_OK(hTest, rc);
+ if (pThis)
+ g_UsbHidMou.pfnDestruct(pThis);
+}
+#endif
+
+int main()
+{
+ /*
+ * Init the runtime, test and say hello.
+ */
+ RTTEST hTest;
+ PDRVTSTMOUSE pThis;
+ int rc = RTTestInitAndCreate("tstUsbMouse", &hTest);
+ if (rc)
+ return rc;
+ RTTestBanner(hTest);
+ /* Set up our faked PDMUSBHLP interface. */
+ s_tstUsbHlp.pfnVMSetErrorV = tstVMSetErrorV;
+ s_tstUsbHlp.pfnDriverAttach = tstDriverAttach;
+ /* Set up our global mouse driver */
+ s_drvTstMouse.IBase.pfnQueryInterface = tstMouseQueryInterface;
+ s_drvTstMouse.IConnector.pfnReportModes = tstMouseReportModes;
+
+ /*
+ * Run the tests.
+ */
+ testConstructAndDestruct(hTest);
+ testSendPositionRel(hTest);
+ testSendPositionAbs(hTest);
+ /* testSendPositionMT(hTest); */
+ return RTTestSummaryAndDestroy(hTest);
+}