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
Line 
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/*
7 * Copyright (C) 2012-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
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 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
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
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.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
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>
42 * François Revol <revol@free.fr>
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
66
67/*********************************************************************************************************************************
68* Header Files *
69*********************************************************************************************************************************/
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
91
92/*********************************************************************************************************************************
93* Global Variables *
94*********************************************************************************************************************************/
95int32 api_version = B_CUR_DRIVER_API_VERSION;
96
97
98/**
99 * Driver open hook.
100 *
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.
106 */
107static status_t vgdrvHaikuOpen(const char *name, uint32 flags, void **cookie)
108{
109 int rc;
110 PVBOXGUESTSESSION pSession;
111
112 LogFlow((DRIVER_NAME ":vgdrvHaikuOpen\n"));
113
114 /*
115 * Create a new session.
116 */
117 rc = VGDrvCommonCreateUserSession(&g_DevExt, VMMDEV_REQUESTOR_USERMODE, &pSession);
118 if (RT_SUCCESS(rc))
119 {
120 Log((DRIVER_NAME ":vgdrvHaikuOpen success: g_DevExt=%p pSession=%p rc=%d pid=%d\n",&g_DevExt, pSession, rc,(int)RTProcSelf()));
121 ASMAtomicIncU32(&cUsers);
122 *cookie = pSession;
123 return B_OK;
124 }
125
126 LogRel((DRIVER_NAME ":vgdrvHaikuOpen: failed. rc=%d\n", rc));
127 return RTErrConvertToErrno(rc);
128}
129
130
131/**
132 * Driver close hook.
133 * @param cookie The session.
134 *
135 * @return Haiku status code.
136 */
137static status_t vgdrvHaikuClose(void *cookie)
138{
139 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie;
140 Log(("vgdrvHaikuClose: pSession=%p\n", pSession));
141
142 /** @todo r=ramshankar: should we really be using the session spinlock here? */
143 RTSpinlockAcquire(g_DevExt.SessionSpinlock);
144
145 /** @todo we don't know if it belongs to this session!! */
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
155 RTSpinlockRelease(g_DevExt.SessionSpinlock);
156 return B_OK;
157}
158
159
160/**
161 * Driver free hook.
162 * @param cookie The session.
163 *
164 * @return Haiku status code.
165 */
166static status_t vgdrvHaikuFree(void *cookie)
167{
168 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie;
169 Log(("vgdrvHaikuFree: pSession=%p\n", pSession));
170
171 /*
172 * Close the session if it's still hanging on to the device...
173 */
174 if (RT_VALID_PTR(pSession))
175 {
176 VGDrvCommonCloseSession(&g_DevExt, pSession);
177 ASMAtomicDecU32(&cUsers);
178 }
179 else
180 Log(("vgdrvHaikuFree: si_drv1=%p!\n", pSession));
181 return B_OK;
182}
183
184
185/**
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.
191 *
192 * @return Haiku status code.
193 */
194static status_t vgdrvHaikuIOCtl(void *cookie, uint32 op, void *data, size_t len)
195{
196 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie;
197 int rc;
198 Log(("vgdrvHaikuIOCtl: cookie=%p op=0x%08x data=%p len=%lu)\n", cookie, op, data, len));
199
200 /*
201 * Validate the input.
202 */
203 if (RT_UNLIKELY(!RT_VALID_PTR(pSession)))
204 return EINVAL;
205
206 /*
207 * Validate the request wrapper.
208 */
209#if 0
210 if (IOCPARM_LEN(ulCmd) != sizeof(VBGLBIGREQ))
211 {
212 Log((DRIVER_NAME ": vgdrvHaikuIOCtl: bad request %lu size=%lu expected=%d\n", ulCmd, IOCPARM_LEN(ulCmd),
213 sizeof(VBGLBIGREQ)));
214 return ENOTTY;
215 }
216#endif
217
218 if (RT_UNLIKELY(len > _1M * 16))
219 {
220 dprintf(DRIVER_NAME ": vgdrvHaikuIOCtl: bad size %#x; pArg=%p Cmd=%lu.\n", (unsigned)len, data, op);
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 {
233 LogRel((DRIVER_NAME ":vgdrvHaikuIOCtl: RTMemTmpAlloc failed to alloc %d bytes.\n", len));
234 return ENOMEM;
235 }
236
237 /** @todo r=ramshankar: replace with RTR0MemUserCopyFrom() */
238 rc = user_memcpy(pvBuf, data, len);
239 if (RT_UNLIKELY(rc < 0))
240 {
241 RTMemTmpFree(pvBuf);
242 LogRel((DRIVER_NAME ":vgdrvHaikuIOCtl: user_memcpy failed; pvBuf=%p data=%p op=%d. rc=%d\n", pvBuf, data, op, rc));
243 return EFAULT;
244 }
245 if (RT_UNLIKELY(!RT_VALID_PTR(pvBuf)))
246 {
247 RTMemTmpFree(pvBuf);
248 LogRel((DRIVER_NAME ":vgdrvHaikuIOCtl: pvBuf invalid pointer %p\n", pvBuf));
249 return EINVAL;
250 }
251 }
252 Log(("vgdrvHaikuIOCtl: pSession=%p pid=%d.\n", pSession,(int)RTProcSelf()));
253
254 /*
255 * Process the IOCtl.
256 */
257 size_t cbDataReturned;
258 rc = VGDrvCommonIoCtl(op, &g_DevExt, pSession, pvBuf, len, &cbDataReturned);
259 if (RT_SUCCESS(rc))
260 {
261 rc = 0;
262 if (RT_UNLIKELY(cbDataReturned > len))
263 {
264 Log(("vgdrvHaikuIOCtl: too much output data %d expected %d\n", cbDataReturned, len));
265 cbDataReturned = len;
266 }
267 if (cbDataReturned > 0)
268 {
269 rc = user_memcpy(data, pvBuf, cbDataReturned);
270 if (RT_UNLIKELY(rc < 0))
271 {
272 Log(("vgdrvHaikuIOCtl: user_memcpy failed; pvBuf=%p pArg=%p Cmd=%lu. rc=%d\n", pvBuf, data, op, rc));
273 rc = EFAULT;
274 }
275 }
276 }
277 else
278 {
279 Log(("vgdrvHaikuIOCtl: VGDrvCommonIoCtl failed. rc=%d\n", rc));
280 rc = EFAULT;
281 }
282 RTMemTmpFree(pvBuf);
283 return rc;
284}
285
286
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 */
297static status_t vgdrvHaikuSelect(void *cookie, uint8 event, uint32 ref, selectsync *sync)
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
310 RTSpinlockAcquire(g_DevExt.SessionSpinlock);
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
327 RTSpinlockRelease(g_DevExt.SessionSpinlock);
328
329 return err;
330}
331
332
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 */
341static status_t vgdrvHaikuDeselect(void *cookie, uint8 event, selectsync *sync)
342{
343 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie;
344 status_t err = B_OK;
345 //dprintf(DRIVER_NAME "deselect(,%d,%p)\n", event, sync);
346
347 RTSpinlockAcquire(g_DevExt.SessionSpinlock);
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
359 RTSpinlockRelease(g_DevExt.SessionSpinlock);
360 return err;
361}
362
363
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 */
373static status_t vgdrvHaikuWrite(void *cookie, off_t position, const void *data, size_t *numBytes)
374{
375 *numBytes = 0;
376 return B_OK;
377}
378
379
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 */
389static status_t vgdrvHaikuRead(void *cookie, off_t position, void *data, size_t *numBytes)
390{
391 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie;
392
393 if (*numBytes == 0)
394 return B_OK;
395
396 uint32_t u32CurSeq = ASMAtomicUoReadU32(&g_DevExt.u32MousePosChangedSeq);
397 if (pSession->u32MousePosChangedSeq != u32CurSeq)
398 {
399 pSession->u32MousePosChangedSeq = u32CurSeq;
400 *numBytes = 1;
401 return B_OK;
402 }
403
404 *numBytes = 0;
405 return B_OK;
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
420device_hooks *find_device(const char *name)
421{
422 static device_hooks s_vgdrvHaikuDeviceHooks =
423 {
424 vgdrvHaikuOpen,
425 vgdrvHaikuClose,
426 vgdrvHaikuFree,
427 vgdrvHaikuIOCtl,
428 vgdrvHaikuRead,
429 vgdrvHaikuWrite,
430 vgdrvHaikuSelect,
431 vgdrvHaikuDeselect,
432 };
433 return &s_vgdrvHaikuDeviceHooks;
434}
435
436const char **publish_devices()
437{
438 static const char *s_papszDevices[] = { DEVICE_NAME, NULL };
439 return s_papszDevices;
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