VirtualBox

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

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

Additions/Haiku: missed file.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.1 KB
Line 
1/* $Id: VBoxDev-haiku.c 43368 2012-09-20 13:02:45Z 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#define LOG_GROUP LOG_GROUP_SUP_DRV
49//#undef LOG_DISABLED
50//#define LOG_ENABLED
51//#define LOG_ENABLE_FLOW
52//#define DO_LOG
53#include <sys/param.h>
54#include <sys/types.h>
55#include <sys/uio.h>
56#include <OS.h>
57#include <Drivers.h>
58#include <KernelExport.h>
59#include <PCI.h>
60
61#include "VBoxGuest-haiku.h"
62#include "VBoxGuestInternal.h"
63#include <VBox/log.h>
64#include <iprt/assert.h>
65#include <iprt/initterm.h>
66#include <iprt/process.h>
67#include <iprt/mem.h>
68#include <iprt/asm.h>
69
70#define DRIVER_NAME "vboxdev"
71#define DEVICE_NAME "misc/vboxguest"
72#define MODULE_NAME "generic/vboxguest"
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 * File open handler
98 *
99 */
100static status_t VBoxGuestHaikuOpen(const char *name, uint32 flags, void **cookie)
101{
102 int rc;
103 PVBOXGUESTSESSION pSession;
104
105 LogFlow((DRIVER_NAME ":VBoxGuestHaikuOpen\n"));
106
107 /*
108 * Create a new session.
109 */
110 rc = VBoxGuestCreateUserSession(&g_DevExt, &pSession);
111 if (RT_SUCCESS(rc))
112 {
113 Log((DRIVER_NAME ":VBoxGuestHaikuOpen success: g_DevExt=%p pSession=%p rc=%d pid=%d\n",&g_DevExt, pSession, rc,(int)RTProcSelf()));
114 ASMAtomicIncU32(&cUsers);
115 *cookie = pSession;
116 return 0;
117 }
118
119 LogRel((DRIVER_NAME ":VBoxGuestHaikuOpen: failed. rc=%d\n", rc));
120 return RTErrConvertToErrno(rc);
121}
122
123
124/**
125 * File close handler
126 *
127 */
128static status_t VBoxGuestHaikuClose(void *cookie)
129{
130 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie;
131 RTSPINLOCKTMP tmp;
132 Log(("VBoxGuestHaikuClose: pSession=%p\n", pSession));
133
134 RTSpinlockAcquireNoInts(g_DevExt.SessionSpinlock, &tmp);
135
136 //XXX: we don't know if it belongs to this session !
137 if (sState.selectSync)
138 {
139 //dprintf(DRIVER_NAME "close: unblocking select %p %x\n", sState.selectSync, sState.selectEvent);
140 notify_select_event(sState.selectSync, sState.selectEvent);
141 sState.selectEvent = (uint8_t)0;
142 sState.selectRef = (uint32_t)0;
143 sState.selectSync = (void *)NULL;
144 }
145
146 RTSpinlockReleaseNoInts(g_DevExt.SessionSpinlock, &tmp);
147
148 return 0;
149}
150
151
152/**
153 * File free handler
154 *
155 */
156static status_t VBoxGuestHaikuFree(void *cookie)
157{
158 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie;
159 Log(("VBoxGuestHaikuFree: pSession=%p\n", pSession));
160
161 /*
162 * Close the session if it's still hanging on to the device...
163 */
164 if (VALID_PTR(pSession))
165 {
166 VBoxGuestCloseSession(&g_DevExt, pSession);
167 ASMAtomicDecU32(&cUsers);
168 }
169 else
170 Log(("VBoxGuestHaikuFree: si_drv1=%p!\n", pSession));
171 return 0;
172}
173
174
175/**
176 * IOCTL handler
177 *
178 */
179static status_t VBoxGuestHaikuIOCtl(void *cookie, uint32 op, void *data, size_t len)
180{
181 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie;
182 //Log(("VBoxGuestHaikuFree: pSession=%p\n", pSession));
183 //LogFlow((DRIVER_NAME ":VBoxGuestHaikuIOCtl(, 0x%08x, %p, %d)\n", op, data, len));
184 Log((DRIVER_NAME ":VBoxGuestHaikuIOCtl(, 0x%08x, %p, %d)\n", op, data, len));
185
186 int rc = 0;
187
188 /*
189 * Validate the input.
190 */
191 if (RT_UNLIKELY(!VALID_PTR(pSession)))
192 return EINVAL;
193
194 /*
195 * Validate the request wrapper.
196 */
197#if 0
198 if (IOCPARM_LEN(ulCmd) != sizeof(VBGLBIGREQ))
199 {
200 Log((DRIVER_NAME ": VBoxGuestHaikuIOCtl: bad request %lu size=%lu expected=%d\n", ulCmd, IOCPARM_LEN(ulCmd), sizeof(VBGLBIGREQ)));
201 return ENOTTY;
202 }
203#endif
204
205 if (RT_UNLIKELY(len > _1M * 16))
206 {
207 dprintf(DRIVER_NAME ": VBoxGuestHaikuIOCtl: bad size %#x; pArg=%p Cmd=%lu.\n", len, data, op);
208 return EINVAL;
209 }
210
211 /*
212 * Read the request.
213 */
214 void *pvBuf = NULL;
215 if (RT_LIKELY(len > 0))
216 {
217 pvBuf = RTMemTmpAlloc(len);
218 if (RT_UNLIKELY(!pvBuf))
219 {
220 LogRel((DRIVER_NAME ":VBoxGuestHaikuIOCtl: RTMemTmpAlloc failed to alloc %d bytes.\n", len));
221 return ENOMEM;
222 }
223
224 rc = user_memcpy(pvBuf, data, len);
225 if (RT_UNLIKELY(rc < 0))
226 {
227 RTMemTmpFree(pvBuf);
228 LogRel((DRIVER_NAME ":VBoxGuestHaikuIOCtl: user_memcpy failed; pvBuf=%p data=%p op=%d. rc=%d\n", pvBuf, data, op, rc));
229 return EFAULT;
230 }
231 if (RT_UNLIKELY(!VALID_PTR(pvBuf)))
232 {
233 RTMemTmpFree(pvBuf);
234 LogRel((DRIVER_NAME ":VBoxGuestHaikuIOCtl: pvBuf invalid pointer %p\n", pvBuf));
235 return EINVAL;
236 }
237 }
238 Log((DRIVER_NAME ":VBoxGuestHaikuIOCtl: pSession=%p pid=%d.\n", pSession,(int)RTProcSelf()));
239
240 /*
241 * Process the IOCtl.
242 */
243 size_t cbDataReturned;
244 rc = VBoxGuestCommonIOCtl(op, &g_DevExt, pSession, pvBuf, len, &cbDataReturned);
245 if (RT_SUCCESS(rc))
246 {
247 rc = 0;
248 if (RT_UNLIKELY(cbDataReturned > len))
249 {
250 Log((DRIVER_NAME ":VBoxGuestHaikuIOCtl: too much output data %d expected %d\n", cbDataReturned, len));
251 cbDataReturned = len;
252 }
253 if (cbDataReturned > 0)
254 {
255 rc = user_memcpy(data, pvBuf, cbDataReturned);
256 if (RT_UNLIKELY(rc < 0))
257 {
258 Log((DRIVER_NAME ":VBoxGuestHaikuIOCtl: user_memcpy failed; pvBuf=%p pArg=%p Cmd=%lu. rc=%d\n", pvBuf, data, op, rc));
259 rc = EFAULT;
260 }
261 }
262 }
263 else
264 {
265 Log((DRIVER_NAME ":VBoxGuestHaikuIOCtl: VBoxGuestCommonIOCtl failed. rc=%d\n", rc));
266 rc = EFAULT;
267 }
268 RTMemTmpFree(pvBuf);
269 return rc;
270#if 0
271#endif
272}
273
274
275static status_t VBoxGuestHaikuSelect(void *cookie, uint8 event, uint32 ref, selectsync *sync)
276{
277 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie;
278 RTSPINLOCKTMP tmp;
279 status_t err = B_OK;
280 //dprintf(DRIVER_NAME "select(,%d,%p)\n", event, sync);
281
282
283 switch (event)
284 {
285 case B_SELECT_READ:
286 //case B_SELECT_ERROR:
287 break;
288 default:
289 return EINVAL;
290 }
291
292 RTSpinlockAcquireNoInts(g_DevExt.SessionSpinlock, &tmp);
293
294 uint32_t u32CurSeq = ASMAtomicUoReadU32(&g_DevExt.u32MousePosChangedSeq);
295 if (pSession->u32MousePosChangedSeq != u32CurSeq)
296 {
297 //dprintf(DRIVER_NAME "select: notifying now: %p %x\n", sync, event);
298 pSession->u32MousePosChangedSeq = u32CurSeq;
299 notify_select_event(sync, event);
300 }
301 else if (sState.selectSync == NULL)
302 {
303 //dprintf(DRIVER_NAME "select: caching: %p %x\n", sync, event);
304 sState.selectEvent = (uint8_t)event;
305 sState.selectRef = (uint32_t)ref;
306 sState.selectSync = (void *)sync;
307 }
308 else
309 {
310 //dprintf(DRIVER_NAME "select: dropping: %p %x\n", sync, event);
311 err = B_WOULD_BLOCK;
312 }
313
314 RTSpinlockReleaseNoInts(g_DevExt.SessionSpinlock, &tmp);
315
316 return err;
317#if 0
318 int fEventsProcessed;
319
320 LogFlow((DRIVER_NAME "::Poll: fEvents=%d\n", fEvents));
321
322 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)pDev->si_drv1;
323 if (RT_UNLIKELY(!VALID_PTR(pSession)))
324 {
325 Log((DRIVER_NAME "::Poll: no state data for %s\n", devtoname(pDev)));
326 return (fEvents & (POLLHUP|POLLIN|POLLRDNORM|POLLOUT|POLLWRNORM));
327 }
328
329 uint32_t u32CurSeq = ASMAtomicUoReadU32(&g_DevExt.u32MousePosChangedSeq);
330 if (pSession->u32MousePosChangedSeq != u32CurSeq)
331 {
332 fEventsProcessed = fEvents & (POLLIN | POLLRDNORM);
333 pSession->u32MousePosChangedSeq = u32CurSeq;
334 }
335 else
336 {
337 fEventsProcessed = 0;
338
339 selrecord(td, &g_SelInfo);
340 }
341
342 return fEventsProcessed;
343#endif
344}
345
346
347static status_t VBoxGuestHaikuDeselect(void *cookie, uint8 event, selectsync *sync)
348{
349 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie;
350 RTSPINLOCKTMP tmp;
351 status_t err = B_OK;
352 //dprintf(DRIVER_NAME "deselect(,%d,%p)\n", event, sync);
353
354 RTSpinlockAcquireNoInts(g_DevExt.SessionSpinlock, &tmp);
355
356 if (sState.selectSync == sync)
357 {
358 //dprintf(DRIVER_NAME "deselect: dropping: %p %x\n", sState.selectSync, sState.selectEvent);
359 sState.selectEvent = (uint8_t)0;
360 sState.selectRef = (uint32_t)0;
361 sState.selectSync = NULL;
362 }
363 else
364 err = B_OK;
365
366 RTSpinlockReleaseNoInts(g_DevExt.SessionSpinlock, &tmp);
367 return err;
368}
369
370
371static status_t VBoxGuestHaikuWrite(void *cookie, off_t position, const void *data, size_t *numBytes)
372{
373 *numBytes = 0;
374 return 0;
375}
376
377
378static status_t VBoxGuestHaikuRead(void *cookie, off_t position, void *data, size_t *numBytes)
379{
380 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie;
381
382 //dprintf(DRIVER_NAME "read(,,%d)\n", *numBytes);
383
384 if (*numBytes == 0)
385 return 0;
386
387 uint32_t u32CurSeq = ASMAtomicUoReadU32(&g_DevExt.u32MousePosChangedSeq);
388 if (pSession->u32MousePosChangedSeq != u32CurSeq)
389 {
390 pSession->u32MousePosChangedSeq = u32CurSeq;
391 //dprintf(DRIVER_NAME "read: giving 1 byte\n");
392 *numBytes = 1;
393 return 0;
394 }
395
396 *numBytes = 0;
397 return 0;
398}
399
400
401int32 api_version = B_CUR_DRIVER_API_VERSION;
402
403status_t init_hardware()
404{
405 return get_module(MODULE_NAME, (module_info **)&g_VBoxGuest);
406}
407
408status_t init_driver()
409{
410 return B_OK;
411}
412
413device_hooks* find_device(const char *name)
414{
415 static device_hooks g_VBoxGuestHaikuDeviceHooks =
416 {
417 VBoxGuestHaikuOpen,
418 VBoxGuestHaikuClose,
419 VBoxGuestHaikuFree,
420 VBoxGuestHaikuIOCtl,
421 VBoxGuestHaikuRead,
422 VBoxGuestHaikuWrite,
423 VBoxGuestHaikuSelect,
424 VBoxGuestHaikuDeselect
425 };
426 return &g_VBoxGuestHaikuDeviceHooks;
427}
428
429const char** publish_devices()
430{
431 static const char *devices[] = { DEVICE_NAME, NULL };
432 return devices;
433}
434
435void uninit_driver()
436{
437 put_module(MODULE_NAME);
438}
439
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