VirtualBox

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

Last change on this file since 43409 was 43409, checked in by vboxsync, 12 years ago

Additions/haiku: cleanup.

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

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