准备全线迁到Linux下做实验,虚拟机里编译太慢了。DNW是个问题。其实DNW到底是个什么东西我并不清楚,厂家提供的bootloader就是用DNW通过USB线接受PC传来数据。记得两年前就见过网友Linux版的DNW。那时没开始接触内核,觉得写这个东西的人真NB。现在把那个代码找出来看看,原来蛮简单的。一个内核态的驱动,一个用户态的程序。通过看用户态的程序,知道了DNW传输的格式,即4字节的下载地址+4字节的传输总长度+传输内容+2字节的checksum。checksum就是把前面三个部分以unsigned char的形式全部加起来。
后来找到了无需内核态驱动的DNW,借助libusb纯在用户态做。这个蛮不错,昨晚准备编一个试一下,结果装了libusb一还干了别的事,到头到也没试。今天又找到了一个xdnw,它用QT给DNW做了个UI,还是利用libusb纯在用户态下实现。为了试一下它还特意去装了QT4,看了下界面,很简陋。没有具体使用,不过应该问题不大。
想了半天,还是决定看能不能用Python实现一个。首先要找到能操纵USB的Python模块。有个叫PyUSB的东西一搜就搜到了。大致扫了一眼它的文档,觉得蛮简单的,于是开始着手实现。Python的一些东西还是很不熟悉,搞了几个小时,总算是搞出来了。不到40行代码,有效代码可能还没有30行,但确实折腾了两三个小时。偷了不少懒,错误处理都没做,而且直接假定第一个configuration的第一个interface的第一个setting的第二个endpoint是用来输出的。跟USB相关的代码只有四行。测试了一下,有时候是正常,有时候传输到的内存地址有误,比如要传到0x32000000结果终端上显示传到0x30000000。
有凑合用吧,以后再慢慢完善。用Python写的好处在于便是扩展。比如想加个界面,或者作为模块融入到更大的代码中,都是很容易的。
#!/usr/bin/python
import usb.core
import StringIO
import struct
import sys
if len(sys.argv) == 2 :
addr = 0x32000000
elif len(sys.argv) == 3:
addr = int(sys.argv[2], 16)
else:
print 'Usage: dnw filename [address]'
quit()
def checksum(data):
s = 0
for i in data:
s += struct.unpack('B', i)[0];
return s&0xffff
content = open(sys.argv[1]).read()
address = struct.pack('L', addr)
length = struct.pack('L', len(content) + 10)
check = struct.pack('H', checksum(address + length + content))
inp = StringIO.StringIO(address + length + content + check)
dev = usb.core.find(idVendor=0x5345, idProduct=0x1234)
dev.set_configuration()
ep = dev[0][(0,0)][1]
data = inp.read(512)
while data:
ep.write(data)
data = inp.read(512)