本实验基于Spice-gtk:https://gitlab.freedesktop.org/spice/spice-gtk
在Spice-GTK中的 usb-device-manager.c 中,当我们热插拔USB设备时就会触发到 spice_usb_device_manager_hotplug_idle_cb 函数
static gboolean spice_usb_device_manager_hotplug_idle_cb(gpointer user_data)
{
struct hotplug_idle_cb_args *args = user_data;
SpiceUsbDeviceManager *manager = SPICE_USB_DEVICE_MANAGER(args->manager);
if (args->added) {
//添加设备时
spice_usb_device_manager_add_dev(manager, args->device);
} else {
//移除设备时
spice_usb_device_manager_remove_dev(manager, args->device);
}
spice_usb_backend_device_unref(args->device);
g_object_unref(manager);
g_free(args);
return FALSE;
}
下面,跟着添加设备的函数来看一下内部的逻辑
static void spice_usb_device_manager_add_dev(SpiceUsbDeviceManager *manager, SpiceUsbDevice *bdev)
{
SpiceUsbDeviceManagerPrivate *priv = manager->priv;
const UsbDeviceInformation *b_info = spice_usb_backend_device_get_info(bdev);
SpiceUsbDevice *device;
//首先在设备列表中找到这个设备
if (spice_usb_device_manager_find_device(manager, b_info->bus, b_info->address)) {
SPICE_DEBUG("device not added %d:%d %04x:%04x",
b_info->bus, b_info->address, b_info->vid, b_info->pid);
return;
}
//对设备的引用加一
device = spice_usb_device_new(bdev);
if (!device) {
return;
}
//---------在这添加的过滤代码---------
if (spice_usb_filter_mouse(device)) {
return;
}
g_ptr_array_add(priv->devices, device);
if (priv->auto_connect) {
gboolean can_redirect, auto_ok;
can_redirect = spice_usb_device_manager_can_redirect_device(manager, device, NULL);
auto_ok = spice_usb_backend_device_check_filter(bdev,
priv->auto_conn_filter_rules,
priv->auto_conn_filter_rules_count) == 0;
if (can_redirect && auto_ok) {
spice_usb_device_manager_connect_device_async(manager, device, NULL,
spice_usb_device_manager_auto_connect_cb,
spice_usb_device_ref(device));
}
}
SPICE_DEBUG("device added %04x:%04x (%p)",
spice_usb_device_get_vid(device),
spice_usb_device_get_pid(device),
device);
g_signal_emit(manager, signals[DEVICE_ADDED], 0, device);
}
下面的函数为在 spice_usb_device_manager_add_dev
函数中调用的函数 (可以略过)
//对比 bus 和 address 就是命令 lsusb -D /dev/bus/usb/xxx/xxx 的两个参数
//日志:libusb: debug [linux_get_device_address] bus=4 dev=2
//日志:GSpice-DEBUG: 11:12:10.519: usb-device-manager.c:1111 ---->bus:4 address:0x2
static gboolean spice_usb_device_match(SpiceUsbDevice *device, const int bus, const int address)
{
return (spice_usb_device_get_busnum(device) == bus &&
spice_usb_device_get_devaddr(device) == address);
}
//遍历设备列表,然后找到匹配bus号和address号的USB设备,并返回
static SpiceUsbDevice*
spice_usb_device_manager_find_device(SpiceUsbDeviceManager *manager, const int bus, const int address)
{
SpiceUsbDeviceManagerPrivate *priv = manager->priv;
SpiceUsbDevice *curr, *device = NULL;
guint i;
for (i = 0; i < priv->devices->len; i++) {
curr = g_ptr_array_index(priv->devices, i);
if (spice_usb_device_match(curr, bus, address)) {
device = curr;
break;
}
}
return device;
}
static SpiceUsbDevice *spice_usb_device_new(SpiceUsbDevice *bdev)
{
g_return_val_if_fail(bdev != NULL, NULL);
return spice_usb_backend_device_ref(bdev);
}
//这个函数在usb-backend.c中
SpiceUsbDevice *spice_usb_backend_device_ref(SpiceUsbDevice *dev)
{
LOUD_DEBUG("%s >> %p", __FUNCTION__, dev);
//原子整数操作 对引用计数加一
g_atomic_int_inc(&dev->ref_count);
return dev;
}
添加的函数如下
gboolean spice_usb_filter_mouse(SpiceUsbDevice *device)
{
#ifdef USE_USBREDIR
int e = 0;
char str2[256];
struct libusb_device_handle *handle = NULL;
struct libusb_device_descriptor desc;
//描述符的获取
r = libusb_get_device_descriptor(device, &desc);
if (r < 0)
{
return TRUE;
}
e = libusb_open(libdev, &handle);
if (e < 0)
{
return TRUE;
}
e = libusb_get_string_descriptor_ascii(handle, libdesc.iProduct, (unsigned char*) str2, sizeof(str2));
if(e < 0)
{
return TRUE;
}
SPICE_DEBUG("Product : %s",str2);
if (strstr(str2, "Mouse")!= NULL){
SPICE_DEBUG("鼠标设备");
return TRUE;
}
else if(strstr(str2, "mouse") != NULL){
SPICE_DEBUG("鼠标设备");
return TRUE;
}else{
return FALSE
}
return TRUE;
#endif
return TRUE;
}