Merge pull request #2719 from bmiklautz/pull/2481
OSS, tsmf, usb and BSD fixes and improvements
This commit is contained in:
commit
ddf2519f1e
@ -651,17 +651,6 @@ set(FREERDP_EXTENSION_PATH "${CMAKE_INSTALL_FULL_LIBDIR}/freerdp/extensions")
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR}/include)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
if(BSD)
|
||||
if(IS_DIRECTORY /usr/local/include)
|
||||
include_directories(/usr/local/include)
|
||||
link_directories(/usr/local/lib)
|
||||
endif()
|
||||
if(OPENBSD)
|
||||
if(IS_DIRECTORY /usr/X11R6/include)
|
||||
include_directories(/usr/X11R6/include)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Configure files
|
||||
add_definitions("-DHAVE_CONFIG_H")
|
||||
@ -722,10 +711,6 @@ add_subdirectory(include)
|
||||
|
||||
add_subdirectory(libfreerdp)
|
||||
|
||||
if(WITH_CHANNELS)
|
||||
add_subdirectory(channels)
|
||||
endif()
|
||||
|
||||
if (IOS)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "")
|
||||
if (IOS_PLATFORM MATCHES "SIMULATOR")
|
||||
@ -741,6 +726,22 @@ include_directories("${CMAKE_BINARY_DIR}/rdtk/include")
|
||||
|
||||
add_subdirectory(rdtk)
|
||||
|
||||
if(BSD)
|
||||
if(IS_DIRECTORY /usr/local/include)
|
||||
include_directories(/usr/local/include)
|
||||
link_directories(/usr/local/lib)
|
||||
endif()
|
||||
if(OPENBSD)
|
||||
if(IS_DIRECTORY /usr/X11R6/include)
|
||||
include_directories(/usr/X11R6/include)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_CHANNELS)
|
||||
add_subdirectory(channels)
|
||||
endif()
|
||||
|
||||
if(WITH_CLIENT)
|
||||
add_subdirectory(client)
|
||||
endif()
|
||||
@ -749,6 +750,7 @@ if(WITH_SERVER)
|
||||
add_subdirectory(server)
|
||||
endif()
|
||||
|
||||
|
||||
# Exporting
|
||||
|
||||
if(${CMAKE_VERSION} VERSION_GREATER "2.8.10")
|
||||
|
@ -97,7 +97,7 @@ static int audin_process_version(IWTSVirtualChannelCallback* pChannelCallback, w
|
||||
|
||||
Stream_Read_UINT32(s, Version);
|
||||
|
||||
DEBUG_DVC("process_version: Version=%d", Version);
|
||||
DEBUG_DVC("Version=%d", Version);
|
||||
|
||||
out = Stream_New(NULL, 5);
|
||||
Stream_Write_UINT8(out, MSG_SNDIN_VERSION);
|
||||
@ -130,7 +130,7 @@ static int audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, w
|
||||
UINT32 cbSizeFormatsPacket;
|
||||
|
||||
Stream_Read_UINT32(s, NumFormats);
|
||||
DEBUG_DVC("process_formats: NumFormats %d", NumFormats);
|
||||
DEBUG_DVC("NumFormats %d", NumFormats);
|
||||
if ((NumFormats < 1) || (NumFormats > 1000))
|
||||
{
|
||||
WLog_ERR(TAG, "bad NumFormats %d", NumFormats);
|
||||
@ -158,7 +158,7 @@ static int audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, w
|
||||
format.data = Stream_Pointer(s);
|
||||
Stream_Seek(s, format.cbSize);
|
||||
|
||||
DEBUG_DVC("process_formats: wFormatTag=%d nChannels=%d nSamplesPerSec=%d "
|
||||
DEBUG_DVC("wFormatTag=%d nChannels=%d nSamplesPerSec=%d "
|
||||
"nBlockAlign=%d wBitsPerSample=%d cbSize=%d",
|
||||
format.wFormatTag, format.nChannels, format.nSamplesPerSec,
|
||||
format.nBlockAlign, format.wBitsPerSample, format.cbSize);
|
||||
@ -171,7 +171,7 @@ static int audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, w
|
||||
continue;
|
||||
if (audin->device && audin->device->FormatSupported(audin->device, &format))
|
||||
{
|
||||
DEBUG_DVC("process_formats: format ok");
|
||||
DEBUG_DVC("format ok");
|
||||
|
||||
/* Store the agreed format in the corresponding index */
|
||||
callback->formats[callback->formats_count++] = format;
|
||||
@ -264,7 +264,7 @@ static int audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, wStr
|
||||
Stream_Read_UINT32(s, FramesPerPacket);
|
||||
Stream_Read_UINT32(s, initialFormat);
|
||||
|
||||
DEBUG_DVC("process_open: FramesPerPacket=%d initialFormat=%d",
|
||||
DEBUG_DVC("FramesPerPacket=%d initialFormat=%d",
|
||||
FramesPerPacket, initialFormat);
|
||||
|
||||
if (initialFormat >= (UINT32) callback->formats_count)
|
||||
@ -296,7 +296,7 @@ static int audin_process_format_change(IWTSVirtualChannelCallback* pChannelCallb
|
||||
|
||||
Stream_Read_UINT32(s, NewFormat);
|
||||
|
||||
DEBUG_DVC("process_format_change: NewFormat=%d", NewFormat);
|
||||
DEBUG_DVC("NewFormat=%d", NewFormat);
|
||||
|
||||
if (NewFormat >= (UINT32) callback->formats_count)
|
||||
{
|
||||
@ -326,7 +326,7 @@ static int audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
|
||||
|
||||
Stream_Read_UINT8(data, MessageId);
|
||||
|
||||
DEBUG_DVC("on_data_received: MessageId=0x%x", MessageId);
|
||||
DEBUG_DVC("MessageId=0x%x", MessageId);
|
||||
|
||||
switch (MessageId)
|
||||
{
|
||||
@ -360,7 +360,7 @@ static int audin_on_close(IWTSVirtualChannelCallback* pChannelCallback)
|
||||
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
|
||||
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin;
|
||||
|
||||
DEBUG_DVC("on_close");
|
||||
DEBUG_DVC("...");
|
||||
|
||||
if (audin->device)
|
||||
IFCALL(audin->device->Close, audin->device);
|
||||
@ -378,7 +378,7 @@ static int audin_on_new_channel_connection(IWTSListenerCallback* pListenerCallba
|
||||
AUDIN_CHANNEL_CALLBACK* callback;
|
||||
AUDIN_LISTENER_CALLBACK* listener_callback = (AUDIN_LISTENER_CALLBACK*) pListenerCallback;
|
||||
|
||||
DEBUG_DVC("on_new_channel_connection");
|
||||
DEBUG_DVC("...");
|
||||
|
||||
callback = (AUDIN_CHANNEL_CALLBACK*) malloc(sizeof(AUDIN_CHANNEL_CALLBACK));
|
||||
ZeroMemory(callback, sizeof(AUDIN_CHANNEL_CALLBACK));
|
||||
@ -398,7 +398,7 @@ static int audin_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManage
|
||||
{
|
||||
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin;
|
||||
|
||||
DEBUG_DVC("plugin_initialize");
|
||||
DEBUG_DVC("...");
|
||||
|
||||
audin->listener_callback = (AUDIN_LISTENER_CALLBACK*) malloc(sizeof(AUDIN_LISTENER_CALLBACK));
|
||||
ZeroMemory(audin->listener_callback, sizeof(AUDIN_LISTENER_CALLBACK));
|
||||
@ -415,7 +415,7 @@ static int audin_plugin_terminated(IWTSPlugin* pPlugin)
|
||||
{
|
||||
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin;
|
||||
|
||||
DEBUG_DVC("plugin_terminated");
|
||||
DEBUG_DVC("...");
|
||||
|
||||
if (audin->device)
|
||||
{
|
||||
@ -445,7 +445,7 @@ static void audin_register_device_plugin(IWTSPlugin* pPlugin, IAudinDevice* devi
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_DVC("register_device_plugin: device registered.");
|
||||
DEBUG_DVC("device registered.");
|
||||
|
||||
audin->device = device;
|
||||
}
|
||||
|
@ -37,9 +37,9 @@
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#if defined(__OpenBSD__)
|
||||
#include <soundcard.h>
|
||||
#include <soundcard.h>
|
||||
#else
|
||||
#include <sys/soundcard.h>
|
||||
#include <sys/soundcard.h>
|
||||
#endif
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
@ -49,14 +49,15 @@
|
||||
|
||||
#include "audin_main.h"
|
||||
|
||||
typedef struct _AudinOSSDevice {
|
||||
typedef struct _AudinOSSDevice
|
||||
{
|
||||
IAudinDevice iface;
|
||||
|
||||
FREERDP_DSP_CONTEXT* dsp_context;
|
||||
|
||||
HANDLE thread;
|
||||
HANDLE stopEvent;
|
||||
|
||||
|
||||
audinFormat format;
|
||||
UINT32 FramesPerPacket;
|
||||
int dev_unit;
|
||||
@ -70,193 +71,259 @@ typedef struct _AudinOSSDevice {
|
||||
WLog_ERR(TAG, "%s: %i - %s\n", _text, _error, strerror(_error));
|
||||
|
||||
|
||||
static int audin_oss_get_format(audinFormat *format) {
|
||||
static int audin_oss_get_format(audinFormat* format)
|
||||
{
|
||||
switch (format->wFormatTag)
|
||||
{
|
||||
case WAVE_FORMAT_PCM:
|
||||
|
||||
switch (format->wFormatTag) {
|
||||
case WAVE_FORMAT_PCM:
|
||||
switch (format->wBitsPerSample) {
|
||||
case 8:
|
||||
return AFMT_S8;
|
||||
case 16:
|
||||
return AFMT_S16_LE;
|
||||
}
|
||||
break;
|
||||
case WAVE_FORMAT_ALAW:
|
||||
return AFMT_A_LAW;
|
||||
switch (format->wBitsPerSample)
|
||||
{
|
||||
case 8:
|
||||
return AFMT_S8;
|
||||
case 16:
|
||||
return AFMT_S16_LE;
|
||||
}
|
||||
|
||||
break;
|
||||
case WAVE_FORMAT_ALAW:
|
||||
return AFMT_A_LAW;
|
||||
#if 0 /* This does not work on my desktop. */
|
||||
case WAVE_FORMAT_MULAW:
|
||||
return AFMT_MU_LAW;
|
||||
case WAVE_FORMAT_MULAW:
|
||||
return AFMT_MU_LAW;
|
||||
#endif
|
||||
case WAVE_FORMAT_ADPCM:
|
||||
case WAVE_FORMAT_DVI_ADPCM:
|
||||
return AFMT_S16_LE;
|
||||
case WAVE_FORMAT_ADPCM:
|
||||
case WAVE_FORMAT_DVI_ADPCM:
|
||||
return AFMT_S16_LE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL audin_oss_format_supported(IAudinDevice *device, audinFormat *format) {
|
||||
static BOOL audin_oss_format_supported(IAudinDevice* device, audinFormat* format)
|
||||
{
|
||||
int req_fmt = 0;
|
||||
|
||||
if (device == NULL || format == NULL)
|
||||
return FALSE;
|
||||
|
||||
switch (format->wFormatTag) {
|
||||
case WAVE_FORMAT_PCM:
|
||||
if (format->cbSize != 0 ||
|
||||
format->nSamplesPerSec > 48000 ||
|
||||
(format->wBitsPerSample != 8 && format->wBitsPerSample != 16) ||
|
||||
(format->nChannels != 1 && format->nChannels != 2))
|
||||
return FALSE;
|
||||
break;
|
||||
case WAVE_FORMAT_ADPCM:
|
||||
case WAVE_FORMAT_DVI_ADPCM:
|
||||
if (format->nSamplesPerSec > 48000 ||
|
||||
format->wBitsPerSample != 4 ||
|
||||
(format->nChannels != 1 && format->nChannels != 2))
|
||||
return FALSE;
|
||||
break;
|
||||
switch (format->wFormatTag)
|
||||
{
|
||||
case WAVE_FORMAT_PCM:
|
||||
|
||||
if (format->cbSize != 0 ||
|
||||
format->nSamplesPerSec > 48000 ||
|
||||
(format->wBitsPerSample != 8 && format->wBitsPerSample != 16) ||
|
||||
(format->nChannels != 1 && format->nChannels != 2))
|
||||
return FALSE;
|
||||
|
||||
break;
|
||||
case WAVE_FORMAT_ADPCM:
|
||||
case WAVE_FORMAT_DVI_ADPCM:
|
||||
|
||||
if (format->nSamplesPerSec > 48000 ||
|
||||
format->wBitsPerSample != 4 ||
|
||||
(format->nChannels != 1 && format->nChannels != 2))
|
||||
return FALSE;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
req_fmt = audin_oss_get_format(format);
|
||||
|
||||
if (req_fmt == 0)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void audin_oss_set_format(IAudinDevice *device, audinFormat *format, UINT32 FramesPerPacket) {
|
||||
AudinOSSDevice *oss = (AudinOSSDevice*)device;
|
||||
static void audin_oss_set_format(IAudinDevice* device, audinFormat* format, UINT32 FramesPerPacket)
|
||||
{
|
||||
AudinOSSDevice* oss = (AudinOSSDevice*)device;
|
||||
|
||||
if (device == NULL || format == NULL)
|
||||
return;
|
||||
|
||||
|
||||
oss->FramesPerPacket = FramesPerPacket;
|
||||
CopyMemory(&(oss->format), format, sizeof(audinFormat));
|
||||
switch (format->wFormatTag) {
|
||||
case WAVE_FORMAT_ADPCM:
|
||||
case WAVE_FORMAT_DVI_ADPCM:
|
||||
oss->FramesPerPacket *= 4; /* Compression ratio. */
|
||||
oss->format.wBitsPerSample *= 4;
|
||||
break;
|
||||
|
||||
switch (format->wFormatTag)
|
||||
{
|
||||
case WAVE_FORMAT_ADPCM:
|
||||
case WAVE_FORMAT_DVI_ADPCM:
|
||||
oss->FramesPerPacket *= 4; /* Compression ratio. */
|
||||
oss->format.wBitsPerSample *= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void *audin_oss_thread_func(void *arg)
|
||||
static void* audin_oss_thread_func(void* arg)
|
||||
{
|
||||
char dev_name[PATH_MAX] = "/dev/dsp";
|
||||
int pcm_handle = -1;
|
||||
BYTE *buffer = NULL, *encoded_data;
|
||||
char mixer_name[PATH_MAX] = "/dev/mixer";
|
||||
int pcm_handle = -1, mixer_handle;
|
||||
BYTE* buffer = NULL, *encoded_data;
|
||||
int tmp, buffer_size, encoded_size;
|
||||
AudinOSSDevice *oss = (AudinOSSDevice*)arg;
|
||||
AudinOSSDevice* oss = (AudinOSSDevice*)arg;
|
||||
|
||||
if (arg == NULL)
|
||||
goto err_out;
|
||||
|
||||
if (oss->dev_unit != -1)
|
||||
{
|
||||
snprintf(dev_name, (PATH_MAX - 1), "/dev/dsp%i", oss->dev_unit);
|
||||
snprintf(mixer_name, PATH_MAX - 1, "/dev/mixer%i", oss->dev_unit);
|
||||
}
|
||||
|
||||
WLog_INFO(TAG, "open: %s", dev_name);
|
||||
if ((pcm_handle = open(dev_name, O_RDONLY)) < 0) {
|
||||
|
||||
if ((pcm_handle = open(dev_name, O_RDONLY)) < 0)
|
||||
{
|
||||
OSS_LOG_ERR("sound dev open failed", errno);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* Set rec volume to 100%. */
|
||||
if ((mixer_handle = open(mixer_name, O_RDWR)) < 0)
|
||||
{
|
||||
OSS_LOG_ERR("mixer open failed, not critical", errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = (100 | (100 << 8));
|
||||
|
||||
if (ioctl(mixer_handle, MIXER_WRITE(SOUND_MIXER_MIC), &tmp) == -1)
|
||||
OSS_LOG_ERR("WRITE_MIXER - SOUND_MIXER_MIC, not critical", errno);
|
||||
|
||||
tmp = (100 | (100 << 8));
|
||||
|
||||
if (ioctl(mixer_handle, MIXER_WRITE(SOUND_MIXER_RECLEV), &tmp) == -1)
|
||||
OSS_LOG_ERR("WRITE_MIXER - SOUND_MIXER_RECLEV, not critical", errno);
|
||||
|
||||
close(mixer_handle);
|
||||
}
|
||||
|
||||
#if 0 /* FreeBSD OSS implementation at this moment (2015.03) does not set PCM_CAP_INPUT flag. */
|
||||
tmp = 0;
|
||||
if (ioctl(pcm_handle, SNDCTL_DSP_GETCAPS, &tmp) == -1) {
|
||||
|
||||
if (ioctl(pcm_handle, SNDCTL_DSP_GETCAPS, &tmp) == -1)
|
||||
{
|
||||
OSS_LOG_ERR("SNDCTL_DSP_GETCAPS failed, try ignory", errno);
|
||||
} else if ((tmp & PCM_CAP_INPUT) == 0) {
|
||||
}
|
||||
else if ((tmp & PCM_CAP_INPUT) == 0)
|
||||
{
|
||||
OSS_LOG_ERR("Device does not supports playback", EOPNOTSUPP);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
#endif
|
||||
/* Set format. */
|
||||
tmp = audin_oss_get_format(&oss->format);
|
||||
|
||||
if (ioctl(pcm_handle, SNDCTL_DSP_SETFMT, &tmp) == -1)
|
||||
OSS_LOG_ERR("SNDCTL_DSP_SETFMT failed", errno);
|
||||
|
||||
tmp = oss->format.nChannels;
|
||||
|
||||
if (ioctl(pcm_handle, SNDCTL_DSP_CHANNELS, &tmp) == -1)
|
||||
OSS_LOG_ERR("SNDCTL_DSP_CHANNELS failed", errno);
|
||||
|
||||
tmp = oss->format.nSamplesPerSec;
|
||||
|
||||
if (ioctl(pcm_handle, SNDCTL_DSP_SPEED, &tmp) == -1)
|
||||
OSS_LOG_ERR("SNDCTL_DSP_SPEED failed", errno);
|
||||
|
||||
tmp = oss->format.nBlockAlign;
|
||||
|
||||
if (ioctl(pcm_handle, SNDCTL_DSP_SETFRAGMENT, &tmp) == -1)
|
||||
OSS_LOG_ERR("SNDCTL_DSP_SETFRAGMENT failed", errno);
|
||||
|
||||
buffer_size = (oss->FramesPerPacket * oss->format.nChannels * (oss->format.wBitsPerSample / 8));
|
||||
buffer_size = (oss->FramesPerPacket * oss->format.nChannels * (oss->format.wBitsPerSample / 8));
|
||||
buffer = (BYTE*)malloc((buffer_size + sizeof(void*)));
|
||||
if (NULL == buffer) {
|
||||
|
||||
if (NULL == buffer)
|
||||
{
|
||||
OSS_LOG_ERR("malloc() fail", errno);
|
||||
goto err_out;
|
||||
}
|
||||
ZeroMemory(buffer, buffer_size);
|
||||
|
||||
ZeroMemory(buffer, buffer_size);
|
||||
freerdp_dsp_context_reset_adpcm(oss->dsp_context);
|
||||
|
||||
while (WaitForSingleObject(oss->stopEvent, 0) != WAIT_OBJECT_0) {
|
||||
while (WaitForSingleObject(oss->stopEvent, 0) != WAIT_OBJECT_0)
|
||||
{
|
||||
tmp = read(pcm_handle, buffer, buffer_size);
|
||||
if (tmp < 0) { /* Error happen. */
|
||||
|
||||
/* Error happen. */
|
||||
if (tmp < 0)
|
||||
{
|
||||
OSS_LOG_ERR("read() error", errno);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tmp < buffer_size) /* Not enouth data. */
|
||||
continue;
|
||||
|
||||
/* Process. */
|
||||
switch (oss->format.wFormatTag) {
|
||||
case WAVE_FORMAT_ADPCM:
|
||||
oss->dsp_context->encode_ms_adpcm(oss->dsp_context,
|
||||
buffer, buffer_size, oss->format.nChannels, oss->format.nBlockAlign);
|
||||
encoded_data = oss->dsp_context->adpcm_buffer;
|
||||
encoded_size = oss->dsp_context->adpcm_size;
|
||||
break;
|
||||
case WAVE_FORMAT_DVI_ADPCM:
|
||||
oss->dsp_context->encode_ima_adpcm(oss->dsp_context,
|
||||
buffer, buffer_size, oss->format.nChannels, oss->format.nBlockAlign);
|
||||
encoded_data = oss->dsp_context->adpcm_buffer;
|
||||
encoded_size = oss->dsp_context->adpcm_size;
|
||||
break;
|
||||
default:
|
||||
encoded_data = buffer;
|
||||
encoded_size = buffer_size;
|
||||
break;
|
||||
switch (oss->format.wFormatTag)
|
||||
{
|
||||
case WAVE_FORMAT_ADPCM:
|
||||
oss->dsp_context->encode_ms_adpcm(oss->dsp_context,
|
||||
buffer, buffer_size, oss->format.nChannels, oss->format.nBlockAlign);
|
||||
encoded_data = oss->dsp_context->adpcm_buffer;
|
||||
encoded_size = oss->dsp_context->adpcm_size;
|
||||
break;
|
||||
case WAVE_FORMAT_DVI_ADPCM:
|
||||
oss->dsp_context->encode_ima_adpcm(oss->dsp_context,
|
||||
buffer, buffer_size, oss->format.nChannels, oss->format.nBlockAlign);
|
||||
encoded_data = oss->dsp_context->adpcm_buffer;
|
||||
encoded_size = oss->dsp_context->adpcm_size;
|
||||
break;
|
||||
default:
|
||||
encoded_data = buffer;
|
||||
encoded_size = buffer_size;
|
||||
break;
|
||||
}
|
||||
if (0 != oss->receive(encoded_data, encoded_size, oss->user_data))
|
||||
|
||||
if (0 == oss->receive(encoded_data, encoded_size, oss->user_data))
|
||||
break;
|
||||
}
|
||||
|
||||
err_out:
|
||||
|
||||
if (pcm_handle != -1)
|
||||
{
|
||||
WLog_INFO(TAG, "close: %s", dev_name);
|
||||
close(pcm_handle);
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
|
||||
ExitThread(0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void audin_oss_open(IAudinDevice *device, AudinReceive receive, void *user_data) {
|
||||
AudinOSSDevice *oss = (AudinOSSDevice*)device;
|
||||
|
||||
static void audin_oss_open(IAudinDevice* device, AudinReceive receive, void* user_data)
|
||||
{
|
||||
AudinOSSDevice* oss = (AudinOSSDevice*)device;
|
||||
oss->receive = receive;
|
||||
oss->user_data = user_data;
|
||||
|
||||
oss->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
oss->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)audin_oss_thread_func, oss, 0, NULL);
|
||||
}
|
||||
|
||||
static void audin_oss_close(IAudinDevice *device) {
|
||||
AudinOSSDevice *oss = (AudinOSSDevice*)device;
|
||||
static void audin_oss_close(IAudinDevice* device)
|
||||
{
|
||||
AudinOSSDevice* oss = (AudinOSSDevice*)device;
|
||||
|
||||
if (device == NULL)
|
||||
return;
|
||||
|
||||
if (oss->stopEvent != NULL) {
|
||||
if (oss->stopEvent != NULL)
|
||||
{
|
||||
SetEvent(oss->stopEvent);
|
||||
WaitForSingleObject(oss->thread, INFINITE);
|
||||
|
||||
CloseHandle(oss->stopEvent);
|
||||
oss->stopEvent = NULL;
|
||||
|
||||
CloseHandle(oss->thread);
|
||||
oss->thread = NULL;
|
||||
}
|
||||
@ -265,81 +332,79 @@ static void audin_oss_close(IAudinDevice *device) {
|
||||
oss->user_data = NULL;
|
||||
}
|
||||
|
||||
static void audin_oss_free(IAudinDevice *device) {
|
||||
AudinOSSDevice *oss = (AudinOSSDevice*)device;
|
||||
static void audin_oss_free(IAudinDevice* device)
|
||||
{
|
||||
AudinOSSDevice* oss = (AudinOSSDevice*)device;
|
||||
|
||||
if (device == NULL)
|
||||
return;
|
||||
|
||||
audin_oss_close(device);
|
||||
freerdp_dsp_context_free(oss->dsp_context);
|
||||
|
||||
free(oss);
|
||||
}
|
||||
|
||||
COMMAND_LINE_ARGUMENT_A audin_oss_args[] = {
|
||||
COMMAND_LINE_ARGUMENT_A audin_oss_args[] =
|
||||
{
|
||||
{ "dev", COMMAND_LINE_VALUE_REQUIRED, "<device>", NULL, NULL, -1, NULL, "audio device name" },
|
||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
static void audin_oss_parse_addin_args(AudinOSSDevice *device, ADDIN_ARGV *args) {
|
||||
static void audin_oss_parse_addin_args(AudinOSSDevice* device, ADDIN_ARGV* args)
|
||||
{
|
||||
int status;
|
||||
char *str_num, *eptr;
|
||||
char* str_num, *eptr;
|
||||
DWORD flags;
|
||||
COMMAND_LINE_ARGUMENT_A *arg;
|
||||
AudinOSSDevice *oss = (AudinOSSDevice*)device;
|
||||
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
AudinOSSDevice* oss = (AudinOSSDevice*)device;
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD;
|
||||
|
||||
status = CommandLineParseArgumentsA(args->argc, (const char**)args->argv, audin_oss_args, flags, oss, NULL, NULL);
|
||||
|
||||
if (status < 0)
|
||||
return;
|
||||
|
||||
arg = audin_oss_args;
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
|
||||
continue;
|
||||
|
||||
CommandLineSwitchStart(arg)
|
||||
|
||||
CommandLineSwitchCase(arg, "dev") {
|
||||
CommandLineSwitchCase(arg, "dev")
|
||||
{
|
||||
str_num = _strdup(arg->Value);
|
||||
oss->dev_unit = strtol(str_num, &eptr, 10);
|
||||
|
||||
if (oss->dev_unit < 0 || *eptr != '\0')
|
||||
oss->dev_unit = -1;
|
||||
|
||||
free(str_num);
|
||||
}
|
||||
|
||||
CommandLineSwitchEnd(arg)
|
||||
} while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
}
|
||||
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_audin_client_subsystem_entry oss_freerdp_audin_client_subsystem_entry
|
||||
#endif
|
||||
|
||||
int freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints) {
|
||||
ADDIN_ARGV *args;
|
||||
AudinOSSDevice *oss;
|
||||
|
||||
int freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
ADDIN_ARGV* args;
|
||||
AudinOSSDevice* oss;
|
||||
oss = (AudinOSSDevice*)malloc(sizeof(AudinOSSDevice));
|
||||
ZeroMemory(oss, sizeof(AudinOSSDevice));
|
||||
|
||||
oss->iface.Open = audin_oss_open;
|
||||
oss->iface.FormatSupported = audin_oss_format_supported;
|
||||
oss->iface.SetFormat = audin_oss_set_format;
|
||||
oss->iface.Close = audin_oss_close;
|
||||
oss->iface.Free = audin_oss_free;
|
||||
|
||||
oss->dev_unit = -1;
|
||||
|
||||
args = pEntryPoints->args;
|
||||
audin_oss_parse_addin_args(oss, args);
|
||||
|
||||
oss->dsp_context = freerdp_dsp_context_new();
|
||||
|
||||
pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*)oss);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -37,9 +37,9 @@
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#if defined(__OpenBSD__)
|
||||
#include <soundcard.h>
|
||||
#include <soundcard.h>
|
||||
#else
|
||||
#include <sys/soundcard.h>
|
||||
#include <sys/soundcard.h>
|
||||
#endif
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
@ -51,7 +51,8 @@
|
||||
|
||||
typedef struct rdpsnd_oss_plugin rdpsndOssPlugin;
|
||||
|
||||
struct rdpsnd_oss_plugin {
|
||||
struct rdpsnd_oss_plugin
|
||||
{
|
||||
rdpsndDevicePlugin device;
|
||||
|
||||
int pcm_handle;
|
||||
@ -63,68 +64,85 @@ struct rdpsnd_oss_plugin {
|
||||
int latency;
|
||||
AUDIO_FORMAT format;
|
||||
|
||||
FREERDP_DSP_CONTEXT *dsp_context;
|
||||
FREERDP_DSP_CONTEXT* dsp_context;
|
||||
};
|
||||
|
||||
#define OSS_LOG_ERR(_text, _error) \
|
||||
if (_error != 0) \
|
||||
WLog_ERR(TAG, "%s: %i - %s", _text, _error, strerror(_error));
|
||||
{ \
|
||||
if (_error != 0) \
|
||||
WLog_ERR(TAG, "%s: %i - %s", _text, _error, strerror(_error)); \
|
||||
}
|
||||
|
||||
|
||||
static int rdpsnd_oss_get_format(AUDIO_FORMAT *format) {
|
||||
static int rdpsnd_oss_get_format(AUDIO_FORMAT* format)
|
||||
{
|
||||
switch (format->wFormatTag)
|
||||
{
|
||||
case WAVE_FORMAT_PCM:
|
||||
|
||||
switch (format->wFormatTag) {
|
||||
case WAVE_FORMAT_PCM:
|
||||
switch (format->wBitsPerSample) {
|
||||
case 8:
|
||||
return AFMT_S8;
|
||||
case 16:
|
||||
return AFMT_S16_LE;
|
||||
}
|
||||
break;
|
||||
case WAVE_FORMAT_ALAW:
|
||||
return AFMT_A_LAW;
|
||||
switch (format->wBitsPerSample)
|
||||
{
|
||||
case 8:
|
||||
return AFMT_S8;
|
||||
case 16:
|
||||
return AFMT_S16_LE;
|
||||
}
|
||||
|
||||
break;
|
||||
case WAVE_FORMAT_ALAW:
|
||||
return AFMT_A_LAW;
|
||||
#if 0 /* This does not work on my desktop. */
|
||||
case WAVE_FORMAT_MULAW:
|
||||
return AFMT_MU_LAW;
|
||||
case WAVE_FORMAT_MULAW:
|
||||
return AFMT_MU_LAW;
|
||||
#endif
|
||||
case WAVE_FORMAT_ADPCM:
|
||||
case WAVE_FORMAT_DVI_ADPCM:
|
||||
return AFMT_S16_LE;
|
||||
case WAVE_FORMAT_ADPCM:
|
||||
case WAVE_FORMAT_DVI_ADPCM:
|
||||
return AFMT_S16_LE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL rdpsnd_oss_format_supported(rdpsndDevicePlugin *device, AUDIO_FORMAT *format) {
|
||||
static BOOL rdpsnd_oss_format_supported(rdpsndDevicePlugin* device, AUDIO_FORMAT* format)
|
||||
{
|
||||
int req_fmt = 0;
|
||||
rdpsndOssPlugin *oss = (rdpsndOssPlugin*)device;
|
||||
rdpsndOssPlugin* oss = (rdpsndOssPlugin*)device;
|
||||
|
||||
if (device == NULL || format == NULL)
|
||||
return FALSE;
|
||||
|
||||
switch (format->wFormatTag) {
|
||||
case WAVE_FORMAT_PCM:
|
||||
if (format->cbSize != 0 ||
|
||||
format->nSamplesPerSec > 48000 ||
|
||||
(format->wBitsPerSample != 8 && format->wBitsPerSample != 16) ||
|
||||
(format->nChannels != 1 && format->nChannels != 2))
|
||||
return FALSE;
|
||||
break;
|
||||
case WAVE_FORMAT_ADPCM:
|
||||
case WAVE_FORMAT_DVI_ADPCM:
|
||||
if (format->nSamplesPerSec > 48000 ||
|
||||
format->wBitsPerSample != 4 ||
|
||||
(format->nChannels != 1 && format->nChannels != 2))
|
||||
return FALSE;
|
||||
break;
|
||||
switch (format->wFormatTag)
|
||||
{
|
||||
case WAVE_FORMAT_PCM:
|
||||
|
||||
if (format->cbSize != 0 ||
|
||||
format->nSamplesPerSec > 48000 ||
|
||||
(format->wBitsPerSample != 8 && format->wBitsPerSample != 16) ||
|
||||
(format->nChannels != 1 && format->nChannels != 2))
|
||||
return FALSE;
|
||||
|
||||
break;
|
||||
case WAVE_FORMAT_ADPCM:
|
||||
case WAVE_FORMAT_DVI_ADPCM:
|
||||
|
||||
if (format->nSamplesPerSec > 48000 ||
|
||||
format->wBitsPerSample != 4 ||
|
||||
(format->nChannels != 1 && format->nChannels != 2))
|
||||
return FALSE;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
req_fmt = rdpsnd_oss_get_format(format);
|
||||
if (oss->pcm_handle != -1) { /* Check really supported formats by dev. */
|
||||
|
||||
/* Check really supported formats by dev. */
|
||||
if (oss->pcm_handle != -1)
|
||||
{
|
||||
if ((req_fmt & oss->supported_formats) == 0)
|
||||
return FALSE;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (req_fmt == 0)
|
||||
return FALSE;
|
||||
}
|
||||
@ -132,45 +150,57 @@ static BOOL rdpsnd_oss_format_supported(rdpsndDevicePlugin *device, AUDIO_FORMAT
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void rdpsnd_oss_set_format(rdpsndDevicePlugin *device, AUDIO_FORMAT *format, int latency) {
|
||||
static void rdpsnd_oss_set_format(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency)
|
||||
{
|
||||
int tmp;
|
||||
rdpsndOssPlugin *oss = (rdpsndOssPlugin*)device;
|
||||
rdpsndOssPlugin* oss = (rdpsndOssPlugin*)device;
|
||||
|
||||
if (device == NULL || oss->pcm_handle == -1 || format == NULL)
|
||||
return;
|
||||
|
||||
|
||||
oss->latency = latency;
|
||||
CopyMemory(&(oss->format), format, sizeof(AUDIO_FORMAT));
|
||||
|
||||
tmp = rdpsnd_oss_get_format(format);
|
||||
|
||||
if (ioctl(oss->pcm_handle, SNDCTL_DSP_SETFMT, &tmp) == -1)
|
||||
OSS_LOG_ERR("SNDCTL_DSP_SETFMT failed", errno);
|
||||
|
||||
tmp = format->nChannels;
|
||||
|
||||
if (ioctl(oss->pcm_handle, SNDCTL_DSP_CHANNELS, &tmp) == -1)
|
||||
OSS_LOG_ERR("SNDCTL_DSP_CHANNELS failed", errno);
|
||||
|
||||
tmp = format->nSamplesPerSec;
|
||||
|
||||
if (ioctl(oss->pcm_handle, SNDCTL_DSP_SPEED, &tmp) == -1)
|
||||
OSS_LOG_ERR("SNDCTL_DSP_SPEED failed", errno);
|
||||
|
||||
tmp = format->nBlockAlign;
|
||||
|
||||
if (ioctl(oss->pcm_handle, SNDCTL_DSP_SETFRAGMENT, &tmp) == -1)
|
||||
OSS_LOG_ERR("SNDCTL_DSP_SETFRAGMENT failed", errno);
|
||||
}
|
||||
|
||||
static void rdpsnd_oss_open_mixer(rdpsndOssPlugin *oss) {
|
||||
static void rdpsnd_oss_open_mixer(rdpsndOssPlugin* oss)
|
||||
{
|
||||
int devmask = 0;
|
||||
char mixer[PATH_MAX] = "/dev/mixer";
|
||||
char mixer_name[PATH_MAX] = "/dev/mixer";
|
||||
|
||||
if (oss->mixer_handle != -1)
|
||||
return;
|
||||
|
||||
if (oss->dev_unit != -1)
|
||||
snprintf(mixer, PATH_MAX - 1, "/dev/mixer%i", oss->dev_unit);
|
||||
if ((oss->mixer_handle = open(mixer, O_RDWR)) < 0) {
|
||||
snprintf(mixer_name, PATH_MAX - 1, "/dev/mixer%i", oss->dev_unit);
|
||||
|
||||
if ((oss->mixer_handle = open(mixer_name, O_RDWR)) < 0)
|
||||
{
|
||||
OSS_LOG_ERR("mixer open failed", errno);
|
||||
oss->mixer_handle = -1;
|
||||
return;
|
||||
}
|
||||
if (ioctl(oss->mixer_handle, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) {
|
||||
|
||||
if (ioctl(oss->mixer_handle, SOUND_MIXER_READ_DEVMASK, &devmask) == -1)
|
||||
{
|
||||
OSS_LOG_ERR("SOUND_MIXER_READ_DEVMASK failed", errno);
|
||||
close(oss->mixer_handle);
|
||||
oss->mixer_handle = -1;
|
||||
@ -178,158 +208,172 @@ static void rdpsnd_oss_open_mixer(rdpsndOssPlugin *oss) {
|
||||
}
|
||||
}
|
||||
|
||||
static void rdpsnd_oss_open(rdpsndDevicePlugin *device, AUDIO_FORMAT *format, int latency) {
|
||||
static void rdpsnd_oss_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format, int latency)
|
||||
{
|
||||
char dev_name[PATH_MAX] = "/dev/dsp";
|
||||
rdpsndOssPlugin *oss = (rdpsndOssPlugin*)device;
|
||||
rdpsndOssPlugin* oss = (rdpsndOssPlugin*)device;
|
||||
|
||||
if (device == NULL || oss->pcm_handle != -1)
|
||||
return;
|
||||
|
||||
if (oss->dev_unit != -1)
|
||||
snprintf(dev_name, PATH_MAX - 1, "/dev/dsp%i", oss->dev_unit);
|
||||
|
||||
WLog_INFO(TAG, "open: %s", dev_name);
|
||||
if ((oss->pcm_handle = open(dev_name, O_WRONLY)) < 0) {
|
||||
|
||||
if ((oss->pcm_handle = open(dev_name, O_WRONLY)) < 0)
|
||||
{
|
||||
OSS_LOG_ERR("sound dev open failed", errno);
|
||||
oss->pcm_handle = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0 /* FreeBSD OSS implementation at this moment (2015.03) does not set PCM_CAP_OUTPUT flag. */
|
||||
int mask = 0;
|
||||
|
||||
if (ioctl(oss->pcm_handle, SNDCTL_DSP_GETCAPS, &mask) == -1) {
|
||||
if (ioctl(oss->pcm_handle, SNDCTL_DSP_GETCAPS, &mask) == -1)
|
||||
{
|
||||
OSS_LOG_ERR("SNDCTL_DSP_GETCAPS failed, try ignory", errno);
|
||||
} else if ((mask & PCM_CAP_OUTPUT) == 0) {
|
||||
}
|
||||
else if ((mask & PCM_CAP_OUTPUT) == 0)
|
||||
{
|
||||
OSS_LOG_ERR("Device does not supports playback", EOPNOTSUPP);
|
||||
close(oss->pcm_handle);
|
||||
oss->pcm_handle = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
if (ioctl(oss->pcm_handle, SNDCTL_DSP_GETFMTS, &oss->supported_formats) == -1) {
|
||||
|
||||
if (ioctl(oss->pcm_handle, SNDCTL_DSP_GETFMTS, &oss->supported_formats) == -1)
|
||||
{
|
||||
OSS_LOG_ERR("SNDCTL_DSP_GETFMTS failed", errno);
|
||||
close(oss->pcm_handle);
|
||||
oss->pcm_handle = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
freerdp_dsp_context_reset_adpcm(oss->dsp_context);
|
||||
rdpsnd_oss_set_format(device, format, latency);
|
||||
rdpsnd_oss_open_mixer(oss);
|
||||
}
|
||||
|
||||
static void rdpsnd_oss_close(rdpsndDevicePlugin *device) {
|
||||
rdpsndOssPlugin *oss = (rdpsndOssPlugin*)device;
|
||||
static void rdpsnd_oss_close(rdpsndDevicePlugin* device)
|
||||
{
|
||||
rdpsndOssPlugin* oss = (rdpsndOssPlugin*)device;
|
||||
|
||||
if (device == NULL)
|
||||
return;
|
||||
|
||||
if (oss->pcm_handle != -1) {
|
||||
if (oss->pcm_handle != -1)
|
||||
{
|
||||
WLog_INFO(TAG, "close: dsp");
|
||||
close(oss->pcm_handle);
|
||||
oss->pcm_handle = -1;
|
||||
}
|
||||
|
||||
if (oss->mixer_handle != -1) {
|
||||
if (oss->mixer_handle != -1)
|
||||
{
|
||||
WLog_INFO(TAG, "close: mixer");
|
||||
close(oss->mixer_handle);
|
||||
oss->mixer_handle = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void rdpsnd_oss_free(rdpsndDevicePlugin *device) {
|
||||
rdpsndOssPlugin *oss = (rdpsndOssPlugin*)device;
|
||||
static void rdpsnd_oss_free(rdpsndDevicePlugin* device)
|
||||
{
|
||||
rdpsndOssPlugin* oss = (rdpsndOssPlugin*)device;
|
||||
|
||||
if (device == NULL)
|
||||
return;
|
||||
|
||||
rdpsnd_oss_close(device);
|
||||
freerdp_dsp_context_free(oss->dsp_context);
|
||||
|
||||
free(oss);
|
||||
}
|
||||
|
||||
static UINT32 rdpsnd_oss_get_volume(rdpsndDevicePlugin *device) {
|
||||
static UINT32 rdpsnd_oss_get_volume(rdpsndDevicePlugin* device)
|
||||
{
|
||||
int vol;
|
||||
UINT32 dwVolume;
|
||||
UINT16 dwVolumeLeft, dwVolumeRight;
|
||||
rdpsndOssPlugin *oss = (rdpsndOssPlugin*)device;
|
||||
|
||||
rdpsndOssPlugin* oss = (rdpsndOssPlugin*)device;
|
||||
/* On error return 50% volume. */
|
||||
dwVolumeLeft = ((50 * 0xFFFF) / 100); /* 50% */
|
||||
dwVolumeRight = ((50 * 0xFFFF) / 100); /* 50% */
|
||||
dwVolume = ((dwVolumeLeft << 16) | dwVolumeRight);
|
||||
|
||||
|
||||
if (device == NULL || oss->mixer_handle == -1)
|
||||
return dwVolume;
|
||||
|
||||
if (ioctl(oss->mixer_handle, MIXER_READ(SOUND_MIXER_VOLUME), &vol) == -1) {
|
||||
|
||||
if (ioctl(oss->mixer_handle, MIXER_READ(SOUND_MIXER_VOLUME), &vol) == -1)
|
||||
{
|
||||
OSS_LOG_ERR("MIXER_READ", errno);
|
||||
return dwVolume;
|
||||
}
|
||||
|
||||
|
||||
dwVolumeLeft = (((vol & 0x7f) * 0xFFFF) / 100);
|
||||
dwVolumeRight = ((((vol >> 8) & 0x7f) * 0xFFFF) / 100);
|
||||
dwVolume = ((dwVolumeLeft << 16) | dwVolumeRight);
|
||||
|
||||
return dwVolume;
|
||||
}
|
||||
|
||||
static void rdpsnd_oss_set_volume(rdpsndDevicePlugin *device, UINT32 value) {
|
||||
static void rdpsnd_oss_set_volume(rdpsndDevicePlugin* device, UINT32 value)
|
||||
{
|
||||
int left, right;
|
||||
rdpsndOssPlugin *oss = (rdpsndOssPlugin*)device;
|
||||
rdpsndOssPlugin* oss = (rdpsndOssPlugin*)device;
|
||||
|
||||
if (device == NULL || oss->mixer_handle == -1)
|
||||
return;
|
||||
|
||||
left = (value & 0xFFFF);
|
||||
right = ((value >> 16) & 0xFFFF);
|
||||
left = (((value & 0xFFFF) * 100) / 0xFFFF);
|
||||
right = ((((value >> 16) & 0xFFFF) * 100) / 0xFFFF);
|
||||
|
||||
if (left < 0)
|
||||
left = 0;
|
||||
else if (left > 100)
|
||||
left = 100;
|
||||
|
||||
if (right < 0)
|
||||
right = 0;
|
||||
else if (right > 100)
|
||||
right = 100;
|
||||
|
||||
left |= (right << 8);
|
||||
|
||||
if (ioctl(oss->mixer_handle, MIXER_WRITE(SOUND_MIXER_VOLUME), &left) == -1)
|
||||
OSS_LOG_ERR("WRITE_MIXER", errno);
|
||||
}
|
||||
|
||||
static void rdpsnd_oss_wave_decode(rdpsndDevicePlugin *device, RDPSND_WAVE *wave) {
|
||||
int size;
|
||||
BYTE *data;
|
||||
rdpsndOssPlugin *oss = (rdpsndOssPlugin*)device;
|
||||
static void rdpsnd_oss_wave_decode(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)
|
||||
{
|
||||
rdpsndOssPlugin* oss = (rdpsndOssPlugin*)device;
|
||||
|
||||
if (device == NULL || wave == NULL)
|
||||
return;
|
||||
|
||||
switch (oss->format.wFormatTag) {
|
||||
case WAVE_FORMAT_ADPCM:
|
||||
oss->dsp_context->decode_ms_adpcm(oss->dsp_context,
|
||||
wave->data, wave->length, oss->format.nChannels, oss->format.nBlockAlign);
|
||||
size = oss->dsp_context->adpcm_size;
|
||||
data = oss->dsp_context->adpcm_buffer;
|
||||
break;
|
||||
case WAVE_FORMAT_DVI_ADPCM:
|
||||
oss->dsp_context->decode_ima_adpcm(oss->dsp_context,
|
||||
wave->data, wave->length, oss->format.nChannels, oss->format.nBlockAlign);
|
||||
size = oss->dsp_context->adpcm_size;
|
||||
data = oss->dsp_context->adpcm_buffer;
|
||||
break;
|
||||
default:
|
||||
size = wave->length;
|
||||
data = wave->data;
|
||||
switch (oss->format.wFormatTag)
|
||||
{
|
||||
case WAVE_FORMAT_ADPCM:
|
||||
oss->dsp_context->decode_ms_adpcm(oss->dsp_context,
|
||||
wave->data, wave->length, oss->format.nChannels, oss->format.nBlockAlign);
|
||||
wave->length = oss->dsp_context->adpcm_size;
|
||||
wave->data = oss->dsp_context->adpcm_buffer;
|
||||
break;
|
||||
case WAVE_FORMAT_DVI_ADPCM:
|
||||
oss->dsp_context->decode_ima_adpcm(oss->dsp_context,
|
||||
wave->data, wave->length, oss->format.nChannels, oss->format.nBlockAlign);
|
||||
wave->length = oss->dsp_context->adpcm_size;
|
||||
wave->data = oss->dsp_context->adpcm_buffer;
|
||||
break;
|
||||
}
|
||||
|
||||
wave->data = (BYTE*)malloc(size);
|
||||
CopyMemory(wave->data, data, size);
|
||||
wave->length = size;
|
||||
}
|
||||
|
||||
static void rdpsnd_oss_wave_play(rdpsndDevicePlugin *device, RDPSND_WAVE *wave) {
|
||||
BYTE *data;
|
||||
int offset, size, status;
|
||||
rdpsndOssPlugin *oss = (rdpsndOssPlugin*)device;
|
||||
static void rdpsnd_oss_wave_play(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)
|
||||
{
|
||||
BYTE* data;
|
||||
int offset, size, status, latency;
|
||||
rdpsndOssPlugin* oss = (rdpsndOssPlugin*)device;
|
||||
|
||||
if (device == NULL || wave == NULL)
|
||||
return;
|
||||
@ -337,61 +381,69 @@ static void rdpsnd_oss_wave_play(rdpsndDevicePlugin *device, RDPSND_WAVE *wave)
|
||||
offset = 0;
|
||||
data = wave->data;
|
||||
size = wave->length;
|
||||
latency = oss->latency;
|
||||
|
||||
while (offset < size) {
|
||||
while (offset < size)
|
||||
{
|
||||
status = write(oss->pcm_handle, &data[offset], (size - offset));
|
||||
if (status < 0) {
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
OSS_LOG_ERR("write fail", errno);
|
||||
rdpsnd_oss_close(device);
|
||||
rdpsnd_oss_open(device, NULL, 0);
|
||||
rdpsnd_oss_open(device, NULL, latency);
|
||||
break;
|
||||
}
|
||||
|
||||
offset += status;
|
||||
}
|
||||
/* From rdpsnd_main.c */
|
||||
wave->wTimeStampB = wave->wTimeStampA + wave->wAudioLength + 65;
|
||||
wave->wLocalTimeB = wave->wLocalTimeA + wave->wAudioLength + 65;
|
||||
|
||||
free(data);
|
||||
/* From rdpsnd_main.c */
|
||||
wave->wTimeStampB = wave->wTimeStampA + wave->wAudioLength + 65 + latency;
|
||||
wave->wLocalTimeB = wave->wLocalTimeA + wave->wAudioLength + 65 + latency;
|
||||
}
|
||||
|
||||
|
||||
static COMMAND_LINE_ARGUMENT_A rdpsnd_oss_args[] = {
|
||||
static COMMAND_LINE_ARGUMENT_A rdpsnd_oss_args[] =
|
||||
{
|
||||
{ "dev", COMMAND_LINE_VALUE_REQUIRED, "<device>", NULL, NULL, -1, NULL, "device" },
|
||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||
};
|
||||
|
||||
static int rdpsnd_oss_parse_addin_args(rdpsndDevicePlugin *device, ADDIN_ARGV *args) {
|
||||
static int rdpsnd_oss_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* args)
|
||||
{
|
||||
int status;
|
||||
char *str_num, *eptr;
|
||||
char* str_num, *eptr;
|
||||
DWORD flags;
|
||||
COMMAND_LINE_ARGUMENT_A *arg;
|
||||
rdpsndOssPlugin *oss = (rdpsndOssPlugin*)device;
|
||||
|
||||
COMMAND_LINE_ARGUMENT_A* arg;
|
||||
rdpsndOssPlugin* oss = (rdpsndOssPlugin*)device;
|
||||
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD;
|
||||
|
||||
status = CommandLineParseArgumentsA(args->argc, (const char**)args->argv, rdpsnd_oss_args, flags, oss, NULL, NULL);
|
||||
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
arg = rdpsnd_oss_args;
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
|
||||
continue;
|
||||
|
||||
CommandLineSwitchStart(arg)
|
||||
|
||||
CommandLineSwitchCase(arg, "dev") {
|
||||
CommandLineSwitchCase(arg, "dev")
|
||||
{
|
||||
str_num = _strdup(arg->Value);
|
||||
oss->dev_unit = strtol(str_num, &eptr, 10);
|
||||
|
||||
if (oss->dev_unit < 0 || *eptr != '\0')
|
||||
oss->dev_unit = -1;
|
||||
|
||||
free(str_num);
|
||||
}
|
||||
|
||||
CommandLineSwitchEnd(arg)
|
||||
} while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
}
|
||||
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -400,13 +452,12 @@ static int rdpsnd_oss_parse_addin_args(rdpsndDevicePlugin *device, ADDIN_ARGV *a
|
||||
#define freerdp_rdpsnd_client_subsystem_entry oss_freerdp_rdpsnd_client_subsystem_entry
|
||||
#endif
|
||||
|
||||
int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints) {
|
||||
ADDIN_ARGV *args;
|
||||
rdpsndOssPlugin *oss;
|
||||
|
||||
int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
ADDIN_ARGV* args;
|
||||
rdpsndOssPlugin* oss;
|
||||
oss = (rdpsndOssPlugin*)malloc(sizeof(rdpsndOssPlugin));
|
||||
ZeroMemory(oss, sizeof(rdpsndOssPlugin));
|
||||
|
||||
oss->device.Open = rdpsnd_oss_open;
|
||||
oss->device.FormatSupported = rdpsnd_oss_format_supported;
|
||||
oss->device.SetFormat = rdpsnd_oss_set_format;
|
||||
@ -416,17 +467,12 @@ int freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS pE
|
||||
oss->device.WavePlay = rdpsnd_oss_wave_play;
|
||||
oss->device.Close = rdpsnd_oss_close;
|
||||
oss->device.Free = rdpsnd_oss_free;
|
||||
|
||||
oss->pcm_handle = -1;
|
||||
oss->mixer_handle = -1;
|
||||
oss->dev_unit = -1;
|
||||
|
||||
args = pEntryPoints->args;
|
||||
rdpsnd_oss_parse_addin_args((rdpsndDevicePlugin*)oss, args);
|
||||
|
||||
oss->dsp_context = freerdp_dsp_context_new();
|
||||
|
||||
pEntryPoints->pRegisterRdpsndDevice(pEntryPoints->rdpsnd, (rdpsndDevicePlugin*)oss);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -62,6 +62,10 @@ if(WITH_GSTREAMER_0_10 OR WITH_GSTREAMER_1_0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_OSS)
|
||||
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "oss" "audio")
|
||||
endif()
|
||||
|
||||
if(WITH_ALSA)
|
||||
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "alsa" "audio")
|
||||
endif()
|
||||
|
@ -68,8 +68,7 @@ static BOOL tsmf_alsa_open(ITSMFAudioDevice *audio, const char *device)
|
||||
TSMFAlsaAudioDevice *alsa = (TSMFAlsaAudioDevice *) audio;
|
||||
if(!device)
|
||||
{
|
||||
if(!alsa->device[0])
|
||||
strncpy(alsa->device, "default", sizeof(alsa->device));
|
||||
strncpy(alsa->device, "default", sizeof(alsa->device));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -25,6 +25,9 @@
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <winpr/thread.h>
|
||||
|
||||
#include <gst/gst.h>
|
||||
@ -61,8 +64,8 @@ struct X11Handle
|
||||
|
||||
static const char* get_shm_id()
|
||||
{
|
||||
static char shm_id[64];
|
||||
snprintf(shm_id, sizeof(shm_id), "com.freerdp.xfreerdp.tsmf_%016X", GetCurrentProcessId());
|
||||
static char shm_id[128];
|
||||
snprintf(shm_id, sizeof(shm_id), "/com.freerdp.xfreerdp.tsmf_%016X", GetCurrentProcessId());
|
||||
return shm_id;
|
||||
}
|
||||
|
||||
@ -87,7 +90,6 @@ int tsmf_platform_create(TSMFGstreamerDecoder* decoder)
|
||||
return -1;
|
||||
|
||||
hdl = calloc(1, sizeof(struct X11Handle));
|
||||
|
||||
if (!hdl)
|
||||
{
|
||||
WLog_ERR(TAG, "Could not allocate handle.");
|
||||
@ -95,26 +97,21 @@ int tsmf_platform_create(TSMFGstreamerDecoder* decoder)
|
||||
}
|
||||
|
||||
decoder->platform = hdl;
|
||||
hdl->shmid = shm_open(get_shm_id(), O_RDWR, PROT_READ | PROT_WRITE);;
|
||||
|
||||
if (hdl->shmid < 0)
|
||||
hdl->shmid = shm_open(get_shm_id(), (O_RDWR | O_CREAT), (PROT_READ | PROT_WRITE));
|
||||
if (hdl->shmid == -1)
|
||||
{
|
||||
WLog_ERR(TAG, "failed to get access to shared memory - shmget()");
|
||||
WLog_ERR(TAG, "failed to get access to shared memory - shmget(%s): %i - %s", get_shm_id(), errno, strerror(errno));
|
||||
return -2;
|
||||
}
|
||||
else
|
||||
{
|
||||
hdl->xfwin = mmap(0, sizeof(void *), PROT_READ | PROT_WRITE, MAP_SHARED, hdl->shmid, 0);
|
||||
}
|
||||
|
||||
if (hdl->xfwin == (int*)-1)
|
||||
hdl->xfwin = mmap(0, sizeof(void *), PROT_READ | PROT_WRITE, MAP_SHARED, hdl->shmid, 0);
|
||||
if (hdl->xfwin == MAP_FAILED)
|
||||
{
|
||||
WLog_ERR(TAG, "shmat failed!");
|
||||
return -3;
|
||||
}
|
||||
|
||||
hdl->disp = XOpenDisplay(NULL);
|
||||
|
||||
if (!hdl->disp)
|
||||
{
|
||||
WLog_ERR(TAG, "Failed to open display");
|
||||
|
32
channels/tsmf/client/oss/CMakeLists.txt
Normal file
32
channels/tsmf/client/oss/CMakeLists.txt
Normal file
@ -0,0 +1,32 @@
|
||||
# FreeRDP: A Remote Desktop Protocol Implementation
|
||||
# FreeRDP cmake build script
|
||||
#
|
||||
# Copyright (c) 2015 Rozhuk Ivan <rozhuk.im@gmail.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.
|
||||
|
||||
define_channel_client_subsystem("tsmf" "oss" "audio")
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
tsmf_oss.c)
|
||||
|
||||
include_directories(..)
|
||||
include_directories(${OSS_INCLUDE_DIRS})
|
||||
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
|
||||
|
||||
|
||||
|
||||
target_link_libraries(${MODULE_NAME} freerdp ${OSS_LIBRARIES})
|
||||
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
|
251
channels/tsmf/client/oss/tsmf_oss.c
Normal file
251
channels/tsmf/client/oss/tsmf_oss.c
Normal file
@ -0,0 +1,251 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Video Redirection Virtual Channel - OSS Audio Device
|
||||
*
|
||||
* Copyright (c) 2015 Rozhuk Ivan <rozhuk.im@gmail.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 <unistd.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <libgen.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/soundcard.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/codec/dsp.h>
|
||||
|
||||
#include "tsmf_audio.h"
|
||||
|
||||
|
||||
typedef struct _TSMFOSSAudioDevice
|
||||
{
|
||||
ITSMFAudioDevice iface;
|
||||
|
||||
char dev_name[PATH_MAX];
|
||||
int pcm_handle;
|
||||
|
||||
UINT32 sample_rate;
|
||||
UINT32 channels;
|
||||
UINT32 bits_per_sample;
|
||||
|
||||
UINT32 data_size_last;
|
||||
} TSMFOssAudioDevice;
|
||||
|
||||
|
||||
#define OSS_LOG_ERR(_text, _error) \
|
||||
if (_error != 0) \
|
||||
WLog_ERR(TAG, "%s: %i - %s", _text, _error, strerror(_error));
|
||||
|
||||
|
||||
static BOOL tsmf_oss_open(ITSMFAudioDevice* audio, const char* device)
|
||||
{
|
||||
int tmp;
|
||||
TSMFOssAudioDevice* oss = (TSMFOssAudioDevice*)audio;
|
||||
|
||||
if (oss == NULL || oss->pcm_handle != -1)
|
||||
return FALSE;
|
||||
|
||||
if (device == NULL) /* Default device. */
|
||||
{
|
||||
strncpy(oss->dev_name, "/dev/dsp", sizeof(oss->dev_name));
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(oss->dev_name, device, sizeof(oss->dev_name));
|
||||
}
|
||||
|
||||
if ((oss->pcm_handle = open(oss->dev_name, O_WRONLY)) < 0)
|
||||
{
|
||||
OSS_LOG_ERR("sound dev open failed", errno);
|
||||
oss->pcm_handle = -1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#if 0 /* FreeBSD OSS implementation at this moment (2015.03) does not set PCM_CAP_OUTPUT flag. */
|
||||
tmp = 0;
|
||||
|
||||
if (ioctl(oss->pcm_handle, SNDCTL_DSP_GETCAPS, &mask) == -1)
|
||||
{
|
||||
OSS_LOG_ERR("SNDCTL_DSP_GETCAPS failed, try ignory", errno);
|
||||
}
|
||||
else if ((mask & PCM_CAP_OUTPUT) == 0)
|
||||
{
|
||||
OSS_LOG_ERR("Device does not supports playback", EOPNOTSUPP);
|
||||
close(oss->pcm_handle);
|
||||
oss->pcm_handle = -1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#endif
|
||||
tmp = 0;
|
||||
|
||||
if (ioctl(oss->pcm_handle, SNDCTL_DSP_GETFMTS, &tmp) == -1)
|
||||
{
|
||||
OSS_LOG_ERR("SNDCTL_DSP_GETFMTS failed", errno);
|
||||
close(oss->pcm_handle);
|
||||
oss->pcm_handle = -1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((AFMT_S16_LE & tmp) == 0)
|
||||
{
|
||||
OSS_LOG_ERR("SNDCTL_DSP_GETFMTS - AFMT_S16_LE", EOPNOTSUPP);
|
||||
close(oss->pcm_handle);
|
||||
oss->pcm_handle = -1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WLog_INFO(TAG, "open: %s", oss->dev_name);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL tsmf_oss_set_format(ITSMFAudioDevice* audio, UINT32 sample_rate, UINT32 channels, UINT32 bits_per_sample)
|
||||
{
|
||||
int tmp;
|
||||
TSMFOssAudioDevice* oss = (TSMFOssAudioDevice*)audio;
|
||||
|
||||
if (oss == NULL || oss->pcm_handle == -1)
|
||||
return FALSE;
|
||||
|
||||
oss->sample_rate = sample_rate;
|
||||
oss->channels = channels;
|
||||
oss->bits_per_sample = bits_per_sample;
|
||||
tmp = AFMT_S16_LE;
|
||||
|
||||
if (ioctl(oss->pcm_handle, SNDCTL_DSP_SETFMT, &tmp) == -1)
|
||||
OSS_LOG_ERR("SNDCTL_DSP_SETFMT failed", errno);
|
||||
|
||||
tmp = channels;
|
||||
|
||||
if (ioctl(oss->pcm_handle, SNDCTL_DSP_CHANNELS, &tmp) == -1)
|
||||
OSS_LOG_ERR("SNDCTL_DSP_CHANNELS failed", errno);
|
||||
|
||||
tmp = sample_rate;
|
||||
|
||||
if (ioctl(oss->pcm_handle, SNDCTL_DSP_SPEED, &tmp) == -1)
|
||||
OSS_LOG_ERR("SNDCTL_DSP_SPEED failed", errno);
|
||||
|
||||
tmp = ((bits_per_sample / 8) * channels * sample_rate);
|
||||
|
||||
if (ioctl(oss->pcm_handle, SNDCTL_DSP_SETFRAGMENT, &tmp) == -1)
|
||||
OSS_LOG_ERR("SNDCTL_DSP_SETFRAGMENT failed", errno);
|
||||
|
||||
DEBUG_TSMF("sample_rate %d channels %d bits_per_sample %d",
|
||||
sample_rate, channels, bits_per_sample);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL tsmf_oss_play(ITSMFAudioDevice* audio, BYTE* data, UINT32 data_size)
|
||||
{
|
||||
int status;
|
||||
UINT32 offset;
|
||||
TSMFOssAudioDevice* oss = (TSMFOssAudioDevice*)audio;
|
||||
DEBUG_TSMF("tsmf_oss_play: data_size %d", data_size);
|
||||
|
||||
if (oss == NULL || oss->pcm_handle == -1)
|
||||
return FALSE;
|
||||
|
||||
if (data == NULL || data_size == 0)
|
||||
{
|
||||
free(data);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
oss->data_size_last = data_size;
|
||||
|
||||
while (offset < data_size)
|
||||
{
|
||||
status = write(oss->pcm_handle, &data[offset], (data_size - offset));
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
OSS_LOG_ERR("write fail", errno);
|
||||
free(data);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
offset += status;
|
||||
}
|
||||
|
||||
free(data);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static UINT64 tsmf_oss_get_latency(ITSMFAudioDevice* audio)
|
||||
{
|
||||
UINT64 latency = 0;
|
||||
TSMFOssAudioDevice* oss = (TSMFOssAudioDevice*)audio;
|
||||
|
||||
if (oss == NULL)
|
||||
return 0;
|
||||
|
||||
//latency = ((oss->data_size_last / (oss->bits_per_sample / 8)) * oss->sample_rate);
|
||||
//WLog_INFO(TAG, "latency: %zu", latency);
|
||||
return latency;
|
||||
}
|
||||
|
||||
static void tsmf_oss_flush(ITSMFAudioDevice* audio)
|
||||
{
|
||||
}
|
||||
|
||||
static void tsmf_oss_free(ITSMFAudioDevice* audio)
|
||||
{
|
||||
TSMFOssAudioDevice* oss = (TSMFOssAudioDevice*)audio;
|
||||
|
||||
if (oss == NULL)
|
||||
return;
|
||||
|
||||
if (oss->pcm_handle != -1)
|
||||
{
|
||||
WLog_INFO(TAG, "close: %s", oss->dev_name);
|
||||
close(oss->pcm_handle);
|
||||
}
|
||||
|
||||
free(oss);
|
||||
}
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_tsmf_client_audio_subsystem_entry oss_freerdp_tsmf_client_audio_subsystem_entry
|
||||
#endif
|
||||
|
||||
ITSMFAudioDevice* freerdp_tsmf_client_audio_subsystem_entry(void)
|
||||
{
|
||||
TSMFOssAudioDevice* oss;
|
||||
oss = (TSMFOssAudioDevice*)malloc(sizeof(TSMFOssAudioDevice));
|
||||
ZeroMemory(oss, sizeof(TSMFOssAudioDevice));
|
||||
oss->iface.Open = tsmf_oss_open;
|
||||
oss->iface.SetFormat = tsmf_oss_set_format;
|
||||
oss->iface.Play = tsmf_oss_play;
|
||||
oss->iface.GetLatency = tsmf_oss_get_latency;
|
||||
oss->iface.Flush = tsmf_oss_flush;
|
||||
oss->iface.Free = tsmf_oss_free;
|
||||
oss->pcm_handle = -1;
|
||||
return (ITSMFAudioDevice*)oss;
|
||||
}
|
@ -49,6 +49,11 @@ static ITSMFAudioDevice* tsmf_load_audio_device_by_name(const char* name, const
|
||||
{
|
||||
audio->Free(audio);
|
||||
audio = NULL;
|
||||
WLog_ERR(TAG, "failed to open, name: %s, device: %s", name, device);
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_DBG(TAG, "name: %s, device: %s", name, device);
|
||||
}
|
||||
|
||||
return audio;
|
||||
@ -56,7 +61,7 @@ static ITSMFAudioDevice* tsmf_load_audio_device_by_name(const char* name, const
|
||||
|
||||
ITSMFAudioDevice* tsmf_load_audio_device(const char* name, const char* device)
|
||||
{
|
||||
ITSMFAudioDevice* audio;
|
||||
ITSMFAudioDevice* audio = NULL;
|
||||
|
||||
if (name)
|
||||
{
|
||||
@ -64,10 +69,29 @@ ITSMFAudioDevice* tsmf_load_audio_device(const char* name, const char* device)
|
||||
}
|
||||
else
|
||||
{
|
||||
audio = tsmf_load_audio_device_by_name("pulse", device);
|
||||
#if defined(WITH_PULSE)
|
||||
if (!audio)
|
||||
audio = tsmf_load_audio_device_by_name("pulse", device);
|
||||
#endif
|
||||
|
||||
#if defined(WITH_OSS)
|
||||
if (!audio)
|
||||
audio = tsmf_load_audio_device_by_name("oss", device);
|
||||
#endif
|
||||
|
||||
#if defined(WITH_ALSA)
|
||||
if (!audio)
|
||||
audio = tsmf_load_audio_device_by_name("alsa", device);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (audio == NULL)
|
||||
{
|
||||
WLog_ERR(TAG, "no sound device.");
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_DBG(TAG, "name: %s, device: %s", name, device);
|
||||
}
|
||||
|
||||
return audio;
|
||||
|
@ -362,8 +362,8 @@ static int tsmf_plugin_terminated(IWTSPlugin* pPlugin)
|
||||
|
||||
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" },
|
||||
{ "sys", COMMAND_LINE_VALUE_REQUIRED, "<subsystem>", NULL, NULL, -1, NULL, "audio subsystem" },
|
||||
{ "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 }
|
||||
};
|
||||
@ -386,11 +386,11 @@ static void tsmf_process_addin_args(IWTSPlugin *pPlugin, ADDIN_ARGV *args)
|
||||
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
|
||||
continue;
|
||||
CommandLineSwitchStart(arg)
|
||||
CommandLineSwitchCase(arg, "audio")
|
||||
CommandLineSwitchCase(arg, "sys")
|
||||
{
|
||||
tsmf->audio_name = _strdup(arg->Value);
|
||||
}
|
||||
CommandLineSwitchCase(arg, "audio-dev")
|
||||
CommandLineSwitchCase(arg, "dev")
|
||||
{
|
||||
tsmf->audio_device = _strdup(arg->Value);
|
||||
}
|
||||
|
@ -424,13 +424,13 @@ static void tsmf_sample_playback_audio(TSMF_SAMPLE* sample)
|
||||
DEBUG_TSMF("MessageId %d EndTime %d consumed.",
|
||||
sample->sample_id, (int)sample->end_time);
|
||||
|
||||
if (sample->stream->audio && sample->data)
|
||||
if (stream->audio && sample->data)
|
||||
{
|
||||
sample->stream->audio->Play(sample->stream->audio, sample->data, sample->decoded_size);
|
||||
stream->audio->Play(stream->audio, sample->data, sample->decoded_size);
|
||||
sample->data = NULL;
|
||||
sample->decoded_size = 0;
|
||||
|
||||
if (stream->audio && stream->audio->GetLatency)
|
||||
if (stream->audio->GetLatency)
|
||||
latency = stream->audio->GetLatency(stream->audio);
|
||||
}
|
||||
else
|
||||
|
@ -18,15 +18,28 @@
|
||||
define_channel("urbdrc")
|
||||
|
||||
if(NOT WIN32)
|
||||
find_package(DevD)
|
||||
find_package(UDev)
|
||||
find_package(UUID)
|
||||
find_package(DbusGlib)
|
||||
find_package(libusb-1.0)
|
||||
endif()
|
||||
|
||||
if(UDEV_FOUND AND UUID_FOUND AND DBUS_GLIB_FOUND AND LIBUSB_1_FOUND)
|
||||
set(URBDRC_DEPENDENCIES_FOUND TRUE)
|
||||
message(STATUS "Found all URBDRC dependencies")
|
||||
if(DEVD_FOUND OR UDEV_FOUND)
|
||||
if(UUID_FOUND AND DBUS_GLIB_FOUND AND LIBUSB_1_FOUND)
|
||||
set(URBDRC_DEPENDENCIES_FOUND TRUE)
|
||||
message(STATUS "Found all URBDRC dependencies")
|
||||
else()
|
||||
if(NOT UUID_FOUND)
|
||||
message(STATUS "URBDRC dependencie not found: UUID")
|
||||
endif()
|
||||
if(NOT DBUS_GLIB_FOUND)
|
||||
message(STATUS "URBDRC dependencie not found: DBUS_GLIB")
|
||||
endif()
|
||||
if(NOT LIBUSB_1_FOUND)
|
||||
message(STATUS "URBDRC dependencie not found: LIBUSB_1")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_CLIENT_CHANNELS)
|
||||
|
@ -39,8 +39,10 @@ add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS
|
||||
${DBUS_GLIB_LIBRARIES}
|
||||
${UDEV_LIBRARIES}
|
||||
${UUID_LIBRARIES})
|
||||
if (UDEV_FOUND AND UDEV_LIBRARIES)
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${UDEV_LIBRARIES})
|
||||
endif()
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} winpr freerdp)
|
||||
|
||||
|
@ -1281,7 +1281,7 @@ static int urb_os_feature_descriptor_request(URBDRC_CHANNEL_CALLBACK * callback,
|
||||
|
||||
data_read_UINT32(data + 0, RequestId);
|
||||
data_read_BYTE(data + 4, Recipient); /** Recipient */
|
||||
Recipient = Recipient && 0x1f;
|
||||
Recipient = (Recipient & 0x1f); /* XXX: origin: Recipient && 0x1f !? */
|
||||
data_read_BYTE(data + 5, InterfaceNumber); /** InterfaceNumber */
|
||||
data_read_BYTE(data + 6, Ms_PageIndex); /** Ms_PageIndex */
|
||||
data_read_UINT16(data + 7, Ms_featureDescIndex); /** Ms_featureDescIndex */
|
||||
|
@ -22,7 +22,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#if defined(__linux__)
|
||||
#include <libudev.h>
|
||||
#endif
|
||||
|
||||
#include "libusb_udevice.h"
|
||||
|
||||
@ -455,8 +457,7 @@ static void print_status(enum libusb_transfer_status status)
|
||||
|
||||
static LIBUSB_DEVICE* udev_get_libusb_dev(int bus_number, int dev_number)
|
||||
{
|
||||
int i;
|
||||
ssize_t total_device;
|
||||
ssize_t i, total_device;
|
||||
LIBUSB_DEVICE** libusb_list;
|
||||
|
||||
total_device = libusb_get_device_list(NULL, &libusb_list);
|
||||
@ -492,7 +493,69 @@ static LIBUSB_DEVICE_DESCRIPTOR* udev_new_descript(LIBUSB_DEVICE* libusb_dev)
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
/* Get HUB handle */
|
||||
/* Get HUB handle */
|
||||
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
|
||||
static int udev_get_hub_handle(UDEVICE* pdev, UINT16 bus_number, UINT16 dev_number) {
|
||||
int error;
|
||||
ssize_t i, total_device, ports_cnt;
|
||||
uint8_t port_numbers[16];
|
||||
LIBUSB_DEVICE **libusb_list;
|
||||
|
||||
total_device = libusb_get_device_list(NULL, &libusb_list);
|
||||
/* Look for device. */
|
||||
error = -1;
|
||||
for (i = 0; i < total_device; i ++)
|
||||
{
|
||||
if ((bus_number != libusb_get_bus_number(libusb_list[i])) ||
|
||||
(dev_number != libusb_get_device_address(libusb_list[i])))
|
||||
continue;
|
||||
error = libusb_open(libusb_list[i], &pdev->hub_handle);
|
||||
if (error < 0)
|
||||
{
|
||||
WLog_ERR(TAG,"libusb_open error: %i - %s", error, libusb_strerror(error));
|
||||
break;
|
||||
}
|
||||
/* get port number */
|
||||
error = libusb_get_port_numbers(libusb_list[i], port_numbers, sizeof(port_numbers));
|
||||
libusb_close(pdev->hub_handle);
|
||||
if (error < 1)
|
||||
{ /* Prevent open hub, treat as error. */
|
||||
WLog_ERR(TAG,"libusb_get_port_numbers error: %i - %s", error, libusb_strerror(error));
|
||||
break;
|
||||
}
|
||||
pdev->port_number = port_numbers[(error - 1)];
|
||||
error = 0;
|
||||
WLog_DBG(TAG, " Port: %d", pdev->port_number);
|
||||
/* gen device path */
|
||||
sprintf(pdev->path, "ugen%d.%d", bus_number, dev_number);
|
||||
WLog_DBG(TAG, " DevPath: %s", pdev->path);
|
||||
break;
|
||||
}
|
||||
/* Look for device hub. */
|
||||
if (error == 0)
|
||||
{
|
||||
error = -1;
|
||||
for (i = 0; i < total_device; i ++)
|
||||
{
|
||||
if ((bus_number != libusb_get_bus_number(libusb_list[i])) ||
|
||||
(1 != libusb_get_device_address(libusb_list[i]))) /* Root hub allways first on bus. */
|
||||
continue;
|
||||
WLog_DBG(TAG, " Open hub: %d", bus_number);
|
||||
error = libusb_open(libusb_list[i], &pdev->hub_handle);
|
||||
if (error < 0)
|
||||
WLog_ERR(TAG,"libusb_open error: %i - %s", error, libusb_strerror(error));
|
||||
break;
|
||||
}
|
||||
}
|
||||
libusb_free_device_list(libusb_list, 1);
|
||||
|
||||
if (error < 0)
|
||||
return -1;
|
||||
WLog_DBG(TAG, "libusb_open success!");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if defined(__linux__)
|
||||
static int udev_get_hub_handle(UDEVICE* pdev, UINT16 bus_number, UINT16 dev_number)
|
||||
{
|
||||
struct udev* udev;
|
||||
@ -627,6 +690,7 @@ static int udev_get_hub_handle(UDEVICE* pdev, UINT16 bus_number, UINT16 dev_numb
|
||||
/* Success! */
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int libusb_udev_select_interface(IUDEVICE* idev, BYTE InterfaceNumber, BYTE AlternateSetting)
|
||||
{
|
||||
@ -1211,6 +1275,7 @@ static int libusb_udev_query_device_port_status(IUDEVICE* idev, UINT32* UsbdStat
|
||||
UDEVICE* pdev = (UDEVICE*) idev;
|
||||
int success = 0, ret;
|
||||
|
||||
WLog_DBG(TAG,"...");
|
||||
if (pdev->hub_handle != NULL)
|
||||
{
|
||||
ret = idev->control_transfer(idev, 0xffff, 0, 0,
|
||||
@ -1815,10 +1880,10 @@ int udev_new_by_id(UINT16 idVendor, UINT16 idProduct, IUDEVICE*** devArray)
|
||||
UDEVICE** array;
|
||||
UINT16 bus_number;
|
||||
UINT16 dev_number;
|
||||
ssize_t total_device;
|
||||
int i, status, num = 0;
|
||||
ssize_t i, total_device;
|
||||
int status, num = 0;
|
||||
|
||||
WLog_ERR(TAG, "VID: 0x%04X PID: 0x%04X", idVendor, idProduct);
|
||||
WLog_INFO(TAG, "VID: 0x%04X, PID: 0x%04X", idVendor, idProduct);
|
||||
|
||||
array = (UDEVICE**) malloc(16 * sizeof(UDEVICE*));
|
||||
|
||||
@ -1839,7 +1904,7 @@ int udev_new_by_id(UINT16 idVendor, UINT16 idProduct, IUDEVICE*** devArray)
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "libusb_open: (by id) error: 0x%08X (%d)", status, status);
|
||||
WLog_ERR(TAG, "libusb_open: (by id) error: 0x%08X (%d)", status, status);
|
||||
zfree(descriptor);
|
||||
zfree(array[num]);
|
||||
continue;
|
||||
|
@ -23,7 +23,11 @@
|
||||
#ifndef __LIBUSB_UDEVICE_H
|
||||
#define __LIBUSB_UDEVICE_H
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
|
||||
#include <libusb.h>
|
||||
#else
|
||||
#include <libusb-1.0/libusb.h>
|
||||
#endif
|
||||
|
||||
#include "urbdrc_types.h"
|
||||
#include "request_queue.h"
|
||||
|
@ -610,5 +610,7 @@ int freerdp_urbdrc_client_subsystem_entry(PFREERDP_URBDRC_SERVICE_ENTRY_POINTS p
|
||||
|
||||
pEntryPoints->pRegisterUDEVMAN(pEntryPoints->plugin, (IUDEVMAN*) udevman);
|
||||
|
||||
WLog_DBG(TAG, "UDEVMAN device registered.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -24,7 +24,16 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <errno.h>
|
||||
#include <err.h>
|
||||
#endif
|
||||
#if defined(__linux__)
|
||||
#include <libudev.h>
|
||||
#endif
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
@ -435,6 +444,266 @@ static int urbdrc_exchange_capabilities(URBDRC_CHANNEL_CALLBACK* callback, char*
|
||||
return error;
|
||||
}
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
|
||||
static char *devd_get_val(char *buf, size_t buf_size, const char *val_name, size_t val_name_size, size_t *val_size) {
|
||||
char *ret, *buf_end, *ptr;
|
||||
|
||||
buf_end = (buf + buf_size);
|
||||
for (ret = buf; ret != NULL && ret < buf_end;)
|
||||
{
|
||||
ret = memmem(ret, (buf_end - ret), val_name, val_name_size);
|
||||
if (ret == NULL)
|
||||
return NULL;
|
||||
/* Found. */
|
||||
/* Check: space before or buf+1. */
|
||||
if ((buf + 1) < ret && ret[-1] != ' ')
|
||||
{
|
||||
ret += val_name_size;
|
||||
continue;
|
||||
}
|
||||
/* Check: = after name and size for value. */
|
||||
ret += val_name_size;
|
||||
if ((ret + 1) >= buf_end)
|
||||
return NULL;
|
||||
if (ret[0] != '=')
|
||||
continue;
|
||||
ret ++;
|
||||
break;
|
||||
}
|
||||
if (ret == NULL || val_size == NULL)
|
||||
return ret;
|
||||
/* Calc value data size. */
|
||||
ptr = memchr(ret, ' ', (buf_end - ret));
|
||||
if (ptr == NULL) /* End of string/last value. */
|
||||
ptr = buf_end;
|
||||
(*val_size) = (ptr - ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *urbdrc_search_usb_device(void *arg) {
|
||||
USB_SEARCHMAN *searchman = (USB_SEARCHMAN*)arg;
|
||||
URBDRC_PLUGIN *urbdrc = (URBDRC_PLUGIN*)searchman->urbdrc;
|
||||
IUDEVMAN *udevman = urbdrc->udevman;
|
||||
IWTSVirtualChannelManager *channel_mgr = urbdrc->listener_callback->channel_mgr;
|
||||
IWTSVirtualChannel *dvc_channel;
|
||||
USB_SEARCHDEV *sdev;
|
||||
IUDEVICE *pdev;
|
||||
HANDLE listobj[2];
|
||||
HANDLE mon_fd;
|
||||
int devd_skt;
|
||||
char buf[4096], *val, *ptr, *end_val;
|
||||
ssize_t data_size;
|
||||
size_t val_size, tm;
|
||||
int idVendor, idProduct;
|
||||
int busnum, devnum;
|
||||
int action, success, error, found, on_close;
|
||||
struct sockaddr_un sun;
|
||||
|
||||
WLog_DBG(TAG, "urbdrc_search_usb_device - devd: start");
|
||||
|
||||
devd_skt = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
|
||||
if (devd_skt == -1)
|
||||
{
|
||||
WLog_ERR(TAG, "Can't create devd socket: error = %i", errno);
|
||||
goto err_out;
|
||||
}
|
||||
memset(&sun, 0, sizeof(sun));
|
||||
sun.sun_family = PF_LOCAL;
|
||||
sun.sun_len = sizeof(sun);
|
||||
strlcpy(sun.sun_path, "/var/run/devd.seqpacket.pipe", sizeof(sun.sun_path));
|
||||
if (-1 == connect(devd_skt, (struct sockaddr*)&sun, sizeof(sun)))
|
||||
{
|
||||
WLog_ERR(TAG, "Can't connect devd socket: error = %i - %s", errno, strerror(errno));
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* Get the file descriptor (fd) for the monitor.
|
||||
This fd will get passed to select() */
|
||||
mon_fd = CreateFileDescriptorEvent(NULL, TRUE, FALSE, devd_skt);
|
||||
listobj[0] = searchman->term_event;
|
||||
listobj[1] = mon_fd;
|
||||
|
||||
while (WaitForMultipleObjects(2, listobj, FALSE, INFINITE) != WAIT_OBJECT_0)
|
||||
{
|
||||
WLog_DBG(TAG, "======= SEARCH ======= ");
|
||||
|
||||
/* !system=USB subsystem=DEVICE type=ATTACH ugen=ugen3.3 cdev=ugen3.3 vendor=0x046d product=0x082d devclass=0xef devsubclass=0x02 sernum="6E7D726F" release=0x0011 mode=host port=4 parent=ugen3.1 */
|
||||
/* !system=USB subsystem=DEVICE type=DETACH ugen=ugen3.3 cdev=ugen3.3 vendor=0x046d product=0x082d devclass=0xef devsubclass=0x02 sernum="6E7D726F" release=0x0011 mode=host port=4 parent=ugen3.1 */
|
||||
data_size = read(devd_skt, buf, (sizeof(buf) - 1));
|
||||
if (data_size == -1)
|
||||
{
|
||||
WLog_ERR(TAG, "devd socket read: error = %i", errno);
|
||||
break;
|
||||
}
|
||||
buf[data_size] = 0;
|
||||
WLog_DBG(TAG, "devd event: %s", buf);
|
||||
|
||||
if (buf[0] != '!') /* Skeep non notify events. */
|
||||
continue;
|
||||
/* Check: system=USB */
|
||||
val = devd_get_val(buf, data_size, "system", 6, &val_size);
|
||||
if (val == NULL || val_size != 3 || memcmp(val, "USB", 3) != 0)
|
||||
continue;
|
||||
/* Check: subsystem=DEVICE */
|
||||
val = devd_get_val(buf, data_size, "subsystem", 9, &val_size);
|
||||
if (val == NULL || val_size != 6 || memcmp(val, "DEVICE", 6) != 0)
|
||||
continue;
|
||||
/* Get event type. */
|
||||
val = devd_get_val(buf, data_size, "type", 4, &val_size);
|
||||
if (val == NULL || val_size != 6)
|
||||
continue;
|
||||
action = -1;
|
||||
if (memcmp(val, "ATTACH", 6) == 0)
|
||||
action = 0;
|
||||
if (memcmp(val, "DETACH", 6) == 0)
|
||||
action = 1;
|
||||
if (action == -1)
|
||||
continue; /* Skeep other actions. */
|
||||
|
||||
/* Get bus and dev num. */
|
||||
/* ugen=ugen3.3 */
|
||||
val = devd_get_val(buf, data_size, "ugen", 4, &val_size);
|
||||
if (val == NULL || val_size < 7 || memcmp(val, "ugen", 4) != 0)
|
||||
continue;
|
||||
val += 4;
|
||||
val_size -= 4;
|
||||
ptr = memchr(val, '.', val_size);
|
||||
if (ptr == NULL)
|
||||
continue;
|
||||
/* Prepare strings. */
|
||||
ptr[0] = 0;
|
||||
ptr ++;
|
||||
val[val_size] = 0;
|
||||
/* Extract numbers. */
|
||||
busnum = atoi(val);
|
||||
devnum = atoi(ptr);
|
||||
/* Restore spaces. */
|
||||
ptr[-1] = ' ';
|
||||
val[val_size] = ' ';
|
||||
|
||||
/* Handle event. */
|
||||
dvc_channel = NULL;
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case 0: /* ATTACH */
|
||||
sdev = NULL;
|
||||
success = 0;
|
||||
found = 0;
|
||||
|
||||
/* vendor=0x046d */
|
||||
val = devd_get_val(buf, data_size, "vendor", 6, &val_size);
|
||||
if (val == NULL || val_size < 1)
|
||||
continue;
|
||||
val[val_size] = 0;
|
||||
idVendor = strtol(val, NULL, 16);
|
||||
val[val_size] = ' ';
|
||||
|
||||
/* product=0x082d */
|
||||
val = devd_get_val(buf, data_size, "product", 7, &val_size);
|
||||
if (val == NULL || val_size < 1)
|
||||
continue;
|
||||
val[val_size] = 0;
|
||||
idProduct = strtol(val, NULL, 16);
|
||||
val[val_size] = ' ';
|
||||
|
||||
WLog_DBG(TAG, "ATTACH: bus: %i, dev: %i, ven: %i, prod: %i", busnum, devnum, idVendor, idProduct);
|
||||
|
||||
dvc_channel = channel_mgr->FindChannelById(channel_mgr, urbdrc->first_channel_id);
|
||||
searchman->rewind(searchman);
|
||||
while (dvc_channel && searchman->has_next(searchman))
|
||||
{
|
||||
sdev = searchman->get_next(searchman);
|
||||
if (sdev->idVendor == idVendor &&
|
||||
sdev->idProduct == idProduct)
|
||||
{
|
||||
WLog_VRB(TAG, "Searchman Found Device: %04x:%04x",
|
||||
sdev->idVendor, sdev->idProduct);
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found && udevman->isAutoAdd(udevman))
|
||||
{
|
||||
WLog_VRB(TAG, "Auto Find Device: %04x:%04x ",
|
||||
idVendor, idProduct);
|
||||
found = 2;
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
success = udevman->register_udevice(udevman, busnum, devnum,
|
||||
searchman->UsbDevice, 0, 0, UDEVMAN_FLAG_ADD_BY_ADDR);
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
searchman->UsbDevice ++;
|
||||
|
||||
usleep(400000);
|
||||
error = urdbrc_send_virtual_channel_add(dvc_channel, 0);
|
||||
if (found == 1)
|
||||
searchman->remove(searchman, sdev->idVendor, sdev->idProduct);
|
||||
}
|
||||
break;
|
||||
case 1: /* DETACH */
|
||||
pdev = NULL;
|
||||
on_close = 0;
|
||||
WLog_DBG(TAG, "DETACH: bus: %i, dev: %i", busnum, devnum);
|
||||
|
||||
usleep(500000);
|
||||
udevman->loading_lock(udevman);
|
||||
udevman->rewind(udevman);
|
||||
while (udevman->has_next(udevman))
|
||||
{
|
||||
pdev = udevman->get_next(udevman);
|
||||
if (pdev->get_bus_number(pdev) == busnum &&
|
||||
pdev->get_dev_number(pdev) == devnum)
|
||||
{
|
||||
dvc_channel = channel_mgr->FindChannelById(channel_mgr, pdev->get_channel_id(pdev));
|
||||
|
||||
if (dvc_channel == NULL)
|
||||
{
|
||||
WLog_ERR(TAG, "SEARCH: dvc_channel %d is NULL!!", pdev->get_channel_id(pdev));
|
||||
func_close_udevice(searchman, pdev);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!pdev->isSigToEnd(pdev))
|
||||
{
|
||||
dvc_channel->Write(dvc_channel, 0, NULL, NULL);
|
||||
pdev->SigToEnd(pdev);
|
||||
}
|
||||
|
||||
on_close = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
udevman->loading_unlock(udevman);
|
||||
usleep(300000);
|
||||
|
||||
if (pdev && on_close && dvc_channel &&
|
||||
pdev->isSigToEnd(pdev) &&
|
||||
!(pdev->isChannelClosed(pdev)))
|
||||
{
|
||||
dvc_channel->Close(dvc_channel);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(mon_fd);
|
||||
err_out:
|
||||
close(devd_skt);
|
||||
sem_post(&searchman->sem_term);
|
||||
WLog_DBG(TAG, "urbdrc_search_usb_device - devd: end");
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if defined (__linux__)
|
||||
static void* urbdrc_search_usb_device(void* arg)
|
||||
{
|
||||
USB_SEARCHMAN* searchman = (USB_SEARCHMAN*) arg;
|
||||
@ -658,6 +927,7 @@ fail_create_monfd_event:
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void* urbdrc_new_device_create(void* arg)
|
||||
{
|
||||
@ -674,8 +944,10 @@ void* urbdrc_new_device_create(void* arg)
|
||||
UINT32 FunctionId;
|
||||
int i = 0, found = 0;
|
||||
|
||||
WLog_DBG(TAG, "...");
|
||||
|
||||
channel_mgr = urbdrc->listener_callback->channel_mgr;
|
||||
ChannelId = channel_mgr->GetChannelId(callback->channel);
|
||||
ChannelId = channel_mgr->GetChannelId(callback->channel);
|
||||
|
||||
data_read_UINT32(pBuffer + 0, MessageId);
|
||||
data_read_UINT32(pBuffer + 4, FunctionId);
|
||||
@ -743,6 +1015,8 @@ static int urbdrc_process_channel_notification(URBDRC_CHANNEL_CALLBACK* callback
|
||||
UINT32 FunctionId;
|
||||
URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*) callback->plugin;
|
||||
|
||||
WLog_DBG(TAG, "...");
|
||||
|
||||
data_read_UINT32(pBuffer + 0, MessageId);
|
||||
data_read_UINT32(pBuffer + 4, FunctionId);
|
||||
|
||||
@ -793,7 +1067,7 @@ static int urbdrc_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
|
||||
UINT32 Mask;
|
||||
int error = 0;
|
||||
char* pBuffer = (char*)Stream_Pointer(data);
|
||||
UINT32 cbSize = Stream_GetRemainingLength(data);
|
||||
UINT32 cbSize = Stream_GetRemainingLength(data);
|
||||
|
||||
if (callback == NULL)
|
||||
return 0;
|
||||
|
@ -30,7 +30,11 @@
|
||||
#include <freerdp/channels/log.h>
|
||||
#include <freerdp/utils/msusb.h>
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
|
||||
#include <uuid.h>
|
||||
#else
|
||||
#include <uuid/uuid.h>
|
||||
#endif
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
|
@ -335,7 +335,7 @@ static void xf_SetWindowPID(xfContext* xfc, Window window, pid_t pid)
|
||||
static const char* get_shm_id()
|
||||
{
|
||||
static char shm_id[64];
|
||||
snprintf(shm_id, sizeof(shm_id), "com.freerdp.xfreerdp.tsmf_%016X", GetCurrentProcessId());
|
||||
snprintf(shm_id, sizeof(shm_id), "/com.freerdp.xfreerdp.tsmf_%016X", GetCurrentProcessId());
|
||||
return shm_id;
|
||||
}
|
||||
|
||||
@ -368,7 +368,7 @@ xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char* name, int width, int heig
|
||||
CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
|
||||
CWBorderPixel | CWWinGravity | CWBitGravity, &xfc->attribs);
|
||||
|
||||
window->shmid = shm_open(get_shm_id(), O_CREAT | O_EXCL | O_RDWR, S_IREAD | S_IWRITE);
|
||||
window->shmid = shm_open(get_shm_id(), (O_CREAT | O_RDWR), (S_IREAD | S_IWRITE));
|
||||
|
||||
if (window->shmid < 0)
|
||||
{
|
||||
@ -382,7 +382,7 @@ xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char* name, int width, int heig
|
||||
|
||||
mem = mmap(0, sizeof(window->handle), PROT_READ | PROT_WRITE, MAP_SHARED, window->shmid, 0);
|
||||
|
||||
if (mem == ((int*) -1))
|
||||
if (mem == MAP_FAILED)
|
||||
{
|
||||
DEBUG_X11("xf_CreateDesktopWindow: failed to assign pointer to the memory address - shmat()\n");
|
||||
}
|
||||
|
@ -91,10 +91,10 @@ COMMAND_LINE_ARGUMENT_A args[] =
|
||||
{ "compression-level", COMMAND_LINE_VALUE_REQUIRED, "<level>", NULL, NULL, -1, NULL, "Compression level (0,1,2)" },
|
||||
{ "shell", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Alternate shell" },
|
||||
{ "shell-dir", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Shell working directory" },
|
||||
{ "sound", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, "audio", "Audio output (sound)" },
|
||||
{ "microphone", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, "mic", "Audio input (microphone)" },
|
||||
{ "sound", COMMAND_LINE_VALUE_OPTIONAL, "[sys][dev][format][rate][channel][latency][quality]", NULL, NULL, -1, "audio", "Audio output (sound)" },
|
||||
{ "microphone", COMMAND_LINE_VALUE_OPTIONAL, "[sys][dev][format][rate][channel]", NULL, NULL, -1, "mic", "Audio input (microphone)" },
|
||||
{ "audio-mode", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Audio output mode" },
|
||||
{ "multimedia", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, "mmr", "Redirect multimedia (video)" },
|
||||
{ "multimedia", COMMAND_LINE_VALUE_OPTIONAL, "[sys][dev][decoder]", NULL, NULL, -1, "mmr", "Redirect multimedia (video)" },
|
||||
{ "network", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Network connection type" },
|
||||
{ "drive", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Redirect drive" },
|
||||
{ "drives", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Redirect all drives" },
|
||||
@ -104,7 +104,7 @@ COMMAND_LINE_ARGUMENT_A args[] =
|
||||
{ "parallel", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, NULL, "Redirect parallel device" },
|
||||
{ "smartcard", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, NULL, "Redirect smartcard device" },
|
||||
{ "printer", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, NULL, "Redirect printer device" },
|
||||
{ "usb", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Redirect USB device" },
|
||||
{ "usb", COMMAND_LINE_VALUE_REQUIRED, "[dbg][dev][id|addr][auto]", NULL, NULL, -1, NULL, "Redirect USB device" },
|
||||
{ "multitouch", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Redirect multitouch input" },
|
||||
{ "gestures", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Consume multitouch input locally" },
|
||||
{ "echo", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "echo", "Echo channel" },
|
||||
@ -268,10 +268,13 @@ int freerdp_client_print_command_line_help(int argc, char** argv)
|
||||
printf("Printer Redirection: /printer:<device>,<driver>\n");
|
||||
printf("\n");
|
||||
|
||||
printf("Audio Output Redirection: /sound:sys:oss,dev:1,format:1\n");
|
||||
printf("Audio Output Redirection: /sound:sys:alsa\n");
|
||||
printf("Audio Input Redirection: /microphone:sys:oss,dev:1,format:1\n");
|
||||
printf("Audio Input Redirection: /microphone:sys:alsa\n");
|
||||
printf("\n");
|
||||
|
||||
printf("Multimedia Redirection: /multimedia:sys:oss,dev:/dev/dsp1,decoder:ffmpeg\n");
|
||||
printf("Multimedia Redirection: /multimedia:sys:alsa\n");
|
||||
printf("USB Device Redirection: /usb:id,dev:054c:0268\n");
|
||||
printf("\n");
|
||||
|
31
cmake/FindDevD.cmake
Normal file
31
cmake/FindDevD.cmake
Normal file
@ -0,0 +1,31 @@
|
||||
# Configure devd environment
|
||||
#
|
||||
# DEVD_FOUND - system has a devd
|
||||
# DEVD_BIN_DIR - devd bin dir
|
||||
# DEVD_SKT_DIR - devd socket dir
|
||||
#
|
||||
# Copyright (c) 2015 Rozhuk Ivan <rozhuk.im@gmail.com>
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
#
|
||||
|
||||
|
||||
FIND_PATH(
|
||||
DEVD_BIN_DIR
|
||||
NAMES devd
|
||||
PATHS /sbin /usr/sbin /usr/local/sbin
|
||||
)
|
||||
|
||||
FIND_PATH(
|
||||
DEVD_SKT_DIR
|
||||
NAMES devd.seqpacket.pipe devd.pipe
|
||||
PATHS /var/run/
|
||||
)
|
||||
|
||||
|
||||
if (DEVD_BIN_DIR)
|
||||
set(DEVD_FOUND "YES")
|
||||
message(STATUS "devd found")
|
||||
if (NOT DEVD_SKT_DIR)
|
||||
message(STATUS "devd not running!")
|
||||
endif (NOT DEVD_SKT_DIR)
|
||||
endif (DEVD_BIN_DIR)
|
@ -20,6 +20,7 @@ set(UUID_FOUND TRUE)
|
||||
else (UUID_LIBRARIES AND UUID_INCLUDE_DIRS)
|
||||
find_path(UUID_INCLUDE_DIR
|
||||
NAMES
|
||||
uuid.h
|
||||
uuid/uuid.h
|
||||
PATHS
|
||||
${UUID_DIR}/include
|
||||
@ -85,26 +86,27 @@ $ENV{OSG_ROOT}/lib
|
||||
/opt/lib
|
||||
/usr/freeware/lib64
|
||||
)
|
||||
if (NOT UUID_LIBRARY AND BSD)
|
||||
set(UUID_LIBRARY "")
|
||||
endif(NOT UUID_LIBRARY AND BSD)
|
||||
|
||||
set(UUID_INCLUDE_DIRS
|
||||
${UUID_INCLUDE_DIR}
|
||||
)
|
||||
set(UUID_LIBRARIES
|
||||
${UUID_LIBRARY}
|
||||
)
|
||||
set(UUID_INCLUDE_DIRS ${UUID_INCLUDE_DIR})
|
||||
set(UUID_LIBRARIES ${UUID_LIBRARY})
|
||||
|
||||
if (UUID_INCLUDE_DIRS AND UUID_LIBRARIES)
|
||||
set(UUID_FOUND TRUE)
|
||||
endif (UUID_INCLUDE_DIRS AND UUID_LIBRARIES)
|
||||
if (UUID_INCLUDE_DIRS)
|
||||
if (BSD OR UUID_LIBRARIES)
|
||||
set(UUID_FOUND TRUE)
|
||||
endif (BSD OR UUID_LIBRARIES)
|
||||
endif (UUID_INCLUDE_DIRS)
|
||||
|
||||
if (UUID_FOUND)
|
||||
if (NOT UUID_FIND_QUIETLY)
|
||||
message(STATUS "Found UUID: ${UUID_LIBRARIES}")
|
||||
endif (NOT UUID_FIND_QUIETLY)
|
||||
if (NOT UUID_FIND_QUIETLY)
|
||||
message(STATUS "Found UUID: ${UUID_LIBRARIES}")
|
||||
endif (NOT UUID_FIND_QUIETLY)
|
||||
else (UUID_FOUND)
|
||||
if (UUID_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find UUID")
|
||||
endif (UUID_FIND_REQUIRED)
|
||||
if (UUID_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find UUID")
|
||||
endif (UUID_FIND_REQUIRED)
|
||||
endif (UUID_FOUND)
|
||||
|
||||
# show the UUID_INCLUDE_DIRS and UUID_LIBRARIES variables only in the advanced view
|
||||
|
@ -263,13 +263,19 @@ static int fastpath_recv_update(rdpFastPath* fastpath, BYTE updateCode, UINT32 s
|
||||
{
|
||||
case FASTPATH_UPDATETYPE_ORDERS:
|
||||
if (!fastpath_recv_orders(fastpath, s))
|
||||
{
|
||||
WLog_ERR(TAG, "FASTPATH_UPDATETYPE_ORDERS - fastpath_recv_orders()");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case FASTPATH_UPDATETYPE_BITMAP:
|
||||
case FASTPATH_UPDATETYPE_PALETTE:
|
||||
if (!fastpath_recv_update_common(fastpath, s))
|
||||
{
|
||||
WLog_ERR(TAG, "FASTPATH_UPDATETYPE_ORDERS - fastpath_recv_orders()");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case FASTPATH_UPDATETYPE_SYNCHRONIZE:
|
||||
@ -281,6 +287,8 @@ static int fastpath_recv_update(rdpFastPath* fastpath, BYTE updateCode, UINT32 s
|
||||
|
||||
case FASTPATH_UPDATETYPE_SURFCMDS:
|
||||
status = update_recv_surfcmds(update, size, s);
|
||||
if (status < 0)
|
||||
WLog_ERR(TAG, "FASTPATH_UPDATETYPE_SURFCMDS - update_recv_surfcmds() - %i", status);
|
||||
break;
|
||||
|
||||
case FASTPATH_UPDATETYPE_PTR_NULL:
|
||||
@ -291,30 +299,41 @@ static int fastpath_recv_update(rdpFastPath* fastpath, BYTE updateCode, UINT32 s
|
||||
case FASTPATH_UPDATETYPE_PTR_DEFAULT:
|
||||
update->pointer->pointer_system.type = SYSPTR_DEFAULT;
|
||||
IFCALL(pointer->PointerSystem, context, &pointer->pointer_system);
|
||||
|
||||
break;
|
||||
|
||||
case FASTPATH_UPDATETYPE_PTR_POSITION:
|
||||
if (!update_read_pointer_position(s, &pointer->pointer_position))
|
||||
{
|
||||
WLog_ERR(TAG, "FASTPATH_UPDATETYPE_PTR_POSITION - update_read_pointer_position()");
|
||||
return -1;
|
||||
}
|
||||
IFCALL(pointer->PointerPosition, context, &pointer->pointer_position);
|
||||
break;
|
||||
|
||||
case FASTPATH_UPDATETYPE_COLOR:
|
||||
if (!update_read_pointer_color(s, &pointer->pointer_color, 24))
|
||||
{
|
||||
WLog_ERR(TAG, "FASTPATH_UPDATETYPE_COLOR - update_read_pointer_color()");
|
||||
return -1;
|
||||
}
|
||||
IFCALL(pointer->PointerColor, context, &pointer->pointer_color);
|
||||
break;
|
||||
|
||||
case FASTPATH_UPDATETYPE_CACHED:
|
||||
if (!update_read_pointer_cached(s, &pointer->pointer_cached))
|
||||
{
|
||||
WLog_ERR(TAG, "FASTPATH_UPDATETYPE_CACHED - update_read_pointer_cached()");
|
||||
return -1;
|
||||
}
|
||||
IFCALL(pointer->PointerCached, context, &pointer->pointer_cached);
|
||||
break;
|
||||
|
||||
case FASTPATH_UPDATETYPE_POINTER:
|
||||
if (!update_read_pointer_new(s, &pointer->pointer_new))
|
||||
{
|
||||
WLog_ERR(TAG, "FASTPATH_UPDATETYPE_POINTER - update_read_pointer_new()");
|
||||
return -1;
|
||||
}
|
||||
IFCALL(pointer->PointerNew, context, &pointer->pointer_new);
|
||||
break;
|
||||
|
||||
@ -371,7 +390,10 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
|
||||
Stream_Read_UINT16(s, size);
|
||||
|
||||
if (Stream_GetRemainingLength(s) < size)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_GetRemainingLength() < size");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cs = s;
|
||||
next_pos = Stream_GetPosition(s) + size;
|
||||
@ -380,7 +402,7 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
|
||||
|
||||
if (bulkStatus < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "bulk_decompress() failed");
|
||||
WLog_ERR(TAG, "bulk_decompress() failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -402,7 +424,7 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
|
||||
{
|
||||
if (fastpath->fragmentation != -1)
|
||||
{
|
||||
WLog_ERR(TAG, "Unexpected FASTPATH_FRAGMENT_SINGLE");
|
||||
WLog_ERR(TAG, "Unexpected FASTPATH_FRAGMENT_SINGLE");
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
@ -410,7 +432,10 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
|
||||
status = fastpath_recv_update(fastpath, updateCode, totalSize, cs);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "fastpath_recv_update() - %i", status);
|
||||
goto out_fail;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -418,7 +443,7 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
|
||||
{
|
||||
if (fastpath->fragmentation != -1)
|
||||
{
|
||||
WLog_ERR(TAG, "Unexpected FASTPATH_FRAGMENT_FIRST");
|
||||
WLog_ERR(TAG, "fastpath_recv_update_data: Unexpected FASTPATH_FRAGMENT_FIRST");
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
@ -428,7 +453,7 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
|
||||
|
||||
if (totalSize > transport->settings->MultifragMaxRequestSize)
|
||||
{
|
||||
WLog_ERR(TAG, "Total size (%d) exceeds MultifragMaxRequestSize (%d)",
|
||||
WLog_ERR(TAG, "Total size (%d) exceeds MultifragMaxRequestSize (%d)",
|
||||
totalSize, transport->settings->MultifragMaxRequestSize);
|
||||
goto out_fail;
|
||||
}
|
||||
@ -445,7 +470,7 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
|
||||
if ((fastpath->fragmentation != FASTPATH_FRAGMENT_FIRST) &&
|
||||
(fastpath->fragmentation != FASTPATH_FRAGMENT_NEXT))
|
||||
{
|
||||
WLog_ERR(TAG, "Unexpected FASTPATH_FRAGMENT_NEXT");
|
||||
WLog_ERR(TAG, "fastpath_recv_update_data: Unexpected FASTPATH_FRAGMENT_NEXT");
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
@ -455,7 +480,7 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
|
||||
|
||||
if (totalSize > transport->settings->MultifragMaxRequestSize)
|
||||
{
|
||||
WLog_ERR(TAG, "Total size (%d) exceeds MultifragMaxRequestSize (%d)",
|
||||
WLog_ERR(TAG, "Total size (%d) exceeds MultifragMaxRequestSize (%d)",
|
||||
totalSize, transport->settings->MultifragMaxRequestSize);
|
||||
goto out_fail;
|
||||
}
|
||||
@ -473,7 +498,7 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
|
||||
if ((fastpath->fragmentation != FASTPATH_FRAGMENT_FIRST) &&
|
||||
(fastpath->fragmentation != FASTPATH_FRAGMENT_NEXT))
|
||||
{
|
||||
WLog_ERR(TAG, "Unexpected FASTPATH_FRAGMENT_LAST");
|
||||
WLog_ERR(TAG, "fastpath_recv_update_data: Unexpected FASTPATH_FRAGMENT_LAST");
|
||||
goto out_fail;
|
||||
}
|
||||
|
||||
@ -483,7 +508,7 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
|
||||
|
||||
if (totalSize > transport->settings->MultifragMaxRequestSize)
|
||||
{
|
||||
WLog_ERR(TAG, "Total size (%d) exceeds MultifragMaxRequestSize (%d)",
|
||||
WLog_ERR(TAG, "Total size (%d) exceeds MultifragMaxRequestSize (%d)",
|
||||
totalSize, transport->settings->MultifragMaxRequestSize);
|
||||
goto out_fail;
|
||||
}
|
||||
@ -504,7 +529,10 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
|
||||
Stream_Release(fastpath->updateData);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "fastpath_recv_update_data: fastpath_recv_update() - %i", status);
|
||||
goto out_fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -526,7 +554,6 @@ out_fail:
|
||||
|
||||
int fastpath_recv_updates(rdpFastPath* fastpath, wStream* s)
|
||||
{
|
||||
int status = 0;
|
||||
rdpUpdate* update = fastpath->rdp->update;
|
||||
|
||||
IFCALL(update->BeginPaint, update->context);
|
||||
@ -534,12 +561,15 @@ int fastpath_recv_updates(rdpFastPath* fastpath, wStream* s)
|
||||
while (Stream_GetRemainingLength(s) >= 3)
|
||||
{
|
||||
if (fastpath_recv_update_data(fastpath, s) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "fastpath_recv_update_data() fail");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
IFCALL(update->EndPaint, update->context);
|
||||
|
||||
return status;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL fastpath_read_input_event_header(wStream* s, BYTE* eventFlags, BYTE* eventCode)
|
||||
@ -683,7 +713,7 @@ static BOOL fastpath_recv_input_event(rdpFastPath* fastpath, wStream* s)
|
||||
break;
|
||||
|
||||
default:
|
||||
WLog_ERR(TAG, "Unknown eventCode %d", eventCode);
|
||||
WLog_ERR(TAG, "Unknown eventCode %d", eventCode);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -794,7 +824,7 @@ BOOL fastpath_send_multiple_input_pdu(rdpFastPath* fastpath, wStream* s, int iNu
|
||||
|
||||
if (length >= (2 << 14))
|
||||
{
|
||||
WLog_ERR(TAG, "Maximum FastPath PDU length is 32767");
|
||||
WLog_ERR(TAG, "Maximum FastPath PDU length is 32767");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -210,6 +210,7 @@ BOOL freerdp_check_fds(freerdp* instance)
|
||||
TerminateEventArgs e;
|
||||
rdpContext* context = instance->context;
|
||||
|
||||
WLog_DBG(TAG, "rdp_check_fds() - %i", status);
|
||||
EventArgsInit(&e, "freerdp");
|
||||
e.code = 0;
|
||||
PubSub_OnTerminate(context->pubSub, context, &e);
|
||||
@ -244,9 +245,17 @@ BOOL freerdp_check_event_handles(rdpContext* context)
|
||||
status = freerdp_check_fds(context->instance);
|
||||
|
||||
if (!status)
|
||||
{
|
||||
WLog_ERR(TAG, "freerdp_check_fds() failed - %i", status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
status = freerdp_channels_check_fds(context->channels, context->instance);
|
||||
if (!status)
|
||||
{
|
||||
WLog_ERR(TAG, "freerdp_channels_check_fds() failed - %i", status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -500,7 +500,10 @@ static INLINE BOOL update_read_delta(wStream* s, INT32* value)
|
||||
BYTE byte;
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 1)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_GetRemainingLength(s) < 1");
|
||||
return FALSE;
|
||||
}
|
||||
Stream_Read_UINT8(s, byte);
|
||||
|
||||
if (byte & 0x40)
|
||||
@ -511,7 +514,10 @@ static INLINE BOOL update_read_delta(wStream* s, INT32* value)
|
||||
if (byte & 0x80)
|
||||
{
|
||||
if (Stream_GetRemainingLength(s) < 1)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_GetRemainingLength(s) < 1");
|
||||
return FALSE;
|
||||
}
|
||||
Stream_Read_UINT8(s, byte);
|
||||
*value = (*value << 8) | byte;
|
||||
}
|
||||
@ -723,7 +729,10 @@ static INLINE BOOL update_read_delta_points(wStream* s, DELTA_POINT* points, int
|
||||
zeroBitsSize = ((number + 3) / 4);
|
||||
|
||||
if (Stream_GetRemainingLength(s) < zeroBitsSize)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_GetRemainingLength(s) < %i", zeroBitsSize);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Stream_GetPointer(s, zeroBits);
|
||||
Stream_Seek(s, zeroBitsSize);
|
||||
@ -736,10 +745,16 @@ static INLINE BOOL update_read_delta_points(wStream* s, DELTA_POINT* points, int
|
||||
flags = zeroBits[i / 4];
|
||||
|
||||
if ((~flags & 0x80) && !update_read_delta(s, &points[i].x))
|
||||
{
|
||||
WLog_ERR(TAG, "update_read_delta(x) failed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((~flags & 0x40) && !update_read_delta(s, &points[i].y))
|
||||
{
|
||||
WLog_ERR(TAG, "update_read_delta(y) failed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
flags <<= 2;
|
||||
}
|
||||
@ -1336,12 +1351,18 @@ BOOL update_read_polyline_order(wStream* s, ORDER_INFO* orderInfo, POLYLINE_ORDE
|
||||
DELTA_POINT *new_points;
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 1)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_GetRemainingLength(s) < 1");
|
||||
return FALSE;
|
||||
}
|
||||
Stream_Read_UINT8(s, polyline->cbData);
|
||||
|
||||
new_points = (DELTA_POINT*) realloc(polyline->points, sizeof(DELTA_POINT) * new_num);
|
||||
if (!new_points)
|
||||
{
|
||||
WLog_ERR(TAG, "realloc(%i) failed", new_num);
|
||||
return FALSE;
|
||||
}
|
||||
polyline->points = new_points;
|
||||
polyline->numDeltaEntries = new_num;
|
||||
|
||||
@ -3139,14 +3160,20 @@ BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags)
|
||||
|
||||
if (!update_read_field_flags(s, &(orderInfo->fieldFlags), flags,
|
||||
PRIMARY_DRAWING_ORDER_FIELD_BYTES[orderInfo->orderType]))
|
||||
{
|
||||
WLog_ERR(TAG, "update_read_field_flags() failed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (flags & ORDER_BOUNDS)
|
||||
{
|
||||
if (!(flags & ORDER_ZERO_BOUNDS_DELTAS))
|
||||
{
|
||||
if (!update_read_bounds(s, &orderInfo->bounds))
|
||||
{
|
||||
WLog_ERR(TAG, "update_read_bounds() failed");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
IFCALL(update->SetBounds, context, &orderInfo->bounds);
|
||||
@ -3162,154 +3189,220 @@ BOOL update_recv_primary_order(rdpUpdate* update, wStream* s, BYTE flags)
|
||||
{
|
||||
case ORDER_TYPE_DSTBLT:
|
||||
if (!update_read_dstblt_order(s, orderInfo, &(primary->dstblt)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_DSTBLT - update_read_dstblt_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "DstBlt");
|
||||
IFCALL(primary->DstBlt, context, &primary->dstblt);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_PATBLT:
|
||||
if (!update_read_patblt_order(s, orderInfo, &(primary->patblt)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_PATBLT - update_read_patblt_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "PatBlt");
|
||||
IFCALL(primary->PatBlt, context, &primary->patblt);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_SCRBLT:
|
||||
if (!update_read_scrblt_order(s, orderInfo, &(primary->scrblt)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_SCRBLT - update_read_scrblt_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "ScrBlt");
|
||||
IFCALL(primary->ScrBlt, context, &primary->scrblt);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_OPAQUE_RECT:
|
||||
if (!update_read_opaque_rect_order(s, orderInfo, &(primary->opaque_rect)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_OPAQUE_RECT - update_read_opaque_rect_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "OpaqueRect");
|
||||
IFCALL(primary->OpaqueRect, context, &primary->opaque_rect);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_DRAW_NINE_GRID:
|
||||
if (!update_read_draw_nine_grid_order(s, orderInfo, &(primary->draw_nine_grid)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_DRAW_NINE_GRID - update_read_draw_nine_grid_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "DrawNineGrid");
|
||||
IFCALL(primary->DrawNineGrid, context, &primary->draw_nine_grid);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_MULTI_DSTBLT:
|
||||
if (!update_read_multi_dstblt_order(s, orderInfo, &(primary->multi_dstblt)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_MULTI_DSTBLT - update_read_multi_dstblt_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "MultiDstBlt");
|
||||
IFCALL(primary->MultiDstBlt, context, &primary->multi_dstblt);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_MULTI_PATBLT:
|
||||
if (!update_read_multi_patblt_order(s, orderInfo, &(primary->multi_patblt)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_MULTI_PATBLT - update_read_multi_patblt_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "MultiPatBlt");
|
||||
IFCALL(primary->MultiPatBlt, context, &primary->multi_patblt);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_MULTI_SCRBLT:
|
||||
if (!update_read_multi_scrblt_order(s, orderInfo, &(primary->multi_scrblt)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_MULTI_SCRBLT - update_read_multi_scrblt_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "MultiScrBlt");
|
||||
IFCALL(primary->MultiScrBlt, context, &primary->multi_scrblt);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_MULTI_OPAQUE_RECT:
|
||||
if (!update_read_multi_opaque_rect_order(s, orderInfo, &(primary->multi_opaque_rect)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_MULTI_OPAQUE_RECT - update_read_multi_opaque_rect_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "MultiOpaqueRect");
|
||||
IFCALL(primary->MultiOpaqueRect, context, &primary->multi_opaque_rect);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_MULTI_DRAW_NINE_GRID:
|
||||
if (!update_read_multi_draw_nine_grid_order(s, orderInfo, &(primary->multi_draw_nine_grid)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_MULTI_DRAW_NINE_GRID - update_read_multi_draw_nine_grid_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "MultiDrawNineGrid");
|
||||
IFCALL(primary->MultiDrawNineGrid, context, &primary->multi_draw_nine_grid);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_LINE_TO:
|
||||
if (!update_read_line_to_order(s, orderInfo, &(primary->line_to)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_LINE_TO - update_read_line_to_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "LineTo");
|
||||
IFCALL(primary->LineTo, context, &primary->line_to);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_POLYLINE:
|
||||
if (!update_read_polyline_order(s, orderInfo, &(primary->polyline)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_POLYLINE - update_read_polyline_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "Polyline");
|
||||
IFCALL(primary->Polyline, context, &primary->polyline);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_MEMBLT:
|
||||
if (!update_read_memblt_order(s, orderInfo, &(primary->memblt)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_MEMBLT - update_read_memblt_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "MemBlt");
|
||||
IFCALL(primary->MemBlt, context, &primary->memblt);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_MEM3BLT:
|
||||
if (!update_read_mem3blt_order(s, orderInfo, &(primary->mem3blt)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_MEM3BLT - update_read_mem3blt_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "Mem3Blt");
|
||||
IFCALL(primary->Mem3Blt, context, &primary->mem3blt);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_SAVE_BITMAP:
|
||||
if (!update_read_save_bitmap_order(s, orderInfo, &(primary->save_bitmap)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_SAVE_BITMAP - update_read_save_bitmap_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "SaveBitmap");
|
||||
IFCALL(primary->SaveBitmap, context, &primary->save_bitmap);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_GLYPH_INDEX:
|
||||
if (!update_read_glyph_index_order(s, orderInfo, &(primary->glyph_index)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_GLYPH_INDEX - update_read_glyph_index_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "GlyphIndex");
|
||||
IFCALL(primary->GlyphIndex, context, &primary->glyph_index);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_FAST_INDEX:
|
||||
if (!update_read_fast_index_order(s, orderInfo, &(primary->fast_index)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_FAST_INDEX - update_read_fast_index_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "FastIndex");
|
||||
IFCALL(primary->FastIndex, context, &primary->fast_index);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_FAST_GLYPH:
|
||||
if (!update_read_fast_glyph_order(s, orderInfo, &(primary->fast_glyph)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_FAST_GLYPH - update_read_fast_glyph_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "FastGlyph");
|
||||
IFCALL(primary->FastGlyph, context, &primary->fast_glyph);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_POLYGON_SC:
|
||||
if (!update_read_polygon_sc_order(s, orderInfo, &(primary->polygon_sc)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_POLYGON_SC - update_read_polygon_sc_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "PolygonSC");
|
||||
IFCALL(primary->PolygonSC, context, &primary->polygon_sc);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_POLYGON_CB:
|
||||
if (!update_read_polygon_cb_order(s, orderInfo, &(primary->polygon_cb)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_POLYGON_CB - update_read_polygon_cb_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "PolygonCB");
|
||||
IFCALL(primary->PolygonCB, context, &primary->polygon_cb);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_ELLIPSE_SC:
|
||||
if (!update_read_ellipse_sc_order(s, orderInfo, &(primary->ellipse_sc)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_ELLIPSE_SC - update_read_ellipse_sc_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "EllipseSC");
|
||||
IFCALL(primary->EllipseSC, context, &primary->ellipse_sc);
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_ELLIPSE_CB:
|
||||
if (!update_read_ellipse_cb_order(s, orderInfo, &(primary->ellipse_cb)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_ELLIPSE_CB - update_read_ellipse_cb_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "EllipseCB");
|
||||
IFCALL(primary->EllipseCB, context, &primary->ellipse_cb);
|
||||
break;
|
||||
@ -3336,7 +3429,10 @@ BOOL update_recv_secondary_order(rdpUpdate* update, wStream* s, BYTE flags)
|
||||
rdpSecondaryUpdate* secondary = update->secondary;
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 5)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_GetRemainingLength(s) < 5");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Stream_Read_UINT16(s, orderLength); /* orderLength (2 bytes) */
|
||||
Stream_Read_UINT16(s, extraFlags); /* extraFlags (2 bytes) */
|
||||
@ -3355,42 +3451,60 @@ BOOL update_recv_secondary_order(rdpUpdate* update, wStream* s, BYTE flags)
|
||||
{
|
||||
case ORDER_TYPE_BITMAP_UNCOMPRESSED:
|
||||
if (!update_read_cache_bitmap_order(s, &(secondary->cache_bitmap_order), FALSE, extraFlags))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_BITMAP_UNCOMPRESSED - update_read_cache_bitmap_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "CacheBitmapUncompressed");
|
||||
IFCALL(secondary->CacheBitmap, context, &(secondary->cache_bitmap_order));
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_CACHE_BITMAP_COMPRESSED:
|
||||
if (!update_read_cache_bitmap_order(s, &(secondary->cache_bitmap_order), TRUE, extraFlags))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_CACHE_BITMAP_COMPRESSED - update_read_cache_bitmap_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "CacheBitmapCompressed");
|
||||
IFCALL(secondary->CacheBitmap, context, &(secondary->cache_bitmap_order));
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_BITMAP_UNCOMPRESSED_V2:
|
||||
if (!update_read_cache_bitmap_v2_order(s, &(secondary->cache_bitmap_v2_order), FALSE, extraFlags))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_BITMAP_UNCOMPRESSED_V2 - update_read_cache_bitmap_v2_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "CacheBitmapUncompressedV2");
|
||||
IFCALL(secondary->CacheBitmapV2, context, &(secondary->cache_bitmap_v2_order));
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_BITMAP_COMPRESSED_V2:
|
||||
if (!update_read_cache_bitmap_v2_order(s, &(secondary->cache_bitmap_v2_order), TRUE, extraFlags))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_BITMAP_COMPRESSED_V2 - update_read_cache_bitmap_v2_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "CacheBitmapCompressedV2");
|
||||
IFCALL(secondary->CacheBitmapV2, context, &(secondary->cache_bitmap_v2_order));
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_BITMAP_COMPRESSED_V3:
|
||||
if (!update_read_cache_bitmap_v3_order(s, &(secondary->cache_bitmap_v3_order), extraFlags))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_BITMAP_COMPRESSED_V3 - update_read_cache_bitmap_v3_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "CacheBitmapCompressedV3");
|
||||
IFCALL(secondary->CacheBitmapV3, context, &(secondary->cache_bitmap_v3_order));
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_CACHE_COLOR_TABLE:
|
||||
if (!update_read_cache_color_table_order(s, &(secondary->cache_color_table_order), extraFlags))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_CACHE_COLOR_TABLE - update_read_cache_color_table_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "CacheColorTable");
|
||||
IFCALL(secondary->CacheColorTable, context, &(secondary->cache_color_table_order));
|
||||
break;
|
||||
@ -3399,14 +3513,20 @@ BOOL update_recv_secondary_order(rdpUpdate* update, wStream* s, BYTE flags)
|
||||
if (secondary->glyph_v2)
|
||||
{
|
||||
if (!update_read_cache_glyph_v2_order(s, &(secondary->cache_glyph_v2_order), extraFlags))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_CACHE_GLYPH - update_read_cache_glyph_v2_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "CacheGlyphV2");
|
||||
IFCALL(secondary->CacheGlyphV2, context, &(secondary->cache_glyph_v2_order));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!update_read_cache_glyph_order(s, &(secondary->cache_glyph_order), extraFlags))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_CACHE_GLYPH - update_read_cache_glyph_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "CacheGlyph");
|
||||
IFCALL(secondary->CacheGlyph, context, &(secondary->cache_glyph_order));
|
||||
}
|
||||
@ -3414,7 +3534,10 @@ BOOL update_recv_secondary_order(rdpUpdate* update, wStream* s, BYTE flags)
|
||||
|
||||
case ORDER_TYPE_CACHE_BRUSH:
|
||||
if (!update_read_cache_brush_order(s, &(secondary->cache_brush_order), extraFlags))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_CACHE_BRUSH - update_read_cache_brush_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "CacheBrush");
|
||||
IFCALL(secondary->CacheBrush, context, &(secondary->cache_brush_order));
|
||||
break;
|
||||
@ -3438,37 +3561,49 @@ BOOL update_recv_altsec_order(rdpUpdate* update, wStream* s, BYTE flags)
|
||||
|
||||
#ifdef WITH_DEBUG_ORDERS
|
||||
if (orderType < ALTSEC_DRAWING_ORDER_COUNT)
|
||||
WLog_DBG(TAG, "%s Alternate Secondary Drawing Order (0x%02X)", ALTSEC_DRAWING_ORDER_STRINGS[orderType], orderType);
|
||||
WLog_DBG(TAG, "%s Alternate Secondary Drawing Order (0x%02X)", ALTSEC_DRAWING_ORDER_STRINGS[orderType], orderType);
|
||||
else
|
||||
WLog_DBG(TAG, "Unknown Alternate Secondary Drawing Order: 0x%02X", orderType);
|
||||
WLog_DBG(TAG, "Unknown Alternate Secondary Drawing Order: 0x%02X", orderType);
|
||||
#endif
|
||||
|
||||
switch (orderType)
|
||||
{
|
||||
case ORDER_TYPE_CREATE_OFFSCREEN_BITMAP:
|
||||
if (!update_read_create_offscreen_bitmap_order(s, &(altsec->create_offscreen_bitmap)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_CREATE_OFFSCREEN_BITMAP - update_read_create_offscreen_bitmap_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "CreateOffscreenBitmap");
|
||||
IFCALL(altsec->CreateOffscreenBitmap, context, &(altsec->create_offscreen_bitmap));
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_SWITCH_SURFACE:
|
||||
if (!update_read_switch_surface_order(s, &(altsec->switch_surface)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_SWITCH_SURFACE - update_read_switch_surface_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "SwitchSurface");
|
||||
IFCALL(altsec->SwitchSurface, context, &(altsec->switch_surface));
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_CREATE_NINE_GRID_BITMAP:
|
||||
if (!update_read_create_nine_grid_bitmap_order(s, &(altsec->create_nine_grid_bitmap)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_CREATE_NINE_GRID_BITMAP - update_read_create_nine_grid_bitmap_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "CreateNineGridBitmap");
|
||||
IFCALL(altsec->CreateNineGridBitmap, context, &(altsec->create_nine_grid_bitmap));
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_FRAME_MARKER:
|
||||
if (!update_read_frame_marker_order(s, &(altsec->frame_marker)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_FRAME_MARKER - update_read_frame_marker_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "AltSecFrameMarker: action: %s (%d)",
|
||||
(!altsec->frame_marker.action) ? "Begin" : "End", altsec->frame_marker.action);
|
||||
IFCALL(altsec->FrameMarker, context, &(altsec->frame_marker));
|
||||
@ -3476,56 +3611,80 @@ BOOL update_recv_altsec_order(rdpUpdate* update, wStream* s, BYTE flags)
|
||||
|
||||
case ORDER_TYPE_STREAM_BITMAP_FIRST:
|
||||
if (!update_read_stream_bitmap_first_order(s, &(altsec->stream_bitmap_first)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_STREAM_BITMAP_FIRST - update_read_stream_bitmap_first_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "StreamBitmapFirst");
|
||||
IFCALL(altsec->StreamBitmapFirst, context, &(altsec->stream_bitmap_first));
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_STREAM_BITMAP_NEXT:
|
||||
if (!update_read_stream_bitmap_next_order(s, &(altsec->stream_bitmap_next)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_STREAM_BITMAP_NEXT - update_read_stream_bitmap_next_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "StreamBitmapNext");
|
||||
IFCALL(altsec->StreamBitmapNext, context, &(altsec->stream_bitmap_next));
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_GDIPLUS_FIRST:
|
||||
if (!update_read_draw_gdiplus_first_order(s, &(altsec->draw_gdiplus_first)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_GDIPLUS_FIRST - update_read_draw_gdiplus_first_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "DrawGdiPlusFirst");
|
||||
IFCALL(altsec->DrawGdiPlusFirst, context, &(altsec->draw_gdiplus_first));
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_GDIPLUS_NEXT:
|
||||
if (!update_read_draw_gdiplus_next_order(s, &(altsec->draw_gdiplus_next)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_GDIPLUS_NEXT - update_read_draw_gdiplus_next_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "DrawGdiPlusNext");
|
||||
IFCALL(altsec->DrawGdiPlusNext, context, &(altsec->draw_gdiplus_next));
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_GDIPLUS_END:
|
||||
if (update_read_draw_gdiplus_end_order(s, &(altsec->draw_gdiplus_end)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_GDIPLUS_END - update_read_draw_gdiplus_end_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "DrawGdiPlusEnd");
|
||||
IFCALL(altsec->DrawGdiPlusEnd, context, &(altsec->draw_gdiplus_end));
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_GDIPLUS_CACHE_FIRST:
|
||||
if (!update_read_draw_gdiplus_cache_first_order(s, &(altsec->draw_gdiplus_cache_first)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_GDIPLUS_CACHE_FIRST - update_read_draw_gdiplus_cache_first_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "DrawGdiPlusCacheFirst");
|
||||
IFCALL(altsec->DrawGdiPlusCacheFirst, context, &(altsec->draw_gdiplus_cache_first));
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_GDIPLUS_CACHE_NEXT:
|
||||
if (!update_read_draw_gdiplus_cache_next_order(s, &(altsec->draw_gdiplus_cache_next)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_GDIPLUS_CACHE_NEXT - update_read_draw_gdiplus_cache_next_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "DrawGdiPlusCacheNext");
|
||||
IFCALL(altsec->DrawGdiPlusCacheNext, context, &(altsec->draw_gdiplus_cache_next));
|
||||
break;
|
||||
|
||||
case ORDER_TYPE_GDIPLUS_CACHE_END:
|
||||
if (!update_read_draw_gdiplus_cache_end_order(s, &(altsec->draw_gdiplus_cache_end)))
|
||||
{
|
||||
WLog_ERR(TAG, "ORDER_TYPE_GDIPLUS_CACHE_END - update_read_draw_gdiplus_cache_end_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
WLog_Print(update->log, WLOG_DEBUG, "DrawGdiPlusCacheEnd");
|
||||
IFCALL(altsec->DrawGdiPlusCacheEnd, context, &(altsec->draw_gdiplus_cache_end));
|
||||
break;
|
||||
@ -3548,7 +3707,10 @@ BOOL update_recv_order(rdpUpdate* update, wStream* s)
|
||||
BYTE controlFlags;
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 1)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_GetRemainingLength(s) < 1");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Stream_Read_UINT8(s, controlFlags); /* controlFlags (1 byte) */
|
||||
|
||||
|
@ -331,7 +331,7 @@ static BOOL peer_recv_data_pdu(freerdp_peer* client, wStream* s)
|
||||
break;
|
||||
|
||||
default:
|
||||
WLog_ERR(TAG, "Data PDU type %d", type);
|
||||
WLog_ERR(TAG, "Data PDU type %d", type);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -352,7 +352,7 @@ static int peer_recv_tpkt_pdu(freerdp_peer* client, wStream* s)
|
||||
|
||||
if (!rdp_read_header(rdp, s, &length, &channelId))
|
||||
{
|
||||
WLog_ERR(TAG, "Incorrect RDP header.");
|
||||
WLog_ERR(TAG, "Incorrect RDP header.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -368,7 +368,7 @@ static int peer_recv_tpkt_pdu(freerdp_peer* client, wStream* s)
|
||||
{
|
||||
if (!rdp_decrypt(rdp, s, length - 4, securityFlags))
|
||||
{
|
||||
WLog_ERR(TAG, "rdp_decrypt failed");
|
||||
WLog_ERR(TAG, "rdp_decrypt failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -399,7 +399,7 @@ static int peer_recv_tpkt_pdu(freerdp_peer* client, wStream* s)
|
||||
break;
|
||||
|
||||
default:
|
||||
WLog_ERR(TAG, "Client sent pduType %d", pduType);
|
||||
WLog_ERR(TAG, "Client sent pduType %d", pduType);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -433,7 +433,7 @@ static int peer_recv_fastpath_pdu(freerdp_peer* client, wStream* s)
|
||||
|
||||
if ((length == 0) || (length > Stream_GetRemainingLength(s)))
|
||||
{
|
||||
WLog_ERR(TAG, "incorrect FastPath PDU header length %d", length);
|
||||
WLog_ERR(TAG, "incorrect FastPath PDU header length %d", length);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -463,7 +463,10 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
{
|
||||
case CONNECTION_STATE_INITIAL:
|
||||
if (!rdp_server_accept_nego(rdp, s))
|
||||
{
|
||||
WLog_ERR(TAG, "peer_recv_callback: CONNECTION_STATE_INITIAL - rdp_server_accept_nego() fail");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rdp->nego->SelectedProtocol & PROTOCOL_NLA)
|
||||
{
|
||||
@ -481,29 +484,44 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
|
||||
case CONNECTION_STATE_NEGO:
|
||||
if (!rdp_server_accept_mcs_connect_initial(rdp, s))
|
||||
{
|
||||
WLog_ERR(TAG, "peer_recv_callback: CONNECTION_STATE_NEGO - rdp_server_accept_mcs_connect_initial() fail");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_MCS_CONNECT:
|
||||
if (!rdp_server_accept_mcs_erect_domain_request(rdp, s))
|
||||
{
|
||||
WLog_ERR(TAG, "peer_recv_callback: CONNECTION_STATE_MCS_CONNECT - rdp_server_accept_mcs_erect_domain_request() fail");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_MCS_ERECT_DOMAIN:
|
||||
if (!rdp_server_accept_mcs_attach_user_request(rdp, s))
|
||||
{
|
||||
WLog_ERR(TAG, "peer_recv_callback: CONNECTION_STATE_MCS_ERECT_DOMAIN - rdp_server_accept_mcs_attach_user_request() fail");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_MCS_ATTACH_USER:
|
||||
if (!rdp_server_accept_mcs_channel_join_request(rdp, s))
|
||||
{
|
||||
WLog_ERR(TAG, "peer_recv_callback: CONNECTION_STATE_MCS_ATTACH_USER - rdp_server_accept_mcs_channel_join_request() fail");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_RDP_SECURITY_COMMENCEMENT:
|
||||
if (rdp->settings->UseRdpSecurityLayer)
|
||||
{
|
||||
if (!rdp_server_establish_keys(rdp, s))
|
||||
{
|
||||
WLog_ERR(TAG, "peer_recv_callback: CONNECTION_STATE_RDP_SECURITY_COMMENCEMENT - rdp_server_establish_keys() fail");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE);
|
||||
@ -512,9 +530,11 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE:
|
||||
|
||||
if (!rdp_recv_client_info(rdp, s))
|
||||
{
|
||||
WLog_ERR(TAG, "peer_recv_callback: CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE - rdp_recv_client_info() fail");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_LICENSING);
|
||||
return peer_recv_callback(transport, NULL, extra);
|
||||
@ -522,9 +542,11 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_LICENSING:
|
||||
|
||||
if (!license_send_valid_client_error_packet(rdp->license))
|
||||
{
|
||||
WLog_ERR(TAG, "peer_recv_callback: CONNECTION_STATE_LICENSING - license_send_valid_client_error_packet() fail");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE);
|
||||
return peer_recv_callback(transport, NULL, extra);
|
||||
@ -538,14 +560,20 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
IFCALL(client->Capabilities, client);
|
||||
|
||||
if (!rdp_send_demand_active(rdp))
|
||||
{
|
||||
WLog_ERR(TAG, "peer_recv_callback: CONNECTION_STATE_CAPABILITIES_EXCHANGE - rdp_send_demand_active() fail");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rdp->AwaitCapabilities = TRUE;
|
||||
|
||||
if (s)
|
||||
{
|
||||
if (peer_recv_pdu(client, s) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "peer_recv_callback: CONNECTION_STATE_CAPABILITIES_EXCHANGE - peer_recv_pdu() fail");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -556,23 +584,32 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
*/
|
||||
|
||||
if (peer_recv_pdu(client, s) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "peer_recv_callback: CONNECTION_STATE_CAPABILITIES_EXCHANGE - peer_recv_pdu() fail");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_FINALIZATION:
|
||||
if (peer_recv_pdu(client, s) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "peer_recv_callback: CONNECTION_STATE_FINALIZATION - peer_recv_pdu() fail");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_ACTIVE:
|
||||
if (peer_recv_pdu(client, s) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "peer_recv_callback: CONNECTION_STATE_ACTIVE - peer_recv_pdu() fail");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
WLog_ERR(TAG, "Invalid state %d", rdp->state);
|
||||
WLog_ERR(TAG, "Invalid state %d", rdp->state);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -768,7 +768,10 @@ int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s)
|
||||
UINT16 compressedLength;
|
||||
|
||||
if (!rdp_read_share_data_header(s, &length, &type, &shareId, &compressedType, &compressedLength))
|
||||
{
|
||||
WLog_ERR(TAG, "rdp_read_share_data_header() failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cs = s;
|
||||
|
||||
@ -815,72 +818,114 @@ int rdp_recv_data_pdu(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
case DATA_PDU_TYPE_UPDATE:
|
||||
if (!update_recv(rdp->update, cs))
|
||||
{
|
||||
WLog_ERR(TAG, "DATA_PDU_TYPE_UPDATE - update_recv() failed");
|
||||
goto out_fail;
|
||||
}
|
||||
break;
|
||||
|
||||
case DATA_PDU_TYPE_CONTROL:
|
||||
if (!rdp_recv_server_control_pdu(rdp, cs))
|
||||
{
|
||||
WLog_ERR(TAG, "DATA_PDU_TYPE_CONTROL - rdp_recv_server_control_pdu() failed");
|
||||
goto out_fail;
|
||||
}
|
||||
break;
|
||||
|
||||
case DATA_PDU_TYPE_POINTER:
|
||||
if (!update_recv_pointer(rdp->update, cs))
|
||||
{
|
||||
WLog_ERR(TAG, "DATA_PDU_TYPE_POINTER - update_recv_pointer() failed");
|
||||
goto out_fail;
|
||||
}
|
||||
break;
|
||||
|
||||
case DATA_PDU_TYPE_SYNCHRONIZE:
|
||||
if (!rdp_recv_synchronize_pdu(rdp, cs))
|
||||
{
|
||||
WLog_ERR(TAG, "DATA_PDU_TYPE_SYNCHRONIZE - rdp_recv_synchronize_pdu() failed");
|
||||
goto out_fail;
|
||||
}
|
||||
break;
|
||||
|
||||
case DATA_PDU_TYPE_PLAY_SOUND:
|
||||
if (!update_recv_play_sound(rdp->update, cs))
|
||||
{
|
||||
WLog_ERR(TAG, "DATA_PDU_TYPE_PLAY_SOUND - update_recv_play_sound() failed");
|
||||
goto out_fail;
|
||||
}
|
||||
break;
|
||||
|
||||
case DATA_PDU_TYPE_SHUTDOWN_DENIED:
|
||||
if (!rdp_recv_server_shutdown_denied_pdu(rdp, cs))
|
||||
{
|
||||
WLog_ERR(TAG, "DATA_PDU_TYPE_SHUTDOWN_DENIED - rdp_recv_server_shutdown_denied_pdu() failed");
|
||||
goto out_fail;
|
||||
}
|
||||
break;
|
||||
|
||||
case DATA_PDU_TYPE_SAVE_SESSION_INFO:
|
||||
if (!rdp_recv_save_session_info(rdp, cs))
|
||||
{
|
||||
WLog_ERR(TAG, "DATA_PDU_TYPE_SAVE_SESSION_INFO - rdp_recv_save_session_info() failed");
|
||||
goto out_fail;
|
||||
}
|
||||
break;
|
||||
|
||||
case DATA_PDU_TYPE_FONT_MAP:
|
||||
if (!rdp_recv_font_map_pdu(rdp, cs))
|
||||
{
|
||||
WLog_ERR(TAG, "DATA_PDU_TYPE_FONT_MAP - rdp_recv_font_map_pdu() failed");
|
||||
goto out_fail;
|
||||
}
|
||||
break;
|
||||
|
||||
case DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS:
|
||||
if (!rdp_recv_server_set_keyboard_indicators_pdu(rdp, cs))
|
||||
{
|
||||
WLog_ERR(TAG, "DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS - rdp_recv_server_set_keyboard_indicators_pdu() failed");
|
||||
goto out_fail;
|
||||
}
|
||||
break;
|
||||
|
||||
case DATA_PDU_TYPE_SET_KEYBOARD_IME_STATUS:
|
||||
if (!rdp_recv_server_set_keyboard_ime_status_pdu(rdp, cs))
|
||||
{
|
||||
WLog_ERR(TAG, "DATA_PDU_TYPE_SET_KEYBOARD_IME_STATUS - rdp_recv_server_set_keyboard_ime_status_pdu() failed");
|
||||
goto out_fail;
|
||||
}
|
||||
break;
|
||||
|
||||
case DATA_PDU_TYPE_SET_ERROR_INFO:
|
||||
if (!rdp_recv_set_error_info_data_pdu(rdp, cs))
|
||||
{
|
||||
WLog_ERR(TAG, "DATA_PDU_TYPE_SET_ERROR_INFO - rdp_recv_set_error_info_data_pdu() failed");
|
||||
goto out_fail;
|
||||
}
|
||||
break;
|
||||
|
||||
case DATA_PDU_TYPE_ARC_STATUS:
|
||||
if (!rdp_recv_server_auto_reconnect_status_pdu(rdp, cs))
|
||||
{
|
||||
WLog_ERR(TAG, "DATA_PDU_TYPE_ARC_STATUS - rdp_recv_server_auto_reconnect_status_pdu() failed");
|
||||
goto out_fail;
|
||||
}
|
||||
break;
|
||||
|
||||
case DATA_PDU_TYPE_STATUS_INFO:
|
||||
if (!rdp_recv_server_status_info_pdu(rdp, cs))
|
||||
{
|
||||
WLog_ERR(TAG, "DATA_PDU_TYPE_STATUS_INFO - rdp_recv_server_status_info_pdu() failed");
|
||||
goto out_fail;
|
||||
}
|
||||
break;
|
||||
|
||||
case DATA_PDU_TYPE_MONITOR_LAYOUT:
|
||||
if (!rdp_recv_monitor_layout_pdu(rdp, cs))
|
||||
{
|
||||
WLog_ERR(TAG, "DATA_PDU_TYPE_MONITOR_LAYOUT - rdp_recv_monitor_layout_pdu() failed");
|
||||
goto out_fail;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1087,7 +1132,10 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
|
||||
if (rdp->settings->UseRdpSecurityLayer)
|
||||
{
|
||||
if (!rdp_read_security_header(s, &securityFlags))
|
||||
{
|
||||
WLog_ERR(TAG, "rdp_recv_tpkt_pdu: rdp_read_security_header() fail");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (securityFlags & (SEC_ENCRYPT | SEC_REDIRECTION_PKT))
|
||||
{
|
||||
@ -1117,7 +1165,10 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
|
||||
nextPosition = Stream_GetPosition(s);
|
||||
|
||||
if (!rdp_read_share_control_header(s, &pduLength, &pduType, &pduSource))
|
||||
{
|
||||
WLog_ERR(TAG, "rdp_recv_tpkt_pdu: rdp_read_share_control_header() fail");
|
||||
return -1;
|
||||
}
|
||||
|
||||
nextPosition += pduLength;
|
||||
|
||||
@ -1128,14 +1179,17 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
|
||||
case PDU_TYPE_DATA:
|
||||
if (rdp_recv_data_pdu(rdp, s) < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "rdp_recv_data_pdu failed");
|
||||
WLog_ERR(TAG, "rdp_recv_data_pdu() failed");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case PDU_TYPE_DEACTIVATE_ALL:
|
||||
if (!rdp_recv_deactivate_all(rdp, s))
|
||||
{
|
||||
WLog_ERR(TAG, "rdp_recv_tpkt_pdu: rdp_recv_deactivate_all() fail");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case PDU_TYPE_SERVER_REDIRECTION:
|
||||
@ -1166,7 +1220,10 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
|
||||
else
|
||||
{
|
||||
if (!freerdp_channel_process(rdp->instance, s, channelId))
|
||||
{
|
||||
WLog_ERR(TAG, "rdp_recv_tpkt_pdu: freerdp_channel_process() fail");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1180,7 +1237,10 @@ static int rdp_recv_fastpath_pdu(rdpRdp* rdp, wStream* s)
|
||||
fastpath = rdp->fastpath;
|
||||
|
||||
if (!fastpath_read_header_rdp(fastpath, s, &length))
|
||||
{
|
||||
WLog_ERR(TAG, "rdp_recv_fastpath_pdu: fastpath_read_header_rdp() fail");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((length == 0) || (length > Stream_GetRemainingLength(s)))
|
||||
{
|
||||
@ -1198,7 +1258,10 @@ static int rdp_recv_fastpath_pdu(rdpRdp* rdp, wStream* s)
|
||||
UINT16 flags = (fastpath->encryptionFlags & FASTPATH_OUTPUT_SECURE_CHECKSUM) ? SEC_SECURE_CHECKSUM : 0;
|
||||
|
||||
if (!rdp_decrypt(rdp, s, length, flags))
|
||||
{
|
||||
WLog_ERR(TAG, "rdp_recv_fastpath_pdu: rdp_decrypt() fail");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return fastpath_recv_updates(rdp->fastpath, s);
|
||||
@ -1233,7 +1296,10 @@ int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
{
|
||||
case CONNECTION_STATE_NLA:
|
||||
if (nla_recv_pdu(rdp->nla, s) < 1)
|
||||
{
|
||||
WLog_ERR(TAG, "rdp_recv_callback: CONNECTION_STATE_NLA - nla_recv_pdu() fail");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rdp->nla->state == NLA_STATE_AUTH_INFO)
|
||||
{
|
||||
@ -1243,7 +1309,10 @@ int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
rdp->nla = NULL;
|
||||
|
||||
if (!mcs_client_begin(rdp->mcs))
|
||||
{
|
||||
WLog_ERR(TAG, "rdp_recv_callback: CONNECTION_STATE_NLA - mcs_client_begin() fail");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
@ -1288,15 +1357,22 @@ int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
|
||||
case CONNECTION_STATE_MCS_CHANNEL_JOIN:
|
||||
if (!rdp_client_connect_mcs_channel_join_confirm(rdp, s))
|
||||
{
|
||||
WLog_ERR(TAG, "rdp_recv_callback: CONNECTION_STATE_MCS_CHANNEL_JOIN - rdp_client_connect_mcs_channel_join_confirm() fail");
|
||||
status = -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_LICENSING:
|
||||
status = rdp_client_connect_license(rdp, s);
|
||||
if (status < 0)
|
||||
WLog_DBG(TAG, "CONNECTION_STATE_LICENSING - rdp_client_connect_license() - %i", status);
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_CAPABILITIES_EXCHANGE:
|
||||
status = rdp_client_connect_demand_active(rdp, s);
|
||||
if (status < 0)
|
||||
WLog_DBG(TAG, "CONNECTION_STATE_CAPABILITIES_EXCHANGE - rdp_client_connect_demand_active() - %i", status);
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_FINALIZATION:
|
||||
@ -1307,10 +1383,14 @@ int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
rdp_client_transition_to_state(rdp, CONNECTION_STATE_ACTIVE);
|
||||
return 2;
|
||||
}
|
||||
if (status < 0)
|
||||
WLog_DBG(TAG, "CONNECTION_STATE_FINALIZATION - rdp_recv_pdu() - %i", status);
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_ACTIVE:
|
||||
status = rdp_recv_pdu(rdp, s);
|
||||
if (status < 0)
|
||||
WLog_DBG(TAG, "CONNECTION_STATE_ACTIVE - rdp_recv_pdu() - %i", status);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1356,7 +1436,10 @@ int rdp_check_fds(rdpRdp* rdp)
|
||||
status = tsg_check_event_handles(tsg);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "rdp_check_fds: tsg_check_event_handles() - %i", status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tsg->state != TSG_STATE_PIPE_CREATED)
|
||||
return status;
|
||||
@ -1368,6 +1451,8 @@ int rdp_check_fds(rdpRdp* rdp)
|
||||
{
|
||||
status = rdp_client_redirect(rdp); /* session redirection */
|
||||
}
|
||||
if (status < 0)
|
||||
WLog_DBG(TAG, "transport_check_fds() - %i", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -768,6 +768,9 @@ int transport_check_fds(rdpTransport* transport)
|
||||
*/
|
||||
if ((status = transport_read_pdu(transport, transport->ReceiveBuffer)) <= 0)
|
||||
{
|
||||
if (status < 0)
|
||||
WLog_DBG(TAG, "transport_check_fds: transport_read_pdu() - %i", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -790,7 +793,10 @@ int transport_check_fds(rdpTransport* transport)
|
||||
}
|
||||
|
||||
if (recv_status < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "transport_check_fds: transport->ReceiveCallback() - %i", recv_status);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -921,6 +927,7 @@ static void* transport_client_thread(void* arg)
|
||||
|
||||
if (transport->layer == TRANSPORT_LAYER_CLOSED)
|
||||
{
|
||||
WLog_DBG(TAG, "TRANSPORT_LAYER_CLOSED");
|
||||
rdp_set_error_info(rdp, ERRINFO_PEER_DISCONNECTED);
|
||||
break;
|
||||
}
|
||||
@ -934,6 +941,7 @@ static void* transport_client_thread(void* arg)
|
||||
{
|
||||
if (!freerdp_check_event_handles(context))
|
||||
{
|
||||
WLog_ERR(TAG, "freerdp_check_event_handles()");
|
||||
rdp_set_error_info(rdp, ERRINFO_PEER_DISCONNECTED);
|
||||
break;
|
||||
}
|
||||
|
@ -52,7 +52,10 @@ BOOL update_recv_orders(rdpUpdate* update, wStream* s)
|
||||
UINT16 numberOrders;
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 6)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_GetRemainingLength(s) < 6");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Stream_Seek_UINT16(s); /* pad2OctetsA (2 bytes) */
|
||||
Stream_Read_UINT16(s, numberOrders); /* numberOrders (2 bytes) */
|
||||
@ -61,7 +64,10 @@ BOOL update_recv_orders(rdpUpdate* update, wStream* s)
|
||||
while (numberOrders > 0)
|
||||
{
|
||||
if (!update_recv_order(update, s))
|
||||
{
|
||||
WLog_ERR(TAG, "update_recv_order() failed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
numberOrders--;
|
||||
}
|
||||
@ -488,7 +494,10 @@ BOOL update_recv(rdpUpdate* update, wStream* s)
|
||||
rdpContext* context = update->context;
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 2)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_GetRemainingLength(s) < 2");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Stream_Read_UINT16(s, updateType); /* updateType (2 bytes) */
|
||||
//WLog_DBG(TAG, "%s Update Data PDU", UPDATE_TYPE_STRINGS[updateType]);
|
||||
@ -501,19 +510,26 @@ BOOL update_recv(rdpUpdate* update, wStream* s)
|
||||
if (!update_recv_orders(update, s))
|
||||
{
|
||||
/* XXX: Do we have to call EndPaint? */
|
||||
WLog_ERR(TAG, "UPDATE_TYPE_ORDERS - update_recv_orders() failed");
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case UPDATE_TYPE_BITMAP:
|
||||
if (!update_read_bitmap_update(update, s, &update->bitmap_update))
|
||||
{
|
||||
WLog_ERR(TAG, "UPDATE_TYPE_BITMAP - update_read_bitmap_update() failed");
|
||||
return FALSE;
|
||||
}
|
||||
IFCALL(update->BitmapUpdate, context, &update->bitmap_update);
|
||||
break;
|
||||
|
||||
case UPDATE_TYPE_PALETTE:
|
||||
if (!update_read_palette(update, s, &update->palette_update))
|
||||
{
|
||||
WLog_ERR(TAG, "UPDATE_TYPE_PALETTE - update_read_palette() failed");
|
||||
return FALSE;
|
||||
}
|
||||
IFCALL(update->Palette, context, &update->palette_update);
|
||||
break;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user