~ubuntu-branches/ubuntu/raring/virtualbox-ose/raring

« back to all changes in this revision

Viewing changes to src/VBox/GuestHost/OpenGL/util/vboxhgcm.c

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2011-01-30 23:27:25 UTC
  • mfrom: (0.3.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20110130232725-2ouajjd2ggdet0zd
Tags: 4.0.2-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add Apport hook.
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Drop *-source packages.
* Drop ubuntu-01-fix-build-gcc45.patch, fixed upstream.
* Drop ubuntu-02-as-needed.patch, added to the Debian package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: vboxhgcm.c $ */
 
1
/* $Id: vboxhgcm.c 34887 2010-12-09 14:13:56Z vboxsync $ */
2
2
 
3
3
/** @file
4
4
 * VBox HGCM connection
15
15
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16
16
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17
17
 */
18
 
 
19
18
#ifdef RT_OS_WINDOWS
20
19
    #include <windows.h>
21
20
    #include <ddraw.h>
35
34
#include "cr_endian.h"
36
35
#include "cr_threads.h"
37
36
#include "net_internals.h"
 
37
#include "cr_process.h"
 
38
 
 
39
#include <iprt/thread.h>
38
40
 
39
41
#if 1 /** @todo Try use the Vbgl interface instead of talking directly to the driver? */
40
42
# include <VBox/VBoxGuest.h>
43
45
#endif
44
46
#include <VBox/HostServices/VBoxCrOpenGLSvc.h>
45
47
 
 
48
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
 
49
#include <VBox/VBoxCrHgsmi.h>
 
50
#endif
 
51
 
 
52
/*@todo move define somewhere else, and make sure it's less than VBGLR0_MAX_HGCM_KERNEL_PARM*/
 
53
/*If we fail to pass data in one chunk, send it in chunks of this size instead*/
 
54
#define CR_HGCM_SPLIT_BUFFER_SIZE (8*_1M)
 
55
 
 
56
#ifndef MIN
 
57
# define MIN(a, b) ((a) < (b) ? (a) : (b))
 
58
#endif
 
59
 
 
60
#ifdef DEBUG_misha
 
61
#ifdef CRASSERT
 
62
# undef CRASSERT
 
63
#endif
 
64
#define CRASSERT Assert
 
65
#endif
 
66
//#define IN_GUEST
 
67
//#if defined(IN_GUEST)
 
68
//#define VBOX_WITH_CRHGSMIPROFILE
 
69
//#endif
 
70
#ifdef VBOX_WITH_CRHGSMIPROFILE
 
71
#include <iprt/time.h>
 
72
#include <stdio.h>
 
73
 
 
74
typedef struct VBOXCRHGSMIPROFILE
 
75
{
 
76
    uint64_t cStartTime;
 
77
    uint64_t cStepsTime;
 
78
    uint64_t cSteps;
 
79
} VBOXCRHGSMIPROFILE, *PVBOXCRHGSMIPROFILE;
 
80
 
 
81
#define VBOXCRHGSMIPROFILE_GET_TIME_NANO() RTTimeNanoTS()
 
82
#define VBOXCRHGSMIPROFILE_GET_TIME_MILLI() RTTimeMilliTS()
 
83
 
 
84
/* 10 sec */
 
85
#define VBOXCRHGSMIPROFILE_LOG_STEP_TIME (10000000000.)
 
86
 
 
87
DECLINLINE(void) vboxCrHgsmiProfileStart(PVBOXCRHGSMIPROFILE pProfile)
 
88
{
 
89
    pProfile->cStepsTime = 0;
 
90
    pProfile->cSteps = 0;
 
91
    pProfile->cStartTime = VBOXCRHGSMIPROFILE_GET_TIME_NANO();
 
92
}
 
93
 
 
94
DECLINLINE(void) vboxCrHgsmiProfileStep(PVBOXCRHGSMIPROFILE pProfile, uint64_t cStepTime)
 
95
{
 
96
    pProfile->cStepsTime += cStepTime;
 
97
    ++pProfile->cSteps;
 
98
}
 
99
 
 
100
typedef struct VBOXCRHGSMIPROFILE_SCOPE
 
101
{
 
102
    uint64_t cStartTime;
 
103
//    bool bDisable;
 
104
} VBOXCRHGSMIPROFILE_SCOPE, *PVBOXCRHGSMIPROFILE_SCOPE;
 
105
 
 
106
static VBOXCRHGSMIPROFILE g_VBoxProfile;
 
107
 
 
108
static void vboxCrHgsmiLog(char * szString, ...)
 
109
{
 
110
    char szBuffer[4096] = {0};
 
111
     va_list pArgList;
 
112
     va_start(pArgList, szString);
 
113
     _vsnprintf(szBuffer, sizeof(szBuffer) / sizeof(szBuffer[0]), szString, pArgList);
 
114
     va_end(pArgList);
 
115
 
 
116
#ifdef VBOX_WITH_CRHGSMI
 
117
     VBoxCrHgsmiLog(szBuffer);
 
118
#else
 
119
     OutputDebugString(szBuffer);
 
120
#endif
 
121
}
 
122
 
 
123
DECLINLINE(void) vboxCrHgsmiProfileLog(PVBOXCRHGSMIPROFILE pProfile, uint64_t cTime)
 
124
{
 
125
    uint64_t profileTime = cTime - pProfile->cStartTime;
 
126
    double percent = ((double)100.0) * pProfile->cStepsTime / profileTime;
 
127
    double cps = ((double)1000000000.) * pProfile->cSteps / profileTime;
 
128
    vboxCrHgsmiLog("hgcm: cps: %.1f, host %.1f%%\n", cps, percent);
 
129
}
 
130
 
 
131
DECLINLINE(void) vboxCrHgsmiProfileScopeEnter(PVBOXCRHGSMIPROFILE_SCOPE pScope)
 
132
{
 
133
//    pScope->bDisable = false;
 
134
    pScope->cStartTime = VBOXCRHGSMIPROFILE_GET_TIME_NANO();
 
135
}
 
136
 
 
137
DECLINLINE(void) vboxCrHgsmiProfileScopeExit(PVBOXCRHGSMIPROFILE_SCOPE pScope)
 
138
{
 
139
//    if (!pScope->bDisable)
 
140
    {
 
141
        uint64_t cTime = VBOXCRHGSMIPROFILE_GET_TIME_NANO();
 
142
        vboxCrHgsmiProfileStep(&g_VBoxProfile, cTime - pScope->cStartTime);
 
143
        if (VBOXCRHGSMIPROFILE_LOG_STEP_TIME < cTime - g_VBoxProfile.cStartTime)
 
144
        {
 
145
            vboxCrHgsmiProfileLog(&g_VBoxProfile, cTime);
 
146
            vboxCrHgsmiProfileStart(&g_VBoxProfile);
 
147
        }
 
148
    }
 
149
}
 
150
 
 
151
 
 
152
#define VBOXCRHGSMIPROFILE_INIT() vboxCrHgsmiProfileStart(&g_VBoxProfile)
 
153
#define VBOXCRHGSMIPROFILE_TERM() do {} while (0)
 
154
 
 
155
#define VBOXCRHGSMIPROFILE_FUNC_PROLOGUE() \
 
156
        VBOXCRHGSMIPROFILE_SCOPE __vboxCrHgsmiProfileScope; \
 
157
        vboxCrHgsmiProfileScopeEnter(&__vboxCrHgsmiProfileScope);
 
158
 
 
159
#define VBOXCRHGSMIPROFILE_FUNC_EPILOGUE() \
 
160
        vboxCrHgsmiProfileScopeExit(&__vboxCrHgsmiProfileScope); \
 
161
 
 
162
 
 
163
#else
 
164
#define VBOXCRHGSMIPROFILE_INIT() do {} while (0)
 
165
#define VBOXCRHGSMIPROFILE_TERM() do {} while (0)
 
166
#define VBOXCRHGSMIPROFILE_FUNC_PROLOGUE() do {} while (0)
 
167
#define VBOXCRHGSMIPROFILE_FUNC_EPILOGUE() do {} while (0)
 
168
#endif
 
169
 
46
170
typedef struct {
47
171
    int                  initialized;
48
172
    int                  num_conns;
60
184
#else
61
185
    int                  iGuestDrv;
62
186
#endif
 
187
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
 
188
    bool bHgsmiOn;
 
189
#endif
63
190
} CRVBOXHGCMDATA;
64
191
 
65
192
static CRVBOXHGCMDATA g_crvboxhgcm = {0,};
71
198
#ifdef RT_OS_WINDOWS
72
199
    ,CR_VBOXHGCM_DDRAW_SURFACE
73
200
#endif
 
201
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
 
202
    ,CR_VBOXHGCM_UHGSMI_BUFFER
 
203
#endif
74
204
} CRVBOXHGCMBUFFERKIND;
75
205
 
