spice usb过滤规则

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值