VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxUSB/solaris/USBLib-solaris.cpp@ 36657

Last change on this file since 36657 was 36341, checked in by vboxsync, 14 years ago

HostDrivers/VBoxUSB/solaris: LogRel device capture/release and fix misleading variable names.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.0 KB
Line 
1/** $Id: USBLib-solaris.cpp 36341 2011-03-22 13:27:34Z vboxsync $ */
2/** @file
3 * USBLib - Library for wrapping up the VBoxUSB functionality, Solaris flavor.
4 */
5
6/*
7 * Copyright (C) 2008 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 <VBox/usblib.h>
23#include <VBox/err.h>
24#include <VBox/log.h>
25#include <iprt/assert.h>
26#include <iprt/asm.h>
27#include <iprt/file.h>
28#include <iprt/mem.h>
29#include <iprt/process.h>
30#include <iprt/env.h>
31#include <iprt/path.h>
32#include <iprt/string.h>
33
34# include <sys/types.h>
35# include <sys/stat.h>
36# include <errno.h>
37# include <unistd.h>
38# include <string.h>
39# include <limits.h>
40# include <strings.h>
41
42/** -XXX- Remove this hackery eventually */
43#ifdef DEBUG_ramshankar
44# undef Log
45# undef LogFlow
46# define Log LogRel
47# define LogFlow LogRel
48#endif
49
50/*******************************************************************************
51* Defined Constants And Macros *
52*******************************************************************************/
53/** Logging class. */
54#define USBLIBR3 "USBLibR3"
55
56
57/*******************************************************************************
58* Global Variables *
59*******************************************************************************/
60/** Reference counter. */
61static uint32_t volatile g_cUsers = 0;
62/** VBoxUSB Device handle. */
63static RTFILE g_File = NIL_RTFILE;
64/** List of tasks handled by the USB helper. */
65typedef enum USBHELPER_OP
66{
67 ADD_ALIAS = 0,
68 DEL_ALIAS,
69 RESET
70};
71
72/*******************************************************************************
73* Internal Functions *
74*******************************************************************************/
75static int usblibDoIOCtl(unsigned iFunction, void *pvData, size_t cbData);
76static int usblibRunHelper(USBHELPER_OP HelperOp, void *pvData);
77
78
79USBLIB_DECL(int) USBLibInit(void)
80{
81 LogFlow((USBLIBR3 ":USBLibInit\n"));
82
83 /*
84 * Already open?
85 * This isn't properly serialized, but we'll be fine with the current usage.
86 */
87 if (g_cUsers)
88 {
89 ASMAtomicIncU32(&g_cUsers);
90 return VINF_SUCCESS;
91 }
92
93 RTFILE File;
94 int rc = RTFileOpen(&File, VBOXUSB_DEVICE_NAME, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
95 if (RT_FAILURE(rc))
96 {
97 LogRel((USBLIBR3 ":RTFileOpen failed to open VBoxUSB device.rc=%d\n", rc));
98 return rc;
99 }
100 g_File = File;
101
102 ASMAtomicIncU32(&g_cUsers);
103 /*
104 * Check the USBMonitor version.
105 */
106 VBOXUSBREQ_GET_VERSION Req;
107 bzero(&Req, sizeof(Req));
108 rc = usblibDoIOCtl(VBOXUSBMON_IOCTL_GET_VERSION, &Req, sizeof(Req));
109 if (RT_SUCCESS(rc))
110 {
111 if ( Req.u32Major != VBOXUSBMON_VERSION_MAJOR
112 || Req.u32Minor < VBOXUSBMON_VERSION_MINOR)
113 {
114 rc = VERR_VERSION_MISMATCH;
115 LogRel((USBLIBR3 ":USBMonitor version mismatch! driver v%d.%d, expecting ~v%d.%d\n",
116 Req.u32Major, Req.u32Minor, VBOXUSBMON_VERSION_MAJOR, VBOXUSBMON_VERSION_MINOR));
117
118 RTFileClose(File);
119 g_File = NIL_RTFILE;
120 ASMAtomicDecU32(&g_cUsers);
121 return rc;
122 }
123 }
124 else
125 {
126 LogRel((USBLIBR3 ":USBMonitor driver version query failed. rc=%Rrc\n", rc));
127 RTFileClose(File);
128 g_File = NIL_RTFILE;
129 ASMAtomicDecU32(&g_cUsers);
130 return rc;
131 }
132
133 return VINF_SUCCESS;
134}
135
136
137USBLIB_DECL(int) USBLibTerm(void)
138{
139 LogFlow((USBLIBR3 ":USBLibTerm\n"));
140
141 if (!g_cUsers)
142 return VERR_WRONG_ORDER;
143 if (ASMAtomicDecU32(&g_cUsers) != 0)
144 return VINF_SUCCESS;
145
146 /*
147 * We're the last guy, close down the connection.
148 */
149 RTFILE File = g_File;
150 g_File = NIL_RTFILE;
151 if (File == NIL_RTFILE)
152 return VERR_INTERNAL_ERROR;
153
154 int rc = RTFileClose(File);
155 AssertRC(rc);
156 return rc;
157}
158
159
160USBLIB_DECL(void *) USBLibAddFilter(PCUSBFILTER pFilter)
161{
162 LogFlow((USBLIBR3 ":USBLibAddFilter pFilter=%p\n", pFilter));
163
164 VBOXUSBREQ_ADD_FILTER Req;
165 Req.Filter = *pFilter;
166 Req.uId = 0;
167
168 int rc = usblibDoIOCtl(VBOXUSBMON_IOCTL_ADD_FILTER, &Req, sizeof(Req));
169 if (RT_SUCCESS(rc))
170 return (void *)Req.uId;
171
172 AssertMsgFailed((USBLIBR3 ":VBOXUSBMON_IOCTL_ADD_FILTER failed! rc=%Rrc\n", rc));
173 return NULL;
174}
175
176
177USBLIB_DECL(void) USBLibRemoveFilter(void *pvId)
178{
179 LogFlow((USBLIBR3 ":USBLibRemoveFilter pvId=%p\n", pvId));
180
181 VBOXUSBREQ_REMOVE_FILTER Req;
182 Req.uId = (uintptr_t)pvId;
183
184 int rc = usblibDoIOCtl(VBOXUSBMON_IOCTL_REMOVE_FILTER, &Req, sizeof(Req));
185 if (RT_SUCCESS(rc))
186 return;
187
188 AssertMsgFailed((USBLIBR3 ":VBOXUSBMON_IOCTL_REMOVE_FILTER failed! rc=%Rrc\n", rc));
189}
190
191
192USBLIB_DECL(int) USBLibGetClientInfo(char *pszDeviceIdent, char **ppszClientPath, int *pInstance)
193{
194 LogFlow((USBLIBR3 ":USBLibGetClientInfo pszDeviceIdent=%s ppszClientPath=%p pInstance=%p\n",
195 pszDeviceIdent, ppszClientPath, pInstance));
196
197 AssertPtrReturn(pInstance, VERR_INVALID_PARAMETER);
198 AssertPtrReturn(ppszClientPath, VERR_INVALID_PARAMETER);
199 AssertPtrReturn(pszDeviceIdent, VERR_INVALID_PARAMETER);
200
201 VBOXUSBREQ_CLIENT_INFO Req;
202 bzero(&Req, sizeof(Req));
203 RTStrPrintf(Req.szDeviceIdent, sizeof(Req.szDeviceIdent), "%s", pszDeviceIdent);
204
205 int rc = usblibDoIOCtl(VBOXUSBMON_IOCTL_CLIENT_INFO, &Req, sizeof(Req));
206 if (RT_SUCCESS(rc))
207 {
208 *pInstance = Req.Instance;
209 rc = RTStrDupEx(ppszClientPath, Req.szClientPath);
210 if (RT_SUCCESS(rc))
211 return VINF_SUCCESS;
212
213 LogRel((USBLIBR3 ":USBLibGetClientInfo RTStrDupEx failed! rc=%Rrc szClientPath=%s\n", rc, Req.szClientPath));
214 }
215 else
216 LogRel((USBLIBR3 ":USBLibGetClientInfo VBOXUSBMON_IOCTL_CLIENTPATH failed! rc=%Rrc\n", rc));
217
218 return rc;
219}
220
221
222#if 1
223USBLIB_DECL(int) USBLibResetDevice(char *pszDevicePath, bool fReattach)
224{
225 LogFlow((USBLIBR3 ":USBLibResetDevice pszDevicePath=%s\n", pszDevicePath));
226
227 size_t cbReq = sizeof(VBOXUSBREQ_RESET_DEVICE) + strlen(pszDevicePath);
228 VBOXUSBREQ_RESET_DEVICE *pReq = (VBOXUSBREQ_RESET_DEVICE *)RTMemTmpAllocZ(cbReq);
229 if (RT_UNLIKELY(!pReq))
230 return VERR_NO_MEMORY;
231
232 pReq->fReattach = fReattach;
233 strcpy(pReq->szDevicePath, pszDevicePath);
234
235 int rc = usblibDoIOCtl(VBOXUSBMON_IOCTL_RESET_DEVICE, pReq, cbReq);
236 if (RT_FAILURE(rc))
237 LogRel((USBLIBR3 ":VBOXUSBMON_IOCTL_RESET_DEVICE failed! rc=%Rrc\n", rc));
238
239 RTMemFree(pReq);
240 return rc;
241}
242#else
243
244USBLIB_DECL(int) USBLibResetDevice(char *pszDevicePath, bool fReattach)
245{
246 VBOXUSBHELPERDATA_RESET Data;
247 Data.pszDevicePath = pszDevicePath;
248 Data.fHardReset = fReattach;
249 return usblibRunHelper(RESET, &Data);
250}
251#endif
252
253USBLIB_DECL(int) USBLibAddDeviceAlias(PUSBDEVICE pDevice)
254{
255 VBOXUSBHELPERDATA_ALIAS Data;
256 Data.idVendor = pDevice->idVendor;
257 Data.idProduct = pDevice->idProduct;
258 Data.bcdDevice = pDevice->bcdDevice;
259 Data.pszDevicePath = pDevice->pszDevicePath;
260 return usblibRunHelper(ADD_ALIAS, &Data);
261}
262
263
264USBLIB_DECL(int) USBLibRemoveDeviceAlias(PUSBDEVICE pDevice)
265{
266 VBOXUSBHELPERDATA_ALIAS Data;
267 Data.idVendor = pDevice->idVendor;
268 Data.idProduct = pDevice->idProduct;
269 Data.bcdDevice = pDevice->bcdDevice;
270 Data.pszDevicePath = pDevice->pszDevicePath;
271 return usblibRunHelper(DEL_ALIAS, &Data);
272}
273
274#if 0
275USBLIB_DECL(int) USBLibConfigureDevice(PUSBDEVICE pDevice)
276{
277 return usblibRunHelper(pDevice, CONFIGURE);
278}
279#endif
280
281static int usblibRunHelper(USBHELPER_OP HelperOp, void *pvUsbHelperData)
282{
283 LogFlow((USBLIBR3 ":usblibRunHelper HelperOp=%d pvUSBHelperData=%p\n", HelperOp, pvUsbHelperData));
284
285 /*
286 * Find VBoxUSBHelper.
287 */
288 char szDriverCtl[PATH_MAX];
289 int rc = RTPathExecDir(szDriverCtl, sizeof(szDriverCtl) - sizeof("/" VBOXUSB_HELPER_NAME));
290 if (RT_SUCCESS(rc))
291 {
292 strcat(szDriverCtl, "/" VBOXUSB_HELPER_NAME);
293 if (!RTPathExists(szDriverCtl))
294 {
295 LogRel(("USBProxy: path %s does not exist. Failed to run USB helper %s.\n", szDriverCtl, VBOXUSB_HELPER_NAME));
296 return VERR_FILE_NOT_FOUND;
297 }
298
299 /*
300 * Run VBoxUSBHelper task.
301 */
302 const char *pszArgs[5];
303 if (HelperOp == RESET)
304 {
305 PVBOXUSBHELPERDATA_RESET pData = (PVBOXUSBHELPERDATA_RESET)pvUsbHelperData;
306 pszArgs[0] = szDriverCtl;
307 pszArgs[1] = pData->fHardReset ? "hardreset" : "softreset";
308 pszArgs[2] = pData->pszDevicePath;
309 pszArgs[3] = NULL;
310 }
311 else
312 {
313 PVBOXUSBHELPERDATA_ALIAS pData = (PVBOXUSBHELPERDATA_ALIAS)pvUsbHelperData;
314 char szDriverAlias[128];
315
316#if 0
317 /*
318 * USB vid.pid.rev driver binding alias.
319 */
320 RTStrPrintf(szDriverAlias, sizeof(szDriverAlias), "usb%x,%x.%x", pData->idVendor, pData->idProduct, pData->bcdDevice);
321#else
322 /*
323 * Path based driver binding alias.
324 */
325 RTStrPrintf(szDriverAlias, sizeof(szDriverAlias), "%s", pData->pszDevicePath + sizeof("/devices"));
326#endif
327 pszArgs[0] = szDriverCtl;
328 pszArgs[1] = HelperOp == ADD_ALIAS ? "add" : "del";
329 pszArgs[2] = szDriverAlias;
330 pszArgs[3] = VBOXUSB_DRIVER_NAME;
331 }
332 pszArgs[4] = NULL;
333 RTPROCESS pid = NIL_RTPROCESS;
334 rc = RTProcCreate(pszArgs[0], pszArgs, RTENV_DEFAULT, 0, &pid);
335 if (RT_SUCCESS(rc))
336 {
337 RTPROCSTATUS Status;
338 rc = RTProcWait(pid, 0, &Status);
339 if (RT_SUCCESS(rc))
340 {
341 if (Status.enmReason == RTPROCEXITREASON_NORMAL)
342 {
343 switch (Status.iStatus)
344 {
345 case 0: return VINF_SUCCESS; /* @todo later maybe ignore -4 as well (see VBoxUSBHelper return codes). */
346 case -1: return VERR_PERMISSION_DENIED;
347 case -2: return VERR_INVALID_PARAMETER;
348 case -3: return VERR_GENERAL_FAILURE;
349 default: return VERR_INTERNAL_ERROR;
350 }
351 }
352 else
353 LogRel((USBLIBR3 ":abnormal termination of USB Helper. enmReason=%d\n", Status.enmReason));
354 rc = VERR_GENERAL_FAILURE;
355 }
356 else
357 LogRel((USBLIBR3 ":RTProcWait failed rc=%Rrc\n", rc));
358 }
359 else
360 {
361 /* Bad. RTProcCreate() failed! */
362 LogRel((USBLIBR3 ":Failed to fork() process for running USB helper for device %s: rc=%Rrc\n", rc));
363 }
364 }
365 return rc;
366}
367
368
369static int usblibDoIOCtl(unsigned iFunction, void *pvData, size_t cbData)
370{
371 if (g_File == NIL_RTFILE)
372 {
373 LogRel((USBLIBR3 ":IOCtl failed, device not open.\n"));
374 return VERR_FILE_NOT_FOUND;
375 }
376
377 VBOXUSBREQ Hdr;
378 Hdr.u32Magic = VBOXUSBMON_MAGIC;
379 Hdr.cbData = cbData; /* Don't include full size because the header size is fixed. */
380 Hdr.pvDataR3 = pvData;
381
382 int rc = ioctl((int)g_File, iFunction, &Hdr);
383 if (rc < 0)
384 {
385 rc = errno;
386 LogRel((USBLIBR3 ":IOCtl failed iFunction=%x errno=%d g_file=%d\n", iFunction, rc, (int)g_File));
387 return RTErrConvertFromErrno(rc);
388 }
389
390 rc = Hdr.rc;
391 if (RT_UNLIKELY(RT_FAILURE(rc)))
392 LogRel((USBLIBR3 ":Function (%x) failed. rc=%Rrc\n", iFunction, rc));
393
394 return rc;
395}
396
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