76
206
#define CR_VBOXHGCM_BUFFER_MAGIC 0xABCDE321
78
208
typedef struct CRVBOXHGCMBUFFER {
79
209
    uint32_t             magic;
80
210
    CRVBOXHGCMBUFFERKIND kind;
81
 
    uint32_t             len;
82
 
    uint32_t             allocated;
 
211
    union
 
212
    {
 
213
        struct
 
214
        {
 
215
            uint32_t             len;
 
216
            uint32_t             allocated;
 
217
        };
 
218
 
 
219
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
 
220
        PVBOXUHGSMI_BUFFER pBuffer;
 
221
#endif
 
222
    };
83
223
#ifdef RT_OS_WINDOWS
84
224
    LPDIRECTDRAWSURFACE  pDDS;
85
225
#endif
91
231
    #define INVALID_HANDLE_VALUE (-1)
92
232
#endif
93
233
 
 
234
 
 
235
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
 
236
 
 
237
/* add sizeof header + page align */
 
238
#define CRVBOXHGSMI_PAGE_ALIGN(_s) (((_s)  + 0xfff) & ~0xfff)
 
239
#define CRVBOXHGSMI_BUF_HDR_SIZE() (sizeof (CRVBOXHGCMBUFFER))
 
240
#define CRVBOXHGSMI_BUF_SIZE(_s) CRVBOXHGSMI_PAGE_ALIGN((_s) + CRVBOXHGSMI_BUF_HDR_SIZE())
 
241
#define CRVBOXHGSMI_BUF_LOCK_SIZE(_s) ((_s) + CRVBOXHGSMI_BUF_HDR_SIZE())
 
242
#define CRVBOXHGSMI_BUF_DATA(_p) ((void*)(((CRVBOXHGCMBUFFER*)(_p)) + 1))
 
243
#define CRVBOXHGSMI_BUF_HDR(_p) (((CRVBOXHGCMBUFFER*)(_p)) - 1)
 
244
#define CRVBOXHGSMI_BUF_OFFSET(_st2, _st1) ((uint32_t)(((uint8_t*)(_st2)) - ((uint8_t*)(_st1))))
 
245
 
 
246
static int _crVBoxHGSMIClientInit(PCRVBOXHGSMI_CLIENT pClient, PVBOXUHGSMI pHgsmi)
 
247
{
 
248
    int rc;
 
249
    pClient->pHgsmi = pHgsmi;
 
250
    rc = pHgsmi->pfnBufferCreate(pHgsmi, CRVBOXHGSMI_PAGE_ALIGN(1),
 
251
                            VBOXUHGSMI_SYNCHOBJECT_TYPE_EVENT,
 
252
                            NULL,
 
253
                            &pClient->pCmdBuffer);
 
254
    AssertRC(rc);
 
255
    if (RT_SUCCESS(rc))
 
256
    {
 
257
        rc = pHgsmi->pfnBufferCreate(pHgsmi, CRVBOXHGSMI_PAGE_ALIGN(1),
 
258
                                        VBOXUHGSMI_SYNCHOBJECT_TYPE_EVENT,
 
259
                                        NULL,
 
260
                                        &pClient->pHGBuffer);
 
261
        AssertRC(rc);
 
262
        if (RT_SUCCESS(rc))
 
263
        {
 
264
            pClient->pvHGBuffer = NULL;
 
265
            pClient->bufpool = crBufferPoolInit(16);
 
266
            return VINF_SUCCESS;
 
267
        }
 
268
        pClient->pCmdBuffer->pfnDestroy(pClient->pCmdBuffer);
 
269
    }
 
270
    pClient->pHgsmi = NULL;
 
271
    return rc;
 
272
}
 
273
 
 
274
void _crVBoxHGSMIBufferFree(void *data)
 
275
{
 
276
    PVBOXUHGSMI_BUFFER pBuffer = (PVBOXUHGSMI_BUFFER)data;
 
277
    pBuffer->pfnDestroy(pBuffer);
 
278
}
 
279
 
 
280
static int _crVBoxHGSMIClientTerm(PCRVBOXHGSMI_CLIENT pClient, PVBOXUHGSMI *ppHgsmi)
 
281
{
 
282
    if (pClient->bufpool)
 
283
        crBufferPoolCallbackFree(pClient->bufpool, _crVBoxHGSMIBufferFree);
 
284
    pClient->bufpool = NULL;
 
285
 
 
286
    if (pClient->pHGBuffer)
 
287
    {
 
288
        pClient->pHGBuffer->pfnDestroy(pClient->pHGBuffer);
 
289
        pClient->pHGBuffer = NULL;
 
290
    }
 
291
 
 
292
    if (pClient->pCmdBuffer)
 
293
    {
 
294
        pClient->pCmdBuffer->pfnDestroy(pClient->pCmdBuffer);
 
295
        pClient->pCmdBuffer = NULL;
 
296
    }
 
297
 
 
298
    if (ppHgsmi)
 
299
    {
 
300
        *ppHgsmi = pClient->pHgsmi;
 
301
    }
 
302
    pClient->pHgsmi = NULL;
 
303
 
 
304
    return VINF_SUCCESS;
 
305
}
 
306
 
 
307
 
 
308
#ifdef VBOX_CRHGSMI_WITH_D3DDEV
 
309
 
 
310
DECLCALLBACK(HVBOXCRHGSMI_CLIENT) _crVBoxHGSMIClientCreate(PVBOXUHGSMI pHgsmi)
 
311
{
 
312
    PCRVBOXHGSMI_CLIENT pClient = crAlloc(sizeof (CRVBOXHGSMI_CLIENT));
 
313
 
 
314
    if (pClient)
 
315
    {
 
316
        int rc = _crVBoxHGSMIClientInit(pClient, pHgsmi);
 
317
        AssertRC(rc);
 
318
        if (RT_SUCCESS(rc))
 
319
            return (HVBOXCRHGSMI_CLIENT)pClient;
 
320
 
 
321
        crFree(pCLient);
 
322
    }
 
323
 
 
324
    return NULL;
 
325
}
 
326
 
 
327
DECLCALLBACK(void) _crVBoxHGSMIClientDestroy(HVBOXCRHGSMI_CLIENT hClient)
 
328
{
 
329
    PCRVBOXHGSMI_CLIENT pClient = (PCRVBOXHGSMI_CLIENT)hClient;
 
330
    _crVBoxHGSMIClientTerm(pClient, NULL);
 
331
    crFree(pClient);
 
332
}
 
333
#endif
 
334
 
 
335
DECLINLINE(PCRVBOXHGSMI_CLIENT) _crVBoxHGSMIClientGet(CRConnection *conn)
 
336
{
 
337
#ifdef VBOX_CRHGSMI_WITH_D3DDEV
 
338
    PCRVBOXHGSMI_CLIENT pClient = (PCRVBOXHGSMI_CLIENT)VBoxCrHgsmiQueryClient();
 
339
    Assert(pClient);
 
340
    return pClient;
 
341
#else
 
342
    if (conn->HgsmiClient.pHgsmi)
 
343
        return &conn->HgsmiClient;
 
344
    {
 
345
        PVBOXUHGSMI pHgsmi = VBoxCrHgsmiCreate();
 
346
        Assert(pHgsmi);
 
347
        if (pHgsmi)
 
348
        {
 
349
            int rc = _crVBoxHGSMIClientInit(&conn->HgsmiClient, pHgsmi);
 
350
            AssertRC(rc);
 
351
            if (RT_SUCCESS(rc))
 
352
            {
 
353
                Assert(conn->HgsmiClient.pHgsmi);
 
354
                return &conn->HgsmiClient;
 
355
            }
 
356
            VBoxCrHgsmiDestroy(pHgsmi);
 
357
        }
 
358
    }
 
359
    return NULL;
 
360
#endif
 
361
}
 
362
 
 
363
static PVBOXUHGSMI_BUFFER _crVBoxHGSMIBufAlloc(PCRVBOXHGSMI_CLIENT pClient, uint32_t cbSize)
 
364
{
 
365
    PVBOXUHGSMI_BUFFER buf;
 
366
    int rc;
 
367
 
 
368
    buf = (PVBOXUHGSMI_BUFFER ) crBufferPoolPop(pClient->bufpool, cbSize);
 
369
 
 
370
    if (!buf)
 
371
    {
 
372
        crDebug("Buffer pool %p was empty; allocating new %d byte buffer.",
 
373
                        (void *) pClient->bufpool,
 
374
                        cbSize);
 
375
        rc = pClient->pHgsmi->pfnBufferCreate(pClient->pHgsmi, cbSize,
 
376
                                VBOXUHGSMI_SYNCHOBJECT_TYPE_NONE, NULL,
 
377
                                &buf);
 
378
        AssertRC(rc);
 
379
        if (RT_FAILURE(rc))
 
380
            crWarning("Failed to Create a buffer of size(%d), rc(%d)\n", cbSize, rc);
 
381
    }
 
382
    return buf;
 
383
}
 
384
 
 
385
static PVBOXUHGSMI_BUFFER _crVBoxHGSMIBufFromHdr(CRVBOXHGCMBUFFER *pHdr)
 
386
{
 
387
    PVBOXUHGSMI_BUFFER pBuf;
 
388
    int rc;
 
389
    CRASSERT(pHdr->magic == CR_VBOXHGCM_BUFFER_MAGIC);
 
390
    CRASSERT(pHdr->kind == CR_VBOXHGCM_UHGSMI_BUFFER);
 
391
    pBuf = pHdr->pBuffer;
 
392
    rc = pBuf->pfnUnlock(pBuf);
 
393
    AssertRC(rc);
 
394
    if (RT_FAILURE(rc))
 
395
    {
 
396
        return NULL;
 
397
    }
 
398
    return pBuf;
 
399
}
 
400
 
 
401
static void _crVBoxHGSMIBufFree(PCRVBOXHGSMI_CLIENT pClient, PVBOXUHGSMI_BUFFER pBuf)
 
402
{
 
403
    crBufferPoolPush(pClient->bufpool, pBuf, pBuf->cbBuffer);
 
404
}
 
405
 
 
406
static CRVBOXHGSMIHDR *_crVBoxHGSMICmdBufferLock(PCRVBOXHGSMI_CLIENT pClient, uint32_t cbBuffer)
 
407
{
 
408
    /* in theory it is OK to use one cmd buffer for asynch cmd submission
 
409
     * because bDiscard flag should result in allocating a new memory backend if the
 
410
     * allocation is still in use.
 
411
     * However, NOTE: since one and the same semaphore synch event is used for completion notification,
 
412
     * for the notification mechanism working as expected
 
413
     * 1. host must complete commands in the same order as it receives them
 
414
     * (to avoid situation when guest receives notification for another command completion)
 
415
     * 2. guest must eventually wait for command completion unless he specified bDoNotSignalCompletion
 
416
     * 3. guest must wait for command completion in the same order as it submits them
 
417
     * in case we can not satisfy any of the above, we should introduce multiple command buffers */
 
418
    CRVBOXHGSMIHDR * pHdr;
 
419
    VBOXUHGSMI_BUFFER_LOCK_FLAGS fFlags;
 
420
    int rc;
 
421
    fFlags.Value = 0;
 
422
    fFlags.bDiscard = 1;
 
423
    rc = pClient->pCmdBuffer->pfnLock(pClient->pCmdBuffer, 0, cbBuffer, fFlags, (void**)&pHdr);
 
424
    AssertRC(rc);
 
425
    if (RT_SUCCESS(rc))
 
426
        return pHdr;
 
427
 
 
428
    crWarning("Failed to Lock the command buffer of size(%d), rc(%d)\n", cbBuffer, rc);
 
429
    return NULL;
 
430
}
 
431
 
 
432
static CRVBOXHGSMIHDR *_crVBoxHGSMICmdBufferLockRo(PCRVBOXHGSMI_CLIENT pClient, uint32_t cbBuffer)
 
433
{
 
434
    /* in theory it is OK to use one cmd buffer for asynch cmd submission
 
435
     * because bDiscard flag should result in allocating a new memory backend if the
 
436
     * allocation is still in use.
 
437
     * However, NOTE: since one and the same semaphore synch event is used for completion notification,
 
438
     * for the notification mechanism working as expected
 
439
     * 1. host must complete commands in the same order as it receives them
 
440
     * (to avoid situation when guest receives notification for another command completion)
 
441
     * 2. guest must eventually wait for command completion unless he specified bDoNotSignalCompletion
 
442
     * 3. guest must wait for command completion in the same order as it submits them
 
443
     * in case we can not satisfy any of the above, we should introduce multiple command buffers */
 
444
    CRVBOXHGSMIHDR * pHdr;
 
445
    VBOXUHGSMI_BUFFER_LOCK_FLAGS fFlags;
 
446
    int rc;
 
447
    fFlags.Value = 0;
 
448
    fFlags.bReadOnly = 1;
 
449
    rc = pClient->pCmdBuffer->pfnLock(pClient->pCmdBuffer, 0, cbBuffer, fFlags, (void**)&pHdr);
 
450
    AssertRC(rc);
 
451
    if (RT_FAILURE(rc))
 
452
        crWarning("Failed to Lock the command buffer of size(%d), rc(%d)\n", cbBuffer, rc);
 
453
    return pHdr;
 
454
}
 
455
 
 
456
static void _crVBoxHGSMICmdBufferUnlock(PCRVBOXHGSMI_CLIENT pClient)
 
457
{
 
458
    int rc = pClient->pCmdBuffer->pfnUnlock(pClient->pCmdBuffer);
 
459
    AssertRC(rc);
 
460
    if (RT_FAILURE(rc))
 
461
        crWarning("Failed to Unlock the command buffer rc(%d)\n", rc);
 
462
}
 
463
 
 
464
static int32_t _crVBoxHGSMICmdBufferGetRc(PCRVBOXHGSMI_CLIENT pClient)
 
465
{
 
466
    CRVBOXHGSMIHDR * pHdr;
 
467
    VBOXUHGSMI_BUFFER_LOCK_FLAGS fFlags;
 
468
    int rc;
 
469
 
 
470
    fFlags.Value = 0;
 
471
    fFlags.bReadOnly = 1;
 
472
    rc = pClient->pCmdBuffer->pfnLock(pClient->pCmdBuffer, 0, sizeof (*pHdr), fFlags, (void**)&pHdr);
 
473
    AssertRC(rc);
 
474
    if (RT_FAILURE(rc))
 
475
    {
 
476
        crWarning("Failed to Lock the command buffer of size(%d), rc(%d)\n", sizeof (*pHdr), rc);
 
477
        return rc;
 
478
    }
 
479
 
 
480
    rc = pHdr->result;
 
481
    AssertRC(rc);
 
482
    pClient->pCmdBuffer->pfnUnlock(pClient->pCmdBuffer);
 
483
 
 
484
    return rc;
 
485
}
 
486
 
 
487
DECLINLINE(PVBOXUHGSMI_BUFFER) _crVBoxHGSMIRecvBufGet(PCRVBOXHGSMI_CLIENT pClient)
 
488
{
 
489
    if (pClient->pvHGBuffer)
 
490
    {
 
491
        int rc = pClient->pHGBuffer->pfnUnlock(pClient->pHGBuffer);
 
492
        if (RT_FAILURE(rc))
 
493
        {
 
494
            return NULL;
 
495
        }
 
496
        pClient->pvHGBuffer = NULL;
 
497
    }
 
498
    return pClient->pHGBuffer;
 
499
}
 
500
 
 
501
DECLINLINE(void*) _crVBoxHGSMIRecvBufData(PCRVBOXHGSMI_CLIENT pClient, uint32_t cbBuffer)
 
502
{
 
503
    VBOXUHGSMI_BUFFER_LOCK_FLAGS fFlags;
 
504
    int rc;
 
505
    Assert(!pClient->pvHGBuffer);
 
506
    fFlags.Value = 0;
 
507
    rc = pClient->pHGBuffer->pfnLock(pClient->pHGBuffer, 0, cbBuffer, fFlags, &pClient->pvHGBuffer);
 
508
    AssertRC(rc);
 
509
    if (RT_SUCCESS(rc))
 
510
    {
 
511
        return pClient->pvHGBuffer;
 
512
    }
 
513
    return NULL;
 
514
}
 
515
 
 
516
DECLINLINE(void) _crVBoxHGSMIFillCmd(VBOXUHGSMI_BUFFER_SUBMIT *pSubm, PCRVBOXHGSMI_CLIENT pClient, uint32_t cbData)
 
517
{
 
518
    pSubm->pBuf = pClient->pCmdBuffer;
 
519
    pSubm->offData = 0;
 
520
    pSubm->cbData = cbData;
 
521
    pSubm->fFlags.Value = 0;
 
522
    pSubm->fFlags.bDoNotRetire = 1;
 
523
//    pSubm->fFlags.bDoNotSignalCompletion = 1; /* <- we do not need that actually since
 
524
//                                                       * in case we want completion,
 
525
//                                                       * we will block in _crVBoxHGSMICmdBufferGetRc (when locking the buffer)
 
526
//                                                       * which is needed for getting the result */
 
527
}
 
528
 
 
529
#ifdef RT_OS_WINDOWS
 
530
#define CRVBOXHGSMI_BUF_WAIT(_pBub) WaitForSingleObject((_pBub)->hSynch, INFINITE);
 
531
#else
 
532
# error "Port Me!!"
 
533
#endif
 
534
 
 
535
DECLINLINE(void) _crVBoxHGSMIWaitCmd(PCRVBOXHGSMI_CLIENT pClient)
 
536
{
 
537
    int rc = CRVBOXHGSMI_BUF_WAIT(pClient->pCmdBuffer);
 
538
    Assert(rc == 0);
 
539
}
 
540
#endif
 
541
 
94
542
/* Some forward declarations */
95
 
static void crVBoxHGCMReceiveMessage(CRConnection *conn);
 
543
static void _crVBoxHGCMReceiveMessage(CRConnection *conn);
96
544
 
97
545
#ifndef IN_GUEST
98
546
static bool _crVBoxHGCMReadBytes(CRConnection *conn, void *buf, uint32_t len)
121
569
 
122
570
    if (conn->cbHostBufferAllocated < len)
123
571
    {
124
 
        crDebug("Host buffer too small %d out of requsted %d bytes, reallocating", conn->cbHostBufferAllocated, len);
 
572
        crDebug("Host buffer too small %d out of requested %d bytes, reallocating", conn->cbHostBufferAllocated, len);
125
573
        crFree(conn->pHostBuffer);
126
574
        conn->pHostBuffer = crAlloc(len);
127
575
        if (!conn->pHostBuffer)
189
637
    }
190
638
#  ifdef RT_OS_LINUX
191
639
    if (rc >= 0) /* positive values are negated VBox error status codes. */
 
640
    {
192
641
        crWarning("vboxCall failed with VBox status code %d\n", -rc);
 
642
        if (rc==VINF_INTERRUPTED)
 
643
        {
 
644
            RTMSINTERVAL sl;
 
645
            int i;
 
646
 
 
647
            for (i=0, sl=50; i<6; i++, sl=sl*2)
 
648
            {
 
649
                RTThreadSleep(sl);
 
650
                rc = ioctl(g_crvboxhgcm.iGuestDrv, VBOXGUEST_IOCTL_HGCM_CALL(cbData), pvData);
 
651
                if (rc==0)
 
652
                {
 
653
                    crWarning("vboxCall retry(%i) succeeded", i+1);
 
654
                    return VINF_SUCCESS;
 
655
                }
 
656
                else if (rc==VINF_INTERRUPTED)
 
657
                {
 
658
                    continue;
 
659
                }
 
660
                else
 
661
                {
 
662
                    crWarning("vboxCall retry(%i) failed with VBox status code %d", i+1, -rc);
 
663
                    break;
 
664
                }
 
665
            }
 
666
        }
 
667
        return -rc;
 
668
    }
193
669
    else
194
670
#  endif
195
671
        crWarning("vboxCall failed with %x\n", errno);
203
679
#endif
204
680
}
205
681
 
