mirror of
https://github.com/FreeRDP/FreeRDP.git
synced 2025-01-21 14:54:12 +08:00
commit
1565e032e5
@ -50,6 +50,7 @@ struct drdynvc_plugin
|
||||
int PriorityCharge1;
|
||||
int PriorityCharge2;
|
||||
int PriorityCharge3;
|
||||
int channel_error;
|
||||
|
||||
IWTSVirtualChannelManager* channel_mgr;
|
||||
};
|
||||
@ -70,7 +71,7 @@ static int drdynvc_write_variable_uint(STREAM* stream, uint32 val)
|
||||
}
|
||||
else
|
||||
{
|
||||
cb = 3;
|
||||
cb = 2;
|
||||
stream_write_uint32(stream, val);
|
||||
}
|
||||
return cb;
|
||||
@ -87,11 +88,22 @@ int drdynvc_write_data(drdynvcPlugin* drdynvc, uint32 ChannelId, uint8* data, ui
|
||||
|
||||
DEBUG_DVC("ChannelId=%d size=%d", ChannelId, data_size);
|
||||
|
||||
if (drdynvc->channel_error != CHANNEL_RC_OK)
|
||||
return 1;
|
||||
|
||||
data_out = stream_new(CHANNEL_CHUNK_LENGTH);
|
||||
stream_set_pos(data_out, 1);
|
||||
cbChId = drdynvc_write_variable_uint(data_out, ChannelId);
|
||||
|
||||
if (data_size <= CHANNEL_CHUNK_LENGTH - pos)
|
||||
if(data_size == 0)
|
||||
{
|
||||
pos = stream_get_pos(data_out);
|
||||
stream_set_pos(data_out, 0);
|
||||
stream_write_uint8(data_out, 0x40 | cbChId);
|
||||
stream_set_pos(data_out, pos);
|
||||
error = svc_plugin_send((rdpSvcPlugin*)drdynvc, data_out);
|
||||
}
|
||||
else if (data_size <= CHANNEL_CHUNK_LENGTH - pos)
|
||||
{
|
||||
pos = stream_get_pos(data_out);
|
||||
stream_set_pos(data_out, 0);
|
||||
@ -136,6 +148,7 @@ int drdynvc_write_data(drdynvcPlugin* drdynvc, uint32 ChannelId, uint8* data, ui
|
||||
}
|
||||
if (error != CHANNEL_RC_OK)
|
||||
{
|
||||
drdynvc->channel_error = error;
|
||||
DEBUG_WARN("VirtualChannelWrite failed %d", error);
|
||||
return 1;
|
||||
}
|
||||
@ -179,6 +192,8 @@ static int drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp, in
|
||||
DEBUG_WARN("VirtualChannelWrite failed %d", error);
|
||||
return 1;
|
||||
}
|
||||
drdynvc->channel_error = error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -326,6 +341,7 @@ static void drdynvc_process_connect(rdpSvcPlugin* plugin)
|
||||
DEBUG_DVC("connecting");
|
||||
|
||||
drdynvc->channel_mgr = dvcman_new(drdynvc);
|
||||
drdynvc->channel_error = 0;
|
||||
dvcman_load_plugin(drdynvc->channel_mgr, svc_plugin_get_data(plugin));
|
||||
dvcman_init(drdynvc->channel_mgr);
|
||||
}
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <freerdp/dvc.h>
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/utils/debug.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#ifdef WITH_DEBUG_DVC
|
||||
#define DEBUG_DVC(fmt, ...) DEBUG_CLASS(DVC, fmt, ## __VA_ARGS__)
|
||||
@ -35,3 +36,4 @@
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -83,6 +83,8 @@ struct _DVCMAN_CHANNEL
|
||||
IWTSVirtualChannelCallback* channel_callback;
|
||||
|
||||
STREAM* dvc_data;
|
||||
|
||||
pthread_mutex_t dvc_chan_mutex;
|
||||
};
|
||||
|
||||
static int dvcman_get_configuration(IWTSListener* pListener, void** ppPropertyBag)
|
||||
@ -179,6 +181,28 @@ RDP_PLUGIN_DATA* dvcman_get_plugin_data(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||
return ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->plugin_data;
|
||||
}
|
||||
|
||||
uint32 dvcman_get_channel_id(IWTSVirtualChannel * channel)
|
||||
{
|
||||
return ((DVCMAN_CHANNEL*)channel)->channel_id;
|
||||
}
|
||||
|
||||
IWTSVirtualChannel* dvcman_find_channel_by_id(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId)
|
||||
{
|
||||
LIST_ITEM* curr;
|
||||
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
|
||||
|
||||
for (curr = dvcman->channels->head; curr; curr = curr->next)
|
||||
{
|
||||
if (((DVCMAN_CHANNEL*) curr->data)->channel_id == ChannelId)
|
||||
{
|
||||
return (IWTSVirtualChannel*)curr->data;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
|
||||
{
|
||||
DVCMAN* dvcman;
|
||||
@ -186,6 +210,8 @@ IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
|
||||
dvcman = xnew(DVCMAN);
|
||||
dvcman->iface.CreateListener = dvcman_create_listener;
|
||||
dvcman->iface.PushEvent = dvcman_push_event;
|
||||
dvcman->iface.FindChannelById = dvcman_find_channel_by_id;
|
||||
dvcman->iface.GetChannelId = dvcman_get_channel_id;
|
||||
dvcman->drdynvc = plugin;
|
||||
dvcman->channels = list_new();
|
||||
|
||||
@ -276,8 +302,13 @@ int dvcman_init(IWTSVirtualChannelManager* pChannelMgr)
|
||||
static int dvcman_write_channel(IWTSVirtualChannel* pChannel, uint32 cbSize, uint8* pBuffer, void* pReserved)
|
||||
{
|
||||
DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) pChannel;
|
||||
int error;
|
||||
|
||||
return drdynvc_write_data(channel->dvcman->drdynvc, channel->channel_id, pBuffer, cbSize);
|
||||
pthread_mutex_lock(&channel->dvc_chan_mutex);
|
||||
error = drdynvc_write_data(channel->dvcman->drdynvc, channel->channel_id, pBuffer, cbSize);
|
||||
pthread_mutex_unlock(&channel->dvc_chan_mutex);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int dvcman_close_channel_iface(IWTSVirtualChannel* pChannel)
|
||||
@ -315,6 +346,7 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, uint32 Channel
|
||||
channel->iface.Close = dvcman_close_channel_iface;
|
||||
channel->dvcman = dvcman;
|
||||
channel->channel_id = ChannelId;
|
||||
pthread_mutex_init(&channel->dvc_chan_mutex, NULL);
|
||||
|
||||
bAccept = 1;
|
||||
pCallback = NULL;
|
||||
@ -341,28 +373,13 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, uint32 Channel
|
||||
return 1;
|
||||
}
|
||||
|
||||
static DVCMAN_CHANNEL* dvcman_find_channel_by_id(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId)
|
||||
{
|
||||
LIST_ITEM* curr;
|
||||
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
|
||||
|
||||
for (curr = dvcman->channels->head; curr; curr = curr->next)
|
||||
{
|
||||
if (((DVCMAN_CHANNEL*) curr->data)->channel_id == ChannelId)
|
||||
{
|
||||
return (DVCMAN_CHANNEL*)curr->data;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId)
|
||||
{
|
||||
DVCMAN_CHANNEL* channel;
|
||||
IWTSVirtualChannel* ichannel;
|
||||
|
||||
channel = dvcman_find_channel_by_id(pChannelMgr, ChannelId);
|
||||
channel = (DVCMAN_CHANNEL*)dvcman_find_channel_by_id(pChannelMgr, ChannelId);
|
||||
|
||||
if (channel == NULL)
|
||||
{
|
||||
@ -387,7 +404,7 @@ int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, ui
|
||||
{
|
||||
DVCMAN_CHANNEL* channel;
|
||||
|
||||
channel = dvcman_find_channel_by_id(pChannelMgr, ChannelId);
|
||||
channel = (DVCMAN_CHANNEL*)dvcman_find_channel_by_id(pChannelMgr, ChannelId);
|
||||
|
||||
if (channel == NULL)
|
||||
{
|
||||
@ -408,7 +425,7 @@ int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, uint32 C
|
||||
int error = 0;
|
||||
DVCMAN_CHANNEL* channel;
|
||||
|
||||
channel = dvcman_find_channel_by_id(pChannelMgr, ChannelId);
|
||||
channel = (DVCMAN_CHANNEL*)dvcman_find_channel_by_id(pChannelMgr, ChannelId);
|
||||
|
||||
if (channel == NULL)
|
||||
{
|
||||
|
@ -33,3 +33,4 @@ int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, ui
|
||||
int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId, uint8* data, uint32 data_size);
|
||||
|
||||
#endif
|
||||
|
||||
|
24
channels/urbdrc/CMakeLists.txt
Normal file
24
channels/urbdrc/CMakeLists.txt
Normal file
@ -0,0 +1,24 @@
|
||||
# FreeRDP: A Remote Desktop Protocol Client
|
||||
# FreeRDP cmake build script
|
||||
#
|
||||
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@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.
|
||||
|
||||
add_subdirectory(libusb)
|
||||
|
||||
if(WITH_CLIENT_CHANNELS)
|
||||
add_subdirectory(client)
|
||||
endif()
|
||||
|
||||
|
11
channels/urbdrc/ChannelOptions.cmake
Normal file
11
channels/urbdrc/ChannelOptions.cmake
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
set(CHANNEL_TYPE "dynamic")
|
||||
set(CHANNEL_SHORT_NAME "urbdrc")
|
||||
set(CHANNEL_LONG_NAME "USB Devices Virtual Channel Extension")
|
||||
set(CHANNEL_SPECIFICATIONS "[MS-RDPEUSB]")
|
||||
|
||||
string(TOUPPER "WITH_${CHANNEL_SHORT_NAME}" CHANNEL_OPTION)
|
||||
|
||||
option(${CHANNEL_OPTION} "Build ${CHANNEL_SHORT_NAME}" OFF)
|
||||
|
||||
|
42
channels/urbdrc/client/CMakeLists.txt
Normal file
42
channels/urbdrc/client/CMakeLists.txt
Normal file
@ -0,0 +1,42 @@
|
||||
# FreeRDP: A Remote Desktop Protocol Client
|
||||
# FreeRDP cmake build script
|
||||
#
|
||||
# Copyright 2012 Atrust corp.
|
||||
# Copyright 2012 Alfred Liu <alfred.liu@atruscorp.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set(URBDRC_SRCS
|
||||
searchman.c
|
||||
searchman.h
|
||||
isoch_queue.c
|
||||
isoch_queue.h
|
||||
data_transfer.c
|
||||
data_transfer.h
|
||||
urbdrc_main.c
|
||||
urbdrc_main.h
|
||||
urbdrc_types.h)
|
||||
|
||||
include_directories(..)
|
||||
|
||||
add_library(urbdrc ${URBDRC_SRCS})
|
||||
set_target_properties(urbdrc PROPERTIES PREFIX "")
|
||||
|
||||
target_link_libraries(urbdrc udev)
|
||||
target_link_libraries(urbdrc dbus-glib-1)
|
||||
target_link_libraries(urbdrc pthread)
|
||||
target_link_libraries(urbdrc uuid)
|
||||
target_link_libraries(urbdrc freerdp-utils)
|
||||
|
||||
install(TARGETS urbdrc DESTINATION ${FREERDP_PLUGIN_PATH})
|
||||
|
2450
channels/urbdrc/client/data_transfer.c
Normal file
2450
channels/urbdrc/client/data_transfer.c
Normal file
File diff suppressed because it is too large
Load Diff
41
channels/urbdrc/client/data_transfer.h
Normal file
41
channels/urbdrc/client/data_transfer.h
Normal file
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* RemoteFX USB Redirection
|
||||
*
|
||||
* Copyright 2012 Atrust corp.
|
||||
* Copyright 2012 Alfred Liu <alfred.liu@atruscorp.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __DATA_TRANSFER_H
|
||||
#define __DATA_TRANSFER_H
|
||||
|
||||
|
||||
#include "urbdrc_main.h"
|
||||
|
||||
|
||||
#define DEVICE_CTX(dev) ((dev)->ctx)
|
||||
#define HANDLE_CTX(handle) (DEVICE_CTX((handle)->dev))
|
||||
#define TRANSFER_CTX(transfer) (HANDLE_CTX((transfer)->dev_handle))
|
||||
#define ITRANSFER_CTX(transfer) \
|
||||
(TRANSFER_CTX(__USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer)))
|
||||
|
||||
|
||||
|
||||
void*
|
||||
urbdrc_process_udev_data_transfer(void* arg);
|
||||
|
||||
|
||||
#endif
|
||||
|
185
channels/urbdrc/client/isoch_queue.c
Normal file
185
channels/urbdrc/client/isoch_queue.c
Normal file
@ -0,0 +1,185 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* RemoteFX USB Redirection
|
||||
*
|
||||
* Copyright 2012 Atrust corp.
|
||||
* Copyright 2012 Alfred Liu <alfred.liu@atruscorp.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "isoch_queue.h"
|
||||
|
||||
static void isoch_queue_rewind(ISOCH_CALLBACK_QUEUE* queue)
|
||||
{
|
||||
queue->curr = queue->head;
|
||||
}
|
||||
|
||||
static int isoch_queue_has_next(ISOCH_CALLBACK_QUEUE* queue)
|
||||
{
|
||||
if (queue->curr == NULL)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static ISOCH_CALLBACK_DATA* isoch_queue_get_next(ISOCH_CALLBACK_QUEUE* queue)
|
||||
{
|
||||
ISOCH_CALLBACK_DATA* isoch;
|
||||
|
||||
isoch = queue->curr;
|
||||
queue->curr = (ISOCH_CALLBACK_DATA*)queue->curr->next;
|
||||
|
||||
return isoch;
|
||||
}
|
||||
|
||||
static ISOCH_CALLBACK_DATA* isoch_queue_register_data(ISOCH_CALLBACK_QUEUE* queue, void* callback, void* dev)
|
||||
{
|
||||
ISOCH_CALLBACK_DATA* isoch;
|
||||
|
||||
isoch = (ISOCH_CALLBACK_DATA*) malloc(sizeof(ISOCH_CALLBACK_DATA));
|
||||
|
||||
isoch->prev = NULL;
|
||||
isoch->next = NULL;
|
||||
|
||||
isoch->out_data = NULL;
|
||||
isoch->out_size = 0;
|
||||
isoch->device = dev;
|
||||
isoch->callback = callback;
|
||||
|
||||
pthread_mutex_lock(&queue->isoch_loading);
|
||||
|
||||
if (queue->head == NULL)
|
||||
{
|
||||
/* linked queue is empty */
|
||||
queue->head = isoch;
|
||||
queue->tail = isoch;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* append data to the end of the linked queue */
|
||||
queue->tail->next = (void*)isoch;
|
||||
isoch->prev = (void*)queue->tail;
|
||||
queue->tail = isoch;
|
||||
}
|
||||
queue->isoch_num += 1;
|
||||
|
||||
pthread_mutex_unlock(&queue->isoch_loading);
|
||||
|
||||
return isoch;
|
||||
}
|
||||
|
||||
static int isoch_queue_unregister_data(ISOCH_CALLBACK_QUEUE* queue, ISOCH_CALLBACK_DATA* isoch)
|
||||
{
|
||||
ISOCH_CALLBACK_DATA* p;
|
||||
|
||||
queue->rewind(queue);
|
||||
|
||||
while (queue->has_next(queue) != 0)
|
||||
{
|
||||
p = queue->get_next(queue);
|
||||
|
||||
if (p == isoch) /* data exists */
|
||||
{
|
||||
/* set previous data to point to next data */
|
||||
|
||||
if (isoch->prev != NULL)
|
||||
{
|
||||
/* unregistered data is not the head */
|
||||
p = (ISOCH_CALLBACK_DATA*)isoch->prev;
|
||||
p->next = isoch->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* unregistered data is the head, update head */
|
||||
queue->head = (ISOCH_CALLBACK_DATA*)isoch->next;
|
||||
}
|
||||
|
||||
/* set next data to point to previous data */
|
||||
|
||||
if (isoch->next != NULL)
|
||||
{
|
||||
/* unregistered data is not the tail */
|
||||
p = (ISOCH_CALLBACK_DATA*)isoch->next;
|
||||
p->prev = isoch->prev;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* unregistered data is the tail, update tail */
|
||||
queue->tail = (ISOCH_CALLBACK_DATA*)isoch->prev;
|
||||
}
|
||||
queue->isoch_num--;
|
||||
|
||||
/* free data info */
|
||||
isoch->out_data = NULL;
|
||||
|
||||
if (isoch) zfree(isoch);
|
||||
|
||||
return 1; /* unregistration successful */
|
||||
}
|
||||
}
|
||||
|
||||
/* if we reach this point, the isoch wasn't found */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void isoch_queue_free(ISOCH_CALLBACK_QUEUE* queue)
|
||||
{
|
||||
ISOCH_CALLBACK_DATA* isoch;
|
||||
|
||||
pthread_mutex_lock(&queue->isoch_loading);
|
||||
|
||||
/** unregister all isochronous data*/
|
||||
queue->rewind(queue);
|
||||
|
||||
while (queue->has_next(queue))
|
||||
{
|
||||
isoch = queue->get_next(queue);
|
||||
if (isoch != NULL)
|
||||
queue->unregister_data(queue, isoch);
|
||||
}
|
||||
pthread_mutex_unlock(&queue->isoch_loading);
|
||||
|
||||
pthread_mutex_destroy(&queue->isoch_loading);
|
||||
|
||||
/* free queue */
|
||||
if (queue)
|
||||
zfree(queue);
|
||||
}
|
||||
|
||||
ISOCH_CALLBACK_QUEUE* isoch_queue_new()
|
||||
{
|
||||
ISOCH_CALLBACK_QUEUE* queue;
|
||||
|
||||
queue = (ISOCH_CALLBACK_QUEUE*) malloc(sizeof(ISOCH_CALLBACK_QUEUE));
|
||||
queue->isoch_num = 0;
|
||||
queue->curr = NULL;
|
||||
queue->head = NULL;
|
||||
queue->tail = NULL;
|
||||
|
||||
pthread_mutex_init(&queue->isoch_loading, NULL);
|
||||
|
||||
/* load service */
|
||||
queue->get_next = isoch_queue_get_next;
|
||||
queue->has_next = isoch_queue_has_next;
|
||||
queue->rewind = isoch_queue_rewind;
|
||||
queue->register_data = isoch_queue_register_data;
|
||||
queue->unregister_data = isoch_queue_unregister_data;
|
||||
queue->free = isoch_queue_free;
|
||||
|
||||
return queue;
|
||||
}
|
69
channels/urbdrc/client/isoch_queue.h
Normal file
69
channels/urbdrc/client/isoch_queue.h
Normal file
@ -0,0 +1,69 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* RemoteFX USB Redirection
|
||||
*
|
||||
* Copyright 2012 Atrust corp.
|
||||
* Copyright 2012 Alfred Liu <alfred.liu@atruscorp.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __ISOCH_QUEUE_H
|
||||
#define __ISOCH_QUEUE_H
|
||||
|
||||
#include "urbdrc_types.h"
|
||||
|
||||
|
||||
typedef struct _ISOCH_CALLBACK_DATA ISOCH_CALLBACK_DATA;
|
||||
typedef struct _ISOCH_CALLBACK_QUEUE ISOCH_CALLBACK_QUEUE;
|
||||
|
||||
|
||||
struct _ISOCH_CALLBACK_DATA
|
||||
{
|
||||
void * inode;
|
||||
void * prev;
|
||||
void * next;
|
||||
void * device;
|
||||
uint8 * out_data;
|
||||
uint32 out_size;
|
||||
void * callback;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct _ISOCH_CALLBACK_QUEUE
|
||||
{
|
||||
int isoch_num;
|
||||
ISOCH_CALLBACK_DATA* curr; /* current point */
|
||||
ISOCH_CALLBACK_DATA* head; /* head point in linked list */
|
||||
ISOCH_CALLBACK_DATA* tail; /* tail point in linked list */
|
||||
|
||||
pthread_mutex_t isoch_loading;
|
||||
|
||||
/* Isochronous queue service */
|
||||
void (*rewind) (ISOCH_CALLBACK_QUEUE * queue);
|
||||
int (*has_next) (ISOCH_CALLBACK_QUEUE * queue);
|
||||
int (*unregister_data) (ISOCH_CALLBACK_QUEUE* queue, ISOCH_CALLBACK_DATA* isoch);
|
||||
ISOCH_CALLBACK_DATA *(*get_next) (ISOCH_CALLBACK_QUEUE * queue);
|
||||
ISOCH_CALLBACK_DATA *(*register_data) (ISOCH_CALLBACK_QUEUE* queue,
|
||||
void * callback, void * dev);
|
||||
void (*free) (ISOCH_CALLBACK_QUEUE * queue);
|
||||
|
||||
};
|
||||
|
||||
|
||||
ISOCH_CALLBACK_QUEUE* isoch_queue_new();
|
||||
|
||||
|
||||
|
||||
#endif /* __ISOCH_QUEUE_H */
|
221
channels/urbdrc/client/searchman.c
Normal file
221
channels/urbdrc/client/searchman.c
Normal file
@ -0,0 +1,221 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* RemoteFX USB Redirection
|
||||
*
|
||||
* Copyright 2012 Atrust corp.
|
||||
* Copyright 2012 Alfred Liu <alfred.liu@atruscorp.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "searchman.h"
|
||||
|
||||
static void searchman_rewind(USB_SEARCHMAN* searchman)
|
||||
{
|
||||
searchman->idev = searchman->head;
|
||||
}
|
||||
|
||||
static int searchman_has_next(USB_SEARCHMAN* searchman)
|
||||
{
|
||||
if (searchman->idev == NULL)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static USB_SEARCHDEV* searchman_get_next(USB_SEARCHMAN* searchman)
|
||||
{
|
||||
USB_SEARCHDEV* search;
|
||||
|
||||
search = searchman->idev;
|
||||
searchman->idev = (USB_SEARCHDEV*) searchman->idev->next;
|
||||
|
||||
return search;
|
||||
}
|
||||
|
||||
static int searchman_list_add(USB_SEARCHMAN* searchman, uint16 idVendor, uint16 idProduct)
|
||||
{
|
||||
USB_SEARCHDEV* search;
|
||||
|
||||
search = (USB_SEARCHDEV*) malloc(sizeof(USB_SEARCHDEV));
|
||||
|
||||
search->prev = NULL;
|
||||
search->next = NULL;
|
||||
search->idVendor = idVendor;
|
||||
search->idProduct = idProduct;
|
||||
|
||||
if (searchman->head == NULL)
|
||||
{
|
||||
/* linked list is empty */
|
||||
searchman->head = search;
|
||||
searchman->tail = search;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* append device to the end of the linked list */
|
||||
searchman->tail->next = (void*)search;
|
||||
search->prev = (void*)searchman->tail;
|
||||
searchman->tail = search;
|
||||
}
|
||||
searchman->usb_numbers += 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int searchman_list_remove(USB_SEARCHMAN* searchman, uint16 idVendor, uint16 idProduct)
|
||||
{
|
||||
USB_SEARCHDEV* search;
|
||||
USB_SEARCHDEV* point;
|
||||
|
||||
searchman_rewind(searchman);
|
||||
|
||||
while (searchman_has_next(searchman) != 0)
|
||||
{
|
||||
point = searchman_get_next(searchman);
|
||||
|
||||
if (point->idVendor == idVendor &&
|
||||
point->idProduct == idProduct)
|
||||
{
|
||||
/* set previous device to point to next device */
|
||||
|
||||
search = point;
|
||||
if (search->prev != NULL)
|
||||
{
|
||||
/* unregistered device is not the head */
|
||||
point = (USB_SEARCHDEV*)search->prev;
|
||||
point->next = search->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* unregistered device is the head, update head */
|
||||
searchman->head = (USB_SEARCHDEV*)search->next;
|
||||
}
|
||||
|
||||
/* set next device to point to previous device */
|
||||
|
||||
if (search->next != NULL)
|
||||
{
|
||||
/* unregistered device is not the tail */
|
||||
point = (USB_SEARCHDEV*)search->next;
|
||||
point->prev = search->prev;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* unregistered device is the tail, update tail */
|
||||
searchman->tail = (USB_SEARCHDEV*)search->prev;
|
||||
}
|
||||
searchman->usb_numbers--;
|
||||
|
||||
free(search);
|
||||
|
||||
return 1; /* unregistration successful */
|
||||
}
|
||||
}
|
||||
|
||||
/* if we reach this point, the device wasn't found */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void searchman_start(USB_SEARCHMAN* self, void* func)
|
||||
{
|
||||
pthread_t thread;
|
||||
|
||||
/* create search thread */
|
||||
pthread_create(&thread, 0, func, self);
|
||||
pthread_detach(thread);
|
||||
self->strated = 1;
|
||||
}
|
||||
|
||||
/* close thread */
|
||||
static void searchman_close(USB_SEARCHMAN* self)
|
||||
{
|
||||
wait_obj_set(self->term_event);
|
||||
}
|
||||
|
||||
static void searchman_list_show(USB_SEARCHMAN* self)
|
||||
{
|
||||
int num = 0;
|
||||
USB_SEARCHDEV* usb;
|
||||
|
||||
printf("=========== Usb Search List ========= \n");
|
||||
self->rewind(self);
|
||||
while (self->has_next(self))
|
||||
{
|
||||
usb = self->get_next(self);
|
||||
printf(" USB %d: \n", num++);
|
||||
printf(" idVendor: 0x%04X \n", usb->idVendor);
|
||||
printf(" idProduct: 0x%04X \n", usb->idProduct);
|
||||
}
|
||||
printf("================= END =============== \n");
|
||||
}
|
||||
|
||||
void searchman_free(USB_SEARCHMAN* self)
|
||||
{
|
||||
USB_SEARCHDEV * dev;
|
||||
|
||||
while (self->head != NULL)
|
||||
{
|
||||
dev = (USB_SEARCHDEV *)self->head;
|
||||
self->remove (self, dev->idVendor, dev->idProduct);
|
||||
}
|
||||
|
||||
/* free searchman */
|
||||
sem_destroy(&self->sem_term);
|
||||
wait_obj_free(self->term_event);
|
||||
free(self);
|
||||
}
|
||||
|
||||
USB_SEARCHMAN* searchman_new(void * urbdrc, uint32 UsbDevice)
|
||||
{
|
||||
int ret;
|
||||
USB_SEARCHMAN* searchman;
|
||||
|
||||
searchman = (USB_SEARCHMAN*) malloc(sizeof(USB_SEARCHMAN));
|
||||
|
||||
searchman->idev = NULL;
|
||||
searchman->head = NULL;
|
||||
searchman->tail = NULL;
|
||||
searchman->usb_numbers = 0;
|
||||
searchman->urbdrc = urbdrc;
|
||||
searchman->UsbDevice = UsbDevice;
|
||||
|
||||
ret = pthread_mutex_init(&searchman->mutex, NULL);
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
printf("searchman mutex initialization: searchman->mutex failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* load service */
|
||||
searchman->add = searchman_list_add;
|
||||
searchman->remove = searchman_list_remove;
|
||||
searchman->rewind = searchman_rewind;
|
||||
searchman->get_next = searchman_get_next;
|
||||
searchman->has_next = searchman_has_next;
|
||||
searchman->show = searchman_list_show;
|
||||
searchman->start = searchman_start;
|
||||
searchman->close = searchman_close;
|
||||
searchman->free = searchman_free;
|
||||
|
||||
searchman->strated = 0;
|
||||
searchman->term_event = wait_obj_new();
|
||||
sem_init(&searchman->sem_term, 0, 0);
|
||||
|
||||
return searchman;
|
||||
}
|
77
channels/urbdrc/client/searchman.h
Normal file
77
channels/urbdrc/client/searchman.h
Normal file
@ -0,0 +1,77 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* RemoteFX USB Redirection
|
||||
*
|
||||
* Copyright 2012 Atrust corp.
|
||||
* Copyright 2012 Alfred Liu <alfred.liu@atruscorp.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __SEACH_MAN_H
|
||||
#define __SEACH_MAN_H
|
||||
|
||||
#include "urbdrc_types.h"
|
||||
#include <freerdp/utils/wait_obj.h>
|
||||
|
||||
typedef struct _USB_SEARCHDEV USB_SEARCHDEV;
|
||||
struct _USB_SEARCHDEV
|
||||
{
|
||||
void * inode;
|
||||
void * prev;
|
||||
void * next;
|
||||
uint16 idVendor;
|
||||
uint16 idProduct;
|
||||
};
|
||||
|
||||
typedef struct _USB_SEARCHMAN USB_SEARCHMAN;
|
||||
struct _USB_SEARCHMAN
|
||||
{
|
||||
int usb_numbers;
|
||||
uint32 UsbDevice;
|
||||
USB_SEARCHDEV * idev; /* iterator device */
|
||||
USB_SEARCHDEV * head; /* head device in linked list */
|
||||
USB_SEARCHDEV * tail; /* tail device in linked list */
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
struct wait_obj * term_event;
|
||||
sem_t sem_term;
|
||||
int strated;
|
||||
|
||||
/* for urbdrc channel call back */
|
||||
void * urbdrc;
|
||||
|
||||
/* load service */
|
||||
void (*rewind) (USB_SEARCHMAN* seachman);
|
||||
/* show all device in the list */
|
||||
void (*show) (USB_SEARCHMAN* self);
|
||||
/* start searchman */
|
||||
void (*start) (USB_SEARCHMAN* self, void * func);
|
||||
/* close searchman */
|
||||
void (*close) (USB_SEARCHMAN* self);
|
||||
/* add a new usb device for search */
|
||||
int (*add) (USB_SEARCHMAN* seachman, uint16 idVendor, uint16 idProduct);
|
||||
/* remove a usb device from list */
|
||||
int (*remove) (USB_SEARCHMAN* searchman, uint16 idVendor, uint16 idProduct);
|
||||
/* check list has next device*/
|
||||
int (*has_next) (USB_SEARCHMAN* seachman);
|
||||
/* get the device from list*/
|
||||
USB_SEARCHDEV* (*get_next) (USB_SEARCHMAN* seachman);
|
||||
/* free! */
|
||||
void (*free) (USB_SEARCHMAN* searchman);
|
||||
};
|
||||
|
||||
USB_SEARCHMAN * searchman_new(void * urbdrc, uint32 UsbDevice);
|
||||
|
||||
#endif
|
||||
|
1077
channels/urbdrc/client/urbdrc_main.c
Normal file
1077
channels/urbdrc/client/urbdrc_main.c
Normal file
File diff suppressed because it is too large
Load Diff
263
channels/urbdrc/client/urbdrc_main.h
Normal file
263
channels/urbdrc/client/urbdrc_main.h
Normal file
@ -0,0 +1,263 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* RemoteFX USB Redirection
|
||||
*
|
||||
* Copyright 2012 Atrust corp.
|
||||
* Copyright 2012 Alfred Liu <alfred.liu@atruscorp.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef __URBDRC_MAIN_H
|
||||
#define __URBDRC_MAIN_H
|
||||
|
||||
#include "searchman.h"
|
||||
#include "isoch_queue.h"
|
||||
|
||||
#define DEVICE_HARDWARE_ID_SIZE 32
|
||||
#define DEVICE_COMPATIBILITY_ID_SIZE 36
|
||||
#define DEVICE_INSTANCE_STR_SIZE 37
|
||||
#define DEVICE_CONTAINER_STR_SIZE 39
|
||||
|
||||
typedef struct _IUDEVICE IUDEVICE;
|
||||
typedef struct _IUDEVMAN IUDEVMAN;
|
||||
|
||||
#define BASIC_DEV_STATE_DEFINED(_arg, _type) \
|
||||
_type (*get_##_arg) (IUDEVICE *pdev); \
|
||||
void (*set_##_arg) (IUDEVICE *pdev, _type _arg)
|
||||
#define BASIC_DEVMAN_STATE_DEFINED(_arg, _type) \
|
||||
_type (*get_##_arg) (IUDEVMAN *udevman); \
|
||||
void (*set_##_arg) (IUDEVMAN *udevman, _type _arg)
|
||||
|
||||
typedef struct _URBDRC_LISTENER_CALLBACK URBDRC_LISTENER_CALLBACK;
|
||||
|
||||
struct _URBDRC_LISTENER_CALLBACK
|
||||
{
|
||||
IWTSListenerCallback iface;
|
||||
|
||||
IWTSPlugin* plugin;
|
||||
IWTSVirtualChannelManager* channel_mgr;
|
||||
};
|
||||
|
||||
typedef struct _URBDRC_CHANNEL_CALLBACK URBDRC_CHANNEL_CALLBACK;
|
||||
|
||||
struct _URBDRC_CHANNEL_CALLBACK
|
||||
{
|
||||
IWTSVirtualChannelCallback iface;
|
||||
|
||||
IWTSPlugin* plugin;
|
||||
IWTSVirtualChannelManager* channel_mgr;
|
||||
IWTSVirtualChannel* channel;
|
||||
};
|
||||
|
||||
typedef struct _URBDRC_PLUGIN URBDRC_PLUGIN;
|
||||
|
||||
struct _URBDRC_PLUGIN
|
||||
{
|
||||
IWTSPlugin iface;
|
||||
|
||||
URBDRC_LISTENER_CALLBACK* listener_callback;
|
||||
|
||||
IUDEVMAN* udevman;
|
||||
USB_SEARCHMAN* searchman;
|
||||
uint32 first_channel_id;
|
||||
uint32 vchannel_status;
|
||||
};
|
||||
|
||||
#define URBDRC_UDEVMAN_EXPORT_FUNC_NAME "FreeRDPUDEVMANEntry"
|
||||
|
||||
typedef void (*PREGISTERURBDRCSERVICE)(IWTSPlugin* plugin, IUDEVMAN* udevman);
|
||||
|
||||
struct _FREERDP_URBDRC_SERVICE_ENTRY_POINTS
|
||||
{
|
||||
IWTSPlugin* plugin;
|
||||
PREGISTERURBDRCSERVICE pRegisterUDEVMAN;
|
||||
RDP_PLUGIN_DATA* plugin_data;
|
||||
};
|
||||
typedef struct _FREERDP_URBDRC_SERVICE_ENTRY_POINTS FREERDP_URBDRC_SERVICE_ENTRY_POINTS;
|
||||
typedef FREERDP_URBDRC_SERVICE_ENTRY_POINTS* PFREERDP_URBDRC_SERVICE_ENTRY_POINTS;
|
||||
|
||||
typedef int (*PFREERDP_URBDRC_DEVICE_ENTRY)(PFREERDP_URBDRC_SERVICE_ENTRY_POINTS pEntryPoints);
|
||||
|
||||
typedef struct _TRANSFER_DATA TRANSFER_DATA;
|
||||
|
||||
struct _TRANSFER_DATA
|
||||
{
|
||||
URBDRC_CHANNEL_CALLBACK* callback;
|
||||
URBDRC_PLUGIN* urbdrc;
|
||||
IUDEVMAN* udevman;
|
||||
uint8* pBuffer;
|
||||
uint32 cbSize;
|
||||
uint32 UsbDevice;
|
||||
};
|
||||
|
||||
struct _IUDEVICE
|
||||
{
|
||||
/* Transfer */
|
||||
int (*isoch_transfer) (IUDEVICE * idev, uint32 RequestId,
|
||||
uint32 EndpointAddress,
|
||||
uint32 TransferFlags,
|
||||
int NoAck,
|
||||
uint32 *ErrorCount,
|
||||
uint32 *UrbdStatus,
|
||||
uint32 *StartFrame,
|
||||
uint32 NumberOfPackets,
|
||||
uint8 *IsoPacket,
|
||||
uint32 *BufferSize,
|
||||
uint8 *Buffer,
|
||||
int Timeout);
|
||||
|
||||
int (*control_transfer) (IUDEVICE * idev, uint32 RequestId,
|
||||
uint32 EndpointAddress,
|
||||
uint32 TransferFlags,
|
||||
uint8 bmRequestType,
|
||||
uint8 Request,
|
||||
uint16 Value,
|
||||
uint16 Index,
|
||||
uint32 *UrbdStatus,
|
||||
uint32 *BufferSize,
|
||||
uint8 *Buffer,
|
||||
uint32 Timeout);
|
||||
|
||||
int (*bulk_or_interrupt_transfer) (IUDEVICE * idev, uint32 RequestId,
|
||||
uint32 EndpointAddress,
|
||||
uint32 TransferFlags,
|
||||
uint32 *UsbdStatus,
|
||||
uint32 *BufferSize,
|
||||
uint8 *Buffer,
|
||||
uint32 Timeout);
|
||||
|
||||
|
||||
int (*select_configuration) (IUDEVICE * idev, uint32 bConfigurationValue);
|
||||
|
||||
int (*select_interface) (IUDEVICE * idev, uint8 InterfaceNumber,
|
||||
uint8 AlternateSetting);
|
||||
|
||||
int (*control_pipe_request) (IUDEVICE * idev, uint32 RequestId,
|
||||
uint32 EndpointAddress,
|
||||
uint32 *UsbdStatus,
|
||||
int command);
|
||||
|
||||
int (*control_query_device_text) (IUDEVICE * idev, uint32 TextType,
|
||||
uint32 LocaleId,
|
||||
uint32 *BufferSize,
|
||||
uint8 * Buffer);
|
||||
|
||||
int (*os_feature_descriptor_request) (IUDEVICE * idev, uint32 RequestId,
|
||||
uint8 Recipient,
|
||||
uint8 InterfaceNumber,
|
||||
uint8 Ms_PageIndex,
|
||||
uint16 Ms_featureDescIndex,
|
||||
uint32 * UsbdStatus,
|
||||
uint32 * BufferSize,
|
||||
uint8* Buffer,
|
||||
int Timeout);
|
||||
|
||||
void (*cancel_all_transfer_request) (IUDEVICE * idev);
|
||||
|
||||
int (*cancel_transfer_request) (IUDEVICE * idev, uint32 RequestId);
|
||||
|
||||
int (*query_device_descriptor) (IUDEVICE * idev, int offset);
|
||||
|
||||
void (*detach_kernel_driver) (IUDEVICE * idev);
|
||||
|
||||
void (*attach_kernel_driver) (IUDEVICE * idev);
|
||||
|
||||
int (*wait_action_completion) (IUDEVICE * idev);
|
||||
|
||||
void (*push_action) (IUDEVICE * idev);
|
||||
|
||||
void (*complete_action) (IUDEVICE * idev);
|
||||
|
||||
/* Wait for 5 sec */
|
||||
int (*wait_for_detach) (IUDEVICE * idev);
|
||||
|
||||
/* FIXME: Currently this is a way of stupid, SHOULD to improve it.
|
||||
* Isochronous transfer must to FIFO */
|
||||
void (*lock_fifo_isoch) (IUDEVICE * idev);
|
||||
void (*unlock_fifo_isoch) (IUDEVICE * idev);
|
||||
|
||||
int (*query_device_port_status) (IUDEVICE * idev, uint32 *UsbdStatus,
|
||||
uint32 * BufferSize,
|
||||
uint8 * Buffer);
|
||||
|
||||
int (*request_queue_is_none) (IUDEVICE * idev);
|
||||
|
||||
MSUSB_CONFIG_DESCRIPTOR * (*complete_msconfig_setup) (IUDEVICE * idev,
|
||||
MSUSB_CONFIG_DESCRIPTOR * MsConfig);
|
||||
/* Basic state */
|
||||
int (*isCompositeDevice) (IUDEVICE * idev);
|
||||
int (*isSigToEnd) (IUDEVICE * idev);
|
||||
int (*isExist) (IUDEVICE * idev);
|
||||
int (*isAlreadySend) (IUDEVICE * idev);
|
||||
int (*isChannelClosed) (IUDEVICE * idev);
|
||||
void (*SigToEnd) (IUDEVICE * idev);
|
||||
void (*setAlreadySend) (IUDEVICE * idev);
|
||||
void (*setChannelClosed) (IUDEVICE * idev);
|
||||
char *(*getPath) (IUDEVICE * idev);
|
||||
|
||||
BASIC_DEV_STATE_DEFINED(channel_id, uint32);
|
||||
BASIC_DEV_STATE_DEFINED(UsbDevice, uint32);
|
||||
BASIC_DEV_STATE_DEFINED(ReqCompletion, uint32);
|
||||
BASIC_DEV_STATE_DEFINED(bus_number, uint16);
|
||||
BASIC_DEV_STATE_DEFINED(dev_number, uint16);
|
||||
BASIC_DEV_STATE_DEFINED(port_number, int);
|
||||
BASIC_DEV_STATE_DEFINED(isoch_queue, void *);
|
||||
BASIC_DEV_STATE_DEFINED(MsConfig, MSUSB_CONFIG_DESCRIPTOR *);
|
||||
|
||||
BASIC_DEV_STATE_DEFINED(p_udev, void *);
|
||||
BASIC_DEV_STATE_DEFINED(p_prev, void *);
|
||||
BASIC_DEV_STATE_DEFINED(p_next, void *);
|
||||
|
||||
/* Control semaphore or mutex lock */
|
||||
|
||||
};
|
||||
|
||||
struct _IUDEVMAN
|
||||
{
|
||||
/* Standard */
|
||||
void (*free) (IUDEVMAN *idevman);
|
||||
/* Manage devices */
|
||||
void (*rewind) (IUDEVMAN *idevman);
|
||||
int (*has_next) (IUDEVMAN *idevman);
|
||||
int (*unregister_udevice) (IUDEVMAN* idevman, int bus_number,
|
||||
int dev_number);
|
||||
int (*register_udevice) (IUDEVMAN* idevman, int bus_number,
|
||||
int dev_number,
|
||||
int UsbDevice,
|
||||
uint16 idVendor,
|
||||
uint16 idProduct,
|
||||
int flag);
|
||||
IUDEVICE *(*get_next) (IUDEVMAN *idevman);
|
||||
IUDEVICE *(*get_udevice_by_UsbDevice) (IUDEVMAN * idevman,
|
||||
uint32 UsbDevice);
|
||||
IUDEVICE *(*get_udevice_by_UsbDevice_try_again) (IUDEVMAN * idevman,
|
||||
uint32 UsbDevice);
|
||||
/* Extension */
|
||||
int (*check_device_exist_by_id) (IUDEVMAN * idevman, uint16 idVendor,
|
||||
uint16 idProduct);
|
||||
int (*isAutoAdd) (IUDEVMAN * idevman);
|
||||
/* Basic state */
|
||||
BASIC_DEVMAN_STATE_DEFINED(defUsbDevice, uint32);
|
||||
BASIC_DEVMAN_STATE_DEFINED(device_num, int);
|
||||
BASIC_DEVMAN_STATE_DEFINED(sem_timeout, int);
|
||||
/* control semaphore or mutex lock */
|
||||
void (*loading_lock) (IUDEVMAN * idevman);
|
||||
void (*loading_unlock) (IUDEVMAN * idevman);
|
||||
void (*push_urb) (IUDEVMAN * idevman);
|
||||
void (*wait_urb) (IUDEVMAN * idevman);
|
||||
};
|
||||
|
||||
#endif /* __URBDRC_MAIN_H */
|
337
channels/urbdrc/client/urbdrc_types.h
Normal file
337
channels/urbdrc/client/urbdrc_types.h
Normal file
@ -0,0 +1,337 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* RemoteFX USB Redirection
|
||||
*
|
||||
* Copyright 2012 Atrust corp.
|
||||
* Copyright 2012 Alfred Liu <alfred.liu@atruscorp.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __URBDRC_TYPES_H
|
||||
#define __URBDRC_TYPES_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <freerdp/dvc.h>
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/utils/debug.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
#include <freerdp/utils/msusb.h>
|
||||
|
||||
#include <uuid/uuid.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
#ifdef WITH_DEBUG_DVC
|
||||
#define DEBUG_DVC(fmt, ...) DEBUG_CLASS(DVC, fmt, ## __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_DVC(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#define CAPABILITIES_NEGOTIATOR 0x00000000
|
||||
#define CLIENT_DEVICE_SINK 0x00000001
|
||||
#define SERVER_CHANNEL_NOTIFICATION 0x00000002
|
||||
#define CLIENT_CHANNEL_NOTIFICATION 0x00000003
|
||||
#define BASE_USBDEVICE_NUM 0x00000005
|
||||
|
||||
#define RIMCALL_RELEASE 0x00000001
|
||||
#define RIM_EXCHANGE_CAPABILITY_REQUEST 0x00000100
|
||||
#define CHANNEL_CREATED 0x00000100
|
||||
#define ADD_VIRTUAL_CHANNEL 0x00000100
|
||||
#define ADD_DEVICE 0x00000101
|
||||
|
||||
#define INIT_CHANNEL_IN 1
|
||||
#define INIT_CHANNEL_OUT 0
|
||||
|
||||
/* InterfaceClass */
|
||||
#define CLASS_RESERVE 0x00
|
||||
#define CLASS_AUDIO 0x01
|
||||
#define CLASS_COMMUNICATION_IF 0x02
|
||||
#define CLASS_HID 0x03
|
||||
#define CLASS_PHYSICAL 0x05
|
||||
#define CLASS_IMAGE 0x06
|
||||
#define CLASS_PRINTER 0x07
|
||||
#define CLASS_MASS_STORAGE 0x08
|
||||
#define CLASS_HUB 0x09
|
||||
#define CLASS_COMMUNICATION_DATA_IF 0x0a
|
||||
#define CLASS_SMART_CARD 0x0b
|
||||
#define CLASS_CONTENT_SECURITY 0x0d
|
||||
#define CLASS_VIDEO 0x0e
|
||||
#define CLASS_PERSONAL_HEALTHCARE 0x0f
|
||||
#define CLASS_DIAGNOSTIC 0xdc
|
||||
#define CLASS_WIRELESS_CONTROLLER 0xe0
|
||||
#define CLASS_ELSE_DEVICE 0xef
|
||||
#define CLASS_DEPENDENCE 0xfe
|
||||
#define CLASS_VENDOR_DEPENDENCE 0xff
|
||||
|
||||
/* usb version */
|
||||
#define USB_v1_0 0x100
|
||||
#define USB_v1_1 0x110
|
||||
#define USB_v2_0 0x200
|
||||
#define USB_v3_0 0x300
|
||||
|
||||
#define STREAM_ID_NONE 0x0
|
||||
#define STREAM_ID_PROXY 0x1
|
||||
#define STREAM_ID_STUB 0x2
|
||||
|
||||
#define CANCEL_REQUEST 0x00000100
|
||||
#define REGISTER_REQUEST_CALLBACK 0x00000101
|
||||
#define IO_CONTROL 0x00000102
|
||||
#define INTERNAL_IO_CONTROL 0x00000103
|
||||
#define QUERY_DEVICE_TEXT 0x00000104
|
||||
#define TRANSFER_IN_REQUEST 0x00000105
|
||||
#define TRANSFER_OUT_REQUEST 0x00000106
|
||||
#define RETRACT_DEVICE 0x00000107
|
||||
|
||||
|
||||
#define IOCONTROL_COMPLETION 0x00000100
|
||||
#define URB_COMPLETION 0x00000101
|
||||
#define URB_COMPLETION_NO_DATA 0x00000102
|
||||
|
||||
/* The USB device is to be stopped from being redirected because the
|
||||
* device is blocked by the server's policy. */
|
||||
#define UsbRetractReason_BlockedByPolicy 0x00000001
|
||||
|
||||
enum device_text_type
|
||||
{
|
||||
DeviceTextDescription = 0,
|
||||
DeviceTextLocationInformation = 1,
|
||||
};
|
||||
|
||||
enum device_descriptor_table
|
||||
{
|
||||
B_LENGTH = 0,
|
||||
B_DESCRIPTOR_TYPE = 1,
|
||||
BCD_USB = 2,
|
||||
B_DEVICE_CLASS = 4,
|
||||
B_DEVICE_SUBCLASS = 5,
|
||||
B_DEVICE_PROTOCOL = 6,
|
||||
B_MAX_PACKET_SIZE0 = 7,
|
||||
ID_VENDOR = 8,
|
||||
ID_PRODUCT = 10,
|
||||
BCD_DEVICE = 12,
|
||||
I_MANUFACTURER = 14,
|
||||
I_PRODUCT = 15,
|
||||
I_SERIAL_NUMBER = 16,
|
||||
B_NUM_CONFIGURATIONS = 17
|
||||
};
|
||||
|
||||
#define PIPE_CANCEL 0
|
||||
#define PIPE_RESET 1
|
||||
|
||||
#define IOCTL_INTERNAL_USB_SUBMIT_URB 0x00220003
|
||||
#define IOCTL_INTERNAL_USB_RESET_PORT 0x00220007
|
||||
#define IOCTL_INTERNAL_USB_GET_PORT_STATUS 0x00220013
|
||||
#define IOCTL_INTERNAL_USB_CYCLE_PORT 0x0022001F
|
||||
#define IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION 0x00220027
|
||||
|
||||
|
||||
|
||||
#define URB_FUNCTION_SELECT_CONFIGURATION 0x0000
|
||||
#define URB_FUNCTION_SELECT_INTERFACE 0x0001
|
||||
#define URB_FUNCTION_ABORT_PIPE 0x0002
|
||||
#define URB_FUNCTION_TAKE_FRAME_LENGTH_CONTROL 0x0003
|
||||
#define URB_FUNCTION_RELEASE_FRAME_LENGTH_CONTROL 0x0004
|
||||
#define URB_FUNCTION_GET_FRAME_LENGTH 0x0005
|
||||
#define URB_FUNCTION_SET_FRAME_LENGTH 0x0006
|
||||
#define URB_FUNCTION_GET_CURRENT_FRAME_NUMBER 0x0007
|
||||
#define URB_FUNCTION_CONTROL_TRANSFER 0x0008
|
||||
#define URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER 0x0009
|
||||
#define URB_FUNCTION_ISOCH_TRANSFER 0x000A
|
||||
#define URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE 0x000B
|
||||
#define URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE 0x000C
|
||||
#define URB_FUNCTION_SET_FEATURE_TO_DEVICE 0x000D
|
||||
#define URB_FUNCTION_SET_FEATURE_TO_INTERFACE 0x000E
|
||||
#define URB_FUNCTION_SET_FEATURE_TO_ENDPOINT 0x000F
|
||||
#define URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE 0x0010
|
||||
#define URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE 0x0011
|
||||
#define URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT 0x0012
|
||||
#define URB_FUNCTION_GET_STATUS_FROM_DEVICE 0x0013
|
||||
#define URB_FUNCTION_GET_STATUS_FROM_INTERFACE 0x0014
|
||||
#define URB_FUNCTION_GET_STATUS_FROM_ENDPOINT 0x0015
|
||||
#define URB_FUNCTION_RESERVED_0X0016 0x0016
|
||||
#define URB_FUNCTION_VENDOR_DEVICE 0x0017
|
||||
#define URB_FUNCTION_VENDOR_INTERFACE 0x0018
|
||||
#define URB_FUNCTION_VENDOR_ENDPOINT 0x0019
|
||||
#define URB_FUNCTION_CLASS_DEVICE 0x001A
|
||||
#define URB_FUNCTION_CLASS_INTERFACE 0x001B
|
||||
#define URB_FUNCTION_CLASS_ENDPOINT 0x001C
|
||||
#define URB_FUNCTION_RESERVE_0X001D 0x001D
|
||||
#define URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL 0x001E
|
||||
#define URB_FUNCTION_CLASS_OTHER 0x001F
|
||||
#define URB_FUNCTION_VENDOR_OTHER 0x0020
|
||||
#define URB_FUNCTION_GET_STATUS_FROM_OTHER 0x0021
|
||||
#define URB_FUNCTION_CLEAR_FEATURE_TO_OTHER 0x0022
|
||||
#define URB_FUNCTION_SET_FEATURE_TO_OTHER 0x0023
|
||||
#define URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT 0x0024
|
||||
#define URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT 0x0025
|
||||
#define URB_FUNCTION_GET_CONFIGURATION 0x0026
|
||||
#define URB_FUNCTION_GET_INTERFACE 0x0027
|
||||
#define URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE 0x0028
|
||||
#define URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE 0x0029
|
||||
#define URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR 0x002A
|
||||
#define URB_FUNCTION_RESERVE_0X002B 0x002B
|
||||
#define URB_FUNCTION_RESERVE_0X002C 0x002C
|
||||
#define URB_FUNCTION_RESERVE_0X002D 0x002D
|
||||
#define URB_FUNCTION_RESERVE_0X002E 0x002E
|
||||
#define URB_FUNCTION_RESERVE_0X002F 0x002F
|
||||
// USB 2.0 calls start at 0x0030
|
||||
#define URB_FUNCTION_SYNC_RESET_PIPE 0x0030
|
||||
#define URB_FUNCTION_SYNC_CLEAR_STALL 0x0031
|
||||
#define URB_FUNCTION_CONTROL_TRANSFER_EX 0x0032
|
||||
|
||||
#define USBD_STATUS_SUCCESS 0x0
|
||||
#define USBD_STATUS_PENDING 0x40000000
|
||||
#define USBD_STATUS_CANCELED 0xC0010000
|
||||
|
||||
#define USBD_STATUS_CRC 0xC0000001
|
||||
#define USBD_STATUS_BTSTUFF 0xC0000002
|
||||
#define USBD_STATUS_DATA_TOGGLE_MISMATCH 0xC0000003
|
||||
#define USBD_STATUS_STALL_PID 0xC0000004
|
||||
#define USBD_STATUS_DEV_NOT_RESPONDING 0xC0000005
|
||||
#define USBD_STATUS_PID_CHECK_FAILURE 0xC0000006
|
||||
#define USBD_STATUS_UNEXPECTED_PID 0xC0000007
|
||||
#define USBD_STATUS_DATA_OVERRUN 0xC0000008
|
||||
#define USBD_STATUS_DATA_UNDERRUN 0xC0000009
|
||||
#define USBD_STATUS_RESERVED1 0xC000000A
|
||||
#define USBD_STATUS_RESERVED2 0xC000000B
|
||||
#define USBD_STATUS_BUFFER_OVERRUN 0xC000000C
|
||||
#define USBD_STATUS_BUFFER_UNDERRUN 0xC000000D
|
||||
|
||||
/* unknown */
|
||||
#define USBD_STATUS_NO_DATA 0xC000000E
|
||||
|
||||
#define USBD_STATUS_NOT_ACCESSED 0xC000000F
|
||||
#define USBD_STATUS_FIFO 0xC0000010
|
||||
#define USBD_STATUS_XACT_ERROR 0xC0000011
|
||||
#define USBD_STATUS_BABBLE_DETECTED 0xC0000012
|
||||
#define USBD_STATUS_DATA_BUFFER_ERROR 0xC0000013
|
||||
|
||||
#define USBD_STATUS_NOT_SUPPORTED 0xC0000E00
|
||||
#define USBD_STATUS_BUFFER_TOO_SMALL 0xC0003000
|
||||
#define USBD_STATUS_TIMEOUT 0xC0006000
|
||||
#define USBD_STATUS_DEVICE_GONE 0xC0007000
|
||||
|
||||
#define USBD_STATUS_NO_MEMORY 0x80000100
|
||||
#define USBD_STATUS_INVALID_URB_FUNCTION 0x80000200
|
||||
#define USBD_STATUS_INVALID_PARAMETER 0x80000300
|
||||
#define USBD_STATUS_REQUEST_FAILED 0x80000500
|
||||
#define USBD_STATUS_INVALID_PIPE_HANDLE 0x80000600
|
||||
#define USBD_STATUS_ERROR_SHORT_TRANSFER 0x80000900
|
||||
|
||||
// Values for URB TransferFlags Field
|
||||
//
|
||||
|
||||
/*
|
||||
Set if data moves device->host
|
||||
*/
|
||||
#define USBD_TRANSFER_DIRECTION 0x00000001
|
||||
/*
|
||||
This bit if not set indicates that a short packet, and hence,
|
||||
a short transfer is an error condition
|
||||
*/
|
||||
#define USBD_SHORT_TRANSFER_OK 0x00000002
|
||||
/*
|
||||
Subit the iso transfer on the next frame
|
||||
*/
|
||||
#define USBD_START_ISO_TRANSFER_ASAP 0x00000004
|
||||
#define USBD_DEFAULT_PIPE_TRANSFER 0x00000008
|
||||
|
||||
|
||||
#define USBD_TRANSFER_DIRECTION_FLAG(flags) ((flags) & USBD_TRANSFER_DIRECTION)
|
||||
|
||||
#define USBD_TRANSFER_DIRECTION_OUT 0
|
||||
#define USBD_TRANSFER_DIRECTION_IN 1
|
||||
|
||||
#define VALID_TRANSFER_FLAGS_MASK USBD_SHORT_TRANSFER_OK | \
|
||||
USBD_TRANSFER_DIRECTION | \
|
||||
USBD_START_ISO_TRANSFER_ASAP | \
|
||||
USBD_DEFAULT_PIPE_TRANSFER)
|
||||
|
||||
#define ENDPOINT_HALT 0x00
|
||||
#define DEVICE_REMOTE_WAKEUP 0x01
|
||||
|
||||
/* transfer type */
|
||||
#define CONTROL_TRANSFER 0x00
|
||||
#define ISOCHRONOUS_TRANSFER 0x01
|
||||
#define BULK_TRANSFER 0x02
|
||||
#define INTERRUPT_TRANSFER 0x03
|
||||
|
||||
#define ClearHubFeature (0x2000 | LIBUSB_REQUEST_CLEAR_FEATURE)
|
||||
#define ClearPortFeature (0x2300 | LIBUSB_REQUEST_CLEAR_FEATURE)
|
||||
#define GetHubDescriptor (0xa000 | LIBUSB_REQUEST_GET_DESCRIPTOR)
|
||||
#define GetHubStatus (0xa000 | LIBUSB_REQUEST_GET_STATUS)
|
||||
#define GetPortStatus (0xa300 | LIBUSB_REQUEST_GET_STATUS)
|
||||
#define SetHubFeature (0x2000 | LIBUSB_REQUEST_SET_FEATURE)
|
||||
#define SetPortFeature (0x2300 | LIBUSB_REQUEST_SET_FEATURE)
|
||||
|
||||
#define USBD_PF_CHANGE_MAX_PACKET 0x00000001
|
||||
#define USBD_PF_SHORT_PACKET_OPT 0x00000002
|
||||
#define USBD_PF_ENABLE_RT_THREAD_ACCESS 0x00000004
|
||||
#define USBD_PF_MAP_ADD_TRANSFERS 0x00000008
|
||||
|
||||
/* feature request */
|
||||
#define URB_SET_FEATURE 0x00
|
||||
#define URB_CLEAR_FEATURE 0x01
|
||||
|
||||
#define USBD_PF_CHANGE_MAX_PACKET 0x00000001
|
||||
#define USBD_PF_SHORT_PACKET_OPT 0x00000002
|
||||
#define USBD_PF_ENABLE_RT_THREAD_ACCESS 0x00000004
|
||||
#define USBD_PF_MAP_ADD_TRANSFERS 0x00000008
|
||||
|
||||
#define URB_CONTROL_TRANSFER_EXTERNAL 0x1
|
||||
#define URB_CONTROL_TRANSFER_NONEXTERNAL 0x0
|
||||
|
||||
#define USBFS_URB_SHORT_NOT_OK 0x01
|
||||
#define USBFS_URB_ISO_ASAP 0x02
|
||||
#define USBFS_URB_BULK_CONTINUATION 0x04
|
||||
#define USBFS_URB_QUEUE_BULK 0x10
|
||||
|
||||
#define URBDRC_DEVICE_INITIALIZED 0x01
|
||||
#define URBDRC_DEVICE_NOT_FOUND 0x02
|
||||
#define URBDRC_DEVICE_SIGNAL_END 0x04
|
||||
#define URBDRC_DEVICE_CHANNEL_CLOSED 0x08
|
||||
#define URBDRC_DEVICE_ALREADY_SEND 0x10
|
||||
#define URBDRC_DEVICE_DETACH_KERNEL 0x20
|
||||
|
||||
#define UDEVMAN_FLAG_ADD_BY_VID_PID 0x01
|
||||
#define UDEVMAN_FLAG_ADD_BY_ADDR 0x02
|
||||
#define UDEVMAN_FLAG_ADD_BY_AUTO 0x04
|
||||
#define UDEVMAN_FLAG_DEBUG 0x08
|
||||
|
||||
#define MAX_URB_REQUSET_NUM 0x80
|
||||
|
||||
#define LOG_LEVEL 1
|
||||
#define LLOG(_level, _args) \
|
||||
do { if (_level < LOG_LEVEL) { printf _args ; } } while (0)
|
||||
#define LLOGLN(_level, _args) \
|
||||
do { if (_level < LOG_LEVEL) { printf _args ; printf("\n"); } } while (0)
|
||||
|
||||
#define dummy_wait_obj(void) do{ sleep(5); } while(0)
|
||||
#define dummy_wait_s_obj(_s) do{ sleep(_s); } while(0)
|
||||
|
||||
#define ISOCH_FIFO 1
|
||||
#define WAIT_COMPLETE_SLEEP 10000 /* for cpu high loading */
|
||||
|
||||
#define urbdrc_get_mstime(_t) do { \
|
||||
struct timeval _tp; \
|
||||
gettimeofday(&_tp, 0); \
|
||||
_t = (_tp.tv_sec * 1000) + (_tp.tv_usec / 1000); \
|
||||
} while (0)
|
||||
|
||||
extern int urbdrc_debug;
|
||||
|
||||
#endif /* __URBDRC_TYPES_H */
|
38
channels/urbdrc/libusb/CMakeLists.txt
Normal file
38
channels/urbdrc/libusb/CMakeLists.txt
Normal file
@ -0,0 +1,38 @@
|
||||
# FreeRDP: A Remote Desktop Protocol Client
|
||||
# FreeRDP cmake build script
|
||||
#
|
||||
# Copyright 2012 Atrust corp.
|
||||
# Copyright 2012 Alfred Liu <alfred.liu@atruscorp.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set(LIBUSB_UDEVMAN_SRCS
|
||||
libusb_udevman.c
|
||||
libusb_udevice.c
|
||||
libusb_udevice.h
|
||||
request_queue.c
|
||||
request_queue.h)
|
||||
|
||||
include_directories(../client)
|
||||
|
||||
add_library(libusb_udevman ${LIBUSB_UDEVMAN_SRCS})
|
||||
set_target_properties(libusb_udevman PROPERTIES PREFIX "")
|
||||
|
||||
target_link_libraries(libusb_udevman udev)
|
||||
target_link_libraries(libusb_udevman dbus-glib-1)
|
||||
target_link_libraries(libusb_udevman pthread)
|
||||
target_link_libraries(libusb_udevman usb-1.0)
|
||||
target_link_libraries(libusb_udevman freerdp-utils)
|
||||
|
||||
install(TARGETS libusb_udevman DESTINATION ${FREERDP_PLUGIN_PATH})
|
||||
|
1901
channels/urbdrc/libusb/libusb_udevice.c
Normal file
1901
channels/urbdrc/libusb/libusb_udevice.c
Normal file
File diff suppressed because it is too large
Load Diff
86
channels/urbdrc/libusb/libusb_udevice.h
Normal file
86
channels/urbdrc/libusb/libusb_udevice.h
Normal file
@ -0,0 +1,86 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* RemoteFX USB Redirection
|
||||
*
|
||||
* Copyright 2012 Atrust corp.
|
||||
* Copyright 2012 Alfred Liu <alfred.liu@atruscorp.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef __LIBUSB_UDEVICE_H
|
||||
#define __LIBUSB_UDEVICE_H
|
||||
|
||||
#include <libusb-1.0/libusb.h>
|
||||
|
||||
#include "urbdrc_types.h"
|
||||
#include "request_queue.h"
|
||||
#include "urbdrc_main.h"
|
||||
|
||||
|
||||
|
||||
typedef struct libusb_device LIBUSB_DEVICE;
|
||||
typedef struct libusb_device_handle LIBUSB_DEVICE_HANDLE;
|
||||
typedef struct libusb_device_descriptor LIBUSB_DEVICE_DESCRIPTOR;
|
||||
typedef struct libusb_config_descriptor LIBUSB_CONFIG_DESCRIPTOR;
|
||||
typedef struct libusb_interface LIBUSB_INTERFACE;
|
||||
typedef struct libusb_interface_descriptor LIBUSB_INTERFACE_DESCRIPTOR;
|
||||
typedef struct libusb_endpoint_descriptor LIBUSB_ENDPOINT_DESCEIPTOR;
|
||||
|
||||
|
||||
typedef struct _UDEVICE UDEVICE;
|
||||
struct _UDEVICE
|
||||
{
|
||||
IUDEVICE iface;
|
||||
|
||||
void * udev;
|
||||
void * prev;
|
||||
void * next;
|
||||
|
||||
uint32 UsbDevice; /* An unique interface ID */
|
||||
uint32 ReqCompletion; /* An unique interface ID */
|
||||
uint32 channel_id;
|
||||
uint16 status;
|
||||
uint16 bus_number;
|
||||
uint16 dev_number;
|
||||
char path[17];
|
||||
int port_number;
|
||||
int isCompositeDevice;
|
||||
|
||||
LIBUSB_DEVICE_HANDLE * libusb_handle;
|
||||
LIBUSB_DEVICE_HANDLE * hub_handle;
|
||||
LIBUSB_DEVICE * libusb_dev;
|
||||
LIBUSB_DEVICE_DESCRIPTOR * devDescriptor;
|
||||
MSUSB_CONFIG_DESCRIPTOR * MsConfig;
|
||||
LIBUSB_CONFIG_DESCRIPTOR * LibusbConfig;
|
||||
|
||||
REQUEST_QUEUE * request_queue;
|
||||
/* Used in isochronous transfer */
|
||||
void * isoch_queue;
|
||||
|
||||
pthread_mutex_t mutex_isoch;
|
||||
sem_t sem_id;
|
||||
};
|
||||
typedef UDEVICE * PUDEVICE;
|
||||
|
||||
|
||||
int
|
||||
udev_new_by_id(uint16_t idVendor, uint16_t idProduct, IUDEVICE ***devArray);
|
||||
IUDEVICE*
|
||||
udev_new_by_addr(int bus_number, int dev_number);
|
||||
|
||||
extern int libusb_debug;
|
||||
|
||||
#endif /* __LIBUSB_UDEVICE_H */
|
567
channels/urbdrc/libusb/libusb_udevman.c
Normal file
567
channels/urbdrc/libusb/libusb_udevman.c
Normal file
@ -0,0 +1,567 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* RemoteFX USB Redirection
|
||||
*
|
||||
* Copyright 2012 Atrust corp.
|
||||
* Copyright 2012 Alfred Liu <alfred.liu@atruscorp.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include "urbdrc_types.h"
|
||||
#include "urbdrc_main.h"
|
||||
#include "libusb_udevice.h"
|
||||
|
||||
int libusb_debug;
|
||||
|
||||
#define BASIC_STATE_FUNC_DEFINED(_arg, _type) \
|
||||
static _type udevman_get_##_arg (IUDEVMAN * idevman) \
|
||||
{ \
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman; \
|
||||
return udevman->_arg; \
|
||||
} \
|
||||
static void udevman_set_##_arg (IUDEVMAN * idevman, _type _t) \
|
||||
{ \
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman; \
|
||||
udevman->_arg = _t; \
|
||||
}
|
||||
|
||||
#define BASIC_STATE_FUNC_REGISTER(_arg, _man) \
|
||||
_man->iface.get_##_arg = udevman_get_##_arg; \
|
||||
_man->iface.set_##_arg = udevman_set_##_arg
|
||||
|
||||
|
||||
typedef struct _UDEVMAN UDEVMAN;
|
||||
struct _UDEVMAN
|
||||
{
|
||||
IUDEVMAN iface;
|
||||
|
||||
IUDEVICE* idev; /* iterator device */
|
||||
IUDEVICE* head; /* head device in linked list */
|
||||
IUDEVICE* tail; /* tail device in linked list */
|
||||
|
||||
uint32 defUsbDevice;
|
||||
uint16 flags;
|
||||
int device_num;
|
||||
int sem_timeout;
|
||||
|
||||
pthread_mutex_t devman_loading;
|
||||
sem_t sem_urb_lock;
|
||||
};
|
||||
typedef UDEVMAN * PUDEVMAN;
|
||||
|
||||
|
||||
|
||||
static void
|
||||
udevman_rewind(IUDEVMAN * idevman)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
udevman->idev = udevman->head;
|
||||
}
|
||||
|
||||
static int
|
||||
udevman_has_next(IUDEVMAN * idevman)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
if (udevman->idev == NULL)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static IUDEVICE*
|
||||
udevman_get_next(IUDEVMAN * idevman)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
IUDEVICE* pdev;
|
||||
|
||||
pdev = udevman->idev;
|
||||
udevman->idev = (IUDEVICE*) ((UDEVICE*)udevman->idev)->next;
|
||||
|
||||
return pdev;
|
||||
}
|
||||
|
||||
|
||||
static IUDEVICE*
|
||||
udevman_get_udevice_by_addr(IUDEVMAN * idevman, int bus_number, int dev_number)
|
||||
{
|
||||
IUDEVICE * pdev;
|
||||
|
||||
idevman->loading_lock(idevman);
|
||||
idevman->rewind (idevman);
|
||||
while (idevman->has_next (idevman))
|
||||
{
|
||||
pdev = idevman->get_next (idevman);
|
||||
if (pdev->get_bus_number(pdev) == bus_number &&
|
||||
pdev->get_dev_number(pdev) == dev_number)
|
||||
{
|
||||
idevman->loading_unlock(idevman);
|
||||
return pdev;
|
||||
}
|
||||
}
|
||||
idevman->loading_unlock(idevman);
|
||||
LLOGLN(libusb_debug, ("%s: bus:%d dev:%d not exist in udevman",
|
||||
__func__, bus_number, dev_number));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
udevman_register_udevice(IUDEVMAN* idevman, int bus_number, int dev_number,
|
||||
int UsbDevice,
|
||||
uint16 idVendor,
|
||||
uint16 idProduct,
|
||||
int flag)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
IUDEVICE * pdev = NULL;
|
||||
IUDEVICE ** devArray;
|
||||
int i, num, addnum = 0;
|
||||
|
||||
pdev = (IUDEVICE *)udevman_get_udevice_by_addr(idevman, bus_number, dev_number);
|
||||
if (pdev != NULL)
|
||||
return 0;
|
||||
|
||||
if (flag == UDEVMAN_FLAG_ADD_BY_ADDR)
|
||||
{
|
||||
pdev = udev_new_by_addr(bus_number, dev_number);
|
||||
if (pdev == NULL)
|
||||
return 0;
|
||||
|
||||
pdev->set_UsbDevice(pdev, UsbDevice);
|
||||
idevman->loading_lock(idevman);
|
||||
if (udevman->head == NULL)
|
||||
{
|
||||
/* linked list is empty */
|
||||
udevman->head = pdev;
|
||||
udevman->tail = pdev;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* append device to the end of the linked list */
|
||||
udevman->tail->set_p_next(udevman->tail, pdev);
|
||||
pdev->set_p_prev(pdev, udevman->tail);
|
||||
udevman->tail = pdev;
|
||||
}
|
||||
udevman->device_num += 1;
|
||||
idevman->loading_unlock(idevman);
|
||||
}
|
||||
else if (flag == UDEVMAN_FLAG_ADD_BY_VID_PID)
|
||||
{
|
||||
addnum = 0;
|
||||
/* register all device that match pid vid */
|
||||
num = udev_new_by_id(idVendor, idProduct, &devArray);
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
pdev = devArray[i];
|
||||
if (udevman_get_udevice_by_addr(idevman,
|
||||
pdev->get_bus_number(pdev),
|
||||
pdev->get_dev_number(pdev))
|
||||
!= NULL)
|
||||
{
|
||||
zfree(pdev);
|
||||
continue;
|
||||
}
|
||||
|
||||
pdev->set_UsbDevice(pdev, UsbDevice);
|
||||
idevman->loading_lock(idevman);
|
||||
if (udevman->head == NULL)
|
||||
{
|
||||
/* linked list is empty */
|
||||
udevman->head = pdev;
|
||||
udevman->tail = pdev;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* append device to the end of the linked list */
|
||||
udevman->tail->set_p_next(udevman->tail, pdev);
|
||||
pdev->set_p_prev(pdev, udevman->tail);
|
||||
udevman->tail = pdev;
|
||||
}
|
||||
udevman->device_num += 1;
|
||||
idevman->loading_unlock(idevman);
|
||||
addnum++;
|
||||
}
|
||||
zfree(devArray);
|
||||
return addnum;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("udevman_register_udevice: function error!!");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
udevman_unregister_udevice(IUDEVMAN * idevman, int bus_number, int dev_number)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
UDEVICE * pdev, * dev;
|
||||
int ret = 0, err = 0;
|
||||
|
||||
dev = (UDEVICE *)udevman_get_udevice_by_addr(idevman, bus_number, dev_number);
|
||||
|
||||
idevman->loading_lock(idevman);
|
||||
idevman->rewind(idevman);
|
||||
while (idevman->has_next(idevman) != 0)
|
||||
{
|
||||
pdev = (UDEVICE *)idevman->get_next(idevman);
|
||||
|
||||
if (pdev == dev) /* device exists */
|
||||
{
|
||||
/* set previous device to point to next device */
|
||||
|
||||
if (dev->prev != NULL)
|
||||
{
|
||||
/* unregistered device is not the head */
|
||||
pdev = dev->prev;
|
||||
pdev->next = dev->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* unregistered device is the head, update head */
|
||||
udevman->head = (IUDEVICE*)dev->next;
|
||||
}
|
||||
|
||||
/* set next device to point to previous device */
|
||||
|
||||
if (dev->next != NULL)
|
||||
{
|
||||
/* unregistered device is not the tail */
|
||||
pdev = (UDEVICE *)dev->next;
|
||||
pdev->prev = dev->prev;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* unregistered device is the tail, update tail */
|
||||
udevman->tail = (IUDEVICE*)dev->prev;
|
||||
}
|
||||
udevman->device_num--;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
idevman->loading_unlock(idevman);
|
||||
|
||||
if (dev)
|
||||
{
|
||||
/* reset device */
|
||||
if (err != LIBUSB_ERROR_NO_DEVICE)
|
||||
{
|
||||
ret = libusb_reset_device(dev->libusb_handle);
|
||||
if (ret<0){
|
||||
LLOGLN(10, ("libusb_reset_device: ERROR!!ret:%d\n", ret));
|
||||
}
|
||||
}
|
||||
|
||||
/* release all interface and attach kernel driver */
|
||||
dev->iface.attach_kernel_driver((IUDEVICE*)dev);
|
||||
|
||||
if(dev->request_queue) zfree(dev->request_queue);
|
||||
/* free the config descriptor that send from windows */
|
||||
msusb_msconfig_free(dev->MsConfig);
|
||||
|
||||
libusb_close (dev->libusb_handle);
|
||||
libusb_close (dev->hub_handle);
|
||||
|
||||
sem_destroy(&dev->sem_id);
|
||||
/* free device info */
|
||||
if (dev->devDescriptor)
|
||||
zfree(dev->devDescriptor);
|
||||
if (dev)
|
||||
zfree(dev);
|
||||
return 1; /* unregistration successful */
|
||||
}
|
||||
|
||||
|
||||
/* if we reach this point, the device wasn't found */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
udevman_parse_device_addr (char *str, int *id1, int *id2, char sign)
|
||||
{
|
||||
char s1[8], *s2;
|
||||
memset(s1, 0, sizeof(s1));
|
||||
|
||||
s2 = (strchr(str, sign)) + 1;
|
||||
strncpy(s1, str, strlen(str) - (strlen(s2)+1));
|
||||
|
||||
*id1 = atoi(s1);
|
||||
*id2 = atoi(s2);
|
||||
}
|
||||
|
||||
static void
|
||||
udevman_parse_device_pid_vid (char *str, int *id1, int *id2, char sign)
|
||||
{
|
||||
char s1[8], *s2;
|
||||
memset(s1, 0, sizeof(s1));
|
||||
|
||||
s2 = (strchr(str, sign)) + 1;
|
||||
strncpy(s1, str, strlen(str) - (strlen(s2)+1));
|
||||
|
||||
*id1 = (int) strtol(s1, NULL, 16);
|
||||
*id2 = (int) strtol(s2, NULL, 16);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
udevman_check_device_exist_by_id(IUDEVMAN * idevman, uint16 idVendor, uint16 idProduct)
|
||||
{
|
||||
if (libusb_open_device_with_vid_pid (NULL, idVendor, idProduct))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
udevman_is_auto_add(IUDEVMAN * idevman)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
return (udevman->flags & UDEVMAN_FLAG_ADD_BY_AUTO) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
static IUDEVICE*
|
||||
udevman_get_udevice_by_UsbDevice_try_again(IUDEVMAN * idevman, uint32 UsbDevice)
|
||||
{
|
||||
UDEVICE * pdev;
|
||||
idevman->loading_lock(idevman);
|
||||
idevman->rewind (idevman);
|
||||
while (idevman->has_next (idevman))
|
||||
{
|
||||
pdev = (UDEVICE *)idevman->get_next (idevman);
|
||||
if (pdev->UsbDevice == UsbDevice)
|
||||
{
|
||||
idevman->loading_unlock(idevman);
|
||||
return (IUDEVICE *)pdev;
|
||||
}
|
||||
}
|
||||
idevman->loading_unlock(idevman);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static IUDEVICE*
|
||||
udevman_get_udevice_by_UsbDevice(IUDEVMAN * idevman, uint32 UsbDevice)
|
||||
{
|
||||
UDEVICE * pdev;
|
||||
idevman->loading_lock(idevman);
|
||||
idevman->rewind (idevman);
|
||||
while (idevman->has_next (idevman))
|
||||
{
|
||||
pdev = (UDEVICE *)idevman->get_next (idevman);
|
||||
if (pdev->UsbDevice == UsbDevice)
|
||||
{
|
||||
idevman->loading_unlock(idevman);
|
||||
return (IUDEVICE *)pdev;
|
||||
}
|
||||
}
|
||||
idevman->loading_unlock(idevman);
|
||||
/* try again */
|
||||
pdev = (UDEVICE *)idevman->get_udevice_by_UsbDevice_try_again(idevman, UsbDevice);
|
||||
if (pdev)
|
||||
{
|
||||
return (IUDEVICE *)pdev;
|
||||
}
|
||||
|
||||
LLOGLN(libusb_debug, ("udevman_get_udevice_by_UsbDevice: 0x%x ERROR!!\n",
|
||||
UsbDevice));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
udevman_loading_lock(IUDEVMAN * idevman)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
pthread_mutex_lock(&udevman->devman_loading);
|
||||
}
|
||||
|
||||
static void
|
||||
udevman_loading_unlock(IUDEVMAN * idevman)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
pthread_mutex_unlock(&udevman->devman_loading);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
udevman_wait_urb(IUDEVMAN * idevman)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
sem_wait(&udevman->sem_urb_lock);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
udevman_push_urb(IUDEVMAN * idevman)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
sem_post(&udevman->sem_urb_lock);
|
||||
}
|
||||
|
||||
|
||||
BASIC_STATE_FUNC_DEFINED(defUsbDevice, uint32)
|
||||
BASIC_STATE_FUNC_DEFINED(device_num, int)
|
||||
BASIC_STATE_FUNC_DEFINED(sem_timeout, int)
|
||||
|
||||
|
||||
static void
|
||||
udevman_free(IUDEVMAN* idevman)
|
||||
{
|
||||
UDEVMAN * udevman = (UDEVMAN *) idevman;
|
||||
pthread_mutex_destroy(&udevman->devman_loading);
|
||||
sem_destroy(&udevman->sem_urb_lock);
|
||||
|
||||
libusb_exit(NULL);
|
||||
|
||||
/* free udevman */
|
||||
if (udevman)
|
||||
zfree(udevman);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
udevman_load_interface(UDEVMAN * udevman)
|
||||
{
|
||||
/* standard */
|
||||
udevman->iface.free = udevman_free;
|
||||
/* manage devices */
|
||||
udevman->iface.rewind = udevman_rewind;
|
||||
udevman->iface.get_next = udevman_get_next;
|
||||
udevman->iface.has_next = udevman_has_next;
|
||||
udevman->iface.register_udevice = udevman_register_udevice;
|
||||
udevman->iface.unregister_udevice = udevman_unregister_udevice;
|
||||
udevman->iface.get_udevice_by_UsbDevice = udevman_get_udevice_by_UsbDevice;
|
||||
udevman->iface.get_udevice_by_UsbDevice_try_again =
|
||||
udevman_get_udevice_by_UsbDevice_try_again;
|
||||
/* Extension */
|
||||
udevman->iface.check_device_exist_by_id = udevman_check_device_exist_by_id;
|
||||
udevman->iface.isAutoAdd = udevman_is_auto_add;
|
||||
/* Basic state */
|
||||
BASIC_STATE_FUNC_REGISTER(defUsbDevice, udevman);
|
||||
BASIC_STATE_FUNC_REGISTER(device_num, udevman);
|
||||
BASIC_STATE_FUNC_REGISTER(sem_timeout, udevman);
|
||||
/* control semaphore or mutex lock */
|
||||
udevman->iface.loading_lock = udevman_loading_lock;
|
||||
udevman->iface.loading_unlock = udevman_loading_unlock;
|
||||
udevman->iface.push_urb = udevman_push_urb;
|
||||
udevman->iface.wait_urb = udevman_wait_urb;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int FreeRDPUDEVMANEntry(PFREERDP_URBDRC_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
UDEVMAN* udevman;
|
||||
RDP_PLUGIN_DATA * plugin_data = pEntryPoints->plugin_data;
|
||||
uint32 UsbDevice = BASE_USBDEVICE_NUM;
|
||||
char * token;
|
||||
char * message = "id";
|
||||
char hardware_id[16];
|
||||
int idVendor;
|
||||
int idProduct;
|
||||
int bus_number;
|
||||
int dev_number;
|
||||
int success = 0;
|
||||
|
||||
libusb_init(NULL);
|
||||
|
||||
udevman = (PUDEVMAN)malloc(sizeof(UDEVMAN));
|
||||
udevman->device_num = 0;
|
||||
udevman->idev = NULL;
|
||||
udevman->head = NULL;
|
||||
udevman->tail = NULL;
|
||||
udevman->sem_timeout = 0;
|
||||
udevman->flags = UDEVMAN_FLAG_ADD_BY_VID_PID;
|
||||
|
||||
pthread_mutex_init(&udevman->devman_loading, NULL);
|
||||
sem_init(&udevman->sem_urb_lock, 0, MAX_URB_REQUSET_NUM);
|
||||
|
||||
/* load usb device service management */
|
||||
udevman_load_interface(udevman);
|
||||
|
||||
/* set debug flag, to enable Debug message for usb data transfer*/
|
||||
if (plugin_data->data[2])
|
||||
message = (char *)plugin_data->data[2];
|
||||
|
||||
if (strstr(message, "id"))
|
||||
udevman->flags = UDEVMAN_FLAG_ADD_BY_VID_PID;
|
||||
else if (strstr(message, "addr"))
|
||||
udevman->flags = UDEVMAN_FLAG_ADD_BY_ADDR;
|
||||
|
||||
if (strstr(message, "auto"))
|
||||
udevman->flags |= UDEVMAN_FLAG_ADD_BY_AUTO;
|
||||
libusb_debug = 10;
|
||||
if (strstr(message, "debug"))
|
||||
{
|
||||
libusb_debug = 0;
|
||||
udevman->flags |= UDEVMAN_FLAG_DEBUG;
|
||||
}
|
||||
/* register all usb device */
|
||||
token = strtok((char *)plugin_data->data[1], "#");
|
||||
while (token)
|
||||
{
|
||||
bus_number = 0;
|
||||
dev_number = 0;
|
||||
idVendor = 0;
|
||||
idProduct = 0;
|
||||
|
||||
strcpy(hardware_id, token);
|
||||
token = strtok(NULL, "#");
|
||||
if (udevman->flags & UDEVMAN_FLAG_ADD_BY_VID_PID)
|
||||
{
|
||||
udevman_parse_device_pid_vid(hardware_id, &idVendor,
|
||||
&idProduct,
|
||||
'_');
|
||||
success = udevman->iface.register_udevice((IUDEVMAN *)udevman,
|
||||
0,
|
||||
0,
|
||||
UsbDevice,
|
||||
(uint16) idVendor,
|
||||
(uint16) idProduct,
|
||||
UDEVMAN_FLAG_ADD_BY_VID_PID);
|
||||
}
|
||||
else if (udevman->flags & UDEVMAN_FLAG_ADD_BY_ADDR)
|
||||
{
|
||||
udevman_parse_device_addr(hardware_id, &bus_number,
|
||||
&dev_number,
|
||||
'_');
|
||||
success = udevman->iface.register_udevice((IUDEVMAN *)udevman,
|
||||
bus_number,
|
||||
dev_number,
|
||||
UsbDevice,
|
||||
0,
|
||||
0,
|
||||
UDEVMAN_FLAG_ADD_BY_ADDR);
|
||||
}
|
||||
|
||||
if (success)
|
||||
UsbDevice++;
|
||||
}
|
||||
|
||||
udevman->defUsbDevice = UsbDevice;
|
||||
|
||||
pEntryPoints->pRegisterUDEVMAN(pEntryPoints->plugin, (IUDEVMAN*) udevman);
|
||||
|
||||
return 0;
|
||||
}
|
188
channels/urbdrc/libusb/request_queue.c
Normal file
188
channels/urbdrc/libusb/request_queue.c
Normal file
@ -0,0 +1,188 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* RemoteFX USB Redirection
|
||||
*
|
||||
* Copyright 2012 Atrust corp.
|
||||
* Copyright 2012 Alfred Liu <alfred.liu@atruscorp.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "request_queue.h"
|
||||
|
||||
|
||||
|
||||
|
||||
TRANSFER_REQUEST*
|
||||
request_queue_get_next(REQUEST_QUEUE* queue)
|
||||
{
|
||||
TRANSFER_REQUEST* request;
|
||||
|
||||
request = queue->ireq;
|
||||
queue->ireq = (TRANSFER_REQUEST *)queue->ireq->next;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
int
|
||||
request_queue_has_next(REQUEST_QUEUE* queue)
|
||||
{
|
||||
if (queue->ireq == NULL)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
TRANSFER_REQUEST*
|
||||
request_queue_register_request(REQUEST_QUEUE* queue, uint32 RequestId,
|
||||
struct libusb_transfer * transfer,
|
||||
uint8 endpoint)
|
||||
{
|
||||
TRANSFER_REQUEST* request;
|
||||
|
||||
request = (TRANSFER_REQUEST*)malloc(sizeof(TRANSFER_REQUEST));
|
||||
|
||||
request->prev = NULL;
|
||||
request->next = NULL;
|
||||
|
||||
request->RequestId = RequestId;
|
||||
request->transfer = transfer;
|
||||
request->endpoint = endpoint;
|
||||
request->submit = 0;
|
||||
pthread_mutex_lock(&queue->request_loading);
|
||||
if (queue->head == NULL)
|
||||
{
|
||||
/* linked queue is empty */
|
||||
queue->head = request;
|
||||
queue->tail = request;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* append data to the end of the linked queue */
|
||||
queue->tail->next = (void*)request;
|
||||
request->prev = (void*)queue->tail;
|
||||
queue->tail = request;
|
||||
}
|
||||
queue->request_num += 1;
|
||||
pthread_mutex_unlock(&queue->request_loading);
|
||||
return request;
|
||||
}
|
||||
|
||||
void
|
||||
request_queue_rewind(REQUEST_QUEUE *queue)
|
||||
{
|
||||
queue->ireq = queue->head;
|
||||
}
|
||||
|
||||
/* Get first*/
|
||||
TRANSFER_REQUEST*
|
||||
request_queue_get_request_by_endpoint(REQUEST_QUEUE *queue, uint8 ep)
|
||||
{
|
||||
TRANSFER_REQUEST * request;
|
||||
pthread_mutex_lock(&queue->request_loading);
|
||||
queue->rewind (queue);
|
||||
while (queue->has_next (queue))
|
||||
{
|
||||
request = queue->get_next (queue);
|
||||
if (request->endpoint == ep)
|
||||
{
|
||||
pthread_mutex_unlock(&queue->request_loading);
|
||||
return request;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&queue->request_loading);
|
||||
printf("request_queue_get_request_by_id: ERROR!!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
request_queue_unregister_request(REQUEST_QUEUE *queue, uint32 RequestId)
|
||||
{
|
||||
TRANSFER_REQUEST *request, *request_temp;
|
||||
pthread_mutex_lock(&queue->request_loading);
|
||||
queue->rewind(queue);
|
||||
|
||||
while (queue->has_next(queue) != 0)
|
||||
{
|
||||
request = queue->get_next(queue);
|
||||
if (request->RequestId == RequestId)
|
||||
{
|
||||
|
||||
if (request->prev != NULL)
|
||||
{
|
||||
request_temp = (TRANSFER_REQUEST*)request->prev;
|
||||
request_temp->next = (TRANSFER_REQUEST*)request->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
queue->head = (TRANSFER_REQUEST*)request->next;
|
||||
}
|
||||
|
||||
if (request->next != NULL)
|
||||
{
|
||||
request_temp = (TRANSFER_REQUEST*)request->next;
|
||||
request_temp->prev = (TRANSFER_REQUEST*)request->prev;
|
||||
}
|
||||
else
|
||||
{
|
||||
queue->tail = (TRANSFER_REQUEST*)request->prev;
|
||||
|
||||
}
|
||||
|
||||
queue->request_num--;
|
||||
|
||||
if (request)
|
||||
{
|
||||
request->transfer = NULL;
|
||||
zfree(request);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&queue->request_loading);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&queue->request_loading);
|
||||
/* it wasn't found */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
REQUEST_QUEUE*
|
||||
request_queue_new()
|
||||
{
|
||||
REQUEST_QUEUE* queue;
|
||||
|
||||
queue = (REQUEST_QUEUE*)malloc(sizeof(REQUEST_QUEUE));
|
||||
queue->request_num = 0;
|
||||
queue->ireq = NULL;
|
||||
queue->head = NULL;
|
||||
queue->tail = NULL;
|
||||
|
||||
pthread_mutex_init(&queue->request_loading, NULL);
|
||||
|
||||
/* load service */
|
||||
queue->get_next = request_queue_get_next;
|
||||
queue->has_next = request_queue_has_next;
|
||||
queue->rewind = request_queue_rewind;
|
||||
queue->register_request = request_queue_register_request;
|
||||
queue->unregister_request = request_queue_unregister_request;
|
||||
queue->get_request_by_ep = request_queue_get_request_by_endpoint;
|
||||
|
||||
return queue;
|
||||
}
|
||||
|
65
channels/urbdrc/libusb/request_queue.h
Normal file
65
channels/urbdrc/libusb/request_queue.h
Normal file
@ -0,0 +1,65 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* RemoteFX USB Redirection
|
||||
*
|
||||
* Copyright 2012 Atrust corp.
|
||||
* Copyright 2012 Alfred Liu <alfred.liu@atruscorp.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __REQUEST_QUEUE_H
|
||||
#define __REQUEST_QUEUE_H
|
||||
|
||||
#include "urbdrc_types.h"
|
||||
|
||||
typedef struct _TRANSFER_REQUEST TRANSFER_REQUEST;
|
||||
typedef struct _REQUEST_QUEUE REQUEST_QUEUE;
|
||||
|
||||
struct _TRANSFER_REQUEST
|
||||
{
|
||||
void* request;
|
||||
void* prev;
|
||||
void* next;
|
||||
|
||||
uint32 RequestId;
|
||||
uint8 endpoint;
|
||||
struct libusb_transfer *transfer;
|
||||
int submit;
|
||||
};
|
||||
|
||||
|
||||
struct _REQUEST_QUEUE
|
||||
{
|
||||
int request_num;
|
||||
TRANSFER_REQUEST* ireq; /* iterator request */
|
||||
TRANSFER_REQUEST* head; /* head request in linked queue */
|
||||
TRANSFER_REQUEST* tail; /* tail request in linked queue */
|
||||
|
||||
pthread_mutex_t request_loading;
|
||||
|
||||
/* request queue manager service */
|
||||
void (*rewind) (REQUEST_QUEUE *queue);
|
||||
int (*has_next) (REQUEST_QUEUE* queue);
|
||||
int (*unregister_request) (REQUEST_QUEUE *queue, uint32 RequestId);
|
||||
TRANSFER_REQUEST *(*get_next) (REQUEST_QUEUE* queue);
|
||||
TRANSFER_REQUEST *(*get_request_by_ep) (REQUEST_QUEUE *queue, uint8 ep);
|
||||
TRANSFER_REQUEST *(*register_request) (REQUEST_QUEUE* queue,
|
||||
uint32 RequestId, struct libusb_transfer * transfer, uint8 endpoint);
|
||||
};
|
||||
|
||||
|
||||
REQUEST_QUEUE* request_queue_new();
|
||||
|
||||
|
||||
#endif /* __REQUEST_QUEUE_H */
|
@ -92,6 +92,10 @@ struct _IWTSVirtualChannelManager
|
||||
This is a FreeRDP extension to standard MS API. */
|
||||
int (*PushEvent) (IWTSVirtualChannelManager* pChannelMgr,
|
||||
RDP_EVENT* pEvent);
|
||||
/* Find the channel or ID to send data to a specific endpoint. */
|
||||
uint32 (*GetChannelId) (IWTSVirtualChannel * channel);
|
||||
IWTSVirtualChannel* (*FindChannelById) (IWTSVirtualChannelManager* pChannelMgr,
|
||||
uint32 ChannelId);
|
||||
};
|
||||
|
||||
struct _IWTSPlugin
|
||||
|
148
include/freerdp/utils/msusb.h
Normal file
148
include/freerdp/utils/msusb.h
Normal file
@ -0,0 +1,148 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* RemoteFX USB Redirection
|
||||
*
|
||||
* Copyright 2012 Atrust corp.
|
||||
* Copyright 2012 Alfred Liu <alfred.liu@atruscorp.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __MSCONFIG_H
|
||||
#define __MSCONFIG_H
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/utils/memory.h>
|
||||
#include <freerdp/utils/stream.h>
|
||||
|
||||
/* a safer free helper */
|
||||
#define zfree(p) do { if (p != NULL) {free(p); p = NULL;} } while (0)
|
||||
|
||||
/* Data maintenance helper only used in URBDRC */
|
||||
#define data_read_uint8(_p, _v) do { _v = \
|
||||
*((uint8 *) (_p)); \
|
||||
} while (0)
|
||||
#define data_read_uint16(_p, _v) do { _v = \
|
||||
((uint16) (*((uint8 *) (_p)))) + \
|
||||
((uint16) (*(((uint8 *) (_p)) + 1)) << 8); \
|
||||
} while (0)
|
||||
#define data_read_uint32(_p, _v) do { _v = \
|
||||
(uint32) (*((uint8 *) (_p))) + \
|
||||
((uint32) (*(((uint8 *) (_p)) + 1)) << 8) + \
|
||||
((uint32) (*(((uint8 *) (_p)) + 2)) << 16) + \
|
||||
((uint32) (*(((uint8 *) (_p)) + 3)) << 24); \
|
||||
} while (0)
|
||||
#define data_read_uint64(_p, _v) do { _v = \
|
||||
(uint64) (*((uint8 *) (_p))) + \
|
||||
((uint64) (*(((uint8 *) (_p)) + 1)) << 8) + \
|
||||
((uint64) (*(((uint8 *) (_p)) + 2)) << 16) + \
|
||||
((uint64) (*(((uint8 *) (_p)) + 3)) << 24) + \
|
||||
((uint64) (*(((uint8 *) (_p)) + 4)) << 32) + \
|
||||
((uint64) (*(((uint8 *) (_p)) + 5)) << 40) + \
|
||||
((uint64) (*(((uint8 *) (_p)) + 6)) << 48) + \
|
||||
((uint64) (*(((uint8 *) (_p)) + 7)) << 56); \
|
||||
} while (0)
|
||||
|
||||
#define data_write_uint8(_p, _v) do { \
|
||||
*((uint8 *) _p) = (uint8) (_v); \
|
||||
} while (0)
|
||||
#define data_write_uint16(_p, _v) do { \
|
||||
*((uint8 *) _p) = (uint8) (((uint16) (_v)) & 0xff); \
|
||||
*(((uint8 *) _p) + 1) = (uint8) ((((uint16) (_v)) >> 8) & 0xff); \
|
||||
} while (0)
|
||||
#define data_write_uint32(_p, _v) do { \
|
||||
*((uint8 *) _p) = (uint8) (((uint32) (_v)) & 0xff); \
|
||||
*(((uint8 *) _p) + 1) = (uint8) ((((uint32) (_v)) >> 8) & 0xff); \
|
||||
*(((uint8 *) _p) + 2) = (uint8) ((((uint32) (_v)) >> 16) & 0xff); \
|
||||
*(((uint8 *) _p) + 3) = (uint8) ((((uint32) (_v)) >> 24) & 0xff); \
|
||||
} while (0)
|
||||
#define data_write_uint64(_p, _v) do { \
|
||||
*((uint8 *) _p) = (uint8) (((uint64) (_v)) & 0xff); \
|
||||
*(((uint8 *) _p) + 1) = (uint8) ((((uint64) (_v)) >> 8) & 0xff); \
|
||||
*(((uint8 *) _p) + 2) = (uint8) ((((uint64) (_v)) >> 16) & 0xff); \
|
||||
*(((uint8 *) _p) + 3) = (uint8) ((((uint64) (_v)) >> 24) & 0xff); \
|
||||
*(((uint8 *) _p) + 4) = (uint8) ((((uint64) (_v)) >> 32) & 0xff); \
|
||||
*(((uint8 *) _p) + 5) = (uint8) ((((uint64) (_v)) >> 40) & 0xff); \
|
||||
*(((uint8 *) _p) + 6) = (uint8) ((((uint64) (_v)) >> 48) & 0xff); \
|
||||
*(((uint8 *) _p) + 7) = (uint8) ((((uint64) (_v)) >> 56) & 0xff); \
|
||||
} while (0)
|
||||
|
||||
typedef struct _MSUSB_INTERFACE_DESCRIPTOR MSUSB_INTERFACE_DESCRIPTOR;
|
||||
typedef struct _MSUSB_PIPE_DESCRIPTOR MSUSB_PIPE_DESCRIPTOR;
|
||||
typedef struct _MSUSB_CONFIG_DESCRIPTOR MSUSB_CONFIG_DESCRIPTOR;
|
||||
|
||||
struct _MSUSB_PIPE_DESCRIPTOR
|
||||
{
|
||||
uint16 MaximumPacketSize;
|
||||
uint32 MaximumTransferSize;
|
||||
uint32 PipeFlags;
|
||||
uint32 PipeHandle;
|
||||
uint8 bEndpointAddress;
|
||||
uint8 bInterval;
|
||||
uint8 PipeType;
|
||||
int InitCompleted;
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
struct _MSUSB_INTERFACE_DESCRIPTOR
|
||||
{
|
||||
uint16 Length;
|
||||
uint16 NumberOfPipesExpected;
|
||||
uint8 InterfaceNumber;
|
||||
uint8 AlternateSetting;
|
||||
uint32 NumberOfPipes;
|
||||
uint32 InterfaceHandle;
|
||||
uint8 bInterfaceClass;
|
||||
uint8 bInterfaceSubClass;
|
||||
uint8 bInterfaceProtocol;
|
||||
MSUSB_PIPE_DESCRIPTOR ** MsPipes;
|
||||
int InitCompleted;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct _MSUSB_CONFIG_DESCRIPTOR
|
||||
{
|
||||
uint16 wTotalLength;
|
||||
uint8 bConfigurationValue;
|
||||
uint32 ConfigurationHandle;
|
||||
uint32 NumInterfaces;
|
||||
MSUSB_INTERFACE_DESCRIPTOR ** MsInterfaces;
|
||||
int InitCompleted;
|
||||
int MsOutSize;
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
/* MSUSB_PIPE exported functions */
|
||||
void
|
||||
msusb_mspipes_replace(MSUSB_INTERFACE_DESCRIPTOR * MsInterface, MSUSB_PIPE_DESCRIPTOR ** NewMsPipes, uint32 NewNumberOfPipes);
|
||||
|
||||
/* MSUSB_INTERFACE exported functions */
|
||||
void
|
||||
msusb_msinterface_replace(MSUSB_CONFIG_DESCRIPTOR * MsConfig, uint8 InterfaceNumber, MSUSB_INTERFACE_DESCRIPTOR * NewMsInterface);
|
||||
MSUSB_INTERFACE_DESCRIPTOR *
|
||||
msusb_msinterface_read(uint8 * data, uint32 data_size, int * offset);
|
||||
int
|
||||
msusb_msinterface_write(MSUSB_INTERFACE_DESCRIPTOR * MsInterface, uint8 * data, int * offset);
|
||||
|
||||
/* MSUSB_CONFIG exported functions */
|
||||
MSUSB_CONFIG_DESCRIPTOR *
|
||||
msusb_msconfig_new();
|
||||
void
|
||||
msusb_msconfig_free(MSUSB_CONFIG_DESCRIPTOR * MsConfig);
|
||||
MSUSB_CONFIG_DESCRIPTOR *
|
||||
msusb_msconfig_read(uint8 * data, uint32 data_size, uint32 NumInterfaces);
|
||||
int
|
||||
msusb_msconfig_write(MSUSB_CONFIG_DESCRIPTOR * MsConfg, uint8 * data, int * offset);
|
||||
void
|
||||
msusb_msconfig_dump(MSUSB_CONFIG_DESCRIPTOR * MsConfg);
|
||||
|
||||
#endif
|
@ -29,6 +29,7 @@ set(${MODULE_PREFIX}_SRCS
|
||||
hexdump.c
|
||||
list.c
|
||||
file.c
|
||||
msusb.c
|
||||
load_plugin.c
|
||||
memory.c
|
||||
passphrase.c
|
||||
|
368
libfreerdp/utils/msusb.c
Normal file
368
libfreerdp/utils/msusb.c
Normal file
@ -0,0 +1,368 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol client.
|
||||
* RemoteFX USB Redirection
|
||||
*
|
||||
* Copyright 2012 Atrust corp.
|
||||
* Copyright 2012 Alfred Liu <alfred.liu@atruscorp.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <freerdp/utils/debug.h>
|
||||
#include <freerdp/utils/msusb.h>
|
||||
|
||||
static MSUSB_PIPE_DESCRIPTOR *
|
||||
msusb_mspipe_new()
|
||||
{
|
||||
MSUSB_PIPE_DESCRIPTOR * MsPipe = (MSUSB_PIPE_DESCRIPTOR *)malloc(sizeof(MSUSB_PIPE_DESCRIPTOR));
|
||||
memset(MsPipe, 0, sizeof(MSUSB_PIPE_DESCRIPTOR));
|
||||
return MsPipe;
|
||||
}
|
||||
|
||||
static void
|
||||
msusb_mspipes_free(MSUSB_PIPE_DESCRIPTOR ** MsPipes, uint32 NumberOfPipes)
|
||||
{
|
||||
int pnum = 0;
|
||||
if (MsPipes)
|
||||
{
|
||||
for (pnum = 0; pnum < NumberOfPipes && MsPipes[pnum]; pnum++)
|
||||
{
|
||||
zfree(MsPipes[pnum]);
|
||||
}
|
||||
zfree(MsPipes);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
msusb_mspipes_replace(MSUSB_INTERFACE_DESCRIPTOR * MsInterface, MSUSB_PIPE_DESCRIPTOR ** NewMsPipes, uint32 NewNumberOfPipes)
|
||||
{
|
||||
/* free orignal MsPipes */
|
||||
msusb_mspipes_free(MsInterface->MsPipes, MsInterface->NumberOfPipes);
|
||||
/* And replace it */
|
||||
MsInterface->MsPipes = NewMsPipes;
|
||||
MsInterface->NumberOfPipes = NewNumberOfPipes;
|
||||
|
||||
}
|
||||
|
||||
static MSUSB_PIPE_DESCRIPTOR **
|
||||
msusb_mspipes_read(uint8 * data, uint32 data_size, uint32 NumberOfPipes, int * offset)
|
||||
{
|
||||
MSUSB_PIPE_DESCRIPTOR ** MsPipes;
|
||||
int pnum, move = 0;
|
||||
|
||||
MsPipes = (MSUSB_PIPE_DESCRIPTOR **)malloc(NumberOfPipes *
|
||||
sizeof(MSUSB_PIPE_DESCRIPTOR *));
|
||||
|
||||
for(pnum = 0;pnum < NumberOfPipes; pnum++)
|
||||
{
|
||||
MSUSB_PIPE_DESCRIPTOR * MsPipe = msusb_mspipe_new();
|
||||
|
||||
data_read_uint16(data + move, MsPipe->MaximumPacketSize);
|
||||
data_read_uint32(data + move + 4, MsPipe->MaximumTransferSize);
|
||||
data_read_uint32(data + move + 8, MsPipe->PipeFlags);
|
||||
move += 12;
|
||||
/* Already set to zero by memset
|
||||
MsPipe->PipeHandle = 0;
|
||||
MsPipe->bEndpointAddress = 0;
|
||||
MsPipe->bInterval = 0;
|
||||
MsPipe->PipeType = 0;
|
||||
MsPipe->InitCompleted = 0;
|
||||
*/
|
||||
|
||||
MsPipes[pnum] = MsPipe;
|
||||
}
|
||||
*offset += move;
|
||||
|
||||
return MsPipes;
|
||||
}
|
||||
|
||||
static MSUSB_INTERFACE_DESCRIPTOR *
|
||||
msusb_msinterface_new()
|
||||
{
|
||||
MSUSB_INTERFACE_DESCRIPTOR * MsInterface = (MSUSB_INTERFACE_DESCRIPTOR *)malloc(sizeof(MSUSB_INTERFACE_DESCRIPTOR));
|
||||
memset(MsInterface, 0, sizeof(MSUSB_INTERFACE_DESCRIPTOR));
|
||||
return MsInterface;
|
||||
}
|
||||
|
||||
static void
|
||||
msusb_msinterface_free(MSUSB_INTERFACE_DESCRIPTOR * MsInterface)
|
||||
{
|
||||
if (MsInterface)
|
||||
{
|
||||
msusb_mspipes_free(MsInterface->MsPipes, MsInterface->NumberOfPipes);
|
||||
MsInterface->MsPipes = NULL;
|
||||
zfree(MsInterface);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
msusb_msinterface_free_list(MSUSB_INTERFACE_DESCRIPTOR ** MsInterfaces, uint32 NumInterfaces)
|
||||
{
|
||||
int inum = 0;
|
||||
|
||||
if (MsInterfaces)
|
||||
{
|
||||
for (inum = 0; inum < NumInterfaces; inum++)
|
||||
{
|
||||
msusb_msinterface_free(MsInterfaces[inum]);
|
||||
}
|
||||
zfree(MsInterfaces);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
msusb_msinterface_replace(MSUSB_CONFIG_DESCRIPTOR * MsConfig, uint8 InterfaceNumber, MSUSB_INTERFACE_DESCRIPTOR * NewMsInterface)
|
||||
{
|
||||
msusb_msinterface_free(MsConfig->MsInterfaces[InterfaceNumber]);
|
||||
MsConfig->MsInterfaces[InterfaceNumber] = NewMsInterface;
|
||||
}
|
||||
|
||||
MSUSB_INTERFACE_DESCRIPTOR *
|
||||
msusb_msinterface_read(uint8 * data, uint32 data_size, int * offset)
|
||||
{
|
||||
MSUSB_INTERFACE_DESCRIPTOR * MsInterface;
|
||||
|
||||
MsInterface = msusb_msinterface_new();
|
||||
|
||||
data_read_uint16(data, MsInterface->Length);
|
||||
data_read_uint16(data + 2, MsInterface->NumberOfPipesExpected);
|
||||
data_read_uint8(data + 4, MsInterface->InterfaceNumber);
|
||||
data_read_uint8(data + 5, MsInterface->AlternateSetting);
|
||||
data_read_uint32(data + 8, MsInterface->NumberOfPipes);
|
||||
*offset += 12;
|
||||
|
||||
MsInterface->InterfaceHandle = 0;
|
||||
MsInterface->bInterfaceClass = 0;
|
||||
MsInterface->bInterfaceSubClass = 0;
|
||||
MsInterface->bInterfaceProtocol = 0;
|
||||
MsInterface->InitCompleted = 0;
|
||||
MsInterface->MsPipes = NULL;
|
||||
|
||||
if (MsInterface->NumberOfPipes > 0)
|
||||
{
|
||||
MsInterface->MsPipes =
|
||||
msusb_mspipes_read(data+(*offset), data_size-(*offset), MsInterface->NumberOfPipes, offset);
|
||||
}
|
||||
|
||||
return MsInterface;
|
||||
}
|
||||
|
||||
int
|
||||
msusb_msinterface_write(MSUSB_INTERFACE_DESCRIPTOR * MsInterface, uint8 * data, int * offset)
|
||||
{
|
||||
MSUSB_PIPE_DESCRIPTOR ** MsPipes;
|
||||
MSUSB_PIPE_DESCRIPTOR * MsPipe;
|
||||
int pnum = 0, move = 0;
|
||||
|
||||
/* Length */
|
||||
data_write_uint16(data, MsInterface->Length);
|
||||
/* InterfaceNumber */
|
||||
data_write_uint8(data + 2, MsInterface->InterfaceNumber);
|
||||
/* AlternateSetting */
|
||||
data_write_uint8(data + 3, MsInterface->AlternateSetting);
|
||||
/* bInterfaceClass */
|
||||
data_write_uint8(data + 4, MsInterface->bInterfaceClass);
|
||||
/* bInterfaceSubClass */
|
||||
data_write_uint8(data + 5, MsInterface->bInterfaceSubClass);
|
||||
/* bInterfaceProtocol */
|
||||
data_write_uint8(data + 6, MsInterface->bInterfaceProtocol);
|
||||
/* Padding */
|
||||
data_write_uint8(data + 7, 0);
|
||||
/* InterfaceHandle */
|
||||
data_write_uint32(data + 8, MsInterface->InterfaceHandle);
|
||||
/* NumberOfPipes */
|
||||
data_write_uint32(data + 12, MsInterface->NumberOfPipes);
|
||||
move += 16;
|
||||
/* Pipes */
|
||||
MsPipes = MsInterface->MsPipes;
|
||||
for(pnum = 0; pnum < MsInterface->NumberOfPipes; pnum++)
|
||||
{
|
||||
MsPipe = MsPipes[pnum];
|
||||
/* MaximumPacketSize */
|
||||
data_write_uint16(data + move, MsPipe->MaximumPacketSize);
|
||||
/* EndpointAddress */
|
||||
data_write_uint8(data + move + 2, MsPipe->bEndpointAddress);
|
||||
/* Interval */
|
||||
data_write_uint8(data + move + 3, MsPipe->bInterval);
|
||||
/* PipeType */
|
||||
data_write_uint32(data + move + 4, MsPipe->PipeType);
|
||||
/* PipeHandle */
|
||||
data_write_uint32(data + move + 8, MsPipe->PipeHandle);
|
||||
/* MaximumTransferSize */
|
||||
data_write_uint32(data + move + 12, MsPipe->MaximumTransferSize);
|
||||
/* PipeFlags */
|
||||
data_write_uint32(data + move + 16, MsPipe->PipeFlags);
|
||||
|
||||
move += 20;
|
||||
}
|
||||
|
||||
*offset += move;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MSUSB_INTERFACE_DESCRIPTOR **
|
||||
msusb_msinterface_read_list(uint8 * data, uint32 data_size, uint32 NumInterfaces)
|
||||
{
|
||||
MSUSB_INTERFACE_DESCRIPTOR ** MsInterfaces;
|
||||
int inum, offset = 0;
|
||||
|
||||
MsInterfaces = (MSUSB_INTERFACE_DESCRIPTOR **)malloc(NumInterfaces *
|
||||
sizeof(MSUSB_INTERFACE_DESCRIPTOR *));
|
||||
|
||||
for(inum = 0; inum < NumInterfaces; inum++)
|
||||
{
|
||||
MsInterfaces[inum] = msusb_msinterface_read(data + offset, data_size - offset, &offset);
|
||||
}
|
||||
|
||||
|
||||
return MsInterfaces;
|
||||
}
|
||||
|
||||
int
|
||||
msusb_msconfig_write(MSUSB_CONFIG_DESCRIPTOR * MsConfg, uint8 * data, int * offset)
|
||||
{
|
||||
MSUSB_INTERFACE_DESCRIPTOR ** MsInterfaces;
|
||||
MSUSB_INTERFACE_DESCRIPTOR * MsInterface;
|
||||
int inum = 0;
|
||||
|
||||
/* ConfigurationHandle*/
|
||||
data_write_uint32(data + *offset, MsConfg->ConfigurationHandle);
|
||||
/* NumInterfaces*/
|
||||
data_write_uint32(data + *offset + 4, MsConfg->NumInterfaces);
|
||||
*offset += 8;
|
||||
/* Interfaces */
|
||||
MsInterfaces = MsConfg->MsInterfaces;
|
||||
for(inum = 0; inum < MsConfg->NumInterfaces; inum++)
|
||||
{
|
||||
MsInterface = MsInterfaces[inum];
|
||||
msusb_msinterface_write(MsInterface, data + (*offset), offset);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MSUSB_CONFIG_DESCRIPTOR *
|
||||
msusb_msconfig_new()
|
||||
{
|
||||
MSUSB_CONFIG_DESCRIPTOR * MsConfig = NULL;
|
||||
MsConfig = (MSUSB_CONFIG_DESCRIPTOR *)malloc(sizeof(MSUSB_CONFIG_DESCRIPTOR));
|
||||
memset(MsConfig, 0, sizeof(MSUSB_CONFIG_DESCRIPTOR));
|
||||
|
||||
return MsConfig;
|
||||
}
|
||||
|
||||
void
|
||||
msusb_msconfig_free(MSUSB_CONFIG_DESCRIPTOR * MsConfig)
|
||||
{
|
||||
if (MsConfig)
|
||||
{
|
||||
msusb_msinterface_free_list(MsConfig->MsInterfaces, MsConfig->NumInterfaces);
|
||||
MsConfig->MsInterfaces = NULL;
|
||||
zfree(MsConfig);
|
||||
}
|
||||
}
|
||||
|
||||
MSUSB_CONFIG_DESCRIPTOR *
|
||||
msusb_msconfig_read(uint8 * data, uint32 data_size, uint32 NumInterfaces)
|
||||
{
|
||||
MSUSB_CONFIG_DESCRIPTOR * MsConfig;
|
||||
uint8 lenConfiguration, typeConfiguration;
|
||||
uint16 lenInterface;
|
||||
int i, offset = 0;
|
||||
|
||||
MsConfig = msusb_msconfig_new();
|
||||
|
||||
for(i = 0; i < NumInterfaces; i++)
|
||||
{
|
||||
data_read_uint16(data + offset, lenInterface);
|
||||
offset += lenInterface;
|
||||
}
|
||||
data_read_uint8(data + offset, lenConfiguration);
|
||||
data_read_uint8(data + offset + 1, typeConfiguration);
|
||||
if (lenConfiguration != 0x9 || typeConfiguration != 0x2)
|
||||
{
|
||||
DEBUG("%s: len and type must be 0x9 and 0x2 , but it is 0x%x and 0x%x",
|
||||
lenConfiguration, typeConfiguration);
|
||||
}
|
||||
data_read_uint16(data + offset + 2, MsConfig->wTotalLength);
|
||||
data_read_uint8(data + offset + 5, MsConfig->bConfigurationValue);
|
||||
MsConfig->NumInterfaces = NumInterfaces;
|
||||
MsConfig->ConfigurationHandle = 0;
|
||||
MsConfig->InitCompleted = 0;
|
||||
MsConfig->MsOutSize = 0;
|
||||
MsConfig->MsInterfaces = NULL;
|
||||
offset = 0;
|
||||
|
||||
if (NumInterfaces > 0)
|
||||
{
|
||||
MsConfig->MsInterfaces =
|
||||
msusb_msinterface_read_list(data, data_size, NumInterfaces);
|
||||
}
|
||||
|
||||
return MsConfig;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
msusb_msconfig_dump(MSUSB_CONFIG_DESCRIPTOR * MsConfig)
|
||||
{
|
||||
MSUSB_INTERFACE_DESCRIPTOR ** MsInterfaces;
|
||||
MSUSB_INTERFACE_DESCRIPTOR * MsInterface;
|
||||
MSUSB_PIPE_DESCRIPTOR ** MsPipes;
|
||||
MSUSB_PIPE_DESCRIPTOR * MsPipe;
|
||||
int inum = 0, pnum = 0;
|
||||
|
||||
printf("=================MsConfig:========================\n");
|
||||
printf("wTotalLength:%d\n", MsConfig->wTotalLength);
|
||||
printf("bConfigurationValue:%d\n", MsConfig->bConfigurationValue);
|
||||
printf("ConfigurationHandle:0x%x\n", MsConfig->ConfigurationHandle);
|
||||
printf("InitCompleted:%d\n", MsConfig->InitCompleted);
|
||||
printf("MsOutSize:%d\n", MsConfig->MsOutSize);
|
||||
printf("NumInterfaces:%d\n\n", MsConfig->NumInterfaces);
|
||||
MsInterfaces = MsConfig->MsInterfaces;
|
||||
for(inum = 0; inum < MsConfig->NumInterfaces; inum++)
|
||||
{
|
||||
MsInterface = MsInterfaces[inum];
|
||||
printf(" Interfase: %d\n", MsInterface->InterfaceNumber);
|
||||
printf(" Length: %d\n", MsInterface->Length);
|
||||
printf(" NumberOfPipesExpected: %d\n", MsInterface->NumberOfPipesExpected);
|
||||
printf(" AlternateSetting: %d\n", MsInterface->AlternateSetting);
|
||||
printf(" NumberOfPipes: %d\n", MsInterface->NumberOfPipes);
|
||||
printf(" InterfaceHandle: 0x%x\n", MsInterface->InterfaceHandle);
|
||||
printf(" bInterfaceClass: 0x%x\n", MsInterface->bInterfaceClass);
|
||||
printf(" bInterfaceSubClass: 0x%x\n", MsInterface->bInterfaceSubClass);
|
||||
printf(" bInterfaceProtocol: 0x%x\n", MsInterface->bInterfaceProtocol);
|
||||
printf(" InitCompleted: %d\n\n", MsInterface->InitCompleted);
|
||||
MsPipes = MsInterface->MsPipes;
|
||||
for (pnum = 0; pnum < MsInterface->NumberOfPipes; pnum++)
|
||||
{
|
||||
MsPipe = MsPipes[pnum];
|
||||
printf(" Pipe: %d\n", pnum);
|
||||
printf(" MaximumPacketSize: 0x%x\n", MsPipe->MaximumPacketSize);
|
||||
printf(" MaximumTransferSize: 0x%x\n", MsPipe->MaximumTransferSize);
|
||||
printf(" PipeFlags: 0x%x\n", MsPipe->PipeFlags);
|
||||
printf(" PipeHandle: 0x%x\n", MsPipe->PipeHandle);
|
||||
printf(" bEndpointAddress: 0x%x\n", MsPipe->bEndpointAddress);
|
||||
printf(" bInterval: %d\n", MsPipe->bInterval);
|
||||
printf(" PipeType: 0x%x\n", MsPipe->PipeType);
|
||||
printf(" InitCompleted: %d\n\n", MsPipe->InitCompleted);
|
||||
}
|
||||
}
|
||||
printf("==================================================\n");
|
||||
}
|
@ -411,8 +411,11 @@ int svc_plugin_send(rdpSvcPlugin* plugin, STREAM* data_out)
|
||||
|
||||
DEBUG_SVC("length %d", (int) stream_get_length(data_out));
|
||||
|
||||
error = plugin->channel_entry_points.pVirtualChannelWrite(plugin->priv->open_handle,
|
||||
stream_get_data(data_out), stream_get_length(data_out), data_out);
|
||||
if (!plugin || !plugin->priv)
|
||||
error = CHANNEL_RC_BAD_INIT_HANDLE;
|
||||
else
|
||||
error = plugin->channel_entry_points.pVirtualChannelWrite(plugin->priv->open_handle,
|
||||
stream_get_data(data_out), stream_get_length(data_out), data_out);
|
||||
|
||||
if (error != CHANNEL_RC_OK)
|
||||
{
|
||||
@ -436,3 +439,4 @@ int svc_plugin_send_event(rdpSvcPlugin* plugin, RDP_EVENT* event)
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user