|
|
|
@ -75,12 +75,59 @@ struct _ASYNC_TRANSFER_USER_DATA
|
|
|
|
|
UINT32 OutputBufferSize;
|
|
|
|
|
URBDRC_CHANNEL_CALLBACK* callback;
|
|
|
|
|
t_isoch_transfer_cb cb;
|
|
|
|
|
wHashTable* queue;
|
|
|
|
|
wArrayList* queue;
|
|
|
|
|
#if !defined(HAVE_STREAM_ID_API)
|
|
|
|
|
UINT32 streamID;
|
|
|
|
|
#endif
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static struct libusb_transfer* list_contains(wArrayList* list, UINT32 streamID)
|
|
|
|
|
{
|
|
|
|
|
int x, count;
|
|
|
|
|
if (!list)
|
|
|
|
|
return NULL;
|
|
|
|
|
count = ArrayList_Count(list);
|
|
|
|
|
for (x = 0; x < count; x++)
|
|
|
|
|
{
|
|
|
|
|
struct libusb_transfer* transfer = ArrayList_GetItem(list, x);
|
|
|
|
|
|
|
|
|
|
#if defined(HAVE_STREAM_ID_API)
|
|
|
|
|
const UINT32 currentID = libusb_transfer_get_stream_id(transfer);
|
|
|
|
|
#else
|
|
|
|
|
const ASYNC_TRANSFER_USER_DATA* user_data = (ASYNC_TRANSFER_USER_DATA*)transfer->user_data;
|
|
|
|
|
const UINT32 currentID = user_data->streamID;
|
|
|
|
|
#endif
|
|
|
|
|
if (currentID == streamID)
|
|
|
|
|
return transfer;
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static UINT32 stream_id_from_buffer(struct libusb_transfer* transfer)
|
|
|
|
|
{
|
|
|
|
|
if (!transfer)
|
|
|
|
|
return 0;
|
|
|
|
|
#if defined(HAVE_STREAM_ID_API)
|
|
|
|
|
return libusb_transfer_get_stream_id(transfer);
|
|
|
|
|
#else
|
|
|
|
|
ASYNC_TRANSFER_USER_DATA* user_data = (ASYNC_TRANSFER_USER_DATA*)transfer->user_data;
|
|
|
|
|
if (!user_data)
|
|
|
|
|
return 0;
|
|
|
|
|
return user_data->streamID;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void set_stream_id_for_buffer(struct libusb_transfer* transfer, UINT32 streamID)
|
|
|
|
|
{
|
|
|
|
|
#if defined(HAVE_STREAM_ID_API)
|
|
|
|
|
libusb_transfer_set_stream_id(transfer, streamID);
|
|
|
|
|
#else
|
|
|
|
|
ASYNC_TRANSFER_USER_DATA* user_data = (ASYNC_TRANSFER_USER_DATA*)transfer->user_data;
|
|
|
|
|
if (!user_data)
|
|
|
|
|
return;
|
|
|
|
|
user_data->streamID = streamID;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
static BOOL log_libusb_result(wLog* log, DWORD lvl, const char* fmt, int error, ...)
|
|
|
|
|
{
|
|
|
|
|
if (error < 0)
|
|
|
|
@ -176,7 +223,6 @@ static ASYNC_TRANSFER_USER_DATA* async_transfer_user_data_new(IUDEVICE* idev, UI
|
|
|
|
|
|
|
|
|
|
static void async_transfer_user_data_free(ASYNC_TRANSFER_USER_DATA* user_data)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if (user_data)
|
|
|
|
|
{
|
|
|
|
|
Stream_Free(user_data->data, TRUE);
|
|
|
|
@ -187,15 +233,12 @@ static void async_transfer_user_data_free(ASYNC_TRANSFER_USER_DATA* user_data)
|
|
|
|
|
static void func_iso_callback(struct libusb_transfer* transfer)
|
|
|
|
|
{
|
|
|
|
|
ASYNC_TRANSFER_USER_DATA* user_data = (ASYNC_TRANSFER_USER_DATA*)transfer->user_data;
|
|
|
|
|
#if defined(HAVE_STREAM_ID_API)
|
|
|
|
|
const UINT32 streamID = libusb_transfer_get_stream_id(transfer);
|
|
|
|
|
#else
|
|
|
|
|
const UINT32 streamID = user_data->streamID;
|
|
|
|
|
#endif
|
|
|
|
|
const UINT32 streamID = stream_id_from_buffer(transfer);
|
|
|
|
|
wArrayList* list = user_data->queue;
|
|
|
|
|
|
|
|
|
|
ArrayList_Lock(list);
|
|
|
|
|
switch (transfer->status)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
case LIBUSB_TRANSFER_COMPLETED:
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
@ -235,7 +278,7 @@ static void func_iso_callback(struct libusb_transfer* transfer)
|
|
|
|
|
const UINT32 InterfaceId =
|
|
|
|
|
((STREAM_ID_PROXY << 30) | user_data->idev->get_ReqCompletion(user_data->idev));
|
|
|
|
|
|
|
|
|
|
if (HashTable_Contains(user_data->queue, (void*)(size_t)streamID))
|
|
|
|
|
if (list_contains(list, streamID))
|
|
|
|
|
{
|
|
|
|
|
if (!user_data->noack)
|
|
|
|
|
{
|
|
|
|
@ -247,13 +290,14 @@ static void func_iso_callback(struct libusb_transfer* transfer)
|
|
|
|
|
user_data->OutputBufferSize);
|
|
|
|
|
user_data->data = NULL;
|
|
|
|
|
}
|
|
|
|
|
HashTable_Remove(user_data->queue, (void*)(size_t)streamID);
|
|
|
|
|
ArrayList_Remove(list, transfer);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
ArrayList_Unlock(list);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const LIBUSB_ENDPOINT_DESCEIPTOR* func_get_ep_desc(LIBUSB_CONFIG_DESCRIPTOR* LibusbConfig,
|
|
|
|
@ -289,6 +333,7 @@ static void func_bulk_transfer_cb(struct libusb_transfer* transfer)
|
|
|
|
|
{
|
|
|
|
|
ASYNC_TRANSFER_USER_DATA* user_data;
|
|
|
|
|
uint32_t streamID;
|
|
|
|
|
wArrayList* list;
|
|
|
|
|
|
|
|
|
|
user_data = (ASYNC_TRANSFER_USER_DATA*)transfer->user_data;
|
|
|
|
|
if (!user_data)
|
|
|
|
@ -296,14 +341,11 @@ static void func_bulk_transfer_cb(struct libusb_transfer* transfer)
|
|
|
|
|
WLog_ERR(TAG, "[%s]: Invalid transfer->user_data!");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
list = user_data->queue;
|
|
|
|
|
ArrayList_Lock(list);
|
|
|
|
|
streamID = stream_id_from_buffer(transfer);
|
|
|
|
|
|
|
|
|
|
#if defined(HAVE_STREAM_ID_API)
|
|
|
|
|
streamID = libusb_transfer_get_stream_id(transfer);
|
|
|
|
|
#else
|
|
|
|
|
streamID = user_data->streamID;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (HashTable_Contains(user_data->queue, (void*)(size_t)streamID))
|
|
|
|
|
if (list_contains(list, streamID))
|
|
|
|
|
{
|
|
|
|
|
const UINT32 InterfaceId =
|
|
|
|
|
((STREAM_ID_PROXY << 30) | user_data->idev->get_ReqCompletion(user_data->idev));
|
|
|
|
@ -314,8 +356,9 @@ static void func_bulk_transfer_cb(struct libusb_transfer* transfer)
|
|
|
|
|
transfer->status, user_data->StartFrame, user_data->ErrorCount,
|
|
|
|
|
transfer->actual_length);
|
|
|
|
|
user_data->data = NULL;
|
|
|
|
|
HashTable_Remove(user_data->queue, (void*)(size_t)streamID);
|
|
|
|
|
ArrayList_Remove(list, transfer);
|
|
|
|
|
}
|
|
|
|
|
ArrayList_Unlock(list);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static BOOL func_set_usbd_status(URBDRC_PLUGIN* urbdrc, UDEVICE* pdev, UINT32* status,
|
|
|
|
@ -884,7 +927,10 @@ static int libusb_udev_os_feature_descriptor_request(IUDEVICE* idev, UINT32 Requ
|
|
|
|
|
LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | Recipient,
|
|
|
|
|
bMS_Vendorcode, (InterfaceNumber << 8) | Ms_PageIndex,
|
|
|
|
|
Ms_featureDescIndex, Buffer, *BufferSize, Timeout);
|
|
|
|
|
*BufferSize = error;
|
|
|
|
|
log_libusb_result(pdev->urbdrc->log, WLOG_DEBUG, "libusb_control_transfer", error);
|
|
|
|
|
|
|
|
|
|
if (error >= 0)
|
|
|
|
|
*BufferSize = error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (error < 0)
|
|
|
|
@ -1044,10 +1090,28 @@ static int libusb_udev_is_already_send(IUDEVICE* idev)
|
|
|
|
|
return (pdev->status & URBDRC_DEVICE_ALREADY_SEND) ? 1 : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* This is called from channel cleanup code.
|
|
|
|
|
* Avoid double free, just remove the device and mark the channel closed. */
|
|
|
|
|
static void libusb_udev_mark_channel_closed(IUDEVICE* idev)
|
|
|
|
|
{
|
|
|
|
|
UDEVICE* pdev = (UDEVICE*)idev;
|
|
|
|
|
if (pdev && ((pdev->status & URBDRC_DEVICE_CHANNEL_CLOSED) == 0))
|
|
|
|
|
{
|
|
|
|
|
URBDRC_PLUGIN* urbdrc = pdev->urbdrc;
|
|
|
|
|
const uint8_t busNr = idev->get_bus_number(idev);
|
|
|
|
|
const uint8_t devNr = idev->get_dev_number(idev);
|
|
|
|
|
|
|
|
|
|
pdev->status |= URBDRC_DEVICE_CHANNEL_CLOSED;
|
|
|
|
|
urbdrc->udevman->unregister_udevice(urbdrc->udevman, busNr, devNr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* This is called by local events where the device is removed or in an error
|
|
|
|
|
* state. Remove the device from redirection and close the channel. */
|
|
|
|
|
static void libusb_udev_channel_closed(IUDEVICE* idev)
|
|
|
|
|
{
|
|
|
|
|
UDEVICE* pdev = (UDEVICE*)idev;
|
|
|
|
|
if (pdev)
|
|
|
|
|
if (pdev && ((pdev->status & URBDRC_DEVICE_CHANNEL_CLOSED) == 0))
|
|
|
|
|
{
|
|
|
|
|
URBDRC_PLUGIN* urbdrc = pdev->urbdrc;
|
|
|
|
|
const uint8_t busNr = idev->get_bus_number(idev);
|
|
|
|
@ -1061,10 +1125,8 @@ static void libusb_udev_channel_closed(IUDEVICE* idev)
|
|
|
|
|
pdev->status |= URBDRC_DEVICE_CHANNEL_CLOSED;
|
|
|
|
|
|
|
|
|
|
if (channel)
|
|
|
|
|
{
|
|
|
|
|
/* Notify the server the device is no longer available. */
|
|
|
|
|
channel->Write(channel, 0, NULL, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
urbdrc->udevman->unregister_udevice(urbdrc->udevman, busNr, devNr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1165,14 +1227,18 @@ static int libusb_udev_isoch_transfer(IUDEVICE* idev, URBDRC_CHANNEL_CALLBACK* c
|
|
|
|
|
libusb_fill_iso_transfer(iso_transfer, pdev->libusb_handle, EndpointAddress,
|
|
|
|
|
Stream_Pointer(user_data->data), BufferSize, NumberOfPackets,
|
|
|
|
|
func_iso_callback, user_data, Timeout);
|
|
|
|
|
#if defined(HAVE_STREAM_ID_API)
|
|
|
|
|
libusb_transfer_set_stream_id(iso_transfer, streamID);
|
|
|
|
|
#else
|
|
|
|
|
user_data->streamID = streamID;
|
|
|
|
|
#endif
|
|
|
|
|
set_stream_id_for_buffer(iso_transfer, streamID);
|
|
|
|
|
libusb_set_iso_packet_lengths(iso_transfer, iso_packet_size);
|
|
|
|
|
|
|
|
|
|
HashTable_Add(pdev->request_queue, (void*)(size_t)streamID, iso_transfer);
|
|
|
|
|
if (ArrayList_Add(pdev->request_queue, iso_transfer) < 0)
|
|
|
|
|
{
|
|
|
|
|
WLog_Print(urbdrc->log, WLOG_WARN,
|
|
|
|
|
"Failed to queue iso transfer, streamID %08" PRIx32 " already in use!",
|
|
|
|
|
streamID);
|
|
|
|
|
async_transfer_user_data_free(user_data);
|
|
|
|
|
libusb_free_transfer(iso_transfer);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
return libusb_submit_transfer(iso_transfer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1277,21 +1343,24 @@ static int libusb_udev_bulk_or_interrupt_transfer(IUDEVICE* idev, URBDRC_CHANNEL
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if defined(HAVE_STREAM_ID_API)
|
|
|
|
|
libusb_transfer_set_stream_id(transfer, streamID);
|
|
|
|
|
#else
|
|
|
|
|
user_data->streamID = streamID;
|
|
|
|
|
#endif
|
|
|
|
|
HashTable_Add(pdev->request_queue, (void*)(size_t)streamID, transfer);
|
|
|
|
|
set_stream_id_for_buffer(transfer, streamID);
|
|
|
|
|
|
|
|
|
|
if (ArrayList_Add(pdev->request_queue, transfer) < 0)
|
|
|
|
|
{
|
|
|
|
|
WLog_Print(urbdrc->log, WLOG_WARN,
|
|
|
|
|
"Failed to queue transfer, streamID %08" PRIx32 " already in use!", streamID);
|
|
|
|
|
async_transfer_user_data_free(user_data);
|
|
|
|
|
libusb_free_transfer(transfer);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
return libusb_submit_transfer(transfer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int func_cancel_xact_request(URBDRC_PLUGIN* urbdrc, wHashTable* queue, uint32_t streamID,
|
|
|
|
|
struct libusb_transfer* transfer)
|
|
|
|
|
static int func_cancel_xact_request(URBDRC_PLUGIN* urbdrc, struct libusb_transfer* transfer)
|
|
|
|
|
{
|
|
|
|
|
int status;
|
|
|
|
|
|
|
|
|
|
if (!urbdrc || !queue || !transfer)
|
|
|
|
|
if (!urbdrc || !transfer)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
status = libusb_cancel_transfer(transfer);
|
|
|
|
@ -1306,50 +1375,51 @@ static int func_cancel_xact_request(URBDRC_PLUGIN* urbdrc, wHashTable* queue, ui
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void libusb_udev_cancel_all_transfer_request(IUDEVICE* idev)
|
|
|
|
|
{
|
|
|
|
|
UDEVICE* pdev = (UDEVICE*)idev;
|
|
|
|
|
ULONG_PTR* keys;
|
|
|
|
|
int count, x;
|
|
|
|
|
|
|
|
|
|
if (!pdev || !pdev->request_queue || !pdev->urbdrc)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
count = HashTable_GetKeys(pdev->request_queue, &keys);
|
|
|
|
|
ArrayList_Lock(pdev->request_queue);
|
|
|
|
|
count = ArrayList_Count(pdev->request_queue);
|
|
|
|
|
|
|
|
|
|
for (x = 0; x < count; x++)
|
|
|
|
|
{
|
|
|
|
|
struct libusb_transfer* transfer =
|
|
|
|
|
HashTable_GetItemValue(pdev->request_queue, (void*)keys[x]);
|
|
|
|
|
func_cancel_xact_request(pdev->urbdrc, pdev->request_queue, (uint32_t)keys[x], transfer);
|
|
|
|
|
struct libusb_transfer* transfer = ArrayList_GetItem(pdev->request_queue, x);
|
|
|
|
|
func_cancel_xact_request(pdev->urbdrc, transfer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(keys);
|
|
|
|
|
ArrayList_Unlock(pdev->request_queue);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int libusb_udev_cancel_transfer_request(IUDEVICE* idev, UINT32 RequestId)
|
|
|
|
|
{
|
|
|
|
|
int rc = -1;
|
|
|
|
|
UDEVICE* pdev = (UDEVICE*)idev;
|
|
|
|
|
struct libusb_transfer* transfer;
|
|
|
|
|
URBDRC_PLUGIN* urbdrc;
|
|
|
|
|
BOOL id1;
|
|
|
|
|
uint32_t cancelID;
|
|
|
|
|
uint32_t cancelID1 = 0x40000000 | RequestId;
|
|
|
|
|
uint32_t cancelID2 = 0x80000000 | RequestId;
|
|
|
|
|
|
|
|
|
|
if (!idev || !pdev->urbdrc || !pdev->request_queue)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
id1 = HashTable_Contains(pdev->request_queue, (void*)(size_t)cancelID1);
|
|
|
|
|
ArrayList_Lock(pdev->request_queue);
|
|
|
|
|
transfer = list_contains(pdev->request_queue, cancelID1);
|
|
|
|
|
if (!transfer)
|
|
|
|
|
transfer = list_contains(pdev->request_queue, cancelID2);
|
|
|
|
|
|
|
|
|
|
if (!id1)
|
|
|
|
|
return -1;
|
|
|
|
|
if (transfer)
|
|
|
|
|
{
|
|
|
|
|
URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)pdev->urbdrc;
|
|
|
|
|
|
|
|
|
|
urbdrc = (URBDRC_PLUGIN*)pdev->urbdrc;
|
|
|
|
|
cancelID = (id1) ? cancelID1 : cancelID2;
|
|
|
|
|
|
|
|
|
|
transfer = HashTable_GetItemValue(pdev->request_queue, (void*)(size_t)cancelID);
|
|
|
|
|
return func_cancel_xact_request(urbdrc, pdev->request_queue, cancelID, transfer);
|
|
|
|
|
rc = func_cancel_xact_request(urbdrc, transfer);
|
|
|
|
|
}
|
|
|
|
|
ArrayList_Unlock(pdev->request_queue);
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BASIC_STATE_FUNC_DEFINED(channelManager, IWTSVirtualChannelManager*)
|
|
|
|
@ -1404,7 +1474,7 @@ static void udev_free(IUDEVICE* idev)
|
|
|
|
|
|
|
|
|
|
/* release all interface and attach kernel driver */
|
|
|
|
|
udev->iface.attach_kernel_driver(idev);
|
|
|
|
|
HashTable_Free(udev->request_queue);
|
|
|
|
|
ArrayList_Free(udev->request_queue);
|
|
|
|
|
/* free the config descriptor that send from windows */
|
|
|
|
|
msusb_msconfig_free(udev->MsConfig);
|
|
|
|
|
libusb_close(udev->libusb_handle);
|
|
|
|
@ -1434,6 +1504,7 @@ static void udev_load_interface(UDEVICE* pdev)
|
|
|
|
|
pdev->iface.isChannelClosed = libusb_udev_is_channel_closed;
|
|
|
|
|
pdev->iface.setAlreadySend = libusb_udev_set_already_send;
|
|
|
|
|
pdev->iface.setChannelClosed = libusb_udev_channel_closed;
|
|
|
|
|
pdev->iface.markChannelClosed = libusb_udev_mark_channel_closed;
|
|
|
|
|
pdev->iface.getPath = libusb_udev_get_path;
|
|
|
|
|
/* Transfer */
|
|
|
|
|
pdev->iface.isoch_transfer = libusb_udev_isoch_transfer;
|
|
|
|
@ -1541,6 +1612,7 @@ static void request_free(void* value)
|
|
|
|
|
|
|
|
|
|
user_data = (ASYNC_TRANSFER_USER_DATA*)transfer->user_data;
|
|
|
|
|
async_transfer_user_data_free(user_data);
|
|
|
|
|
transfer->user_data = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static IUDEVICE* udev_init(URBDRC_PLUGIN* urbdrc, libusb_context* context, LIBUSB_DEVICE* device,
|
|
|
|
@ -1639,12 +1711,12 @@ static IUDEVICE* udev_init(URBDRC_PLUGIN* urbdrc, libusb_context* context, LIBUS
|
|
|
|
|
/* initialize pdev */
|
|
|
|
|
pdev->bus_number = bus_number;
|
|
|
|
|
pdev->dev_number = dev_number;
|
|
|
|
|
pdev->request_queue = HashTable_New(TRUE);
|
|
|
|
|
pdev->request_queue = ArrayList_New(TRUE);
|
|
|
|
|
|
|
|
|
|
if (!pdev->request_queue)
|
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
|
|
pdev->request_queue->valueFree = request_free;
|
|
|
|
|
ArrayList_Object(pdev->request_queue)->fnObjectFree = request_free;
|
|
|
|
|
|
|
|
|
|
/* set config of windows */
|
|
|
|
|
pdev->MsConfig = msusb_msconfig_new();
|
|
|
|
|