Changeset 42031 in vbox for trunk/src/VBox
- Timestamp:
- Jul 5, 2012 8:02:43 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/solaris/Mouse/vboxmouse.c
r41852 r42031 25 25 */ 26 26 27 #define LOG_GROUP LOG_GROUP_DRV_MOUSE 27 28 28 29 /****************************************************************************** … … 30 31 ******************************************************************************/ 31 32 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 32 39 #ifndef TESTCASE 33 # include <sys/conf.h>34 40 # include <sys/modctl.h> 35 41 # include <sys/msio.h> 36 # include <sys/pci.h>37 42 # include <sys/stat.h> 38 43 # include <sys/ddi.h> 39 # include <sys/ddi_intr.h>40 # include <sys/open.h>41 44 # include <sys/strsun.h> 42 45 # include <sys/stropts.h> 43 46 # include <sys/sunddi.h> 44 # include <sys/sunldi.h>45 47 # include <sys/vuid_event.h> 46 48 # include <sys/vuid_wheel.h> 47 # include <sys/file.h>48 49 #undef u /* /usr/include/sys/user.h:249:1 is where this is defined to (curproc->p_user). very cool. */ 49 50 #else /* TESTCASE */ … … 52 53 #endif /* TESTCASE */ 53 54 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 67 55 #ifdef TESTCASE /* Include this last as we . */ 68 56 # include "testcase/solaris.h" … … 85 73 ******************************************************************************/ 86 74 75 static int vbmsSolAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd); 76 static int vbmsSolDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd); 77 static int vbmsSolGetInfo(dev_info_t *pDip, ddi_info_cmd_t enmCmd, void *pvArg, 78 void **ppvResult); 87 79 static int vbmsSolOpen(queue_t *pReadQueue, dev_t *pDev, int fFlag, 88 80 int fMode, cred_t *pCred); … … 156 148 157 149 /** 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 */ 152 static 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 */ 162 167 &g_vbmsSolStreamTab, 163 D_MP 168 D_MP, 169 CB_REV /* revision */ 164 170 }; 165 171 166 172 /** 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 */ 175 static 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 */ 193 static struct modldrv g_vbmsSolModule = 194 { 195 &mod_driverops, /* extern from kernel */ 172 196 DEVICE_DESC " " VBOX_VERSION_STRING "r" RT_XSTR(VBOX_SVN_REV), 173 &g_vbmsSol StrWrapper197 &g_vbmsSolDevOps 174 198 }; 175 199 … … 193 217 typedef struct 194 218 { 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; 195 226 /** The STREAMS write queue which we need for sending messages up to 196 227 * user-space. */ … … 222 253 int _init(void) 223 254 { 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. */ 275 static 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. */ 284 int _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. */ 297 int _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 */ 319 int 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 */ 358 int 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 */ 392 int 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 422 static void vbmsSolNotify(void *pvState); 423 static 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 */ 430 int 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 224 440 /* 225 441 * Initialize IPRT R0 driver, which internally calls OS-specific r0 init. 226 442 */ 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)) 241 449 { 242 450 cmn_err(CE_NOTE, "_init: VbglInit failed. rc=%d\n", rc); 243 451 return EINVAL; 244 452 } 245 246 LogRel((DEVICE_NAME ": initialisation returning %d.\n", rc));247 return rc;248 }249 250 251 #ifdef TESTCASE252 /** 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 #endif259 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 open295 * 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 307 453 /* 308 454 * Sanity check on the mode parameter - only open as a driver, not a … … 341 487 ASMAtomicWriteNullPtr(&pState->pWriteQueue); 342 488 343 LogRel((DEVICE_NAME "::Open: VBoxGuestCreateUserSession failed. rc= %d\n", rc));489 LogRel((DEVICE_NAME "::Open: VBoxGuestCreateUserSession failed. rc=EFAULT\n")); 344 490 return EFAULT; 345 491 } … … 357 503 int rc; 358 504 uint32_t x, y; 359 Log Flow((DEVICE_NAME "::NativeISRMousePollEvent:\n"));505 LogRelFlow((DEVICE_NAME "::NativeISRMousePollEvent:\n")); 360 506 361 507 rc = VbglGetMouseStatus(NULL, &x, &y); … … 408 554 PVBMSSTATE pState = (PVBMSSTATE)pReadQueue->q_ptr; 409 555 410 Log Flow((DEVICE_NAME "::Close\n"));556 LogRelFlow((DEVICE_NAME "::Close\n")); 411 557 NOREF(fFlag); 412 558 NOREF(pCred); … … 428 574 ASMAtomicWriteNullPtr(&pState->pWriteQueue); 429 575 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); 430 581 return 0; 431 582 } … … 899 1050 enum IOCTLDIRECTION enmDirection; 900 1051 901 Log FlowFunc((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)); 903 1054 switch (iCmdType) 904 1055 { … … 967 1118 struct iocblk *pIOCBlk = (struct iocblk *)pMBlk->b_rptr; 968 1119 1120 LogFlowFunc(("iCmd=0x%x, cbBuffer=%d, enmDirection=%d\n", 1121 (unsigned)iCmd, (int)cbTransparent, (int)enmDirection)); 969 1122 if (pMBlk->b_datap->db_type == M_IOCDATA) 970 1123 return vbmsSolHandleIOCtlData(pWriteQueue, pMBlk, pfnHandler, iCmd, … … 995 1148 PVBMSSTATE pState = (PVBMSSTATE)pWriteQueue->q_ptr; 996 1149 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)); 997 1154 if (pCopyResp->cp_rval) /* cp_rval is a pointer used as a boolean. */ 998 1155 { … … 1041 1198 PVBMSSTATE pState = (PVBMSSTATE)pWriteQueue->q_ptr; 1042 1199 1200 LogFlowFunc(("iCmd=0x%x, cbBuffer=%d, enmDirection=%d\n", 1201 (unsigned)iCmd, (int)cbTransparent, (int)enmDirection)); 1043 1202 if ( (enmDirection != NONE && !pMBlk->b_cont) 1044 1203 || enmDirection == UNSPECIFIED) … … 1091 1250 size_t cbData = 0; 1092 1251 1252 LogFlowFunc(("iCmd=0x%x, cbBuffer=%u, b_cont=%p\n", 1253 (unsigned)iCmd, cbBuffer, (void *)pMBlk->b_cont)); 1093 1254 if (cbBuffer && !pMBlk->b_cont) 1094 1255 return EINVAL; … … 1099 1260 if (err) 1100 1261 return err; 1262 } 1263 if (pMBlk->b_cont) /* consms forgets to set ioc_count. */ 1264 { 1101 1265 pvData = pMBlk->b_cont->b_rptr; 1266 cbBuffer = pMBlk->b_cont->b_wptr - pMBlk->b_cont->b_rptr; 1102 1267 } 1103 1268 err = pfnHandler(pState, iCmd, pvData, cbBuffer, &cbData, &rc); … … 1115 1280 size_t cbBuffer, size_t *pcbData, int *prc) 1116 1281 { 1117 Log FlowFunc((DEVICE_NAME ":: " /* no '\n' */));1282 LogRelFlowFunc((DEVICE_NAME ":: " /* no '\n' */)); 1118 1283 switch (iCmd) 1119 1284 { 1120 1285 case VUIDGFORMAT: 1121 1286 { 1122 Log FlowFunc(("VUIDGFORMAT\n"));1287 LogRelFlowFunc(("VUIDGFORMAT\n")); 1123 1288 if (cbBuffer < sizeof(int)) 1124 1289 return EINVAL; … … 1128 1293 } 1129 1294 case VUIDSFORMAT: 1130 Log FlowFunc(("VUIDSFORMAT\n"));1295 LogRelFlowFunc(("VUIDSFORMAT\n")); 1131 1296 /* We define our native format to be VUID_FIRM_EVENT, so there 1132 1297 * is nothing more to do and we exit here on success or on … … 1135 1300 case VUIDGADDR: 1136 1301 case VUIDSADDR: 1137 Log FlowFunc(("VUIDGADDR/VUIDSADDR\n"));1302 LogRelFlowFunc(("VUIDGADDR/VUIDSADDR\n")); 1138 1303 return ENOTTY; 1139 1304 case MSIOGETPARMS: … … 1141 1306 Ms_parms parms = { 0 }; 1142 1307 1143 Log FlowFunc(("MSIOGETPARMS\n"));1308 LogRelFlowFunc(("MSIOGETPARMS\n")); 1144 1309 if (cbBuffer < sizeof(Ms_parms)) 1145 1310 return EINVAL; … … 1149 1314 } 1150 1315 case MSIOSETPARMS: 1151 Log FlowFunc(("MSIOSETPARMS\n"));1316 LogRelFlowFunc(("MSIOSETPARMS\n")); 1152 1317 return 0; 1153 1318 case MSIOSRESOLUTION: … … 1156 1321 int rc; 1157 1322 1158 LogFlowFunc(("MSIOSRESOLUTION\n")); 1323 LogRelFlowFunc(("MSIOSRESOLUTION, cbBuffer=%d, sizeof(Ms_screen_resolution)=%d\n", 1324 (int) cbBuffer, 1325 (int) sizeof(Ms_screen_resolution))); 1159 1326 if (cbBuffer < sizeof(Ms_screen_resolution)) 1160 1327 return EINVAL; 1328 LogRelFlowFunc(("%dx%d\n", pResolution->width, 1329 pResolution->height)); 1161 1330 pState->cMaxScreenX = pResolution->width - 1; 1162 1331 pState->cMaxScreenY = pResolution->height - 1; … … 1172 1341 case MSIOBUTTONS: 1173 1342 { 1174 Log FlowFunc(("MSIOBUTTONS\n"));1343 LogRelFlowFunc(("MSIOBUTTONS\n")); 1175 1344 if (cbBuffer < sizeof(int)) 1176 1345 return EINVAL; … … 1181 1350 case VUIDGWHEELCOUNT: 1182 1351 { 1183 Log FlowFunc(("VUIDGWHEELCOUNT\n"));1352 LogRelFlowFunc(("VUIDGWHEELCOUNT\n")); 1184 1353 if (cbBuffer < sizeof(int)) 1185 1354 return EINVAL; … … 1191 1360 case VUIDGWHEELSTATE: 1192 1361 case VUIDSWHEELSTATE: 1193 Log FlowFunc(("VUIDGWHEELINFO/VUIDGWHEELSTATE/VUIDSWHEELSTATE\n"));1362 LogRelFlowFunc(("VUIDGWHEELINFO/VUIDGWHEELSTATE/VUIDSWHEELSTATE\n")); 1194 1363 return EINVAL; 1195 1364 default: 1196 Log FlowFunc(("Invalid IOCtl command %x\n", iCmd));1365 LogRelFlowFunc(("Invalid IOCtl command %x\n", iCmd)); 1197 1366 return EINVAL; 1198 1367 }
Note:
See TracChangeset
for help on using the changeset viewer.