Skip to content

Latest commit

 

History

History
255 lines (230 loc) · 10.4 KB

README.md

File metadata and controls

255 lines (230 loc) · 10.4 KB

USB Packet Viewer parser

USB Packet Viewer的插件项目,使用lua 5.3.4开发。包含文件读写,USB协议解析功能。

An add-on project for USB Packet viewer, writen in lua 5.3.4.

用scripts目录替换USB Packet Viewer中的scripts.lua文件,以使用最新的解析器。

Replace scripts.lua in USB Packet Viewer with scripts folder here to use the latest parser.

确保目录结构如下 Ensure the directory structure as below:

\---usbpv
    |   usbpv.exe
    |
    \---scripts
            build.bat
            decoder_ethernet.lua
            decoder_rndis.lua
            decoder_scsi.lua
            file_base.lua
            file_iti1480a.lua
            file_pcap.lua
            html.lua
            init.lua
            macro_defs.lua
            upv_parser.lua
            usb_class_cdc_acm.lua
            usb_class_hid.lua
            usb_class_hub.lua
            usb_class_msc_bot.lua
            usb_control_transfer.lua
            usb_descriptor_parser.lua
            usb_device_ftdi.lua
            usb_register_class.lua
            usb_setup_parser.lua
            util.lua

脚本接口说明

-- encoding: UTF8
----------------------------------------
---  USB Packet Viewer 脚本接口说明  ---
----------------------------------------
-- 将此说明内容保存为文本文件,并重命名为scripts.lua,替换自带的脚本可以看到此示例的运行效果

--------------------------------
------  文件相关API开始  -------
-- 文件相关操作的API一共有三个
-- valid_filter 获取支持的文件名后缀
-- open_file    读取文件
-- write_file   写入文件
--------------------------------
-- 返回Qt风格的文件Filter
-- 默认支持 USB Packet Viewer File (*.upv)
function valid_filter()
    return "Text File (*.txt);;All Files (*.*)"
end

-- 打开并读取文件,此函数可以阻塞,不会影响UI
-- 参数说明
--           name              文件名
--           packet_handler    数据回调,当读取到文件中的数据后,调用packet_handler
--           context           调用packet_handler时的传入的第一个参数
-- 返回值(1个)
--           读取的数据包数量

-- packet_handler 函数原型  packet_handler(context, ts, nano, pkt, status, pos, total)
-- packet_handler 参数说明 
--                       context   传入open_file的第三个参数
--                       ts        以秒为单位的时间戳
--                       nano      以纳秒为单位的时间戳
--                       pkt       数据包内容,包含前面的PID和后面的CRC
--                       status    状态值
--                       pos       当前已经读取的文件长度
--                       total     文件总长度
-- packet_handler 返回值(1个)
--                        nil 表示读取到的包处理出错
--                        true 表示处理成功
function open_file(name, packet_handler, context)
    for i=1,10 do
        packet_handler(context, i,i, "\x69\x00\x10", 0, i, 10)
    end
    return 10
end

-- 将数据写入文件,此函数可以阻塞,不会影响UI
-- 参数说明
--           name              文件名
--           packet_handler    数据回调,调用packet_handler获取需要写入文件的数据包,当没有更多的数据包时,返回nil
--           context           调用packet_handler时的传入的第一个参数
-- 返回值(1个)
--           写入的数据包数量

-- packet_handler 函数原型  packet_handler(context)
-- packet_handler 参数说明 
--                       context   write_file
-- packet_handler 返回值(4个)
--                       ts        以秒为单位的时间戳
--                       nano      以纳秒为单位的时间戳
--                       pkt       数据包内容,包含前面的PID和后面的CRC
--                       status    状态值

function write_file(name, packet_handler, context)
    local f = io.open(name, "w+")
    local count = 0
    while f do
        local ts,nano,pkt,status = packet_handler(context)
        if not ts then break end
        f:write(string.format("ts %d, nano %d, status %d:", ts, nano, status&0xff))
        for i=1,#pkt do
            f:write(string.format("%02x ", pkt:byte(i)))
        end
        f:write("\n")
        count = count + 1
    end
    f:close()
    return count
end

--------------------------------
------  解码相关API开始  -------
--------------------------------
-- 解码相关操作的API一共有六个
-- upv_register_decoder   向USBPV注册解码器,此函数由USBPV实现,脚本中只能调用
-- upv_reset_parser       重置解码器
-- upv_parse_transaction  解析Transaction
-- upv_add_decoder        添加解码器
-- upv_remove_decoder     移除解码器
-- upv_valid_parser       获取支持的解码器

-- 注册解码器,此函数由USBPV实现,当脚本需要向USBPV注册解码器时,调用此函数
-- 此函数内部会调用 upv_add_decoder, 用来向脚本添加端点对应的解码器
-- 函数原型 upv_register_decoder(name, param)
-- 参数说明
--          name      解码器名称,脚本中通过名称来区分不同的解码器
--          param     端点参数,格式为由地址和端点序列组成的字符串 string.char(addr,endp1,addr,endp2,...)
--
-- 说明:   此函数会将解码器注册到对应的地址和端点上。
--          USBPV会先检测当前数据包的地址端点是否已经注册,如果没有注册且端点号不为0,不会将数据发给脚本进行解码。
--          端点号为0的数据会直接发往脚本进行解码,不需要预先注册。
local upv_register_decoder = upv_register_decoder

