VirtualBox

source: vbox/trunk/src/VBox/Additions/common/VBoxGuest/VBoxDev-haiku.c

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.7 KB
RevLine 
[43368]1/* $Id: VBoxDev-haiku.c 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBoxGuest kernel driver, Haiku Guest Additions, implementation.
4 */
5
6/*
[98103]7 * Copyright (C) 2012-2023 Oracle and/or its affiliates.
[43368]8 *
[96407]9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
[69308]11 *
[96407]12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
[69308]25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
[96407]27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
[69308]29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
[96407]33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
[43368]35 */
36
37/*
38 * This code is based on:
39 *
40 * VirtualBox Guest Additions for Haiku.
41 * Copyright (c) 2011 Mike Smith <mike@scgtrp.net>
[92181]42 * François Revol <revol@free.fr>
[43368]43 *
44 * Permission is hereby granted, free of charge, to any person
45 * obtaining a copy of this software and associated documentation
46 * files (the "Software"), to deal in the Software without
47 * restriction, including without limitation the rights to use,
48 * copy, modify, merge, publish, distribute, sublicense, and/or sell
49 * copies of the Software, and to permit persons to whom the
50 * Software is furnished to do so, subject to the following
51 * conditions:
52 *
53 * The above copyright notice and this permission notice shall be
54 * included in all copies or substantial portions of the Software.
55 *
56 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
57 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
58 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
59 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
60 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
61 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
62 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
63 * OTHER DEALINGS IN THE SOFTWARE.
64 */
65
[57358]66
67/*********************************************************************************************************************************
68* Header Files *
69*********************************************************************************************************************************/
[43368]70#include <sys/param.h>
71#include <sys/types.h>
72#include <sys/uio.h>
73#include <OS.h>
74#include <Drivers.h>
75#include <KernelExport.h>
76#include <PCI.h>
77
78#include "VBoxGuest-haiku.h"
79#include "VBoxGuestInternal.h"
80#include <VBox/log.h>
81#include <iprt/assert.h>
82#include <iprt/initterm.h>
83#include <iprt/process.h>
84#include <iprt/mem.h>
85#include <iprt/asm.h>
86
87#define DRIVER_NAME "vboxdev"
88#define DEVICE_NAME "misc/vboxguest"
89#define MODULE_NAME "generic/vboxguest"
90
[57358]91
92/*********************************************************************************************************************************
[58113]93* Global Variables *
[57358]94*********************************************************************************************************************************/
[58113]95int32 api_version = B_CUR_DRIVER_API_VERSION;
[43368]96
97
98/**
[43409]99 * Driver open hook.
[43368]100 *
[43409]101 * @param name The name of the device as returned by publish_devices.
102 * @param flags Open flags.
103 * @param cookie Where to store the session pointer.
104 *
105 * @return Haiku status code.
[43368]106 */
[58113]107static status_t vgdrvHaikuOpen(const char *name, uint32 flags, void **cookie)
[43368]108{
109 int rc;
110 PVBOXGUESTSESSION pSession;
111
[58113]112 LogFlow((DRIVER_NAME ":vgdrvHaikuOpen\n"));
[43368]113
114 /*
115 * Create a new session.
116 */
[70873]117 rc = VGDrvCommonCreateUserSession(&g_DevExt, VMMDEV_REQUESTOR_USERMODE, &pSession);
[43368]118 if (RT_SUCCESS(rc))
119 {
[58113]120 Log((DRIVER_NAME ":vgdrvHaikuOpen success: g_DevExt=%p pSession=%p rc=%d pid=%d\n",&g_DevExt, pSession, rc,(int)RTProcSelf()));
[43368]121 ASMAtomicIncU32(&cUsers);
122 *cookie = pSession;
[43409]123 return B_OK;
[43368]124 }
125
[58113]126 LogRel((DRIVER_NAME ":vgdrvHaikuOpen: failed. rc=%d\n", rc));
[43368]127 return RTErrConvertToErrno(rc);
128}
129
130
131/**
[43409]132 * Driver close hook.
133 * @param cookie The session.
[43368]134 *
[43409]135 * @return Haiku status code.
[43368]136 */
[58113]137static status_t vgdrvHaikuClose(void *cookie)
[43368]138{
139 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie;
[58113]140 Log(("vgdrvHaikuClose: pSession=%p\n", pSession));
[43368]141
[43369]142 /** @todo r=ramshankar: should we really be using the session spinlock here? */
143 RTSpinlockAcquire(g_DevExt.SessionSpinlock);
[43368]144
[63566]145 /** @todo we don't know if it belongs to this session!! */
[43368]146 if (sState.selectSync)
147 {
148 //dprintf(DRIVER_NAME "close: unblocking select %p %x\n", sState.selectSync, sState.selectEvent);
149 notify_select_event(sState.selectSync, sState.selectEvent);
150 sState.selectEvent = (uint8_t)0;
151 sState.selectRef = (uint32_t)0;
152 sState.selectSync = (void *)NULL;
153 }
154
[43369]155 RTSpinlockRelease(g_DevExt.SessionSpinlock);
[43409]156 return B_OK;
[43368]157}
158
159
160/**
[43409]161 * Driver free hook.
162 * @param cookie The session.
[43368]163 *
[43409]164 * @return Haiku status code.
[43368]165 */
[58113]166static status_t vgdrvHaikuFree(void *cookie)
[43368]167{
168 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie;
[58113]169 Log(("vgdrvHaikuFree: pSession=%p\n", pSession));
[43368]170
171 /*
172 * Close the session if it's still hanging on to the device...
173 */
[90794]174 if (RT_VALID_PTR(pSession))
[43368]175 {
[58053]176 VGDrvCommonCloseSession(&g_DevExt, pSession);
[43368]177 ASMAtomicDecU32(&cUsers);
178 }
179 else
[58113]180 Log(("vgdrvHaikuFree: si_drv1=%p!\n", pSession));
[43409]181 return B_OK;
[43368]182}
183
184
185/**
[43409]186 * Driver IOCtl entry.
187 * @param cookie The session.
188 * @param op The operation to perform.
189 * @param data The data associated with the operation.
190 * @param len Size of the data in bytes.
[43368]191 *
[43409]192 * @return Haiku status code.
[43368]193 */
[58113]194static status_t vgdrvHaikuIOCtl(void *cookie, uint32 op, void *data, size_t len)
[43368]195{
196 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie;
[58113]197 int rc;
198 Log(("vgdrvHaikuIOCtl: cookie=%p op=0x%08x data=%p len=%lu)\n", cookie, op, data, len));
[43368]199
200 /*
201 * Validate the input.
202 */
[90794]203 if (RT_UNLIKELY(!RT_VALID_PTR(pSession)))
[43368]204 return EINVAL;
205
206 /*
207 * Validate the request wrapper.
208 */
209#if 0
210 if (IOCPARM_LEN(ulCmd) != sizeof(VBGLBIGREQ))
211 {
[58113]212 Log((DRIVER_NAME ": vgdrvHaikuIOCtl: bad request %lu size=%lu expected=%d\n", ulCmd, IOCPARM_LEN(ulCmd),
[43409]213 sizeof(VBGLBIGREQ)));
[43368]214 return ENOTTY;
215 }
216#endif
217
218 if (RT_UNLIKELY(len > _1M * 16))
219 {
[58113]220 dprintf(DRIVER_NAME ": vgdrvHaikuIOCtl: bad size %#x; pArg=%p Cmd=%lu.\n", (unsigned)len, data, op);
[43368]221 return EINVAL;
222 }
223
224 /*
225 * Read the request.
226 */
227 void *pvBuf = NULL;
228 if (RT_LIKELY(len > 0))
229 {
230 pvBuf = RTMemTmpAlloc(len);
231 if (RT_UNLIKELY(!pvBuf))
232 {
[58113]233 LogRel((DRIVER_NAME ":vgdrvHaikuIOCtl: RTMemTmpAlloc failed to alloc %d bytes.\n", len));
[43368]234 return ENOMEM;
235 }
236
[43409]237 /** @todo r=ramshankar: replace with RTR0MemUserCopyFrom() */
[43368]238 rc = user_memcpy(pvBuf, data, len);
239 if (RT_UNLIKELY(rc < 0))
240 {
241 RTMemTmpFree(pvBuf);
[58113]242 LogRel((DRIVER_NAME ":vgdrvHaikuIOCtl: user_memcpy failed; pvBuf=%p data=%p op=%d. rc=%d\n", pvBuf, data, op, rc));
[43368]243 return EFAULT;
244 }
[90794]245 if (RT_UNLIKELY(!RT_VALID_PTR(pvBuf)))
[43368]246 {
247 RTMemTmpFree(pvBuf);
[58113]248 LogRel((DRIVER_NAME ":vgdrvHaikuIOCtl: pvBuf invalid pointer %p\n", pvBuf));
[43368]249 return EINVAL;
250 }
251 }
[58113]252 Log(("vgdrvHaikuIOCtl: pSession=%p pid=%d.\n", pSession,(int)RTProcSelf()));
[43368]253
254 /*
255 * Process the IOCtl.
256 */
257 size_t cbDataReturned;
[58053]258 rc = VGDrvCommonIoCtl(op, &g_DevExt, pSession, pvBuf, len, &cbDataReturned);
[43368]259 if (RT_SUCCESS(rc))
260 {
261 rc = 0;
262 if (RT_UNLIKELY(cbDataReturned > len))
263 {
[58113]264 Log(("vgdrvHaikuIOCtl: too much output data %d expected %d\n", cbDataReturned, len));
[43368]265 cbDataReturned = len;
266 }
267 if (cbDataReturned > 0)
268 {
269 rc = user_memcpy(data, pvBuf, cbDataReturned);
270 if (RT_UNLIKELY(rc < 0))
271 {
[58113]272 Log(("vgdrvHaikuIOCtl: user_memcpy failed; pvBuf=%p pArg=%p Cmd=%lu. rc=%d\n", pvBuf, data, op, rc));
[43368]273 rc = EFAULT;
274 }
275 }
276 }
277 else
278 {
[58113]279 Log(("vgdrvHaikuIOCtl: VGDrvCommonIoCtl failed. rc=%d\n", rc));
[43368]280 rc = EFAULT;
281 }
282 RTMemTmpFree(pvBuf);
283 return rc;
284}
285
286
[43409]287/**
288 * Driver select hook.
289 *
290 * @param cookie The session.
291 * @param event The event.
292 * @param ref ???
293 * @param sync ???
294 *
295 * @return Haiku status code.
296 */
[58113]297static status_t vgdrvHaikuSelect(void *cookie, uint8 event, uint32 ref, selectsync *sync)
[43368]298{
299 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie;
300 status_t err = B_OK;
301
302 switch (event)
303 {
304 case B_SELECT_READ:
305 break;
306 default:
307 return EINVAL;
308 }
309
[43369]310 RTSpinlockAcquire(g_DevExt.SessionSpinlock);
[43368]311
312 uint32_t u32CurSeq = ASMAtomicUoReadU32(&g_DevExt.u32MousePosChangedSeq);
313 if (pSession->u32MousePosChangedSeq != u32CurSeq)
314 {
315 pSession->u32MousePosChangedSeq = u32CurSeq;
316 notify_select_event(sync, event);
317 }
318 else if (sState.selectSync == NULL)
319 {
320 sState.selectEvent = (uint8_t)event;
321 sState.selectRef = (uint32_t)ref;
322 sState.selectSync = (void *)sync;
323 }
324 else
325 err = B_WOULD_BLOCK;
326
[43369]327 RTSpinlockRelease(g_DevExt.SessionSpinlock);
[43368]328
329 return err;
330}
331
332
[43409]333/**
334 * Driver deselect hook.
335 * @param cookie The session.
336 * @param event The event.
337 * @param sync ???
338 *
339 * @return Haiku status code.
340 */
[58113]341static status_t vgdrvHaikuDeselect(void *cookie, uint8 event, selectsync *sync)
[43368]342{
343 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie;
344 status_t err = B_OK;
345 //dprintf(DRIVER_NAME "deselect(,%d,%p)\n", event, sync);
346
[43369]347 RTSpinlockAcquire(g_DevExt.SessionSpinlock);
[43368]348
349 if (sState.selectSync == sync)
350 {
351 //dprintf(DRIVER_NAME "deselect: dropping: %p %x\n", sState.selectSync, sState.selectEvent);
352 sState.selectEvent = (uint8_t)0;
353 sState.selectRef = (uint32_t)0;
354 sState.selectSync = NULL;
355 }
356 else
357 err = B_OK;
358
[43369]359 RTSpinlockRelease(g_DevExt.SessionSpinlock);
[43368]360 return err;
361}
362
363
[43409]364/**
365 * Driver write hook.
366 * @param cookie The session.
367 * @param position The offset.
368 * @param data Pointer to the data.
369 * @param numBytes Where to store the number of bytes written.
370 *
371 * @return Haiku status code.
372 */
[58113]373static status_t vgdrvHaikuWrite(void *cookie, off_t position, const void *data, size_t *numBytes)
[43368]374{
375 *numBytes = 0;
[43409]376 return B_OK;
[43368]377}
378
379
[43409]380/**
381 * Driver read hook.
382 * @param cookie The session.
383 * @param position The offset.
384 * @param data Pointer to the data.
385 * @param numBytes Where to store the number of bytes read.
386 *
387 * @return Haiku status code.
388 */
[58113]389static status_t vgdrvHaikuRead(void *cookie, off_t position, void *data, size_t *numBytes)
[43368]390{
391 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie;
392
393 if (*numBytes == 0)
[43409]394 return B_OK;
[43368]395
396 uint32_t u32CurSeq = ASMAtomicUoReadU32(&g_DevExt.u32MousePosChangedSeq);
397 if (pSession->u32MousePosChangedSeq != u32CurSeq)
398 {
399 pSession->u32MousePosChangedSeq = u32CurSeq;
400 *numBytes = 1;
[43409]401 return B_OK;
[43368]402 }
403
404 *numBytes = 0;
[43409]405 return B_OK;
[43368]406}
407
408
409
410status_t init_hardware()
411{
412 return get_module(MODULE_NAME, (module_info **)&g_VBoxGuest);
413}
414
415status_t init_driver()
416{
417 return B_OK;
418}
419
[58113]420device_hooks *find_device(const char *name)
[43368]421{
[58113]422 static device_hooks s_vgdrvHaikuDeviceHooks =
[43368]423 {
[58113]424 vgdrvHaikuOpen,
425 vgdrvHaikuClose,
426 vgdrvHaikuFree,
427 vgdrvHaikuIOCtl,
428 vgdrvHaikuRead,
429 vgdrvHaikuWrite,
430 vgdrvHaikuSelect,
431 vgdrvHaikuDeselect,
[43368]432 };
[58113]433 return &s_vgdrvHaikuDeviceHooks;
[43368]434}
435
[58113]436const char **publish_devices()
[43368]437{
[58113]438 static const char *s_papszDevices[] = { DEVICE_NAME, NULL };
439 return s_papszDevices;
[43368]440}
441
442void uninit_driver()
443{
444 put_module(MODULE_NAME);
445}
446
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use