206
 
static void *crVBoxHGCMAlloc(CRConnection *conn)
 
682
static void *_crVBoxHGCMAlloc(CRConnection *conn)
207
683
{
208
684
    CRVBOXHGCMBUFFER *buf;
209
685
 
328
804
 
329
805
}
330
806
 
 
807
static void *crVBoxHGCMAlloc(CRConnection *conn)
 
808
{
 
809
    void *pvBuff;
 
810
    VBOXCRHGSMIPROFILE_FUNC_PROLOGUE();
 
811
    pvBuff = _crVBoxHGCMAlloc(conn);
 
812
    VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
 
813
    return pvBuff;
 
814
}
 
815
 
 
816
static void _crVBoxHGCMWriteExact(CRConnection *conn, const void *buf, unsigned int len)
 
817
{
 
818
    int rc;
 
819
    int32_t callRes;
 
820
 
 
821
#ifdef IN_GUEST
 
822
    if (conn->u32InjectClientID)
 
823
    {
 
824
        CRVBOXHGCMINJECT parms;
 
825
 
 
826
        parms.hdr.result      = VERR_WRONG_ORDER;
 
827
        parms.hdr.u32ClientID = conn->u32ClientID;
 
828
        parms.hdr.u32Function = SHCRGL_GUEST_FN_INJECT;
 
829
        parms.hdr.cParms      = SHCRGL_CPARMS_INJECT;
 
830
 
 
831
        parms.u32ClientID.type       = VMMDevHGCMParmType_32bit;
 
832
        parms.u32ClientID.u.value32  = conn->u32InjectClientID;
 
833
 
 
834
        parms.pBuffer.type                   = VMMDevHGCMParmType_LinAddr_In;
 
835
        parms.pBuffer.u.Pointer.size         = len;
 
836
        parms.pBuffer.u.Pointer.u.linearAddr = (uintptr_t) buf;
 
837
 
 
838
        rc = crVBoxHGCMCall(&parms, sizeof(parms));
 
839
        callRes = parms.hdr.result;
 
840
    }
 
841
    else
 
842
#endif
 
843
    {
 
844
        CRVBOXHGCMWRITE parms;
 
845
 
 
846
        parms.hdr.result      = VERR_WRONG_ORDER;
 
847
        parms.hdr.u32ClientID = conn->u32ClientID;
 
848
        parms.hdr.u32Function = SHCRGL_GUEST_FN_WRITE;
 
849
        parms.hdr.cParms      = SHCRGL_CPARMS_WRITE;
 
850
 
 
851
        parms.pBuffer.type                   = VMMDevHGCMParmType_LinAddr_In;
 
852
        parms.pBuffer.u.Pointer.size         = len;
 
853
        parms.pBuffer.u.Pointer.u.linearAddr = (uintptr_t) buf;
 
854
 
 
855
        rc = crVBoxHGCMCall(&parms, sizeof(parms));
 
856
        callRes = parms.hdr.result;
 
857
    }
 
858
 
 
859
    if (RT_FAILURE(rc) || RT_FAILURE(callRes))
 
860
    {
 
861
        crWarning("SHCRGL_GUEST_FN_WRITE failed with %x %x\n", rc, callRes);
 
862
    }
 
863
}
 
864
 
331
865
static void crVBoxHGCMWriteExact(CRConnection *conn, const void *buf, unsigned int len)
332
866
{
333
 
    CRVBOXHGCMWRITE parms;
334
 
    int rc;
335
 
 
336
 
    parms.hdr.result      = VERR_WRONG_ORDER;
337
 
    parms.hdr.u32ClientID = conn->u32ClientID;
338
 
    parms.hdr.u32Function = SHCRGL_GUEST_FN_WRITE;
339
 
    parms.hdr.cParms      = SHCRGL_CPARMS_WRITE;
340
 
 
341
 
    parms.pBuffer.type                   = VMMDevHGCMParmType_LinAddr_In;
342
 
    parms.pBuffer.u.Pointer.size         = len;
343
 
    parms.pBuffer.u.Pointer.u.linearAddr = (uintptr_t) buf;
344
 
 
345
 
    rc = crVBoxHGCMCall(&parms, sizeof(parms));
346
 
 
347
 
    if (RT_FAILURE(rc) || RT_FAILURE(parms.hdr.result))
348
 
    {
349
 
        crWarning("SHCRGL_GUEST_FN_WRITE failed with %x %x\n", rc, parms.hdr.result);
350
 
    }
 
867
    VBOXCRHGSMIPROFILE_FUNC_PROLOGUE();
 
868
    _crVBoxHGCMWriteExact(conn, buf, len);
 
869
    VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
351
870
}
352
871
 
353
872
static void crVBoxHGCMReadExact( CRConnection *conn, const void *buf, unsigned int len )
384
903
    }
385
904
 
386
905
    if (conn->cbBuffer)
387
 
        crVBoxHGCMReceiveMessage(conn);
 
906
        _crVBoxHGCMReceiveMessage(conn);
388
907
 
389
908
}
390
909
 
426
945
 
427
946
    rc = crVBoxHGCMCall(&parms, sizeof(parms));
428
947
 
 
948
#ifdef RT_OS_LINUX
 
949
    if (VERR_OUT_OF_RANGE==rc && CR_VBOXHGCM_USERALLOCATED==bufferKind)
 
