VirtualBox

Changeset 42031 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jul 5, 2012 8:02:43 PM (13 years ago)
Author:
vboxsync
Message:

Additions/solaris/vboxmouse: convert vboxmouse back to a driver again, and a number of fixes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/solaris/Mouse/vboxmouse.c

    r41852 r42031  
    2525 */
    2626
     27#define LOG_GROUP LOG_GROUP_DRV_MOUSE
    2728
    2829/******************************************************************************
     
    3031******************************************************************************/
    3132
     33#include <VBox/VBoxGuestLib.h>
     34#include <VBox/log.h>
     35#include <VBox/version.h>
     36#include <iprt/assert.h>
     37#include <iprt/asm.h>
     38
    3239#ifndef TESTCASE
    33 # include <sys/conf.h>
    3440# include <sys/modctl.h>
    3541# include <sys/msio.h>
    36 # include <sys/pci.h>
    3742# include <sys/stat.h>
    3843# include <sys/ddi.h>
    39 # include <sys/ddi_intr.h>
    40 # include <sys/open.h>
    4144# include <sys/strsun.h>
    4245# include <sys/stropts.h>
    4346# include <sys/sunddi.h>
    44 # include <sys/sunldi.h>
    4547# include <sys/vuid_event.h>
    4648# include <sys/vuid_wheel.h>
    47 # include <sys/file.h>
    4849#undef u /* /usr/include/sys/user.h:249:1 is where this is defined to (curproc->p_user). very cool. */
    4950#else  /* TESTCASE */
     
    5253#endif  /* TESTCASE */
    5354
    54 #include "../../common/VBoxGuestLib/SysHlp.h"
    55 #include <VBox/VBoxGuest.h>
    56 #include <VBox/VBoxGuestLib.h>
    57 #include <VBox/log.h>
    58 #include <VBox/version.h>
    59 #include <iprt/assert.h>
    60 #include <iprt/initterm.h>
    61 #include <iprt/process.h>
    62 #include <iprt/mem.h>
    63 #include <iprt/cdefs.h>
    64 #include <iprt/asm.h>
    65 #include <iprt/string.h>
    66 
    6755#ifdef TESTCASE  /* Include this last as we . */
    6856# include "testcase/solaris.h"
     
    8573******************************************************************************/
    8674
     75static int vbmsSolAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd);
     76static int vbmsSolDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd);
     77static int vbmsSolGetInfo(dev_info_t *pDip, ddi_info_cmd_t enmCmd, void *pvArg,
     78                          void **ppvResult);
    8779static int vbmsSolOpen(queue_t *pReadQueue, dev_t *pDev, int fFlag,
    8880                                int fMode, cred_t *pCred);
     
    156148
    157149/**
    158  * fmodsw: loadable module wrapper for streams drivers.
    159  */
    160 static struct fmodsw g_vbmsSolStrWrapper = {
    161     "vboxms",
     150 * cb_ops: for drivers that support char/block entry points
     151 */
     152static struct cb_ops g_vbmsSolCbOps =
     153{
     154    nodev,                  /* open */
     155    nodev,                  /* close */
     156    nodev,                  /* b strategy */
     157    nodev,                  /* b dump */
     158    nodev,                  /* b print */
     159    nodev,                  /* c read */
     160    nodev,                  /* c write */
     161    nodev,                  /* c ioctl */
     162    nodev,                  /* c devmap */
     163    nodev,                  /* c mmap */
     164    nodev,                  /* c segmap */
     165    nochpoll,               /* c poll */
     166    ddi_prop_op,            /* property ops */
    162167    &g_vbmsSolStreamTab,
    163     D_MP
     168    D_MP,
     169    CB_REV                  /* revision */
    164170};
    165171
    166172/**
    167  * modlstrmod: export stream modules specifics to the kernel.
    168  */
    169 static struct modlstrmod g_vbmsSolModule =
    170 {
    171     &mod_strmodops,         /* extern from kernel */
     173 * dev_ops: for driver device operations
     174 */
     175static struct dev_ops g_vbmsSolDevOps =
     176{
     177    DEVO_REV,               /* driver build revision */
     178    0,                      /* ref count */
     179    vbmsSolGetInfo,
     180    nulldev,                /* identify */
     181    nulldev,                /* probe */
     182    vbmsSolAttach,
     183    vbmsSolDetach,
     184    nodev,                  /* reset */
     185    &g_vbmsSolCbOps,
     186    NULL,                   /* bus operations */
     187    nodev                   /* power */
     188};
     189
     190/**
     191 * modldrv: export driver specifics to the kernel
     192 */
     193static struct modldrv g_vbmsSolModule =
     194{
     195    &mod_driverops,         /* extern from kernel */
    172196    DEVICE_DESC " " VBOX_VERSION_STRING "r" RT_XSTR(VBOX_SVN_REV),
    173     &g_vbmsSolStrWrapper
     197    &g_vbmsSolDevOps
    174198};
    175199
     
    193217typedef struct
    194218{
     219    /** Device handle. */
     220    dev_info_t        *pDip;
     221    /** Mutex protecting the guest library against multiple initialistation or
     222     * uninitialisation. */
     223    kmutex_t           InitMtx;
     224    /** Initialisation counter for the guest library. */
     225    size_t             cInits;
    195226    /** The STREAMS write queue which we need for sending messages up to
    196227     * user-space. */
     
    222253int _init(void)
    223254{
     255    int rc;
     256    LogRelFlow((DEVICE_NAME ": built on " __DATE__ " at " __TIME__ "\n"));
     257    mutex_init(&g_OpenNodeState.InitMtx, NULL, MUTEX_DRIVER, NULL);
     258    /*
     259     * Prevent module autounloading.
     260     */
     261    modctl_t *pModCtl = mod_getctl(&g_vbmsSolModLinkage);
     262    if (pModCtl)
     263        pModCtl->mod_loadflags |= MOD_NOAUTOUNLOAD;
     264    else
     265        LogRel((DEVICE_NAME ": failed to disable autounloading!\n"));
     266    rc = mod_install(&g_vbmsSolModLinkage);
     267
     268    LogRel((DEVICE_NAME ": initialisation returning %d.\n", rc));
     269    return rc;
     270}
     271
     272
     273#ifdef TESTCASE
     274/** Simple test of the flow through _init. */
     275static void test_init(RTTEST hTest)
     276{
     277    RTTestSub(hTest, "Testing _init");
     278    RTTEST_CHECK(hTest, _init() == 0);
     279}
     280#endif
     281
     282
     283/** Driver cleanup. */
     284int _fini(void)
     285{
     286    int rc;
     287
     288    LogRelFlow((DEVICE_NAME ":_fini\n"));
     289    rc = mod_remove(&g_vbmsSolModLinkage);
     290    mutex_destroy(&g_OpenNodeState.InitMtx);
     291
     292    return rc;
     293}
     294
     295
     296/** Driver identification. */
     297int _info(struct modinfo *pModInfo)
     298{
     299    int rc;
     300    LogRelFlow((DEVICE_NAME ":_info\n"));
     301    rc = mod_info(&g_vbmsSolModLinkage, pModInfo);
     302    LogRelFlow((DEVICE_NAME ":_info returning %d\n", rc));
     303    return rc;
     304}
     305
     306
     307/******************************************************************************
     308*   Initialisation entry points                                               *
     309******************************************************************************/
     310
     311/**
     312 * Attach entry point, to attach a device to the system or resume it.
     313 *
     314 * @param   pDip            The module structure instance.
     315 * @param   enmCmd          Attach type (ddi_attach_cmd_t)
     316 *
     317 * @return  corresponding solaris error code.
     318 */
     319int vbmsSolAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd)
     320{
     321    LogRelFlow((DEVICE_NAME "::Attach\n"));
     322    switch (enmCmd)
     323    {
     324        case DDI_ATTACH:
     325        {
     326            int rc;
     327            int instance = ddi_get_instance(pDip);
     328            /* Only one instance supported. */
     329            if (!ASMAtomicCmpXchgPtr(&g_OpenNodeState.pDip, pDip, NULL))
     330                return DDI_FAILURE;
     331            rc = ddi_create_minor_node(pDip, DEVICE_NAME, S_IFCHR, instance, DDI_PSEUDO, 0);
     332            if (rc == DDI_SUCCESS)
     333                return DDI_SUCCESS;
     334            ASMAtomicWritePtr(&g_OpenNodeState.pDip, NULL);
     335            return DDI_FAILURE;
     336        }
     337
     338        case DDI_RESUME:
     339        {
     340            /** @todo implement resume for guest driver. */
     341            return DDI_SUCCESS;
     342        }
     343
     344        default:
     345            return DDI_FAILURE;
     346    }
     347}
     348
     349
     350/**
     351 * Detach entry point, to detach a device to the system or suspend it.
     352 *
     353 * @param   pDip            The module structure instance.
     354 * @param   enmCmd          Attach type (ddi_attach_cmd_t)
     355 *
     356 * @return  corresponding solaris error code.
     357 */
     358int vbmsSolDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd)
     359{
     360    LogRelFlow((DEVICE_NAME "::Detach\n"));
     361    switch (enmCmd)
     362    {
     363        case DDI_DETACH:
     364        {
     365            ddi_remove_minor_node(pDip, NULL);
     366            ASMAtomicWritePtr(&g_OpenNodeState.pDip, NULL);
     367            return DDI_SUCCESS;
     368        }
     369
     370        case DDI_SUSPEND:
     371        {
     372            /** @todo implement suspend for guest driver. */
     373            return DDI_SUCCESS;
     374        }
     375
     376        default:
     377            return DDI_FAILURE;
     378    }
     379}
     380
     381
     382/**
     383 * Info entry point, called by solaris kernel for obtaining driver info.
     384 *
     385 * @param   pDip            The module structure instance (do not use).
     386 * @param   enmCmd          Information request type.
     387 * @param   pvArg           Type specific argument.
     388 * @param   ppvResult       Where to store the requested info.
     389 *
     390 * @return  corresponding solaris error code.
     391 */
     392int vbmsSolGetInfo(dev_info_t *pDip, ddi_info_cmd_t enmCmd, void *pvArg,
     393                   void **ppvResult)
     394{
     395    LogRelFlow((DEVICE_NAME "::GetInfo\n"));
     396
     397    int rc = DDI_SUCCESS;
     398    switch (enmCmd)
     399    {
     400        case DDI_INFO_DEVT2DEVINFO:
     401            *ppvResult = (void *)g_OpenNodeState.pDip;
     402            break;
     403
     404        case DDI_INFO_DEVT2INSTANCE:
     405            *ppvResult = (void *)(uintptr_t)ddi_get_instance(g_OpenNodeState.pDip);
     406            break;
     407
     408        default:
     409            rc = DDI_FAILURE;
     410            break;
     411    }
     412
     413    NOREF(pvArg);
     414    return rc;
     415}
     416
     417
     418/******************************************************************************
     419*   Main code                                                                 *
     420******************************************************************************/
     421
     422static void vbmsSolNotify(void *pvState);
     423static void vbmsSolVUIDPutAbsEvent(PVBMSSTATE pState, ushort_t cEvent,
     424                                   int cValue);
     425
     426/**
     427 * Open callback for the read queue, which we use as a generic device open
     428 * handler.
     429 */
     430int vbmsSolOpen(queue_t *pReadQueue, dev_t *pDev, int fFlag, int fMode,
     431                 cred_t *pCred)
     432{
     433    PVBMSSTATE pState = NULL;
     434    int rc = VINF_SUCCESS;
     435
     436    NOREF(fFlag);
     437    NOREF(pCred);
     438    LogRelFlow((DEVICE_NAME "::Open\n"));
     439
    224440    /*
    225441     * Initialize IPRT R0 driver, which internally calls OS-specific r0 init.
    226442     */
    227     int rc = VbglInit();
    228     if (RT_SUCCESS(rc))
    229     {
    230         /*
    231          * Prevent module autounloading.
    232          */
    233         modctl_t *pModCtl = mod_getctl(&g_vbmsSolModLinkage);
    234         if (pModCtl)
    235             pModCtl->mod_loadflags |= MOD_NOAUTOUNLOAD;
    236         else
    237             LogRel((DEVICE_NAME ":failed to disable autounloading!\n"));
    238         rc = mod_install(&g_vbmsSolModLinkage);
    239     }
    240     else
     443    mutex_enter(&g_OpenNodeState.InitMtx);
     444    if (!g_OpenNodeState.cInits)
     445        rc = VbglInit();
     446    ++g_OpenNodeState.cInits;
     447    mutex_exit(&g_OpenNodeState.InitMtx);
     448    if (RT_FAILURE(rc))
    241449    {
    242450        cmn_err(CE_NOTE, "_init: VbglInit failed. rc=%d\n", rc);
    243451        return EINVAL;
    244452    }
    245 
    246     LogRel((DEVICE_NAME ": initialisation returning %d.\n", rc));
    247     return rc;
    248 }
    249 
    250 
    251 #ifdef TESTCASE
    252 /** Simple test of the flow through _init. */
    253 static void test_init(RTTEST hTest)
    254 {
    255     RTTestSub(hTest, "Testing _init");
    256     RTTEST_CHECK(hTest, _init() == 0);
    257 }
    258 #endif
    259 
    260 
    261 /** Driver cleanup. */
    262 int _fini(void)
    263 {
    264     int rc;
    265 
    266     LogRelFlow((DEVICE_NAME ":_fini\n"));
    267     rc = mod_remove(&g_vbmsSolModLinkage);
    268 
    269     RTLogDestroy(RTLogRelSetDefaultInstance(NULL));
    270     RTLogDestroy(RTLogSetDefaultInstance(NULL));
    271 
    272     RTR0Term();
    273     return rc;
    274 }
    275 
    276 
    277 /** Driver identification. */
    278 int _info(struct modinfo *pModInfo)
    279 {
    280     LogFlow((DEVICE_NAME ":_info\n"));
    281     return mod_info(&g_vbmsSolModLinkage, pModInfo);
    282 }
    283 
    284 
    285 /******************************************************************************
    286 *   Main code                                                                 *
    287 ******************************************************************************/
    288 
    289 static void vbmsSolNotify(void *pvState);
    290 static void vbmsSolVUIDPutAbsEvent(PVBMSSTATE pState, ushort_t cEvent,
    291                                    int cValue);
    292 
    293 /**
    294  * Open callback for the read queue, which we use as a generic device open
    295  * handler.
    296  */
    297 int vbmsSolOpen(queue_t *pReadQueue, dev_t *pDev, int fFlag, int fMode,
    298                  cred_t *pCred)
    299 {
    300     int                 rc;
    301     PVBMSSTATE pState = NULL;
    302 
    303     NOREF(fFlag);
    304     NOREF(pCred);
    305     LogRelFlow((DEVICE_NAME "::Open\n"));
    306 
    307453    /*
    308454     * Sanity check on the mode parameter - only open as a driver, not a
     
    341487    ASMAtomicWriteNullPtr(&pState->pWriteQueue);
    342488
    343     LogRel((DEVICE_NAME "::Open: VBoxGuestCreateUserSession failed. rc=%d\n", rc));
     489    LogRel((DEVICE_NAME "::Open: VBoxGuestCreateUserSession failed. rc=EFAULT\n"));
    344490    return EFAULT;
    345491}
     
    357503    int rc;
    358504    uint32_t x, y;
    359     LogFlow((DEVICE_NAME "::NativeISRMousePollEvent:\n"));
     505    LogRelFlow((DEVICE_NAME "::NativeISRMousePollEvent:\n"));
    360506
    361507    rc = VbglGetMouseStatus(NULL, &x, &y);
     
    408554    PVBMSSTATE pState = (PVBMSSTATE)pReadQueue->q_ptr;
    409555
    410     LogFlow((DEVICE_NAME "::Close\n"));
     556    LogRelFlow((DEVICE_NAME "::Close\n"));
    411557    NOREF(fFlag);
    412558    NOREF(pCred);
     
    428574    ASMAtomicWriteNullPtr(&pState->pWriteQueue);
    429575    pReadQueue->q_ptr = NULL;
     576    mutex_enter(&g_OpenNodeState.InitMtx);
     577    --g_OpenNodeState.cInits;
     578    if (!g_OpenNodeState.cInits)
     579        VbglTerminate();
     580    mutex_exit(&g_OpenNodeState.InitMtx);
    430581    return 0;
    431582}
     
    8991050    enum IOCTLDIRECTION enmDirection;
    9001051
    901     LogFlowFunc((DEVICE_NAME "::iCmdType=%c, iCmd=%d\n",
    902                  (char) (iCmdType >> 8), iCmd));
     1052    LogRelFlowFunc((DEVICE_NAME "::iCmdType=%c, iCmd=0x%x\n",
     1053                 (char) (iCmdType >> 8), (unsigned)iCmd));
    9031054    switch (iCmdType)
    9041055    {
     
    9671118    struct iocblk *pIOCBlk = (struct iocblk *)pMBlk->b_rptr;
    9681119
     1120    LogFlowFunc(("iCmd=0x%x, cbBuffer=%d, enmDirection=%d\n",
     1121                 (unsigned)iCmd, (int)cbTransparent, (int)enmDirection));
    9691122    if (pMBlk->b_datap->db_type == M_IOCDATA)
    9701123        return vbmsSolHandleIOCtlData(pWriteQueue, pMBlk, pfnHandler, iCmd,
     
    9951148    PVBMSSTATE pState = (PVBMSSTATE)pWriteQueue->q_ptr;
    9961149
     1150    LogFlowFunc(("iCmd=0x%x, cbBuffer=%d, enmDirection=%d, cp_rval=%d, cp_private=%p\n",
     1151                 (unsigned)iCmd, (int)cbTransparent, (int)enmDirection,
     1152                 (int)(uintptr_t)pCopyResp->cp_rval,
     1153                 (void *)pCopyResp->cp_private));
    9971154    if (pCopyResp->cp_rval)  /* cp_rval is a pointer used as a boolean. */
    9981155    {
     
    10411198    PVBMSSTATE pState = (PVBMSSTATE)pWriteQueue->q_ptr;
    10421199
     1200    LogFlowFunc(("iCmd=0x%x, cbBuffer=%d, enmDirection=%d\n",
     1201                 (unsigned)iCmd, (int)cbTransparent, (int)enmDirection));
    10431202    if (   (enmDirection != NONE && !pMBlk->b_cont)
    10441203        || enmDirection == UNSPECIFIED)
     
    10911250    size_t cbData = 0;
    10921251   
     1252    LogFlowFunc(("iCmd=0x%x, cbBuffer=%u, b_cont=%p\n",
     1253                 (unsigned)iCmd, cbBuffer, (void *)pMBlk->b_cont));
    10931254    if (cbBuffer && !pMBlk->b_cont)
    10941255        return EINVAL;
     
    10991260        if (err)
    11001261            return err;
     1262    }
     1263    if (pMBlk->b_cont)  /* consms forgets to set ioc_count. */
     1264    {
    11011265        pvData = pMBlk->b_cont->b_rptr;
     1266        cbBuffer = pMBlk->b_cont->b_wptr - pMBlk->b_cont->b_rptr;
    11021267    }
    11031268    err = pfnHandler(pState, iCmd, pvData, cbBuffer, &cbData, &rc);
     
    11151280                             size_t cbBuffer, size_t *pcbData, int *prc)
    11161281{
    1117     LogFlowFunc((DEVICE_NAME ":: " /* no '\n' */));
     1282    LogRelFlowFunc((DEVICE_NAME ":: " /* no '\n' */));
    11181283    switch (iCmd)
    11191284    {
    11201285        case VUIDGFORMAT:
    11211286        {
    1122             LogFlowFunc(("VUIDGFORMAT\n"));
     1287            LogRelFlowFunc(("VUIDGFORMAT\n"));
    11231288            if (cbBuffer < sizeof(int))
    11241289                return EINVAL;
     
    11281293        }
    11291294        case VUIDSFORMAT:
    1130             LogFlowFunc(("VUIDSFORMAT\n"));
     1295            LogRelFlowFunc(("VUIDSFORMAT\n"));
    11311296            /* We define our native format to be VUID_FIRM_EVENT, so there
    11321297             * is nothing more to do and we exit here on success or on
     
    11351300        case VUIDGADDR:
    11361301        case VUIDSADDR:
    1137             LogFlowFunc(("VUIDGADDR/VUIDSADDR\n"));
     1302            LogRelFlowFunc(("VUIDGADDR/VUIDSADDR\n"));
    11381303            return ENOTTY;
    11391304        case MSIOGETPARMS:
     
    11411306            Ms_parms parms = { 0 };
    11421307
    1143             LogFlowFunc(("MSIOGETPARMS\n"));
     1308            LogRelFlowFunc(("MSIOGETPARMS\n"));
    11441309            if (cbBuffer < sizeof(Ms_parms))
    11451310                return EINVAL;
     
    11491314        }
    11501315        case MSIOSETPARMS:
    1151             LogFlowFunc(("MSIOSETPARMS\n"));
     1316            LogRelFlowFunc(("MSIOSETPARMS\n"));
    11521317            return 0;
    11531318        case MSIOSRESOLUTION:
     
    11561321            int rc;
    11571322
    1158             LogFlowFunc(("MSIOSRESOLUTION\n"));
     1323            LogRelFlowFunc(("MSIOSRESOLUTION, cbBuffer=%d, sizeof(Ms_screen_resolution)=%d\n",
     1324                            (int) cbBuffer,
     1325                            (int) sizeof(Ms_screen_resolution)));
    11591326            if (cbBuffer < sizeof(Ms_screen_resolution))
    11601327                return EINVAL;
     1328            LogRelFlowFunc(("%dx%d\n", pResolution->width,
     1329                            pResolution->height));
    11611330            pState->cMaxScreenX = pResolution->width  - 1;
    11621331            pState->cMaxScreenY = pResolution->height - 1;
     
    11721341        case MSIOBUTTONS:
    11731342        {
    1174             LogFlowFunc(("MSIOBUTTONS\n"));
     1343            LogRelFlowFunc(("MSIOBUTTONS\n"));
    11751344            if (cbBuffer < sizeof(int))
    11761345                return EINVAL;
     
    11811350        case VUIDGWHEELCOUNT:
    11821351        {
    1183             LogFlowFunc(("VUIDGWHEELCOUNT\n"));
     1352            LogRelFlowFunc(("VUIDGWHEELCOUNT\n"));
    11841353            if (cbBuffer < sizeof(int))
    11851354                return EINVAL;
     
    11911360        case VUIDGWHEELSTATE:
    11921361        case VUIDSWHEELSTATE:
    1193             LogFlowFunc(("VUIDGWHEELINFO/VUIDGWHEELSTATE/VUIDSWHEELSTATE\n"));
     1362            LogRelFlowFunc(("VUIDGWHEELINFO/VUIDGWHEELSTATE/VUIDSWHEELSTATE\n"));
    11941363            return EINVAL;
    11951364        default:
    1196             LogFlowFunc(("Invalid IOCtl command %x\n", iCmd));
     1365            LogRelFlowFunc(("Invalid IOCtl command %x\n", iCmd));
    11971366            return EINVAL;
    11981367    }
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette