S社NB30機種向SHDIAG
日系机圈子里的,看到这个标题就应该明白这是干什么用的了吧?
说实话写的很烂,能凑合用的水平,也不知道那么多依赖的更新之后,还能不能用。
稍稍做了一些小修补,由于在国外也没有机器测试,还是希望有人可以来测一下。
这个小东西是很久以前的商用品了,现在也觉得没啥价值,故直接公开
想法及思路来自tewilove
依赖PyUSB
2023-03-26更新:找到了当初的稀烂笔记,整理了一下放在这里
# NB30 SHDIAG USB Protocol v0.2
# (C)Yuu 2019
# Modified History:
# Nov.02-2022:v0.2:Normal Improvement
import sys
import usb.core
import usb.util
import random
NB30_USB_VID = 0x04dd
NB30_USB_PID = 0x933a
def shdiag_xchar(c):
xft = [0, 2, 4, 6, 1, 3, 5, 7]
r = 0
for i in range(8):
r |= (((c >> i) & 1) << xft[i])
return r
# 取随机值位于F到7F/下一字节为XOR Key/之后数据全部XOR/如果换行则重置XOR Key
def shdiag_encode_data(in_data):
ip = 0
op = 1
out_data = [0] * (len(in_data) * 2)
v = (random.randint(0, 0x7f) + 0xf)
x = shdiag_xchar(v)
out_data[0] = v
while ip < len(in_data):
if in_data[ip] == '\r' or in_data[ip] == '\n':
out_data[op] = in_data[ip]
op += 1
if in_data[ip] == '\n' and ip + 1 < len(in_data):
x = shdiag_xchar(v)
out_data[op] = v
op += 1
else:
out_data[op] = (in_data[ip] ^ (x & 0x7f)) + 0xf
x = (x >> 1) | ((x & 1) << 7)
op += 1
ip += 1
return out_data[:op]
def shdiag_decode_data(in_data):
ip = 1
op = 0
out_data = [0] * (len(in_data) - 1)
x = in_data[0]
x = shdiag_xchar(x)
while ip < len(in_data):
if in_data[ip] == '\r' or in_data[ip] == '\n':
out_data[op] = in_data[ip]
op += 1
if in_data[ip] == '\n' and ip + 1 < len(in_data):
x = in_data[ip + 1]
x = shdiag_xchar(x)
ip += 1
else:
out_data[op] = (in_data[ip] - 0xf) ^ (x & 0x7f)
x = (x >> 1) | ((x & 1) << 7)
op += 1
ip += 1
return out_data[:op]
def nb30port_open():
dev = usb.core.find(idVendor=NB30_USB_VID, idProduct=NB30_USB_PID)
if dev is None:
return None
dev.set_configuration()
cfg = dev.get_active_configuration()
intf = cfg[(1, 1)]
ep_in = usb.util.find_descriptor(intf, custom_match=lambda e: usb.util.endpoint_direction(
e.bEndpointAddress) == usb.util.ENDPOINT_IN)
ep_out = usb.util.find_descriptor(intf, custom_match=lambda e: usb.util.endpoint_direction(
e.bEndpointAddress) == usb.util.ENDPOINT_OUT)
return dev, ep_in, ep_out
def nb30port_close(dev):
usb.util.dispose_resources(dev)
def nb30port_read(ep_in):
return ep_in.read(ep_in.wMaxPacketSize, 1000)
def nb30port_write(ep_out, data):
return ep_out.write(data, 1000)
def main():
print("YuuSHDIAG v0.2")
print("Usage: python shdiag.py <SHDIAG_COMMAND>")
if len(sys.argv) != 2:
return 1
while True:
dev, ep_in, ep_out = nb30port_open()
if dev is not None:
break
res = nb30port_read(ep_in)
if len(res) > 0:
res_decode = shdiag_decode_data(res)
print(''.join(map(chr, res_decode)))
req = '{}\r\n'.format(sys.argv[1])
req_encode = shdiag_encode_data(req)
if 0 < len(req_encode) == nb30port_write(ep_out, req_encode):
res = nb30port_read(ep_in)
if len(res) > 0:
res_decode = shdiag_decode_data(res)
print(''.join(map(chr, res_decode)))
nb30port_close(dev)
if __name__ == '__main__':
main()