2 * Windows CE backend for libusbx 1.0
3 * Copyright © 2011-2013 RealVNC Ltd.
4 * Large portions taken from Windows backend, which is
5 * Copyright © 2009-2010 Pete Batard <pbatard@gmail.com>
6 * With contributions from Michael Plante, Orin Eman et al.
7 * Parts of this code adapted from libusb-win32-v1 by Stephan Meyer
8 * Major code testing contribution by Xiaofan Chen
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
31 #include "wince_usb.h"
34 static int wince_clock_gettime(int clk_id
, struct timespec
*tp
);
35 unsigned __stdcall
wince_clock_gettime_threaded(void* param
);
38 uint64_t hires_frequency
, hires_ticks_to_ps
;
40 const uint64_t epoch_time
= UINT64_C(116444736000000000); // 1970.01.01 00:00:000 in MS Filetime
41 enum windows_version windows_version
= WINDOWS_CE
;
42 static int concurrent_usage
= -1;
44 // NB: index 0 is for monotonic and 1 is for the thread exit event
45 HANDLE timer_thread
= NULL
;
46 HANDLE timer_mutex
= NULL
;
47 struct timespec timer_tp
;
48 volatile LONG request_count
[2] = {0, 1}; // last one must be > 0
49 HANDLE timer_request
[2] = { NULL
, NULL
};
50 HANDLE timer_response
= NULL
;
51 HANDLE driver_handle
= INVALID_HANDLE_VALUE
;
54 * Converts a windows error to human readable string
55 * uses retval as errorcode, or, if 0, use GetLastError()
57 #if defined(ENABLE_LOGGING)
58 static char* windows_error_str(uint32_t retval
)
60 static TCHAR wErr_string
[ERR_BUFFER_SIZE
];
61 static char err_string
[ERR_BUFFER_SIZE
];
65 uint32_t error_code
, format_error
;
67 error_code
= retval
?retval
:GetLastError();
69 safe_stprintf(wErr_string
, ERR_BUFFER_SIZE
, _T("[%d] "), error_code
);
71 size
= FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
, NULL
, error_code
,
72 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
), &wErr_string
[safe_tcslen(wErr_string
)],
73 ERR_BUFFER_SIZE
- (DWORD
)safe_tcslen(wErr_string
), NULL
);
75 format_error
= GetLastError();
77 safe_stprintf(wErr_string
, ERR_BUFFER_SIZE
,
78 _T("Windows error code %u (FormatMessage error code %u)"), error_code
, format_error
);
80 safe_stprintf(wErr_string
, ERR_BUFFER_SIZE
, _T("Unknown error code %u"), error_code
);
82 // Remove CR/LF terminators
83 for (i
=safe_tcslen(wErr_string
)-1; ((wErr_string
[i
]==0x0A) || (wErr_string
[i
]==0x0D)); i
--) {
87 if (WideCharToMultiByte(CP_ACP
, 0, wErr_string
, -1, err_string
, ERR_BUFFER_SIZE
, NULL
, NULL
) < 0)
89 strcpy(err_string
, "Unable to convert error string");
95 static struct wince_device_priv
*_device_priv(struct libusb_device
*dev
)
97 return (struct wince_device_priv
*) dev
->os_priv
;
100 // ceusbkwrapper to libusb error code mapping
101 static int translate_driver_error(int error
)
104 case ERROR_INVALID_PARAMETER
:
105 return LIBUSB_ERROR_INVALID_PARAM
;
106 case ERROR_CALL_NOT_IMPLEMENTED
:
107 case ERROR_NOT_SUPPORTED
:
108 return LIBUSB_ERROR_NOT_SUPPORTED
;
109 case ERROR_NOT_ENOUGH_MEMORY
:
110 return LIBUSB_ERROR_NO_MEM
;
111 case ERROR_INVALID_HANDLE
:
112 return LIBUSB_ERROR_NO_DEVICE
;
114 return LIBUSB_ERROR_BUSY
;
116 // Error codes that are either unexpected, or have
117 // no suitable LIBUSB_ERROR equivilant.
118 case ERROR_CANCELLED
:
119 case ERROR_INTERNAL_ERROR
:
121 return LIBUSB_ERROR_OTHER
;
125 static int init_dllimports()
127 DLL_LOAD(ceusbkwrapper
.dll
, UkwOpenDriver
, TRUE
);
128 DLL_LOAD(ceusbkwrapper
.dll
, UkwGetDeviceList
, TRUE
);
129 DLL_LOAD(ceusbkwrapper
.dll
, UkwReleaseDeviceList
, TRUE
);
130 DLL_LOAD(ceusbkwrapper
.dll
, UkwGetDeviceAddress
, TRUE
);
131 DLL_LOAD(ceusbkwrapper
.dll
, UkwGetDeviceDescriptor
, TRUE
);
132 DLL_LOAD(ceusbkwrapper
.dll
, UkwGetConfigDescriptor
, TRUE
);
133 DLL_LOAD(ceusbkwrapper
.dll
, UkwCloseDriver
, TRUE
);
134 DLL_LOAD(ceusbkwrapper
.dll
, UkwCancelTransfer
, TRUE
);
135 DLL_LOAD(ceusbkwrapper
.dll
, UkwIssueControlTransfer
, TRUE
);
136 DLL_LOAD(ceusbkwrapper
.dll
, UkwClaimInterface
, TRUE
);
137 DLL_LOAD(ceusbkwrapper
.dll
, UkwReleaseInterface
, TRUE
);
138 DLL_LOAD(ceusbkwrapper
.dll
, UkwSetInterfaceAlternateSetting
, TRUE
);
139 DLL_LOAD(ceusbkwrapper
.dll
, UkwClearHaltHost
, TRUE
);
140 DLL_LOAD(ceusbkwrapper
.dll
, UkwClearHaltDevice
, TRUE
);
141 DLL_LOAD(ceusbkwrapper
.dll
, UkwGetConfig
, TRUE
);
142 DLL_LOAD(ceusbkwrapper
.dll
, UkwSetConfig
, TRUE
);
143 DLL_LOAD(ceusbkwrapper
.dll
, UkwResetDevice
, TRUE
);
144 DLL_LOAD(ceusbkwrapper
.dll
, UkwKernelDriverActive
, TRUE
);
145 DLL_LOAD(ceusbkwrapper
.dll
, UkwAttachKernelDriver
, TRUE
);
146 DLL_LOAD(ceusbkwrapper
.dll
, UkwDetachKernelDriver
, TRUE
);
147 DLL_LOAD(ceusbkwrapper
.dll
, UkwIssueBulkTransfer
, TRUE
);
148 DLL_LOAD(ceusbkwrapper
.dll
, UkwIsPipeHalted
, TRUE
);
149 return LIBUSB_SUCCESS
;
152 static int init_device(struct libusb_device
*dev
, UKW_DEVICE drv_dev
,
153 unsigned char bus_addr
, unsigned char dev_addr
)
155 struct wince_device_priv
*priv
= _device_priv(dev
);
156 int r
= LIBUSB_SUCCESS
;
158 dev
->bus_number
= bus_addr
;
159 dev
->device_address
= dev_addr
;
162 if (!UkwGetDeviceDescriptor(priv
->dev
, &(priv
->desc
))) {
163 r
= translate_driver_error(GetLastError());
168 // Internal API functions
169 static int wince_init(struct libusb_context
*ctx
)
171 int i
, r
= LIBUSB_ERROR_OTHER
;
173 TCHAR sem_name
[11+1+8]; // strlen(libusb_init)+'\0'+(32-bit hex PID)
175 _stprintf(sem_name
, _T("libusb_init%08X"), (unsigned int)GetCurrentProcessId()&0xFFFFFFFF);
176 semaphore
= CreateSemaphore(NULL
, 1, 1, sem_name
);
177 if (semaphore
== NULL
) {
178 usbi_err(ctx
, "could not create semaphore: %s", windows_error_str(0));
179 return LIBUSB_ERROR_NO_MEM
;
182 // A successful wait brings our semaphore count to 0 (unsignaled)
183 // => any concurent wait stalls until the semaphore's release
184 if (WaitForSingleObject(semaphore
, INFINITE
) != WAIT_OBJECT_0
) {
185 usbi_err(ctx
, "failure to access semaphore: %s", windows_error_str(0));
186 CloseHandle(semaphore
);
187 return LIBUSB_ERROR_NO_MEM
;
190 // NB: concurrent usage supposes that init calls are equally balanced with
191 // exit calls. If init is called more than exit, we will not exit properly
192 if ( ++concurrent_usage
== 0 ) { // First init?
193 // Initialize pollable file descriptors
197 if (init_dllimports() != LIBUSB_SUCCESS
) {
198 usbi_err(ctx
, "could not resolve DLL functions");
199 r
= LIBUSB_ERROR_NOT_SUPPORTED
;
203 // try to open a handle to the driver
204 driver_handle
= UkwOpenDriver();
205 if (driver_handle
== INVALID_HANDLE_VALUE
) {
206 usbi_err(ctx
, "could not connect to driver");
207 r
= LIBUSB_ERROR_NOT_SUPPORTED
;
211 // Windows CE doesn't have a way of specifying thread affinity, so this code
212 // just has to hope QueryPerformanceCounter doesn't report different values when
213 // running on different cores.
214 r
= LIBUSB_ERROR_NO_MEM
;
215 for (i
= 0; i
< 2; i
++) {
216 timer_request
[i
] = CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
217 if (timer_request
[i
] == NULL
) {
218 usbi_err(ctx
, "could not create timer request event %d - aborting", i
);
222 timer_response
= CreateSemaphore(NULL
, 0, MAX_TIMER_SEMAPHORES
, NULL
);
223 if (timer_response
== NULL
) {
224 usbi_err(ctx
, "could not create timer response semaphore - aborting");
227 timer_mutex
= CreateMutex(NULL
, FALSE
, NULL
);
228 if (timer_mutex
== NULL
) {
229 usbi_err(ctx
, "could not create timer mutex - aborting");
232 timer_thread
= CreateThread(NULL
, 0, wince_clock_gettime_threaded
, NULL
, 0, NULL
);
233 if (timer_thread
== NULL
) {
234 usbi_err(ctx
, "Unable to create timer thread - aborting");
238 // Wait for timer thread to init before continuing.
239 if (WaitForSingleObject(timer_response
, INFINITE
) != WAIT_OBJECT_0
) {
240 usbi_err(ctx
, "Failed to wait for timer thread to become ready - aborting");
244 // At this stage, either we went through full init successfully, or didn't need to
247 init_exit
: // Holds semaphore here.
248 if (!concurrent_usage
&& r
!= LIBUSB_SUCCESS
) { // First init failed?
249 if (driver_handle
!= INVALID_HANDLE_VALUE
) {
250 UkwCloseDriver(driver_handle
);
251 driver_handle
= INVALID_HANDLE_VALUE
;
254 SetEvent(timer_request
[1]); // actually the signal to quit the thread.
255 if (WAIT_OBJECT_0
!= WaitForSingleObject(timer_thread
, INFINITE
)) {
256 usbi_warn(ctx
, "could not wait for timer thread to quit");
257 TerminateThread(timer_thread
, 1); // shouldn't happen, but we're destroying
258 // all objects it might have held anyway.
260 CloseHandle(timer_thread
);
263 for (i
= 0; i
< 2; i
++) {
264 if (timer_request
[i
]) {
265 CloseHandle(timer_request
[i
]);
266 timer_request
[i
] = NULL
;
269 if (timer_response
) {
270 CloseHandle(timer_response
);
271 timer_response
= NULL
;
274 CloseHandle(timer_mutex
);
279 if (r
!= LIBUSB_SUCCESS
)
280 --concurrent_usage
; // Not expected to call libusb_exit if we failed.
282 ReleaseSemaphore(semaphore
, 1, NULL
); // increase count back to 1
283 CloseHandle(semaphore
);
287 static void wince_exit(void)
291 TCHAR sem_name
[11+1+8]; // strlen(libusb_init)+'\0'+(32-bit hex PID)
293 _stprintf(sem_name
, _T("libusb_init%08X"), (unsigned int)GetCurrentProcessId()&0xFFFFFFFF);
294 semaphore
= CreateSemaphore(NULL
, 1, 1, sem_name
);
295 if (semaphore
== NULL
) {
299 // A successful wait brings our semaphore count to 0 (unsignaled)
300 // => any concurent wait stalls until the semaphore release
301 if (WaitForSingleObject(semaphore
, INFINITE
) != WAIT_OBJECT_0
) {
302 CloseHandle(semaphore
);
306 // Only works if exits and inits are balanced exactly
307 if (--concurrent_usage
< 0) { // Last exit
311 SetEvent(timer_request
[1]); // actually the signal to quit the thread.
312 if (WAIT_OBJECT_0
!= WaitForSingleObject(timer_thread
, INFINITE
)) {
313 usbi_dbg("could not wait for timer thread to quit");
314 TerminateThread(timer_thread
, 1);
316 CloseHandle(timer_thread
);
319 for (i
= 0; i
< 2; i
++) {
320 if (timer_request
[i
]) {
321 CloseHandle(timer_request
[i
]);
322 timer_request
[i
] = NULL
;
325 if (timer_response
) {
326 CloseHandle(timer_response
);
327 timer_response
= NULL
;
330 CloseHandle(timer_mutex
);
333 if (driver_handle
!= INVALID_HANDLE_VALUE
) {
334 UkwCloseDriver(driver_handle
);
335 driver_handle
= INVALID_HANDLE_VALUE
;
339 ReleaseSemaphore(semaphore
, 1, NULL
); // increase count back to 1
340 CloseHandle(semaphore
);
343 static int wince_get_device_list(
344 struct libusb_context
*ctx
,
345 struct discovered_devs
**discdevs
)
347 UKW_DEVICE devices
[MAX_DEVICE_COUNT
];
348 struct discovered_devs
* new_devices
= *discdevs
;
350 struct libusb_device
*dev
= NULL
;
351 unsigned char bus_addr
, dev_addr
;
352 unsigned long session_id
;
354 DWORD release_list_offset
= 0;
355 int r
= LIBUSB_SUCCESS
;
357 success
= UkwGetDeviceList(driver_handle
, devices
, MAX_DEVICE_COUNT
, &count
);
359 int libusbErr
= translate_driver_error(GetLastError());
360 usbi_err(ctx
, "could not get devices: %s", windows_error_str(0));
363 for(i
= 0; i
< count
; ++i
) {
364 release_list_offset
= i
;
365 success
= UkwGetDeviceAddress(devices
[i
], &bus_addr
, &dev_addr
, &session_id
);
367 r
= translate_driver_error(GetLastError());
368 usbi_err(ctx
, "could not get device address for %d: %s", i
, windows_error_str(0));
371 dev
= usbi_get_device_by_session_id(ctx
, session_id
);
373 usbi_dbg("using existing device for %d/%d (session %ld)",
374 bus_addr
, dev_addr
, session_id
);
375 // Release just this element in the device list (as we already hold a
377 UkwReleaseDeviceList(driver_handle
, &devices
[i
], 1);
378 release_list_offset
++;
380 usbi_dbg("allocating new device for %d/%d (session %ld)",
381 bus_addr
, dev_addr
, session_id
);
382 dev
= usbi_alloc_device(ctx
, session_id
);
384 r
= LIBUSB_ERROR_NO_MEM
;
387 r
= init_device(dev
, devices
[i
], bus_addr
, dev_addr
);
390 r
= usbi_sanitize_device(dev
);
394 new_devices
= discovered_devs_append(new_devices
, dev
);
396 r
= LIBUSB_ERROR_NO_MEM
;
399 safe_unref_device(dev
);
401 *discdevs
= new_devices
;
404 *discdevs
= new_devices
;
405 safe_unref_device(dev
);
406 // Release the remainder of the unprocessed device list.
407 // The devices added to new_devices already will still be passed up to libusb,
408 // which can dispose of them at its leisure.
409 UkwReleaseDeviceList(driver_handle
, &devices
[release_list_offset
], count
- release_list_offset
);
413 static int wince_open(struct libusb_device_handle
*handle
)
415 // Nothing to do to open devices as a handle to it has
416 // been retrieved by wince_get_device_list
417 return LIBUSB_SUCCESS
;
420 static void wince_close(struct libusb_device_handle
*handle
)
422 // Nothing to do as wince_open does nothing.
425 static int wince_get_device_descriptor(
426 struct libusb_device
*device
,
427 unsigned char *buffer
, int *host_endian
)
429 struct wince_device_priv
*priv
= _device_priv(device
);
432 memcpy(buffer
, &priv
->desc
, DEVICE_DESC_LENGTH
);
433 return LIBUSB_SUCCESS
;
436 static int wince_get_active_config_descriptor(
437 struct libusb_device
*device
,
438 unsigned char *buffer
, size_t len
, int *host_endian
)
440 struct wince_device_priv
*priv
= _device_priv(device
);
441 DWORD actualSize
= len
;
443 if (!UkwGetConfigDescriptor(priv
->dev
, UKW_ACTIVE_CONFIGURATION
, buffer
, len
, &actualSize
)) {
444 return translate_driver_error(GetLastError());
449 static int wince_get_config_descriptor(
450 struct libusb_device
*device
,
451 uint8_t config_index
,
452 unsigned char *buffer
, size_t len
, int *host_endian
)
454 struct wince_device_priv
*priv
= _device_priv(device
);
455 DWORD actualSize
= len
;
457 if (!UkwGetConfigDescriptor(priv
->dev
, config_index
, buffer
, len
, &actualSize
)) {
458 return translate_driver_error(GetLastError());
463 static int wince_get_configuration(
464 struct libusb_device_handle
*handle
,
467 struct wince_device_priv
*priv
= _device_priv(handle
->dev
);
469 if (!UkwGetConfig(priv
->dev
, &cv
)) {
470 return translate_driver_error(GetLastError());
473 return LIBUSB_SUCCESS
;
476 static int wince_set_configuration(
477 struct libusb_device_handle
*handle
,
480 struct wince_device_priv
*priv
= _device_priv(handle
->dev
);
481 // Setting configuration 0 places the device in Address state.
482 // This should correspond to the "unconfigured state" required by
483 // libusb when the specified configuration is -1.
484 UCHAR cv
= (config
< 0) ? 0 : config
;
485 if (!UkwSetConfig(priv
->dev
, cv
)) {
486 return translate_driver_error(GetLastError());
488 return LIBUSB_SUCCESS
;
491 static int wince_claim_interface(
492 struct libusb_device_handle
*handle
,
493 int interface_number
)
495 struct wince_device_priv
*priv
= _device_priv(handle
->dev
);
496 if (!UkwClaimInterface(priv
->dev
, interface_number
)) {
497 return translate_driver_error(GetLastError());
499 return LIBUSB_SUCCESS
;
502 static int wince_release_interface(
503 struct libusb_device_handle
*handle
,
504 int interface_number
)
506 struct wince_device_priv
*priv
= _device_priv(handle
->dev
);
507 if (!UkwSetInterfaceAlternateSetting(priv
->dev
, interface_number
, 0)) {
508 return translate_driver_error(GetLastError());
510 if (!UkwReleaseInterface(priv
->dev
, interface_number
)) {
511 return translate_driver_error(GetLastError());
513 return LIBUSB_SUCCESS
;
516 static int wince_set_interface_altsetting(
517 struct libusb_device_handle
*handle
,
518 int interface_number
, int altsetting
)
520 struct wince_device_priv
*priv
= _device_priv(handle
->dev
);
521 if (!UkwSetInterfaceAlternateSetting(priv
->dev
, interface_number
, altsetting
)) {
522 return translate_driver_error(GetLastError());
524 return LIBUSB_SUCCESS
;
527 static int wince_clear_halt(
528 struct libusb_device_handle
*handle
,
529 unsigned char endpoint
)
531 struct wince_device_priv
*priv
= _device_priv(handle
->dev
);
532 if (!UkwClearHaltHost(priv
->dev
, endpoint
)) {
533 return translate_driver_error(GetLastError());
535 if (!UkwClearHaltDevice(priv
->dev
, endpoint
)) {
536 return translate_driver_error(GetLastError());
538 return LIBUSB_SUCCESS
;
541 static int wince_reset_device(
542 struct libusb_device_handle
*handle
)
544 struct wince_device_priv
*priv
= _device_priv(handle
->dev
);
545 if (!UkwResetDevice(priv
->dev
)) {
546 return translate_driver_error(GetLastError());
548 return LIBUSB_SUCCESS
;
551 static int wince_kernel_driver_active(
552 struct libusb_device_handle
*handle
,
553 int interface_number
)
555 struct wince_device_priv
*priv
= _device_priv(handle
->dev
);
557 if (!UkwKernelDriverActive(priv
->dev
, interface_number
, &result
)) {
558 return translate_driver_error(GetLastError());
560 return result
? 1 : 0;
563 static int wince_detach_kernel_driver(
564 struct libusb_device_handle
*handle
,
565 int interface_number
)
567 struct wince_device_priv
*priv
= _device_priv(handle
->dev
);
568 if (!UkwDetachKernelDriver(priv
->dev
, interface_number
)) {
569 return translate_driver_error(GetLastError());
571 return LIBUSB_SUCCESS
;
574 static int wince_attach_kernel_driver(
575 struct libusb_device_handle
*handle
,
576 int interface_number
)
578 struct wince_device_priv
*priv
= _device_priv(handle
->dev
);
579 if (!UkwAttachKernelDriver(priv
->dev
, interface_number
)) {
580 return translate_driver_error(GetLastError());
582 return LIBUSB_SUCCESS
;
585 static void wince_destroy_device(
586 struct libusb_device
*dev
)
588 struct wince_device_priv
*priv
= _device_priv(dev
);
589 UkwReleaseDeviceList(driver_handle
, &priv
->dev
, 1);
592 static void wince_clear_transfer_priv(
593 struct usbi_transfer
*itransfer
)
595 struct wince_transfer_priv
*transfer_priv
= (struct wince_transfer_priv
*)usbi_transfer_get_os_priv(itransfer
);
596 struct winfd wfd
= fd_to_winfd(transfer_priv
->pollable_fd
.fd
);
597 // No need to cancel transfer as it is either complete or abandoned
598 wfd
.itransfer
= NULL
;
599 CloseHandle(wfd
.handle
);
600 usbi_free_fd(&transfer_priv
->pollable_fd
);
603 static int wince_cancel_transfer(
604 struct usbi_transfer
*itransfer
)
606 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
607 struct wince_device_priv
*priv
= _device_priv(transfer
->dev_handle
->dev
);
608 struct wince_transfer_priv
*transfer_priv
= (struct wince_transfer_priv
*)usbi_transfer_get_os_priv(itransfer
);
610 if (!UkwCancelTransfer(priv
->dev
, transfer_priv
->pollable_fd
.overlapped
, UKW_TF_NO_WAIT
)) {
611 return translate_driver_error(GetLastError());
613 return LIBUSB_SUCCESS
;
616 static int wince_submit_control_or_bulk_transfer(struct usbi_transfer
*itransfer
)
618 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
619 struct libusb_context
*ctx
= DEVICE_CTX(transfer
->dev_handle
->dev
);
620 struct wince_transfer_priv
*transfer_priv
= (struct wince_transfer_priv
*)usbi_transfer_get_os_priv(itransfer
);
621 struct wince_device_priv
*priv
= _device_priv(transfer
->dev_handle
->dev
);
622 BOOL direction_in
, ret
;
626 PUKW_CONTROL_HEADER setup
= NULL
;
627 const BOOL control_transfer
= transfer
->type
== LIBUSB_TRANSFER_TYPE_CONTROL
;
629 transfer_priv
->pollable_fd
= INVALID_WINFD
;
630 if (control_transfer
) {
631 setup
= (PUKW_CONTROL_HEADER
) transfer
->buffer
;
632 direction_in
= setup
->bmRequestType
& LIBUSB_ENDPOINT_IN
;
634 direction_in
= transfer
->endpoint
& LIBUSB_ENDPOINT_IN
;
636 flags
= direction_in
? UKW_TF_IN_TRANSFER
: UKW_TF_OUT_TRANSFER
;
637 flags
|= UKW_TF_SHORT_TRANSFER_OK
;
639 eventHandle
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
640 if (eventHandle
== NULL
) {
641 usbi_err(ctx
, "Failed to create event for async transfer");
642 return LIBUSB_ERROR_NO_MEM
;
645 wfd
= usbi_create_fd(eventHandle
, direction_in
? RW_READ
: RW_WRITE
, itransfer
, &wince_cancel_transfer
);
647 CloseHandle(eventHandle
);
648 return LIBUSB_ERROR_NO_MEM
;
651 transfer_priv
->pollable_fd
= wfd
;
652 if (control_transfer
) {
653 // Split out control setup header and data buffer
654 DWORD bufLen
= transfer
->length
- sizeof(UKW_CONTROL_HEADER
);
655 PVOID buf
= (PVOID
) &transfer
->buffer
[sizeof(UKW_CONTROL_HEADER
)];
657 ret
= UkwIssueControlTransfer(priv
->dev
, flags
, setup
, buf
, bufLen
, &transfer
->actual_length
, wfd
.overlapped
);
659 ret
= UkwIssueBulkTransfer(priv
->dev
, flags
, transfer
->endpoint
, transfer
->buffer
,
660 transfer
->length
, &transfer
->actual_length
, wfd
.overlapped
);
663 int libusbErr
= translate_driver_error(GetLastError());
664 usbi_err(ctx
, "UkwIssue%sTransfer failed: error %d",
665 control_transfer
? "Control" : "Bulk", GetLastError());
666 wince_clear_transfer_priv(itransfer
);
669 usbi_add_pollfd(ctx
, transfer_priv
->pollable_fd
.fd
, direction_in
? POLLIN
: POLLOUT
);
670 itransfer
->flags
|= USBI_TRANSFER_UPDATED_FDS
;
672 return LIBUSB_SUCCESS
;
675 static int wince_submit_iso_transfer(struct usbi_transfer
*itransfer
)
677 return LIBUSB_ERROR_NOT_SUPPORTED
;
680 static int wince_submit_transfer(
681 struct usbi_transfer
*itransfer
)
683 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
685 switch (transfer
->type
) {
686 case LIBUSB_TRANSFER_TYPE_CONTROL
:
687 case LIBUSB_TRANSFER_TYPE_BULK
:
688 case LIBUSB_TRANSFER_TYPE_INTERRUPT
:
689 return wince_submit_control_or_bulk_transfer(itransfer
);
690 case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS
:
691 return wince_submit_iso_transfer(itransfer
);
693 usbi_err(TRANSFER_CTX(transfer
), "unknown endpoint type %d", transfer
->type
);
694 return LIBUSB_ERROR_INVALID_PARAM
;
698 static void wince_transfer_callback(struct usbi_transfer
*itransfer
, uint32_t io_result
, uint32_t io_size
)
700 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
701 struct wince_transfer_priv
*transfer_priv
= (struct wince_transfer_priv
*)usbi_transfer_get_os_priv(itransfer
);
702 struct wince_device_priv
*priv
= _device_priv(transfer
->dev_handle
->dev
);
705 usbi_dbg("handling I/O completion with errcode %d", io_result
);
707 if (io_result
== ERROR_NOT_SUPPORTED
&&
708 transfer
->type
!= LIBUSB_TRANSFER_TYPE_CONTROL
) {
709 /* For functional stalls, the WinCE USB layer (and therefore the USB Kernel Wrapper
710 * Driver) will report USB_ERROR_STALL/ERROR_NOT_SUPPORTED in situations where the
711 * endpoint isn't actually stalled.
713 * One example of this is that some devices will occasionally fail to reply to an IN
714 * token. The WinCE USB layer carries on with the transaction until it is completed
715 * (or cancelled) but then completes it with USB_ERROR_STALL.
717 * This code therefore needs to confirm that there really is a stall error, by both
718 * checking the pipe status and requesting the endpoint status from the device.
721 usbi_dbg("checking I/O completion with errcode ERROR_NOT_SUPPORTED is really a stall");
722 if (UkwIsPipeHalted(priv
->dev
, transfer
->endpoint
, &halted
)) {
723 /* Pipe status retrieved, so now request endpoint status by sending a GET_STATUS
724 * control request to the device. This is done synchronously, which is a bit
725 * naughty, but this is a special corner case.
729 UKW_CONTROL_HEADER ctrlHeader
;
730 ctrlHeader
.bmRequestType
= LIBUSB_REQUEST_TYPE_STANDARD
|
731 LIBUSB_ENDPOINT_IN
| LIBUSB_RECIPIENT_ENDPOINT
;
732 ctrlHeader
.bRequest
= LIBUSB_REQUEST_GET_STATUS
;
733 ctrlHeader
.wValue
= 0;
734 ctrlHeader
.wIndex
= transfer
->endpoint
;
735 ctrlHeader
.wLength
= sizeof(wStatus
);
736 if (UkwIssueControlTransfer(priv
->dev
,
737 UKW_TF_IN_TRANSFER
| UKW_TF_SEND_TO_ENDPOINT
,
738 &ctrlHeader
, &wStatus
, sizeof(wStatus
), &written
, NULL
)) {
739 if (written
== sizeof(wStatus
) &&
740 (wStatus
& STATUS_HALT_FLAG
) == 0) {
741 if (!halted
|| UkwClearHaltHost(priv
->dev
, transfer
->endpoint
)) {
742 usbi_dbg("Endpoint doesn't appear to be stalled, overriding error with success");
743 io_result
= ERROR_SUCCESS
;
745 usbi_dbg("Endpoint doesn't appear to be stalled, but the host is halted, changing error");
746 io_result
= ERROR_IO_DEVICE
;
755 itransfer
->transferred
+= io_size
;
756 status
= LIBUSB_TRANSFER_COMPLETED
;
758 case ERROR_CANCELLED
:
759 usbi_dbg("detected transfer cancel");
760 status
= LIBUSB_TRANSFER_CANCELLED
;
762 case ERROR_NOT_SUPPORTED
:
763 case ERROR_GEN_FAILURE
:
764 usbi_dbg("detected endpoint stall");
765 status
= LIBUSB_TRANSFER_STALL
;
767 case ERROR_SEM_TIMEOUT
:
768 usbi_dbg("detected semaphore timeout");
769 status
= LIBUSB_TRANSFER_TIMED_OUT
;
771 case ERROR_OPERATION_ABORTED
:
772 if (itransfer
->flags
& USBI_TRANSFER_TIMED_OUT
) {
773 usbi_dbg("detected timeout");
774 status
= LIBUSB_TRANSFER_TIMED_OUT
;
776 usbi_dbg("detected operation aborted");
777 status
= LIBUSB_TRANSFER_CANCELLED
;
781 usbi_err(ITRANSFER_CTX(itransfer
), "detected I/O error: %s", windows_error_str(io_result
));
782 status
= LIBUSB_TRANSFER_ERROR
;
785 wince_clear_transfer_priv(itransfer
);
786 if (status
== LIBUSB_TRANSFER_CANCELLED
) {
787 usbi_handle_transfer_cancellation(itransfer
);
789 usbi_handle_transfer_completion(itransfer
, (enum libusb_transfer_status
)status
);
793 static void wince_handle_callback (struct usbi_transfer
*itransfer
, uint32_t io_result
, uint32_t io_size
)
795 struct libusb_transfer
*transfer
= USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer
);
797 switch (transfer
->type
) {
798 case LIBUSB_TRANSFER_TYPE_CONTROL
:
799 case LIBUSB_TRANSFER_TYPE_BULK
:
800 case LIBUSB_TRANSFER_TYPE_INTERRUPT
:
801 case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS
:
802 wince_transfer_callback (itransfer
, io_result
, io_size
);
805 usbi_err(ITRANSFER_CTX(itransfer
), "unknown endpoint type %d", transfer
->type
);
809 static int wince_handle_events(
810 struct libusb_context
*ctx
,
811 struct pollfd
*fds
, POLL_NFDS_TYPE nfds
, int num_ready
)
813 struct wince_transfer_priv
* transfer_priv
= NULL
;
814 POLL_NFDS_TYPE i
= 0;
816 struct usbi_transfer
*transfer
;
817 DWORD io_size
, io_result
;
819 usbi_mutex_lock(&ctx
->open_devs_lock
);
820 for (i
= 0; i
< nfds
&& num_ready
> 0; i
++) {
822 usbi_dbg("checking fd %d with revents = %04x", fds
[i
].fd
, fds
[i
].revents
);
824 if (!fds
[i
].revents
) {
830 // Because a Windows OVERLAPPED is used for poll emulation,
831 // a pollable fd is created and stored with each transfer
832 usbi_mutex_lock(&ctx
->flying_transfers_lock
);
833 list_for_each_entry(transfer
, &ctx
->flying_transfers
, list
, struct usbi_transfer
) {
834 transfer_priv
= usbi_transfer_get_os_priv(transfer
);
835 if (transfer_priv
->pollable_fd
.fd
== fds
[i
].fd
) {
840 usbi_mutex_unlock(&ctx
->flying_transfers_lock
);
842 if (found
&& HasOverlappedIoCompleted(transfer_priv
->pollable_fd
.overlapped
)) {
843 io_result
= (DWORD
)transfer_priv
->pollable_fd
.overlapped
->Internal
;
844 io_size
= (DWORD
)transfer_priv
->pollable_fd
.overlapped
->InternalHigh
;
845 usbi_remove_pollfd(ctx
, transfer_priv
->pollable_fd
.fd
);
846 // let handle_callback free the event using the transfer wfd
847 // If you don't use the transfer wfd, you run a risk of trying to free a
848 // newly allocated wfd that took the place of the one from the transfer.
849 wince_handle_callback(transfer
, io_result
, io_size
);
851 usbi_err(ctx
, "matching transfer for fd %x has not completed", fds
[i
]);
852 return LIBUSB_ERROR_OTHER
;
854 usbi_err(ctx
, "could not find a matching transfer for fd %x", fds
[i
]);
855 return LIBUSB_ERROR_NOT_FOUND
;
859 usbi_mutex_unlock(&ctx
->open_devs_lock
);
860 return LIBUSB_SUCCESS
;
864 * Monotonic and real time functions
866 unsigned __stdcall
wince_clock_gettime_threaded(void* param
)
868 LARGE_INTEGER hires_counter
, li_frequency
;
872 // Init - find out if we have access to a monotonic (hires) timer
873 if (!QueryPerformanceFrequency(&li_frequency
)) {
874 usbi_dbg("no hires timer available on this platform");
876 hires_ticks_to_ps
= UINT64_C(0);
878 hires_frequency
= li_frequency
.QuadPart
;
879 // The hires frequency can go as high as 4 GHz, so we'll use a conversion
880 // to picoseconds to compute the tv_nsecs part in clock_gettime
881 hires_ticks_to_ps
= UINT64_C(1000000000000) / hires_frequency
;
882 usbi_dbg("hires timer available (Frequency: %"PRIu64
" Hz)", hires_frequency
);
885 // Signal wince_init() that we're ready to service requests
886 if (ReleaseSemaphore(timer_response
, 1, NULL
) == 0) {
887 usbi_dbg("unable to release timer semaphore: %s", windows_error_str(0));
890 // Main loop - wait for requests
892 timer_index
= WaitForMultipleObjects(2, timer_request
, FALSE
, INFINITE
) - WAIT_OBJECT_0
;
893 if ( (timer_index
!= 0) && (timer_index
!= 1) ) {
894 usbi_dbg("failure to wait on requests: %s", windows_error_str(0));
897 if (request_count
[timer_index
] == 0) {
898 // Request already handled
899 ResetEvent(timer_request
[timer_index
]);
900 // There's still a possiblity that a thread sends a request between the
901 // time we test request_count[] == 0 and we reset the event, in which case
902 // the request would be ignored. The simple solution to that is to test
903 // request_count again and process requests if non zero.
904 if (request_count
[timer_index
] == 0)
907 switch (timer_index
) {
909 WaitForSingleObject(timer_mutex
, INFINITE
);
910 // Requests to this thread are for hires always
911 if (QueryPerformanceCounter(&hires_counter
) != 0) {
912 timer_tp
.tv_sec
= (long)(hires_counter
.QuadPart
/ hires_frequency
);
913 timer_tp
.tv_nsec
= (long)(((hires_counter
.QuadPart
% hires_frequency
)/1000) * hires_ticks_to_ps
);
915 // Fallback to real-time if we can't get monotonic value
916 // Note that real-time clock does not wait on the mutex or this thread.
917 wince_clock_gettime(USBI_CLOCK_REALTIME
, &timer_tp
);
919 ReleaseMutex(timer_mutex
);
921 nb_responses
= InterlockedExchange((LONG
*)&request_count
[0], 0);
923 && (ReleaseSemaphore(timer_response
, nb_responses
, NULL
) == 0) ) {
924 usbi_dbg("unable to release timer semaphore: %s", windows_error_str(0));
927 case 1: // time to quit
928 usbi_dbg("timer thread quitting");
932 usbi_dbg("ERROR: broken timer thread");
936 static int wince_clock_gettime(int clk_id
, struct timespec
*tp
)
939 ULARGE_INTEGER rtime
;
943 case USBI_CLOCK_MONOTONIC
:
944 if (hires_frequency
!= 0) {
946 InterlockedIncrement((LONG
*)&request_count
[0]);
947 SetEvent(timer_request
[0]);
948 r
= WaitForSingleObject(timer_response
, TIMER_REQUEST_RETRY_MS
);
951 WaitForSingleObject(timer_mutex
, INFINITE
);
953 ReleaseMutex(timer_mutex
);
954 return LIBUSB_SUCCESS
;
956 usbi_dbg("could not obtain a timer value within reasonable timeframe - too much load?");
957 break; // Retry until successful
959 usbi_dbg("WaitForSingleObject failed: %s", windows_error_str(0));
960 return LIBUSB_ERROR_OTHER
;
964 // Fall through and return real-time if monotonic was not detected @ timer init
965 case USBI_CLOCK_REALTIME
:
966 // We follow http://msdn.microsoft.com/en-us/library/ms724928%28VS.85%29.aspx
967 // with a predef epoch_time to have an epoch that starts at 1970.01.01 00:00
968 // Note however that our resolution is bounded by the Windows system time
969 // functions and is at best of the order of 1 ms (or, usually, worse)
971 SystemTimeToFileTime(&st
, &filetime
);
972 rtime
.LowPart
= filetime
.dwLowDateTime
;
973 rtime
.HighPart
= filetime
.dwHighDateTime
;
974 rtime
.QuadPart
-= epoch_time
;
975 tp
->tv_sec
= (long)(rtime
.QuadPart
/ 10000000);
976 tp
->tv_nsec
= (long)((rtime
.QuadPart
% 10000000)*100);
977 return LIBUSB_SUCCESS
;
979 return LIBUSB_ERROR_INVALID_PARAM
;
983 const struct usbi_os_backend wince_backend
= {
989 wince_get_device_list
,
990 NULL
, /* hotplug_poll */
994 wince_get_device_descriptor
,
995 wince_get_active_config_descriptor
,
996 wince_get_config_descriptor
,
997 NULL
, /* get_config_descriptor_by_value() */
999 wince_get_configuration
,
1000 wince_set_configuration
,
1001 wince_claim_interface
,
1002 wince_release_interface
,
1004 wince_set_interface_altsetting
,
1008 wince_kernel_driver_active
,
1009 wince_detach_kernel_driver
,
1010 wince_attach_kernel_driver
,
1012 wince_destroy_device
,
1014 wince_submit_transfer
,
1015 wince_cancel_transfer
,
1016 wince_clear_transfer_priv
,
1018 wince_handle_events
,
1020 wince_clock_gettime
,
1021 sizeof(struct wince_device_priv
),
1022 sizeof(struct wince_device_handle_priv
),
1023 sizeof(struct wince_transfer_priv
),