diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2014-03-26 19:21:20 +0000 |
---|---|---|
committer | <> | 2014-05-08 15:03:54 +0000 |
commit | fb123f93f9f5ce42c8e5785d2f8e0edaf951740e (patch) | |
tree | c2103d76aec5f1f10892cd1d3a38e24f665ae5db /src/VBox/Devices/Input/testcase/tstUsbMouse.cpp | |
parent | 58ed4748338f9466599adfc8a9171280ed99e23f (diff) | |
download | VirtualBox-master.tar.gz |
Imported from /home/lorry/working-area/delta_VirtualBox/VirtualBox-4.3.10.tar.bz2.HEADVirtualBox-4.3.10master
Diffstat (limited to 'src/VBox/Devices/Input/testcase/tstUsbMouse.cpp')
-rw-r--r-- | src/VBox/Devices/Input/testcase/tstUsbMouse.cpp | 329 |
1 files changed, 329 insertions, 0 deletions
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); +} |