1ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch/* 2ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * Windows CE backend for libusbx 1.0 3ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * Copyright © 2011-2013 RealVNC Ltd. 4ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * Large portions taken from Windows backend, which is 5ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * Copyright © 2009-2010 Pete Batard <pbatard@gmail.com> 6ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * With contributions from Michael Plante, Orin Eman et al. 7ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer 8ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * Major code testing contribution by Xiaofan Chen 9ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * 10ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * This library is free software; you can redistribute it and/or 11ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * modify it under the terms of the GNU Lesser General Public 12ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * License as published by the Free Software Foundation; either 13ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * version 2.1 of the License, or (at your option) any later version. 14ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * 15ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * This library is distributed in the hope that it will be useful, 16ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * but WITHOUT ANY WARRANTY; without even the implied warranty of 17ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * Lesser General Public License for more details. 19ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * 20ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * You should have received a copy of the GNU Lesser General Public 21ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * License along with this library; if not, write to the Free Software 22ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 23ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch */ 24ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 25ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include <libusbi.h> 26ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 27ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include <stdint.h> 28ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include <errno.h> 29ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include <inttypes.h> 30ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 31ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "wince_usb.h" 32ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 33ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Forward declares 34ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int wince_clock_gettime(int clk_id, struct timespec *tp); 35ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochunsigned __stdcall wince_clock_gettime_threaded(void* param); 36ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 37ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Global variables 38ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochuint64_t hires_frequency, hires_ticks_to_ps; 39ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochint errno; 40ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochconst uint64_t epoch_time = UINT64_C(116444736000000000); // 1970.01.01 00:00:000 in MS Filetime 41ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochenum windows_version windows_version = WINDOWS_CE; 42ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int concurrent_usage = -1; 43ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Timer thread 44ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// NB: index 0 is for monotonic and 1 is for the thread exit event 45ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochHANDLE timer_thread = NULL; 46ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochHANDLE timer_mutex = NULL; 47ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstruct timespec timer_tp; 48ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvolatile LONG request_count[2] = {0, 1}; // last one must be > 0 49ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochHANDLE timer_request[2] = { NULL, NULL }; 50ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochHANDLE timer_response = NULL; 51ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochHANDLE driver_handle = INVALID_HANDLE_VALUE; 52ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 53ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch/* 54ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * Converts a windows error to human readable string 55ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * uses retval as errorcode, or, if 0, use GetLastError() 56ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch */ 57ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#if defined(ENABLE_LOGGING) 58ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic char* windows_error_str(uint32_t retval) 59ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 60ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch static TCHAR wErr_string[ERR_BUFFER_SIZE]; 61ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch static char err_string[ERR_BUFFER_SIZE]; 62ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 63ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DWORD size; 64ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch size_t i; 65ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch uint32_t error_code, format_error; 66ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 67ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch error_code = retval?retval:GetLastError(); 68ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 69ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch safe_stprintf(wErr_string, ERR_BUFFER_SIZE, _T("[%d] "), error_code); 70ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 71ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch size = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code, 72ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &wErr_string[safe_tcslen(wErr_string)], 73ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ERR_BUFFER_SIZE - (DWORD)safe_tcslen(wErr_string), NULL); 74ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (size == 0) { 75ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch format_error = GetLastError(); 76ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (format_error) 77ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch safe_stprintf(wErr_string, ERR_BUFFER_SIZE, 78ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch _T("Windows error code %u (FormatMessage error code %u)"), error_code, format_error); 79ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch else 80ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch safe_stprintf(wErr_string, ERR_BUFFER_SIZE, _T("Unknown error code %u"), error_code); 81ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } else { 82ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Remove CR/LF terminators 83ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch for (i=safe_tcslen(wErr_string)-1; ((wErr_string[i]==0x0A) || (wErr_string[i]==0x0D)); i--) { 84ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wErr_string[i] = 0; 85ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 86ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 87ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (WideCharToMultiByte(CP_ACP, 0, wErr_string, -1, err_string, ERR_BUFFER_SIZE, NULL, NULL) < 0) 88ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch { 89ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch strcpy(err_string, "Unable to convert error string"); 90ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 91ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return err_string; 92ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 93ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#endif 94ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 95ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic struct wince_device_priv *_device_priv(struct libusb_device *dev) 96ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 97ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return (struct wince_device_priv *) dev->os_priv; 98ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 99ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 100ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// ceusbkwrapper to libusb error code mapping 101ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int translate_driver_error(int error) 102ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 103ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch switch (error) { 104ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case ERROR_INVALID_PARAMETER: 105ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_ERROR_INVALID_PARAM; 106ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case ERROR_CALL_NOT_IMPLEMENTED: 107ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case ERROR_NOT_SUPPORTED: 108ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_ERROR_NOT_SUPPORTED; 109ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case ERROR_NOT_ENOUGH_MEMORY: 110ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_ERROR_NO_MEM; 111ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case ERROR_INVALID_HANDLE: 112ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_ERROR_NO_DEVICE; 113ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case ERROR_BUSY: 114ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_ERROR_BUSY; 115ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 116ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Error codes that are either unexpected, or have 117ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // no suitable LIBUSB_ERROR equivilant. 118ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case ERROR_CANCELLED: 119ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case ERROR_INTERNAL_ERROR: 120ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch default: 121ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_ERROR_OTHER; 122ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 123ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 124ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 125ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int init_dllimports() 126ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 127ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DLL_LOAD(ceusbkwrapper.dll, UkwOpenDriver, TRUE); 128ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DLL_LOAD(ceusbkwrapper.dll, UkwGetDeviceList, TRUE); 129ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DLL_LOAD(ceusbkwrapper.dll, UkwReleaseDeviceList, TRUE); 130ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DLL_LOAD(ceusbkwrapper.dll, UkwGetDeviceAddress, TRUE); 131ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DLL_LOAD(ceusbkwrapper.dll, UkwGetDeviceDescriptor, TRUE); 132ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DLL_LOAD(ceusbkwrapper.dll, UkwGetConfigDescriptor, TRUE); 133ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DLL_LOAD(ceusbkwrapper.dll, UkwCloseDriver, TRUE); 134ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DLL_LOAD(ceusbkwrapper.dll, UkwCancelTransfer, TRUE); 135ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DLL_LOAD(ceusbkwrapper.dll, UkwIssueControlTransfer, TRUE); 136ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DLL_LOAD(ceusbkwrapper.dll, UkwClaimInterface, TRUE); 137ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DLL_LOAD(ceusbkwrapper.dll, UkwReleaseInterface, TRUE); 138ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DLL_LOAD(ceusbkwrapper.dll, UkwSetInterfaceAlternateSetting, TRUE); 139ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DLL_LOAD(ceusbkwrapper.dll, UkwClearHaltHost, TRUE); 140ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DLL_LOAD(ceusbkwrapper.dll, UkwClearHaltDevice, TRUE); 141ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DLL_LOAD(ceusbkwrapper.dll, UkwGetConfig, TRUE); 142ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DLL_LOAD(ceusbkwrapper.dll, UkwSetConfig, TRUE); 143ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DLL_LOAD(ceusbkwrapper.dll, UkwResetDevice, TRUE); 144ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DLL_LOAD(ceusbkwrapper.dll, UkwKernelDriverActive, TRUE); 145ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DLL_LOAD(ceusbkwrapper.dll, UkwAttachKernelDriver, TRUE); 146ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DLL_LOAD(ceusbkwrapper.dll, UkwDetachKernelDriver, TRUE); 147ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DLL_LOAD(ceusbkwrapper.dll, UkwIssueBulkTransfer, TRUE); 148ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DLL_LOAD(ceusbkwrapper.dll, UkwIsPipeHalted, TRUE); 149ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_SUCCESS; 150ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 151ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 152ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int init_device(struct libusb_device *dev, UKW_DEVICE drv_dev, 153ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch unsigned char bus_addr, unsigned char dev_addr) 154ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 155ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct wince_device_priv *priv = _device_priv(dev); 156ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int r = LIBUSB_SUCCESS; 157ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 158ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch dev->bus_number = bus_addr; 159ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch dev->device_address = dev_addr; 160ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch priv->dev = drv_dev; 161ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 162ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!UkwGetDeviceDescriptor(priv->dev, &(priv->desc))) { 163ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch r = translate_driver_error(GetLastError()); 164ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 165ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return r; 166ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 167ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 168ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Internal API functions 169ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int wince_init(struct libusb_context *ctx) 170ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 171ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int i, r = LIBUSB_ERROR_OTHER; 172ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch HANDLE semaphore; 173ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch TCHAR sem_name[11+1+8]; // strlen(libusb_init)+'\0'+(32-bit hex PID) 174ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 175ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch _stprintf(sem_name, _T("libusb_init%08X"), (unsigned int)GetCurrentProcessId()&0xFFFFFFFF); 176ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch semaphore = CreateSemaphore(NULL, 1, 1, sem_name); 177ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (semaphore == NULL) { 178ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_err(ctx, "could not create semaphore: %s", windows_error_str(0)); 179ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_ERROR_NO_MEM; 180ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 181ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 182ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // A successful wait brings our semaphore count to 0 (unsignaled) 183ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // => any concurent wait stalls until the semaphore's release 184ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) { 185ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_err(ctx, "failure to access semaphore: %s", windows_error_str(0)); 186ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseHandle(semaphore); 187ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_ERROR_NO_MEM; 188ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 189ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 190ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // NB: concurrent usage supposes that init calls are equally balanced with 191ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // exit calls. If init is called more than exit, we will not exit properly 192ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if ( ++concurrent_usage == 0 ) { // First init? 193ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Initialize pollable file descriptors 194ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch init_polling(); 195ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 196ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Load DLL imports 197ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (init_dllimports() != LIBUSB_SUCCESS) { 198ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_err(ctx, "could not resolve DLL functions"); 199ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch r = LIBUSB_ERROR_NOT_SUPPORTED; 200ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch goto init_exit; 201ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 202ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 203ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // try to open a handle to the driver 204ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch driver_handle = UkwOpenDriver(); 205ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (driver_handle == INVALID_HANDLE_VALUE) { 206ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_err(ctx, "could not connect to driver"); 207ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch r = LIBUSB_ERROR_NOT_SUPPORTED; 208ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch goto init_exit; 209ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 210ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 211ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Windows CE doesn't have a way of specifying thread affinity, so this code 212ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // just has to hope QueryPerformanceCounter doesn't report different values when 213ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // running on different cores. 214ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch r = LIBUSB_ERROR_NO_MEM; 215ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch for (i = 0; i < 2; i++) { 216ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch timer_request[i] = CreateEvent(NULL, TRUE, FALSE, NULL); 217ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (timer_request[i] == NULL) { 218ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_err(ctx, "could not create timer request event %d - aborting", i); 219ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch goto init_exit; 220ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 221ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 222ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch timer_response = CreateSemaphore(NULL, 0, MAX_TIMER_SEMAPHORES, NULL); 223ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (timer_response == NULL) { 224ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_err(ctx, "could not create timer response semaphore - aborting"); 225ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch goto init_exit; 226ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 227ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch timer_mutex = CreateMutex(NULL, FALSE, NULL); 228ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (timer_mutex == NULL) { 229ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_err(ctx, "could not create timer mutex - aborting"); 230ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch goto init_exit; 231ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 232ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch timer_thread = CreateThread(NULL, 0, wince_clock_gettime_threaded, NULL, 0, NULL); 233ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (timer_thread == NULL) { 234ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_err(ctx, "Unable to create timer thread - aborting"); 235ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch goto init_exit; 236ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 23768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 23868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Wait for timer thread to init before continuing. 23968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (WaitForSingleObject(timer_response, INFINITE) != WAIT_OBJECT_0) { 24068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) usbi_err(ctx, "Failed to wait for timer thread to become ready - aborting"); 24168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) goto init_exit; 24268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 243ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 244ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // At this stage, either we went through full init successfully, or didn't need to 245ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch r = LIBUSB_SUCCESS; 246ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 247ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochinit_exit: // Holds semaphore here. 248ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed? 249ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (driver_handle != INVALID_HANDLE_VALUE) { 250ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch UkwCloseDriver(driver_handle); 251ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch driver_handle = INVALID_HANDLE_VALUE; 252ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 253ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (timer_thread) { 254ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch SetEvent(timer_request[1]); // actually the signal to quit the thread. 255ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (WAIT_OBJECT_0 != WaitForSingleObject(timer_thread, INFINITE)) { 256ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_warn(ctx, "could not wait for timer thread to quit"); 257ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch TerminateThread(timer_thread, 1); // shouldn't happen, but we're destroying 258ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // all objects it might have held anyway. 259ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 260ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseHandle(timer_thread); 261ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch timer_thread = NULL; 262ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 263ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch for (i = 0; i < 2; i++) { 264ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (timer_request[i]) { 265ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseHandle(timer_request[i]); 266ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch timer_request[i] = NULL; 267ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 268ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 269ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (timer_response) { 270ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseHandle(timer_response); 271ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch timer_response = NULL; 272ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 273ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (timer_mutex) { 274ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseHandle(timer_mutex); 275ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch timer_mutex = NULL; 276ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 277ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 278ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 279ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (r != LIBUSB_SUCCESS) 280ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch --concurrent_usage; // Not expected to call libusb_exit if we failed. 281ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 282ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 283ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseHandle(semaphore); 284ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return r; 285ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 286ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 287ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic void wince_exit(void) 288ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 289ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int i; 290ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch HANDLE semaphore; 291ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch TCHAR sem_name[11+1+8]; // strlen(libusb_init)+'\0'+(32-bit hex PID) 292ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 293ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch _stprintf(sem_name, _T("libusb_init%08X"), (unsigned int)GetCurrentProcessId()&0xFFFFFFFF); 294ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch semaphore = CreateSemaphore(NULL, 1, 1, sem_name); 295ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (semaphore == NULL) { 296ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 297ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 298ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 299ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // A successful wait brings our semaphore count to 0 (unsignaled) 300ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // => any concurent wait stalls until the semaphore release 301ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) { 302ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseHandle(semaphore); 303ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 304ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 305ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 306ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Only works if exits and inits are balanced exactly 307ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (--concurrent_usage < 0) { // Last exit 308ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch exit_polling(); 309ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 310ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (timer_thread) { 311ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch SetEvent(timer_request[1]); // actually the signal to quit the thread. 312ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (WAIT_OBJECT_0 != WaitForSingleObject(timer_thread, INFINITE)) { 313ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg("could not wait for timer thread to quit"); 314ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch TerminateThread(timer_thread, 1); 315ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 316ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseHandle(timer_thread); 317ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch timer_thread = NULL; 318ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 319ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch for (i = 0; i < 2; i++) { 320ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (timer_request[i]) { 321ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseHandle(timer_request[i]); 322ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch timer_request[i] = NULL; 323ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 324ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 325ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (timer_response) { 326ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseHandle(timer_response); 327ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch timer_response = NULL; 328ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 329ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (timer_mutex) { 330ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseHandle(timer_mutex); 331ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch timer_mutex = NULL; 332ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 333ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (driver_handle != INVALID_HANDLE_VALUE) { 334ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch UkwCloseDriver(driver_handle); 335ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch driver_handle = INVALID_HANDLE_VALUE; 336ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 337ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 338ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 339ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 340ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseHandle(semaphore); 341ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 342ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 343ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int wince_get_device_list( 344ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_context *ctx, 345ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct discovered_devs **discdevs) 346ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 347ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch UKW_DEVICE devices[MAX_DEVICE_COUNT]; 348ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct discovered_devs * new_devices = *discdevs; 349ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DWORD count = 0, i; 350ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_device *dev = NULL; 351ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch unsigned char bus_addr, dev_addr; 352ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch unsigned long session_id; 353ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch BOOL success; 354ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DWORD release_list_offset = 0; 355ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int r = LIBUSB_SUCCESS; 356ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 357ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch success = UkwGetDeviceList(driver_handle, devices, MAX_DEVICE_COUNT, &count); 358ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!success) { 359ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int libusbErr = translate_driver_error(GetLastError()); 360ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_err(ctx, "could not get devices: %s", windows_error_str(0)); 361ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return libusbErr; 362ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 363ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch for(i = 0; i < count; ++i) { 364ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch release_list_offset = i; 365ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch success = UkwGetDeviceAddress(devices[i], &bus_addr, &dev_addr, &session_id); 366ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!success) { 367ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch r = translate_driver_error(GetLastError()); 368ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_err(ctx, "could not get device address for %d: %s", i, windows_error_str(0)); 369ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch goto err_out; 370ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 371ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch dev = usbi_get_device_by_session_id(ctx, session_id); 372ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (dev) { 373ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg("using existing device for %d/%d (session %ld)", 374ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch bus_addr, dev_addr, session_id); 375ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch libusb_ref_device(dev); 376ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Release just this element in the device list (as we already hold a 377ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // reference to it). 378ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch UkwReleaseDeviceList(driver_handle, &devices[i], 1); 379ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch release_list_offset++; 380ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } else { 381ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg("allocating new device for %d/%d (session %ld)", 382ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch bus_addr, dev_addr, session_id); 383ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch dev = usbi_alloc_device(ctx, session_id); 384ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!dev) { 385ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch r = LIBUSB_ERROR_NO_MEM; 386ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch goto err_out; 387ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 388ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch r = init_device(dev, devices[i], bus_addr, dev_addr); 389ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (r < 0) 390ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch goto err_out; 391ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch r = usbi_sanitize_device(dev); 392ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (r < 0) 393ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch goto err_out; 394ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 395ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch new_devices = discovered_devs_append(new_devices, dev); 396ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!discdevs) { 397ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch r = LIBUSB_ERROR_NO_MEM; 398ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch goto err_out; 399ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 400ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch safe_unref_device(dev); 401ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 402ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch *discdevs = new_devices; 403ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return r; 404ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdocherr_out: 405ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch *discdevs = new_devices; 406ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch safe_unref_device(dev); 407ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Release the remainder of the unprocessed device list. 408ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // The devices added to new_devices already will still be passed up to libusb, 409ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // which can dispose of them at its leisure. 410ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch UkwReleaseDeviceList(driver_handle, &devices[release_list_offset], count - release_list_offset); 411ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return r; 412ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 413ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 414ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int wince_open(struct libusb_device_handle *handle) 415ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 416ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Nothing to do to open devices as a handle to it has 417ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // been retrieved by wince_get_device_list 418ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_SUCCESS; 419ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 420ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 421ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic void wince_close(struct libusb_device_handle *handle) 422ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 423ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Nothing to do as wince_open does nothing. 424ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 425ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 426ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int wince_get_device_descriptor( 427ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_device *device, 428ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch unsigned char *buffer, int *host_endian) 429ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 430ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct wince_device_priv *priv = _device_priv(device); 431ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 432ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch *host_endian = 1; 433ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch memcpy(buffer, &priv->desc, DEVICE_DESC_LENGTH); 434ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_SUCCESS; 435ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 436ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 437ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int wince_get_active_config_descriptor( 438ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_device *device, 439ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch unsigned char *buffer, size_t len, int *host_endian) 440ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 441ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct wince_device_priv *priv = _device_priv(device); 442ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DWORD actualSize = len; 443ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch *host_endian = 0; 444ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!UkwGetConfigDescriptor(priv->dev, UKW_ACTIVE_CONFIGURATION, buffer, len, &actualSize)) { 445ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return translate_driver_error(GetLastError()); 446ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 447ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return actualSize; 448ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 449ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 450ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int wince_get_config_descriptor( 451ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_device *device, 452ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch uint8_t config_index, 453ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch unsigned char *buffer, size_t len, int *host_endian) 454ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 455ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct wince_device_priv *priv = _device_priv(device); 456ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DWORD actualSize = len; 457ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch *host_endian = 0; 458ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!UkwGetConfigDescriptor(priv->dev, config_index, buffer, len, &actualSize)) { 459ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return translate_driver_error(GetLastError()); 460ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 461ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return actualSize; 462ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 463ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 464ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int wince_get_configuration( 465ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_device_handle *handle, 466ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int *config) 467ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 468ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct wince_device_priv *priv = _device_priv(handle->dev); 469ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch UCHAR cv = 0; 470ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!UkwGetConfig(priv->dev, &cv)) { 471ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return translate_driver_error(GetLastError()); 472ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 473ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (*config) = cv; 474ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_SUCCESS; 475ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 476ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 477ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int wince_set_configuration( 478ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_device_handle *handle, 479ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int config) 480ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 481ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct wince_device_priv *priv = _device_priv(handle->dev); 482ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Setting configuration 0 places the device in Address state. 483ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // This should correspond to the "unconfigured state" required by 484ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // libusb when the specified configuration is -1. 485ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch UCHAR cv = (config < 0) ? 0 : config; 486ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!UkwSetConfig(priv->dev, cv)) { 487ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return translate_driver_error(GetLastError()); 488ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 489ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_SUCCESS; 490ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 491ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 492ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int wince_claim_interface( 493ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_device_handle *handle, 494ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int interface_number) 495ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 496ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct wince_device_priv *priv = _device_priv(handle->dev); 497ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!UkwClaimInterface(priv->dev, interface_number)) { 498ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return translate_driver_error(GetLastError()); 499ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 500ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_SUCCESS; 501ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 502ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 503ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int wince_release_interface( 504ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_device_handle *handle, 505ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int interface_number) 506ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 507ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct wince_device_priv *priv = _device_priv(handle->dev); 508ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!UkwSetInterfaceAlternateSetting(priv->dev, interface_number, 0)) { 509ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return translate_driver_error(GetLastError()); 510ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 511ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!UkwReleaseInterface(priv->dev, interface_number)) { 512ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return translate_driver_error(GetLastError()); 513ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 514ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_SUCCESS; 515ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 516ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 517ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int wince_set_interface_altsetting( 518ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_device_handle *handle, 519ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int interface_number, int altsetting) 520ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 521ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct wince_device_priv *priv = _device_priv(handle->dev); 522ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!UkwSetInterfaceAlternateSetting(priv->dev, interface_number, altsetting)) { 523ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return translate_driver_error(GetLastError()); 524ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 525ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_SUCCESS; 526ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 527ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 528ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int wince_clear_halt( 529ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_device_handle *handle, 530ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch unsigned char endpoint) 531ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 532ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct wince_device_priv *priv = _device_priv(handle->dev); 533ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!UkwClearHaltHost(priv->dev, endpoint)) { 534ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return translate_driver_error(GetLastError()); 535ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 536ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!UkwClearHaltDevice(priv->dev, endpoint)) { 537ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return translate_driver_error(GetLastError()); 538ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 539ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_SUCCESS; 540ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 541ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 542ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int wince_reset_device( 543ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_device_handle *handle) 544ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 545ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct wince_device_priv *priv = _device_priv(handle->dev); 546ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!UkwResetDevice(priv->dev)) { 547ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return translate_driver_error(GetLastError()); 548ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 549ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_SUCCESS; 550ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 551ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 552ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int wince_kernel_driver_active( 553ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_device_handle *handle, 554ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int interface_number) 555ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 556ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct wince_device_priv *priv = _device_priv(handle->dev); 557ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch BOOL result = FALSE; 558ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!UkwKernelDriverActive(priv->dev, interface_number, &result)) { 559ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return translate_driver_error(GetLastError()); 560ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 561ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return result ? 1 : 0; 562ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 563ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 564ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int wince_detach_kernel_driver( 565ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_device_handle *handle, 566ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int interface_number) 567ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 568ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct wince_device_priv *priv = _device_priv(handle->dev); 569ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!UkwDetachKernelDriver(priv->dev, interface_number)) { 570ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return translate_driver_error(GetLastError()); 571ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 572ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_SUCCESS; 573ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 574ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 575ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int wince_attach_kernel_driver( 576ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_device_handle *handle, 577ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int interface_number) 578ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 579ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct wince_device_priv *priv = _device_priv(handle->dev); 580ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!UkwAttachKernelDriver(priv->dev, interface_number)) { 581ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return translate_driver_error(GetLastError()); 582ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 583ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_SUCCESS; 584ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 585ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 586ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic void wince_destroy_device( 587ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_device *dev) 588ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 589ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct wince_device_priv *priv = _device_priv(dev); 590ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch UkwReleaseDeviceList(driver_handle, &priv->dev, 1); 591ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 592ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 593ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic void wince_clear_transfer_priv( 594ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct usbi_transfer *itransfer) 595ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 596ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct wince_transfer_priv *transfer_priv = (struct wince_transfer_priv*)usbi_transfer_get_os_priv(itransfer); 597ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct winfd wfd = fd_to_winfd(transfer_priv->pollable_fd.fd); 598ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // No need to cancel transfer as it is either complete or abandoned 599ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wfd.itransfer = NULL; 600ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseHandle(wfd.handle); 601ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_free_fd(&transfer_priv->pollable_fd); 602ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 603ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 604ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int wince_cancel_transfer( 605ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct usbi_transfer *itransfer) 606ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 607ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); 608ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct wince_device_priv *priv = _device_priv(transfer->dev_handle->dev); 609ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct wince_transfer_priv *transfer_priv = (struct wince_transfer_priv*)usbi_transfer_get_os_priv(itransfer); 610ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 611ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!UkwCancelTransfer(priv->dev, transfer_priv->pollable_fd.overlapped, UKW_TF_NO_WAIT)) { 612ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return translate_driver_error(GetLastError()); 613ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 614ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_SUCCESS; 615ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 616ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 617ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int wince_submit_control_or_bulk_transfer(struct usbi_transfer *itransfer) 618ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 619ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); 620ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev); 621ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct wince_transfer_priv *transfer_priv = (struct wince_transfer_priv*)usbi_transfer_get_os_priv(itransfer); 622ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct wince_device_priv *priv = _device_priv(transfer->dev_handle->dev); 623ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch BOOL direction_in, ret; 624ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct winfd wfd; 625ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DWORD flags; 626ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch HANDLE eventHandle; 627ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch PUKW_CONTROL_HEADER setup = NULL; 628ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const BOOL control_transfer = transfer->type == LIBUSB_TRANSFER_TYPE_CONTROL; 629ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 630ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch transfer_priv->pollable_fd = INVALID_WINFD; 631ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (control_transfer) { 632ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch setup = (PUKW_CONTROL_HEADER) transfer->buffer; 633ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch direction_in = setup->bmRequestType & LIBUSB_ENDPOINT_IN; 634ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } else { 635ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch direction_in = transfer->endpoint & LIBUSB_ENDPOINT_IN; 636ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 637ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch flags = direction_in ? UKW_TF_IN_TRANSFER : UKW_TF_OUT_TRANSFER; 638ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch flags |= UKW_TF_SHORT_TRANSFER_OK; 639ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 640ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch eventHandle = CreateEvent(NULL, FALSE, FALSE, NULL); 641ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (eventHandle == NULL) { 642ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_err(ctx, "Failed to create event for async transfer"); 643ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_ERROR_NO_MEM; 644ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 645ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 646ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wfd = usbi_create_fd(eventHandle, direction_in ? RW_READ : RW_WRITE, itransfer, &wince_cancel_transfer); 647ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (wfd.fd < 0) { 648ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CloseHandle(eventHandle); 649ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_ERROR_NO_MEM; 650ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 651ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 652ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch transfer_priv->pollable_fd = wfd; 653ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (control_transfer) { 654ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Split out control setup header and data buffer 655ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DWORD bufLen = transfer->length - sizeof(UKW_CONTROL_HEADER); 656ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch PVOID buf = (PVOID) &transfer->buffer[sizeof(UKW_CONTROL_HEADER)]; 657ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 658ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ret = UkwIssueControlTransfer(priv->dev, flags, setup, buf, bufLen, &transfer->actual_length, wfd.overlapped); 659ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } else { 660ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ret = UkwIssueBulkTransfer(priv->dev, flags, transfer->endpoint, transfer->buffer, 661ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch transfer->length, &transfer->actual_length, wfd.overlapped); 662ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 663ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!ret) { 664ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int libusbErr = translate_driver_error(GetLastError()); 665ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_err(ctx, "UkwIssue%sTransfer failed: error %d", 666ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch control_transfer ? "Control" : "Bulk", GetLastError()); 667ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_clear_transfer_priv(itransfer); 668ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return libusbErr; 669ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 670ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, direction_in ? POLLIN : POLLOUT); 671ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch itransfer->flags |= USBI_TRANSFER_UPDATED_FDS; 672ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 673ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_SUCCESS; 674ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 675ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 676ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int wince_submit_iso_transfer(struct usbi_transfer *itransfer) 677ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 678ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_ERROR_NOT_SUPPORTED; 679ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 680ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 681ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int wince_submit_transfer( 682ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct usbi_transfer *itransfer) 683ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 684ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); 685ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 686ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch switch (transfer->type) { 687ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case LIBUSB_TRANSFER_TYPE_CONTROL: 688ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case LIBUSB_TRANSFER_TYPE_BULK: 689ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case LIBUSB_TRANSFER_TYPE_INTERRUPT: 690ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return wince_submit_control_or_bulk_transfer(itransfer); 691ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: 692ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return wince_submit_iso_transfer(itransfer); 693ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch default: 694ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); 695ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_ERROR_INVALID_PARAM; 696ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 697ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 698ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 699ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic void wince_transfer_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size) 700ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 701ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); 702ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct wince_transfer_priv *transfer_priv = (struct wince_transfer_priv*)usbi_transfer_get_os_priv(itransfer); 703ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct wince_device_priv *priv = _device_priv(transfer->dev_handle->dev); 704ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int status; 705ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 706ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg("handling I/O completion with errcode %d", io_result); 707ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 708ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (io_result == ERROR_NOT_SUPPORTED && 709ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch transfer->type != LIBUSB_TRANSFER_TYPE_CONTROL) { 710ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* For functional stalls, the WinCE USB layer (and therefore the USB Kernel Wrapper 711ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * Driver) will report USB_ERROR_STALL/ERROR_NOT_SUPPORTED in situations where the 712ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * endpoint isn't actually stalled. 713ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * 714ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * One example of this is that some devices will occasionally fail to reply to an IN 715ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * token. The WinCE USB layer carries on with the transaction until it is completed 716ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * (or cancelled) but then completes it with USB_ERROR_STALL. 717ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * 718ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * This code therefore needs to confirm that there really is a stall error, by both 719ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * checking the pipe status and requesting the endpoint status from the device. 720ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch */ 721ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch BOOL halted = FALSE; 722ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg("checking I/O completion with errcode ERROR_NOT_SUPPORTED is really a stall"); 723ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (UkwIsPipeHalted(priv->dev, transfer->endpoint, &halted)) { 724ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch /* Pipe status retrieved, so now request endpoint status by sending a GET_STATUS 725ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * control request to the device. This is done synchronously, which is a bit 726ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * naughty, but this is a special corner case. 727ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch */ 728ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch WORD wStatus = 0; 729ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DWORD written = 0; 730ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch UKW_CONTROL_HEADER ctrlHeader; 731ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ctrlHeader.bmRequestType = LIBUSB_REQUEST_TYPE_STANDARD | 732ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch LIBUSB_ENDPOINT_IN | LIBUSB_RECIPIENT_ENDPOINT; 733ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ctrlHeader.bRequest = LIBUSB_REQUEST_GET_STATUS; 734ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ctrlHeader.wValue = 0; 735ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ctrlHeader.wIndex = transfer->endpoint; 736ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ctrlHeader.wLength = sizeof(wStatus); 737ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (UkwIssueControlTransfer(priv->dev, 738ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch UKW_TF_IN_TRANSFER | UKW_TF_SEND_TO_ENDPOINT, 739ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch &ctrlHeader, &wStatus, sizeof(wStatus), &written, NULL)) { 740ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (written == sizeof(wStatus) && 741ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (wStatus & STATUS_HALT_FLAG) == 0) { 742ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!halted || UkwClearHaltHost(priv->dev, transfer->endpoint)) { 743ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg("Endpoint doesn't appear to be stalled, overriding error with success"); 744ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch io_result = ERROR_SUCCESS; 745ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } else { 746ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg("Endpoint doesn't appear to be stalled, but the host is halted, changing error"); 747ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch io_result = ERROR_IO_DEVICE; 748ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 749ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 750ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 751ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 752ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 753ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 754ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch switch(io_result) { 755ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case ERROR_SUCCESS: 756ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch itransfer->transferred += io_size; 757ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch status = LIBUSB_TRANSFER_COMPLETED; 758ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 759ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case ERROR_CANCELLED: 760ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg("detected transfer cancel"); 761ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch status = LIBUSB_TRANSFER_CANCELLED; 762ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 763ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case ERROR_NOT_SUPPORTED: 764ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case ERROR_GEN_FAILURE: 765ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg("detected endpoint stall"); 766ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch status = LIBUSB_TRANSFER_STALL; 767ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 768ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case ERROR_SEM_TIMEOUT: 769ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg("detected semaphore timeout"); 770ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch status = LIBUSB_TRANSFER_TIMED_OUT; 771ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 772ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case ERROR_OPERATION_ABORTED: 773ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (itransfer->flags & USBI_TRANSFER_TIMED_OUT) { 774ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg("detected timeout"); 775ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch status = LIBUSB_TRANSFER_TIMED_OUT; 776ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } else { 777ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg("detected operation aborted"); 778ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch status = LIBUSB_TRANSFER_CANCELLED; 779ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 780ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 781ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch default: 782ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error: %s", windows_error_str(io_result)); 783ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch status = LIBUSB_TRANSFER_ERROR; 784ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 785ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 786ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_clear_transfer_priv(itransfer); 787ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (status == LIBUSB_TRANSFER_CANCELLED) { 788ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_handle_transfer_cancellation(itransfer); 789ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } else { 790ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status); 791ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 792ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 793ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 794ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic void wince_handle_callback (struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size) 795ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 796ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); 797ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 798ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch switch (transfer->type) { 799ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case LIBUSB_TRANSFER_TYPE_CONTROL: 800ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case LIBUSB_TRANSFER_TYPE_BULK: 801ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case LIBUSB_TRANSFER_TYPE_INTERRUPT: 802ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: 803ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_transfer_callback (itransfer, io_result, io_size); 804ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 805ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch default: 806ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type); 807ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 808ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 809ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 810ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int wince_handle_events( 811ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct libusb_context *ctx, 812ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) 813ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 814ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct wince_transfer_priv* transfer_priv = NULL; 815ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch POLL_NFDS_TYPE i = 0; 816ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch BOOL found = FALSE; 817ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct usbi_transfer *transfer; 818ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DWORD io_size, io_result; 819ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 820ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_mutex_lock(&ctx->open_devs_lock); 821ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch for (i = 0; i < nfds && num_ready > 0; i++) { 822ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 823ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents); 824ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 825ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!fds[i].revents) { 826ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch continue; 827ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 828ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 829ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch num_ready--; 830ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 831ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Because a Windows OVERLAPPED is used for poll emulation, 832ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // a pollable fd is created and stored with each transfer 833ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_mutex_lock(&ctx->flying_transfers_lock); 834ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) { 835ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch transfer_priv = usbi_transfer_get_os_priv(transfer); 836ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (transfer_priv->pollable_fd.fd == fds[i].fd) { 837ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch found = TRUE; 838ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 839ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 840ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 841ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_mutex_unlock(&ctx->flying_transfers_lock); 842ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 843ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (found && HasOverlappedIoCompleted(transfer_priv->pollable_fd.overlapped)) { 844ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch io_result = (DWORD)transfer_priv->pollable_fd.overlapped->Internal; 845ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch io_size = (DWORD)transfer_priv->pollable_fd.overlapped->InternalHigh; 846ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_remove_pollfd(ctx, transfer_priv->pollable_fd.fd); 847ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // let handle_callback free the event using the transfer wfd 848ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // If you don't use the transfer wfd, you run a risk of trying to free a 849ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // newly allocated wfd that took the place of the one from the transfer. 850ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_handle_callback(transfer, io_result, io_size); 851ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } else if (found) { 852ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_err(ctx, "matching transfer for fd %x has not completed", fds[i]); 853ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_ERROR_OTHER; 854ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } else { 855ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_err(ctx, "could not find a matching transfer for fd %x", fds[i]); 856ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_ERROR_NOT_FOUND; 857ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 858ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 859ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 860ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_mutex_unlock(&ctx->open_devs_lock); 861ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_SUCCESS; 862ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 863ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 864ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch/* 865ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * Monotonic and real time functions 866ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch */ 867ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochunsigned __stdcall wince_clock_gettime_threaded(void* param) 868ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 869ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch LARGE_INTEGER hires_counter, li_frequency; 870ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch LONG nb_responses; 871ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int timer_index; 872ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 873ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Init - find out if we have access to a monotonic (hires) timer 874ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!QueryPerformanceFrequency(&li_frequency)) { 875ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg("no hires timer available on this platform"); 876ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch hires_frequency = 0; 877ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch hires_ticks_to_ps = UINT64_C(0); 878ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } else { 879ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch hires_frequency = li_frequency.QuadPart; 880ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // The hires frequency can go as high as 4 GHz, so we'll use a conversion 881ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // to picoseconds to compute the tv_nsecs part in clock_gettime 882ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency; 883ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg("hires timer available (Frequency: %"PRIu64" Hz)", hires_frequency); 884ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 885ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 88668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Signal wince_init() that we're ready to service requests 88768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (ReleaseSemaphore(timer_response, 1, NULL) == 0) { 88868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) usbi_dbg("unable to release timer semaphore: %s", windows_error_str(0)); 88968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 89068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 891ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Main loop - wait for requests 892ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch while (1) { 893ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch timer_index = WaitForMultipleObjects(2, timer_request, FALSE, INFINITE) - WAIT_OBJECT_0; 894ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if ( (timer_index != 0) && (timer_index != 1) ) { 895ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg("failure to wait on requests: %s", windows_error_str(0)); 896ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch continue; 897ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 898ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (request_count[timer_index] == 0) { 899ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Request already handled 900ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ResetEvent(timer_request[timer_index]); 901ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // There's still a possiblity that a thread sends a request between the 902ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // time we test request_count[] == 0 and we reset the event, in which case 903ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // the request would be ignored. The simple solution to that is to test 904ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // request_count again and process requests if non zero. 905ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (request_count[timer_index] == 0) 906ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch continue; 907ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 908ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch switch (timer_index) { 909ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case 0: 910ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch WaitForSingleObject(timer_mutex, INFINITE); 911ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Requests to this thread are for hires always 912ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (QueryPerformanceCounter(&hires_counter) != 0) { 913ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch timer_tp.tv_sec = (long)(hires_counter.QuadPart / hires_frequency); 914ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch timer_tp.tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency)/1000) * hires_ticks_to_ps); 915ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } else { 916ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Fallback to real-time if we can't get monotonic value 917ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Note that real-time clock does not wait on the mutex or this thread. 918ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_clock_gettime(USBI_CLOCK_REALTIME, &timer_tp); 919ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 920ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ReleaseMutex(timer_mutex); 921ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 922ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch nb_responses = InterlockedExchange((LONG*)&request_count[0], 0); 923ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if ( (nb_responses) 924ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch && (ReleaseSemaphore(timer_response, nb_responses, NULL) == 0) ) { 92568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) usbi_dbg("unable to release timer semaphore: %s", windows_error_str(0)); 926ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 927ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch continue; 928ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case 1: // time to quit 929ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg("timer thread quitting"); 930ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return 0; 931ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 932ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 933ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg("ERROR: broken timer thread"); 934ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return 1; 935ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 936ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 937ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int wince_clock_gettime(int clk_id, struct timespec *tp) 938ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 939ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch FILETIME filetime; 940ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ULARGE_INTEGER rtime; 941ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DWORD r; 942ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch SYSTEMTIME st; 943ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch switch(clk_id) { 944ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case USBI_CLOCK_MONOTONIC: 945ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (hires_frequency != 0) { 946ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch while (1) { 947ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch InterlockedIncrement((LONG*)&request_count[0]); 948ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch SetEvent(timer_request[0]); 949ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch r = WaitForSingleObject(timer_response, TIMER_REQUEST_RETRY_MS); 950ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch switch(r) { 951ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case WAIT_OBJECT_0: 952ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch WaitForSingleObject(timer_mutex, INFINITE); 953ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch *tp = timer_tp; 954ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch ReleaseMutex(timer_mutex); 955ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_SUCCESS; 956ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case WAIT_TIMEOUT: 957ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg("could not obtain a timer value within reasonable timeframe - too much load?"); 958ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; // Retry until successful 959ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch default: 960ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg("WaitForSingleObject failed: %s", windows_error_str(0)); 961ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_ERROR_OTHER; 962ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 963ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 964ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 965ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Fall through and return real-time if monotonic was not detected @ timer init 966ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case USBI_CLOCK_REALTIME: 967ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // We follow http://msdn.microsoft.com/en-us/library/ms724928%28VS.85%29.aspx 968ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // with a predef epoch_time to have an epoch that starts at 1970.01.01 00:00 969ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Note however that our resolution is bounded by the Windows system time 970ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // functions and is at best of the order of 1 ms (or, usually, worse) 971ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch GetSystemTime(&st); 972ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch SystemTimeToFileTime(&st, &filetime); 973ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch rtime.LowPart = filetime.dwLowDateTime; 974ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch rtime.HighPart = filetime.dwHighDateTime; 975ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch rtime.QuadPart -= epoch_time; 976ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch tp->tv_sec = (long)(rtime.QuadPart / 10000000); 977ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch tp->tv_nsec = (long)((rtime.QuadPart % 10000000)*100); 978ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_SUCCESS; 979ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch default: 980ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return LIBUSB_ERROR_INVALID_PARAM; 981ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 982ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 983ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 984ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochconst struct usbi_os_backend wince_backend = { 985ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch "Windows CE", 986ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 0, 987ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_init, 988ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_exit, 989ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 990ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_get_device_list, 991ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch NULL, /* hotplug_poll */ 992ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_open, 993ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_close, 994ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 995ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_get_device_descriptor, 996ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_get_active_config_descriptor, 997ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_get_config_descriptor, 998ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch NULL, /* get_config_descriptor_by_value() */ 999ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1000ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_get_configuration, 1001ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_set_configuration, 1002ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_claim_interface, 1003ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_release_interface, 1004ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1005ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_set_interface_altsetting, 1006ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_clear_halt, 1007ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_reset_device, 1008ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1009ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_kernel_driver_active, 1010ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_detach_kernel_driver, 1011ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_attach_kernel_driver, 1012ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1013ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_destroy_device, 1014ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1015ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_submit_transfer, 1016ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_cancel_transfer, 1017ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_clear_transfer_priv, 1018ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1019ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_handle_events, 1020ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1021ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wince_clock_gettime, 1022ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch sizeof(struct wince_device_priv), 1023ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch sizeof(struct wince_device_handle_priv), 1024ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch sizeof(struct wince_transfer_priv), 1025ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 0, 1026ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}; 1027