950
    {
 
951
        /*Buffer is too big, so send it in split chunks*/
 
952
        CRVBOXHGCMWRITEBUFFER wbParms;
 
953
 
 
954
        wbParms.hdr.result = VERR_WRONG_ORDER;
 
955
        wbParms.hdr.u32ClientID = conn->u32ClientID;
 
956
        wbParms.hdr.u32Function = SHCRGL_GUEST_FN_WRITE_BUFFER;
 
957
        wbParms.hdr.cParms = SHCRGL_CPARMS_WRITE_BUFFER;
 
958
 
 
959
        wbParms.iBufferID.type = VMMDevHGCMParmType_32bit;
 
960
        wbParms.iBufferID.u.value32 = 0;
 
961
 
 
962
        wbParms.cbBufferSize.type = VMMDevHGCMParmType_32bit;
 
963
        wbParms.cbBufferSize.u.value32 = len;
 
964
 
 
965
        wbParms.ui32Offset.type = VMMDevHGCMParmType_32bit;
 
966
        wbParms.ui32Offset.u.value32 = 0;
 
967
 
 
968
        wbParms.pBuffer.type = VMMDevHGCMParmType_LinAddr_In;
 
969
        wbParms.pBuffer.u.Pointer.size         = MIN(CR_HGCM_SPLIT_BUFFER_SIZE, len);
 
970
        wbParms.pBuffer.u.Pointer.u.linearAddr = (uintptr_t) buf;
 
971
 
 
972
        if (len<CR_HGCM_SPLIT_BUFFER_SIZE)
 
973
        {
 
974
            crError("VERR_OUT_OF_RANGE in crVBoxHGCMWriteReadExact for %u bytes write", len);
 
975
            return;
 
976
        }
 
977
 
 
978
        while (wbParms.pBuffer.u.Pointer.size)
 
979
        {
 
980
            crDebug("SHCRGL_GUEST_FN_WRITE_BUFFER, offset=%u, size=%u", wbParms.ui32Offset.u.value32, wbParms.pBuffer.u.Pointer.size);
 
981
 
 
982
            rc = crVBoxHGCMCall(&wbParms, sizeof(wbParms));
 
983
            if (RT_FAILURE(rc) || RT_FAILURE(wbParms.hdr.result))
 
984
            {
 
985
                crError("SHCRGL_GUEST_FN_WRITE_BUFFER (%i) failed with %x %x\n", wbParms.pBuffer.u.Pointer.size, rc, wbParms.hdr.result);
 
986
                return;
 
987
            }
 
988
 
 
989
            wbParms.ui32Offset.u.value32 += wbParms.pBuffer.u.Pointer.size;
 
990
            wbParms.pBuffer.u.Pointer.u.linearAddr += (uintptr_t) wbParms.pBuffer.u.Pointer.size;
 
991
            wbParms.pBuffer.u.Pointer.size = MIN(CR_HGCM_SPLIT_BUFFER_SIZE, len-wbParms.ui32Offset.u.value32);
 
992
        }
 
993
 
 
994
        /*now issue GUEST_FN_WRITE_READ_BUFFERED referencing the buffer we'd made*/
 
995
        {
 
996
            CRVBOXHGCMWRITEREADBUFFERED wrbParms;
 
997
 
 
998
            wrbParms.hdr.result = VERR_WRONG_ORDER;
 
999
            wrbParms.hdr.u32ClientID = conn->u32ClientID;
 
1000
            wrbParms.hdr.u32Function = SHCRGL_GUEST_FN_WRITE_READ_BUFFERED;
 
1001
            wrbParms.hdr.cParms = SHCRGL_CPARMS_WRITE_READ_BUFFERED;
 
1002
 
 
1003
            crMemcpy(&wrbParms.iBufferID, &wbParms.iBufferID, sizeof(HGCMFunctionParameter));
 
1004
            crMemcpy(&wrbParms.pWriteback, &parms.pWriteback, sizeof(HGCMFunctionParameter));
 
1005
            crMemcpy(&wrbParms.cbWriteback, &parms.cbWriteback, sizeof(HGCMFunctionParameter));
 
1006
 
 
1007
            rc = crVBoxHGCMCall(&wrbParms, sizeof(wrbParms));
 
1008
 
 
1009
            /*bit of hack to reuse code below*/
 
1010
            parms.hdr.result = wrbParms.hdr.result;
 
1011
            crMemcpy(&parms.cbWriteback, &wrbParms.cbWriteback, sizeof(HGCMFunctionParameter));
 
1012
            crMemcpy(&parms.pWriteback, &wrbParms.pWriteback, sizeof(HGCMFunctionParameter));
 
1013
        }
 
1014
    }
 
1015
#endif
 
1016
 
429
1017
    if (RT_FAILURE(rc) || RT_FAILURE(parms.hdr.result))
430
1018
    {
431
1019
 
460
1048
    }
461
1049
 
462
1050
    if (conn->cbBuffer)
463
 
        crVBoxHGCMReceiveMessage(conn);
 
1051
        _crVBoxHGCMReceiveMessage(conn);
464
1052
}
465
1053
 
466
1054
static void crVBoxHGCMSend(CRConnection *conn, void **bufp,
467
1055
                           const void *start, unsigned int len)
468
1056
{
469
1057
    CRVBOXHGCMBUFFER *hgcm_buffer;
 
1058
    VBOXCRHGSMIPROFILE_FUNC_PROLOGUE();
470
1059
 
471
1060
    if (!bufp) /* We're sending a user-allocated buffer. */
472
1061
    {
475
1064
            /* we're at the host side, so just store data until guest polls us */
476
1065
            _crVBoxHGCMWriteBytes(conn, start, len);
477
1066
#else
 
1067
            CRASSERT(!conn->u32InjectClientID);
478
1068
            crDebug("SHCRGL: sending userbuf with %d bytes\n", len);
479
1069
            crVBoxHGCMWriteReadExact(conn, start, len, CR_VBOXHGCM_USERALLOCATED);
480
1070
#endif
 
1071
            VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
481
1072
        return;
482
1073
    }
483
1074
 
492
1083
    /* Length would be passed as part of HGCM pointer description
493
1084
     * No need to prepend it to the buffer
494
1085
     */
 
1086
#ifdef IN_GUEST
 
1087
    if (conn->u32InjectClientID)
 
1088
    {
 
1089
        _crVBoxHGCMWriteExact(conn, start, len);
 
1090
    }
 
1091
    else
 
1092
#endif
495
1093
    crVBoxHGCMWriteReadExact(conn, start, len, hgcm_buffer->kind);
496
1094
 
497
1095
    /* Reclaim this pointer for reuse */
508
1106
     * doesn't try to re-use the buffer.
509
1107
     */
510
1108
    *bufp = NULL;
 
1109
 
 
1110
    VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
511
1111
}
512
1112
 
513
1113
static void crVBoxHGCMPollHost(CRConnection *conn)
546
1146
 
547
1147
static void crVBoxHGCMSingleRecv(CRConnection *conn, void *buf, unsigned int len)
548
1148
{
 
1149
    VBOXCRHGSMIPROFILE_FUNC_PROLOGUE();
549
1150
    crVBoxHGCMReadExact(conn, buf, len);
 
1151
    VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
550
1152
}
551
1153
 
552
 
static void crVBoxHGCMFree(CRConnection *conn, void *buf)
 
1154
static void _crVBoxHGCMFree(CRConnection *conn, void *buf)
553
1155
{
554
1156
    CRVBOXHGCMBUFFER *hgcm_buffer = (CRVBOXHGCMBUFFER *) buf - 1;
555
1157
 
588
1190
    }
589
1191
}
590
1192
 
591
 
static void crVBoxHGCMReceiveMessage(CRConnection *conn)
 
1193
static void crVBoxHGCMFree(CRConnection *conn, void *buf)
 
1194
{
 
1195
    VBOXCRHGSMIPROFILE_FUNC_PROLOGUE();
 
1196
    _crVBoxHGCMFree(conn, buf);
 
1197
    VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
 
1198
}
 
1199
 
 
1200
static void _crVBoxHGCMReceiveMessage(CRConnection *conn)
592
1201
{
593
1202
    uint32_t len;
594
1203
    CRVBOXHGCMBUFFER *hgcm_buffer;
605
1214
#endif //IN_GUEST
606
1215
        CRASSERT(conn->buffer_size >= sizeof(CRMessageRedirPtr));
607
1216
 
608
 
        hgcm_buffer = (CRVBOXHGCMBUFFER *) crVBoxHGCMAlloc( conn ) - 1;
 
1217
        hgcm_buffer = (CRVBOXHGCMBUFFER *) _crVBoxHGCMAlloc( conn ) - 1;
609
1218
        hgcm_buffer->len = sizeof(CRMessageRedirPtr);
610
1219
 
611
1220
        msg = (CRMessage *) (hgcm_buffer + 1);
625
1234
        if ( len <= conn->buffer_size )
626
1235
        {
627
1236
            /* put in pre-allocated buffer */
628
 
            hgcm_buffer = (CRVBOXHGCMBUFFER *) crVBoxHGCMAlloc( conn ) - 1;
 
1237
            hgcm_buffer = (CRVBOXHGCMBUFFER *) _crVBoxHGCMAlloc( conn ) - 1;
629
1238
        }
630
1239
        else
631
1240
        {
642
1251
        }
643
1252
 
644
1253
        hgcm_buffer->len = len;
645
 
 
646
1254
        _crVBoxHGCMReadBytes(conn, hgcm_buffer + 1, len);
647
1255
 
648
1256
        msg = (CRMessage *) (hgcm_buffer + 1);
652
1260
 
653
1261
    conn->recv_credits     -= len;
654
1262
    conn->total_bytes_recv += len;
 
1263
    conn->recv_count++;
655
1264
 
656
1265
    crNetDispatchMessage( g_crvboxhgcm.recv_list, conn, msg, len );
657
1266
 
662
1271
        && cached_type != CR_MESSAGE_OOB
663
1272
        && cached_type != CR_MESSAGE_GATHER)
664
1273
    {
665
 
        crVBoxHGCMFree(conn, msg);
 
1274
        _crVBoxHGCMFree(conn, msg);
666
1275
    }
667
1276
}
668
1277
 
 
1278
static void crVBoxHGCMReceiveMessage(CRConnection *conn)
 
1279
{
 
1280
    VBOXCRHGSMIPROFILE_FUNC_PROLOGUE();
 
1281
    _crVBoxHGCMReceiveMessage(conn);
 
1282
    VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
 
1283
}
 
1284
 
 
1285
 
669
1286
/*
670
1287
 * Called on host side only, to "accept" client connection
671
1288
 */
672
1289
static void crVBoxHGCMAccept( CRConnection *conn, const char *hostname, unsigned short port )
673
1290
{
 
1291
    VBOXCRHGSMIPROFILE_FUNC_PROLOGUE();
674
1292
    CRASSERT(conn && conn->pHostBuffer);
675
1293
#ifdef IN_GUEST
676
1294
    CRASSERT(FALSE);
677
1295
#endif
 
1296
    VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
678
1297
}
679
1298
 
680
1299
static int crVBoxHGCMSetVersion(CRConnection *conn, unsigned int vMajor, unsigned int vMinor)
696
1315
 
697
1316
    if (RT_FAILURE(rc) || RT_FAILURE(parms.hdr.result))
698
1317
    {
 
1318
        Assert(0);
 
1319
 
699
1320
        crWarning("Host doesn't accept our version %d.%d. Make sure you have appropriate additions installed!",
700
1321
                  parms.vMajor.u.value32, parms.vMinor.u.value32);
701
1322
        return FALSE;
707
1328
    return TRUE;
708
1329
}
709
1330
 
 
1331
static int crVBoxHGCMSetPID(CRConnection *conn, unsigned long long pid)
 
1332
{
 
1333
    CRVBOXHGCMSETPID parms;
 
1334
    int rc;
 
1335
 
 
1336
    parms.hdr.result      = VERR_WRONG_ORDER;
 
1337
    parms.hdr.u32ClientID = conn->u32ClientID;
 
1338
    parms.hdr.u32Function = SHCRGL_GUEST_FN_SET_PID;
 
1339
    parms.hdr.cParms      = SHCRGL_CPARMS_SET_PID;
 
1340
 
 
1341
    parms.u64PID.type     = VMMDevHGCMParmType_64bit;
 
1342
    parms.u64PID.u.value64 = pid;
 
1343
 
 
1344
    rc = crVBoxHGCMCall(&parms, sizeof(parms));
 
1345
 
 
1346
    if (RT_FAILURE(rc) || RT_FAILURE(parms.hdr.result))
 
1347
    {
 
1348
        Assert(0);
 
1349
 
 
1350
        crWarning("SHCRGL_GUEST_FN_SET_PID failed!");
 
1351
        return FALSE;
 
1352
    }
 
1353
 
 
1354
    return TRUE;
 
1355
}
 
1356
 
710
1357
/**
711
1358
 * The function that actually connects.  This should only be called by clients,
712
1359
 * guests in vbox case.
721
1368
#ifdef RT_OS_WINDOWS
722
1369
    DWORD cbReturned;
723
1370
 
 
1371
    VBOXCRHGSMIPROFILE_FUNC_PROLOGUE();
 
1372
 
724
1373
    if (g_crvboxhgcm.hGuestDrv == INVALID_HANDLE_VALUE)
725
1374
    {
726
1375
        /* open VBox guest driver */
735
1384
        /* @todo check if we could rollback to softwareopengl */
736
1385
        if (g_crvboxhgcm.hGuestDrv == INVALID_HANDLE_VALUE)
737
1386
        {
 
1387
            Assert(0);
738
1388
            crDebug("could not open VBox Guest Additions driver! rc = %d\n", GetLastError());
 
1389
            VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
739
1390
            return FALSE;
740
1391
        }
741
1392
    }
742
1393
#else
 
1394
    VBOXCRHGSMIPROFILE_FUNC_PROLOGUE();
743
1395
    if (g_crvboxhgcm.iGuestDrv == INVALID_HANDLE_VALUE)
744
1396
    {
745
1397
        g_crvboxhgcm.iGuestDrv = open(VBOXGUEST_USER_DEVICE_NAME, O_RDWR, 0);
746
1398
        if (g_crvboxhgcm.iGuestDrv == INVALID_HANDLE_VALUE)
747
1399
        {
748
1400
            crDebug("could not open Guest Additions kernel module! rc = %d\n", errno);
 
1401
            VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
 
1402
            Assert(0);
749
1403
            return FALSE;
750
1404
        }
751
1405
    }
772
1426
# endif
773
1427
    if (ioctl(g_crvboxhgcm.iGuestDrv, VBOXGUEST_IOCTL_HGCM_CONNECT, &Hdr) >= 0)
774
1428
#else
775
 
    /*@todo it'd fail */
776
1429
    if (ioctl(g_crvboxhgcm.iGuestDrv, VBOXGUEST_IOCTL_HGCM_CONNECT, &info, sizeof (info)) >= 0)
777
1430
#endif
778
1431
    {
779
1432
        if (info.result == VINF_SUCCESS)
780
1433
        {
 
1434
            int rc;
781
1435
            conn->u32ClientID = info.u32ClientID;
782
1436
            crDebug("HGCM connect was successful: client id =0x%x\n", conn->u32ClientID);
783
1437
 
784
 
            return crVBoxHGCMSetVersion(conn, CR_PROTOCOL_VERSION_MAJOR, CR_PROTOCOL_VERSION_MINOR);
 
1438
            rc = crVBoxHGCMSetVersion(conn, CR_PROTOCOL_VERSION_MAJOR, CR_PROTOCOL_VERSION_MINOR);
 
1439
            if (!rc)
 
1440
            {
 
1441
                return rc;
 
1442
            }
 
1443
#ifdef RT_OS_WINDOWS
 
1444
            rc = crVBoxHGCMSetPID(conn, GetCurrentProcessId());
 
1445
#else
 
1446
            rc = crVBoxHGCMSetPID(conn, crGetPID());
 
1447
#endif
 
1448
            VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
 
1449
            return rc;
785
1450
        }
786
1451
        else
787
1452
        {
788
1453
            crDebug("HGCM connect failed with rc=0x%x\n", info.result);
 
1454
            Assert(0);
 
1455
 
 
1456
            VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
789
1457
            return FALSE;
790
1458
        }
791
1459
    }
792
1460
    else
793
1461
    {
794
1462
#ifdef RT_OS_WINDOWS
795
 
        crDebug("IOCTL for HGCM connect failed with rc=0x%x\n", GetLastError());
 
1463
        DWORD winEr = GetLastError();
 
1464
        Assert(0);
 
1465
        crDebug("IOCTL for HGCM connect failed with rc=0x%x\n", winEr);
796
1466
#else
797
1467
        crDebug("IOCTL for HGCM connect failed with rc=0x%x\n", errno);
798
1468
#endif
 
1469
        VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
799
1470
        return FALSE;
800
1471
    }
801
1472
 
 
1473
    VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
802
1474
    return TRUE;
803
1475
 
804
1476
#else /*#ifdef IN_GUEST*/
819
1491
    int i;
820
1492
#endif
821
1493
 
 
1494
    if (!g_crvboxhgcm.initialized) return;
 
1495
 
 
1496
#ifdef CHROMIUM_THREADSAFE
 
1497
    crLockMutex(&g_crvboxhgcm.mutex);
 
1498
#endif
 
1499
 
 
1500
    VBOXCRHGSMIPROFILE_FUNC_PROLOGUE();
 
1501
 
822
1502
    if (conn->pHostBuffer)
823
1503
    {
824
1504
        crFree(conn->pHostBuffer);
830
1510
    conn->pBuffer = NULL;
831
1511
    conn->cbBuffer = 0;
832
1512
 
833
 
    //@todo hold lock here?
834
1513
    if (conn->type == CR_VBOXHGCM)
835
1514
    {
836
1515
        --g_crvboxhgcm.num_conns;
898
1577
# endif
899
1578
    }
900
1579
#endif /* IN_GUEST */
 
1580
 
 
1581
    VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
 
1582
 
 
1583
#ifdef CHROMIUM_THREADSAFE
 
1584
    crUnlockMutex(&g_crvboxhgcm.mutex);
 
1585
#endif
901
1586
}
902
1587
 
903
1588
static void crVBoxHGCMInstantReclaim(CRConnection *conn, CRMessage *mess)
904
1589
{
905
 
    crVBoxHGCMFree(conn, mess);
 
1590
    VBOXCRHGSMIPROFILE_FUNC_PROLOGUE();
 
1591
    _crVBoxHGCMFree(conn, mess);
906
1592
    CRASSERT(FALSE);
 
1593
    VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
907
1594
}
908
1595
 
909
1596
static void crVBoxHGCMHandleNewMessage( CRConnection *conn, CRMessage *msg, unsigned int len )
910
1597
{
911
 
    CRASSERT(FALSE);
912
 
}
 
1598
    VBOXCRHGSMIPROFILE_FUNC_PROLOGUE();
 
1599
    CRASSERT(FALSE);
 
1600
    VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
 
1601
}
 
1602
 
 
1603
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
 
1604
 
 
1605
bool _crVBoxHGSMIInit()
 
1606
{
 
1607
#ifndef VBOX_CRHGSMI_WITH_D3DDEV
 
1608
    static
 
1609
#endif
 
1610
    int bHasHGSMI = -1;
 
1611
 
 
1612
    if (bHasHGSMI < 0)
 
1613
    {
 
1614
        int rc;
 
1615
#ifndef VBOX_CRHGSMI_WITH_D3DDEV
 
1616
        rc = VBoxCrHgsmiInit();
 
1617
#else
 
1618
        VBOXCRHGSMI_CALLBACKS Callbacks;
 
1619
        Callbacks.pfnClientCreate = _crVBoxHGSMIClientCreate;
 
1620
        Callbacks.pfnClientDestroy = _crVBoxHGSMIClientDestroy;
 
1621
        rc = VBoxCrHgsmiInit(&Callbacks);
 
1622
#endif
 
1623
        if (RT_SUCCESS(rc))
 
1624
            bHasHGSMI = 1;
 
1625
        else
 
1626
            bHasHGSMI = 0;
 
1627
 
 
1628
        crDebug("CrHgsmi is %s", bHasHGSMI ? "ENABLED" : "DISABLED");
 
1629
    }
 
1630
 
 
1631
    Assert(bHasHGSMI >= 0);
 
1632
 
 
1633
    return bHasHGSMI;
 
1634
}
 
1635
 
 
1636
void _crVBoxHGSMITearDown()
 
1637
{
 
1638
    VBoxCrHgsmiTerm();
 
1639
}
 
1640
 
 
1641
static void *_crVBoxHGSMIDoAlloc(CRConnection *conn, PCRVBOXHGSMI_CLIENT pClient)
 
1642
{
 
1643
    PVBOXUHGSMI_BUFFER buf;
 
1644
    CRVBOXHGCMBUFFER *pData = NULL;
 
1645
    uint32_t cbSize = conn->buffer_size;
 
1646
    int rc;
 
1647
 
 
1648
    buf = _crVBoxHGSMIBufAlloc(pClient, CRVBOXHGSMI_BUF_SIZE(cbSize));
 
1649
    Assert(buf);
 
1650
    if (buf)
 
1651
    {
 
1652
        VBOXUHGSMI_BUFFER_LOCK_FLAGS fFlags;
 
1653
        buf->pvUserData = pClient;
 
1654
        fFlags.Value = 0;
 
1655
        fFlags.bDiscard = 1;
 
1656
        rc = buf->pfnLock(buf, 0, CRVBOXHGSMI_BUF_LOCK_SIZE(cbSize), fFlags, (void**)&pData);
 
1657
        if (RT_SUCCESS(rc))
 
1658
        {
 
1659
            pData->magic = CR_VBOXHGCM_BUFFER_MAGIC;
 
1660
            pData->kind = CR_VBOXHGCM_UHGSMI_BUFFER;
 
1661
            pData->pBuffer = buf;
 
1662
        }
 
1663
        else
 
1664
        {
 
1665
            crWarning("Failed to Lock the buffer, rc(%d)\n", rc);
 
1666
        }
 
1667
        return CRVBOXHGSMI_BUF_DATA(pData);
 
1668
    }
 
1669
 
 
1670
    /* fall back */
 
1671
    return _crVBoxHGCMAlloc(conn);
 
1672
}
 
1673
 
 
1674
static void _crVBoxHGSMIFree(CRConnection *conn, void *buf)
 
1675
{
 
1676
    CRVBOXHGCMBUFFER *hgcm_buffer = (CRVBOXHGCMBUFFER *) buf - 1;
 
1677
 
 
1678
    CRASSERT(hgcm_buffer->magic == CR_VBOXHGCM_BUFFER_MAGIC);
 
1679
 
 
1680
    if (hgcm_buffer->kind == CR_VBOXHGCM_UHGSMI_BUFFER)
 
1681
    {
 
1682
        PVBOXUHGSMI_BUFFER pBuf = _crVBoxHGSMIBufFromHdr(hgcm_buffer);
 
1683
        PCRVBOXHGSMI_CLIENT pClient = (PCRVBOXHGSMI_CLIENT)pBuf->pvUserData;
 
1684
        pBuf->pfnUnlock(pBuf);
 
1685
        _crVBoxHGSMIBufFree(pClient, pBuf);
 
1686
    }
 
1687
    else
 
1688
    {
 
1689
        _crVBoxHGCMFree(conn, buf);
 
1690
    }
 
1691
}
 
1692
 
 
1693
static void *crVBoxHGSMIAlloc(CRConnection *conn)
 
1694
{
 
1695
    PCRVBOXHGSMI_CLIENT pClient;
 
1696
    void *pvBuf;
 
1697
 
 
1698
    VBOXCRHGSMIPROFILE_FUNC_PROLOGUE();
 
1699
 
 
1700
    pClient = _crVBoxHGSMIClientGet(conn);
 
1701
    if (pClient)
 
1702
    {
 
1703
        pvBuf = _crVBoxHGSMIDoAlloc(conn, pClient);
 
1704
        Assert(pvBuf);
 
1705
    }
 
1706
    else
 
1707
    {
 
1708
        pvBuf = _crVBoxHGCMAlloc(conn);
 
1709
    }
 
1710
 
 
1711
    VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
 
1712
 
 
1713
    return pvBuf;
 
1714
}
 
1715
 
 
1716
static void crVBoxHGSMIFree(CRConnection *conn, void *buf)
 
1717
{
 
1718
    VBOXCRHGSMIPROFILE_FUNC_PROLOGUE();
 
1719
    _crVBoxHGSMIFree(conn, buf);
 
1720
    VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
 
1721
}
 
1722
 
 
1723
static void _crVBoxHGSMIPollHost(CRConnection *conn, PCRVBOXHGSMI_CLIENT pClient)
 
