Merge pull request #751 from FreeRDP/usb

USB Redirection Integration
This commit is contained in:
Marc-André Moreau 2012-10-02 14:28:48 -07:00
commit 1565e032e5
27 changed files with 8226 additions and 23 deletions

View File

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

View File

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

View File

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

View File

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

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

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

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

File diff suppressed because it is too large Load Diff

View 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

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

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

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

View 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

File diff suppressed because it is too large Load Diff

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

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

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

File diff suppressed because it is too large Load Diff

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

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

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

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

View File

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

View 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

View File

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

View File

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