为何在rusb(Rust libusb绑定库)中调用claim_interface失败?
问题:调用libusb的claim_interface时触发NotFound错误
我尝试用Rust通过libusb向Pixel6设备写入Bulk数据以学习其用法,代码省略了大部分错误处理,但调用claim_interface时出现NotFound错误,根据rusb文档,该错误表示指定接口编号不存在。请问错误原因是什么?
错误日志
[timestamp] [threadID] facility level [function call] <message> -------------------------------------------------------------------------------- [ 0.005973] [000015a8] libusb: debug [libusb_get_device_list] [ 0.005981] [000015a8] libusb: debug [libusb_get_device_descriptor] [ 0.005983] [000015a8] libusb: debug [libusb_open] open 7.8 [ 0.006006] [000015a8] libusb: debug [usbi_add_event_source] add fd 7 events 4 [ 0.006009] [000015a8] libusb: debug [libusb_get_device_descriptor] [ 0.006011] [000015a8] libusb: debug [libusb_get_config_descriptor] index 0 [ 0.006015] [000015a8] libusb: debug [parse_endpoint] skipping descriptor 0x30 [ 0.006016] [000015a8] libusb: debug [parse_endpoint] skipping descriptor 0x30 [ 0.006021] [000015a8] libusb: debug [libusb_kernel_driver_active] interface 0 [ 0.006023] [000015a8] libusb: debug [libusb_set_configuration] configuration 0 [ 0.007677] [000015a8] libusb: debug [libusb_claim_interface] interface 0 thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: NotFound', src/bulk.rs:37:68 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace [ 0.007738] [000015a8] libusb: debug [libusb_close] [ 0.007743] [000015a8] libusb: debug [usbi_remove_event_source] remove fd 7
问题代码
use rusb::devices; use rusb::Direction::{In, Out}; use rusb::TransferType::{Bulk, Control}; use rusb::{open_device_with_vid_pid, TransferType}; use std::time::Duration; pub fn pixel6_bulk() { write_to_device(6353, 20199, Bulk); } fn write_to_device(vendor_id: u16, product_id: u16, ttype: TransferType) { let mut has_kernel_driver: bool = false; if let Some(mut device_handle) = open_device_with_vid_pid(vendor_id, product_id) { let dev = device_handle.device(); let dd = dev.device_descriptor().unwrap(); let num_config = dd.num_configurations(); for p in 0..num_config { let cd = dev.config_descriptor(p).unwrap(); let ifaces = cd.interfaces(); for iface in ifaces { let inumber = iface.number(); let ifds = iface.descriptors(); for ifd in ifds { let setting_number = ifd.setting_number(); for efd in ifd.endpoint_descriptors() { if efd.direction() == Out && efd.transfer_type() == ttype { let buf: &[u8] = "Hello".as_bytes(); let endpoint_address = efd.address(); if device_handle.kernel_driver_active(inumber).unwrap() { has_kernel_driver = match device_handle.detach_kernel_driver(inumber) { Ok(_) => true, _ => false, }; } //let endpoint_number = efd.number(); device_handle.set_active_configuration(p).unwrap(); device_handle.claim_interface(inumber).unwrap(); device_handle .set_alternate_setting(inumber, setting_number) .unwrap(); match device_handle.write_bulk( endpoint_address, buf, Duration::new(2, 0), ) { Ok(n) => println!("{} bytes was written with bulk", n), Err(_) => println!("Write_bulk was failed"), } if has_kernel_driver { match device_handle.attach_kernel_driver(inumber) { Ok(_) => (), Err(_) => println!("Kernel driver attach failed"), } } device_handle.release_interface(inumber).unwrap(); } } } } } } else { panic!("There is no device"); } }
错误原因分析
1. 配置与接口操作顺序颠倒
你当前的逻辑是先枚举所有配置下的接口和端点,找到符合条件的端点后才调用set_active_configuration(p)切换配置。但USB设备切换配置后,之前枚举的接口信息会失效,此时尝试申请的接口属于未激活的配置,自然会返回NotFound错误。
2. 接口有效性依赖当前激活配置
USB设备的接口属于特定配置,只有当前激活的配置下的接口才能被申请。你在未激活目标配置的情况下就获取了接口编号,后续切换配置后该接口编号可能在新配置中不存在,或者无法被访问。
修正方案
调整操作顺序,先激活目标配置,再枚举该配置下的接口和端点,最后执行接口申请和数据传输:
use rusb::Direction::{In, Out}; use rusb::TransferType::{Bulk, Control}; use rusb::{open_device_with_vid_pid, TransferType}; use std::time::Duration; pub fn pixel6_bulk() { write_to_device(6353, 20199, Bulk); } fn write_to_device(vendor_id: u16, product_id: u16, ttype: TransferType) { let mut has_kernel_driver: bool = false; if let Some(mut device_handle) = open_device_with_vid_pid(vendor_id, product_id) { let dev = device_handle.device(); let dd = dev.device_descriptor().unwrap(); // 遍历所有配置,先激活再处理接口 for config_idx in 0..dd.num_configurations() { let cd = dev.config_descriptor(config_idx).unwrap(); // 先激活当前配置 if let Err(e) = device_handle.set_active_configuration(config_idx) { eprintln!("激活配置{}失败: {}", config_idx, e); continue; } let ifaces = cd.interfaces(); for iface in ifaces { let inumber = iface.number(); let ifds = iface.descriptors(); for ifd in ifds { let setting_number = ifd.setting_number(); for efd in ifd.endpoint_descriptors() { if efd.direction() == Out && efd.transfer_type() == ttype { let buf: &[u8] = "Hello".as_bytes(); let endpoint_address = efd.address(); // 检查并分离内核驱动 if device_handle.kernel_driver_active(inumber).unwrap_or(false) { has_kernel_driver = match device_handle.detach_kernel_driver(inumber) { Ok(_) => true, Err(e) => { eprintln!("分离接口{}的内核驱动失败: {}", inumber, e); false } }; } // 申请接口 if let Err(e) = device_handle.claim_interface(inumber) { eprintln!("申请接口{}失败: {}", inumber, e); if has_kernel_driver { let _ = device_handle.attach_kernel_driver(inumber); } continue; } // 设置替代设置 if let Err(e) = device_handle.set_alternate_setting(inumber, setting_number) { eprintln!("为接口{}设置替代设置{}失败: {}", inumber, setting_number, e); let _ = device_handle.release_interface(inumber); if has_kernel_driver { let _ = device_handle.attach_kernel_driver(inumber); } continue; } // 执行Bulk写入 match device_handle.write_bulk(endpoint_address, buf, Duration::new(2, 0)) { Ok(n) => println!("通过Bulk写入{}字节", n), Err(e) => println!("Bulk写入失败: {}", e), } // 释放资源 let _ = device_handle.release_interface(inumber); if has_kernel_driver { match device_handle.attach_kernel_driver(inumber) { Ok(_) => (), Err(e) => println!("重新挂载内核驱动失败: {}", e), } } } } } } } } else { panic!("未找到匹配设备"); } }
内容的提问来源于stack exchange,提问作者KiYugadgeter
相关产品推荐
相关产品推荐