-- 模拟一个 decoder_map
local decoder_map = {}

-- 重置解码器,无参数,无返回值。UI上点击清除按钮后会调用此函数
function upv_reset_parser()
    -- 下面的代码,将地址为01的设备中的0x81和0x01端点注册到了名为MSC的解码器上
    upv_register_decoder("MSC", "\x01\x81\x01\x01")
end

-- 解码Transaction数据
-- 参数说明
--           param       transaction 参数,包含了地址,端点,PID,和响应信息
--           data        transaction 数据,(不包含PID和CRC)
--           needDetail  是否需要详细信息
--           forceBegin  是否强制重新解码
--           autoDecoder 是否为脚本自动设置的解码器
-- 返回值(3个)
--           state       解码状态。 0-解码失败         Transaction不能解码
--                                1-数据开始         Xfer数据的第一包
--                                2-数据结束         Xfer数据的最后一包
--                                3-数据开始及结束   Xfer只有一包Transaction数据,例如普通的HID数据
--                                4-还有更多的数据   Xfer中的数据,既不是第一包,也不是最后一包
--           transaction transaction 解码结果
--           transfer    transfer    解码结果
--
-- 解码结果数据格式为以"\x00"分隔的字符串,分别表示 标题、名字、描述、状态、html信息、数据信息
function upv_parse_transaction(param, data, needDetail, forceBegin, autoDecoder)
    -- 从param中分离出地址,端点,PID及响应信息
    local addr, ep, pid, ack = param:byte(1), param:byte(2), param:byte(3), param:byte(4)
    if ep == 0 then
        -- TODO: 端点为0的为控制传输,可以在此将端点0上的Transaction合并成Control Transfer
        -- 然后解码设备的各种描述,根据描述符调用 upv_register_decoder 自动注册相应的解码器
        return 0
    end
    local title = decoder_map[string.char(addr,ep)]
    if title ~= "MSC" then return 0 end
    local state = 4
    -- CBW 数据
    if #data == 31 then state = 1 end
    -- CSW 数据
    if #data == 13 then state = 2 end
    
    if not needDetail then
        -- 不需要详细信息,只返回状态
        return state
    end
    return state,
           title .. "-Xact标题"
           .."\x00".."Xact名字"
           .."\x00".."Xact描述"
           .."\x00".."success"
           .."\x00".."<h>Transaction Html Info</h>"
           .."\x00".."\x01\x02\x00\x03\x00\x04",
           title .."-Xfer标题"
           .."\x00".."Xfer名字"
           .."\x00".."Xfer描述"
           .."\x00".."success"
           .."\x00".."<h>Xfer Html Info</h>"
           .."\x00".."\x11\x12\x00\x13\x00\x14"
end

-- 为端点添加添加解码器
-- 参数说明
--          name   解码器名称,脚本中通过名称来区分不同的解码器
--          eps    端点参数,格式为由地址和端点序列组成的字符串 string.char(addr,endp1,addr,endp2,...)
-- 返回值(1个)
--          true-成功,  false-失败
function upv_add_decoder(name, eps)
    if name == "MSC" then
        for i=1,#eps,2 do
            decoder_map[string.char(eps:byte(i), eps:byte(i+1))] = "MSC"
        end
        return true
    end
    return false
end

-- 为端点移除解码器
-- 参数说明
--          name   解码器名称,脚本中通过名称来区分不同的解码器
--          eps    端点参数,格式为由地址和端点序列组成的字符串 string.char(addr,endp1,addr,endp2,...)
-- 返回值(1个)
--          true成功, nil或false失败
function upv_remove_decoder(name, eps)
    for i=1,#eps,2 do
        decoder_map[string.char(eps:byte(i), eps:byte(i+1))] = nil
    end
    return true
end

-- 获取支持的解码器
-- 返回值(1个)
--        字符串形式的解码器列表,格式为以;号分隔的解码器参数:
--        <解码器参数1>;<解码器参数2>;<解码器参数3>
-- 解码器参数格式如下:
--       <解码器名>:<端点参数1>,<端点参数2>,<端点参数3>,
-- 端点参数格式如下:
--       <端点描述><端点类型>
-- 端点类型为012456这六种类型的一种,0-IN, 1-OUT, 2-INOUT, 4-可选IN, 5-可选OUT, 6-可选INOUT
function upv_valid_parser()
   -- 下面的参数表示三个解码器,名称分别为MSC, CDC和Video
   -- MSC    有两个端点,分别为:Bulk IN,类型为IN;Bulk OUT,类型为OUT
   -- CDC    有三个端点,分别为:Bulk IN,类型为IN;Bulk OUT,类型为OUT。Notify,类型为IN
   -- Video  有两个端点,分别为:Stream,类型为INOUT;StillImage,类型为可选的INOUT
   return "MSC:Bulk IN1,Bulk Out0;CDC:Bulk In1,Bulk Out0,Notify1;Video:Stream2,StillImage6"
end