VirtualBox

source: vbox/trunk/src/VBox/Devices/USB/usbip/USBProxyDevice-usbip.cpp@ 60550

最後變更 在這個檔案從60550是 60550,由 vboxsync 提交於 9 年 前

Devices/USB/USBProxyDevice-usbip.cpp: Fixes

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 57.6 KB
 
1/* $Id: USBProxyDevice-usbip.cpp 60550 2016-04-18 17:35:51Z vboxsync $ */
2/** @file
3 * USB device proxy - USB/IP backend.
4 */
5
6/*
7 * Copyright (C) 2014-2015 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.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#define LOG_GROUP LOG_GROUP_DRV_USBPROXY
23
24#include <VBox/log.h>
25#include <VBox/err.h>
26#include <VBox/vmm/pdm.h>
27
28#include <iprt/asm.h>
29#include <iprt/assert.h>
30#include <iprt/alloc.h>
31#include <iprt/string.h>
32#include <iprt/socket.h>
33#include <iprt/poll.h>
34#include <iprt/tcp.h>
35#include <iprt/pipe.h>
36#include <iprt/list.h>
37#include <iprt/semaphore.h>
38
39#include "../USBProxyDevice.h"
40
41
42/*********************************************************************************************************************************
43* Constants And Macros, Structures and Typedefs *
44*********************************************************************************************************************************/
45
46/** The USB version number used for the protocol. */
47#define USBIP_VERSION UINT16_C(0x0111)
48/** Request indicator in the command code. */
49#define USBIP_INDICATOR_REQ RT_BIT(15)
50
51/** Command/Reply code for OP_REQ/RET_DEVLIST. */
52#define USBIP_REQ_RET_DEVLIST UINT16_C(5)
53/** Command/Reply code for OP_REQ/REP_IMPORT. */
54#define USBIP_REQ_RET_IMPORT UINT16_C(3)
55/** USB submit command identifier. */
56#define USBIP_CMD_SUBMIT UINT32_C(1)
57/** USB submit status identifier. */
58#define USBIP_RET_SUBMIT UINT32_C(3)
59/** URB unlink (cancel) command identifier. */
60#define USBIP_CMD_UNLINK UINT32_C(2)
61/** URB unlink (cancel) reply identifier. */
62#define USBIP_RET_UNLINK UINT32_C(4)
63
64/** Short read is not okay for the specified URB. */
65#define USBIP_XFER_FLAGS_SHORT_NOT_OK RT_BIT_32(0)
66/** Queue the isochronous URB as soon as possible. */
67#define USBIP_XFER_FLAGS_ISO_ASAP RT_BIT_32(1)
68/** Don't use DMA mappings for this URB. */
69#define USBIP_XFER_FLAGS_NO_TRANSFER_DMA_MAP RT_BIT_32(2)
70/** Explain - only applies to UHCI. */
71#define USBIP_XFER_FLAGS_FSBR RT_BIT_32(4)
72
73/** URB direction - input. */
74#define USBIP_DIR_IN UINT32_C(1)
75/** URB direction - output. */
76#define USBIP_DIR_OUT UINT32_C(0)
77
78/** @name USB/IP error codes.
79 * @{ */
80/** Success indicator. */
81#define USBIP_STATUS_SUCCESS INT32_C(0)
82/** Pipe stalled. */
83#define USBIP_STATUS_PIPE_STALLED INT32_C(-32)
84/** Short read. */
85#define USBIP_STATUS_SHORT_READ INT32_C(-121)
86/** @} */
87
88/**
89 * Exported device entry in the OP_RET_DEVLIST reply.
90 */
91#pragma pack(1)
92typedef struct UsbIpExportedDevice
93{
94 /** Path of the device, zero terminated string. */
95 char szPath[256];
96 /** Bus ID of the exported device, zero terminated string. */
97 char szBusId[32];
98 /** Bus number. */
99 uint32_t u32BusNum;
100 /** Device number. */
101 uint32_t u32DevNum;
102 /** Speed indicator of the device. */
103 uint32_t u32Speed;
104 /** Vendor ID of the device. */
105 uint16_t u16VendorId;
106 /** Product ID of the device. */
107 uint16_t u16ProductId;
108 /** Device release number. */
109 uint16_t u16BcdDevice;
110 /** Device class. */
111 uint8_t bDeviceClass;
112 /** Device Subclass. */
113 uint8_t bDeviceSubClass;
114 /** Device protocol. */
115 uint8_t bDeviceProtocol;
116 /** Configuration value. */
117 uint8_t bConfigurationValue;
118 /** Current configuration value of the device. */
119 uint8_t bNumConfigurations;
120 /** Number of interfaces for the device. */
121 uint8_t bNumInterfaces;
122} UsbIpExportedDevice;
123/** Pointer to a exported device entry. */
124typedef UsbIpExportedDevice *PUsbIpExportedDevice;
125#pragma pack()
126AssertCompileSize(UsbIpExportedDevice, 312);
127
128/**
129 * Interface descriptor entry for an exported device.
130 */
131#pragma pack(1)
132typedef struct UsbIpDeviceInterface
133{
134 /** Intefrace class. */
135 uint8_t bInterfaceClass;
136 /** Interface sub class. */
137 uint8_t bInterfaceSubClass;
138 /** Interface protocol identifier. */
139 uint8_t bInterfaceProtocol;
140 /** Padding byte for alignment. */
141 uint8_t bPadding;
142} UsbIpDeviceInterface;
143/** Pointer to an interface descriptor entry. */
144typedef UsbIpDeviceInterface *PUsbIpDeviceInterface;
145#pragma pack()
146
147/**
148 * USB/IP Import request.
149 */
150#pragma pack(1)
151typedef struct UsbIpReqImport
152{
153 /** Protocol version number. */
154 uint16_t u16Version;
155 /** Command code. */
156 uint16_t u16Cmd;
157 /** Status field, unused. */
158 int32_t u32Status;
159 /** Bus Id of the device as zero terminated string. */
160 char aszBusId[32];
161} UsbIpReqImport;
162/** Pointer to a import request. */
163typedef UsbIpReqImport *PUsbIpReqImport;
164#pragma pack()
165
166/**
167 * USB/IP Import reply.
168 *
169 * This is only the header, for successful
170 * imports the device details are sent to as
171 * defined in UsbIpExportedDevice.
172 */
173#pragma pack(1)
174typedef struct UsbIpRetImport
175{
176 /** Protocol version number. */
177 uint16_t u16Version;
178 /** Command code. */
179 uint16_t u16Cmd;
180 /** Status field, unused. */
181 int32_t u32Status;
182} UsbIpRetImport;
183/** Pointer to a import reply. */
184typedef UsbIpRetImport *PUsbIpRetImport;
185#pragma pack()
186
187/**
188 * Command/Reply header common to the submit and unlink commands
189 * replies.
190 */
191#pragma pack(1)
192typedef struct UsbIpReqRetHdr
193{
194 /** Request/Return code. */
195 uint32_t u32ReqRet;
196 /** Sequence number to identify the URB. */
197 uint32_t u32SeqNum;
198 /** Device id. */
199 uint32_t u32DevId;
200 /** Direction of the endpoint (host->device, device->host). */
201 uint32_t u32Direction;
202 /** Endpoint number. */
203 uint32_t u32Endpoint;
204} UsbIpReqRetHdr;
205/** Pointer to a request/reply header. */
206typedef UsbIpReqRetHdr *PUsbIpReqRetHdr;
207#pragma pack()
208
209/**
210 * USB/IP Submit request.
211 */
212#pragma pack(1)
213typedef struct UsbIpReqSubmit
214{
215 /** The request header. */
216 UsbIpReqRetHdr Hdr;
217 /** Transfer flags for the URB. */
218 uint32_t u32XferFlags;
219 /** Transfer buffer length. */
220 uint32_t u32TransferBufferLength;
221 /** Frame to transmit an ISO frame. */
222 uint32_t u32StartFrame;
223 /** Number of isochronous packets. */
224 uint32_t u32NumIsocPkts;
225 /** Maximum time for the request on the server side host controller. */
226 uint32_t u32Interval;
227 /** Setup data for a control URB. */
228 VUSBSETUP Setup;
229} UsbIpReqSubmit;
230/** Pointer to a submit request. */
231typedef UsbIpReqSubmit *PUsbIpReqSubmit;
232#pragma pack()
233AssertCompileSize(UsbIpReqSubmit, 48);
234
235/**
236 * USB/IP Submit reply.
237 */
238#pragma pack(1)
239typedef struct UsbIpRetSubmit
240{
241 /** The reply header. */
242 UsbIpReqRetHdr Hdr;
243 /** Status code. */
244 int32_t u32Status;
245 /** Actual length of the reply buffer. */
246 uint32_t u32ActualLength;
247 /** The actual selected frame for a isochronous transmit. */
248 uint32_t u32StartFrame;
249 /** Number of isochronous packets. */
250 uint32_t u32NumIsocPkts;
251 /** Number of failed isochronous packets. */
252 uint32_t u32ErrorCount;
253 /** Setup data for a control URB. */
254 VUSBSETUP Setup;
255} UsbIpRetSubmit;
256/** Pointer to a submit reply. */
257typedef UsbIpRetSubmit *PUsbIpRetSubmit;
258#pragma pack()
259AssertCompileSize(UsbIpRetSubmit, 48);
260
261/**
262 * Unlink URB request.
263 */
264#pragma pack(1)
265typedef struct UsbIpReqUnlink
266{
267 /** The request header. */
268 UsbIpReqRetHdr Hdr;
269 /** The sequence number to unlink. */
270 uint32_t u32SeqNum;
271 /** Padding - unused. */
272 uint8_t abPadding[24];
273} UsbIpReqUnlink;
274/** Pointer to a URB unlink request. */
275typedef UsbIpReqUnlink *PUsbIpReqUnlink;
276#pragma pack()
277AssertCompileSize(UsbIpReqUnlink, 48);
278
279/**
280 * Unlink URB reply.
281 */
282#pragma pack(1)
283typedef struct UsbIpRetUnlink
284{
285 /** The reply header. */
286 UsbIpReqRetHdr Hdr;
287 /** Status of the request. */
288 int32_t u32Status;
289 /** Padding - unused. */
290 uint8_t abPadding[24];
291} UsbIpRetUnlink;
292/** Pointer to a URB unlink request. */
293typedef UsbIpRetUnlink *PUsbIpRetUnlink;
294#pragma pack()
295AssertCompileSize(UsbIpRetUnlink, 48);
296
297/**
298 * Union of possible replies from the server during normal operation.
299 */
300#pragma pack(1)
301typedef union UsbIpRet
302{
303 /** The header. */
304 UsbIpReqRetHdr Hdr;
305 /** Submit reply. */
306 UsbIpRetSubmit RetSubmit;
307 /** Unlink reply. */
308 UsbIpRetUnlink RetUnlink;
309 /** Byte view. */
310 uint8_t abReply[1];
311} UsbIpRet;
312/** Pointer to a reply union. */
313typedef UsbIpRet *PUsbIpRet;
314#pragma pack()
315
316/**
317 * Isochronous packet descriptor.
318*/
319#pragma pack(1)
320typedef struct UsbIpIsocPktDesc
321{
322 /** Offset */
323 uint32_t u32Offset;
324 /** Length of the packet including padding. */
325 uint32_t u32Length;
326 /** Size of the transmitted data. */
327 uint32_t u32ActualLength;
328 /** Completion status for this packet. */
329 int32_t i32Status;
330} UsbIpIsocPktDesc;
331/** Pointer to a isochronous packet descriptor. */
332typedef UsbIpIsocPktDesc *PUsbIpIsocPktDesc;
333#pragma pack()
334
335/**
336 * USB/IP backend specific data for one URB.
337 * Required for tracking in flight and landed URBs.
338 */
339typedef struct USBPROXYURBUSBIP
340{
341 /** List node for the in flight or landed URB list. */
342 RTLISTNODE NodeList;
343 /** Sequence number the assigned URB is identified by. */
344 uint32_t u32SeqNumUrb;
345 /** Sequence number of the unlink command if the URB was cancelled. */
346 uint32_t u32SeqNumUrbUnlink;
347 /** Flag whether the URB was cancelled. */
348 bool fCancelled;
349 /** Pointer to the VUSB URB. */
350 PVUSBURB pVUsbUrb;
351} USBPROXYURBUSBIP;
352/** Pointer to a USB/IP URB. */
353typedef USBPROXYURBUSBIP *PUSBPROXYURBUSBIP;
354
355/**
356 * USB/IP data receive states.
357 */
358typedef enum USBPROXYUSBIPRECVSTATE
359{
360 /** Invalid receive state. */
361 USBPROXYUSBIPRECVSTATE_INVALID = 0,
362 /** Currently receiving the common header structure. */
363 USBPROXYUSBIPRECVSTATE_HDR_COMMON,
364 /** Currently receieving the rest of the header structure. */
365 USBPROXYUSBIPRECVSTATE_HDR_RESIDUAL,
366 /** Currently receiving data into the URB buffer. */
367 USBPROXYUSBIPRECVSTATE_URB_BUFFER,
368 /** Currently receiving the isochronous packet descriptors. */
369 USBPROXYUSBIPRECVSTATE_ISOC_PKT_DESCS,
370 /** Usual 32bit hack. */
371 USBPROXYUSBIPRECVSTATE_32BIT_HACK = 0x7fffffff
372} USBPROXYUSBIPRECVSTATE;
373/** Pointer to an receive state. */
374typedef USBPROXYUSBIPRECVSTATE *PUSBPROXYUSBIPRECVSTATE;
375
376/**
377 * Backend data for the USB/IP USB Proxy device backend.
378 */
379typedef struct USBPROXYDEVUSBIP
380{
381 /** IPRT socket handle. */
382 RTSOCKET hSocket;
383 /** Pollset with the wakeup pipe and socket. */
384 RTPOLLSET hPollSet;
385 /** Pipe endpoint - read (in the pollset). */
386 RTPIPE hPipeR;
387 /** Pipe endpoint - write. */
388 RTPIPE hPipeW;
389 /** Next sequence number to use for identifying submitted URBs. */
390 volatile uint32_t u32SeqNumNext;
391 /** Fast mutex protecting the lists below against concurrent access. */
392 RTSEMFASTMUTEX hMtxLists;
393 /** List of in flight URBs. */
394 RTLISTANCHOR ListUrbsInFlight;
395 /** List of landed URBs. */
396 RTLISTANCHOR ListUrbsLanded;
397 /** List of URBs to submit. */
398 RTLISTANCHOR ListUrbsToQueue;
399 /** Port of the USB/IP host to connect to. */
400 uint32_t uPort;
401 /** USB/IP host address. */
402 char *pszHost;
403 /** USB Bus ID of the device to capture. */
404 char *pszBusId;
405 /** The device ID to use to identify the device. */
406 uint32_t u32DevId;
407 /** Temporary buffer for the next reply header */
408 UsbIpRet BufRet;
409 /** Temporary buffer to hold all isochronous packet descriptors. */
410 UsbIpIsocPktDesc aIsocPktDesc[8];
411 /** Pointer to the current buffer to write received data to. */
412 uint8_t *pbRecv;
413 /** Number of bytes received so far. */
414 size_t cbRecv;
415 /** Number of bytes left to receive. until we advance the state machine and process the data */
416 size_t cbLeft;
417 /** The current receiving state. */
418 USBPROXYUSBIPRECVSTATE enmRecvState;
419 /** The URB we currently receive a response for. */
420 PUSBPROXYURBUSBIP pUrbUsbIp;
421} USBPROXYDEVUSBIP, *PUSBPROXYDEVUSBIP;
422
423/** Pollset id of the socket. */
424#define USBIP_POLL_ID_SOCKET 0
425/** Pollset id of the pipe. */
426#define USBIP_POLL_ID_PIPE 1
427
428/** USB/IP address prefix for identifcation. */
429#define USBIP_URI_PREFIX "usbip://"
430/** USB/IP address prefix length. */
431#define USBIP_URI_PREFIX_LEN (sizeof(USBIP_URI_PREFIX) - 1)
432
433/** Waking reason for the USB I/P reaper: New URBs to queue. */
434#define USBIP_REAPER_WAKEUP_REASON_QUEUE 'Q'
435/** Waking reason for the USB I/P reaper: External wakeup. */
436#define USBIP_REAPER_WAKEUP_REASON_EXTERNAL 'E'
437
438/**
439 * Converts a request/reply header from network to host endianness.
440 *
441 * @returns nothing.
442 * @param pHdr The header to convert.
443 */
444DECLINLINE(void) usbProxyUsbIpReqRetHdrN2H(PUsbIpReqRetHdr pHdr)
445{
446 pHdr->u32ReqRet = RT_H2N_U32(pHdr->u32ReqRet);
447 pHdr->u32SeqNum = RT_H2N_U32(pHdr->u32SeqNum);
448 pHdr->u32DevId = RT_H2N_U32(pHdr->u32DevId);
449 pHdr->u32Direction = RT_H2N_U32(pHdr->u32Direction);
450 pHdr->u32Endpoint = RT_H2N_U32(pHdr->u32Endpoint);
451}
452
453/**
454 * Converts a request/reply header from host to network endianness.
455 *
456 * @returns nothing.
457 * @param pHdr The header to convert.
458 */
459DECLINLINE(void) usbProxyUsbIpReqRetHdrH2N(PUsbIpReqRetHdr pHdr)
460{
461 pHdr->u32ReqRet = RT_N2H_U32(pHdr->u32ReqRet);
462 pHdr->u32SeqNum = RT_N2H_U32(pHdr->u32SeqNum);
463 pHdr->u32DevId = RT_N2H_U32(pHdr->u32DevId);
464 pHdr->u32Direction = RT_N2H_U32(pHdr->u32Direction);
465 pHdr->u32Endpoint = RT_N2H_U32(pHdr->u32Endpoint);
466}
467
468/**
469 * Converts a submit request from host to network endianness.
470 *
471 * @returns nothing.
472 * @param pReqSubmit The submit request to convert.
473 */
474DECLINLINE(void) usbProxyUsbIpReqSubmitH2N(PUsbIpReqSubmit pReqSubmit)
475{
476 usbProxyUsbIpReqRetHdrH2N(&pReqSubmit->Hdr);
477 pReqSubmit->u32XferFlags = RT_H2N_U32(pReqSubmit->u32XferFlags);
478 pReqSubmit->u32TransferBufferLength = RT_H2N_U32(pReqSubmit->u32TransferBufferLength);
479 pReqSubmit->u32StartFrame = RT_H2N_U32(pReqSubmit->u32StartFrame);
480 pReqSubmit->u32NumIsocPkts = RT_H2N_U32(pReqSubmit->u32NumIsocPkts);
481 pReqSubmit->u32Interval = RT_H2N_U32(pReqSubmit->u32Interval);
482}
483
484/**
485 * Converts a submit reply from network to host endianness.
486 *
487 * @returns nothing.
488 * @param pReqSubmit The submit reply to convert.
489 */
490DECLINLINE(void) usbProxyUsbIpRetSubmitN2H(PUsbIpRetSubmit pRetSubmit)
491{
492 usbProxyUsbIpReqRetHdrN2H(&pRetSubmit->Hdr);
493 pRetSubmit->u32Status = RT_N2H_U32(pRetSubmit->u32Status);
494 pRetSubmit->u32ActualLength = RT_N2H_U32(pRetSubmit->u32ActualLength);
495 pRetSubmit->u32StartFrame = RT_N2H_U32(pRetSubmit->u32StartFrame);
496 pRetSubmit->u32NumIsocPkts = RT_N2H_U32(pRetSubmit->u32NumIsocPkts);
497 pRetSubmit->u32ErrorCount = RT_N2H_U32(pRetSubmit->u32ErrorCount);
498}
499
500/**
501 * Converts a isochronous packet descriptor from host to network endianness.
502 *
503 * @returns nothing.
504 * @param pIsocPktDesc The packet descriptor to convert.
505 */
506DECLINLINE(void) usbProxyUsbIpIsocPktDescH2N(PUsbIpIsocPktDesc pIsocPktDesc)
507{
508 pIsocPktDesc->u32Offset = RT_H2N_U32(pIsocPktDesc->u32Offset);
509 pIsocPktDesc->u32Length = RT_H2N_U32(pIsocPktDesc->u32Length);
510 pIsocPktDesc->u32ActualLength = RT_H2N_U32(pIsocPktDesc->u32ActualLength);
511 pIsocPktDesc->i32Status = RT_H2N_U32(pIsocPktDesc->i32Status);
512}
513
514/**
515 * Converts a isochronous packet descriptor from network to host endianness.
516 *
517 * @returns nothing.
518 * @param pIsocPktDesc The packet descriptor to convert.
519 */
520DECLINLINE(void) usbProxyUsbIpIsocPktDescN2H(PUsbIpIsocPktDesc pIsocPktDesc)
521{
522 pIsocPktDesc->u32Offset = RT_N2H_U32(pIsocPktDesc->u32Offset);
523 pIsocPktDesc->u32Length = RT_N2H_U32(pIsocPktDesc->u32Length);
524 pIsocPktDesc->u32ActualLength = RT_N2H_U32(pIsocPktDesc->u32ActualLength);
525 pIsocPktDesc->i32Status = RT_N2H_U32(pIsocPktDesc->i32Status);
526}
527
528/**
529 * Converts a unlink request from host to network endianness.
530 *
531 * @returns nothing.
532 * @param pReqUnlink The unlink request to convert.
533 */
534DECLINLINE(void) usbProxyUsbIpReqUnlinkH2N(PUsbIpReqUnlink pReqUnlink)
535{
536 usbProxyUsbIpReqRetHdrH2N(&pReqUnlink->Hdr);
537 pReqUnlink->u32SeqNum = RT_H2N_U32(pReqUnlink->u32SeqNum);
538}
539
540/**
541 * Converts a unlink reply from network to host endianness.
542 *
543 * @returns nothing.
544 * @param pRetUnlink The unlink reply to convert.
545 */
546DECLINLINE(void) usbProxyUsbIpRetUnlinkN2H(PUsbIpRetUnlink pRetUnlink)
547{
548 usbProxyUsbIpReqRetHdrN2H(&pRetUnlink->Hdr);
549 pRetUnlink->u32Status = RT_N2H_U32(pRetUnlink->u32Status);
550}
551
552/**
553 * Convert the given exported device structure from host to network byte order.
554 *
555 * @returns nothing.
556 * @param pDevice The device structure to convert.
557 */
558DECLINLINE(void) usbProxyUsbIpExportedDeviceN2H(PUsbIpExportedDevice pDevice)
559{
560 pDevice->u32BusNum = RT_N2H_U32(pDevice->u32BusNum);
561 pDevice->u32DevNum = RT_N2H_U32(pDevice->u32DevNum);
562 pDevice->u32Speed = RT_N2H_U16(pDevice->u32Speed);
563 pDevice->u16VendorId = RT_N2H_U16(pDevice->u16VendorId);
564 pDevice->u16ProductId = RT_N2H_U16(pDevice->u16ProductId);
565 pDevice->u16BcdDevice = RT_N2H_U16(pDevice->u16BcdDevice);
566}
567
568/**
569 * Converts a USB/IP status code to a VBox status code.
570 *
571 * @returns VUSB status code.
572 * @param i32Status The USB/IP status code from the reply.
573 */
574DECLINLINE(int) usbProxyUsbIpStatusConvertFromStatus(int32_t i32Status)
575{
576 if (RT_LIKELY( i32Status == USBIP_STATUS_SUCCESS
577 || i32Status == USBIP_STATUS_SHORT_READ))
578 return VINF_SUCCESS;
579
580 switch (i32Status)
581 {
582 case USBIP_STATUS_PIPE_STALLED:
583 return VINF_SUCCESS;
584 default:
585 return VERR_INVALID_STATE;
586 }
587
588 return VERR_INVALID_STATE;
589}
590
591/**
592 * Converts a USB/IP status code to a VUSB status code.
593 *
594 * @returns VUSB status code.
595 * @param i32Status The USB/IP status code from the reply.
596 */
597DECLINLINE(VUSBSTATUS) usbProxyUsbIpVUsbStatusConvertFromStatus(int32_t i32Status)
598{
599 if (RT_LIKELY( i32Status == USBIP_STATUS_SUCCESS
600 || i32Status == USBIP_STATUS_SHORT_READ))
601 return VUSBSTATUS_OK;
602
603 switch (i32Status)
604 {
605 case USBIP_STATUS_PIPE_STALLED:
606 return VUSBSTATUS_STALL;
607 default:
608 return VUSBSTATUS_DNR;
609 }
610
611 return VUSBSTATUS_DNR;
612}
613
614/**
615 * Gets the next free sequence number.
616 *
617 * @returns Next free sequence number.
618 * @param pProxyDevUsbIp The USB/IP proxy device data.
619 */
620DECLINLINE(uint32_t) usbProxyUsbIpSeqNumGet(PUSBPROXYDEVUSBIP pProxyDevUsbIp)
621{
622 return ASMAtomicIncU32(&pProxyDevUsbIp->u32SeqNumNext);
623}
624
625/**
626 * Links a given URB into the given list.
627 *
628 * @returns nothing.
629 * @param pProxyDevUsbIp The USB/IP proxy device data.
630 * @param pList The list to link the URB into.
631 * @param pUrbUsbIp The URB to link.
632 */
633DECLINLINE(void) usbProxyUsbIpLinkUrb(PUSBPROXYDEVUSBIP pProxyDevUsbIp, PRTLISTANCHOR pList, PUSBPROXYURBUSBIP pUrbUsbIp)
634{
635 int rc = RTSemFastMutexRequest(pProxyDevUsbIp->hMtxLists);
636 AssertRC(rc);
637 RTListAppend(pList, &pUrbUsbIp->NodeList);
638 RTSemFastMutexRelease(pProxyDevUsbIp->hMtxLists);
639}
640
641/**
642 * Unlinks a given URB from the current assigned list.
643 *
644 * @returns nothing.
645 * @param pProxyDevUsbIp The USB/IP proxy device data.
646 * @param pUrbUsbIp The URB to unlink.
647 */
648DECLINLINE(void) usbProxyUsbIpUnlinkUrb(PUSBPROXYDEVUSBIP pProxyDevUsbIp, PUSBPROXYURBUSBIP pUrbUsbIp)
649{
650 int rc = RTSemFastMutexRequest(pProxyDevUsbIp->hMtxLists);
651 AssertRC(rc);
652 RTListNodeRemove(&pUrbUsbIp->NodeList);
653 RTSemFastMutexRelease(pProxyDevUsbIp->hMtxLists);
654}
655
656/**
657 * Allocates a USB/IP proxy specific URB state.
658 *
659 * @returns Pointer to the USB/IP specific URB data or NULL on failure.
660 * @param pProxyDevUsbIp The USB/IP proxy device data.
661 */
662static PUSBPROXYURBUSBIP usbProxyUsbIpUrbAlloc(PUSBPROXYDEVUSBIP pProxyDevUsbIp)
663{
664 NOREF(pProxyDevUsbIp);
665 return (PUSBPROXYURBUSBIP)RTMemAllocZ(sizeof(USBPROXYURBUSBIP));
666}
667
668/**
669 * Frees the given USB/IP URB state.
670 *
671 * @returns nothing.
672 * @param pProxyDevUsbIp The USB/IP proxy device data.
673 * @param pUrbUsbIp The USB/IP speciic URB data.
674 */
675static void usbProxyUsbIpUrbFree(PUSBPROXYDEVUSBIP pProxyDevUsbIp, PUSBPROXYURBUSBIP pUrbUsbIp)
676{
677 NOREF(pProxyDevUsbIp);
678 RTMemFree(pUrbUsbIp);
679}
680
681/**
682 * Parse the string representation of the host address.
683 *
684 * @returns VBox status code.
685 * @param pProxyDevUsbIp The USB/IP proxy device data to parse the address for.
686 * @param pszAddress The address string to parse.
687 */
688static int usbProxyUsbIpParseAddress(PUSBPROXYDEVUSBIP pProxyDevUsbIp, const char *pszAddress)
689{
690 int rc = VINF_SUCCESS;
691
692 if (!RTStrNCmp(pszAddress, USBIP_URI_PREFIX, USBIP_URI_PREFIX_LEN))
693 {
694 pszAddress += USBIP_URI_PREFIX_LEN;
695
696 const char *pszPortStart = RTStrStr(pszAddress, ":");
697 if (pszPortStart)
698 {
699 pszPortStart++;
700
701 const char *pszBusIdStart = RTStrStr(pszPortStart, ":");
702 if (pszBusIdStart)
703 {
704 size_t cbHost = pszPortStart - pszAddress - 1;
705 size_t cbBusId = strlen(pszBusIdStart);
706
707 pszBusIdStart++;
708
709 rc = RTStrToUInt32Ex(pszPortStart, NULL, 10 /* uBase */, &pProxyDevUsbIp->uPort);
710 if ( rc == VINF_SUCCESS
711 || rc == VWRN_TRAILING_CHARS)
712 {
713 rc = RTStrAllocEx(&pProxyDevUsbIp->pszHost, cbHost + 1);
714 if (RT_SUCCESS(rc))
715 rc = RTStrAllocEx(&pProxyDevUsbIp->pszBusId, cbBusId + 1);
716 if (RT_SUCCESS(rc))
717 {
718 rc = RTStrCopyEx(pProxyDevUsbIp->pszHost, cbHost + 1, pszAddress, cbHost);
719 AssertRC(rc);
720
721 rc = RTStrCopyEx(pProxyDevUsbIp->pszBusId, cbBusId + 1, pszBusIdStart, cbBusId);
722 AssertRC(rc);
723
724 return VINF_SUCCESS;
725 }
726 }
727 else
728 rc = VERR_INVALID_PARAMETER;
729 }
730 else
731 rc = VERR_INVALID_PARAMETER;
732 }
733 else
734 rc = VERR_INVALID_PARAMETER;
735 }
736 else
737 rc = VERR_INVALID_PARAMETER;
738
739 return rc;
740}
741
742/**
743 * Connects to the USB/IP host and claims the device given in the proxy device data.
744 *
745 * @returns VBox status code.
746 * @param pProxyDevUsbIp The USB/IP proxy device data.
747 */
748static int usbProxyUsbIpConnect(PUSBPROXYDEVUSBIP pProxyDevUsbIp)
749{
750 int rc = VINF_SUCCESS;
751 rc = RTTcpClientConnect(pProxyDevUsbIp->pszHost, pProxyDevUsbIp->uPort, &pProxyDevUsbIp->hSocket);
752 if (RT_SUCCESS(rc))
753 {
754 /* Disable send coalescing. */
755 rc = RTTcpSetSendCoalescing(pProxyDevUsbIp->hSocket, false);
756 if (RT_FAILURE(rc))
757 LogRel(("UsbIp: Disabling send coalescing failed (rc=%Rrc), continuing nevertheless but expect reduced performance\n", rc));
758
759 /* Import the device, i.e. claim it for our use. */
760 UsbIpReqImport ReqImport;
761 ReqImport.u16Version = RT_H2N_U16(USBIP_VERSION);
762 ReqImport.u16Cmd = RT_H2N_U16(USBIP_INDICATOR_REQ | USBIP_REQ_RET_IMPORT);
763 ReqImport.u32Status = RT_H2N_U32(USBIP_STATUS_SUCCESS);
764 rc = RTStrCopy(&ReqImport.aszBusId[0], sizeof(ReqImport.aszBusId), pProxyDevUsbIp->pszBusId);
765 if (rc == VINF_SUCCESS)
766 {
767 rc = RTTcpWrite(pProxyDevUsbIp->hSocket, &ReqImport, sizeof(ReqImport));
768 if (RT_SUCCESS(rc))
769 {
770 /* Read the reply. */
771 UsbIpRetImport RetImport;
772 rc = RTTcpRead(pProxyDevUsbIp->hSocket, &RetImport, sizeof(RetImport), NULL);
773 if (RT_SUCCESS(rc))
774 {
775 RetImport.u16Version = RT_N2H_U16(RetImport.u16Version);
776 RetImport.u16Cmd = RT_N2H_U16(RetImport.u16Cmd);
777 RetImport.u32Status = RT_N2H_U32(RetImport.u32Status);
778 if ( RetImport.u16Version == USBIP_VERSION
779 && RetImport.u16Cmd == USBIP_REQ_RET_IMPORT
780 && RetImport.u32Status == USBIP_STATUS_SUCCESS)
781 {
782 /* Read the device data. */
783 UsbIpExportedDevice Device;
784 rc = RTTcpRead(pProxyDevUsbIp->hSocket, &Device, sizeof(Device), NULL);
785 if (RT_SUCCESS(rc))
786 {
787 usbProxyUsbIpExportedDeviceN2H(&Device);
788 pProxyDevUsbIp->u32DevId = (Device.u32BusNum << 16) | Device.u32DevNum;
789
790 rc = RTPollSetAddSocket(pProxyDevUsbIp->hPollSet, pProxyDevUsbIp->hSocket,
791 RTPOLL_EVT_READ | RTPOLL_EVT_ERROR, USBIP_POLL_ID_SOCKET);
792 }
793 }
794 else
795 {
796 /* Check what went wrong and leave a meaningful error message in the log. */
797 if (RetImport.u16Version != USBIP_VERSION)
798 LogRel(("UsbIp: Unexpected protocol version received from host (%#x vs. %#x)\n",
799 RetImport.u16Version, USBIP_VERSION));
800 else if (RetImport.u16Cmd != USBIP_REQ_RET_IMPORT)
801 LogRel(("UsbIp: Unexpected reply code received from host (%#x vs. %#x)\n",
802 RetImport.u16Cmd, USBIP_REQ_RET_IMPORT));
803 else if (RetImport.u32Status != 0)
804 LogRel(("UsbIp: Claiming the device has failed on the host with an unspecified error\n"));
805 else
806 AssertMsgFailed(("Something went wrong with if condition\n"));
807 }
808 }
809 }
810 }
811 else
812 {
813 LogRel(("UsbIp: Given bus ID is exceeds permitted protocol length: %u vs %u\n",
814 strlen(pProxyDevUsbIp->pszBusId) + 1, sizeof(ReqImport.aszBusId)));
815 rc = VERR_INVALID_PARAMETER;
816 }
817
818 if (RT_FAILURE(rc))
819 RTTcpClientCloseEx(pProxyDevUsbIp->hSocket, false /*fGracefulShutdown*/);
820 }
821 if (RT_FAILURE(rc))
822 LogRel(("UsbIp: Connecting to the host %s failed with %Rrc\n", pProxyDevUsbIp->pszHost, rc));
823 return rc;
824}
825
826/**
827 * Disconnects from the USB/IP host releasing the device given in the proxy device data.
828 *
829 * @returns VBox status code.
830 * @param pProxyDevUsbIp The USB/IP proxy device data.
831 */
832static int usbProxyUsbIpDisconnect(PUSBPROXYDEVUSBIP pProxyDevUsbIp)
833{
834 int rc = VINF_SUCCESS;
835
836 rc = RTTcpClientCloseEx(pProxyDevUsbIp->hSocket, false /*fGracefulShutdown*/);
837 if (RT_SUCCESS(rc))
838 pProxyDevUsbIp->hSocket = NIL_RTSOCKET;
839 return rc;
840}
841
842/**
843 * Synchronously exchange a given control message with the remote device.
844 *
845 * @eturns VBox status code.
846 * @param pProxyDevUsbIp The USB/IP proxy device data.
847 * @param pSetup The setup message.
848 *
849 * @note This method is only used to implement the *SetConfig, *SetInterface and *ClearHaltedEp
850 * callbacks because the USB/IP protocol lacks dedicated requests for these.
851 * @remark It is assumed that this method is never called while usbProxyUsbIpUrbReap is called
852 * on another thread.
853 */
854static int usbProxyUsbIpCtrlUrbExchangeSync(PUSBPROXYDEVUSBIP pProxyDevUsbIp, PVUSBSETUP pSetup)
855{
856 int rc = VINF_SUCCESS;
857
858 UsbIpReqSubmit ReqSubmit;
859
860 RT_ZERO(ReqSubmit);
861
862 uint32_t u32SeqNum = usbProxyUsbIpSeqNumGet(pProxyDevUsbIp);
863 ReqSubmit.Hdr.u32ReqRet = USBIP_CMD_SUBMIT;
864 ReqSubmit.Hdr.u32SeqNum = u32SeqNum;
865 ReqSubmit.Hdr.u32DevId = pProxyDevUsbIp->u32DevId;
866 ReqSubmit.Hdr.u32Direction = USBIP_DIR_OUT;
867 ReqSubmit.Hdr.u32Endpoint = 0; /* Only default control endpoint is allowed for these kind of messages. */
868 ReqSubmit.u32XferFlags = 0;
869 ReqSubmit.u32TransferBufferLength = 0;
870 ReqSubmit.u32StartFrame = 0;
871 ReqSubmit.u32NumIsocPkts = 0;
872 ReqSubmit.u32Interval = 0;
873 memcpy(&ReqSubmit.Setup, pSetup, sizeof(ReqSubmit.Setup));
874 usbProxyUsbIpReqSubmitH2N(&ReqSubmit);
875
876 /* Send the command. */
877 rc = RTTcpWrite(pProxyDevUsbIp->hSocket, &ReqSubmit, sizeof(ReqSubmit));
878 if (RT_SUCCESS(rc))
879 {
880 /* Wait for the response. */
881 /** @todo: Don't wait indefinitely long. */
882 UsbIpRetSubmit RetSubmit;
883 rc = RTTcpRead(pProxyDevUsbIp->hSocket, &RetSubmit, sizeof(RetSubmit), NULL);
884 if (RT_SUCCESS(rc))
885 {
886 usbProxyUsbIpRetSubmitN2H(&RetSubmit);
887 rc = usbProxyUsbIpStatusConvertFromStatus(RetSubmit.u32Status);
888 }
889 }
890 return rc;
891}
892
893/**
894 * Returns the URB matching the given sequence number from the in flight list.
895 *
896 * @returns pointer to the URB matching the given sequence number or NULL
897 * @param pProxyDevUsbIp The USB/IP proxy device data.
898 * @param u32SeqNum The sequence number to search for.
899 */
900static PUSBPROXYURBUSBIP usbProxyUsbIpGetInFlightUrbFromSeqNum(PUSBPROXYDEVUSBIP pProxyDevUsbIp, uint32_t u32SeqNum)
901{
902 bool fFound = false;
903 PUSBPROXYURBUSBIP pIt;
904
905 RTListForEach(&pProxyDevUsbIp->ListUrbsInFlight, pIt, USBPROXYURBUSBIP, NodeList)
906 {
907 if (pIt->u32SeqNumUrb == u32SeqNum)
908 {
909 fFound = true;
910 break;
911 }
912 }
913
914 return fFound ? pIt : NULL;
915}
916
917/**
918 * Returns the URB matching the given sequence number from the cancel list.
919 *
920 * @returns pointer to the URB matching the given sequence number or NULL
921 * @param pProxyDevUsbIp The USB/IP proxy device data.
922 * @param u32SeqNum The sequence number to search for.
923 */
924static PUSBPROXYURBUSBIP usbProxyUsbIpGetCancelledUrbFromSeqNum(PUSBPROXYDEVUSBIP pProxyDevUsbIp, uint32_t u32SeqNum)
925{
926 bool fFound = false;
927 PUSBPROXYURBUSBIP pIt;
928
929 RTListForEach(&pProxyDevUsbIp->ListUrbsInFlight, pIt, USBPROXYURBUSBIP, NodeList)
930 {
931 if ( pIt->u32SeqNumUrbUnlink == u32SeqNum
932 && pIt->fCancelled == true)
933 {
934 fFound = true;
935 break;
936 }
937 }
938
939 return fFound ? pIt : NULL;
940}
941
942/**
943 * Resets the receive state for a new reply.
944 *
945 * @returns nothing.
946 * @param pProxyDevUsbIp The USB/IP proxy device data.
947 */
948static void usbProxyUsbIpResetRecvState(PUSBPROXYDEVUSBIP pProxyDevUsbIp)
949{
950 pProxyDevUsbIp->enmRecvState = USBPROXYUSBIPRECVSTATE_HDR_COMMON;
951 pProxyDevUsbIp->pbRecv = (uint8_t *)&pProxyDevUsbIp->BufRet;
952 pProxyDevUsbIp->cbRecv = 0;
953 pProxyDevUsbIp->cbLeft = sizeof(UsbIpReqRetHdr);
954}
955
956static void usbProxyUsbIpRecvStateAdvance(PUSBPROXYDEVUSBIP pProxyDevUsbIp, USBPROXYUSBIPRECVSTATE enmState,
957 uint8_t *pbData, size_t cbData)
958{
959 pProxyDevUsbIp->enmRecvState = enmState;
960 pProxyDevUsbIp->cbRecv = 0;
961 pProxyDevUsbIp->cbLeft = cbData;
962 pProxyDevUsbIp->pbRecv = pbData;
963}
964
965/**
966 * Handles reception of a USB/IP PDU.
967 *
968 * @returns VBox status code.
969 * @param pProxyDevUsbIp The USB/IP proxy device data.
970 * @param ppUrbUsbIp Where to store the pointer to the USB/IP URB which completed.
971 * Will be NULL if the received PDU is not complete and we have
972 * have to wait for more data or on failure.
973 */
974static int usbProxyUsbIpRecvPdu(PUSBPROXYDEVUSBIP pProxyDevUsbIp, PUSBPROXYURBUSBIP *ppUrbUsbIp)
975{
976 int rc = VINF_SUCCESS;
977 size_t cbRead = 0;
978 PUSBPROXYURBUSBIP pUrbUsbIp = NULL;
979
980 Assert(pProxyDevUsbIp->cbLeft);
981
982 /* Read any available data first. */
983 rc = RTTcpReadNB(pProxyDevUsbIp->hSocket, pProxyDevUsbIp->pbRecv, pProxyDevUsbIp->cbLeft, &cbRead);
984 if (RT_SUCCESS(rc))
985 {
986 pProxyDevUsbIp->cbRecv += cbRead;
987 pProxyDevUsbIp->cbLeft -= cbRead;
988 pProxyDevUsbIp->pbRecv += cbRead;
989
990 /* Process the received data if there is nothing to receive left for the current state. */
991 if (!pProxyDevUsbIp->cbLeft)
992 {
993 switch (pProxyDevUsbIp->enmRecvState)
994 {
995 case USBPROXYUSBIPRECVSTATE_HDR_COMMON:
996 {
997 Assert(pProxyDevUsbIp->cbRecv == sizeof(UsbIpReqRetHdr));
998
999 /*
1000 * Determine the residual amount of data to receive until
1001 * the complete reply header was received.
1002 */
1003 switch (RT_N2H_U32(pProxyDevUsbIp->BufRet.Hdr.u32ReqRet))
1004 {
1005 case USBIP_RET_SUBMIT:
1006 pProxyDevUsbIp->cbLeft = sizeof(UsbIpRetSubmit) - sizeof(UsbIpReqRetHdr);
1007 pProxyDevUsbIp->enmRecvState = USBPROXYUSBIPRECVSTATE_HDR_RESIDUAL;
1008 break;
1009 case USBIP_RET_UNLINK:
1010 pProxyDevUsbIp->cbLeft = sizeof(UsbIpRetUnlink) - sizeof(UsbIpReqRetHdr);
1011 pProxyDevUsbIp->enmRecvState = USBPROXYUSBIPRECVSTATE_HDR_RESIDUAL;
1012 break;
1013 default:
1014 AssertLogRelMsgFailed(("Invalid reply header received: %d\n",
1015 pProxyDevUsbIp->BufRet.Hdr.u32ReqRet));
1016 usbProxyUsbIpResetRecvState(pProxyDevUsbIp);
1017 }
1018
1019 break;
1020 }
1021 case USBPROXYUSBIPRECVSTATE_HDR_RESIDUAL:
1022 {
1023 /** @todo: Verify that the directions match, verify that the length doesn't exceed the buffer. */
1024
1025 switch (RT_N2H_U32(pProxyDevUsbIp->BufRet.Hdr.u32ReqRet))
1026 {
1027 case USBIP_RET_SUBMIT:
1028 /* Get the URB from the in flight list. */
1029 pProxyDevUsbIp->pUrbUsbIp = usbProxyUsbIpGetInFlightUrbFromSeqNum(pProxyDevUsbIp, RT_N2H_U32(pProxyDevUsbIp->BufRet.Hdr.u32SeqNum));
1030 if (pProxyDevUsbIp->pUrbUsbIp)
1031 {
1032 usbProxyUsbIpRetSubmitN2H(&pProxyDevUsbIp->BufRet.RetSubmit);
1033
1034 pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->enmStatus = usbProxyUsbIpVUsbStatusConvertFromStatus(pProxyDevUsbIp->BufRet.RetSubmit.u32Status);
1035 if ( pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->enmDir == VUSBDIRECTION_IN
1036 && pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->enmStatus == VUSBSTATUS_OK)
1037 {
1038 uint8_t *pbData = NULL;
1039
1040 if (pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->enmType == VUSBXFERTYPE_MSG)
1041 {
1042 /* Preserve the setup request. */
1043 pbData = &pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->abData[sizeof(VUSBSETUP)];
1044 pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->cbData = pProxyDevUsbIp->BufRet.RetSubmit.u32ActualLength + sizeof(VUSBSETUP);
1045 }
1046 else
1047 {
1048 pbData = &pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->abData[0];
1049 pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->cbData = pProxyDevUsbIp->BufRet.RetSubmit.u32ActualLength;
1050 }
1051
1052 usbProxyUsbIpRecvStateAdvance(pProxyDevUsbIp, USBPROXYUSBIPRECVSTATE_URB_BUFFER,
1053 pbData, pProxyDevUsbIp->BufRet.RetSubmit.u32ActualLength);
1054 }
1055 else
1056 {
1057 Assert( pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->enmDir == VUSBDIRECTION_OUT
1058 || pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->enmStatus != VUSBSTATUS_OK);
1059 pUrbUsbIp = pProxyDevUsbIp->pUrbUsbIp;
1060 usbProxyUsbIpResetRecvState(pProxyDevUsbIp);
1061 }
1062 }
1063 else
1064 {
1065 LogRel(("USB/IP: Received reply with sequence number %u doesn't match any local URB\n", pProxyDevUsbIp->BufRet.Hdr.u32SeqNum));
1066 usbProxyUsbIpResetRecvState(pProxyDevUsbIp);
1067 }
1068 break;
1069 case USBIP_RET_UNLINK:
1070 pProxyDevUsbIp->pUrbUsbIp = usbProxyUsbIpGetCancelledUrbFromSeqNum(pProxyDevUsbIp, RT_N2H_U32(pProxyDevUsbIp->BufRet.Hdr.u32SeqNum));
1071 if (pProxyDevUsbIp->pUrbUsbIp)
1072 {
1073 usbProxyUsbIpRetUnlinkN2H(&pProxyDevUsbIp->BufRet.RetUnlink);
1074 pUrbUsbIp = pProxyDevUsbIp->pUrbUsbIp;
1075 pUrbUsbIp->pVUsbUrb->enmStatus = usbProxyUsbIpVUsbStatusConvertFromStatus(pProxyDevUsbIp->BufRet.RetUnlink.u32Status);
1076 }
1077 /* else: Probably received the data for the URB and is complete already. */
1078
1079 usbProxyUsbIpResetRecvState(pProxyDevUsbIp);
1080 break;
1081 }
1082
1083 break;
1084 }
1085 case USBPROXYUSBIPRECVSTATE_URB_BUFFER:
1086 if (pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->enmType == VUSBXFERTYPE_ISOC)
1087 usbProxyUsbIpRecvStateAdvance(pProxyDevUsbIp, USBPROXYUSBIPRECVSTATE_ISOC_PKT_DESCS,
1088 (uint8_t *)&pProxyDevUsbIp->aIsocPktDesc[0],
1089 pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->cIsocPkts * sizeof(UsbIpIsocPktDesc));
1090 else
1091 {
1092 pUrbUsbIp = pProxyDevUsbIp->pUrbUsbIp;
1093 usbProxyUsbIpResetRecvState(pProxyDevUsbIp);
1094 }
1095 break;
1096 case USBPROXYUSBIPRECVSTATE_ISOC_PKT_DESCS:
1097 /* Process all received isochronous packet descriptors. */
1098 for (unsigned i = 0; i < pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->cIsocPkts; i++)
1099 {
1100 PVUSBURBISOCPTK pIsocPkt = &pProxyDevUsbIp->pUrbUsbIp->pVUsbUrb->aIsocPkts[i];
1101 usbProxyUsbIpIsocPktDescN2H(&pProxyDevUsbIp->aIsocPktDesc[i]);
1102 pIsocPkt->enmStatus = usbProxyUsbIpVUsbStatusConvertFromStatus(pProxyDevUsbIp->aIsocPktDesc[i].i32Status);
1103 pIsocPkt->off = pProxyDevUsbIp->aIsocPktDesc[i].u32Offset;
1104 pIsocPkt->cb = pProxyDevUsbIp->aIsocPktDesc[i].u32ActualLength;
1105 }
1106
1107 pUrbUsbIp = pProxyDevUsbIp->pUrbUsbIp;
1108 usbProxyUsbIpResetRecvState(pProxyDevUsbIp);
1109 break;
1110 default:
1111 AssertLogRelMsgFailed(("USB/IP: Invalid receive state %d\n", pProxyDevUsbIp->enmRecvState));
1112 }
1113 }
1114 }
1115 else
1116 {
1117 /** @todo: Complete all URBs with DNR error and mark device as unplugged. */
1118#if 0
1119 pUrbUsbIp = pProxyDevUsbIp->pUrbUsbIp;
1120 pUrbUsbIp->pVUsbUrb->enmStatus = VUSBSTATUS_DNR;
1121 usbProxyUsbIpResetRecvState(pProxyDevUsbIp);
1122#endif
1123 }
1124
1125 if (RT_SUCCESS(rc))
1126 *ppUrbUsbIp = pUrbUsbIp;
1127
1128 return rc;
1129}
1130
1131/**
1132 * Worker for queueing an URB on the main I/O thread.
1133 *
1134 * @returns VBox status code.
1135 * @param pProxyDevUsbIp The USB/IP proxy device data.
1136 * @param pUrbUsbIp The USB/IP URB to queue.
1137 */
1138static int usbProxyUsbIpUrbQueueWorker(PUSBPROXYDEVUSBIP pProxyDevUsbIp, PUSBPROXYURBUSBIP pUrbUsbIp)
1139{
1140 PVUSBURB pUrb = pUrbUsbIp->pVUsbUrb;
1141
1142 pUrbUsbIp->u32SeqNumUrb = usbProxyUsbIpSeqNumGet(pProxyDevUsbIp);
1143
1144 UsbIpReqSubmit ReqSubmit;
1145
1146 RT_ZERO(ReqSubmit);
1147 ReqSubmit.Hdr.u32ReqRet = USBIP_CMD_SUBMIT;
1148 ReqSubmit.Hdr.u32SeqNum = pUrbUsbIp->u32SeqNumUrb;
1149 ReqSubmit.Hdr.u32DevId = pProxyDevUsbIp->u32DevId;
1150 ReqSubmit.Hdr.u32Endpoint = pUrb->EndPt;
1151 ReqSubmit.Hdr.u32Direction = pUrb->enmDir == VUSBDIRECTION_IN ? USBIP_DIR_IN : USBIP_DIR_OUT;
1152 ReqSubmit.u32XferFlags = 0;
1153 if (pUrb->enmDir == VUSBDIRECTION_IN && pUrb->fShortNotOk)
1154 ReqSubmit.u32XferFlags |= USBIP_XFER_FLAGS_SHORT_NOT_OK;
1155
1156 ReqSubmit.u32TransferBufferLength = pUrb->cbData;
1157 ReqSubmit.u32StartFrame = 0;
1158 ReqSubmit.u32NumIsocPkts = 0;
1159 ReqSubmit.u32Interval = 0;
1160
1161 RTSGSEG aSegReq[3]; /* Maximum number of segments used for a Isochronous transfer. */
1162 UsbIpIsocPktDesc aIsocPktsDesc[8];
1163 unsigned cSegsUsed = 1;
1164 aSegReq[0].pvSeg = &ReqSubmit;
1165 aSegReq[0].cbSeg = sizeof(ReqSubmit);
1166
1167 switch (pUrb->enmType)
1168 {
1169 case VUSBXFERTYPE_MSG:
1170 memcpy(&ReqSubmit.Setup, &pUrb->abData, sizeof(ReqSubmit.Setup));
1171 ReqSubmit.u32TransferBufferLength -= sizeof(VUSBSETUP);
1172 if (pUrb->enmDir == VUSBDIRECTION_OUT)
1173 {
1174 aSegReq[cSegsUsed].cbSeg = pUrb->cbData - sizeof(VUSBSETUP);
1175 aSegReq[cSegsUsed].pvSeg = pUrb->abData + sizeof(VUSBSETUP);
1176 if (aSegReq[cSegsUsed].cbSeg)
1177 cSegsUsed++;
1178 }
1179 LogFlowFunc(("Message (Control) URB\n"));
1180 break;
1181 case VUSBXFERTYPE_ISOC:
1182 LogFlowFunc(("Isochronous URB\n"));
1183 ReqSubmit.u32XferFlags |= USBIP_XFER_FLAGS_ISO_ASAP;
1184 ReqSubmit.u32NumIsocPkts = pUrb->cIsocPkts;
1185 if (pUrb->enmDir == VUSBDIRECTION_OUT)
1186 {
1187 aSegReq[cSegsUsed].cbSeg = pUrb->cbData;
1188 aSegReq[cSegsUsed].pvSeg = pUrb->abData;
1189 cSegsUsed++;
1190 }
1191
1192 for (unsigned i = 0; i < pUrb->cIsocPkts; i++)
1193 {
1194 aIsocPktsDesc[i].u32Offset = pUrb->aIsocPkts[i].off;
1195 aIsocPktsDesc[i].u32Length = pUrb->aIsocPkts[i].cb;
1196 aIsocPktsDesc[i].u32ActualLength = 0; /** @todo */
1197 aIsocPktsDesc[i].i32Status = pUrb->aIsocPkts[i].enmStatus;
1198 usbProxyUsbIpIsocPktDescH2N(&aIsocPktsDesc[i]);
1199 }
1200
1201 if (pUrb->cIsocPkts)
1202 {
1203 aSegReq[cSegsUsed].cbSeg = pUrb->cIsocPkts * sizeof(UsbIpIsocPktDesc);
1204 aSegReq[cSegsUsed].pvSeg = &aIsocPktsDesc[0];
1205 cSegsUsed++;
1206 }
1207
1208 break;
1209 case VUSBXFERTYPE_BULK:
1210 case VUSBXFERTYPE_INTR:
1211 LogFlowFunc(("Bulk URB\n"));
1212 if (pUrb->enmDir == VUSBDIRECTION_OUT)
1213 {
1214 aSegReq[cSegsUsed].cbSeg = pUrb->cbData;
1215 aSegReq[cSegsUsed].pvSeg = pUrb->abData;
1216 cSegsUsed++;
1217 }
1218 break;
1219 default:
1220 usbProxyUsbIpUrbFree(pProxyDevUsbIp, pUrbUsbIp);
1221 return VERR_INVALID_PARAMETER; /** @todo: better status code. */
1222 }
1223
1224 usbProxyUsbIpReqSubmitH2N(&ReqSubmit);
1225
1226 Assert(cSegsUsed <= RT_ELEMENTS(aSegReq));
1227
1228 /* Send the command. */
1229 RTSGBUF SgBufReq;
1230 RTSgBufInit(&SgBufReq, &aSegReq[0], cSegsUsed);
1231
1232 int rc = RTTcpSgWrite(pProxyDevUsbIp->hSocket, &SgBufReq);
1233 if (RT_SUCCESS(rc))
1234 {
1235 /* Link the URB into the list of in flight URBs. */
1236 usbProxyUsbIpLinkUrb(pProxyDevUsbIp, &pProxyDevUsbIp->ListUrbsInFlight, pUrbUsbIp);
1237 }
1238
1239 return rc;
1240}
1241
1242/**
1243 * Queues all pending URBs from the list.
1244 *
1245 * @returns VBox status code.
1246 * @param pProxyDevUsbIp The USB/IP proxy device data.
1247 */
1248static int usbProxyUsbIpUrbsQueuePending(PUSBPROXYDEVUSBIP pProxyDevUsbIp)
1249{
1250 RTLISTANCHOR ListUrbsPending;
1251
1252 RTListInit(&ListUrbsPending);
1253 int rc = RTSemFastMutexRequest(pProxyDevUsbIp->hMtxLists);
1254 AssertRC(rc);
1255 RTListMove(&ListUrbsPending, &pProxyDevUsbIp->ListUrbsToQueue);
1256 RTSemFastMutexRelease(pProxyDevUsbIp->hMtxLists);
1257
1258 PUSBPROXYURBUSBIP pIter = NULL;
1259 PUSBPROXYURBUSBIP pIterNext = NULL;
1260 RTListForEachSafe(&ListUrbsPending, pIter, pIterNext, USBPROXYURBUSBIP, NodeList)
1261 {
1262 RTListNodeRemove(&pIter->NodeList);
1263 rc = usbProxyUsbIpUrbQueueWorker(pProxyDevUsbIp, pIter);
1264 if (RT_FAILURE(rc))
1265 {
1266 /** @todo: Complete the URB with an error. */
1267 usbProxyUsbIpUrbFree(pProxyDevUsbIp, pIter);
1268 }
1269 }
1270
1271 return VINF_SUCCESS;
1272}
1273
1274/**
1275 * Kick the reaper thread.
1276 *
1277 * @returns VBox status code.
1278 * @param pProxyDevUsbIp The USB/IP proxy device data.
1279 * @param bReason The wakeup reason.
1280 */
1281static char usbProxyReaperKick(PUSBPROXYDEVUSBIP pProxyDevUsbIp, char bReason)
1282{
1283 int rc = VINF_SUCCESS;
1284 size_t cbWritten = 0;
1285
1286 rc = RTPipeWrite(pProxyDevUsbIp->hPipeW, &bReason, 1, &cbWritten);
1287 Assert(RT_SUCCESS(rc) || cbWritten == 0);
1288
1289 return rc;
1290}
1291
1292/**
1293 * Drain the wakeup pipe.
1294 *
1295 * @returns Wakeup reason.
1296 * @param pProxyDevUsbIp The USB/IP proxy device data.
1297 */
1298static char usbProxyUsbIpWakeupPipeDrain(PUSBPROXYDEVUSBIP pProxyDevUsbIp)
1299{
1300 char bRead = 0;
1301 size_t cbRead = 0;
1302
1303 int rc = RTPipeRead(pProxyDevUsbIp->hPipeR, &bRead, 1, &cbRead);
1304 Assert(RT_SUCCESS(rc) && cbRead == 1);
1305
1306 return bRead;
1307}
1308
1309/*
1310 * The USB proxy device functions.
1311 */
1312
1313static DECLCALLBACK(int) usbProxyUsbIpOpen(PUSBPROXYDEV pProxyDev, const char *pszAddress, void *pvBackend)
1314{
1315 LogFlowFunc(("pProxyDev=%p pszAddress=%s, pvBackend=%p\n", pProxyDev, pszAddress, pvBackend));
1316
1317 PUSBPROXYDEVUSBIP pDevUsbIp = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
1318 int rc = VINF_SUCCESS;
1319
1320 RTListInit(&pDevUsbIp->ListUrbsInFlight);
1321 RTListInit(&pDevUsbIp->ListUrbsLanded);
1322 RTListInit(&pDevUsbIp->ListUrbsToQueue);
1323 pDevUsbIp->hSocket = NIL_RTSOCKET;
1324 pDevUsbIp->hPollSet = NIL_RTPOLLSET;
1325 pDevUsbIp->hPipeW = NIL_RTPIPE;
1326 pDevUsbIp->hPipeR = NIL_RTPIPE;
1327 pDevUsbIp->u32SeqNumNext = 0;
1328 pDevUsbIp->pszHost = NULL;
1329 pDevUsbIp->pszBusId = NULL;
1330 usbProxyUsbIpResetRecvState(pDevUsbIp);
1331
1332 rc = RTSemFastMutexCreate(&pDevUsbIp->hMtxLists);
1333 if (RT_SUCCESS(rc))
1334 {
1335 /* Setup wakeup pipe and poll set first. */
1336 rc = RTPipeCreate(&pDevUsbIp->hPipeR, &pDevUsbIp->hPipeW, 0);
1337 if (RT_SUCCESS(rc))
1338 {
1339 rc = RTPollSetCreate(&pDevUsbIp->hPollSet);
1340 if (RT_SUCCESS(rc))
1341 {
1342 rc = RTPollSetAddPipe(pDevUsbIp->hPollSet, pDevUsbIp->hPipeR,
1343 RTPOLL_EVT_READ, USBIP_POLL_ID_PIPE);
1344 if (RT_SUCCESS(rc))
1345 {
1346 /* Connect to the USB/IP host. */
1347 rc = usbProxyUsbIpParseAddress(pDevUsbIp, pszAddress);
1348 if (RT_SUCCESS(rc))
1349 rc = usbProxyUsbIpConnect(pDevUsbIp);
1350 }
1351
1352 if (RT_FAILURE(rc))
1353 {
1354 RTPollSetRemove(pDevUsbIp->hPollSet, USBIP_POLL_ID_PIPE);
1355 int rc2 = RTPollSetDestroy(pDevUsbIp->hPollSet);
1356 AssertRC(rc2);
1357 }
1358 }
1359
1360 if (RT_FAILURE(rc))
1361 {
1362 int rc2 = RTPipeClose(pDevUsbIp->hPipeR);
1363 AssertRC(rc2);
1364 rc2 = RTPipeClose(pDevUsbIp->hPipeW);
1365 AssertRC(rc2);
1366 }
1367 }
1368 }
1369
1370 return rc;
1371}
1372
1373static DECLCALLBACK(void) usbProxyUsbIpClose(PUSBPROXYDEV pProxyDev)
1374{
1375 int rc = VINF_SUCCESS;
1376 LogFlowFunc(("pProxyDev = %p\n", pProxyDev));
1377
1378 PUSBPROXYDEVUSBIP pDevUsbIp = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
1379 /* Destroy the pipe and pollset if necessary. */
1380 if (pDevUsbIp->hPollSet != NIL_RTPOLLSET)
1381 {
1382 if (pDevUsbIp->hSocket != NIL_RTSOCKET)
1383 {
1384 rc = RTPollSetRemove(pDevUsbIp->hPollSet, USBIP_POLL_ID_SOCKET);
1385 Assert(RT_SUCCESS(rc) || rc == VERR_POLL_HANDLE_ID_NOT_FOUND);
1386 }
1387 rc = RTPollSetRemove(pDevUsbIp->hPollSet, USBIP_POLL_ID_PIPE);
1388 AssertRC(rc);
1389 rc = RTPollSetDestroy(pDevUsbIp->hPollSet);
1390 AssertRC(rc);
1391 rc = RTPipeClose(pDevUsbIp->hPipeR);
1392 AssertRC(rc);
1393 rc = RTPipeClose(pDevUsbIp->hPipeW);
1394 AssertRC(rc);
1395 }
1396
1397 if (pDevUsbIp->hSocket != NIL_RTSOCKET)
1398 usbProxyUsbIpDisconnect(pDevUsbIp);
1399 if (pDevUsbIp->pszHost)
1400 RTStrFree(pDevUsbIp->pszHost);
1401 if (pDevUsbIp->pszBusId)
1402 RTStrFree(pDevUsbIp->pszBusId);
1403
1404 /* Clear the URB lists. */
1405 rc = RTSemFastMutexRequest(pDevUsbIp->hMtxLists);
1406 AssertRC(rc);
1407 PUSBPROXYURBUSBIP pIter = NULL;
1408 PUSBPROXYURBUSBIP pIterNext = NULL;
1409 RTListForEachSafe(&pDevUsbIp->ListUrbsInFlight, pIter, pIterNext, USBPROXYURBUSBIP, NodeList)
1410 {
1411 RTListNodeRemove(&pIter->NodeList);
1412 RTMemFree(pIter);
1413 }
1414
1415 RTListForEachSafe(&pDevUsbIp->ListUrbsLanded, pIter, pIterNext, USBPROXYURBUSBIP, NodeList)
1416 {
1417 RTListNodeRemove(&pIter->NodeList);
1418 RTMemFree(pIter);
1419 }
1420 RTSemFastMutexRelease(pDevUsbIp->hMtxLists);
1421 RTSemFastMutexDestroy(pDevUsbIp->hMtxLists);
1422}
1423
1424static DECLCALLBACK(int) usbProxyUsbIpReset(PUSBPROXYDEV pProxyDev, bool fResetOnLinux)
1425{
1426 LogFlowFunc(("pProxyDev = %p\n", pProxyDev));
1427
1428 int rc = VINF_SUCCESS;
1429 PUSBPROXYDEVUSBIP pProxyDevUsbIp = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
1430 VUSBSETUP Setup;
1431
1432 if (fResetOnLinux)
1433 {
1434 Setup.bmRequestType = RT_BIT(5) | 0x03; /* Port request. */
1435 Setup.bRequest = 0x03; /* SET_FEATURE */
1436 Setup.wValue = 4; /* Port feature: Reset */
1437 Setup.wIndex = 0; /* Port number, irrelevant */
1438 Setup.wLength = 0;
1439 rc = usbProxyUsbIpCtrlUrbExchangeSync(pProxyDevUsbIp, &Setup);
1440 if (RT_SUCCESS(rc))
1441 {
1442 pProxyDev->iActiveCfg = -1;
1443 pProxyDev->cIgnoreSetConfigs = 2;
1444 }
1445 }
1446
1447 return rc;
1448}
1449
1450static DECLCALLBACK(int) usbProxyUsbIpSetConfig(PUSBPROXYDEV pProxyDev, int iCfg)
1451{
1452 LogFlowFunc(("pProxyDev=%s cfg=%#x\n", pProxyDev->pUsbIns->pszName, iCfg));
1453
1454 PUSBPROXYDEVUSBIP pProxyDevUsbIp = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
1455 VUSBSETUP Setup;
1456
1457 Setup.bmRequestType = 0;
1458 Setup.bRequest = 0x09;
1459 Setup.wValue = iCfg;
1460 Setup.wIndex = 0;
1461 Setup.wLength = 0;
1462 return usbProxyUsbIpCtrlUrbExchangeSync(pProxyDevUsbIp, &Setup);
1463}
1464
1465static DECLCALLBACK(int) usbProxyUsbIpClaimInterface(PUSBPROXYDEV pProxyDev, int ifnum)
1466{
1467 LogFlowFunc(("pProxyDev=%s ifnum=%#x\n", pProxyDev->pUsbIns->pszName, ifnum));
1468 return VINF_SUCCESS;
1469}
1470
1471static DECLCALLBACK(int) usbProxyUsbIpReleaseInterface(PUSBPROXYDEV pProxyDev, int ifnum)
1472{
1473 LogFlowFunc(("pProxyDev=%s ifnum=%#x\n", pProxyDev->pUsbIns->pszName, ifnum));
1474 return VINF_SUCCESS;
1475}
1476
1477static DECLCALLBACK(int) usbProxyUsbIpSetInterface(PUSBPROXYDEV pProxyDev, int ifnum, int setting)
1478{
1479 LogFlowFunc(("pProxyDev=%p ifnum=%#x setting=%#x\n", pProxyDev, ifnum, setting));
1480
1481 PUSBPROXYDEVUSBIP pProxyDevUsbIp = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
1482 VUSBSETUP Setup;
1483
1484 Setup.bmRequestType = 0x1;
1485 Setup.bRequest = 0x0b; /* SET_INTERFACE */
1486 Setup.wValue = setting;
1487 Setup.wIndex = ifnum;
1488 Setup.wLength = 0;
1489 return usbProxyUsbIpCtrlUrbExchangeSync(pProxyDevUsbIp, &Setup);
1490}
1491
1492static DECLCALLBACK(int) usbProxyUsbIpClearHaltedEp(PUSBPROXYDEV pProxyDev, unsigned int iEp)
1493{
1494 LogFlowFunc(("pProxyDev=%s ep=%u\n", pProxyDev->pUsbIns->pszName, iEp));
1495
1496 PUSBPROXYDEVUSBIP pProxyDevUsbIp = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
1497 VUSBSETUP Setup;
1498
1499 Setup.bmRequestType = 0x2;
1500 Setup.bRequest = 0x01; /* CLEAR_FEATURE */
1501 Setup.wValue = 0x00; /* ENDPOINT_HALT */
1502 Setup.wIndex = iEp;
1503 Setup.wLength = 0;
1504 return usbProxyUsbIpCtrlUrbExchangeSync(pProxyDevUsbIp, &Setup);
1505}
1506
1507static DECLCALLBACK(int) usbProxyUsbIpUrbQueue(PUSBPROXYDEV pProxyDev, PVUSBURB pUrb)
1508{
1509 LogFlowFunc(("pUrb=%p\n", pUrb));
1510
1511 PUSBPROXYDEVUSBIP pProxyDevUsbIp = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
1512
1513 /* Allocate a USB/IP Urb. */
1514 PUSBPROXYURBUSBIP pUrbUsbIp = usbProxyUsbIpUrbAlloc(pProxyDevUsbIp);
1515 if (!pUrbUsbIp)
1516 return VERR_NO_MEMORY;
1517
1518 pUrbUsbIp->fCancelled = false;
1519 pUrbUsbIp->pVUsbUrb = pUrb;
1520 pUrb->Dev.pvPrivate = pUrbUsbIp;
1521
1522 int rc = RTSemFastMutexRequest(pProxyDevUsbIp->hMtxLists);
1523 AssertRC(rc);
1524 RTListAppend(&pProxyDevUsbIp->ListUrbsToQueue, &pUrbUsbIp->NodeList);
1525 RTSemFastMutexRelease(pProxyDevUsbIp->hMtxLists);
1526
1527 return usbProxyReaperKick(pProxyDevUsbIp, USBIP_REAPER_WAKEUP_REASON_QUEUE);
1528}
1529
1530static DECLCALLBACK(PVUSBURB) usbProxyUsbIpUrbReap(PUSBPROXYDEV pProxyDev, RTMSINTERVAL cMillies)
1531{
1532 LogFlowFunc(("pProxyDev=%s\n", pProxyDev->pUsbIns->pszName));
1533
1534 PUSBPROXYDEVUSBIP pProxyDevUsbIp = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
1535 PUSBPROXYURBUSBIP pUrbUsbIp = NULL;
1536 PVUSBURB pUrb = NULL;
1537 int rc = VINF_SUCCESS;
1538
1539 /* Queue new URBs first. */
1540 rc = usbProxyUsbIpUrbsQueuePending(pProxyDevUsbIp);
1541 AssertRC(rc);
1542
1543 /* Any URBs pending delivery? */
1544 if (!RTListIsEmpty(&pProxyDevUsbIp->ListUrbsLanded))
1545 pUrbUsbIp = RTListGetFirst(&pProxyDevUsbIp->ListUrbsLanded, USBPROXYURBUSBIP, NodeList);
1546
1547 while (!pUrbUsbIp && RT_SUCCESS(rc) && cMillies)
1548 {
1549 uint32_t uIdReady = 0;
1550 uint32_t fEventsRecv = 0;
1551 RTMSINTERVAL msStart = RTTimeMilliTS();
1552 RTMSINTERVAL msNow;
1553
1554 rc = RTPoll(pProxyDevUsbIp->hPollSet, cMillies, &fEventsRecv, &uIdReady);
1555 Assert(RT_SUCCESS(rc) || rc == VERR_TIMEOUT);
1556 if (RT_SUCCESS(rc))
1557 {
1558 msNow = RTTimeMilliTS();
1559 cMillies = msNow - msStart >= cMillies ? 0 : cMillies - (msNow - msStart);
1560
1561 if (uIdReady == USBIP_POLL_ID_SOCKET)
1562 rc = usbProxyUsbIpRecvPdu(pProxyDevUsbIp, &pUrbUsbIp);
1563 else
1564 {
1565 AssertLogRelMsg(uIdReady == USBIP_POLL_ID_PIPE, ("Invalid pollset ID given\n"));
1566
1567 char bReason = usbProxyUsbIpWakeupPipeDrain(pProxyDevUsbIp);
1568 if (bReason == USBIP_REAPER_WAKEUP_REASON_QUEUE)
1569 usbProxyUsbIpUrbsQueuePending(pProxyDevUsbIp);
1570 else
1571 {
1572 Assert(bReason == USBIP_REAPER_WAKEUP_REASON_EXTERNAL);
1573 break;
1574 }
1575 }
1576 }
1577 }
1578
1579 if (pUrbUsbIp)
1580 {
1581 pUrb = pUrbUsbIp->pVUsbUrb;
1582
1583 /* unlink from the pending delivery list */
1584 usbProxyUsbIpUnlinkUrb(pProxyDevUsbIp, pUrbUsbIp);
1585 usbProxyUsbIpUrbFree(pProxyDevUsbIp, pUrbUsbIp);
1586 }
1587
1588 return pUrb;
1589}
1590
1591static DECLCALLBACK(int) usbProxyUsbIpUrbCancel(PUSBPROXYDEV pProxyDev, PVUSBURB pUrb)
1592{
1593 LogFlowFunc(("pUrb=%p\n", pUrb));
1594
1595 PUSBPROXYDEVUSBIP pProxyDevUsbIp = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
1596 PUSBPROXYURBUSBIP pUrbUsbIp = (PUSBPROXYURBUSBIP)pUrb->Dev.pvPrivate;
1597 UsbIpReqUnlink ReqUnlink;
1598
1599 RT_ZERO(ReqUnlink);
1600
1601 uint32_t u32SeqNum = usbProxyUsbIpSeqNumGet(pProxyDevUsbIp);
1602 ReqUnlink.Hdr.u32ReqRet = USBIP_CMD_UNLINK;
1603 ReqUnlink.Hdr.u32SeqNum = u32SeqNum;
1604 ReqUnlink.Hdr.u32DevId = pProxyDevUsbIp->u32DevId;
1605 ReqUnlink.Hdr.u32Direction = USBIP_DIR_OUT;
1606 ReqUnlink.Hdr.u32Endpoint = pUrb->EndPt;
1607 ReqUnlink.u32SeqNum = pUrbUsbIp->u32SeqNumUrb;
1608
1609 usbProxyUsbIpReqUnlinkH2N(&ReqUnlink);
1610 int rc = RTTcpWrite(pProxyDevUsbIp->hSocket, &ReqUnlink, sizeof(ReqUnlink));
1611 if (RT_SUCCESS(rc))
1612 {
1613 pUrbUsbIp->u32SeqNumUrbUnlink = u32SeqNum;
1614 pUrbUsbIp->fCancelled = true;
1615 }
1616
1617 return rc;
1618}
1619
1620static DECLCALLBACK(int) usbProxyUsbIpWakeup(PUSBPROXYDEV pProxyDev)
1621{
1622 LogFlowFunc(("pProxyDev=%s\n", pProxyDev->pUsbIns->pszName));
1623
1624 PUSBPROXYDEVUSBIP pProxyDevUsbIp = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVUSBIP);
1625 return usbProxyReaperKick(pProxyDevUsbIp, USBIP_REAPER_WAKEUP_REASON_EXTERNAL);
1626}
1627
1628/**
1629 * The USB/IP USB Proxy Backend operations.
1630 */
1631extern const USBPROXYBACK g_USBProxyDeviceUsbIp =
1632{
1633 /* pszName */
1634 "usbip",
1635 /* cbBackend */
1636 sizeof(USBPROXYDEVUSBIP),
1637 usbProxyUsbIpOpen,
1638 NULL,
1639 usbProxyUsbIpClose,
1640 usbProxyUsbIpReset,
1641 usbProxyUsbIpSetConfig,
1642 usbProxyUsbIpClaimInterface,
1643 usbProxyUsbIpReleaseInterface,
1644 usbProxyUsbIpSetInterface,
1645 usbProxyUsbIpClearHaltedEp,
1646 usbProxyUsbIpUrbQueue,
1647 usbProxyUsbIpUrbCancel,
1648 usbProxyUsbIpUrbReap,
1649 usbProxyUsbIpWakeup,
1650 0
1651};
1652
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette