Python版DNW
准备全线迁到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)