1724
{
 
1725
    CRVBOXHGSMIREAD *parms = (CRVBOXHGSMIREAD *)_crVBoxHGSMICmdBufferLock(pClient, sizeof (*parms));
 
1726
    int rc;
 
1727
    VBOXUHGSMI_BUFFER_SUBMIT aSubmit[2];
 
1728
    PVBOXUHGSMI_BUFFER pRecvBuffer;
 
1729
    uint32_t cbBuffer;
 
1730
 
 
1731
    Assert(parms);
 
1732
 
 
1733
    parms->hdr.result      = VERR_WRONG_ORDER;
 
1734
    parms->hdr.u32ClientID = conn->u32ClientID;
 
1735
    parms->hdr.u32Function = SHCRGL_GUEST_FN_READ;
 
1736
//    parms->hdr.u32Reserved = 0;
 
1737
 
 
1738
    CRASSERT(!conn->pBuffer); //make sure there's no data to process
 
1739
    parms->iBuffer = 1;
 
1740
    parms->cbBuffer = 0;
 
1741
 
 
1742
    _crVBoxHGSMICmdBufferUnlock(pClient);
 
1743
 
 
1744
    pRecvBuffer = _crVBoxHGSMIRecvBufGet(pClient);
 
1745
    Assert(pRecvBuffer);
 
1746
    if (!pRecvBuffer)
 
1747
        return;
 
1748
 
 
1749
    _crVBoxHGSMIFillCmd(&aSubmit[0], pClient, sizeof (*parms));
 
1750
 
 
1751
    aSubmit[1].pBuf = pRecvBuffer;
 
1752
    aSubmit[1].offData = 0;
 
1753
    aSubmit[1].cbData = pRecvBuffer->cbBuffer;
 
1754
    aSubmit[1].fFlags.Value = 0;
 
1755
    aSubmit[1].fFlags.bHostWriteOnly = 1;
 
1756
 
 
1757
    rc = pClient->pHgsmi->pfnBufferSubmitAsynch(pClient->pHgsmi, aSubmit, 2);
 
1758
    AssertRC(rc);
 
1759
    if (RT_FAILURE(rc))
 
1760
    {
 
1761
        crError("pfnBufferSubmitAsynch failed with %d \n", rc);
 
1762
        return;
 
1763
    }
 
1764
 
 
1765
    _crVBoxHGSMIWaitCmd(pClient);
 
1766
 
 
1767
    parms = (CRVBOXHGSMIREAD *)_crVBoxHGSMICmdBufferLockRo(pClient, sizeof (*parms));
 
1768
    Assert(parms);
 
1769
    if (!parms)
 
1770
    {
 
1771
        crWarning("_crVBoxHGSMICmdBufferLockRo failed\n");
 
1772
        return;
 
1773
    }
 
1774
 
 
1775
    if (RT_SUCCESS(parms->hdr.result))
 
1776
        cbBuffer = parms->cbBuffer;
 
1777
    else
 
1778
        cbBuffer = 0;
 
1779
 
 
1780
    _crVBoxHGSMICmdBufferUnlock(pClient);
 
1781
 
 
1782
    if (cbBuffer)
 
1783
    {
 
1784
        void *pvData = _crVBoxHGSMIRecvBufData(pClient, cbBuffer);
 
1785
        Assert(pvData);
 
1786
        if (pvData)
 
1787
        {
 
1788
            conn->pBuffer  = pvData;
 
1789
            conn->cbBuffer = cbBuffer;
 
1790
        }
 
1791
    }
 
1792
}
 
1793
 
 
1794
static void _crVBoxHGSMIReadExact(CRConnection *conn, PCRVBOXHGSMI_CLIENT pClient)
 
1795
{
 
1796
    _crVBoxHGSMIPollHost(conn, pClient);
 
1797
 
 
1798
    if (conn->cbBuffer)
 
1799
        _crVBoxHGCMReceiveMessage(conn);
 
1800
}
 
1801
 
 
1802
/* Same as crVBoxHGCMWriteExact, but combined with read of writeback data.
 
1803
 * This halves the number of HGCM calls we do,
 
1804
 * most likely crVBoxHGCMPollHost shouldn't be called at all now.
 
1805
 */
 
1806
static void
 
1807
_crVBoxHGSMIWriteReadExact(CRConnection *conn, PCRVBOXHGSMI_CLIENT pClient, void *buf, uint32_t offBuffer, unsigned int len, bool bIsBuffer)
 
1808
{
 
1809
    CRVBOXHGSMIWRITEREAD *parms = (CRVBOXHGSMIWRITEREAD*)_crVBoxHGSMICmdBufferLock(pClient, sizeof (*parms));
 
1810
    int rc;
 
1811
    VBOXUHGSMI_BUFFER_SUBMIT aSubmit[3];
 
1812
    PVBOXUHGSMI_BUFFER pBuf = NULL;
 
1813
    VBOXUHGSMI_BUFFER_LOCK_FLAGS fFlags;
 
1814
//    uint32_t cbBuffer;
 
1815
 
 
1816
    parms->hdr.result      = VERR_WRONG_ORDER;
 
1817
    parms->hdr.u32ClientID = conn->u32ClientID;
 
1818
    parms->hdr.u32Function = SHCRGL_GUEST_FN_WRITE_READ;
 
1819
//    parms->hdr.u32Reserved = 0;
 
1820
 
 
1821
    parms->iBuffer = 1;
 
1822
 
 
1823
    CRASSERT(!conn->pBuffer); //make sure there's no data to process
 
1824
    parms->iWriteback = 2;
 
1825
    parms->cbWriteback = 0;
 
1826
 
 
1827
    _crVBoxHGSMICmdBufferUnlock(pClient);
 
1828
 
 
1829
    if (!bIsBuffer)
 
1830
    {
 
1831
        void *pvBuf;
 
1832
        pBuf = _crVBoxHGSMIBufAlloc(pClient, len);
 
1833
        Assert(pBuf);
 
1834
        if (!pBuf)
 
1835
        {
 
1836
            /* fallback */
 
1837
            crVBoxHGCMWriteReadExact(conn, buf, len, CR_VBOXHGCM_USERALLOCATED);
 
1838
            return;
 
1839
        }
 
1840
 
 
1841
        Assert(!offBuffer);
 
1842
 
 
1843
        offBuffer = 0;
 
1844
        fFlags.Value = 0;
 
1845
        fFlags.bDiscard = 1;
 
1846
        fFlags.bWriteOnly = 1;
 
1847
        rc = pBuf->pfnLock(pBuf, 0, len, fFlags, &pvBuf);
 
1848
        AssertRC(rc);
 
1849
        if (RT_SUCCESS(rc))
 
1850
        {
 
1851
            memcpy(pvBuf, buf, len);
 
1852
            rc = pBuf->pfnUnlock(pBuf);
 
1853
            AssertRC(rc);
 
1854
            CRASSERT(RT_SUCCESS(rc));
 
1855
        }
 
1856
        else
 
1857
        {
 
1858
            _crVBoxHGSMIBufFree(pClient, pBuf);
 
1859
            /* fallback */
 
1860
            crVBoxHGCMWriteReadExact(conn, buf, len, CR_VBOXHGCM_USERALLOCATED);
 
1861
            return;
 
1862
        }
 
1863
    }
 
1864
    else
 
1865
    {
 
1866
        pBuf = (PVBOXUHGSMI_BUFFER)buf;
 
1867
    }
 
1868
 
 
1869
    do
 
1870
    {
 
1871
        PVBOXUHGSMI_BUFFER pRecvBuffer = _crVBoxHGSMIRecvBufGet(pClient);
 
1872
        Assert(pRecvBuffer);
 
1873
        if (!pRecvBuffer)
 
1874
        {
 
1875
            break;
 
1876
        }
 
1877
 
 
1878
        _crVBoxHGSMIFillCmd(&aSubmit[0], pClient, sizeof (*parms));
 
1879
 
 
1880
        aSubmit[1].pBuf = pBuf;
 
1881
        aSubmit[1].offData = offBuffer;
 
1882
        aSubmit[1].cbData = len;
 
1883
        aSubmit[1].fFlags.Value = 0;
 
1884
        aSubmit[1].fFlags.bHostReadOnly = 1;
 
1885
 
 
1886
        aSubmit[2].pBuf = pRecvBuffer;
 
1887
        aSubmit[2].offData = 0;
 
1888
        aSubmit[2].cbData = pRecvBuffer->cbBuffer;
 
1889
        aSubmit[2].fFlags.Value = 0;
 
1890
 
 
1891
        rc = pClient->pHgsmi->pfnBufferSubmitAsynch(pClient->pHgsmi, aSubmit, 3);
 
1892
        AssertRC(rc);
 
1893
        if (RT_FAILURE(rc))
 
1894
        {
 
1895
            crError("pfnBufferSubmitAsynch failed with %d \n", rc);
 
1896
            break;
 
1897
        }
 
1898
 
 
1899
        _crVBoxHGSMIWaitCmd(pClient);
 
1900
 
 
1901
        parms = (CRVBOXHGSMIWRITEREAD *)_crVBoxHGSMICmdBufferLockRo(pClient, sizeof (*parms));
 
1902
        Assert(parms);
 
1903
        if (parms)
 
1904
        {
 
1905
            uint32_t cbWriteback = parms->cbWriteback;
 
1906
            rc = parms->hdr.result;
 
1907
            _crVBoxHGSMICmdBufferUnlock(pClient);
 
1908
#ifdef DEBUG
 
1909
            parms = NULL;
 
1910
#endif
 
1911
            if (RT_SUCCESS(rc))
 
1912
            {
 
1913
                if (cbWriteback)
 
1914
                {
 
1915
                    void *pvData = _crVBoxHGSMIRecvBufData(pClient, cbWriteback);
 
1916
                    Assert(pvData);
 
1917
                    if (pvData)
 
1918
                    {
 
1919
                        conn->pBuffer  = pvData;
 
1920
                        conn->cbBuffer = cbWriteback;
 
1921
                        _crVBoxHGCMReceiveMessage(conn);
 
1922
                    }
 
1923
                }
 
1924
            }
 
1925
            else if (VERR_BUFFER_OVERFLOW == rc)
 
1926
            {
 
1927
                PVBOXUHGSMI_BUFFER pOldBuf = pClient->pHGBuffer;
 
1928
                Assert(!pClient->pvHGBuffer);
 
1929
                CRASSERT(cbWriteback>pClient->pHGBuffer->cbBuffer);
 
1930
                crDebug("Reallocating host buffer from %d to %d bytes", conn->cbHostBufferAllocated, cbWriteback);
 
1931
 
 
1932
                rc = pClient->pHgsmi->pfnBufferCreate(pClient->pHgsmi, CRVBOXHGSMI_PAGE_ALIGN(cbWriteback),
 
1933
                                VBOXUHGSMI_SYNCHOBJECT_TYPE_NONE, NULL, &pClient->pHGBuffer);
 
1934
                AssertRC(rc);
 
1935
                CRASSERT(RT_SUCCESS(rc));
 
1936
                if (RT_SUCCESS(rc))
 
1937
                {
 
1938
                    rc = pOldBuf->pfnDestroy(pOldBuf);
 
1939
                    CRASSERT(RT_SUCCESS(rc));
 
1940
 
 
1941
                    _crVBoxHGSMIReadExact(conn, pClient/*, cbWriteback*/);
 
1942
                }
 
1943
                else
 
1944
                {
 
1945
                    crFree(conn->pHostBuffer);
 
1946
                    conn->cbHostBufferAllocated = cbWriteback;
 
1947
                    conn->pHostBuffer = crAlloc(conn->cbHostBufferAllocated);
 
1948
                    crVBoxHGCMReadExact(conn, NULL, cbWriteback);
 
1949
                }
 
1950
            }
 
1951
            else
 
1952
            {
 
1953
                crWarning("SHCRGL_GUEST_FN_WRITE_READ (%i) failed with %x \n", len, rc);
 
1954
            }
 
1955
        }
 
1956
        else
 
1957
        {
 
1958
            crWarning("_crVBoxHGSMICmdBufferLockRo failed\n");
 
1959
            break;
 
1960
        }
 
1961
    } while (0);
 
1962
 
 
1963
    if (!bIsBuffer)
 
1964
        _crVBoxHGSMIBufFree(pClient, pBuf);
 
1965
 
 
1966
    return;
 
1967
}
 
