mirror of https://github.com/FreeRDP/FreeRDP
Merge pull request #816 from awakecoding/master
Refactoring, Channels, CMake, Settings, TSG, Command-Line Interface, .rdp File Support,
This commit is contained in:
commit
f0c5a0fdb9
209
CMakeLists.txt
209
CMakeLists.txt
|
@ -38,10 +38,11 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/)
|
|||
# Check for cmake compatibility (enable/disable features)
|
||||
include(CheckCmakeCompat)
|
||||
|
||||
include(FindFeature)
|
||||
include(AutoVersioning)
|
||||
include(ConfigOptions)
|
||||
include(ComplexLibrary)
|
||||
include(FindOptionalPackage)
|
||||
include(FeatureSummary)
|
||||
include(CheckCCompilerFlag)
|
||||
include(GNUInstallDirsWrapper)
|
||||
|
||||
|
@ -77,7 +78,7 @@ if(NOT DEFINED BUILD_SHARED_LIBS)
|
|||
endif()
|
||||
|
||||
if(NOT DEFINED EXPORT_ALL_SYMBOLS)
|
||||
set(EXPORT_ALL_SYMBOLS FALSE)
|
||||
set(EXPORT_ALL_SYMBOLS TRUE)
|
||||
endif()
|
||||
|
||||
# Configure MSVC Runtime
|
||||
|
@ -136,14 +137,13 @@ if(MSVC)
|
|||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MT")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /O2")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Ob2")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W2")
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_AMD64_")
|
||||
else()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_X86_")
|
||||
endif()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_UNICODE")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWINPR_EXPORTS")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DFREERDP_EXPORTS")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_WIN32_WINNT=0x0501")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWIN32_LEAN_AND_MEAN")
|
||||
|
@ -151,6 +151,9 @@ if(MSVC)
|
|||
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR})
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWINPR_EXPORTS")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DFREERDP_EXPORTS")
|
||||
|
||||
# Include files
|
||||
check_include_files(fcntl.h HAVE_FCNTL_H)
|
||||
check_include_files(unistd.h HAVE_UNISTD_H)
|
||||
|
@ -168,52 +171,118 @@ if(APPLE)
|
|||
include_directories(/opt/local/include)
|
||||
link_directories(/opt/local/lib)
|
||||
endif()
|
||||
|
||||
if(WITH_CLANG)
|
||||
set(CMAKE_C_COMPILER "clang")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=10.4")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl-framework,CoreFoundation")
|
||||
endif()
|
||||
|
||||
# Android
|
||||
if(ANDROID)
|
||||
set(WITH_X11 OFF)
|
||||
set(WITH_CUPS OFF)
|
||||
set(WITH_ALSA OFF)
|
||||
set(WITH_PULSE OFF)
|
||||
set(WITH_FFMPEG OFF)
|
||||
set(WITH_GSTREAMER OFF)
|
||||
set(WITH_PCSC OFF)
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
if(UNIX OR CYGWIN)
|
||||
set(X11_FEATURE_TYPE "RECOMMENDED")
|
||||
else()
|
||||
set(X11_FEATURE_TYPE "DISABLED")
|
||||
endif()
|
||||
|
||||
if(NOT WIN32)
|
||||
find_required_package(ZLIB)
|
||||
find_optional_package(PCSC)
|
||||
find_optional_package(PulseAudio)
|
||||
set(X11_FEATURE_PURPOSE "X11")
|
||||
set(X11_FEATURE_DESCRIPTION "X11 client and server")
|
||||
|
||||
if(NOT ANDROID)
|
||||
find_suggested_package(Cups)
|
||||
endif()
|
||||
set(DIRECTFB_FEATURE_TYPE "OPTIONAL")
|
||||
set(DIRECTFB_FEATURE_PURPOSE "DirectFB")
|
||||
set(DIRECTFB_FEATURE_DESCRIPTION "DirectFB client")
|
||||
|
||||
if(NOT APPLE)
|
||||
find_suggested_package(XRandR)
|
||||
find_suggested_package(Gstreamer)
|
||||
if(NOT ANDROID)
|
||||
find_suggested_package(ALSA)
|
||||
endif()
|
||||
endif()
|
||||
set(ZLIB_FEATURE_TYPE "REQUIRED")
|
||||
set(ZLIB_FEATURE_PURPOSE "compression")
|
||||
set(ZLIB_FEATURE_DESCRIPTION "data compression")
|
||||
|
||||
if((NOT ANDROID) AND (NOT APPLE))
|
||||
find_suggested_package(FFmpeg)
|
||||
endif()
|
||||
endif()
|
||||
set(OPENSSL_FEATURE_TYPE "REQUIRED")
|
||||
set(OPENSSL_FEATURE_PURPOSE "cryptography")
|
||||
set(OPENSSL_FEATURE_DESCRIPTION "encryption, certificate validation, hashing functions")
|
||||
|
||||
set(ALSA_FEATURE_TYPE "RECOMMENDED")
|
||||
set(ALSA_FEATURE_PURPOSE "sound")
|
||||
set(ALSA_FEATURE_DESCRIPTION "audio input, audio output and multimedia redirection")
|
||||
|
||||
set(PULSE_FEATURE_TYPE "OPTIONAL")
|
||||
set(PULSE_FEATURE_PURPOSE "sound")
|
||||
set(PULSE_FEATURE_DESCRIPTION "audio input, audio output and multimedia redirection")
|
||||
|
||||
set(CUPS_FEATURE_TYPE "OPTIONAL")
|
||||
set(CUPS_FEATURE_PURPOSE "printing")
|
||||
set(CUPS_FEATURE_DESCRIPTION "printer device redirection")
|
||||
|
||||
set(PCSC_FEATURE_TYPE "OPTIONAL")
|
||||
set(PCSC_FEATURE_PURPOSE "smart card")
|
||||
set(PCSC_FEATURE_DESCRIPTION "smart card device redirection")
|
||||
|
||||
set(FFMPEG_FEATURE_TYPE "RECOMMENDED")
|
||||
set(FFMPEG_FEATURE_PURPOSE "multimedia")
|
||||
set(FFMPEG_FEATURE_DESCRIPTION "multimedia redirection, audio and video playback")
|
||||
|
||||
set(GSTREAMER_FEATURE_TYPE "RECOMMENDED")
|
||||
set(GSTREAMER_FEATURE_PURPOSE "multimedia")
|
||||
set(GSTREAMER_FEATURE_DESCRIPTION "multimedia redirection, audio and video playback")
|
||||
|
||||
if(WIN32)
|
||||
set(CMAKE_INSTALL_BINDIR ${CMAKE_INSTALL_PREFIX})
|
||||
set(CMAKE_INSTALL_LIBDIR ${CMAKE_INSTALL_PREFIX})
|
||||
set(CMAKE_INSTALL_FULL_LIBDIR ${CMAKE_INSTALL_PREFIX})
|
||||
set(X11_FEATURE_TYPE "DISABLED")
|
||||
set(ZLIB_FEATURE_TYPE "DISABLED")
|
||||
set(DIRECTFB_FEATURE_TYPE "DISABLED")
|
||||
set(ALSA_FEATURE_TYPE "DISABLED")
|
||||
set(PULSE_FEATURE_TYPE "DISABLED")
|
||||
set(CUPS_FEATURE_TYPE "DISABLED")
|
||||
set(PCSC_FEATURE_TYPE "DISABLED")
|
||||
set(FFMPEG_FEATURE_TYPE "DISABLED")
|
||||
set(GSTREAMER_FEATURE_TYPE "DISABLED")
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
set(DIRECTFB_FEATURE_TYPE "DISABLED")
|
||||
set(FFMPEG_FEATURE_TYPE "OPTIONAL")
|
||||
endif()
|
||||
|
||||
if(ANDROID)
|
||||
set(X11_FEATURE_TYPE "DISABLED")
|
||||
set(DIRECTFB_FEATURE_TYPE "DISABLED")
|
||||
set(ALSA_FEATURE_TYPE "DISABLED")
|
||||
set(PULSE_FEATURE_TYPE "DISABLED")
|
||||
set(CUPS_FEATURE_TYPE "DISABLED")
|
||||
set(PCSC_FEATURE_TYPE "DISABLED")
|
||||
set(FFMPEG_FEATURE_TYPE "DISABLED")
|
||||
set(GSTREAMER_FEATURE_TYPE "DISABLED")
|
||||
endif()
|
||||
|
||||
if(IOS)
|
||||
set(X11_FEATURE_TYPE "DISABLED")
|
||||
set(DIRECTFB_FEATURE_TYPE "DISABLED")
|
||||
set(ALSA_FEATURE_TYPE "DISABLED")
|
||||
set(PULSE_FEATURE_TYPE "DISABLED")
|
||||
set(CUPS_FEATURE_TYPE "DISABLED")
|
||||
set(PCSC_FEATURE_TYPE "DISABLED")
|
||||
set(FFMPEG_FEATURE_TYPE "DISABLED")
|
||||
set(GSTREAMER_FEATURE_TYPE "DISABLED")
|
||||
endif()
|
||||
|
||||
find_feature(X11 ${X11_FEATURE_TYPE} ${X11_FEATURE_PURPOSE} ${X11_FEATURE_DESCRIPTION})
|
||||
find_feature(DirectFB ${DIRECTFB_FEATURE_TYPE} ${DIRECTFB_FEATURE_PURPOSE} ${DIRECTFB_FEATURE_DESCRIPTION})
|
||||
|
||||
find_feature(ZLIB ${ZLIB_FEATURE_TYPE} ${ZLIB_FEATURE_PURPOSE} ${ZLIB_FEATURE_DESCRIPTION})
|
||||
find_feature(OpenSSL ${OPENSSL_FEATURE_TYPE} ${OPENSSL_FEATURE_PURPOSE} ${OPENSSL_FEATURE_DESCRIPTION})
|
||||
|
||||
find_feature(ALSA ${ALSA_FEATURE_TYPE} ${ALSA_FEATURE_PURPOSE} ${ALSA_FEATURE_DESCRIPTION})
|
||||
find_feature(Pulse ${PULSE_FEATURE_TYPE} ${PULSE_FEATURE_PURPOSE} ${PULSE_FEATURE_DESCRIPTION})
|
||||
|
||||
find_feature(Cups ${CUPS_FEATURE_TYPE} ${CUPS_FEATURE_PURPOSE} ${CUPS_FEATURE_DESCRIPTION})
|
||||
find_feature(PCSC ${PCSC_FEATURE_TYPE} ${PCSC_FEATURE_PURPOSE} ${PCSC_FEATURE_DESCRIPTION})
|
||||
|
||||
find_feature(FFmpeg ${FFMPEG_FEATURE_TYPE} ${FFMPEG_FEATURE_PURPOSE} ${FFMPEG_FEATURE_DESCRIPTION})
|
||||
find_feature(Gstreamer ${GSTREAMER_FEATURE_TYPE} ${GSTREAMER_FEATURE_PURPOSE} ${GSTREAMER_FEATURE_DESCRIPTION})
|
||||
|
||||
# Installation Paths
|
||||
if(WIN32)
|
||||
set(CMAKE_INSTALL_BINDIR ".")
|
||||
set(CMAKE_INSTALL_LIBDIR ".")
|
||||
endif()
|
||||
|
||||
# Path to put FreeRDP data
|
||||
|
@ -222,14 +291,10 @@ set(FREERDP_KEYMAP_PATH "${FREERDP_DATA_PATH}/keymaps")
|
|||
|
||||
# Path to put plugins
|
||||
|
||||
if(WIN32)
|
||||
set(FREERDP_PLUGIN_PATH "${CMAKE_INSTALL_LIBDIR}")
|
||||
else()
|
||||
set(FREERDP_PLUGIN_PATH "${CMAKE_INSTALL_LIBDIR}/freerdp")
|
||||
endif()
|
||||
set(FREERDP_LIBRARY_PATH "${CMAKE_INSTALL_LIBDIR}")
|
||||
|
||||
set(FREERDP_CLIENT_PLUGIN_PATH "${FREERDP_PLUGIN_PATH}/client")
|
||||
set(FREERDP_SERVER_PLUGIN_PATH "${FREERDP_PLUGIN_PATH}/server")
|
||||
set(FREERDP_PLUGIN_PATH "${CMAKE_INSTALL_LIBDIR}/freerdp")
|
||||
set(FREERDP_ADDIN_PATH "${FREERDP_PLUGIN_PATH}")
|
||||
|
||||
# Path to put extensions
|
||||
set(FREERDP_EXTENSION_PATH "${CMAKE_INSTALL_FULL_LIBDIR}/freerdp/extensions")
|
||||
|
@ -246,14 +311,19 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_SOURCE_DI
|
|||
set(CMAKE_SKIP_BUILD_RPATH FALSE)
|
||||
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
|
||||
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
set(CMAKE_INSTALL_RPATH "\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}")
|
||||
set(CMAKE_INSTALL_RPATH "\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}:\$ORIGIN/..")
|
||||
|
||||
# Unit Tests
|
||||
|
||||
INCLUDE(CTest)
|
||||
include(CTest)
|
||||
|
||||
if(BUILD_TESTING)
|
||||
find_package(Cmockery)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DFREERDP_TEST_EXPORTS")
|
||||
|
||||
enable_testing()
|
||||
|
||||
if(MSVC)
|
||||
set(TESTING_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
|
||||
else()
|
||||
|
@ -273,9 +343,6 @@ if(NOT MSVC)
|
|||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/freerdp.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
endif()
|
||||
|
||||
# Intel Performance Primitives
|
||||
#find_optional_package(IPP)
|
||||
|
||||
if(WITH_CUNIT)
|
||||
message(FATAL_ERROR "cunit (WITH_CUNIT) is deprecated please use BUILD_TESTING to build ctest tests.
|
||||
The cunit directory contains the old tests and is kept until all tests are converted.")
|
||||
|
@ -311,14 +378,13 @@ endif()
|
|||
|
||||
set(CPACK_SOURCE_IGNORE_FILES "/\\\\.git/;/\\\\.gitignore;/CMakeCache.txt")
|
||||
|
||||
set(CPACK_PACKAGE_EXECUTABLES "xfreerdp")
|
||||
|
||||
if(WITH_SERVER)
|
||||
set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} "xfreerdp-server")
|
||||
if(NOT WIN32)
|
||||
set(CPACK_PACKAGE_EXECUTABLES "xfreerdp")
|
||||
if(WITH_SERVER)
|
||||
set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} "xfreerdp-server")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "FreeRDP: A Remote Desktop Protocol Implementation")
|
||||
|
||||
set(CPACK_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
|
||||
set(CPACK_TOPLEVEL_TAG "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
|
||||
|
||||
|
@ -332,9 +398,7 @@ set(CPACK_PACKAGE_VERSION ${FREERDP_VERSION_FULL})
|
|||
set(CPACK_PACKAGE_VERSION_MAJOR ${FREERDP_VERSION_MAJOR})
|
||||
set(CPACK_PACKAGE_VERSION_MINOR ${FREERDP_VERSION_MINOR})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${FREERDP_VERSION_REVISION})
|
||||
|
||||
set(CPACK_SET_DESTDIR "on")
|
||||
set(CPACK_PACKAGING_INSTALL_PREFIX "/tmp")
|
||||
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "FreeRDP: A Remote Desktop Protocol Implementation")
|
||||
|
||||
set(CPACK_PACKAGE_CONTACT "Marc-Andre Moreau")
|
||||
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "marcandre.moreau@gmail.com")
|
||||
|
@ -351,15 +415,30 @@ set(CPACK_NSIS_MUI_UNICON "${CMAKE_SOURCE_DIR}/resource\\\\FreeRDP_Icon_96px.ico
|
|||
|
||||
if(MSVC)
|
||||
if(MSVC_RUNTIME STREQUAL "dynamic")
|
||||
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE)
|
||||
include(InstallRequiredSystemLibraries)
|
||||
install(PROGRAMS ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS}
|
||||
DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
COMPONENT libraries)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CPACK_COMPONENTS_ALL client server libraries headers)
|
||||
|
||||
set(CPACK_COMPONENT_CLIENT_DISPLAY_NAME "Client")
|
||||
set(CPACK_COMPONENT_CLIENT_GROUP "Applications")
|
||||
|
||||
set(CPACK_COMPONENT_SERVER_DISPLAY_NAME "Server")
|
||||
set(CPACK_COMPONENT_SERVER_GROUP "Applications")
|
||||
|
||||
set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries")
|
||||
set(CPACK_COMPONENT_LIBRARIES_GROUP "Runtime")
|
||||
|
||||
set(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "Headers")
|
||||
set(CPACK_COMPONENT_HEADERS_GROUP "Development")
|
||||
|
||||
set(CPACK_COMPONENT_GROUP_RUNTIME_DESCRIPTION "Runtime")
|
||||
set(CPACK_COMPONENT_GROUP_APPLICATIONS_DESCRIPTION "Applications")
|
||||
set(CPACK_COMPONENT_GROUP_DEVELOPMENT_DESCRIPTION "Development")
|
||||
|
||||
include(CPack)
|
||||
|
||||
cpack_add_component(headers DISPLAY_NAME "Headers")
|
||||
cpack_add_component(libraries DISPLAY_NAME "Libraries")
|
||||
cpack_add_component(clients DISPLAY_NAME "Clients")
|
||||
|
||||
set(CPACK_COMPONENTS_ALL clients libraries headers)
|
||||
|
||||
|
|
|
@ -22,14 +22,35 @@ include(CMakeDependentOption)
|
|||
|
||||
macro(define_channel_options)
|
||||
set(PREFIX "CHANNEL")
|
||||
|
||||
|
||||
cmake_parse_arguments(${PREFIX}
|
||||
""
|
||||
"NAME;TYPE;DESCRIPTION;SPECIFICATIONS;DEFAULT"
|
||||
""
|
||||
${ARGN})
|
||||
|
||||
|
||||
string(TOUPPER "CHANNEL_${CHANNEL_NAME}" CHANNEL_OPTION)
|
||||
string(TOUPPER "CHANNEL_${CHANNEL_NAME}_CLIENT" CHANNEL_CLIENT_OPTION)
|
||||
string(TOUPPER "CHANNEL_${CHANNEL_NAME}_SERVER" CHANNEL_SERVER_OPTION)
|
||||
|
||||
if(${${CHANNEL_CLIENT_OPTION}})
|
||||
set(OPTION_CLIENT_DEFAULT ${${CHANNEL_CLIENT_OPTION}})
|
||||
endif()
|
||||
|
||||
if(${${CHANNEL_SERVER_OPTION}})
|
||||
set(OPTION_SERVER_DEFAULT ${${CHANNEL_SERVER_OPTION}})
|
||||
endif()
|
||||
|
||||
if(${${CHANNEL_OPTION}})
|
||||
set(OPTION_DEFAULT ${${CHANNEL_OPTION}})
|
||||
endif()
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT "ON")
|
||||
endif()
|
||||
|
||||
set(CHANNEL_DEFAULT ${OPTION_DEFAULT})
|
||||
|
||||
set(CHANNEL_OPTION_DOC "Build ${CHANNEL_NAME} ${CHANNEL_TYPE} channel")
|
||||
option(${CHANNEL_OPTION} "${CHANNEL_OPTION_DOC}" ${CHANNEL_DEFAULT})
|
||||
|
||||
|
@ -73,10 +94,11 @@ macro(define_channel_client_subsystem _channel_name _subsystem _type)
|
|||
set(CHANNEL_NAME ${_channel_name})
|
||||
set(CHANNEL_SUBSYSTEM ${_subsystem})
|
||||
string(LENGTH "${_type}" _type_length)
|
||||
string(TOUPPER "CHANNEL_${CHANNEL_NAME}_CLIENT" CHANNEL_PREFIX)
|
||||
if(_type_length GREATER 0)
|
||||
set(SUBSYSTEM_TYPE ${_type})
|
||||
set(MODULE_NAME "${CHANNEL_NAME}-client-${CHANNEL_SUBSYSTEM}-${SUBSYSTEM_TYPE}")
|
||||
string(TOUPPER "CHANNEL_${CHANNEL_NAME}_CLIENT_${CHANNEL_SUBSYSTEM}-${SUBSYSTEM_TYPE}" MODULE_PREFIX)
|
||||
string(TOUPPER "CHANNEL_${CHANNEL_NAME}_CLIENT_${CHANNEL_SUBSYSTEM}_${SUBSYSTEM_TYPE}" MODULE_PREFIX)
|
||||
else()
|
||||
set(MODULE_NAME "${CHANNEL_NAME}-client-${CHANNEL_SUBSYSTEM}")
|
||||
string(TOUPPER "CHANNEL_${CHANNEL_NAME}_CLIENT_${CHANNEL_SUBSYSTEM}" MODULE_PREFIX)
|
||||
|
@ -112,13 +134,31 @@ macro(add_channel_server _channel_prefix _channel_name)
|
|||
endif()
|
||||
endmacro(add_channel_server)
|
||||
|
||||
macro(add_channel_client_library _module_prefix _module_name _channel_name _plugin _entry)
|
||||
macro(add_channel_client_subsystem _channel_prefix _channel_name _subsystem _type)
|
||||
add_subdirectory(${_subsystem})
|
||||
set(_channel_module_name "${_channel_name}-client")
|
||||
string(LENGTH "${_type}" _type_length)
|
||||
if(_type_length GREATER 0)
|
||||
string(TOUPPER "CHANNEL_${_channel_name}_CLIENT_${_subsystem}_${_type}" _subsystem_prefix)
|
||||
else()
|
||||
string(TOUPPER "CHANNEL_${_channel_name}_CLIENT_${_subsystem}" _subsystem_prefix)
|
||||
endif()
|
||||
if(${${_subsystem_prefix}_STATIC})
|
||||
get_target_property(CHANNEL_SUBSYSTEMS ${_channel_module_name} SUBSYSTEMS)
|
||||
if(_type_length GREATER 0)
|
||||
set(SUBSYSTEMS ${SUBSYSTEMS} "${_subsystem}-${_type}")
|
||||
else()
|
||||
set(SUBSYSTEMS ${SUBSYSTEMS} ${_subsystem})
|
||||
endif()
|
||||
set_target_properties(${_channel_module_name} PROPERTIES SUBSYSTEMS "${SUBSYSTEMS}")
|
||||
endif()
|
||||
endmacro(add_channel_client_subsystem)
|
||||
|
||||
if(${_plugin} AND MSVC AND (NOT STATIC_CHANNELS))
|
||||
macro(add_channel_client_library _module_prefix _module_name _channel_name _dynamic _entry)
|
||||
if(${_dynamic} AND MSVC AND (NOT STATIC_CHANNELS))
|
||||
set(${_module_prefix}_SRCS ${${_module_prefix}_SRCS} module.def)
|
||||
endif()
|
||||
|
||||
if(${_plugin} AND (NOT STATIC_CHANNELS))
|
||||
if(${_dynamic} AND (NOT STATIC_CHANNELS))
|
||||
add_library(${_module_name} ${${_module_prefix}_SRCS})
|
||||
else()
|
||||
set(${_module_prefix}_STATIC ON PARENT_SCOPE)
|
||||
|
@ -127,16 +167,27 @@ macro(add_channel_client_library _module_prefix _module_name _channel_name _plug
|
|||
set(${_module_prefix}_ENTRY ${_entry} PARENT_SCOPE)
|
||||
add_library(${_module_name} STATIC ${${_module_prefix}_SRCS})
|
||||
endif()
|
||||
|
||||
endmacro(add_channel_client_library)
|
||||
|
||||
macro(add_channel_server_library _module_prefix _module_name _channel_name _plugin _entry)
|
||||
|
||||
if(${_plugin} AND MSVC AND (NOT STATIC_CHANNELS))
|
||||
macro(add_channel_client_subsystem_library _module_prefix _module_name _channel_name _type _dynamic _entry)
|
||||
if(${_dynamic} AND MSVC AND (NOT STATIC_CHANNELS))
|
||||
set(${_module_prefix}_SRCS ${${_module_prefix}_SRCS} module.def)
|
||||
endif()
|
||||
|
||||
if(${_plugin} AND (NOT STATIC_CHANNELS))
|
||||
if(${_dynamic} AND (NOT STATIC_CHANNELS))
|
||||
add_library(${_module_name} ${${_module_prefix}_SRCS})
|
||||
else()
|
||||
set(${_module_prefix}_STATIC ON PARENT_SCOPE)
|
||||
set(${_module_prefix}_NAME ${_module_name} PARENT_SCOPE)
|
||||
set(${_module_prefix}_TYPE ${_type} PARENT_SCOPE)
|
||||
add_library(${_module_name} STATIC ${${_module_prefix}_SRCS})
|
||||
endif()
|
||||
endmacro(add_channel_client_subsystem_library)
|
||||
|
||||
macro(add_channel_server_library _module_prefix _module_name _channel_name _dynamic _entry)
|
||||
if(${_dynamic} AND MSVC AND (NOT STATIC_CHANNELS))
|
||||
set(${_module_prefix}_SRCS ${${_module_prefix}_SRCS} module.def)
|
||||
endif()
|
||||
if(${_dynamic} AND (NOT STATIC_CHANNELS))
|
||||
add_library(${_module_name} ${${_module_prefix}_SRCS})
|
||||
else()
|
||||
set(${_module_prefix}_STATIC ON PARENT_SCOPE)
|
||||
|
@ -145,7 +196,6 @@ macro(add_channel_server_library _module_prefix _module_name _channel_name _plug
|
|||
set(${_module_prefix}_ENTRY ${_entry} PARENT_SCOPE)
|
||||
add_library(${_module_name} STATIC ${${_module_prefix}_SRCS})
|
||||
endif()
|
||||
|
||||
endmacro(add_channel_server_library)
|
||||
|
||||
set(FILENAME "ChannelOptions.cmake")
|
||||
|
|
|
@ -8,10 +8,6 @@ if(ANDROID)
|
|||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
endif()
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "audin" TYPE "dynamic"
|
||||
DESCRIPTION "Audio Input Redirection Virtual Channel Extension"
|
||||
SPECIFICATIONS "[MS-RDPEAI]"
|
||||
|
@ -19,3 +15,4 @@ define_channel_options(NAME "audin" TYPE "dynamic"
|
|||
|
||||
define_channel_client_options(${OPTION_CLIENT_DEFAULT})
|
||||
define_channel_server_options(${OPTION_SERVER_DEFAULT})
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
|||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE freerdp
|
||||
MODULES freerdp-utils)
|
||||
MODULES freerdp-common freerdp-utils)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
|
@ -41,9 +41,9 @@ endif()
|
|||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")
|
||||
|
||||
if(WITH_ALSA)
|
||||
add_subdirectory(alsa)
|
||||
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "alsa" "")
|
||||
endif()
|
||||
|
||||
if(WITH_PULSE)
|
||||
add_subdirectory(pulse)
|
||||
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "pulse" "")
|
||||
endif()
|
||||
|
|
|
@ -23,7 +23,7 @@ set(${MODULE_PREFIX}_SRCS
|
|||
include_directories(..)
|
||||
include_directories(${ALSA_INCLUDE_DIRS})
|
||||
|
||||
add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
|
@ -36,4 +36,6 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${ALSA_LIBRARIES})
|
|||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
|
||||
if(NOT STATIC_CHANNELS)
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
|
||||
endif()
|
||||
|
|
|
@ -25,10 +25,14 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/cmdline.h>
|
||||
|
||||
#include <alsa/asoundlib.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/thread.h>
|
||||
|
||||
#include <freerdp/addin.h>
|
||||
#include <freerdp/utils/dsp.h>
|
||||
#include <freerdp/utils/thread.h>
|
||||
|
||||
#include "audin_main.h"
|
||||
|
||||
|
@ -36,7 +40,7 @@ typedef struct _AudinALSADevice
|
|||
{
|
||||
IAudinDevice iface;
|
||||
|
||||
char device_name[32];
|
||||
char* device_name;
|
||||
UINT32 frames_per_packet;
|
||||
UINT32 target_rate;
|
||||
UINT32 actual_rate;
|
||||
|
@ -183,10 +187,13 @@ static void* audin_alsa_thread_func(void* arg)
|
|||
|
||||
rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_channel;
|
||||
tbytes_per_frame = alsa->target_channels * alsa->bytes_per_channel;
|
||||
alsa->buffer = (BYTE*) xzalloc(tbytes_per_frame * alsa->frames_per_packet);
|
||||
alsa->buffer = (BYTE*) malloc(tbytes_per_frame * alsa->frames_per_packet);
|
||||
ZeroMemory(alsa->buffer, tbytes_per_frame * alsa->frames_per_packet);
|
||||
alsa->buffer_frames = 0;
|
||||
buffer = (BYTE*) xzalloc(rbytes_per_frame * alsa->frames_per_packet);
|
||||
buffer = (BYTE*) malloc(rbytes_per_frame * alsa->frames_per_packet);
|
||||
ZeroMemory(buffer, rbytes_per_frame * alsa->frames_per_packet);
|
||||
freerdp_dsp_context_reset_adpcm(alsa->dsp_context);
|
||||
|
||||
do
|
||||
{
|
||||
if ((error = snd_pcm_open(&capture_handle, alsa->device_name, SND_PCM_STREAM_CAPTURE, 0)) < 0)
|
||||
|
@ -236,6 +243,9 @@ static void audin_alsa_free(IAudinDevice* device)
|
|||
|
||||
freerdp_thread_free(alsa->thread);
|
||||
freerdp_dsp_context_free(alsa->dsp_context);
|
||||
|
||||
free(alsa->device_name);
|
||||
|
||||
free(alsa);
|
||||
}
|
||||
|
||||
|
@ -328,36 +338,66 @@ static void audin_alsa_close(IAudinDevice* device)
|
|||
alsa->user_data = NULL;
|
||||
}
|
||||
|
||||
int FreeRDPAudinDeviceEntry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints)
|
||||
COMMAND_LINE_ARGUMENT_A audin_alsa_args[] =
|
||||
{
|
||||
AudinALSADevice* alsa;
|
||||
RDP_PLUGIN_DATA* data;
|
||||
{ "audio-dev", COMMAND_LINE_VALUE_REQUIRED, "<device>", NULL, NULL, -1, NULL, "audio device name" },
|
||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
alsa = xnew(AudinALSADevice);
|
||||
static void audin_alsa_parse_addin_args(AudinALSADevice* device, ADDIN_ARGV* args)
|
||||
{
|
||||
int status;
|
||||
DWORD flags;
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
AudinALSADevice* alsa = (AudinALSADevice*) device;
|
||||
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
|
||||
|
||||
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, audin_alsa_args, flags, alsa, NULL, NULL);
|
||||
|
||||
arg = audin_alsa_args;
|
||||
|
||||
do
|
||||
{
|
||||
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
|
||||
continue;
|
||||
|
||||
CommandLineSwitchStart(arg)
|
||||
|
||||
CommandLineSwitchCase(arg, "audio-dev")
|
||||
{
|
||||
alsa->device_name = _strdup(arg->Value);
|
||||
}
|
||||
|
||||
CommandLineSwitchEnd(arg)
|
||||
}
|
||||
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_audin_client_subsystem_entry alsa_freerdp_audin_client_subsystem_entry
|
||||
#endif
|
||||
|
||||
int freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
ADDIN_ARGV* args;
|
||||
AudinALSADevice* alsa;
|
||||
|
||||
alsa = (AudinALSADevice*) malloc(sizeof(AudinALSADevice));
|
||||
ZeroMemory(alsa, sizeof(AudinALSADevice));
|
||||
|
||||
alsa->iface.Open = audin_alsa_open;
|
||||
alsa->iface.FormatSupported = audin_alsa_format_supported;
|
||||
alsa->iface.SetFormat = audin_alsa_set_format;
|
||||
alsa->iface.Close = audin_alsa_close;
|
||||
alsa->iface.Free = audin_alsa_free;
|
||||
alsa->device_name[0] = '\0';
|
||||
|
||||
data = pEntryPoints->plugin_data;
|
||||
if (data)
|
||||
{
|
||||
char *data2 = (char *) (data->data[2]);
|
||||
if (data->data[0] && (strcmp(data->data[0], "audin") == 0) &&
|
||||
data->data[1] && (strcmp(data->data[1], "alsa") == 0) &&
|
||||
data2 && (*data2 != '\0'))
|
||||
{
|
||||
strncpy(alsa->device_name, data2, sizeof(alsa->device_name));
|
||||
}
|
||||
}
|
||||
args = pEntryPoints->args;
|
||||
|
||||
if (alsa->device_name[0] == '\0')
|
||||
{
|
||||
strcpy(alsa->device_name, "default");
|
||||
}
|
||||
audin_alsa_parse_addin_args(alsa, args);
|
||||
|
||||
if (!alsa->device_name)
|
||||
alsa->device_name = _strdup("default");
|
||||
|
||||
alsa->frames_per_packet = 128;
|
||||
alsa->target_rate = 22050;
|
||||
|
@ -374,4 +414,3 @@ int FreeRDPAudinDeviceEntry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,9 +25,12 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/cmdline.h>
|
||||
|
||||
#include <freerdp/addin.h>
|
||||
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/load_plugin.h>
|
||||
|
||||
#include "audin_main.h"
|
||||
|
||||
|
@ -77,6 +80,8 @@ struct _AUDIN_PLUGIN
|
|||
UINT16 fixed_format;
|
||||
UINT16 fixed_channel;
|
||||
UINT32 fixed_rate;
|
||||
char* subsystem;
|
||||
char* device_name;
|
||||
|
||||
/* Device interface */
|
||||
IAudinDevice* device;
|
||||
|
@ -132,7 +137,8 @@ static int audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, S
|
|||
}
|
||||
stream_seek_UINT32(s); /* cbSizeFormatsPacket */
|
||||
|
||||
callback->formats = (audinFormat*) xzalloc(NumFormats * sizeof(audinFormat));
|
||||
callback->formats = (audinFormat*) malloc(NumFormats * sizeof(audinFormat));
|
||||
ZeroMemory(callback->formats, NumFormats * sizeof(audinFormat));
|
||||
|
||||
out = stream_new(9);
|
||||
stream_seek(out, 9);
|
||||
|
@ -373,7 +379,8 @@ static int audin_on_new_channel_connection(IWTSListenerCallback* pListenerCallba
|
|||
|
||||
DEBUG_DVC("");
|
||||
|
||||
callback = xnew(AUDIN_CHANNEL_CALLBACK);
|
||||
callback = (AUDIN_CHANNEL_CALLBACK*) malloc(sizeof(AUDIN_CHANNEL_CALLBACK));
|
||||
ZeroMemory(callback, sizeof(AUDIN_CHANNEL_CALLBACK));
|
||||
|
||||
callback->iface.OnDataReceived = audin_on_data_received;
|
||||
callback->iface.OnClose = audin_on_close;
|
||||
|
@ -392,7 +399,8 @@ static int audin_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManage
|
|||
|
||||
DEBUG_DVC("");
|
||||
|
||||
audin->listener_callback = xnew(AUDIN_LISTENER_CALLBACK);
|
||||
audin->listener_callback = (AUDIN_LISTENER_CALLBACK*) malloc(sizeof(AUDIN_LISTENER_CALLBACK));
|
||||
ZeroMemory(audin->listener_callback, sizeof(AUDIN_LISTENER_CALLBACK));
|
||||
|
||||
audin->listener_callback->iface.OnNewChannelConnection = audin_on_new_channel_connection;
|
||||
audin->listener_callback->plugin = pPlugin;
|
||||
|
@ -436,31 +444,19 @@ static void audin_register_device_plugin(IWTSPlugin* pPlugin, IAudinDevice* devi
|
|||
audin->device = device;
|
||||
}
|
||||
|
||||
static BOOL audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, RDP_PLUGIN_DATA* data)
|
||||
static BOOL audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, ADDIN_ARGV* args)
|
||||
{
|
||||
char* fullname;
|
||||
PFREERDP_AUDIN_DEVICE_ENTRY entry;
|
||||
FREERDP_AUDIN_DEVICE_ENTRY_POINTS entryPoints;
|
||||
|
||||
if (strrchr(name, '.') != NULL)
|
||||
{
|
||||
entry = (PFREERDP_AUDIN_DEVICE_ENTRY) freerdp_load_plugin(name, AUDIN_DEVICE_EXPORT_FUNC_NAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
fullname = xzalloc(strlen(name) + 8);
|
||||
strcpy(fullname, "audin_");
|
||||
strcat(fullname, name);
|
||||
entry = (PFREERDP_AUDIN_DEVICE_ENTRY) freerdp_load_plugin(fullname, AUDIN_DEVICE_EXPORT_FUNC_NAME);
|
||||
free(fullname);
|
||||
}
|
||||
entry = (PFREERDP_AUDIN_DEVICE_ENTRY) freerdp_load_channel_addin_entry("audin", (LPSTR) name, NULL, 0);
|
||||
|
||||
if (entry == NULL)
|
||||
return FALSE;
|
||||
|
||||
entryPoints.plugin = pPlugin;
|
||||
entryPoints.pRegisterAudinDevice = audin_register_device_plugin;
|
||||
entryPoints.plugin_data = data;
|
||||
entryPoints.args = args;
|
||||
|
||||
if (entry(&entryPoints) != 0)
|
||||
{
|
||||
|
@ -471,54 +467,81 @@ static BOOL audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, RDP_
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL audin_process_plugin_data(IWTSPlugin* pPlugin, RDP_PLUGIN_DATA* data)
|
||||
void audin_set_subsystem(AUDIN_PLUGIN* audin, char* subsystem)
|
||||
{
|
||||
BOOL ret;
|
||||
if (audin->subsystem)
|
||||
free(audin->subsystem);
|
||||
|
||||
audin->subsystem = _strdup(subsystem);
|
||||
}
|
||||
|
||||
void audin_set_device_name(AUDIN_PLUGIN* audin, char* device_name)
|
||||
{
|
||||
if (audin->device_name)
|
||||
free(audin->device_name);
|
||||
|
||||
audin->device_name = _strdup(device_name);
|
||||
}
|
||||
|
||||
COMMAND_LINE_ARGUMENT_A audin_args[] =
|
||||
{
|
||||
{ "sys", COMMAND_LINE_VALUE_REQUIRED, "<subsystem>", NULL, NULL, -1, NULL, "subsystem" },
|
||||
{ "dev", COMMAND_LINE_VALUE_REQUIRED, "<device>", NULL, NULL, -1, NULL, "device" },
|
||||
{ "format", COMMAND_LINE_VALUE_REQUIRED, "<format>", NULL, NULL, -1, NULL, "format" },
|
||||
{ "rate", COMMAND_LINE_VALUE_REQUIRED, "<rate>", NULL, NULL, -1, NULL, "rate" },
|
||||
{ "channel", COMMAND_LINE_VALUE_REQUIRED, "<channel>", NULL, NULL, -1, NULL, "channel" },
|
||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
static BOOL audin_process_addin_args(IWTSPlugin* pPlugin, ADDIN_ARGV* args)
|
||||
{
|
||||
int status;
|
||||
DWORD flags;
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin;
|
||||
RDP_PLUGIN_DATA default_data[2] = { { 0 }, { 0 } };
|
||||
|
||||
if (data->data[0] && (strcmp((char*)data->data[0], "audin") == 0 || strstr((char*) data->data[0], "/audin.") != NULL))
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
|
||||
|
||||
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
|
||||
audin_args, flags, audin, NULL, NULL);
|
||||
|
||||
arg = audin_args;
|
||||
|
||||
do
|
||||
{
|
||||
if (data->data[1] && strcmp((char*)data->data[1], "format") == 0)
|
||||
{
|
||||
audin->fixed_format = atoi(data->data[2]);
|
||||
return TRUE;
|
||||
}
|
||||
else if (data->data[1] && strcmp((char*)data->data[1], "rate") == 0)
|
||||
{
|
||||
audin->fixed_rate = atoi(data->data[2]);
|
||||
return TRUE;
|
||||
}
|
||||
else if (data->data[1] && strcmp((char*)data->data[1], "channel") == 0)
|
||||
{
|
||||
audin->fixed_channel = atoi(data->data[2]);
|
||||
return TRUE;
|
||||
}
|
||||
else if (data->data[1] && ((char*)data->data[1])[0])
|
||||
{
|
||||
return audin_load_device_plugin(pPlugin, (char*) data->data[1], data);
|
||||
}
|
||||
else
|
||||
{
|
||||
default_data[0].size = sizeof(RDP_PLUGIN_DATA);
|
||||
default_data[0].data[0] = "audin";
|
||||
default_data[0].data[1] = "pulse";
|
||||
default_data[0].data[2] = "";
|
||||
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
|
||||
continue;
|
||||
|
||||
ret = audin_load_device_plugin(pPlugin, "pulse", default_data);
|
||||
CommandLineSwitchStart(arg)
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
default_data[0].size = sizeof(RDP_PLUGIN_DATA);
|
||||
default_data[0].data[0] = "audin";
|
||||
default_data[0].data[1] = "alsa";
|
||||
default_data[0].data[2] = "default";
|
||||
ret = audin_load_device_plugin(pPlugin, "alsa", default_data);
|
||||
}
|
||||
|
||||
return ret;
|
||||
CommandLineSwitchCase(arg, "sys")
|
||||
{
|
||||
audin_set_subsystem(audin, arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "dev")
|
||||
{
|
||||
audin_set_device_name(audin, arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "format")
|
||||
{
|
||||
audin->fixed_format = atoi(arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "rate")
|
||||
{
|
||||
audin->fixed_rate = atoi(arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "channel")
|
||||
{
|
||||
audin->fixed_channel = atoi(arg->Value);
|
||||
}
|
||||
CommandLineSwitchDefault(arg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CommandLineSwitchEnd(arg)
|
||||
}
|
||||
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -530,23 +553,50 @@ static BOOL audin_process_plugin_data(IWTSPlugin* pPlugin, RDP_PLUGIN_DATA* data
|
|||
int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||
{
|
||||
int error = 0;
|
||||
ADDIN_ARGV* args;
|
||||
AUDIN_PLUGIN* audin;
|
||||
|
||||
audin = (AUDIN_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "audin");
|
||||
|
||||
if (audin == NULL)
|
||||
{
|
||||
audin = xnew(AUDIN_PLUGIN);
|
||||
audin = (AUDIN_PLUGIN*) malloc(sizeof(AUDIN_PLUGIN));
|
||||
ZeroMemory(audin, sizeof(AUDIN_PLUGIN));
|
||||
|
||||
audin->iface.Initialize = audin_plugin_initialize;
|
||||
audin->iface.Connected = NULL;
|
||||
audin->iface.Disconnected = NULL;
|
||||
audin->iface.Terminated = audin_plugin_terminated;
|
||||
|
||||
error = pEntryPoints->RegisterPlugin(pEntryPoints, "audin", (IWTSPlugin*) audin);
|
||||
}
|
||||
|
||||
args = pEntryPoints->GetPluginData(pEntryPoints);
|
||||
|
||||
if (error == 0)
|
||||
audin_process_plugin_data((IWTSPlugin*) audin, pEntryPoints->GetPluginData(pEntryPoints));
|
||||
audin_process_addin_args((IWTSPlugin*) audin, args);
|
||||
|
||||
if (audin->subsystem)
|
||||
audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args);
|
||||
|
||||
if (!audin->device)
|
||||
{
|
||||
audin_set_subsystem(audin, "pulse");
|
||||
audin_set_device_name(audin, "");
|
||||
audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args);
|
||||
}
|
||||
|
||||
if (!audin->device)
|
||||
{
|
||||
audin_set_subsystem(audin, "alsa");
|
||||
audin_set_device_name(audin, "default");
|
||||
audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args);
|
||||
}
|
||||
|
||||
if (audin->device == NULL)
|
||||
{
|
||||
DEBUG_WARN("no sound device.");
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <freerdp/dvc.h>
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/addin.h>
|
||||
#include <freerdp/utils/debug.h>
|
||||
|
||||
#ifdef WITH_DEBUG_DVC
|
||||
|
@ -58,7 +59,7 @@ struct _IAudinDevice
|
|||
void (*Free) (IAudinDevice* devplugin);
|
||||
};
|
||||
|
||||
#define AUDIN_DEVICE_EXPORT_FUNC_NAME "FreeRDPAudinDeviceEntry"
|
||||
#define AUDIN_DEVICE_EXPORT_FUNC_NAME "freerdp_audin_client_subsystem_entry"
|
||||
|
||||
typedef void (*PREGISTERAUDINDEVICE)(IWTSPlugin* plugin, IAudinDevice* device);
|
||||
|
||||
|
@ -66,7 +67,7 @@ struct _FREERDP_AUDIN_DEVICE_ENTRY_POINTS
|
|||
{
|
||||
IWTSPlugin* plugin;
|
||||
PREGISTERAUDINDEVICE pRegisterAudinDevice;
|
||||
RDP_PLUGIN_DATA* plugin_data;
|
||||
ADDIN_ARGV* args;
|
||||
};
|
||||
typedef struct _FREERDP_AUDIN_DEVICE_ENTRY_POINTS FREERDP_AUDIN_DEVICE_ENTRY_POINTS;
|
||||
typedef FREERDP_AUDIN_DEVICE_ENTRY_POINTS* PFREERDP_AUDIN_DEVICE_ENTRY_POINTS;
|
||||
|
|
|
@ -23,7 +23,7 @@ set(${MODULE_PREFIX}_SRCS
|
|||
include_directories(..)
|
||||
include_directories(${PULSE_INCLUDE_DIR})
|
||||
|
||||
add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
|
@ -36,4 +36,6 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${PULSE_LIBRARY})
|
|||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
|
||||
if(NOT STATIC_CHANNELS)
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
|
||||
endif()
|
||||
|
|
|
@ -25,9 +25,13 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/cmdline.h>
|
||||
|
||||
#include <pulse/pulseaudio.h>
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/addin.h>
|
||||
#include <freerdp/utils/dsp.h>
|
||||
|
||||
#include "audin_main.h"
|
||||
|
@ -36,7 +40,7 @@ typedef struct _AudinPulseDevice
|
|||
{
|
||||
IAudinDevice iface;
|
||||
|
||||
char device_name[32];
|
||||
char* device_name;
|
||||
UINT32 frames_per_packet;
|
||||
pa_threaded_mainloop* mainloop;
|
||||
pa_context* context;
|
||||
|
@ -420,7 +424,8 @@ static void audin_pulse_open(IAudinDevice* device, AudinReceive receive, void* u
|
|||
if (state == PA_STREAM_READY)
|
||||
{
|
||||
freerdp_dsp_context_reset_adpcm(pulse->dsp_context);
|
||||
pulse->buffer = xzalloc(pulse->bytes_per_frame * pulse->frames_per_packet);
|
||||
pulse->buffer = malloc(pulse->bytes_per_frame * pulse->frames_per_packet);
|
||||
ZeroMemory(pulse->buffer, pulse->bytes_per_frame * pulse->frames_per_packet);
|
||||
pulse->buffer_frames = 0;
|
||||
DEBUG_DVC("connected");
|
||||
}
|
||||
|
@ -430,12 +435,53 @@ static void audin_pulse_open(IAudinDevice* device, AudinReceive receive, void* u
|
|||
}
|
||||
}
|
||||
|
||||
int FreeRDPAudinDeviceEntry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints)
|
||||
COMMAND_LINE_ARGUMENT_A audin_pulse_args[] =
|
||||
{
|
||||
AudinPulseDevice* pulse;
|
||||
RDP_PLUGIN_DATA * data;
|
||||
{ "audio-dev", COMMAND_LINE_VALUE_REQUIRED, "<device>", NULL, NULL, -1, NULL, "audio device name" },
|
||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
pulse = xnew(AudinPulseDevice);
|
||||
static void audin_pulse_parse_addin_args(AudinPulseDevice* device, ADDIN_ARGV* args)
|
||||
{
|
||||
int status;
|
||||
DWORD flags;
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
AudinPulseDevice* pulse = (AudinPulseDevice*) device;
|
||||
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
|
||||
|
||||
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, audin_pulse_args, flags, pulse, NULL, NULL);
|
||||
|
||||
arg = audin_pulse_args;
|
||||
|
||||
do
|
||||
{
|
||||
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
|
||||
continue;
|
||||
|
||||
CommandLineSwitchStart(arg)
|
||||
|
||||
CommandLineSwitchCase(arg, "audio-dev")
|
||||
{
|
||||
pulse->device_name = _strdup(arg->Value);
|
||||
}
|
||||
|
||||
CommandLineSwitchEnd(arg)
|
||||
}
|
||||
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_audin_client_subsystem_entry pulse_freerdp_audin_client_subsystem_entry
|
||||
#endif
|
||||
|
||||
int freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
ADDIN_ARGV* args;
|
||||
AudinPulseDevice* pulse;
|
||||
|
||||
pulse = (AudinPulseDevice*) malloc(sizeof(AudinPulseDevice));
|
||||
ZeroMemory(pulse, sizeof(AudinPulseDevice));
|
||||
|
||||
pulse->iface.Open = audin_pulse_open;
|
||||
pulse->iface.FormatSupported = audin_pulse_format_supported;
|
||||
|
@ -443,30 +489,35 @@ int FreeRDPAudinDeviceEntry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints)
|
|||
pulse->iface.Close = audin_pulse_close;
|
||||
pulse->iface.Free = audin_pulse_free;
|
||||
|
||||
data = pEntryPoints->plugin_data;
|
||||
if (data && data->data[0] && strcmp(data->data[0], "audin") == 0 &&
|
||||
data->data[1] && strcmp(data->data[1], "pulse") == 0)
|
||||
{
|
||||
strncpy(pulse->device_name, (char*)data->data[2], sizeof(pulse->device_name));
|
||||
}
|
||||
args = pEntryPoints->args;
|
||||
|
||||
audin_pulse_parse_addin_args(pulse, args);
|
||||
|
||||
if (!pulse->device_name)
|
||||
pulse->device_name = _strdup("default");
|
||||
|
||||
pulse->dsp_context = freerdp_dsp_context_new();
|
||||
|
||||
pulse->mainloop = pa_threaded_mainloop_new();
|
||||
|
||||
if (!pulse->mainloop)
|
||||
{
|
||||
DEBUG_WARN("pa_threaded_mainloop_new failed");
|
||||
audin_pulse_free((IAudinDevice*) pulse);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pulse->context = pa_context_new(pa_threaded_mainloop_get_api(pulse->mainloop), "freerdp");
|
||||
|
||||
if (!pulse->context)
|
||||
{
|
||||
DEBUG_WARN("pa_context_new failed");
|
||||
audin_pulse_free((IAudinDevice*) pulse);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pa_context_set_state_callback(pulse->context, audin_pulse_context_state_callback, pulse);
|
||||
|
||||
if (!audin_pulse_connect((IAudinDevice*) pulse))
|
||||
{
|
||||
audin_pulse_free((IAudinDevice*) pulse);
|
||||
|
@ -477,4 +528,3 @@ int FreeRDPAudinDeviceEntry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,10 +25,11 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/utils/dsp.h>
|
||||
#include <freerdp/utils/thread.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/wait_obj.h>
|
||||
#include <freerdp/channels/wtsvc.h>
|
||||
#include <freerdp/server/audin.h>
|
||||
|
@ -134,7 +135,9 @@ static BOOL audin_server_recv_formats(audin_server* audin, STREAM* s, UINT32 len
|
|||
if (audin->context.num_client_formats <= 0)
|
||||
return FALSE;
|
||||
|
||||
audin->context.client_formats = xzalloc(audin->context.num_client_formats * sizeof(rdpsndFormat));
|
||||
audin->context.client_formats = malloc(audin->context.num_client_formats * sizeof(rdpsndFormat));
|
||||
ZeroMemory(audin->context.client_formats, audin->context.num_client_formats * sizeof(rdpsndFormat));
|
||||
|
||||
for (i = 0; i < audin->context.num_client_formats; i++)
|
||||
{
|
||||
if (length < 18)
|
||||
|
@ -410,7 +413,9 @@ audin_server_context* audin_server_context_new(WTSVirtualChannelManager* vcm)
|
|||
{
|
||||
audin_server* audin;
|
||||
|
||||
audin = xnew(audin_server);
|
||||
audin = (audin_server*) malloc(sizeof(audin_server));
|
||||
ZeroMemory(audin, sizeof(audin_server));
|
||||
|
||||
audin->context.vcm = vcm;
|
||||
audin->context.selected_client_format = -1;
|
||||
audin->context.frames_per_packet = 4096;
|
||||
|
@ -428,9 +433,12 @@ void audin_server_context_free(audin_server_context* context)
|
|||
audin_server* audin = (audin_server*) context;
|
||||
|
||||
audin_server_close(context);
|
||||
|
||||
if (audin->dsp_context)
|
||||
freerdp_dsp_context_free(audin->dsp_context);
|
||||
|
||||
if (audin->context.client_formats)
|
||||
free(audin->context.client_formats);
|
||||
|
||||
free(audin);
|
||||
}
|
||||
|
|
|
@ -26,9 +26,7 @@ set(${MODULE_PREFIX}_SRCS
|
|||
list(REMOVE_DUPLICATES CHANNEL_STATIC_CLIENT_ENTRIES)
|
||||
|
||||
foreach(STATIC_ENTRY ${CHANNEL_STATIC_CLIENT_ENTRIES})
|
||||
|
||||
foreach(STATIC_MODULE ${CHANNEL_STATIC_CLIENT_MODULES})
|
||||
|
||||
if(${${STATIC_MODULE}_CLIENT_ENTRY} STREQUAL ${STATIC_ENTRY})
|
||||
set(STATIC_MODULE_NAME ${${STATIC_MODULE}_CLIENT_NAME})
|
||||
set(STATIC_MODULE_CHANNEL ${${STATIC_MODULE}_CLIENT_CHANNEL})
|
||||
|
@ -39,26 +37,59 @@ foreach(STATIC_ENTRY ${CHANNEL_STATIC_CLIENT_ENTRIES})
|
|||
set(${STATIC_ENTRY}_IMPORTS "${${STATIC_ENTRY}_IMPORTS}\n${ENTRY_POINT_IMPORT}")
|
||||
set(${STATIC_ENTRY}_TABLE "${${STATIC_ENTRY}_TABLE}\n\t{ \"${STATIC_MODULE_CHANNEL}\", ${ENTRY_POINT_NAME} },")
|
||||
endif()
|
||||
|
||||
endforeach()
|
||||
|
||||
endforeach()
|
||||
|
||||
set(CLIENT_STATIC_ENTRY_TABLES_LIST "${CLIENT_STATIC_ENTRY_TABLES_LIST}\nconst STATIC_ENTRY_TABLE CLIENT_STATIC_ENTRY_TABLES[] =\n{")
|
||||
|
||||
foreach(STATIC_ENTRY ${CHANNEL_STATIC_CLIENT_ENTRIES})
|
||||
|
||||
set(CLIENT_STATIC_ENTRY_IMPORTS "${CLIENT_STATIC_ENTRY_IMPORTS}\n${${STATIC_ENTRY}_IMPORTS}")
|
||||
|
||||
set(CLIENT_STATIC_ENTRY_TABLES "${CLIENT_STATIC_ENTRY_TABLES}\nconst STATIC_ENTRY CLIENT_${STATIC_ENTRY}_TABLE[] =\n{")
|
||||
set(CLIENT_STATIC_ENTRY_TABLES "${CLIENT_STATIC_ENTRY_TABLES}\n${${STATIC_ENTRY}_TABLE}")
|
||||
set(CLIENT_STATIC_ENTRY_TABLES "${CLIENT_STATIC_ENTRY_TABLES}\n\t{ \"\", NULL }\n};")
|
||||
|
||||
set(CLIENT_STATIC_ENTRY_TABLES_LIST "${CLIENT_STATIC_ENTRY_TABLES_LIST}\n\t{ \"${STATIC_ENTRY}\", CLIENT_${STATIC_ENTRY}_TABLE },")
|
||||
endforeach()
|
||||
|
||||
set(CLIENT_STATIC_ENTRY_TABLES_LIST "${CLIENT_STATIC_ENTRY_TABLES_LIST}\n\t{ \"\", NULL }\n};")
|
||||
|
||||
set(CLIENT_STATIC_ADDIN_TABLE "const STATIC_ADDIN_TABLE CLIENT_STATIC_ADDIN_TABLE[] =\n{")
|
||||
foreach(STATIC_MODULE ${CHANNEL_STATIC_CLIENT_MODULES})
|
||||
set(STATIC_MODULE_NAME ${${STATIC_MODULE}_CLIENT_NAME})
|
||||
set(STATIC_MODULE_CHANNEL ${${STATIC_MODULE}_CLIENT_CHANNEL})
|
||||
string(TOUPPER "CLIENT_${STATIC_MODULE_CHANNEL}_SUBSYSTEM_TABLE" SUBSYSTEM_TABLE_NAME)
|
||||
set(SUBSYSTEM_TABLE "const STATIC_SUBSYSTEM_ENTRY ${SUBSYSTEM_TABLE_NAME}[] =\n{")
|
||||
get_target_property(CHANNEL_SUBSYSTEMS ${STATIC_MODULE_NAME} SUBSYSTEMS)
|
||||
if(CHANNEL_SUBSYSTEMS MATCHES "NOTFOUND")
|
||||
set(CHANNEL_SUBSYSTEMS "")
|
||||
endif()
|
||||
message(STATUS "Channel: ${STATIC_MODULE_CHANNEL} Subsystems: ${CHANNEL_SUBSYSTEMS}")
|
||||
foreach(STATIC_SUBSYSTEM ${CHANNEL_SUBSYSTEMS})
|
||||
if(${STATIC_SUBSYSTEM} MATCHES "^([^-]*)-(.*)")
|
||||
string(REGEX REPLACE "^([^-]*)-(.*)" "\\1" STATIC_SUBSYSTEM_NAME ${STATIC_SUBSYSTEM})
|
||||
string(REGEX REPLACE "^([^-]*)-(.*)" "\\2" STATIC_SUBSYSTEM_TYPE ${STATIC_SUBSYSTEM})
|
||||
else()
|
||||
set(STATIC_SUBSYSTEM_NAME "${STATIC_SUBSYSTEM}")
|
||||
set(STATIC_SUBSYSTEM_TYPE "")
|
||||
endif()
|
||||
string(LENGTH "${STATIC_SUBSYSTEM_TYPE}" _type_length)
|
||||
set(SUBSYSTEM_MODULE_NAME "${STATIC_MODULE_NAME}-${STATIC_SUBSYSTEM}")
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${SUBSYSTEM_MODULE_NAME})
|
||||
if(_type_length GREATER 0)
|
||||
set(STATIC_SUBSYSTEM_ENTRY "${STATIC_SUBSYSTEM_NAME}_freerdp_${STATIC_MODULE_CHANNEL}_client_${STATIC_SUBSYSTEM_TYPE}_subsystem_entry")
|
||||
else()
|
||||
set(STATIC_SUBSYSTEM_ENTRY "${STATIC_SUBSYSTEM_NAME}_freerdp_${STATIC_MODULE_CHANNEL}_client_subsystem_entry")
|
||||
endif()
|
||||
set(SUBSYSTEM_TABLE "${SUBSYSTEM_TABLE}\n\t{ \"${STATIC_SUBSYSTEM_NAME}\", \"${STATIC_SUBSYSTEM_TYPE}\", ${STATIC_SUBSYSTEM_ENTRY} },")
|
||||
set(SUBSYSTEM_IMPORT "extern void ${STATIC_SUBSYSTEM_ENTRY}();")
|
||||
set(CLIENT_STATIC_SUBSYSTEM_IMPORTS "${CLIENT_STATIC_SUBSYSTEM_IMPORTS}\n${SUBSYSTEM_IMPORT}")
|
||||
endforeach()
|
||||
set(SUBSYSTEM_TABLE "${SUBSYSTEM_TABLE}\n\t{ NULL, NULL, NULL }\n};")
|
||||
set(CLIENT_STATIC_SUBSYSTEM_TABLES "${CLIENT_STATIC_SUBSYSTEM_TABLES}\n${SUBSYSTEM_TABLE}")
|
||||
set(ENTRY_POINT_NAME "${STATIC_MODULE_CHANNEL}_${${STATIC_MODULE}_CLIENT_ENTRY}")
|
||||
set(CLIENT_STATIC_ADDIN_TABLE "${CLIENT_STATIC_ADDIN_TABLE}\n\t{ \"${STATIC_MODULE_CHANNEL}\", ${ENTRY_POINT_NAME}, ${SUBSYSTEM_TABLE_NAME} },")
|
||||
endforeach()
|
||||
set(CLIENT_STATIC_ADDIN_TABLE "${CLIENT_STATIC_ADDIN_TABLE}\n\t{ NULL, NULL, NULL }\n};")
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/tables.c.in ${CMAKE_CURRENT_SOURCE_DIR}/tables.c)
|
||||
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
|
@ -69,7 +100,7 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
|||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE winpr
|
||||
MODULES winpr-crt winpr-synch winpr-interlocked)
|
||||
MODULES winpr-crt winpr-path winpr-file winpr-synch winpr-library winpr-interlocked)
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} PARENT_SCOPE)
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE)
|
||||
|
|
|
@ -34,15 +34,17 @@
|
|||
#include <freerdp/client/channels.h>
|
||||
#include <freerdp/channels/channels.h>
|
||||
#include <freerdp/svc.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/addin.h>
|
||||
#include <freerdp/utils/wait_obj.h>
|
||||
#include <freerdp/utils/load_plugin.h>
|
||||
#include <freerdp/utils/file.h>
|
||||
#include <freerdp/utils/event.h>
|
||||
#include <freerdp/utils/debug.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/path.h>
|
||||
#include <winpr/file.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/library.h>
|
||||
#include <winpr/interlocked.h>
|
||||
|
||||
#ifdef WITH_DEBUG_CHANNELS
|
||||
|
@ -109,35 +111,262 @@ void* freerdp_channels_client_find_static_entry(const char* name, const char* id
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void* freerdp_channels_client_find_dynamic_entry(const char* name, const char* identifier)
|
||||
extern const STATIC_ADDIN_TABLE CLIENT_STATIC_ADDIN_TABLE[];
|
||||
|
||||
FREERDP_ADDIN** freerdp_channels_list_client_static_addins(LPSTR pszName, LPSTR pszSubsystem, LPSTR pszType, DWORD dwFlags)
|
||||
{
|
||||
char* path;
|
||||
void* entry;
|
||||
char* module;
|
||||
int i, j;
|
||||
DWORD nAddins;
|
||||
FREERDP_ADDIN* pAddin;
|
||||
FREERDP_ADDIN** ppAddins = NULL;
|
||||
STATIC_SUBSYSTEM_ENTRY* subsystems;
|
||||
|
||||
module = freerdp_append_shared_library_suffix((char*) identifier);
|
||||
path = freerdp_construct_path(FREERDP_CLIENT_PLUGIN_PATH, module);
|
||||
nAddins = 0;
|
||||
ppAddins = (FREERDP_ADDIN**) malloc(sizeof(FREERDP_ADDIN*) * 128);
|
||||
ppAddins[nAddins] = NULL;
|
||||
|
||||
entry = freerdp_load_library_symbol(path, module);
|
||||
|
||||
free(module);
|
||||
free(path);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
void* freerdp_channels_client_find_entry(const char* name, const char* identifier)
|
||||
{
|
||||
void* pChannelEntry = NULL;
|
||||
|
||||
pChannelEntry = freerdp_channels_client_find_static_entry(name, identifier);
|
||||
|
||||
if (!pChannelEntry)
|
||||
for (i = 0; CLIENT_STATIC_ADDIN_TABLE[i].name != NULL; i++)
|
||||
{
|
||||
pChannelEntry = freerdp_channels_client_find_dynamic_entry(name, identifier);
|
||||
pAddin = (FREERDP_ADDIN*) malloc(sizeof(FREERDP_ADDIN));
|
||||
ZeroMemory(pAddin, sizeof(FREERDP_ADDIN));
|
||||
|
||||
strcpy(pAddin->cName, CLIENT_STATIC_ADDIN_TABLE[i].name);
|
||||
|
||||
pAddin->dwFlags = FREERDP_ADDIN_CLIENT;
|
||||
pAddin->dwFlags |= FREERDP_ADDIN_STATIC;
|
||||
pAddin->dwFlags |= FREERDP_ADDIN_NAME;
|
||||
|
||||
ppAddins[nAddins++] = pAddin;
|
||||
|
||||
subsystems = (STATIC_SUBSYSTEM_ENTRY*) CLIENT_STATIC_ADDIN_TABLE[i].table;
|
||||
|
||||
for (j = 0; subsystems[j].name != NULL; j++)
|
||||
{
|
||||
pAddin = (FREERDP_ADDIN*) malloc(sizeof(FREERDP_ADDIN));
|
||||
ZeroMemory(pAddin, sizeof(FREERDP_ADDIN));
|
||||
|
||||
strcpy(pAddin->cName, CLIENT_STATIC_ADDIN_TABLE[i].name);
|
||||
strcpy(pAddin->cSubsystem, subsystems[j].name);
|
||||
|
||||
pAddin->dwFlags = FREERDP_ADDIN_CLIENT;
|
||||
pAddin->dwFlags |= FREERDP_ADDIN_STATIC;
|
||||
pAddin->dwFlags |= FREERDP_ADDIN_NAME;
|
||||
pAddin->dwFlags |= FREERDP_ADDIN_SUBSYSTEM;
|
||||
|
||||
ppAddins[nAddins++] = pAddin;
|
||||
}
|
||||
}
|
||||
|
||||
return pChannelEntry;
|
||||
ppAddins[nAddins] = NULL;
|
||||
|
||||
return ppAddins;
|
||||
}
|
||||
|
||||
LPCSTR gAddinPath = FREERDP_ADDIN_PATH;
|
||||
LPCSTR gInstallPrefix = FREERDP_INSTALL_PREFIX;
|
||||
|
||||
FREERDP_ADDIN** freerdp_channels_list_dynamic_addins(LPSTR pszName, LPSTR pszSubsystem, LPSTR pszType, DWORD dwFlags)
|
||||
{
|
||||
int index;
|
||||
int nDashes;
|
||||
HANDLE hFind;
|
||||
DWORD nAddins;
|
||||
LPSTR pszPattern;
|
||||
size_t cchPattern;
|
||||
LPCSTR pszExtension;
|
||||
LPSTR pszSearchPath;
|
||||
size_t cchSearchPath;
|
||||
size_t cchAddinPath;
|
||||
size_t cchInstallPrefix;
|
||||
FREERDP_ADDIN** ppAddins;
|
||||
WIN32_FIND_DATAA FindData;
|
||||
|
||||
cchAddinPath = strlen(gAddinPath);
|
||||
cchInstallPrefix = strlen(gInstallPrefix);
|
||||
|
||||
pszExtension = PathGetSharedLibraryExtensionA(0);
|
||||
|
||||
cchPattern = 128 + strlen(pszExtension) + 2;
|
||||
pszPattern = (LPSTR) malloc(cchPattern + 1);
|
||||
|
||||
if (pszName && pszSubsystem && pszType)
|
||||
{
|
||||
sprintf_s(pszPattern, cchPattern, "%s-client-%s-%s.%s", pszName, pszSubsystem, pszType, pszExtension);
|
||||
}
|
||||
else if (pszName && pszType)
|
||||
{
|
||||
sprintf_s(pszPattern, cchPattern, "%s-client-?-%s.%s", pszName, pszType, pszExtension);
|
||||
}
|
||||
else if (pszName)
|
||||
{
|
||||
sprintf_s(pszPattern, cchPattern, "%s-client*.%s", pszName, pszExtension);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf_s(pszPattern, cchPattern, "?-client*.%s", pszExtension);
|
||||
}
|
||||
|
||||
cchPattern = strlen(pszPattern);
|
||||
|
||||
cchSearchPath = cchInstallPrefix + cchAddinPath + cchPattern + 3;
|
||||
pszSearchPath = (LPSTR) malloc(cchSearchPath + 1);
|
||||
|
||||
CopyMemory(pszSearchPath, gInstallPrefix, cchInstallPrefix);
|
||||
pszSearchPath[cchInstallPrefix] = '\0';
|
||||
|
||||
NativePathCchAppendA(pszSearchPath, cchSearchPath + 1, gAddinPath);
|
||||
NativePathCchAppendA(pszSearchPath, cchSearchPath + 1, pszPattern);
|
||||
|
||||
cchSearchPath = strlen(pszSearchPath);
|
||||
|
||||
hFind = FindFirstFileA(pszSearchPath, &FindData);
|
||||
|
||||
nAddins = 0;
|
||||
ppAddins = (FREERDP_ADDIN**) malloc(sizeof(FREERDP_ADDIN*) * 128);
|
||||
ppAddins[nAddins] = NULL;
|
||||
|
||||
if (hFind == INVALID_HANDLE_VALUE)
|
||||
return ppAddins;
|
||||
|
||||
do
|
||||
{
|
||||
char* p[5];
|
||||
FREERDP_ADDIN* pAddin;
|
||||
|
||||
nDashes = 0;
|
||||
pAddin = (FREERDP_ADDIN*) malloc(sizeof(FREERDP_ADDIN));
|
||||
ZeroMemory(pAddin, sizeof(FREERDP_ADDIN));
|
||||
|
||||
for (index = 0; FindData.cFileName[index]; index++)
|
||||
nDashes += (FindData.cFileName[index] == '-') ? 1 : 0;
|
||||
|
||||
if (nDashes == 1)
|
||||
{
|
||||
/* <name>-client.<extension> */
|
||||
|
||||
p[0] = FindData.cFileName;
|
||||
p[1] = strchr(p[0], '-') + 1;
|
||||
|
||||
strncpy(pAddin->cName, p[0], (p[1] - p[0]) - 1);
|
||||
|
||||
pAddin->dwFlags = FREERDP_ADDIN_CLIENT;
|
||||
pAddin->dwFlags |= FREERDP_ADDIN_DYNAMIC;
|
||||
pAddin->dwFlags |= FREERDP_ADDIN_NAME;
|
||||
|
||||
ppAddins[nAddins++] = pAddin;
|
||||
}
|
||||
else if (nDashes == 2)
|
||||
{
|
||||
/* <name>-client-<subsystem>.<extension> */
|
||||
|
||||
p[0] = FindData.cFileName;
|
||||
p[1] = strchr(p[0], '-') + 1;
|
||||
p[2] = strchr(p[1], '-') + 1;
|
||||
p[3] = strchr(p[2], '.') + 1;
|
||||
|
||||
strncpy(pAddin->cName, p[0], (p[1] - p[0]) - 1);
|
||||
strncpy(pAddin->cSubsystem, p[2], (p[3] - p[2]) - 1);
|
||||
|
||||
pAddin->dwFlags = FREERDP_ADDIN_CLIENT;
|
||||
pAddin->dwFlags |= FREERDP_ADDIN_DYNAMIC;
|
||||
pAddin->dwFlags |= FREERDP_ADDIN_NAME;
|
||||
pAddin->dwFlags |= FREERDP_ADDIN_SUBSYSTEM;
|
||||
|
||||
ppAddins[nAddins++] = pAddin;
|
||||
}
|
||||
else if (nDashes == 3)
|
||||
{
|
||||
/* <name>-client-<subsystem>-<type>.<extension> */
|
||||
|
||||
p[0] = FindData.cFileName;
|
||||
p[1] = strchr(p[0], '-') + 1;
|
||||
p[2] = strchr(p[1], '-') + 1;
|
||||
p[3] = strchr(p[2], '-') + 1;
|
||||
p[4] = strchr(p[3], '.') + 1;
|
||||
|
||||
strncpy(pAddin->cName, p[0], (p[1] - p[0]) - 1);
|
||||
strncpy(pAddin->cSubsystem, p[2], (p[3] - p[2]) - 1);
|
||||
strncpy(pAddin->cType, p[3], (p[4] - p[3]) - 1);
|
||||
|
||||
pAddin->dwFlags = FREERDP_ADDIN_CLIENT;
|
||||
pAddin->dwFlags |= FREERDP_ADDIN_DYNAMIC;
|
||||
pAddin->dwFlags |= FREERDP_ADDIN_NAME;
|
||||
pAddin->dwFlags |= FREERDP_ADDIN_SUBSYSTEM;
|
||||
pAddin->dwFlags |= FREERDP_ADDIN_TYPE;
|
||||
|
||||
ppAddins[nAddins++] = pAddin;
|
||||
}
|
||||
else
|
||||
{
|
||||
free(pAddin);
|
||||
}
|
||||
}
|
||||
while (FindNextFileA(hFind, &FindData));
|
||||
|
||||
FindClose(hFind);
|
||||
|
||||
ppAddins[nAddins] = NULL;
|
||||
|
||||
return ppAddins;
|
||||
}
|
||||
|
||||
FREERDP_ADDIN** freerdp_channels_list_addins(LPSTR pszName, LPSTR pszSubsystem, LPSTR pszType, DWORD dwFlags)
|
||||
{
|
||||
if (dwFlags & FREERDP_ADDIN_STATIC)
|
||||
return freerdp_channels_list_client_static_addins(pszName, pszSubsystem, pszType, dwFlags);
|
||||
else if (dwFlags & FREERDP_ADDIN_DYNAMIC)
|
||||
return freerdp_channels_list_dynamic_addins(pszName, pszSubsystem, pszType, dwFlags);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void freerdp_channels_addin_list_free(FREERDP_ADDIN** ppAddins)
|
||||
{
|
||||
int index;
|
||||
|
||||
for (index = 0; ppAddins[index] != NULL; index++)
|
||||
free(ppAddins[index]);
|
||||
|
||||
free(ppAddins);
|
||||
}
|
||||
|
||||
void* freerdp_channels_load_static_addin_entry(LPCSTR pszName, LPSTR pszSubsystem, LPSTR pszType, DWORD dwFlags)
|
||||
{
|
||||
int i, j;
|
||||
STATIC_SUBSYSTEM_ENTRY* subsystems;
|
||||
|
||||
for (i = 0; CLIENT_STATIC_ADDIN_TABLE[i].name != NULL; i++)
|
||||
{
|
||||
if (pszSubsystem != NULL)
|
||||
{
|
||||
subsystems = (STATIC_SUBSYSTEM_ENTRY*) CLIENT_STATIC_ADDIN_TABLE[i].table;
|
||||
|
||||
for (j = 0; subsystems[j].name != NULL; j++)
|
||||
{
|
||||
if (strcmp(subsystems[j].name, pszSubsystem) == 0)
|
||||
{
|
||||
if (pszType)
|
||||
{
|
||||
if (strcmp(subsystems[j].type, pszType) == 0)
|
||||
return (void*) subsystems[j].entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (void*) subsystems[j].entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strcmp(CLIENT_STATIC_ADDIN_TABLE[i].name, pszName) == 0)
|
||||
{
|
||||
return (void*) CLIENT_STATIC_ADDIN_TABLE[i].entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct lib_data
|
||||
|
@ -319,13 +548,13 @@ static rdpChannel* freerdp_channels_find_channel_by_id(rdpChannels* channels, rd
|
|||
int lcount;
|
||||
rdpChannel* lrdp_channel;
|
||||
|
||||
lcount = settings->num_channels;
|
||||
lcount = settings->ChannelCount;
|
||||
|
||||
for (lindex = 0; lindex < lcount; lindex++)
|
||||
{
|
||||
lrdp_channel = settings->channels + lindex;
|
||||
lrdp_channel = settings->ChannelDefArray + lindex;
|
||||
|
||||
if (lrdp_channel->channel_id == channel_id)
|
||||
if (lrdp_channel->ChannelId == channel_id)
|
||||
{
|
||||
if (pindex != 0)
|
||||
*pindex = lindex;
|
||||
|
@ -345,13 +574,13 @@ static rdpChannel* freerdp_channels_find_channel_by_name(rdpChannels* channels,
|
|||
int lcount;
|
||||
rdpChannel* lrdp_channel;
|
||||
|
||||
lcount = settings->num_channels;
|
||||
lcount = settings->ChannelCount;
|
||||
|
||||
for (lindex = 0; lindex < lcount; lindex++)
|
||||
{
|
||||
lrdp_channel = settings->channels + lindex;
|
||||
lrdp_channel = settings->ChannelDefArray + lindex;
|
||||
|
||||
if (strcmp(channel_name, lrdp_channel->name) == 0)
|
||||
if (strcmp(channel_name, lrdp_channel->Name) == 0)
|
||||
{
|
||||
if (pindex != 0)
|
||||
*pindex = lindex;
|
||||
|
@ -449,12 +678,12 @@ static UINT32 FREERDP_CC MyVirtualChannelInit(void** ppInitHandle, PCHANNEL_DEF
|
|||
strncpy(lchannel_data->name, lchannel_def->name, CHANNEL_NAME_LEN);
|
||||
lchannel_data->options = lchannel_def->options;
|
||||
|
||||
if (channels->settings->num_channels < 16)
|
||||
if (channels->settings->ChannelCount < 16)
|
||||
{
|
||||
lrdp_channel = channels->settings->channels + channels->settings->num_channels;
|
||||
strncpy(lrdp_channel->name, lchannel_def->name, 7);
|
||||
lrdp_channel = channels->settings->ChannelDefArray + channels->settings->ChannelCount;
|
||||
strncpy(lrdp_channel->Name, lchannel_def->name, 7);
|
||||
lrdp_channel->options = lchannel_def->options;
|
||||
channels->settings->num_channels++;
|
||||
channels->settings->ChannelCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -699,7 +928,8 @@ rdpChannels* freerdp_channels_new(void)
|
|||
rdpChannels* channels;
|
||||
rdpChannelsList* channels_list;
|
||||
|
||||
channels = xnew(rdpChannels);
|
||||
channels = (rdpChannels*) malloc(sizeof(rdpChannels));
|
||||
ZeroMemory(channels, sizeof(rdpChannels));
|
||||
|
||||
channels->pSyncDataList = (PSLIST_HEADER) _aligned_malloc(sizeof(SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT);
|
||||
InitializeSListHead(channels->pSyncDataList);
|
||||
|
@ -708,7 +938,8 @@ rdpChannels* freerdp_channels_new(void)
|
|||
channels->signal = wait_obj_new();
|
||||
|
||||
/* Add it to the global list */
|
||||
channels_list = xnew(rdpChannelsList);
|
||||
channels_list = (rdpChannelsList*) malloc(sizeof(rdpChannelsList));
|
||||
ZeroMemory(channels_list, sizeof(rdpChannelsList));
|
||||
channels_list->channels = channels;
|
||||
|
||||
WaitForSingleObject(g_mutex_list, INFINITE);
|
||||
|
@ -762,7 +993,7 @@ int freerdp_channels_client_load(rdpChannels* channels, rdpSettings* settings, v
|
|||
|
||||
if (channels->num_libs_data + 1 >= CHANNEL_MAX_COUNT)
|
||||
{
|
||||
DEBUG_CHANNELS("too many channels");
|
||||
printf("error: too many channels\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -796,7 +1027,7 @@ int freerdp_channels_client_load(rdpChannels* channels, rdpSettings* settings, v
|
|||
|
||||
if (!status)
|
||||
{
|
||||
DEBUG_CHANNELS("export function call failed");
|
||||
printf("error: channel export function call failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -813,7 +1044,7 @@ int freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings, c
|
|||
|
||||
DEBUG_CHANNELS("%s", name);
|
||||
|
||||
entry = (PVIRTUALCHANNELENTRY) freerdp_load_plugin(name, CHANNEL_EXPORT_FUNC_NAME);
|
||||
entry = (PVIRTUALCHANNELENTRY) freerdp_load_channel_addin_entry(name, NULL, NULL, FREERDP_ADDIN_CHANNEL_STATIC);
|
||||
|
||||
if (entry == NULL)
|
||||
{
|
||||
|
@ -886,7 +1117,7 @@ int freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance)
|
|||
struct lib_data* llib;
|
||||
|
||||
channels->is_connected = 1;
|
||||
hostname = instance->settings->hostname;
|
||||
hostname = instance->settings->ServerHostname;
|
||||
hostname_len = strlen(hostname);
|
||||
|
||||
DEBUG_CHANNELS("hostname [%s] channels->num_libs [%d]", hostname, channels->num_libs_data);
|
||||
|
@ -929,7 +1160,7 @@ int freerdp_channels_data(freerdp* instance, int channel_id, void* data, int dat
|
|||
return 1;
|
||||
}
|
||||
|
||||
lchannel_data = freerdp_channels_find_channel_data_by_name(channels, lrdp_channel->name, &index);
|
||||
lchannel_data = freerdp_channels_find_channel_data_by_name(channels, lrdp_channel->Name, &index);
|
||||
|
||||
if (lchannel_data == 0)
|
||||
{
|
||||
|
@ -1017,7 +1248,7 @@ static void freerdp_channels_process_sync(rdpChannels* channels, freerdp* instan
|
|||
lchannel_data->name, &item->Index);
|
||||
|
||||
if (lrdp_channel != NULL)
|
||||
instance->SendChannelData(instance, lrdp_channel->channel_id, item->Data, item->DataLength);
|
||||
instance->SendChannelData(instance, lrdp_channel->ChannelId, item->Data, item->DataLength);
|
||||
|
||||
if (lchannel_data->open_event_proc != 0)
|
||||
{
|
||||
|
|
|
@ -25,4 +25,9 @@ ${CLIENT_STATIC_ENTRY_TABLES}
|
|||
|
||||
${CLIENT_STATIC_ENTRY_TABLES_LIST}
|
||||
|
||||
${CLIENT_STATIC_SUBSYSTEM_IMPORTS}
|
||||
|
||||
${CLIENT_STATIC_SUBSYSTEM_TABLES}
|
||||
|
||||
${CLIENT_STATIC_ADDIN_TABLE}
|
||||
|
||||
|
|
|
@ -32,3 +32,19 @@ struct _STATIC_ENTRY_TABLE
|
|||
const STATIC_ENTRY* table;
|
||||
};
|
||||
typedef struct _STATIC_ENTRY_TABLE STATIC_ENTRY_TABLE;
|
||||
|
||||
struct _STATIC_SUBSYSTEM_ENTRY
|
||||
{
|
||||
const char* name;
|
||||
const char* type;
|
||||
const void* entry;
|
||||
};
|
||||
typedef struct _STATIC_SUBSYSTEM_ENTRY STATIC_SUBSYSTEM_ENTRY;
|
||||
|
||||
struct _STATIC_ADDIN_TABLE
|
||||
{
|
||||
const char* name;
|
||||
const void* entry;
|
||||
const STATIC_SUBSYSTEM_ENTRY* table;
|
||||
};
|
||||
typedef struct _STATIC_ADDIN_TABLE STATIC_ADDIN_TABLE;
|
||||
|
|
|
@ -3,10 +3,6 @@ set(OPTION_DEFAULT OFF)
|
|||
set(OPTION_CLIENT_DEFAULT ON)
|
||||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "cliprdr" TYPE "static"
|
||||
DESCRIPTION "Clipboard Virtual Channel Extension"
|
||||
SPECIFICATIONS "[MS-RDPECLIP]"
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include <freerdp/types.h>
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/utils/hexdump.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/unicode.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
#include <freerdp/client/cliprdr.h>
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/unicode.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
#include <freerdp/client/cliprdr.h>
|
||||
|
@ -274,7 +273,7 @@ static void cliprdr_process_terminate(rdpSvcPlugin* plugin)
|
|||
/* cliprdr is always built-in */
|
||||
#define VirtualChannelEntry cliprdr_VirtualChannelEntry
|
||||
|
||||
const int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
cliprdrPlugin* _p;
|
||||
|
||||
|
@ -298,5 +297,3 @@ const int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
|||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3,10 +3,6 @@ set(OPTION_DEFAULT OFF)
|
|||
set(OPTION_CLIENT_DEFAULT ON)
|
||||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "drdynvc" TYPE "static"
|
||||
DESCRIPTION "Dynamic Virtual Channel Extension"
|
||||
SPECIFICATIONS "[MS-RDPEDYC]"
|
||||
|
|
|
@ -28,20 +28,19 @@
|
|||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
#include <freerdp/utils/wait_obj.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
#include "dvcman.h"
|
||||
#include "drdynvc_types.h"
|
||||
#include "drdynvc_main.h"
|
||||
|
||||
#define CREATE_REQUEST_PDU 0x01
|
||||
#define DATA_FIRST_PDU 0x02
|
||||
#define DATA_PDU 0x03
|
||||
#define CLOSE_REQUEST_PDU 0x04
|
||||
#define CAPABILITY_REQUEST_PDU 0x05
|
||||
#define CREATE_REQUEST_PDU 0x01
|
||||
#define DATA_FIRST_PDU 0x02
|
||||
#define DATA_PDU 0x03
|
||||
#define CLOSE_REQUEST_PDU 0x04
|
||||
#define CAPABILITY_REQUEST_PDU 0x05
|
||||
|
||||
struct drdynvc_plugin
|
||||
{
|
||||
|
@ -76,6 +75,7 @@ static int drdynvc_write_variable_uint(STREAM* stream, UINT32 val)
|
|||
cb = 2;
|
||||
stream_write_UINT32(stream, val);
|
||||
}
|
||||
|
||||
return cb;
|
||||
}
|
||||
|
||||
|
@ -97,13 +97,13 @@ int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UIN
|
|||
stream_set_pos(data_out, 1);
|
||||
cbChId = drdynvc_write_variable_uint(data_out, ChannelId);
|
||||
|
||||
if(data_size == 0)
|
||||
if (data_size == 0)
|
||||
{
|
||||
pos = stream_get_pos(data_out);
|
||||
stream_set_pos(data_out, 0);
|
||||
stream_write_BYTE(data_out, 0x40 | cbChId);
|
||||
stream_set_pos(data_out, pos);
|
||||
error = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out);
|
||||
error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out);
|
||||
}
|
||||
else if (data_size <= CHANNEL_CHUNK_LENGTH - pos)
|
||||
{
|
||||
|
@ -112,7 +112,7 @@ int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UIN
|
|||
stream_write_BYTE(data_out, 0x30 | cbChId);
|
||||
stream_set_pos(data_out, pos);
|
||||
stream_write(data_out, data, data_size);
|
||||
error = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out);
|
||||
error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -126,7 +126,7 @@ int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UIN
|
|||
stream_write(data_out, data, chunk_len);
|
||||
data += chunk_len;
|
||||
data_size -= chunk_len;
|
||||
error = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out);
|
||||
error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out);
|
||||
|
||||
while (error == CHANNEL_RC_OK && data_size > 0)
|
||||
{
|
||||
|
@ -148,12 +148,14 @@ int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UIN
|
|||
error = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out);
|
||||
}
|
||||
}
|
||||
|
||||
if (error != CHANNEL_RC_OK)
|
||||
{
|
||||
drdynvc->channel_error = error;
|
||||
DEBUG_WARN("VirtualChannelWrite failed %d", error);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -161,12 +163,14 @@ int drdynvc_push_event(drdynvcPlugin* drdynvc, RDP_EVENT* event)
|
|||
{
|
||||
int error;
|
||||
|
||||
error = svc_plugin_send_event((rdpSvcPlugin*)drdynvc, event);
|
||||
error = svc_plugin_send_event((rdpSvcPlugin*) drdynvc, event);
|
||||
|
||||
if (error != CHANNEL_RC_OK)
|
||||
{
|
||||
DEBUG_WARN("pVirtualChannelEventPush failed %d", error);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -178,6 +182,7 @@ static int drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp, in
|
|||
DEBUG_DVC("Sp=%d cbChId=%d", Sp, cbChId);
|
||||
stream_seek(s, 1); /* pad */
|
||||
stream_read_UINT16(s, drdynvc->version);
|
||||
|
||||
if (drdynvc->version == 2)
|
||||
{
|
||||
stream_read_UINT16(s, drdynvc->PriorityCharge0);
|
||||
|
@ -185,15 +190,18 @@ static int drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp, in
|
|||
stream_read_UINT16(s, drdynvc->PriorityCharge2);
|
||||
stream_read_UINT16(s, drdynvc->PriorityCharge3);
|
||||
}
|
||||
|
||||
data_out = stream_new(4);
|
||||
stream_write_UINT16(data_out, 0x0050); /* Cmd+Sp+cbChId+Pad. Note: MSTSC sends 0x005c */
|
||||
stream_write_UINT16(data_out, drdynvc->version);
|
||||
error = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out);
|
||||
error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out);
|
||||
|
||||
if (error != CHANNEL_RC_OK)
|
||||
{
|
||||
DEBUG_WARN("VirtualChannelWrite failed %d", error);
|
||||
return 1;
|
||||
}
|
||||
|
||||
drdynvc->channel_error = error;
|
||||
|
||||
return 0;
|
||||
|
@ -208,28 +216,31 @@ static UINT32 drdynvc_read_variable_uint(STREAM* stream, int cbLen)
|
|||
case 0:
|
||||
stream_read_BYTE(stream, val);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
stream_read_UINT16(stream, val);
|
||||
break;
|
||||
|
||||
default:
|
||||
stream_read_UINT32(stream, val);
|
||||
break;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static int drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, STREAM* s)
|
||||
{
|
||||
STREAM* data_out;
|
||||
int pos;
|
||||
int error;
|
||||
UINT32 ChannelId;
|
||||
STREAM* data_out;
|
||||
|
||||
ChannelId = drdynvc_read_variable_uint(s, cbChId);
|
||||
pos = stream_get_pos(s);
|
||||
DEBUG_DVC("ChannelId=%d ChannelName=%s", ChannelId, stream_get_tail(s));
|
||||
|
||||
error = dvcman_create_channel(drdynvc->channel_mgr, ChannelId, (char*)stream_get_tail(s));
|
||||
error = dvcman_create_channel(drdynvc->channel_mgr, ChannelId, (char*) stream_get_tail(s));
|
||||
|
||||
data_out = stream_new(pos + 4);
|
||||
stream_write_BYTE(data_out, 0x10 | cbChId);
|
||||
|
@ -247,26 +258,29 @@ static int drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cb
|
|||
stream_write_UINT32(data_out, (UINT32)(-1));
|
||||
}
|
||||
|
||||
error = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out);
|
||||
error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out);
|
||||
|
||||
if (error != CHANNEL_RC_OK)
|
||||
{
|
||||
DEBUG_WARN("VirtualChannelWrite failed %d", error);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drdynvc_process_data_first(drdynvcPlugin* drdynvc, int Sp, int cbChId, STREAM* s)
|
||||
{
|
||||
UINT32 ChannelId;
|
||||
UINT32 Length;
|
||||
int error;
|
||||
UINT32 Length;
|
||||
UINT32 ChannelId;
|
||||
|
||||
ChannelId = drdynvc_read_variable_uint(s, cbChId);
|
||||
Length = drdynvc_read_variable_uint(s, Sp);
|
||||
DEBUG_DVC("ChannelId=%d Length=%d", ChannelId, Length);
|
||||
|
||||
error = dvcman_receive_channel_data_first(drdynvc->channel_mgr, ChannelId, Length);
|
||||
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
|
@ -298,11 +312,11 @@ static int drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp, int cbC
|
|||
|
||||
static void drdynvc_process_receive(rdpSvcPlugin* plugin, STREAM* s)
|
||||
{
|
||||
drdynvcPlugin* drdynvc = (drdynvcPlugin*)plugin;
|
||||
int value;
|
||||
int Cmd;
|
||||
int Sp;
|
||||
int cbChId;
|
||||
drdynvcPlugin* drdynvc = (drdynvcPlugin*) plugin;
|
||||
|
||||
stream_read_BYTE(s, value);
|
||||
Cmd = (value & 0xf0) >> 4;
|
||||
|
@ -338,13 +352,24 @@ static void drdynvc_process_receive(rdpSvcPlugin* plugin, STREAM* s)
|
|||
|
||||
static void drdynvc_process_connect(rdpSvcPlugin* plugin)
|
||||
{
|
||||
int index;
|
||||
ADDIN_ARGV* args;
|
||||
rdpSettings* settings;
|
||||
drdynvcPlugin* drdynvc = (drdynvcPlugin*)plugin;
|
||||
|
||||
DEBUG_DVC("connecting");
|
||||
|
||||
drdynvc->channel_mgr = dvcman_new(drdynvc);
|
||||
drdynvc->channel_error = 0;
|
||||
dvcman_load_plugin(drdynvc->channel_mgr, svc_plugin_get_data(plugin));
|
||||
|
||||
settings = (rdpSettings*) ((rdpSvcPlugin*) plugin)->channel_entry_points.pExtendedData;
|
||||
|
||||
for (index = 0; index < settings->DynamicChannelCount; index++)
|
||||
{
|
||||
args = settings->DynamicChannelArray[index];
|
||||
dvcman_load_addin(drdynvc->channel_mgr, args);
|
||||
}
|
||||
|
||||
dvcman_init(drdynvc->channel_mgr);
|
||||
}
|
||||
|
||||
|
@ -355,7 +380,7 @@ static void drdynvc_process_event(rdpSvcPlugin* plugin, RDP_EVENT* event)
|
|||
|
||||
static void drdynvc_process_terminate(rdpSvcPlugin* plugin)
|
||||
{
|
||||
drdynvcPlugin* drdynvc = (drdynvcPlugin*)plugin;
|
||||
drdynvcPlugin* drdynvc = (drdynvcPlugin*) plugin;
|
||||
|
||||
DEBUG_DVC("terminating");
|
||||
|
||||
|
@ -368,7 +393,7 @@ static void drdynvc_process_terminate(rdpSvcPlugin* plugin)
|
|||
/* drdynvc is always built-in */
|
||||
#define VirtualChannelEntry drdynvc_VirtualChannelEntry
|
||||
|
||||
const int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
drdynvcPlugin* _p;
|
||||
|
||||
|
@ -391,4 +416,3 @@ const int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
|||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,10 +28,10 @@
|
|||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/addin.h>
|
||||
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/list.h>
|
||||
#include <freerdp/utils/load_plugin.h>
|
||||
|
||||
#include "drdynvc_types.h"
|
||||
#include "dvcman.h"
|
||||
|
@ -39,6 +39,7 @@
|
|||
#define MAX_PLUGINS 10
|
||||
|
||||
typedef struct _DVCMAN DVCMAN;
|
||||
|
||||
struct _DVCMAN
|
||||
{
|
||||
IWTSVirtualChannelManager iface;
|
||||
|
@ -72,7 +73,7 @@ struct _DVCMAN_ENTRY_POINTS
|
|||
IDRDYNVC_ENTRY_POINTS iface;
|
||||
|
||||
DVCMAN* dvcman;
|
||||
RDP_PLUGIN_DATA* plugin_data;
|
||||
ADDIN_ARGV* args;
|
||||
};
|
||||
|
||||
typedef struct _DVCMAN_CHANNEL DVCMAN_CHANNEL;
|
||||
|
@ -100,13 +101,16 @@ static int dvcman_create_listener(IWTSVirtualChannelManager* pChannelMgr,
|
|||
const char* pszChannelName, UINT32 ulFlags,
|
||||
IWTSListenerCallback* pListenerCallback, IWTSListener** ppListener)
|
||||
{
|
||||
DVCMAN* dvcman = (DVCMAN*)pChannelMgr;
|
||||
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
|
||||
DVCMAN_LISTENER* listener;
|
||||
|
||||
if (dvcman->num_listeners < MAX_PLUGINS)
|
||||
{
|
||||
DEBUG_DVC("%d.%s.", dvcman->num_listeners, pszChannelName);
|
||||
listener = xnew(DVCMAN_LISTENER);
|
||||
|
||||
listener = (DVCMAN_LISTENER*) malloc(sizeof(DVCMAN_LISTENER));
|
||||
ZeroMemory(listener, sizeof(DVCMAN_LISTENER));
|
||||
|
||||
listener->iface.GetConfiguration = dvcman_get_configuration;
|
||||
listener->dvcman = dvcman;
|
||||
listener->channel_name = _strdup(pszChannelName);
|
||||
|
@ -181,14 +185,14 @@ IWTSPlugin* dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* n
|
|||
return NULL;
|
||||
}
|
||||
|
||||
RDP_PLUGIN_DATA* dvcman_get_plugin_data(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||
ADDIN_ARGV* dvcman_get_plugin_data(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||
{
|
||||
return ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->plugin_data;
|
||||
return ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->args;
|
||||
}
|
||||
|
||||
UINT32 dvcman_get_channel_id(IWTSVirtualChannel * channel)
|
||||
{
|
||||
return ((DVCMAN_CHANNEL*)channel)->channel_id;
|
||||
return ((DVCMAN_CHANNEL*) channel)->channel_id;
|
||||
}
|
||||
|
||||
IWTSVirtualChannel* dvcman_find_channel_by_id(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId)
|
||||
|
@ -200,7 +204,7 @@ IWTSVirtualChannel* dvcman_find_channel_by_id(IWTSVirtualChannelManager* pChanne
|
|||
{
|
||||
if (((DVCMAN_CHANNEL*) curr->data)->channel_id == ChannelId)
|
||||
{
|
||||
return (IWTSVirtualChannel*)curr->data;
|
||||
return (IWTSVirtualChannel*) curr->data;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -211,7 +215,9 @@ IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
|
|||
{
|
||||
DVCMAN* dvcman;
|
||||
|
||||
dvcman = xnew(DVCMAN);
|
||||
dvcman = (DVCMAN*) malloc(sizeof(DVCMAN));
|
||||
ZeroMemory(dvcman, sizeof(DVCMAN));
|
||||
|
||||
dvcman->iface.CreateListener = dvcman_create_listener;
|
||||
dvcman->iface.PushEvent = dvcman_push_event;
|
||||
dvcman->iface.FindChannelById = dvcman_find_channel_by_id;
|
||||
|
@ -222,26 +228,24 @@ IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
|
|||
return (IWTSVirtualChannelManager*) dvcman;
|
||||
}
|
||||
|
||||
int dvcman_load_plugin(IWTSVirtualChannelManager* pChannelMgr, RDP_PLUGIN_DATA* data)
|
||||
int dvcman_load_addin(IWTSVirtualChannelManager* pChannelMgr, ADDIN_ARGV* args)
|
||||
{
|
||||
DVCMAN_ENTRY_POINTS entryPoints;
|
||||
PDVC_PLUGIN_ENTRY pDVCPluginEntry = NULL;
|
||||
|
||||
while (data && data->size > 0)
|
||||
{
|
||||
pDVCPluginEntry = (PDVC_PLUGIN_ENTRY) freerdp_load_plugin((char*) data->data[0], "DVCPluginEntry");
|
||||
printf("Loading Dynamic Virtual Channel %s\n", args->argv[0]);
|
||||
|
||||
if (pDVCPluginEntry != NULL)
|
||||
{
|
||||
entryPoints.iface.RegisterPlugin = dvcman_register_plugin;
|
||||
entryPoints.iface.GetPlugin = dvcman_get_plugin;
|
||||
entryPoints.iface.GetPluginData = dvcman_get_plugin_data;
|
||||
entryPoints.dvcman = (DVCMAN*) pChannelMgr;
|
||||
entryPoints.plugin_data = data;
|
||||
pDVCPluginEntry((IDRDYNVC_ENTRY_POINTS*) &entryPoints);
|
||||
}
|
||||
|
||||
data = (RDP_PLUGIN_DATA*)(((BYTE*) data) + data->size);
|
||||
pDVCPluginEntry = (PDVC_PLUGIN_ENTRY) freerdp_load_channel_addin_entry(args->argv[0],
|
||||
NULL, NULL, FREERDP_ADDIN_CHANNEL_DYNAMIC);
|
||||
|
||||
if (pDVCPluginEntry != NULL)
|
||||
{
|
||||
entryPoints.iface.RegisterPlugin = dvcman_register_plugin;
|
||||
entryPoints.iface.GetPlugin = dvcman_get_plugin;
|
||||
entryPoints.iface.GetPluginData = dvcman_get_plugin_data;
|
||||
entryPoints.dvcman = (DVCMAN*) pChannelMgr;
|
||||
entryPoints.args = args;
|
||||
pDVCPluginEntry((IDRDYNVC_ENTRY_POINTS*) &entryPoints);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -341,11 +345,13 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 Channel
|
|||
|
||||
for (i = 0; i < dvcman->num_listeners; i++)
|
||||
{
|
||||
listener = (DVCMAN_LISTENER*)dvcman->listeners[i];
|
||||
listener = (DVCMAN_LISTENER*) dvcman->listeners[i];
|
||||
|
||||
if (strcmp(listener->channel_name, ChannelName) == 0)
|
||||
{
|
||||
channel = xnew(DVCMAN_CHANNEL);
|
||||
channel = (DVCMAN_CHANNEL*) malloc(sizeof(DVCMAN_CHANNEL));
|
||||
ZeroMemory(channel, sizeof(DVCMAN_CHANNEL));
|
||||
|
||||
channel->iface.Write = dvcman_write_channel;
|
||||
channel->iface.Close = dvcman_close_channel_iface;
|
||||
channel->dvcman = dvcman;
|
||||
|
@ -377,7 +383,6 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 Channel
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId)
|
||||
{
|
||||
DVCMAN_CHANNEL* channel;
|
||||
|
|
|
@ -21,10 +21,12 @@
|
|||
#define __DVCMAN_H
|
||||
|
||||
#include <freerdp/dvc.h>
|
||||
#include <freerdp/addin.h>
|
||||
|
||||
#include "drdynvc_main.h"
|
||||
|
||||
IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin);
|
||||
int dvcman_load_plugin(IWTSVirtualChannelManager* pChannelMgr, RDP_PLUGIN_DATA* data);
|
||||
int dvcman_load_addin(IWTSVirtualChannelManager* pChannelMgr, ADDIN_ARGV* args);
|
||||
void dvcman_free(IWTSVirtualChannelManager* pChannelMgr);
|
||||
int dvcman_init(IWTSVirtualChannelManager* pChannelMgr);
|
||||
int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, const char* ChannelName);
|
||||
|
|
|
@ -15,8 +15,9 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
define_channel("disk")
|
||||
define_channel("drive")
|
||||
|
||||
if(WITH_CLIENT_CHANNELS)
|
||||
add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
|
||||
endif()
|
||||
|
|
@ -8,12 +8,8 @@ if(ANDROID)
|
|||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
endif()
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "disk" TYPE "device"
|
||||
DESCRIPTION "Disk Redirection Virtual Channel Extension"
|
||||
define_channel_options(NAME "drive" TYPE "device"
|
||||
DESCRIPTION "Drive Redirection Virtual Channel Extension"
|
||||
SPECIFICATIONS "[MS-RDPEFS]"
|
||||
DEFAULT ${OPTION_DEFAULT})
|
||||
|
|
@ -15,13 +15,13 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
define_channel_client("disk")
|
||||
define_channel_client("drive")
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
disk_file.c
|
||||
disk_file.h
|
||||
disk_main.c)
|
||||
|
||||
drive_file.c
|
||||
drive_file.h
|
||||
drive_main.c)
|
||||
|
||||
if(WIN32)
|
||||
set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS}
|
||||
statvfs.c
|
||||
|
@ -41,14 +41,12 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
|||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE winpr
|
||||
MODULES winpr-crt winpr-synch winpr-thread winpr-interlocked)
|
||||
MODULES winpr-crt winpr-file winpr-synch winpr-thread winpr-interlocked)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
if(NOT STATIC_CHANNELS)
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
|
||||
endif()
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")
|
||||
|
||||
|
|
@ -39,8 +39,8 @@
|
|||
#include <sys/stat.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/file.h>
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/unicode.h>
|
||||
#include <freerdp/channels/rdpdr.h>
|
||||
|
@ -49,47 +49,19 @@
|
|||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include "disk_file.h"
|
||||
#include "drive_file.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4244)
|
||||
#endif
|
||||
|
||||
static BOOL disk_file_wildcard_match(const char* pattern, const char* filename)
|
||||
{
|
||||
const char *p = pattern, *f = filename;
|
||||
char c;
|
||||
|
||||
/*
|
||||
* TODO: proper wildcard rules per msft's File System Behavior Overview
|
||||
* Simple cases for now.
|
||||
*/
|
||||
f = filename;
|
||||
while ((c = *p++))
|
||||
{
|
||||
if (c == '*')
|
||||
{
|
||||
c = *p++;
|
||||
if (!c) /* shortcut */
|
||||
return TRUE;
|
||||
/* TODO: skip to tail comparison */
|
||||
}
|
||||
if (c != *f++)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!*f)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void disk_file_fix_path(char* path)
|
||||
static void drive_file_fix_path(char* path)
|
||||
{
|
||||
int i;
|
||||
int length;
|
||||
|
@ -114,19 +86,19 @@ static void disk_file_fix_path(char* path)
|
|||
path[length - 1] = '\0';
|
||||
}
|
||||
|
||||
static char* disk_file_combine_fullpath(const char* base_path, const char* path)
|
||||
static char* drive_file_combine_fullpath(const char* base_path, const char* path)
|
||||
{
|
||||
char* fullpath;
|
||||
|
||||
fullpath = (char*) malloc(strlen(base_path) + strlen(path) + 1);
|
||||
strcpy(fullpath, base_path);
|
||||
strcat(fullpath, path);
|
||||
disk_file_fix_path(fullpath);
|
||||
drive_file_fix_path(fullpath);
|
||||
|
||||
return fullpath;
|
||||
}
|
||||
|
||||
static BOOL disk_file_remove_dir(const char* path)
|
||||
static BOOL drive_file_remove_dir(const char* path)
|
||||
{
|
||||
DIR* dir;
|
||||
char* p;
|
||||
|
@ -159,7 +131,7 @@ static BOOL disk_file_remove_dir(const char* path)
|
|||
}
|
||||
else if (S_ISDIR(st.st_mode))
|
||||
{
|
||||
ret = disk_file_remove_dir(p);
|
||||
ret = drive_file_remove_dir(p);
|
||||
}
|
||||
else if (unlink(p) < 0)
|
||||
{
|
||||
|
@ -193,7 +165,7 @@ static BOOL disk_file_remove_dir(const char* path)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void disk_file_set_fullpath(DISK_FILE* file, char* fullpath)
|
||||
static void drive_file_set_fullpath(DRIVE_FILE* file, char* fullpath)
|
||||
{
|
||||
free(file->fullpath);
|
||||
file->fullpath = fullpath;
|
||||
|
@ -205,7 +177,7 @@ static void disk_file_set_fullpath(DISK_FILE* file, char* fullpath)
|
|||
file->filename += 1;
|
||||
}
|
||||
|
||||
static BOOL disk_file_init(DISK_FILE* file, UINT32 DesiredAccess, UINT32 CreateDisposition, UINT32 CreateOptions)
|
||||
static BOOL drive_file_init(DRIVE_FILE* file, UINT32 DesiredAccess, UINT32 CreateDisposition, UINT32 CreateOptions)
|
||||
{
|
||||
struct STAT st;
|
||||
BOOL exists;
|
||||
|
@ -221,8 +193,8 @@ static BOOL disk_file_init(DISK_FILE* file, UINT32 DesiredAccess, UINT32 CreateD
|
|||
{
|
||||
file->is_dir = (S_ISDIR(st.st_mode) ? TRUE : FALSE);
|
||||
#ifndef WIN32
|
||||
if (st.st_size > (unsigned long)0x07fffffff)
|
||||
largeFile = TRUE;
|
||||
if (st.st_size > (unsigned long) 0x07FFFFFFF)
|
||||
largeFile = TRUE;
|
||||
#endif
|
||||
exists = TRUE;
|
||||
}
|
||||
|
@ -231,14 +203,14 @@ static BOOL disk_file_init(DISK_FILE* file, UINT32 DesiredAccess, UINT32 CreateD
|
|||
file->is_dir = ((CreateOptions & FILE_DIRECTORY_FILE) ? TRUE : FALSE);
|
||||
if (file->is_dir)
|
||||
{
|
||||
//Should only create the directory if the disposition allows for it
|
||||
/* Should only create the directory if the disposition allows for it */
|
||||
if ((CreateDisposition == FILE_OPEN_IF) || (CreateDisposition == FILE_CREATE))
|
||||
{
|
||||
if (mkdir(file->fullpath, mode) != 0)
|
||||
{
|
||||
file->err = errno;
|
||||
return TRUE;
|
||||
}
|
||||
if (mkdir(file->fullpath, mode) != 0)
|
||||
{
|
||||
file->err = errno;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
exists = FALSE;
|
||||
|
@ -247,6 +219,7 @@ static BOOL disk_file_init(DISK_FILE* file, UINT32 DesiredAccess, UINT32 CreateD
|
|||
if (file->is_dir)
|
||||
{
|
||||
file->dir = opendir(file->fullpath);
|
||||
|
||||
if (file->dir == NULL)
|
||||
{
|
||||
file->err = errno;
|
||||
|
@ -278,7 +251,7 @@ static BOOL disk_file_init(DISK_FILE* file, UINT32 DesiredAccess, UINT32 CreateD
|
|||
break;
|
||||
}
|
||||
|
||||
if (CreateOptions & FILE_DELETE_ON_CLOSE && DesiredAccess & DELETE)
|
||||
if ((CreateOptions & FILE_DELETE_ON_CLOSE) && (DesiredAccess & DELETE))
|
||||
{
|
||||
file->delete_pending = TRUE;
|
||||
}
|
||||
|
@ -301,6 +274,7 @@ static BOOL disk_file_init(DISK_FILE* file, UINT32 DesiredAccess, UINT32 CreateD
|
|||
}
|
||||
#endif
|
||||
file->fd = OPEN(file->fullpath, oflag, mode);
|
||||
|
||||
if (file->fd == -1)
|
||||
{
|
||||
file->err = errno;
|
||||
|
@ -311,37 +285,40 @@ static BOOL disk_file_init(DISK_FILE* file, UINT32 DesiredAccess, UINT32 CreateD
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
DISK_FILE* disk_file_new(const char* base_path, const char* path, UINT32 id,
|
||||
DRIVE_FILE* drive_file_new(const char* base_path, const char* path, UINT32 id,
|
||||
UINT32 DesiredAccess, UINT32 CreateDisposition, UINT32 CreateOptions)
|
||||
{
|
||||
DISK_FILE* file;
|
||||
DRIVE_FILE* file;
|
||||
|
||||
file = (DRIVE_FILE*) malloc(sizeof(DRIVE_FILE));
|
||||
ZeroMemory(file, sizeof(DRIVE_FILE));
|
||||
|
||||
file = xnew(DISK_FILE);
|
||||
file->id = id;
|
||||
file->basepath = (char*) base_path;
|
||||
disk_file_set_fullpath(file, disk_file_combine_fullpath(base_path, path));
|
||||
drive_file_set_fullpath(file, drive_file_combine_fullpath(base_path, path));
|
||||
file->fd = -1;
|
||||
|
||||
if (!disk_file_init(file, DesiredAccess, CreateDisposition, CreateOptions))
|
||||
if (!drive_file_init(file, DesiredAccess, CreateDisposition, CreateOptions))
|
||||
{
|
||||
disk_file_free(file);
|
||||
drive_file_free(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
void disk_file_free(DISK_FILE* file)
|
||||
void drive_file_free(DRIVE_FILE* file)
|
||||
{
|
||||
if (file->fd != -1)
|
||||
close(file->fd);
|
||||
|
||||
if (file->dir != NULL)
|
||||
closedir(file->dir);
|
||||
|
||||
if (file->delete_pending)
|
||||
{
|
||||
if (file->is_dir)
|
||||
disk_file_remove_dir(file->fullpath);
|
||||
drive_file_remove_dir(file->fullpath);
|
||||
else
|
||||
unlink(file->fullpath);
|
||||
}
|
||||
|
@ -351,7 +328,7 @@ void disk_file_free(DISK_FILE* file)
|
|||
free(file);
|
||||
}
|
||||
|
||||
BOOL disk_file_seek(DISK_FILE* file, UINT64 Offset)
|
||||
BOOL drive_file_seek(DRIVE_FILE* file, UINT64 Offset)
|
||||
{
|
||||
if (file->is_dir || file->fd == -1)
|
||||
return FALSE;
|
||||
|
@ -362,7 +339,7 @@ BOOL disk_file_seek(DISK_FILE* file, UINT64 Offset)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL disk_file_read(DISK_FILE* file, BYTE* buffer, UINT32* Length)
|
||||
BOOL drive_file_read(DRIVE_FILE* file, BYTE* buffer, UINT32* Length)
|
||||
{
|
||||
ssize_t r;
|
||||
|
||||
|
@ -370,14 +347,16 @@ BOOL disk_file_read(DISK_FILE* file, BYTE* buffer, UINT32* Length)
|
|||
return FALSE;
|
||||
|
||||
r = read(file->fd, buffer, *Length);
|
||||
|
||||
if (r < 0)
|
||||
return FALSE;
|
||||
*Length = (UINT32)r;
|
||||
|
||||
*Length = (UINT32) r;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL disk_file_write(DISK_FILE* file, BYTE* buffer, UINT32 Length)
|
||||
BOOL drive_file_write(DRIVE_FILE* file, BYTE* buffer, UINT32 Length)
|
||||
{
|
||||
ssize_t r;
|
||||
|
||||
|
@ -387,8 +366,10 @@ BOOL disk_file_write(DISK_FILE* file, BYTE* buffer, UINT32 Length)
|
|||
while (Length > 0)
|
||||
{
|
||||
r = write(file->fd, buffer, Length);
|
||||
|
||||
if (r == -1)
|
||||
return FALSE;
|
||||
|
||||
Length -= r;
|
||||
buffer += r;
|
||||
}
|
||||
|
@ -396,7 +377,7 @@ BOOL disk_file_write(DISK_FILE* file, BYTE* buffer, UINT32 Length)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL disk_file_query_information(DISK_FILE* file, UINT32 FsInformationClass, STREAM* output)
|
||||
BOOL drive_file_query_information(DRIVE_FILE* file, UINT32 FsInformationClass, STREAM* output)
|
||||
{
|
||||
struct STAT st;
|
||||
|
||||
|
@ -405,6 +386,7 @@ BOOL disk_file_query_information(DISK_FILE* file, UINT32 FsInformationClass, STR
|
|||
stream_write_UINT32(output, 0); /* Length */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (FsInformationClass)
|
||||
{
|
||||
case FileBasicInformation:
|
||||
|
@ -447,7 +429,7 @@ BOOL disk_file_query_information(DISK_FILE* file, UINT32 FsInformationClass, STR
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL disk_file_set_information(DISK_FILE* file, UINT32 FsInformationClass, UINT32 Length, STREAM* input)
|
||||
BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UINT32 Length, STREAM* input)
|
||||
{
|
||||
char* s;
|
||||
|
||||
|
@ -522,14 +504,14 @@ BOOL disk_file_set_information(DISK_FILE* file, UINT32 FsInformationClass, UINT3
|
|||
|
||||
freerdp_UnicodeToAsciiAlloc((WCHAR*) stream_get_tail(input), &s, FileNameLength / 2);
|
||||
|
||||
fullpath = disk_file_combine_fullpath(file->basepath, s);
|
||||
fullpath = drive_file_combine_fullpath(file->basepath, s);
|
||||
free(s);
|
||||
|
||||
/* TODO rename does not work on win32 */
|
||||
if (rename(file->fullpath, fullpath) == 0)
|
||||
{
|
||||
DEBUG_SVC("renamed %s to %s", file->fullpath, fullpath);
|
||||
disk_file_set_fullpath(file, fullpath);
|
||||
drive_file_set_fullpath(file, fullpath);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -548,7 +530,7 @@ BOOL disk_file_set_information(DISK_FILE* file, UINT32 FsInformationClass, UINT3
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL disk_file_query_directory(DISK_FILE* file, UINT32 FsInformationClass, BYTE InitialQuery,
|
||||
BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYTE InitialQuery,
|
||||
const char* path, STREAM* output)
|
||||
{
|
||||
int length;
|
||||
|
@ -586,9 +568,11 @@ BOOL disk_file_query_directory(DISK_FILE* file, UINT32 FsInformationClass, BYTE
|
|||
if (ent == NULL)
|
||||
continue;
|
||||
|
||||
if (disk_file_wildcard_match(file->pattern, ent->d_name))
|
||||
if (FilePatternMatchA(ent->d_name, file->pattern))
|
||||
break;
|
||||
} while (ent);
|
||||
|
||||
}
|
||||
while (ent);
|
||||
}
|
||||
else
|
||||
{
|
|
@ -19,8 +19,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __DISK_FILE_H
|
||||
#define __DISK_FILE_H
|
||||
#ifndef FREERDP_CHANNEL_DRIVE_FILE_H
|
||||
#define FREERDP_CHANNEL_DRIVE_FILE_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
@ -84,8 +84,9 @@ typedef UINT32 mode_t;
|
|||
(_f->delete_pending ? FILE_ATTRIBUTE_TEMPORARY : 0) | \
|
||||
(st.st_mode & S_IWUSR ? 0 : FILE_ATTRIBUTE_READONLY))
|
||||
|
||||
typedef struct _DISK_FILE DISK_FILE;
|
||||
struct _DISK_FILE
|
||||
typedef struct _DRIVE_FILE DRIVE_FILE;
|
||||
|
||||
struct _DRIVE_FILE
|
||||
{
|
||||
UINT32 id;
|
||||
BOOL is_dir;
|
||||
|
@ -99,16 +100,16 @@ struct _DISK_FILE
|
|||
BOOL delete_pending;
|
||||
};
|
||||
|
||||
DISK_FILE* disk_file_new(const char* base_path, const char* path, UINT32 id,
|
||||
DRIVE_FILE* drive_file_new(const char* base_path, const char* path, UINT32 id,
|
||||
UINT32 DesiredAccess, UINT32 CreateDisposition, UINT32 CreateOptions);
|
||||
void disk_file_free(DISK_FILE* file);
|
||||
void drive_file_free(DRIVE_FILE* file);
|
||||
|
||||
BOOL disk_file_seek(DISK_FILE* file, UINT64 Offset);
|
||||
BOOL disk_file_read(DISK_FILE* file, BYTE* buffer, UINT32* Length);
|
||||
BOOL disk_file_write(DISK_FILE* file, BYTE* buffer, UINT32 Length);
|
||||
BOOL disk_file_query_information(DISK_FILE* file, UINT32 FsInformationClass, STREAM* output);
|
||||
BOOL disk_file_set_information(DISK_FILE* file, UINT32 FsInformationClass, UINT32 Length, STREAM* input);
|
||||
BOOL disk_file_query_directory(DISK_FILE* file, UINT32 FsInformationClass, BYTE InitialQuery,
|
||||
BOOL drive_file_seek(DRIVE_FILE* file, UINT64 Offset);
|
||||
BOOL drive_file_read(DRIVE_FILE* file, BYTE* buffer, UINT32* Length);
|
||||
BOOL drive_file_write(DRIVE_FILE* file, BYTE* buffer, UINT32 Length);
|
||||
BOOL drive_file_query_information(DRIVE_FILE* file, UINT32 FsInformationClass, STREAM* output);
|
||||
BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UINT32 Length, STREAM* input);
|
||||
BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYTE InitialQuery,
|
||||
const char* path, STREAM* output);
|
||||
|
||||
#endif /* __DISK_FILE_H */
|
||||
#endif /* FREERDP_CHANNEL_DRIVE_FILE_H */
|
|
@ -35,7 +35,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/unicode.h>
|
||||
#include <freerdp/utils/list.h>
|
||||
|
@ -47,11 +46,11 @@
|
|||
#include <winpr/thread.h>
|
||||
#include <winpr/interlocked.h>
|
||||
|
||||
#include "disk_file.h"
|
||||
#include "drive_file.h"
|
||||
|
||||
typedef struct _DISK_DEVICE DISK_DEVICE;
|
||||
typedef struct _DRIVE_DEVICE DRIVE_DEVICE;
|
||||
|
||||
struct _DISK_DEVICE
|
||||
struct _DRIVE_DEVICE
|
||||
{
|
||||
DEVICE device;
|
||||
|
||||
|
@ -66,7 +65,7 @@ struct _DISK_DEVICE
|
|||
DEVMAN* devman;
|
||||
};
|
||||
|
||||
static UINT32 disk_map_posix_err(int fs_errno)
|
||||
static UINT32 drive_map_posix_err(int fs_errno)
|
||||
{
|
||||
UINT32 rc;
|
||||
|
||||
|
@ -101,14 +100,14 @@ static UINT32 disk_map_posix_err(int fs_errno)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static DISK_FILE* disk_get_file_by_id(DISK_DEVICE* disk, UINT32 id)
|
||||
static DRIVE_FILE* drive_get_file_by_id(DRIVE_DEVICE* disk, UINT32 id)
|
||||
{
|
||||
LIST_ITEM* item;
|
||||
DISK_FILE* file;
|
||||
DRIVE_FILE* file;
|
||||
|
||||
for (item = disk->files->head; item; item = item->next)
|
||||
{
|
||||
file = (DISK_FILE*) item->data;
|
||||
file = (DRIVE_FILE*) item->data;
|
||||
|
||||
if (file->id == id)
|
||||
return file;
|
||||
|
@ -117,11 +116,11 @@ static DISK_FILE* disk_get_file_by_id(DISK_DEVICE* disk, UINT32 id)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void disk_process_irp_create(DISK_DEVICE* disk, IRP* irp)
|
||||
static void drive_process_irp_create(DRIVE_DEVICE* disk, IRP* irp)
|
||||
{
|
||||
char* path;
|
||||
UINT32 FileId;
|
||||
DISK_FILE* file;
|
||||
DRIVE_FILE* file;
|
||||
BYTE Information;
|
||||
UINT32 DesiredAccess;
|
||||
UINT32 CreateDisposition;
|
||||
|
@ -138,7 +137,7 @@ static void disk_process_irp_create(DISK_DEVICE* disk, IRP* irp)
|
|||
|
||||
FileId = irp->devman->id_sequence++;
|
||||
|
||||
file = disk_file_new(disk->path, path, FileId,
|
||||
file = drive_file_new(disk->path, path, FileId,
|
||||
DesiredAccess, CreateDisposition, CreateOptions);
|
||||
|
||||
if (file == NULL)
|
||||
|
@ -155,8 +154,8 @@ static void disk_process_irp_create(DISK_DEVICE* disk, IRP* irp)
|
|||
Information = 0;
|
||||
|
||||
/* map errno to windows result */
|
||||
irp->IoStatus = disk_map_posix_err(file->err);
|
||||
disk_file_free(file);
|
||||
irp->IoStatus = drive_map_posix_err(file->err);
|
||||
drive_file_free(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -191,11 +190,11 @@ static void disk_process_irp_create(DISK_DEVICE* disk, IRP* irp)
|
|||
irp->Complete(irp);
|
||||
}
|
||||
|
||||
static void disk_process_irp_close(DISK_DEVICE* disk, IRP* irp)
|
||||
static void drive_process_irp_close(DRIVE_DEVICE* disk, IRP* irp)
|
||||
{
|
||||
DISK_FILE* file;
|
||||
DRIVE_FILE* file;
|
||||
|
||||
file = disk_get_file_by_id(disk, irp->FileId);
|
||||
file = drive_get_file_by_id(disk, irp->FileId);
|
||||
|
||||
if (file == NULL)
|
||||
{
|
||||
|
@ -208,7 +207,7 @@ static void disk_process_irp_close(DISK_DEVICE* disk, IRP* irp)
|
|||
DEBUG_SVC("%s(%d) closed.", file->fullpath, file->id);
|
||||
|
||||
list_remove(disk->files, file);
|
||||
disk_file_free(file);
|
||||
drive_file_free(file);
|
||||
}
|
||||
|
||||
stream_write_zero(irp->output, 5); /* Padding(5) */
|
||||
|
@ -216,9 +215,9 @@ static void disk_process_irp_close(DISK_DEVICE* disk, IRP* irp)
|
|||
irp->Complete(irp);
|
||||
}
|
||||
|
||||
static void disk_process_irp_read(DISK_DEVICE* disk, IRP* irp)
|
||||
static void drive_process_irp_read(DRIVE_DEVICE* disk, IRP* irp)
|
||||
{
|
||||
DISK_FILE* file;
|
||||
DRIVE_FILE* file;
|
||||
UINT32 Length;
|
||||
UINT64 Offset;
|
||||
BYTE* buffer = NULL;
|
||||
|
@ -226,7 +225,7 @@ static void disk_process_irp_read(DISK_DEVICE* disk, IRP* irp)
|
|||
stream_read_UINT32(irp->input, Length);
|
||||
stream_read_UINT64(irp->input, Offset);
|
||||
|
||||
file = disk_get_file_by_id(disk, irp->FileId);
|
||||
file = drive_get_file_by_id(disk, irp->FileId);
|
||||
|
||||
if (file == NULL)
|
||||
{
|
||||
|
@ -235,7 +234,7 @@ static void disk_process_irp_read(DISK_DEVICE* disk, IRP* irp)
|
|||
|
||||
DEBUG_WARN("FileId %d not valid.", irp->FileId);
|
||||
}
|
||||
else if (!disk_file_seek(file, Offset))
|
||||
else if (!drive_file_seek(file, Offset))
|
||||
{
|
||||
irp->IoStatus = STATUS_UNSUCCESSFUL;
|
||||
Length = 0;
|
||||
|
@ -245,7 +244,7 @@ static void disk_process_irp_read(DISK_DEVICE* disk, IRP* irp)
|
|||
else
|
||||
{
|
||||
buffer = (BYTE*) malloc(Length);
|
||||
if (!disk_file_read(file, buffer, &Length))
|
||||
if (!drive_file_read(file, buffer, &Length))
|
||||
{
|
||||
irp->IoStatus = STATUS_UNSUCCESSFUL;
|
||||
free(buffer);
|
||||
|
@ -273,9 +272,9 @@ static void disk_process_irp_read(DISK_DEVICE* disk, IRP* irp)
|
|||
irp->Complete(irp);
|
||||
}
|
||||
|
||||
static void disk_process_irp_write(DISK_DEVICE* disk, IRP* irp)
|
||||
static void drive_process_irp_write(DRIVE_DEVICE* disk, IRP* irp)
|
||||
{
|
||||
DISK_FILE* file;
|
||||
DRIVE_FILE* file;
|
||||
UINT32 Length;
|
||||
UINT64 Offset;
|
||||
|
||||
|
@ -283,7 +282,7 @@ static void disk_process_irp_write(DISK_DEVICE* disk, IRP* irp)
|
|||
stream_read_UINT64(irp->input, Offset);
|
||||
stream_seek(irp->input, 20); /* Padding */
|
||||
|
||||
file = disk_get_file_by_id(disk, irp->FileId);
|
||||
file = drive_get_file_by_id(disk, irp->FileId);
|
||||
|
||||
if (file == NULL)
|
||||
{
|
||||
|
@ -292,14 +291,14 @@ static void disk_process_irp_write(DISK_DEVICE* disk, IRP* irp)
|
|||
|
||||
DEBUG_WARN("FileId %d not valid.", irp->FileId);
|
||||
}
|
||||
else if (!disk_file_seek(file, Offset))
|
||||
else if (!drive_file_seek(file, Offset))
|
||||
{
|
||||
irp->IoStatus = STATUS_UNSUCCESSFUL;
|
||||
Length = 0;
|
||||
|
||||
DEBUG_WARN("seek %s(%d) failed.", file->fullpath, file->id);
|
||||
}
|
||||
else if (!disk_file_write(file, stream_get_tail(irp->input), Length))
|
||||
else if (!drive_file_write(file, stream_get_tail(irp->input), Length))
|
||||
{
|
||||
irp->IoStatus = STATUS_UNSUCCESSFUL;
|
||||
Length = 0;
|
||||
|
@ -317,14 +316,14 @@ static void disk_process_irp_write(DISK_DEVICE* disk, IRP* irp)
|
|||
irp->Complete(irp);
|
||||
}
|
||||
|
||||
static void disk_process_irp_query_information(DISK_DEVICE* disk, IRP* irp)
|
||||
static void drive_process_irp_query_information(DRIVE_DEVICE* disk, IRP* irp)
|
||||
{
|
||||
DISK_FILE* file;
|
||||
DRIVE_FILE* file;
|
||||
UINT32 FsInformationClass;
|
||||
|
||||
stream_read_UINT32(irp->input, FsInformationClass);
|
||||
|
||||
file = disk_get_file_by_id(disk, irp->FileId);
|
||||
file = drive_get_file_by_id(disk, irp->FileId);
|
||||
|
||||
if (file == NULL)
|
||||
{
|
||||
|
@ -332,7 +331,7 @@ static void disk_process_irp_query_information(DISK_DEVICE* disk, IRP* irp)
|
|||
|
||||
DEBUG_WARN("FileId %d not valid.", irp->FileId);
|
||||
}
|
||||
else if (!disk_file_query_information(file, FsInformationClass, irp->output))
|
||||
else if (!drive_file_query_information(file, FsInformationClass, irp->output))
|
||||
{
|
||||
irp->IoStatus = STATUS_UNSUCCESSFUL;
|
||||
|
||||
|
@ -346,9 +345,9 @@ static void disk_process_irp_query_information(DISK_DEVICE* disk, IRP* irp)
|
|||
irp->Complete(irp);
|
||||
}
|
||||
|
||||
static void disk_process_irp_set_information(DISK_DEVICE* disk, IRP* irp)
|
||||
static void drive_process_irp_set_information(DRIVE_DEVICE* disk, IRP* irp)
|
||||
{
|
||||
DISK_FILE* file;
|
||||
DRIVE_FILE* file;
|
||||
UINT32 FsInformationClass;
|
||||
UINT32 Length;
|
||||
|
||||
|
@ -356,7 +355,7 @@ static void disk_process_irp_set_information(DISK_DEVICE* disk, IRP* irp)
|
|||
stream_read_UINT32(irp->input, Length);
|
||||
stream_seek(irp->input, 24); /* Padding */
|
||||
|
||||
file = disk_get_file_by_id(disk, irp->FileId);
|
||||
file = drive_get_file_by_id(disk, irp->FileId);
|
||||
|
||||
if (file == NULL)
|
||||
{
|
||||
|
@ -364,7 +363,7 @@ static void disk_process_irp_set_information(DISK_DEVICE* disk, IRP* irp)
|
|||
|
||||
DEBUG_WARN("FileId %d not valid.", irp->FileId);
|
||||
}
|
||||
else if (!disk_file_set_information(file, FsInformationClass, Length, irp->input))
|
||||
else if (!drive_file_set_information(file, FsInformationClass, Length, irp->input))
|
||||
{
|
||||
irp->IoStatus = STATUS_UNSUCCESSFUL;
|
||||
|
||||
|
@ -380,7 +379,7 @@ static void disk_process_irp_set_information(DISK_DEVICE* disk, IRP* irp)
|
|||
irp->Complete(irp);
|
||||
}
|
||||
|
||||
static void disk_process_irp_query_volume_information(DISK_DEVICE* disk, IRP* irp)
|
||||
static void drive_process_irp_query_volume_information(DRIVE_DEVICE* disk, IRP* irp)
|
||||
{
|
||||
UINT32 FsInformationClass;
|
||||
STREAM* output = irp->output;
|
||||
|
@ -466,10 +465,10 @@ static void disk_process_irp_query_volume_information(DISK_DEVICE* disk, IRP* ir
|
|||
irp->Complete(irp);
|
||||
}
|
||||
|
||||
static void disk_process_irp_query_directory(DISK_DEVICE* disk, IRP* irp)
|
||||
static void drive_process_irp_query_directory(DRIVE_DEVICE* disk, IRP* irp)
|
||||
{
|
||||
char* path;
|
||||
DISK_FILE* file;
|
||||
DRIVE_FILE* file;
|
||||
BYTE InitialQuery;
|
||||
UINT32 PathLength;
|
||||
UINT32 FsInformationClass;
|
||||
|
@ -481,7 +480,7 @@ static void disk_process_irp_query_directory(DISK_DEVICE* disk, IRP* irp)
|
|||
|
||||
freerdp_UnicodeToAsciiAlloc((WCHAR*) stream_get_tail(irp->input), &path, PathLength / 2);
|
||||
|
||||
file = disk_get_file_by_id(disk, irp->FileId);
|
||||
file = drive_get_file_by_id(disk, irp->FileId);
|
||||
|
||||
if (file == NULL)
|
||||
{
|
||||
|
@ -489,7 +488,7 @@ static void disk_process_irp_query_directory(DISK_DEVICE* disk, IRP* irp)
|
|||
stream_write_UINT32(irp->output, 0); /* Length */
|
||||
DEBUG_WARN("FileId %d not valid.", irp->FileId);
|
||||
}
|
||||
else if (!disk_file_query_directory(file, FsInformationClass, InitialQuery, path, irp->output))
|
||||
else if (!drive_file_query_directory(file, FsInformationClass, InitialQuery, path, irp->output))
|
||||
{
|
||||
irp->IoStatus = STATUS_NO_MORE_FILES;
|
||||
}
|
||||
|
@ -499,12 +498,12 @@ static void disk_process_irp_query_directory(DISK_DEVICE* disk, IRP* irp)
|
|||
irp->Complete(irp);
|
||||
}
|
||||
|
||||
static void disk_process_irp_directory_control(DISK_DEVICE* disk, IRP* irp)
|
||||
static void drive_process_irp_directory_control(DRIVE_DEVICE* disk, IRP* irp)
|
||||
{
|
||||
switch (irp->MinorFunction)
|
||||
{
|
||||
case IRP_MN_QUERY_DIRECTORY:
|
||||
disk_process_irp_query_directory(disk, irp);
|
||||
drive_process_irp_query_directory(disk, irp);
|
||||
break;
|
||||
|
||||
case IRP_MN_NOTIFY_CHANGE_DIRECTORY: /* TODO */
|
||||
|
@ -520,52 +519,52 @@ static void disk_process_irp_directory_control(DISK_DEVICE* disk, IRP* irp)
|
|||
}
|
||||
}
|
||||
|
||||
static void disk_process_irp_device_control(DISK_DEVICE* disk, IRP* irp)
|
||||
static void drive_process_irp_device_control(DRIVE_DEVICE* disk, IRP* irp)
|
||||
{
|
||||
stream_write_UINT32(irp->output, 0); /* OutputBufferLength */
|
||||
irp->Complete(irp);
|
||||
}
|
||||
|
||||
static void disk_process_irp(DISK_DEVICE* disk, IRP* irp)
|
||||
static void drive_process_irp(DRIVE_DEVICE* disk, IRP* irp)
|
||||
{
|
||||
irp->IoStatus = STATUS_SUCCESS;
|
||||
|
||||
switch (irp->MajorFunction)
|
||||
{
|
||||
case IRP_MJ_CREATE:
|
||||
disk_process_irp_create(disk, irp);
|
||||
drive_process_irp_create(disk, irp);
|
||||
break;
|
||||
|
||||
case IRP_MJ_CLOSE:
|
||||
disk_process_irp_close(disk, irp);
|
||||
drive_process_irp_close(disk, irp);
|
||||
break;
|
||||
|
||||
case IRP_MJ_READ:
|
||||
disk_process_irp_read(disk, irp);
|
||||
drive_process_irp_read(disk, irp);
|
||||
break;
|
||||
|
||||
case IRP_MJ_WRITE:
|
||||
disk_process_irp_write(disk, irp);
|
||||
drive_process_irp_write(disk, irp);
|
||||
break;
|
||||
|
||||
case IRP_MJ_QUERY_INFORMATION:
|
||||
disk_process_irp_query_information(disk, irp);
|
||||
drive_process_irp_query_information(disk, irp);
|
||||
break;
|
||||
|
||||
case IRP_MJ_SET_INFORMATION:
|
||||
disk_process_irp_set_information(disk, irp);
|
||||
drive_process_irp_set_information(disk, irp);
|
||||
break;
|
||||
|
||||
case IRP_MJ_QUERY_VOLUME_INFORMATION:
|
||||
disk_process_irp_query_volume_information(disk, irp);
|
||||
drive_process_irp_query_volume_information(disk, irp);
|
||||
break;
|
||||
|
||||
case IRP_MJ_DIRECTORY_CONTROL:
|
||||
disk_process_irp_directory_control(disk, irp);
|
||||
drive_process_irp_directory_control(disk, irp);
|
||||
break;
|
||||
|
||||
case IRP_MJ_DEVICE_CONTROL:
|
||||
disk_process_irp_device_control(disk, irp);
|
||||
drive_process_irp_device_control(disk, irp);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -576,7 +575,7 @@ static void disk_process_irp(DISK_DEVICE* disk, IRP* irp)
|
|||
}
|
||||
}
|
||||
|
||||
static void disk_process_irp_list(DISK_DEVICE* disk)
|
||||
static void drive_process_irp_list(DRIVE_DEVICE* disk)
|
||||
{
|
||||
IRP* irp;
|
||||
|
||||
|
@ -590,13 +589,13 @@ static void disk_process_irp_list(DISK_DEVICE* disk)
|
|||
if (irp == NULL)
|
||||
break;
|
||||
|
||||
disk_process_irp(disk, irp);
|
||||
drive_process_irp(disk, irp);
|
||||
}
|
||||
}
|
||||
|
||||
static void* disk_thread_func(void* arg)
|
||||
static void* drive_thread_func(void* arg)
|
||||
{
|
||||
DISK_DEVICE* disk = (DISK_DEVICE*) arg;
|
||||
DRIVE_DEVICE* disk = (DRIVE_DEVICE*) arg;
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
@ -606,26 +605,26 @@ static void* disk_thread_func(void* arg)
|
|||
break;
|
||||
|
||||
ResetEvent(disk->irpEvent);
|
||||
disk_process_irp_list(disk);
|
||||
drive_process_irp_list(disk);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void disk_irp_request(DEVICE* device, IRP* irp)
|
||||
static void drive_irp_request(DEVICE* device, IRP* irp)
|
||||
{
|
||||
DISK_DEVICE* disk = (DISK_DEVICE*) device;
|
||||
DRIVE_DEVICE* disk = (DRIVE_DEVICE*) device;
|
||||
|
||||
InterlockedPushEntrySList(disk->pIrpList, &(irp->ItemEntry));
|
||||
|
||||
SetEvent(disk->irpEvent);
|
||||
}
|
||||
|
||||
static void disk_free(DEVICE* device)
|
||||
static void drive_free(DEVICE* device)
|
||||
{
|
||||
IRP* irp;
|
||||
DISK_FILE* file;
|
||||
DISK_DEVICE* disk = (DISK_DEVICE*) device;
|
||||
DRIVE_FILE* file;
|
||||
DRIVE_DEVICE* disk = (DRIVE_DEVICE*) device;
|
||||
|
||||
SetEvent(disk->stopEvent);
|
||||
CloseHandle(disk->thread);
|
||||
|
@ -636,17 +635,18 @@ static void disk_free(DEVICE* device)
|
|||
|
||||
_aligned_free(disk->pIrpList);
|
||||
|
||||
while ((file = (DISK_FILE*) list_dequeue(disk->files)) != NULL)
|
||||
disk_file_free(file);
|
||||
while ((file = (DRIVE_FILE*) list_dequeue(disk->files)) != NULL)
|
||||
drive_file_free(file);
|
||||
|
||||
list_free(disk->files);
|
||||
|
||||
free(disk);
|
||||
}
|
||||
|
||||
void disk_register_disk_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, char* name, char* path)
|
||||
void drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, char* name, char* path)
|
||||
{
|
||||
int i, length;
|
||||
DISK_DEVICE* disk;
|
||||
DRIVE_DEVICE* disk;
|
||||
|
||||
#ifdef WIN32
|
||||
/*
|
||||
|
@ -664,12 +664,13 @@ void disk_register_disk_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, char* na
|
|||
|
||||
if (name[0] && path[0])
|
||||
{
|
||||
disk = xnew(DISK_DEVICE);
|
||||
disk = (DRIVE_DEVICE*) malloc(sizeof(DRIVE_DEVICE));
|
||||
ZeroMemory(disk, sizeof(DRIVE_DEVICE));
|
||||
|
||||
disk->device.type = RDPDR_DTYP_FILESYSTEM;
|
||||
disk->device.name = name;
|
||||
disk->device.IRPRequest = disk_irp_request;
|
||||
disk->device.Free = disk_free;
|
||||
disk->device.IRPRequest = drive_irp_request;
|
||||
disk->device.Free = drive_free;
|
||||
|
||||
length = strlen(name);
|
||||
disk->device.data = stream_new(length + 1);
|
||||
|
@ -685,7 +686,7 @@ void disk_register_disk_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, char* na
|
|||
|
||||
disk->irpEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
disk->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
disk->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) disk_thread_func, disk, CREATE_SUSPENDED, NULL);
|
||||
disk->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) drive_thread_func, disk, CREATE_SUSPENDED, NULL);
|
||||
|
||||
pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) disk);
|
||||
|
||||
|
@ -694,31 +695,33 @@ void disk_register_disk_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, char* na
|
|||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define DeviceServiceEntry disk_DeviceServiceEntry
|
||||
#define DeviceServiceEntry drive_DeviceServiceEntry
|
||||
#endif
|
||||
|
||||
const int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
char* name;
|
||||
char* path;
|
||||
RDPDR_DRIVE* drive;
|
||||
#ifdef WIN32
|
||||
char* dev;
|
||||
int len;
|
||||
char devlist[512], buf[512];
|
||||
#endif
|
||||
|
||||
name = (char*) pEntryPoints->plugin_data->data[1];
|
||||
path = (char*) pEntryPoints->plugin_data->data[2];
|
||||
drive = (RDPDR_DRIVE*) pEntryPoints->device;
|
||||
name = drive->Name;
|
||||
path = drive->Path;
|
||||
|
||||
#ifndef WIN32
|
||||
disk_register_disk_path(pEntryPoints, name, path);
|
||||
drive_register_drive_path(pEntryPoints, name, path);
|
||||
#else
|
||||
/* Special case: path[0] == '*' -> export all drives */
|
||||
/* Special case: path[0] == '%' -> user home dir */
|
||||
if( path[0] == '%' )
|
||||
{
|
||||
_snprintf(buf, sizeof(buf), "%s\\", getenv("USERPROFILE"));
|
||||
disk_register_disk_path(pEntryPoints, name, _strdup(buf));
|
||||
drive_register_drive_path(pEntryPoints, name, _strdup(buf));
|
||||
}
|
||||
else if( path[0] == '*' )
|
||||
{
|
||||
|
@ -738,13 +741,13 @@ const int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
|||
buf[len + 1] = dev[0];
|
||||
buf[len + 2] = 0;
|
||||
buf[len + 3] = 0;
|
||||
disk_register_disk_path(pEntryPoints, _strdup(buf), _strdup(dev));
|
||||
drive_register_drive_path(pEntryPoints, _strdup(buf), _strdup(dev));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
disk_register_disk_path(pEntryPoints, name, path);
|
||||
drive_register_drive_path(pEntryPoints, name, path);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
LIBRARY "disk"
|
||||
LIBRARY "drive"
|
||||
EXPORTS
|
||||
DeviceServiceEntry @1
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* statvfs emulation für windows
|
||||
* statvfs emulation for Windows
|
||||
*
|
||||
* Copyright 2012 Gerald Richter
|
||||
*
|
|
@ -13,10 +13,6 @@ if(ANDROID)
|
|||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
endif()
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "parallel" TYPE "device"
|
||||
DESCRIPTION "Parallel Port Virtual Channel Extension"
|
||||
SPECIFICATIONS "[MS-RDPESP]"
|
||||
|
|
|
@ -53,7 +53,6 @@
|
|||
#include <freerdp/constants.h>
|
||||
#include <freerdp/utils/list.h>
|
||||
#include <freerdp/utils/thread.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/unicode.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
@ -316,14 +315,17 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
|||
char* name;
|
||||
char* path;
|
||||
int i, length;
|
||||
RDPDR_PARALLEL* device;
|
||||
PARALLEL_DEVICE* parallel;
|
||||
|
||||
name = (char*) pEntryPoints->plugin_data->data[1];
|
||||
path = (char*) pEntryPoints->plugin_data->data[2];
|
||||
device = (RDPDR_PARALLEL*) pEntryPoints->device;
|
||||
name = device->Name;
|
||||
path = device->Path;
|
||||
|
||||
if (name[0] && path[0])
|
||||
{
|
||||
parallel = xnew(PARALLEL_DEVICE);
|
||||
parallel = (PARALLEL_DEVICE*) malloc(sizeof(PARALLEL_DEVICE));
|
||||
ZeroMemory(parallel, sizeof(PARALLEL_DEVICE));
|
||||
|
||||
parallel->device.type = RDPDR_DTYP_PARALLEL;
|
||||
parallel->device.name = name;
|
||||
|
|
|
@ -14,10 +14,6 @@ else()
|
|||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
endif()
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "printer" TYPE "device"
|
||||
DESCRIPTION "Print Virtual Channel Extension"
|
||||
SPECIFICATIONS "[MS-RDPEPC]"
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
#include <freerdp/channels/rdpdr.h>
|
||||
|
||||
|
@ -79,36 +78,39 @@ static void printer_cups_get_printjob_name(char* buf, int size)
|
|||
|
||||
static void printer_cups_write_printjob(rdpPrintJob* printjob, BYTE* data, int size)
|
||||
{
|
||||
rdpCupsPrintJob* cups_printjob = (rdpCupsPrintJob*)printjob;
|
||||
rdpCupsPrintJob* cups_printjob = (rdpCupsPrintJob*) printjob;
|
||||
|
||||
#ifndef _CUPS_API_1_4
|
||||
|
||||
{
|
||||
FILE* fp;
|
||||
|
||||
fp = fopen((const char*)cups_printjob->printjob_object, "a+b");
|
||||
fp = fopen((const char*) cups_printjob->printjob_object, "a+b");
|
||||
|
||||
if (fp == NULL)
|
||||
{
|
||||
DEBUG_WARN("failed to open file %s", (char*)cups_printjob->printjob_object);
|
||||
DEBUG_WARN("failed to open file %s", (char*) cups_printjob->printjob_object);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fwrite(data, 1, size, fp) < size)
|
||||
{
|
||||
DEBUG_WARN("failed to write file %s", (char*)cups_printjob->printjob_object);
|
||||
DEBUG_WARN("failed to write file %s", (char*) cups_printjob->printjob_object);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
cupsWriteRequestData((http_t*)cups_printjob->printjob_object, (const char*)data, size);
|
||||
cupsWriteRequestData((http_t*) cups_printjob->printjob_object, (const char*) data, size);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static void printer_cups_close_printjob(rdpPrintJob* printjob)
|
||||
{
|
||||
rdpCupsPrintJob* cups_printjob = (rdpCupsPrintJob*)printjob;
|
||||
rdpCupsPrintJob* cups_printjob = (rdpCupsPrintJob*) printjob;
|
||||
|
||||
#ifndef _CUPS_API_1_4
|
||||
|
||||
|
@ -116,35 +118,38 @@ static void printer_cups_close_printjob(rdpPrintJob* printjob)
|
|||
char buf[100];
|
||||
|
||||
printer_cups_get_printjob_name(buf, sizeof(buf));
|
||||
if (cupsPrintFile(printjob->printer->name, (const char *)cups_printjob->printjob_object, buf, 0, NULL) == 0)
|
||||
|
||||
if (cupsPrintFile(printjob->printer->name, (const char*) cups_printjob->printjob_object, buf, 0, NULL) == 0)
|
||||
{
|
||||
DEBUG_WARN("cupsPrintFile: %s", cupsLastErrorString());
|
||||
}
|
||||
|
||||
unlink(cups_printjob->printjob_object);
|
||||
free(cups_printjob->printjob_object);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
cupsFinishDocument((http_t*)cups_printjob->printjob_object, printjob->printer->name);
|
||||
cupsFinishDocument((http_t*) cups_printjob->printjob_object, printjob->printer->name);
|
||||
cups_printjob->printjob_id = 0;
|
||||
httpClose((http_t*)cups_printjob->printjob_object);
|
||||
httpClose((http_t*) cups_printjob->printjob_object);
|
||||
|
||||
#endif
|
||||
|
||||
((rdpCupsPrinter*)printjob->printer)->printjob = NULL;
|
||||
((rdpCupsPrinter*) printjob->printer)->printjob = NULL;
|
||||
free(cups_printjob) ;
|
||||
}
|
||||
|
||||
static rdpPrintJob* printer_cups_create_printjob(rdpPrinter* printer, UINT32 id)
|
||||
{
|
||||
rdpCupsPrinter* cups_printer = (rdpCupsPrinter*)printer;
|
||||
rdpCupsPrinter* cups_printer = (rdpCupsPrinter*) printer;
|
||||
rdpCupsPrintJob* cups_printjob;
|
||||
|
||||
if (cups_printer->printjob != NULL)
|
||||
return NULL;
|
||||
|
||||
cups_printjob = xnew(rdpCupsPrintJob);
|
||||
cups_printjob = (rdpCupsPrintJob*) malloc(sizeof(rdpCupsPrintJob));
|
||||
ZeroMemory(cups_printjob, sizeof(rdpCupsPrintJob));
|
||||
|
||||
cups_printjob->printjob.id = id;
|
||||
cups_printjob->printjob.printer = printer;
|
||||
|
@ -161,6 +166,7 @@ static rdpPrintJob* printer_cups_create_printjob(rdpPrinter* printer, UINT32 id)
|
|||
char buf[100];
|
||||
|
||||
cups_printjob->printjob_object = httpConnectEncrypt(cupsServer(), ippPort(), HTTP_ENCRYPT_IF_REQUESTED);
|
||||
|
||||
if (cups_printjob->printjob_object == NULL)
|
||||
{
|
||||
DEBUG_WARN("httpConnectEncrypt: %s", cupsLastErrorString());
|
||||
|
@ -169,19 +175,19 @@ static rdpPrintJob* printer_cups_create_printjob(rdpPrinter* printer, UINT32 id)
|
|||
}
|
||||
|
||||
printer_cups_get_printjob_name(buf, sizeof(buf));
|
||||
cups_printjob->printjob_id = cupsCreateJob((http_t*)cups_printjob->printjob_object,
|
||||
cups_printjob->printjob_id = cupsCreateJob((http_t*) cups_printjob->printjob_object,
|
||||
printer->name, buf, 0, NULL);
|
||||
|
||||
if (cups_printjob->printjob_id == 0)
|
||||
{
|
||||
DEBUG_WARN("cupsCreateJob: %s", cupsLastErrorString());
|
||||
httpClose((http_t*)cups_printjob->printjob_object);
|
||||
httpClose((http_t*) cups_printjob->printjob_object);
|
||||
free(cups_printjob);
|
||||
return NULL;
|
||||
}
|
||||
cupsStartDocument((http_t*)cups_printjob->printjob_object,
|
||||
printer->name, cups_printjob->printjob_id, buf,
|
||||
CUPS_FORMAT_AUTO, 1);
|
||||
|
||||
cupsStartDocument((http_t*) cups_printjob->printjob_object,
|
||||
printer->name, cups_printjob->printjob_id, buf, CUPS_FORMAT_AUTO, 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -205,10 +211,11 @@ static rdpPrintJob* printer_cups_find_printjob(rdpPrinter* printer, UINT32 id)
|
|||
|
||||
static void printer_cups_free_printer(rdpPrinter* printer)
|
||||
{
|
||||
rdpCupsPrinter* cups_printer = (rdpCupsPrinter*)printer;
|
||||
rdpCupsPrinter* cups_printer = (rdpCupsPrinter*) printer;
|
||||
|
||||
if (cups_printer->printjob)
|
||||
cups_printer->printjob->printjob.Close((rdpPrintJob*)cups_printer->printjob);
|
||||
cups_printer->printjob->printjob.Close((rdpPrintJob*) cups_printer->printjob);
|
||||
|
||||
free(printer->name);
|
||||
free(printer);
|
||||
}
|
||||
|
@ -217,7 +224,8 @@ static rdpPrinter* printer_cups_new_printer(rdpCupsPrinterDriver* cups_driver, c
|
|||
{
|
||||
rdpCupsPrinter* cups_printer;
|
||||
|
||||
cups_printer = xnew(rdpCupsPrinter);
|
||||
cups_printer = (rdpCupsPrinter*) malloc(sizeof(rdpCupsPrinter));
|
||||
ZeroMemory(cups_printer, sizeof(rdpCupsPrinter));
|
||||
|
||||
cups_printer->printer.id = cups_driver->id_sequence++;
|
||||
cups_printer->printer.name = _strdup(name);
|
||||
|
@ -229,7 +237,7 @@ static rdpPrinter* printer_cups_new_printer(rdpCupsPrinterDriver* cups_driver, c
|
|||
cups_printer->printer.FindPrintJob = printer_cups_find_printjob;
|
||||
cups_printer->printer.Free = printer_cups_free_printer;
|
||||
|
||||
return (rdpPrinter*)cups_printer;
|
||||
return (rdpPrinter*) cups_printer;
|
||||
}
|
||||
|
||||
static rdpPrinter** printer_cups_enum_printers(rdpPrinterDriver* driver)
|
||||
|
@ -242,13 +250,16 @@ static rdpPrinter** printer_cups_enum_printers(rdpPrinterDriver* driver)
|
|||
int i;
|
||||
|
||||
num_dests = cupsGetDests(&dests);
|
||||
printers = (rdpPrinter**)xzalloc(sizeof(rdpPrinter*) * (num_dests + 1));
|
||||
printers = (rdpPrinter**) malloc(sizeof(rdpPrinter*) * (num_dests + 1));
|
||||
ZeroMemory(printers, sizeof(rdpPrinter*) * (num_dests + 1));
|
||||
|
||||
num_printers = 0;
|
||||
|
||||
for (i = 0, dest = dests; i < num_dests; i++, dest++)
|
||||
{
|
||||
if (dest->instance == NULL)
|
||||
{
|
||||
printers[num_printers++] = printer_cups_new_printer((rdpCupsPrinterDriver*)driver,
|
||||
printers[num_printers++] = printer_cups_new_printer((rdpCupsPrinterDriver*) driver,
|
||||
dest->name, dest->is_default);
|
||||
}
|
||||
}
|
||||
|
@ -259,7 +270,7 @@ static rdpPrinter** printer_cups_enum_printers(rdpPrinterDriver* driver)
|
|||
|
||||
static rdpPrinter* printer_cups_get_printer(rdpPrinterDriver* driver, const char* name)
|
||||
{
|
||||
rdpCupsPrinterDriver* cups_driver = (rdpCupsPrinterDriver*)driver;
|
||||
rdpCupsPrinterDriver* cups_driver = (rdpCupsPrinterDriver*) driver;
|
||||
|
||||
return printer_cups_new_printer(cups_driver, name, cups_driver->id_sequence == 1 ? TRUE : FALSE);
|
||||
}
|
||||
|
@ -270,7 +281,8 @@ rdpPrinterDriver* printer_cups_get_driver(void)
|
|||
{
|
||||
if (cups_driver == NULL)
|
||||
{
|
||||
cups_driver = xnew(rdpCupsPrinterDriver);
|
||||
cups_driver = (rdpCupsPrinterDriver*) malloc(sizeof(rdpCupsPrinterDriver));
|
||||
ZeroMemory(cups_driver, sizeof(rdpCupsPrinterDriver));
|
||||
|
||||
cups_driver->driver.EnumPrinters = printer_cups_enum_printers;
|
||||
cups_driver->driver.GetPrinter = printer_cups_get_printer;
|
||||
|
@ -284,6 +296,6 @@ rdpPrinterDriver* printer_cups_get_driver(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
return (rdpPrinterDriver*)cups_driver;
|
||||
return (rdpPrinterDriver*) cups_driver;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/unicode.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/thread.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
#include <freerdp/channels/rdpdr.h>
|
||||
|
@ -247,7 +246,8 @@ void printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, rdpPrinter* pri
|
|||
port = malloc(10);
|
||||
snprintf(port, 10, "PRN%d", printer->id);
|
||||
|
||||
printer_dev = xnew(PRINTER_DEVICE);
|
||||
printer_dev = (PRINTER_DEVICE*) malloc(sizeof(PRINTER_DEVICE));
|
||||
ZeroMemory(printer_dev, sizeof(PRINTER_DEVICE));
|
||||
|
||||
printer_dev->device.type = RDPDR_DTYP_PRINT;
|
||||
printer_dev->device.name = port;
|
||||
|
@ -311,6 +311,7 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
|||
char* driver_name;
|
||||
rdpPrinter* printer;
|
||||
rdpPrinter** printers;
|
||||
RDPDR_PRINTER* device;
|
||||
rdpPrinterDriver* driver = NULL;
|
||||
|
||||
#ifdef WITH_CUPS
|
||||
|
@ -326,8 +327,9 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
|||
return 1;
|
||||
}
|
||||
|
||||
name = (char*) pEntryPoints->plugin_data->data[1];
|
||||
driver_name = (char*) pEntryPoints->plugin_data->data[2];
|
||||
device = (RDPDR_PRINTER*) pEntryPoints->device;
|
||||
name = device->Name;
|
||||
driver_name = device->DriverName;
|
||||
|
||||
if (name && name[0])
|
||||
{
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include <string.h>
|
||||
#include <winspool.h>
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
#include "printer_main.h"
|
||||
|
@ -121,7 +120,8 @@ static rdpPrintJob* printer_win_create_printjob(rdpPrinter* printer, UINT32 id)
|
|||
if (win_printer->printjob != NULL)
|
||||
return NULL;
|
||||
|
||||
win_printjob = xnew(rdpWinPrintJob);
|
||||
win_printjob = (rdpWinPrintJob*) malloc(sizeof(rdpWinPrintJob));
|
||||
ZeroMemory(win_printjob, sizeof(rdpWinPrintJob));
|
||||
|
||||
win_printjob->printjob.id = id;
|
||||
win_printjob->printjob.printer = printer;
|
||||
|
@ -129,44 +129,46 @@ static rdpPrintJob* printer_win_create_printjob(rdpPrinter* printer, UINT32 id)
|
|||
win_printjob->di.pDatatype= NULL;
|
||||
win_printjob->di.pOutputFile = NULL;
|
||||
|
||||
win_printjob->handle = StartDocPrinter(win_printer->hPrinter, 1, (LPBYTE)&(win_printjob->di) );
|
||||
if(! win_printjob->handle) DEBUG_WINPR("StartDocPrinter failed");
|
||||
if ( ! StartPagePrinter(win_printer->hPrinter) )
|
||||
DEBUG_WINPR("ClosePrinter failed");
|
||||
win_printjob->handle = StartDocPrinter(win_printer->hPrinter, 1, (LPBYTE) &(win_printjob->di));
|
||||
|
||||
if (!win_printjob->handle)
|
||||
DEBUG_WINPR("StartDocPrinter failed");
|
||||
|
||||
if (!StartPagePrinter(win_printer->hPrinter))
|
||||
DEBUG_WINPR("ClosePrinter failed");
|
||||
|
||||
win_printjob->printjob.Write = printer_win_write_printjob;
|
||||
win_printjob->printjob.Close = printer_win_close_printjob;
|
||||
|
||||
|
||||
|
||||
win_printer->printjob = win_printjob;
|
||||
|
||||
return (rdpPrintJob*)win_printjob;
|
||||
return (rdpPrintJob*) win_printjob;
|
||||
}
|
||||
|
||||
static rdpPrintJob* printer_win_find_printjob(rdpPrinter* printer, UINT32 id)
|
||||
{
|
||||
rdpWinPrinter* win_printer = (rdpWinPrinter*)printer;
|
||||
rdpWinPrinter* win_printer = (rdpWinPrinter*) printer;
|
||||
|
||||
DEBUG_WINPR("");
|
||||
DEBUG_WINPR("");
|
||||
|
||||
if (win_printer->printjob == NULL)
|
||||
return NULL;
|
||||
|
||||
if (win_printer->printjob->printjob.id != id)
|
||||
return NULL;
|
||||
|
||||
return (rdpPrintJob*)win_printer->printjob;
|
||||
return (rdpPrintJob*) win_printer->printjob;
|
||||
}
|
||||
|
||||
static void printer_win_free_printer(rdpPrinter* printer)
|
||||
{
|
||||
rdpWinPrinter* win_printer = (rdpWinPrinter*)printer;
|
||||
rdpWinPrinter* win_printer = (rdpWinPrinter*) printer;
|
||||
|
||||
DEBUG_WINPR("");
|
||||
DEBUG_WINPR("");
|
||||
|
||||
if (win_printer->printjob)
|
||||
win_printer->printjob->printjob.Close((rdpPrintJob*)win_printer->printjob);
|
||||
win_printer->printjob->printjob.Close((rdpPrintJob*) win_printer->printjob);
|
||||
|
||||
free(printer->name);
|
||||
free(printer);
|
||||
}
|
||||
|
@ -174,13 +176,14 @@ static void printer_win_free_printer(rdpPrinter* printer)
|
|||
static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver, const char* name, const wchar_t* drivername, BOOL is_default)
|
||||
{
|
||||
rdpWinPrinter* win_printer;
|
||||
wchar_t wname[256];
|
||||
wchar_t wname[256];
|
||||
DWORD needed;
|
||||
PRINTER_INFO_2 *prninfo=NULL;
|
||||
size_t charsConverted;
|
||||
DEBUG_WINPR("");
|
||||
|
||||
win_printer = xnew(rdpWinPrinter);
|
||||
win_printer = (rdpWinPrinter*) malloc(sizeof(rdpWinPrinter));
|
||||
ZeroMemory(win_printer, sizeof(rdpWinPrinter));
|
||||
|
||||
win_printer->printer.id = win_driver->id_sequence++;
|
||||
win_printer->printer.name = _strdup(name);
|
||||
|
@ -190,7 +193,7 @@ static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver, cons
|
|||
win_printer->printer.FindPrintJob = printer_win_find_printjob;
|
||||
win_printer->printer.Free = printer_win_free_printer;
|
||||
|
||||
swprintf(wname, 256, L"%hs", name);
|
||||
swprintf(wname, 256, L"%hs", name);
|
||||
OpenPrinter(wname, &(win_printer->hPrinter), NULL);
|
||||
DEBUG_WINPR("handle: 0x%08X", win_printer->hPrinter);
|
||||
|
||||
|
@ -211,31 +214,30 @@ static rdpPrinter** printer_win_enum_printers(rdpPrinterDriver* driver)
|
|||
int i;
|
||||
char pname[1000];
|
||||
size_t charsConverted;
|
||||
|
||||
PRINTER_INFO_2 *prninfo=NULL;
|
||||
DWORD needed, returned;
|
||||
PRINTER_INFO_2* prninfo = NULL;
|
||||
DWORD needed, returned;
|
||||
|
||||
DEBUG_WINPR("");
|
||||
DEBUG_WINPR("");
|
||||
|
||||
/* find required size for the buffer */
|
||||
EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, NULL, 2, NULL, 0, &needed, &returned);
|
||||
|
||||
|
||||
//find required size for the buffer
|
||||
EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, NULL, 2, NULL, 0, &needed, &returned);
|
||||
|
||||
|
||||
//allocate array of PRINTER_INFO structures
|
||||
prninfo = (PRINTER_INFO_2*) GlobalAlloc(GPTR,needed);
|
||||
/* allocate array of PRINTER_INFO structures */
|
||||
prninfo = (PRINTER_INFO_2*) GlobalAlloc(GPTR,needed);
|
||||
|
||||
//call again
|
||||
if ( !EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, NULL, 2, (LPBYTE) prninfo, needed, &needed, &returned) ) {
|
||||
/* call again */
|
||||
if ( !EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, NULL, 2, (LPBYTE) prninfo, needed, &needed, &returned) )
|
||||
{
|
||||
DEBUG_WINPR("EnumPrinters failed");
|
||||
|
||||
} ; /* eRROR... */
|
||||
} ; /* ERROR... */
|
||||
|
||||
DEBUG_WINPR("printers found: %d", returned);
|
||||
|
||||
printers = (rdpPrinter**) malloc(sizeof(rdpPrinter*) * (returned + 1));
|
||||
ZeroMemory(printers, sizeof(rdpPrinter*) * (returned + 1));
|
||||
|
||||
printers = (rdpPrinter**)xzalloc(sizeof(rdpPrinter*) * (returned + 1));
|
||||
num_printers = 0;
|
||||
num_printers = 0;
|
||||
|
||||
for (i = 0; i < (int)returned; i++)
|
||||
{
|
||||
|
@ -268,20 +270,15 @@ rdpPrinterDriver* printer_win_get_driver(void)
|
|||
|
||||
if (win_driver == NULL)
|
||||
{
|
||||
win_driver = xnew(rdpWinPrinterDriver);
|
||||
win_driver = (rdpWinPrinterDriver*) malloc(sizeof(rdpWinPrinterDriver));
|
||||
ZeroMemory(win_driver, sizeof(rdpWinPrinterDriver));
|
||||
|
||||
win_driver->driver.EnumPrinters = printer_win_enum_printers;
|
||||
win_driver->driver.GetPrinter = printer_win_get_printer;
|
||||
|
||||
win_driver->id_sequence = 1;
|
||||
|
||||
//#ifdef _win_API_1_4
|
||||
// DEBUG_SVC("using win API 1.4");
|
||||
//#else
|
||||
// DEBUG_SVC("using win API 1.2");
|
||||
//#endif
|
||||
}
|
||||
|
||||
return (rdpPrinterDriver*)win_driver;
|
||||
return (rdpPrinterDriver*) win_driver;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,10 +3,6 @@ set(OPTION_DEFAULT OFF)
|
|||
set(OPTION_CLIENT_DEFAULT ON)
|
||||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "rail" TYPE "static"
|
||||
DESCRIPTION "Remote Programs Virtual Channel Extension"
|
||||
SPECIFICATIONS "[MS-RDPERP]"
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
#include <freerdp/utils/rail.h>
|
||||
#include <freerdp/rail.h>
|
||||
|
@ -80,7 +79,7 @@ static void rail_process_connect(rdpSvcPlugin* plugin)
|
|||
railPlugin* rail = (railPlugin*) plugin;
|
||||
|
||||
rail->rail_order = rail_order_new();
|
||||
rail->rail_order->plugin_data = (RDP_PLUGIN_DATA*)plugin->channel_entry_points.pExtendedData;
|
||||
rail->rail_order->settings = (rdpSettings*) plugin->channel_entry_points.pExtendedData;
|
||||
rail->rail_order->plugin = rail;
|
||||
}
|
||||
|
||||
|
@ -96,11 +95,11 @@ static void rail_process_receive(rdpSvcPlugin* plugin, STREAM* s)
|
|||
stream_free(s);
|
||||
}
|
||||
|
||||
static void rail_process_plugin_data(rdpRailOrder* rail_order, RDP_PLUGIN_DATA* data)
|
||||
static void rail_process_addin_args(rdpRailOrder* rail_order, rdpSettings* settings)
|
||||
{
|
||||
char* exeOrFile;
|
||||
|
||||
exeOrFile = (char*) data->data[0];
|
||||
exeOrFile = settings->RemoteApplicationProgram;
|
||||
|
||||
if (strlen(exeOrFile) >= 2)
|
||||
{
|
||||
|
@ -108,21 +107,20 @@ static void rail_process_plugin_data(rdpRailOrder* rail_order, RDP_PLUGIN_DATA*
|
|||
rail_order->exec.flags |= RAIL_EXEC_FLAG_FILE;
|
||||
}
|
||||
|
||||
rail_string_to_unicode_string(rail_order, (char*) data->data[0], &rail_order->exec.exeOrFile);
|
||||
rail_string_to_unicode_string(rail_order, (char*) data->data[1], &rail_order->exec.workingDir);
|
||||
rail_string_to_unicode_string(rail_order, (char*) data->data[2], &rail_order->exec.arguments);
|
||||
rail_string_to_unicode_string(rail_order, settings->RemoteApplicationProgram, &rail_order->exec.exeOrFile);
|
||||
rail_string_to_unicode_string(rail_order, settings->ShellWorkingDirectory, &rail_order->exec.workingDir);
|
||||
rail_string_to_unicode_string(rail_order, settings->RemoteApplicationCmdLine, &rail_order->exec.arguments);
|
||||
|
||||
rail_send_client_exec_order(rail_order);
|
||||
}
|
||||
|
||||
static void rail_recv_set_sysparams_event(rdpRailOrder* rail_order, RDP_EVENT* event)
|
||||
{
|
||||
RDP_PLUGIN_DATA* data;
|
||||
RAIL_SYSPARAM_ORDER* sysparam;
|
||||
|
||||
/* Send System Parameters */
|
||||
|
||||
sysparam = (RAIL_SYSPARAM_ORDER*)event->user_data;
|
||||
sysparam = (RAIL_SYSPARAM_ORDER*) event->user_data;
|
||||
memmove(&rail_order->sysparam, sysparam, sizeof(RAIL_SYSPARAM_ORDER));
|
||||
|
||||
rail_send_client_sysparams_order(rail_order);
|
||||
|
@ -131,19 +129,18 @@ static void rail_recv_set_sysparams_event(rdpRailOrder* rail_order, RDP_EVENT* e
|
|||
|
||||
rail_order->exec.flags = RAIL_EXEC_FLAG_EXPAND_ARGUMENTS;
|
||||
|
||||
data = rail_order->plugin_data;
|
||||
while (data && data->size > 0)
|
||||
{
|
||||
rail_process_plugin_data(rail_order, data);
|
||||
data = (RDP_PLUGIN_DATA*)((char *)(data) + data->size);
|
||||
}
|
||||
rail_process_addin_args(rail_order, rail_order->settings);
|
||||
}
|
||||
|
||||
static void rail_recv_exec_remote_app_event(rdpRailOrder* rail_order, RDP_EVENT* event)
|
||||
{
|
||||
RDP_PLUGIN_DATA* data = (RDP_PLUGIN_DATA*) event->user_data;
|
||||
/**
|
||||
* TODO: replace event system by an API to allow the execution
|
||||
* of multiple remote apps over the same connection. RAIL is
|
||||
* always built-in, so clients can safely link to it.
|
||||
*/
|
||||
|
||||
rail_process_plugin_data(rail_order, data);
|
||||
//rail_process_addin_args(rail_order, data);
|
||||
}
|
||||
|
||||
static void rail_recv_activate_event(rdpRailOrder* rail_order, RDP_EVENT* event)
|
||||
|
@ -255,7 +252,7 @@ static void rail_process_event(rdpSvcPlugin* plugin, RDP_EVENT* event)
|
|||
/* rail is always built-in */
|
||||
#define VirtualChannelEntry rail_VirtualChannelEntry
|
||||
|
||||
const int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
railPlugin* _p;
|
||||
|
||||
|
@ -279,4 +276,3 @@ const int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
|||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,17 +19,18 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __RAIL_MAIN_H
|
||||
#define __RAIL_MAIN_H
|
||||
#ifndef FREERDP_CHANNEL_CLIENT_RAIL_MAIN_H
|
||||
#define FREERDP_CHANNEL_CLIENT_RAIL_MAIN_H
|
||||
|
||||
#include <freerdp/rail.h>
|
||||
#include <freerdp/settings.h>
|
||||
#include <freerdp/utils/debug.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
struct rdp_rail_order
|
||||
{
|
||||
RDP_PLUGIN_DATA* plugin_data;
|
||||
rdpSettings* settings;
|
||||
void* plugin;
|
||||
RAIL_HANDSHAKE_ORDER handshake;
|
||||
RAIL_CLIENT_STATUS_ORDER client_status;
|
||||
|
@ -65,4 +66,4 @@ void rail_send_channel_data(void* rail_object, void* data, size_t length);
|
|||
#define DEBUG_RAIL(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#endif /* __RAIL_MAIN_H */
|
||||
#endif /* FREERDP_CHANNEL_CLIENT_RAIL_MAIN_H */
|
||||
|
|
|
@ -3,10 +3,6 @@ set(OPTION_DEFAULT OFF)
|
|||
set(OPTION_CLIENT_DEFAULT ON)
|
||||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "rdpdr" TYPE "static"
|
||||
DESCRIPTION "Device Redirection Virtual Channel Extension"
|
||||
SPECIFICATIONS "[MS-RDPEFS] [MS-RDPEPC] [MS-RDPESC] [MS-RDPESP]"
|
||||
|
|
|
@ -26,22 +26,26 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/addin.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/list.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
#include <freerdp/utils/load_plugin.h>
|
||||
#include <freerdp/client/channels.h>
|
||||
|
||||
#include "rdpdr_main.h"
|
||||
|
||||
#include "devman.h"
|
||||
|
||||
DEVMAN* devman_new(rdpSvcPlugin* plugin)
|
||||
{
|
||||
DEVMAN* devman;
|
||||
|
||||
devman = xnew(DEVMAN);
|
||||
devman = (DEVMAN*) malloc(sizeof(DEVMAN));
|
||||
ZeroMemory(devman, sizeof(DEVMAN));
|
||||
|
||||
devman->plugin = plugin;
|
||||
devman->id_sequence = 1;
|
||||
devman->devices = list_new();
|
||||
|
@ -69,31 +73,41 @@ static void devman_register_device(DEVMAN* devman, DEVICE* device)
|
|||
DEBUG_SVC("device %d.%s registered", device->id, device->name);
|
||||
}
|
||||
|
||||
BOOL devman_load_device_service(DEVMAN* devman, RDP_PLUGIN_DATA* plugin_data)
|
||||
static char DRIVE_SERVICE_NAME[] = "drive";
|
||||
static char PRINTER_SERVICE_NAME[] = "printer";
|
||||
static char SMARTCARD_SERVICE_NAME[] = "smartcard";
|
||||
static char SERIAL_SERVICE_NAME[] = "serial";
|
||||
static char PARALLEL_SERVICE_NAME[] = "parallel";
|
||||
|
||||
BOOL devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device)
|
||||
{
|
||||
char* name;
|
||||
char* ServiceName = NULL;
|
||||
DEVICE_SERVICE_ENTRY_POINTS ep;
|
||||
PDEVICE_SERVICE_ENTRY entry = NULL;
|
||||
|
||||
name = (char*) plugin_data->data[0];
|
||||
entry = (PDEVICE_SERVICE_ENTRY) freerdp_channels_client_find_static_entry("DeviceServiceEntry", name);
|
||||
if (device->Type == RDPDR_DTYP_FILESYSTEM)
|
||||
ServiceName = DRIVE_SERVICE_NAME;
|
||||
else if (device->Type == RDPDR_DTYP_PRINT)
|
||||
ServiceName = PRINTER_SERVICE_NAME;
|
||||
else if (device->Type == RDPDR_DTYP_SMARTCARD)
|
||||
ServiceName = SMARTCARD_SERVICE_NAME;
|
||||
else if (device->Type == RDPDR_DTYP_SERIAL)
|
||||
ServiceName = SERIAL_SERVICE_NAME;
|
||||
else if (device->Type == RDPDR_DTYP_PARALLEL)
|
||||
ServiceName = PARALLEL_SERVICE_NAME;
|
||||
|
||||
if (!entry)
|
||||
{
|
||||
printf("loading device service %s (plugin)\n", name);
|
||||
entry = freerdp_load_plugin(name, "DeviceServiceEntry");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("loading device service %s (static)\n", name);
|
||||
}
|
||||
if (!ServiceName)
|
||||
return FALSE;
|
||||
|
||||
printf("Loading device service %s (static)\n", ServiceName);
|
||||
entry = (PDEVICE_SERVICE_ENTRY) freerdp_load_channel_addin_entry(ServiceName, NULL, "DeviceServiceEntry", 0);
|
||||
|
||||
if (entry == NULL)
|
||||
return FALSE;
|
||||
|
||||
ep.devman = devman;
|
||||
ep.RegisterDevice = devman_register_device;
|
||||
ep.plugin_data = plugin_data;
|
||||
ep.device = device;
|
||||
|
||||
entry(&ep);
|
||||
|
||||
|
|
|
@ -21,9 +21,10 @@
|
|||
#ifndef FREERDP_CHANNEL_RDPDR_CLIENT_DEVMAN_H
|
||||
#define FREERDP_CHANNEL_RDPDR_CLIENT_DEVMAN_H
|
||||
|
||||
DEVMAN* devman_new(rdpSvcPlugin* plugin);
|
||||
void devman_free(DEVMAN* devman);
|
||||
BOOL devman_load_device_service(DEVMAN* devman, RDP_PLUGIN_DATA* plugin_data);
|
||||
BOOL devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device);
|
||||
DEVICE* devman_get_device_by_id(DEVMAN* devman, UINT32 id);
|
||||
|
||||
DEVMAN* devman_new(rdpSvcPlugin* plugin);
|
||||
void devman_free(DEVMAN* devman);
|
||||
|
||||
#endif /* FREERDP_CHANNEL_RDPDR_CLIENT_DEVMAN_H */
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/unicode.h>
|
||||
#include <freerdp/channels/rdpdr.h>
|
||||
|
@ -49,25 +48,20 @@
|
|||
|
||||
static void rdpdr_process_connect(rdpSvcPlugin* plugin)
|
||||
{
|
||||
int index;
|
||||
RDPDR_DEVICE* device;
|
||||
rdpSettings* settings;
|
||||
rdpdrPlugin* rdpdr = (rdpdrPlugin*) plugin;
|
||||
RDP_PLUGIN_DATA* data;
|
||||
|
||||
rdpdr->devman = devman_new(plugin);
|
||||
data = (RDP_PLUGIN_DATA*) plugin->channel_entry_points.pExtendedData;
|
||||
settings = (rdpSettings*) plugin->channel_entry_points.pExtendedData;
|
||||
|
||||
while (data && data->size > 0)
|
||||
strncpy(rdpdr->computerName, settings->ComputerName, sizeof(rdpdr->computerName) - 1);
|
||||
|
||||
for (index = 0; index < settings->DeviceCount; index++)
|
||||
{
|
||||
if (strcmp((char*) data->data[0], "clientname") == 0)
|
||||
{
|
||||
strncpy(rdpdr->computerName, (char*) data->data[1], sizeof(rdpdr->computerName) - 1);
|
||||
DEBUG_SVC("computerName %s", rdpdr->computerName);
|
||||
}
|
||||
else
|
||||
{
|
||||
devman_load_device_service(rdpdr->devman, data);
|
||||
}
|
||||
|
||||
data = (RDP_PLUGIN_DATA*) (((BYTE*) data) + data->size);
|
||||
device = settings->DeviceArray[index];
|
||||
devman_load_device_service(rdpdr->devman, device);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,8 +172,9 @@ static void rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, BOOL use
|
|||
* 2. smartcard devices should be always sent
|
||||
* 3. other devices are sent only after user_loggedon
|
||||
*/
|
||||
if (rdpdr->versionMinor == 0x0005 ||
|
||||
device->type == RDPDR_DTYP_SMARTCARD || user_loggedon)
|
||||
|
||||
if ((rdpdr->versionMinor == 0x0005) ||
|
||||
(device->type == RDPDR_DTYP_SMARTCARD) || user_loggedon)
|
||||
{
|
||||
data_len = (device->data == NULL ? 0 : stream_get_length(device->data));
|
||||
stream_check_size(data_out, 20 + data_len);
|
||||
|
@ -319,7 +314,7 @@ static void rdpdr_process_terminate(rdpSvcPlugin* plugin)
|
|||
/* rdpdr is always built-in */
|
||||
#define VirtualChannelEntry rdpdr_VirtualChannelEntry
|
||||
|
||||
const int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
rdpdrPlugin* _p;
|
||||
|
||||
|
|
|
@ -3,10 +3,6 @@ set(OPTION_DEFAULT OFF)
|
|||
set(OPTION_CLIENT_DEFAULT ON)
|
||||
set(OPTION_SERVER_DEFAULT ON)
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "rdpsnd" TYPE "static"
|
||||
DESCRIPTION "Audio Output Virtual Channel Extension"
|
||||
SPECIFICATIONS "[MS-RDPEA]"
|
||||
|
|
|
@ -29,20 +29,24 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
|||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE freerdp
|
||||
MODULES freerdp-utils)
|
||||
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE winpr
|
||||
MODULES winpr-utils)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")
|
||||
|
||||
if(WITH_ALSA)
|
||||
add_subdirectory(alsa)
|
||||
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "alsa" "")
|
||||
endif()
|
||||
|
||||
if(WITH_PULSE)
|
||||
add_subdirectory(pulse)
|
||||
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "pulse" "")
|
||||
endif()
|
||||
|
||||
if(WITH_MACAUDIO)
|
||||
add_subdirectory(mac)
|
||||
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "mac" "")
|
||||
endif()
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ set(${MODULE_PREFIX}_SRCS
|
|||
include_directories(..)
|
||||
include_directories(${ALSA_INCLUDE_DIRS})
|
||||
|
||||
add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
|
@ -32,8 +32,15 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
|||
MODULE freerdp
|
||||
MODULES freerdp-utils)
|
||||
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE winpr
|
||||
MODULES winpr-utils)
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${ALSA_LIBRARIES})
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
|
||||
if(NOT STATIC_CHANNELS)
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
|
||||
endif()
|
||||
|
|
|
@ -27,17 +27,18 @@
|
|||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/cmdline.h>
|
||||
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/dsp.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
#include "rdpsnd_main.h"
|
||||
|
||||
typedef struct rdpsnd_alsa_plugin rdpsndAlsaPlugin;
|
||||
|
||||
struct rdpsnd_alsa_plugin
|
||||
{
|
||||
rdpsndDevicePlugin device;
|
||||
|
@ -416,12 +417,53 @@ static void rdpsnd_alsa_start(rdpsndDevicePlugin* device)
|
|||
snd_pcm_start(alsa->out_handle);
|
||||
}
|
||||
|
||||
int FreeRDPRdpsndDeviceEntry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
|
||||
COMMAND_LINE_ARGUMENT_A rdpsnd_alsa_args[] =
|
||||
{
|
||||
rdpsndAlsaPlugin* alsa;
|
||||
RDP_PLUGIN_DATA* data;
|
||||
{ "dev", COMMAND_LINE_VALUE_REQUIRED, "<device>", NULL, NULL, -1, NULL, "device" },
|
||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
alsa = xnew(rdpsndAlsaPlugin);
|
||||
static void rdpsnd_alsa_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* args)
|
||||
{
|
||||
int status;
|
||||
DWORD flags;
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device;
|
||||
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
|
||||
|
||||
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, rdpsnd_alsa_args, flags, alsa, NULL, NULL);
|
||||
|
||||
arg = rdpsnd_alsa_args;
|
||||
|
||||
do
|
||||
{
|
||||
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
|
||||
continue;
|
||||
|
||||
CommandLineSwitchStart(arg)
|
||||
|
||||
CommandLineSwitchCase(arg, "dev")
|
||||
{
|
||||
alsa->device_name = _strdup(arg->Value);
|
||||
}
|
||||
|
||||
CommandLineSwitchEnd(arg)
|
||||
}
|
||||
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_rdpsnd_client_subsystem_entry alsa_freerdp_rdpsnd_client_subsystem_entry
|
||||
#endif
|
||||
|
||||
int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
ADDIN_ARGV* args;
|
||||
rdpsndAlsaPlugin* alsa;
|
||||
|
||||
alsa = (rdpsndAlsaPlugin*) malloc(sizeof(rdpsndAlsaPlugin));
|
||||
ZeroMemory(alsa, sizeof(rdpsndAlsaPlugin));
|
||||
|
||||
alsa->device.Open = rdpsnd_alsa_open;
|
||||
alsa->device.FormatSupported = rdpsnd_alsa_format_supported;
|
||||
|
@ -432,17 +474,8 @@ int FreeRDPRdpsndDeviceEntry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
|
|||
alsa->device.Close = rdpsnd_alsa_close;
|
||||
alsa->device.Free = rdpsnd_alsa_free;
|
||||
|
||||
data = pEntryPoints->plugin_data;
|
||||
|
||||
if (data && strcmp((char*) data->data[0], "alsa") == 0)
|
||||
{
|
||||
alsa->device_name = _strdup((char*) data->data[1]);
|
||||
}
|
||||
|
||||
if (alsa->device_name == NULL)
|
||||
{
|
||||
alsa->device_name = _strdup("default");
|
||||
}
|
||||
args = pEntryPoints->args;
|
||||
rdpsnd_alsa_parse_addin_args((rdpsndDevicePlugin*) alsa, args);
|
||||
|
||||
alsa->out_handle = 0;
|
||||
alsa->source_rate = 22050;
|
||||
|
@ -458,4 +491,3 @@ int FreeRDPRdpsndDeviceEntry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ set(${MODULE_PREFIX}_SRCS
|
|||
include_directories(..)
|
||||
include_directories(${MACAUDIO_INCLUDE_DIRS})
|
||||
|
||||
add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
|
@ -38,5 +38,6 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${MAC_COREFOUNDATION_LIBRARY_
|
|||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
|
||||
|
||||
if(NOT STATIC_CHANNELS)
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
|
||||
endif()
|
||||
|
|
|
@ -29,8 +29,9 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/dsp.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
|
@ -192,19 +193,22 @@ static void rdpsnd_audio_start(rdpsndDevicePlugin* device)
|
|||
* our job here is to fill aq_buf_ref with audio data and enqueue it
|
||||
*/
|
||||
|
||||
static void aq_playback_cb(void *user_data,
|
||||
AudioQueueRef aq_ref,
|
||||
AudioQueueBufferRef aq_buf_ref
|
||||
)
|
||||
static void aq_playback_cb(void* user_data, AudioQueueRef aq_ref, AudioQueueBufferRef aq_buf_ref)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int FreeRDPRdpsndDeviceEntry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_rdpsnd_client_subsystem_entry mac_freerdp_rdpsnd_client_subsystem_entry
|
||||
#endif
|
||||
|
||||
int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
ADDIN_ARGV* args;
|
||||
rdpsndAudioQPlugin* aqPlugin;
|
||||
RDP_PLUGIN_DATA* data;
|
||||
|
||||
aqPlugin = xnew(rdpsndAudioQPlugin);
|
||||
aqPlugin = (rdpsndAudioQPlugin*) malloc(sizeof(rdpsndAudioQPlugin));
|
||||
ZeroMemory(aqPlugin, sizeof(rdpsndAudioQPlugin));
|
||||
|
||||
aqPlugin->device.Open = rdpsnd_audio_open;
|
||||
aqPlugin->device.FormatSupported = rdpsnd_audio_format_supported;
|
||||
|
@ -215,15 +219,14 @@ int FreeRDPRdpsndDeviceEntry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
|
|||
aqPlugin->device.Close = rdpsnd_audio_close;
|
||||
aqPlugin->device.Free = rdpsnd_audio_free;
|
||||
|
||||
data = pEntryPoints->plugin_data;
|
||||
args = pEntryPoints->args;
|
||||
|
||||
if (data && strcmp((char *)data->data[0], "macaudio") == 0) {
|
||||
if(strlen((char *)data->data[1]) > 0)
|
||||
aqPlugin->device_name = strdup((char *)data->data[1]);
|
||||
else
|
||||
aqPlugin->device_name = NULL;
|
||||
if (args->argc > 2)
|
||||
{
|
||||
/* TODO: parse device name */
|
||||
}
|
||||
pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*)aqPlugin);
|
||||
|
||||
pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*) aqPlugin);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ set(${MODULE_PREFIX}_SRCS
|
|||
include_directories(..)
|
||||
include_directories(${PULSE_INCLUDE_DIR})
|
||||
|
||||
add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
|
@ -36,4 +36,6 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${PULSE_LIBRARY})
|
|||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
|
||||
if(NOT STATIC_CHANNELS)
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
|
||||
endif()
|
||||
|
|
|
@ -26,11 +26,11 @@
|
|||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/cmdline.h>
|
||||
|
||||
#include <pulse/pulseaudio.h>
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/dsp.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
|
@ -523,12 +523,54 @@ static void rdpsnd_pulse_start(rdpsndDevicePlugin* device)
|
|||
pa_stream_trigger(pulse->stream, NULL, NULL);
|
||||
}
|
||||
|
||||
int FreeRDPRdpsndDeviceEntry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
|
||||
COMMAND_LINE_ARGUMENT_A rdpsnd_pulse_args[] =
|
||||
{
|
||||
rdpsndPulsePlugin* pulse;
|
||||
RDP_PLUGIN_DATA* data;
|
||||
{ "dev", COMMAND_LINE_VALUE_REQUIRED, "<device>", NULL, NULL, -1, NULL, "device" },
|
||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
pulse = xnew(rdpsndPulsePlugin);
|
||||
static void rdpsnd_pulse_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* args)
|
||||
{
|
||||
int status;
|
||||
DWORD flags;
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
rdpsndPulsePlugin* pulse = (rdpsndPulsePlugin*) device;
|
||||
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
|
||||
|
||||
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
|
||||
rdpsnd_pulse_args, flags, pulse, NULL, NULL);
|
||||
|
||||
arg = rdpsnd_pulse_args;
|
||||
|
||||
do
|
||||
{
|
||||
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
|
||||
continue;
|
||||
|
||||
CommandLineSwitchStart(arg)
|
||||
|
||||
CommandLineSwitchCase(arg, "dev")
|
||||
{
|
||||
pulse->device_name = _strdup(arg->Value);
|
||||
}
|
||||
|
||||
CommandLineSwitchEnd(arg)
|
||||
}
|
||||
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_rdpsnd_client_subsystem_entry pulse_freerdp_rdpsnd_client_subsystem_entry
|
||||
#endif
|
||||
|
||||
int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
ADDIN_ARGV* args;
|
||||
rdpsndPulsePlugin* pulse;
|
||||
|
||||
pulse = (rdpsndPulsePlugin*) malloc(sizeof(rdpsndPulsePlugin));
|
||||
ZeroMemory(pulse, sizeof(rdpsndPulsePlugin));
|
||||
|
||||
pulse->device.Open = rdpsnd_pulse_open;
|
||||
pulse->device.FormatSupported = rdpsnd_pulse_format_supported;
|
||||
|
@ -539,15 +581,8 @@ int FreeRDPRdpsndDeviceEntry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
|
|||
pulse->device.Close = rdpsnd_pulse_close;
|
||||
pulse->device.Free = rdpsnd_pulse_free;
|
||||
|
||||
data = pEntryPoints->plugin_data;
|
||||
|
||||
if (data && strcmp((char*)data->data[0], "pulse") == 0)
|
||||
{
|
||||
if(data->data[1] && strlen((char*)data->data[1]) > 0)
|
||||
pulse->device_name = _strdup((char*)data->data[1]);
|
||||
else
|
||||
pulse->device_name = NULL;
|
||||
}
|
||||
args = pEntryPoints->args;
|
||||
rdpsnd_pulse_parse_addin_args((rdpsndDevicePlugin*) pulse, args);
|
||||
|
||||
pulse->dsp_context = freerdp_dsp_context_new();
|
||||
|
||||
|
|
|
@ -31,13 +31,13 @@
|
|||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/cmdline.h>
|
||||
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/addin.h>
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/list.h>
|
||||
#include <freerdp/utils/load_plugin.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
#include "rdpsnd_main.h"
|
||||
|
@ -67,6 +67,9 @@ struct rdpsnd_plugin
|
|||
UINT32 fixed_rate;
|
||||
int latency;
|
||||
|
||||
char* subsystem;
|
||||
char* device_name;
|
||||
|
||||
/* Device plugin */
|
||||
rdpsndDevicePlugin* device;
|
||||
};
|
||||
|
@ -190,7 +193,8 @@ static void rdpsnd_process_message_formats(rdpsndPlugin* rdpsnd, STREAM* data_in
|
|||
return;
|
||||
}
|
||||
|
||||
out_formats = (rdpsndFormat*)xzalloc(wNumberOfFormats * sizeof(rdpsndFormat));
|
||||
out_formats = (rdpsndFormat*) malloc(wNumberOfFormats * sizeof(rdpsndFormat));
|
||||
ZeroMemory(out_formats, wNumberOfFormats * sizeof(rdpsndFormat));
|
||||
n_out_formats = 0;
|
||||
|
||||
data_out = stream_new(24);
|
||||
|
@ -357,7 +361,9 @@ static void rdpsnd_process_message_wave(rdpsndPlugin* rdpsnd, STREAM* data_in)
|
|||
DEBUG_SVC("data_size %d delay_ms %u process_ms %u",
|
||||
stream_get_size(data_in), delay_ms, process_ms);
|
||||
|
||||
item = xnew(struct data_out_item);
|
||||
item = (struct data_out_item*) malloc(sizeof(struct data_out_item));
|
||||
ZeroMemory(item, sizeof(struct data_out_item));
|
||||
|
||||
item->data_out = stream_new(8);
|
||||
stream_write_BYTE(item->data_out, SNDC_WAVECONFIRM);
|
||||
stream_write_BYTE(item->data_out, 0);
|
||||
|
@ -444,67 +450,114 @@ static void rdpsnd_register_device_plugin(rdpsndPlugin* rdpsnd, rdpsndDevicePlug
|
|||
rdpsnd->device = device;
|
||||
}
|
||||
|
||||
static BOOL rdpsnd_load_device_plugin(rdpsndPlugin* rdpsnd, const char* name, RDP_PLUGIN_DATA* data)
|
||||
static BOOL rdpsnd_load_device_plugin(rdpsndPlugin* rdpsnd, const char* name, ADDIN_ARGV* args)
|
||||
{
|
||||
FREERDP_RDPSND_DEVICE_ENTRY_POINTS entryPoints;
|
||||
PFREERDP_RDPSND_DEVICE_ENTRY entry;
|
||||
char* fullname;
|
||||
FREERDP_RDPSND_DEVICE_ENTRY_POINTS entryPoints;
|
||||
|
||||
entry = (PFREERDP_RDPSND_DEVICE_ENTRY) freerdp_load_channel_addin_entry("rdpsnd", (LPSTR) name, NULL, 0);
|
||||
|
||||
if (strrchr(name, '.') != NULL)
|
||||
entry = (PFREERDP_RDPSND_DEVICE_ENTRY)freerdp_load_plugin(name, RDPSND_DEVICE_EXPORT_FUNC_NAME);
|
||||
else
|
||||
{
|
||||
fullname = xzalloc(strlen(name) + 8);
|
||||
strcpy(fullname, "rdpsnd_");
|
||||
strcat(fullname, name);
|
||||
entry = (PFREERDP_RDPSND_DEVICE_ENTRY)freerdp_load_plugin(fullname, RDPSND_DEVICE_EXPORT_FUNC_NAME);
|
||||
free(fullname);
|
||||
}
|
||||
if (entry == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
entryPoints.rdpsnd = rdpsnd;
|
||||
entryPoints.pRegisterRdpsndDevice = rdpsnd_register_device_plugin;
|
||||
entryPoints.plugin_data = data;
|
||||
entryPoints.args = args;
|
||||
|
||||
if (entry(&entryPoints) != 0)
|
||||
{
|
||||
DEBUG_WARN("%s entry returns error.", name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void rdpsnd_process_plugin_data(rdpsndPlugin* rdpsnd, RDP_PLUGIN_DATA* data)
|
||||
void rdpsnd_set_subsystem(rdpsndPlugin* rdpsnd, char* subsystem)
|
||||
{
|
||||
if (strcmp((char*)data->data[0], "format") == 0)
|
||||
if (rdpsnd->subsystem)
|
||||
free(rdpsnd->subsystem);
|
||||
|
||||
rdpsnd->subsystem = _strdup(subsystem);
|
||||
}
|
||||
|
||||
void rdpsnd_set_device_name(rdpsndPlugin* rdpsnd, char* device_name)
|
||||
{
|
||||
if (rdpsnd->device_name)
|
||||
free(rdpsnd->device_name);
|
||||
|
||||
rdpsnd->device_name = _strdup(device_name);
|
||||
}
|
||||
|
||||
COMMAND_LINE_ARGUMENT_A rdpsnd_args[] =
|
||||
{
|
||||
{ "sys", COMMAND_LINE_VALUE_REQUIRED, "<subsystem>", NULL, NULL, -1, NULL, "subsystem" },
|
||||
{ "dev", COMMAND_LINE_VALUE_REQUIRED, "<device>", NULL, NULL, -1, NULL, "device" },
|
||||
{ "format", COMMAND_LINE_VALUE_REQUIRED, "<format>", NULL, NULL, -1, NULL, "format" },
|
||||
{ "rate", COMMAND_LINE_VALUE_REQUIRED, "<rate>", NULL, NULL, -1, NULL, "rate" },
|
||||
{ "channel", COMMAND_LINE_VALUE_REQUIRED, "<channel>", NULL, NULL, -1, NULL, "channel" },
|
||||
{ "latency", COMMAND_LINE_VALUE_REQUIRED, "<latency>", NULL, NULL, -1, NULL, "latency" },
|
||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
static void rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args)
|
||||
{
|
||||
int status;
|
||||
DWORD flags;
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
|
||||
|
||||
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
|
||||
rdpsnd_args, flags, rdpsnd, NULL, NULL);
|
||||
|
||||
arg = rdpsnd_args;
|
||||
|
||||
do
|
||||
{
|
||||
rdpsnd->fixed_format = atoi(data->data[1]);
|
||||
}
|
||||
else if (strcmp((char*)data->data[0], "rate") == 0)
|
||||
{
|
||||
rdpsnd->fixed_rate = atoi(data->data[1]);
|
||||
}
|
||||
else if (strcmp((char*)data->data[0], "channel") == 0)
|
||||
{
|
||||
rdpsnd->fixed_channel = atoi(data->data[1]);
|
||||
}
|
||||
else if (strcmp((char*)data->data[0], "latency") == 0)
|
||||
{
|
||||
rdpsnd->latency = atoi(data->data[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
rdpsnd_load_device_plugin(rdpsnd, (char*)data->data[0], data);
|
||||
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
|
||||
continue;
|
||||
|
||||
CommandLineSwitchStart(arg)
|
||||
|
||||
CommandLineSwitchCase(arg, "sys")
|
||||
{
|
||||
rdpsnd_set_subsystem(rdpsnd, arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "dev")
|
||||
{
|
||||
rdpsnd_set_device_name(rdpsnd, arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "format")
|
||||
{
|
||||
rdpsnd->fixed_format = atoi(arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "rate")
|
||||
{
|
||||
rdpsnd->fixed_rate = atoi(arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "channel")
|
||||
{
|
||||
rdpsnd->fixed_channel = atoi(arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "latency")
|
||||
{
|
||||
rdpsnd->latency = atoi(arg->Value);
|
||||
}
|
||||
CommandLineSwitchDefault(arg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CommandLineSwitchEnd(arg)
|
||||
}
|
||||
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
}
|
||||
|
||||
static void rdpsnd_process_connect(rdpSvcPlugin* plugin)
|
||||
{
|
||||
ADDIN_ARGV* args;
|
||||
rdpsndPlugin* rdpsnd = (rdpsndPlugin*) plugin;
|
||||
RDP_PLUGIN_DATA* data;
|
||||
RDP_PLUGIN_DATA default_data[2] = { { 0 }, { 0 } };
|
||||
|
||||
DEBUG_SVC("connecting");
|
||||
|
||||
|
@ -513,42 +566,40 @@ static void rdpsnd_process_connect(rdpSvcPlugin* plugin)
|
|||
rdpsnd->data_out_list = list_new();
|
||||
rdpsnd->latency = -1;
|
||||
|
||||
data = (RDP_PLUGIN_DATA*) plugin->channel_entry_points.pExtendedData;
|
||||
args = (ADDIN_ARGV*) plugin->channel_entry_points.pExtendedData;
|
||||
|
||||
while (data && data->size > 0)
|
||||
if (args)
|
||||
rdpsnd_process_addin_args(rdpsnd, args);
|
||||
|
||||
if (rdpsnd->subsystem)
|
||||
{
|
||||
rdpsnd_process_plugin_data(rdpsnd, data);
|
||||
data = (RDP_PLUGIN_DATA*) (((BYTE*) data) + data->size);
|
||||
if (strcmp(rdpsnd->subsystem, "fake") == 0)
|
||||
return;
|
||||
|
||||
rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args);
|
||||
}
|
||||
|
||||
if (rdpsnd->device == NULL)
|
||||
if (!rdpsnd->device)
|
||||
{
|
||||
default_data[0].size = sizeof(RDP_PLUGIN_DATA);
|
||||
default_data[0].data[0] = "pulse";
|
||||
default_data[0].data[1] = "";
|
||||
|
||||
if (!rdpsnd_load_device_plugin(rdpsnd, "pulse", default_data))
|
||||
{
|
||||
default_data[0].data[0] = "alsa";
|
||||
default_data[0].data[1] = "default";
|
||||
|
||||
if (!rdpsnd_load_device_plugin(rdpsnd, "alsa", default_data))
|
||||
{
|
||||
default_data[0].data[0] = "macaudio";
|
||||
default_data[0].data[1] = "default";
|
||||
|
||||
rdpsnd_load_device_plugin(rdpsnd, "macaudio", default_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("rdpsnd: successfully loaded alsa plugin\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("rdpsnd: successfully loaded pulseaudio plugin\n");
|
||||
}
|
||||
rdpsnd_set_subsystem(rdpsnd, "pulse");
|
||||
rdpsnd_set_device_name(rdpsnd, "");
|
||||
rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args);
|
||||
}
|
||||
|
||||
if (!rdpsnd->device)
|
||||
{
|
||||
rdpsnd_set_subsystem(rdpsnd, "alsa");
|
||||
rdpsnd_set_device_name(rdpsnd, "default");
|
||||
rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args);
|
||||
}
|
||||
|
||||
if (!rdpsnd->device)
|
||||
{
|
||||
rdpsnd_set_subsystem(rdpsnd, "macaudio");
|
||||
rdpsnd_set_device_name(rdpsnd, "default");
|
||||
rdpsnd_load_device_plugin(rdpsnd, rdpsnd->subsystem, args);
|
||||
}
|
||||
|
||||
if (rdpsnd->device == NULL)
|
||||
{
|
||||
DEBUG_WARN("no sound device.");
|
||||
|
@ -575,6 +626,12 @@ static void rdpsnd_process_terminate(rdpSvcPlugin* plugin)
|
|||
}
|
||||
list_free(rdpsnd->data_out_list);
|
||||
|
||||
if (rdpsnd->subsystem)
|
||||
free(rdpsnd->subsystem);
|
||||
|
||||
if (rdpsnd->device_name)
|
||||
free(rdpsnd->device_name);
|
||||
|
||||
rdpsnd_free_supported_formats(rdpsnd);
|
||||
|
||||
free(plugin);
|
||||
|
@ -583,7 +640,7 @@ static void rdpsnd_process_terminate(rdpSvcPlugin* plugin)
|
|||
/* rdpsnd is always built-in */
|
||||
#define VirtualChannelEntry rdpsnd_VirtualChannelEntry
|
||||
|
||||
const int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
rdpsndPlugin* _p;
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ struct rdpsnd_device_plugin
|
|||
pcFree Free;
|
||||
};
|
||||
|
||||
#define RDPSND_DEVICE_EXPORT_FUNC_NAME "FreeRDPRdpsndDeviceEntry"
|
||||
#define RDPSND_DEVICE_EXPORT_FUNC_NAME "freerdp_rdpsnd_client_subsystem_entry"
|
||||
|
||||
typedef void (*PREGISTERRDPSNDDEVICE)(rdpsndPlugin* rdpsnd, rdpsndDevicePlugin* device);
|
||||
|
||||
|
@ -55,7 +55,7 @@ struct _FREERDP_RDPSND_DEVICE_ENTRY_POINTS
|
|||
{
|
||||
rdpsndPlugin* rdpsnd;
|
||||
PREGISTERRDPSNDDEVICE pRegisterRdpsndDevice;
|
||||
RDP_PLUGIN_DATA* plugin_data;
|
||||
ADDIN_ARGV* args;
|
||||
};
|
||||
typedef struct _FREERDP_RDPSND_DEVICE_ENTRY_POINTS FREERDP_RDPSND_DEVICE_ENTRY_POINTS;
|
||||
typedef FREERDP_RDPSND_DEVICE_ENTRY_POINTS* PFREERDP_RDPSND_DEVICE_ENTRY_POINTS;
|
||||
|
@ -63,4 +63,3 @@ typedef FREERDP_RDPSND_DEVICE_ENTRY_POINTS* PFREERDP_RDPSND_DEVICE_ENTRY_POINTS;
|
|||
typedef int (*PFREERDP_RDPSND_DEVICE_ENTRY)(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints);
|
||||
|
||||
#endif /* __RDPSND_MAIN_H */
|
||||
|
||||
|
|
|
@ -27,9 +27,8 @@
|
|||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/dsp.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/thread.h>
|
||||
#include <freerdp/utils/wait_obj.h>
|
||||
#include <freerdp/channels/wtsvc.h>
|
||||
|
@ -109,6 +108,8 @@ static BOOL rdpsnd_server_send_formats(rdpsnd_server* rdpsnd, STREAM* s)
|
|||
}
|
||||
|
||||
RDPSND_PDU_FINISH(s);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL rdpsnd_server_recv_formats(rdpsnd_server* rdpsnd, STREAM* s)
|
||||
|
@ -451,7 +452,9 @@ rdpsnd_server_context* rdpsnd_server_context_new(WTSVirtualChannelManager* vcm)
|
|||
{
|
||||
rdpsnd_server* rdpsnd;
|
||||
|
||||
rdpsnd = xnew(rdpsnd_server);
|
||||
rdpsnd = (rdpsnd_server*) malloc(sizeof(rdpsnd_server));
|
||||
ZeroMemory(rdpsnd, sizeof(rdpsnd_server));
|
||||
|
||||
rdpsnd->context.vcm = vcm;
|
||||
rdpsnd->context.selected_client_format = -1;
|
||||
rdpsnd->context.Initialize = rdpsnd_server_initialize;
|
||||
|
|
|
@ -8,10 +8,6 @@ if(WITH_SAMPLE)
|
|||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
endif()
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "sample" TYPE "static"
|
||||
DESCRIPTION "Sample Virtual Channel Extension"
|
||||
SPECIFICATIONS ""
|
||||
|
|
|
@ -34,10 +34,8 @@
|
|||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/list.h>
|
||||
#include <freerdp/utils/load_plugin.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
#include "sample_main.h"
|
||||
|
@ -136,7 +134,7 @@ static void sample_process_terminate(rdpSvcPlugin* plugin)
|
|||
|
||||
#define VirtualChannelEntry sample_VirtualChannelEntry
|
||||
|
||||
const int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
samplePlugin* _p;
|
||||
|
||||
|
|
|
@ -13,10 +13,6 @@ if(ANDROID)
|
|||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
endif()
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "serial" TYPE "device"
|
||||
DESCRIPTION "Serial Port Virtual Channel Extension"
|
||||
SPECIFICATIONS "[MS-RDPESP]"
|
||||
|
|
|
@ -397,49 +397,6 @@ static void serial_free(DEVICE* device)
|
|||
free(serial);
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define DeviceServiceEntry serial_DeviceServiceEntry
|
||||
#endif
|
||||
|
||||
int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
int i, len;
|
||||
char* name;
|
||||
char* path;
|
||||
SERIAL_DEVICE* serial;
|
||||
|
||||
name = (char*) pEntryPoints->plugin_data->data[1];
|
||||
path = (char*) pEntryPoints->plugin_data->data[2];
|
||||
|
||||
if (name[0] && path[0])
|
||||
{
|
||||
serial = xnew(SERIAL_DEVICE);
|
||||
|
||||
serial->device.type = RDPDR_DTYP_SERIAL;
|
||||
serial->device.name = name;
|
||||
serial->device.IRPRequest = serial_irp_request;
|
||||
serial->device.Free = serial_free;
|
||||
|
||||
len = strlen(name);
|
||||
serial->device.data = stream_new(len + 1);
|
||||
|
||||
for (i = 0; i <= len; i++)
|
||||
stream_write_BYTE(serial->device.data, name[i] < 0 ? '_' : name[i]);
|
||||
|
||||
serial->path = path;
|
||||
serial->irp_list = list_new();
|
||||
serial->pending_irps = list_new();
|
||||
serial->thread = freerdp_thread_new();
|
||||
serial->in_event = wait_obj_new();
|
||||
|
||||
pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*)serial);
|
||||
|
||||
freerdp_thread_start(serial->thread, serial_thread_func, serial);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void serial_abort_single_io(SERIAL_DEVICE* serial, UINT32 file_id, UINT32 abort_io, UINT32 io_status)
|
||||
{
|
||||
IRP* irp = NULL;
|
||||
|
@ -732,3 +689,49 @@ static BOOL serial_check_fds(SERIAL_DEVICE* serial)
|
|||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define DeviceServiceEntry serial_DeviceServiceEntry
|
||||
#endif
|
||||
|
||||
int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
int i, len;
|
||||
char* name;
|
||||
char* path;
|
||||
RDPDR_SERIAL* device;
|
||||
SERIAL_DEVICE* serial;
|
||||
|
||||
device = (RDPDR_SERIAL*) pEntryPoints->device;
|
||||
name = device->Name;
|
||||
path = device->Path;
|
||||
|
||||
if (name[0] && path[0])
|
||||
{
|
||||
serial = (SERIAL_DEVICE*) malloc(sizeof(SERIAL_DEVICE));
|
||||
ZeroMemory(serial, sizeof(SERIAL_DEVICE));
|
||||
|
||||
serial->device.type = RDPDR_DTYP_SERIAL;
|
||||
serial->device.name = name;
|
||||
serial->device.IRPRequest = serial_irp_request;
|
||||
serial->device.Free = serial_free;
|
||||
|
||||
len = strlen(name);
|
||||
serial->device.data = stream_new(len + 1);
|
||||
|
||||
for (i = 0; i <= len; i++)
|
||||
stream_write_BYTE(serial->device.data, name[i] < 0 ? '_' : name[i]);
|
||||
|
||||
serial->path = path;
|
||||
serial->irp_list = list_new();
|
||||
serial->pending_irps = list_new();
|
||||
serial->thread = freerdp_thread_new();
|
||||
serial->in_event = wait_obj_new();
|
||||
|
||||
pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*)serial);
|
||||
|
||||
freerdp_thread_start(serial->thread, serial_thread_func, serial);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/unicode.h>
|
||||
#include <freerdp/utils/list.h>
|
||||
|
@ -467,31 +468,40 @@ SERIAL_TTY* serial_tty_new(const char* path, UINT32 id)
|
|||
{
|
||||
SERIAL_TTY* tty;
|
||||
|
||||
tty = xnew(SERIAL_TTY);
|
||||
tty = (SERIAL_TTY*) malloc(sizeof(SERIAL_TTY));
|
||||
ZeroMemory(tty, sizeof(SERIAL_TTY));
|
||||
|
||||
tty->id = id;
|
||||
tty->fd = open(path, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
||||
|
||||
if (tty->fd < 0)
|
||||
{
|
||||
perror("open");
|
||||
DEBUG_WARN("failed to open device %s", path);
|
||||
serial_tty_free(tty) ;
|
||||
serial_tty_free(tty);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_SVC("tty fd %d successfully opened", tty->fd);
|
||||
}
|
||||
|
||||
tty->ptermios = (struct termios*) malloc(sizeof(struct termios));
|
||||
ZeroMemory(tty->ptermios, sizeof(struct termios));
|
||||
|
||||
tty->ptermios = (struct termios*) xzalloc(sizeof(struct termios));
|
||||
if (tty->ptermios == NULL)
|
||||
{
|
||||
serial_tty_free(tty) ;
|
||||
serial_tty_free(tty);
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
tty->pold_termios = (struct termios*) xzalloc(sizeof(struct termios));
|
||||
tty->pold_termios = (struct termios*) malloc(sizeof(struct termios));
|
||||
ZeroMemory(tty->pold_termios, sizeof(struct termios));
|
||||
|
||||
if (tty->pold_termios == NULL)
|
||||
{
|
||||
serial_tty_free(tty) ;
|
||||
return NULL ;
|
||||
serial_tty_free(tty);
|
||||
return NULL;
|
||||
}
|
||||
tcgetattr(tty->fd, tty->pold_termios);
|
||||
|
||||
|
@ -499,7 +509,7 @@ SERIAL_TTY* serial_tty_new(const char* path, UINT32 id)
|
|||
{
|
||||
DEBUG_WARN("%s access denied", path);
|
||||
fflush(stdout);
|
||||
serial_tty_free(tty) ;
|
||||
serial_tty_free(tty);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -976,6 +986,7 @@ static UINT32 tty_write_data(SERIAL_TTY* tty, BYTE* data, int len)
|
|||
DEBUG_SVC("in");
|
||||
|
||||
r = write(tty->fd, data, len);
|
||||
|
||||
if (r < 0)
|
||||
return tty_get_error_status();
|
||||
|
||||
|
|
|
@ -27,9 +27,9 @@
|
|||
#include <string.h>
|
||||
|
||||
#include <freerdp/constants.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/server/channels.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
|
||||
#include "channels.h"
|
||||
|
@ -99,7 +99,9 @@ static void wts_queue_receive_data(rdpPeerChannel* channel, const BYTE* buffer,
|
|||
{
|
||||
wts_data_item* item;
|
||||
|
||||
item = xnew(wts_data_item);
|
||||
item = (wts_data_item*) malloc(sizeof(wts_data_item));
|
||||
ZeroMemory(item, sizeof(wts_data_item));
|
||||
|
||||
item->length = length;
|
||||
item->buffer = malloc(length);
|
||||
memcpy(item->buffer, buffer, length);
|
||||
|
@ -174,7 +176,7 @@ static void wts_read_drdynvc_create_response(rdpPeerChannel* channel, STREAM* s,
|
|||
|
||||
if ((INT32) CreationStatus < 0)
|
||||
{
|
||||
DEBUG_DVC("ChannelId %d creation failed (%d)", channel->channel_id, (INT32)CreationStatus);
|
||||
DEBUG_DVC("ChannelId %d creation failed (%d)", channel->channel_id, (INT32) CreationStatus);
|
||||
channel->dvc_open_state = DVC_OPEN_STATE_FAILED;
|
||||
}
|
||||
else
|
||||
|
@ -388,14 +390,14 @@ static int WTSReceiveChannelData(freerdp_peer* client, int channelId, BYTE* data
|
|||
BOOL result = FALSE;
|
||||
rdpPeerChannel* channel;
|
||||
|
||||
for (i = 0; i < client->settings->num_channels; i++)
|
||||
for (i = 0; i < client->settings->ChannelCount; i++)
|
||||
{
|
||||
if (client->settings->channels[i].channel_id == channelId)
|
||||
if (client->settings->ChannelDefArray[i].ChannelId == channelId)
|
||||
break;
|
||||
}
|
||||
if (i < client->settings->num_channels)
|
||||
if (i < client->settings->ChannelCount)
|
||||
{
|
||||
channel = (rdpPeerChannel*) client->settings->channels[i].handle;
|
||||
channel = (rdpPeerChannel*) client->settings->ChannelDefArray[i].handle;
|
||||
|
||||
if (channel != NULL)
|
||||
{
|
||||
|
@ -411,10 +413,12 @@ WTSVirtualChannelManager* WTSCreateVirtualChannelManager(freerdp_peer* client)
|
|||
{
|
||||
WTSVirtualChannelManager* vcm;
|
||||
|
||||
vcm = xnew(WTSVirtualChannelManager);
|
||||
vcm = (WTSVirtualChannelManager*) malloc(sizeof(WTSVirtualChannelManager));
|
||||
|
||||
if (vcm != NULL)
|
||||
{
|
||||
ZeroMemory(vcm, sizeof(WTSVirtualChannelManager));
|
||||
|
||||
vcm->client = client;
|
||||
vcm->send_event = wait_obj_new();
|
||||
vcm->send_queue = list_new();
|
||||
|
@ -535,11 +539,13 @@ void* WTSVirtualChannelOpenEx(
|
|||
return NULL;
|
||||
}
|
||||
|
||||
channel = xnew(rdpPeerChannel);
|
||||
channel = (rdpPeerChannel*) malloc(sizeof(rdpPeerChannel));
|
||||
ZeroMemory(channel, sizeof(rdpPeerChannel));
|
||||
|
||||
channel->vcm = vcm;
|
||||
channel->client = client;
|
||||
channel->channel_type = RDP_PEER_CHANNEL_TYPE_DVC;
|
||||
channel->receive_data = stream_new(client->settings->vc_chunk_size);
|
||||
channel->receive_data = stream_new(client->settings->VirtualChannelChunkSize);
|
||||
channel->receive_event = wait_obj_new();
|
||||
channel->receive_queue = list_new();
|
||||
channel->mutex = CreateMutex(NULL, FALSE, NULL);
|
||||
|
@ -563,34 +569,36 @@ void* WTSVirtualChannelOpenEx(
|
|||
if (len > 8)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < client->settings->num_channels; i++)
|
||||
for (i = 0; i < client->settings->ChannelCount; i++)
|
||||
{
|
||||
if (client->settings->channels[i].joined &&
|
||||
strncmp(client->settings->channels[i].name, pVirtualName, len) == 0)
|
||||
if (client->settings->ChannelDefArray[i].joined &&
|
||||
strncmp(client->settings->ChannelDefArray[i].Name, pVirtualName, len) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= client->settings->num_channels)
|
||||
if (i >= client->settings->ChannelCount)
|
||||
return NULL;
|
||||
|
||||
channel = (rdpPeerChannel*) client->settings->channels[i].handle;
|
||||
channel = (rdpPeerChannel*) client->settings->ChannelDefArray[i].handle;
|
||||
|
||||
if (channel == NULL)
|
||||
{
|
||||
channel = xnew(rdpPeerChannel);
|
||||
channel = (rdpPeerChannel*) malloc(sizeof(rdpPeerChannel));
|
||||
ZeroMemory(channel, sizeof(rdpPeerChannel));
|
||||
|
||||
channel->vcm = vcm;
|
||||
channel->client = client;
|
||||
channel->channel_id = client->settings->channels[i].channel_id;
|
||||
channel->channel_id = client->settings->ChannelDefArray[i].ChannelId;
|
||||
channel->index = i;
|
||||
channel->channel_type = RDP_PEER_CHANNEL_TYPE_SVC;
|
||||
channel->receive_data = stream_new(client->settings->vc_chunk_size);
|
||||
channel->receive_data = stream_new(client->settings->VirtualChannelChunkSize);
|
||||
channel->receive_event = wait_obj_new();
|
||||
channel->receive_queue = list_new();
|
||||
channel->mutex = CreateMutex(NULL, FALSE, NULL);
|
||||
|
||||
client->settings->channels[i].handle = channel;
|
||||
client->settings->ChannelDefArray[i].handle = channel;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -718,7 +726,9 @@ BOOL WTSVirtualChannelWrite(
|
|||
|
||||
if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_SVC)
|
||||
{
|
||||
item = xnew(wts_data_item);
|
||||
item = (wts_data_item*) malloc(sizeof(wts_data_item));
|
||||
ZeroMemory(item, sizeof(wts_data_item));
|
||||
|
||||
item->buffer = malloc(Length);
|
||||
item->length = Length;
|
||||
memcpy(item->buffer, Buffer, Length);
|
||||
|
@ -737,9 +747,11 @@ BOOL WTSVirtualChannelWrite(
|
|||
|
||||
while (Length > 0)
|
||||
{
|
||||
item = xnew(wts_data_item);
|
||||
item->buffer = malloc(channel->client->settings->vc_chunk_size);
|
||||
stream_attach(s, item->buffer, channel->client->settings->vc_chunk_size);
|
||||
item = (wts_data_item*) malloc(sizeof(wts_data_item));
|
||||
ZeroMemory(item, sizeof(wts_data_item));
|
||||
|
||||
item->buffer = malloc(channel->client->settings->VirtualChannelChunkSize);
|
||||
stream_attach(s, item->buffer, channel->client->settings->VirtualChannelChunkSize);
|
||||
|
||||
stream_seek_BYTE(s);
|
||||
cbChId = wts_write_variable_uint(s, channel->channel_id);
|
||||
|
@ -791,8 +803,8 @@ BOOL WTSVirtualChannelClose(
|
|||
|
||||
if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_SVC)
|
||||
{
|
||||
if (channel->index < channel->client->settings->num_channels)
|
||||
channel->client->settings->channels[channel->index].handle = NULL;
|
||||
if (channel->index < channel->client->settings->ChannelCount)
|
||||
channel->client->settings->ChannelDefArray[channel->index].handle = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -8,10 +8,6 @@ if(WITH_PCSC)
|
|||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
endif()
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "smartcard" TYPE "device"
|
||||
DESCRIPTION "Smart Card Virtual Channel Extension"
|
||||
SPECIFICATIONS "[MS-RDPESC]"
|
||||
|
|
|
@ -18,8 +18,9 @@
|
|||
define_channel_client("smartcard")
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
scard_main.c
|
||||
scard_operations.c)
|
||||
smartcard_main.c
|
||||
smartcard_main.h
|
||||
smartcard_operations.c)
|
||||
|
||||
include_directories(${PCSC_INCLUDE_DIR})
|
||||
|
||||
|
@ -46,3 +47,4 @@ if(NOT STATIC_CHANNELS)
|
|||
endif()
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")
|
||||
|
||||
|
|
|
@ -1,332 +0,0 @@
|
|||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Smartcard Device Service Virtual Channel
|
||||
*
|
||||
* Copyright 2011 O.S. Systems Software Ltda.
|
||||
* Copyright 2011 Eduardo Fiss Beloni <beloni@ossystems.com.br>
|
||||
* Copyright 2011 Anthony Tong <atong@trustedcs.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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <freerdp/utils/list.h>
|
||||
#include <freerdp/utils/thread.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
#include <freerdp/utils/debug.h>
|
||||
#include <freerdp/channels/rdpdr.h>
|
||||
|
||||
#include "scard_main.h"
|
||||
|
||||
static void scard_free(DEVICE* dev)
|
||||
{
|
||||
IRP* irp;
|
||||
COMPLETIONIDINFO* CompletionIdInfo;
|
||||
SCARD_DEVICE* scard = (SCARD_DEVICE*) dev;
|
||||
|
||||
freerdp_thread_stop(scard->thread);
|
||||
freerdp_thread_free(scard->thread);
|
||||
|
||||
while ((irp = (IRP*) InterlockedPopEntrySList(scard->pIrpList)) != NULL)
|
||||
irp->Discard(irp);
|
||||
|
||||
_aligned_free(scard->pIrpList);
|
||||
|
||||
/* Begin TS Client defect workaround. */
|
||||
|
||||
while ((CompletionIdInfo = (COMPLETIONIDINFO*) list_dequeue(scard->CompletionIds)) != NULL)
|
||||
free(CompletionIdInfo);
|
||||
|
||||
list_free(scard->CompletionIds);
|
||||
|
||||
/* End TS Client defect workaround. */
|
||||
|
||||
free(dev);
|
||||
return;
|
||||
}
|
||||
|
||||
static void scard_process_irp(SCARD_DEVICE* scard, IRP* irp)
|
||||
{
|
||||
switch (irp->MajorFunction)
|
||||
{
|
||||
case IRP_MJ_DEVICE_CONTROL:
|
||||
scard_device_control(scard, irp);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("MajorFunction 0x%X unexpected for smartcards.", irp->MajorFunction);
|
||||
DEBUG_WARN("Smartcard MajorFunction 0x%X not supported.", irp->MajorFunction);
|
||||
irp->IoStatus = STATUS_NOT_SUPPORTED;
|
||||
irp->Complete(irp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void scard_process_irp_list(SCARD_DEVICE* scard)
|
||||
{
|
||||
IRP* irp;
|
||||
|
||||
while (!freerdp_thread_is_stopped(scard->thread))
|
||||
{
|
||||
irp = (IRP*) InterlockedPopEntrySList(scard->pIrpList);
|
||||
|
||||
if (irp == NULL)
|
||||
break;
|
||||
|
||||
scard_process_irp(scard, irp);
|
||||
}
|
||||
}
|
||||
|
||||
struct scard_irp_thread_args
|
||||
{
|
||||
SCARD_DEVICE* scard;
|
||||
IRP* irp;
|
||||
freerdp_thread* thread;
|
||||
};
|
||||
|
||||
static void scard_process_irp_thread_func(struct scard_irp_thread_args* args)
|
||||
{
|
||||
scard_process_irp(args->scard, args->irp);
|
||||
|
||||
freerdp_thread_free(args->thread);
|
||||
free(args);
|
||||
}
|
||||
|
||||
static void* scard_thread_func(void* arg)
|
||||
{
|
||||
SCARD_DEVICE* scard = (SCARD_DEVICE*) arg;
|
||||
|
||||
while (1)
|
||||
{
|
||||
freerdp_thread_wait(scard->thread);
|
||||
|
||||
if (freerdp_thread_is_stopped(scard->thread))
|
||||
break;
|
||||
|
||||
freerdp_thread_reset(scard->thread);
|
||||
scard_process_irp_list(scard);
|
||||
}
|
||||
|
||||
freerdp_thread_quit(scard->thread);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Begin TS Client defect workaround. */
|
||||
static COMPLETIONIDINFO* scard_mark_duplicate_id(SCARD_DEVICE* scard, UINT32 CompletionId)
|
||||
{
|
||||
/*
|
||||
* Search from the beginning of the LIST for one outstanding "CompletionID"
|
||||
* that matches the one passed in. If there is one, mark it as a duplicate
|
||||
* if it is not already marked.
|
||||
*/
|
||||
LIST_ITEM* item;
|
||||
COMPLETIONIDINFO* CompletionIdInfo;
|
||||
|
||||
for (item = scard->CompletionIds->head; item; item = item->next)
|
||||
{
|
||||
CompletionIdInfo = (COMPLETIONIDINFO*)item->data;
|
||||
if (CompletionIdInfo->ID == CompletionId)
|
||||
{
|
||||
if (FALSE == CompletionIdInfo->duplicate)
|
||||
{
|
||||
CompletionIdInfo->duplicate = TRUE;
|
||||
DEBUG_WARN("CompletionID number %u is now marked as a duplicate.", CompletionId);
|
||||
}
|
||||
return CompletionIdInfo;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL; /* Either no items in the list or no match. */
|
||||
}
|
||||
|
||||
static BOOL scard_check_for_duplicate_id(SCARD_DEVICE* scard, UINT32 CompletionId)
|
||||
{
|
||||
/*
|
||||
* Search from the end of the LIST for one outstanding "CompletionID"
|
||||
* that matches the one passed in. Remove it from the list and free the
|
||||
* memory associated with it. Return whether or not it was marked
|
||||
* as a duplicate.
|
||||
*/
|
||||
LIST_ITEM* item;
|
||||
COMPLETIONIDINFO* CompletionIdInfo;
|
||||
BOOL duplicate;
|
||||
|
||||
for (item = scard->CompletionIds->tail; item; item = item->prev)
|
||||
{
|
||||
CompletionIdInfo = (COMPLETIONIDINFO*)item->data;
|
||||
if (CompletionIdInfo->ID == CompletionId)
|
||||
{
|
||||
duplicate = CompletionIdInfo->duplicate;
|
||||
if (TRUE == duplicate)
|
||||
{
|
||||
DEBUG_WARN("CompletionID number %u was previously marked as a duplicate. The response to the command is removed.", CompletionId);
|
||||
}
|
||||
list_remove(scard->CompletionIds, CompletionIdInfo);
|
||||
free(CompletionIdInfo);
|
||||
return duplicate;
|
||||
}
|
||||
}
|
||||
|
||||
/* This function should only be called when there is
|
||||
* at least one outstanding CompletionID item in the list.
|
||||
*/
|
||||
DEBUG_WARN("Error!!! No CompletionIDs (or no matching IDs) in the list!");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void scard_irp_complete(IRP* irp)
|
||||
{
|
||||
/* This function is (mostly) a copy of the statically-declared "irp_complete()"
|
||||
* function except that this function adds extra operations for the
|
||||
* smart card's handling of duplicate "CompletionID"s. This function needs
|
||||
* to be in this file so that "scard_irp_request()" can reference it.
|
||||
*/
|
||||
int pos;
|
||||
BOOL duplicate;
|
||||
SCARD_DEVICE* scard = (SCARD_DEVICE*)irp->device;
|
||||
|
||||
DEBUG_SVC("DeviceId %d FileId %d CompletionId %d", irp->device->id, irp->FileId, irp->CompletionId);
|
||||
|
||||
pos = stream_get_pos(irp->output);
|
||||
stream_set_pos(irp->output, 12);
|
||||
stream_write_UINT32(irp->output, irp->IoStatus);
|
||||
stream_set_pos(irp->output, pos);
|
||||
|
||||
/* Begin TS Client defect workaround. */
|
||||
WaitForSingleObject(scard->CompletionIdsMutex, INFINITE);
|
||||
/* Remove from the list the item identified by the CompletionID.
|
||||
* The function returns whether or not it was a duplicate CompletionID.
|
||||
*/
|
||||
duplicate = scard_check_for_duplicate_id(scard, irp->CompletionId);
|
||||
ReleaseMutex(scard->CompletionIdsMutex);
|
||||
|
||||
if (FALSE == duplicate)
|
||||
{
|
||||
svc_plugin_send(irp->devman->plugin, irp->output);
|
||||
irp->output = NULL;
|
||||
}
|
||||
/* End TS Client defect workaround. */
|
||||
|
||||
/* irp_free(irp); The "irp_free()" function is statically-declared
|
||||
* and so is not available to be called
|
||||
* here. Instead, call it indirectly by calling
|
||||
* the IRP's "Discard()" function,
|
||||
* which has already been assigned
|
||||
* to point to "irp_free()" in "irp_new()".
|
||||
*/
|
||||
irp->Discard(irp);
|
||||
}
|
||||
/* End TS Client defect workaround. */
|
||||
|
||||
static void scard_irp_request(DEVICE* device, IRP* irp)
|
||||
{
|
||||
COMPLETIONIDINFO* CompletionIdInfo;
|
||||
SCARD_DEVICE* scard = (SCARD_DEVICE*) device;
|
||||
|
||||
/* Begin TS Client defect workaround. */
|
||||
CompletionIdInfo= xnew(COMPLETIONIDINFO);
|
||||
CompletionIdInfo->ID = irp->CompletionId;/* "duplicate" member is set
|
||||
* to FALSE by "xnew()"
|
||||
*/
|
||||
WaitForSingleObject(scard->CompletionIdsMutex, INFINITE);
|
||||
scard_mark_duplicate_id(scard, irp->CompletionId);
|
||||
list_enqueue(scard->CompletionIds, CompletionIdInfo);
|
||||
ReleaseMutex(scard->CompletionIdsMutex);
|
||||
|
||||
irp->Complete = scard_irp_complete; /* Overwrite the previous
|
||||
* assignment made in
|
||||
* "irp_new()".
|
||||
*/
|
||||
/* End TS Client defect workaround. */
|
||||
|
||||
if (irp->MajorFunction == IRP_MJ_DEVICE_CONTROL &&
|
||||
scard_async_op(irp))
|
||||
{
|
||||
/*
|
||||
* certain potentially long running operations
|
||||
* get their own thread
|
||||
* TODO: revise this mechanism.. maybe worker pool
|
||||
*/
|
||||
struct scard_irp_thread_args *args = malloc(sizeof(struct scard_irp_thread_args));
|
||||
|
||||
|
||||
args->thread = freerdp_thread_new();
|
||||
args->scard = scard;
|
||||
args->irp = irp;
|
||||
freerdp_thread_start(args->thread, scard_process_irp_thread_func, args);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
InterlockedPushEntrySList(scard->pIrpList, &(irp->ItemEntry));
|
||||
|
||||
freerdp_thread_signal(scard->thread);
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define DeviceServiceEntry smartcard_DeviceServiceEntry
|
||||
#endif
|
||||
|
||||
int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
char* name;
|
||||
char* path;
|
||||
int i, length;
|
||||
SCARD_DEVICE* scard;
|
||||
|
||||
name = (char*) pEntryPoints->plugin_data->data[1];
|
||||
path = (char*) pEntryPoints->plugin_data->data[2];
|
||||
|
||||
if (name)
|
||||
{
|
||||
/* TODO: check if server supports sc redirect (version 5.1) */
|
||||
|
||||
scard = xnew(SCARD_DEVICE);
|
||||
|
||||
scard->device.type = RDPDR_DTYP_SMARTCARD;
|
||||
scard->device.name = "SCARD";
|
||||
scard->device.IRPRequest = scard_irp_request;
|
||||
scard->device.Free = scard_free;
|
||||
|
||||
length = strlen(scard->device.name);
|
||||
scard->device.data = stream_new(length + 1);
|
||||
|
||||
for (i = 0; i <= length; i++)
|
||||
stream_write_BYTE(scard->device.data, name[i] < 0 ? '_' : name[i]);
|
||||
|
||||
scard->path = path;
|
||||
|
||||
scard->pIrpList = (PSLIST_HEADER) _aligned_malloc(sizeof(SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT);
|
||||
InitializeSListHead(scard->pIrpList);
|
||||
|
||||
scard->thread = freerdp_thread_new();
|
||||
|
||||
scard->CompletionIds = list_new();
|
||||
scard->CompletionIdsMutex = CreateMutex(NULL, FALSE, NULL);
|
||||
|
||||
pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE *)scard);
|
||||
|
||||
freerdp_thread_start(scard->thread, scard_thread_func, scard);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,353 @@
|
|||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Smartcard Device Service Virtual Channel
|
||||
*
|
||||
* Copyright 2011 O.S. Systems Software Ltda.
|
||||
* Copyright 2011 Eduardo Fiss Beloni <beloni@ossystems.com.br>
|
||||
* Copyright 2011 Anthony Tong <atong@trustedcs.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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/utils/list.h>
|
||||
#include <freerdp/utils/debug.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
#include <freerdp/channels/rdpdr.h>
|
||||
|
||||
#include "smartcard_main.h"
|
||||
|
||||
static void smartcard_free(DEVICE* dev)
|
||||
{
|
||||
IRP* irp;
|
||||
COMPLETIONIDINFO* CompletionIdInfo;
|
||||
SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) dev;
|
||||
|
||||
SetEvent(smartcard->stopEvent);
|
||||
CloseHandle(smartcard->thread);
|
||||
CloseHandle(smartcard->irpEvent);
|
||||
|
||||
while ((irp = (IRP*) InterlockedPopEntrySList(smartcard->pIrpList)) != NULL)
|
||||
irp->Discard(irp);
|
||||
|
||||
_aligned_free(smartcard->pIrpList);
|
||||
|
||||
/* Begin TS Client defect workaround. */
|
||||
|
||||
while ((CompletionIdInfo = (COMPLETIONIDINFO*) list_dequeue(smartcard->CompletionIds)) != NULL)
|
||||
free(CompletionIdInfo);
|
||||
|
||||
list_free(smartcard->CompletionIds);
|
||||
|
||||
/* End TS Client defect workaround. */
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static void smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
||||
{
|
||||
switch (irp->MajorFunction)
|
||||
{
|
||||
case IRP_MJ_DEVICE_CONTROL:
|
||||
smartcard_device_control(smartcard, irp);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("MajorFunction 0x%X unexpected for smartcards.", irp->MajorFunction);
|
||||
DEBUG_WARN("Smartcard MajorFunction 0x%X not supported.", irp->MajorFunction);
|
||||
irp->IoStatus = STATUS_NOT_SUPPORTED;
|
||||
irp->Complete(irp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void smartcard_process_irp_list(SMARTCARD_DEVICE* smartcard)
|
||||
{
|
||||
IRP* irp;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (WaitForSingleObject(smartcard->stopEvent, 0) == WAIT_OBJECT_0)
|
||||
break;
|
||||
|
||||
irp = (IRP*) InterlockedPopEntrySList(smartcard->pIrpList);
|
||||
|
||||
if (irp == NULL)
|
||||
break;
|
||||
|
||||
smartcard_process_irp(smartcard, irp);
|
||||
}
|
||||
}
|
||||
|
||||
struct _SMARTCARD_IRP_WORKER
|
||||
{
|
||||
SMARTCARD_DEVICE* smartcard;
|
||||
IRP* irp;
|
||||
HANDLE thread;
|
||||
};
|
||||
typedef struct _SMARTCARD_IRP_WORKER SMARTCARD_IRP_WORKER;
|
||||
|
||||
static void smartcard_process_irp_thread_func(SMARTCARD_IRP_WORKER* irpWorker)
|
||||
{
|
||||
smartcard_process_irp(irpWorker->smartcard, irpWorker->irp);
|
||||
|
||||
CloseHandle(irpWorker->thread);
|
||||
|
||||
free(irpWorker);
|
||||
}
|
||||
|
||||
static void* smartcard_thread_func(void* arg)
|
||||
{
|
||||
SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) arg;
|
||||
|
||||
while (1)
|
||||
{
|
||||
WaitForSingleObject(smartcard->irpEvent, INFINITE);
|
||||
|
||||
if (WaitForSingleObject(smartcard->stopEvent, 0) == WAIT_OBJECT_0)
|
||||
break;
|
||||
|
||||
ResetEvent(smartcard->irpEvent);
|
||||
smartcard_process_irp_list(smartcard);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Begin TS Client defect workaround. */
|
||||
static COMPLETIONIDINFO* smartcard_mark_duplicate_id(SMARTCARD_DEVICE* smartcard, UINT32 CompletionId)
|
||||
{
|
||||
LIST_ITEM* item;
|
||||
COMPLETIONIDINFO* CompletionIdInfo;
|
||||
|
||||
/*
|
||||
* Search from the beginning of the LIST for one outstanding "CompletionID"
|
||||
* that matches the one passed in. If there is one, mark it as a duplicate
|
||||
* if it is not already marked.
|
||||
*/
|
||||
|
||||
for (item = smartcard->CompletionIds->head; item; item = item->next)
|
||||
{
|
||||
CompletionIdInfo = (COMPLETIONIDINFO*) item->data;
|
||||
|
||||
if (CompletionIdInfo->ID == CompletionId)
|
||||
{
|
||||
if (!CompletionIdInfo->duplicate)
|
||||
{
|
||||
CompletionIdInfo->duplicate = TRUE;
|
||||
DEBUG_WARN("CompletionID number %u is now marked as a duplicate.", CompletionId);
|
||||
}
|
||||
|
||||
return CompletionIdInfo;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL; /* Either no items in the list or no match. */
|
||||
}
|
||||
|
||||
static BOOL smartcard_check_for_duplicate_id(SMARTCARD_DEVICE* smartcard, UINT32 CompletionId)
|
||||
{
|
||||
BOOL duplicate;
|
||||
LIST_ITEM* item;
|
||||
COMPLETIONIDINFO* CompletionIdInfo;
|
||||
|
||||
/*
|
||||
* Search from the end of the LIST for one outstanding "CompletionID"
|
||||
* that matches the one passed in. Remove it from the list and free the
|
||||
* memory associated with it. Return whether or not it was marked
|
||||
* as a duplicate.
|
||||
*/
|
||||
|
||||
for (item = smartcard->CompletionIds->tail; item; item = item->prev)
|
||||
{
|
||||
CompletionIdInfo = (COMPLETIONIDINFO*) item->data;
|
||||
|
||||
if (CompletionIdInfo->ID == CompletionId)
|
||||
{
|
||||
duplicate = CompletionIdInfo->duplicate;
|
||||
|
||||
if (duplicate)
|
||||
{
|
||||
DEBUG_WARN("CompletionID number %u was previously marked as a duplicate.", CompletionId);
|
||||
}
|
||||
|
||||
list_remove(smartcard->CompletionIds, CompletionIdInfo);
|
||||
free(CompletionIdInfo);
|
||||
|
||||
return duplicate;
|
||||
}
|
||||
}
|
||||
|
||||
/* This function should only be called when there is
|
||||
* at least one outstanding CompletionID item in the list.
|
||||
*/
|
||||
DEBUG_WARN("Error!!! No CompletionIDs (or no matching IDs) in the list!");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void smartcard_irp_complete(IRP* irp)
|
||||
{
|
||||
int pos;
|
||||
BOOL duplicate;
|
||||
SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) irp->device;
|
||||
|
||||
/* This function is (mostly) a copy of the statically-declared "irp_complete()"
|
||||
* function except that this function adds extra operations for the
|
||||
* smart card's handling of duplicate "CompletionID"s. This function needs
|
||||
* to be in this file so that "smartcard_irp_request()" can reference it.
|
||||
*/
|
||||
|
||||
DEBUG_SVC("DeviceId %d FileId %d CompletionId %d", irp->device->id, irp->FileId, irp->CompletionId);
|
||||
|
||||
pos = stream_get_pos(irp->output);
|
||||
stream_set_pos(irp->output, 12);
|
||||
stream_write_UINT32(irp->output, irp->IoStatus);
|
||||
stream_set_pos(irp->output, pos);
|
||||
|
||||
/* Begin TS Client defect workaround. */
|
||||
WaitForSingleObject(smartcard->CompletionIdsMutex, INFINITE);
|
||||
/* Remove from the list the item identified by the CompletionID.
|
||||
* The function returns whether or not it was a duplicate CompletionID.
|
||||
*/
|
||||
duplicate = smartcard_check_for_duplicate_id(smartcard, irp->CompletionId);
|
||||
ReleaseMutex(smartcard->CompletionIdsMutex);
|
||||
|
||||
if (!duplicate)
|
||||
{
|
||||
svc_plugin_send(irp->devman->plugin, irp->output);
|
||||
irp->output = NULL;
|
||||
}
|
||||
|
||||
/* End TS Client defect workaround. */
|
||||
|
||||
/* irp_free(irp); The "irp_free()" function is statically-declared
|
||||
* and so is not available to be called
|
||||
* here. Instead, call it indirectly by calling
|
||||
* the IRP's "Discard()" function,
|
||||
* which has already been assigned
|
||||
* to point to "irp_free()" in "irp_new()".
|
||||
*/
|
||||
irp->Discard(irp);
|
||||
}
|
||||
/* End TS Client defect workaround. */
|
||||
|
||||
static void smartcard_irp_request(DEVICE* device, IRP* irp)
|
||||
{
|
||||
COMPLETIONIDINFO* CompletionIdInfo;
|
||||
SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) device;
|
||||
|
||||
/* Begin TS Client defect workaround. */
|
||||
|
||||
CompletionIdInfo = (COMPLETIONIDINFO*) malloc(sizeof(COMPLETIONIDINFO));
|
||||
ZeroMemory(CompletionIdInfo, sizeof(COMPLETIONIDINFO));
|
||||
|
||||
CompletionIdInfo->ID = irp->CompletionId;
|
||||
|
||||
WaitForSingleObject(smartcard->CompletionIdsMutex, INFINITE);
|
||||
smartcard_mark_duplicate_id(smartcard, irp->CompletionId);
|
||||
list_enqueue(smartcard->CompletionIds, CompletionIdInfo);
|
||||
ReleaseMutex(smartcard->CompletionIdsMutex);
|
||||
|
||||
/* Overwrite the previous assignment made in irp_new() */
|
||||
irp->Complete = smartcard_irp_complete;
|
||||
|
||||
/* End TS Client defect workaround. */
|
||||
|
||||
if ((irp->MajorFunction == IRP_MJ_DEVICE_CONTROL) && smartcard_async_op(irp))
|
||||
{
|
||||
/* certain potentially long running operations get their own thread */
|
||||
SMARTCARD_IRP_WORKER* irpWorker = malloc(sizeof(SMARTCARD_IRP_WORKER));
|
||||
|
||||
irpWorker->thread = CreateThread(NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE) smartcard_process_irp_thread_func,
|
||||
irpWorker, CREATE_SUSPENDED, NULL);
|
||||
|
||||
irpWorker->smartcard = smartcard;
|
||||
irpWorker->irp = irp;
|
||||
|
||||
ResumeThread(irpWorker->thread);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
InterlockedPushEntrySList(smartcard->pIrpList, &(irp->ItemEntry));
|
||||
|
||||
SetEvent(smartcard->irpEvent);
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define DeviceServiceEntry smartcard_DeviceServiceEntry
|
||||
#endif
|
||||
|
||||
int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
char* name;
|
||||
char* path;
|
||||
int i, length;
|
||||
RDPDR_SMARTCARD* device;
|
||||
SMARTCARD_DEVICE* smartcard;
|
||||
|
||||
device = (RDPDR_SMARTCARD*) pEntryPoints->device;
|
||||
name = device->Name;
|
||||
path = device->Path;
|
||||
|
||||
if (name)
|
||||
{
|
||||
/* TODO: check if server supports sc redirect (version 5.1) */
|
||||
|
||||
smartcard = (SMARTCARD_DEVICE*) malloc(sizeof(SMARTCARD_DEVICE));
|
||||
ZeroMemory(smartcard, sizeof(SMARTCARD_DEVICE));
|
||||
|
||||
smartcard->device.type = RDPDR_DTYP_SMARTCARD;
|
||||
smartcard->device.name = "SCARD";
|
||||
smartcard->device.IRPRequest = smartcard_irp_request;
|
||||
smartcard->device.Free = smartcard_free;
|
||||
|
||||
length = strlen(smartcard->device.name);
|
||||
smartcard->device.data = stream_new(length + 1);
|
||||
|
||||
for (i = 0; i <= length; i++)
|
||||
stream_write_BYTE(smartcard->device.data, name[i] < 0 ? '_' : name[i]);
|
||||
|
||||
smartcard->path = path;
|
||||
|
||||
smartcard->pIrpList = (PSLIST_HEADER) _aligned_malloc(sizeof(SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT);
|
||||
InitializeSListHead(smartcard->pIrpList);
|
||||
|
||||
smartcard->irpEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
smartcard->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
smartcard->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) smartcard_thread_func,
|
||||
smartcard, CREATE_SUSPENDED, NULL);
|
||||
|
||||
smartcard->CompletionIds = list_new();
|
||||
smartcard->CompletionIdsMutex = CreateMutex(NULL, FALSE, NULL);
|
||||
|
||||
pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) smartcard);
|
||||
|
||||
ResumeThread(smartcard->thread);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -18,8 +18,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __SCARD_MAIN_H
|
||||
#define __SCARD_MAIN_H
|
||||
#ifndef FREERDP_CHANNEL_SMARTCARD_CLIENT_MAIN_H
|
||||
#define FREERDP_CHANNEL_SMARTCARD_CLIENT_MAIN_H
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
|||
#include <freerdp/utils/debug.h>
|
||||
#include <freerdp/channels/rdpdr.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
|
||||
/*
|
||||
|
@ -81,6 +82,7 @@
|
|||
* This structure tracks outstanding Terminal Services server "CompletionIDs"
|
||||
* used by the redirected smart card device.
|
||||
*/
|
||||
|
||||
struct _COMPLETIONIDINFO
|
||||
{
|
||||
UINT32 ID; /* CompletionID */
|
||||
|
@ -89,11 +91,9 @@ struct _COMPLETIONIDINFO
|
|||
* earlier, outstanding, CompletionID.
|
||||
*/
|
||||
};
|
||||
|
||||
typedef struct _COMPLETIONIDINFO COMPLETIONIDINFO;
|
||||
|
||||
|
||||
struct _SCARD_DEVICE
|
||||
struct _SMARTCARD_DEVICE
|
||||
{
|
||||
DEVICE device;
|
||||
|
||||
|
@ -102,12 +102,14 @@ struct _SCARD_DEVICE
|
|||
|
||||
PSLIST_HEADER pIrpList;
|
||||
|
||||
freerdp_thread* thread;
|
||||
HANDLE thread;
|
||||
HANDLE irpEvent;
|
||||
HANDLE stopEvent;
|
||||
|
||||
LIST* CompletionIds;
|
||||
HANDLE CompletionIdsMutex;
|
||||
};
|
||||
typedef struct _SCARD_DEVICE SCARD_DEVICE;
|
||||
typedef struct _SMARTCARD_DEVICE SMARTCARD_DEVICE;
|
||||
|
||||
#ifdef WITH_DEBUG_SCARD
|
||||
#define DEBUG_SCARD(fmt, ...) DEBUG_CLASS(SCARD, fmt, ## __VA_ARGS__)
|
||||
|
@ -115,7 +117,7 @@ typedef struct _SCARD_DEVICE SCARD_DEVICE;
|
|||
#define DEBUG_SCARD(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
BOOL scard_async_op(IRP*);
|
||||
void scard_device_control(SCARD_DEVICE*, IRP*);
|
||||
BOOL smartcard_async_op(IRP*);
|
||||
void smartcard_device_control(SMARTCARD_DEVICE*, IRP*);
|
||||
|
||||
#endif
|
||||
#endif /* FREERDP_CHANNEL_SMARTCARD_CLIENT_MAIN_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -20,5 +20,3 @@ define_channel("tsmf")
|
|||
if(WITH_CLIENT_CHANNELS)
|
||||
add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
|
||||
endif()
|
||||
|
||||
|
||||
|
|
|
@ -13,10 +13,6 @@ if(ANDROID)
|
|||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
endif()
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "tsmf" TYPE "dynamic"
|
||||
DESCRIPTION "Video Redirection Virtual Channel Extension"
|
||||
SPECIFICATIONS "[MS-RDPEV]"
|
||||
|
|
|
@ -43,7 +43,7 @@ set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
|||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE freerdp
|
||||
MODULES freerdp-utils)
|
||||
MODULES freerdp-utils freerdp-common)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
|
@ -54,19 +54,19 @@ endif()
|
|||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")
|
||||
|
||||
if(WITH_FFMPEG)
|
||||
add_subdirectory(ffmpeg)
|
||||
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "ffmpeg" "decoder")
|
||||
endif()
|
||||
|
||||
if(WITH_XRANDR)
|
||||
if(GSTREAMER_FOUND)
|
||||
add_subdirectory(gstreamer)
|
||||
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "gstreamer" "decoder")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_ALSA)
|
||||
add_subdirectory(alsa)
|
||||
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "alsa" "audio")
|
||||
endif()
|
||||
|
||||
if(WITH_PULSE)
|
||||
add_subdirectory(pulse)
|
||||
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "pulse" "audio")
|
||||
endif()
|
||||
|
|
|
@ -23,7 +23,7 @@ set(${MODULE_PREFIX}_SRCS
|
|||
include_directories(..)
|
||||
include_directories(${ALSA_INCLUDE_DIRS})
|
||||
|
||||
add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
|
@ -36,6 +36,6 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${ALSA_LIBRARIES})
|
|||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
|
||||
|
||||
|
||||
if(NOT STATIC_CHANNELS)
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
|
||||
endif()
|
||||
|
|
|
@ -26,9 +26,12 @@
|
|||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/dsp.h>
|
||||
|
||||
#include "tsmf_audio.h"
|
||||
|
@ -248,11 +251,16 @@ static void tsmf_alsa_free(ITSMFAudioDevice* audio)
|
|||
free(alsa);
|
||||
}
|
||||
|
||||
ITSMFAudioDevice* TSMFAudioDeviceEntry(void)
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_tsmf_client_audio_subsystem_entry alsa_freerdp_tsmf_client_audio_subsystem_entry
|
||||
#endif
|
||||
|
||||
ITSMFAudioDevice* freerdp_tsmf_client_audio_subsystem_entry(void)
|
||||
{
|
||||
TSMFALSAAudioDevice* alsa;
|
||||
|
||||
alsa = xnew(TSMFALSAAudioDevice);
|
||||
alsa = (TSMFALSAAudioDevice*) malloc(sizeof(TSMFALSAAudioDevice));
|
||||
ZeroMemory(alsa, sizeof(TSMFALSAAudioDevice));
|
||||
|
||||
alsa->iface.Open = tsmf_alsa_open;
|
||||
alsa->iface.SetFormat = tsmf_alsa_set_format;
|
||||
|
@ -265,4 +273,3 @@ ITSMFAudioDevice* TSMFAudioDeviceEntry(void)
|
|||
|
||||
return (ITSMFAudioDevice*) alsa;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
define_channel_client_subsystem("tsmf" "ffmpeg" "video")
|
||||
define_channel_client_subsystem("tsmf" "ffmpeg" "decoder")
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
tsmf_ffmpeg.c)
|
||||
|
@ -23,7 +23,7 @@ set(${MODULE_PREFIX}_SRCS
|
|||
include_directories(..)
|
||||
include_directories(${FFMPEG_INCLUDE_DIRS})
|
||||
|
||||
add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
|
@ -36,4 +36,6 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${FFMPEG_LIBRARIES})
|
|||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
|
||||
if(NOT STATIC_CHANNELS)
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
|
||||
endif()
|
||||
|
|
|
@ -25,7 +25,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/utils/event.h>
|
||||
#include <freerdp/client/tsmf.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
|
@ -60,6 +61,7 @@ static BOOL tsmf_ffmpeg_init_context(ITSMFDecoder* decoder)
|
|||
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
|
||||
|
||||
mdecoder->codec_context = avcodec_alloc_context3(NULL);
|
||||
|
||||
if (!mdecoder->codec_context)
|
||||
{
|
||||
DEBUG_WARN("avcodec_alloc_context failed.");
|
||||
|
@ -108,12 +110,13 @@ static BOOL tsmf_ffmpeg_init_audio_stream(ITSMFDecoder* decoder, const TS_AM_MED
|
|||
|
||||
static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE* media_type)
|
||||
{
|
||||
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
|
||||
BYTE* p;
|
||||
UINT32 size;
|
||||
const BYTE* s;
|
||||
BYTE* p;
|
||||
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
|
||||
|
||||
mdecoder->codec = avcodec_find_decoder(mdecoder->codec_id);
|
||||
|
||||
if (!mdecoder->codec)
|
||||
{
|
||||
DEBUG_WARN("avcodec_find_decoder failed.");
|
||||
|
@ -142,7 +145,8 @@ static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYP
|
|||
/* The extradata format that FFmpeg uses is following CodecPrivate in Matroska.
|
||||
See http://haali.su/mkv/codecs.pdf */
|
||||
mdecoder->codec_context->extradata_size = media_type->ExtraDataSize + 8;
|
||||
mdecoder->codec_context->extradata = xzalloc(mdecoder->codec_context->extradata_size);
|
||||
mdecoder->codec_context->extradata = malloc(mdecoder->codec_context->extradata_size);
|
||||
ZeroMemory(mdecoder->codec_context->extradata, mdecoder->codec_context->extradata_size);
|
||||
p = mdecoder->codec_context->extradata;
|
||||
*p++ = 1; /* Reserved? */
|
||||
*p++ = media_type->ExtraData[8]; /* Profile */
|
||||
|
@ -163,7 +167,8 @@ static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYP
|
|||
{
|
||||
/* Add a padding to avoid invalid memory read in some codec */
|
||||
mdecoder->codec_context->extradata_size = media_type->ExtraDataSize + 8;
|
||||
mdecoder->codec_context->extradata = xzalloc(mdecoder->codec_context->extradata_size);
|
||||
mdecoder->codec_context->extradata = malloc(mdecoder->codec_context->extradata_size);
|
||||
ZeroMemory(mdecoder->codec_context->extradata, mdecoder->codec_context->extradata_size);
|
||||
memcpy(mdecoder->codec_context->extradata, media_type->ExtraData, media_type->ExtraDataSize);
|
||||
memset(mdecoder->codec_context->extradata + media_type->ExtraDataSize, 0, 8);
|
||||
}
|
||||
|
@ -303,13 +308,14 @@ static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder* decoder, const BYTE* data, UI
|
|||
|
||||
mdecoder->decoded_size = avpicture_get_size(mdecoder->codec_context->pix_fmt,
|
||||
mdecoder->codec_context->width, mdecoder->codec_context->height);
|
||||
mdecoder->decoded_data = xzalloc(mdecoder->decoded_size);
|
||||
mdecoder->decoded_data = malloc(mdecoder->decoded_size);
|
||||
ZeroMemory(mdecoder->decoded_data, mdecoder->decoded_size);
|
||||
frame = avcodec_alloc_frame();
|
||||
avpicture_fill((AVPicture *) frame, mdecoder->decoded_data,
|
||||
avpicture_fill((AVPicture*) frame, mdecoder->decoded_data,
|
||||
mdecoder->codec_context->pix_fmt,
|
||||
mdecoder->codec_context->width, mdecoder->codec_context->height);
|
||||
|
||||
av_picture_copy((AVPicture *) frame, (AVPicture *) mdecoder->frame,
|
||||
av_picture_copy((AVPicture*) frame, (AVPicture*) mdecoder->frame,
|
||||
mdecoder->codec_context->pix_fmt,
|
||||
mdecoder->codec_context->width, mdecoder->codec_context->height);
|
||||
|
||||
|
@ -343,9 +349,10 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE* data, UI
|
|||
|
||||
if (mdecoder->decoded_size_max == 0)
|
||||
mdecoder->decoded_size_max = AVCODEC_MAX_AUDIO_FRAME_SIZE + 16;
|
||||
mdecoder->decoded_data = xzalloc(mdecoder->decoded_size_max);
|
||||
mdecoder->decoded_data = malloc(mdecoder->decoded_size_max);
|
||||
ZeroMemory(mdecoder->decoded_data, mdecoder->decoded_size_max);
|
||||
/* align the memory for SSE2 needs */
|
||||
dst = (BYTE*) (((uintptr_t)mdecoder->decoded_data + 15) & ~ 0x0F);
|
||||
dst = (BYTE*) (((uintptr_t) mdecoder->decoded_data + 15) & ~ 0x0F);
|
||||
dst_offset = dst - mdecoder->decoded_data;
|
||||
src = data;
|
||||
src_size = data_size;
|
||||
|
@ -373,7 +380,7 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE* data, UI
|
|||
(int16_t*) dst, &frame_size, src, src_size);
|
||||
#else
|
||||
{
|
||||
AVFrame* decoded_frame = avcodec_alloc_frame();
|
||||
AVFrame* decoded_frame = avcodec_alloc_frame();
|
||||
int got_frame = 0;
|
||||
AVPacket pkt;
|
||||
av_init_packet(&pkt);
|
||||
|
@ -383,7 +390,7 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE* data, UI
|
|||
|
||||
if (len >= 0 && got_frame)
|
||||
{
|
||||
frame_size = av_samples_get_buffer_size(NULL, mdecoder->codec_context->channels,
|
||||
frame_size = av_samples_get_buffer_size(NULL, mdecoder->codec_context->channels,
|
||||
decoded_frame->nb_samples, mdecoder->codec_context->sample_fmt, 1);
|
||||
memcpy(dst, decoded_frame->data[0], frame_size);
|
||||
}
|
||||
|
@ -396,6 +403,7 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE* data, UI
|
|||
DEBUG_WARN("error decoding");
|
||||
break;
|
||||
}
|
||||
|
||||
src += len;
|
||||
src_size -= len;
|
||||
mdecoder->decoded_size += frame_size;
|
||||
|
@ -444,13 +452,14 @@ static BOOL tsmf_ffmpeg_decode(ITSMFDecoder* decoder, const BYTE* data, UINT32 d
|
|||
|
||||
static BYTE* tsmf_ffmpeg_get_decoded_data(ITSMFDecoder* decoder, UINT32* size)
|
||||
{
|
||||
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
|
||||
BYTE* buf;
|
||||
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
|
||||
|
||||
*size = mdecoder->decoded_size;
|
||||
buf = mdecoder->decoded_data;
|
||||
mdecoder->decoded_data = NULL;
|
||||
mdecoder->decoded_size = 0;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
@ -492,8 +501,10 @@ static void tsmf_ffmpeg_free(ITSMFDecoder* decoder)
|
|||
|
||||
if (mdecoder->frame)
|
||||
av_free(mdecoder->frame);
|
||||
|
||||
if (mdecoder->decoded_data)
|
||||
free(mdecoder->decoded_data);
|
||||
|
||||
if (mdecoder->codec_context)
|
||||
{
|
||||
if (mdecoder->prepared)
|
||||
|
@ -502,15 +513,19 @@ static void tsmf_ffmpeg_free(ITSMFDecoder* decoder)
|
|||
free(mdecoder->codec_context->extradata);
|
||||
av_free(mdecoder->codec_context);
|
||||
}
|
||||
|
||||
free(decoder);
|
||||
}
|
||||
|
||||
static BOOL initialized = FALSE;
|
||||
|
||||
ITSMFDecoder*
|
||||
TSMFDecoderEntry(void)
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_tsmf_client_decoder_subsystem_entry ffmpeg_freerdp_tsmf_client_decoder_subsystem_entry
|
||||
#endif
|
||||
|
||||
ITSMFDecoder* freerdp_tsmf_client_decoder_subsystem_entry(void)
|
||||
{
|
||||
TSMFFFmpegDecoder * decoder;
|
||||
TSMFFFmpegDecoder* decoder;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
|
@ -518,7 +533,10 @@ TSMFDecoderEntry(void)
|
|||
initialized = TRUE;
|
||||
}
|
||||
|
||||
decoder = xnew(TSMFFFmpegDecoder);
|
||||
printf("TSMFDecoderEntry FFMPEG\n");
|
||||
|
||||
decoder = (TSMFFFmpegDecoder*) malloc(sizeof(TSMFFFmpegDecoder));
|
||||
ZeroMemory(decoder, sizeof(TSMFFFmpegDecoder));
|
||||
|
||||
decoder->iface.SetFormat = tsmf_ffmpeg_set_format;
|
||||
decoder->iface.Decode = tsmf_ffmpeg_decode;
|
||||
|
@ -529,4 +547,3 @@ TSMFDecoderEntry(void)
|
|||
|
||||
return (ITSMFDecoder*) decoder;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
define_channel_client_subsystem("tsmf" "gstreamer" "video")
|
||||
define_channel_client_subsystem("tsmf" "gstreamer" "decoder")
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
tsmf_gstreamer.c)
|
||||
|
@ -23,7 +23,7 @@ set(${MODULE_PREFIX}_SRCS
|
|||
include_directories(..)
|
||||
include_directories(${GSTREAMER_INCLUDE_DIRS})
|
||||
|
||||
add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
|
@ -40,4 +40,6 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS}
|
|||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
|
||||
if(NOT STATIC_CHANNELS)
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
|
||||
endif()
|
||||
|
|
|
@ -1565,10 +1565,13 @@ static void tsmf_gstreamer_update_rendering_area(ITSMFDecoder * decoder, int new
|
|||
|
||||
static int initialized = 0;
|
||||
|
||||
ITSMFDecoder *
|
||||
TSMFDecoderEntry(void)
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_tsmf_client_decoder_subsystem_entry gstreamer_freerdp_tsmf_client_decoder_subsystem_entry
|
||||
#endif
|
||||
|
||||
ITSMFDecoder* freerdp_tsmf_client_decoder_subsystem_entry(void)
|
||||
{
|
||||
TSMFGstreamerDecoder * decoder;
|
||||
TSMFGstreamerDecoder* decoder;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
|
|
|
@ -23,7 +23,7 @@ set(${MODULE_PREFIX}_SRCS
|
|||
include_directories(..)
|
||||
include_directories(${PULSE_INCLUDE_DIR})
|
||||
|
||||
add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
|
@ -36,4 +36,7 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${PULSE_LIBRARY})
|
|||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
|
||||
if(NOT STATIC_CHANNELS)
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
|
||||
endif()
|
||||
|
||||
|
|
|
@ -26,8 +26,9 @@
|
|||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <pulse/pulseaudio.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
|
||||
#include "tsmf_audio.h"
|
||||
|
||||
|
@ -389,11 +390,16 @@ static void tsmf_pulse_free(ITSMFAudioDevice* audio)
|
|||
free(pulse);
|
||||
}
|
||||
|
||||
ITSMFAudioDevice* TSMFAudioDeviceEntry(void)
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_tsmf_client_audio_subsystem_entry pulse_freerdp_tsmf_client_audio_subsystem_entry
|
||||
#endif
|
||||
|
||||
ITSMFAudioDevice* freerdp_tsmf_client_audio_subsystem_entry(void)
|
||||
{
|
||||
TSMFPulseAudioDevice* pulse;
|
||||
|
||||
pulse = xnew(TSMFPulseAudioDevice);
|
||||
pulse = (TSMFPulseAudioDevice*) malloc(sizeof(TSMFPulseAudioDevice));
|
||||
ZeroMemory(pulse, sizeof(TSMFPulseAudioDevice));
|
||||
|
||||
pulse->iface.Open = tsmf_pulse_open;
|
||||
pulse->iface.SetFormat = tsmf_pulse_set_format;
|
||||
|
|
|
@ -25,43 +25,32 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/load_plugin.h>
|
||||
|
||||
#include "tsmf_audio.h"
|
||||
|
||||
static ITSMFAudioDevice* tsmf_load_audio_device_by_name(const char* name, const char* device)
|
||||
{
|
||||
ITSMFAudioDevice* audio;
|
||||
TSMF_AUDIO_DEVICE_ENTRY entry;
|
||||
char* fullname;
|
||||
|
||||
if (strrchr(name, '.') != NULL)
|
||||
entry = (TSMF_AUDIO_DEVICE_ENTRY) freerdp_load_plugin(name, TSMF_AUDIO_DEVICE_EXPORT_FUNC_NAME);
|
||||
else
|
||||
{
|
||||
fullname = xzalloc(strlen(name) + 6);
|
||||
strcpy(fullname, "tsmf_");
|
||||
strcat(fullname, name);
|
||||
entry = (TSMF_AUDIO_DEVICE_ENTRY) freerdp_load_plugin(fullname, TSMF_AUDIO_DEVICE_EXPORT_FUNC_NAME);
|
||||
free(fullname);
|
||||
}
|
||||
entry = (TSMF_AUDIO_DEVICE_ENTRY) freerdp_load_channel_addin_entry("tsmf", (LPSTR) name, "audio", 0);
|
||||
|
||||
if (entry == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
audio = entry();
|
||||
|
||||
if (audio == NULL)
|
||||
{
|
||||
DEBUG_WARN("failed to call export function in %s", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!audio->Open(audio, device))
|
||||
{
|
||||
audio->Free(audio);
|
||||
audio = NULL;
|
||||
}
|
||||
|
||||
return audio;
|
||||
}
|
||||
|
||||
|
@ -76,6 +65,7 @@ ITSMFAudioDevice* tsmf_load_audio_device(const char* name, const char* device)
|
|||
else
|
||||
{
|
||||
audio = tsmf_load_audio_device_by_name("pulse", device);
|
||||
|
||||
if (!audio)
|
||||
audio = tsmf_load_audio_device_by_name("alsa", device);
|
||||
}
|
||||
|
|
|
@ -526,4 +526,3 @@ BOOL tsmf_codec_check_media_type(STREAM* s)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/load_plugin.h>
|
||||
#include <freerdp/addin.h>
|
||||
#include <freerdp/client/channels.h>
|
||||
|
||||
#include "tsmf_types.h"
|
||||
#include "tsmf_constants.h"
|
||||
|
@ -36,34 +36,26 @@ static ITSMFDecoder* tsmf_load_decoder_by_name(const char* name, TS_AM_MEDIA_TYP
|
|||
{
|
||||
ITSMFDecoder* decoder;
|
||||
TSMF_DECODER_ENTRY entry;
|
||||
char* fullname;
|
||||
|
||||
if (strrchr(name, '.') != NULL)
|
||||
entry = (TSMF_DECODER_ENTRY) freerdp_load_plugin(name, TSMF_DECODER_EXPORT_FUNC_NAME);
|
||||
else
|
||||
{
|
||||
fullname = xzalloc(strlen(name) + 6);
|
||||
strcpy(fullname, "tsmf_");
|
||||
strcat(fullname, name);
|
||||
entry = (TSMF_DECODER_ENTRY) freerdp_load_plugin(fullname, TSMF_DECODER_EXPORT_FUNC_NAME);
|
||||
free(fullname);
|
||||
}
|
||||
entry = (TSMF_DECODER_ENTRY) freerdp_load_channel_addin_entry("tsmf", (LPSTR) name, "decoder", 0);
|
||||
|
||||
if (entry == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
decoder = entry();
|
||||
|
||||
if (decoder == NULL)
|
||||
{
|
||||
DEBUG_WARN("failed to call export function in %s", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!decoder->SetFormat(decoder, media_type))
|
||||
{
|
||||
decoder->Free(decoder);
|
||||
decoder = NULL;
|
||||
}
|
||||
|
||||
return decoder;
|
||||
}
|
||||
|
||||
|
@ -82,4 +74,3 @@ ITSMFDecoder* tsmf_load_decoder(const char* name, TS_AM_MEDIA_TYPE* media_type)
|
|||
|
||||
return decoder;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/utils/stream.h>
|
||||
|
||||
#include "tsmf_types.h"
|
||||
|
@ -65,11 +66,13 @@ int tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman)
|
|||
|
||||
stream_set_pos(ifman->output, pos);
|
||||
stream_read_UINT32(ifman->output, numHostCapabilities);
|
||||
|
||||
for (i = 0; i < numHostCapabilities; i++)
|
||||
{
|
||||
stream_read_UINT32(ifman->output, CapabilityType);
|
||||
stream_read_UINT32(ifman->output, cbCapabilityLength);
|
||||
pos = stream_get_pos(ifman->output);
|
||||
|
||||
switch (CapabilityType)
|
||||
{
|
||||
case 1: /* Protocol version request */
|
||||
|
@ -128,10 +131,11 @@ static TSMF_PRESENTATION* pexisted = 0;
|
|||
|
||||
int tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman)
|
||||
{
|
||||
int error = 0;
|
||||
int status = 0;
|
||||
TSMF_PRESENTATION* presentation;
|
||||
|
||||
DEBUG_DVC("");
|
||||
|
||||
if (pexisted)
|
||||
{
|
||||
ifman->output_pending = FALSE;
|
||||
|
@ -141,18 +145,21 @@ int tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman)
|
|||
|
||||
presentation = tsmf_presentation_new(stream_get_tail(ifman->input), ifman->channel_callback);
|
||||
pexisted = presentation;
|
||||
|
||||
if (presentation == NULL)
|
||||
error = 1;
|
||||
status = 1;
|
||||
else
|
||||
tsmf_presentation_set_audio_device(presentation, ifman->audio_name, ifman->audio_device);
|
||||
|
||||
ifman->output_pending = TRUE;
|
||||
return error;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int tsmf_ifman_add_stream(TSMF_IFMAN* ifman)
|
||||
{
|
||||
UINT32 StreamId;
|
||||
int error = 0;
|
||||
int status = 0;
|
||||
TSMF_STREAM* stream;
|
||||
TSMF_PRESENTATION* presentation;
|
||||
|
||||
|
@ -162,17 +169,22 @@ int tsmf_ifman_add_stream(TSMF_IFMAN* ifman)
|
|||
stream_seek(ifman->input, 16);
|
||||
|
||||
if (presentation == NULL)
|
||||
error = 1;
|
||||
{
|
||||
status = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream_read_UINT32(ifman->input, StreamId);
|
||||
stream_seek_UINT32(ifman->input); /* numMediaType */
|
||||
stream = tsmf_stream_new(presentation, StreamId);
|
||||
|
||||
if (stream)
|
||||
tsmf_stream_set_format(stream, ifman->decoder_name, ifman->input);
|
||||
}
|
||||
|
||||
ifman->output_pending = TRUE;
|
||||
return error;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int tsmf_ifman_set_topology_request(TSMF_IFMAN* ifman)
|
||||
|
@ -183,12 +195,13 @@ int tsmf_ifman_set_topology_request(TSMF_IFMAN* ifman)
|
|||
stream_write_UINT32(ifman->output, 1); /* TopologyReady */
|
||||
stream_write_UINT32(ifman->output, 0); /* Result */
|
||||
ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tsmf_ifman_remove_stream(TSMF_IFMAN* ifman)
|
||||
{
|
||||
int error = 0;
|
||||
int status = 0;
|
||||
UINT32 StreamId;
|
||||
TSMF_STREAM* stream;
|
||||
TSMF_PRESENTATION* presentation;
|
||||
|
@ -199,7 +212,9 @@ int tsmf_ifman_remove_stream(TSMF_IFMAN* ifman)
|
|||
stream_seek(ifman->input, 16);
|
||||
|
||||
if (presentation == NULL)
|
||||
error = 1;
|
||||
{
|
||||
status = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream_read_UINT32(ifman->input, StreamId);
|
||||
|
@ -207,10 +222,12 @@ int tsmf_ifman_remove_stream(TSMF_IFMAN* ifman)
|
|||
if (stream)
|
||||
tsmf_stream_free(stream);
|
||||
else
|
||||
error = 1;
|
||||
status = 1;
|
||||
}
|
||||
|
||||
ifman->output_pending = TRUE;
|
||||
return error;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int tsmf_ifman_shutdown_presentation(TSMF_IFMAN* ifman)
|
||||
|
@ -220,6 +237,7 @@ int tsmf_ifman_shutdown_presentation(TSMF_IFMAN* ifman)
|
|||
DEBUG_DVC("");
|
||||
|
||||
presentation = tsmf_presentation_find_by_id(stream_get_tail(ifman->input));
|
||||
|
||||
if (presentation)
|
||||
tsmf_presentation_free(presentation);
|
||||
|
||||
|
@ -228,6 +246,7 @@ int tsmf_ifman_shutdown_presentation(TSMF_IFMAN* ifman)
|
|||
stream_check_size(ifman->output, 4);
|
||||
stream_write_UINT32(ifman->output, 0); /* Result */
|
||||
ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -335,7 +354,9 @@ int tsmf_ifman_update_geometry_info(TSMF_IFMAN* ifman)
|
|||
{
|
||||
if (num_rects > 0)
|
||||
{
|
||||
rects = (RDP_RECT*) xzalloc(sizeof(RDP_RECT) * num_rects);
|
||||
rects = (RDP_RECT*) malloc(sizeof(RDP_RECT) * num_rects);
|
||||
ZeroMemory(rects, sizeof(RDP_RECT) * num_rects);
|
||||
|
||||
for (i = 0; i < num_rects; i++)
|
||||
{
|
||||
stream_read_UINT16(ifman->input, rects[i].y); /* Top */
|
||||
|
@ -402,35 +423,41 @@ int tsmf_ifman_on_sample(TSMF_IFMAN* ifman)
|
|||
(int)ThrottleDuration, SampleExtensions, cbData);
|
||||
|
||||
presentation = tsmf_presentation_find_by_id(ifman->presentation_id);
|
||||
|
||||
if (presentation == NULL)
|
||||
{
|
||||
DEBUG_WARN("unknown presentation id");
|
||||
return 1;
|
||||
}
|
||||
|
||||
stream = tsmf_stream_find_by_id(presentation, StreamId);
|
||||
|
||||
if (stream == NULL)
|
||||
{
|
||||
DEBUG_WARN("unknown stream id");
|
||||
return 1;
|
||||
}
|
||||
|
||||
tsmf_stream_push_sample(stream, ifman->channel_callback,
|
||||
ifman->message_id, SampleStartTime, SampleEndTime, ThrottleDuration, SampleExtensions,
|
||||
cbData, stream_get_tail(ifman->input));
|
||||
|
||||
ifman->output_pending = TRUE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tsmf_ifman_on_flush(TSMF_IFMAN* ifman)
|
||||
{
|
||||
TSMF_PRESENTATION* presentation;
|
||||
UINT32 StreamId;
|
||||
TSMF_PRESENTATION* presentation;
|
||||
|
||||
stream_seek(ifman->input, 16);
|
||||
stream_read_UINT32(ifman->input, StreamId);
|
||||
DEBUG_DVC("StreamId %d", StreamId);
|
||||
|
||||
presentation = tsmf_presentation_find_by_id(ifman->presentation_id);
|
||||
|
||||
if (presentation == NULL)
|
||||
{
|
||||
DEBUG_WARN("unknown presentation id");
|
||||
|
@ -440,18 +467,20 @@ int tsmf_ifman_on_flush(TSMF_IFMAN* ifman)
|
|||
tsmf_presentation_flush(presentation);
|
||||
|
||||
ifman->output_pending = TRUE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tsmf_ifman_on_end_of_stream(TSMF_IFMAN* ifman)
|
||||
{
|
||||
TSMF_PRESENTATION* presentation;
|
||||
TSMF_STREAM* stream;
|
||||
UINT32 StreamId;
|
||||
TSMF_STREAM* stream;
|
||||
TSMF_PRESENTATION* presentation;
|
||||
|
||||
presentation = tsmf_presentation_find_by_id(stream_get_tail(ifman->input));
|
||||
stream_seek(ifman->input, 16);
|
||||
stream_read_UINT32(ifman->input, StreamId);
|
||||
|
||||
if (presentation)
|
||||
{
|
||||
stream = tsmf_stream_find_by_id(presentation, StreamId);
|
||||
|
@ -477,6 +506,7 @@ int tsmf_ifman_on_playback_started(TSMF_IFMAN* ifman)
|
|||
DEBUG_DVC("");
|
||||
|
||||
presentation = tsmf_presentation_find_by_id(stream_get_tail(ifman->input));
|
||||
|
||||
if (presentation)
|
||||
tsmf_presentation_start(presentation);
|
||||
else
|
||||
|
@ -502,10 +532,12 @@ int tsmf_ifman_on_playback_paused(TSMF_IFMAN* ifman)
|
|||
/* Added pause control so gstreamer pipeline can be paused accordingly */
|
||||
|
||||
presentation = tsmf_presentation_find_by_id(stream_get_tail(ifman->input));
|
||||
|
||||
if (presentation)
|
||||
tsmf_presentation_paused(presentation);
|
||||
else
|
||||
DEBUG_WARN("unknown presentation id");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -564,4 +596,3 @@ int tsmf_ifman_on_playback_rate_changed(TSMF_IFMAN * ifman)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,9 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/cmdline.h>
|
||||
|
||||
#include <freerdp/utils/stream.h>
|
||||
|
||||
#include "tsmf_types.h"
|
||||
|
@ -76,7 +78,7 @@ void tsmf_playback_ack(IWTSVirtualChannelCallback* pChannelCallback,
|
|||
UINT32 message_id, UINT64 duration, UINT32 data_size)
|
||||
{
|
||||
STREAM* s;
|
||||
int error;
|
||||
int status;
|
||||
TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback;
|
||||
|
||||
s = stream_new(32);
|
||||
|
@ -88,26 +90,29 @@ void tsmf_playback_ack(IWTSVirtualChannelCallback* pChannelCallback,
|
|||
stream_write_UINT64(s, data_size); /* cbData */
|
||||
|
||||
DEBUG_DVC("response size %d", (int) stream_get_length(s));
|
||||
error = callback->channel->Write(callback->channel, stream_get_length(s), stream_get_head(s), NULL);
|
||||
if (error)
|
||||
status = callback->channel->Write(callback->channel, stream_get_length(s), stream_get_head(s), NULL);
|
||||
|
||||
if (status)
|
||||
{
|
||||
DEBUG_WARN("response error %d", error);
|
||||
DEBUG_WARN("response error %d", status);
|
||||
}
|
||||
|
||||
stream_free(s);
|
||||
}
|
||||
|
||||
BOOL tsmf_push_event(IWTSVirtualChannelCallback* pChannelCallback,
|
||||
RDP_EVENT* event)
|
||||
BOOL tsmf_push_event(IWTSVirtualChannelCallback* pChannelCallback, RDP_EVENT* event)
|
||||
{
|
||||
int error;
|
||||
int status;
|
||||
TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback;
|
||||
|
||||
error = callback->channel_mgr->PushEvent(callback->channel_mgr, event);
|
||||
if (error)
|
||||
status = callback->channel_mgr->PushEvent(callback->channel_mgr, event);
|
||||
|
||||
if (status)
|
||||
{
|
||||
DEBUG_WARN("response error %d", error);
|
||||
DEBUG_WARN("response error %d", status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -118,7 +123,7 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
|
|||
int length;
|
||||
STREAM* input;
|
||||
STREAM* output;
|
||||
int error = -1;
|
||||
int status = -1;
|
||||
TSMF_IFMAN ifman;
|
||||
UINT32 MessageId;
|
||||
UINT32 FunctionId;
|
||||
|
@ -163,7 +168,7 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
|
|||
switch (FunctionId)
|
||||
{
|
||||
case RIM_EXCHANGE_CAPABILITY_REQUEST:
|
||||
error = tsmf_ifman_rim_exchange_capability_request(&ifman);
|
||||
status = tsmf_ifman_rim_exchange_capability_request(&ifman);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -181,91 +186,91 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
|
|||
stream_read_UINT32(input, callback->stream_id);
|
||||
DEBUG_DVC("SET_CHANNEL_PARAMS StreamId=%d", callback->stream_id);
|
||||
ifman.output_pending = TRUE;
|
||||
error = 0;
|
||||
status = 0;
|
||||
break;
|
||||
|
||||
case EXCHANGE_CAPABILITIES_REQ:
|
||||
error = tsmf_ifman_exchange_capability_request(&ifman);
|
||||
status = tsmf_ifman_exchange_capability_request(&ifman);
|
||||
break;
|
||||
|
||||
case CHECK_FORMAT_SUPPORT_REQ:
|
||||
error = tsmf_ifman_check_format_support_request(&ifman);
|
||||
status = tsmf_ifman_check_format_support_request(&ifman);
|
||||
break;
|
||||
|
||||
case ON_NEW_PRESENTATION:
|
||||
error = tsmf_ifman_on_new_presentation(&ifman);
|
||||
status = tsmf_ifman_on_new_presentation(&ifman);
|
||||
break;
|
||||
|
||||
case ADD_STREAM:
|
||||
error = tsmf_ifman_add_stream(&ifman);
|
||||
status = tsmf_ifman_add_stream(&ifman);
|
||||
break;
|
||||
|
||||
case SET_TOPOLOGY_REQ:
|
||||
error = tsmf_ifman_set_topology_request(&ifman);
|
||||
status = tsmf_ifman_set_topology_request(&ifman);
|
||||
break;
|
||||
|
||||
case REMOVE_STREAM:
|
||||
error = tsmf_ifman_remove_stream(&ifman);
|
||||
status = tsmf_ifman_remove_stream(&ifman);
|
||||
break;
|
||||
|
||||
case SHUTDOWN_PRESENTATION_REQ:
|
||||
error = tsmf_ifman_shutdown_presentation(&ifman);
|
||||
status = tsmf_ifman_shutdown_presentation(&ifman);
|
||||
break;
|
||||
|
||||
case ON_STREAM_VOLUME:
|
||||
error = tsmf_ifman_on_stream_volume(&ifman);
|
||||
status = tsmf_ifman_on_stream_volume(&ifman);
|
||||
break;
|
||||
|
||||
case ON_CHANNEL_VOLUME:
|
||||
error = tsmf_ifman_on_channel_volume(&ifman);
|
||||
status = tsmf_ifman_on_channel_volume(&ifman);
|
||||
break;
|
||||
|
||||
case SET_VIDEO_WINDOW:
|
||||
error = tsmf_ifman_set_video_window(&ifman);
|
||||
status = tsmf_ifman_set_video_window(&ifman);
|
||||
break;
|
||||
|
||||
case UPDATE_GEOMETRY_INFO:
|
||||
error = tsmf_ifman_update_geometry_info(&ifman);
|
||||
status = tsmf_ifman_update_geometry_info(&ifman);
|
||||
break;
|
||||
|
||||
case SET_ALLOCATOR:
|
||||
error = tsmf_ifman_set_allocator(&ifman);
|
||||
status = tsmf_ifman_set_allocator(&ifman);
|
||||
break;
|
||||
|
||||
case NOTIFY_PREROLL:
|
||||
error = tsmf_ifman_notify_preroll(&ifman);
|
||||
status = tsmf_ifman_notify_preroll(&ifman);
|
||||
break;
|
||||
|
||||
case ON_SAMPLE:
|
||||
error = tsmf_ifman_on_sample(&ifman);
|
||||
status = tsmf_ifman_on_sample(&ifman);
|
||||
break;
|
||||
|
||||
case ON_FLUSH:
|
||||
error = tsmf_ifman_on_flush(&ifman);
|
||||
status = tsmf_ifman_on_flush(&ifman);
|
||||
break;
|
||||
|
||||
case ON_END_OF_STREAM:
|
||||
error = tsmf_ifman_on_end_of_stream(&ifman);
|
||||
status = tsmf_ifman_on_end_of_stream(&ifman);
|
||||
break;
|
||||
|
||||
case ON_PLAYBACK_STARTED:
|
||||
error = tsmf_ifman_on_playback_started(&ifman);
|
||||
status = tsmf_ifman_on_playback_started(&ifman);
|
||||
break;
|
||||
|
||||
case ON_PLAYBACK_PAUSED:
|
||||
error = tsmf_ifman_on_playback_paused(&ifman);
|
||||
status = tsmf_ifman_on_playback_paused(&ifman);
|
||||
break;
|
||||
|
||||
case ON_PLAYBACK_RESTARTED:
|
||||
error = tsmf_ifman_on_playback_restarted(&ifman);
|
||||
status = tsmf_ifman_on_playback_restarted(&ifman);
|
||||
break;
|
||||
|
||||
case ON_PLAYBACK_STOPPED:
|
||||
error = tsmf_ifman_on_playback_stopped(&ifman);
|
||||
status = tsmf_ifman_on_playback_stopped(&ifman);
|
||||
break;
|
||||
|
||||
case ON_PLAYBACK_RATE_CHANGED:
|
||||
error = tsmf_ifman_on_playback_rate_changed(&ifman);
|
||||
status = tsmf_ifman_on_playback_rate_changed(&ifman);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -282,34 +287,34 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
|
|||
input = NULL;
|
||||
ifman.input = NULL;
|
||||
|
||||
if (error == -1)
|
||||
if (status == -1)
|
||||
{
|
||||
switch (FunctionId)
|
||||
{
|
||||
case RIMCALL_RELEASE:
|
||||
/* [MS-RDPEXPS] 2.2.2.2 Interface Release (IFACE_RELEASE)
|
||||
This message does not require a reply. */
|
||||
error = 0;
|
||||
status = 0;
|
||||
ifman.output_pending = 1;
|
||||
break;
|
||||
|
||||
case RIMCALL_QUERYINTERFACE:
|
||||
/* [MS-RDPEXPS] 2.2.2.1.2 Query Interface Response (QI_RSP)
|
||||
This message is not supported in this channel. */
|
||||
error = 0;
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (error == -1)
|
||||
if (status == -1)
|
||||
{
|
||||
DEBUG_WARN("InterfaceId 0x%X FunctionId 0x%X not processed.",
|
||||
InterfaceId, FunctionId);
|
||||
/* When a request is not implemented we return empty response indicating error */
|
||||
}
|
||||
error = 0;
|
||||
status = 0;
|
||||
}
|
||||
|
||||
if (error == 0 && !ifman.output_pending)
|
||||
if (status == 0 && !ifman.output_pending)
|
||||
{
|
||||
/* Response packet does not have FunctionId */
|
||||
length = stream_get_length(output);
|
||||
|
@ -318,16 +323,16 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
|
|||
stream_write_UINT32(output, MessageId);
|
||||
|
||||
DEBUG_DVC("response size %d", length);
|
||||
error = callback->channel->Write(callback->channel, length, stream_get_head(output), NULL);
|
||||
if (error)
|
||||
status = callback->channel->Write(callback->channel, length, stream_get_head(output), NULL);
|
||||
if (status)
|
||||
{
|
||||
DEBUG_WARN("response error %d", error);
|
||||
DEBUG_WARN("response error %d", status);
|
||||
}
|
||||
}
|
||||
|
||||
stream_free(output);
|
||||
|
||||
return error;
|
||||
return status;
|
||||
}
|
||||
|
||||
static int tsmf_on_close(IWTSVirtualChannelCallback* pChannelCallback)
|
||||
|
@ -341,13 +346,16 @@ static int tsmf_on_close(IWTSVirtualChannelCallback* pChannelCallback)
|
|||
if (callback->stream_id)
|
||||
{
|
||||
presentation = tsmf_presentation_find_by_id(callback->presentation_id);
|
||||
|
||||
if (presentation)
|
||||
{
|
||||
stream = tsmf_stream_find_by_id(presentation, callback->stream_id);
|
||||
|
||||
if (stream)
|
||||
tsmf_stream_free(stream);
|
||||
}
|
||||
}
|
||||
|
||||
free(pChannelCallback);
|
||||
|
||||
return 0;
|
||||
|
@ -364,7 +372,9 @@ static int tsmf_on_new_channel_connection(IWTSListenerCallback* pListenerCallbac
|
|||
|
||||
DEBUG_DVC("");
|
||||
|
||||
callback = xnew(TSMF_CHANNEL_CALLBACK);
|
||||
callback = (TSMF_CHANNEL_CALLBACK*) malloc(sizeof(TSMF_CHANNEL_CALLBACK));
|
||||
ZeroMemory(callback, sizeof(TSMF_CHANNEL_CALLBACK));
|
||||
|
||||
callback->iface.OnDataReceived = tsmf_on_data_received;
|
||||
callback->iface.OnClose = tsmf_on_close;
|
||||
callback->plugin = listener_callback->plugin;
|
||||
|
@ -381,10 +391,13 @@ static int tsmf_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager
|
|||
|
||||
DEBUG_DVC("");
|
||||
|
||||
tsmf->listener_callback = xnew(TSMF_LISTENER_CALLBACK);
|
||||
tsmf->listener_callback = (TSMF_LISTENER_CALLBACK*) malloc(sizeof(TSMF_LISTENER_CALLBACK));
|
||||
ZeroMemory(tsmf->listener_callback, sizeof(TSMF_LISTENER_CALLBACK));
|
||||
|
||||
tsmf->listener_callback->iface.OnNewChannelConnection = tsmf_on_new_channel_connection;
|
||||
tsmf->listener_callback->plugin = pPlugin;
|
||||
tsmf->listener_callback->channel_mgr = pChannelMgr;
|
||||
|
||||
return pChannelMgr->CreateListener(pChannelMgr, "TSMF", 0,
|
||||
(IWTSListenerCallback*) tsmf->listener_callback, NULL);
|
||||
}
|
||||
|
@ -402,27 +415,55 @@ static int tsmf_plugin_terminated(IWTSPlugin* pPlugin)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void tsmf_process_plugin_data(IWTSPlugin* pPlugin, RDP_PLUGIN_DATA* data)
|
||||
COMMAND_LINE_ARGUMENT_A tsmf_args[] =
|
||||
{
|
||||
{ "audio", COMMAND_LINE_VALUE_REQUIRED, "<subsystem>", NULL, NULL, -1, NULL, "audio subsystem" },
|
||||
{ "audio-dev", COMMAND_LINE_VALUE_REQUIRED, "<device>", NULL, NULL, -1, NULL, "audio device name" },
|
||||
{ "decoder", COMMAND_LINE_VALUE_REQUIRED, "<subsystem>", NULL, NULL, -1, NULL, "decoder subsystem" },
|
||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
static void tsmf_process_addin_args(IWTSPlugin* pPlugin, ADDIN_ARGV* args)
|
||||
{
|
||||
int status;
|
||||
DWORD flags;
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
TSMF_PLUGIN* tsmf = (TSMF_PLUGIN*) pPlugin;
|
||||
|
||||
while (data && data->size > 0)
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
|
||||
|
||||
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
|
||||
tsmf_args, flags, tsmf, NULL, NULL);
|
||||
|
||||
arg = tsmf_args;
|
||||
|
||||
do
|
||||
{
|
||||
if (data->data[0] && ( strcmp((char*)data->data[0], "tsmf") == 0 || strstr((char*)data->data[0], "/tsmf.") != NULL) )
|
||||
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
|
||||
continue;
|
||||
|
||||
CommandLineSwitchStart(arg)
|
||||
|
||||
CommandLineSwitchCase(arg, "audio")
|
||||
{
|
||||
if (data->data[1] && strcmp((char*)data->data[1], "decoder") == 0)
|
||||
{
|
||||
tsmf->decoder_name = data->data[2];
|
||||
}
|
||||
else if (data->data[1] && strcmp((char*)data->data[1], "audio") == 0)
|
||||
{
|
||||
tsmf->audio_name = data->data[2];
|
||||
tsmf->audio_device = data->data[3];
|
||||
}
|
||||
tsmf->audio_name = _strdup(arg->Value);
|
||||
}
|
||||
|
||||
data = (RDP_PLUGIN_DATA*)(((BYTE*)data) + data->size);
|
||||
CommandLineSwitchCase(arg, "audio-dev")
|
||||
{
|
||||
tsmf->audio_device = _strdup(arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "decoder")
|
||||
{
|
||||
tsmf->decoder_name = _strdup(arg->Value);
|
||||
}
|
||||
CommandLineSwitchDefault(arg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CommandLineSwitchEnd(arg)
|
||||
}
|
||||
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
|
@ -431,29 +472,29 @@ static void tsmf_process_plugin_data(IWTSPlugin* pPlugin, RDP_PLUGIN_DATA* data)
|
|||
|
||||
int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||
{
|
||||
int error = 0;
|
||||
int status = 0;
|
||||
TSMF_PLUGIN* tsmf;
|
||||
|
||||
tsmf = (TSMF_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "tsmf");
|
||||
|
||||
if (tsmf == NULL)
|
||||
{
|
||||
tsmf = xnew(TSMF_PLUGIN);
|
||||
tsmf = (TSMF_PLUGIN*) malloc(sizeof(TSMF_PLUGIN));
|
||||
ZeroMemory(tsmf, sizeof(TSMF_PLUGIN));
|
||||
|
||||
tsmf->iface.Initialize = tsmf_plugin_initialize;
|
||||
tsmf->iface.Connected = NULL;
|
||||
tsmf->iface.Disconnected = NULL;
|
||||
tsmf->iface.Terminated = tsmf_plugin_terminated;
|
||||
error = pEntryPoints->RegisterPlugin(pEntryPoints, "tsmf", (IWTSPlugin*) tsmf);
|
||||
status = pEntryPoints->RegisterPlugin(pEntryPoints, "tsmf", (IWTSPlugin*) tsmf);
|
||||
|
||||
tsmf_media_init();
|
||||
}
|
||||
if (error == 0)
|
||||
|
||||
if (status == 0)
|
||||
{
|
||||
tsmf_process_plugin_data((IWTSPlugin*) tsmf,
|
||||
pEntryPoints->GetPluginData(pEntryPoints));
|
||||
tsmf_process_addin_args((IWTSPlugin*) tsmf, pEntryPoints->GetPluginData(pEntryPoints));
|
||||
}
|
||||
|
||||
return error;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,8 @@
|
|||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/list.h>
|
||||
#include <freerdp/utils/thread.h>
|
||||
|
@ -259,7 +260,7 @@ TSMF_PRESENTATION* tsmf_presentation_new(const BYTE* guid, IWTSVirtualChannelCal
|
|||
|
||||
if (fout)
|
||||
{
|
||||
fprintf(fout, "%d\n", (int) thid);
|
||||
fprintf(fout, "%d\n", (int) (size_t) thid);
|
||||
fclose(fout);
|
||||
}
|
||||
|
||||
|
@ -271,7 +272,8 @@ TSMF_PRESENTATION* tsmf_presentation_new(const BYTE* guid, IWTSVirtualChannelCal
|
|||
return NULL;
|
||||
}
|
||||
|
||||
presentation = xnew(TSMF_PRESENTATION);
|
||||
presentation = (TSMF_PRESENTATION*) malloc(sizeof(TSMF_PRESENTATION));
|
||||
ZeroMemory(presentation, sizeof(TSMF_PRESENTATION));
|
||||
|
||||
memcpy(presentation->presentation_id, guid, GUID_SIZE);
|
||||
presentation->channel_callback = pChannelCallback;
|
||||
|
@ -364,10 +366,14 @@ static void tsmf_sample_playback_video(TSMF_SAMPLE* sample)
|
|||
free(presentation->last_rects);
|
||||
presentation->last_rects = NULL;
|
||||
}
|
||||
|
||||
presentation->last_num_rects = presentation->output_num_rects;
|
||||
|
||||
if (presentation->last_num_rects > 0)
|
||||
{
|
||||
presentation->last_rects = xzalloc(presentation->last_num_rects * sizeof(RDP_RECT));
|
||||
presentation->last_rects = malloc(presentation->last_num_rects * sizeof(RDP_RECT));
|
||||
ZeroMemory(presentation->last_rects, presentation->last_num_rects * sizeof(RDP_RECT));
|
||||
|
||||
memcpy(presentation->last_rects, presentation->output_rects,
|
||||
presentation->last_num_rects * sizeof(RDP_RECT));
|
||||
}
|
||||
|
@ -384,10 +390,14 @@ static void tsmf_sample_playback_video(TSMF_SAMPLE* sample)
|
|||
vevent->y = presentation->output_y;
|
||||
vevent->width = presentation->output_width;
|
||||
vevent->height = presentation->output_height;
|
||||
|
||||
if (presentation->output_num_rects > 0)
|
||||
{
|
||||
vevent->num_visible_rects = presentation->output_num_rects;
|
||||
vevent->visible_rects = (RDP_RECT*) xzalloc(presentation->output_num_rects * sizeof(RDP_RECT));
|
||||
|
||||
vevent->visible_rects = (RDP_RECT*) malloc(presentation->output_num_rects * sizeof(RDP_RECT));
|
||||
ZeroMemory(vevent->visible_rects, presentation->output_num_rects * sizeof(RDP_RECT));
|
||||
|
||||
memcpy(vevent->visible_rects, presentation->output_rects,
|
||||
presentation->output_num_rects * sizeof(RDP_RECT));
|
||||
}
|
||||
|
@ -567,10 +577,13 @@ static void tsmf_sample_playback(TSMF_SAMPLE* sample)
|
|||
free(presentation->last_rects);
|
||||
presentation->last_rects = NULL;
|
||||
}
|
||||
|
||||
presentation->last_num_rects = presentation->output_num_rects;
|
||||
|
||||
if (presentation->last_num_rects > 0)
|
||||
{
|
||||
presentation->last_rects = xzalloc(presentation->last_num_rects * sizeof(RDP_RECT));
|
||||
presentation->last_rects = malloc(presentation->last_num_rects * sizeof(RDP_RECT));
|
||||
ZeroMemory(presentation->last_rects, presentation->last_num_rects * sizeof(RDP_RECT));
|
||||
memcpy(presentation->last_rects, presentation->output_rects, presentation->last_num_rects * sizeof(RDP_RECT));
|
||||
}
|
||||
if(stream->decoder->UpdateRenderingArea)
|
||||
|
@ -921,7 +934,8 @@ TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
stream = xnew(TSMF_STREAM);
|
||||
stream = (TSMF_STREAM*) malloc(sizeof(TSMF_STREAM));
|
||||
ZeroMemory(stream, sizeof(TSMF_STREAM));
|
||||
|
||||
stream->stream_id = stream_id;
|
||||
stream->presentation = presentation;
|
||||
|
@ -1035,7 +1049,8 @@ void tsmf_stream_push_sample(TSMF_STREAM* stream, IWTSVirtualChannelCallback* pC
|
|||
|
||||
ReleaseMutex(tsmf_mutex);
|
||||
|
||||
sample = xnew(TSMF_SAMPLE);
|
||||
sample = (TSMF_SAMPLE*) malloc(sizeof(TSMF_SAMPLE));
|
||||
ZeroMemory(sample, sizeof(TSMF_SAMPLE));
|
||||
|
||||
sample->sample_id = sample_id;
|
||||
sample->start_time = start_time;
|
||||
|
@ -1045,7 +1060,8 @@ void tsmf_stream_push_sample(TSMF_STREAM* stream, IWTSVirtualChannelCallback* pC
|
|||
sample->stream = stream;
|
||||
sample->channel_callback = pChannelCallback;
|
||||
sample->data_size = data_size;
|
||||
sample->data = xzalloc(data_size + TSMF_BUFFER_PADDING_SIZE);
|
||||
sample->data = malloc(data_size + TSMF_BUFFER_PADDING_SIZE);
|
||||
ZeroMemory(sample->data, data_size + TSMF_BUFFER_PADDING_SIZE);
|
||||
memcpy(sample->data, data, data_size);
|
||||
|
||||
freerdp_thread_lock(stream->thread);
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
|
||||
define_channel("urbdrc")
|
||||
|
||||
add_subdirectory(libusb)
|
||||
|
||||
if(WITH_CLIENT_CHANNELS)
|
||||
add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
|
||||
endif()
|
||||
|
|
|
@ -3,15 +3,10 @@ set(OPTION_DEFAULT OFF)
|
|||
set(OPTION_CLIENT_DEFAULT OFF)
|
||||
set(OPTION_SERVER_DEFAULT OFF)
|
||||
|
||||
if(${OPTION_CLIENT_DEFAULT} OR ${OPTION_SERVER_DEFAULT})
|
||||
set(OPTION_DEFAULT ON)
|
||||
endif()
|
||||
|
||||
define_channel_options(NAME "urbdrc" TYPE "dynamic"
|
||||
DESCRIPTION "USB Devices Virtual Channel Extension"
|
||||
SPECIFICATIONS "[MS-RDPEUSB]"
|
||||
DEFAULT ${OPTION_DEFAULT})
|
||||
|
||||
define_channel_client_options(${OPTION_CLIENT_DEFAULT})
|
||||
#define_channel_server_options(${OPTION_SERVER_DEFAULT})
|
||||
|
||||
define_channel_server_options(${OPTION_SERVER_DEFAULT})
|
||||
|
|
|
@ -35,17 +35,22 @@ add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE
|
|||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} libusb-devman)
|
||||
#set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} libusb-devman)
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS
|
||||
dbus-glib-1
|
||||
udev
|
||||
uuid)
|
||||
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE winpr
|
||||
MODULES winpr-utils)
|
||||
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE freerdp
|
||||
MODULES freerdp-utils)
|
||||
MODULES freerdp-common freerdp-utils)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
|
@ -55,3 +60,5 @@ endif()
|
|||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")
|
||||
|
||||
# libusb subsystem
|
||||
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "libusb" "")
|
||||
|
|
|
@ -798,8 +798,7 @@ static int urb_bulk_or_interrupt_transfer(URBDRC_CHANNEL_CALLBACK* callback, BYT
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
urb_isoch_transfer(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
static int urb_isoch_transfer(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
UINT32 data_sizem,
|
||||
UINT32 MessageId,
|
||||
IUDEVMAN * udevman,
|
||||
|
@ -963,8 +962,7 @@ urb_isoch_transfer(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
urb_control_descriptor_request(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
static int urb_control_descriptor_request(URBDRC_CHANNEL_CALLBACK* callback,
|
||||
BYTE * data,
|
||||
UINT32 data_sizem,
|
||||
UINT32 MessageId,
|
||||
|
@ -973,17 +971,19 @@ urb_control_descriptor_request(URBDRC_CHANNEL_CALLBACK * callback,
|
|||
BYTE func_recipient,
|
||||
int transferDir)
|
||||
{
|
||||
IUDEVICE * pdev;
|
||||
UINT32 out_size, InterfaceId, RequestId, OutputBufferSize, usbd_status;
|
||||
BYTE bmRequestType, desc_index, desc_type;
|
||||
UINT16 langId;
|
||||
BYTE * buffer;
|
||||
BYTE * out_data;
|
||||
int ret, offset;
|
||||
IUDEVICE* pdev;
|
||||
UINT32 out_size, InterfaceId, RequestId, OutputBufferSize, usbd_status;
|
||||
BYTE bmRequestType, desc_index, desc_type;
|
||||
UINT16 langId;
|
||||
BYTE* buffer;
|
||||
BYTE* out_data;
|
||||
int ret, offset;
|
||||
|
||||
pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice);
|
||||
|
||||
if (pdev == NULL)
|
||||
return 0;
|
||||
|
||||
InterfaceId = ((STREAM_ID_PROXY<<30) | pdev->get_ReqCompletion(pdev));
|
||||
data_read_UINT32(data + 0, RequestId);
|
||||
data_read_BYTE(data + 4, desc_index);
|
||||
|
@ -1055,11 +1055,7 @@ urb_control_descriptor_request(URBDRC_CHANNEL_CALLBACK * callback,
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int
|
||||
urb_control_get_status_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
static int urb_control_get_status_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
UINT32 data_sizem,
|
||||
UINT32 MessageId,
|
||||
IUDEVMAN * udevman,
|
||||
|
@ -1067,13 +1063,13 @@ urb_control_get_status_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
|||
BYTE func_recipient,
|
||||
int transferDir)
|
||||
{
|
||||
IUDEVICE * pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, OutputBufferSize, usbd_status;
|
||||
UINT16 Index;
|
||||
BYTE bmRequestType;
|
||||
BYTE * buffer;
|
||||
BYTE * out_data;
|
||||
int offset, ret;
|
||||
IUDEVICE* pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, OutputBufferSize, usbd_status;
|
||||
UINT16 Index;
|
||||
BYTE bmRequestType;
|
||||
BYTE* buffer;
|
||||
BYTE* out_data;
|
||||
int offset, ret;
|
||||
|
||||
if (transferDir == 0){
|
||||
LLOGLN(urbdrc_debug, ("urb_control_get_status_request: not support transfer out\n"));
|
||||
|
@ -1150,8 +1146,7 @@ urb_control_get_status_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
urb_control_vendor_or_class_request(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
static int urb_control_vendor_or_class_request(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
BYTE * data,
|
||||
UINT32 data_sizem,
|
||||
UINT32 MessageId,
|
||||
|
@ -1161,14 +1156,14 @@ urb_control_vendor_or_class_request(URBDRC_CHANNEL_CALLBACK * callback,
|
|||
BYTE func_recipient,
|
||||
int transferDir)
|
||||
{
|
||||
IUDEVICE * pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, TransferFlags, usbd_status;
|
||||
UINT32 OutputBufferSize;
|
||||
BYTE ReqTypeReservedBits, Request, bmRequestType;
|
||||
UINT16 Value, Index, Padding;
|
||||
BYTE * buffer;
|
||||
BYTE * out_data;
|
||||
int offset, ret;
|
||||
IUDEVICE* pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, TransferFlags, usbd_status;
|
||||
UINT32 OutputBufferSize;
|
||||
BYTE ReqTypeReservedBits, Request, bmRequestType;
|
||||
UINT16 Value, Index, Padding;
|
||||
BYTE* buffer;
|
||||
BYTE* out_data;
|
||||
int offset, ret;
|
||||
/** control by vendor command */
|
||||
|
||||
pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice);
|
||||
|
@ -1260,8 +1255,7 @@ urb_control_vendor_or_class_request(URBDRC_CHANNEL_CALLBACK * callback,
|
|||
|
||||
|
||||
|
||||
static int
|
||||
urb_os_feature_descriptor_request(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
static int urb_os_feature_descriptor_request(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
BYTE * data,
|
||||
UINT32 data_sizem,
|
||||
UINT32 MessageId,
|
||||
|
@ -1269,17 +1263,19 @@ urb_os_feature_descriptor_request(URBDRC_CHANNEL_CALLBACK * callback,
|
|||
UINT32 UsbDevice,
|
||||
int transferDir)
|
||||
{
|
||||
IUDEVICE * pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, OutputBufferSize, usbd_status;
|
||||
BYTE Recipient, InterfaceNumber, Ms_PageIndex;
|
||||
UINT16 Ms_featureDescIndex;
|
||||
BYTE * out_data;
|
||||
BYTE * buffer;
|
||||
int offset, ret;
|
||||
IUDEVICE* pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, OutputBufferSize, usbd_status;
|
||||
BYTE Recipient, InterfaceNumber, Ms_PageIndex;
|
||||
UINT16 Ms_featureDescIndex;
|
||||
BYTE* out_data;
|
||||
BYTE* buffer;
|
||||
int offset, ret;
|
||||
|
||||
pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice);
|
||||
|
||||
if (pdev == NULL)
|
||||
return 0;
|
||||
|
||||
InterfaceId = ((STREAM_ID_PROXY<<30) | pdev->get_ReqCompletion(pdev));
|
||||
|
||||
data_read_UINT32(data + 0, RequestId);
|
||||
|
@ -1351,14 +1347,11 @@ urb_os_feature_descriptor_request(URBDRC_CHANNEL_CALLBACK * callback,
|
|||
callback->channel->Write(callback->channel, out_size, out_data, NULL);
|
||||
|
||||
zfree(out_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int
|
||||
urb_pipe_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
static int urb_pipe_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
UINT32 data_sizem,
|
||||
UINT32 MessageId,
|
||||
IUDEVMAN * udevman,
|
||||
|
@ -1366,11 +1359,11 @@ urb_pipe_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
|||
int transferDir,
|
||||
int action)
|
||||
{
|
||||
IUDEVICE * pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, PipeHandle, EndpointAddress;
|
||||
UINT32 OutputBufferSize, usbd_status = 0;
|
||||
BYTE * out_data;
|
||||
int out_offset, ret;
|
||||
IUDEVICE* pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, PipeHandle, EndpointAddress;
|
||||
UINT32 OutputBufferSize, usbd_status = 0;
|
||||
BYTE* out_data;
|
||||
int out_offset, ret;
|
||||
|
||||
if (transferDir == 0){
|
||||
LLOGLN(urbdrc_debug, ("urb_pipe_request: not support transfer out\n"));
|
||||
|
@ -1378,8 +1371,10 @@ urb_pipe_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
|||
}
|
||||
|
||||
pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice);
|
||||
|
||||
if (pdev == NULL)
|
||||
return 0;
|
||||
|
||||
InterfaceId = ((STREAM_ID_PROXY<<30) | pdev->get_ReqCompletion(pdev));
|
||||
|
||||
data_read_UINT32(data + 0, RequestId);
|
||||
|
@ -1445,14 +1440,11 @@ urb_pipe_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
|||
if (!pdev->isSigToEnd(pdev))
|
||||
callback->channel->Write(callback->channel, out_size, out_data, NULL);
|
||||
zfree(out_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int
|
||||
urb_get_current_frame_number(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
static int urb_get_current_frame_number(URBDRC_CHANNEL_CALLBACK* callback,
|
||||
BYTE * data,
|
||||
UINT32 data_sizem,
|
||||
UINT32 MessageId,
|
||||
|
@ -1460,10 +1452,10 @@ urb_get_current_frame_number(URBDRC_CHANNEL_CALLBACK * callback,
|
|||
UINT32 UsbDevice,
|
||||
int transferDir)
|
||||
{
|
||||
IUDEVICE * pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, OutputBufferSize;
|
||||
UINT32 dummy_frames;
|
||||
BYTE * out_data;
|
||||
IUDEVICE* pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, OutputBufferSize;
|
||||
UINT32 dummy_frames;
|
||||
BYTE* out_data;
|
||||
|
||||
if (transferDir == 0){
|
||||
LLOGLN(urbdrc_debug, ("urb_get_current_frame_number: not support transfer out\n"));
|
||||
|
@ -1510,8 +1502,7 @@ urb_get_current_frame_number(URBDRC_CHANNEL_CALLBACK * callback,
|
|||
|
||||
|
||||
/* Unused function for current server */
|
||||
static int
|
||||
urb_control_get_configuration_request(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
static int urb_control_get_configuration_request(URBDRC_CHANNEL_CALLBACK* callback,
|
||||
BYTE * data,
|
||||
UINT32 data_sizem,
|
||||
UINT32 MessageId,
|
||||
|
@ -1519,21 +1510,24 @@ urb_control_get_configuration_request(URBDRC_CHANNEL_CALLBACK * callback,
|
|||
UINT32 UsbDevice,
|
||||
int transferDir)
|
||||
{
|
||||
IUDEVICE * pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, OutputBufferSize, usbd_status;
|
||||
BYTE * buffer;
|
||||
BYTE * out_data;
|
||||
int ret, offset;
|
||||
IUDEVICE* pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, OutputBufferSize, usbd_status;
|
||||
BYTE* buffer;
|
||||
BYTE* out_data;
|
||||
int ret, offset;
|
||||
|
||||
if (transferDir == 0){
|
||||
if (transferDir == 0)
|
||||
{
|
||||
LLOGLN(urbdrc_debug, ("urb_control_get_configuration_request:"
|
||||
" not support transfer out\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice);
|
||||
|
||||
if (pdev == NULL)
|
||||
return 0;
|
||||
|
||||
InterfaceId = ((STREAM_ID_PROXY<<30) | pdev->get_ReqCompletion(pdev));
|
||||
|
||||
data_read_UINT32(data + 0, RequestId);
|
||||
|
@ -1589,8 +1583,7 @@ urb_control_get_configuration_request(URBDRC_CHANNEL_CALLBACK * callback,
|
|||
}
|
||||
|
||||
/* Unused function for current server */
|
||||
static int
|
||||
urb_control_get_interface_request(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
static int urb_control_get_interface_request(URBDRC_CHANNEL_CALLBACK* callback,
|
||||
BYTE * data,
|
||||
UINT32 data_sizem,
|
||||
UINT32 MessageId,
|
||||
|
@ -1598,12 +1591,12 @@ urb_control_get_interface_request(URBDRC_CHANNEL_CALLBACK * callback,
|
|||
UINT32 UsbDevice,
|
||||
int transferDir)
|
||||
{
|
||||
IUDEVICE * pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, OutputBufferSize, usbd_status;
|
||||
UINT16 interface;
|
||||
BYTE * buffer;
|
||||
BYTE * out_data;
|
||||
int ret, offset;
|
||||
IUDEVICE* pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, OutputBufferSize, usbd_status;
|
||||
UINT16 interface;
|
||||
BYTE* buffer;
|
||||
BYTE* out_data;
|
||||
int ret, offset;
|
||||
|
||||
if (transferDir == 0){
|
||||
LLOGLN(urbdrc_debug, ("urb_control_get_interface_request: not support transfer out\n"));
|
||||
|
@ -1666,8 +1659,7 @@ urb_control_get_interface_request(URBDRC_CHANNEL_CALLBACK * callback,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
urb_control_feature_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
static int urb_control_feature_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
UINT32 data_sizem,
|
||||
UINT32 MessageId,
|
||||
IUDEVMAN * udevman,
|
||||
|
@ -1676,17 +1668,19 @@ urb_control_feature_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
|||
BYTE command,
|
||||
int transferDir)
|
||||
{
|
||||
IUDEVICE * pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, OutputBufferSize, usbd_status;
|
||||
UINT16 FeatureSelector, Index;
|
||||
BYTE bmRequestType, bmRequest;
|
||||
BYTE * buffer;
|
||||
BYTE * out_data;
|
||||
int ret, offset;
|
||||
IUDEVICE* pdev;
|
||||
UINT32 out_size, RequestId, InterfaceId, OutputBufferSize, usbd_status;
|
||||
UINT16 FeatureSelector, Index;
|
||||
BYTE bmRequestType, bmRequest;
|
||||
BYTE* buffer;
|
||||
BYTE* out_data;
|
||||
int ret, offset;
|
||||
|
||||
pdev = udevman->get_udevice_by_UsbDevice(udevman, UsbDevice);
|
||||
|
||||
if (pdev == NULL)
|
||||
return 0;
|
||||
|
||||
InterfaceId = ((STREAM_ID_PROXY<<30) | pdev->get_ReqCompletion(pdev));
|
||||
|
||||
data_read_UINT32(data + 0, RequestId);
|
||||
|
@ -1769,8 +1763,7 @@ urb_control_feature_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
urbdrc_process_transfer_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
static int urbdrc_process_transfer_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
||||
UINT32 data_sizem,
|
||||
UINT32 MessageId,
|
||||
IUDEVMAN * udevman,
|
||||
|
@ -2296,13 +2289,13 @@ urbdrc_process_transfer_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE * data,
|
|||
break;
|
||||
default:
|
||||
LLOGLN(urbdrc_debug, ("URB_Func: %x is not found!", URB_Function));
|
||||
break;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void*
|
||||
urbdrc_process_udev_data_transfer(void* arg)
|
||||
void* urbdrc_process_udev_data_transfer(void* arg)
|
||||
{
|
||||
TRANSFER_DATA* transfer_data = (TRANSFER_DATA*) arg;
|
||||
URBDRC_CHANNEL_CALLBACK * callback = transfer_data->callback;
|
||||
|
@ -2450,5 +2443,3 @@ urbdrc_process_udev_data_transfer(void* arg)
|
|||
udevman->push_urb(udevman);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -149,9 +149,11 @@ void isoch_queue_free(ISOCH_CALLBACK_QUEUE* 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);
|
||||
|
|
|
@ -16,8 +16,7 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set(MODULE_NAME "libusb-devman")
|
||||
set(MODULE_PREFIX "CHANNEL_URBDRC_LIBUSB_DEVMAN")
|
||||
define_channel_client_subsystem("urbdrc" "libusb" "")
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
libusb_udevman.c
|
||||
|
@ -26,25 +25,27 @@ set(${MODULE_PREFIX}_SRCS
|
|||
request_queue.c
|
||||
request_queue.h)
|
||||
|
||||
include_directories(../client)
|
||||
include_directories(..)
|
||||
|
||||
if(STATIC_CHANNELS)
|
||||
add_library(${MODULE_NAME} STATIC ${${MODULE_PREFIX}_SRCS})
|
||||
else()
|
||||
add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
endif()
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS
|
||||
${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS}
|
||||
dbus-glib-1
|
||||
usb-1.0
|
||||
pthread
|
||||
udev)
|
||||
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
MODULE winpr
|
||||
MODULES winpr-utils)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
if(NOT STATIC_CHANNELS)
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH})
|
||||
endif()
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -22,6 +22,11 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/cmdline.h>
|
||||
|
||||
#include <freerdp/addin.h>
|
||||
|
||||
#include "urbdrc_types.h"
|
||||
#include "urbdrc_main.h"
|
||||
|
||||
|
@ -61,19 +66,20 @@ struct _UDEVMAN
|
|||
int sem_timeout;
|
||||
|
||||
pthread_mutex_t devman_loading;
|
||||
sem_t sem_urb_lock;
|
||||
sem_t sem_urb_lock;
|
||||
};
|
||||
typedef UDEVMAN * PUDEVMAN;
|
||||
typedef UDEVMAN* PUDEVMAN;
|
||||
|
||||
static void udevman_rewind(IUDEVMAN* idevman)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
UDEVMAN* udevman = (UDEVMAN*) idevman;
|
||||
udevman->idev = udevman->head;
|
||||
}
|
||||
|
||||
static int udevman_has_next(IUDEVMAN* idevman)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
UDEVMAN* udevman = (UDEVMAN*) idevman;
|
||||
|
||||
if (udevman->idev == NULL)
|
||||
return 0;
|
||||
else
|
||||
|
@ -82,60 +88,63 @@ static int udevman_has_next(IUDEVMAN* idevman)
|
|||
|
||||
static IUDEVICE* udevman_get_next(IUDEVMAN* idevman)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN*) idevman;
|
||||
UDEVMAN* udevman = (UDEVMAN*) idevman;
|
||||
IUDEVICE* pdev;
|
||||
|
||||
pdev = udevman->idev;
|
||||
udevman->idev = (IUDEVICE*) ((UDEVICE*)udevman->idev)->next;
|
||||
udevman->idev = (IUDEVICE*) ((UDEVICE*) udevman->idev)->next;
|
||||
|
||||
return pdev;
|
||||
}
|
||||
|
||||
static IUDEVICE* udevman_get_udevice_by_addr(IUDEVMAN* idevman, int bus_number, int dev_number)
|
||||
{
|
||||
IUDEVICE * pdev;
|
||||
IUDEVICE* pdev;
|
||||
|
||||
idevman->loading_lock(idevman);
|
||||
idevman->rewind (idevman);
|
||||
while (idevman->has_next (idevman))
|
||||
idevman->rewind(idevman);
|
||||
|
||||
while (idevman->has_next(idevman))
|
||||
{
|
||||
pdev = idevman->get_next (idevman);
|
||||
if (pdev->get_bus_number(pdev) == bus_number &&
|
||||
pdev->get_dev_number(pdev) == dev_number)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
idevman->loading_unlock(idevman);
|
||||
LLOGLN(libusb_debug, ("%s: bus:%d dev:%d not exist in udevman",
|
||||
__func__, bus_number, dev_number));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int udevman_register_udevice(IUDEVMAN* idevman, int bus_number, int dev_number,
|
||||
int UsbDevice,
|
||||
UINT16 idVendor,
|
||||
UINT16 idProduct,
|
||||
int flag)
|
||||
int UsbDevice, UINT16 idVendor, UINT16 idProduct, int flag)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
IUDEVICE * pdev = NULL;
|
||||
IUDEVICE ** devArray;
|
||||
UDEVMAN* udevman = (UDEVMAN*) idevman;
|
||||
IUDEVICE* pdev = NULL;
|
||||
IUDEVICE** devArray;
|
||||
int i, num, addnum = 0;
|
||||
|
||||
pdev = (IUDEVICE *)udevman_get_udevice_by_addr(idevman, bus_number, dev_number);
|
||||
pdev = (IUDEVICE*) udevman_get_udevice_by_addr(idevman, bus_number, dev_number);
|
||||
|
||||
if (pdev != NULL)
|
||||
return 0;
|
||||
|
||||
if (flag == UDEVMAN_FLAG_ADD_BY_ADDR)
|
||||
{
|
||||
pdev = udev_new_by_addr(bus_number, dev_number);
|
||||
|
||||
if (pdev == NULL)
|
||||
return 0;
|
||||
|
||||
pdev->set_UsbDevice(pdev, UsbDevice);
|
||||
idevman->loading_lock(idevman);
|
||||
|
||||
if (udevman->head == NULL)
|
||||
{
|
||||
/* linked list is empty */
|
||||
|
@ -149,6 +158,7 @@ static int udevman_register_udevice(IUDEVMAN* idevman, int bus_number, int dev_n
|
|||
pdev->set_p_prev(pdev, udevman->tail);
|
||||
udevman->tail = pdev;
|
||||
}
|
||||
|
||||
udevman->device_num += 1;
|
||||
idevman->loading_unlock(idevman);
|
||||
}
|
||||
|
@ -157,13 +167,13 @@ 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);
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
pdev = devArray[i];
|
||||
|
||||
if (udevman_get_udevice_by_addr(idevman,
|
||||
pdev->get_bus_number(pdev),
|
||||
pdev->get_dev_number(pdev))
|
||||
!= NULL)
|
||||
pdev->get_bus_number(pdev), pdev->get_dev_number(pdev)) != NULL)
|
||||
{
|
||||
zfree(pdev);
|
||||
continue;
|
||||
|
@ -171,6 +181,7 @@ static int udevman_register_udevice(IUDEVMAN* idevman, int bus_number, int dev_n
|
|||
|
||||
pdev->set_UsbDevice(pdev, UsbDevice);
|
||||
idevman->loading_lock(idevman);
|
||||
|
||||
if (udevman->head == NULL)
|
||||
{
|
||||
/* linked list is empty */
|
||||
|
@ -184,10 +195,12 @@ static int udevman_register_udevice(IUDEVMAN* idevman, int bus_number, int dev_n
|
|||
pdev->set_p_prev(pdev, udevman->tail);
|
||||
udevman->tail = pdev;
|
||||
}
|
||||
|
||||
udevman->device_num += 1;
|
||||
idevman->loading_unlock(idevman);
|
||||
addnum++;
|
||||
}
|
||||
|
||||
zfree(devArray);
|
||||
return addnum;
|
||||
}
|
||||
|
@ -196,23 +209,24 @@ static int udevman_register_udevice(IUDEVMAN* idevman, int bus_number, int dev_n
|
|||
printf("udevman_register_udevice: function error!!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int udevman_unregister_udevice(IUDEVMAN* idevman, int bus_number, int dev_number)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
UDEVMAN* udevman = (UDEVMAN*) idevman;
|
||||
UDEVICE * pdev, * dev;
|
||||
int ret = 0, err = 0;
|
||||
|
||||
dev = (UDEVICE *)udevman_get_udevice_by_addr(idevman, bus_number, dev_number);
|
||||
dev = (UDEVICE*) udevman_get_udevice_by_addr(idevman, bus_number, dev_number);
|
||||
|
||||
idevman->loading_lock(idevman);
|
||||
idevman->rewind(idevman);
|
||||
|
||||
while (idevman->has_next(idevman) != 0)
|
||||
{
|
||||
pdev = (UDEVICE *)idevman->get_next(idevman);
|
||||
pdev = (UDEVICE*) idevman->get_next(idevman);
|
||||
|
||||
if (pdev == dev) /* device exists */
|
||||
{
|
||||
|
@ -280,30 +294,33 @@ static int udevman_unregister_udevice(IUDEVMAN* idevman, int bus_number, int dev
|
|||
return 1; /* unregistration successful */
|
||||
}
|
||||
|
||||
|
||||
/* if we reach this point, the device wasn't found */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void udevman_parse_device_addr (char *str, int *id1, int *id2, char sign)
|
||||
static void udevman_parse_device_addr(char* str, int* id1, int* id2, char sign)
|
||||
{
|
||||
char s1[8], *s2;
|
||||
memset(s1, 0, sizeof(s1));
|
||||
char s1[8];
|
||||
char* s2;
|
||||
|
||||
ZeroMemory(s1, sizeof(s1));
|
||||
|
||||
s2 = (strchr(str, sign)) + 1;
|
||||
strncpy(s1, str, strlen(str) - (strlen(s2)+1));
|
||||
strncpy(s1, str, strlen(str) - (strlen(s2) + 1));
|
||||
|
||||
*id1 = atoi(s1);
|
||||
*id2 = atoi(s2);
|
||||
}
|
||||
|
||||
static void udevman_parse_device_pid_vid (char *str, int *id1, int *id2, char sign)
|
||||
static void udevman_parse_device_pid_vid(char* str, int* id1, int* id2, char sign)
|
||||
{
|
||||
char s1[8], *s2;
|
||||
memset(s1, 0, sizeof(s1));
|
||||
char s1[8];
|
||||
char* s2;
|
||||
|
||||
ZeroMemory(s1, sizeof(s1));
|
||||
|
||||
s2 = (strchr(str, sign)) + 1;
|
||||
strncpy(s1, str, strlen(str) - (strlen(s2)+1));
|
||||
strncpy(s1, str, strlen(str) - (strlen(s2) + 1));
|
||||
|
||||
*id1 = (int) strtol(s1, NULL, 16);
|
||||
*id2 = (int) strtol(s2, NULL, 16);
|
||||
|
@ -311,7 +328,7 @@ static void udevman_parse_device_pid_vid (char *str, int *id1, int *id2, char si
|
|||
|
||||
static int udevman_check_device_exist_by_id(IUDEVMAN* idevman, UINT16 idVendor, UINT16 idProduct)
|
||||
{
|
||||
if (libusb_open_device_with_vid_pid (NULL, idVendor, idProduct))
|
||||
if (libusb_open_device_with_vid_pid(NULL, idVendor, idProduct))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
@ -319,106 +336,113 @@ static int udevman_check_device_exist_by_id(IUDEVMAN* idevman, UINT16 idVendor,
|
|||
|
||||
static int udevman_is_auto_add(IUDEVMAN* idevman)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
UDEVMAN* udevman = (UDEVMAN*) 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;
|
||||
UDEVICE* pdev;
|
||||
idevman->loading_lock(idevman);
|
||||
idevman->rewind (idevman);
|
||||
while (idevman->has_next (idevman))
|
||||
idevman->rewind(idevman);
|
||||
|
||||
while (idevman->has_next(idevman))
|
||||
{
|
||||
pdev = (UDEVICE *)idevman->get_next (idevman);
|
||||
pdev = (UDEVICE*) idevman->get_next(idevman);
|
||||
|
||||
if (pdev->UsbDevice == UsbDevice)
|
||||
{
|
||||
idevman->loading_unlock(idevman);
|
||||
return (IUDEVICE *)pdev;
|
||||
return (IUDEVICE*) pdev;
|
||||
}
|
||||
}
|
||||
|
||||
idevman->loading_unlock(idevman);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static IUDEVICE* udevman_get_udevice_by_UsbDevice(IUDEVMAN* idevman, UINT32 UsbDevice)
|
||||
{
|
||||
UDEVICE * pdev;
|
||||
UDEVICE* pdev;
|
||||
idevman->loading_lock(idevman);
|
||||
idevman->rewind (idevman);
|
||||
while (idevman->has_next (idevman))
|
||||
idevman->rewind(idevman);
|
||||
|
||||
while (idevman->has_next(idevman))
|
||||
{
|
||||
pdev = (UDEVICE *)idevman->get_next (idevman);
|
||||
pdev = (UDEVICE*) idevman->get_next(idevman);
|
||||
|
||||
if (pdev->UsbDevice == UsbDevice)
|
||||
{
|
||||
idevman->loading_unlock(idevman);
|
||||
return (IUDEVICE *)pdev;
|
||||
return (IUDEVICE*) pdev;
|
||||
}
|
||||
}
|
||||
|
||||
idevman->loading_unlock(idevman);
|
||||
|
||||
/* try again */
|
||||
pdev = (UDEVICE *)idevman->get_udevice_by_UsbDevice_try_again(idevman, UsbDevice);
|
||||
|
||||
pdev = (UDEVICE*) idevman->get_udevice_by_UsbDevice_try_again(idevman, UsbDevice);
|
||||
|
||||
if (pdev)
|
||||
{
|
||||
return (IUDEVICE *)pdev;
|
||||
return (IUDEVICE*) pdev;
|
||||
}
|
||||
|
||||
LLOGLN(libusb_debug, ("udevman_get_udevice_by_UsbDevice: 0x%x ERROR!!\n",
|
||||
UsbDevice));
|
||||
LLOGLN(libusb_debug, ("udevman_get_udevice_by_UsbDevice: 0x%x ERROR!!\n", UsbDevice));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void udevman_loading_lock(IUDEVMAN* idevman)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
UDEVMAN* udevman = (UDEVMAN*) idevman;
|
||||
pthread_mutex_lock(&udevman->devman_loading);
|
||||
}
|
||||
|
||||
static void udevman_loading_unlock(IUDEVMAN* idevman)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
UDEVMAN* udevman = (UDEVMAN*) idevman;
|
||||
pthread_mutex_unlock(&udevman->devman_loading);
|
||||
}
|
||||
|
||||
|
||||
static void udevman_wait_urb(IUDEVMAN* idevman)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
UDEVMAN* udevman = (UDEVMAN*) idevman;
|
||||
sem_wait(&udevman->sem_urb_lock);
|
||||
}
|
||||
|
||||
|
||||
static void udevman_push_urb(IUDEVMAN* idevman)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
UDEVMAN* udevman = (UDEVMAN*) idevman;
|
||||
sem_post(&udevman->sem_urb_lock);
|
||||
}
|
||||
|
||||
|
||||
BASIC_STATE_FUNC_DEFINED(defUsbDevice, UINT32)
|
||||
BASIC_STATE_FUNC_DEFINED(device_num, int)
|
||||
BASIC_STATE_FUNC_DEFINED(sem_timeout, int)
|
||||
|
||||
|
||||
static void udevman_free(IUDEVMAN* idevman)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
UDEVMAN* udevman = (UDEVMAN*) idevman;
|
||||
|
||||
pthread_mutex_destroy(&udevman->devman_loading);
|
||||
sem_destroy(&udevman->sem_urb_lock);
|
||||
|
||||
libusb_exit(NULL);
|
||||
|
||||
/* free udevman */
|
||||
|
||||
if (udevman)
|
||||
zfree(udevman);
|
||||
}
|
||||
|
||||
|
||||
static void udevman_load_interface(UDEVMAN * udevman)
|
||||
{
|
||||
/* standard */
|
||||
udevman->iface.free = udevman_free;
|
||||
|
||||
/* manage devices */
|
||||
udevman->iface.rewind = udevman_rewind;
|
||||
udevman->iface.get_next = udevman_get_next;
|
||||
|
@ -428,13 +452,16 @@ static void udevman_load_interface(UDEVMAN * udevman)
|
|||
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;
|
||||
|
||||
/* Basic state */
|
||||
BASIC_STATE_FUNC_REGISTER(defUsbDevice, udevman);
|
||||
BASIC_STATE_FUNC_REGISTER(device_num, udevman);
|
||||
BASIC_STATE_FUNC_REGISTER(sem_timeout, udevman);
|
||||
|
||||
/* control semaphore or mutex lock */
|
||||
udevman->iface.loading_lock = udevman_loading_lock;
|
||||
udevman->iface.loading_unlock = udevman_loading_unlock;
|
||||
|
@ -442,25 +469,127 @@ static void udevman_load_interface(UDEVMAN * udevman)
|
|||
udevman->iface.wait_urb = udevman_wait_urb;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int FreeRDPUDEVMANEntry(PFREERDP_URBDRC_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
COMMAND_LINE_ARGUMENT_A urbdrc_udevman_args[] =
|
||||
{
|
||||
UDEVMAN* udevman;
|
||||
RDP_PLUGIN_DATA * plugin_data = pEntryPoints->plugin_data;
|
||||
UINT32 UsbDevice = BASE_USBDEVICE_NUM;
|
||||
char * token;
|
||||
char * message = "id";
|
||||
char hardware_id[16];
|
||||
{ "dbg", COMMAND_LINE_VALUE_FLAG, "", NULL, BoolValueFalse, -1, NULL, "debug" },
|
||||
{ "dev", COMMAND_LINE_VALUE_REQUIRED, "<devices>", NULL, NULL, -1, NULL, "device list" },
|
||||
{ "id", COMMAND_LINE_VALUE_FLAG, "", NULL, BoolValueFalse, -1, NULL, "FLAG_ADD_BY_VID_PID" },
|
||||
{ "addr", COMMAND_LINE_VALUE_FLAG, "", NULL, BoolValueFalse, -1, NULL, "FLAG_ADD_BY_ADDR" },
|
||||
{ "auto", COMMAND_LINE_VALUE_FLAG, "", NULL, BoolValueFalse, -1, NULL, "FLAG_ADD_BY_AUTO" },
|
||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
static void urbdrc_udevman_register_devices(UDEVMAN* udevman, char* devices)
|
||||
{
|
||||
char* token;
|
||||
int idVendor;
|
||||
int idProduct;
|
||||
int bus_number;
|
||||
int dev_number;
|
||||
int bus_number;
|
||||
int dev_number;
|
||||
int success = 0;
|
||||
char hardware_id[16];
|
||||
char* default_devices = "id";
|
||||
UINT32 UsbDevice = BASE_USBDEVICE_NUM;
|
||||
|
||||
if (!devices)
|
||||
devices = default_devices;
|
||||
|
||||
/* register all usb devices */
|
||||
token = strtok(devices, "#");
|
||||
|
||||
while (token)
|
||||
{
|
||||
bus_number = 0;
|
||||
dev_number = 0;
|
||||
idVendor = 0;
|
||||
idProduct = 0;
|
||||
|
||||
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);
|
||||
}
|
||||
else if (udevman->flags & UDEVMAN_FLAG_ADD_BY_ADDR)
|
||||
{
|
||||
udevman_parse_device_addr(hardware_id, &bus_number, &dev_number, ':');
|
||||
|
||||
success = udevman->iface.register_udevice((IUDEVMAN*) udevman,
|
||||
bus_number, dev_number, UsbDevice, 0, 0, UDEVMAN_FLAG_ADD_BY_ADDR);
|
||||
}
|
||||
|
||||
if (success)
|
||||
UsbDevice++;
|
||||
}
|
||||
|
||||
udevman->defUsbDevice = UsbDevice;
|
||||
}
|
||||
|
||||
static void urbdrc_udevman_parse_addin_args(UDEVMAN* udevman, ADDIN_ARGV* args)
|
||||
{
|
||||
int status;
|
||||
DWORD flags;
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
|
||||
|
||||
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
|
||||
urbdrc_udevman_args, flags, udevman, NULL, NULL);
|
||||
|
||||
arg = urbdrc_udevman_args;
|
||||
|
||||
do
|
||||
{
|
||||
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
|
||||
continue;
|
||||
|
||||
CommandLineSwitchStart(arg)
|
||||
|
||||
CommandLineSwitchCase(arg, "dbg")
|
||||
{
|
||||
urbdrc_debug = 0;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "dev")
|
||||
{
|
||||
urbdrc_udevman_register_devices(udevman, arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "id")
|
||||
{
|
||||
udevman->flags = UDEVMAN_FLAG_ADD_BY_VID_PID;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "addr")
|
||||
{
|
||||
udevman->flags = UDEVMAN_FLAG_ADD_BY_ADDR;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "auto")
|
||||
{
|
||||
udevman->flags |= UDEVMAN_FLAG_ADD_BY_AUTO;
|
||||
}
|
||||
CommandLineSwitchDefault(arg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CommandLineSwitchEnd(arg)
|
||||
}
|
||||
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_urbdrc_client_subsystem_entry libusb_freerdp_urbdrc_client_subsystem_entry
|
||||
#endif
|
||||
|
||||
int freerdp_urbdrc_client_subsystem_entry(PFREERDP_URBDRC_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
UDEVMAN* udevman;
|
||||
ADDIN_ARGV* args = pEntryPoints->args;
|
||||
|
||||
libusb_init(NULL);
|
||||
|
||||
udevman = (PUDEVMAN)malloc(sizeof(UDEVMAN));
|
||||
udevman = (PUDEVMAN) malloc(sizeof(UDEVMAN));
|
||||
udevman->device_num = 0;
|
||||
udevman->idev = NULL;
|
||||
udevman->head = NULL;
|
||||
|
@ -474,66 +603,11 @@ int FreeRDPUDEVMANEntry(PFREERDP_URBDRC_SERVICE_ENTRY_POINTS pEntryPoints)
|
|||
/* load usb device service management */
|
||||
udevman_load_interface(udevman);
|
||||
|
||||
/* set debug flag, to enable Debug message for usb data transfer*/
|
||||
if (plugin_data->data[2])
|
||||
message = (char *)plugin_data->data[2];
|
||||
/* set debug flag, to enable Debug message for usb data transfer */
|
||||
|
||||
if (strstr(message, "id"))
|
||||
udevman->flags = UDEVMAN_FLAG_ADD_BY_VID_PID;
|
||||
else if (strstr(message, "addr"))
|
||||
udevman->flags = UDEVMAN_FLAG_ADD_BY_ADDR;
|
||||
|
||||
if (strstr(message, "auto"))
|
||||
udevman->flags |= UDEVMAN_FLAG_ADD_BY_AUTO;
|
||||
libusb_debug = 10;
|
||||
if (strstr(message, "debug"))
|
||||
{
|
||||
libusb_debug = 0;
|
||||
udevman->flags |= UDEVMAN_FLAG_DEBUG;
|
||||
}
|
||||
/* register all usb device */
|
||||
token = strtok((char *)plugin_data->data[1], "#");
|
||||
while (token)
|
||||
{
|
||||
bus_number = 0;
|
||||
dev_number = 0;
|
||||
idVendor = 0;
|
||||
idProduct = 0;
|
||||
|
||||
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);
|
||||
}
|
||||
else if (udevman->flags & UDEVMAN_FLAG_ADD_BY_ADDR)
|
||||
{
|
||||
udevman_parse_device_addr(hardware_id, &bus_number,
|
||||
&dev_number,
|
||||
'_');
|
||||
success = udevman->iface.register_udevice((IUDEVMAN *)udevman,
|
||||
bus_number,
|
||||
dev_number,
|
||||
UsbDevice,
|
||||
0,
|
||||
0,
|
||||
UDEVMAN_FLAG_ADD_BY_ADDR);
|
||||
}
|
||||
|
||||
if (success)
|
||||
UsbDevice++;
|
||||
}
|
||||
|
||||
udevman->defUsbDevice = UsbDevice;
|
||||
urbdrc_udevman_parse_addin_args(udevman, args);
|
||||
|
||||
pEntryPoints->pRegisterUDEVMAN(pEntryPoints->plugin, (IUDEVMAN*) udevman);
|
||||
|
|
@ -43,12 +43,11 @@ int request_queue_has_next(REQUEST_QUEUE* queue)
|
|||
}
|
||||
|
||||
TRANSFER_REQUEST* request_queue_register_request(REQUEST_QUEUE* queue, UINT32 RequestId,
|
||||
struct libusb_transfer * transfer,
|
||||
BYTE endpoint)
|
||||
struct libusb_transfer* transfer, BYTE endpoint)
|
||||
{
|
||||
TRANSFER_REQUEST* request;
|
||||
TRANSFER_REQUEST* request;
|
||||
|
||||
request = (TRANSFER_REQUEST*)malloc(sizeof(TRANSFER_REQUEST));
|
||||
request = (TRANSFER_REQUEST*) malloc(sizeof(TRANSFER_REQUEST));
|
||||
|
||||
request->prev = NULL;
|
||||
request->next = NULL;
|
||||
|
@ -57,7 +56,9 @@ TRANSFER_REQUEST* request_queue_register_request(REQUEST_QUEUE* queue, UINT32 Re
|
|||
request->transfer = transfer;
|
||||
request->endpoint = endpoint;
|
||||
request->submit = 0;
|
||||
|
||||
pthread_mutex_lock(&queue->request_loading);
|
||||
|
||||
if (queue->head == NULL)
|
||||
{
|
||||
/* linked queue is empty */
|
||||
|
@ -67,22 +68,24 @@ TRANSFER_REQUEST* request_queue_register_request(REQUEST_QUEUE* queue, UINT32 Re
|
|||
else
|
||||
{
|
||||
/* append data to the end of the linked queue */
|
||||
queue->tail->next = (void*)request;
|
||||
request->prev = (void*)queue->tail;
|
||||
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)
|
||||
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_queue_get_request_by_endpoint(REQUEST_QUEUE* queue, BYTE ep)
|
||||
{
|
||||
TRANSFER_REQUEST * request;
|
||||
pthread_mutex_lock(&queue->request_loading);
|
||||
|
@ -101,7 +104,7 @@ TRANSFER_REQUEST* request_queue_get_request_by_endpoint(REQUEST_QUEUE *queue, BY
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int request_queue_unregister_request(REQUEST_QUEUE *queue, UINT32 RequestId)
|
||||
int request_queue_unregister_request(REQUEST_QUEUE* queue, UINT32 RequestId)
|
||||
{
|
||||
TRANSFER_REQUEST *request, *request_temp;
|
||||
pthread_mutex_lock(&queue->request_loading);
|
||||
|
@ -110,27 +113,28 @@ int request_queue_unregister_request(REQUEST_QUEUE *queue, UINT32 RequestId)
|
|||
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;
|
||||
request_temp = (TRANSFER_REQUEST*) request->prev;
|
||||
request_temp->next = (TRANSFER_REQUEST*) request->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
queue->head = (TRANSFER_REQUEST*)request->next;
|
||||
queue->head = (TRANSFER_REQUEST*) request->next;
|
||||
}
|
||||
|
||||
if (request->next != NULL)
|
||||
{
|
||||
request_temp = (TRANSFER_REQUEST*)request->next;
|
||||
request_temp->prev = (TRANSFER_REQUEST*)request->prev;
|
||||
request_temp = (TRANSFER_REQUEST*) request->next;
|
||||
request_temp->prev = (TRANSFER_REQUEST*) request->prev;
|
||||
}
|
||||
else
|
||||
{
|
||||
queue->tail = (TRANSFER_REQUEST*)request->prev;
|
||||
queue->tail = (TRANSFER_REQUEST*) request->prev;
|
||||
|
||||
}
|
||||
|
||||
|
@ -156,7 +160,7 @@ REQUEST_QUEUE* request_queue_new()
|
|||
{
|
||||
REQUEST_QUEUE* queue;
|
||||
|
||||
queue = (REQUEST_QUEUE*)malloc(sizeof(REQUEST_QUEUE));
|
||||
queue = (REQUEST_QUEUE*) malloc(sizeof(REQUEST_QUEUE));
|
||||
queue->request_num = 0;
|
||||
queue->ireq = NULL;
|
||||
queue->head = NULL;
|
|
@ -25,8 +25,11 @@
|
|||
#include <time.h>
|
||||
#include <libudev.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/cmdline.h>
|
||||
|
||||
#include <freerdp/dvc.h>
|
||||
#include <freerdp/utils/load_plugin.h>
|
||||
#include <freerdp/addin.h>
|
||||
|
||||
#include "urbdrc_types.h"
|
||||
#include "urbdrc_main.h"
|
||||
|
@ -54,7 +57,7 @@ static int func_hardware_id_format(IUDEVICE* pdev, char (*HardwareIds)[DEVICE_HA
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int func_compat_id_format(IUDEVICE *pdev, char (*CompatibilityIds)[DEVICE_COMPATIBILITY_ID_SIZE])
|
||||
static int func_compat_id_format(IUDEVICE* pdev, char (*CompatibilityIds)[DEVICE_COMPATIBILITY_ID_SIZE])
|
||||
{
|
||||
char str[DEVICE_COMPATIBILITY_ID_SIZE];
|
||||
int bDeviceClass, bDeviceSubClass, bDeviceProtocol;
|
||||
|
@ -260,8 +263,9 @@ static int urbdrc_process_channel_create(URBDRC_CHANNEL_CALLBACK* callback, char
|
|||
InterfaceId = ((STREAM_ID_PROXY<<30) | CLIENT_CHANNEL_NOTIFICATION);
|
||||
|
||||
out_size = 24;
|
||||
out_data = (char *) malloc(out_size);
|
||||
out_data = (char*) malloc(out_size);
|
||||
memset(out_data, 0, out_size);
|
||||
|
||||
data_write_UINT32(out_data + 0, InterfaceId); /* interface id */
|
||||
data_write_UINT32(out_data + 4, MessageId); /* message id */
|
||||
data_write_UINT32(out_data + 8, CHANNEL_CREATED); /* function id */
|
||||
|
@ -285,8 +289,9 @@ static int urdbrc_send_virtual_channel_add(IWTSVirtualChannel* channel, UINT32 M
|
|||
InterfaceId = ((STREAM_ID_PROXY<<30) | CLIENT_DEVICE_SINK);
|
||||
|
||||
out_size = 12;
|
||||
out_data = (char *) malloc(out_size);
|
||||
out_data = (char*) malloc(out_size);
|
||||
memset(out_data, 0, out_size);
|
||||
|
||||
data_write_UINT32(out_data + 0, InterfaceId); /* interface */
|
||||
data_write_UINT32(out_data + 4, MessageId); /* message id */
|
||||
data_write_UINT32(out_data + 8, ADD_VIRTUAL_CHANNEL); /* function id */
|
||||
|
@ -651,9 +656,9 @@ static void* urbdrc_search_usb_device(void* arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void* urbdrc_new_device_create(void * arg)
|
||||
void* urbdrc_new_device_create(void* arg)
|
||||
{
|
||||
TRANSFER_DATA* transfer_data = (TRANSFER_DATA*) arg;
|
||||
TRANSFER_DATA* transfer_data = (TRANSFER_DATA*) arg;
|
||||
URBDRC_CHANNEL_CALLBACK* callback = transfer_data->callback;
|
||||
IWTSVirtualChannelManager* channel_mgr;
|
||||
URBDRC_PLUGIN* urbdrc = transfer_data->urbdrc;
|
||||
|
@ -756,7 +761,7 @@ static int urbdrc_process_channel_notification(URBDRC_CHANNEL_CALLBACK* callback
|
|||
transfer_data->udevman = urbdrc->udevman;
|
||||
transfer_data->urbdrc = urbdrc;
|
||||
transfer_data->cbSize = cbSize;
|
||||
transfer_data->pBuffer = (BYTE *)malloc((cbSize));
|
||||
transfer_data->pBuffer = (BYTE*) malloc((cbSize));
|
||||
|
||||
for (i = 0; i < (cbSize); i++)
|
||||
{
|
||||
|
@ -919,7 +924,7 @@ static int urbdrc_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManag
|
|||
{
|
||||
URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*) pPlugin;
|
||||
IUDEVMAN* udevman = NULL;
|
||||
USB_SEARCHMAN * searchman = NULL;
|
||||
USB_SEARCHMAN* searchman = NULL;
|
||||
|
||||
LLOGLN(10, ("urbdrc_plugin_initialize:"));
|
||||
urbdrc->listener_callback = (URBDRC_LISTENER_CALLBACK*) malloc(sizeof(URBDRC_LISTENER_CALLBACK));
|
||||
|
@ -935,7 +940,7 @@ static int urbdrc_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManag
|
|||
urbdrc->searchman = searchman;
|
||||
|
||||
return pChannelMgr->CreateListener(pChannelMgr, "URBDRC", 0,
|
||||
(IWTSListenerCallback *) urbdrc->listener_callback, NULL);
|
||||
(IWTSListenerCallback*) urbdrc->listener_callback, NULL);
|
||||
}
|
||||
|
||||
static int urbdrc_plugin_terminated(IWTSPlugin* pPlugin)
|
||||
|
@ -979,7 +984,7 @@ static int urbdrc_plugin_terminated(IWTSPlugin* pPlugin)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void urbdrc_register_udevman_plugin(IWTSPlugin* pPlugin, IUDEVMAN* udevman)
|
||||
static void urbdrc_register_udevman_addin(IWTSPlugin* pPlugin, IUDEVMAN* udevman)
|
||||
{
|
||||
URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*) pPlugin;
|
||||
|
||||
|
@ -994,31 +999,19 @@ static void urbdrc_register_udevman_plugin(IWTSPlugin* pPlugin, IUDEVMAN* udevma
|
|||
urbdrc->udevman = udevman;
|
||||
}
|
||||
|
||||
static int urbdrc_load_udevman_plugin(IWTSPlugin* pPlugin, const char* name, RDP_PLUGIN_DATA* data)
|
||||
static int urbdrc_load_udevman_addin(IWTSPlugin* pPlugin, const char* name, ADDIN_ARGV* args)
|
||||
{
|
||||
char* fullname;
|
||||
PFREERDP_URBDRC_DEVICE_ENTRY entry;
|
||||
FREERDP_URBDRC_SERVICE_ENTRY_POINTS entryPoints;
|
||||
|
||||
if (strrchr(name, '.') != NULL)
|
||||
{
|
||||
entry = (PFREERDP_URBDRC_DEVICE_ENTRY) freerdp_load_plugin(name, URBDRC_UDEVMAN_EXPORT_FUNC_NAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
fullname = xzalloc(strlen(name) + 8);
|
||||
strcpy(fullname, name);
|
||||
strcat(fullname, "_udevman");
|
||||
entry = (PFREERDP_URBDRC_DEVICE_ENTRY) freerdp_load_plugin(fullname, URBDRC_UDEVMAN_EXPORT_FUNC_NAME);
|
||||
free(fullname);
|
||||
}
|
||||
entry = (PFREERDP_URBDRC_DEVICE_ENTRY) freerdp_load_channel_addin_entry("urbdrc", (LPSTR) name, NULL, 0);
|
||||
|
||||
if (entry == NULL)
|
||||
return FALSE;
|
||||
|
||||
entryPoints.plugin = pPlugin;
|
||||
entryPoints.pRegisterUDEVMAN = urbdrc_register_udevman_plugin;
|
||||
entryPoints.plugin_data = data;
|
||||
entryPoints.pRegisterUDEVMAN = urbdrc_register_udevman_addin;
|
||||
entryPoints.args = args;
|
||||
|
||||
if (entry(&entryPoints) != 0)
|
||||
{
|
||||
|
@ -1029,17 +1022,57 @@ static int urbdrc_load_udevman_plugin(IWTSPlugin* pPlugin, const char* name, RDP
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static int urbdrc_process_plugin_data(IWTSPlugin* pPlugin, RDP_PLUGIN_DATA* data)
|
||||
void urbdrc_set_subsystem(URBDRC_PLUGIN* urbdrc, char* subsystem)
|
||||
{
|
||||
BOOL ret;
|
||||
if (urbdrc->subsystem)
|
||||
free(urbdrc->subsystem);
|
||||
|
||||
if (data->data[0] && (strcmp((char*)data->data[0], "urbdrc") == 0 || strstr((char*) data->data[0], "/urbdrc.") != NULL))
|
||||
urbdrc->subsystem = _strdup(subsystem);
|
||||
}
|
||||
|
||||
COMMAND_LINE_ARGUMENT_A urbdrc_args[] =
|
||||
{
|
||||
{ "dbg", COMMAND_LINE_VALUE_FLAG, "", NULL, BoolValueFalse, -1, NULL, "debug" },
|
||||
{ "sys", COMMAND_LINE_VALUE_REQUIRED, "<subsystem>", NULL, NULL, -1, NULL, "subsystem" },
|
||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
static void urbdrc_process_addin_args(URBDRC_PLUGIN* urbdrc, ADDIN_ARGV* args)
|
||||
{
|
||||
int status;
|
||||
DWORD flags;
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
|
||||
|
||||
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
|
||||
urbdrc_args, flags, urbdrc, NULL, NULL);
|
||||
|
||||
arg = urbdrc_args;
|
||||
|
||||
do
|
||||
{
|
||||
ret = urbdrc_load_udevman_plugin(pPlugin, "libusb", data);
|
||||
return ret;
|
||||
}
|
||||
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
|
||||
continue;
|
||||
|
||||
return TRUE;
|
||||
CommandLineSwitchStart(arg)
|
||||
|
||||
CommandLineSwitchCase(arg, "dbg")
|
||||
{
|
||||
urbdrc_debug = 0;
|
||||
}
|
||||
CommandLineSwitchCase(arg, "sys")
|
||||
{
|
||||
urbdrc_set_subsystem(urbdrc, arg->Value);
|
||||
}
|
||||
CommandLineSwitchDefault(arg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CommandLineSwitchEnd(arg)
|
||||
}
|
||||
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
|
@ -1048,16 +1081,17 @@ static int urbdrc_process_plugin_data(IWTSPlugin* pPlugin, RDP_PLUGIN_DATA* data
|
|||
|
||||
int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||
{
|
||||
int error = 0;
|
||||
int status = 0;
|
||||
ADDIN_ARGV* args;
|
||||
URBDRC_PLUGIN* urbdrc;
|
||||
RDP_PLUGIN_DATA* data;
|
||||
|
||||
urbdrc = (URBDRC_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "urbdrc");
|
||||
data = pEntryPoints->GetPluginData(pEntryPoints);
|
||||
args = pEntryPoints->GetPluginData(pEntryPoints);
|
||||
|
||||
if (urbdrc == NULL)
|
||||
{
|
||||
urbdrc = xnew(URBDRC_PLUGIN);
|
||||
urbdrc = (URBDRC_PLUGIN*) malloc(sizeof(URBDRC_PLUGIN));
|
||||
ZeroMemory(urbdrc, sizeof(URBDRC_PLUGIN));
|
||||
|
||||
urbdrc->iface.Initialize = urbdrc_plugin_initialize;
|
||||
urbdrc->iface.Connected = NULL;
|
||||
|
@ -1068,14 +1102,16 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
|||
|
||||
urbdrc_debug = 10;
|
||||
|
||||
if (data->data[2] && strstr((char *)data->data[2], "debug"))
|
||||
urbdrc_debug = 0;
|
||||
|
||||
error = pEntryPoints->RegisterPlugin(pEntryPoints, "urbdrc", (IWTSPlugin *) urbdrc);
|
||||
status = pEntryPoints->RegisterPlugin(pEntryPoints, "urbdrc", (IWTSPlugin*) urbdrc);
|
||||
}
|
||||
|
||||
if (error == 0)
|
||||
urbdrc_process_plugin_data((IWTSPlugin*) urbdrc, data);
|
||||
if (status == 0)
|
||||
urbdrc_process_addin_args(urbdrc, args);
|
||||
|
||||
return error;
|
||||
if (!urbdrc->subsystem)
|
||||
urbdrc_set_subsystem(urbdrc, "libusb");
|
||||
|
||||
urbdrc_load_udevman_addin((IWTSPlugin*) urbdrc, urbdrc->subsystem, args);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -35,11 +35,12 @@ typedef struct _IUDEVICE IUDEVICE;
|
|||
typedef struct _IUDEVMAN IUDEVMAN;
|
||||
|
||||
#define BASIC_DEV_STATE_DEFINED(_arg, _type) \
|
||||
_type (*get_##_arg) (IUDEVICE *pdev); \
|
||||
void (*set_##_arg) (IUDEVICE *pdev, _type _arg)
|
||||
_type (*get_##_arg) (IUDEVICE* pdev); \
|
||||
void (*set_##_arg) (IUDEVICE* pdev, _type _arg)
|
||||
|
||||
#define BASIC_DEVMAN_STATE_DEFINED(_arg, _type) \
|
||||
_type (*get_##_arg) (IUDEVMAN *udevman); \
|
||||
void (*set_##_arg) (IUDEVMAN *udevman, _type _arg)
|
||||
_type (*get_##_arg) (IUDEVMAN* udevman); \
|
||||
void (*set_##_arg) (IUDEVMAN* udevman, _type _arg)
|
||||
|
||||
typedef struct _URBDRC_LISTENER_CALLBACK URBDRC_LISTENER_CALLBACK;
|
||||
|
||||
|
@ -74,17 +75,16 @@ struct _URBDRC_PLUGIN
|
|||
USB_SEARCHMAN* searchman;
|
||||
UINT32 first_channel_id;
|
||||
UINT32 vchannel_status;
|
||||
char* subsystem;
|
||||
};
|
||||
|
||||
#define URBDRC_UDEVMAN_EXPORT_FUNC_NAME "FreeRDPUDEVMANEntry"
|
||||
|
||||
typedef void (*PREGISTERURBDRCSERVICE)(IWTSPlugin* plugin, IUDEVMAN* udevman);
|
||||
|
||||
struct _FREERDP_URBDRC_SERVICE_ENTRY_POINTS
|
||||
{
|
||||
IWTSPlugin* plugin;
|
||||
PREGISTERURBDRCSERVICE pRegisterUDEVMAN;
|
||||
RDP_PLUGIN_DATA* plugin_data;
|
||||
ADDIN_ARGV* args;
|
||||
};
|
||||
typedef struct _FREERDP_URBDRC_SERVICE_ENTRY_POINTS FREERDP_URBDRC_SERVICE_ENTRY_POINTS;
|
||||
typedef FREERDP_URBDRC_SERVICE_ENTRY_POINTS* PFREERDP_URBDRC_SERVICE_ENTRY_POINTS;
|
||||
|
@ -106,107 +106,75 @@ struct _TRANSFER_DATA
|
|||
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, 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 (*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 (*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, UINT32 RequestId, UINT32 EndpointAddress,
|
||||
UINT32 TransferFlags, UINT32* UsbdStatus, UINT32* BufferSize, BYTE* Buffer, UINT32 Timeout);
|
||||
|
||||
int (*select_configuration) (IUDEVICE* idev, UINT32 bConfigurationValue);
|
||||
|
||||
int (*select_configuration) (IUDEVICE * idev, UINT32 bConfigurationValue);
|
||||
|
||||
int (*select_interface) (IUDEVICE * idev, BYTE InterfaceNumber,
|
||||
int (*select_interface) (IUDEVICE* idev, BYTE InterfaceNumber,
|
||||
BYTE AlternateSetting);
|
||||
|
||||
int (*control_pipe_request) (IUDEVICE * idev, UINT32 RequestId,
|
||||
UINT32 EndpointAddress,
|
||||
UINT32 *UsbdStatus,
|
||||
int command);
|
||||
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);
|
||||
int (*control_query_device_text) (IUDEVICE* idev, UINT32 TextType,
|
||||
UINT32 LocaleId, UINT32*BufferSize, BYTE* Buffer);
|
||||
|
||||
int (*os_feature_descriptor_request) (IUDEVICE * idev, UINT32 RequestId,
|
||||
BYTE Recipient,
|
||||
BYTE InterfaceNumber,
|
||||
BYTE Ms_PageIndex,
|
||||
UINT16 Ms_featureDescIndex,
|
||||
UINT32 * UsbdStatus,
|
||||
UINT32 * BufferSize,
|
||||
BYTE* Buffer,
|
||||
int Timeout);
|
||||
int (*os_feature_descriptor_request) (IUDEVICE* idev, UINT32 RequestId, BYTE Recipient,
|
||||
BYTE InterfaceNumber, BYTE Ms_PageIndex, UINT16 Ms_featureDescIndex, UINT32* UsbdStatus,
|
||||
UINT32* BufferSize, BYTE* Buffer, int Timeout);
|
||||
|
||||
void (*cancel_all_transfer_request) (IUDEVICE * idev);
|
||||
void (*cancel_all_transfer_request) (IUDEVICE* idev);
|
||||
|
||||
int (*cancel_transfer_request) (IUDEVICE * idev, UINT32 RequestId);
|
||||
int (*cancel_transfer_request) (IUDEVICE* idev, UINT32 RequestId);
|
||||
|
||||
int (*query_device_descriptor) (IUDEVICE * idev, int offset);
|
||||
int (*query_device_descriptor) (IUDEVICE* idev, int offset);
|
||||
|
||||
void (*detach_kernel_driver) (IUDEVICE * idev);
|
||||
void (*detach_kernel_driver) (IUDEVICE* idev);
|
||||
|
||||
void (*attach_kernel_driver) (IUDEVICE * idev);
|
||||
void (*attach_kernel_driver) (IUDEVICE* idev);
|
||||
|
||||
int (*wait_action_completion) (IUDEVICE * idev);
|
||||
int (*wait_action_completion) (IUDEVICE* idev);
|
||||
|
||||
void (*push_action) (IUDEVICE * idev);
|
||||
void (*push_action) (IUDEVICE* idev);
|
||||
|
||||
void (*complete_action) (IUDEVICE * idev);
|
||||
void (*complete_action) (IUDEVICE* idev);
|
||||
|
||||
/* Wait for 5 sec */
|
||||
int (*wait_for_detach) (IUDEVICE * idev);
|
||||
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);
|
||||
void (*lock_fifo_isoch) (IUDEVICE* idev);
|
||||
void (*unlock_fifo_isoch) (IUDEVICE* idev);
|
||||
|
||||
int (*query_device_port_status) (IUDEVICE * idev, UINT32 *UsbdStatus,
|
||||
UINT32 * BufferSize,
|
||||
BYTE * Buffer);
|
||||
int (*query_device_port_status) (IUDEVICE* idev, UINT32 *UsbdStatus,
|
||||
UINT32* BufferSize,
|
||||
BYTE* Buffer);
|
||||
|
||||
int (*request_queue_is_none) (IUDEVICE * idev);
|
||||
int (*request_queue_is_none) (IUDEVICE* idev);
|
||||
|
||||
MSUSB_CONFIG_DESCRIPTOR * (*complete_msconfig_setup) (IUDEVICE * idev,
|
||||
MSUSB_CONFIG_DESCRIPTOR * MsConfig);
|
||||
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);
|
||||
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);
|
||||
BASIC_DEV_STATE_DEFINED(UsbDevice, UINT32);
|
||||
|
@ -214,12 +182,12 @@ struct _IUDEVICE
|
|||
BASIC_DEV_STATE_DEFINED(bus_number, UINT16);
|
||||
BASIC_DEV_STATE_DEFINED(dev_number, UINT16);
|
||||
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(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 *);
|
||||
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 */
|
||||
|
||||
|
@ -228,36 +196,32 @@ struct _IUDEVICE
|
|||
struct _IUDEVMAN
|
||||
{
|
||||
/* Standard */
|
||||
void (*free) (IUDEVMAN *idevman);
|
||||
void (*free) (IUDEVMAN* idevman);
|
||||
|
||||
/* 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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
int (*isAutoAdd) (IUDEVMAN * idevman);
|
||||
int (*check_device_exist_by_id) (IUDEVMAN* idevman, UINT16 idVendor, UINT16 idProduct);
|
||||
int (*isAutoAdd) (IUDEVMAN* idevman);
|
||||
|
||||
/* Basic state */
|
||||
BASIC_DEVMAN_STATE_DEFINED(defUsbDevice, UINT32);
|
||||
BASIC_DEVMAN_STATE_DEFINED(device_num, int);
|
||||
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);
|
||||
void (*loading_lock) (IUDEVMAN* idevman);
|
||||
void (*loading_unlock) (IUDEVMAN* idevman);
|
||||
void (*push_urb) (IUDEVMAN* idevman);
|
||||
void (*wait_urb) (IUDEVMAN* idevman);
|
||||
};
|
||||
|
||||
#endif /* __URBDRC_MAIN_H */
|
||||
|
|
|
@ -26,20 +26,16 @@ else()
|
|||
add_subdirectory(Sample)
|
||||
endif()
|
||||
|
||||
find_optional_package(DirectFB)
|
||||
if(WITH_DIRECTFB)
|
||||
add_subdirectory(DirectFB)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT WIN32 AND (NOT ANDROID))
|
||||
find_suggested_package(X11)
|
||||
if(WITH_X11)
|
||||
add_subdirectory(X11)
|
||||
endif()
|
||||
if(WITH_X11)
|
||||
add_subdirectory(X11)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
if(APPLE AND (NOT IOS))
|
||||
add_subdirectory(Mac)
|
||||
endif()
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue