ccGamepadManager::~ccGamepadManager() { releaseDevice(); if (m_menu) { delete m_menu; } }
int main(int argc, char *argv[]){ if (argc != 2){ printHelp("flash"); return 0; } struct device dev; getDevice(argv[1], &dev); readTests(&dev); printf("\n"); writeTests(&dev); releaseDevice(&dev); return 0; }
int initVKeyboardDevice(char* uinputPath) { int i; int deviceHandle = -1; struct uinput_user_dev uidev; deviceHandle = open(uinputPath, O_WRONLY | O_NONBLOCK | O_NDELAY); // if a valid handle could be determined, try to enable key events if(deviceHandle > 0) { if(ioctl(deviceHandle, UI_SET_EVBIT, EV_KEY) < 0) { if(releaseDevice(deviceHandle) < 0) { exit(EXIT_FAILURE); } else { deviceHandle = -1; } } else { // register key events - only values from 1 to 255 are valid for(i=1; i<256; i++) { ioctl(deviceHandle, UI_SET_KEYBIT, i); } memset(&uidev, 0, sizeof (uidev)); snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "uinput_vkeyboard"); uidev.id.bustype = BUS_USB; uidev.id.vendor = 0x4711; uidev.id.product = 0x0815; uidev.id.version = 1; if (write(deviceHandle, &uidev, sizeof (uidev)) < 0) { exit(EXIT_FAILURE); } if (ioctl(deviceHandle, UI_DEV_CREATE) < 0) { exit(EXIT_FAILURE); } sleep(2); } } return deviceHandle; }
static DECLCALLBACK(void) iface_CancelURB(PREMOTEUSBDEVICE pDevice, PREMOTEUSBQURB pRemoteURB) { RemoteUSBBackend *pThis = pDevice->pOwner; VRDE_USB_REQ_CANCEL_URB_PARM parm; parm.code = VRDE_USB_REQ_CANCEL_URB; parm.id = pDevice->id; parm.handle = pRemoteURB->u32Handle; pThis->VRDPServer()->SendUSBRequest(pDevice->u32ClientId, &parm, sizeof(parm)); requestDevice(pDevice); /* Remove this urb from the queue. It is safe because if * client will return the URB, it will be just ignored * in reapURB. */ if (pRemoteURB->prev) { pRemoteURB->prev->next = pRemoteURB->next; } else { pDevice->pHeadQURBs = pRemoteURB->next; } if (pRemoteURB->next) { pRemoteURB->next->prev = pRemoteURB->prev; } else { pDevice->pTailQURBs = pRemoteURB->prev; } qurbFree(pRemoteURB); releaseDevice(pDevice); return; }
static unsigned int releaseDevices(deviceList *devList) { usbDeviceList *list = (usbDeviceList*)devList; unsigned int count = list->deviceList.count; usbDevice *head, *prev = NULL; /* loop, but if head does not change then sleep a bit */ while((head = (usbDevice*)firstItem(&list->deviceList)) != NULL) { if (head != prev) releaseDevice(&head->info); else sleep(100); prev = head; } /* illegal to access the list after this call */ free(list); return count; }
int __cdecl wmain(void) { HRESULT hr = CoInitialize(NULL); if (FAILED(hr)) { LOG(L"Failed CoInitializeEx: hr = 0x%08x", hr); return __LINE__; } CoUninitializeOnExit cuoe; // get active devices IMMDeviceEnumerator *pEnum = NULL; hr = CoCreateInstance( __uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pEnum ); if (FAILED(hr)) { LOG(L"Couldn't get device enumerator: hr = 0x%08x", hr); return __LINE__; } ReleaseOnExit releaseEnum(pEnum); IMMDeviceCollection *pDeviceCollection = NULL; hr = pEnum->EnumAudioEndpoints(eAll, DEVICE_STATE_ACTIVE | DEVICE_STATE_UNPLUGGED, &pDeviceCollection); if (FAILED(hr)) { LOG(L"Couldn't get device collection: hr = 0x%08x", hr); return __LINE__; } ReleaseOnExit releaseDeviceCollection(pDeviceCollection); UINT nDevices = 0; hr = pDeviceCollection->GetCount(&nDevices); if (FAILED(hr)) { LOG(L"Couldn't get device collection count: hr = 0x%08x", hr); return __LINE__; } for (UINT i = 0; i < nDevices; i++) { IMMDevice *pDevice = NULL; hr = pDeviceCollection->Item(i, &pDevice); if (FAILED(hr)) { LOG(L"Couldn't get device: hr = 0x%08x", hr); return __LINE__; } ReleaseOnExit releaseDevice(pDevice); IMMEndpoint *pEndpoint = NULL; hr = pDevice->QueryInterface(IID_PPV_ARGS(&pEndpoint)); if (FAILED(hr)) { LOG(L"Couldn't get endpoint: hr = 0x%08x", hr); return __LINE__; } ReleaseOnExit releaseEndpoint(pEndpoint); EDataFlow eDirection = eAll; hr = pEndpoint->GetDataFlow(&eDirection); if (FAILED(hr)) { LOG(L"Couldn't get data flow: hr = 0x%08x", hr); return __LINE__; } LOG(L"%s endpoint", StringFromDataFlow(eDirection)); IPropertyStore *pPropertyStore = NULL; hr = pDevice->OpenPropertyStore(STGM_READ, &pPropertyStore); if (FAILED(hr)) { LOG(L"Couldn't get property store: hr = 0x%08x", hr); return __LINE__; } ReleaseOnExit releasePropertyStore(pPropertyStore); // get the long name property PROPVARIANT pv; PropVariantInit(&pv); hr = pPropertyStore->GetValue(PKEY_Device_FriendlyName, &pv); if (FAILED(hr)) { LOG(L"Couldn't get friendly name: hr = 0x%08x", hr); return hr; } PropVariantClearOnExit clearPropVariant(&pv); LOG(L"Name: %s", pv.pwszVal); // get the ID WCHAR *wszId = NULL; hr = pDevice->GetId(&wszId); if (FAILED(hr)) { LOG(L"Couldn't get device ID: hr = 0x%08x", hr); return __LINE__; } CoTaskMemFreeOnExit releaseId(wszId); LOG(L"Endpoint ID: %s", wszId); // get device topology object for that endpoint IDeviceTopology *pDT = NULL; hr = pDevice->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL, (void**)&pDT); if (FAILED(hr)) { LOG(L"Couldn't get device topology object: hr = 0x%08x", hr); return __LINE__; } ReleaseOnExit releaseDT(pDT); // get the single connector for that endpoint IConnector *pConnector = NULL; hr = pDT->GetConnector(0, &pConnector); if (FAILED(hr)) { LOG(L"Couldn't get the connector on the endpoint: hr = 0x%08x", hr); return __LINE__; } ReleaseOnExit releaseConnector(pConnector); // QI on the device's connector for IPart IPart *pPart = NULL; hr = pConnector->QueryInterface(IID_PPV_ARGS(&pPart)); if (FAILED(hr)) { LOG(L"Couldn't get the part: hr = 0x%08x", hr); return __LINE__; } ReleaseOnExit releasePart(pPart); // all the real work is done in this function // follow the connector from this trivial endpoint topology // over to the rest of the topologies hr = WalkTreeFromPart(pPart, eDirection, true, 1); if (FAILED(hr)) { LOG(L"Couldn't walk the tree: hr = 0x%08x", hr); return __LINE__; } LOG(L""); } return 0; }
/* The function checks the URB queue for completed URBs. Also if the client * has requested URB polling, the function will send URB poll requests. */ static DECLCALLBACK(int) iface_ReapURB(PREMOTEUSBDEVICE pDevice, uint32_t u32Millies, void **ppvURB, uint32_t *pu32Len, uint32_t *pu32Err) { int rc = VINF_SUCCESS; LogFlow(("RemoteUSBBackend::iface_ReapURB %d ms\n", u32Millies)); if (pDevice->fFailed) { return VERR_VUSB_DEVICE_NOT_ATTACHED; } RemoteUSBBackend *pThis = pDevice->pOwner; /* Wait for transaction completion. */ uint64_t u64StartTime = RTTimeMilliTS(); if (pThis->pollingEnabledURB()) { VRDE_USB_REQ_REAP_URB_PARM parm; parm.code = VRDE_USB_REQ_REAP_URB; pThis->VRDPServer()->SendUSBRequest(pDevice->u32ClientId, &parm, sizeof(parm)); } REMOTEUSBQURB *qurb = NULL; for (;;) { uint32_t u32ClientId; if (ASMAtomicXchgBool(&pDevice->fWokenUp, false)) break; /* Scan queued URBs, look for completed. */ requestDevice(pDevice); u32ClientId = pDevice->u32ClientId; qurb = pDevice->pHeadQURBs; while (qurb) { if (qurb->fCompleted) { /* Remove this completed urb from the queue. */ if (qurb->prev) { qurb->prev->next = qurb->next; } else { pDevice->pHeadQURBs = qurb->next; } if (qurb->next) { qurb->next->prev = qurb->prev; } else { pDevice->pTailQURBs = qurb->prev; } qurb->next = NULL; qurb->prev = NULL; break; } qurb = qurb->next; } releaseDevice(pDevice); if ( qurb || !pDevice->pHeadQURBs || u32Millies == 0 || pDevice->fFailed || (RTTimeMilliTS() - u64StartTime >= (uint64_t)u32Millies)) { /* Got an URB or do not have to wait for an URB. */ break; } LogFlow(("RemoteUSBBackend::iface_ReapURB iteration.\n")); RTThreadSleep(10); if (pThis->pollingEnabledURB()) { VRDE_USB_REQ_REAP_URB_PARM parm; parm.code = VRDE_USB_REQ_REAP_URB; pThis->VRDPServer()->SendUSBRequest(u32ClientId, &parm, sizeof(parm)); } } LogFlow(("RemoteUSBBackend::iface_ReapURB completed in %lld ms, qurb = %p\n", RTTimeMilliTS () - u64StartTime, qurb)); if (!qurb) { *ppvURB = NULL; *pu32Len = 0; *pu32Err = VUSBSTATUS_OK; } else { *ppvURB = qurb->pvURB; *pu32Len = qurb->u32Len; *pu32Err = qurb->u32Err; #ifdef LOG_ENABLED Log(("URB len = %d, data = %p\n", qurb->u32Len, qurb->pvURB)); if (qurb->u32Len) { Log(("Received URB content:\n%.*Rhxd\n", qurb->u32Len, qurb->pvData)); } #endif qurbFree(qurb); } return rc; }
static DECLCALLBACK(int) iface_QueueURB(PREMOTEUSBDEVICE pDevice, uint8_t u8Type, uint8_t u8Ep, uint8_t u8Direction, uint32_t u32Len, void *pvData, void *pvURB, PREMOTEUSBQURB *ppRemoteURB) { int rc = VINF_SUCCESS; #ifdef DEBUG_sunlover LogFlow(("RemoteUSBBackend::iface_QueueURB: u8Type = %d, u8Ep = %d, u8Direction = %d, data\n%.*Rhxd\n", u8Type, u8Ep, u8Direction, u32Len, pvData)); #endif /* DEBUG_sunlover */ if (pDevice->fFailed) { return VERR_VUSB_DEVICE_NOT_ATTACHED; } RemoteUSBBackend *pThis = pDevice->pOwner; VRDE_USB_REQ_QUEUE_URB_PARM parm; uint32_t u32Handle = 0; uint32_t u32DataLen = 0; REMOTEUSBQURB *qurb = qurbAlloc(pDevice); if (qurb == NULL) { rc = VERR_NO_MEMORY; goto l_leave; } /* * Compute length of data which need to be transferred to the client. */ switch(u8Direction) { case VUSB_DIRECTION_IN: { if (u8Type == VUSBXFERTYPE_MSG) { u32DataLen = 8; /* 8 byte header. */ // u32DataLen = u32Len; // @todo do messages need all information? } } break; case VUSB_DIRECTION_OUT: { u32DataLen = u32Len; } break; default: { AssertFailed(); rc = VERR_INVALID_PARAMETER; goto l_leave; } } parm.code = VRDE_USB_REQ_QUEUE_URB; parm.id = pDevice->id; u32Handle = pDevice->hURB++; if (u32Handle == 0) { u32Handle = pDevice->hURB++; } LogFlow(("RemoteUSBBackend::iface_QueueURB: handle = %d\n", u32Handle)); parm.handle = u32Handle; switch(u8Type) { case VUSBXFERTYPE_CTRL: parm.type = VRDE_USB_TRANSFER_TYPE_CTRL; break; case VUSBXFERTYPE_ISOC: parm.type = VRDE_USB_TRANSFER_TYPE_ISOC; break; case VUSBXFERTYPE_BULK: parm.type = VRDE_USB_TRANSFER_TYPE_BULK; break; case VUSBXFERTYPE_INTR: parm.type = VRDE_USB_TRANSFER_TYPE_INTR; break; case VUSBXFERTYPE_MSG: parm.type = VRDE_USB_TRANSFER_TYPE_MSG; break; default: AssertFailed(); rc = VERR_INVALID_PARAMETER; goto l_leave; } parm.ep = u8Ep; switch(u8Direction) { case VUSB_DIRECTION_SETUP: AssertFailed(); parm.direction = VRDE_USB_DIRECTION_SETUP; break; case VUSB_DIRECTION_IN: parm.direction = VRDE_USB_DIRECTION_IN; break; case VUSB_DIRECTION_OUT: parm.direction = VRDE_USB_DIRECTION_OUT; break; default: AssertFailed(); rc = VERR_INVALID_PARAMETER; goto l_leave; } parm.urblen = u32Len; parm.datalen = u32DataLen; if (u32DataLen) { parm.data = pvData; } requestDevice (pDevice); /* Add at tail of queued urb list. */ qurb->next = NULL; qurb->prev = pDevice->pTailQURBs; qurb->u32Err = VRDE_USB_XFER_OK; qurb->u32Len = u32Len; qurb->pvData = pvData; qurb->pvURB = pvURB; qurb->u32Handle = u32Handle; qurb->fCompleted = false; qurb->fInput = (u8Direction == VUSB_DIRECTION_IN); qurb->u32TransferredLen = 0; if (pDevice->pTailQURBs) { Assert(pDevice->pTailQURBs->next == NULL); pDevice->pTailQURBs->next = qurb; } else { /* This is the first URB to be added. */ Assert(pDevice->pHeadQURBs == NULL); pDevice->pHeadQURBs = qurb; } pDevice->pTailQURBs = qurb; releaseDevice(pDevice); *ppRemoteURB = qurb; pThis->VRDPServer()->SendUSBRequest(pDevice->u32ClientId, &parm, sizeof(parm)); l_leave: if (RT_FAILURE(rc)) { qurbFree(qurb); } return rc; }
int RemoteUSBBackend::reapURB(const void *pvBody, uint32_t cbBody) { int rc = VINF_SUCCESS; LogFlow(("RemoteUSBBackend::reapURB: pvBody = %p, cbBody = %d\n", pvBody, cbBody)); VRDEUSBREQREAPURBBODY *pBody = (VRDEUSBREQREAPURBBODY *)pvBody; while (cbBody >= sizeof(VRDEUSBREQREAPURBBODY)) { Log(("RemoteUSBBackend::reapURB: id = %d, flags = %02X, error = %d, handle %d, len = %d.\n", pBody->id, pBody->flags, pBody->error, pBody->handle, pBody->len)); uint8_t fu8ReapValidFlags; if (mClientVersion == VRDE_USB_VERSION_1 || mClientVersion == VRDE_USB_VERSION_2) { fu8ReapValidFlags = VRDE_USB_REAP_VALID_FLAGS; } else { fu8ReapValidFlags = VRDE_USB_REAP_VALID_FLAGS_3; } /* Verify client's data. */ if ( (pBody->flags & ~fu8ReapValidFlags) != 0 || sizeof(VRDEUSBREQREAPURBBODY) > cbBody || pBody->handle == 0) { LogFlow(("RemoteUSBBackend::reapURB: WARNING: invalid reply data. Skipping the reply.\n")); rc = VERR_INVALID_PARAMETER; break; } PREMOTEUSBDEVICE pDevice = deviceFromId(pBody->id); if (!pDevice) { LogFlow(("RemoteUSBBackend::reapURB: WARNING: invalid device id. Skipping the reply.\n")); rc = VERR_INVALID_PARAMETER; break; } uint32_t cbBodyData = 0; /* Data contained in the URB body structure for input URBs. */ requestDevice(pDevice); /* Search the queued URB for given handle. */ REMOTEUSBQURB *qurb = pDevice->pHeadQURBs; while (qurb && qurb->u32Handle != pBody->handle) { LogFlow(("RemoteUSBBackend::reapURB: searching: %p handle = %d.\n", qurb, qurb->u32Handle)); qurb = qurb->next; } if (!qurb) { LogFlow(("RemoteUSBBackend::reapURB: Queued URB not found, probably already canceled. Skipping the URB.\n")); } else { LogFlow(("RemoteUSBBackend::reapURB: qurb = %p\n", qurb)); /* Update the URB error field. */ if (mClientVersion == VRDE_USB_VERSION_1) { switch(pBody->error) { case VRDE_USB_XFER_OK: qurb->u32Err = VUSBSTATUS_OK; break; case VRDE_USB_XFER_STALL: qurb->u32Err = VUSBSTATUS_STALL; break; case VRDE_USB_XFER_DNR: qurb->u32Err = VUSBSTATUS_DNR; break; case VRDE_USB_XFER_CRC: qurb->u32Err = VUSBSTATUS_CRC; break; default: Log(("RemoteUSBBackend::reapURB: Invalid error %d\n", pBody->error)); qurb->u32Err = VUSBSTATUS_DNR; break; } } else if ( mClientVersion == VRDE_USB_VERSION_2 || mClientVersion == VRDE_USB_VERSION_3) { switch(pBody->error) { case VRDE_USB_XFER_OK: qurb->u32Err = VUSBSTATUS_OK; break; case VRDE_USB_XFER_STALL: qurb->u32Err = VUSBSTATUS_STALL; break; case VRDE_USB_XFER_DNR: qurb->u32Err = VUSBSTATUS_DNR; break; case VRDE_USB_XFER_CRC: qurb->u32Err = VUSBSTATUS_CRC; break; case VRDE_USB_XFER_DO: qurb->u32Err = VUSBSTATUS_DATA_OVERRUN; break; case VRDE_USB_XFER_DU: qurb->u32Err = VUSBSTATUS_DATA_UNDERRUN; break; /* Unmapped errors. */ case VRDE_USB_XFER_BS: case VRDE_USB_XFER_DTM: case VRDE_USB_XFER_PCF: case VRDE_USB_XFER_UPID: case VRDE_USB_XFER_BO: case VRDE_USB_XFER_BU: case VRDE_USB_XFER_ERR: default: Log(("RemoteUSBBackend::reapURB: Invalid error %d\n", pBody->error)); qurb->u32Err = VUSBSTATUS_DNR; break; } } else { qurb->u32Err = VUSBSTATUS_DNR; } /* Get the URB data. */ bool fURBCompleted = true; if (qurb->fInput) { cbBodyData = pBody->len; /* VRDE_USB_DIRECTION_IN URBs include some data. */ } if ( qurb->u32Err == VUSBSTATUS_OK && qurb->fInput) { LogFlow(("RemoteUSBBackend::reapURB: copying data %d bytes\n", pBody->len)); uint32_t u32DataLen = qurb->u32TransferredLen + pBody->len; if (u32DataLen > qurb->u32Len) { /* Received more data than expected for this URB. If there more fragments follow, * they will be discarded because the URB handle will not be valid anymore. */ qurb->u32Err = VUSBSTATUS_DNR; } else { memcpy ((uint8_t *)qurb->pvData + qurb->u32TransferredLen, &pBody[1], pBody->len); } if ( qurb->u32Err == VUSBSTATUS_OK && (pBody->flags & VRDE_USB_REAP_FLAG_FRAGMENT) != 0) { /* If the client sends fragmented packets, accumulate the URB data. */ fURBCompleted = false; } } qurb->u32TransferredLen += pBody->len; /* Update the value for all URBs. */ if (fURBCompleted) { /* Move the URB near the head of URB list, so that iface_ReapURB can * find it faster. Note that the order of completion must be preserved! */ if (qurb->prev) { /* The URB is not in the head. Unlink it from its current position. */ qurb->prev->next = qurb->next; if (qurb->next) { qurb->next->prev = qurb->prev; } else { pDevice->pTailQURBs = qurb->prev; } /* And insert it to its new place. */ if (pDevice->pHeadQURBs->fCompleted) { /* At least one other completed URB; insert after the * last completed URB. */ REMOTEUSBQURB *prev_qurb = pDevice->pHeadQURBs; while (prev_qurb->next && prev_qurb->next->fCompleted) prev_qurb = prev_qurb->next; qurb->next = prev_qurb->next; qurb->prev = prev_qurb; if (prev_qurb->next) prev_qurb->next->prev = qurb; else pDevice->pTailQURBs = qurb; prev_qurb->next = qurb; } else { /* No other completed URBs; insert at head. */ qurb->next = pDevice->pHeadQURBs; qurb->prev = NULL; pDevice->pHeadQURBs->prev = qurb; pDevice->pHeadQURBs = qurb; } } qurb->u32Len = qurb->u32TransferredLen; /* Update the final length. */ qurb->fCompleted = true; } } releaseDevice (pDevice); if (pBody->flags & VRDE_USB_REAP_FLAG_LAST) { break; } /* There is probably a further URB body. */ uint32_t cbBodySize = sizeof (VRDEUSBREQREAPURBBODY) + cbBodyData; if (cbBodySize > cbBody) { rc = VERR_INVALID_PARAMETER; break; } pBody = (VRDEUSBREQREAPURBBODY *)((uint8_t *)pBody + cbBodySize); cbBody -= cbBodySize; } LogFlow(("RemoteUSBBackend::reapURB: returns %Rrc\n", rc)); return rc; }