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

使用PyUSB读取TI计算器文件系统时dev.read()超时求助

解决TI计算器USB文件系统读取超时问题

问题根源

你的代码直接调用dev.read()读取IN端点超时,核心原因是TI计算器的USB接口属于Vendor Specific自定义类(从配置信息的bInterfaceClass: 0xff可确认),不是通用存储设备。这类设备不会主动推送数据,必须先通过OUT端点发送符合TI设备协议的命令,设备才会响应并返回数据。

修正方案

需要先获取OUT端点发送协议命令,触发设备返回文件系统数据,再循环读取IN端点的响应。以下是调整后的代码:

import usb.core, usb.util

print("Finding devices...")

# 查找所有TI设备(厂商ID 0x0451)
devices = usb.core.find(find_all=True, idVendor=0x0451)

for dev in devices:
    print("Found a TI calculator!")
    dev.set_configuration()
    cfg = dev.get_active_configuration()
    intf = cfg[(0, 0)]
    
    # 获取Bulk IN(接收数据)和OUT(发送命令)端点
    ep_in = usb.util.find_descriptor(
        intf,
        custom_match=lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_IN 
        and usb.util.endpoint_type(e.bmAttributes) == usb.util.ENDPOINT_TYPE_BULK
    )
    ep_out = usb.util.find_descriptor(
        intf,
        custom_match=lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_OUT 
        and usb.util.endpoint_type(e.bmAttributes) == usb.util.ENDPOINT_TYPE_BULK
    )

    if not ep_in or not ep_out:
        print("Failed to find required endpoints")
        continue

    with open("filesystem.img", "wb") as f:
        data = bytearray()
        try:
            # 1. 发送初始化命令(需根据TI设备协议调整,示例参考libticables2实现)
            init_cmd = b'\x01\x00\x00\x00'
            dev.write(ep_out.bEndpointAddress, init_cmd, timeout=2000)
            
            # 2. 发送读取整个文件系统的命令(示例,需替换为对应型号的实际协议指令)
            # 参考libticables2中TI-84 CE的闪存读取命令格式
            read_fs_cmd = b'\x03\x00\x00\x00\x00\x00\x00\x00'
            dev.write(ep_out.bEndpointAddress, read_fs_cmd, timeout=2000)
            
            # 3. 循环读取数据,直到设备无数据返回或触发正常超时
            while True:
                print("Reading packet...")
                packet = dev.read(ep_in.bEndpointAddress, ep_in.wMaxPacketSize, timeout=2000)
                if len(packet) == 0:
                    break
                data.extend(packet)
                print(f"Received {len(data)} bytes so far")
        
        except usb.core.USBError as e:
            # 超时通常表示数据读取完成(需根据协议确认结束逻辑)
            if e.errno == 110:
                print("Data read completed (normal timeout)")
            else:
                print(f"USB Error: {str(e)}")
        
        f.write(data)
        print(f"Filesystem saved to filesystem.img, total size: {len(data)} bytes")

    usb.util.dispose_resources(dev)

重要补充说明

  1. 协议命令适配:TI不同型号计算器的协议命令有差异,上述示例中的命令仅作参考。建议直接参考libticables2(TiLP工具的底层库)的源码,找到TI-84 Plus CE-T对应的初始化、闪存读取命令序列,确保命令准确。
  2. 权限问题:Linux系统下需添加udev规则,赋予普通用户访问TI设备的权限,避免权限拒绝错误。示例规则可参考:
    SUBSYSTEM=="usb", ATTRS{idVendor}=="0451", MODE="0666"
    
  3. 结束条件优化:不要单纯依赖超时判断读取完成,最好解析协议返回的数据包中的长度字段,精准判断是否读取完毕,避免数据截断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 01:02:54