You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何向指定USB设备发送目标字节序列?(支持Python/Java/Bash无GUI)

解决USB设备字节序列发送问题

我来帮你搞定这个问题——直接往/dev/bus/usb/XXX/XXX写数据失败,本质是因为USB设备通信得遵循USB协议规范,不是像写普通文件那样丢字节流就行。你得先从Wireshark/usbmon的抓包结果里抠出关键参数(比如传输类型、端点地址、控制传输的请求参数),再用对应的工具或库来发送数据。下面分几种语言给你具体方案:

第一步:先确认核心参数(必须做)

从抓包结果里提取以下信息,这是所有方案的基础:

  • 传输类型:是Control(控制传输,最常见的设备指令交互方式)还是Bulk(批量传输)?
  • 如果是控制传输:需要bmRequestType、bRequest、wValue、wIndex这四个参数,以及要发送的字节内容
  • 如果是批量传输:需要目标输出端点地址(比如0x01)

方案1:Bash 实现(适合快速测试)

先确保安装libusb相关工具(Debian/Ubuntu系):

sudo apt install libusb-1.0-0-dev usbutils

控制传输示例

假设你抓包得到的参数是:bmRequestType=0x21、bRequest=0x09、wValue=0x0001、wIndex=0x0000,字节序列是01 02 03,用usb-send命令发送:

sudo usb-send -b 1 -d 5 -t control -r 0x21 -R 0x09 -v 0x0001 -i 0x0000 -D "01 02 03"
  • -b是总线号,-d是设备号(对应你lsusb的Bus 001 Device 005)

批量传输示例

如果是批量传输,先找输出端点地址(比如0x01),可以用lsusb -v -d 04b4:0a0a查看端点信息,然后用pyusb的命令行工具(或者写个简单Python脚本)配合Bash调用:

# 先安装pyusb
pip install pyusb
# 然后写个简单脚本send_bulk.py,再用Bash调用
sudo python3 send_bulk.py

方案2:Python 实现(推荐,灵活易集成)

用pyusb库,这是Python操作USB设备的标准工具,灵活性拉满。

安装依赖

pip install pyusb

控制传输示例

把你抓包的参数填到下面的脚本里:

import usb.core
import usb.util

# 匹配你的设备ID
VENDOR_ID = 0x04b4
PRODUCT_ID = 0x0a0a

# 从抓包提取的控制传输参数
BM_REQUEST_TYPE = 0x21
B_REQUEST = 0x09
W_VALUE = 0x0001
W_INDEX = 0x0000
# 要发送的字节序列(替换成你的抓包内容)
DATA = b'\x01\x02\x03\x04'

# 查找设备
dev = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID)
if not dev:
    raise ValueError("设备未找到,请检查lsusb输出")

# 解除内核驱动绑定(如果设备被内核占用)
if dev.is_kernel_driver_active(0):
    try:
        dev.detach_kernel_driver(0)
    except usb.core.USBError as e:
        raise RuntimeError(f"无法解除内核驱动绑定: {str(e)}")

# 设置设备配置
dev.set_configuration()

# 发送控制传输
try:
    dev.ctrl_transfer(BM_REQUEST_TYPE, B_REQUEST, W_VALUE, W_INDEX, DATA)
    print("字节序列发送成功")
except usb.core.USBError as e:
    print(f"发送失败: {str(e)}")

# 可选:恢复内核驱动绑定(如果需要设备正常使用)
usb.util.dispose_resources(dev)
if not dev.is_kernel_driver_active(0):
    dev.attach_kernel_driver(0)

批量传输示例

如果是批量传输,替换成下面的脚本:

import usb.core
import usb.util

VENDOR_ID = 0x04b4
PRODUCT_ID = 0x0a0a
# 抓包得到的输出端点地址
OUT_ENDPOINT = 0x01
DATA = b'\x01\x02\x03\x04'

dev = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID)
if not dev:
    raise ValueError("设备未找到")

