- Timestamp:
- Aug 20, 2018 10:27:35 AM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 124458
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/USB/linux/USBProxyDevice-linux.cpp
r69500 r73775 133 133 /** This split element is reaped. */ 134 134 bool fSplitElementReaped; 135 /** This URB was discarded. */ 136 bool fDiscarded; 135 137 /** Size to transfer in remaining fragments of a split URB */ 136 138 uint32_t cbSplitRemaining; … … 152 154 * Only the split head will appear in this list. (USBPROXYURBLNX) */ 153 155 RTLISTANCHOR ListInFlight; 154 /** The list of landed linux URBs. Doubly linked.155 * Only the split head will appear in this list. (USBPROXYURBLNX) */156 RTLISTANCHOR ListTaxing;157 156 /** Are we using sysfs to find the active configuration? */ 158 157 bool fUsingSysfs; … … 240 239 RTListForEachSafe(&pDevLnx->ListInFlight, pUrbLnx, pUrbLnxNext, USBPROXYURBLNX, NodeList) 241 240 { 242 RTListNodeRemove(&pUrbLnx->NodeList); 243 244 ioctl(RTFileToNative(pDevLnx->hFile), USBDEVFS_DISCARDURB, &pUrbLnx->KUrb); /* not sure if this is required.. */ 245 if (!pUrbLnx->KUrb.status) 246 pUrbLnx->KUrb.status = -ENODEV; 247 248 /* insert into the taxing list. */ 249 if ( !pUrbLnx->pSplitHead 250 || pUrbLnx == pUrbLnx->pSplitHead) 251 RTListAppend(&pDevLnx->ListTaxing, &pUrbLnx->NodeList); 241 if (!pUrbLnx->fDiscarded) 242 { 243 pUrbLnx->fDiscarded = true; 244 /* Cancel the URB. It will be reaped normally. */ 245 ioctl(RTFileToNative(pDevLnx->hFile), USBDEVFS_DISCARDURB, &pUrbLnx->KUrb); 246 if (!pUrbLnx->KUrb.status) 247 pUrbLnx->KUrb.status = -ENODEV; 248 } 252 249 } 253 250 … … 354 351 pUrbLnx->fCanceledBySubmit = false; 355 352 pUrbLnx->fSplitElementReaped = false; 353 pUrbLnx->fDiscarded = false; 356 354 LogFlowFunc(("returns pUrbLnx=%p\n", pUrbLnx)); 357 355 return pUrbLnx; … … 670 668 RTListInit(&pDevLnx->ListFree); 671 669 RTListInit(&pDevLnx->ListInFlight); 672 RTListInit(&pDevLnx->ListTaxing);673 670 pDevLnx->pszPath = RTStrDupN(pszPath, cchPath); 674 671 if (pDevLnx->pszPath) … … 1674 1671 PUSBPROXYDEVLNX pDevLnx = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVLNX); 1675 1672 1676 /* 1677 * Any URBs pending delivery? 1678 */ 1679 if (!RTListIsEmpty(&pDevLnx->ListTaxing)) 1680 { 1681 RTCritSectEnter(&pDevLnx->CritSect); 1682 pUrbLnx = RTListGetFirst(&pDevLnx->ListTaxing, USBPROXYURBLNX, NodeList); 1683 if (pUrbLnx) 1684 { 1685 /* unlink from the pending delivery list */ 1686 RTListNodeRemove(&pUrbLnx->NodeList); 1687 1688 /* temporarily into the active list, so free works right. */ 1689 RTListAppend(&pDevLnx->ListInFlight, &pUrbLnx->NodeList); 1690 } 1691 RTCritSectLeave(&pDevLnx->CritSect); 1692 } 1693 if (!pUrbLnx) 1694 { 1695 /* 1696 * Block for requested period. 1697 * 1698 * It seems to me that the path of poll() is shorter and 1699 * involves less semaphores than ioctl() on usbfs. So, we'll 1700 * do a poll regardless of whether cMillies == 0 or not. 1701 */ 1702 if (cMillies) 1703 { 1704 int cMilliesWait = cMillies == RT_INDEFINITE_WAIT ? -1 : cMillies; 1705 1706 for (;;) 1673 /* 1674 * Block for requested period. 1675 * 1676 * It seems to me that the path of poll() is shorter and 1677 * involves less semaphores than ioctl() on usbfs. So, we'll 1678 * do a poll regardless of whether cMillies == 0 or not. 1679 */ 1680 if (cMillies) 1681 { 1682 int cMilliesWait = cMillies == RT_INDEFINITE_WAIT ? -1 : cMillies; 1683 1684 for (;;) 1685 { 1686 struct pollfd pfd[2]; 1687 pfd[0].fd = RTFileToNative(pDevLnx->hFile); 1688 pfd[0].events = POLLOUT | POLLWRNORM /* completed async */ 1689 | POLLERR | POLLHUP /* disconnected */; 1690 pfd[0].revents = 0; 1691 1692 pfd[1].fd = RTPipeToNative(pDevLnx->hPipeWakeupR); 1693 pfd[1].events = POLLIN | POLLHUP; 1694 pfd[1].revents = 0; 1695 1696 int rc = poll(&pfd[0], 2, cMilliesWait); 1697 Log(("usbProxyLinuxUrbReap: poll rc = %d\n", rc)); 1698 if (rc >= 1) 1707 1699 { 1708 struct pollfd pfd[2]; 1709 pfd[0].fd = RTFileToNative(pDevLnx->hFile); 1710 pfd[0].events = POLLOUT | POLLWRNORM /* completed async */ 1711 | POLLERR | POLLHUP /* disconnected */; 1712 pfd[0].revents = 0; 1713 1714 pfd[1].fd = RTPipeToNative(pDevLnx->hPipeWakeupR); 1715 pfd[1].events = POLLIN | POLLHUP; 1716 pfd[1].revents = 0; 1717 1718 int rc = poll(&pfd[0], 2, cMilliesWait); 1719 Log(("usbProxyLinuxUrbReap: poll rc = %d\n", rc)); 1720 if (rc >= 1) 1700 /* If the pipe caused the return drain it. */ 1701 if (pfd[1].revents & POLLIN) 1721 1702 { 1722 /* If the pipe caused the return drain it. */ 1723 if (pfd[1].revents & POLLIN) 1724 { 1725 uint8_t bRead; 1726 size_t cbIgnored = 0; 1727 RTPipeRead(pDevLnx->hPipeWakeupR, &bRead, 1, &cbIgnored); 1728 } 1703 uint8_t bRead; 1704 size_t cbIgnored = 0; 1705 RTPipeRead(pDevLnx->hPipeWakeupR, &bRead, 1, &cbIgnored); 1706 } 1707 break; 1708 } 1709 if (rc >= 0) 1710 return NULL; 1711 1712 if (errno != EAGAIN) 1713 { 1714 Log(("usb-linux: Reap URB - poll -> %d errno=%d pProxyDev=%s\n", rc, errno, usbProxyGetName(pProxyDev))); 1715 return NULL; 1716 } 1717 Log(("usbProxyLinuxUrbReap: poll again - weird!!!\n")); 1718 } 1719 } 1720 1721 /* 1722 * Reap URBs, non-blocking. 1723 */ 1724 for (;;) 1725 { 1726 struct usbdevfs_urb *pKUrb; 1727 while (ioctl(RTFileToNative(pDevLnx->hFile), USBDEVFS_REAPURBNDELAY, &pKUrb)) 1728 if (errno != EINTR) 1729 { 1730 if (errno == ENODEV) 1731 usbProxLinuxUrbUnplugged(pProxyDev); 1732 else 1733 Log(("usb-linux: Reap URB. errno=%d pProxyDev=%s\n", errno, usbProxyGetName(pProxyDev))); 1734 return NULL; 1735 } 1736 pUrbLnx = (PUSBPROXYURBLNX)pKUrb; 1737 1738 /* split list: Is the entire split list done yet? */ 1739 if (pUrbLnx->pSplitHead) 1740 { 1741 pUrbLnx->fSplitElementReaped = true; 1742 1743 /* for variable size URBs, we may need to queue more if the just-reaped URB was completely filled */ 1744 if (pUrbLnx->cbSplitRemaining && (pKUrb->actual_length == pKUrb->buffer_length) && !pUrbLnx->pSplitNext) 1745 { 1746 bool fUnplugged = false; 1747 bool fSucceeded; 1748 1749 Assert(pUrbLnx->pSplitHead); 1750 Assert((pKUrb->endpoint & 0x80) && !(pKUrb->flags & USBDEVFS_URB_SHORT_NOT_OK)); 1751 PUSBPROXYURBLNX pNew = usbProxyLinuxSplitURBFragment(pProxyDev, pUrbLnx->pSplitHead, pUrbLnx); 1752 if (!pNew) 1753 { 1754 Log(("usb-linux: Allocating URB fragment failed. errno=%d pProxyDev=%s\n", errno, usbProxyGetName(pProxyDev))); 1755 return NULL; 1756 } 1757 PVUSBURB pUrb = (PVUSBURB)pUrbLnx->KUrb.usercontext; 1758 fSucceeded = usbProxyLinuxSubmitURB(pProxyDev, pNew, pUrb, &fUnplugged); 1759 if (fUnplugged) 1760 usbProxLinuxUrbUnplugged(pProxyDev); 1761 if (!fSucceeded) 1762 return NULL; 1763 continue; /* try reaping another URB */ 1764 } 1765 PUSBPROXYURBLNX pCur; 1766 for (pCur = pUrbLnx->pSplitHead; pCur; pCur = pCur->pSplitNext) 1767 if (!pCur->fSplitElementReaped) 1768 { 1769 pUrbLnx = NULL; 1729 1770 break; 1730 1771 } 1731 if (rc >= 0) 1732 return NULL; 1733 1734 if (errno != EAGAIN) 1735 { 1736 Log(("usb-linux: Reap URB - poll -> %d errno=%d pProxyDev=%s\n", rc, errno, usbProxyGetName(pProxyDev))); 1737 return NULL; 1738 } 1739 Log(("usbProxyLinuxUrbReap: poll again - weird!!!\n")); 1740 } 1741 } 1742 1743 /* 1744 * Reap URBs, non-blocking. 1745 */ 1746 for (;;) 1747 { 1748 struct usbdevfs_urb *pKUrb; 1749 while (ioctl(RTFileToNative(pDevLnx->hFile), USBDEVFS_REAPURBNDELAY, &pKUrb)) 1750 if (errno != EINTR) 1751 { 1752 if (errno == ENODEV) 1753 usbProxLinuxUrbUnplugged(pProxyDev); 1754 else 1755 Log(("usb-linux: Reap URB. errno=%d pProxyDev=%s\n", errno, usbProxyGetName(pProxyDev))); 1756 return NULL; 1757 } 1758 pUrbLnx = (PUSBPROXYURBLNX)pKUrb; 1759 1760 /* split list: Is the entire split list done yet? */ 1761 if (pUrbLnx->pSplitHead) 1762 { 1763 pUrbLnx->fSplitElementReaped = true; 1764 1765 /* for variable size URBs, we may need to queue more if the just-reaped URB was completely filled */ 1766 if (pUrbLnx->cbSplitRemaining && (pKUrb->actual_length == pKUrb->buffer_length) && !pUrbLnx->pSplitNext) 1767 { 1768 bool fUnplugged = false; 1769 bool fSucceeded; 1770 1771 Assert(pUrbLnx->pSplitHead); 1772 Assert((pKUrb->endpoint & 0x80) && !(pKUrb->flags & USBDEVFS_URB_SHORT_NOT_OK)); 1773 PUSBPROXYURBLNX pNew = usbProxyLinuxSplitURBFragment(pProxyDev, pUrbLnx->pSplitHead, pUrbLnx); 1774 if (!pNew) 1775 { 1776 Log(("usb-linux: Allocating URB fragment failed. errno=%d pProxyDev=%s\n", errno, usbProxyGetName(pProxyDev))); 1777 return NULL; 1778 } 1779 PVUSBURB pUrb = (PVUSBURB)pUrbLnx->KUrb.usercontext; 1780 fSucceeded = usbProxyLinuxSubmitURB(pProxyDev, pNew, pUrb, &fUnplugged); 1781 if (fUnplugged) 1782 usbProxLinuxUrbUnplugged(pProxyDev); 1783 if (!fSucceeded) 1784 return NULL; 1785 continue; /* try reaping another URB */ 1786 } 1787 PUSBPROXYURBLNX pCur; 1788 for (pCur = pUrbLnx->pSplitHead; pCur; pCur = pCur->pSplitNext) 1789 if (!pCur->fSplitElementReaped) 1790 { 1791 pUrbLnx = NULL; 1792 break; 1793 } 1794 if (!pUrbLnx) 1795 continue; 1796 pUrbLnx = pUrbLnx->pSplitHead; 1797 } 1798 break; 1799 } 1772 if (!pUrbLnx) 1773 continue; 1774 pUrbLnx = pUrbLnx->pSplitHead; 1775 } 1776 break; 1800 1777 } 1801 1778
Note:
See TracChangeset
for help on using the changeset viewer.