/** * SET_INTERFACE. * * @returns success indicator. */ static DECLCALLBACK(int) usbProxyFreeBSDSetInterface(PUSBPROXYDEV pProxyDev, int iIf, int iAlt) { PUSBPROXYDEVFBSD pDevFBSD = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVFBSD); struct usb_alt_interface UsbIntAlt; int rc; LogFlow(("usbProxyFreeBSDSetInterface: pProxyDev=%p iIf=%x iAlt=%x\n", pProxyDev, iIf, iAlt)); /* We need to release kernel ressources first. */ rc = usbProxyFreeBSDFsUnInit(pProxyDev); if (RT_FAILURE(rc)) { LogFlow(("usbProxyFreeBSDSetInterface: Freeing kernel resources " "failed failed rc=%d\n", rc)); return rc; } memset(&UsbIntAlt, 0, sizeof(UsbIntAlt)); UsbIntAlt.uai_interface_index = iIf; UsbIntAlt.uai_alt_index = iAlt; rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_SET_ALTINTERFACE, &UsbIntAlt, true); if (RT_FAILURE(rc)) { LogFlow(("usbProxyFreeBSDSetInterface: Setting interface %d %d " "failed rc=%d\n", iIf, iAlt, rc)); return rc; } return usbProxyFreeBSDFsInit(pProxyDev); }
/** * SET_CONFIGURATION. * * The caller makes sure that it's not called first time after open or reset * with the active interface. * * @returns success indicator. * @param pProxyDev The device instance data. * @param iCfg The configuration to set. */ static int usbProxyFreeBSDSetConfig(PUSBPROXYDEV pProxyDev, int iCfg) { PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD) pProxyDev->Backend.pv; int iCfgIndex; int rc; LogFlow(("usbProxyFreeBSDSetConfig: pProxyDev=%s cfg=%x\n", pProxyDev->pUsbIns->pszName, iCfg)); /* We need to release kernel ressources first. */ rc = usbProxyFreeBSDFsUnInit(pProxyDev); if (RT_FAILURE(rc)) { LogFlow(("usbProxyFreeBSDSetInterface: Freeing kernel resources " "failed failed rc=%d\n", rc)); return false; } if (iCfg == 0) { /* Unconfigure */ iCfgIndex = 255; } else { /* Get the configuration index matching the value. */ for (iCfgIndex = 0; iCfgIndex < pProxyDev->DevDesc.bNumConfigurations; iCfgIndex++) { if (pProxyDev->paCfgDescs[iCfgIndex].Core.bConfigurationValue == iCfg) break; } if (iCfgIndex == pProxyDev->DevDesc.bNumConfigurations) { LogFlow(("usbProxyFreeBSDSetConfig: configuration " "%d not found\n", iCfg)); return false; } } /* Set the config */ rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_SET_CONFIG, &iCfgIndex, true); if (RT_FAILURE(rc)) return false; /* Allocate kernel ressources again. */ rc = usbProxyFreeBSDFsInit(pProxyDev); if (RT_FAILURE(rc)) return false; return true; }
/** * Opens the device file. * * @returns VBox status code. * @param pProxyDev The device instance. * @param pszAddress If we are using usbfs, this is the path to the * device. If we are using sysfs, this is a string of * the form "sysfs:<sysfs path>//device:<device node>". * In the second case, the two paths are guaranteed * not to contain the substring "//". * @param pvBackend Backend specific pointer, unused for the linux backend. */ static int usbProxyFreeBSDOpen(PUSBPROXYDEV pProxyDev, const char *pszAddress, void *pvBackend) { int rc; LogFlow(("usbProxyFreeBSDOpen: pProxyDev=%p pszAddress=%s\n", pProxyDev, pszAddress)); /* * Try open the device node. */ RTFILE hFile; rc = RTFileOpen(&hFile, pszAddress, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); if (RT_SUCCESS(rc)) { /* * Allocate and initialize the linux backend data. */ PUSBPROXYDEVFBSD pDevFBSD = (PUSBPROXYDEVFBSD)RTMemAllocZ(sizeof(USBPROXYDEVFBSD)); if (pDevFBSD) { pDevFBSD->hFile = hFile; pProxyDev->Backend.pv = pDevFBSD; rc = usbProxyFreeBSDFsInit(pProxyDev); if (RT_SUCCESS(rc)) { LogFlow(("usbProxyFreeBSDOpen(%p, %s): returns successfully hFile=%RTfile iActiveCfg=%d\n", pProxyDev, pszAddress, pDevFBSD->hFile, pProxyDev->iActiveCfg)); return VINF_SUCCESS; } RTMemFree(pDevFBSD); } else rc = VERR_NO_MEMORY; RTFileClose(hFile); } else if (rc == VERR_ACCESS_DENIED) rc = VERR_VUSB_USBFS_PERMISSION; Log(("usbProxyFreeBSDOpen(%p, %s) failed, rc=%d!\n", pProxyDev, pszAddress, rc)); pProxyDev->Backend.pv = NULL; NOREF(pvBackend); return rc; }
/** * Opens the device file. * * @returns VBox status code. * @param pProxyDev The device instance. * @param pszAddress If we are using usbfs, this is the path to the * device. If we are using sysfs, this is a string of * the form "sysfs:<sysfs path>//device:<device node>". * In the second case, the two paths are guaranteed * not to contain the substring "//". * @param pvBackend Backend specific pointer, unused for the linux backend. */ static DECLCALLBACK(int) usbProxyFreeBSDOpen(PUSBPROXYDEV pProxyDev, const char *pszAddress, void *pvBackend) { PUSBPROXYDEVFBSD pDevFBSD = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVFBSD); int rc; LogFlow(("usbProxyFreeBSDOpen: pProxyDev=%p pszAddress=%s\n", pProxyDev, pszAddress)); NOREF(pvBackend); /* * Try open the device node. */ RTFILE hFile; rc = RTFileOpen(&hFile, pszAddress, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); if (RT_SUCCESS(rc)) { /* * Initialize the FreeBSD backend data. */ pDevFBSD->hFile = hFile; rc = usbProxyFreeBSDFsInit(pProxyDev); if (RT_SUCCESS(rc)) { /* * Create wakeup pipe. */ rc = RTPipeCreate(&pDevFBSD->hPipeWakeupR, &pDevFBSD->hPipeWakeupW, 0); if (RT_SUCCESS(rc)) { LogFlow(("usbProxyFreeBSDOpen(%p, %s): returns successfully hFile=%RTfile iActiveCfg=%d\n", pProxyDev, pszAddress, pDevFBSD->hFile, pProxyDev->iActiveCfg)); return VINF_SUCCESS; } } RTFileClose(hFile); } else if (rc == VERR_ACCESS_DENIED) rc = VERR_VUSB_USBFS_PERMISSION; Log(("usbProxyFreeBSDOpen(%p, %s) failed, rc=%d!\n", pProxyDev, pszAddress, rc)); return rc; }
/** * Reset a device. * * @returns VBox status code. * @param pDev The device to reset. */ static DECLCALLBACK(int) usbProxyFreeBSDReset(PUSBPROXYDEV pProxyDev, bool fResetOnFreeBSD) { PUSBPROXYDEVFBSD pDevFBSD = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVFBSD); int iParm; int rc = VINF_SUCCESS; LogFlow(("usbProxyFreeBSDReset: pProxyDev=%s\n", pProxyDev->pUsbIns->pszName)); if (!fResetOnFreeBSD) goto done; /* We need to release kernel ressources first. */ rc = usbProxyFreeBSDFsUnInit(pProxyDev); if (RT_FAILURE(rc)) goto done; /* Resetting is only possible as super-user, ignore any failures: */ iParm = 0; rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_DEVICEENUMERATE, &iParm, true); if (RT_FAILURE(rc)) { /* Set the config instead of bus reset */ iParm = 255; rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_SET_CONFIG, &iParm, true); if (RT_SUCCESS(rc)) { iParm = 0; rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_SET_CONFIG, &iParm, true); } } usleep(10000); /* nice it! */ /* Allocate kernel ressources again. */ rc = usbProxyFreeBSDFsInit(pProxyDev); if (RT_FAILURE(rc)) goto done; /* Retrieve current active configuration. */ rc = usbProxyFreeBSDInit(pProxyDev); done: pProxyDev->cIgnoreSetConfigs = 2; return rc; }