Skip to content

Instantly share code, notes, and snippets.

@v3l0c1r4pt0r
Created August 21, 2022 10:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save v3l0c1r4pt0r/d50ca7393d93a6be30cf6fead2e3cd75 to your computer and use it in GitHub Desktop.
Save v3l0c1r4pt0r/d50ca7393d93a6be30cf6fead2e3cd75 to your computer and use it in GitHub Desktop.
Wireshark dissector for DM9601 USB to Ethernet adapter chips
-- DM9601 dissector for Wireshark
--
-- Usage: wireshark -X lua_script:dm9601.lua
--
p_dm9601 = Proto("dm9601", "DM9601 USB Protocol")
p_dm9601_ethin = Proto("dm9601_ethin", "DM9601 USB Protocol Ethernet Input Stream")
p_dm9601_ethout = Proto("dm9601_ethout", "DM9601 USB Protocol Ethernet Output Stream")
p_dm9601_irq = Proto("dm9601_irq", "DM9601 USB Protocol Interrupts")
local operations = {
[0xc000] = "READ_REGISTER()",
[0x4001] = "WRITE_REGISTER()",
[0x4003] = "WRITE1_REGISTER()",
[0xc002] = "READ_MEMORY()",
[0x4005] = "WRITE_MEMORY()",
[0x4007] = "WRITE1_MEMORY()",
}
local regs = {
[0x00] = "Network Control Register",
[0x01] = "Network Status Register",
[0x02] = "TX Control Register",
[0x03] = "TX Status Register I",
[0x04] = "TX Status Register II",
[0x05] = "RX Control Register",
[0x06] = "RX Status Register",
[0x07] = "Receive Overflow Counter Register",
[0x08] = "Back Pressure Threshold Register",
[0x09] = "Flow Control Threshold Register",
[0x0a] = "RX/TX Flow Control Register",
[0x0b] = "EEPROM & PHY Control Register",
[0x0c] = "EEPROM & PHY Address Register",
[0x0d] = "EEPROM & PHY Data Register Low",
[0x0e] = "EEPROM & PHY Data Register High",
[0x0f] = "Wake Up Control Register",
[0x10] = "Physical Address Byte 0 Register",
[0x11] = "Physical Address Byte 1 Register",
[0x12] = "Physical Address Byte 2 Register",
[0x13] = "Physical Address Byte 3 Register",
[0x14] = "Physical Address Byte 4 Register",
[0x15] = "Physical Address Byte 5 Register",
[0x16] = "Multicast Address Byte 0 Register",
[0x17] = "Multicast Address Byte 1 Register",
[0x18] = "Multicast Address Byte 2 Register",
[0x19] = "Multicast Address Byte 3 Register",
[0x1a] = "Multicast Address Byte 4 Register",
[0x1b] = "Multicast Address Byte 5 Register",
[0x1c] = "Multicast Address Byte 6 Register",
[0x1d] = "Multicast Address Byte 7 Register",
[0x1e] = "General Purpose Control Register",
[0x1f] = "General Purpose Register",
[0x20] = "TX SRAM Write Pointer Address Register Low",
[0x21] = "TX SRAM Write Pointer Address Register High",
[0x22] = "TX SRAM Read Pointer Address Register Low",
[0x23] = "TX SRAM Read Pointer Address Register High",
[0x24] = "RX SRAM Write Pointer Address Register Low",
[0x25] = "RX SRAM Write Pointer Address Register High",
[0x26] = "RX SRAM Read Pointer Address Register Low",
[0x27] = "RX SRAM Read Pointer Address Register High",
[0x28] = "Vendor ID Register Low [DM9620]",
[0x29] = "Vendor ID Register High [DM9620]",
[0x2a] = "Product ID Register Low",
[0x2b] = "Product ID Register High",
[0x2c] = "Chip Revision Register",
[0x2d] = "TX Special Control Register [DM9620]",
[0x2e] = "External PHY Force Mode Control Register [DM9620]",
[0x31] = "Transmit Check Sum Control Register [DM9620]",
[0x32] = "Receive Check Sum Control Register [DM9620]",
[0x33] = "External PHY Address Register [DM9620]",
[0x34] = "General Purpose Control Register 2 [DM9620]",
[0x35] = "General Purpose Register 2 [DM9620]",
[0x36] = "General Purpose Control Register 3 [DM9620]",
[0x37] = "General Purpose Register 3 [DM9620]",
[0x3a] = "EEPROM and PHY Control Register [DM9620]",
[0x3d] = "Pause Packet Control/Status Register [DM9620]",
[0x81] = "Transmit Packet Counter [DM9620]",
[0x82] = "USB Packet Error Counter [DM9620]",
[0x83] = "Ethernet Receive Packet CRC Error Counter [DM9620]",
[0x84] = "Ethernet Transmit Excessive Collision Counter [DM9620]",
[0x85] = "Ethernet Transmit Collision Counter [DM9620]",
[0x86] = "Ethernet Transmit Late Collision Counter [DM9620]",
[0x91] = "RX Header Control/Status Register [DM9620]",
[0x95] = "USB Squelch Control Register [DM9620]",
[0x96] = "USB Address Register [DM9620]",
[0xf0] = "USB Device Address Register",
[0xf1] = "Receive Packet Counter Register",
[0xf2] = "Transmit Packet Counter Register/USB Status Register",
[0xf4] = "USB Control Register",
}
p_dm9601.fields.operation = ProtoField.uint8("dm9601.op", "Operation", base.HEX, operations)
p_dm9601.fields.regoffset = ProtoField.uint8("dm9601.regoffset", "RegOffset", base.HEX, regs)
p_dm9601.fields.bc = ProtoField.uint8("dm9601.bc", "BC", base.HEX)
p_dm9601.fields.data = ProtoField.uint8("dm9601.data", "Data", base.HEX)
-- Network Control Register
p_dm9601.fields.ncr = ProtoField.uint8("dm9601.ncr", "Network Control Register", base.HEX)
p_dm9601.fields.ext_phy = ProtoField.uint8("dm9601.ncr.ext_phy", "EXT_PHY", base.HEX, {[0]="Internal PHY", [1]="External PHY"}, 0x80)
p_dm9601.fields.wakeen = ProtoField.uint8("dm9601.ncr.wakeen", "WAKEEN", base.HEX, {[0]="Wakeup disable", [1]="Wakeup enable"}, 0x40)
p_dm9601.fields.reserved = ProtoField.uint8("dm9601.ncr.reserved", "RESERVED", base.HEX, {[0]="Reserved", [1]="Invalid"}, 0x20)
p_dm9601.fields.fcol = ProtoField.uint8("dm9601.ncr.fcol", "FCOL", base.HEX, {[0]="No force collision", [1]="Force collision mode"}, 0x10)
p_dm9601.fields.fdx = ProtoField.uint8("dm9601.ncr.fdx", "FDX", base.HEX, {[0]="No Full-Duplex", [1]="Full-Duplex mode"}, 0x08)
p_dm9601.fields.lbk = ProtoField.uint8("dm9601.ncr.lbk", "LBK", base.HEX, {[0]="normal", [1]="MAC internal loopback", [2]="internal PHY digital loopback", [3]="internal PHY analog loopback"}, 0x06)
p_dm9601.fields.rst = ProtoField.uint8("dm9601.ncr.rst", "RST", base.HEX, {[0]="No", [1]="Software Reset"}, 0x01)
-- EEPROM & PHY Control Register
p_dm9601.fields.epc = ProtoField.uint8("dm9601.epc", "EEPROM & PHY Control Register", base.HEX)
p_dm9601.fields.no_eep = ProtoField.uint8("dm9601.epc.no_eep", "NO_EEP", base.HEX, {[0]="EEPROM detected", [1]="No EEPROM"}, 0x80)
p_dm9601.fields.ee_type = ProtoField.uint8("dm9601.epc.ee_type", "EE_TYPE", base.HEX, {[0]="93C46", [1]="93C56/66"}, 0x40)
p_dm9601.fields.reep = ProtoField.uint8("dm9601.epc.reep", "REEP", base.HEX, {[0]="No EEPROM reload", [1]="Reload EEPROM"}, 0x20)
p_dm9601.fields.wep = ProtoField.uint8("dm9601.epc.wep", "WEP", base.HEX, {[0]="EEPROM write disable", [1]="EEPROM write enable"}, 0x10)
p_dm9601.fields.epos = ProtoField.uint8("dm9601.epc.epos", "EPOS", base.HEX, {[0]="EEPROM operation", [1]="PHY operation"}, 0x08)
p_dm9601.fields.erprr = ProtoField.uint8("dm9601.epc.erprr", "ERPRR", base.HEX, {[0]="No EEPROM/PHY read initiated", [1]="EEPROM/PHY read initiated"}, 0x04)
p_dm9601.fields.erprw = ProtoField.uint8("dm9601.epc.erprw", "ERPRW", base.HEX, {[0]="No EEPROM/PHY write initiated", [1]="EEPROM/PHY write initiated"}, 0x02)
p_dm9601.fields.erre = ProtoField.uint8("dm9601.epc.erre", "ERRE", base.HEX, {[0]="No EEPROM/PHY access in progress", [1]="EEPROM/PHY access in progress"}, 0x01)
-- EEPROM & PHY Address Register
p_dm9601.fields.epa = ProtoField.uint8("dm9601.epa", "EEPROM & PHY Address Register", base.HEX)
p_dm9601.fields.phy_adr = ProtoField.uint8("dm9601.epa.phy_adr", "PHY_ADR", base.HEX, {}, 0xc0)
p_dm9601.fields.eroa = ProtoField.uint8("dm9601.epa.eroa", "EEPROM word address", base.HEX, {}, 0x3f)
-- EEPROM & PHY Data Register
p_dm9601.fields.epd = ProtoField.uint8("dm9601.epd", "EEPROM & PHY Data Register", base.HEX)
-- General Purpose Control Register
p_dm9601.fields.gpcr = ProtoField.uint8("dm9601.gpcr", "General Purpose Control Register", base.HEX)
p_dm9601.fields.reserved1 = ProtoField.uint8("dm9601.gpcr.reserved", "RESERVED", base.HEX, {[0]="Reserved", [1]="Invalid"}, 0x80)
p_dm9601.fields.gepio6dir = ProtoField.uint8("dm9601.gpcr.gepio6dir", "GEPIO6 direction", base.HEX, {[0]="Input", [1]="Output"}, 0x40)
p_dm9601.fields.gepio5dir = ProtoField.uint8("dm9601.gpcr.gepio5dir", "GEPIO5 direction", base.HEX, {[0]="Input", [1]="Output"}, 0x20)
p_dm9601.fields.gepio4dir = ProtoField.uint8("dm9601.gpcr.gepio4dir", "GEPIO4 direction", base.HEX, {[0]="Input", [1]="Output"}, 0x10)
p_dm9601.fields.gepio3dir = ProtoField.uint8("dm9601.gpcr.gepio3dir", "GEPIO3 direction", base.HEX, {[0]="Input", [1]="Output"}, 0x08)
p_dm9601.fields.gepio2dir = ProtoField.uint8("dm9601.gpcr.gepio2dir", "GEPIO2 direction", base.HEX, {[0]="Input", [1]="Output"}, 0x04)
p_dm9601.fields.gepio1dir = ProtoField.uint8("dm9601.gpcr.gepio1dir", "GEPIO1 direction", base.HEX, {[0]="Input", [1]="Output"}, 0x02)
p_dm9601.fields.gepio0dir = ProtoField.uint8("dm9601.gpcr.gepio0dir", "GEPIO0 direction", base.HEX, {[0]="Input", [1]="Output"}, 0x01)
-- General Purpose Register
p_dm9601.fields.gpr = ProtoField.uint8("dm9601.gpr", "General Purpose Register", base.HEX)
p_dm9601.fields.gepio6 = ProtoField.uint8("dm9601.ncr.gpr.gepio6", "GEPIO6", base.HEX, {[0]="GEPIO6=0", [1]="GEPIO6=1"}, 0x40)
p_dm9601.fields.gepio5 = ProtoField.uint8("dm9601.ncr.gpr.gepio5", "GEPIO5", base.HEX, {[0]="GEPIO5=0", [1]="GEPIO5=1"}, 0x20)
p_dm9601.fields.gepio4 = ProtoField.uint8("dm9601.ncr.gpr.gepio4", "GEPIO4", base.HEX, {[0]="GEPIO4=0", [1]="GEPIO4=1"}, 0x10)
p_dm9601.fields.gepio3 = ProtoField.uint8("dm9601.ncr.gpr.gepio3", "GEPIO3", base.HEX, {[0]="GEPIO3=0", [1]="GEPIO3=1"}, 0x08)
p_dm9601.fields.gepio2 = ProtoField.uint8("dm9601.ncr.gpr.gepio2", "GEPIO2", base.HEX, {[0]="GEPIO2=0", [1]="GEPIO2=1"}, 0x04)
p_dm9601.fields.gepio1 = ProtoField.uint8("dm9601.ncr.gpr.gepio1", "GEPIO1", base.HEX, {[0]="GEPIO1=0", [1]="GEPIO1=1"}, 0x02)
p_dm9601.fields.gepio0 = ProtoField.uint8("dm9601.ncr.gpr.gepio0", "GEPIO0", base.HEX, {[0]="GEPIO0=0", [1]="GEPIO0=1"}, 0x01)
-- DM9601 IRQ fields
p_dm9601_irq.fields.nsr = ProtoField.uint8("dm9601_irq.nsr", "Network Status Register", base.HEX)
p_dm9601_irq.fields.tsr1 = ProtoField.uint8("dm9601_irq.tsr1", "Reserved", base.HEX)
p_dm9601_irq.fields.tsr2 = ProtoField.uint8("dm9601_irq.tsr2", "Reserved", base.HEX)
p_dm9601_irq.fields.rsr = ProtoField.uint8("dm9601_irq.rsr", "RX Status Register", base.HEX)
p_dm9601_irq.fields.rocr = ProtoField.uint8("dm9601_irq.rocr", "Received Overflow Counter Register", base.HEX)
p_dm9601_irq.fields.rxc = ProtoField.uint8("dm9601_irq.rxc", "Received Packet Register", base.HEX)
p_dm9601_irq.fields.txc = ProtoField.uint8("dm9601_irq.txc", "Transmit Packet Register", base.HEX)
p_dm9601_irq.fields.gpr = ProtoField.uint8("dm9601_irq.gpr", "Reserved", base.HEX)
-- Referenced USB dissector fields.
local f_pid = Field.new("usbll.pid")
local f_bmRequestType = Field.new("usb.bmRequestType")
local f_frame_number = Field.new("frame.number")
local f_request_in = Field.new("usb.request_in")
local f_usb_src = Field.new("usb.src")
local f_usb_dst = Field.new("usb.dst")
local frame2reg = {}
local function network_control_register_dissector(tvb, pinfo, subtree)
local Data = tonumber(tostring(tvb(0,1)), 16)
local ncr_tree = subtree:add(p_dm9601.fields.ncr, tvb(0,1), Data)
ncr_tree:add(p_dm9601.fields.ext_phy, tvb(0,1), Data)
ncr_tree:add(p_dm9601.fields.wakeen, tvb(0,1), Data)
ncr_tree:add(p_dm9601.fields.reserved, tvb(0,1), Data)
ncr_tree:add(p_dm9601.fields.fcol, tvb(0,1), Data)
ncr_tree:add(p_dm9601.fields.fdx, tvb(0,1), Data)
ncr_tree:add(p_dm9601.fields.lbk, tvb(0,1), Data)
ncr_tree:add(p_dm9601.fields.rst, tvb(0,1), Data)
end
local function eeprom_phy_control_register_dissector(tvb, pinfo, subtree)
local Data = tonumber(tostring(tvb(0,1)), 16)
local epc_tree = subtree:add(p_dm9601.fields.epc, tvb(0,1), Data)
epc_tree:add(p_dm9601.fields.no_eep, tvb(0,1), Data)
epc_tree:add(p_dm9601.fields.ee_type, tvb(0,1), Data)
epc_tree:add(p_dm9601.fields.reep, tvb(0,1), Data)
epc_tree:add(p_dm9601.fields.wep, tvb(0,1), Data)
epc_tree:add(p_dm9601.fields.epos, tvb(0,1), Data)
epc_tree:add(p_dm9601.fields.erprr, tvb(0,1), Data)
epc_tree:add(p_dm9601.fields.erprw, tvb(0,1), Data)
epc_tree:add(p_dm9601.fields.erre, tvb(0,1), Data)
end
local function eeprom_phy_address_register_dissector(tvb, pinfo, subtree)
local Data = tonumber(tostring(tvb(0,1)), 16)
local epa_tree = subtree:add(p_dm9601.fields.epa, tvb(0,1), Data)
epa_tree:add(p_dm9601.fields.phy_adr, tvb(0,1), Data)
epa_tree:add(p_dm9601.fields.eroa, tvb(0,1), Data)
end
local function eeprom_phy_data_register_dissector(tvb, pinfo, subtree)
local Data = tonumber(tostring(tvb(0,1)), 16)
local epd_tree = subtree:add(p_dm9601.fields.epd, tvb(0,1), Data)
end
local function general_purpose_control_register_dissector(tvb, pinfo, subtree)
local Data = tonumber(tostring(tvb(0,1)), 16)
local gpcr_tree = subtree:add(p_dm9601.fields.gpcr, tvb(0,1), Data)
gpcr_tree:add(p_dm9601.fields.reserved1, tvb(0,1), Data)
gpcr_tree:add(p_dm9601.fields.gepio6dir, tvb(0,1), Data)
gpcr_tree:add(p_dm9601.fields.gepio5dir, tvb(0,1), Data)
gpcr_tree:add(p_dm9601.fields.gepio4dir, tvb(0,1), Data)
gpcr_tree:add(p_dm9601.fields.gepio3dir, tvb(0,1), Data)
gpcr_tree:add(p_dm9601.fields.gepio2dir, tvb(0,1), Data)
gpcr_tree:add(p_dm9601.fields.gepio1dir, tvb(0,1), Data)
gpcr_tree:add(p_dm9601.fields.gepio0dir, tvb(0,1), Data)
end
local function general_purpose_register_dissector(tvb, pinfo, subtree)
local Data = tonumber(tostring(tvb(0,1)), 16)
local gpr_tree = subtree:add(p_dm9601.fields.gpr, tvb(0,1), Data)
gpr_tree:add(p_dm9601.fields.gepio6, tvb(0,1), Data)
gpr_tree:add(p_dm9601.fields.gepio5, tvb(0,1), Data)
gpr_tree:add(p_dm9601.fields.gepio4, tvb(0,1), Data)
gpr_tree:add(p_dm9601.fields.gepio3, tvb(0,1), Data)
gpr_tree:add(p_dm9601.fields.gepio2, tvb(0,1), Data)
gpr_tree:add(p_dm9601.fields.gepio1, tvb(0,1), Data)
gpr_tree:add(p_dm9601.fields.gepio0, tvb(0,1), Data)
end
local function x_register_dissector(tvb, pinfo, subtree, op)
local RegOffset = tonumber(tostring(tvb(3,1)), 16)
local BC = tonumber(tostring(tvb(5,1)), 16)
subtree:add(p_dm9601.fields.regoffset, tvb(3,1), RegOffset)
subtree:add(p_dm9601.fields.bc, tvb(5,1), BC)
-- translate operation name
if op == 'WRITE_REGISTER()' then
op = 'Write'
pinfo.cols.info = op..' '..regs[RegOffset]
elseif op == 'READ_REGISTER()' then
op = 'Read'
end
-- ensure register is known and set info column
if regs[RegOffset] ~= nil then
pinfo.cols.info = op..' '..regs[RegOffset]
else
pinfo.cols.info = op..' '..RegOffset
end
-- save register for response dissector
local frame_number = tonumber(tostring(f_frame_number()))
frame2reg[frame_number] = RegOffset
end
local function write1_register_dissector(tvb, pinfo, subtree)
local Data = tonumber(tostring(tvb(1,1)), 16)
local RegOffset = tonumber(tostring(tvb(3,1)), 16)
local BC = tonumber(tostring(tvb(5,1)), 16)
local register_tree = subtree:add(p_dm9601.fields.data, tvb(1,1), Data)
subtree:add(p_dm9601.fields.regoffset, tvb(3,1), RegOffset)
subtree:add(p_dm9601.fields.bc, tvb(5,1), BC)
if regs[RegOffset] ~= nil then
pinfo.cols.info = 'Write1 '..regs[RegOffset]
else
pinfo.cols.info = 'Write1 '..RegOffset
end
-- dissect register if known
if RegOffset == 0x00 then
network_control_register_dissector(tvb(1,1), pinfo, register_tree)
elseif RegOffset == 0x0b then
eeprom_phy_control_register_dissector(tvb(1,1), pinfo, register_tree)
elseif RegOffset == 0x0c then
eeprom_phy_address_register_dissector(tvb(1,1), pinfo, register_tree)
elseif RegOffset == 0x1e then
general_purpose_control_register_dissector(tvb(1,1), pinfo, register_tree)
elseif RegOffset == 0x1f then
general_purpose_register_dissector(tvb(1,1), pinfo, register_tree)
end
end
local function register_read_response_dissector(tvb, pinfo, subtree, RegOffset)
local Data = tonumber(tostring(tvb(0,1)), 16)
local register_tree = subtree:add(p_dm9601.fields.data, tvb(0,1), Data)
if RegOffset == 0x00 then
network_control_register_dissector(tvb(0,1), pinfo, register_tree)
elseif RegOffset == 0x0b then
eeprom_phy_control_register_dissector(tvb(0,1), pinfo, register_tree)
elseif RegOffset == 0x0d then
eeprom_phy_data_register_dissector(tvb(0,1), pinfo, register_tree)
elseif RegOffset == 0x1f then
general_purpose_register_dissector(tvb(0,1), pinfo, register_tree)
end
end
-- Take USB address in form <bus>.<dev>.<endpoint> and extract endpoint
local function addr2endpoint(addr)
addr = tostring(addr) -- usually we get FieldInfo, which gmatch is not happy about
for e in addr:gmatch('[.][^.]+') do r=e end
return r:sub(2)
end
-- dissect interrupt packet (Endpoint 3)
local function interrupt_dissector(tvb, pinfo, subtree, RegOffset)
local NSR = tonumber(tostring(tvb(0,1)), 16)
local nsr = subtree:add(p_dm9601_irq.fields.nsr, tvb(0,1), NSR)
local TSR1 = tonumber(tostring(tvb(1,1)), 16)
local tsr1 = subtree:add(p_dm9601_irq.fields.tsr1, tvb(1,1), TSR1)
local TSR2 = tonumber(tostring(tvb(2,1)), 16)
local tsr2 = subtree:add(p_dm9601_irq.fields.tsr2, tvb(2,1), TSR2)
local RSR = tonumber(tostring(tvb(3,1)), 16)
local rsr = subtree:add(p_dm9601_irq.fields.rsr, tvb(3,1), RSR)
local ROCR = tonumber(tostring(tvb(4,1)), 16)
local rocr = subtree:add(p_dm9601_irq.fields.rocr, tvb(4,1), ROCR)
local RXC = tonumber(tostring(tvb(5,1)), 16)
local rxc = subtree:add(p_dm9601_irq.fields.rxc, tvb(5,1), RXC)
local TXC = tonumber(tostring(tvb(6,1)), 16)
local txc = subtree:add(p_dm9601_irq.fields.txc, tvb(6,1), TXC)
local GPR = tonumber(tostring(tvb(7,1)), 16)
local gpr = subtree:add(p_dm9601_irq.fields.gpr, tvb(7,1), GPR)
end
-- Main DM9601 dissector function.
function p_dm9601.dissector(tvb, pinfo, tree)
-- get usbll.pid
local err, result = pcall(function () return tonumber(tostring(f_pid())) end)
local pid = 'Error'
if err == false then
-- in usbmon pcaps there is no USBLL
-- FIXME: what about data packets?
pid = 0xc3
else
pid = result
end
local usb_src = f_usb_src()
local usb_dst = f_usb_dst()
src_ep = addr2endpoint(usb_src)
dst_ep = addr2endpoint(usb_dst)
if src_ep == '1' or dst_ep == '1' then
pinfo.cols.protocol = 'EthIn'
return
end
if src_ep == '2' or dst_ep == '2' then
pinfo.cols.protocol = 'EthOut'
return
end
if src_ep == '3' or dst_ep == '3' then
pinfo.cols.protocol = p_dm9601.name..' IRQ'
local subtree = tree:add(p_dm9601_irq, tvb(0,8), "DM9601 IRQ")
interrupt_dissector(tvb, pinfo, subtree)
return
end
if pid == 0xc3 then -- SETUP DATA0
pinfo.cols.protocol = p_dm9601.name
local bmRequestType = tonumber(tostring(f_bmRequestType()))
local subtree = tree:add(p_dm9601, tvb(), "DM9601")
local bRequest = tonumber(tostring(tvb(0,1)))
local op = bit.bor(bit.lshift(bmRequestType, 8), bRequest)
--if bmRequestType == 0xc0 and bRequest == 0x00 then -- READ_REGISTER()
if operations[op] ~= nil then
subtree:add(p_dm9601.fields.operation, tvb(0,1), op)
pinfo.cols.info = operations[op]
end
if operations[op] == 'READ_REGISTER()' or operations[op] == 'WRITE_REGISTER()' then
x_register_dissector(tvb, pinfo, subtree, operations[op])
elseif operations[op] == 'WRITE1_REGISTER()' then
write1_register_dissector(tvb, pinfo, subtree)
end
elseif pid == 0x4b and f_usb_src() ~= "host" then
-- TODO: catch reassembled requests!!!
local subtree = tree:add(p_dm9601, tvb(), "DM9601")
pinfo.cols.protocol = p_dm9601.name
local request_in = f_request_in()
pinfo.cols.info = 'Read Response'
local err, result = pcall(function () return tonumber(tostring(request_in)) end)
if err == false then
err = result
return 0
end
request_in = result
local request_reg = frame2reg[request_in]
if regs[request_reg] ~= nil then
pinfo.cols.info = regs[request_reg]..' Response'
else
pinfo.cols.info = request_reg..' Response'
end
register_read_response_dissector(tvb, pinfo, subtree, request_reg)
end
return 0
end
-- Register DM9601 protocol dissector during initialization.
function p_dm9601.init()
local usb_product_dissectors = DissectorTable.get("usb.product")
usb_product_dissectors:add(0x0fe68101, p_dm9601) -- DM9601 USB to Fast Ethernet Adapter
usb_product_dissectors:add(0x0fe69700, p_dm9601) -- DM9601 USB to Fast Ethernet Adapter
local usb_bulk_dissectors = DissectorTable.get("usb.bulk")
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment