diff options
Diffstat (limited to '')
-rw-r--r-- | channels/urbdrc/common/urbdrc_helpers.c | 425 |
1 files changed, 425 insertions, 0 deletions
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 +} |