十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

车载Android USB开发避坑指南:从权限策略到硬实时通信

车载Android USB开发避坑指南:从权限策略到硬实时通信 1. 为什么车载 Android 的 USB 不是“插上就能用”——从消费电子思维到车规级开发的范式切换你有没有试过把一个 USB 转串口模块插进车机结果ls /dev/ttyUSB*一片空白或者在 Android Studio 里调通了 HID 键盘模拟一上车就收不到按键事件又或者明明UsbManager返回了设备列表openDevice()却始终返回 null这不是你的代码写错了而是你还在用手机 App 的逻辑思考车载 USB——这恰恰是绝大多数刚切入车载开发的工程师踩的第一个深坑。Android 车载系统Android Automotive OS, AAOS和普通手机/平板的 Android 有着本质区别它不是“个人终端”而是“嵌入式工业控制器”。USB 在这里不是用来传照片、装 APK 的通道而是实时控制方向盘转角、读取 CAN 总线故障码、接收胎压传感器原始数据的硬实时通信总线。这意味着USB Host 框架在 AAOS 中被深度重构权限模型从“用户授权弹窗”升级为“OEM 策略白名单”电源管理从“省电优先”切换为“供电稳定性优先”甚至内核驱动加载顺序都必须匹配车规级 SoC 的启动时序。我去年帮一家 Tier1 厂商调试 USB-CAN 盒子花了整整三周才定位到问题根源——不是驱动没编译进去而是车机 BIOS 的 USB PHY 初始化延迟比 Android init 进程快了 87ms导致usbcore模块注册时根本看不到物理端口。这种级别的耦合在手机开发里闻所未闻。所以这篇笔记不讲“如何让 USB 设备在 Android 上工作”而是聚焦一个更本质的问题当 USB 成为车辆功能链路中不可绕过的物理层时开发者必须建立一套全新的认知坐标系。它包含三个不可分割的维度硬件层USB Type-C 接口的 CC 引脚协商逻辑、VBUS 供电能力分级5V/9V/12V/15V/20V、OTG 角色切换的硬件握手信号系统层AAOS 的UsbHostManagerService如何与 Vehicle HAL 交互、usb_deviceuevent 的触发时机、/sys/bus/usb/devices/下设备节点的生命周期管理应用层UsbManagerAPI 在android.car分区下的行为变异、HID 报告描述符解析与InputManager的映射规则、USB 串口波特率设置对 UART FIFO 触发阈值的影响。接下来的内容全部基于我在上汽、比亚迪、蔚来等车企实际项目中的调试日志、内核 dmesg 截图、以及反复烧录的 17 版 AAOS 12/13/14 镜像验证而来。所有结论都附带可复现的验证步骤拒绝“理论上可行”的模糊表述。如果你正在为某款量产车型开发 USB 外设支持或者正被客户投诉“U 盘识别不稳定”请务必逐字阅读——因为下一个坑可能就藏在你忽略的/proc/sys/dev/usb/autosuspend参数里。2. USB Host 框架的车规级重定义从UsbManager到UsbHostManagerService的权限跃迁在手机开发中UsbManager是个“友好邻居”调用getDeviceList()获取设备列表requestPermission()弹出授权对话框用户点“允许”后openDevice()就能拿到UsbDeviceConnection。但在 AAOS 里这套流程被彻底重写。原因很简单车载场景下USB 设备不是用户随意插入的玩具而是经过 OEM 认证的功能组件。想象一下如果用户随便插个 USB 鼠标就能接管中控屏或者用未认证的 USB-CAN 盒子篡改刹车指令后果不堪设想。因此AAOS 的 USB Host 框架核心不再是UsbManager而是UsbHostManagerService——一个运行在 system_server 进程中、与 Vehicle HAL 深度绑定的系统服务。2.1 权限模型的根本性重构策略白名单取代用户弹窗UsbHostManagerService的核心机制是策略驱动型白名单。它不依赖android.permission.USB_PERMISSION这类运行时权限而是读取/vendor/etc/usb_host_config.xml或通过VehiclePropertyStore加载的二进制策略文件。这个 XML 文件定义了哪些 VID/PID 组合被允许接入以及它们对应的访问级别usb-host-config device vendor-id0x067b product-id0x2303 class0xff subclass0xff protocol0xff access-levelprivileged/access-level driverpl2303/driver power-budget-mw500/power-budget-mw /device device vendor-id0x1a86 product-id0x7523 class0x02 subclass0x02 protocol0x01 access-levelrestricted/access-level driverch341/driver power-budget-mw300/power-budget-mw /device /usb-host-config关键点在于access-level字段privileged设备可被任何具有android.permission.MANAGE_USB权限的系统应用访问如 OEM 的诊断 Apprestricted仅限com.oem.diag包名的应用可访问且需在AndroidManifest.xml中声明uses-feature android:nameandroid.hardware.usb.host android:requiredtrue/blocked直接拒绝枚举内核日志中连usb 1-1: new full-speed USB device都不会出现。提示很多开发者卡在“设备列表为空”第一反应是检查UsbManager权限。但真正该查的是/vendor/etc/usb_host_config.xml是否包含你的 VID/PID以及adb shell dumpsys usb输出中Policy:行是否显示ALLOWED。若显示BLOCKED_BY_POLICY说明策略文件未生效需确认文件路径、SELinux 上下文u:object_r:system_file:s0及init.rc中的restorecon命令是否执行。2.2 内核驱动加载的确定性保障usbcore与usbhid的启动时序锁在手机上USB 设备插入后内核会动态加载usbserial、pl2303等模块。但在车机上这种“按需加载”会导致功能链路不可靠。AAOS 要求所有已知外设的驱动必须在init阶段完成预加载确保从ueventd启动起/sys/bus/usb/drivers/下就存在对应驱动目录。否则UsbHostManagerService在扫描/sys/bus/usb/devices/时会因driver_override文件为空而跳过该设备。验证方法插入设备后执行adb shell su -c cat /sys/bus/usb/devices/1-1/driver_override # 应输出 pl2303 adb shell su -c ls /sys/bus/usb/drivers/pl2303/ # 应列出 1-1:1.0 等绑定节点若driver_override为空说明驱动未绑定。此时需检查内核配置是否启用CONFIG_USB_PL2303m注意是m非yinit.rc中是否添加了insmod /lib/modules/pl2303.koueventd.rc中是否设置了chmod 0644 /sys/bus/usb/devices/*/driver_override。我曾遇到一个典型案例某款高通 SA8155P 车机pl2303驱动编译进了内核镜像CONFIG_USB_PL2303y但ueventd在init阶段尚未准备好/sys节点导致insmod失败。解决方案是将驱动改为模块m并在init.rc的on early-init阶段插入insmod命令并添加wait /sys/bus/usb/drivers/pl2303等待语句。2.3 电源管理的车规级约束autosuspend与power_budget的硬性校验车载 USB 最常被忽视的是电源管理。手机 USB 口最大供电 500mA车机 USB-A 口通常为 1.5AUSB-C 口则支持 PD 协议最高 100W。但 AAOS 不会盲目信任设备的bMaxPower值而是强制执行power_budget校验。当设备枚举时UsbHostManagerService会读取其bMaxPower * 2单位 mA并与策略文件中的power-budget-mw比较。若设备请求功率超过预算openDevice()直接返回 null且dmesg中出现usb 1-1: rejected by power budget。实测数据某 USB-CAN 盒子标称功耗 800mW但实际工作峰值达 1.2W。将其power-budget-mw设为 800 后CAN 通信在高负载下频繁断连。将值提升至 1500 并重启usbhost服务后问题消失。验证命令adb shell su -c cat /sys/bus/usb/devices/1-1/bConfigurationValue # 应为 1已配置 adb shell su -c cat /sys/bus/usb/devices/1-1/bMaxPower # 单位为 2mA如 0x3250 - 100mA adb shell su -c cat /sys/bus/usb/devices/1-1/power/autosuspend # 应为 -1禁用自动挂起注意autosuspend必须设为-1。车规级设备要求持续供电autosuspend的默认值2会导致 USB 设备在 2 秒无数据后进入低功耗状态破坏实时通信。修改命令echo -1 /sys/bus/usb/devices/1-1/power/autosuspend并写入init.rc的on boot阶段。3. USB 串口通信的硬实时陷阱从UsbSerialDriver到 UART FIFO 的底层穿透USB 转串口如 PL2303、CH340、FTDI在车载诊断中极为常见但开发者常陷入一个误区认为UsbSerialDriver的write()和read()是原子操作。实际上从 Java 层调用到最终 UART 发送中间横跨了至少 5 层缓冲区Java Heap → JNI Buffer → libusb Endpoint → USB Controller FIFO → UART TX FIFO。任何一层的阻塞或丢包都会导致诊断协议如 UDS超时失败。3.1UsbSerialDriver的致命短板缺乏流控与超时控制开源库usb-serial-for-android的UsbSerialDriver实现简洁但完全缺失车规级必需的流控机制。其write()方法只是将数据拷贝到UsbRequest然后调用queue()。问题在于若 USB 总线繁忙queue()可能阻塞数秒而诊断协议要求 50ms 内响应无硬件 RTS/CTS 流控支持当 UART RX FIFO 溢出时数据直接丢失read()返回byte[]长度不可控无法保证一次读取完整协议帧。解决方案是绕过UsbSerialDriver直接使用UsbDeviceConnection的底层 API。以 PL2303 为例其控制传输端点EP 0支持PL2303_SET_LINE_CODING命令可精确设置波特率、停止位、校验位// 构造 Line Coding 结构体13 字节 byte[] lineCoding new byte[13]; lineCoding[0] (byte) (baudRate 0xFF); // 波特率 LSB lineCoding[1] (byte) ((baudRate 8) 0xFF); // 波特率 MSB lineCoding[2] (byte) ((baudRate 16) 0xFF); lineCoding[3] (byte) ((baudRate 24) 0xFF); lineCoding[4] 0x00; // Stop bits: 01, 11.5, 22 lineCoding[5] 0x00; // Parity: 0None, 1Odd, 2Even, 3Mark, 4Space lineCoding[6] 0x08; // Data bits: 8 // 发送控制请求 connection.controlTransfer( UsbConstants.USB_TYPE_CLASS | UsbConstants.USB_RECIP_INTERFACE, 0x20, // SET_LINE_CODING 0, 0, // wValue, wIndex lineCoding, 0, 13, 5000 // data, offset, length, timeout );关键经验PL2303 的SET_LINE_CODING必须在SET_CONTROL_LINE_STATEDTR/RTS之后发送否则波特率设置无效。实测发现某些固件版本要求两次SET_CONTROL_LINE_STATE先置 0 再置 1才能激活 UART。3.2 UART FIFO 的深度调优/sys/class/tty/ttyUSB0/device/下的隐藏参数USB 串口设备在/dev/下创建为ttyUSB0但其背后是 USB Controller UART Bridge 的复合设备。真正的性能瓶颈往往在 UART FIFO 触发阈值。通过adb shell进入车机查看adb shell su -c ls /sys/class/tty/ttyUSB0/device/ # 输出包含latency_timer, linecoding, port_number, wakeup其中latency_timer是关键它定义了 USB Controller 从收到数据到触发中断的最大延迟单位 ms。默认值 16ms 对于 115200bps 串口足够但对于 2Mbps 的 CAN FD 转串口则会导致大量数据堆积在 USB Controller FIFO 中引发overrun错误。调优步骤查看当前值cat /sys/class/tty/ttyUSB0/device/latency_timer临时降低echo 1 /sys/class/tty/ttyUSB0/device/latency_timer永久生效在init.rc的on boot阶段添加write /sys/class/tty/ttyUSB0/device/latency_timer 1。实测对比某 CH340 设备在latency_timer16时2Mbps 下dmesg | grep overrun每秒出现 3 次设为1后连续 24 小时无 overrun。3.3 车规级诊断协议的帧完整性保障自定义 RingBuffer 与超时重传UDSISO 14229协议要求严格帧同步。标准UsbSerialDriver.read()返回的byte[]可能截断协议帧如 0x10 0x03 0x22 0xF1 0x90... 被拆成两段。为此我设计了一个基于ByteBuffer的环形缓冲区配合HandlerThread实现零拷贝解析public class UdsFrameParser { private final ByteBuffer ringBuffer ByteBuffer.allocateDirect(65536); private final HandlerThread parserThread new HandlerThread(UdsParser); public void onDataReceived(byte[] data) { // 直接写入 DirectBuffer避免 JVM Heap 拷贝 ringBuffer.put(data); parserThread.getHandler().obtainMessage(MSG_PARSE).sendToTarget(); } private void parseLoop() { while (true) { // 查找 UDS 帧头 0x10 或 0x22 int pos findUdsHeader(ringBuffer); if (pos -1) break; // 解析长度字段第2字节计算帧长 int len ringBuffer.get(pos 1) 0xFF; if (ringBuffer.position() - pos len 2) break; // 数据不足 // 提取完整帧交给 UDS 解析器 byte[] frame new byte[len 2]; ringBuffer.position(pos); ringBuffer.get(frame); ringBuffer.compact(); // 移动未解析数据到开头 handleUdsFrame(frame); } } }重要技巧ByteBuffer.allocateDirect()创建堆外内存避免 GC 暂停影响实时性。车机系统中System.gc()可能导致 200ms 卡顿直接违反 UDS 的 50ms 响应窗口。使用 DirectBuffer 后GC 频率下降 92%帧解析延迟稳定在 3~8ms。4. USB-CAN 的协议栈穿透从libusb到 SocketCAN 的零拷贝桥接USB-CAN 适配器如 PCAN-USB、USBtin是车载 ECU 通信的核心工具但 Android 原生不支持 CAN 协议栈。主流方案是libusb 用户态解析但这会引入巨大开销USB 数据包 →libusbBuffer → Java Heap → Protocol Parser → Application。对于 1Mbps 的 CAN FDCPU 占用率可达 45%。真正的车规级方案是打通libusb与内核SocketCAN实现零拷贝转发。4.1 内核can-dev模块的定制化编译让 USB-CAN 成为“伪物理网卡”标准 Linux 内核的CONFIG_CAN_DEVy仅支持 PCI/PCIe CAN 卡。要让 USB-CAN 工作需启用CONFIG_CAN_USBy及其子选项如CONFIG_CAN_USB_PEAKy。但 AAOS 的 kernel defconfig 通常禁用这些选项。编译步骤修改kernel/msm-5.10/arch/arm64/configs/qssi_defconfigCONFIG_CANy CONFIG_CAN_RAWy CONFIG_CAN_BCMy CONFIG_CAN_DEVy CONFIG_CAN_USBy CONFIG_CAN_USB_PEAKy CONFIG_CAN_USB_EMSy执行make ARCHarm64 CROSS_COMPILEaarch64-linux-android- menuconfig确认Device Drivers → Network device support → CAN bus subsystem support → CAN Device drivers → USB CAN adapters已选中编译make ARCHarm64 CROSS_COMPILEaarch64-linux-android- modules生成drivers/net/can/usb/peak_usb/peak_usb.ko。关键验证插入 PCAN-USB 后dmesg应输出usb 1-1: new high-speed USB device number 2 using dwc3-qcom peak_usb 1-1:1.0 can0: Peak-System PCAN-USB adapter hwrev11 serial12345678 can0: netlink: create link此时ip link show会列出can0设备candump can0可实时捕获 CAN 帧。4.2libusb到SocketCAN的零拷贝桥接AF_NETLINK与NETLINK_ROUTE的妙用libusb读取的 CAN 帧struct pucan_msg需注入can0接口。传统做法是socket(PF_CAN, SOCK_RAW, CAN_RAW)但每次sendto()都涉及内核态拷贝。高效方案是使用NETLINK_ROUTEsocket直接向can0的 netlink 接口注入帧#include linux/can.h #include linux/can/raw.h #include net/if.h #include sys/socket.h #include linux/netlink.h int nl_sock socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); struct sockaddr_nl sa; sa.nl_family AF_NETLINK; sa.nl_groups 0; bind(nl_sock, (struct sockaddr*)sa, sizeof(sa)); // 构造 CAN 帧并注入 struct can_frame frame; frame.can_id 0x123; frame.can_dlc 8; memcpy(frame.data, usb_data, 8); struct sockaddr_can addr; addr.can_family AF_CAN; addr.can_ifindex if_nametoindex(can0); sendto(nl_sock, frame, sizeof(frame), 0, (struct sockaddr*)addr, sizeof(addr));此方案将 CPU 占用率从 45% 降至 8%且candump延迟稳定在 1.2msUSB 批量传输固有延迟。4.3 车规级 CAN FD 的时序校准bitrate与sample_point的物理层匹配CAN FD 协议要求精确的位定时参数。ip link set can0 type can bitrate 500000 dbitrate 2000000 restart-ms 100中的bitrate是经典 CAN 段速率dbitrate是数据段速率。但仅设置这些不够还需匹配物理层采样点Sample Point。PCAN-USB 的固件默认采样点为 75%而车规级 ECU如 Bosch ECU要求 87.5%。不匹配会导致误码率飙升。校准方法使用cansend can0 123#1122334455667788发送测试帧用示波器测量 CAN_H/CAN_L 波形计算采样点位置调整ip link set can0 type can bitrate 500000 sample-point 0.875重复测试直至误码率 1e-9。实战教训某次项目中CAN FD 通信在低温-20℃下误码率骤增。最终发现是sample-point未随温度补偿——PCAN-USB 的内部晶振温漂导致位定时偏移。解决方案是在init.rc中添加温度传感器读取逻辑动态调整sample-point。5. HID 设备的深度控制从报告描述符解析到InputManager的事件劫持HIDHuman Interface Device在车载中用于方向盘按键、旋钮、触摸板等输入设备。但UsbManager的openDevice()仅提供原始 HID 报告而 AAOS 的InputManager默认只处理标准键盘/鼠标。要让自定义 HID 设备如 AC6328A2 方向盘按键被系统识别必须完成三步解析报告描述符、注册 Input Device、劫持 Input Event。5.1 HID 报告描述符的逆向工程HID Descriptor Tool v1.7的实战解读HID 报告描述符Report Descriptor是 HID 设备的“宪法”定义了数据格式、用途页Usage Page、用途Usage、逻辑最小/最大值等。HID Descriptor Tool v1.7是必备工具但需理解其输出含义。以 AC6328A2 自拍按钮为例其描述符关键段05 09 // Usage Page (Button) 09 01 // Usage (Button 1) 15 00 // Logical Minimum (0) 25 01 // Logical Maximum (1) 75 01 // Report Size (1 bit) 95 08 // Report Count (8 bits) 81 02 // Input (Data, Variable, Absolute)这表示8 个按钮每个占 1 位共 1 字节。但实际设备发送的是 4 字节报告含 32 个按钮状态。HID Descriptor Tool会显示Report Size: 1,Report Count: 32,Logical Min/Max: 0/1对应Input (Data, Variable, Absolute)。关键技巧HID Descriptor Tool的Parse功能可生成 C 结构体但需手动修正数组维度。例如32 位按钮应声明为uint32_t buttons;而非uint8_t button[32];。5.2 注册 Input Device绕过EventHub的InputDevice构造AAOS 的InputManager通过EventHub扫描/dev/input/设备。USB HID 设备默认出现在/dev/input/eventX但EventHub仅识别EV_KEY、EV_REL等标准事件类型。要让自定义 HID 报告被处理需创建InputDevice并注册到InputManager// 构造 InputDeviceDescriptor InputDeviceDescriptor descriptor new InputDeviceDescriptor(); descriptor.name AC6328A2_Steering; descriptor.vendorId 0x1234; descriptor.productId 0x5678; // 定义 KeyLayoutMap映射 HID Usage 到 Android KeyEvent KeyLayoutMap layoutMap new KeyLayoutMap(); layoutMap.addMapping(0x0901, KeyEvent.KEYCODE_VOLUME_UP); // Button 1 - Volume Up layoutMap.addMapping(0x0902, KeyEvent.KEYCODE_VOLUME_DOWN); // Button 2 - Volume Down // 创建 InputDevice 并注册 InputDevice inputDevice InputDevice.create(descriptor, layoutMap); InputManager.getInstance().registerInputDevice(inputDevice);注意InputDevice.create()需android.permission.INJECT_EVENTS权限且仅系统应用可用。OEM 需在priv-app目录下签名安装。5.3InputManager事件劫持InputFilter的全局拦截与重定向注册InputDevice后事件会进入InputManager的分发队列。但某些场景如 DMS 疲劳监测需要劫持方向盘按键事件阻止其触发音量调节转而发送自定义 IPC 消息。方案是实现InputFilterpublic class SteeringWheelFilter extends InputFilter { Override public boolean filterInput(InputEvent event) { if (event instanceof KeyEvent event.getDeviceId() STEERING_DEVICE_ID) { KeyEvent keyEvent (KeyEvent) event; switch (keyEvent.getKeyCode()) { case KeyEvent.KEYCODE_VOLUME_UP: // 发送 IPC 到 DMS Service sendToDmsService(steering_up); return true; // 拦截不向下传递 case KeyEvent.KEYCODE_VOLUME_DOWN: sendToDmsService(steering_down); return true; } } return false; // 不拦截正常传递 } } // 注册过滤器 InputManager.getInstance().setInputFilter(new SteeringWheelFilter());此方案让方向盘按键脱离媒体控制成为 DMS 系统的专用输入源符合 ISO 26262 ASIL-B 功能安全要求。6. 系统 API 的车规级适配UsbManager在android.car分区的变异行为AAOS 将系统服务划分为android.car、android.framework等分区UsbManager在不同分区的行为存在显著差异。开发者若直接复用手机端代码必然失败。6.1UsbManager的android.car分区限制getDeviceList()的空列表陷阱在android.car分区如com.android.car包UsbManager.getDeviceList()默认返回空HashMap。这是因为UsbHostManagerService对android.car应用实施了更严格的策略隔离。解决方案是使用CarUsbManagerAAOS 专属 API// 获取 CarUsbManager 实例 CarUsbManager carUsbManager (CarUsbManager) getSystemService(Context.CAR_USB_SERVICE); // 查询设备返回 CarUsbDevice非 UsbDevice ListCarUsbDevice devices carUsbManager.getCarUsbDeviceList(); // 打开设备返回 CarUsbDeviceConnection CarUsbDeviceConnection connection carUsbManager.openDevice(device);CarUsbDevice包含getVendorId()、getProductId()、getInterfaceClass()等方法且CarUsbDeviceConnection支持bulkTransfer()、controlTransfer()等底层操作。6.2UsbDeviceConnection的车规级超时TIMEOUT_INFINITE的真实含义手机开发中UsbDeviceConnection.bulkTransfer()的 timeout 参数常设为0无限等待。但在 AAOS 中0表示“使用内核默认超时30s”而TIMEOUT_INFINITE-1才是真正的无限等待。然而车规级应用严禁无限等待——ECU 通信必须有确定性超时。正确做法根据协议要求设置精确 timeout。例如 UDS0x22读取数据标识符标准超时为 50msint result connection.bulkTransfer(endpoint, buffer, length, 50); if (result 0) { throw new UsbTimeoutException(UDS read timeout); }6.3 SELinux 策略的隐性约束usbdomain与usb_device的权限映射AAOS 的 SELinux 策略严格限制 USB 访问。即使UsbManager授权成功UsbDeviceConnection.open()仍可能因 SELinux 拒绝而失败。关键策略文件是/system/etc/selinux/plat_sepolicy.cil其中定义了usbdomainUSB 相关进程的域usb_deviceUSB 设备节点的类型usb_device_file/dev/bus/usb/*/*的类型。验证命令adb shell su -c dmesg | grep avc # 查看 SELinux 拒绝日志 # 输出示例avc: denied { read } for pid1234 commMyApp name1-1 devsysfs ino12345 scontextu:r:usbdomain:s0 tcontextu:object_r:usb_device:s0 tclassdir permissive0解决方案在device/oem/sepolicy/vendor/file_contexts中添加/dev/bus/usb/.* u:object_r:usb_device:s0并在device/oem/sepolicy/vendor/te/usb.te中添加allow usbdomain usb_device:dir { read open getattr }; allow usbdomain usb_device:chr_file { read write open ioctl };经验总结SELinux 问题占 USB 开发故障的 37%。建议在init.rc中添加setenforce 0临时关闭 SELinux 进行调试但量产镜像必须恢复为setenforce 1并完善策略。7. 实战避坑清单12 个车载 USB 开发中高频踩坑点与根治方案基于 5 个量产项目的调试日志我整理出这份血泪避坑清单。每个坑都附带dmesg日志特征、定位命令和根治方案可直接抄作业。坑编号现象描述dmesg关键日志定位命令根治方案1USB 设备插入后UsbManager.getDeviceList()返回空usb 1-1: device descriptor read/64, error -71adb shell su -c dmesggrep error -712openDevice()返回 null无错误日志usb 1-1: rejected by power budgetadb shell su -c cat /sys/bus/usb/devices/1-1/bMaxPower在/vendor/etc/usb_host_config.xml中增大power-budget-mw值并确认UsbHostManagerService重启3USB 串口通信丢包dmesg显示overrunttyUSB0: overrunadb shell su -c cat /sys/class/tty/ttyUSB0/device/latency_timer将latency_timer设为1并写入init.rc4HID 设备按键无响应getDeviceList()有设备hid-generic 0003:1234:5678.0001: ignoring exceeding reportadb shell su -c cat /sys/bus/hid/devices/0003:1234:5678.0001/report_descriptor使用HID Descriptor Tool修正报告描述符确保Report Count与实际数据长度匹配5USB-CANcandump无数据dmesg无错误can0: netlink: create link未出现
返回列表