if dev.is_kernel_driver_active(0):
    dev.detach_kernel_driver(0)

dev.set_configuration()

# 获取输出端点
endpoint = dev[0][(0, 0)][OUT_ENDPOINT]

try:
    dev.write(endpoint.bEndpointAddress, DATA)
    print("批量传输发送成功")
except usb.core.USBError as e:
    print(f"发送失败: {str(e)}")

# 恢复驱动绑定
usb.util.dispose_resources(dev)
if not dev.is_kernel_driver_active(0):
    dev.attach_kernel_driver(0)

注意:运行脚本需要sudo权限,或者通过udev规则给普通用户授权(见下文注意事项)。


方案3:Java 实现

用usb4java库,适合Java项目集成。

添加Maven依赖

<dependency>
    <groupId>org.usb4java</groupId>
    <artifactId>usb4java</artifactId>
    <version>1.3.0</version>
</dependency>

控制传输示例代码

import org.usb4java.*;

public class UsbLockSender {
    public static void main(String[] args) {
        // 初始化libusb
        Context context = new Context();
        int result = LibUsb.init(context);
        if (result != LibUsb.SUCCESS) {
            throw new RuntimeException("初始化libusb失败: " + LibUsb.strError(result));
        }

        // 打开设备
        DeviceHandle handle = new DeviceHandle();
        result = LibUsb.openDeviceWithVidPid(context, (short) 0x04b4, (short) 0x0a0a, handle);
        if (result != LibUsb.SUCCESS) {
            throw new RuntimeException("无法打开设备: " + LibUsb.strError(result));
        }

        try {
            // 解除内核驱动绑定
            if (LibUsb.kernelDriverActive(handle, 0)) {
                result = LibUsb.detachKernelDriver(handle, 0);
                if (result != LibUsb.SUCCESS) {
                    throw new RuntimeException("无法解除内核驱动: " + LibUsb.strError(result));
                }
            }

            // 声明接口
            result = LibUsb.claimInterface(handle, 0);
            if (result != LibUsb.SUCCESS) {
                throw new RuntimeException("无法声明接口: " + LibUsb.strError(result));
            }

            // 准备发送数据
            byte[] data = {0x01, 0x02, 0x03, 0x04};
            IntBuffer transferred = IntBuffer.allocate(1);

            // 发送控制传输
            result = LibUsb.controlTransfer(
                handle,
                (byte) 0x21,  // bmRequestType
                (byte) 0x09,  // bRequest
                (short) 0x0001,  // wValue
                (short) 0x0000,  // wIndex
                data,
                transferred,
                1000  // 超时时间(毫秒)
            );

            if (result == LibUsb.SUCCESS) {
                System.out.println("发送成功,传输字节数: " + transferred.get(0));
            } else {
                throw new RuntimeException("控制传输失败: " + LibUsb.strError(result));
            }

        } finally {
            // 释放资源
            LibUsb.releaseInterface(handle, 0);
            if (!LibUsb.kernelDriverActive(handle, 0)) {
                LibUsb.attachKernelDriver(handle, 0);
            }
            LibUsb.close(handle);
            LibUsb.exit(context);
        }
    }
}

关键注意事项

  1. 权限问题:所有操作USB设备的程序都需要root权限,或者你可以创建udev规则给普通用户授权:
    创建/etc/udev/rules.d/50-usb-lock.rules文件:
    SUBSYSTEM=="usb", ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="0a0a", MODE="0666"
    
    然后重新加载规则:
    sudo udevadm control --reload-rules && sudo udevadm trigger
    
  2. 内核驱动占用:如果设备被内核驱动(比如usbhid)占用,必须先解除绑定才能操作,否则会报错。
  3. 参数准确性:所有传输参数必须和抓包结果完全一致,差一个字节都可能无法触发解锁行为。

内容的提问来源于stack exchange,提问作者Salocin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:57:08