Created
August 21, 2022 10:22
-
-
Save v3l0c1r4pt0r/d50ca7393d93a6be30cf6fead2e3cd75 to your computer and use it in GitHub Desktop.
Wireshark dissector for DM9601 USB to Ethernet adapter chips
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- 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