DfuDevice.py 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import usb.util
  2. import time
  3. DFU_REQUEST_SEND = 0x21
  4. DFU_REQUEST_RECEIVE = 0xa1
  5. DFU_DETACH = 0x00
  6. DFU_DNLOAD = 0x01
  7. DFU_UPLOAD = 0x02
  8. DFU_GETSTATUS = 0x03
  9. DFU_CLRSTATUS = 0x04
  10. DFU_GETSTATE = 0x05
  11. DFU_ABORT = 0x06
  12. # Order is LSB first
  13. def address_to_4bytes(a):
  14. return [ a % 256, (a >> 8)%256, (a >> 16)%256, (a >> 24)%256 ]
  15. class DfuDevice:
  16. def __init__(self, device):
  17. self.dev = device
  18. self.cfg = self.dev[0]
  19. self.intf = None
  20. #self.dev.reset()
  21. self.cfg.set()
  22. def alternates(self):
  23. return [(self.get_string(intf.iInterface), intf) for intf in self.cfg]
  24. def set_alternate(self, intf):
  25. if isinstance(intf, tuple):
  26. self.intf = intf[1]
  27. else:
  28. self.intf = intf
  29. self.intf.set_altsetting()
  30. def control_msg(self, requestType, request, value, buffer):
  31. return self.dev.ctrl_transfer(requestType, request, value, self.intf.bInterfaceNumber, buffer)
  32. def detach(self, timeout):
  33. return self.control_msg(DFU_REQUEST_SEND, DFU_DETACH, timeout, None)
  34. def dnload(self, blockNum, data):
  35. return self.control_msg(DFU_REQUEST_SEND, DFU_DNLOAD, blockNum, data)
  36. def upload(self, blockNum, size):
  37. return self.control_msg(DFU_REQUEST_RECEIVE, DFU_UPLOAD, blockNum, size)
  38. def get_status(self):
  39. status = self.control_msg(DFU_REQUEST_RECEIVE, DFU_GETSTATUS, 0, 6)
  40. return (status[0], status[4], status[1] + (status[2] << 8) + (status[3] << 16), status[5])
  41. def clear_status(self):
  42. self.control_msg(DFU_REQUEST_SEND, DFU_CLRSTATUS, 0, None)
  43. def get_state(self):
  44. return self.control_msg(DFU_REQUEST_RECEIVE, DFU_GETSTATE, 0, 1)[0]
  45. def set_address(self, ap):
  46. return self.dnload(0x0, [0x21] + address_to_4bytes(ap))
  47. def write(self, block, data):
  48. return self.dnload(block + 2, data)
  49. def erase(self, pa):
  50. return self.dnload(0x0, [0x41] + address_to_4bytes(pa))
  51. # return self.dnload(0x0, [0x41]) #mass erase
  52. def leave(self):
  53. return self.dnload(0x0, []) # Just send an empty data.
  54. def get_string(self, index):
  55. return usb.util.get_string(self.dev, 256, index)
  56. def wait_while_state(self, state):
  57. if not isinstance(state, (list, tuple)):
  58. states = (state,)
  59. else:
  60. states = state
  61. status = self.get_status()
  62. while (status[1] in states):
  63. status = self.get_status()
  64. time.sleep(status[2] / 1000)
  65. return status