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

« back to all changes in this revision

Viewing changes to src/VBox/Main/src-server/win/USBProxyServiceWindows.cpp

  • 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: USBProxyServiceWindows.cpp 35368 2010-12-30 13:38:23Z vboxsync $ */
 
2
/** @file
 
3
 * VirtualBox USB Proxy Service, Windows Specialization.
 
4
 */
 
5
 
 
6
/*
 
7
 * Copyright (C) 2006-2010 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
/*******************************************************************************
 
20
*   Header Files                                                               *
 
21
*******************************************************************************/
 
22
#include "USBProxyService.h"
 
23
#include "Logging.h"
 
24
 
 
25
#include <VBox/usb.h>
 
26
#include <VBox/err.h>
 
27
 
 
28
#include <iprt/string.h>
 
29
#include <iprt/alloc.h>
 
30
#include <iprt/assert.h>
 
31
#include <iprt/file.h>
 
32
#include <iprt/err.h>
 
33
 
 
34
#include <VBox/usblib.h>
 
35
 
 
36
 
 
37
/**
 
38
 * Initialize data members.
 
39
 */
 
40
USBProxyServiceWindows::USBProxyServiceWindows(Host *aHost)
 
41
    : USBProxyService(aHost), mhEventInterrupt(INVALID_HANDLE_VALUE)
 
42
{
 
43
    LogFlowThisFunc(("aHost=%p\n", aHost));
 
44
}
 
45
 
 
46
 
 
47
/**
 
48
 * Initializes the object (called right after construction).
 
49
 *
 
50
 * @returns S_OK on success and non-fatal failures, some COM error otherwise.
 
51
 */
 
52
HRESULT USBProxyServiceWindows::init(void)
 
53
{
 
54
    /*
 
55
     * Call the superclass method first.
 
56
     */
 
57
    HRESULT hrc = USBProxyService::init();
 
58
    AssertComRCReturn(hrc, hrc);
 
59
 
 
60
    /*
 
61
     * Create the semaphore (considered fatal).
 
62
     */
 
63
    mhEventInterrupt = CreateEvent(NULL, FALSE, FALSE, NULL);
 
64
    AssertReturn(mhEventInterrupt != INVALID_HANDLE_VALUE, E_FAIL);
 
65
 
 
66
    /*
 
67
     * Initialize the USB lib and stuff.
 
68
     */
 
69
    int rc = USBLibInit();
 
70
    if (RT_SUCCESS(rc))
 
71
    {
 
72
        /*
 
73
         * Start the poller thread.
 
74
         */
 
75
        rc = start();
 
76
        if (RT_SUCCESS(rc))
 
77
        {
 
78
            LogFlowThisFunc(("returns successfully\n"));
 
79
            return S_OK;
 
80
        }
 
81
 
 
82
        USBLibTerm();
 
83
    }
 
84
 
 
85
    CloseHandle(mhEventInterrupt);
 
86
    mhEventInterrupt = INVALID_HANDLE_VALUE;
 
87
 
 
88
    LogFlowThisFunc(("returns failure!!! (rc=%Rrc)\n", rc));
 
89
    mLastError = rc;
 
90
    return S_OK;
 
91
}
 
92
 
 
93
 
 
94
/**
 
95
 * Stop all service threads and free the device chain.
 
96
 */
 
97
USBProxyServiceWindows::~USBProxyServiceWindows()
 
98
{
 
99
    LogFlowThisFunc(("\n"));
 
100
 
 
101
    /*
 
102
     * Stop the service.
 
103
     */
 
104
    if (isActive())
 
105
        stop();
 
106
 
 
107
    if (mhEventInterrupt != INVALID_HANDLE_VALUE)
 
108
        CloseHandle(mhEventInterrupt);
 
109
    mhEventInterrupt = INVALID_HANDLE_VALUE;
 
110
 
 
111
    /*
 
112
     * Terminate the library...
 
113
     */
 
114
    int rc = USBLibTerm();
 
115
    AssertRC(rc);
 
116
}
 
117
 
 
118
 
 
119
void *USBProxyServiceWindows::insertFilter(PCUSBFILTER aFilter)
 
120
{
 
121
    AssertReturn(aFilter, NULL);
 
122
 
 
123
    LogFlow(("USBProxyServiceWindows::insertFilter()\n"));
 
124
 
 
125
    void *pvId = USBLibAddFilter(aFilter);
 
126
 
 
127
    LogFlow(("USBProxyServiceWindows::insertFilter(): returning pvId=%p\n", pvId));
 
128
 
 
129
    return pvId;
 
130
}
 
131
 
 
132
 
 
133
void USBProxyServiceWindows::removeFilter(void *aID)
 
134
{
 
135
    LogFlow(("USBProxyServiceWindows::removeFilter(): id=%p\n", aID));
 
136
 
 
137
    AssertReturnVoid(aID);
 
138
 
 
139
    USBLibRemoveFilter(aID);
 
140
}
 
141
 
 
142
 
 
143
int USBProxyServiceWindows::captureDevice(HostUSBDevice *aDevice)
 
