- Timestamp:
- Apr 14, 2016 10:33:11 AM (9 years ago)
- svn:sync-xref-src-repo-rev:
- 106590
- Location:
- trunk/src/VBox/ValidationKit
- Files:
-
- 1 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ValidationKit/tests/usb/Makefile.kmk
r56295 r60488 34 34 ValidationKitTestsUsb_EXEC_SOURCES := \ 35 35 $(PATH_SUB_CURRENT)/tdUsb1.py \ 36 $(PATH_SUB_CURRENT)/usbgadget.py 36 $(PATH_SUB_CURRENT)/usbgadget.py \ 37 $(PATH_SUB_CURRENT)/usbgadget2.py 37 38 38 39 VBOX_VALIDATIONKIT_PYTHON_SOURCES += $(ValidationKitTestsUsb_EXEC_SOURCES) -
trunk/src/VBox/ValidationKit/tests/usb/tdUsb1.py
r59884 r60488 49 49 50 50 # USB gadget control import 51 import usbgadget ;51 import usbgadget2; 52 52 53 53 class tdUsbBenchmark(vbox.TestDriver): # pylint: disable=R0902 … … 65 65 kdGadgetParams = { 66 66 # The following is for local testing and not for the test lab. 67 #'adaris': { 68 # 'Low': ('beaglebone',), 69 # 'Full': ('beaglebone',), 70 # 'High': ('beaglebone',), 71 # 'Super': ('odroidxu3',) 72 #}, 67 73 'adaris': { 68 'Low': ('beaglebone', usbgadget.g_ksGadgetTypeBeaglebone), 69 'Full': ('beaglebone', usbgadget.g_ksGadgetTypeBeaglebone), 70 'High': ('beaglebone', usbgadget.g_ksGadgetTypeBeaglebone), 71 'Super': ('odroidxu3', usbgadget.g_ksGadgetTypeODroidXu3) 72 }, 73 'archusb': { 74 'Low': ('beaglebone', usbgadget.g_ksGadgetTypeBeaglebone), 75 'Full': ('beaglebone', usbgadget.g_ksGadgetTypeBeaglebone), 76 'High': ('beaglebone', usbgadget.g_ksGadgetTypeBeaglebone), 77 'Super': ('odroidxu3', usbgadget.g_ksGadgetTypeODroidXu3) 74 'Low': ('127.0.0.1', 0), 75 'Full': ('127.0.0.1', 0), 76 'High': ('127.0.0.1', 0), 77 'Super': ('127.0.0.1', 0) 78 78 }, 79 79 }; … … 105 105 self.cUsbReattachCycles = self.cUsbReattachCyclesDef; 106 106 self.sHostname = socket.gethostname().lower(); 107 self.fUseTxs = True;108 107 109 108 # … … 132 131 reporter.log(' --usb-reattach-cycles <cycles>'); 133 132 reporter.log(' Default: %s' % (self.cUsbReattachCyclesDef)); 134 reporter.log(' --local');135 reporter.log(' Don\'t use TXS for communication with the gadget but do everything');136 reporter.log(' on this host');137 133 return rc; 138 134 … … 200 196 raise base.InvalidOption('The "--usb-reattach-cycles" value "%s" is zero or negative.' \ 201 197 % (self.cUsbReattachCycles,)); 202 elif asArgs[iArg] == '--local':203 self.fUseTxs = False;204 198 else: 205 199 return vbox.TestDriver.parseOption(self, asArgs, iArg); … … 294 288 """ 295 289 # Get configured USB test devices from hostname we are running on 296 if self.fUseTxs is True: 297 sGadgetHost, sGadgetType = self.getGadgetParams(self.sHostname, sSpeed); 298 else: 299 sGadgetHost = 'dummy'; 300 sGadgetType = usbgadget.g_ksGadgetTypeDummyHcd; 301 302 # Create device filter 303 fRc = oSession.addUsbDeviceFilter('Compliance device', '0525', 'a4a0'); 290 sGadgetHost, _ = self.getGadgetParams(self.sHostname, sSpeed); 291 292 oUsbGadget = usbgadget2.UsbGadget(); 293 reporter.log('Connecting to UTS: ' + sGadgetHost); 294 fRc = oUsbGadget.connectTo(30 * 1000, sGadgetHost); 304 295 if fRc is True: 305 oUsbGadget = usbgadget.UsbGadget(); 306 reporter.log('Connecting to gadget: ' + sGadgetType); 307 fRc = oUsbGadget.connectTo(30 * 1000, sGadgetType, self.fUseTxs, sGadgetHost); 296 reporter.log('Connect succeeded'); 297 self.oVBox.host.addUSBDeviceSource('USBIP', sGadgetHost, sGadgetHost, [], []); 298 299 # Create device filter 300 fRc = oSession.addUsbDeviceFilter('Compliance device', '0525', 'a4a0'); 308 301 if fRc is True: 309 reporter.log('Connect succeeded'); 310 fRc = oUsbGadget.impersonate(usbgadget.g_ksGadgetImpersonationTest); 302 fRc = oUsbGadget.impersonate(usbgadget2.g_ksGadgetImpersonationTest); 311 303 if fRc is True: 312 304 313 305 # Wait a moment to let the USB device appear 314 self.sleep( 3);306 self.sleep(10); 315 307 316 308 tupCmdLine = ('UsbTest', ); … … 329 321 oUsbGadget.disconnectFrom(); 330 322 else: 331 reporter.testFailure('Failed to connect to USB gadget'); 323 reporter.testFailure('Failed to create USB device filter'); 324 325 self.oVBox.host.removeUSBDeviceSource(sGadgetHost); 332 326 else: 333 reporter.testFailure('Failed to c reate USB device filter');327 reporter.testFailure('Failed to connect to USB gadget'); 334 328 335 329 return fRc; … … 340 334 """ 341 335 # Get configured USB test devices from hostname we are running on 342 if self.fUseTxs is True: 343 sGadgetHost, sGadgetType = self.getGadgetParams(self.sHostname, sSpeed); 344 else: 345 sGadgetHost = 'dummy'; 346 sGadgetType = usbgadget.g_ksGadgetTypeDummyHcd; 347 348 # Create device filter 349 fRc = oSession.addUsbDeviceFilter('Compliance device', '0525', 'a4a0'); 336 sGadgetHost, _ = self.getGadgetParams(self.sHostname, sSpeed); 337 338 oUsbGadget = usbgadget2.UsbGadget(); 339 reporter.log('Connecting to UTS: ' + sGadgetHost); 340 fRc = oUsbGadget.connectTo(30 * 1000, sGadgetHost); 350 341 if fRc is True: 351 oUsbGadget = usbgadget.UsbGadget(); 352 reporter.log('Connecting to gadget: ' + sGadgetType); 353 fRc = oUsbGadget.connectTo(30 * 1000, sGadgetType, self.fUseTxs, sGadgetHost); 342 reporter.log('Connect succeeded'); 343 self.oVBox.host.addUSBDeviceSource('USBIP', sGadgetHost, sGadgetHost, [], []); 344 345 # Create device filter 346 fRc = oSession.addUsbDeviceFilter('Compliance device', '0525', 'a4a0'); 354 347 if fRc is True: 355 reporter.log('Connect succeeded'); 356 fRc = oUsbGadget.impersonate(usbgadget.g_ksGadgetImpersonationTest); 348 fRc = oUsbGadget.impersonate(usbgadget2.g_ksGadgetImpersonationTest); 357 349 if fRc is True: 358 350 -
trunk/src/VBox/ValidationKit/tests/usb/usbgadget.py
r59884 r60488 30 30 __version__ = "$Revision$" 31 31 32 import time; 32 33 33 34 # Validation Kit imports. … … 150 151 sPath = '/sys/class/udc/' + sUdcFile + '/soft_connect'; 151 152 152 return self._execLocallyOrThroughTxs('/usr/bin/sh', ('-c', 'echo ' + sAction + ' > ' + sPath));153 return self._execLocallyOrThroughTxs('/usr/bin/sh', ('-c', 'echo ' + sAction + ' > ' + sPath)); 153 154 154 155 def _prepareGadget(self): … … 192 193 self.sImpersonation = sImpersonation; 193 194 194 if sImpersonation == g_ksGadgetImpersonationInvalid: 195 return False; 196 elif sImpersonation == g_ksGadgetImpersonationTest: 197 return self._loadModule('g_zero'); 195 fRc = False; 196 if sImpersonation == g_ksGadgetImpersonationTest: 197 fRc = self._loadModule('g_zero'); 198 198 elif sImpersonation == g_ksGadgetImpersonationMsd: 199 199 # @todo: Not complete 200 returnself._loadModule('g_mass_storage');200 fRc = self._loadModule('g_mass_storage'); 201 201 elif sImpersonation == g_ksGadgetImpersonationWebcam: 202 202 # @todo: Not complete 203 returnself._loadModule('g_webcam');203 fRc = self._loadModule('g_webcam'); 204 204 elif sImpersonation == g_ksGadgetImpersonationEther: 205 returnself._loadModule('g_ether');205 fRc = self._loadModule('g_ether'); 206 206 else: 207 207 reporter.log('Invalid impersonation'); 208 208 209 return False; 209 if fRc and self.sGadgetType is g_ksGadgetTypeDummyHcd and self.oTxsSession is not None: 210 time.sleep(2); # Fudge 211 # For the dummy HCD over USB/IP case we have to bind the device to the USB/IP server 212 self._execLocallyOrThroughTxs('/usr/bin/sh', ('-c', '/usr/bin/usbip bind -b 3-1')); 213 214 return fRc; 210 215 211 216 def connectTo(self, cMsTimeout, sGadgetType, fUseTxs, sHostname, uPort = None): -
trunk/src/VBox/ValidationKit/tests/usb/usbgadget2.py
r60429 r60488 71 71 # 72 72 73 def getU64(abData, off): 74 """Get a U64 field.""" 75 return abData[off] \ 76 + abData[off + 1] * 256 \ 77 + abData[off + 2] * 65536 \ 78 + abData[off + 3] * 16777216 \ 79 + abData[off + 4] * 4294967296 \ 80 + abData[off + 5] * 1099511627776 \ 81 + abData[off + 6] * 281474976710656 \ 82 + abData[off + 7] * 72057594037927936; 83 73 84 def getU32(abData, off): 74 85 """Get a U32 field.""" … … 77 88 + abData[off + 2] * 65536 \ 78 89 + abData[off + 3] * 16777216; 90 91 def getU16(abData, off): 92 """Get a U16 field.""" 93 return abData[off] \ 94 + abData[off + 1] * 256; 95 96 def getU8(abData, off): 97 """Get a U8 field.""" 98 return abData[off]; 79 99 80 100 def getSZ(abData, off, sDefault = None): … … 150 170 def u8ToByteArray(u8): 151 171 """Encodes the u8 value as a little endian byte (B) array.""" 152 return array.array('B', (u8 % 256); 172 return array.array('B', (u8 % 256)); 173 174 def zeroByteArray(cb): 175 """Returns an array with the given size containing 0.""" 176 abArray = array.array('B', (0, )); 177 cb = cb - 1; 178 for i in range(cb): 179 abArray.append(0); 180 return abArray; 153 181 154 182 class TransportBase(object): … … 693 721 def taskGreet(self, cMsIdleFudge): 694 722 """Greets the UTS""" 695 rc = self.sendMsg("HOWDY", ()); 723 sHostname = socket.gethostname().lower(); 724 cbFill = 68 - len(sHostname) - 1; 725 rc = self.sendMsg("HOWDY", (long((1 << 16) | 0), long(0x1), long(len(sHostname)), sHostname, zeroByteArray(cbFill))); 696 726 if rc is True: 697 727 rc = self.recvAckLogged("HOWDY", self.fTryConnect); … … 718 748 def taskGadgetCreate(self, iGadgetType, iGadgetAccess): 719 749 """Creates a new gadget on UTS""" 720 fRc = self.sen fMsg("GDGTCRT", (iGadgetType, iGadgetAccess, 0));750 fRc = self.sendMsg("GDGTCRT", (iGadgetType, iGadgetAccess, 0)); 721 751 if fRc is True: 722 752 fRc = self.recvAckLogged("GDGTCRT"); … … 725 755 def taskGadgetDestroy(self, iGadgetId): 726 756 """Destroys the given gadget handle on UTS""" 727 fRc = self.sen fMsg("GDGTDTOR", (iGadgetId, ));757 fRc = self.sendMsg("GDGTDTOR", (iGadgetId, )); 728 758 if fRc is True: 729 759 fRc = self.recvAckLogged("GDGTDTOR"); … … 732 762 def taskGadgetConnect(self, iGadgetId): 733 763 """Connects the given gadget handle on UTS""" 734 fRc = self.sen fMsg("GDGTCNCT", (iGadgetId, ));764 fRc = self.sendMsg("GDGTCNCT", (iGadgetId, )); 735 765 if fRc is True: 736 766 fRc = self.recvAckLogged("GDGTCNCT"); … … 739 769 def taskGadgetDisconnect(self, iGadgetId): 740 770 """Disconnects the given gadget handle from UTS""" 741 fRc = self.sen fMsg("GDGTDCNT", (iGadgetId, ));771 fRc = self.sendMsg("GDGTDCNT", (iGadgetId, )); 742 772 if fRc is True: 743 773 fRc = self.recvAckLogged("GDGTDCNT"); … … 805 835 # 806 836 807 def 837 def asyncGadgetCreate(self, iGadgetType, iGadgetAccess, cMsTimeout = 30000, fIgnoreErrors = False): 838 """ 839 Initiates a gadget create task. 840 841 Returns True on success, False on failure (logged). 842 843 The task returns True on success and False on failure. 844 """ 845 return self.startTask(cMsTimeout, fIgnoreErrors, "GadgetCreate", self.taskGadgetCreate, \ 846 (long(iGadgetType), long(iGadgetAccess))); 847 848 def syncGadgetCreate(self, iGadgetType, iGadgetAccess, cMsTimeout = 30000, fIgnoreErrors = False): 849 """Synchronous version.""" 850 return self.asyncToSync(self.asyncGadgetCreate, iGadgetType, iGadgetAccess, cMsTimeout, fIgnoreErrors); 851 852 def asyncGadgetDestroy(self, iGadgetId, cMsTimeout = 30000, fIgnoreErrors = False): 853 """ 854 Initiates a gadget destroy task. 855 856 Returns True on success, False on failure (logged). 857 858 The task returns True on success and False on failure. 859 """ 860 return self.startTask(cMsTimeout, fIgnoreErrors, "GadgetDestroy", self.taskGadgetDestroy, \ 861 (long(iGadgetId), )); 862 863 def syncGadgetDestroy(self, iGadgetId, cMsTimeout = 30000, fIgnoreErrors = False): 864 """Synchronous version.""" 865 return self.asyncToSync(self.asyncGadgetDestroy, iGadgetId, cMsTimeout, fIgnoreErrors); 866 867 def asyncGadgetConnect(self, iGadgetId, cMsTimeout = 30000, fIgnoreErrors = False): 868 """ 869 Initiates a gadget connect task. 870 871 Returns True on success, False on failure (logged). 872 873 The task returns True on success and False on failure. 874 """ 875 return self.startTask(cMsTimeout, fIgnoreErrors, "GadgetConnect", self.taskGadgetConnect, \ 876 (long(iGadgetId), )); 877 878 def syncGadgetConnect(self, iGadgetId, cMsTimeout = 30000, fIgnoreErrors = False): 879 """Synchronous version.""" 880 return self.asyncToSync(self.asyncGadgetConnect, iGadgetId, cMsTimeout, fIgnoreErrors); 881 882 def asyncGadgetDisconnect(self, iGadgetId, cMsTimeout = 30000, fIgnoreErrors = False): 883 """ 884 Initiates a gadget disconnect task. 885 886 Returns True on success, False on failure (logged). 887 888 The task returns True on success and False on failure. 889 """ 890 return self.startTask(cMsTimeout, fIgnoreErrors, "GadgetDisconnect", self.taskGadgetDisconnect, \ 891 (long(iGadgetId), )); 892 893 def syncGadgetDisconnect(self, iGadgetId, cMsTimeout = 30000, fIgnoreErrors = False): 894 """Synchronous version.""" 895 return self.asyncToSync(self.asyncGadgetDisconnect, iGadgetId, cMsTimeout, fIgnoreErrors); 808 896 809 897 … … 1203 1291 self.oUtsSession = None; 1204 1292 self.sImpersonation = g_ksGadgetImpersonationInvalid; 1205 self.sGadgetType = g_ksGadgetTypeInvalid;1206 1293 self.idGadget = None; 1294 self.iUsbIpPort = None; 1207 1295 1208 1296 def _clearImpersonation(self): … … 1247 1335 return fRc; 1248 1336 1249 def connectTo(self, cMsTimeout, sHostname, uPort = None): 1337 def getUsbIpPort(self): 1338 """ 1339 Returns the port the USB/IP server is listening on if requested, 1340 None if USB/IP is not supported. 1341 """ 1342 return self.iUsbIpPort; 1343 1344 def connectTo(self, cMsTimeout, sHostname, uPort = None, fUsbIpSupport = True, cMsIdleFudge = 0): 1250 1345 """ 1251 1346 Connects to the specified target device. … … 1270 1365 else: 1271 1366 fRc = False; 1272 1273 if fRc:1274 fRc = self._prepareGadget();1275 1367 except: 1276 1368 reporter.errorXcpt(None, 15); -
trunk/src/VBox/ValidationKit/utils/usb/UsbTestService.cpp
r60417 r60488 462 462 463 463 return utsReplyFailure(pClient, pPktHdr, "FAILED ", rcOperation, "%s failed with rc=%Rrc (opcode '%.8s')", 464 rcOperation,szOperation, rcOperation, pPktHdr->achOpcode);464 szOperation, rcOperation, pPktHdr->achOpcode); 465 465 } 466 466 … … 600 600 601 601 /* Extract string. */ 602 pClient->pszHostname = RTStrDup( pClient->pszHostname);602 pClient->pszHostname = RTStrDup(&pReq->achHostname[0]); 603 603 if (!pClient->pszHostname) 604 return utsReplyRC(pClient, pPktHdr, VERR_NO_MEMORY, "Failed to all locate memory for the hostname string");604 return utsReplyRC(pClient, pPktHdr, VERR_NO_MEMORY, "Failed to allocate memory for the hostname string"); 605 605 606 606 if (pReq->fUsbConn & UTSPKT_HOWDY_CONN_F_PHYSICAL) … … 897 897 898 898 uint8_t bRead; 899 rc = RTPipeRead(g_hPipeR, &bRead, 1, NULL); 899 size_t cbRead = 0; 900 rc = RTPipeRead(g_hPipeR, &bRead, 1, &cbRead); 900 901 AssertRC(rc); 901 902 … … 950 951 /* Client sends a request, pick the right client and process it. */ 951 952 PUTSCLIENT pClient = papClients[uId - 1]; 953 AssertPtr(pClient); 952 954 if (fEvts & RTPOLL_EVT_READ) 953 955 rc = utsClientReqProcess(pClient); … … 957 959 { 958 960 /* Close connection and remove client from array. */ 961 rc = g_pTransport->pfnPollSetRemove(hPollSet, pClient->pTransportClient, uId); 962 AssertRC(rc); 963 959 964 g_pTransport->pfnNotifyBye(pClient->pTransportClient); 960 965 papClients[uId - 1] = NULL; … … 995 1000 * the request handling thread. 996 1001 */ 997 PUTSCLIENT pClient = (PUTSCLIENT)RTMemAllocZ(sizeof( PUTSCLIENT));1002 PUTSCLIENT pClient = (PUTSCLIENT)RTMemAllocZ(sizeof(UTSCLIENT)); 998 1003 if (RT_LIKELY(pClient)) 999 1004 { … … 1003 1008 pClient->hGadgetHost = NIL_UTSGADGETHOST; 1004 1009 pClient->hGadget = NIL_UTSGADGET; 1010 1011 /* Add client to the new list and inform the worker thread. */ 1012 RTCritSectEnter(&g_CritSectClients); 1013 RTListAppend(&g_LstClientsNew, &pClient->NdLst); 1014 RTCritSectLeave(&g_CritSectClients); 1015 1016 size_t cbWritten = 0; 1017 rc = RTPipeWrite(g_hPipeW, "", 1, &cbWritten); 1018 if (RT_FAILURE(rc)) 1019 RTMsgError("Failed to inform worker thread of a new client"); 1005 1020 } 1006 1021 else -
trunk/src/VBox/ValidationKit/utils/usb/UsbTestServiceGadgetHostUsbIp.cpp
r60375 r60488 101 101 { 102 102 /* Make sure the kernel drivers are loaded. */ 103 rc = utsGadgetHostUsbIpLoadModule("usbip-core .ko");103 rc = utsGadgetHostUsbIpLoadModule("usbip-core"); 104 104 if (RT_SUCCESS(rc)) 105 105 { 106 rc = utsGadgetHostUsbIpLoadModule("usbip-host .ko");106 rc = utsGadgetHostUsbIpLoadModule("usbip-host"); 107 107 if (RT_SUCCESS(rc)) 108 108 { 109 109 char aszPort[10]; 110 110 char aszPidFile[64]; 111 const char *apszArgv[ 5];111 const char *apszArgv[6]; 112 112 113 113 RTStrPrintf(aszPort, RT_ELEMENTS(aszPort), "%u", uPort); … … 117 117 apszArgv[1] = "--tcp-port"; 118 118 apszArgv[2] = aszPort; 119 apszArgv[3] = "--pid -file";119 apszArgv[3] = "--pid"; 120 120 apszArgv[4] = aszPidFile; 121 apszArgv[5] = NULL; 121 122 rc = RTProcCreate("usbipd", apszArgv, RTENV_DEFAULT, RTPROC_FLAGS_SEARCH_PATH, &pIf->hProcUsbIp); 122 123 if (RT_SUCCESS(rc)) -
trunk/src/VBox/ValidationKit/utils/usb/UsbTestServiceInternal.h
r60279 r60488 122 122 123 123 /** 124 * Removes the given client frmo the given pollset. 125 * 126 * @returns IPRT status code. 127 * @param hPollSet The poll set to remove from. 128 * @paramm pClient The transport client structure. 129 * @param idStart The handle ID to remove. 130 */ 131 DECLR3CALLBACKMEMBER(int, pfnPollSetRemove, (RTPOLLSET hPollSet, PUTSTRANSPORTCLIENT pClient, uint32_t idStart)); 132 133 /** 124 134 * Receives an incoming packet. 125 135 * -
trunk/src/VBox/ValidationKit/utils/usb/UsbTestServiceProtocol.h
r60417 r60488 100 100 uint32_t cchHostname; 101 101 /** The client host name as terminated ASCII string. */ 102 uint8_tachHostname[68];102 char achHostname[68]; 103 103 } UTSPKTREQHOWDY; 104 104 AssertCompileSizeAlignment(UTSPKTREQHOWDY, UTSPKT_ALIGNMENT); -
trunk/src/VBox/ValidationKit/utils/usb/UsbTestServiceTcp.cpp
r60281 r60488 93 93 94 94 /** 95 * Disconnects the current client and frees its data structure.95 * Disconnects the current client and frees all stashed data. 96 96 */ 97 97 static void utsTcpDisconnectClient(PUTSTRANSPORTCLIENT pClient) 98 98 { 99 int rc = RTTcpServerDisconnectClient2(pClient->hTcpClient); 100 AssertRCSuccess(rc); 99 if (pClient->hTcpClient == NIL_RTSOCKET) 100 { 101 int rc = RTTcpServerDisconnectClient2(pClient->hTcpClient); 102 pClient->hTcpClient = NIL_RTSOCKET; 103 AssertRCSuccess(rc); 104 } 105 101 106 if (pClient->pbTcpStashed) 107 { 102 108 RTMemFree(pClient->pbTcpStashed); 103 RTMemFree(pClient); 109 pClient->pbTcpStashed = NULL; 110 } 104 111 } 105 112 … … 158 165 Log(("utsTcpNotifyBye: utsTcpDisconnectClient %RTsock\n", pClient->hTcpClient)); 159 166 utsTcpDisconnectClient(pClient); 167 RTMemFree(pClient); 160 168 } 161 169 … … 347 355 348 356 /** 357 * @interface_method_impl{UTSTRANSPORT,pfnPollSetRemove} 358 */ 359 static DECLCALLBACK(int) utsTcpPollSetRemove(RTPOLLSET hPollSet, PUTSTRANSPORTCLIENT pClient, uint32_t idStart) 360 { 361 return RTPollSetRemove(hPollSet, idStart); 362 } 363 364 /** 349 365 * @interface_method_impl{UTSTRANSPORT,pfnPollIn} 350 366 */ … … 471 487 /* .pfnPollIn = */ utsTcpPollIn, 472 488 /* .pfnPollSetAdd = */ utsTcpPollSetAdd, 489 /* .pfnPollSetRemove = */ utsTcpPollSetRemove, 473 490 /* .pfnRecvPkt = */ utsTcpRecvPkt, 474 491 /* .pfnSendPkt = */ utsTcpSendPkt,
Note:
See TracChangeset
for help on using the changeset viewer.