1、自动连接规则和重定向连接规则
struct _SpiceUsbDeviceManagerPrivate {
SpiceSession *session;
gboolean auto_connect; //是否自动连接
gchar *auto_connect_filter; //自动连接的过滤规则字符串表示
gchar *redirect_on_connect; //重定向的过滤规则字符串表示
#ifdef USE_USBREDIR
SpiceUsbBackend *context;
struct usbredirfilter_rule *auto_conn_filter_rules; //自动连接过滤规则
struct usbredirfilter_rule *redirect_on_connect_rules;//重定向过滤规则
int auto_conn_filter_rules_count; //自动连接过滤规则条数
int redirect_on_connect_rules_count; //重定向过滤规则条数
gboolean redirecting; //是否开启重定向
#ifdef G_OS_WIN32
usbdk_api_wrapper *usbdk_api;
HANDLE usbdk_hider_handle;
#endif
GPtrArray *devices;
GPtrArray *channels;
#endif
};
2、过滤规则定义结构体
struct usbredirfilter_rule {
int device_class; /* 0-255, -1 to match any class 类型ID*/
int vendor_id; /* 0-65535, -1 to match any id vid号*/
int product_id; /* 0-65535, -1 to match any id pid号*/
int device_version_bcd; /* 0-65535, -1 to match any version bcd版本*/
int allow; /* 0: 拒绝这个设备重定向;非0:允许重定向 */
};
3、以新增设备为例
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;
//触发热插拔事件,从manager中查找到该设备
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;
}
//查找到则创建Spice的USB设备
device = spice_usb_device_new(bdev);
if (!device) {
return;
}
//添加到USB列表中
g_ptr_array_add(priv->devices, device);
//添加设备后是否自动连接
if (priv->auto_connect) {
gboolean can_redirect, auto_ok;
//能否重定向:1.通道是否建立;2.服务器的规则是否允许
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);
}
3.1、检测能否重定向
/**
* spice_usb_device_manager_can_redirect_device:
* @manager: the #SpiceUsbDeviceManager manager
* @device: a #SpiceUsbDevice to disconnect
* @err: (allow-none): a return location for a #GError, or %NULL.
*
* Checks whether it is possible to redirect the @device.
*
* Returns: %TRUE if @device can be redirected
*/
gboolean
spice_usb_device_manager_can_redirect_device(SpiceUsbDeviceManager *manager,SpiceUsbDevice *device,GError **err)
{
#ifdef USE_USBREDIR
const struct usbredirfilter_rule *guest_filter_rules = NULL;
SpiceUsbDeviceManagerPrivate *priv = manager->priv;
int i, guest_filter_rules_count;
g_return_val_if_fail(SPICE_IS_USB_DEVICE_MANAGER(manager), FALSE);
g_return_val_if_fail(device != NULL, FALSE);
g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
if (!spice_session_get_usbredir_enabled(priv->session)) {
g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, _("USB redirection is disabled"));
return FALSE;
}
if (!priv->channels->len) {
g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, _("The connected VM is not configured for USB redirection"));
return FALSE;
}
// 已经连接的设备直接跳过其他检查
if (spice_usb_device_manager_is_device_connected(manager, device)) {
return TRUE;
}
// 我们假设所有通道都有相同的滤波器,所以我们只从第一个通道中取滤波器
spice_usbredir_channel_get_guest_filter(g_ptr_array_index(priv->channels, 0),&guest_filter_rules,&guest_filter_rules_count);
if (guest_filter_rules) {
gboolean filter_ok;
filter_ok = (spice_usb_backend_device_check_filter(device,guest_filter_rules,guest_filter_rules_count) == 0);
if (!filter_ok) {
g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
_("Some USB devices are blocked by host policy"));
return FALSE;
}
}
// 检测是否有空闲的usb通道
for (i = 0; i < priv->channels->len; i++) {
SpiceUsbredirChannel *channel = g_ptr_array_index(priv->channels, i);
spice_usbredir_channel_lock(channel);
if (!spice_usbredir_channel_get_device(channel)){
spice_usbredir_channel_unlock(channel);
break;
}
spice_usbredir_channel_unlock(channel);
}
// 提示错误并返回
if (i == priv->channels->len) {
g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, _("There are no free USB channels"));
return FALSE;
}
return TRUE;
#else
g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, _("USB redirection support not compiled in"));
return FALSE;
#endif
}
3.2、检测本地规则
int spice_usb_backend_device_check_filter(SpiceUsbDevice *dev, const struct usbredirfilter_rule *rules, int count)//count代表规则的数量,rules是规则的数组实体
{
if (dev->libusb_device != NULL) { //libusb管理过滤
return usbredirhost_check_device_filter(rules, count, dev->libusb_device, 0);
} else if (dev->edev != NULL) { //edev管理过滤
return check_edev_device_filter(dev, rules, count);
}
g_warn_if_reached();
return -EINVAL;
}