mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-14 00:14:11 +09:00
Rewrite of urbdrc channel.
* Fix command line parsing * Properly handle channel creation/destruction * Use wStream API for parsing
This commit is contained in:
@@ -17,38 +17,12 @@
|
||||
|
||||
define_channel("urbdrc")
|
||||
|
||||
if(NOT WIN32)
|
||||
find_package(DevD)
|
||||
find_package(UDev)
|
||||
find_package(UUID)
|
||||
find_package(DbusGlib)
|
||||
find_package(libusb-1.0)
|
||||
endif()
|
||||
|
||||
if(DEVD_FOUND OR UDEV_FOUND)
|
||||
include_directories(${UDEV_INCLUDE_DIR})
|
||||
if(UUID_FOUND AND DBUS_GLIB_FOUND AND LIBUSB_1_FOUND)
|
||||
include_directories(${UUID_INCLUDE_DIRS})
|
||||
include_directories(${LIBUSB_1_INCLUDE_DIRS})
|
||||
include_directories(${DBUS_GLIB_INCLUDE_DIRS})
|
||||
|
||||
set(URBDRC_DEPENDENCIES_FOUND TRUE)
|
||||
message(STATUS "Found all URBDRC dependencies")
|
||||
else()
|
||||
if(NOT UUID_FOUND)
|
||||
message(STATUS "URBDRC dependencie not found: UUID")
|
||||
endif()
|
||||
if(NOT DBUS_GLIB_FOUND)
|
||||
message(STATUS "URBDRC dependencie not found: DBUS_GLIB")
|
||||
endif()
|
||||
if(NOT LIBUSB_1_FOUND)
|
||||
message(STATUS "URBDRC dependencie not found: LIBUSB_1")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
include_directories(common)
|
||||
add_subdirectory(common)
|
||||
|
||||
if(WITH_CLIENT_CHANNELS)
|
||||
if(URBDRC_DEPENDENCIES_FOUND)
|
||||
add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
|
||||
endif()
|
||||
find_package(libusb-1.0 REQUIRED)
|
||||
include_directories(${LIBUSB_1_INCLUDE_DIRS})
|
||||
|
||||
add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
|
||||
endif()
|
||||
|
||||
@@ -21,22 +21,15 @@ define_channel_client("urbdrc")
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
searchman.c
|
||||
searchman.h
|
||||
isoch_queue.c
|
||||
isoch_queue.h
|
||||
data_transfer.c
|
||||
data_transfer.h
|
||||
urbdrc_main.c
|
||||
urbdrc_main.h
|
||||
urbdrc_types.h)
|
||||
|
||||
include_directories(..)
|
||||
$<TARGET_OBJECTS:urbdrc-common>
|
||||
)
|
||||
|
||||
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DVCPluginEntry")
|
||||
|
||||
|
||||
|
||||
#set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} libusb-devman)
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS)
|
||||
if (UDEV_FOUND AND UDEV_LIBRARIES)
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${UDEV_LIBRARIES})
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,6 +21,8 @@
|
||||
#ifndef FREERDP_CHANNEL_URBDRC_CLIENT_DATA_TRANSFER_H
|
||||
#define FREERDP_CHANNEL_URBDRC_CLIENT_DATA_TRANSFER_H
|
||||
|
||||
#include <winpr/pool.h>
|
||||
|
||||
#include "urbdrc_main.h"
|
||||
|
||||
#define DEVICE_CTX(dev) ((dev)->ctx)
|
||||
@@ -28,6 +30,7 @@
|
||||
#define TRANSFER_CTX(transfer) (HANDLE_CTX((transfer)->dev_handle))
|
||||
#define ITRANSFER_CTX(transfer) (TRANSFER_CTX(__USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)))
|
||||
|
||||
void* urbdrc_process_udev_data_transfer(void* arg);
|
||||
UINT urbdrc_process_udev_data_transfer(URBDRC_CHANNEL_CALLBACK* callback, URBDRC_PLUGIN* urbdrc,
|
||||
IUDEVMAN* udevman, wStream* data);
|
||||
|
||||
#endif /* FREERDP_CHANNEL_URBDRC_CLIENT_DATA_TRANSFER_H */
|
||||
|
||||
@@ -1,184 +0,0 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RemoteFX USB Redirection
|
||||
*
|
||||
* Copyright 2012 Atrust corp.
|
||||
* Copyright 2012 Alfred Liu <alfred.liu@atruscorp.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "isoch_queue.h"
|
||||
|
||||
static void isoch_queue_rewind(ISOCH_CALLBACK_QUEUE* queue)
|
||||
{
|
||||
queue->curr = queue->head;
|
||||
}
|
||||
|
||||
static BOOL isoch_queue_has_next(ISOCH_CALLBACK_QUEUE* queue)
|
||||
{
|
||||
return (queue->curr != NULL);
|
||||
}
|
||||
|
||||
static ISOCH_CALLBACK_DATA* isoch_queue_get_next(ISOCH_CALLBACK_QUEUE* queue)
|
||||
{
|
||||
ISOCH_CALLBACK_DATA* isoch;
|
||||
|
||||
isoch = queue->curr;
|
||||
queue->curr = (ISOCH_CALLBACK_DATA*)queue->curr->next;
|
||||
|
||||
return isoch;
|
||||
}
|
||||
|
||||
static ISOCH_CALLBACK_DATA* isoch_queue_register_data(ISOCH_CALLBACK_QUEUE* queue, void* callback,
|
||||
void* dev)
|
||||
{
|
||||
ISOCH_CALLBACK_DATA* isoch;
|
||||
|
||||
isoch = (ISOCH_CALLBACK_DATA*)calloc(1, sizeof(ISOCH_CALLBACK_DATA));
|
||||
if (!isoch)
|
||||
return NULL;
|
||||
|
||||
isoch->device = dev;
|
||||
isoch->callback = callback;
|
||||
|
||||
pthread_mutex_lock(&queue->isoch_loading);
|
||||
|
||||
if (queue->head == NULL)
|
||||
{
|
||||
/* linked queue is empty */
|
||||
queue->head = isoch;
|
||||
queue->tail = isoch;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* append data to the end of the linked queue */
|
||||
queue->tail->next = (void*)isoch;
|
||||
isoch->prev = (void*)queue->tail;
|
||||
queue->tail = isoch;
|
||||
}
|
||||
queue->isoch_num += 1;
|
||||
|
||||
pthread_mutex_unlock(&queue->isoch_loading);
|
||||
|
||||
return isoch;
|
||||
}
|
||||
|
||||
static int isoch_queue_unregister_data(ISOCH_CALLBACK_QUEUE* queue, ISOCH_CALLBACK_DATA* isoch)
|
||||
{
|
||||
ISOCH_CALLBACK_DATA* p;
|
||||
|
||||
queue->rewind(queue);
|
||||
|
||||
while (queue->has_next(queue))
|
||||
{
|
||||
p = queue->get_next(queue);
|
||||
|
||||
if (p != isoch)
|
||||
continue;
|
||||
|
||||
/* data exists */
|
||||
/* set previous data to point to next data */
|
||||
|
||||
if (isoch->prev != NULL)
|
||||
{
|
||||
/* unregistered data is not the head */
|
||||
p = (ISOCH_CALLBACK_DATA*)isoch->prev;
|
||||
p->next = isoch->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* unregistered data is the head, update head */
|
||||
queue->head = (ISOCH_CALLBACK_DATA*)isoch->next;
|
||||
}
|
||||
|
||||
/* set next data to point to previous data */
|
||||
|
||||
if (isoch->next != NULL)
|
||||
{
|
||||
/* unregistered data is not the tail */
|
||||
p = (ISOCH_CALLBACK_DATA*)isoch->next;
|
||||
p->prev = isoch->prev;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* unregistered data is the tail, update tail */
|
||||
queue->tail = (ISOCH_CALLBACK_DATA*)isoch->prev;
|
||||
}
|
||||
queue->isoch_num--;
|
||||
|
||||
if (isoch)
|
||||
{
|
||||
/* free data info */
|
||||
isoch->out_data = NULL;
|
||||
|
||||
zfree(isoch);
|
||||
}
|
||||
|
||||
return 1; /* unregistration successful */
|
||||
}
|
||||
|
||||
/* if we reach this point, the isoch wasn't found */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void isoch_queue_free(ISOCH_CALLBACK_QUEUE* queue)
|
||||
{
|
||||
ISOCH_CALLBACK_DATA* isoch;
|
||||
|
||||
pthread_mutex_lock(&queue->isoch_loading);
|
||||
|
||||
/** unregister all isochronous data*/
|
||||
queue->rewind(queue);
|
||||
|
||||
while (queue->has_next(queue))
|
||||
{
|
||||
isoch = queue->get_next(queue);
|
||||
|
||||
if (isoch != NULL)
|
||||
queue->unregister_data(queue, isoch);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&queue->isoch_loading);
|
||||
|
||||
pthread_mutex_destroy(&queue->isoch_loading);
|
||||
|
||||
/* free queue */
|
||||
if (queue)
|
||||
zfree(queue);
|
||||
}
|
||||
|
||||
ISOCH_CALLBACK_QUEUE* isoch_queue_new()
|
||||
{
|
||||
ISOCH_CALLBACK_QUEUE* queue;
|
||||
|
||||
queue = (ISOCH_CALLBACK_QUEUE*)calloc(1, sizeof(ISOCH_CALLBACK_QUEUE));
|
||||
if (!queue)
|
||||
return NULL;
|
||||
|
||||
pthread_mutex_init(&queue->isoch_loading, NULL);
|
||||
|
||||
/* load service */
|
||||
queue->get_next = isoch_queue_get_next;
|
||||
queue->has_next = isoch_queue_has_next;
|
||||
queue->rewind = isoch_queue_rewind;
|
||||
queue->register_data = isoch_queue_register_data;
|
||||
queue->unregister_data = isoch_queue_unregister_data;
|
||||
queue->free = isoch_queue_free;
|
||||
|
||||
return queue;
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RemoteFX USB Redirection
|
||||
*
|
||||
* Copyright 2012 Atrust corp.
|
||||
* Copyright 2012 Alfred Liu <alfred.liu@atruscorp.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_CHANNEL_URBDRC_CLIENT_ISOCH_QUEUE_H
|
||||
#define FREERDP_CHANNEL_URBDRC_CLIENT_ISOCH_QUEUE_H
|
||||
|
||||
#include "urbdrc_types.h"
|
||||
|
||||
typedef struct _ISOCH_CALLBACK_DATA ISOCH_CALLBACK_DATA;
|
||||
typedef struct _ISOCH_CALLBACK_QUEUE ISOCH_CALLBACK_QUEUE;
|
||||
|
||||
struct _ISOCH_CALLBACK_DATA
|
||||
{
|
||||
void* inode;
|
||||
void* prev;
|
||||
void* next;
|
||||
void* device;
|
||||
BYTE* out_data;
|
||||
UINT32 out_size;
|
||||
void* callback;
|
||||
};
|
||||
|
||||
struct _ISOCH_CALLBACK_QUEUE
|
||||
{
|
||||
int isoch_num;
|
||||
ISOCH_CALLBACK_DATA* curr; /* current point */
|
||||
ISOCH_CALLBACK_DATA* head; /* head point in linked list */
|
||||
ISOCH_CALLBACK_DATA* tail; /* tail point in linked list */
|
||||
|
||||
pthread_mutex_t isoch_loading;
|
||||
|
||||
/* Isochronous queue service */
|
||||
void (*rewind)(ISOCH_CALLBACK_QUEUE* queue);
|
||||
BOOL (*has_next)(ISOCH_CALLBACK_QUEUE* queue);
|
||||
int (*unregister_data)(ISOCH_CALLBACK_QUEUE* queue, ISOCH_CALLBACK_DATA* isoch);
|
||||
ISOCH_CALLBACK_DATA* (*get_next)(ISOCH_CALLBACK_QUEUE* queue);
|
||||
ISOCH_CALLBACK_DATA* (*register_data)(ISOCH_CALLBACK_QUEUE* queue, void* callback, void* dev);
|
||||
void (*free)(ISOCH_CALLBACK_QUEUE* queue);
|
||||
};
|
||||
|
||||
ISOCH_CALLBACK_QUEUE* isoch_queue_new(void);
|
||||
|
||||
#endif /* FREERDP_CHANNEL_URBDRC_CLIENT_ISOCH_QUEUE_H */
|
||||
@@ -21,9 +21,7 @@ define_channel_client_subsystem("urbdrc" "libusb" "")
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
libusb_udevman.c
|
||||
libusb_udevice.c
|
||||
libusb_udevice.h
|
||||
request_queue.c
|
||||
request_queue.h)
|
||||
libusb_udevice.h)
|
||||
|
||||
include_directories(..)
|
||||
|
||||
@@ -38,7 +36,7 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS}
|
||||
${LIBUSB_1_LIBRARIES})
|
||||
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} winpr)
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} winpr urbdrc-client)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,14 +21,10 @@
|
||||
#ifndef FREERDP_CHANNEL_URBDRC_CLIENT_LIBUSB_UDEVICE_H
|
||||
#define FREERDP_CHANNEL_URBDRC_CLIENT_LIBUSB_UDEVICE_H
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
|
||||
#include <libusb.h>
|
||||
#else
|
||||
#include <libusb-1.0/libusb.h>
|
||||
#endif
|
||||
#include <semaphore.h>
|
||||
|
||||
#include "urbdrc_types.h"
|
||||
#include "request_queue.h"
|
||||
#include "urbdrc_main.h"
|
||||
|
||||
typedef struct libusb_device LIBUSB_DEVICE;
|
||||
@@ -51,10 +47,11 @@ struct _UDEVICE
|
||||
|
||||
UINT32 UsbDevice; /* An unique interface ID */
|
||||
UINT32 ReqCompletion; /* An unique interface ID */
|
||||
UINT32 channel_id;
|
||||
IWTSVirtualChannelManager* channelManager;
|
||||
UINT32 channelID;
|
||||
UINT16 status;
|
||||
UINT16 bus_number;
|
||||
UINT16 dev_number;
|
||||
BYTE bus_number;
|
||||
BYTE dev_number;
|
||||
char path[17];
|
||||
int port_number;
|
||||
int isCompositeDevice;
|
||||
@@ -66,18 +63,14 @@ struct _UDEVICE
|
||||
MSUSB_CONFIG_DESCRIPTOR* MsConfig;
|
||||
LIBUSB_CONFIG_DESCRIPTOR* LibusbConfig;
|
||||
|
||||
REQUEST_QUEUE* request_queue;
|
||||
/* Used in isochronous transfer */
|
||||
void* isoch_queue;
|
||||
wHashTable* request_queue;
|
||||
|
||||
pthread_mutex_t mutex_isoch;
|
||||
sem_t sem_id;
|
||||
URBDRC_PLUGIN* urbdrc;
|
||||
};
|
||||
typedef UDEVICE* PUDEVICE;
|
||||
|
||||
int udev_new_by_id(UINT16 idVendor, UINT16 idProduct, IUDEVICE*** devArray);
|
||||
IUDEVICE* udev_new_by_addr(int bus_number, int dev_number);
|
||||
|
||||
extern int libusb_debug;
|
||||
size_t udev_new_by_id(URBDRC_PLUGIN* urbdrc, UINT16 idVendor, UINT16 idProduct,
|
||||
IUDEVICE*** devArray);
|
||||
IUDEVICE* udev_new_by_addr(URBDRC_PLUGIN* urbdrc, BYTE bus_number, BYTE dev_number);
|
||||
|
||||
#endif /* FREERDP_CHANNEL_URBDRC_CLIENT_LIBUSB_UDEVICE_H */
|
||||
|
||||
@@ -21,7 +21,9 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <libusb.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/cmdline.h>
|
||||
|
||||
@@ -32,8 +34,6 @@
|
||||
|
||||
#include "libusb_udevice.h"
|
||||
|
||||
int libusb_debug;
|
||||
|
||||
#define BASIC_STATE_FUNC_DEFINED(_arg, _type) \
|
||||
static _type udevman_get_##_arg(IUDEVMAN* idevman) \
|
||||
{ \
|
||||
@@ -62,28 +62,33 @@ struct _UDEVMAN
|
||||
|
||||
UINT32 defUsbDevice;
|
||||
UINT16 flags;
|
||||
int device_num;
|
||||
UINT32 device_num;
|
||||
int sem_timeout;
|
||||
|
||||
pthread_mutex_t devman_loading;
|
||||
sem_t sem_urb_lock;
|
||||
HANDLE devman_loading;
|
||||
libusb_context* context;
|
||||
libusb_hotplug_callback_handle handle;
|
||||
HANDLE thread;
|
||||
BOOL running;
|
||||
};
|
||||
typedef UDEVMAN* PUDEVMAN;
|
||||
|
||||
static BOOL poll_libusb_events(UDEVMAN* udevman);
|
||||
|
||||
static void udevman_rewind(IUDEVMAN* idevman)
|
||||
{
|
||||
UDEVMAN* udevman = (UDEVMAN*)idevman;
|
||||
udevman->idev = udevman->head;
|
||||
}
|
||||
|
||||
static int udevman_has_next(IUDEVMAN* idevman)
|
||||
static BOOL udevman_has_next(IUDEVMAN* idevman)
|
||||
{
|
||||
UDEVMAN* udevman = (UDEVMAN*)idevman;
|
||||
|
||||
if (udevman->idev == NULL)
|
||||
return 0;
|
||||
if (!udevman || !udevman->idev)
|
||||
return FALSE;
|
||||
else
|
||||
return 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static IUDEVICE* udevman_get_next(IUDEVMAN* idevman)
|
||||
@@ -95,36 +100,46 @@ static IUDEVICE* udevman_get_next(IUDEVMAN* idevman)
|
||||
return pdev;
|
||||
}
|
||||
|
||||
static IUDEVICE* udevman_get_udevice_by_addr(IUDEVMAN* idevman, int bus_number, int dev_number)
|
||||
static IUDEVICE* udevman_get_udevice_by_addr(IUDEVMAN* idevman, BYTE bus_number, BYTE dev_number)
|
||||
{
|
||||
IUDEVICE* pdev;
|
||||
IUDEVICE* dev = NULL;
|
||||
|
||||
if (!idevman)
|
||||
return NULL;
|
||||
|
||||
idevman->loading_lock(idevman);
|
||||
idevman->rewind(idevman);
|
||||
|
||||
while (idevman->has_next(idevman))
|
||||
{
|
||||
pdev = idevman->get_next(idevman);
|
||||
IUDEVICE* pdev = idevman->get_next(idevman);
|
||||
|
||||
if ((pdev->get_bus_number(pdev) == bus_number) &&
|
||||
(pdev->get_dev_number(pdev) == dev_number))
|
||||
{
|
||||
idevman->loading_unlock(idevman);
|
||||
return pdev;
|
||||
dev = pdev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
idevman->loading_unlock(idevman);
|
||||
WLog_WARN(TAG, "bus:%d dev:%d not exist in udevman", bus_number, dev_number);
|
||||
return NULL;
|
||||
return dev;
|
||||
}
|
||||
|
||||
static int udevman_register_udevice(IUDEVMAN* idevman, int bus_number, int dev_number,
|
||||
int UsbDevice, UINT16 idVendor, UINT16 idProduct, int flag)
|
||||
static size_t udevman_register_udevice(IUDEVMAN* idevman, BYTE bus_number, BYTE dev_number,
|
||||
UINT32 UsbDevice, UINT16 idVendor, UINT16 idProduct,
|
||||
int flag)
|
||||
{
|
||||
UDEVMAN* udevman = (UDEVMAN*)idevman;
|
||||
IUDEVICE* pdev = NULL;
|
||||
IUDEVICE** devArray;
|
||||
int i, num, addnum = 0;
|
||||
URBDRC_PLUGIN* urbdrc;
|
||||
size_t i, num, addnum = 0;
|
||||
|
||||
if (!idevman || !idevman->plugin)
|
||||
return 0;
|
||||
|
||||
urbdrc = (URBDRC_PLUGIN*)idevman->plugin;
|
||||
pdev = (IUDEVICE*)udevman_get_udevice_by_addr(idevman, bus_number, dev_number);
|
||||
|
||||
if (pdev != NULL)
|
||||
@@ -132,26 +147,26 @@ static int udevman_register_udevice(IUDEVMAN* idevman, int bus_number, int dev_n
|
||||
|
||||
if (flag == UDEVMAN_FLAG_ADD_BY_ADDR)
|
||||
{
|
||||
pdev = udev_new_by_addr(bus_number, dev_number);
|
||||
IUDEVICE* tdev = udev_new_by_addr(urbdrc, bus_number, dev_number);
|
||||
|
||||
if (pdev == NULL)
|
||||
if (tdev == NULL)
|
||||
return 0;
|
||||
|
||||
pdev->set_UsbDevice(pdev, UsbDevice);
|
||||
tdev->set_UsbDevice(tdev, UsbDevice);
|
||||
idevman->loading_lock(idevman);
|
||||
|
||||
if (udevman->head == NULL)
|
||||
{
|
||||
/* linked list is empty */
|
||||
udevman->head = pdev;
|
||||
udevman->tail = pdev;
|
||||
udevman->head = tdev;
|
||||
udevman->tail = tdev;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* append device to the end of the linked list */
|
||||
udevman->tail->set_p_next(udevman->tail, pdev);
|
||||
pdev->set_p_prev(pdev, udevman->tail);
|
||||
udevman->tail = pdev;
|
||||
udevman->tail->set_p_next(udevman->tail, tdev);
|
||||
tdev->set_p_prev(tdev, udevman->tail);
|
||||
udevman->tail = tdev;
|
||||
}
|
||||
|
||||
udevman->device_num += 1;
|
||||
@@ -161,34 +176,35 @@ static int udevman_register_udevice(IUDEVMAN* idevman, int bus_number, int dev_n
|
||||
{
|
||||
addnum = 0;
|
||||
/* register all device that match pid vid */
|
||||
num = udev_new_by_id(idVendor, idProduct, &devArray);
|
||||
num = udev_new_by_id(urbdrc, idVendor, idProduct, &devArray);
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
pdev = devArray[i];
|
||||
IUDEVICE* tdev = devArray[i];
|
||||
|
||||
if (udevman_get_udevice_by_addr(idevman, pdev->get_bus_number(pdev),
|
||||
pdev->get_dev_number(pdev)) != NULL)
|
||||
if (udevman_get_udevice_by_addr(idevman, tdev->get_bus_number(tdev),
|
||||
tdev->get_dev_number(tdev)) != NULL)
|
||||
{
|
||||
zfree(pdev);
|
||||
tdev->free(tdev);
|
||||
devArray[i] = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
pdev->set_UsbDevice(pdev, UsbDevice);
|
||||
tdev->set_UsbDevice(tdev, UsbDevice);
|
||||
idevman->loading_lock(idevman);
|
||||
|
||||
if (udevman->head == NULL)
|
||||
{
|
||||
/* linked list is empty */
|
||||
udevman->head = pdev;
|
||||
udevman->tail = pdev;
|
||||
udevman->head = tdev;
|
||||
udevman->tail = tdev;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* append device to the end of the linked list */
|
||||
udevman->tail->set_p_next(udevman->tail, pdev);
|
||||
pdev->set_p_prev(pdev, udevman->tail);
|
||||
udevman->tail = pdev;
|
||||
udevman->tail->set_p_next(udevman->tail, tdev);
|
||||
tdev->set_p_prev(tdev, udevman->tail);
|
||||
udevman->tail = tdev;
|
||||
}
|
||||
|
||||
udevman->device_num += 1;
|
||||
@@ -196,28 +212,32 @@ static int udevman_register_udevice(IUDEVMAN* idevman, int bus_number, int dev_n
|
||||
addnum++;
|
||||
}
|
||||
|
||||
zfree(devArray);
|
||||
free(devArray);
|
||||
return addnum;
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_ERR(TAG, "udevman_register_udevice: function error!!");
|
||||
WLog_Print(urbdrc->log, WLOG_ERROR, "udevman_register_udevice: Invalid flag=%08 " PRIx32,
|
||||
flag);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int udevman_unregister_udevice(IUDEVMAN* idevman, int bus_number, int dev_number)
|
||||
static BOOL udevman_unregister_udevice(IUDEVMAN* idevman, BYTE bus_number, BYTE dev_number)
|
||||
{
|
||||
UDEVMAN* udevman = (UDEVMAN*)idevman;
|
||||
UDEVICE *pdev, *dev;
|
||||
int ret = 0, err = 0;
|
||||
dev = (UDEVICE*)udevman_get_udevice_by_addr(idevman, bus_number, dev_number);
|
||||
UDEVICE* pdev;
|
||||
UDEVICE* dev = (UDEVICE*)udevman_get_udevice_by_addr(idevman, bus_number, dev_number);
|
||||
|
||||
if (!dev || !idevman)
|
||||
return FALSE;
|
||||
|
||||
idevman->loading_lock(idevman);
|
||||
idevman->rewind(idevman);
|
||||
|
||||
while (idevman->has_next(idevman) != 0)
|
||||
while (idevman->has_next(idevman))
|
||||
{
|
||||
pdev = (UDEVICE*)idevman->get_next(idevman);
|
||||
|
||||
@@ -259,63 +279,158 @@ static int udevman_unregister_udevice(IUDEVMAN* idevman, int bus_number, int dev
|
||||
|
||||
if (dev)
|
||||
{
|
||||
/* reset device */
|
||||
if (err != LIBUSB_ERROR_NO_DEVICE)
|
||||
{
|
||||
ret = libusb_reset_device(dev->libusb_handle);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "libusb_reset_device: ERROR!!ret:%d", ret);
|
||||
}
|
||||
}
|
||||
|
||||
/* release all interface and attach kernel driver */
|
||||
dev->iface.attach_kernel_driver((IUDEVICE*)dev);
|
||||
|
||||
if (dev->request_queue)
|
||||
zfree(dev->request_queue);
|
||||
|
||||
/* free the config descriptor that send from windows */
|
||||
msusb_msconfig_free(dev->MsConfig);
|
||||
libusb_close(dev->libusb_handle);
|
||||
libusb_close(dev->hub_handle);
|
||||
sem_destroy(&dev->sem_id);
|
||||
|
||||
/* free device info */
|
||||
if (dev->devDescriptor)
|
||||
zfree(dev->devDescriptor);
|
||||
|
||||
if (dev)
|
||||
zfree(dev);
|
||||
|
||||
return 1; /* unregistration successful */
|
||||
dev->iface.free(&dev->iface);
|
||||
return TRUE; /* unregistration successful */
|
||||
}
|
||||
|
||||
/* if we reach this point, the device wasn't found */
|
||||
return 0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void udevman_parse_device_addr(char* str, int* id1, int* id2, char sign)
|
||||
static BOOL udevman_cancel_all_device_requests(IUDEVMAN* idevman)
|
||||
{
|
||||
char s1[8];
|
||||
char* s2;
|
||||
ZeroMemory(s1, sizeof(s1));
|
||||
s2 = (strchr(str, sign)) + 1;
|
||||
strncpy(s1, str, strlen(str) - (strlen(s2) + 1));
|
||||
*id1 = strtol(s1, NULL, 0);
|
||||
*id2 = strtol(s2, NULL, 0);
|
||||
UDEVMAN* udevman = (UDEVMAN*)idevman;
|
||||
|
||||
if (!idevman)
|
||||
return FALSE;
|
||||
|
||||
idevman->loading_lock(idevman);
|
||||
idevman->rewind(idevman);
|
||||
|
||||
while (idevman->has_next(idevman))
|
||||
{
|
||||
UDEVICE* dev = (UDEVICE*)idevman->get_next(idevman);
|
||||
|
||||
if (!dev)
|
||||
continue;
|
||||
dev->iface.cancel_all_transfer_request(&dev->iface);
|
||||
}
|
||||
|
||||
idevman->loading_unlock(idevman);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void udevman_parse_device_pid_vid(char* str, int* id1, int* id2, char sign)
|
||||
static BOOL udevman_unregister_all_udevices(IUDEVMAN* idevman)
|
||||
{
|
||||
char s1[8];
|
||||
UDEVMAN* udevman = (UDEVMAN*)idevman;
|
||||
|
||||
if (!idevman)
|
||||
return FALSE;
|
||||
|
||||
idevman->loading_lock(idevman);
|
||||
idevman->rewind(idevman);
|
||||
|
||||
while (idevman->has_next(idevman))
|
||||
{
|
||||
UDEVICE* dev = (UDEVICE*)idevman->get_next(idevman);
|
||||
|
||||
if (!dev)
|
||||
continue;
|
||||
|
||||
/* set previous device to point to next device */
|
||||
if (dev->prev != NULL)
|
||||
{
|
||||
/* unregistered device is not the head */
|
||||
UDEVICE* pdev = dev->prev;
|
||||
pdev->next = dev->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* unregistered device is the head, update head */
|
||||
udevman->head = (IUDEVICE*)dev->next;
|
||||
}
|
||||
|
||||
/* set next device to point to previous device */
|
||||
|
||||
if (dev->next != NULL)
|
||||
{
|
||||
/* unregistered device is not the tail */
|
||||
UDEVICE* pdev = (UDEVICE*)dev->next;
|
||||
pdev->prev = dev->prev;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* unregistered device is the tail, update tail */
|
||||
udevman->tail = (IUDEVICE*)dev->prev;
|
||||
}
|
||||
|
||||
dev->iface.free(&dev->iface);
|
||||
udevman->device_num--;
|
||||
}
|
||||
|
||||
idevman->loading_unlock(idevman);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL udevman_parse_device_addr(const char* str, size_t maxLen, UINT16* id1, UINT16* id2,
|
||||
char sign)
|
||||
{
|
||||
unsigned long rc;
|
||||
char s1[8] = { 0 };
|
||||
char* s2;
|
||||
ZeroMemory(s1, sizeof(s1));
|
||||
size_t len = strnlen(str, maxLen);
|
||||
size_t cpLen;
|
||||
s2 = (strchr(str, sign)) + 1;
|
||||
strncpy(s1, str, strlen(str) - (strlen(s2) + 1));
|
||||
*id1 = strtol(s1, NULL, 16);
|
||||
*id2 = strtol(s2, NULL, 16);
|
||||
|
||||
if (!s2)
|
||||
return FALSE;
|
||||
|
||||
cpLen = len - (strnlen(s2, len) + 1);
|
||||
|
||||
if (cpLen >= sizeof(s1))
|
||||
cpLen = sizeof(s1) - 1;
|
||||
|
||||
strncpy(s1, str, cpLen);
|
||||
rc = strtoul(s1, NULL, 16);
|
||||
|
||||
if ((rc > UINT16_MAX) || (errno != 0))
|
||||
return FALSE;
|
||||
|
||||
*id1 = rc;
|
||||
rc = strtoul(s2, NULL, 16);
|
||||
|
||||
if ((rc > UINT16_MAX) || (errno != 0))
|
||||
return FALSE;
|
||||
|
||||
*id2 = rc;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL udevman_parse_device_pid_vid(const char* str, size_t maxLen, UINT16* id1, UINT16* id2,
|
||||
char sign)
|
||||
{
|
||||
unsigned long rc;
|
||||
char s1[8] = { 0 };
|
||||
char* s2;
|
||||
size_t len = strnlen(str, maxLen);
|
||||
size_t cpLen;
|
||||
s2 = (strchr(str, sign)) + 1;
|
||||
|
||||
if (!s2)
|
||||
return FALSE;
|
||||
|
||||
cpLen = len - (strnlen(s2, len) + 1);
|
||||
|
||||
if (cpLen >= sizeof(s1))
|
||||
cpLen = sizeof(s1) - 1;
|
||||
|
||||
strncpy(s1, str, cpLen);
|
||||
errno = 0;
|
||||
rc = strtoul(s1, NULL, 16);
|
||||
|
||||
if ((rc > UINT16_MAX) || (errno != 0))
|
||||
return FALSE;
|
||||
|
||||
*id1 = rc;
|
||||
rc = strtoul(s2, NULL, 16);
|
||||
|
||||
if ((rc > UINT16_MAX) || (errno != 0))
|
||||
return FALSE;
|
||||
|
||||
*id2 = rc;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int udevman_check_device_exist_by_id(IUDEVMAN* idevman, UINT16 idVendor, UINT16 idProduct)
|
||||
@@ -332,30 +447,17 @@ static int udevman_is_auto_add(IUDEVMAN* idevman)
|
||||
return (udevman->flags & UDEVMAN_FLAG_ADD_BY_AUTO) ? 1 : 0;
|
||||
}
|
||||
|
||||
static IUDEVICE* udevman_get_udevice_by_UsbDevice_try_again(IUDEVMAN* idevman, UINT32 UsbDevice)
|
||||
{
|
||||
UDEVICE* pdev;
|
||||
idevman->loading_lock(idevman);
|
||||
idevman->rewind(idevman);
|
||||
|
||||
while (idevman->has_next(idevman))
|
||||
{
|
||||
pdev = (UDEVICE*)idevman->get_next(idevman);
|
||||
|
||||
if (pdev->UsbDevice == UsbDevice)
|
||||
{
|
||||
idevman->loading_unlock(idevman);
|
||||
return (IUDEVICE*)pdev;
|
||||
}
|
||||
}
|
||||
|
||||
idevman->loading_unlock(idevman);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static IUDEVICE* udevman_get_udevice_by_UsbDevice(IUDEVMAN* idevman, UINT32 UsbDevice)
|
||||
{
|
||||
UDEVICE* pdev;
|
||||
URBDRC_PLUGIN* urbdrc;
|
||||
|
||||
if (!idevman || !idevman->plugin)
|
||||
return NULL;
|
||||
|
||||
/* Mask highest 2 bits, must be ignored */
|
||||
UsbDevice = UsbDevice & INTERFACE_ID_MASK;
|
||||
urbdrc = (URBDRC_PLUGIN*)idevman->plugin;
|
||||
idevman->loading_lock(idevman);
|
||||
idevman->rewind(idevman);
|
||||
|
||||
@@ -371,57 +473,90 @@ static IUDEVICE* udevman_get_udevice_by_UsbDevice(IUDEVMAN* idevman, UINT32 UsbD
|
||||
}
|
||||
|
||||
idevman->loading_unlock(idevman);
|
||||
/* try again */
|
||||
pdev = (UDEVICE*)idevman->get_udevice_by_UsbDevice_try_again(idevman, UsbDevice);
|
||||
|
||||
if (pdev)
|
||||
{
|
||||
return (IUDEVICE*)pdev;
|
||||
}
|
||||
|
||||
WLog_ERR(TAG, "0x%" PRIx32 " ERROR!!", UsbDevice);
|
||||
WLog_Print(urbdrc->log, WLOG_WARN, "Failed to find a USB device mapped to deviceId=%08" PRIx32,
|
||||
UsbDevice);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void udevman_loading_lock(IUDEVMAN* idevman)
|
||||
{
|
||||
UDEVMAN* udevman = (UDEVMAN*)idevman;
|
||||
pthread_mutex_lock(&udevman->devman_loading);
|
||||
WaitForSingleObject(udevman->devman_loading, INFINITE);
|
||||
}
|
||||
|
||||
static void udevman_loading_unlock(IUDEVMAN* idevman)
|
||||
{
|
||||
UDEVMAN* udevman = (UDEVMAN*)idevman;
|
||||
pthread_mutex_unlock(&udevman->devman_loading);
|
||||
}
|
||||
|
||||
static void udevman_wait_urb(IUDEVMAN* idevman)
|
||||
{
|
||||
UDEVMAN* udevman = (UDEVMAN*)idevman;
|
||||
sem_wait(&udevman->sem_urb_lock);
|
||||
}
|
||||
|
||||
static void udevman_push_urb(IUDEVMAN* idevman)
|
||||
{
|
||||
UDEVMAN* udevman = (UDEVMAN*)idevman;
|
||||
sem_post(&udevman->sem_urb_lock);
|
||||
ReleaseMutex(udevman->devman_loading);
|
||||
}
|
||||
|
||||
BASIC_STATE_FUNC_DEFINED(defUsbDevice, UINT32)
|
||||
BASIC_STATE_FUNC_DEFINED(device_num, int)
|
||||
BASIC_STATE_FUNC_DEFINED(device_num, UINT32)
|
||||
BASIC_STATE_FUNC_DEFINED(sem_timeout, int)
|
||||
|
||||
static void udevman_free(IUDEVMAN* idevman)
|
||||
{
|
||||
UDEVMAN* udevman = (UDEVMAN*)idevman;
|
||||
pthread_mutex_destroy(&udevman->devman_loading);
|
||||
sem_destroy(&udevman->sem_urb_lock);
|
||||
libusb_exit(NULL);
|
||||
|
||||
/* free udevman */
|
||||
if (!udevman)
|
||||
return;
|
||||
|
||||
if (udevman)
|
||||
zfree(udevman);
|
||||
libusb_hotplug_deregister_callback(udevman->context, udevman->handle);
|
||||
|
||||
udevman->running = FALSE;
|
||||
WaitForSingleObject(udevman->thread, INFINITE);
|
||||
|
||||
/* Process remaining usb events */
|
||||
while (poll_libusb_events(udevman))
|
||||
;
|
||||
|
||||
udevman_unregister_all_udevices(idevman);
|
||||
CloseHandle(udevman->devman_loading);
|
||||
CloseHandle(udevman->thread);
|
||||
libusb_exit(udevman->context);
|
||||
|
||||
free(udevman);
|
||||
}
|
||||
|
||||
static int hotplug_callback(struct libusb_context* ctx, struct libusb_device* dev,
|
||||
libusb_hotplug_event event, void* user_data)
|
||||
{
|
||||
int rc;
|
||||
struct libusb_device_descriptor desc;
|
||||
IUDEVMAN* idevman = (IUDEVMAN*)user_data;
|
||||
const uint8_t bus = libusb_get_bus_number(dev);
|
||||
const uint8_t addr = libusb_get_device_address(dev);
|
||||
rc = libusb_get_device_descriptor(dev, &desc);
|
||||
|
||||
if (rc != LIBUSB_SUCCESS)
|
||||
return rc;
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED:
|
||||
add_device(idevman, bus, addr, desc.iManufacturer, desc.iProduct);
|
||||
break;
|
||||
|
||||
case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT:
|
||||
del_device(idevman, bus, addr, desc.iManufacturer, desc.iProduct);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL udevman_initialize(IUDEVMAN* idevman, UINT32 channelId)
|
||||
{
|
||||
UDEVMAN* udevman = (UDEVMAN*)idevman;
|
||||
|
||||
if (!udevman)
|
||||
return FALSE;
|
||||
|
||||
idevman->controlChannelId = channelId;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void udevman_load_interface(UDEVMAN* udevman)
|
||||
@@ -435,7 +570,6 @@ static void udevman_load_interface(UDEVMAN* udevman)
|
||||
udevman->iface.register_udevice = udevman_register_udevice;
|
||||
udevman->iface.unregister_udevice = udevman_unregister_udevice;
|
||||
udevman->iface.get_udevice_by_UsbDevice = udevman_get_udevice_by_UsbDevice;
|
||||
udevman->iface.get_udevice_by_UsbDevice_try_again = udevman_get_udevice_by_UsbDevice_try_again;
|
||||
/* Extension */
|
||||
udevman->iface.check_device_exist_by_id = udevman_check_device_exist_by_id;
|
||||
udevman->iface.isAutoAdd = udevman_is_auto_add;
|
||||
@@ -446,47 +580,51 @@ static void udevman_load_interface(UDEVMAN* udevman)
|
||||
/* control semaphore or mutex lock */
|
||||
udevman->iface.loading_lock = udevman_loading_lock;
|
||||
udevman->iface.loading_unlock = udevman_loading_unlock;
|
||||
udevman->iface.push_urb = udevman_push_urb;
|
||||
udevman->iface.wait_urb = udevman_wait_urb;
|
||||
udevman->iface.initialize = udevman_initialize;
|
||||
}
|
||||
|
||||
static void urbdrc_udevman_register_devices(UDEVMAN* udevman, char* devices)
|
||||
static BOOL urbdrc_udevman_register_devices(UDEVMAN* udevman, const char* devices)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
char* token;
|
||||
int idVendor;
|
||||
int idProduct;
|
||||
int bus_number;
|
||||
int dev_number;
|
||||
int success = 0;
|
||||
char* tmp;
|
||||
char hardware_id[16];
|
||||
char* default_devices = "id";
|
||||
const char* default_devices = "id";
|
||||
UINT32 UsbDevice = BASE_USBDEVICE_NUM;
|
||||
|
||||
if (!devices)
|
||||
devices = default_devices;
|
||||
tmp = _strdup(default_devices);
|
||||
else
|
||||
tmp = _strdup(devices);
|
||||
|
||||
/* register all usb devices */
|
||||
token = strtok(devices, "#");
|
||||
token = strtok(tmp, "#");
|
||||
|
||||
while (token)
|
||||
{
|
||||
bus_number = 0;
|
||||
dev_number = 0;
|
||||
idVendor = 0;
|
||||
idProduct = 0;
|
||||
sprintf_s(hardware_id, ARRAYSIZE(hardware_id), "%s", token);
|
||||
strcpy(hardware_id, token);
|
||||
token = strtok(NULL, "#");
|
||||
|
||||
if (udevman->flags & UDEVMAN_FLAG_ADD_BY_VID_PID)
|
||||
{
|
||||
udevman_parse_device_pid_vid(hardware_id, &idVendor, &idProduct, ':');
|
||||
success = udevman->iface.register_udevice((IUDEVMAN*)udevman, 0, 0, UsbDevice,
|
||||
(UINT16)idVendor, (UINT16)idProduct,
|
||||
UDEVMAN_FLAG_ADD_BY_VID_PID);
|
||||
UINT16 idVendor, idProduct;
|
||||
|
||||
if (!udevman_parse_device_pid_vid(hardware_id, sizeof(hardware_id), &idVendor,
|
||||
&idProduct, ':'))
|
||||
goto fail;
|
||||
|
||||
success = udevman->iface.register_udevice((IUDEVMAN*)udevman, 0, 0, UsbDevice, idVendor,
|
||||
idProduct, UDEVMAN_FLAG_ADD_BY_VID_PID);
|
||||
}
|
||||
else if (udevman->flags & UDEVMAN_FLAG_ADD_BY_ADDR)
|
||||
{
|
||||
udevman_parse_device_addr(hardware_id, &bus_number, &dev_number, ':');
|
||||
UINT16 bus_number, dev_number;
|
||||
|
||||
if (!udevman_parse_device_addr(hardware_id, sizeof(hardware_id), &bus_number,
|
||||
&dev_number, ':'))
|
||||
goto fail;
|
||||
|
||||
success = udevman->iface.register_udevice((IUDEVMAN*)udevman, bus_number, dev_number,
|
||||
UsbDevice, 0, 0, UDEVMAN_FLAG_ADD_BY_ADDR);
|
||||
}
|
||||
@@ -496,12 +634,18 @@ static void urbdrc_udevman_register_devices(UDEVMAN* udevman, char* devices)
|
||||
}
|
||||
|
||||
udevman->defUsbDevice = UsbDevice;
|
||||
rc = TRUE;
|
||||
fail:
|
||||
free(tmp);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void urbdrc_udevman_parse_addin_args(UDEVMAN* udevman, ADDIN_ARGV* args)
|
||||
static UINT urbdrc_udevman_parse_addin_args(UDEVMAN* udevman, ADDIN_ARGV* args)
|
||||
{
|
||||
int status;
|
||||
DWORD flags;
|
||||
LPSTR devices = NULL;
|
||||
const UINT16 mask = UDEVMAN_FLAG_ADD_BY_VID_PID | UDEVMAN_FLAG_ADD_BY_ADDR;
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
COMMAND_LINE_ARGUMENT_A urbdrc_udevman_args[] = {
|
||||
{ "dbg", COMMAND_LINE_VALUE_FLAG, "", NULL, BoolValueFalse, -1, NULL, "debug" },
|
||||
@@ -512,9 +656,14 @@ static void urbdrc_udevman_parse_addin_args(UDEVMAN* udevman, ADDIN_ARGV* args)
|
||||
{ "auto", COMMAND_LINE_VALUE_FLAG, "", NULL, BoolValueFalse, -1, NULL, "FLAG_ADD_BY_AUTO" },
|
||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
|
||||
status = CommandLineParseArgumentsA(args->argc, args->argv, urbdrc_udevman_args, flags, udevman,
|
||||
NULL, NULL);
|
||||
|
||||
if (status != CHANNEL_RC_OK)
|
||||
return status;
|
||||
|
||||
arg = urbdrc_udevman_args;
|
||||
|
||||
do
|
||||
@@ -528,7 +677,7 @@ static void urbdrc_udevman_parse_addin_args(UDEVMAN* udevman, ADDIN_ARGV* args)
|
||||
}
|
||||
CommandLineSwitchCase(arg, "dev")
|
||||
{
|
||||
urbdrc_udevman_register_devices(udevman, arg->Value);
|
||||
devices = arg->Value;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "id")
|
||||
{
|
||||
@@ -547,6 +696,60 @@ static void urbdrc_udevman_parse_addin_args(UDEVMAN* udevman, ADDIN_ARGV* args)
|
||||
}
|
||||
CommandLineSwitchEnd(arg)
|
||||
} while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
|
||||
/* Can not add devices by address and VID/PID */
|
||||
if ((udevman->flags & mask) == mask)
|
||||
return COMMAND_LINE_ERROR_UNEXPECTED_VALUE;
|
||||
|
||||
/* Add listed devices after we know the format of addressing */
|
||||
if (devices)
|
||||
{
|
||||
if (!urbdrc_udevman_register_devices(udevman, devices))
|
||||
return COMMAND_LINE_ERROR_UNEXPECTED_VALUE;
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
static BOOL poll_libusb_events(UDEVMAN* udevman)
|
||||
{
|
||||
int rc = LIBUSB_SUCCESS;
|
||||
struct timeval tv = { 0, 500 };
|
||||
if (libusb_try_lock_events(udevman->context))
|
||||
{
|
||||
if (libusb_event_handling_ok(udevman->context))
|
||||
{
|
||||
rc = libusb_handle_events_locked(udevman->context, &tv);
|
||||
if (rc != LIBUSB_SUCCESS)
|
||||
WLog_WARN(TAG, "libusb_handle_events_locked %d", rc);
|
||||
}
|
||||
libusb_unlock_events(udevman->context);
|
||||
}
|
||||
else
|
||||
{
|
||||
libusb_lock_event_waiters(udevman->context);
|
||||
if (libusb_event_handler_active(udevman->context))
|
||||
{
|
||||
rc = libusb_wait_for_event(udevman->context, &tv);
|
||||
if (rc < LIBUSB_SUCCESS)
|
||||
WLog_WARN(TAG, "libusb_wait_for_event %d", rc);
|
||||
}
|
||||
libusb_unlock_event_waiters(udevman->context);
|
||||
}
|
||||
|
||||
return rc > 0;
|
||||
}
|
||||
|
||||
static DWORD poll_thread(LPVOID lpThreadParameter)
|
||||
{
|
||||
UDEVMAN* udevman = (UDEVMAN*)lpThreadParameter;
|
||||
|
||||
while (udevman->running)
|
||||
{
|
||||
poll_libusb_events(udevman);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
@@ -554,31 +757,56 @@ static void urbdrc_udevman_parse_addin_args(UDEVMAN* udevman, ADDIN_ARGV* args)
|
||||
#else
|
||||
#define freerdp_urbdrc_client_subsystem_entry FREERDP_API freerdp_urbdrc_client_subsystem_entry
|
||||
#endif
|
||||
|
||||
int freerdp_urbdrc_client_subsystem_entry(PFREERDP_URBDRC_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
int rc;
|
||||
UINT status;
|
||||
UDEVMAN* udevman;
|
||||
ADDIN_ARGV* args = pEntryPoints->args;
|
||||
libusb_init(NULL);
|
||||
udevman = (PUDEVMAN)malloc(sizeof(UDEVMAN));
|
||||
udevman = (PUDEVMAN)calloc(1, sizeof(UDEVMAN));
|
||||
|
||||
if (!udevman)
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
udevman->iface.plugin = pEntryPoints->plugin;
|
||||
rc = libusb_init(&udevman->context);
|
||||
|
||||
if (rc != LIBUSB_SUCCESS)
|
||||
goto fail;
|
||||
|
||||
udevman->device_num = 0;
|
||||
udevman->idev = NULL;
|
||||
udevman->head = NULL;
|
||||
udevman->tail = NULL;
|
||||
udevman->sem_timeout = 0;
|
||||
udevman->flags = UDEVMAN_FLAG_ADD_BY_VID_PID;
|
||||
pthread_mutex_init(&udevman->devman_loading, NULL);
|
||||
sem_init(&udevman->sem_urb_lock, 0, MAX_URB_REQUSET_NUM);
|
||||
udevman->devman_loading = CreateMutexA(NULL, FALSE, "devman_loading");
|
||||
|
||||
if (!udevman->devman_loading)
|
||||
goto fail;
|
||||
|
||||
/* load usb device service management */
|
||||
udevman_load_interface(udevman);
|
||||
/* set debug flag, to enable Debug message for usb data transfer */
|
||||
libusb_debug = 10;
|
||||
urbdrc_udevman_parse_addin_args(udevman, args);
|
||||
pEntryPoints->pRegisterUDEVMAN(pEntryPoints->plugin, (IUDEVMAN*)udevman);
|
||||
status = urbdrc_udevman_parse_addin_args(udevman, args);
|
||||
|
||||
if (status != CHANNEL_RC_OK)
|
||||
goto fail;
|
||||
|
||||
udevman->running = TRUE;
|
||||
udevman->thread = CreateThread(NULL, 0, poll_thread, udevman, 0, NULL);
|
||||
|
||||
if (!udevman->thread)
|
||||
goto fail;
|
||||
|
||||
rc = libusb_hotplug_register_callback(
|
||||
udevman->context, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,
|
||||
LIBUSB_HOTPLUG_NO_FLAGS, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY,
|
||||
LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback, udevman, &udevman->handle);
|
||||
|
||||
if (rc != LIBUSB_SUCCESS)
|
||||
goto fail;
|
||||
|
||||
if (!pEntryPoints->pRegisterUDEVMAN(pEntryPoints->plugin, (IUDEVMAN*)udevman))
|
||||
goto fail;
|
||||
|
||||
WLog_DBG(TAG, "UDEVMAN device registered.");
|
||||
return 0;
|
||||
fail:
|
||||
udevman_free(&udevman->iface);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1,179 +0,0 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RemoteFX USB Redirection
|
||||
*
|
||||
* Copyright 2012 Atrust corp.
|
||||
* Copyright 2012 Alfred Liu <alfred.liu@atruscorp.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "request_queue.h"
|
||||
|
||||
TRANSFER_REQUEST* request_queue_get_next(REQUEST_QUEUE* queue)
|
||||
{
|
||||
TRANSFER_REQUEST* request;
|
||||
|
||||
request = queue->ireq;
|
||||
queue->ireq = (TRANSFER_REQUEST*)queue->ireq->next;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
int request_queue_has_next(REQUEST_QUEUE* queue)
|
||||
{
|
||||
if (queue->ireq == NULL)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
TRANSFER_REQUEST* request_queue_register_request(REQUEST_QUEUE* queue, UINT32 RequestId,
|
||||
struct libusb_transfer* transfer, BYTE endpoint)
|
||||
{
|
||||
TRANSFER_REQUEST* request;
|
||||
|
||||
request = (TRANSFER_REQUEST*)malloc(sizeof(TRANSFER_REQUEST));
|
||||
|
||||
request->prev = NULL;
|
||||
request->next = NULL;
|
||||
|
||||
request->RequestId = RequestId;
|
||||
request->transfer = transfer;
|
||||
request->endpoint = endpoint;
|
||||
request->submit = 0;
|
||||
|
||||
pthread_mutex_lock(&queue->request_loading);
|
||||
|
||||
if (queue->head == NULL)
|
||||
{
|
||||
/* linked queue is empty */
|
||||
queue->head = request;
|
||||
queue->tail = request;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* append data to the end of the linked queue */
|
||||
queue->tail->next = (void*)request;
|
||||
request->prev = (void*)queue->tail;
|
||||
queue->tail = request;
|
||||
}
|
||||
|
||||
queue->request_num += 1;
|
||||
pthread_mutex_unlock(&queue->request_loading);
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
void request_queue_rewind(REQUEST_QUEUE* queue)
|
||||
{
|
||||
queue->ireq = queue->head;
|
||||
}
|
||||
|
||||
/* Get first*/
|
||||
TRANSFER_REQUEST* request_queue_get_request_by_endpoint(REQUEST_QUEUE* queue, BYTE ep)
|
||||
{
|
||||
TRANSFER_REQUEST* request;
|
||||
pthread_mutex_lock(&queue->request_loading);
|
||||
queue->rewind(queue);
|
||||
while (queue->has_next(queue))
|
||||
{
|
||||
request = queue->get_next(queue);
|
||||
if (request->endpoint == ep)
|
||||
{
|
||||
pthread_mutex_unlock(&queue->request_loading);
|
||||
return request;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&queue->request_loading);
|
||||
WLog_ERR(TAG, "request_queue_get_request_by_id: ERROR!!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int request_queue_unregister_request(REQUEST_QUEUE* queue, UINT32 RequestId)
|
||||
{
|
||||
TRANSFER_REQUEST *request, *request_temp;
|
||||
pthread_mutex_lock(&queue->request_loading);
|
||||
queue->rewind(queue);
|
||||
|
||||
while (queue->has_next(queue) != 0)
|
||||
{
|
||||
request = queue->get_next(queue);
|
||||
|
||||
if (request->RequestId == RequestId)
|
||||
{
|
||||
|
||||
if (request->prev != NULL)
|
||||
{
|
||||
request_temp = (TRANSFER_REQUEST*)request->prev;
|
||||
request_temp->next = (TRANSFER_REQUEST*)request->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
queue->head = (TRANSFER_REQUEST*)request->next;
|
||||
}
|
||||
|
||||
if (request->next != NULL)
|
||||
{
|
||||
request_temp = (TRANSFER_REQUEST*)request->next;
|
||||
request_temp->prev = (TRANSFER_REQUEST*)request->prev;
|
||||
}
|
||||
else
|
||||
{
|
||||
queue->tail = (TRANSFER_REQUEST*)request->prev;
|
||||
}
|
||||
|
||||
queue->request_num--;
|
||||
|
||||
if (request)
|
||||
{
|
||||
request->transfer = NULL;
|
||||
zfree(request);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&queue->request_loading);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&queue->request_loading);
|
||||
/* it wasn't found */
|
||||
return 1;
|
||||
}
|
||||
|
||||
REQUEST_QUEUE* request_queue_new()
|
||||
{
|
||||
REQUEST_QUEUE* queue;
|
||||
|
||||
queue = (REQUEST_QUEUE*)malloc(sizeof(REQUEST_QUEUE));
|
||||
queue->request_num = 0;
|
||||
queue->ireq = NULL;
|
||||
queue->head = NULL;
|
||||
queue->tail = NULL;
|
||||
|
||||
pthread_mutex_init(&queue->request_loading, NULL);
|
||||
|
||||
/* load service */
|
||||
queue->get_next = request_queue_get_next;
|
||||
queue->has_next = request_queue_has_next;
|
||||
queue->rewind = request_queue_rewind;
|
||||
queue->register_request = request_queue_register_request;
|
||||
queue->unregister_request = request_queue_unregister_request;
|
||||
queue->get_request_by_ep = request_queue_get_request_by_endpoint;
|
||||
|
||||
return queue;
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RemoteFX USB Redirection
|
||||
*
|
||||
* Copyright 2012 Atrust corp.
|
||||
* Copyright 2012 Alfred Liu <alfred.liu@atruscorp.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_CHANNEL_URBDRC_CLIENT_LIBUSB_REQUEST_QUEUE_H
|
||||
#define FREERDP_CHANNEL_URBDRC_CLIENT_LIBUSB_REQUEST_QUEUE_H
|
||||
|
||||
#include "urbdrc_types.h"
|
||||
|
||||
typedef struct _TRANSFER_REQUEST TRANSFER_REQUEST;
|
||||
typedef struct _REQUEST_QUEUE REQUEST_QUEUE;
|
||||
|
||||
struct _TRANSFER_REQUEST
|
||||
{
|
||||
void* request;
|
||||
void* prev;
|
||||
void* next;
|
||||
|
||||
UINT32 RequestId;
|
||||
BYTE endpoint;
|
||||
struct libusb_transfer* transfer;
|
||||
int submit;
|
||||
};
|
||||
|
||||
struct _REQUEST_QUEUE
|
||||
{
|
||||
int request_num;
|
||||
TRANSFER_REQUEST* ireq; /* iterator request */
|
||||
TRANSFER_REQUEST* head; /* head request in linked queue */
|
||||
TRANSFER_REQUEST* tail; /* tail request in linked queue */
|
||||
|
||||
pthread_mutex_t request_loading;
|
||||
|
||||
/* request queue manager service */
|
||||
void (*rewind)(REQUEST_QUEUE* queue);
|
||||
int (*has_next)(REQUEST_QUEUE* queue);
|
||||
int (*unregister_request)(REQUEST_QUEUE* queue, UINT32 RequestId);
|
||||
TRANSFER_REQUEST* (*get_next)(REQUEST_QUEUE* queue);
|
||||
TRANSFER_REQUEST* (*get_request_by_ep)(REQUEST_QUEUE* queue, BYTE ep);
|
||||
TRANSFER_REQUEST* (*register_request)(REQUEST_QUEUE* queue, UINT32 RequestId,
|
||||
struct libusb_transfer* transfer, BYTE endpoint);
|
||||
};
|
||||
|
||||
REQUEST_QUEUE* request_queue_new(void);
|
||||
|
||||
#endif /* FREERDP_CHANNEL_URBDRC_CLIENT_LIBUSB_REQUEST_QUEUE_H */
|
||||
@@ -21,12 +21,12 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
|
||||
#include "searchman.h"
|
||||
#include "urbdrc_main.h"
|
||||
|
||||
static void searchman_rewind(USB_SEARCHMAN* searchman)
|
||||
{
|
||||
@@ -44,18 +44,16 @@ static int searchman_has_next(USB_SEARCHMAN* searchman)
|
||||
static USB_SEARCHDEV* searchman_get_next(USB_SEARCHMAN* searchman)
|
||||
{
|
||||
USB_SEARCHDEV* search;
|
||||
|
||||
search = searchman->idev;
|
||||
searchman->idev = (USB_SEARCHDEV*)searchman->idev->next;
|
||||
|
||||
return search;
|
||||
}
|
||||
|
||||
static BOOL searchman_list_add(USB_SEARCHMAN* searchman, UINT16 idVendor, UINT16 idProduct)
|
||||
{
|
||||
USB_SEARCHDEV* search;
|
||||
|
||||
search = (USB_SEARCHDEV*)calloc(1, sizeof(USB_SEARCHDEV));
|
||||
|
||||
if (!search)
|
||||
return FALSE;
|
||||
|
||||
@@ -75,8 +73,8 @@ static BOOL searchman_list_add(USB_SEARCHMAN* searchman, UINT16 idVendor, UINT16
|
||||
search->prev = (void*)searchman->tail;
|
||||
searchman->tail = search;
|
||||
}
|
||||
searchman->usb_numbers += 1;
|
||||
|
||||
searchman->usb_numbers += 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -84,7 +82,6 @@ static int searchman_list_remove(USB_SEARCHMAN* searchman, UINT16 idVendor, UINT
|
||||
{
|
||||
USB_SEARCHDEV* search;
|
||||
USB_SEARCHDEV* point;
|
||||
|
||||
searchman_rewind(searchman);
|
||||
|
||||
while (searchman_has_next(searchman) != 0)
|
||||
@@ -94,8 +91,8 @@ static int searchman_list_remove(USB_SEARCHMAN* searchman, UINT16 idVendor, UINT
|
||||
if (point->idVendor == idVendor && point->idProduct == idProduct)
|
||||
{
|
||||
/* set previous device to point to next device */
|
||||
|
||||
search = point;
|
||||
|
||||
if (search->prev != NULL)
|
||||
{
|
||||
/* unregistered device is not the head */
|
||||
@@ -121,10 +118,9 @@ static int searchman_list_remove(USB_SEARCHMAN* searchman, UINT16 idVendor, UINT
|
||||
/* unregistered device is the tail, update tail */
|
||||
searchman->tail = (USB_SEARCHDEV*)search->prev;
|
||||
}
|
||||
|
||||
searchman->usb_numbers--;
|
||||
|
||||
free(search);
|
||||
|
||||
return 1; /* unregistration successful */
|
||||
}
|
||||
}
|
||||
@@ -133,42 +129,29 @@ static int searchman_list_remove(USB_SEARCHMAN* searchman, UINT16 idVendor, UINT
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL searchman_start(USB_SEARCHMAN* self, void* (*func)(void*))
|
||||
{
|
||||
pthread_t thread;
|
||||
|
||||
/* create search thread */
|
||||
if (pthread_create(&thread, 0, func, self) != 0)
|
||||
return FALSE;
|
||||
|
||||
if (pthread_detach(thread) != 0)
|
||||
return FALSE;
|
||||
|
||||
self->started = 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* close thread */
|
||||
static void searchman_close(USB_SEARCHMAN* self)
|
||||
{
|
||||
SetEvent(self->term_event);
|
||||
}
|
||||
|
||||
static void searchman_list_show(USB_SEARCHMAN* self)
|
||||
{
|
||||
int num = 0;
|
||||
USB_SEARCHDEV* usb;
|
||||
WLog_DBG(TAG, "=========== Usb Search List =========");
|
||||
URBDRC_PLUGIN* urbdrc;
|
||||
|
||||
if (!self || !self->urbdrc)
|
||||
return;
|
||||
|
||||
urbdrc = self->urbdrc;
|
||||
WLog_Print(urbdrc->log, WLOG_DEBUG, "=========== Usb Search List =========");
|
||||
self->rewind(self);
|
||||
|
||||
while (self->has_next(self))
|
||||
{
|
||||
usb = self->get_next(self);
|
||||
WLog_DBG(TAG, " USB %d: ", num++);
|
||||
WLog_DBG(TAG, " idVendor: 0x%04" PRIX16 "", usb->idVendor);
|
||||
WLog_DBG(TAG, " idProduct: 0x%04" PRIX16 "", usb->idProduct);
|
||||
WLog_Print(urbdrc->log, WLOG_DEBUG, " USB %d: ", num++);
|
||||
WLog_Print(urbdrc->log, WLOG_DEBUG, " idVendor: 0x%04" PRIX16 "", usb->idVendor);
|
||||
WLog_Print(urbdrc->log, WLOG_DEBUG, " idProduct: 0x%04" PRIX16 "", usb->idProduct);
|
||||
}
|
||||
|
||||
WLog_DBG(TAG, "================= END ===============");
|
||||
WLog_Print(urbdrc->log, WLOG_DEBUG, "================= END ===============");
|
||||
}
|
||||
|
||||
void searchman_free(USB_SEARCHMAN* self)
|
||||
@@ -182,30 +165,19 @@ void searchman_free(USB_SEARCHMAN* self)
|
||||
}
|
||||
|
||||
/* free searchman */
|
||||
sem_destroy(&self->sem_term);
|
||||
CloseHandle(self->term_event);
|
||||
free(self);
|
||||
}
|
||||
|
||||
USB_SEARCHMAN* searchman_new(void* urbdrc, UINT32 UsbDevice)
|
||||
{
|
||||
int ret;
|
||||
USB_SEARCHMAN* searchman;
|
||||
|
||||
searchman = (USB_SEARCHMAN*)calloc(1, sizeof(USB_SEARCHMAN));
|
||||
|
||||
if (!searchman)
|
||||
return NULL;
|
||||
|
||||
searchman->urbdrc = urbdrc;
|
||||
searchman->UsbDevice = UsbDevice;
|
||||
|
||||
ret = pthread_mutex_init(&searchman->mutex, NULL);
|
||||
if (ret != 0)
|
||||
{
|
||||
WLog_ERR(TAG, "searchman mutex initialization: searchman->mutex failed");
|
||||
goto out_error_mutex;
|
||||
}
|
||||
|
||||
/* load service */
|
||||
searchman->add = searchman_list_add;
|
||||
searchman->remove = searchman_list_remove;
|
||||
@@ -213,25 +185,6 @@ USB_SEARCHMAN* searchman_new(void* urbdrc, UINT32 UsbDevice)
|
||||
searchman->get_next = searchman_get_next;
|
||||
searchman->has_next = searchman_has_next;
|
||||
searchman->show = searchman_list_show;
|
||||
searchman->start = searchman_start;
|
||||
searchman->close = searchman_close;
|
||||
searchman->free = searchman_free;
|
||||
|
||||
searchman->started = 0;
|
||||
searchman->term_event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if (!searchman->term_event)
|
||||
goto out_error_event;
|
||||
|
||||
if (sem_init(&searchman->sem_term, 0, 0) < 0)
|
||||
goto out_error_sem;
|
||||
|
||||
return searchman;
|
||||
|
||||
out_error_sem:
|
||||
CloseHandle(searchman->term_event);
|
||||
out_error_event:
|
||||
pthread_mutex_destroy(&searchman->mutex);
|
||||
out_error_mutex:
|
||||
free(searchman);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -44,11 +44,6 @@ struct _USB_SEARCHMAN
|
||||
USB_SEARCHDEV* head; /* head device in linked list */
|
||||
USB_SEARCHDEV* tail; /* tail device in linked list */
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
HANDLE term_event;
|
||||
sem_t sem_term;
|
||||
int started;
|
||||
|
||||
/* for urbdrc channel call back */
|
||||
void* urbdrc;
|
||||
|
||||
@@ -56,10 +51,6 @@ struct _USB_SEARCHMAN
|
||||
void (*rewind)(USB_SEARCHMAN* seachman);
|
||||
/* show all device in the list */
|
||||
void (*show)(USB_SEARCHMAN* self);
|
||||
/* start searchman */
|
||||
BOOL (*start)(USB_SEARCHMAN* self, void* (*func)(void*));
|
||||
/* close searchman */
|
||||
void (*close)(USB_SEARCHMAN* self);
|
||||
/* add a new usb device for search */
|
||||
BOOL (*add)(USB_SEARCHMAN* seachman, UINT16 idVendor, UINT16 idProduct);
|
||||
/* remove a usb device from list */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,14 +21,26 @@
|
||||
#ifndef FREERDP_CHANNEL_URBDRC_CLIENT_MAIN_H
|
||||
#define FREERDP_CHANNEL_URBDRC_CLIENT_MAIN_H
|
||||
|
||||
#include <winpr/pool.h>
|
||||
#include <freerdp/channels/log.h>
|
||||
|
||||
#include "searchman.h"
|
||||
#include "isoch_queue.h"
|
||||
|
||||
#define DEVICE_HARDWARE_ID_SIZE 32
|
||||
#define DEVICE_COMPATIBILITY_ID_SIZE 36
|
||||
#define DEVICE_INSTANCE_STR_SIZE 37
|
||||
#define DEVICE_CONTAINER_STR_SIZE 39
|
||||
|
||||
#define TAG CHANNELS_TAG("urbdrc.client")
|
||||
#ifdef WITH_DEBUG_DVC
|
||||
#define DEBUG_DVC(...) WLog_DBG(TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_DVC(...) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
typedef struct _IUDEVICE IUDEVICE;
|
||||
typedef struct _IUDEVMAN IUDEVMAN;
|
||||
|
||||
@@ -71,13 +83,14 @@ struct _URBDRC_PLUGIN
|
||||
|
||||
IUDEVMAN* udevman;
|
||||
USB_SEARCHMAN* searchman;
|
||||
UINT32 first_channel_id;
|
||||
UINT32 vchannel_status;
|
||||
char* subsystem;
|
||||
|
||||
UINT32 status;
|
||||
wLog* log;
|
||||
};
|
||||
|
||||
typedef void (*PREGISTERURBDRCSERVICE)(IWTSPlugin* plugin, IUDEVMAN* udevman);
|
||||
|
||||
typedef BOOL (*PREGISTERURBDRCSERVICE)(IWTSPlugin* plugin, IUDEVMAN* udevman);
|
||||
struct _FREERDP_URBDRC_SERVICE_ENTRY_POINTS
|
||||
{
|
||||
IWTSPlugin* plugin;
|
||||
@@ -96,27 +109,34 @@ struct _TRANSFER_DATA
|
||||
URBDRC_CHANNEL_CALLBACK* callback;
|
||||
URBDRC_PLUGIN* urbdrc;
|
||||
IUDEVMAN* udevman;
|
||||
BYTE* pBuffer;
|
||||
UINT32 cbSize;
|
||||
UINT32 UsbDevice;
|
||||
IWTSVirtualChannel* channel;
|
||||
wStream* s;
|
||||
};
|
||||
|
||||
typedef void (*t_isoch_transfer_cb)(IUDEVICE* idev, URBDRC_CHANNEL_CALLBACK* callback, wStream* out,
|
||||
UINT32 InterfaceId, BOOL noAck, UINT32 MessageId,
|
||||
UINT32 RequestId, UINT32 NumberOfPackets, UINT32 status,
|
||||
UINT32 StartFrame, UINT32 ErrorCount, UINT32 OutputBufferSize);
|
||||
|
||||
struct _IUDEVICE
|
||||
{
|
||||
/* Transfer */
|
||||
int (*isoch_transfer)(IUDEVICE* idev, UINT32 RequestId, UINT32 EndpointAddress,
|
||||
UINT32 TransferFlags, int NoAck, UINT32* ErrorCount, UINT32* UrbdStatus,
|
||||
UINT32* StartFrame, UINT32 NumberOfPackets, BYTE* IsoPacket,
|
||||
UINT32* BufferSize, BYTE* Buffer, int Timeout);
|
||||
int (*isoch_transfer)(IUDEVICE* idev, URBDRC_CHANNEL_CALLBACK* callback, UINT32 MessageId,
|
||||
UINT32 RequestId, UINT32 EndpointAddress, UINT32 TransferFlags,
|
||||
UINT32 StartFrame, UINT32 ErrorCount, BOOL NoAck,
|
||||
const BYTE* packetDescriptorData, UINT32 NumberOfPackets,
|
||||
UINT32 BufferSize, const BYTE* Buffer, t_isoch_transfer_cb cb,
|
||||
UINT32 Timeout);
|
||||
|
||||
int (*control_transfer)(IUDEVICE* idev, UINT32 RequestId, UINT32 EndpointAddress,
|
||||
UINT32 TransferFlags, BYTE bmRequestType, BYTE Request, UINT16 Value,
|
||||
UINT16 Index, UINT32* UrbdStatus, UINT32* BufferSize, BYTE* Buffer,
|
||||
UINT32 Timeout);
|
||||
BOOL(*control_transfer)
|
||||
(IUDEVICE* idev, UINT32 RequestId, UINT32 EndpointAddress, UINT32 TransferFlags,
|
||||
BYTE bmRequestType, BYTE Request, UINT16 Value, UINT16 Index, UINT32* UrbdStatus,
|
||||
UINT32* BufferSize, BYTE* Buffer, UINT32 Timeout);
|
||||
|
||||
int (*bulk_or_interrupt_transfer)(IUDEVICE* idev, UINT32 RequestId, UINT32 EndpointAddress,
|
||||
UINT32 TransferFlags, UINT32* UsbdStatus, UINT32* BufferSize,
|
||||
BYTE* Buffer, UINT32 Timeout);
|
||||
int (*bulk_or_interrupt_transfer)(IUDEVICE* idev, URBDRC_CHANNEL_CALLBACK* callback,
|
||||
UINT32 MessageId, UINT32 RequestId, UINT32 EndpointAddress,
|
||||
UINT32 TransferFlags, BOOL NoAck, UINT32 BufferSize,
|
||||
t_isoch_transfer_cb cb, UINT32 Timeout);
|
||||
|
||||
int (*select_configuration)(IUDEVICE* idev, UINT32 bConfigurationValue);
|
||||
|
||||
@@ -125,8 +145,8 @@ struct _IUDEVICE
|
||||
int (*control_pipe_request)(IUDEVICE* idev, UINT32 RequestId, UINT32 EndpointAddress,
|
||||
UINT32* UsbdStatus, int command);
|
||||
|
||||
int (*control_query_device_text)(IUDEVICE* idev, UINT32 TextType, UINT32 LocaleId,
|
||||
UINT32* BufferSize, BYTE* Buffer);
|
||||
UINT32(*control_query_device_text)
|
||||
(IUDEVICE* idev, UINT32 TextType, UINT16 LocaleId, UINT8* BufferSize, BYTE* Buffer);
|
||||
|
||||
int (*os_feature_descriptor_request)(IUDEVICE* idev, UINT32 RequestId, BYTE Recipient,
|
||||
BYTE InterfaceNumber, BYTE Ms_PageIndex,
|
||||
@@ -139,56 +159,43 @@ struct _IUDEVICE
|
||||
|
||||
int (*query_device_descriptor)(IUDEVICE* idev, int offset);
|
||||
|
||||
void (*detach_kernel_driver)(IUDEVICE* idev);
|
||||
BOOL (*detach_kernel_driver)(IUDEVICE* idev);
|
||||
|
||||
void (*attach_kernel_driver)(IUDEVICE* idev);
|
||||
|
||||
int (*wait_action_completion)(IUDEVICE* idev);
|
||||
|
||||
void (*push_action)(IUDEVICE* idev);
|
||||
|
||||
void (*complete_action)(IUDEVICE* idev);
|
||||
BOOL (*attach_kernel_driver)(IUDEVICE* idev);
|
||||
|
||||
/* Wait for 5 sec */
|
||||
int (*wait_for_detach)(IUDEVICE* idev);
|
||||
|
||||
/* FIXME: Currently this is a way of stupid, SHOULD to improve it.
|
||||
* Isochronous transfer must to FIFO */
|
||||
void (*lock_fifo_isoch)(IUDEVICE* idev);
|
||||
void (*unlock_fifo_isoch)(IUDEVICE* idev);
|
||||
BOOL (*wait_for_detach)(IUDEVICE* idev);
|
||||
|
||||
int (*query_device_port_status)(IUDEVICE* idev, UINT32* UsbdStatus, UINT32* BufferSize,
|
||||
BYTE* Buffer);
|
||||
|
||||
int (*request_queue_is_none)(IUDEVICE* idev);
|
||||
|
||||
MSUSB_CONFIG_DESCRIPTOR* (*complete_msconfig_setup)(IUDEVICE* idev,
|
||||
MSUSB_CONFIG_DESCRIPTOR* MsConfig);
|
||||
/* Basic state */
|
||||
int (*isCompositeDevice)(IUDEVICE* idev);
|
||||
int (*isSigToEnd)(IUDEVICE* idev);
|
||||
|
||||
int (*isExist)(IUDEVICE* idev);
|
||||
int (*isAlreadySend)(IUDEVICE* idev);
|
||||
int (*isChannelClosed)(IUDEVICE* idev);
|
||||
void (*SigToEnd)(IUDEVICE* idev);
|
||||
|
||||
void (*setAlreadySend)(IUDEVICE* idev);
|
||||
void (*setChannelClosed)(IUDEVICE* idev);
|
||||
char* (*getPath)(IUDEVICE* idev);
|
||||
|
||||
BASIC_DEV_STATE_DEFINED(channel_id, UINT32);
|
||||
void (*free)(IUDEVICE* idev);
|
||||
|
||||
BASIC_DEV_STATE_DEFINED(channelManager, IWTSVirtualChannelManager*);
|
||||
BASIC_DEV_STATE_DEFINED(channelID, UINT32);
|
||||
BASIC_DEV_STATE_DEFINED(UsbDevice, UINT32);
|
||||
BASIC_DEV_STATE_DEFINED(ReqCompletion, UINT32);
|
||||
BASIC_DEV_STATE_DEFINED(bus_number, UINT16);
|
||||
BASIC_DEV_STATE_DEFINED(dev_number, UINT16);
|
||||
BASIC_DEV_STATE_DEFINED(bus_number, BYTE);
|
||||
BASIC_DEV_STATE_DEFINED(dev_number, BYTE);
|
||||
BASIC_DEV_STATE_DEFINED(port_number, int);
|
||||
BASIC_DEV_STATE_DEFINED(isoch_queue, void*);
|
||||
BASIC_DEV_STATE_DEFINED(MsConfig, MSUSB_CONFIG_DESCRIPTOR*);
|
||||
|
||||
BASIC_DEV_STATE_DEFINED(p_udev, void*);
|
||||
BASIC_DEV_STATE_DEFINED(p_prev, void*);
|
||||
BASIC_DEV_STATE_DEFINED(p_next, void*);
|
||||
|
||||
/* Control semaphore or mutex lock */
|
||||
};
|
||||
|
||||
struct _IUDEVMAN
|
||||
@@ -198,13 +205,12 @@ struct _IUDEVMAN
|
||||
|
||||
/* Manage devices */
|
||||
void (*rewind)(IUDEVMAN* idevman);
|
||||
int (*has_next)(IUDEVMAN* idevman);
|
||||
int (*unregister_udevice)(IUDEVMAN* idevman, int bus_number, int dev_number);
|
||||
int (*register_udevice)(IUDEVMAN* idevman, int bus_number, int dev_number, int UsbDevice,
|
||||
UINT16 idVendor, UINT16 idProduct, int flag);
|
||||
BOOL (*has_next)(IUDEVMAN* idevman);
|
||||
BOOL (*unregister_udevice)(IUDEVMAN* idevman, BYTE bus_number, BYTE dev_number);
|
||||
size_t (*register_udevice)(IUDEVMAN* idevman, BYTE bus_number, BYTE dev_number,
|
||||
UINT32 UsbDevice, UINT16 idVendor, UINT16 idProduct, int flag);
|
||||
IUDEVICE* (*get_next)(IUDEVMAN* idevman);
|
||||
IUDEVICE* (*get_udevice_by_UsbDevice)(IUDEVMAN* idevman, UINT32 UsbDevice);
|
||||
IUDEVICE* (*get_udevice_by_UsbDevice_try_again)(IUDEVMAN* idevman, UINT32 UsbDevice);
|
||||
|
||||
/* Extension */
|
||||
int (*check_device_exist_by_id)(IUDEVMAN* idevman, UINT16 idVendor, UINT16 idProduct);
|
||||
@@ -212,14 +218,20 @@ struct _IUDEVMAN
|
||||
|
||||
/* Basic state */
|
||||
BASIC_DEVMAN_STATE_DEFINED(defUsbDevice, UINT32);
|
||||
BASIC_DEVMAN_STATE_DEFINED(device_num, int);
|
||||
BASIC_DEVMAN_STATE_DEFINED(device_num, UINT32);
|
||||
BASIC_DEVMAN_STATE_DEFINED(sem_timeout, int);
|
||||
|
||||
/* control semaphore or mutex lock */
|
||||
void (*loading_lock)(IUDEVMAN* idevman);
|
||||
void (*loading_unlock)(IUDEVMAN* idevman);
|
||||
void (*push_urb)(IUDEVMAN* idevman);
|
||||
void (*wait_urb)(IUDEVMAN* idevman);
|
||||
BOOL (*initialize)(IUDEVMAN* idevman, UINT32 channelId);
|
||||
|
||||
IWTSPlugin* plugin;
|
||||
UINT32 controlChannelId;
|
||||
};
|
||||
BOOL add_device(IUDEVMAN* idevman, BYTE busnum, BYTE devnum, UINT16 idVendor, UINT16 idProduct);
|
||||
BOOL del_device(IUDEVMAN* idevman, BYTE busnum, BYTE devnum, UINT16 idVendor, UINT16 idProduct);
|
||||
|
||||
UINT stream_write_and_free(IWTSPlugin* plugin, IWTSVirtualChannel* channel, wStream* s);
|
||||
|
||||
#endif /* FREERDP_CHANNEL_URBDRC_CLIENT_MAIN_H */
|
||||
|
||||
26
channels/urbdrc/common/CMakeLists.txt
Normal file
26
channels/urbdrc/common/CMakeLists.txt
Normal file
@@ -0,0 +1,26 @@
|
||||
# FreeRDP: A Remote Desktop Protocol Implementation
|
||||
# FreeRDP cmake build script
|
||||
#
|
||||
# Copyright 2019 Armin Novak <armin.novak@thincast.com>
|
||||
# Copyright 2019 Thincast Technologies GmbH
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set(SRCS
|
||||
urbdrc_types.h
|
||||
urbdrc_helpers.h
|
||||
urbdrc_helpers.c
|
||||
msusb.h
|
||||
msusb.c)
|
||||
|
||||
add_library(urbdrc-common OBJECT ${SRCS})
|
||||
402
channels/urbdrc/common/msusb.c
Normal file
402
channels/urbdrc/common/msusb.c
Normal file
@@ -0,0 +1,402 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RemoteFX USB Redirection
|
||||
*
|
||||
* Copyright 2012 Atrust corp.
|
||||
* Copyright 2012 Alfred Liu <alfred.liu@atruscorp.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#include <msusb.h>
|
||||
|
||||
#define TAG FREERDP_TAG("utils")
|
||||
|
||||
static MSUSB_PIPE_DESCRIPTOR* msusb_mspipe_new()
|
||||
{
|
||||
return (MSUSB_PIPE_DESCRIPTOR*)calloc(1, sizeof(MSUSB_PIPE_DESCRIPTOR));
|
||||
}
|
||||
|
||||
static void msusb_mspipes_free(MSUSB_PIPE_DESCRIPTOR** MsPipes, UINT32 NumberOfPipes)
|
||||
{
|
||||
UINT32 pnum = 0;
|
||||
|
||||
if (MsPipes)
|
||||
{
|
||||
for (pnum = 0; pnum < NumberOfPipes && MsPipes[pnum]; pnum++)
|
||||
free(MsPipes[pnum]);
|
||||
|
||||
free(MsPipes);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL msusb_mspipes_replace(MSUSB_INTERFACE_DESCRIPTOR* MsInterface,
|
||||
MSUSB_PIPE_DESCRIPTOR** NewMsPipes, UINT32 NewNumberOfPipes)
|
||||
{
|
||||
if (!MsInterface || !NewMsPipes)
|
||||
return FALSE;
|
||||
|
||||
/* free orignal MsPipes */
|
||||
msusb_mspipes_free(MsInterface->MsPipes, MsInterface->NumberOfPipes);
|
||||
/* And replace it */
|
||||
MsInterface->MsPipes = NewMsPipes;
|
||||
MsInterface->NumberOfPipes = NewNumberOfPipes;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static MSUSB_PIPE_DESCRIPTOR** msusb_mspipes_read(wStream* s, UINT32 NumberOfPipes)
|
||||
{
|
||||
UINT32 pnum;
|
||||
MSUSB_PIPE_DESCRIPTOR** MsPipes;
|
||||
|
||||
if (Stream_GetRemainingCapacity(s) < 12 * NumberOfPipes)
|
||||
return NULL;
|
||||
|
||||
MsPipes = (MSUSB_PIPE_DESCRIPTOR**)calloc(NumberOfPipes, sizeof(MSUSB_PIPE_DESCRIPTOR*));
|
||||
|
||||
if (!MsPipes)
|
||||
return NULL;
|
||||
|
||||
for (pnum = 0; pnum < NumberOfPipes; pnum++)
|
||||
{
|
||||
MSUSB_PIPE_DESCRIPTOR* MsPipe = msusb_mspipe_new();
|
||||
|
||||
if (!MsPipe)
|
||||
goto out_error;
|
||||
|
||||
Stream_Read_UINT16(s, MsPipe->MaximumPacketSize);
|
||||
Stream_Seek(s, 2);
|
||||
Stream_Read_UINT32(s, MsPipe->MaximumTransferSize);
|
||||
Stream_Read_UINT32(s, MsPipe->PipeFlags);
|
||||
/* Already set to zero by memset
|
||||
MsPipe->PipeHandle = 0;
|
||||
MsPipe->bEndpointAddress = 0;
|
||||
MsPipe->bInterval = 0;
|
||||
MsPipe->PipeType = 0;
|
||||
MsPipe->InitCompleted = 0;
|
||||
*/
|
||||
MsPipes[pnum] = MsPipe;
|
||||
}
|
||||
|
||||
return MsPipes;
|
||||
out_error:
|
||||
|
||||
for (pnum = 0; pnum < NumberOfPipes; pnum++)
|
||||
free(MsPipes[pnum]);
|
||||
|
||||
free(MsPipes);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static MSUSB_INTERFACE_DESCRIPTOR* msusb_msinterface_new()
|
||||
{
|
||||
return (MSUSB_INTERFACE_DESCRIPTOR*)calloc(1, sizeof(MSUSB_INTERFACE_DESCRIPTOR));
|
||||
}
|
||||
|
||||
static void msusb_msinterface_free(MSUSB_INTERFACE_DESCRIPTOR* MsInterface)
|
||||
{
|
||||
if (MsInterface)
|
||||
{
|
||||
msusb_mspipes_free(MsInterface->MsPipes, MsInterface->NumberOfPipes);
|
||||
MsInterface->MsPipes = NULL;
|
||||
free(MsInterface);
|
||||
}
|
||||
}
|
||||
|
||||
static void msusb_msinterface_free_list(MSUSB_INTERFACE_DESCRIPTOR** MsInterfaces,
|
||||
UINT32 NumInterfaces)
|
||||
{
|
||||
UINT32 inum = 0;
|
||||
|
||||
if (MsInterfaces)
|
||||
{
|
||||
for (inum = 0; inum < NumInterfaces; inum++)
|
||||
{
|
||||
msusb_msinterface_free(MsInterfaces[inum]);
|
||||
}
|
||||
|
||||
free(MsInterfaces);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL msusb_msinterface_replace(MSUSB_CONFIG_DESCRIPTOR* MsConfig, BYTE InterfaceNumber,
|
||||
MSUSB_INTERFACE_DESCRIPTOR* NewMsInterface)
|
||||
{
|
||||
if (!MsConfig || !MsConfig->MsInterfaces)
|
||||
return FALSE;
|
||||
|
||||
msusb_msinterface_free(MsConfig->MsInterfaces[InterfaceNumber]);
|
||||
MsConfig->MsInterfaces[InterfaceNumber] = NewMsInterface;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
MSUSB_INTERFACE_DESCRIPTOR* msusb_msinterface_read(wStream* s)
|
||||
{
|
||||
MSUSB_INTERFACE_DESCRIPTOR* MsInterface;
|
||||
|
||||
if (Stream_GetRemainingCapacity(s) < 12)
|
||||
return NULL;
|
||||
|
||||
MsInterface = msusb_msinterface_new();
|
||||
|
||||
if (!MsInterface)
|
||||
return NULL;
|
||||
|
||||
Stream_Read_UINT16(s, MsInterface->Length);
|
||||
Stream_Read_UINT16(s, MsInterface->NumberOfPipesExpected);
|
||||
Stream_Read_UINT8(s, MsInterface->InterfaceNumber);
|
||||
Stream_Read_UINT8(s, MsInterface->AlternateSetting);
|
||||
Stream_Seek(s, 2);
|
||||
Stream_Read_UINT32(s, MsInterface->NumberOfPipes);
|
||||
MsInterface->InterfaceHandle = 0;
|
||||
MsInterface->bInterfaceClass = 0;
|
||||
MsInterface->bInterfaceSubClass = 0;
|
||||
MsInterface->bInterfaceProtocol = 0;
|
||||
MsInterface->InitCompleted = 0;
|
||||
MsInterface->MsPipes = NULL;
|
||||
|
||||
if (MsInterface->NumberOfPipes > 0)
|
||||
{
|
||||
MsInterface->MsPipes = msusb_mspipes_read(s, MsInterface->NumberOfPipes);
|
||||
|
||||
if (!MsInterface->MsPipes)
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
return MsInterface;
|
||||
out_error:
|
||||
msusb_msinterface_free(MsInterface);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOL msusb_msinterface_write(MSUSB_INTERFACE_DESCRIPTOR* MsInterface, wStream* out)
|
||||
{
|
||||
MSUSB_PIPE_DESCRIPTOR** MsPipes;
|
||||
MSUSB_PIPE_DESCRIPTOR* MsPipe;
|
||||
UINT32 pnum = 0;
|
||||
|
||||
if (!MsInterface)
|
||||
return FALSE;
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(out, 16 + MsInterface->NumberOfPipes * 20))
|
||||
return FALSE;
|
||||
|
||||
/* Length */
|
||||
Stream_Write_UINT16(out, MsInterface->Length);
|
||||
/* InterfaceNumber */
|
||||
Stream_Write_UINT8(out, MsInterface->InterfaceNumber);
|
||||
/* AlternateSetting */
|
||||
Stream_Write_UINT8(out, MsInterface->AlternateSetting);
|
||||
/* bInterfaceClass */
|
||||
Stream_Write_UINT8(out, MsInterface->bInterfaceClass);
|
||||
/* bInterfaceSubClass */
|
||||
Stream_Write_UINT8(out, MsInterface->bInterfaceSubClass);
|
||||
/* bInterfaceProtocol */
|
||||
Stream_Write_UINT8(out, MsInterface->bInterfaceProtocol);
|
||||
/* Padding */
|
||||
Stream_Write_UINT8(out, 0);
|
||||
/* InterfaceHandle */
|
||||
Stream_Write_UINT32(out, MsInterface->InterfaceHandle);
|
||||
/* NumberOfPipes */
|
||||
Stream_Write_UINT32(out, MsInterface->NumberOfPipes);
|
||||
/* Pipes */
|
||||
MsPipes = MsInterface->MsPipes;
|
||||
|
||||
for (pnum = 0; pnum < MsInterface->NumberOfPipes; pnum++)
|
||||
{
|
||||
MsPipe = MsPipes[pnum];
|
||||
/* MaximumPacketSize */
|
||||
Stream_Write_UINT16(out, MsPipe->MaximumPacketSize);
|
||||
/* EndpointAddress */
|
||||
Stream_Write_UINT8(out, MsPipe->bEndpointAddress);
|
||||
/* Interval */
|
||||
Stream_Write_UINT8(out, MsPipe->bInterval);
|
||||
/* PipeType */
|
||||
Stream_Write_UINT32(out, MsPipe->PipeType);
|
||||
/* PipeHandle */
|
||||
Stream_Write_UINT32(out, MsPipe->PipeHandle);
|
||||
/* MaximumTransferSize */
|
||||
Stream_Write_UINT32(out, MsPipe->MaximumTransferSize);
|
||||
/* PipeFlags */
|
||||
Stream_Write_UINT32(out, MsPipe->PipeFlags);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static MSUSB_INTERFACE_DESCRIPTOR** msusb_msinterface_read_list(wStream* s, UINT32 NumInterfaces)
|
||||
{
|
||||
UINT32 inum;
|
||||
MSUSB_INTERFACE_DESCRIPTOR** MsInterfaces;
|
||||
MsInterfaces =
|
||||
(MSUSB_INTERFACE_DESCRIPTOR**)calloc(NumInterfaces, sizeof(MSUSB_INTERFACE_DESCRIPTOR*));
|
||||
|
||||
if (!MsInterfaces)
|
||||
return NULL;
|
||||
|
||||
for (inum = 0; inum < NumInterfaces; inum++)
|
||||
{
|
||||
MsInterfaces[inum] = msusb_msinterface_read(s);
|
||||
|
||||
if (!MsInterfaces[inum])
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return MsInterfaces;
|
||||
fail:
|
||||
|
||||
for (inum = 0; inum < NumInterfaces; inum++)
|
||||
msusb_msinterface_free(MsInterfaces[inum]);
|
||||
|
||||
free(MsInterfaces);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOL msusb_msconfig_write(MSUSB_CONFIG_DESCRIPTOR* MsConfg, wStream* out)
|
||||
{
|
||||
UINT32 inum = 0;
|
||||
MSUSB_INTERFACE_DESCRIPTOR** MsInterfaces;
|
||||
MSUSB_INTERFACE_DESCRIPTOR* MsInterface;
|
||||
|
||||
if (!MsConfg)
|
||||
return FALSE;
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(out, 8))
|
||||
return FALSE;
|
||||
|
||||
/* ConfigurationHandle*/
|
||||
Stream_Write_UINT32(out, MsConfg->ConfigurationHandle);
|
||||
/* NumInterfaces*/
|
||||
Stream_Write_UINT32(out, MsConfg->NumInterfaces);
|
||||
/* Interfaces */
|
||||
MsInterfaces = MsConfg->MsInterfaces;
|
||||
|
||||
for (inum = 0; inum < MsConfg->NumInterfaces; inum++)
|
||||
{
|
||||
MsInterface = MsInterfaces[inum];
|
||||
|
||||
if (!msusb_msinterface_write(MsInterface, out))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
MSUSB_CONFIG_DESCRIPTOR* msusb_msconfig_new(void)
|
||||
{
|
||||
return (MSUSB_CONFIG_DESCRIPTOR*)calloc(1, sizeof(MSUSB_CONFIG_DESCRIPTOR));
|
||||
}
|
||||
|
||||
void msusb_msconfig_free(MSUSB_CONFIG_DESCRIPTOR* MsConfig)
|
||||
{
|
||||
if (MsConfig)
|
||||
{
|
||||
msusb_msinterface_free_list(MsConfig->MsInterfaces, MsConfig->NumInterfaces);
|
||||
MsConfig->MsInterfaces = NULL;
|
||||
free(MsConfig);
|
||||
}
|
||||
}
|
||||
|
||||
MSUSB_CONFIG_DESCRIPTOR* msusb_msconfig_read(wStream* s, UINT32 NumInterfaces)
|
||||
{
|
||||
MSUSB_CONFIG_DESCRIPTOR* MsConfig;
|
||||
BYTE lenConfiguration, typeConfiguration;
|
||||
|
||||
if (Stream_GetRemainingCapacity(s) < 6 + NumInterfaces * 2)
|
||||
return NULL;
|
||||
|
||||
MsConfig = msusb_msconfig_new();
|
||||
|
||||
if (!MsConfig)
|
||||
goto fail;
|
||||
|
||||
MsConfig->MsInterfaces = msusb_msinterface_read_list(s, NumInterfaces);
|
||||
|
||||
if (!MsConfig->MsInterfaces)
|
||||
goto fail;
|
||||
|
||||
Stream_Read_UINT8(s, lenConfiguration);
|
||||
Stream_Read_UINT8(s, typeConfiguration);
|
||||
|
||||
if (lenConfiguration != 0x9 || typeConfiguration != 0x2)
|
||||
{
|
||||
WLog_ERR(TAG, "len and type must be 0x9 and 0x2 , but it is 0x%" PRIx8 " and 0x%" PRIx8 "",
|
||||
lenConfiguration, typeConfiguration);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
Stream_Read_UINT16(s, MsConfig->wTotalLength);
|
||||
Stream_Seek(s, 1);
|
||||
Stream_Read_UINT8(s, MsConfig->bConfigurationValue);
|
||||
MsConfig->NumInterfaces = NumInterfaces;
|
||||
return MsConfig;
|
||||
fail:
|
||||
msusb_msconfig_free(MsConfig);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void msusb_msconfig_dump(MSUSB_CONFIG_DESCRIPTOR* MsConfig)
|
||||
{
|
||||
MSUSB_INTERFACE_DESCRIPTOR** MsInterfaces;
|
||||
MSUSB_INTERFACE_DESCRIPTOR* MsInterface;
|
||||
MSUSB_PIPE_DESCRIPTOR** MsPipes;
|
||||
MSUSB_PIPE_DESCRIPTOR* MsPipe;
|
||||
UINT32 inum = 0, pnum = 0;
|
||||
WLog_INFO(TAG, "=================MsConfig:========================");
|
||||
WLog_INFO(TAG, "wTotalLength:%" PRIu16 "", MsConfig->wTotalLength);
|
||||
WLog_INFO(TAG, "bConfigurationValue:%" PRIu8 "", MsConfig->bConfigurationValue);
|
||||
WLog_INFO(TAG, "ConfigurationHandle:0x%08" PRIx32 "", MsConfig->ConfigurationHandle);
|
||||
WLog_INFO(TAG, "InitCompleted:%d", MsConfig->InitCompleted);
|
||||
WLog_INFO(TAG, "MsOutSize:%d", MsConfig->MsOutSize);
|
||||
WLog_INFO(TAG, "NumInterfaces:%" PRIu32 "", MsConfig->NumInterfaces);
|
||||
MsInterfaces = MsConfig->MsInterfaces;
|
||||
|
||||
for (inum = 0; inum < MsConfig->NumInterfaces; inum++)
|
||||
{
|
||||
MsInterface = MsInterfaces[inum];
|
||||
WLog_INFO(TAG, " Interface: %" PRIu8 "", MsInterface->InterfaceNumber);
|
||||
WLog_INFO(TAG, " Length: %" PRIu16 "", MsInterface->Length);
|
||||
WLog_INFO(TAG, " NumberOfPipesExpected: %" PRIu16 "",
|
||||
MsInterface->NumberOfPipesExpected);
|
||||
WLog_INFO(TAG, " AlternateSetting: %" PRIu8 "", MsInterface->AlternateSetting);
|
||||
WLog_INFO(TAG, " NumberOfPipes: %" PRIu32 "", MsInterface->NumberOfPipes);
|
||||
WLog_INFO(TAG, " InterfaceHandle: 0x%08" PRIx32 "", MsInterface->InterfaceHandle);
|
||||
WLog_INFO(TAG, " bInterfaceClass: 0x%02" PRIx8 "", MsInterface->bInterfaceClass);
|
||||
WLog_INFO(TAG, " bInterfaceSubClass: 0x%02" PRIx8 "", MsInterface->bInterfaceSubClass);
|
||||
WLog_INFO(TAG, " bInterfaceProtocol: 0x%02" PRIx8 "", MsInterface->bInterfaceProtocol);
|
||||
WLog_INFO(TAG, " InitCompleted: %d", MsInterface->InitCompleted);
|
||||
MsPipes = MsInterface->MsPipes;
|
||||
|
||||
for (pnum = 0; pnum < MsInterface->NumberOfPipes; pnum++)
|
||||
{
|
||||
MsPipe = MsPipes[pnum];
|
||||
WLog_INFO(TAG, " Pipe: %d", pnum);
|
||||
WLog_INFO(TAG, " MaximumPacketSize: 0x%04" PRIx16 "", MsPipe->MaximumPacketSize);
|
||||
WLog_INFO(TAG, " MaximumTransferSize: 0x%08" PRIx32 "",
|
||||
MsPipe->MaximumTransferSize);
|
||||
WLog_INFO(TAG, " PipeFlags: 0x%08" PRIx32 "", MsPipe->PipeFlags);
|
||||
WLog_INFO(TAG, " PipeHandle: 0x%08" PRIx32 "", MsPipe->PipeHandle);
|
||||
WLog_INFO(TAG, " bEndpointAddress: 0x%02" PRIx8 "", MsPipe->bEndpointAddress);
|
||||
WLog_INFO(TAG, " bInterval: %" PRIu8 "", MsPipe->bInterval);
|
||||
WLog_INFO(TAG, " PipeType: 0x%02" PRIx8 "", MsPipe->PipeType);
|
||||
WLog_INFO(TAG, " InitCompleted: %d", MsPipe->InitCompleted);
|
||||
}
|
||||
}
|
||||
|
||||
WLog_INFO(TAG, "==================================================");
|
||||
}
|
||||
97
channels/urbdrc/common/msusb.h
Normal file
97
channels/urbdrc/common/msusb.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RemoteFX USB Redirection
|
||||
*
|
||||
* Copyright 2012 Atrust corp.
|
||||
* Copyright 2012 Alfred Liu <alfred.liu@atruscorp.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_UTILS_MSCONFIG_H
|
||||
#define FREERDP_UTILS_MSCONFIG_H
|
||||
|
||||
#include <winpr/stream.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
typedef struct _MSUSB_INTERFACE_DESCRIPTOR MSUSB_INTERFACE_DESCRIPTOR;
|
||||
typedef struct _MSUSB_PIPE_DESCRIPTOR MSUSB_PIPE_DESCRIPTOR;
|
||||
typedef struct _MSUSB_CONFIG_DESCRIPTOR MSUSB_CONFIG_DESCRIPTOR;
|
||||
|
||||
struct _MSUSB_PIPE_DESCRIPTOR
|
||||
{
|
||||
UINT16 MaximumPacketSize;
|
||||
UINT32 MaximumTransferSize;
|
||||
UINT32 PipeFlags;
|
||||
UINT32 PipeHandle;
|
||||
BYTE bEndpointAddress;
|
||||
BYTE bInterval;
|
||||
BYTE PipeType;
|
||||
int InitCompleted;
|
||||
};
|
||||
|
||||
struct _MSUSB_INTERFACE_DESCRIPTOR
|
||||
{
|
||||
UINT16 Length;
|
||||
UINT16 NumberOfPipesExpected;
|
||||
BYTE InterfaceNumber;
|
||||
BYTE AlternateSetting;
|
||||
UINT32 NumberOfPipes;
|
||||
UINT32 InterfaceHandle;
|
||||
BYTE bInterfaceClass;
|
||||
BYTE bInterfaceSubClass;
|
||||
BYTE bInterfaceProtocol;
|
||||
MSUSB_PIPE_DESCRIPTOR** MsPipes;
|
||||
int InitCompleted;
|
||||
};
|
||||
|
||||
struct _MSUSB_CONFIG_DESCRIPTOR
|
||||
{
|
||||
UINT16 wTotalLength;
|
||||
BYTE bConfigurationValue;
|
||||
UINT32 ConfigurationHandle;
|
||||
UINT32 NumInterfaces;
|
||||
MSUSB_INTERFACE_DESCRIPTOR** MsInterfaces;
|
||||
int InitCompleted;
|
||||
int MsOutSize;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* MSUSB_PIPE exported functions */
|
||||
FREERDP_API BOOL msusb_mspipes_replace(MSUSB_INTERFACE_DESCRIPTOR* MsInterface,
|
||||
MSUSB_PIPE_DESCRIPTOR** NewMsPipes,
|
||||
UINT32 NewNumberOfPipes);
|
||||
|
||||
/* MSUSB_INTERFACE exported functions */
|
||||
FREERDP_API BOOL msusb_msinterface_replace(MSUSB_CONFIG_DESCRIPTOR* MsConfig,
|
||||
BYTE InterfaceNumber,
|
||||
MSUSB_INTERFACE_DESCRIPTOR* NewMsInterface);
|
||||
FREERDP_API MSUSB_INTERFACE_DESCRIPTOR* msusb_msinterface_read(wStream* out);
|
||||
FREERDP_API BOOL msusb_msinterface_write(MSUSB_INTERFACE_DESCRIPTOR* MsInterface, wStream* out);
|
||||
|
||||
/* MSUSB_CONFIG exported functions */
|
||||
FREERDP_API MSUSB_CONFIG_DESCRIPTOR* msusb_msconfig_new(void);
|
||||
FREERDP_API void msusb_msconfig_free(MSUSB_CONFIG_DESCRIPTOR* MsConfig);
|
||||
FREERDP_API MSUSB_CONFIG_DESCRIPTOR* msusb_msconfig_read(wStream* s, UINT32 NumInterfaces);
|
||||
FREERDP_API BOOL msusb_msconfig_write(MSUSB_CONFIG_DESCRIPTOR* MsConfg, wStream* out);
|
||||
FREERDP_API void msusb_msconfig_dump(MSUSB_CONFIG_DESCRIPTOR* MsConfg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_UTILS_MSCONFIG_H */
|
||||
408
channels/urbdrc/common/urbdrc_helpers.c
Normal file
408
channels/urbdrc/common/urbdrc_helpers.c
Normal file
@@ -0,0 +1,408 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Server USB redirection channel - helper functions
|
||||
*
|
||||
* Copyright 2019 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2019 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "urbdrc_helpers.h"
|
||||
#include "urbdrc_types.h"
|
||||
|
||||
const char* mask_to_string(UINT32 mask)
|
||||
{
|
||||
switch (mask)
|
||||
{
|
||||
case STREAM_ID_NONE:
|
||||
return "STREAM_ID_NONE";
|
||||
|
||||
case STREAM_ID_PROXY:
|
||||
return "STREAM_ID_PROXY";
|
||||
|
||||
case STREAM_ID_STUB:
|
||||
return "STREAM_ID_STUB";
|
||||
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
const char* interface_to_string(UINT32 id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case CAPABILITIES_NEGOTIATOR:
|
||||
return "CAPABILITIES_NEGOTIATOR";
|
||||
|
||||
case SERVER_CHANNEL_NOTIFICATION:
|
||||
return "SERVER_CHANNEL_NOTIFICATION";
|
||||
|
||||
case CLIENT_CHANNEL_NOTIFICATION:
|
||||
return "CLIENT_CHANNEL_NOTIFICATION";
|
||||
|
||||
default:
|
||||
return "DEVICE_MESSAGE";
|
||||
}
|
||||
}
|
||||
|
||||
static const char* call_to_string_none(BOOL client, UINT32 interfaceId, UINT32 functionId)
|
||||
{
|
||||
WINPR_UNUSED(interfaceId);
|
||||
|
||||
if (client)
|
||||
return "RIM_EXCHANGE_CAPABILITY_RESPONSE [none |client]";
|
||||
else
|
||||
{
|
||||
switch (functionId)
|
||||
{
|
||||
case RIM_EXCHANGE_CAPABILITY_REQUEST:
|
||||
return "RIM_EXCHANGE_CAPABILITY_REQUEST [none |server]";
|
||||
|
||||
case RIMCALL_RELEASE:
|
||||
return "RIMCALL_RELEASE [none |server]";
|
||||
|
||||
case RIMCALL_QUERYINTERFACE:
|
||||
return "RIMCALL_QUERYINTERFACE [none |server]";
|
||||
|
||||
default:
|
||||
return "UNKNOWN [none |server]";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const char* call_to_string_proxy_server(UINT32 functionId)
|
||||
{
|
||||
switch (functionId)
|
||||
{
|
||||
case QUERY_DEVICE_TEXT:
|
||||
return "QUERY_DEVICE_TEXT [proxy|server]";
|
||||
|
||||
case INTERNAL_IO_CONTROL:
|
||||
return "INTERNAL_IO_CONTROL [proxy|server]";
|
||||
|
||||
case IO_CONTROL:
|
||||
return "IO_CONTROL [proxy|server]";
|
||||
|
||||
case REGISTER_REQUEST_CALLBACK:
|
||||
return "REGISTER_REQUEST_CALLBACK [proxy|server]";
|
||||
|
||||
case CANCEL_REQUEST:
|
||||
return "CANCEL_REQUEST [proxy|server]";
|
||||
|
||||
case RETRACT_DEVICE:
|
||||
return "RETRACT_DEVICE [proxy|server]";
|
||||
|
||||
case TRANSFER_IN_REQUEST:
|
||||
return "TRANSFER_IN_REQUEST [proxy|server]";
|
||||
|
||||
default:
|
||||
return "UNKNOWN [proxy|server]";
|
||||
}
|
||||
}
|
||||
|
||||
static const char* call_to_string_proxy_client(UINT32 functionId)
|
||||
{
|
||||
switch (functionId)
|
||||
{
|
||||
case URB_COMPLETION_NO_DATA:
|
||||
return "URB_COMPLETION_NO_DATA [proxy|client]";
|
||||
|
||||
case URB_COMPLETION:
|
||||
return "URB_COMPLETION [proxy|client]";
|
||||
|
||||
case IOCONTROL_COMPLETION:
|
||||
return "IOCONTROL_COMPLETION [proxy|client]";
|
||||
|
||||
case TRANSFER_OUT_REQUEST:
|
||||
return "TRANSFER_OUT_REQUEST [proxy|client]";
|
||||
|
||||
default:
|
||||
return "UNKNOWN [proxy|client]";
|
||||
}
|
||||
}
|
||||
|
||||
static const char* call_to_string_proxy(BOOL client, UINT32 interfaceId, UINT32 functionId)
|
||||
{
|
||||
switch (interfaceId & INTERFACE_ID_MASK)
|
||||
{
|
||||
case CLIENT_DEVICE_SINK:
|
||||
switch (functionId)
|
||||
{
|
||||
case ADD_VIRTUAL_CHANNEL:
|
||||
return "ADD_VIRTUAL_CHANNEL [proxy|sink ]";
|
||||
|
||||
case ADD_DEVICE:
|
||||
return "ADD_DEVICE [proxy|sink ]";
|
||||
case RIMCALL_RELEASE:
|
||||
return "RIMCALL_RELEASE [proxy|sink ]";
|
||||
|
||||
case RIMCALL_QUERYINTERFACE:
|
||||
return "RIMCALL_QUERYINTERFACE [proxy|sink ]";
|
||||
default:
|
||||
return "UNKNOWN [proxy|sink ]";
|
||||
}
|
||||
|
||||
case SERVER_CHANNEL_NOTIFICATION:
|
||||
switch (functionId)
|
||||
{
|
||||
case CHANNEL_CREATED:
|
||||
return "CHANNEL_CREATED [proxy|server]";
|
||||
|
||||
case RIMCALL_RELEASE:
|
||||
return "RIMCALL_RELEASE [proxy|server]";
|
||||
|
||||
case RIMCALL_QUERYINTERFACE:
|
||||
return "RIMCALL_QUERYINTERFACE [proxy|server]";
|
||||
|
||||
default:
|
||||
return "UNKNOWN [proxy|server]";
|
||||
}
|
||||
|
||||
case CLIENT_CHANNEL_NOTIFICATION:
|
||||
switch (functionId)
|
||||
{
|
||||
case CHANNEL_CREATED:
|
||||
return "CHANNEL_CREATED [proxy|client]";
|
||||
case RIMCALL_RELEASE:
|
||||
return "RIMCALL_RELEASE [proxy|client]";
|
||||
case RIMCALL_QUERYINTERFACE:
|
||||
return "RIMCALL_QUERYINTERFACE [proxy|client]";
|
||||
default:
|
||||
return "UNKNOWN [proxy|client]";
|
||||
}
|
||||
|
||||
default:
|
||||
if (client)
|
||||
return call_to_string_proxy_client(functionId);
|
||||
else
|
||||
return call_to_string_proxy_server(functionId);
|
||||
}
|
||||
}
|
||||
|
||||
static const char* call_to_string_stub(BOOL client, UINT32 interfaceId, UINT32 functionId)
|
||||
{
|
||||
return "QUERY_DEVICE_TEXT_RSP [stub |client]";
|
||||
}
|
||||
|
||||
const char* call_to_string(BOOL client, UINT32 interface, UINT32 functionId)
|
||||
{
|
||||
const UINT32 mask = (interface & STREAM_ID_MASK) >> 30;
|
||||
const UINT32 interfaceId = interface & INTERFACE_ID_MASK;
|
||||
|
||||
switch (mask)
|
||||
{
|
||||
case STREAM_ID_NONE:
|
||||
return call_to_string_none(client, interfaceId, functionId);
|
||||
|
||||
case STREAM_ID_PROXY:
|
||||
return call_to_string_proxy(client, interfaceId, functionId);
|
||||
|
||||
case STREAM_ID_STUB:
|
||||
return call_to_string_stub(client, interfaceId, functionId);
|
||||
|
||||
default:
|
||||
return "UNKNOWN[mask]";
|
||||
}
|
||||
}
|
||||
|
||||
const char* urb_function_string(UINT16 urb)
|
||||
{
|
||||
switch (urb)
|
||||
{
|
||||
case TS_URB_SELECT_CONFIGURATION:
|
||||
return "TS_URB_SELECT_CONFIGURATION";
|
||||
|
||||
case TS_URB_SELECT_INTERFACE:
|
||||
return "TS_URB_SELECT_INTERFACE";
|
||||
|
||||
case TS_URB_PIPE_REQUEST:
|
||||
return "TS_URB_PIPE_REQUEST";
|
||||
|
||||
case TS_URB_TAKE_FRAME_LENGTH_CONTROL:
|
||||
return "TS_URB_TAKE_FRAME_LENGTH_CONTROL";
|
||||
|
||||
case TS_URB_RELEASE_FRAME_LENGTH_CONTROL:
|
||||
return "TS_URB_RELEASE_FRAME_LENGTH_CONTROL";
|
||||
|
||||
case TS_URB_GET_FRAME_LENGTH:
|
||||
return "TS_URB_GET_FRAME_LENGTH";
|
||||
|
||||
case TS_URB_SET_FRAME_LENGTH:
|
||||
return "TS_URB_SET_FRAME_LENGTH";
|
||||
|
||||
case TS_URB_GET_CURRENT_FRAME_NUMBER:
|
||||
return "TS_URB_GET_CURRENT_FRAME_NUMBER";
|
||||
|
||||
case TS_URB_CONTROL_TRANSFER:
|
||||
return "TS_URB_CONTROL_TRANSFER";
|
||||
|
||||
case TS_URB_BULK_OR_INTERRUPT_TRANSFER:
|
||||
return "TS_URB_BULK_OR_INTERRUPT_TRANSFER";
|
||||
|
||||
case TS_URB_ISOCH_TRANSFER:
|
||||
return "TS_URB_ISOCH_TRANSFER";
|
||||
|
||||
case TS_URB_GET_DESCRIPTOR_FROM_DEVICE:
|
||||
return "TS_URB_GET_DESCRIPTOR_FROM_DEVICE";
|
||||
|
||||
case TS_URB_SET_DESCRIPTOR_TO_DEVICE:
|
||||
return "TS_URB_SET_DESCRIPTOR_TO_DEVICE";
|
||||
|
||||
case TS_URB_SET_FEATURE_TO_DEVICE:
|
||||
return "TS_URB_SET_FEATURE_TO_DEVICE";
|
||||
|
||||
case TS_URB_SET_FEATURE_TO_INTERFACE:
|
||||
return "TS_URB_SET_FEATURE_TO_INTERFACE";
|
||||
|
||||
case TS_URB_SET_FEATURE_TO_ENDPOINT:
|
||||
return "TS_URB_SET_FEATURE_TO_ENDPOINT";
|
||||
|
||||
case TS_URB_CLEAR_FEATURE_TO_DEVICE:
|
||||
return "TS_URB_CLEAR_FEATURE_TO_DEVICE";
|
||||
|
||||
case TS_URB_CLEAR_FEATURE_TO_INTERFACE:
|
||||
return "TS_URB_CLEAR_FEATURE_TO_INTERFACE";
|
||||
|
||||
case TS_URB_CLEAR_FEATURE_TO_ENDPOINT:
|
||||
return "TS_URB_CLEAR_FEATURE_TO_ENDPOINT";
|
||||
|
||||
case TS_URB_GET_STATUS_FROM_DEVICE:
|
||||
return "TS_URB_GET_STATUS_FROM_DEVICE";
|
||||
|
||||
case TS_URB_GET_STATUS_FROM_INTERFACE:
|
||||
return "TS_URB_GET_STATUS_FROM_INTERFACE";
|
||||
|
||||
case TS_URB_GET_STATUS_FROM_ENDPOINT:
|
||||
return "TS_URB_GET_STATUS_FROM_ENDPOINT";
|
||||
|
||||
case TS_URB_RESERVED_0X0016:
|
||||
return "TS_URB_RESERVED_0X0016";
|
||||
|
||||
case TS_URB_VENDOR_DEVICE:
|
||||
return "TS_URB_VENDOR_DEVICE";
|
||||
|
||||
case TS_URB_VENDOR_INTERFACE:
|
||||
return "TS_URB_VENDOR_INTERFACE";
|
||||
|
||||
case TS_URB_VENDOR_ENDPOINT:
|
||||
return "TS_URB_VENDOR_ENDPOINT";
|
||||
|
||||
case TS_URB_CLASS_DEVICE:
|
||||
return "TS_URB_CLASS_DEVICE";
|
||||
|
||||
case TS_URB_CLASS_INTERFACE:
|
||||
return "TS_URB_CLASS_INTERFACE";
|
||||
|
||||
case TS_URB_CLASS_ENDPOINT:
|
||||
return "TS_URB_CLASS_ENDPOINT";
|
||||
|
||||
case TS_URB_RESERVE_0X001D:
|
||||
return "TS_URB_RESERVE_0X001D";
|
||||
|
||||
case TS_URB_SYNC_RESET_PIPE_AND_CLEAR_STALL:
|
||||
return "TS_URB_SYNC_RESET_PIPE_AND_CLEAR_STALL";
|
||||
|
||||
case TS_URB_CLASS_OTHER:
|
||||
return "TS_URB_CLASS_OTHER";
|
||||
|
||||
case TS_URB_VENDOR_OTHER:
|
||||
return "TS_URB_VENDOR_OTHER";
|
||||
|
||||
case TS_URB_GET_STATUS_FROM_OTHER:
|
||||
return "TS_URB_GET_STATUS_FROM_OTHER";
|
||||
|
||||
case TS_URB_CLEAR_FEATURE_TO_OTHER:
|
||||
return "TS_URB_CLEAR_FEATURE_TO_OTHER";
|
||||
|
||||
case TS_URB_SET_FEATURE_TO_OTHER:
|
||||
return "TS_URB_SET_FEATURE_TO_OTHER";
|
||||
|
||||
case TS_URB_GET_DESCRIPTOR_FROM_ENDPOINT:
|
||||
return "TS_URB_GET_DESCRIPTOR_FROM_ENDPOINT";
|
||||
|
||||
case TS_URB_SET_DESCRIPTOR_TO_ENDPOINT:
|
||||
return "TS_URB_SET_DESCRIPTOR_TO_ENDPOINT";
|
||||
|
||||
case TS_URB_CONTROL_GET_CONFIGURATION_REQUEST:
|
||||
return "TS_URB_CONTROL_GET_CONFIGURATION_REQUEST";
|
||||
|
||||
case TS_URB_CONTROL_GET_INTERFACE_REQUEST:
|
||||
return "TS_URB_CONTROL_GET_INTERFACE_REQUEST";
|
||||
|
||||
case TS_URB_GET_DESCRIPTOR_FROM_INTERFACE:
|
||||
return "TS_URB_GET_DESCRIPTOR_FROM_INTERFACE";
|
||||
|
||||
case TS_URB_SET_DESCRIPTOR_TO_INTERFACE:
|
||||
return "TS_URB_SET_DESCRIPTOR_TO_INTERFACE";
|
||||
|
||||
case TS_URB_GET_OS_FEATURE_DESCRIPTOR_REQUEST:
|
||||
return "TS_URB_GET_OS_FEATURE_DESCRIPTOR_REQUEST";
|
||||
|
||||
case TS_URB_RESERVE_0X002B:
|
||||
return "TS_URB_RESERVE_0X002B";
|
||||
|
||||
case TS_URB_RESERVE_0X002C:
|
||||
return "TS_URB_RESERVE_0X002C";
|
||||
|
||||
case TS_URB_RESERVE_0X002D:
|
||||
return "TS_URB_RESERVE_0X002D";
|
||||
|
||||
case TS_URB_RESERVE_0X002E:
|
||||
return "TS_URB_RESERVE_0X002E";
|
||||
|
||||
case TS_URB_RESERVE_0X002F:
|
||||
return "TS_URB_RESERVE_0X002F";
|
||||
|
||||
case TS_URB_SYNC_RESET_PIPE:
|
||||
return "TS_URB_SYNC_RESET_PIPE";
|
||||
|
||||
case TS_URB_SYNC_CLEAR_STALL:
|
||||
return "TS_URB_SYNC_CLEAR_STALL";
|
||||
|
||||
case TS_URB_CONTROL_TRANSFER_EX:
|
||||
return "TS_URB_CONTROL_TRANSFER_EX";
|
||||
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
void urbdrc_dump_message(wLog* log, BOOL client, BOOL write, wStream* s)
|
||||
{
|
||||
const char* type = write ? "WRITE" : "READ";
|
||||
UINT32 InterfaceId, MessageId, FunctionId;
|
||||
size_t length, pos;
|
||||
|
||||
pos = Stream_GetPosition(s);
|
||||
if (write)
|
||||
{
|
||||
length = Stream_GetPosition(s);
|
||||
Stream_SetPosition(s, 0);
|
||||
}
|
||||
else
|
||||
length = Stream_GetRemainingLength(s);
|
||||
|
||||
if (length < 12)
|
||||
return;
|
||||
|
||||
Stream_Read_UINT32(s, InterfaceId);
|
||||
Stream_Read_UINT32(s, MessageId);
|
||||
Stream_Read_UINT32(s, FunctionId);
|
||||
Stream_SetPosition(s, pos);
|
||||
|
||||
WLog_Print(log, WLOG_DEBUG,
|
||||
"[%-5s] %s [%08" PRIx32 "] InterfaceId=%08" PRIx32 ", MessageId=%08" PRIx32
|
||||
", FunctionId=%08" PRIx32 ", length=%" PRIdz,
|
||||
type, call_to_string(client, InterfaceId, FunctionId), FunctionId, InterfaceId,
|
||||
MessageId, FunctionId, length);
|
||||
}
|
||||
45
channels/urbdrc/common/urbdrc_helpers.h
Normal file
45
channels/urbdrc/common/urbdrc_helpers.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Server USB redirection channel - helper functions
|
||||
*
|
||||
* Copyright 2019 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2019 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_CHANNEL_URBDRC_HELPERS_H
|
||||
#define FREERDP_CHANNEL_URBDRC_HELPERS_H
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <winpr/wlog.h>
|
||||
#include <winpr/stream.h>
|
||||
|
||||
const char* urb_function_string(UINT16 urb);
|
||||
const char* mask_to_string(UINT32 mask);
|
||||
const char* interface_to_string(UINT32 id);
|
||||
const char* call_to_string(BOOL client, UINT32 interface, UINT32 functionId);
|
||||
|
||||
void urbdrc_dump_message(wLog* log, BOOL client, BOOL write, wStream* s);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_CHANNEL_URBDRC_HELPERS_H */
|
||||
@@ -27,24 +27,12 @@
|
||||
|
||||
#include <freerdp/dvc.h>
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/channels/log.h>
|
||||
#include <freerdp/utils/msusb.h>
|
||||
|
||||
#include <uuid.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <msusb.h>
|
||||
|
||||
#include <winpr/stream.h>
|
||||
|
||||
#define TAG CHANNELS_TAG("urbdrc.client")
|
||||
#ifdef WITH_DEBUG_DVC
|
||||
#define DEBUG_DVC(...) WLog_DBG(TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_DVC(...) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#endif
|
||||
#define RIM_CAPABILITY_VERSION_01 0x00000001
|
||||
|
||||
#define CAPABILITIES_NEGOTIATOR 0x00000000
|
||||
#define CLIENT_DEVICE_SINK 0x00000001
|
||||
@@ -53,6 +41,7 @@
|
||||
#define BASE_USBDEVICE_NUM 0x00000005
|
||||
|
||||
#define RIMCALL_RELEASE 0x00000001
|
||||
#define RIMCALL_QUERYINTERFACE 0x00000002
|
||||
#define RIM_EXCHANGE_CAPABILITY_REQUEST 0x00000100
|
||||
#define CHANNEL_CREATED 0x00000100
|
||||
#define ADD_VIRTUAL_CHANNEL 0x00000100
|
||||
@@ -88,15 +77,18 @@
|
||||
#define USB_v2_0 0x200
|
||||
#define USB_v3_0 0x300
|
||||
|
||||
#define STREAM_ID_NONE 0x0
|
||||
#define STREAM_ID_PROXY 0x1
|
||||
#define STREAM_ID_STUB 0x2
|
||||
#define STREAM_ID_NONE 0x0UL
|
||||
#define STREAM_ID_PROXY 0x1UL
|
||||
#define STREAM_ID_STUB 0x2UL
|
||||
#define STREAM_ID_MASK 0xC0000000
|
||||
#define INTERFACE_ID_MASK 0x3FFFFFFF
|
||||
|
||||
#define CANCEL_REQUEST 0x00000100
|
||||
#define REGISTER_REQUEST_CALLBACK 0x00000101
|
||||
#define IO_CONTROL 0x00000102
|
||||
#define INTERNAL_IO_CONTROL 0x00000103
|
||||
#define QUERY_DEVICE_TEXT 0x00000104
|
||||
|
||||
#define TRANSFER_IN_REQUEST 0x00000105
|
||||
#define TRANSFER_OUT_REQUEST 0x00000106
|
||||
#define RETRACT_DEVICE 0x00000107
|
||||
@@ -142,63 +134,64 @@ enum device_descriptor_table
|
||||
#define IOCTL_INTERNAL_USB_CYCLE_PORT 0x0022001F
|
||||
#define IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION 0x00220027
|
||||
|
||||
#define URB_FUNCTION_SELECT_CONFIGURATION 0x0000
|
||||
#define URB_FUNCTION_SELECT_INTERFACE 0x0001
|
||||
#define URB_FUNCTION_ABORT_PIPE 0x0002
|
||||
#define URB_FUNCTION_TAKE_FRAME_LENGTH_CONTROL 0x0003
|
||||
#define URB_FUNCTION_RELEASE_FRAME_LENGTH_CONTROL 0x0004
|
||||
#define URB_FUNCTION_GET_FRAME_LENGTH 0x0005
|
||||
#define URB_FUNCTION_SET_FRAME_LENGTH 0x0006
|
||||
#define URB_FUNCTION_GET_CURRENT_FRAME_NUMBER 0x0007
|
||||
#define URB_FUNCTION_CONTROL_TRANSFER 0x0008
|
||||
#define URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER 0x0009
|
||||
#define URB_FUNCTION_ISOCH_TRANSFER 0x000A
|
||||
#define URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE 0x000B
|
||||
#define URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE 0x000C
|
||||
#define URB_FUNCTION_SET_FEATURE_TO_DEVICE 0x000D
|
||||
#define URB_FUNCTION_SET_FEATURE_TO_INTERFACE 0x000E
|
||||
#define URB_FUNCTION_SET_FEATURE_TO_ENDPOINT 0x000F
|
||||
#define URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE 0x0010
|
||||
#define URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE 0x0011
|
||||
#define URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT 0x0012
|
||||
#define URB_FUNCTION_GET_STATUS_FROM_DEVICE 0x0013
|
||||
#define URB_FUNCTION_GET_STATUS_FROM_INTERFACE 0x0014
|
||||
#define URB_FUNCTION_GET_STATUS_FROM_ENDPOINT 0x0015
|
||||
#define URB_FUNCTION_RESERVED_0X0016 0x0016
|
||||
#define URB_FUNCTION_VENDOR_DEVICE 0x0017
|
||||
#define URB_FUNCTION_VENDOR_INTERFACE 0x0018
|
||||
#define URB_FUNCTION_VENDOR_ENDPOINT 0x0019
|
||||
#define URB_FUNCTION_CLASS_DEVICE 0x001A
|
||||
#define URB_FUNCTION_CLASS_INTERFACE 0x001B
|
||||
#define URB_FUNCTION_CLASS_ENDPOINT 0x001C
|
||||
#define URB_FUNCTION_RESERVE_0X001D 0x001D
|
||||
#define URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL 0x001E
|
||||
#define URB_FUNCTION_CLASS_OTHER 0x001F
|
||||
#define URB_FUNCTION_VENDOR_OTHER 0x0020
|
||||
#define URB_FUNCTION_GET_STATUS_FROM_OTHER 0x0021
|
||||
#define URB_FUNCTION_CLEAR_FEATURE_TO_OTHER 0x0022
|
||||
#define URB_FUNCTION_SET_FEATURE_TO_OTHER 0x0023
|
||||
#define URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT 0x0024
|
||||
#define URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT 0x0025
|
||||
#define URB_FUNCTION_GET_CONFIGURATION 0x0026
|
||||
#define URB_FUNCTION_GET_INTERFACE 0x0027
|
||||
#define URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE 0x0028
|
||||
#define URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE 0x0029
|
||||
#define URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR 0x002A
|
||||
#define URB_FUNCTION_RESERVE_0X002B 0x002B
|
||||
#define URB_FUNCTION_RESERVE_0X002C 0x002C
|
||||
#define URB_FUNCTION_RESERVE_0X002D 0x002D
|
||||
#define URB_FUNCTION_RESERVE_0X002E 0x002E
|
||||
#define URB_FUNCTION_RESERVE_0X002F 0x002F
|
||||
#define TS_URB_SELECT_CONFIGURATION 0x0000
|
||||
#define TS_URB_SELECT_INTERFACE 0x0001
|
||||
#define TS_URB_PIPE_REQUEST 0x0002
|
||||
#define TS_URB_TAKE_FRAME_LENGTH_CONTROL 0x0003
|
||||
#define TS_URB_RELEASE_FRAME_LENGTH_CONTROL 0x0004
|
||||
#define TS_URB_GET_FRAME_LENGTH 0x0005
|
||||
#define TS_URB_SET_FRAME_LENGTH 0x0006
|
||||
#define TS_URB_GET_CURRENT_FRAME_NUMBER 0x0007
|
||||
#define TS_URB_CONTROL_TRANSFER 0x0008
|
||||
#define TS_URB_BULK_OR_INTERRUPT_TRANSFER 0x0009
|
||||
#define TS_URB_ISOCH_TRANSFER 0x000A
|
||||
#define TS_URB_GET_DESCRIPTOR_FROM_DEVICE 0x000B
|
||||
#define TS_URB_SET_DESCRIPTOR_TO_DEVICE 0x000C
|
||||
#define TS_URB_SET_FEATURE_TO_DEVICE 0x000D
|
||||
#define TS_URB_SET_FEATURE_TO_INTERFACE 0x000E
|
||||
#define TS_URB_SET_FEATURE_TO_ENDPOINT 0x000F
|
||||
#define TS_URB_CLEAR_FEATURE_TO_DEVICE 0x0010
|
||||
#define TS_URB_CLEAR_FEATURE_TO_INTERFACE 0x0011
|
||||
#define TS_URB_CLEAR_FEATURE_TO_ENDPOINT 0x0012
|
||||
#define TS_URB_GET_STATUS_FROM_DEVICE 0x0013
|
||||
#define TS_URB_GET_STATUS_FROM_INTERFACE 0x0014
|
||||
#define TS_URB_GET_STATUS_FROM_ENDPOINT 0x0015
|
||||
#define TS_URB_RESERVED_0X0016 0x0016
|
||||
#define TS_URB_VENDOR_DEVICE 0x0017
|
||||
#define TS_URB_VENDOR_INTERFACE 0x0018
|
||||
#define TS_URB_VENDOR_ENDPOINT 0x0019
|
||||
#define TS_URB_CLASS_DEVICE 0x001A
|
||||
#define TS_URB_CLASS_INTERFACE 0x001B
|
||||
#define TS_URB_CLASS_ENDPOINT 0x001C
|
||||
#define TS_URB_RESERVE_0X001D 0x001D
|
||||
#define TS_URB_SYNC_RESET_PIPE_AND_CLEAR_STALL 0x001E
|
||||
#define TS_URB_CLASS_OTHER 0x001F
|
||||
#define TS_URB_VENDOR_OTHER 0x0020
|
||||
#define TS_URB_GET_STATUS_FROM_OTHER 0x0021
|
||||
#define TS_URB_CLEAR_FEATURE_TO_OTHER 0x0022
|
||||
#define TS_URB_SET_FEATURE_TO_OTHER 0x0023
|
||||
#define TS_URB_GET_DESCRIPTOR_FROM_ENDPOINT 0x0024
|
||||
#define TS_URB_SET_DESCRIPTOR_TO_ENDPOINT 0x0025
|
||||
#define TS_URB_CONTROL_GET_CONFIGURATION_REQUEST 0x0026
|
||||
#define TS_URB_CONTROL_GET_INTERFACE_REQUEST 0x0027
|
||||
#define TS_URB_GET_DESCRIPTOR_FROM_INTERFACE 0x0028
|
||||
#define TS_URB_SET_DESCRIPTOR_TO_INTERFACE 0x0029
|
||||
#define TS_URB_GET_OS_FEATURE_DESCRIPTOR_REQUEST 0x002A
|
||||
#define TS_URB_RESERVE_0X002B 0x002B
|
||||
#define TS_URB_RESERVE_0X002C 0x002C
|
||||
#define TS_URB_RESERVE_0X002D 0x002D
|
||||
#define TS_URB_RESERVE_0X002E 0x002E
|
||||
#define TS_URB_RESERVE_0X002F 0x002F
|
||||
// USB 2.0 calls start at 0x0030
|
||||
#define URB_FUNCTION_SYNC_RESET_PIPE 0x0030
|
||||
#define URB_FUNCTION_SYNC_CLEAR_STALL 0x0031
|
||||
#define URB_FUNCTION_CONTROL_TRANSFER_EX 0x0032
|
||||
#define TS_URB_SYNC_RESET_PIPE 0x0030
|
||||
#define TS_URB_SYNC_CLEAR_STALL 0x0031
|
||||
#define TS_URB_CONTROL_TRANSFER_EX 0x0032
|
||||
|
||||
#define USBD_STATUS_SUCCESS 0x0
|
||||
#define USBD_STATUS_PENDING 0x40000000
|
||||
#define USBD_STATUS_CANCELED 0xC0010000
|
||||
|
||||
#define USBD_STATUS_INVALID_URB_FUNCTION 0x80000200
|
||||
#define USBD_STATUS_CRC 0xC0000001
|
||||
#define USBD_STATUS_BTSTUFF 0xC0000002
|
||||
#define USBD_STATUS_DATA_TOGGLE_MISMATCH 0xC0000003
|
||||
@@ -303,7 +296,6 @@ enum device_descriptor_table
|
||||
|
||||
#define URBDRC_DEVICE_INITIALIZED 0x01
|
||||
#define URBDRC_DEVICE_NOT_FOUND 0x02
|
||||
#define URBDRC_DEVICE_SIGNAL_END 0x04
|
||||
#define URBDRC_DEVICE_CHANNEL_CLOSED 0x08
|
||||
#define URBDRC_DEVICE_ALREADY_SEND 0x10
|
||||
#define URBDRC_DEVICE_DETACH_KERNEL 0x20
|
||||
@@ -313,30 +305,4 @@ enum device_descriptor_table
|
||||
#define UDEVMAN_FLAG_ADD_BY_AUTO 0x04
|
||||
#define UDEVMAN_FLAG_DEBUG 0x08
|
||||
|
||||
#define MAX_URB_REQUSET_NUM 0x80
|
||||
|
||||
#define LOG_LEVEL 1
|
||||
|
||||
#define dummy_wait_obj(void) \
|
||||
do \
|
||||
{ \
|
||||
sleep(5); \
|
||||
} while (0)
|
||||
#define dummy_wait_s_obj(_s) \
|
||||
do \
|
||||
{ \
|
||||
sleep(_s); \
|
||||
} while (0)
|
||||
|
||||
#define ISOCH_FIFO 1
|
||||
#define WAIT_COMPLETE_SLEEP 10000 /* for cpu high loading */
|
||||
|
||||
#define urbdrc_get_mstime(_t) \
|
||||
do \
|
||||
{ \
|
||||
struct timeval _tp; \
|
||||
gettimeofday(&_tp, 0); \
|
||||
_t = (_tp.tv_sec * 1000) + (_tp.tv_usec / 1000); \
|
||||
} while (0)
|
||||
|
||||
#endif /* FREERDP_CHANNEL_URBDRC_CLIENT_TYPES_H */
|
||||
30
include/freerdp/channels/urbdrc.h
Normal file
30
include/freerdp/channels/urbdrc.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Server USB redirection Virtual Channel
|
||||
*
|
||||
* Copyright 2019 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2019 Thincast Technologies GmbH
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_CHANNEL_URBDRC_H
|
||||
#define FREERDP_CHANNEL_URBDRC_H
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/dvc.h>
|
||||
#include <freerdp/types.h>
|
||||
|
||||
#define URBDRC_CHANNEL_NAME "urbdrc"
|
||||
|
||||
#endif /* FREERDP_CHANNEL_URBDRC_H */
|
||||
Reference in New Issue
Block a user