summaryrefslogtreecommitdiffstats
path: root/channels/urbdrc/common
diff options
context:
space:
mode:
Diffstat (limited to 'channels/urbdrc/common')
-rw-r--r--channels/urbdrc/common/CMakeLists.txt29
-rw-r--r--channels/urbdrc/common/msusb.c395
-rw-r--r--channels/urbdrc/common/msusb.h98
-rw-r--r--channels/urbdrc/common/urbdrc_helpers.c425
-rw-r--r--channels/urbdrc/common/urbdrc_helpers.h45
-rw-r--r--channels/urbdrc/common/urbdrc_types.h306
6 files changed, 1298 insertions, 0 deletions
diff --git a/channels/urbdrc/common/CMakeLists.txt b/channels/urbdrc/common/CMakeLists.txt
new file mode 100644
index 0000000..df9a8a9
--- /dev/null
+++ b/channels/urbdrc/common/CMakeLists.txt
@@ -0,0 +1,29 @@
+# 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 STATIC ${SRCS})
+
+channel_install(urbdrc-common ${FREERDP_ADDIN_PATH} "FreeRDPTargets")
+
diff --git a/channels/urbdrc/common/msusb.c b/channels/urbdrc/common/msusb.c
new file mode 100644
index 0000000..dd76b1d
--- /dev/null
+++ b/channels/urbdrc/common/msusb.c
@@ -0,0 +1,395 @@
+/**
+ * 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(void)
+{
+ return (MSUSB_PIPE_DESCRIPTOR*)calloc(1, sizeof(MSUSB_PIPE_DESCRIPTOR));
+}
+
+static void msusb_mspipes_free(MSUSB_PIPE_DESCRIPTOR** MsPipes, UINT32 NumberOfPipes)
+{
+ if (MsPipes)
+ {
+ for (UINT32 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)
+{
+ MSUSB_PIPE_DESCRIPTOR** MsPipes = NULL;
+
+ if (!Stream_CheckAndLogRequiredCapacityOfSize(TAG, (s), NumberOfPipes, 12ull))
+ return NULL;
+
+ MsPipes = (MSUSB_PIPE_DESCRIPTOR**)calloc(NumberOfPipes, sizeof(MSUSB_PIPE_DESCRIPTOR*));
+
+ if (!MsPipes)
+ return NULL;
+
+ for (UINT32 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 (UINT32 pnum = 0; pnum < NumberOfPipes; pnum++)
+ free(MsPipes[pnum]);
+
+ free(MsPipes);
+ return NULL;
+}
+
+static MSUSB_INTERFACE_DESCRIPTOR* msusb_msinterface_new(void)
+{
+ return (MSUSB_INTERFACE_DESCRIPTOR*)calloc(1, sizeof(MSUSB_INTERFACE_DESCRIPTOR));
+}
+
+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)
+{
+ if (MsInterfaces)
+ {
+ for (UINT32 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 = NULL;
+
+ if (!Stream_CheckAndLogRequiredCapacity(TAG, (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 = NULL;
+ MSUSB_PIPE_DESCRIPTOR* MsPipe = NULL;
+
+ 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 (UINT32 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)
+{
+ MSUSB_INTERFACE_DESCRIPTOR** MsInterfaces = NULL;
+ MsInterfaces =
+ (MSUSB_INTERFACE_DESCRIPTOR**)calloc(NumInterfaces, sizeof(MSUSB_INTERFACE_DESCRIPTOR*));
+
+ if (!MsInterfaces)
+ return NULL;
+
+ for (UINT32 inum = 0; inum < NumInterfaces; inum++)
+ {
+ MsInterfaces[inum] = msusb_msinterface_read(s);
+
+ if (!MsInterfaces[inum])
+ goto fail;
+ }
+
+ return MsInterfaces;
+fail:
+
+ for (UINT32 inum = 0; inum < NumInterfaces; inum++)
+ msusb_msinterface_free(MsInterfaces[inum]);
+
+ free(MsInterfaces);
+ return NULL;
+}
+
+BOOL msusb_msconfig_write(MSUSB_CONFIG_DESCRIPTOR* MsConfg, wStream* out)
+{
+ MSUSB_INTERFACE_DESCRIPTOR** MsInterfaces = NULL;
+ MSUSB_INTERFACE_DESCRIPTOR* MsInterface = NULL;
+
+ 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 (UINT32 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 = NULL;
+ BYTE lenConfiguration = 0;
+ BYTE typeConfiguration = 0;
+
+ if (!Stream_CheckAndLogRequiredCapacityOfSize(TAG, (s), 3ULL + NumInterfaces, 2ULL))
+ 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 = NULL;
+ MSUSB_INTERFACE_DESCRIPTOR* MsInterface = NULL;
+ MSUSB_PIPE_DESCRIPTOR** MsPipes = NULL;
+ MSUSB_PIPE_DESCRIPTOR* MsPipe = NULL;
+
+ 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 (UINT32 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 (UINT32 pnum = 0; pnum < MsInterface->NumberOfPipes; pnum++)
+ {
+ MsPipe = MsPipes[pnum];
+ WLog_INFO(TAG, " Pipe: %" PRIu32, 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, "==================================================");
+}
diff --git a/channels/urbdrc/common/msusb.h b/channels/urbdrc/common/msusb.h
new file mode 100644
index 0000000..6ce843f
--- /dev/null
+++ b/channels/urbdrc/common/msusb.h
@@ -0,0 +1,98 @@
+/**
+ * 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
+{
+ UINT16 MaximumPacketSize;
+ UINT32 MaximumTransferSize;
+ UINT32 PipeFlags;
+ UINT32 PipeHandle;
+ BYTE bEndpointAddress;
+ BYTE bInterval;
+ BYTE PipeType;
+ int InitCompleted;
+} MSUSB_PIPE_DESCRIPTOR;
+
+typedef struct
+{
+ UINT16 Length;
+ UINT16 NumberOfPipesExpected;
+ BYTE InterfaceNumber;
+ BYTE AlternateSetting;
+ UINT32 NumberOfPipes;
+ UINT32 InterfaceHandle;
+ BYTE bInterfaceClass;
+ BYTE bInterfaceSubClass;
+ BYTE bInterfaceProtocol;
+ MSUSB_PIPE_DESCRIPTOR** MsPipes;
+ int InitCompleted;
+} MSUSB_INTERFACE_DESCRIPTOR;
+
+typedef struct
+{
+ UINT16 wTotalLength;
+ BYTE bConfigurationValue;
+ UINT32 ConfigurationHandle;
+ UINT32 NumInterfaces;
+ MSUSB_INTERFACE_DESCRIPTOR** MsInterfaces;
+ int InitCompleted;
+ int MsOutSize;
+} MSUSB_CONFIG_DESCRIPTOR;
+
+#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);
+ FREERDP_API void msusb_msinterface_free(MSUSB_INTERFACE_DESCRIPTOR* MsInterface);
+
+ /* MSUSB_CONFIG exported functions */
+ FREERDP_API void msusb_msconfig_free(MSUSB_CONFIG_DESCRIPTOR* MsConfig);
+
+ WINPR_ATTR_MALLOC(msusb_msconfig_free, 1)
+ FREERDP_API MSUSB_CONFIG_DESCRIPTOR* msusb_msconfig_new(void);
+
+ WINPR_ATTR_MALLOC(msusb_msconfig_free, 1)
+ 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 */
diff --git a/channels/urbdrc/common/urbdrc_helpers.c b/channels/urbdrc/common/urbdrc_helpers.c
new file mode 100644
index 0000000..9d6bb24
--- /dev/null
+++ b/channels/urbdrc/common/urbdrc_helpers.c
@@ -0,0 +1,425 @@
+/**
+ * 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 <freerdp/config.h>
+
+#include "urbdrc_helpers.h"
+#include "urbdrc_types.h"
+#include <winpr/print.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]";
+
+ case TRANSFER_OUT_REQUEST:
+ return "TRANSFER_OUT_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 interfaceNr, UINT32 functionId)
+{
+ return "QUERY_DEVICE_TEXT_RSP [stub |client]";
+}
+
+const char* call_to_string(BOOL client, UINT32 interfaceNr, UINT32 functionId)
+{
+ const UINT32 mask = (interfaceNr & STREAM_ID_MASK) >> 30;
+ const UINT32 interfaceId = interfaceNr & 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 = 0;
+ UINT32 MessageId = 0;
+ UINT32 FunctionId = 0;
+ size_t length = 0;
+ size_t pos = 0;
+
+ pos = Stream_GetPosition(s);
+ if (write)
+ {
+ length = pos;
+ 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=%" PRIuz,
+ type, call_to_string(client, InterfaceId, FunctionId), FunctionId, InterfaceId,
+ MessageId, FunctionId, length);
+#if defined(WITH_DEBUG_URBDRC)
+ if (write)
+ WLog_Print(log, WLOG_TRACE, "-------------------------- URBDRC sent: ---");
+ else
+ WLog_Print(log, WLOG_TRACE, "-------------------------- URBDRC received:");
+ winpr_HexLogDump(log, WLOG_TRACE, Stream_Buffer(s), length);
+ WLog_Print(log, WLOG_TRACE, "-------------------------- URBDRC end -----");
+#endif
+}
diff --git a/channels/urbdrc/common/urbdrc_helpers.h b/channels/urbdrc/common/urbdrc_helpers.h
new file mode 100644
index 0000000..d766ac5
--- /dev/null
+++ b/channels/urbdrc/common/urbdrc_helpers.h
@@ -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 interfaceNr, UINT32 functionId);
+
+ void urbdrc_dump_message(wLog* log, BOOL client, BOOL write, wStream* s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREERDP_CHANNEL_URBDRC_HELPERS_H */
diff --git a/channels/urbdrc/common/urbdrc_types.h b/channels/urbdrc/common/urbdrc_types.h
new file mode 100644
index 0000000..a3deaf1
--- /dev/null
+++ b/channels/urbdrc/common/urbdrc_types.h
@@ -0,0 +1,306 @@
+/**
+ * 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_TYPES_H
+#define FREERDP_CHANNEL_URBDRC_CLIENT_TYPES_H
+
+#include <freerdp/config.h>
+
+#include <freerdp/dvc.h>
+#include <freerdp/types.h>
+
+#include <msusb.h>
+
+#include <winpr/stream.h>
+
+#define RIM_CAPABILITY_VERSION_01 0x00000001
+
+#define CAPABILITIES_NEGOTIATOR 0x00000000
+#define CLIENT_DEVICE_SINK 0x00000001
+#define SERVER_CHANNEL_NOTIFICATION 0x00000002
+#define CLIENT_CHANNEL_NOTIFICATION 0x00000003
+#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
+#define ADD_DEVICE 0x00000101
+
+#define INIT_CHANNEL_IN 1
+#define INIT_CHANNEL_OUT 0
+
+/* InterfaceClass */
+#define CLASS_RESERVE 0x00
+#define CLASS_AUDIO 0x01
+#define CLASS_COMMUNICATION_IF 0x02
+#define CLASS_HID 0x03
+#define CLASS_PHYSICAL 0x05
+#define CLASS_IMAGE 0x06
+#define CLASS_PRINTER 0x07
+#define CLASS_MASS_STORAGE 0x08
+#define CLASS_HUB 0x09
+#define CLASS_COMMUNICATION_DATA_IF 0x0a
+#define CLASS_SMART_CARD 0x0b
+#define CLASS_CONTENT_SECURITY 0x0d
+#define CLASS_VIDEO 0x0e
+#define CLASS_PERSONAL_HEALTHCARE 0x0f
+#define CLASS_DIAGNOSTIC 0xdc
+#define CLASS_WIRELESS_CONTROLLER 0xe0
+#define CLASS_ELSE_DEVICE 0xef
+#define CLASS_DEPENDENCE 0xfe
+#define CLASS_VENDOR_DEPENDENCE 0xff
+
+/* usb version */
+#define USB_v1_0 0x100
+#define USB_v1_1 0x110
+#define USB_v2_0 0x200
+#define USB_v3_0 0x300
+
+#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
+
+#define IOCONTROL_COMPLETION 0x00000100
+#define URB_COMPLETION 0x00000101
+#define URB_COMPLETION_NO_DATA 0x00000102
+
+/* The USB device is to be stopped from being redirected because the
+ * device is blocked by the server's policy. */
+#define UsbRetractReason_BlockedByPolicy 0x00000001
+
+enum device_text_type
+{
+ DeviceTextDescription = 0,
+ DeviceTextLocationInformation = 1,
+};
+
+enum device_descriptor_table
+{
+ B_LENGTH = 0,
+ B_DESCRIPTOR_TYPE = 1,
+ BCD_USB = 2,
+ B_DEVICE_CLASS = 4,
+ B_DEVICE_SUBCLASS = 5,
+ B_DEVICE_PROTOCOL = 6,
+ B_MAX_PACKET_SIZE0 = 7,
+ ID_VENDOR = 8,
+ ID_PRODUCT = 10,
+ BCD_DEVICE = 12,
+ I_MANUFACTURER = 14,
+ I_PRODUCT = 15,
+ I_SERIAL_NUMBER = 16,
+ B_NUM_CONFIGURATIONS = 17
+};
+
+#define PIPE_CANCEL 0
+#define PIPE_RESET 1
+
+#define IOCTL_INTERNAL_USB_SUBMIT_URB 0x00220003
+#define IOCTL_INTERNAL_USB_RESET_PORT 0x00220007
+#define IOCTL_INTERNAL_USB_GET_PORT_STATUS 0x00220013
+#define IOCTL_INTERNAL_USB_CYCLE_PORT 0x0022001F
+#define IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION 0x00220027
+
+#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 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
+#define USBD_STATUS_STALL_PID 0xC0000004
+#define USBD_STATUS_DEV_NOT_RESPONDING 0xC0000005
+#define USBD_STATUS_PID_CHECK_FAILURE 0xC0000006
+#define USBD_STATUS_UNEXPECTED_PID 0xC0000007
+#define USBD_STATUS_DATA_OVERRUN 0xC0000008
+#define USBD_STATUS_DATA_UNDERRUN 0xC0000009
+#define USBD_STATUS_RESERVED1 0xC000000A
+#define USBD_STATUS_RESERVED2 0xC000000B
+#define USBD_STATUS_BUFFER_OVERRUN 0xC000000C
+#define USBD_STATUS_BUFFER_UNDERRUN 0xC000000D
+
+/* unknown */
+#define USBD_STATUS_NO_DATA 0xC000000E
+
+#define USBD_STATUS_NOT_ACCESSED 0xC000000F
+#define USBD_STATUS_FIFO 0xC0000010
+#define USBD_STATUS_XACT_ERROR 0xC0000011
+#define USBD_STATUS_BABBLE_DETECTED 0xC0000012
+#define USBD_STATUS_DATA_BUFFER_ERROR 0xC0000013
+
+#define USBD_STATUS_NOT_SUPPORTED 0xC0000E00
+#define USBD_STATUS_BUFFER_TOO_SMALL 0xC0003000
+#define USBD_STATUS_TIMEOUT 0xC0006000
+#define USBD_STATUS_DEVICE_GONE 0xC0007000
+
+#define USBD_STATUS_NO_MEMORY 0x80000100
+#define USBD_STATUS_INVALID_URB_FUNCTION 0x80000200
+#define USBD_STATUS_INVALID_PARAMETER 0x80000300
+#define USBD_STATUS_REQUEST_FAILED 0x80000500
+#define USBD_STATUS_INVALID_PIPE_HANDLE 0x80000600
+#define USBD_STATUS_ERROR_SHORT_TRANSFER 0x80000900
+
+// Values for URB TransferFlags Field
+//
+
+/*
+ Set if data moves device->host
+*/
+#define USBD_TRANSFER_DIRECTION 0x00000001
+/*
+ This bit if not set indicates that a short packet, and hence,
+ a short transfer is an error condition
+*/
+#define USBD_SHORT_TRANSFER_OK 0x00000002
+/*
+ Subit the iso transfer on the next frame
+*/
+#define USBD_START_ISO_TRANSFER_ASAP 0x00000004
+#define USBD_DEFAULT_PIPE_TRANSFER 0x00000008
+
+#define USBD_TRANSFER_DIRECTION_FLAG(flags) ((flags)&USBD_TRANSFER_DIRECTION)
+
+#define USBD_TRANSFER_DIRECTION_OUT 0
+#define USBD_TRANSFER_DIRECTION_IN 1
+
+#define VALID_TRANSFER_FLAGS_MASK USBD_SHORT_TRANSFER_OK | \
+ USBD_TRANSFER_DIRECTION | \
+ USBD_START_ISO_TRANSFER_ASAP | \
+ USBD_DEFAULT_PIPE_TRANSFER)
+
+#define ENDPOINT_HALT 0x00
+#define DEVICE_REMOTE_WAKEUP 0x01
+
+/* transfer type */
+#define CONTROL_TRANSFER 0x00
+#define ISOCHRONOUS_TRANSFER 0x01
+#define BULK_TRANSFER 0x02
+#define INTERRUPT_TRANSFER 0x03
+
+#define ClearHubFeature (0x2000 | LIBUSB_REQUEST_CLEAR_FEATURE)
+#define ClearPortFeature (0x2300 | LIBUSB_REQUEST_CLEAR_FEATURE)
+#define GetHubDescriptor (0xa000 | LIBUSB_REQUEST_GET_DESCRIPTOR)
+#define GetHubStatus (0xa000 | LIBUSB_REQUEST_GET_STATUS)
+#define GetPortStatus (0xa300 | LIBUSB_REQUEST_GET_STATUS)
+#define SetHubFeature (0x2000 | LIBUSB_REQUEST_SET_FEATURE)
+#define SetPortFeature (0x2300 | LIBUSB_REQUEST_SET_FEATURE)
+
+#define USBD_PF_CHANGE_MAX_PACKET 0x00000001
+#define USBD_PF_SHORT_PACKET_OPT 0x00000002
+#define USBD_PF_ENABLE_RT_THREAD_ACCESS 0x00000004
+#define USBD_PF_MAP_ADD_TRANSFERS 0x00000008
+
+/* feature request */
+#define URB_SET_FEATURE 0x00
+#define URB_CLEAR_FEATURE 0x01
+
+#define USBD_PF_CHANGE_MAX_PACKET 0x00000001
+#define USBD_PF_SHORT_PACKET_OPT 0x00000002
+#define USBD_PF_ENABLE_RT_THREAD_ACCESS 0x00000004
+#define USBD_PF_MAP_ADD_TRANSFERS 0x00000008
+
+#define URB_CONTROL_TRANSFER_EXTERNAL 0x1
+#define URB_CONTROL_TRANSFER_NONEXTERNAL 0x0
+
+#define USBFS_URB_SHORT_NOT_OK 0x01
+#define USBFS_URB_ISO_ASAP 0x02
+#define USBFS_URB_BULK_CONTINUATION 0x04
+#define USBFS_URB_QUEUE_BULK 0x10
+
+#define URBDRC_DEVICE_INITIALIZED 0x01
+#define URBDRC_DEVICE_NOT_FOUND 0x02
+#define URBDRC_DEVICE_CHANNEL_CLOSED 0x08
+#define URBDRC_DEVICE_ALREADY_SEND 0x10
+#define URBDRC_DEVICE_DETACH_KERNEL 0x20
+
+#define UDEVMAN_FLAG_ADD_BY_VID_PID 0x01
+#define UDEVMAN_FLAG_ADD_BY_ADDR 0x02
+#define UDEVMAN_FLAG_ADD_BY_AUTO 0x04
+#define UDEVMAN_FLAG_DEBUG 0x08
+
+#endif /* FREERDP_CHANNEL_URBDRC_CLIENT_TYPES_H */