VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManageUSB.cpp@ 93507

Last change on this file since 93507 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.9 KB
Line 
1/* $Id: VBoxManageUSB.cpp 93115 2022-01-01 11:31:46Z vboxsync $ */
2/** @file
3 * VBoxManage - VirtualBox's command-line interface.
4 */
5
6/*
7 * Copyright (C) 2006-2022 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#include <VBox/com/com.h>
19#include <VBox/com/string.h>
20#include <VBox/com/Guid.h>
21#include <VBox/com/array.h>
22#include <VBox/com/ErrorInfo.h>
23#include <VBox/com/errorprint.h>
24#include <VBox/com/VirtualBox.h>
25
26#include "VBoxManage.h"
27
28#include <iprt/asm.h>
29
30using namespace com;
31
32DECLARE_TRANSLATION_CONTEXT(Usb);
33
34/**
35 * Quick IUSBDevice implementation for detaching / attaching
36 * devices to the USB Controller.
37 */
38class MyUSBDevice : public IUSBDevice
39{
40public:
41 // public initializer/uninitializer for internal purposes only
42 MyUSBDevice(uint16_t a_u16VendorId, uint16_t a_u16ProductId, uint16_t a_bcdRevision, uint64_t a_u64SerialHash, const char *a_pszComment)
43 : m_usVendorId(a_u16VendorId), m_usProductId(a_u16ProductId),
44 m_bcdRevision(a_bcdRevision), m_u64SerialHash(a_u64SerialHash),
45 m_bstrComment(a_pszComment),
46 m_cRefs(0)
47 {
48 }
49 virtual ~MyUSBDevice() {}
50
51 STDMETHOD_(ULONG, AddRef)(void)
52 {
53 return ASMAtomicIncU32(&m_cRefs);
54 }
55 STDMETHOD_(ULONG, Release)(void)
56 {
57 ULONG cRefs = ASMAtomicDecU32(&m_cRefs);
58 if (!cRefs)
59 delete this;
60 return cRefs;
61 }
62 STDMETHOD(QueryInterface)(const IID &iid, void **ppvObject)
63 {
64 Guid guid(iid);
65 if (guid == Guid(COM_IIDOF(IUnknown)))
66 *ppvObject = (IUnknown *)this;
67#ifdef RT_OS_WINDOWS
68 else if (guid == Guid(COM_IIDOF(IDispatch)))
69 *ppvObject = (IDispatch *)this;
70#endif
71 else if (guid == Guid(COM_IIDOF(IUSBDevice)))
72 *ppvObject = (IUSBDevice *)this;
73 else
74 return E_NOINTERFACE;
75 AddRef();
76 return S_OK;
77 }
78
79 STDMETHOD(COMGETTER(Id))(OUT_GUID a_pId) { NOREF(a_pId); return E_NOTIMPL; }
80 STDMETHOD(COMGETTER(VendorId))(USHORT *a_pusVendorId) { *a_pusVendorId = m_usVendorId; return S_OK; }
81 STDMETHOD(COMGETTER(ProductId))(USHORT *a_pusProductId) { *a_pusProductId = m_usProductId; return S_OK; }
82 STDMETHOD(COMGETTER(Revision))(USHORT *a_pusRevision) { *a_pusRevision = m_bcdRevision; return S_OK; }
83 STDMETHOD(COMGETTER(SerialHash))(ULONG64 *a_pullSerialHash) { *a_pullSerialHash = m_u64SerialHash; return S_OK; }
84 STDMETHOD(COMGETTER(Manufacturer))(BSTR *a_pManufacturer) { NOREF(a_pManufacturer); return E_NOTIMPL; }
85 STDMETHOD(COMGETTER(Product))(BSTR *a_pProduct) { NOREF(a_pProduct); return E_NOTIMPL; }
86 STDMETHOD(COMGETTER(SerialNumber))(BSTR *a_pSerialNumber) { NOREF(a_pSerialNumber); return E_NOTIMPL; }
87 STDMETHOD(COMGETTER(Address))(BSTR *a_pAddress) { NOREF(a_pAddress); return E_NOTIMPL; }
88
89private:
90 /** The vendor id of this USB device. */
91 USHORT m_usVendorId;
92 /** The product id of this USB device. */
93 USHORT m_usProductId;
94 /** The product revision number of this USB device.
95 * (high byte = integer; low byte = decimal) */
96 USHORT m_bcdRevision;
97 /** The USB serial hash of the device. */
98 uint64_t m_u64SerialHash;
99 /** The user comment string. */
100 Bstr m_bstrComment;
101 /** Reference counter. */
102 uint32_t volatile m_cRefs;
103};
104
105
106// types
107///////////////////////////////////////////////////////////////////////////////
108
109template <typename T>
110class Nullable
111{
112public:
113
114 Nullable() : mIsNull(true) {}
115 Nullable(const T &aValue, bool aIsNull = false)
116 : mIsNull(aIsNull), mValue(aValue) {}
117
118 bool isNull() const { return mIsNull; };
119 void setNull(bool aIsNull = true) { mIsNull = aIsNull; }
120
121 operator const T&() const { return mValue; }
122
123 Nullable &operator= (const T &aValue)
124 {
125 mValue = aValue;
126 mIsNull = false;
127 return *this;
128 }
129
130private:
131
132 bool mIsNull;
133 T mValue;
134};
135
136/** helper structure to encapsulate USB filter manipulation commands */
137struct USBFilterCmd
138{
139 struct USBFilter
140 {
141 USBFilter()
142 : mAction(USBDeviceFilterAction_Null)
143 {}
144
145 Bstr mName;
146 Nullable <bool> mActive;
147 Bstr mVendorId;
148 Bstr mProductId;
149 Bstr mRevision;
150 Bstr mManufacturer;
151 Bstr mProduct;
152 Bstr mRemote;
153 Bstr mSerialNumber;
154 Nullable <ULONG> mMaskedInterfaces;
155 USBDeviceFilterAction_T mAction;
156 };
157
158 enum Action { Invalid, Add, Modify, Remove };
159
160 USBFilterCmd() : mAction(Invalid), mIndex(0), mGlobal(false) {}
161
162 Action mAction;
163 uint32_t mIndex;
164 /** flag whether the command target is a global filter */
165 bool mGlobal;
166 /** machine this command is targeted at (null for global filters) */
167 ComPtr<IMachine> mMachine;
168 USBFilter mFilter;
169};
170
171RTEXITCODE handleUSBFilter(HandlerArg *a)
172{
173 HRESULT rc = S_OK;
174 USBFilterCmd cmd;
175
176 /* at least: 0: command, 1: index, 2: --target, 3: <target value> */
177 if (a->argc < 4)
178 return errorSyntax(USAGE_USBFILTER, Usb::tr("Not enough parameters"));
179
180 /* which command? */
181 cmd.mAction = USBFilterCmd::Invalid;
182 if (!strcmp(a->argv[0], "add")) cmd.mAction = USBFilterCmd::Add;
183 else if (!strcmp(a->argv[0], "modify")) cmd.mAction = USBFilterCmd::Modify;
184 else if (!strcmp(a->argv[0], "remove")) cmd.mAction = USBFilterCmd::Remove;
185
186 if (cmd.mAction == USBFilterCmd::Invalid)
187 return errorSyntax(USAGE_USBFILTER, Usb::tr("Invalid parameter '%s'"), a->argv[0]);
188
189 /* which index? */
190 if (VINF_SUCCESS != RTStrToUInt32Full(a->argv[1], 10, &cmd.mIndex))
191 return errorSyntax(USAGE_USBFILTER, Usb::tr("Invalid index '%s'"), a->argv[1]);
192
193 switch (cmd.mAction)
194 {
195 case USBFilterCmd::Add:
196 case USBFilterCmd::Modify:
197 {
198 /* at least: 0: command, 1: index, 2: --target, 3: <target value>, 4: --name, 5: <name value> */
199 if (a->argc < 6)
200 {
201 if (cmd.mAction == USBFilterCmd::Add)
202 return errorSyntaxEx(USAGE_USBFILTER, HELP_SCOPE_USBFILTER_ADD, Usb::tr("Not enough parameters"));
203
204 return errorSyntaxEx(USAGE_USBFILTER, HELP_SCOPE_USBFILTER_MODIFY, Usb::tr("Not enough parameters"));
205 }
206
207 // set Active to true by default
208 // (assuming that the user sets up all necessary attributes
209 // at once and wants the filter to be active immediately)
210 if (cmd.mAction == USBFilterCmd::Add)
211 cmd.mFilter.mActive = true;
212
213 for (int i = 2; i < a->argc; i++)
214 {
215 if ( !strcmp(a->argv[i], "--target")
216 || !strcmp(a->argv[i], "-target"))
217 {
218 if (a->argc <= i + 1 || !*a->argv[i+1])
219 return errorArgument(Usb::tr("Missing argument to '%s'"), a->argv[i]);
220 i++;
221 if (!strcmp(a->argv[i], "global"))
222 cmd.mGlobal = true;
223 else
224 {
225 /* assume it's a UUID of a machine */
226 CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(a->argv[i]).raw(),
227 cmd.mMachine.asOutParam()), RTEXITCODE_FAILURE);
228 }
229 }
230 else if ( !strcmp(a->argv[i], "--name")
231 || !strcmp(a->argv[i], "-name"))
232 {
233 if (a->argc <= i + 1 || !*a->argv[i+1])
234 return errorArgument(Usb::tr("Missing argument to '%s'"), a->argv[i]);
235 i++;
236 cmd.mFilter.mName = a->argv[i];
237 }
238 else if ( !strcmp(a->argv[i], "--active")
239 || !strcmp(a->argv[i], "-active"))
240 {
241 if (a->argc <= i + 1)
242 return errorArgument(Usb::tr("Missing argument to '%s'"), a->argv[i]);
243 i++;
244 if (!strcmp(a->argv[i], "yes"))
245 cmd.mFilter.mActive = true;
246 else if (!strcmp(a->argv[i], "no"))
247 cmd.mFilter.mActive = false;
248 else
249 return errorArgument(Usb::tr("Invalid --active argument '%s'"), a->argv[i]);
250 }
251 else if ( !strcmp(a->argv[i], "--vendorid")
252 || !strcmp(a->argv[i], "-vendorid"))
253 {
254 if (a->argc <= i + 1)
255 return errorArgument(Usb::tr("Missing argument to '%s'"), a->argv[i]);
256 i++;
257 cmd.mFilter.mVendorId = a->argv[i];
258 }
259 else if ( !strcmp(a->argv[i], "--productid")
260 || !strcmp(a->argv[i], "-productid"))
261 {
262 if (a->argc <= i + 1)
263 return errorArgument(Usb::tr("Missing argument to '%s'"), a->argv[i]);
264 i++;
265 cmd.mFilter.mProductId = a->argv[i];
266 }
267 else if ( !strcmp(a->argv[i], "--revision")
268 || !strcmp(a->argv[i], "-revision"))
269 {
270 if (a->argc <= i + 1)
271 return errorArgument(Usb::tr("Missing argument to '%s'"), a->argv[i]);
272 i++;
273 cmd.mFilter.mRevision = a->argv[i];
274 }
275 else if ( !strcmp(a->argv[i], "--manufacturer")
276 || !strcmp(a->argv[i], "-manufacturer"))
277 {
278 if (a->argc <= i + 1)
279 return errorArgument(Usb::tr("Missing argument to '%s'"), a->argv[i]);
280 i++;
281 cmd.mFilter.mManufacturer = a->argv[i];
282 }
283 else if ( !strcmp(a->argv[i], "--product")
284 || !strcmp(a->argv[i], "-product"))
285 {
286 if (a->argc <= i + 1)
287 return errorArgument(Usb::tr("Missing argument to '%s'"), a->argv[i]);
288 i++;
289 cmd.mFilter.mProduct = a->argv[i];
290 }
291 else if ( !strcmp(a->argv[i], "--remote")
292 || !strcmp(a->argv[i], "-remote"))
293 {
294 if (a->argc <= i + 1)
295 return errorArgument(Usb::tr("Missing argument to '%s'"), a->argv[i]);
296 i++;
297 cmd.mFilter.mRemote = a->argv[i];
298 }
299 else if ( !strcmp(a->argv[i], "--serialnumber")
300 || !strcmp(a->argv[i], "-serialnumber"))
301 {
302 if (a->argc <= i + 1)
303 return errorArgument(Usb::tr("Missing argument to '%s'"), a->argv[i]);
304 i++;
305 cmd.mFilter.mSerialNumber = a->argv[i];
306 }
307 else if ( !strcmp(a->argv[i], "--maskedinterfaces")
308 || !strcmp(a->argv[i], "-maskedinterfaces"))
309 {
310 if (a->argc <= i + 1)
311 return errorArgument(Usb::tr("Missing argument to '%s'"), a->argv[i]);
312 i++;
313 uint32_t u32;
314 int vrc = RTStrToUInt32Full(a->argv[i], 0, &u32);
315 if (RT_FAILURE(vrc))
316 return errorArgument(Usb::tr("Failed to convert the --maskedinterfaces value '%s' to a number, vrc=%Rrc"),
317 a->argv[i], vrc);
318 cmd.mFilter.mMaskedInterfaces = u32;
319 }
320 else if ( !strcmp(a->argv[i], "--action")
321 || !strcmp(a->argv[i], "-action"))
322 {
323 if (a->argc <= i + 1)
324 return errorArgument(Usb::tr("Missing argument to '%s'"), a->argv[i]);
325 i++;
326 if (!strcmp(a->argv[i], "ignore"))
327 cmd.mFilter.mAction = USBDeviceFilterAction_Ignore;
328 else if (!strcmp(a->argv[i], "hold"))
329 cmd.mFilter.mAction = USBDeviceFilterAction_Hold;
330 else
331 return errorArgument(Usb::tr("Invalid USB filter action '%s'"), a->argv[i]);
332 }
333 else
334 return errorSyntaxEx(USAGE_USBFILTER, cmd.mAction == USBFilterCmd::Add ? HELP_SCOPE_USBFILTER_ADD : HELP_SCOPE_USBFILTER_MODIFY,
335 Usb::tr("Unknown option '%s'"), a->argv[i]);
336 }
337
338 if (cmd.mAction == USBFilterCmd::Add)
339 {
340 // mandatory/forbidden options
341 if ( cmd.mFilter.mName.isEmpty()
342 ||
343 ( cmd.mGlobal
344 && cmd.mFilter.mAction == USBDeviceFilterAction_Null
345 )
346 || ( !cmd.mGlobal
347 && !cmd.mMachine)
348 || ( cmd.mGlobal
349 && !cmd.mFilter.mRemote.isEmpty())
350 )
351 {
352 return errorSyntaxEx(USAGE_USBFILTER, HELP_SCOPE_USBFILTER_ADD, Usb::tr("Mandatory options not supplied"));
353 }
354 }
355 break;
356 }
357
358 case USBFilterCmd::Remove:
359 {
360 /* at least: 0: command, 1: index, 2: --target, 3: <target value> */
361 if (a->argc < 4)
362 return errorSyntaxEx(USAGE_USBFILTER, HELP_SCOPE_USBFILTER_REMOVE, Usb::tr("Not enough parameters"));
363
364 for (int i = 2; i < a->argc; i++)
365 {
366 if ( !strcmp(a->argv[i], "--target")
367 || !strcmp(a->argv[i], "-target"))
368 {
369 if (a->argc <= i + 1 || !*a->argv[i+1])
370 return errorArgument(Usb::tr("Missing argument to '%s'"), a->argv[i]);
371 i++;
372 if (!strcmp(a->argv[i], "global"))
373 cmd.mGlobal = true;
374 else
375 {
376 CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(a->argv[i]).raw(),
377 cmd.mMachine.asOutParam()), RTEXITCODE_FAILURE);
378 }
379 }
380 }
381
382 // mandatory options
383 if (!cmd.mGlobal && !cmd.mMachine)
384 return errorSyntaxEx(USAGE_USBFILTER, HELP_SCOPE_USBFILTER_REMOVE, Usb::tr("Mandatory options not supplied"));
385
386 break;
387 }
388
389 default: break;
390 }
391
392 USBFilterCmd::USBFilter &f = cmd.mFilter;
393
394 ComPtr<IHost> host;
395 ComPtr<IUSBDeviceFilters> flts;
396 if (cmd.mGlobal)
397 CHECK_ERROR_RET(a->virtualBox, COMGETTER(Host)(host.asOutParam()), RTEXITCODE_FAILURE);
398 else
399 {
400 /* open a session for the VM */
401 CHECK_ERROR_RET(cmd.mMachine, LockMachine(a->session, LockType_Shared), RTEXITCODE_FAILURE);
402 /* get the mutable session machine */
403 a->session->COMGETTER(Machine)(cmd.mMachine.asOutParam());
404 /* and get the USB device filters */
405 CHECK_ERROR_RET(cmd.mMachine, COMGETTER(USBDeviceFilters)(flts.asOutParam()), RTEXITCODE_FAILURE);
406 }
407
408 switch (cmd.mAction)
409 {
410 case USBFilterCmd::Add:
411 {
412 if (cmd.mGlobal)
413 {
414 ComPtr<IHostUSBDeviceFilter> flt;
415 CHECK_ERROR_BREAK(host, CreateUSBDeviceFilter(f.mName.raw(),
416 flt.asOutParam()));
417
418 if (!f.mActive.isNull())
419 CHECK_ERROR_BREAK(flt, COMSETTER(Active)(f.mActive));
420 if (!f.mVendorId.isEmpty())
421 CHECK_ERROR_BREAK(flt, COMSETTER(VendorId)(f.mVendorId.raw()));
422 if (!f.mProductId.isEmpty())
423 CHECK_ERROR_BREAK(flt, COMSETTER(ProductId)(f.mProductId.raw()));
424 if (!f.mRevision.isEmpty())
425 CHECK_ERROR_BREAK(flt, COMSETTER(Revision)(f.mRevision.raw()));
426 if (!f.mManufacturer.isEmpty())
427 CHECK_ERROR_BREAK(flt, COMSETTER(Manufacturer)(f.mManufacturer.raw()));
428 if (!f.mSerialNumber.isEmpty())
429 CHECK_ERROR_BREAK(flt, COMSETTER(SerialNumber)(f.mSerialNumber.raw()));
430 if (!f.mMaskedInterfaces.isNull())
431 CHECK_ERROR_BREAK(flt, COMSETTER(MaskedInterfaces)(f.mMaskedInterfaces));
432
433 if (f.mAction != USBDeviceFilterAction_Null)
434 CHECK_ERROR_BREAK(flt, COMSETTER(Action)(f.mAction));
435
436 CHECK_ERROR_BREAK(host, InsertUSBDeviceFilter(cmd.mIndex, flt));
437 }
438 else
439 {
440 ComPtr<IUSBDeviceFilter> flt;
441 CHECK_ERROR_BREAK(flts, CreateDeviceFilter(f.mName.raw(),
442 flt.asOutParam()));
443
444 if (!f.mActive.isNull())
445 CHECK_ERROR_BREAK(flt, COMSETTER(Active)(f.mActive));
446 if (!f.mVendorId.isEmpty())
447 CHECK_ERROR_BREAK(flt, COMSETTER(VendorId)(f.mVendorId.raw()));
448 if (!f.mProductId.isEmpty())
449 CHECK_ERROR_BREAK(flt, COMSETTER(ProductId)(f.mProductId.raw()));
450 if (!f.mRevision.isEmpty())
451 CHECK_ERROR_BREAK(flt, COMSETTER(Revision)(f.mRevision.raw()));
452 if (!f.mManufacturer.isEmpty())
453 CHECK_ERROR_BREAK(flt, COMSETTER(Manufacturer)(f.mManufacturer.raw()));
454 if (!f.mRemote.isEmpty())
455 CHECK_ERROR_BREAK(flt, COMSETTER(Remote)(f.mRemote.raw()));
456 if (!f.mSerialNumber.isEmpty())
457 CHECK_ERROR_BREAK(flt, COMSETTER(SerialNumber)(f.mSerialNumber.raw()));
458 if (!f.mMaskedInterfaces.isNull())
459 CHECK_ERROR_BREAK(flt, COMSETTER(MaskedInterfaces)(f.mMaskedInterfaces));
460
461 CHECK_ERROR_BREAK(flts, InsertDeviceFilter(cmd.mIndex, flt));
462 }
463 break;
464 }
465 case USBFilterCmd::Modify:
466 {
467 if (cmd.mGlobal)
468 {
469 SafeIfaceArray <IHostUSBDeviceFilter> coll;
470 CHECK_ERROR_BREAK(host, COMGETTER(USBDeviceFilters)(ComSafeArrayAsOutParam(coll)));
471
472 ComPtr<IHostUSBDeviceFilter> flt = coll[cmd.mIndex];
473
474 if (!f.mName.isEmpty())
475 CHECK_ERROR_BREAK(flt, COMSETTER(Name)(f.mName.raw()));
476 if (!f.mActive.isNull())
477 CHECK_ERROR_BREAK(flt, COMSETTER(Active)(f.mActive));
478 if (!f.mVendorId.isEmpty())
479 CHECK_ERROR_BREAK(flt, COMSETTER(VendorId)(f.mVendorId.raw()));
480 if (!f.mProductId.isEmpty())
481 CHECK_ERROR_BREAK(flt, COMSETTER(ProductId)(f.mProductId.raw()));
482 if (!f.mRevision.isEmpty())
483 CHECK_ERROR_BREAK(flt, COMSETTER(Revision)(f.mRevision.raw()));
484 if (!f.mManufacturer.isEmpty())
485 CHECK_ERROR_BREAK(flt, COMSETTER(Manufacturer)(f.mManufacturer.raw()));
486 if (!f.mSerialNumber.isEmpty())
487 CHECK_ERROR_BREAK(flt, COMSETTER(SerialNumber)(f.mSerialNumber.raw()));
488 if (!f.mMaskedInterfaces.isNull())
489 CHECK_ERROR_BREAK(flt, COMSETTER(MaskedInterfaces)(f.mMaskedInterfaces));
490
491 if (f.mAction != USBDeviceFilterAction_Null)
492 CHECK_ERROR_BREAK(flt, COMSETTER(Action)(f.mAction));
493 }
494 else
495 {
496 SafeIfaceArray <IUSBDeviceFilter> coll;
497 CHECK_ERROR_BREAK(flts, COMGETTER(DeviceFilters)(ComSafeArrayAsOutParam(coll)));
498
499 ComPtr<IUSBDeviceFilter> flt = coll[cmd.mIndex];
500
501 if (!f.mName.isEmpty())
502 CHECK_ERROR_BREAK(flt, COMSETTER(Name)(f.mName.raw()));
503 if (!f.mActive.isNull())
504 CHECK_ERROR_BREAK(flt, COMSETTER(Active)(f.mActive));
505 if (!f.mVendorId.isEmpty())
506 CHECK_ERROR_BREAK(flt, COMSETTER(VendorId)(f.mVendorId.raw()));
507 if (!f.mProductId.isEmpty())
508 CHECK_ERROR_BREAK(flt, COMSETTER(ProductId)(f.mProductId.raw()));
509 if (!f.mRevision.isEmpty())
510 CHECK_ERROR_BREAK(flt, COMSETTER(Revision)(f.mRevision.raw()));
511 if (!f.mManufacturer.isEmpty())
512 CHECK_ERROR_BREAK(flt, COMSETTER(Manufacturer)(f.mManufacturer.raw()));
513 if (!f.mRemote.isEmpty())
514 CHECK_ERROR_BREAK(flt, COMSETTER(Remote)(f.mRemote.raw()));
515 if (!f.mSerialNumber.isEmpty())
516 CHECK_ERROR_BREAK(flt, COMSETTER(SerialNumber)(f.mSerialNumber.raw()));
517 if (!f.mMaskedInterfaces.isNull())
518 CHECK_ERROR_BREAK(flt, COMSETTER(MaskedInterfaces)(f.mMaskedInterfaces));
519 }
520 break;
521 }
522 case USBFilterCmd::Remove:
523 {
524 if (cmd.mGlobal)
525 {
526 ComPtr<IHostUSBDeviceFilter> flt;
527 CHECK_ERROR_BREAK(host, RemoveUSBDeviceFilter(cmd.mIndex));
528 }
529 else
530 {
531 ComPtr<IUSBDeviceFilter> flt;
532 CHECK_ERROR_BREAK(flts, RemoveDeviceFilter(cmd.mIndex, flt.asOutParam()));
533 }
534 break;
535 }
536 default:
537 break;
538 }
539
540 if (cmd.mMachine)
541 {
542 if (SUCCEEDED(rc))
543 {
544 /* commit the session */
545 CHECK_ERROR(cmd.mMachine, SaveSettings());
546 }
547 /* close the session */
548 a->session->UnlockMachine();
549 }
550
551 return SUCCEEDED(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
552}
553
554RTEXITCODE handleUSBDevSource(HandlerArg *a)
555{
556 HRESULT rc = S_OK;
557
558 /* at least: 0: command, 1: source id */
559 if (a->argc < 2)
560 return errorSyntax(USAGE_USBDEVSOURCE, Usb::tr("Not enough parameters"));
561
562 ComPtr<IHost> host;
563 if (!strcmp(a->argv[0], "add"))
564 {
565 Bstr strBackend;
566 Bstr strAddress;
567 if (a->argc != 6)
568 return errorSyntax(USAGE_USBDEVSOURCE, Usb::tr("Invalid number of parameters"));
569
570 for (int i = 2; i < a->argc; i++)
571 {
572 if (!strcmp(a->argv[i], "--backend"))
573 {
574 i++;
575 strBackend = a->argv[i];
576 }
577 else if (!strcmp(a->argv[i], "--address"))
578 {
579 i++;
580 strAddress = a->argv[i];
581 }
582 else
583 return errorSyntax(USAGE_USBDEVSOURCE, Usb::tr("Parameter \"%s\" is invalid"), a->argv[i]);
584 }
585
586 SafeArray<BSTR> usbSourcePropNames;
587 SafeArray<BSTR> usbSourcePropValues;
588
589 CHECK_ERROR_RET(a->virtualBox, COMGETTER(Host)(host.asOutParam()), RTEXITCODE_FAILURE);
590 CHECK_ERROR_RET(host, AddUSBDeviceSource(strBackend.raw(), Bstr(a->argv[1]).raw(), strAddress.raw(),
591 ComSafeArrayAsInParam(usbSourcePropNames), ComSafeArrayAsInParam(usbSourcePropValues)),
592 RTEXITCODE_FAILURE);
593 }
594 else if (!strcmp(a->argv[0], "remove"))
595 {
596 CHECK_ERROR_RET(a->virtualBox, COMGETTER(Host)(host.asOutParam()), RTEXITCODE_FAILURE);
597 CHECK_ERROR_RET(host, RemoveUSBDeviceSource(Bstr(a->argv[1]).raw()), RTEXITCODE_FAILURE);
598 }
599
600 return SUCCEEDED(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
601}
602
603/* vi: set tabstop=4 shiftwidth=4 expandtab: */
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