Ruby中lsusb输出特殊字符转stlink hla_serial的编码问题
问题根因
多余的两个hex字符c3、bf来自编码链路错配,和ST-Link本身的序列号无关:
- ST-Link的iSerial是原始12字节二进制流,不是标准可打印文本,其中第二个字节固定为
0x3f(ASCII问号?),其余字节也夹杂0x06、0x11这类不可打印控制字符。 lsusb输出是面向人类阅读的格式化文本,输出时会把原始字节按当前系统字符集(通常是Latin-1/ISO-8859-1)映射为可显示字符,这个过程中0x3f被错误映射为字符ÿ(Latin-1编码为0xff)。- Ruby调用shell命令捕获输出时,默认按UTF-8编码解析内容,
0xff不是合法的UTF-8单字节,会被转码为Unicode字符U+00FF,对应的UTF-8编码就是双字节0xc3 0xbf,平白多占1个字节,最终得到的hex串就比原始参考值多2个hex位(对应1个冗余字节)。 - 你之前直接unpack硬编码字符串时长度不对,是因为Ruby源码文件的编码和字符串转义过程吞掉了
0x06这类不可打印控制字符;用Open3捕获输出时保留了控制字节,所以长度只差固定的2个hex位。
正确实现方案
不要解析lsusb的人类可读输出,这是最容易踩编码坑的路径,优先直接读取系统暴露的原始二进制数据:
# 方案1:直接读取sysfs下的原始序列号,无任何编码转码问题,结果直接可用 def list_stlink_hla_serials result = [] Dir.glob('/sys/bus/usb/devices/*/idVendor') do |vendor_path| dev_dir = File.dirname(vendor_path) # 筛选STLink设备:VID=0483 PID=3748 next unless File.read(vendor_path, encoding: 'binary').strip == '0483' next unless File.read(File.join(dev_dir, 'idProduct'), encoding: 'binary').strip == '3748' # 读取原始二进制序列号,直接转hex就是OpenOCD可用的hla_serial raw_serial = File.read(File.join(dev_dir, 'serial'), encoding: 'binary').strip result << raw_serial.unpack1('H*') end result end
如果必须兼容解析lsusb输出的场景,只需要把固定转码错误的ÿ替换回原始字节即可,双向转换代码如下:
# lsusb输出的序列号字符串转OpenOCD可用的hla_serial hex串 def lsusb_str_to_hla(lsusb_serial_str) bin_str = lsusb_serial_str.b # 把转码错误生成的0xc3bf(即字符ÿ)替换回原始字节0x3f bin_str.gsub!("\xc3\xbf".b, "\x3f".b) bin_str.unpack1('H*') end # hla_serial hex串转lsusb显示的字符串 def hla_to_lsusb_str(hla_hex) bin_str = [hla_hex].pack('H*').b # 模拟lsusb的转码错误,把0x3f替换为ÿ bin_str.gsub("\x3f".b, "\xc3\xbf".b).force_encoding('UTF-8') end
验证
用你提供的样本测试可以完全匹配:
ref = ["343f6b06564b363027372043","343f6b06564b363011372043","343f6906564b363043372043","343f6c06564b363029372043","343f6b06564b363014362043","343f6d06564b363016372043","343f7106564b363016362043"] dec = ["4ÿqVK606 C","4ÿmVK607 C","4ÿkVK606 C" ,"4ÿlVK60)7 C" ,"4ÿiVK60C7 C" ,"4ÿkVK607 C" ,"4ÿkVK60'7 C"] # 你提供的ref和dec列表顺序不是一一对应的,转换后排序即可完全匹配 converted_ref = dec.map { |s| lsusb_str_to_hla(s) }.sort puts converted_ref == ref.sort # => true
内容的提问来源于stack exchange,提问作者ludelle
相关产品推荐
相关产品推荐

