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写的好处在于便是扩展。比如想加个界面,或者作为模块融入到更大的代码中,都是很容易的。

  1. #!/usr/bin/python   
  2. import usb.core  
  3. import StringIO  
  4. import struct  
  5. import sys  
  6.   
  7. if len(sys.argv) == 2 :  
  8.         addr = 0x32000000  
  9. elif len(sys.argv) == 3:  
  10.         addr = int(sys.argv[2], 16)  
  11. else:  
  12.         print 'Usage: dnw filename [address]'  
  13.         quit()  
  14.   
  15. def checksum(data):  
  16.         s = 0  
  17.         for i in data:  
  18.                 s += struct.unpack('B', i)[0];  
  19.         return s&0xffff  
  20.   
  21. content = open(sys.argv[1]).read()  
  22. address = struct.pack('L', addr)  
  23. length = struct.pack('L', len(content) + 10)  
  24. check = struct.pack('H', checksum(address + length + content))  
  25.   
  26. inp = StringIO.StringIO(address + length + content + check)  
  27.   
  28. dev = usb.core.find(idVendor=0x5345, idProduct=0x1234)  
  29. dev.set_configuration()  
  30. ep = dev[0][(0,0)][1]  
  31.   
  32. data = inp.read(512)  
  33. while data:  
  34.         ep.write(data)  
  35.         data = inp.read(512)  

相关内容