VBoxUSBMon-solaris.c revision b4527afd791e3a896aa9e4077910974a438a5ddc
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync/* $Id$ */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync/** @file
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * VirtualBox USB Monitor Driver, Solaris Hosts.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync/*
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * Copyright (C) 2008-2013 Oracle Corporation
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync *
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * available from http://www.virtualbox.org. This file is free software;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * you can redistribute it and/or modify it under the terms of the GNU
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * General Public License (GPL) as published by the Free Software
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync *
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * The contents of this file may alternatively be used under the terms
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * of the Common Development and Distribution License Version 1.0
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * VirtualBox OSE distribution, in which case the provisions of the
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * CDDL are applicable instead of those of the GPL.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync *
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * You may elect to license modified versions of this file under the
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * terms and conditions of either the GPL or the CDDL or both.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync/*******************************************************************************
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync* Header Files *
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync*******************************************************************************/
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#define LOG_GROUP LOG_GROUP_USB_DRV
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#ifdef DEBUG_ramshankar
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync# define LOG_ENABLED
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync# define LOG_INSTANCE RTLogRelDefaultInstance()
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#endif
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#include "VBoxUSBFilterMgr.h"
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#include <VBox/usblib-solaris.h>
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#include <VBox/version.h>
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#include <VBox/log.h>
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#include <VBox/cdefs.h>
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#include <VBox/types.h>
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#include <VBox/version.h>
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#include <iprt/assert.h>
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#include <iprt/string.h>
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#include <iprt/initterm.h>
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#include <iprt/process.h>
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#include <iprt/mem.h>
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#include <iprt/semaphore.h>
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#include <iprt/path.h>
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#define USBDRV_MAJOR_VER 2
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#define USBDRV_MINOR_VER 0
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#include <sys/usb/usba.h>
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#include <sys/conf.h>
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#include <sys/modctl.h>
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#include <sys/mutex.h>
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#include <sys/stat.h>
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#include <sys/ddi.h>
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#include <sys/sunddi.h>
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#include <sys/sunndi.h>
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#include <sys/open.h>
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#include <sys/cmn_err.h>
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync/*******************************************************************************
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync* Defined Constants And Macros *
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync*******************************************************************************/
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync/** The module name. */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#define DEVICE_NAME "vboxusbmon"
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync/** The module description as seen in 'modinfo'. */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#define DEVICE_DESC_DRV "VirtualBox USBMon"
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync/*******************************************************************************
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync* Internal Functions *
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync*******************************************************************************/
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsyncstatic int VBoxUSBMonSolarisOpen(dev_t *pDev, int fFlag, int fType, cred_t *pCred);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsyncstatic int VBoxUSBMonSolarisClose(dev_t Dev, int fFlag, int fType, cred_t *pCred);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsyncstatic int VBoxUSBMonSolarisRead(dev_t Dev, struct uio *pUio, cred_t *pCred);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsyncstatic int VBoxUSBMonSolarisWrite(dev_t Dev, struct uio *pUio, cred_t *pCred);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsyncstatic int VBoxUSBMonSolarisIOCtl(dev_t Dev, int Cmd, intptr_t pArg, int Mode, cred_t *pCred, int *pVal);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsyncstatic int VBoxUSBMonSolarisGetInfo(dev_info_t *pDip, ddi_info_cmd_t enmCmd, void *pArg, void **ppResult);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsyncstatic int VBoxUSBMonSolarisAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsyncstatic int VBoxUSBMonSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync/*******************************************************************************
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync* Structures and Typedefs *
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync*******************************************************************************/
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync/**
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync * cb_ops: for drivers that support char/block entry points
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsyncstatic struct cb_ops g_VBoxUSBMonSolarisCbOps =
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync{
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync VBoxUSBMonSolarisOpen,
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync VBoxUSBMonSolarisClose,
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync nodev, /* b strategy */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync nodev, /* b dump */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync nodev, /* b print */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync VBoxUSBMonSolarisRead,
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync VBoxUSBMonSolarisWrite,
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync VBoxUSBMonSolarisIOCtl,
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync nodev, /* c devmap */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync nodev, /* c mmap */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync nodev, /* c segmap */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync nochpoll, /* c poll */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync ddi_prop_op, /* property ops */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync NULL, /* streamtab */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync D_NEW | D_MP, /* compat. flag */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync CB_REV /* revision */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync};
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync/**
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * dev_ops: for driver device operations
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync */
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsyncstatic struct dev_ops g_VBoxUSBMonSolarisDevOps =
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync{
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync DEVO_REV, /* driver build revision */
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync 0, /* ref count */
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync VBoxUSBMonSolarisGetInfo,
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync nulldev, /* identify */
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync nulldev, /* probe */
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync VBoxUSBMonSolarisAttach,
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync VBoxUSBMonSolarisDetach,
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync nodev, /* reset */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync &g_VBoxUSBMonSolarisCbOps,
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync (struct bus_ops *)0,
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync nodev, /* power */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync ddi_quiesce_not_needed
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync};
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync/**
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * modldrv: export driver specifics to the kernel
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsyncstatic struct modldrv g_VBoxUSBMonSolarisModule =
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync{
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync &mod_driverops, /* extern from kernel */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync DEVICE_DESC_DRV " " VBOX_VERSION_STRING "r" RT_XSTR(VBOX_SVN_REV),
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync &g_VBoxUSBMonSolarisDevOps
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync};
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync/**
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * modlinkage: export install/remove/info to the kernel
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsyncstatic struct modlinkage g_VBoxUSBMonSolarisModLinkage =
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync{
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync MODREV_1,
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync &g_VBoxUSBMonSolarisModule,
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync NULL,
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync};
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync/**
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * Client driver info.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsynctypedef struct vboxusbmon_client_t
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync{
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync dev_info_t *pDip; /* Client device info. pointer */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync VBOXUSB_CLIENT_INFO Info; /* Client registration data. */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync struct vboxusbmon_client_t *pNext; /* Pointer to next client */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync} vboxusbmon_client_t;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync/**
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * Device state info.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsynctypedef struct
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync{
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync RTPROCESS Process; /* The process (id) of the session */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync} vboxusbmon_state_t;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync/*******************************************************************************
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync* Global Variables *
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync*******************************************************************************/
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync/** Global Device handle we only support one instance. */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsyncstatic dev_info_t *g_pDip = NULL;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync/** Global Mutex. */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsyncstatic kmutex_t g_VBoxUSBMonSolarisMtx;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync/** Number of userland clients that have kept us open. */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsyncstatic uint64_t g_cVBoxUSBMonSolarisClient = 0;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync/** Global list of client drivers registered with us. */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsyncvboxusbmon_client_t *g_pVBoxUSBMonSolarisClients = NULL;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync/** Opaque pointer to list of soft states. */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsyncstatic void *g_pVBoxUSBMonSolarisState;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync/*******************************************************************************
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync* Internal Functions *
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync*******************************************************************************/
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsyncstatic int vboxUSBMonSolarisProcessIOCtl(int iFunction, void *pvState, void *pvData, size_t cbData, size_t *pcbReturnedData);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsyncstatic int vboxUSBMonSolarisResetDevice(char *pszDevicePath, bool fReattach);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync/*******************************************************************************
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync* Monitor Global Hooks *
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync*******************************************************************************/
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsyncstatic int vboxUSBMonSolarisClientInfo(vboxusbmon_state_t *pState, PVBOXUSB_CLIENT_INFO pClientInfo);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsyncint VBoxUSBMonSolarisRegisterClient(dev_info_t *pClientDip, PVBOXUSB_CLIENT_INFO pClientInfo);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsyncint VBoxUSBMonSolarisUnregisterClient(dev_info_t *pClientDip);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsyncint VBoxUSBMonSolarisElectDriver(usb_dev_descr_t *pDevDesc, usb_dev_str_t *pDevStrings, char *pszDevicePath, int Bus, int Port,
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync char **ppszDrv, void *pvReserved);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync/**
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * Kernel entry points
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsyncint _init(void)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync{
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync int rc;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogFunc((DEVICE_NAME ":_init\n"));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync g_pDip = NULL;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync /*
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * Prevent module autounloading.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync modctl_t *pModCtl = mod_getctl(&g_VBoxUSBMonSolarisModLinkage);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync if (pModCtl)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync pModCtl->mod_loadflags |= MOD_NOAUTOUNLOAD;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync else
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogRel((DEVICE_NAME ":failed to disable autounloading!\n"));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync /*
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * Initialize IPRT R0 driver, which internally calls OS-specific r0 init.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync rc = RTR0Init(0);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync if (RT_SUCCESS(rc))
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync /*
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * Initialize global mutex.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync mutex_init(&g_VBoxUSBMonSolarisMtx, NULL, MUTEX_DRIVER, NULL);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync rc = VBoxUSBFilterInit();
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync if (RT_SUCCESS(rc))
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync rc = ddi_soft_state_init(&g_pVBoxUSBMonSolarisState, sizeof(vboxusbmon_state_t), 1);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync if (!rc)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync rc = mod_install(&g_VBoxUSBMonSolarisModLinkage);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync if (!rc)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync return rc;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogRel((DEVICE_NAME ":mod_install failed! rc=%d\n", rc));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync ddi_soft_state_fini(&g_pVBoxUSBMonSolarisState);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync else
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogRel((DEVICE_NAME ":ddi_soft_state_init failed! rc=%d\n", rc));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync else
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogRel((DEVICE_NAME ":VBoxUSBFilterInit failed! rc=%d\n", rc));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync mutex_destroy(&g_VBoxUSBMonSolarisMtx);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync RTR0Term();
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync else
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogRel((DEVICE_NAME ":RTR0Init failed! rc=%d\n", rc));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync return -1;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync}
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsyncint _fini(void)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync{
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync int rc;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogFunc((DEVICE_NAME ":_fini\n"));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync rc = mod_remove(&g_VBoxUSBMonSolarisModLinkage);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync if (!rc)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync ddi_soft_state_fini(&g_pVBoxUSBMonSolarisState);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync VBoxUSBFilterTerm();
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync mutex_destroy(&g_VBoxUSBMonSolarisMtx);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync RTR0Term();
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync return rc;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync}
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsyncint _info(struct modinfo *pModInfo)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync{
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogFunc((DEVICE_NAME ":_info\n"));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync return mod_info(&g_VBoxUSBMonSolarisModLinkage, pModInfo);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync}
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync/**
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * Attach entry point, to attach a device to the system or resume it.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync *
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * @param pDip The module structure instance.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * @param enmCmd Attach type (ddi_attach_cmd_t)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync *
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * @returns corresponding solaris error code.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsyncstatic int VBoxUSBMonSolarisAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync{
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogFunc((DEVICE_NAME ":VBoxUSBMonSolarisAttach pDip=%p enmCmd=%d\n", pDip, enmCmd));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync switch (enmCmd)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync case DDI_ATTACH:
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync if (RT_UNLIKELY(g_pDip))
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogRel((DEVICE_NAME ":VBoxUSBMonSolarisAttach global instance already initialized.\n"));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync return DDI_FAILURE;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync g_pDip = pDip;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync int instance = ddi_get_instance(pDip);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync int rc = ddi_create_priv_minor_node(pDip, DEVICE_NAME, S_IFCHR, instance, DDI_PSEUDO, 0,
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync "none", "none", 0660);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync if (rc == DDI_SUCCESS)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync ddi_report_dev(pDip);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync return rc;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync else
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogRel((DEVICE_NAME ":VBoxUSBMonSolarisAttach ddi_create_minor_node failed! rc=%d\n", rc));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync return DDI_FAILURE;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync case DDI_RESUME:
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync /* We don't have to bother about power management. */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync return DDI_SUCCESS;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync default:
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync return DDI_FAILURE;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync}
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync/**
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * Detach entry point, to detach a device to the system or suspend it.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync *
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * @param pDip The module structure instance.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * @param enmCmd Attach type (ddi_attach_cmd_t)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync *
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * @returns corresponding solaris error code.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsyncstatic int VBoxUSBMonSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync{
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogFunc((DEVICE_NAME ":VBoxUSBMonSolarisDetach\n"));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync switch (enmCmd)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync case DDI_DETACH:
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync /*
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * Free all registered clients' info.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync mutex_enter(&g_VBoxUSBMonSolarisMtx);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync vboxusbmon_client_t *pCur = g_pVBoxUSBMonSolarisClients;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync while (pCur)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync vboxusbmon_client_t *pNext = pCur->pNext;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync RTMemFree(pCur);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync pCur = pNext;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync mutex_exit(&g_VBoxUSBMonSolarisMtx);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync ddi_remove_minor_node(pDip, NULL);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync g_pDip = NULL;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync return DDI_SUCCESS;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync case DDI_SUSPEND:
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync /* We don't have to bother about power management. */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync return DDI_SUCCESS;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync default:
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync return DDI_FAILURE;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync}
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync/**
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * Info entry point, called by solaris kernel for obtaining driver info.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync *
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * @param pDip The module structure instance (do not use).
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * @param enmCmd Information request type.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * @param pvArg Type specific argument.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * @param ppvResult Where to store the requested info.
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync *
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * @returns corresponding solaris error code.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsyncstatic int VBoxUSBMonSolarisGetInfo(dev_info_t *pDip, ddi_info_cmd_t enmCmd, void *pvArg, void **ppvResult)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync{
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync int rc = DDI_SUCCESS;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogFunc((DEVICE_NAME ":VBoxUSBMonSolarisGetInfo\n"));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync switch (enmCmd)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync case DDI_INFO_DEVT2DEVINFO:
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync *ppvResult = (void *)g_pDip;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync break;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync case DDI_INFO_DEVT2INSTANCE:
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync *ppvResult = (void *)(uintptr_t)ddi_get_instance(g_pDip);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync break;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync default:
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync rc = DDI_FAILURE;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync break;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync return rc;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync}
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsyncstatic int VBoxUSBMonSolarisOpen(dev_t *pDev, int fFlag, int fType, cred_t *pCred)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync{
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync vboxusbmon_state_t *pState = NULL;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync unsigned iOpenInstance;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogFunc((DEVICE_NAME ":VBoxUSBMonSolarisOpen\n"));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync /*
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * Verify we are being opened as a character device.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync if (fType != OTYP_CHR)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync return EINVAL;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync /*
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * Verify that we're called after attach.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync if (!g_pDip)
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogRel((DEVICE_NAME ":VBoxUSBMonSolarisOpen invalid state for opening.\n"));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync return ENXIO;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync mutex_enter(&g_VBoxUSBMonSolarisMtx);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync if (!g_cVBoxUSBMonSolarisClient)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync mutex_exit(&g_VBoxUSBMonSolarisMtx);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync int rc = usb_register_dev_driver(g_pDip, VBoxUSBMonSolarisElectDriver);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync if (RT_UNLIKELY(rc != DDI_SUCCESS))
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogRel((DEVICE_NAME ":Failed to register driver election callback with USBA rc=%d\n", rc));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync return EINVAL;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync Log((DEVICE_NAME ":Successfully registered election callback with USBA\n"));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync mutex_enter(&g_VBoxUSBMonSolarisMtx);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync g_cVBoxUSBMonSolarisClient++;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync mutex_exit(&g_VBoxUSBMonSolarisMtx);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync for (iOpenInstance = 0; iOpenInstance < 4096; iOpenInstance++)
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync {
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync if ( !ddi_get_soft_state(g_pVBoxUSBMonSolarisState, iOpenInstance) /* faster */
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync && ddi_soft_state_zalloc(g_pVBoxUSBMonSolarisState, iOpenInstance) == DDI_SUCCESS)
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync {
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync pState = ddi_get_soft_state(g_pVBoxUSBMonSolarisState, iOpenInstance);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync break;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync }
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync }
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync if (!pState)
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync {
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync LogRel((DEVICE_NAME ":VBoxUSBMonSolarisOpen: too many open instances."));
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync mutex_enter(&g_VBoxUSBMonSolarisMtx);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync g_cVBoxUSBMonSolarisClient--;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync mutex_exit(&g_VBoxUSBMonSolarisMtx);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync return ENXIO;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync }
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync pState->Process = RTProcSelf();
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync *pDev = makedevice(getmajor(*pDev), iOpenInstance);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync NOREF(fFlag);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync NOREF(pCred);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync return 0;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync}
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsyncstatic int VBoxUSBMonSolarisClose(dev_t Dev, int fFlag, int fType, cred_t *pCred)
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync{
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync vboxusbmon_state_t *pState = NULL;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync LogFunc((DEVICE_NAME ":VBoxUSBMonSolarisClose\n"));
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync pState = ddi_get_soft_state(g_pVBoxUSBMonSolarisState, getminor(Dev));
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync if (!pState)
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync {
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync LogRel((DEVICE_NAME ":VBoxUSBMonSolarisClose: failed to get pState.\n"));
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync return EFAULT;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync }
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync mutex_enter(&g_VBoxUSBMonSolarisMtx);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync g_cVBoxUSBMonSolarisClient--;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync if (!g_cVBoxUSBMonSolarisClient)
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync {
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync if (RT_LIKELY(g_pDip))
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync {
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync mutex_exit(&g_VBoxUSBMonSolarisMtx);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync usb_unregister_dev_driver(g_pDip);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync Log((DEVICE_NAME ":Successfully deregistered driver election callback\n"));
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync }
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync else
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync {
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync mutex_exit(&g_VBoxUSBMonSolarisMtx);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync LogRel((DEVICE_NAME ":Extreme error! Missing device info during close.\n"));
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync }
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync }
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync else
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync mutex_exit(&g_VBoxUSBMonSolarisMtx);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync /*
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync * Remove all filters for this client process.
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync */
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync VBoxUSBFilterRemoveOwner(pState->Process);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync ddi_soft_state_free(g_pVBoxUSBMonSolarisState, getminor(Dev));
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync pState = NULL;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync NOREF(fFlag);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync NOREF(fType);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync NOREF(pCred);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync return 0;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync}
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsyncstatic int VBoxUSBMonSolarisRead(dev_t Dev, struct uio *pUio, cred_t *pCred)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync{
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogFunc((DEVICE_NAME ":VBoxUSBMonSolarisRead\n"));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync return 0;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync}
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsyncstatic int VBoxUSBMonSolarisWrite(dev_t Dev, struct uio *pUio, cred_t *pCred)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync{
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogFunc((DEVICE_NAME ":VBoxUSBMonSolarisWrite\n"));
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync return 0;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync}
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync/** @def IOCPARM_LEN
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * Gets the length from the ioctl number.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * This is normally defined by sys/ioccom.h on BSD systems...
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#ifndef IOCPARM_LEN
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync# define IOCPARM_LEN(Code) (((Code) >> 16) & IOCPARM_MASK)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#endif
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsyncstatic int VBoxUSBMonSolarisIOCtl(dev_t Dev, int Cmd, intptr_t pArg, int Mode, cred_t *pCred, int *pVal)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync{
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogFunc((DEVICE_NAME ":VBoxUSBMonSolarisIOCtl Dev=%d Cmd=%d pArg=%p Mode=%d\n", Dev, Cmd, pArg));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync /*
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * Get the session from the soft state item.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync vboxusbmon_state_t *pState = ddi_get_soft_state(g_pVBoxUSBMonSolarisState, getminor(Dev));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync if (!pState)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogRel((DEVICE_NAME ":VBoxUSBMonSolarisIOCtl: no state data for %d\n", getminor(Dev)));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync return EINVAL;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync /*
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * Read the request wrapper. Though We don't really need wrapper struct. now
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * it's room for the future as Solaris isn't generous regarding the size.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync VBOXUSBREQ ReqWrap;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync if (IOCPARM_LEN(Cmd) != sizeof(ReqWrap))
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogRel((DEVICE_NAME ": VBoxUSBMonSolarisIOCtl: bad request %#x size=%d expected=%d\n", Cmd, IOCPARM_LEN(Cmd), sizeof(ReqWrap)));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync return ENOTTY;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync int rc = ddi_copyin((void *)pArg, &ReqWrap, sizeof(ReqWrap), Mode);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync if (RT_UNLIKELY(rc))
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogRel((DEVICE_NAME ": VBoxUSBMonSolarisIOCtl: ddi_copyin failed to read header pArg=%p Cmd=%d. rc=%d.\n", pArg, Cmd, rc));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync return EINVAL;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync if (ReqWrap.u32Magic != VBOXUSBMON_MAGIC)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogRel((DEVICE_NAME ": VBoxUSBMonSolarisIOCtl: bad magic %#x; pArg=%p Cmd=%d.\n", ReqWrap.u32Magic, pArg, Cmd));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync return EINVAL;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync }
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync if (RT_UNLIKELY( ReqWrap.cbData == 0
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync || ReqWrap.cbData > _1M*16))
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync {
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync LogRel((DEVICE_NAME ": VBoxUSBMonSolarisIOCtl: bad size %#x; pArg=%p Cmd=%d.\n", ReqWrap.cbData, pArg, Cmd));
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync return EINVAL;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync }
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync /*
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync * Read the request.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync void *pvBuf = RTMemTmpAlloc(ReqWrap.cbData);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync if (RT_UNLIKELY(!pvBuf))
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogRel((DEVICE_NAME ":VBoxUSBMonSolarisIOCtl: RTMemTmpAlloc failed to alloc %d bytes.\n", ReqWrap.cbData));
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync return ENOMEM;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync rc = ddi_copyin((void *)(uintptr_t)ReqWrap.pvDataR3, pvBuf, ReqWrap.cbData, Mode);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync if (RT_UNLIKELY(rc))
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync RTMemTmpFree(pvBuf);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogRel((DEVICE_NAME ":VBoxUSBMonSolarisIOCtl: ddi_copyin failed; pvBuf=%p pArg=%p Cmd=%d. rc=%d\n", pvBuf, pArg, Cmd, rc));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync return EFAULT;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync if (RT_UNLIKELY( ReqWrap.cbData != 0
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync && !VALID_PTR(pvBuf)))
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync RTMemTmpFree(pvBuf);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogRel((DEVICE_NAME ":VBoxUSBMonSolarisIOCtl: pvBuf invalid pointer %p\n", pvBuf));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync return EINVAL;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync Log((DEVICE_NAME ":VBoxUSBMonSolarisIOCtl: pid=%d.\n", (int)RTProcSelf()));
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync /*
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync * Process the IOCtl.
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync */
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync size_t cbDataReturned = 0;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync rc = vboxUSBMonSolarisProcessIOCtl(Cmd, pState, pvBuf, ReqWrap.cbData, &cbDataReturned);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync ReqWrap.rc = rc;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync rc = 0;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync if (RT_UNLIKELY(cbDataReturned > ReqWrap.cbData))
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync {
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync LogRel((DEVICE_NAME ":VBoxUSBMonSolarisIOCtl: too much output data %d expected %d\n", cbDataReturned, ReqWrap.cbData));
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync cbDataReturned = ReqWrap.cbData;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync }
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync ReqWrap.cbData = cbDataReturned;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync /*
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync * Copy the request back to user space.
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync */
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync rc = ddi_copyout(&ReqWrap, (void *)pArg, sizeof(ReqWrap), Mode);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync if (RT_LIKELY(!rc))
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync {
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync /*
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync * Copy the payload (if any) back to user space.
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync */
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync if (cbDataReturned > 0)
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync rc = ddi_copyout(pvBuf, (void *)(uintptr_t)ReqWrap.pvDataR3, cbDataReturned, Mode);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync if (RT_UNLIKELY(rc))
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogRel((DEVICE_NAME ":VBoxUSBMonSolarisIOCtl: ddi_copyout failed; pvBuf=%p pArg=%p Cmd=%d. rc=%d\n", pvBuf, pArg, Cmd, rc));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync rc = EFAULT;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync else
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogRel((DEVICE_NAME ":VBoxUSBMonSolarisIOCtl: ddi_copyout(1) failed pArg=%p Cmd=%d\n", pArg, Cmd));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync rc = EFAULT;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync *pVal = rc;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync RTMemTmpFree(pvBuf);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync return rc;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync}
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync/**
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * IOCtl processor for user to kernel and kernel to kernel communication.
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync *
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync * @returns VBox status code.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync *
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync * @param iFunction The requested function.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * @param pvState Opaque pointer to driver state used for getting ring-3 process (Id).
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * @param pvData The input/output data buffer. Can be NULL depending on the function.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * @param cbData The max size of the data buffer.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * @param pcbDataReturned Where to store the amount of returned data. Can be NULL.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsyncstatic int vboxUSBMonSolarisProcessIOCtl(int iFunction, void *pvState, void *pvData, size_t cbData, size_t *pcbReturnedData)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync{
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogFunc((DEVICE_NAME ":solarisUSBProcessIOCtl iFunction=%d pvBuf=%p cbBuf=%zu\n", iFunction, pvData, cbData));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync AssertPtrReturn(pvState, VERR_INVALID_POINTER);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync vboxusbmon_state_t *pState = (vboxusbmon_state_t *)pvState;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync int rc;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync#define CHECKRET_MIN_SIZE(mnemonic, cbMin) \
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync do { \
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync if (cbData < (cbMin)) \
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync { \
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogRel(("vboxUSBSolarisProcessIOCtl: " mnemonic ": cbData=%#zx (%zu) min is %#zx (%zu)\n", \
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync cbData, cbData, (size_t)(cbMin), (size_t)(cbMin))); \
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync return VERR_BUFFER_OVERFLOW; \
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync } \
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync if ((cbMin) != 0 && !VALID_PTR(pvData)) \
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync { \
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync LogRel(("vboxUSBSolarisProcessIOCtl: " mnemonic ": Invalid pointer %p\n", pvData)); \
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync return VERR_INVALID_POINTER; \
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync } \
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync } while (0)
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync switch (iFunction)
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync {
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync case VBOXUSBMON_IOCTL_ADD_FILTER:
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync {
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync CHECKRET_MIN_SIZE("ADD_FILTER", sizeof(VBOXUSBREQ_ADD_FILTER));
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync VBOXUSBREQ_ADD_FILTER *pReq = (VBOXUSBREQ_ADD_FILTER *)pvData;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync PUSBFILTER pFilter = (PUSBFILTER)&pReq->Filter;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync Log(("vboxUSBMonSolarisProcessIOCtl: idVendor=%#x idProduct=%#x bcdDevice=%#x bDeviceClass=%#x bDeviceSubClass=%#x bDeviceProtocol=%#x bBus=%#x bPort=%#x\n",
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync USBFilterGetNum(pFilter, USBFILTERIDX_VENDOR_ID),
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync USBFilterGetNum(pFilter, USBFILTERIDX_PRODUCT_ID),
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync USBFilterGetNum(pFilter, USBFILTERIDX_DEVICE_REV),
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync USBFilterGetNum(pFilter, USBFILTERIDX_DEVICE_CLASS),
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync USBFilterGetNum(pFilter, USBFILTERIDX_DEVICE_SUB_CLASS),
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync USBFilterGetNum(pFilter, USBFILTERIDX_DEVICE_PROTOCOL),
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync USBFilterGetNum(pFilter, USBFILTERIDX_BUS),
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync USBFilterGetNum(pFilter, USBFILTERIDX_PORT)));
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync Log(("vboxUSBMonSolarisProcessIOCtl: Manufacturer=%s Product=%s Serial=%s\n",
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync USBFilterGetString(pFilter, USBFILTERIDX_MANUFACTURER_STR) ? USBFilterGetString(pFilter, USBFILTERIDX_MANUFACTURER_STR) : "<null>",
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync USBFilterGetString(pFilter, USBFILTERIDX_PRODUCT_STR) ? USBFilterGetString(pFilter, USBFILTERIDX_PRODUCT_STR) : "<null>",
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync USBFilterGetString(pFilter, USBFILTERIDX_SERIAL_NUMBER_STR) ? USBFilterGetString(pFilter, USBFILTERIDX_SERIAL_NUMBER_STR) : "<null>"));
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync rc = USBFilterSetMustBePresent(pFilter, USBFILTERIDX_BUS, false /* fMustBePresent */); AssertRC(rc);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync rc = VBoxUSBFilterAdd(pFilter, pState->Process, &pReq->uId);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync *pcbReturnedData = cbData;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync Log((DEVICE_NAME ":vboxUSBMonSolarisProcessIOCtl: ADD_FILTER (Process:%d) returned %d\n", pState->Process, rc));
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync break;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync }
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync case VBOXUSBMON_IOCTL_REMOVE_FILTER:
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync {
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync CHECKRET_MIN_SIZE("REMOVE_FILTER", sizeof(VBOXUSBREQ_REMOVE_FILTER));
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync VBOXUSBREQ_REMOVE_FILTER *pReq = (VBOXUSBREQ_REMOVE_FILTER *)pvData;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync rc = VBoxUSBFilterRemove(pState->Process, (uintptr_t)pReq->uId);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync *pcbReturnedData = 0;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync Log((DEVICE_NAME ":vboxUSBMonSolarisProcessIOCtl: REMOVE_FILTER (Process:%d) returned %d\n", pState->Process, rc));
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync break;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync }
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync case VBOXUSBMON_IOCTL_RESET_DEVICE:
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync {
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync CHECKRET_MIN_SIZE("RESET_DEVICE", sizeof(VBOXUSBREQ_RESET_DEVICE));
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync VBOXUSBREQ_RESET_DEVICE *pReq = (VBOXUSBREQ_RESET_DEVICE *)pvData;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync rc = vboxUSBMonSolarisResetDevice(pReq->szDevicePath, pReq->fReattach);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync *pcbReturnedData = 0;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync Log((DEVICE_NAME ":vboxUSBMonSolarisProcessIOCtl: RESET_DEVICE (Process:%d) returned %d\n", pState->Process, rc));
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync break;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync }
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync case VBOXUSBMON_IOCTL_CLIENT_INFO:
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync {
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync CHECKRET_MIN_SIZE("CLIENT_INFO", sizeof(VBOXUSBREQ_CLIENT_INFO));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync VBOXUSBREQ_CLIENT_INFO *pReq = (VBOXUSBREQ_CLIENT_INFO *)pvData;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync rc = vboxUSBMonSolarisClientInfo(pState, pReq);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync *pcbReturnedData = cbData;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync Log((DEVICE_NAME ":vboxUSBMonSolarisProcessIOCtl: CLIENT_INFO (Process:%d) returned %d\n", pState->Process, rc));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync break;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync case VBOXUSBMON_IOCTL_GET_VERSION:
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync CHECKRET_MIN_SIZE("GET_VERSION", sizeof(VBOXUSBREQ_GET_VERSION));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync PVBOXUSBREQ_GET_VERSION pGetVersionReq = (PVBOXUSBREQ_GET_VERSION)pvData;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync pGetVersionReq->u32Major = VBOXUSBMON_VERSION_MAJOR;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync pGetVersionReq->u32Minor = VBOXUSBMON_VERSION_MINOR;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync *pcbReturnedData = sizeof(VBOXUSBREQ_GET_VERSION);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync rc = VINF_SUCCESS;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync Log((DEVICE_NAME ":vboxUSBMonSolarisProcessIOCtl: GET_VERSION returned %d\n", rc));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync break;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync default:
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogRel((DEVICE_NAME ":vboxUSBMonSolarisProcessIOCtl: Unknown request (Process:%d) %#x\n", pState->Process, iFunction));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync *pcbReturnedData = 0;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync rc = VERR_NOT_SUPPORTED;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync break;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync }
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync return rc;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync}
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsyncstatic int vboxUSBMonSolarisResetDevice(char *pszDevicePath, bool fReattach)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync{
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync int rc = VERR_GENERAL_FAILURE;
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync LogFunc((DEVICE_NAME ":vboxUSBMonSolarisResetDevice pszDevicePath=%s fReattach=%d\n", pszDevicePath, fReattach));
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync /*
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync * Try grabbing the dev_info_t.
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync */
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync dev_info_t *pDeviceInfo = e_ddi_hold_devi_by_path(pszDevicePath, 0);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync if (pDeviceInfo)
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync {
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync ddi_release_devi(pDeviceInfo);
0560d845b0638cde2d51fe9ba84b4847eb9fbb47vboxsync
/*
* Grab the root device node from the parent hub for resetting.
*/
dev_info_t *pTmpDeviceInfo = NULL;
for (;;)
{
pTmpDeviceInfo = ddi_get_parent(pDeviceInfo);
if (!pTmpDeviceInfo)
{
LogRel((DEVICE_NAME ":vboxUSBMonSolarisResetDevice failed to get parent device info for %s\n", pszDevicePath));
return VERR_GENERAL_FAILURE;
}
if (ddi_prop_exists(DDI_DEV_T_ANY, pTmpDeviceInfo, DDI_PROP_DONTPASS, "usb-port-count")) /* parent hub */
break;
pDeviceInfo = pTmpDeviceInfo;
}
/*
* Try re-enumerating the device.
*/
rc = usb_reset_device(pDeviceInfo, fReattach ? USB_RESET_LVL_REATTACH : USB_RESET_LVL_DEFAULT);
Log((DEVICE_NAME ":usb_reset_device for %s level=%s returned %d\n", pszDevicePath, fReattach ? "ReAttach" : "Default", rc));
switch (rc)
{
case USB_SUCCESS: rc = VINF_SUCCESS; break;
case USB_INVALID_PERM: rc = VERR_PERMISSION_DENIED; break;
case USB_INVALID_ARGS: rc = VERR_INVALID_PARAMETER; break;
case USB_BUSY: rc = VERR_RESOURCE_BUSY; break;
case USB_INVALID_CONTEXT: rc = VERR_INVALID_CONTEXT; break;
case USB_FAILURE: rc = VERR_GENERAL_FAILURE; break;
default: rc = VERR_UNRESOLVED_ERROR; break;
}
}
else
{
rc = VERR_INVALID_HANDLE;
LogRel((DEVICE_NAME ":vboxUSBMonSolarisResetDevice Cannot obtain device info for %s\n", pszDevicePath));
}
return rc;
}
/**
* Query client driver information. This also has a side-effect that it informs
* the client driver which upcoming VM process should be allowed to open it.
*
* @returns VBox status code.
* @param pState Pointer to the device state.
* @param pClientInfo Pointer to the client info. object.
*/
static int vboxUSBMonSolarisClientInfo(vboxusbmon_state_t *pState, PVBOXUSB_CLIENT_INFO pClientInfo)
{
LogFunc((DEVICE_NAME ":vboxUSBMonSolarisClientInfo pState=%p pClientInfo=%p\n", pState, pClientInfo));
AssertPtrReturn(pState, VERR_INVALID_POINTER);
AssertPtrReturn(pClientInfo, VERR_INVALID_POINTER);
mutex_enter(&g_VBoxUSBMonSolarisMtx);
vboxusbmon_client_t *pCur = g_pVBoxUSBMonSolarisClients;
vboxusbmon_client_t *pPrev = NULL;
while (pCur)
{
if (strncmp(pClientInfo->szDeviceIdent, pCur->Info.szDeviceIdent, sizeof(pCur->Info.szDeviceIdent) - 1) == 0)
{
pClientInfo->Instance = pCur->Info.Instance;
RTStrPrintf(pClientInfo->szClientPath, sizeof(pClientInfo->szClientPath), "%s", pCur->Info.szClientPath);
/*
* Inform the client driver that this is the client process that is going to open it. We can predict the future!
*/
int rc;
if (pCur->Info.pfnSetConsumerCredentials)
{
rc = pCur->Info.pfnSetConsumerCredentials(pState->Process, pCur->Info.Instance, NULL /* pvReserved */);
if (RT_FAILURE(rc))
LogRel((DEVICE_NAME ":vboxUSBMonSolarisClientInfo pfnSetConsumerCredentials failed. rc=%d\n", rc));
}
else
rc = VERR_INVALID_FUNCTION;
mutex_exit(&g_VBoxUSBMonSolarisMtx);
Log((DEVICE_NAME ":vboxUSBMonSolarisClientInfo found. %s rc=%d\n", pClientInfo->szDeviceIdent, rc));
return rc;
}
pPrev = pCur;
pCur = pCur->pNext;
}
mutex_exit(&g_VBoxUSBMonSolarisMtx);
LogRel((DEVICE_NAME ":vboxUSBMonSolarisClientInfo Failed to find client %s\n", pClientInfo->szDeviceIdent));
return VERR_NOT_FOUND;
}
/**
* Registers client driver.
*
* @returns VBox status code.
* @param pszDevicePath The device path of the client driver.
* @param Instance The client driver instance.
*/
int VBoxUSBMonSolarisRegisterClient(dev_info_t *pClientDip, PVBOXUSB_CLIENT_INFO pClientInfo)
{
LogFunc((DEVICE_NAME ":VBoxUSBMonSolarisRegisterClient pClientDip=%p pClientInfo=%p\n", pClientDip, pClientInfo));
AssertPtrReturn(pClientInfo, VERR_INVALID_PARAMETER);
if (RT_LIKELY(g_pDip))
{
vboxusbmon_client_t *pClient = RTMemAllocZ(sizeof(vboxusbmon_client_t));
if (RT_LIKELY(pClient))
{
pClient->Info.Instance = pClientInfo->Instance;
strncpy(pClient->Info.szClientPath, pClientInfo->szClientPath, sizeof(pClient->Info.szClientPath));
strncpy(pClient->Info.szDeviceIdent, pClientInfo->szDeviceIdent, sizeof(pClient->Info.szDeviceIdent));
pClient->Info.pfnSetConsumerCredentials = pClientInfo->pfnSetConsumerCredentials;
pClient->pDip = pClientDip;
mutex_enter(&g_VBoxUSBMonSolarisMtx);
pClient->pNext = g_pVBoxUSBMonSolarisClients;
g_pVBoxUSBMonSolarisClients = pClient;
mutex_exit(&g_VBoxUSBMonSolarisMtx);
Log((DEVICE_NAME ":VBoxUSBMonSolarisRegisterClient registered. %d %s %s\n",
pClient->Info.Instance, pClient->Info.szClientPath, pClient->Info.szDeviceIdent));
return VINF_SUCCESS;
}
else
return VERR_NO_MEMORY;
}
else
return VERR_INVALID_STATE;
}
/**
* Deregisters client driver.
*
* @returns VBox status code.
* @param pszDevicePath The device path of the client driver.
* @param Instance The client driver instance.
*/
int VBoxUSBMonSolarisUnregisterClient(dev_info_t *pClientDip)
{
LogFunc((DEVICE_NAME ":VBoxUSBMonSolarisUnregisterClient pClientDip=%p\n", pClientDip));
AssertReturn(pClientDip, VERR_INVALID_PARAMETER);
if (RT_LIKELY(g_pDip))
{
mutex_enter(&g_VBoxUSBMonSolarisMtx);
vboxusbmon_client_t *pCur = g_pVBoxUSBMonSolarisClients;
vboxusbmon_client_t *pPrev = NULL;
while (pCur)
{
if (pCur->pDip == pClientDip)
{
if (pPrev)
pPrev->pNext = pCur->pNext;
else
g_pVBoxUSBMonSolarisClients = pCur->pNext;
mutex_exit(&g_VBoxUSBMonSolarisMtx);
Log((DEVICE_NAME ":VBoxUSBMonSolarisUnregisterClient unregistered. %d %s %s\n",
pCur->Info.Instance, pCur->Info.szClientPath, pCur->Info.szDeviceIdent));
RTMemFree(pCur);
pCur = NULL;
return VINF_SUCCESS;
}
pPrev = pCur;
pCur = pCur->pNext;
}
mutex_exit(&g_VBoxUSBMonSolarisMtx);
LogRel((DEVICE_NAME ":VBoxUSBMonSolarisUnregisterClient Failed to find registered client %p\n", pClientDip));
return VERR_NOT_FOUND;
}
else
return VERR_INVALID_STATE;
}
/**
* USBA driver election callback.
*
* @returns USB_SUCCESS if we want to capture the device, USB_FAILURE otherwise.
* @param pDevDesc The parsed device descriptor (does not include subconfigs).
* @param pDevStrings Device strings: Manufacturer, Product, Serial Number.
* @param pszDevicePath The physical path of the device being attached.
* @param Bus The Bus number on which the device is on.
* @param Port The Port number on the bus.
* @param ppszDrv The name of the driver we wish to capture the device with.
* @param pvReserved Reserved for future use.
*/
int VBoxUSBMonSolarisElectDriver(usb_dev_descr_t *pDevDesc, usb_dev_str_t *pDevStrings, char *pszDevicePath, int Bus, int Port,
char **ppszDrv, void *pvReserved)
{
LogFunc((DEVICE_NAME ":VBoxUSBMonSolarisElectDriver pDevDesc=%p pDevStrings=%p pszDevicePath=%s Bus=%d Port=%d\n", pDevDesc,
pDevStrings, pszDevicePath, Bus, Port));
AssertPtrReturn(pDevDesc, USB_FAILURE);
AssertPtrReturn(pDevStrings, USB_FAILURE);
/*
* Create a filter from the device being attached.
*/
USBFILTER Filter;
USBFilterInit(&Filter, USBFILTERTYPE_CAPTURE);
USBFilterSetNumExact(&Filter, USBFILTERIDX_VENDOR_ID, pDevDesc->idVendor, true);
USBFilterSetNumExact(&Filter, USBFILTERIDX_PRODUCT_ID, pDevDesc->idProduct, true);
USBFilterSetNumExact(&Filter, USBFILTERIDX_DEVICE_REV, pDevDesc->bcdDevice, true);
USBFilterSetNumExact(&Filter, USBFILTERIDX_DEVICE_CLASS, pDevDesc->bDeviceClass, true);
USBFilterSetNumExact(&Filter, USBFILTERIDX_DEVICE_SUB_CLASS, pDevDesc->bDeviceSubClass, true);
USBFilterSetNumExact(&Filter, USBFILTERIDX_DEVICE_PROTOCOL, pDevDesc->bDeviceProtocol, true);
USBFilterSetNumExact(&Filter, USBFILTERIDX_BUS, 0x0 /* Bus */, true); /* Use 0x0 as userland initFilterFromDevice function in Main: see comment on "SetMustBePresent" below */
USBFilterSetNumExact(&Filter, USBFILTERIDX_PORT, Port, true);
USBFilterSetStringExact(&Filter, USBFILTERIDX_MANUFACTURER_STR, pDevStrings->usb_mfg ? pDevStrings->usb_mfg : "", true);
USBFilterSetStringExact(&Filter, USBFILTERIDX_PRODUCT_STR, pDevStrings->usb_product ? pDevStrings->usb_product : "", true);
USBFilterSetStringExact(&Filter, USBFILTERIDX_SERIAL_NUMBER_STR, pDevStrings->usb_serialno ? pDevStrings->usb_serialno : "", true);
/* This doesn't work like it should (USBFilterMatch fails on matching field (6) i.e. Bus despite this. Investigate later. */
USBFilterSetMustBePresent(&Filter, USBFILTERIDX_BUS, false /* fMustBePresent */);
Log((DEVICE_NAME ":VBoxUSBMonSolarisElectDriver: idVendor=%#x idProduct=%#x bcdDevice=%#x bDeviceClass=%#x bDeviceSubClass=%#x bDeviceProtocol=%#x bBus=%#x bPort=%#x\n",
USBFilterGetNum(&Filter, USBFILTERIDX_VENDOR_ID),
USBFilterGetNum(&Filter, USBFILTERIDX_PRODUCT_ID),
USBFilterGetNum(&Filter, USBFILTERIDX_DEVICE_REV),
USBFilterGetNum(&Filter, USBFILTERIDX_DEVICE_CLASS),
USBFilterGetNum(&Filter, USBFILTERIDX_DEVICE_SUB_CLASS),
USBFilterGetNum(&Filter, USBFILTERIDX_DEVICE_PROTOCOL),
USBFilterGetNum(&Filter, USBFILTERIDX_BUS),
USBFilterGetNum(&Filter, USBFILTERIDX_PORT)));
Log((DEVICE_NAME ":VBoxUSBMonSolarisElectDriver: Manufacturer=%s Product=%s Serial=%s\n",
USBFilterGetString(&Filter, USBFILTERIDX_MANUFACTURER_STR) ? USBFilterGetString(&Filter, USBFILTERIDX_MANUFACTURER_STR) : "<null>",
USBFilterGetString(&Filter, USBFILTERIDX_PRODUCT_STR) ? USBFilterGetString(&Filter, USBFILTERIDX_PRODUCT_STR) : "<null>",
USBFilterGetString(&Filter, USBFILTERIDX_SERIAL_NUMBER_STR) ? USBFilterGetString(&Filter, USBFILTERIDX_SERIAL_NUMBER_STR) : "<null>"));
/*
* Run through user filters and try to see if it has a match.
*/
uintptr_t uId = 0;
RTPROCESS Owner = VBoxUSBFilterMatch(&Filter, &uId);
USBFilterDelete(&Filter);
if (Owner == NIL_RTPROCESS)
{
Log((DEVICE_NAME ":No matching filters, device %#x:%#x uninteresting.\n", pDevDesc->idVendor, pDevDesc->idProduct));
return USB_FAILURE;
}
*ppszDrv = ddi_strdup(VBOXUSB_DRIVER_NAME, KM_SLEEP);
LogRel((DEVICE_NAME ": Capturing %s %#x:%#x:%s\n", pDevStrings->usb_product ? pDevStrings->usb_product : "<Unnamed USB device>",
pDevDesc->idVendor, pDevDesc->idProduct, pszDevicePath));
return USB_SUCCESS;
}