Changeset 33813 in vbox for trunk/src/VBox/Devices/USB/freebsd/USBProxyDevice-freebsd.cpp
- Timestamp:
- Nov 5, 2010 7:35:30 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/USB/freebsd/USBProxyDevice-freebsd.cpp
r33595 r33813 6 6 /* 7 7 * Copyright (C) 2006-2007 Oracle Corporation 8 * Copyright (C) 2010 Hans Petter Selasky 8 9 * 9 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 19 20 * Header Files * 20 21 *******************************************************************************/ 21 #define LOG_GROUP LOG_GROUP_DRV_USBPROXY22 #define LOG_GROUP LOG_GROUP_DRV_USBPROXY 22 23 #ifdef VBOX 23 # 24 #include <iprt/stdint.h> 24 25 #endif 25 26 #include <sys/types.h> … … 54 55 55 56 /** Maximum endpoints supported. */ 56 #define USBFBSD_MAXENDPOINTS 32 57 #define USBFBSD_EPADDR_NUM_MASK 0x0F 58 #define USBFBSD_EPADDR_DIR_MASK 0x80 59 #define USBPROXY_FREEBSD_NO_ENTRY_FREE ((unsigned)~0) 57 #define USBFBSD_MAXENDPOINTS 127 58 #define USBFBSD_MAXFRAMES 56 59 60 60 /** This really needs to be defined in vusb.h! */ 61 61 #ifndef VUSB_DIR_TO_DEV … … 66 66 * Structures and Typedefs * 67 67 *******************************************************************************/ 68 typedef struct VUSBURBFBSD 69 { 68 typedef struct USBENDPOINTFBSD 69 { 70 /** Flag whether it is opened. */ 71 bool fOpen; 72 /** Flag whether it is cancelling. */ 73 bool fCancelling; 74 /** Buffer pointers. */ 75 void *apvData[USBFBSD_MAXFRAMES]; 76 /** Buffer lengths. */ 77 uint32_t acbData[USBFBSD_MAXFRAMES]; 78 /** Initial buffer length. */ 79 uint32_t cbData0; 70 80 /** Pointer to the URB. */ 71 PVUSBURB pUrb; 72 /** Buffer pointers. */ 73 void *apvData[2]; 74 /** Buffer lengths. */ 75 uint32_t acbData[2]; 76 } VUSBURBFBSD, *PVUSBURBFBSD; 77 78 typedef struct USBENDPOINTFBSD 79 { 80 /** Flag whether it is opened. */ 81 bool fOpen; 82 /** Index in the endpoint list. */ 83 unsigned iEndpoint; 84 /** Associated endpoint. */ 85 struct usb_fs_endpoint *pXferEndpoint; 81 PVUSBURB pUrb; 82 /** Copy of endpoint number. */ 83 unsigned iEpNum; 84 /** Maximum transfer length. */ 85 unsigned cMaxIo; 86 /** Maximum frame count. */ 87 unsigned cMaxFrames; 86 88 } USBENDPOINTFBSD, *PUSBENDPOINTFBSD; 87 89 … … 92 94 { 93 95 /** The open file. */ 94 RTFILE File; 95 /** Critical section protecting the two lists. */ 96 RTCRITSECT CritSect; 97 /** Pointer to the array of USB endpoints. */ 98 struct usb_fs_endpoint *paXferEndpoints; 99 /** Pointer to the array of URB structures. 100 * They entries must be in sync with the above array. */ 101 PVUSBURBFBSD paUrbs; 102 /** Number of entries in both arrays. */ 103 unsigned cXferEndpoints; 104 /** Pointer to the Fifo containing the indexes for free Xfer 105 * endpoints. */ 106 unsigned *paXferFree; 107 /** Index of the next free entry to write to. */ 108 unsigned iXferFreeNextWrite; 109 /** Index of the next entry to read from. */ 110 unsigned iXferFreeNextRead; 111 /** Status of opened endpoints. */ 112 USBENDPOINTFBSD aEpOpened[USBFBSD_MAXENDPOINTS]; 113 /** The list of landed FreeBSD URBs. Doubly linked. 114 * Only the split head will appear in this list. */ 115 PVUSBURB pTaxingHead; 116 /** The tail of the landed FreeBSD URBs. */ 117 PVUSBURB pTaxingTail; 96 RTFILE File; 97 /** Software endpoint structures */ 98 USBENDPOINTFBSD aSwEndpoint[USBFBSD_MAXENDPOINTS]; 99 /** Flag whether an URB is cancelling. */ 100 bool fCancelling; 101 /** Flag whether initialised or not */ 102 bool fInit; 103 /** Kernel endpoint structures */ 104 struct usb_fs_endpoint aHwEndpoint[USBFBSD_MAXENDPOINTS]; 118 105 } USBPROXYDEVFBSD, *PUSBPROXYDEVFBSD; 119 106 … … 121 108 * Internal Functions * 122 109 *******************************************************************************/ 123 static int usbProxyFreeBSDDoIoCtl(PUSBPROXYDEV pProxyDev, unsigned long iCmd, void *pvArg, bool fHandleNoDev, uint32_t cTries);124 static void usbProxFreeBSDUrbUnplugged(PUSBPROXYDEV pProxyDev);125 static PUSBENDPOINTFBSD usbProxyFreeBSDEndpointOpen(PUSBPROXYDEV pProxyDev, int Endpoint);126 110 static int usbProxyFreeBSDEndpointClose(PUSBPROXYDEV pProxyDev, int Endpoint); 127 111 … … 137 121 * @param pvArg The ioctl argument / data. 138 122 * @param fHandleNoDev Whether to handle ENXIO. 139 * @param cTries The number of retries. Use UINT32_MAX for (kind of) indefinite retries.140 123 * @internal 141 124 */ 142 static int usbProxyFreeBSDDoIoCtl(PUSBPROXYDEV pProxyDev, unsigned long iCmd, void *pvArg, bool fHandleNoDev, uint32_t cTries) 125 static int usbProxyFreeBSDDoIoCtl(PUSBPROXYDEV pProxyDev, unsigned long iCmd, 126 void *pvArg, bool fHandleNoDev) 143 127 { 144 128 int rc = VINF_SUCCESS; 145 146 PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)pProxyDev->Backend.pv; 129 PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD) pProxyDev->Backend.pv; 130 131 LogFlow(("usbProxyFreeBSDDoIoCtl: iCmd=%#x\n", iCmd)); 132 147 133 do 148 134 { 149 do 150 { 151 rc = ioctl(pDevFBSD->File, iCmd, pvArg); 152 if (rc >= 0) 153 return rc; 154 } while (errno == EINTR); 155 156 if (errno == ENXIO && fHandleNoDev) 157 { 158 usbProxFreeBSDUrbUnplugged(pProxyDev); 159 Log(("usb-freebsd: ENXIO -> unplugged. pProxyDev=%s\n", pProxyDev->pUsbIns->pszName)); 160 errno = ENODEV; 161 break; 162 } 163 if (errno != EAGAIN) 164 { 165 LogFlow(("usbProxyFreeBSDDoIoCtl returned %Rrc\n", RTErrConvertFromErrno(errno))); 166 break; 167 } 168 } while (cTries-- > 0); 135 rc = ioctl(pDevFBSD->File, iCmd, pvArg); 136 if (rc >= 0) 137 return VINF_SUCCESS; 138 } while (errno == EINTR); 139 140 if (errno == ENXIO && fHandleNoDev) 141 { 142 Log(("usbProxyFreeBSDDoIoCtl: ENXIO -> unplugged. pProxyDev=%s\n", 143 pProxyDev->pUsbIns->pszName)); 144 errno = ENODEV; 145 } 146 else if (errno != EAGAIN) 147 { 148 LogFlow(("usbProxyFreeBSDDoIoCtl: Returned %d. pProxyDev=%s\n", 149 errno, pProxyDev->pUsbIns->pszName)); 150 } 151 return RTErrConvertFromErrno(errno); 152 } 153 154 /** 155 * Init USB subsystem. 156 */ 157 static int usbProxyFreeBSDFsInit(PUSBPROXYDEV pProxyDev) 158 { 159 struct usb_fs_init UsbFsInit; 160 PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD) pProxyDev->Backend.pv; 161 int rc; 162 163 LogFlow(("usbProxyFreeBSDFsInit: pProxyDev=%p\n", (void *)pProxyDev)); 164 165 /* Sanity check */ 166 AssertPtrReturn(pDevFBSD, VERR_INVALID_PARAMETER); 167 168 if (pDevFBSD->fInit == true) 169 return VINF_SUCCESS; 170 171 /* Zero default */ 172 memset(&UsbFsInit, 0, sizeof(UsbFsInit)); 173 174 UsbFsInit.pEndpoints = pDevFBSD->aHwEndpoint; 175 UsbFsInit.ep_index_max = USBFBSD_MAXENDPOINTS; 176 177 /* Init USB subsystem */ 178 rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_INIT, &UsbFsInit, false); 179 if (RT_SUCCESS(rc)) 180 pDevFBSD->fInit = true; 169 181 170 182 return rc; … … 172 184 173 185 /** 186 * Uninit USB subsystem. 187 */ 188 static int usbProxyFreeBSDFsUnInit(PUSBPROXYDEV pProxyDev) 189 { 190 struct usb_fs_uninit UsbFsUninit; 191 PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD) pProxyDev->Backend.pv; 192 int rc; 193 194 LogFlow(("usbProxyFreeBSDFsUnInit: ProxyDev=%p\n", (void *)pProxyDev)); 195 196 /* Sanity check */ 197 AssertPtrReturn(pDevFBSD, VERR_INVALID_PARAMETER); 198 199 if (pDevFBSD->fInit != true) 200 return VINF_SUCCESS; 201 202 /* Close any open endpoints. */ 203 for (unsigned n = 0; n != USBFBSD_MAXENDPOINTS; n++) 204 usbProxyFreeBSDEndpointClose(pProxyDev, n); 205 206 /* Zero default */ 207 memset(&UsbFsUninit, 0, sizeof(UsbFsUninit)); 208 209 /* Uninit USB subsystem */ 210 rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_UNINIT, &UsbFsUninit, false); 211 if (RT_SUCCESS(rc)) 212 pDevFBSD->fInit = false; 213 214 return rc; 215 } 216 217 /** 174 218 * Setup a USB request packet. 175 219 */ 176 static void usbProxyFreeBSDSetupReq(struct usb_device_request *pSetupData, uint8_t bmRequestType, uint8_t bRequest, 177 uint16_t wValue, uint16_t wIndex, uint16_t wLength) 178 { 179 LogFlow(("usbProxyFreeBSDSetupReq: pSetupData=%p bmRequestType=%#x bRequest=%#x wValue=%#x wIndex=%#x wLength=%#x\n", 180 pSetupData, bmRequestType, bRequest, wValue, wIndex, wLength)); 220 static void usbProxyFreeBSDSetupReq(struct usb_device_request *pSetupData, 221 uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, 222 uint16_t wIndex, uint16_t wLength) 223 { 224 LogFlow(("usbProxyFreeBSDSetupReq: pSetupData=%p bmRequestType=%x " 225 "bRequest=%x wValue=%x wIndex=%x wLength=%x\n", (void *)pSetupData, 226 bmRequestType, bRequest, wValue, wIndex, wLength)); 181 227 182 228 pSetupData->bmRequestType = bmRequestType; 183 pSetupData->bRequest 229 pSetupData->bRequest = bRequest; 184 230 185 231 /* Handle endianess here. Currently no swapping is needed. */ 186 pSetupData->wValue[0] = wValue & 0xff; 187 pSetupData->wValue[1] = (wValue >> 8) & 0xff; 188 pSetupData->wIndex[0] = wIndex & 0xff; 189 pSetupData->wIndex[1] = (wIndex >> 8) & 0xff; 190 pSetupData->wLength[0] = wLength & 0xff; 191 pSetupData->wLength[1] = (wLength >> 8) & 0xff; 192 // pSetupData->wIndex = wIndex; 193 // pSetupData->wLength = wLength; 194 } 195 196 /** 197 * The device has been unplugged. 198 * Cancel all in-flight URBs and put them up for reaping. 199 */ 200 static void usbProxFreeBSDUrbUnplugged(PUSBPROXYDEV pProxyDev) 201 { 202 PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)pProxyDev->Backend.pv; 203 204 /* 205 * Shoot down all flying URBs. 206 */ 207 RTCritSectEnter(&pDevFBSD->CritSect); 208 pProxyDev->fDetached = true; 209 210 #if 0 /** @todo */ 211 PUSBPROXYURBFBSD pUrbTaxing = NULL; 212 PUSBPROXYURBFBSD pUrbFBSD = pDevLnx->pInFlightHead; 213 pDevFBSD->pInFlightHead = NULL; 214 while (pUrbFBSD) 215 { 216 PUSBPROXYURBFBSD pCur = pUrbFBSD; 217 pUrbFBSD = pUrbFBSD->pNext; 218 219 ioctl(pDevFBSD->File, USBDEVFS_DISCARDURB, &pCur->KUrb); 220 if (!pCur->KUrb.status) 221 pCur->KUrb.status = -ENODEV; 222 223 /* insert into the taxing list. */ 224 pCur->pPrev = NULL; 225 if ( !pCur->pSplitHead 226 || pCur == pCur->pSplitHead) 227 { 228 pCur->pNext = pUrbTaxing; 229 if (pUrbTaxing) 230 pUrbTaxing->pPrev = pCur; 231 pUrbTaxing = pCur; 232 } 233 else 234 pCur->pNext = NULL; 235 } 236 237 /* Append the URBs we shot down to the taxing queue. */ 238 if (pUrbTaxing) 239 { 240 pUrbTaxing->pPrev = pDevFBSD->pTaxingTail; 241 if (pUrbTaxing->pPrev) 242 pUrbTaxing->pPrev->pNext = pUrbTaxing; 243 else 244 pDevFBSD->pTaxingTail = pDevFBSD->pTaxingHead = pUrbTaxing; 245 } 246 #endif 247 RTCritSectLeave(&pDevFBSD->CritSect); 248 } 249 250 DECLINLINE(void) usbProxyFreeBSDSetEntryFree(PUSBPROXYDEVFBSD pProxyDev, unsigned iEntry) 251 { 252 pProxyDev->paXferFree[pProxyDev->iXferFreeNextWrite] = iEntry; 253 pProxyDev->iXferFreeNextWrite++; 254 pProxyDev->iXferFreeNextWrite %= (pProxyDev->cXferEndpoints+1); 255 } 256 257 DECLINLINE(unsigned) usbProxyFreeBSDGetEntryFree(PUSBPROXYDEVFBSD pProxyDev) 258 { 259 unsigned iEntry; 260 261 if (pProxyDev->iXferFreeNextWrite != pProxyDev->iXferFreeNextRead) 262 { 263 iEntry = pProxyDev->paXferFree[pProxyDev->iXferFreeNextRead]; 264 pProxyDev->iXferFreeNextRead++; 265 pProxyDev->iXferFreeNextRead %= (pProxyDev->cXferEndpoints+1); 266 } 267 else 268 iEntry = USBPROXY_FREEBSD_NO_ENTRY_FREE; 269 270 return iEntry; 271 } 272 273 static PUSBENDPOINTFBSD usbProxyFreeBSDEndpointOpen(PUSBPROXYDEV pProxyDev, int Endpoint) 274 { 275 LogFlow(("usbProxyFreeBSDEndpointOpen: pProxyDev=%p Endpoint=%d\n", pProxyDev, Endpoint)); 276 277 int EndPtIndex = (Endpoint & USBFBSD_EPADDR_NUM_MASK) + ((Endpoint & USBFBSD_EPADDR_DIR_MASK) ? USBFBSD_MAXENDPOINTS / 2 : 0); 278 PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)pProxyDev->Backend.pv; 279 PUSBENDPOINTFBSD pEndpointFBSD = &pDevFBSD->aEpOpened[EndPtIndex]; 232 pSetupData->wValue[0] = wValue & 0xff; 233 pSetupData->wValue[1] = (wValue >> 8) & 0xff; 234 pSetupData->wIndex[0] = wIndex & 0xff; 235 pSetupData->wIndex[1] = (wIndex >> 8) & 0xff; 236 pSetupData->wLength[0] = wLength & 0xff; 237 pSetupData->wLength[1] = (wLength >> 8) & 0xff; 238 } 239 240 static int usbProxyFreeBSDEndpointOpen(PUSBPROXYDEV pProxyDev, int Endpoint, bool fIsoc, int index) 241 { 242 PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD) pProxyDev->Backend.pv; 243 PUSBENDPOINTFBSD pEndpointFBSD; 280 244 struct usb_fs_endpoint *pXferEndpoint; 281 282 AssertMsg(EndPtIndex < USBFBSD_MAXENDPOINTS, ("Endpoint index exceeds limit %d\n", EndPtIndex)); 283 284 if (!pEndpointFBSD->fOpen) 285 { 286 struct usb_fs_open UsbFsOpen; 287 288 pEndpointFBSD->iEndpoint = usbProxyFreeBSDGetEntryFree(pDevFBSD); 289 if (pEndpointFBSD->iEndpoint == USBPROXY_FREEBSD_NO_ENTRY_FREE) 290 return NULL; 291 292 LogFlow(("usbProxyFreeBSDEndpointOpen: ep_index=%d\n", pEndpointFBSD->iEndpoint)); 293 294 UsbFsOpen.ep_index = pEndpointFBSD->iEndpoint; 295 UsbFsOpen.ep_no = Endpoint; 296 UsbFsOpen.max_bufsize = 256 * _1K; /* Hardcoded assumption about the URBs we get. */ 297 UsbFsOpen.max_frames = 2; 298 299 int rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_OPEN, &UsbFsOpen, true, UINT32_MAX); 300 if (rc) 301 return NULL; 302 303 pEndpointFBSD->fOpen = true; 304 pEndpointFBSD->pXferEndpoint = &pDevFBSD->paXferEndpoints[pEndpointFBSD->iEndpoint]; 305 } 306 else 307 { 308 AssertMsgReturn(!pDevFBSD->paUrbs[pEndpointFBSD->iEndpoint].pUrb, ("Endpoint is busy"), NULL); 309 pEndpointFBSD->pXferEndpoint = &pDevFBSD->paXferEndpoints[pEndpointFBSD->iEndpoint]; 310 } 311 312 return pEndpointFBSD; 313 } 314 245 struct usb_fs_open UsbFsOpen; 246 int rc; 247 248 LogFlow(("usbProxyFreeBSDEndpointOpen: pProxyDev=%p Endpoint=%d\n", 249 (void *)pProxyDev, Endpoint)); 250 251 for (; index < USBFBSD_MAXENDPOINTS; index++) 252 { 253 pEndpointFBSD = &pDevFBSD->aSwEndpoint[index]; 254 if (pEndpointFBSD->fCancelling) 255 continue; 256 if ( pEndpointFBSD->fOpen 257 && !pEndpointFBSD->pUrb 258 && (int)pEndpointFBSD->iEpNum == Endpoint) 259 return index; 260 } 261 262 if (index == USBFBSD_MAXENDPOINTS) 263 { 264 for (index = 0; index != USBFBSD_MAXENDPOINTS; index++) 265 { 266 pEndpointFBSD = &pDevFBSD->aSwEndpoint[index]; 267 if (pEndpointFBSD->fCancelling) 268 continue; 269 if (!pEndpointFBSD->fOpen) 270 break; 271 } 272 if (index == USBFBSD_MAXENDPOINTS) 273 return -1; 274 } 275 /* set ppBuffer and pLength */ 276 277 pXferEndpoint = &pDevFBSD->aHwEndpoint[index]; 278 pXferEndpoint->ppBuffer = &pEndpointFBSD->apvData[0]; 279 pXferEndpoint->pLength = &pEndpointFBSD->acbData[0]; 280 281 LogFlow(("usbProxyFreeBSDEndpointOpen: ep_index=%d ep_num=%d\n", 282 index, Endpoint)); 283 284 memset(&UsbFsOpen, 0, sizeof(UsbFsOpen)); 285 286 UsbFsOpen.ep_index = index; 287 UsbFsOpen.ep_no = Endpoint; 288 UsbFsOpen.max_bufsize = 256 * 1024; 289 /* Hardcoded assumption about the URBs we get. */ 290 291 UsbFsOpen.max_frames = fIsoc ? USBFBSD_MAXFRAMES : 2; 292 293 rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_OPEN, &UsbFsOpen, true); 294 if (RT_FAILURE(rc)) 295 { 296 if (rc == VERR_RESOURCE_BUSY) 297 LogFlow(("usbProxyFreeBSDEndpointOpen: EBUSY\n")); 298 299 return -1; 300 } 301 pEndpointFBSD->fOpen = true; 302 pEndpointFBSD->pUrb = NULL; 303 pEndpointFBSD->iEpNum = Endpoint; 304 pEndpointFBSD->cMaxIo = UsbFsOpen.max_bufsize; 305 pEndpointFBSD->cMaxFrames = UsbFsOpen.max_frames; 306 307 return index; 308 } 309 310 /** 311 * Close an endpoint. 312 * 313 * @returns VBox status code. 314 */ 315 315 static int usbProxyFreeBSDEndpointClose(PUSBPROXYDEV pProxyDev, int Endpoint) 316 316 { 317 LogFlow(("usbProxyFreeBSDEndpointClose: pProxyDev=%p Endpoint=%d\n", pProxyDev, Endpoint)); 318 319 AssertMsg(Endpoint < USBFBSD_MAXENDPOINTS, ("Endpoint index exceeds limit %d\n", Endpoint)); 320 321 int EndPtIndex = (Endpoint & USBFBSD_EPADDR_NUM_MASK) + ((Endpoint & USBFBSD_EPADDR_DIR_MASK) ? USBFBSD_MAXENDPOINTS / 2 : 0); 322 PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)pProxyDev->Backend.pv; 323 PUSBENDPOINTFBSD pEndpointFBSD = &pDevFBSD->aEpOpened[EndPtIndex]; 324 317 PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD) pProxyDev->Backend.pv; 318 PUSBENDPOINTFBSD pEndpointFBSD = &pDevFBSD->aSwEndpoint[Endpoint]; 319 struct usb_fs_close UsbFsClose; 320 int rc = VINF_SUCCESS; 321 322 LogFlow(("usbProxyFreeBSDEndpointClose: pProxyDev=%p Endpoint=%d\n", 323 (void *)pProxyDev, Endpoint)); 324 325 /* check for cancelling */ 326 if (pEndpointFBSD->pUrb != NULL) 327 { 328 pEndpointFBSD->fCancelling = true; 329 pDevFBSD->fCancelling = true; 330 } 331 332 /* check for opened */ 325 333 if (pEndpointFBSD->fOpen) 326 334 { 327 struct usb_fs_close UsbFsClose;328 329 AssertMsgReturn(!pDevFBSD->paUrbs[pEndpointFBSD->iEndpoint].pUrb, ("Endpoint is busy"), NULL);330 331 UsbFsClose.ep_index = pEndpointFBSD->iEndpoint;332 333 int rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_CLOSE, &UsbFsClose, true, UINT32_MAX);334 if (rc)335 {336 LogFlow(("usbProxyFreeBSDEndpointClose: failed rc=%d errno=%Rrc\n", rc, RTErrConvertFromErrno(errno)));337 return RTErrConvertFromErrno(errno);338 }339 340 usbProxyFreeBSDSetEntryFree(pDevFBSD, pEndpointFBSD->iEndpoint);341 335 pEndpointFBSD->fOpen = false; 342 } 343 344 return VINF_SUCCESS; 336 337 /* Zero default */ 338 memset(&UsbFsClose, 0, sizeof(UsbFsClose)); 339 340 /* Set endpoint index */ 341 UsbFsClose.ep_index = Endpoint; 342 343 /* Close endpoint */ 344 rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_CLOSE, &UsbFsClose, true); 345 } 346 return rc; 345 347 } 346 348 … … 357 359 * @param pvBackend Backend specific pointer, unused for the linux backend. 358 360 */ 359 static int usbProxyFreeBSDOpen(PUSBPROXYDEV pProxyDev, const char *pszAddress, void *pvBackend) 360 { 361 static int usbProxyFreeBSDOpen(PUSBPROXYDEV pProxyDev, const char *pszAddress, 362 void *pvBackend) 363 { 364 int rc; 365 361 366 LogFlow(("usbProxyFreeBSDOpen: pProxyDev=%p pszAddress=%s\n", pProxyDev, pszAddress)); 362 367 … … 365 370 */ 366 371 RTFILE File; 367 int rc = RTFileOpen(&File, pszAddress, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); 372 373 rc = RTFileOpen(&File, pszAddress, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); 368 374 if (RT_SUCCESS(rc)) 369 375 { 370 376 /* 371 * Allocate and initialize the linux backend data. 372 */ 373 PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)RTMemAllocZ(sizeof(USBPROXYDEVFBSD)); 377 * Allocate and initialize the linux backend data. 378 */ 379 PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD) 380 RTMemAllocZ(sizeof(USBPROXYDEVFBSD)); 381 374 382 if (pDevFBSD) 375 383 { 376 384 pDevFBSD->File = File; 377 rc = RTCritSectInit(&pDevFBSD->CritSect); 385 pProxyDev->Backend.pv = pDevFBSD; 386 387 rc = usbProxyFreeBSDFsInit(pProxyDev); 378 388 if (RT_SUCCESS(rc)) 379 389 { 380 unsigned cTransfersMax = 127; /* Maximum in the kernel atm. */ 381 382 /* Allocate arrays for data transfers. */ 383 pDevFBSD->paXferEndpoints = (struct usb_fs_endpoint *)RTMemAllocZ(cTransfersMax * sizeof(struct usb_fs_endpoint)); 384 pDevFBSD->paUrbs = (PVUSBURBFBSD)RTMemAllocZ(cTransfersMax * sizeof(VUSBURBFBSD)); 385 pDevFBSD->paXferFree = (unsigned *)RTMemAllocZ((cTransfersMax + 1) * sizeof(unsigned)); 386 pDevFBSD->cXferEndpoints = cTransfersMax; 387 388 if (pDevFBSD->paXferEndpoints && pDevFBSD->paUrbs && pDevFBSD->paXferFree) 389 { 390 /* Initialize the kernel side. */ 391 struct usb_fs_init UsbFsInit; 392 393 UsbFsInit.pEndpoints = pDevFBSD->paXferEndpoints; 394 UsbFsInit.ep_index_max = cTransfersMax; 395 rc = ioctl(File, USB_FS_INIT, &UsbFsInit); 396 if (!rc) 397 { 398 for (unsigned i = 0; i < cTransfersMax; i++) 399 usbProxyFreeBSDSetEntryFree(pDevFBSD, i); 400 401 for (unsigned i= 0; i < USBFBSD_MAXENDPOINTS; i++) 402 pDevFBSD->aEpOpened[i].fOpen = false; 403 404 pProxyDev->Backend.pv = pDevFBSD; 405 406 LogFlow(("usbProxyFreeBSDOpen(%p, %s): returns successfully File=%d iActiveCfg=%d\n", 407 pProxyDev, pszAddress, pDevFBSD->File, pProxyDev->iActiveCfg)); 408 409 return VINF_SUCCESS; 410 } 411 else 412 rc = RTErrConvertFromErrno(errno); 413 } 414 else 415 rc = VERR_NO_MEMORY; 416 417 if (pDevFBSD->paXferEndpoints) 418 RTMemFree(pDevFBSD->paXferEndpoints); 419 if (pDevFBSD->paUrbs) 420 RTMemFree(pDevFBSD->paUrbs); 421 if (pDevFBSD->paXferFree) 422 RTMemFree(pDevFBSD->paXferFree); 390 LogFlow(("usbProxyFreeBSDOpen(%p, %s): returns " 391 "successfully File=%d iActiveCfg=%d\n", 392 pProxyDev, pszAddress, 393 pDevFBSD->File, pProxyDev->iActiveCfg)); 394 395 return VINF_SUCCESS; 423 396 } 424 397 … … 427 400 else 428 401 rc = VERR_NO_MEMORY; 402 429 403 RTFileClose(File); 430 404 } … … 432 406 rc = VERR_VUSB_USBFS_PERMISSION; 433 407 434 Log(("usbProxyFreeBSDOpen(%p, %s) failed, rc=%Rrc!\n", pProxyDev, pszAddress, rc)); 408 Log(("usbProxyFreeBSDOpen(%p, %s) failed, rc=%d!\n", 409 pProxyDev, pszAddress, rc)); 410 435 411 pProxyDev->Backend.pv = NULL; 436 412 437 413 NOREF(pvBackend); 438 414 return rc; 439 440 return VINF_SUCCESS;441 415 } 442 416 … … 451 425 static int usbProxyFreeBSDInit(PUSBPROXYDEV pProxyDev) 452 426 { 453 LogFlow(("usbProxyFreeBSDInit: pProxyDev=%s\n", pProxyDev->pUsbIns->pszName)); 454 PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)pProxyDev->Backend.pv; 427 PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD) pProxyDev->Backend.pv; 428 int rc; 429 430 LogFlow(("usbProxyFreeBSDInit: pProxyDev=%s\n", 431 pProxyDev->pUsbIns->pszName)); 455 432 456 433 /* Retrieve current active configuration. */ 457 int rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_GET_CONFIG, &pProxyDev->iActiveCfg, true, UINT32_MAX); 458 if (RT_FAILURE(rc)) 459 { 434 rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_GET_CONFIG, 435 &pProxyDev->iActiveCfg, true); 436 if (RT_FAILURE(rc) || pProxyDev->iActiveCfg == 255) 437 { 438 pProxyDev->cIgnoreSetConfigs = 0; 460 439 pProxyDev->iActiveCfg = -1; 461 return rc; 440 } 441 else 442 { 443 pProxyDev->cIgnoreSetConfigs = 1; 444 pProxyDev->iActiveCfg++; 462 445 } 463 446 464 447 Log(("usbProxyFreeBSDInit: iActiveCfg=%d\n", pProxyDev->iActiveCfg)); 465 pProxyDev->cIgnoreSetConfigs = 1; 466 pProxyDev->iActiveCfg++; 467 468 return VINF_SUCCESS; 469 } 470 448 449 return rc; 450 } 471 451 472 452 /** … … 475 455 static void usbProxyFreeBSDClose(PUSBPROXYDEV pProxyDev) 476 456 { 457 PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD) pProxyDev->Backend.pv; 458 477 459 LogFlow(("usbProxyFreeBSDClose: pProxyDev=%s\n", pProxyDev->pUsbIns->pszName)); 478 PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)pProxyDev->Backend.pv; 479 Assert(pDevFBSD); 480 if (!pDevFBSD) 481 return; 482 483 RTCritSectDelete(&pDevFBSD->CritSect); 484 485 struct usb_fs_uninit UsbFsUninit; 486 UsbFsUninit.dummy = 0; 487 488 int rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_UNINIT, &UsbFsUninit, false, 1); 489 AssertMsg(!rc, ("Freeing kernel resources failed rc=%Rrc\n", RTErrConvertFromErrno(errno))); 490 491 if (pDevFBSD->paXferEndpoints) 492 RTMemFree(pDevFBSD->paXferEndpoints); 493 if (pDevFBSD->paUrbs) 494 RTMemFree(pDevFBSD->paUrbs); 495 if (pDevFBSD->paXferFree) 496 RTMemFree(pDevFBSD->paXferFree); 460 461 /* sanity check */ 462 AssertPtrReturnVoid(pDevFBSD); 463 464 usbProxyFreeBSDFsUnInit(pProxyDev); 497 465 498 466 RTFileClose(pDevFBSD->File); 467 499 468 pDevFBSD->File = NIL_RTFILE; 500 469 501 470 RTMemFree(pDevFBSD); 471 502 472 pProxyDev->Backend.pv = NULL; 503 473 504 474 LogFlow(("usbProxyFreeBSDClose: returns\n")); 505 475 } 506 507 476 508 477 /** … … 514 483 static int usbProxyFreeBSDReset(PUSBPROXYDEV pProxyDev, bool fResetOnFreeBSD) 515 484 { 516 LogFlow(("usbProxyFreeBSDReset: pProxyDev=%s\n", pProxyDev->pUsbIns->pszName)); 517 PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)pProxyDev->Backend.pv; 518 519 /* Close any open endpoints. */ 520 for (unsigned i = 0; i < USBFBSD_MAXENDPOINTS; i++) 521 usbProxyFreeBSDEndpointClose(pProxyDev, i); 522 523 /* We need to release kernel resources first. */ 524 struct usb_fs_uninit UsbFsUninit; 525 UsbFsUninit.dummy = 0; 526 527 int rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_UNINIT, &UsbFsUninit, false, 1); 528 AssertMsg(!rc, ("Freeing kernel resources failed rc=%Rrc\n", RTErrConvertFromErrno(errno))); 529 530 /* Resetting is not possible from a normal user account */ 531 #if 0 532 int iUnused = 0; 533 rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_DEVICEENUMERATE, &iUnused, true, UINT32_MAX); 534 if (rc) 535 return RTErrConvertFromErrno(errno); 536 #endif 537 538 /* Allocate kernel resources again. */ 539 struct usb_fs_init UsbFsInit; 540 541 UsbFsInit.pEndpoints = pDevFBSD->paXferEndpoints; 542 UsbFsInit.ep_index_max = pDevFBSD->cXferEndpoints; 543 rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_INIT, &UsbFsInit, true, UINT32_MAX); 544 if (!rc) 545 { 546 /* Retrieve current active configuration. */ 547 rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_GET_CONFIG, &pProxyDev->iActiveCfg, true, UINT32_MAX); 548 if (rc) 549 { 550 pProxyDev->iActiveCfg = -1; 551 rc = RTErrConvertFromErrno(errno); 552 } 553 else 554 { 555 pProxyDev->cIgnoreSetConfigs = 2; 556 pProxyDev->iActiveCfg++; 557 } 558 } 559 else 560 rc = RTErrConvertFromErrno(errno); 561 562 Log(("usbProxyFreeBSDReset: iActiveCfg=%d\n", pProxyDev->iActiveCfg)); 485 PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD) pProxyDev->Backend.pv; 486 int iParm; 487 int rc = VINF_SUCCESS; 488 489 LogFlow(("usbProxyFreeBSDReset: pProxyDev=%s\n", 490 pProxyDev->pUsbIns->pszName)); 491 492 if (!fResetOnFreeBSD) 493 goto done; 494 495 /* We need to release kernel ressources first. */ 496 rc = usbProxyFreeBSDFsUnInit(pProxyDev); 497 if (RT_FAILURE(rc)) 498 goto done; 499 500 /* Resetting is only possible as super-user, ignore any failures: */ 501 iParm = 0; 502 rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_DEVICEENUMERATE, &iParm, true); 503 if (RT_FAILURE(rc)) 504 { 505 /* Set the config instead of bus reset */ 506 iParm = 255; 507 rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_SET_CONFIG, &iParm, true); 508 if (RT_SUCCESS(rc)) 509 { 510 iParm = 0; 511 rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_SET_CONFIG, &iParm, true); 512 } 513 } 514 usleep(10000); /* nice it! */ 515 516 /* Allocate kernel ressources again. */ 517 rc = usbProxyFreeBSDFsInit(pProxyDev); 518 if (RT_FAILURE(rc)) 519 goto done; 520 521 /* Retrieve current active configuration. */ 522 rc = usbProxyFreeBSDInit(pProxyDev); 523 524 done: 525 pProxyDev->cIgnoreSetConfigs = 2; 563 526 564 527 return rc; 565 528 } 566 567 529 568 530 /** … … 578 540 static int usbProxyFreeBSDSetConfig(PUSBPROXYDEV pProxyDev, int iCfg) 579 541 { 580 PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)pProxyDev->Backend.pv; 581 582 LogFlow(("usbProxyFreeBSDSetConfig: pProxyDev=%s cfg=%#x\n", 542 PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD) pProxyDev->Backend.pv; 543 int iCfgIndex; 544 int rc; 545 546 LogFlow(("usbProxyFreeBSDSetConfig: pProxyDev=%s cfg=%x\n", 583 547 pProxyDev->pUsbIns->pszName, iCfg)); 584 548 585 /* Close any open endpoints. */ 586 for (unsigned i = 0; i < USBFBSD_MAXENDPOINTS; i++) 587 usbProxyFreeBSDEndpointClose(pProxyDev, i); 588 589 /* We need to release kernel resources first. */ 590 struct usb_fs_uninit UsbFsUninit; 591 UsbFsUninit.dummy = 0; 592 593 int rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_UNINIT, &UsbFsUninit, false, 1); 594 AssertMsg(!rc, ("Freeing kernel resources failed rc=%Rrc\n", RTErrConvertFromErrno(errno))); 595 596 int iCfgIndex = 0; 597 598 /* Get the configuration index matching the value. */ 599 for (iCfgIndex = 0; iCfgIndex < pProxyDev->DevDesc.bNumConfigurations; iCfgIndex++) 600 { 601 if (pProxyDev->paCfgDescs[iCfgIndex].Core.bConfigurationValue == iCfg) 602 break; 603 } 604 605 if (RT_UNLIKELY(iCfgIndex == pProxyDev->DevDesc.bNumConfigurations)) 606 { 607 LogFlow(("usbProxyFreeBSDSetConfig: configuration %d not found\n", iCfg)); 549 /* We need to release kernel ressources first. */ 550 rc = usbProxyFreeBSDFsUnInit(pProxyDev); 551 if (RT_FAILURE(rc)) 552 { 553 LogFlow(("usbProxyFreeBSDSetInterface: Freeing kernel resources " 554 "failed failed rc=%d\n", rc)); 608 555 return false; 609 556 } 610 557 558 if (iCfg == 0) 559 { 560 /* Unconfigure */ 561 iCfgIndex = 255; 562 } 563 else 564 { 565 /* Get the configuration index matching the value. */ 566 for (iCfgIndex = 0; iCfgIndex < pProxyDev->DevDesc.bNumConfigurations; iCfgIndex++) 567 { 568 if (pProxyDev->paCfgDescs[iCfgIndex].Core.bConfigurationValue == iCfg) 569 break; 570 } 571 572 if (iCfgIndex == pProxyDev->DevDesc.bNumConfigurations) 573 { 574 LogFlow(("usbProxyFreeBSDSetConfig: configuration " 575 "%d not found\n", iCfg)); 576 return false; 577 } 578 } 579 611 580 /* Set the config */ 612 rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_SET_CONFIG, &iCfgIndex, true, UINT32_MAX); 613 if (RT_FAILURE(rc)) 614 { 615 LogFlow(("usbProxyFreeBSDSetConfig: setting config index %d failed rc=%d errno=%Rrc\n", iCfgIndex, rc, RTErrConvertFromErrno(errno))); 581 rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_SET_CONFIG, &iCfgIndex, true); 582 if (RT_FAILURE(rc)) 616 583 return false; 617 } 618 619 /* Allocate kernel resources again. */ 620 struct usb_fs_init UsbFsInit; 621 622 UsbFsInit.pEndpoints = pDevFBSD->paXferEndpoints; 623 UsbFsInit.ep_index_max = pDevFBSD->cXferEndpoints; 624 rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_INIT, &UsbFsInit, true, UINT32_MAX); 625 626 627 LogFlow(("usbProxyFreeBSDSetConfig: rc=%d errno=%Rrc\n", rc, RTErrConvertFromErrno(errno))); 628 629 if (!rc) 630 return true; 631 else 584 585 /* Allocate kernel ressources again. */ 586 rc = usbProxyFreeBSDFsInit(pProxyDev); 587 if (RT_FAILURE(rc)) 632 588 return false; 633 } 634 589 590 return true; 591 } 635 592 636 593 /** … … 640 597 static int usbProxyFreeBSDClaimInterface(PUSBPROXYDEV pProxyDev, int iIf) 641 598 { 642 LogFlow(("usbProxyFreeBSDClaimInterface: pProxyDev=%s ifnum=%#x\n", pProxyDev->pUsbIns->pszName, iIf)); 643 644 int rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_CLAIM_INTERFACE, &iIf, true, UINT32_MAX); 599 int rc; 600 601 LogFlow(("usbProxyFreeBSDClaimInterface: pProxyDev=%s " 602 "ifnum=%x\n", pProxyDev->pUsbIns->pszName, iIf)); 603 604 /* 605 * Try to detach kernel driver on this interface, ignore any 606 * failures 607 */ 608 rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_IFACE_DRIVER_DETACH, &iIf, true); 609 610 /* Try to claim interface */ 611 rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_CLAIM_INTERFACE, &iIf, true); 645 612 if (RT_FAILURE(rc)) 646 613 return false; … … 648 615 return true; 649 616 } 650 651 617 652 618 /** … … 656 622 static int usbProxyFreeBSDReleaseInterface(PUSBPROXYDEV pProxyDev, int iIf) 657 623 { 658 LogFlow(("usbProxyFreeBSDReleaseInterface: pProxyDev=%s ifnum=%#x\n", pProxyDev->pUsbIns->pszName, iIf)); 659 660 int rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_RELEASE_INTERFACE, &iIf, true, UINT32_MAX); 624 int rc; 625 626 LogFlow(("usbProxyFreeBSDReleaseInterface: pProxyDev=%s " 627 "ifnum=%x\n", pProxyDev->pUsbIns->pszName, iIf)); 628 629 rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_RELEASE_INTERFACE, &iIf, true); 661 630 if (RT_FAILURE(rc)) 662 631 return false; … … 664 633 return true; 665 634 } 666 667 635 668 636 /** … … 671 639 * @returns success indicator. 672 640 */ 673 static int usbProxyFreeBSDSetInterface(PUSBPROXYDEV pProxyDev, int iIf, int iAlt) 674 { 675 PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)pProxyDev->Backend.pv; 676 677 LogFlow(("usbProxyFreeBSDSetInterface: pProxyDev=%p iIf=%#x iAlt=%#x\n", pProxyDev, iIf, iAlt)); 678 679 /* Close any open endpoints. */ 680 for (unsigned i = 0; i < USBFBSD_MAXENDPOINTS; i++) 681 usbProxyFreeBSDEndpointClose(pProxyDev, i); 682 683 /* We need to release kernel resources first. */ 684 struct usb_fs_uninit UsbFsUninit; 685 UsbFsUninit.dummy = 0; 686 687 int rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_UNINIT, &UsbFsUninit, false, 1); 688 AssertMsg(!rc, ("Freeing kernel resources failed rc=%Rrc\n", RTErrConvertFromErrno(errno))); 689 641 static int 642 usbProxyFreeBSDSetInterface(PUSBPROXYDEV pProxyDev, int iIf, int iAlt) 643 { 644 PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD) pProxyDev->Backend.pv; 690 645 struct usb_alt_interface UsbIntAlt; 646 int rc; 647 648 LogFlow(("usbProxyFreeBSDSetInterface: pProxyDev=%p iIf=%x iAlt=%x\n", 649 pProxyDev, iIf, iAlt)); 650 651 /* We need to release kernel ressources first. */ 652 rc = usbProxyFreeBSDFsUnInit(pProxyDev); 653 if (RT_FAILURE(rc)) 654 { 655 LogFlow(("usbProxyFreeBSDSetInterface: Freeing kernel resources " 656 "failed failed rc=%d\n", rc)); 657 return false; 658 } 659 memset(&UsbIntAlt, 0, sizeof(UsbIntAlt)); 691 660 UsbIntAlt.uai_interface_index = iIf; 692 661 UsbIntAlt.uai_alt_index = iAlt; 693 rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_SET_ALTINTERFACE, &UsbIntAlt, true, UINT32_MAX); 694 if (rc) 695 { 696 LogFlow(("usbProxyFreeBSDSetInterface: Setting interface %d %d failed rc=%d errno=%Rrc\n", iIf, iAlt, rc,RTErrConvertFromErrno(errno))); 662 663 rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_SET_ALTINTERFACE, &UsbIntAlt, true); 664 if (RT_FAILURE(rc)) 665 { 666 LogFlow(("usbProxyFreeBSDSetInterface: Setting interface %d %d " 667 "failed rc=%d\n", iIf, iAlt, rc)); 697 668 return false; 698 669 } 699 670 700 /* Allocate kernel resources again. */ 701 struct usb_fs_init UsbFsInit; 702 703 UsbFsInit.pEndpoints = pDevFBSD->paXferEndpoints; 704 UsbFsInit.ep_index_max = pDevFBSD->cXferEndpoints; 705 rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_INIT, &UsbFsInit, true, UINT32_MAX); 706 707 LogFlow(("usbProxyFreeBSDSetInterface: rc=%d errno=%Rrc\n", rc, RTErrConvertFromErrno(errno))); 708 709 if (!rc) 671 rc = usbProxyFreeBSDFsInit(pProxyDev); 672 if (RT_FAILURE(rc)) 673 return false; 674 675 return true; 676 } 677 678 /** 679 * Clears the halted endpoint 'ep_num'. 680 */ 681 static bool usbProxyFreeBSDClearHaltedEp(PUSBPROXYDEV pProxyDev, unsigned int ep_num) 682 { 683 struct usb_ctl_request Req; 684 int rc; 685 686 LogFlow(("usbProxyFreeBSDClearHaltedEp: pProxyDev=%s ep_num=%u\n", 687 pProxyDev->pUsbIns->pszName, ep_num)); 688 689 /* 690 * Clearing the zero control pipe doesn't make sense. 691 * Just ignore it. 692 */ 693 if ((ep_num & 0xF) == 0) 710 694 return true; 711 else 695 696 memset(&Req, 0, sizeof(Req)); 697 698 usbProxyFreeBSDSetupReq(&Req.ucr_request, 699 VUSB_DIR_TO_DEV | VUSB_TO_ENDPOINT, 700 VUSB_REQ_CLEAR_FEATURE, 0, ep_num, 0); 701 702 rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_DO_REQUEST, &Req, true); 703 704 LogFlow(("usbProxyFreeBSDClearHaltedEp: rc=%Rrc\n", rc)); 705 706 if (RT_FAILURE(rc)) 712 707 return false; 713 }714 715 716 /**717 * Clears the halted endpoint 'EndPt'.718 */719 static bool usbProxyFreeBSDClearHaltedEp(PUSBPROXYDEV pProxyDev, unsigned int EndPt)720 {721 LogFlow(("usbProxyFreeBSDClearHaltedEp: pProxyDev=%s EndPt=%u\n", pProxyDev->pUsbIns->pszName, EndPt));722 723 /*724 * Clearing the zero control pipe doesn't make sense. Just ignore it.725 */726 if (EndPt == 0)727 return true;728 729 struct usb_ctl_request Req;730 731 memset(&Req, 0, sizeof(struct usb_ctl_request));732 usbProxyFreeBSDSetupReq(&Req.ucr_request, VUSB_DIR_TO_DEV | VUSB_TO_ENDPOINT, VUSB_REQ_CLEAR_FEATURE, 0, EndPt, 0);733 734 int rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_DO_REQUEST, &Req, true, 1);735 if (rc)736 {737 LogFlow(("usbProxyFreeBSDClearHaltedEp: failed rc=%d errno=%Rrc\n", rc, RTErrConvertFromErrno(errno)));738 return false;739 }740 741 LogFlow(("usbProxyFreeBSDClearHaltedEp: succeeded\n"));742 708 743 709 return true; 744 710 } 745 711 746 747 712 /** 748 713 * @copydoc USBPROXYBACK::pfnUrbQueue … … 751 716 { 752 717 PUSBPROXYDEV pProxyDev = PDMINS_2_DATA(pUrb->pUsbIns, PUSBPROXYDEV); 753 PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)pProxyDev->Backend.pv; 754 755 LogFlow(("usbProxyFreeBSDUrbQueue: pUrb=%p\n", pUrb)); 756 757 uint8_t EndPt = pUrb->EndPt; 758 if (pUrb->EndPt) 759 EndPt = pUrb->EndPt | (pUrb->enmDir == VUSBDIRECTION_IN ? 0x80 : 0); 760 761 PUSBENDPOINTFBSD pEndpointFBSD = usbProxyFreeBSDEndpointOpen(pProxyDev, EndPt); 762 if (!pEndpointFBSD) 763 return false; 764 765 PVUSBURBFBSD pUrbFBSD = &pDevFBSD->paUrbs[pEndpointFBSD->iEndpoint]; 766 AssertMsg(!pUrbFBSD->pUrb, ("Assigned entry is busy\n")); 767 pUrbFBSD->pUrb = pUrb; 768 718 PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD) pProxyDev->Backend.pv; 719 PUSBENDPOINTFBSD pEndpointFBSD; 720 struct usb_fs_endpoint *pXferEndpoint; 769 721 struct usb_fs_start UsbFsStart; 770 722 unsigned cFrames; 771 772 if (pUrb->enmType == VUSBXFERTYPE_MSG) 773 { 774 PVUSBSETUP pSetup = (PVUSBSETUP)&pUrb->abData[0]; 775 776 pUrbFBSD->apvData[0] = pSetup; 777 pUrbFBSD->acbData[0] = sizeof(VUSBSETUP); 778 779 if (pSetup->wLength) 780 { 781 pUrbFBSD->apvData[1] = &pUrb->abData[sizeof(VUSBSETUP)]; 782 pUrbFBSD->acbData[1] = pSetup->wLength; 783 cFrames = 2; 784 } 785 else 723 uint8_t *pbData; 724 int index; 725 int ep_num; 726 int rc; 727 728 LogFlow(("usbProxyFreeBSDUrbQueue: pUrb=%p EndPt=%u Dir=%u\n", 729 pUrb, (unsigned)pUrb->EndPt, (unsigned)pUrb->enmDir)); 730 731 ep_num = pUrb->EndPt; 732 733 if ((pUrb->enmType != VUSBXFERTYPE_MSG) && (pUrb->enmDir == VUSBDIRECTION_IN)) 734 ep_num |= 0x80; 735 736 index = 0; 737 738 retry: 739 740 index = usbProxyFreeBSDEndpointOpen(pProxyDev, ep_num, 741 (pUrb->enmType == VUSBXFERTYPE_ISOC), 742 index); 743 744 if (index < 0) 745 return false; 746 747 pEndpointFBSD = &pDevFBSD->aSwEndpoint[index]; 748 pXferEndpoint = &pDevFBSD->aHwEndpoint[index]; 749 750 pbData = pUrb->abData; 751 752 switch (pUrb->enmType) 753 { 754 case VUSBXFERTYPE_MSG: 755 { 756 pEndpointFBSD->apvData[0] = pbData; 757 pEndpointFBSD->acbData[0] = 8; 758 759 /* check wLength */ 760 if (pbData[6] || pbData[7]) 761 { 762 pEndpointFBSD->apvData[1] = pbData + 8; 763 pEndpointFBSD->acbData[1] = pbData[6] | (pbData[7] << 8); 764 cFrames = 2; 765 } 766 else 767 { 768 pEndpointFBSD->apvData[1] = NULL; 769 pEndpointFBSD->acbData[1] = 0; 770 cFrames = 1; 771 } 772 773 LogFlow(("usbProxyFreeBSDUrbQueue: pUrb->cbData=%u, 0x%02x, " 774 "0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", 775 pUrb->cbData, pbData[0], pbData[1], pbData[2], pbData[3], 776 pbData[4], pbData[5], pbData[6], pbData[7])); 777 778 pXferEndpoint->timeout = USB_FS_TIMEOUT_NONE; 779 pXferEndpoint->flags = USB_FS_FLAG_MULTI_SHORT_OK; 780 break; 781 } 782 case VUSBXFERTYPE_ISOC: 783 { 784 unsigned i; 785 786 for (i = 0; i < pUrb->cIsocPkts; i++) 787 { 788 if (i >= pEndpointFBSD->cMaxFrames) 789 break; 790 pEndpointFBSD->apvData[i] = pbData + pUrb->aIsocPkts[i].off; 791 pEndpointFBSD->acbData[i] = pUrb->aIsocPkts[i].cb; 792 } 793 /* Timeout handling will be done during reap. */ 794 pXferEndpoint->timeout = USB_FS_TIMEOUT_NONE; 795 pXferEndpoint->flags = USB_FS_FLAG_MULTI_SHORT_OK; 796 cFrames = i; 797 break; 798 } 799 default: 800 { 801 pEndpointFBSD->apvData[0] = pbData; 802 pEndpointFBSD->cbData0 = pUrb->cbData; 803 804 /* XXX maybe we have to loop */ 805 if (pUrb->cbData > pEndpointFBSD->cMaxIo) 806 pEndpointFBSD->acbData[0] = pEndpointFBSD->cMaxIo; 807 else 808 pEndpointFBSD->acbData[0] = pUrb->cbData; 809 810 /* Timeout handling will be done during reap. */ 811 pXferEndpoint->timeout = USB_FS_TIMEOUT_NONE; 812 pXferEndpoint->flags = pUrb->fShortNotOk ? 0 : USB_FS_FLAG_MULTI_SHORT_OK; 786 813 cFrames = 1; 787 } 788 else 789 { 790 pUrbFBSD->apvData[0] = &pUrb->abData[0]; 791 pUrbFBSD->acbData[0] = pUrb->cbData; 792 cFrames = 1; 793 } 794 795 struct usb_fs_endpoint *pXferEndpoint = pEndpointFBSD->pXferEndpoint; 796 pXferEndpoint->ppBuffer = &pUrbFBSD->apvData[0]; 797 pXferEndpoint->pLength = &pUrbFBSD->acbData[0]; 798 pXferEndpoint->nFrames = cFrames; 799 pXferEndpoint->timeout = USB_FS_TIMEOUT_NONE; /* Timeout handling will be done during reap. */ 800 pXferEndpoint->flags = pUrb->fShortNotOk ? 0 : USB_FS_FLAG_MULTI_SHORT_OK; 814 break; 815 } 816 } 817 818 /* store number of frames */ 819 pXferEndpoint->nFrames = cFrames; 820 821 /* zero-default */ 822 memset(&UsbFsStart, 0, sizeof(UsbFsStart)); 801 823 802 824 /* Start the transfer */ 803 UsbFsStart.ep_index = pEndpointFBSD->iEndpoint; 804 int rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_START, &UsbFsStart, true, UINT32_MAX); 805 806 LogFlow(("usbProxyFreeBSDUrbQueue: USB_FS_START returned rc=%d errno=%Rrc\n", rc, RTErrConvertFromErrno(errno))); 807 if (rc) 808 { 825 UsbFsStart.ep_index = index; 826 827 rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_START, &UsbFsStart, true); 828 829 LogFlow(("usbProxyFreeBSDUrbQueue: USB_FS_START returned rc=%d " 830 "len[0]=%u len[1]=%u cbData=%u index=%u ep_num=%u\n", rc, 831 (unsigned)pEndpointFBSD->acbData[0], 832 (unsigned)pEndpointFBSD->acbData[1], 833 (unsigned)pUrb->cbData, 834 (unsigned)index, (unsigned)ep_num)); 835 836 if (RT_FAILURE(rc)) 837 { 838 if (rc == VERR_RESOURCE_BUSY) 839 { 840 index++; 841 goto retry; 842 } 809 843 return false; 810 844 } 845 pUrb->Dev.pvPrivate = (void *)(long)(index + 1); 846 pEndpointFBSD->pUrb = pUrb; 811 847 812 848 return true; 813 849 } 814 815 850 816 851 /** … … 824 859 static PVUSBURB usbProxyFreeBSDUrbReap(PUSBPROXYDEV pProxyDev, RTMSINTERVAL cMillies) 825 860 { 826 PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)pProxyDev->Backend.pv;827 828 LogFlow(("usbProxyFreeBSDUrbReap: cMillies=%u\n", cMillies));829 830 /* We will poll for finished urbs because the ioctl doesn't take a timeout parameter. */861 struct usb_fs_endpoint *pXferEndpoint; 862 PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD) pProxyDev->Backend.pv; 863 PUSBENDPOINTFBSD pEndpointFBSD; 864 PVUSBURB pUrb; 865 struct usb_fs_complete UsbFsComplete; 831 866 struct pollfd PollFd; 832 PVUSBURB pUrb = NULL; 833 834 PollFd.fd = (int)pDevFBSD->File; 835 PollFd.events = POLLIN | POLLRDNORM | POLLOUT; 836 PollFd.revents = 0; 837 838 struct usb_fs_complete UsbFsComplete; 839 840 UsbFsComplete.ep_index = 0; 841 842 int rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_COMPLETE, &UsbFsComplete, true, UINT32_MAX); 843 if (!rc) 844 { 845 struct usb_fs_endpoint *pXferEndpoint = &pDevFBSD->paXferEndpoints[UsbFsComplete.ep_index]; 846 PVUSBURBFBSD pUrbFBSD = &pDevFBSD->paUrbs[UsbFsComplete.ep_index]; 847 848 LogFlow(("Reaped URB %#p\n", pUrbFBSD->pUrb)); 849 850 pUrb = pUrbFBSD->pUrb; 851 AssertMsg(pUrb, ("No URB handle for the completed entry\n")); 852 pUrbFBSD->pUrb = NULL; 867 int rc; 868 869 LogFlow(("usbProxyFreeBSDUrbReap: pProxyDev=%p, cMillies=%u\n", 870 pProxyDev, cMillies)); 871 872 repeat: 873 874 pUrb = NULL; 875 876 /* check for cancelled transfers */ 877 if (pDevFBSD->fCancelling) 878 { 879 for (unsigned n = 0; n < USBFBSD_MAXENDPOINTS; n++) 880 { 881 pEndpointFBSD = &pDevFBSD->aSwEndpoint[n]; 882 if (pEndpointFBSD->fCancelling) 883 { 884 pEndpointFBSD->fCancelling = false; 885 pUrb = pEndpointFBSD->pUrb; 886 pEndpointFBSD->pUrb = NULL; 887 888 if (pUrb != NULL) 889 break; 890 } 891 } 892 893 if (pUrb != NULL) 894 { 895 pUrb->enmStatus = VUSBSTATUS_INVALID; 896 pUrb->Dev.pvPrivate = NULL; 897 898 switch (pUrb->enmType) 899 { 900 case VUSBXFERTYPE_MSG: 901 pUrb->cbData = 0; 902 break; 903 case VUSBXFERTYPE_ISOC: 904 pUrb->cbData = 0; 905 for (int n = 0; n < (int)pUrb->cIsocPkts; n++) 906 pUrb->aIsocPkts[n].cb = 0; 907 break; 908 default: 909 pUrb->cbData = 0; 910 break; 911 } 912 return pUrb; 913 } 914 pDevFBSD->fCancelling = false; 915 } 916 /* Zero default */ 917 918 memset(&UsbFsComplete, 0, sizeof(UsbFsComplete)); 919 920 /* Check if any endpoints are complete */ 921 rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_COMPLETE, &UsbFsComplete, true); 922 if (RT_SUCCESS(rc)) 923 { 924 pXferEndpoint = &pDevFBSD->aHwEndpoint[UsbFsComplete.ep_index]; 925 pEndpointFBSD = &pDevFBSD->aSwEndpoint[UsbFsComplete.ep_index]; 926 927 LogFlow(("usbProxyFreeBSDUrbReap: Reaped " 928 "URB %#p\n", pEndpointFBSD->pUrb)); 929 930 if (pXferEndpoint->status == USB_ERR_CANCELLED) 931 goto repeat; 932 933 pUrb = pEndpointFBSD->pUrb; 934 pEndpointFBSD->pUrb = NULL; 935 if (pUrb == NULL) 936 goto repeat; 853 937 854 938 switch (pXferEndpoint->status) … … 861 945 break; 862 946 default: 863 AssertMsgFailed(("Unexpected status code %d\n", pXferEndpoint->status)); 864 } 865 } 866 else 867 { 868 869 rc = poll(&PollFd, 1, cMillies == RT_INDEFINITE_WAIT ? INFTIM : cMillies); 870 if (rc == 1) 871 { 872 // do 947 pUrb->enmStatus = VUSBSTATUS_INVALID; 948 break; 949 } 950 951 pUrb->Dev.pvPrivate = NULL; 952 953 switch (pUrb->enmType) 954 { 955 case VUSBXFERTYPE_MSG: 956 pUrb->cbData = pEndpointFBSD->acbData[0] + pEndpointFBSD->acbData[1]; 957 break; 958 case VUSBXFERTYPE_ISOC: 873 959 { 874 UsbFsComplete.ep_index = 0; 875 rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_COMPLETE, &UsbFsComplete, true, UINT32_MAX); 876 if (!rc) 960 int n; 961 962 if (pUrb->enmDir == VUSBDIRECTION_OUT) 963 break; 964 pUrb->cbData = 0; 965 for (n = 0; n < (int)pUrb->cIsocPkts; n++) 877 966 { 878 struct usb_fs_endpoint *pXferEndpoint = &pDevFBSD->paXferEndpoints[UsbFsComplete.ep_index]; 879 PVUSBURBFBSD pUrbFBSD = &pDevFBSD->paUrbs[UsbFsComplete.ep_index]; 880 881 LogFlow(("Reaped URB %#p\n", pUrbFBSD->pUrb)); 882 883 pUrb = pUrbFBSD->pUrb; 884 AssertMsg(pUrb, ("No URB handle for the completed entry\n")); 885 pUrbFBSD->pUrb = NULL; 886 887 switch (pXferEndpoint->status) 888 { 889 case USB_ERR_NORMAL_COMPLETION: 890 pUrb->enmStatus = VUSBSTATUS_OK; 891 break; 892 case USB_ERR_STALLED: 893 pUrb->enmStatus = VUSBSTATUS_STALL; 894 break; 895 default: 896 AssertMsgFailed(("Unexpected status code %d\n", pXferEndpoint->status)); 897 } 898 899 rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_COMPLETE, &UsbFsComplete, true, UINT32_MAX); 900 AssertMsg(((rc == -1) && (errno == EBUSY)), ("Expected return value rc=%d rc=%Rrc\n", rc, RTErrConvertFromErrno(errno))); 967 if (n >= (int)pEndpointFBSD->cMaxFrames) 968 break; 969 pUrb->cbData += pEndpointFBSD->acbData[n]; 970 pUrb->aIsocPkts[n].cb = pEndpointFBSD->acbData[n]; 901 971 } 902 else 903 LogFlow(("couldn't get completed URB rc=%Rrc\n", RTErrConvertFromErrno(errno))); 972 for (; n < (int)pUrb->cIsocPkts; n++) 973 pUrb->aIsocPkts[n].cb = 0; 974 975 break; 904 976 } 905 // while (!rc); 977 default: 978 pUrb->cbData = pEndpointFBSD->acbData[0]; 979 break; 980 } 981 982 LogFlow(("usbProxyFreeBSDUrbReap: Status=%d epindex=%u " 983 "len[0]=%d len[1]=%d\n", 984 (int)pXferEndpoint->status, 985 (unsigned)UsbFsComplete.ep_index, 986 (unsigned)pEndpointFBSD->acbData[0], 987 (unsigned)pEndpointFBSD->acbData[1])); 988 989 } 990 else if (cMillies && rc == VERR_RESOURCE_BUSY) 991 { 992 /* Poll for finished transfers */ 993 PollFd.fd = (int)pDevFBSD->File; 994 PollFd.events = POLLIN | POLLRDNORM; 995 PollFd.revents = 0; 996 997 rc = poll(&PollFd, 1, (cMillies == RT_INDEFINITE_WAIT) ? INFTIM : cMillies); 998 if (rc >= 1) 999 { 1000 goto repeat; 906 1001 } 907 1002 else 908 LogFlow(("poll returned rc=%d rcRT=%Rrc\n", rc, rc < 0 ? RTErrConvertFromErrno(errno) : VERR_TIMEOUT)); 909 } 910 1003 { 1004 LogFlow(("usbProxyFreeBSDUrbReap: " 1005 "poll returned rc=%d\n", rc)); 1006 } 1007 } 911 1008 return pUrb; 912 1009 } 913 914 1010 915 1011 /** … … 920 1016 { 921 1017 PUSBPROXYDEV pProxyDev = PDMINS_2_DATA(pUrb->pUsbIns, PUSBPROXYDEV); 922 PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)pProxyDev->Backend.pv; 923 924 925 } 926 1018 int index; 1019 1020 index = (int)(long)pUrb->Dev.pvPrivate - 1; 1021 1022 if (index < 0 || index >= USBFBSD_MAXENDPOINTS) 1023 return; 1024 1025 LogFlow(("usbProxyFreeBSDUrbCancel: epindex=%u\n", (unsigned)index)); 1026 1027 usbProxyFreeBSDEndpointClose(pProxyDev, index); 1028 } 927 1029 928 1030 /** … … 947 1049 }; 948 1050 949 950 1051 /* 951 1052 * Local Variables:
Note:
See TracChangeset
for help on using the changeset viewer.