VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/utils/usb/UsbTestServiceGadgetHostUsbIp.cpp@ 104195

Last change on this file since 104195 was 98103, checked in by vboxsync, 23 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.7 KB
Line 
1/* $Id: UsbTestServiceGadgetHostUsbIp.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * UsbTestServ - Remote USB test configuration and execution server, USB gadget host interface
4 * for USB/IP.
5 */
6
7/*
8 * Copyright (C) 2016-2023 Oracle and/or its affiliates.
9 *
10 * This file is part of VirtualBox base platform packages, as
11 * available from https://www.virtualbox.org.
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation, in version 3 of the
16 * License.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see <https://www.gnu.org/licenses>.
25 *
26 * The contents of this file may alternatively be used under the terms
27 * of the Common Development and Distribution License Version 1.0
28 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
29 * in the VirtualBox distribution, in which case the provisions of the
30 * CDDL are applicable instead of those of the GPL.
31 *
32 * You may elect to license modified versions of this file under the
33 * terms and conditions of either the GPL or the CDDL or both.
34 *
35 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
36 */
37
38
39/*********************************************************************************************************************************
40* Header Files *
41*********************************************************************************************************************************/
42#include <iprt/asm.h>
43#include <iprt/ctype.h>
44#include <iprt/err.h>
45#include <iprt/env.h>
46#include <iprt/mem.h>
47#include <iprt/process.h>
48#include <iprt/string.h>
49#include <iprt/thread.h>
50#include <iprt/time.h>
51
52#include "UsbTestServiceGadgetHostInternal.h"
53#include "UsbTestServicePlatform.h"
54
55
56/*********************************************************************************************************************************
57* Constants And Macros, Structures and Typedefs *
58*********************************************************************************************************************************/
59
60/**
61 * Internal UTS gadget host instance data.
62 */
63typedef struct UTSGADGETHOSTTYPEINT
64{
65 /** Handle to the USB/IP daemon process. */
66 RTPROCESS hProcUsbIp;
67} UTSGADGETHOSTTYPEINT;
68
69/** Default port of the USB/IP server. */
70#define UTS_GADGET_HOST_USBIP_PORT_DEF 3240
71
72
73/*********************************************************************************************************************************
74* Internal Functions *
75*********************************************************************************************************************************/
76
77
78/**
79 * Worker for binding/unbinding the given gadget from the USB/IP server.
80 *
81 * @returns IPRT status code.
82 * @param pThis The gadget host instance.
83 * @param hGadget The gadget handle.
84 * @param fBind Flag whether to do a bind or unbind.
85 */
86static int usbGadgetHostUsbIpBindUnbind(PUTSGADGETHOSTTYPEINT pThis, UTSGADGET hGadget, bool fBind)
87{
88 RT_NOREF1(pThis);
89 uint32_t uBusId, uDevId;
90 char aszBus[32];
91
92 uBusId = utsGadgetGetBusId(hGadget);
93 uDevId = utsGadgetGetDevId(hGadget);
94
95 /* Create the busid argument string. */
96 size_t cbRet = RTStrPrintf(&aszBus[0], RT_ELEMENTS(aszBus), "%u-%u", uBusId, uDevId);
97 if (cbRet == RT_ELEMENTS(aszBus))
98 return VERR_BUFFER_OVERFLOW;
99
100 /* Bind to the USB/IP server. */
101 RTPROCESS hProcUsbIp = NIL_RTPROCESS;
102 const char *apszArgv[5];
103
104 apszArgv[0] = "usbip";
105 apszArgv[1] = fBind ? "bind" : "unbind";
106 apszArgv[2] = "-b";
107 apszArgv[3] = &aszBus[0];
108 apszArgv[4] = NULL;
109
110 int rc = RTProcCreate("usbip", apszArgv, RTENV_DEFAULT, RTPROC_FLAGS_SEARCH_PATH, &hProcUsbIp);
111 if (RT_SUCCESS(rc))
112 {
113 RTPROCSTATUS ProcSts;
114 rc = RTProcWait(hProcUsbIp, RTPROCWAIT_FLAGS_BLOCK, &ProcSts);
115 if (RT_SUCCESS(rc))
116 {
117 /* Evaluate the process status. */
118 if ( ProcSts.enmReason != RTPROCEXITREASON_NORMAL
119 || ProcSts.iStatus != 0)
120 rc = VERR_UNRESOLVED_ERROR; /** @todo Log and give finer grained status code. */
121 }
122 }
123
124 return rc;
125}
126
127/**
128 * @interface_method_impl{UTSGADGETHOSTIF,pfnInit}
129 */
130static DECLCALLBACK(int) utsGadgetHostUsbIpInit(PUTSGADGETHOSTTYPEINT pIf, PCUTSGADGETCFGITEM paCfg)
131{
132 int rc = VINF_SUCCESS;
133 uint16_t uPort = 0;
134
135 pIf->hProcUsbIp = NIL_RTPROCESS;
136
137 rc = utsGadgetCfgQueryU16Def(paCfg, "UsbIp/Port", &uPort, UTS_GADGET_HOST_USBIP_PORT_DEF);
138 if (RT_SUCCESS(rc))
139 {
140 /* Make sure the kernel drivers are loaded. */
141 rc = utsPlatformModuleLoad("usbip-core", NULL, 0);
142 if (RT_SUCCESS(rc))
143 {
144 rc = utsPlatformModuleLoad("usbip-host", NULL, 0);
145 if (RT_SUCCESS(rc))
146 {
147 char aszPort[10];
148 char aszPidFile[64];
149 const char *apszArgv[6];
150
151 RTStrPrintf(aszPort, RT_ELEMENTS(aszPort), "%u", uPort);
152 RTStrPrintf(aszPidFile, RT_ELEMENTS(aszPidFile), "/var/run/usbipd-%u.pid", uPort);
153 /* Start the USB/IP server process. */
154 apszArgv[0] = "usbipd";
155 apszArgv[1] = "--tcp-port";
156 apszArgv[2] = aszPort;
157 apszArgv[3] = "--pid";
158 apszArgv[4] = aszPidFile;
159 apszArgv[5] = NULL;
160 rc = RTProcCreate("usbipd", apszArgv, RTENV_DEFAULT, RTPROC_FLAGS_SEARCH_PATH, &pIf->hProcUsbIp);
161 if (RT_SUCCESS(rc))
162 {
163 /* Wait for a bit to make sure the server started up successfully. */
164 uint64_t tsStart = RTTimeMilliTS();
165 do
166 {
167 RTPROCSTATUS ProcSts;
168 rc = RTProcWait(pIf->hProcUsbIp, RTPROCWAIT_FLAGS_NOBLOCK, &ProcSts);
169 if (rc != VERR_PROCESS_RUNNING)
170 {
171 rc = VERR_INVALID_HANDLE;
172 break;
173 }
174 RTThreadSleep(1);
175 rc = VINF_SUCCESS;
176 } while (RTTimeMilliTS() - tsStart < 2 * 1000); /* 2 seconds. */
177 }
178 }
179 }
180 }
181
182 return rc;
183}
184
185
186/**
187 * @interface_method_impl{UTSGADGETHOSTIF,pfnTerm}
188 */
189static DECLCALLBACK(void) utsGadgetHostUsbIpTerm(PUTSGADGETHOSTTYPEINT pIf)
190{
191 /* Kill the process and wait for it to terminate. */
192 RTProcTerminate(pIf->hProcUsbIp);
193
194 RTPROCSTATUS ProcSts;
195 RTProcWait(pIf->hProcUsbIp, RTPROCWAIT_FLAGS_BLOCK, &ProcSts);
196}
197
198
199/**
200 * @interface_method_impl{UTSGADGETHOSTIF,pfnGadgetAdd}
201 */
202static DECLCALLBACK(int) utsGadgetHostUsbIpGadgetAdd(PUTSGADGETHOSTTYPEINT pIf, UTSGADGET hGadget)
203{
204 /* Nothing to do so far. */
205 RT_NOREF2(pIf, hGadget);
206 return VINF_SUCCESS;
207}
208
209
210/**
211 * @interface_method_impl{UTSGADGETHOSTIF,pfnGadgetRemove}
212 */
213static DECLCALLBACK(int) utsGadgetHostUsbIpGadgetRemove(PUTSGADGETHOSTTYPEINT pIf, UTSGADGET hGadget)
214{
215 /* Nothing to do so far. */
216 RT_NOREF2(pIf, hGadget);
217 return VINF_SUCCESS;
218}
219
220
221/**
222 * @interface_method_impl{UTSGADGETHOSTIF,pfnGadgetConnect}
223 */
224static DECLCALLBACK(int) utsGadgetHostUsbIpGadgetConnect(PUTSGADGETHOSTTYPEINT pIf, UTSGADGET hGadget)
225{
226 return usbGadgetHostUsbIpBindUnbind(pIf, hGadget, true /* fBind */);
227}
228
229
230/**
231 * @interface_method_impl{UTSGADGETHOSTIF,pfnGadgetDisconnect}
232 */
233static DECLCALLBACK(int) utsGadgetHostUsbIpGadgetDisconnect(PUTSGADGETHOSTTYPEINT pIf, UTSGADGET hGadget)
234{
235 return usbGadgetHostUsbIpBindUnbind(pIf, hGadget, false /* fBind */);
236}
237
238
239
240/**
241 * The gadget host interface callback table.
242 */
243const UTSGADGETHOSTIF g_UtsGadgetHostIfUsbIp =
244{
245 /** enmType */
246 UTSGADGETHOSTTYPE_USBIP,
247 /** pszDesc */
248 "UTS USB/IP gadget host",
249 /** cbIf */
250 sizeof(UTSGADGETHOSTTYPEINT),
251 /** pfnInit */
252 utsGadgetHostUsbIpInit,
253 /** pfnTerm */
254 utsGadgetHostUsbIpTerm,
255 /** pfnGadgetAdd */
256 utsGadgetHostUsbIpGadgetAdd,
257 /** pfnGadgetRemove */
258 utsGadgetHostUsbIpGadgetRemove,
259 /** pfnGadgetConnect */
260 utsGadgetHostUsbIpGadgetConnect,
261 /** pfnGadgetDisconnect */
262 utsGadgetHostUsbIpGadgetDisconnect
263};
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