Merge pull request #2719 from bmiklautz/pull/2481

OSS, tsmf, usb and BSD fixes and improvements
This commit is contained in:
Marc-André Moreau 2015-06-26 08:27:22 -04:00
commit ddf2519f1e
31 changed files with 1525 additions and 358 deletions

View File

@ -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")

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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()

View File

@ -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
{

View File

@ -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");

View 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)

View 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;
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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 */

View File

@ -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;

View File

@ -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"

View File

@ -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;
}

View File

@ -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;

View File

@ -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>

View File

@ -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");
}

View File

@ -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
View 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)

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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) */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;