144
{
 
145
    AssertReturn(aDevice, VERR_GENERAL_FAILURE);
 
146
    AssertReturn(aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
 
147
    Assert(aDevice->getUnistate() == kHostUSBDeviceState_Capturing);
 
148
 
 
149
/** @todo pass up a one-shot filter like on darwin?  */
 
150
    USHORT vendorId, productId, revision;
 
151
 
 
152
    HRESULT rc;
 
153
 
 
154
    rc = aDevice->COMGETTER(VendorId)(&vendorId);
 
155
    AssertComRCReturn(rc, VERR_INTERNAL_ERROR);
 
156
 
 
157
    rc = aDevice->COMGETTER(ProductId)(&productId);
 
158
    AssertComRCReturn(rc, VERR_INTERNAL_ERROR);
 
159
 
 
160
    rc = aDevice->COMGETTER(Revision)(&revision);
 
161
    AssertComRCReturn(rc, VERR_INTERNAL_ERROR);
 
162
 
 
163
    return USBLibCaptureDevice(vendorId, productId, revision);
 
164
}
 
165
 
 
166
 
 
167
int USBProxyServiceWindows::releaseDevice(HostUSBDevice *aDevice)
 
168
{
 
169
    AssertReturn(aDevice, VERR_GENERAL_FAILURE);
 
170
    AssertReturn(aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
 
171
    Assert(aDevice->getUnistate() == kHostUSBDeviceState_ReleasingToHost);
 
172
 
 
173
/** @todo pass up a one-shot filter like on darwin?  */
 
174
    USHORT vendorId, productId, revision;
 
175
    HRESULT rc;
 
176
 
 
177
    rc = aDevice->COMGETTER(VendorId)(&vendorId);
 
178
    AssertComRCReturn(rc, VERR_INTERNAL_ERROR);
 
179
 
 
180
    rc = aDevice->COMGETTER(ProductId)(&productId);
 
181
    AssertComRCReturn(rc, VERR_INTERNAL_ERROR);
 
182
 
 
183
    rc = aDevice->COMGETTER(Revision)(&revision);
 
184
    AssertComRCReturn(rc, VERR_INTERNAL_ERROR);
 
185
 
 
186
    Log(("USBProxyServiceWindows::releaseDevice\n"));
 
187
    return USBLibReleaseDevice(vendorId, productId, revision);
 
188
}
 
189
 
 
190
 
 
191
bool USBProxyServiceWindows::updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine)
 
192
{
 
193
    /* Nothing special here so far, so fall back on parent */
 
194
    return USBProxyService::updateDeviceState(aDevice, aUSBDevice, aRunFilters, aIgnoreMachine);
 
195
 
 
196
/// @todo remove?
 
197
#if 0
 
198
    AssertReturn(aDevice, false);
 
199
    AssertReturn(aDevice->isWriteLockOnCurrentThread(), false);
 
200
 
 
201
    /*
 
202
     * We're only called in the 'existing device' state, so if there is a pending async
 
203
     * operation we can check if it completed here and suppress state changes if it hasn't.
 
204
     */
 
205
    /* TESTME */
 
206
    if (aDevice->isStatePending())
 
207
    {
 
208
        bool fRc = aDevice->updateState(aUSBDevice);
 
209
        if (fRc)
 
210
        {
 
211
            if (aDevice->state() != aDevice->pendingState())
 
212
                fRc = false;
 
213
        }
 
214
        return fRc;
 
215
    }
 
216
 
 
217
    /* fall back on parent. */
 
218
    return USBProxyService::updateDeviceState(aDevice, aUSBDevice, aRunFilters, aIgnoreMachine);
 
219
#endif
 
220
}
 
221
 
 
222
 
 
223
int USBProxyServiceWindows::wait(unsigned aMillies)
 
224
{
 
225
    DWORD rc;
 
226
 
 
227
    /* Not going to do something fancy where we block in the filter
 
228
     * driver and are woken up when the state has changed.
 
229
     * Would be better, but this is good enough.
 
230
     */
 
231
    do
 
232
    {
 
233
        rc = WaitForSingleObject(mhEventInterrupt, RT_MIN(aMillies, 100));
 
234
        if (rc == WAIT_OBJECT_0)
 
235
            return VINF_SUCCESS;
 
236
        /** @todo handle WAIT_FAILED here */
 
237
 
 
238
        if (USBLibHasPendingDeviceChanges() == true)
 
239
        {
 
240
            Log(("wait thread detected usb change\n"));
 
241
            return VINF_SUCCESS;
 
242
        }
 
243
 
 
244
        if (aMillies > 100)
 
245
            aMillies -= 100;
 
246
    }
 
247
    while (aMillies > 100);
 
248
 
 
249
    return VERR_TIMEOUT;
 
250
}
 
251
 
 
252
 
 
253
int USBProxyServiceWindows::interruptWait(void)
 
254
{
 
255
    SetEvent(mhEventInterrupt);
 
256
    return VINF_SUCCESS;
 
257
}
 
258
 
 
259
 
 
260
/**
 
261
 * Gets a list of all devices the VM can grab
 
262
 */
 
263
PUSBDEVICE USBProxyServiceWindows::getDevices(void)
 
264
{
 
265
    PUSBDEVICE pDevices = NULL;
 
266
    uint32_t cDevices = 0;
 
267
 
 
268
    Log(("USBProxyServiceWindows::getDevices\n"));
 
269
    USBLibGetDevices(&pDevices, &cDevices);
 
270
    return pDevices;
 
271
}
 
272