回顧
在上一篇關於usb的代碼分析https://blog.csdn.net/FlayHigherGT/article/details/85261810中,我們聊到了一些關於usb插入拔出之後spicy迴應的某些回調函數,也聊到了如何實現連接虛擬機時自動重定向已經插着的usb,但是經過最近的研究,發現這個功能其實是在spicy裏面是有功能實現的,下面細說。
spicy兩個功能參數
1、spice-usbredir-auto-redirect-filter 篩選插入的usb設備是否能不用勾選自動重定向到虛擬機內
2、spice-usbredir-redirect-on-connect 篩選spice-channel連接的時候是否能自動重定向已經插在物理機上的usb設備
這是官網對於這兩個參數的用法的解釋https://www.spice-space.org/usbredir.html。默認的參數是0x03,-1,-1,-1,0|-1,-1,-1,-1,1
這個參數是由兩個字符串組成,每個字符串都是五個字段,這些字段的含義分別是:<class>,<vendor>,<product>,<version>,<allow>,前面四個字段是一個usb設備的特徵,表示什麼類型設備啊,兩個id號啊,版本號啊,這些字段都是某一個usb設備的特有的特徵,這些參數中如果是-1,表示不管都可以通過,比如product=-1表示任意product號都ok,最後一個參數表示這樣的設備是否能被重定向,0表示不能,1表示能。
0x03,-1,-1,-1,0|-1,-1,-1,-1,1 0x03鍵鼠設備,後面半段表示所有設備都可以重定向,前面半段表示鍵鼠設備不能重定向,所以整段的意義就是除了鍵鼠設備,其他的設備都能重定向。
下面是libusb中的關於usb的某些特徵枚舉,結構體(決定了第一位是哪類設備):
下面例子是查看usb設備的<vendor>,<product>,<version>等等信息的:
https://blog.csdn.net/FlayHigherGT/article/details/90245349
libusb接口信息:
https://blog.csdn.net/FlayHigherGT/article/details/89297462
代碼分析
usb-device-manager.c中
spice_usb_device_manager_check_redir_on_connect是usb自動連接的代碼函數if (usbredirhost_check_device_filter)是usb自動連接篩選的機制,之後就是進入usbredir子項目內部了
usbredir項目裏面
usbredirhost.c裏面usbredirhost_check_device_filter函數用來篩選usb參數,最終的對比是這樣的:
if (config == NULL) {
return usbredirfilter_check(rules, rules_count, dev_desc.bDeviceClass,
dev_desc.bDeviceSubClass, dev_desc.bDeviceProtocol,
NULL, NULL, NULL, 0,
dev_desc.idVendor, dev_desc.idProduct,
dev_desc.bcdDevice, flags);
}
num_interfaces = config->bNumInterfaces;
printf("usbredir---num_interface=%d\n", num_interfaces);
for (i = 0; i < num_interfaces; i++) {
const struct libusb_interface_descriptor *intf_desc =
config->interface[i].altsetting;
interface_class[i] = intf_desc->bInterfaceClass;
interface_subclass[i] = intf_desc->bInterfaceSubClass;
interface_protocol[i] = intf_desc->bInterfaceProtocol;
printf("usbredir---class=%d, subclass=%d, protocol=%d\n",
interface_class[i], interface_subclass[i], interface_protocol[i]);
//最終對比的class是interface_class(0x03),而interface_subclass始終是1
}
libusb_free_config_descriptor(config);
return usbredirfilter_check(rules, rules_count, dev_desc.bDeviceClass,
dev_desc.bDeviceSubClass, dev_desc.bDeviceProtocol,
interface_class, interface_subclass, interface_protocol,
num_interfaces, dev_desc.idVendor, dev_desc.idProduct,
dev_desc.bcdDevice, flags);
}