1968
 
 
1969
static void _crVBoxHGSMIWriteExact(CRConnection *conn, PCRVBOXHGSMI_CLIENT pClient, PVBOXUHGSMI_BUFFER pBuf, uint32_t offStart, unsigned int len)
 
1970
{
 
1971
    int rc;
 
1972
    int32_t callRes;
 
1973
    VBOXUHGSMI_BUFFER_SUBMIT aSubmit[2];
 
1974
 
 
1975
#ifdef IN_GUEST
 
1976
    if (conn->u32InjectClientID)
 
1977
    {
 
1978
        CRVBOXHGSMIINJECT *parms = (CRVBOXHGSMIINJECT *)_crVBoxHGSMICmdBufferLock(pClient, sizeof (*parms));
 
1979
        Assert(parms);
 
1980
        if (!parms)
 
1981
        {
 
1982
            return;
 
1983
        }
 
1984
 
 
1985
        parms->hdr.result      = VERR_WRONG_ORDER;
 
1986
        parms->hdr.u32ClientID = conn->u32ClientID;
 
1987
        parms->hdr.u32Function = SHCRGL_GUEST_FN_INJECT;
 
1988
//        parms->hdr.u32Reserved = 0;
 
1989
 
 
1990
        parms->u32ClientID = conn->u32InjectClientID;
 
1991
 
 
1992
        parms->iBuffer = 1;
 
1993
        _crVBoxHGSMICmdBufferUnlock(pClient);
 
1994
 
 
1995
        _crVBoxHGSMIFillCmd(&aSubmit[0], pClient, sizeof (*parms));
 
1996
 
 
1997
        aSubmit[1].pBuf = pBuf;
 
1998
        aSubmit[1].offData = offStart;
 
1999
        aSubmit[1].cbData = len;
 
2000
        aSubmit[1].fFlags.Value = 0;
 
2001
        aSubmit[1].fFlags.bHostReadOnly = 1;
 
2002
 
 
2003
        rc = pClient->pHgsmi->pfnBufferSubmitAsynch(pClient->pHgsmi, aSubmit, 2);
 
2004
        AssertRC(rc);
 
2005
        if (RT_SUCCESS(rc))
 
2006
        {
 
2007
            _crVBoxHGSMIWaitCmd(pClient);
 
2008
                /* @todo: do we need to wait for completion actually?
 
2009
                 * NOTE: in case we do not need completion,
 
2010
                 * we MUST specify bDoNotSignalCompletion flag for the command buffer */
 
2011
//                CRVBOXHGSMI_BUF_WAIT(pClient->pCmdBuffer);
 
2012
 
 
2013
            callRes = _crVBoxHGSMICmdBufferGetRc(pClient);
 
2014
        }
 
2015
        else
 
2016
        {
 
2017
            /* we can not recover at this point, report error & exit */
 
2018
            crError("pfnBufferSubmitAsynch failed with %d \n", rc);
 
2019
        }
 
2020
    }
 
2021
    else
 
2022
#endif
 
2023
    {
 
2024
        CRVBOXHGSMIWRITE * parms = (CRVBOXHGSMIWRITE *)_crVBoxHGSMICmdBufferLock(pClient, sizeof (*parms));;
 
2025
 
 
2026
        parms->hdr.result      = VERR_WRONG_ORDER;
 
2027
        parms->hdr.u32ClientID = conn->u32ClientID;
 
2028
        parms->hdr.u32Function = SHCRGL_GUEST_FN_WRITE;
 
2029
//        parms->hdr.u32Reserved = 0;
 
2030
 
 
2031
        parms->iBuffer = 1;
 
2032
        _crVBoxHGSMICmdBufferUnlock(pClient);
 
2033
 
 
2034
        _crVBoxHGSMIFillCmd(&aSubmit[0], pClient, sizeof (*parms));
 
2035
 
 
2036
        aSubmit[1].pBuf = pBuf;
 
2037
        aSubmit[1].offData = offStart;
 
2038
        aSubmit[1].cbData = len;
 
2039
        aSubmit[1].fFlags.Value = 0;
 
2040
        aSubmit[1].fFlags.bHostReadOnly = 1;
 
2041
 
 
2042
        rc = pClient->pHgsmi->pfnBufferSubmitAsynch(pClient->pHgsmi, aSubmit, 2);
 
2043
        AssertRC(rc);
 
2044
        if (RT_SUCCESS(rc))
 
2045
        {
 
2046
            _crVBoxHGSMIWaitCmd(pClient);
 
2047
                /* @todo: do we need to wait for completion actually?
 
2048
                 * NOTE: in case we do not need completion,
 
2049
                 * we MUST specify bDoNotSignalCompletion flag for the command buffer */
 
2050
//                CRVBOXHGSMI_BUF_WAIT(pClient->pCmdBuffer);
 
2051
 
 
2052
            callRes = _crVBoxHGSMICmdBufferGetRc(pClient);
 
2053
        }
 
2054
        else
 
2055
        {
 
2056
            /* we can not recover at this point, report error & exit */
 
2057
            crError("Failed to submit CrHhgsmi buffer");
 
2058
        }
 
2059
    }
 
2060
 
 
2061
    if (RT_FAILURE(rc) || RT_FAILURE(callRes))
 
2062
    {
 
2063
        crWarning("SHCRGL_GUEST_FN_WRITE failed with %x %x\n", rc, callRes);
 
2064
    }
 
2065
}
 
2066
 
 
2067
static void crVBoxHGSMISend(CRConnection *conn, void **bufp,
 
2068
                           const void *start, unsigned int len)
 
2069
{
 
2070
    PCRVBOXHGSMI_CLIENT pClient;
 
2071
    PVBOXUHGSMI_BUFFER pBuf;
 
2072
    CRVBOXHGCMBUFFER *hgcm_buffer;
 
2073
 
 
2074
    VBOXCRHGSMIPROFILE_FUNC_PROLOGUE();
 
2075
 
 
2076
    if (!bufp) /* We're sending a user-allocated buffer. */
 
2077
    {
 
2078
        pClient = _crVBoxHGSMIClientGet(conn);
 
2079
        if (pClient)
 
2080
        {
 
2081
#ifndef IN_GUEST
 
2082
                //@todo remove temp buffer allocation in unpacker
 
2083
                /* we're at the host side, so just store data until guest polls us */
 
2084
                _crVBoxHGCMWriteBytes(conn, start, len);
 
2085
#else
 
2086
            CRASSERT(!conn->u32InjectClientID);
 
2087
            crDebug("SHCRGL: sending userbuf with %d bytes\n", len);
 
2088
            _crVBoxHGSMIWriteReadExact(conn, pClient, (void*)start, 0, len, false);
 
2089
#endif
 
2090
            VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
 
2091
            return;
 
2092
        }
 
2093
 
 
2094
        /* fallback */
 
2095
        crVBoxHGCMSend(conn, bufp, start, len);
 
2096
        VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
 
2097
        return;
 
2098
    }
 
2099
 
 
2100
    hgcm_buffer = (CRVBOXHGCMBUFFER *) *bufp - 1;
 
2101
    Assert(hgcm_buffer->magic == CR_VBOXHGCM_BUFFER_MAGIC);
 
2102
    if (hgcm_buffer->kind != CR_VBOXHGCM_UHGSMI_BUFFER)
 
2103
    {
 
2104
        /* fallback */
 
2105
        crVBoxHGCMSend(conn, bufp, start, len);
 
2106
        VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
 
2107
        return;
 
2108
    }
 
2109
 
 
2110
    /* The region [start .. start + len + 1] lies within a buffer that
 
2111
     * was allocated with crVBoxHGCMAlloc() and can be put into the free
 
2112
     * buffer pool when we're done sending it.
 
2113
     */
 
2114
 
 
2115
    pBuf = _crVBoxHGSMIBufFromHdr(hgcm_buffer);
 
2116
    Assert(pBuf);
 
2117
    if (!pBuf)
 
2118
    {
 
2119
        crVBoxHGCMSend(conn, bufp, start, len);
 
2120
        VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
 
2121
        return;
 
2122
    }
 
2123
 
 
2124
    pClient = (PCRVBOXHGSMI_CLIENT)pBuf->pvUserData;
 
2125
 
 
2126
    /* Length would be passed as part of HGCM pointer description
 
2127
     * No need to prepend it to the buffer
 
2128
     */
 
2129
#ifdef IN_GUEST
 
2130
    if (conn->u32InjectClientID)
 
2131
    {
 
2132
        _crVBoxHGSMIWriteExact(conn, pClient, pBuf, CRVBOXHGSMI_BUF_OFFSET(start, *bufp) + CRVBOXHGSMI_BUF_HDR_SIZE(), len);
 
2133
    }
 
2134
    else
 
2135
#endif
 
2136
    {
 
2137
        _crVBoxHGSMIWriteReadExact(conn, pClient, pBuf, CRVBOXHGSMI_BUF_OFFSET(start, *bufp) + CRVBOXHGSMI_BUF_HDR_SIZE(), len, true);
 
2138
    }
 
2139
 
 
2140
    /* Reclaim this pointer for reuse */
 
2141
    _crVBoxHGSMIBufFree(pClient, pBuf);
 
2142
    /* Since the buffer's now in the 'free' buffer pool, the caller can't
 
2143
     * use it any more.  Setting bufp to NULL will make sure the caller
 
2144
     * doesn't try to re-use the buffer.
 
2145
     */
 
2146
    *bufp = NULL;
 
2147
 
 
2148
    VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
 
2149
}
 
2150
 
 
2151
static void crVBoxHGSMIWriteExact(CRConnection *conn, const void *buf, unsigned int len)
 
2152
{
 
2153
    VBOXCRHGSMIPROFILE_FUNC_PROLOGUE();
 
2154
    Assert(0);
 
2155
 
 
2156
    CRASSERT(0);
 
2157
//    PCRVBOXHGSMI_CLIENT pClient;
 
2158
//    PVBOXUHGSMI_BUFFER pBuf = _crVBoxHGSMIBufFromMemPtr(buf);
 
2159
//    if (!pBuf)
 
2160
//        return;
 
2161
//    pClient = (PCRVBOXHGSMI_CLIENT)pBuf->pvUserData;
 
2162
//    _crVBoxHGSMIWriteExact(conn, pClient, pBuf, 0, len);
 
2163
//    _crVBoxHGSMIBufFree(pClient, pBuf);
 
2164
    VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
 
2165
}
 
2166
 
 
2167
static void crVBoxHGSMISingleRecv(CRConnection *conn, void *buf, unsigned int len)
 
2168
{
 
2169
//    PCRVBOXHGSMI_CLIENT pClient;
 
2170
//    PVBOXUHGSMI_BUFFER pBuf;
 
2171
    VBOXCRHGSMIPROFILE_FUNC_PROLOGUE();
 
2172
//    pBuf = _crVBoxHGSMIBufFromMemPtr(buf);
 
2173
//    Assert(pBuf);
 
2174
    Assert(0);
 
2175
    CRASSERT(0);
 
2176
//    if (!pBuf)
 
2177
//    {
 
2178
//        VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
 
2179
//        return;
 
2180
//    }
 
2181
//    pClient = (PCRVBOXHGSMI_CLIENT)pBuf->pvUserData;
 
2182
//    _crVBoxHGSMIReadExact(conn, pClient);
 
2183
    VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
 
2184
}
 
2185
 
 
2186
static void crVBoxHGSMIReceiveMessage(CRConnection *conn)
 
2187
{
 
2188
    VBOXCRHGSMIPROFILE_FUNC_PROLOGUE();
 
2189
 
 
2190
    Assert(0);
 
2191
 
 
2192
    _crVBoxHGCMReceiveMessage(conn);
 
2193
    VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
 
2194
}
 
2195
 
 
2196
/*
 
2197
 * Called on host side only, to "accept" client connection
 
2198
 */
 
2199
static void crVBoxHGSMIAccept( CRConnection *conn, const char *hostname, unsigned short port )
 
2200
{
 
2201
    VBOXCRHGSMIPROFILE_FUNC_PROLOGUE();
 
2202
    Assert(0);
 
2203
 
 
2204
    CRASSERT(conn && conn->pHostBuffer);
 
2205
#ifdef IN_GUEST
 
2206
    CRASSERT(FALSE);
 
2207
#endif
 
2208
    VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
 
2209
}
 
2210
 
 
2211
static int crVBoxHGSMIDoConnect( CRConnection *conn )
 
2212
{
 
2213
    return crVBoxHGCMDoConnect(conn);
 
2214
}
 
2215
 
 
2216
static void crVBoxHGSMIDoDisconnect( CRConnection *conn )
 
2217
{
 
2218
#ifndef VBOX_CRHGSMI_WITH_D3DDEV
 
2219
    if (conn->HgsmiClient.pHgsmi)
 
2220
    {
 
2221
        PVBOXUHGSMI pHgsmi;
 
2222
        _crVBoxHGSMIClientTerm(&conn->HgsmiClient, &pHgsmi);
 
2223
        Assert(pHgsmi);
 
2224
        VBoxCrHgsmiDestroy(pHgsmi);
 
2225
    }
 
2226
 
 
2227
#endif
 
2228
    crVBoxHGCMDoDisconnect(conn);
 
2229
}
 
2230
 
 
2231
static void crVBoxHGSMIInstantReclaim(CRConnection *conn, CRMessage *mess)
 
2232
{
 
2233
    VBOXCRHGSMIPROFILE_FUNC_PROLOGUE();
 
2234
    Assert(0);
 
2235
 
 
2236
    _crVBoxHGSMIFree(conn, mess);
 
2237
    CRASSERT(FALSE);
 
2238
 
 
2239
    VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
 
2240
}
 
2241
 
 
2242
static void crVBoxHGSMIHandleNewMessage( CRConnection *conn, CRMessage *msg, unsigned int len )
 
2243
{
 
2244
    VBOXCRHGSMIPROFILE_FUNC_PROLOGUE();
 
2245
    Assert(0);
 
2246
 
 
2247
    CRASSERT(FALSE);
 
2248
    VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
 
2249
}
 
2250
#endif
913
2251
 
914
2252
void crVBoxHGCMInit(CRNetReceiveFuncList *rfl, CRNetCloseFuncList *cfl, unsigned int mtu)
915
2253
{
922
2260
        return;
923
2261
    }
924
2262
 
 
2263
    VBOXCRHGSMIPROFILE_INIT();
 
2264
 
925
2265
    g_crvboxhgcm.initialized = 1;
926
2266
 
 
2267
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
 
2268
    g_crvboxhgcm.bHgsmiOn = _crVBoxHGSMIInit();
 
2269
#endif
 
2270
 
927
2271
    g_crvboxhgcm.num_conns = 0;
928
2272
    g_crvboxhgcm.conns     = NULL;
929
2273
 
983
2327
 
984
2328
    if (!g_crvboxhgcm.initialized) return;
985
2329
 
 
2330
#ifdef CHROMIUM_THREADSAFE
 
2331
    crLockMutex(&g_crvboxhgcm.mutex);
 
2332
#endif
 
2333
 
986
2334
    /* Connection count would be changed in calls to crNetDisconnect, so we have to store original value.
987
2335
     * Walking array backwards is not a good idea as it could cause some issues if we'd disconnect clients not in the
988
2336
     * order of their connection.
995
2343
    }
996
2344
    CRASSERT(0==g_crvboxhgcm.num_conns);
997
2345
 
 
2346
    g_crvboxhgcm.initialized = 0;
 
2347
 
998
2348
#ifdef CHROMIUM_THREADSAFE
 
2349
    crUnlockMutex(&g_crvboxhgcm.mutex);
999
2350
    crFreeMutex(&g_crvboxhgcm.mutex);
1000
2351
    crFreeMutex(&g_crvboxhgcm.recvmutex);
1001
2352
#endif
1004
2355
        crBufferPoolCallbackFree(g_crvboxhgcm.bufpool, crVBoxHGCMBufferFree);
1005
2356
    g_crvboxhgcm.bufpool = NULL;
1006
2357
 
1007
 
    g_crvboxhgcm.initialized = 0;
1008
 
 
1009
2358
    crFree(g_crvboxhgcm.conns);
1010
2359
    g_crvboxhgcm.conns = NULL;
1011
2360
 
 
2361
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
 
2362
    if (g_crvboxhgcm.bHgsmiOn)
 
2363
    {
 
2364
        _crVBoxHGSMITearDown();
 
2365
    }
 
2366
#endif
 
2367
 
1012
2368
#ifdef RT_OS_WINDOWS
1013
2369
    if (g_crvboxhgcm.pDirectDraw)
1014
2370
    {
1026
2382
 
1027
2383
    CRASSERT(g_crvboxhgcm.initialized);
1028
2384
 
1029
 
    conn->type = CR_VBOXHGCM;
1030
 
    conn->Alloc = crVBoxHGCMAlloc;
1031
 
    conn->Send = crVBoxHGCMSend;
1032
 
    conn->SendExact = crVBoxHGCMWriteExact;
1033
 
    conn->Recv = crVBoxHGCMSingleRecv;
1034
 
    conn->RecvMsg = crVBoxHGCMReceiveMessage;
1035
 
    conn->Free = crVBoxHGCMFree;
1036
 
    conn->Accept = crVBoxHGCMAccept;
1037
 
    conn->Connect = crVBoxHGCMDoConnect;
1038
 
    conn->Disconnect = crVBoxHGCMDoDisconnect;
1039
 
    conn->InstantReclaim = crVBoxHGCMInstantReclaim;
1040
 
    conn->HandleNewMessage = crVBoxHGCMHandleNewMessage;
1041
 
    conn->index = g_crvboxhgcm.num_conns;
 
2385
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
 
2386
    if (g_crvboxhgcm.bHgsmiOn)
 
2387
    {
 
2388
        conn->type = CR_VBOXHGCM;
 
2389
        conn->Alloc = crVBoxHGSMIAlloc;
 
2390
        conn->Send = crVBoxHGSMISend;
 
2391
        conn->SendExact = crVBoxHGSMIWriteExact;
 
2392
        conn->Recv = crVBoxHGSMISingleRecv;
 
2393
        conn->RecvMsg = crVBoxHGSMIReceiveMessage;
 
2394
        conn->Free = crVBoxHGSMIFree;
 
2395
        conn->Accept = crVBoxHGSMIAccept;
 
2396
        conn->Connect = crVBoxHGSMIDoConnect;
 
2397
        conn->Disconnect = crVBoxHGSMIDoDisconnect;
 
2398
        conn->InstantReclaim = crVBoxHGSMIInstantReclaim;
 
2399
        conn->HandleNewMessage = crVBoxHGSMIHandleNewMessage;
 
2400
    }
 
2401
    else
 
2402
#endif
 
2403
    {
 
2404
        conn->type = CR_VBOXHGCM;
 
2405
        conn->Alloc = crVBoxHGCMAlloc;
 
2406
        conn->Send = crVBoxHGCMSend;
 
2407
        conn->SendExact = crVBoxHGCMWriteExact;
 
2408
        conn->Recv = crVBoxHGCMSingleRecv;
 
2409
        conn->RecvMsg = crVBoxHGCMReceiveMessage;
 
2410
        conn->Free = crVBoxHGCMFree;
 
2411
        conn->Accept = crVBoxHGCMAccept;
 
2412
        conn->Connect = crVBoxHGCMDoConnect;
 
2413
        conn->Disconnect = crVBoxHGCMDoDisconnect;
 
2414
        conn->InstantReclaim = crVBoxHGCMInstantReclaim;
 
2415
        conn->HandleNewMessage = crVBoxHGCMHandleNewMessage;
 
2416
    }
1042
2417
    conn->sizeof_buffer_header = sizeof(CRVBOXHGCMBUFFER);
1043
2418
    conn->actual_network = 1;
1044
2419
 
1054
2429
    CRASSERT(conn->pHostBuffer);
1055
2430
    conn->cbHostBuffer = 0;
1056
2431
 
 
2432
#ifdef CHROMIUM_THREADSAFE
 
2433
    crLockMutex(&g_crvboxhgcm.mutex);
 
2434
#endif
1057
2435
    /* Find a free slot */
1058
2436
    for (i = 0; i < g_crvboxhgcm.num_conns; i++) {
1059
2437
        if (g_crvboxhgcm.conns[i] == NULL) {
1068
2446
    if (found == 0) {
1069
2447
        n_bytes = ( g_crvboxhgcm.num_conns + 1 ) * sizeof(*g_crvboxhgcm.conns);
1070
2448
        crRealloc( (void **) &g_crvboxhgcm.conns, n_bytes );
 
2449
        conn->index = g_crvboxhgcm.num_conns;
1071
2450
        g_crvboxhgcm.conns[g_crvboxhgcm.num_conns++] = conn;
1072
2451
    }
 
2452
#ifdef CHROMIUM_THREADSAFE
 
2453
    crUnlockMutex(&g_crvboxhgcm.mutex);
 
2454
#endif
1073
2455
}
1074
2456
 
1075
2457
int crVBoxHGCMRecv(void)
1076
2458
{
1077
2459
    int32_t i;
1078
2460
 
 
2461
    VBOXCRHGSMIPROFILE_FUNC_PROLOGUE();
 
2462
 
 
2463
#ifdef CHROMIUM_THREADSAFE
 
2464
    crLockMutex(&g_crvboxhgcm.mutex);
 
2465
#endif
 
2466
 
1079
2467
#ifdef IN_GUEST
1080
2468
    /* we're on guest side, poll host if it got something for us */
1081
2469
    for (i=0; i<g_crvboxhgcm.num_conns; i++)
1087
2475
 
1088
2476
        if (!conn->pBuffer)
1089
2477
        {
1090
 
            crVBoxHGCMPollHost(conn);
 
2478
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
 
2479
            PCRVBOXHGSMI_CLIENT pClient;
 
2480
            if (g_crvboxhgcm.bHgsmiOn && !!(pClient = _crVBoxHGSMIClientGet(conn)))
 
2481
            {
 
2482
                _crVBoxHGSMIPollHost(conn, pClient);
 
2483
            }
 
2484
            else
 
2485
#endif
 
2486
            {
 
2487
                crVBoxHGCMPollHost(conn);
 
2488
            }
1091
2489
        }
1092
2490
    }
1093
2491
#endif
1101
2499
 
1102
2500
        if (conn->cbBuffer>0)
1103
2501
        {
1104
 
            crVBoxHGCMReceiveMessage(conn);
 
2502
            _crVBoxHGCMReceiveMessage(conn);
1105
2503
        }
1106
2504
    }
1107
2505
 
 
2506
#ifdef CHROMIUM_THREADSAFE
 
2507
    crUnlockMutex(&g_crvboxhgcm.mutex);
 
2508
#endif
 
2509
 
 
2510
    VBOXCRHGSMIPROFILE_FUNC_EPILOGUE();
 
2511
 
1108
2512
    return 0;
1109
2513
}
1110
2514