Subversion Repositories freemyipod

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
56 benedikt93 1
#!/usr/bin/env python
2
#
3
#
4
#    Copyright 2010 TheSeven, benedikt93
5
#
6
#
7
#    This file is part of emBIOS.
8
#
9
#    emBIOS is free software: you can redistribute it and/or
10
#    modify it under the terms of the GNU General Public License as
11
#    published by the Free Software Foundation, either version 2 of the
12
#    License, or (at your option) any later version.
13
#
14
#    emBIOS is distributed in the hope that it will be useful,
15
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
16
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
#    See the GNU General Public License for more details.
18
#
19
#    You should have received a copy of the GNU General Public License
20
#    along with emBIOS.  If not, see <http://www.gnu.org/licenses/>.
21
#
22
#
23
 
96 benedikt93 24
# note: handles commands 1 to 21
56 benedikt93 25
 
26
import sys
27
import math
28
import struct
29
import time
30
import usb
31
 
32
 
33
class embios:
34
  def __init__(self, devtype = 0, type = 0):
35
    busses = usb.busses()
36
 
37
    for bus in busses:
38
      devices = bus.devices
39
      for dev in devices:
40
        if dev.idVendor == 0xffff and dev.idProduct == 0xe000:
41
          # get endpoints
42
          self.__coutep = dev.configurations[0].interfaces[0][0].endpoints[0].address
43
          self.__cinep = dev.configurations[0].interfaces[0][0].endpoints[1].address
44
          self.__doutep = dev.configurations[0].interfaces[0][0].endpoints[2].address
45
          self.__dinep = dev.configurations[0].interfaces[0][0].endpoints[3].address
46
 
47
          handle = dev.open()
48
          handle.setConfiguration(1)
49
          handle.claimInterface(0)
50
 
51
          # get version info
52
          handle.bulkWrite(self.__coutep, struct.pack("<IIII", 1, 0, 0, 0))
53
          response = self.__getbulk(handle, self.__cinep, 0x10)
54
          self.__checkstatus(response)
55
          i = struct.unpack("<IIBBBBI", response)
56
 
57
          if devtype in [0, i[6]] and type in [0, i[5]]:
58
            # correct device
59
            self.handle = handle
60
            self.dev = dev
61
 
82 benedikt93 62
            self.svnrev, self.major, self.minor, self.patch, self.type, self.devtype = i[1:]
79 benedikt93 63
            self.__myprint("Connected to emBIOS %s v%d.%d.%d (SVN revision: %d) on %s, USB version %s\n" \
64 benedikt93 64
                  % (self.type2name(self.type), self.major, self.minor, self.patch, self.svnrev, \
56 benedikt93 65
                     self.devtype2name(self.devtype), dev.deviceVersion))
66
 
67
            # get packet size info
68
            self.getinfo("packetsize", 1)
69
 
70
            return
71
 
72
          # wrong device
73
          handle.releaseInterface()
74
 
75
    raise Exception("Could not find specified device (devtype = %d, type = %d)" % (devtype, type))
76
 
77
 
78
#=====================================================================================    
79
 
80
 
81
  @staticmethod
82
  def __myprint(data, silent = 0):
82 benedikt93 83
    if not silent:
56 benedikt93 84
      sys.stdout.write(data)
85
      sys.stdout.flush()
86
 
87
 
88
  @staticmethod
64 benedikt93 89
  def __gethexviewprintout(data, title, showaddr):
56 benedikt93 90
    printout_temp = struct.unpack("%dB" % (len(data)), data)
91
 
64 benedikt93 92
    printout = title + ":\n"
56 benedikt93 93
    pointer = 0
94
    pointer2 = 0
95
 
64 benedikt93 96
    while (pointer < len(printout_temp)):
56 benedikt93 97
      pointer2 = 0
64 benedikt93 98
      if (showaddr): printout += "0x%08x     " % (pointer)
99
      while (pointer2 < 0x10) and (pointer < len(printout_temp)):
100
        printout += ("%2x " % (printout_temp[pointer]))
56 benedikt93 101
        pointer += 1
102
        pointer2 += 1
103
      printout += "\n"
104
 
105
    if (pointer2 != 0x10):
106
      printout += "\n"
107
 
108
    return printout
109
 
110
 
111
  @staticmethod
112
  def __getbulk(handle, endpoint, size):
113
    data = handle.bulkRead(endpoint, size, 1000)
114
    return struct.pack("%dB" % len(data), *data)
115
 
116
 
117
  @staticmethod
118
  def __checkstatus(data):
119
    errorcode = struct.unpack("<I", data[:4])[0]
120
    if errorcode == 1:
121
      # everything went fine
122
      return
123
    elif errorcode == 2:
124
      print("\nError: Device doesn't support this function!")
125
      raise Exception("emBIOS device doesn't support this function!")
126
    elif errorcode == 3:
127
      print("\nError: Device is busy!")
128
      raise Exception("emBIOS device is busy!")
129
    else:
130
      print("\nUnknown error %d" % errorcode)
131
      raise Exception("Unknown emBIOS error %d" % errorcode)
132
 
133
 
134
  @staticmethod
135
  def type2name(type):
136
    if type == 1: return "Debugger"
79 benedikt93 137
    else: return "UNKNOWN (0x%08x)" % type
56 benedikt93 138
 
139
 
140
  @staticmethod
141
  def devtype2name(devtype):
142
    if devtype == 0x47324e49: return "iPod Nano 2G"
143
    if devtype == 0x47334e49: return "iPod Nano 3G"
144
    if devtype == 0x47344e49: return "iPod Nano 4G"
145
    if devtype == 0x4c435049: return "iPod Classic"
79 benedikt93 146
    else: return "UNKNOWN (0x%08x)" % devtype
56 benedikt93 147
 
148
 
149
#=====================================================================================
150
 
151
 
152
  def getinfo (self, infotype, silent = 0):
153
    if (infotype == "version"):
154
      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 1, 0, 0, 0))
155
      response = self.__getbulk(self.handle, self.__cinep, 0x10)
156
      self.__checkstatus(response)
157
 
158
      i = struct.unpack("<IIBBBBI", response)
159
 
82 benedikt93 160
      self.svnrev, self.major, self.minor, self.patch, self.type, self.devtype = i[1:]
56 benedikt93 161
 
162
      self.__myprint("emBIOS %s v%d.%d.%d (SVN revision: %d) on %s, USB version %s\n" \
163
              % (self.type2name(self.type), self.major, self.minor, self.patch, self.svnrev, \
93 benedikt93 164
                 self.devtype2name(self.devtype), self.dev.deviceVersion)\
56 benedikt93 165
            , silent)
166
 
167
    elif (infotype == "packetsize"):
168
      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 1, 1, 0, 0))
169
      response = self.__getbulk(self.handle, self.__cinep, 0x10)
170
      self.__checkstatus(response)
171
 
172
      i = struct.unpack("<IHHII", response)
173
 
174
      self.cout_maxsize = i[1]
175
      self.cin_maxsize = i[2]
176
      self.dout_maxsize = i[3]
177
      self.din_maxsize = i[4]
178
 
179
      self.__myprint("Maximum packet sizes:\n     Command out: %d bytes\n     Command in: %d bytes\n     Data out: %d bytes\n     Data in: %d bytes\n" \
180
              % (self.cout_maxsize, self.cin_maxsize, self.dout_maxsize, self.din_maxsize)
181
            , silent)
182
 
183
    elif (infotype == "usermemrange"):
184
      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 1, 1, 0, 0))
185
      response = self.__getbulk(self.handle, self.__cinep, 0x10)
186
      self.__checkstatus(response)
187
 
188
      i = struct.unpack("<IIII", response)
189
 
190
      self.usermem_lower = i[1]
93 benedikt93 191
      self.usermem_upper = i[2]
56 benedikt93 192
 
193
      self.__myprint("User memory range:\n     Lower bound (inclusive): %x\n     Upper bound (exclusive) %x\n" \
194
              % (self.usermem_lower, self.usermem_upper)
195
            , silent)
196
 
197
    else:
198
      self.__myprint("Unsupported type of info: %d" % (infotype))
199
 
200
 
201
  def reset(self, force, silent = 0):
202
    """ Resets the device.
203
      <force>: if 0, the reset will be gracefully, otherwise it will be forced.
204
      <silent>: if not 0, nothing will be printed to the console window
205
    """
206
    if (force == 0):
207
      force = 1
208
    else:
209
      force = 0
210
 
211
    self.__myprint("Resetting device...", silent)
212
    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 2, force, 0, 0))
213
 
214
    if (force == 1):
215
      # reset not forced
216
      response = self.__getbulk(self.handle, self.__cinep, 0x10)
217
      self.__checkstatus(response)
218
 
219
    self.__myprint(" done\n", silent)  
220
 
221
 
222
  def poweroff(self, force, silent = 0):
223
    """ Powers the device off.
224
      <force>: if 0, the poweroff will be gracefully, otherwise it will be forced.
225
      <silent>: if not 0, nothing will be printed to the console window
226
    """
227
    if (force == 0):
228
      force = 1
229
    else:
230
      force = 0
231
 
232
    self.__myprint("Powering device off...", silent)
233
    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 3, force, 0, 0))
234
 
235
    if (force == 1):
236
      # shutdown not forced
237
      response = self.__getbulk(self.handle, self.__cinep, 0x10)
238
      self.__checkstatus(response)
239
 
240
    self.__myprint(" done\n", silent)
241
 
242
 
243
#=====================================================================================
244
 
245
 
246
  def write(self, offset, data, usedma, freezesched, *range):
247
    boffset = 0
248
 
249
    size = len(data)
250
 
251
    if len(range) > 0:
252
      boffset = range[0]
253
    if len(range) > 1:
254
      size = range[1]
255
 
256
    if (size == 0):
257
      return
258
 
259
    # correct alignment
260
    while (offset & 0xF) != 0:
97 benedikt93 261
      blocklen = size
262
 
56 benedikt93 263
      if (blocklen > size):
264
        blocklen = size
265
      if (blocklen > self.cout_maxsize - 0x10):
97 benedikt93 266
        blocklen = self.cout_maxsize - 0x10
56 benedikt93 267
 
97 benedikt93 268
      blocklen = (blocklen & 0xFFFFFFF0) +  (offset & 0xF)
269
 
56 benedikt93 270
      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 5, offset, blocklen, 0) + data[boffset:boffset+blocklen])
271
      response = self.__getbulk(self.handle, self.__cinep, 0x10)
272
      self.__checkstatus(response)
273
 
274
      offset += blocklen
275
      boffset += blocklen
276
      size -= blocklen
277
 
278
    # write data with DMA, if it makes sense (-> much data) and isn't forbidden
97 benedikt93 279
    if (usedma) and (size > 2 * (self.cout_maxsize - 16)): 
56 benedikt93 280
      if (freezesched):
97 benedikt93 281
        self.freezescheduler(1, 0)
56 benedikt93 282
 
97 benedikt93 283
      while (size > (self.cout_maxsize - 16)):
56 benedikt93 284
        blocklen = size
285
 
286
        if (blocklen > self.dout_maxsize):
287
          blocklen = self.dout_maxsize
288
 
289
        self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 7, offset, blocklen, 0))
290
        response = self.__getbulk(self.handle, self.__cinep, 0x10)
291
        self.__checkstatus(response)
292
 
293
        self.handle.bulkWrite(self.__doutep, data[boffset:boffset+blocklen])
294
 
295
        offset += blocklen
296
        boffset += blocklen
297
        size -= blocklen
298
 
299
      if (freezesched):
97 benedikt93 300
        self.freezescheduler(0, 0)
56 benedikt93 301
 
302
    # write rest of data
303
    while (size > 0):
304
      blocklen = size
305
 
64 benedikt93 306
      if (blocklen > self.cout_maxsize - 0x10):
97 benedikt93 307
        blocklen = self.cout_maxsize - 0x10
56 benedikt93 308
 
309
      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 5, offset, blocklen, 0) + data[boffset:boffset+blocklen])
310
      response = self.__getbulk(self.handle, self.__cinep, 0x10)
311
      self.__checkstatus(response)
312
 
313
      offset += blocklen
314
      boffset += blocklen
315
      size -= blocklen
316
 
317
 
318
  def read(self, offset, size, usedma, freezesched):
319
    if (size == 0):
320
      return
321
 
322
    data = ""
323
 
324
    # correct alignment
325
    while (offset & 0xF) != 0:
97 benedikt93 326
      blocklen = size
56 benedikt93 327
 
328
      if (blocklen > size):
329
        blocklen = size
330
      if (blocklen > self.cin_maxsize - 0x10):
97 benedikt93 331
        blocklen = self.cin_maxsize - 0x10
332
 
333
      blocklen = (blocklen & 0xFFFFFFF0) +  (offset & 0xF)
56 benedikt93 334
 
335
      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 4, offset, blocklen, 0))
336
      response = self.__getbulk(self.handle, self.__cinep, 0x10 + blocklen)
337
      self.__checkstatus(response)
338
 
339
      data += response[0x10:]
340
 
341
      offset += blocklen
342
      size -= blocklen
343
 
344
    # read data with DMA, if it makes sense (-> much data) and isn't forbidden
97 benedikt93 345
    if (usedma) and (size > 2 * (self.cin_maxsize - 16)):
56 benedikt93 346
      if (freezesched):
97 benedikt93 347
        self.freezescheduler(1, 0)
56 benedikt93 348
 
97 benedikt93 349
      while (size > (self.cin_maxsize - 16)):
56 benedikt93 350
        blocklen = size
351
 
352
        if (blocklen > self.din_maxsize):
353
          blocklen = self.din_maxsize
354
 
355
        self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 6, offset, blocklen, 0))
356
        response = self.__getbulk(self.handle, self.__cinep, 0x10)
357
        self.__checkstatus(response)
358
 
93 benedikt93 359
        data += self.__getbulk(self.handle, self.__doutep, blocklen)
56 benedikt93 360
 
361
        offset += blocklen
362
        size -= blocklen
363
 
364
      if (freezesched):
97 benedikt93 365
        self.freezescheduler(0, 0)
56 benedikt93 366
 
367
    # read rest of data
368
    while (size > 0):
369
      blocklen = size
370
 
64 benedikt93 371
      if (blocklen > self.cin_maxsize - 0x10):
97 benedikt93 372
        blocklen = self.cin_maxsize - 0x10
56 benedikt93 373
 
374
      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 4, offset, blocklen, 0))
375
      response = self.__getbulk(self.handle, self.__cinep, 0x10 + blocklen)
376
      self.__checkstatus(response)
377
 
378
      data += response[0x10:]
379
 
380
      offset += blocklen
381
      size -= blocklen
382
 
383
    return data
384
 
385
 
386
  def uploadfile(self, offset, file, usedma = 1, freezesched = 0, silent = 0):
94 benedikt93 387
    self.__myprint("Uploading %s to 0x%08x..." % (file, offset), silent)
56 benedikt93 388
    f = open(file, "rb")
389
 
390
    while True:
391
      data = f.read(262144)
392
      if data == "": break
393
      self.write(offset, data, usedma, freezesched)
394
      offset += len(data)
395
      self.__myprint(".")
396
 
397
    self.__myprint(" done\n", silent) 
398
 
399
 
400
  def downloadfile(self, offset, size, file, usedma = 1, freezesched = 0, silent = 0):
94 benedikt93 401
    self.__myprint("Downloading 0x%x bytes from 0x%08x to %s..." % (size, offset, file), silent)
56 benedikt93 402
    f = open(file, "wb")
403
 
404
    while True:
405
      blocklen = size
406
      if blocklen == 0: break
407
      if blocklen > 262144: blocklen = 262144
408
      f.write(self.read(offset, blocklen, usedma, freezesched))
409
      offset += blocklen
410
      size -= blocklen
411
      self.__myprint(".")
412
 
413
    self.__myprint(" done\n", silent)
414
 
415
 
416
  def uploadint(self, offset, data, silent = 0):
94 benedikt93 417
    self.__myprint("Uploading 0x%08x to 0x%08x..." % (data, offset), silent)
123 cmwslw 418
    data = struct.pack('<I', data)
56 benedikt93 419
    self.write(offset, data, 0, 0)
420
    self.__myprint(" done\n", silent)
421
 
422
 
423
  def downloadint(self, offset, silent = 0):
104 benedikt93 424
    self.__myprint("Downloading an integer from 0x%08x..." % (offset), silent)
106 benedikt93 425
    data = self.read(offset, 4, 0, 0)
123 cmwslw 426
    number = struct.unpack('<I', data)
427
    self.__myprint(" done\nValue was: 0x%08x\n" % (number), silent)
56 benedikt93 428
 
429
    return data
430
 
431
 
432
#=====================================================================================  
433
 
434
 
435
  def i2crecv(self, bus, slave, addr, size, silent = 0):
436
    if (size > self.cin_maxsize - 0x10) or (size > 0xFF):
437
      raise Exception ("The data exceeds the maximum amount that can be received with this instruction.")
438
 
439
    self.__myprint("Reading 0x%2x bytes from 0x%2x at I2C device at bus 0x%2x, slave adress 0x%2x ..." % (size, addr, bus, slave), silent)
440
 
441
    self.handle.bulkWrite(self.__coutep, struct.pack("<IBBBBII", 8, bus, slave, addr, size, 0, 0))
442
    data = self.__getbulk(self.handle, self.__cinep, 0x10 + size)
67 benedikt93 443
    self.__checkstatus(response)
56 benedikt93 444
 
67 benedikt93 445
    self.__myprint(" done\n data was:\n%s\n" % (self.__gethexviewprintout(data[16:])), silent)
56 benedikt93 446
 
447
    return data[16:]
448
 
449
 
450
  def i2csend(self, bus, slave, addr, data, silent = 0):
67 benedikt93 451
    size = len(data)
56 benedikt93 452
    if (size > self.cout_maxsize - 0x10) or (size > 0xFF):
453
      raise Exception ("The data exceeds the maximum amount that can be send with this instruction.")
454
 
455
    self.__myprint("Writing 0x%2x bytes to 0x%2x at I2C device at bus 0x%2x, slave adress 0x%2x ..." % (size, addr, bus, slave), silent)
456
 
67 benedikt93 457
    self.handle.bulkWrite(self.__coutep, struct.pack("<IBBBBII", 9, bus, slave, addr, size, 0, 0) + data)
458
    response = self.__getbulk(self.handle, self.__cinep, 0x10)
459
    self.__checkstatus(response)
56 benedikt93 460
 
461
    self.__myprint(" done\n", silent)
462
 
67 benedikt93 463
 
56 benedikt93 464
#=====================================================================================      
465
 
466
  def readusbcon(self, size, outtype = "", file = "", silent = 0):
467
    """ reads from USB console
82 benedikt93 468
      <size>: number of bytes to be read, if its length exceeds the Command In endpoint packet size - 0x10, it will be read in several steps
56 benedikt93 469
      <outtype>: how the data will be put out
470
        "file" => writes data to file <file>
471
        "printstring" => prints data as a string to the console window
472
        "printhex" => prints a hexview view of the data to the console window
473
        "" => only returns the data
474
      <silent>: if 0, nothing will be written to the console window (even if <outtype> defines something else)
475
 
476
      in every case, the data will be returned in an array with additional information
477
        [len, buffersize, datainbuffer, data]
478
          where len is the length of the data actually read,
479
                buffersize is the on-device read buffer size,
82 benedikt93 480
                datainbuffer is the number of bytes still left in the on device buffer,
56 benedikt93 481
                data is the actual data
82 benedikt93 482
 
483
      in case that within 5 secs, it's not possible to read <size> bytes, a timeout will occur
56 benedikt93 484
    """
82 benedikt93 485
    out_data = ""
486
    readbytes = 0
487
    buffersize = 0
488
    bytesleft = 0
489
    timeoutcounter = 0
56 benedikt93 490
 
491
    self.__myprint("Reading 0x%x bytes from USB console..." % (size), silent)
492
 
82 benedikt93 493
    while size > 0 and timoutcounter < 50:
494
      blocklen = size
495
 
496
      if size > self.cin_maxsize - 0x10:
497
        blocklen = self.cin_maxsize - 0x10
498
 
499
      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 10, blocklen, 0, 0))
500
      response = self.__getbulk(self.handle, self.__cinep, blocklen + 0x10)
501
      self.__checkstatus(response)
502
 
108 theseven 503
      readbytes, buffersize, bytesleft = struct.unpack("<III", response[4:])
82 benedikt93 504
      out_data += response[0x10:0x10+readbytes]
505
      size -= blocklen
506
 
507
      if not bytesleft > 0:   # no data left to read => wait a bit and prevent an infinite loop trying to read data when there is none
508
        timeoutcounter += 1
509
        time.sleep(0.1)
510
      else:
511
        timeoutcounter -= 3
512
        if timeoutcounter < 0:
513
          timeoutcounter = 0
514
 
515
    self.__myprint(" done\n", silent)
516
    self.__myprint("\nBytes read: 0x%x\nOn-device buffersize: 0x%x\nBytes still in device's buffer: 0x%x\n\n"\
517
                    % (len(out_data), buffersize, bytesleft)                      
518
                    , silent)
56 benedikt93 519
 
520
    if (outtype == "file"):
521
      f = open(file, "wb")
82 benedikt93 522
      f.write(out_data)
56 benedikt93 523
 
524
    elif (outtype == "printstring"):
82 benedikt93 525
      self.__myprint(out_data, silent)
56 benedikt93 526
      self.__myprint("\n\n", silent)
527
 
528
    elif (outtype == "printhex"):
82 benedikt93 529
      self.__myprint(self.__gethexviewprintout(out_data, "", 1), silent)
56 benedikt93 530
      self.__myprint("\n\n", silent)
67 benedikt93 531
 
532
    elif (outtype == ""):
533
      pass    # return only
82 benedikt93 534
 
67 benedikt93 535
    else:
64 benedikt93 536
      raise Exception ("Invalid argument for <outtype>: '%s'." % (outtype))
56 benedikt93 537
 
82 benedikt93 538
    return [len(out_data), buffersize, bytesleft, out_data]
56 benedikt93 539
 
540
 
64 benedikt93 541
  def writeusbcon(self, data, silent = 0, *range):
56 benedikt93 542
    """ writes to USB console
543
      <data>: the data to be written
544
      <range>: the range in <data> that should be written, in the from [offset, length]
545
      <silent>: if 0, nothing will be written to the console window
546
 
82 benedikt93 547
      if the data to be written exceeds the Command Out endpoint packet size - 0x10, it will be written in several steps
56 benedikt93 548
    """
549
    size = len(data)
550
    boffset = 0
551
 
552
    if len(range) > 0:
553
      boffset = range[0]
554
    if len(range) > 1:
555
      size = range[1]
556
 
557
    self.__myprint("Writing 0x%x bytes to USB console..." % (size), silent)
558
 
559
    timeoutcounter = 0
560
 
82 benedikt93 561
    while (size > 0) and (timeoutcounter < 50):
562
      blocklen = size
563
      if blocklen > self.cout_maxsize - 0x10:
564
        blocklen = self.cout_maxsize - 0x10
565
 
566
      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 11, size, 0, 0) + data[boffset:boffset+blocklen])
56 benedikt93 567
      response = self.__getbulk(self.handle, self.__cinep, 0x10)
568
      self.__checkstatus(response)
569
 
108 theseven 570
      sendbytes = struct.unpack("<I", response[4:])[0]
82 benedikt93 571
      if sendbytes < blocklen:   # not everything has been written, need to resent some stuff but wait a bit before doing so
572
        time.sleep(0.1)
573
        timeoutcounter += 1
574
      elif timeoutcounter > 0:    # lower timeoutcounter again
575
        timeoutcounter -= 3
576
        if timeoutcounter < 0:
577
          timeoutcounter = 0
56 benedikt93 578
 
82 benedikt93 579
      size -= sendbytes
580
      boffset += sendbytes
581
 
56 benedikt93 582
 
82 benedikt93 583
    if (timeoutcounter >=50):
584
      raise Exception("Timeout, 0x%x bytes couldn't be send." % size)
56 benedikt93 585
 
586
    self.__myprint(" done\n", silent)
587
 
82 benedikt93 588
    return size   # number of bytes that have not been sent
589
 
56 benedikt93 590
 
82 benedikt93 591
  def readdevcon(self, bitmask, size, outtype = "", file = "", silent = 0):
592
    """ reads from one or more of the device's consoles
593
      <bitmask>: bitmask of consoles to be read from
594
      <size>: number of bytes to be read, if its length exceeds the Command In endpoint packet size - 0x10, it will be read in several steps
595
      <outtype>: how the data will be put out
596
        "file" => writes data to file <file>
597
        "printstring" => prints data as a string to the console window
598
        "printhex" => prints a hexview view of the data to the console window
599
        "" => only returns the data
600
      <silent>: if 0, nothing will be written to the console window (even if <outtype> defines something else)
601
 
602
      in every case, the data will be returned
603
 
604
      in case that within 5 secs, it's not possible to read <size> bytes, a timeout will occur
605
    """
606
    out_data = ""
607
    readbytes = 0
608
    timeoutcounter = 0
609
 
610
    self.__myprint("Reading 0x%x bytes from device's console(s)..." % (size), silent)
611
 
612
    while size > 0 and timoutcounter < 50:
613
      blocklen = size
614
 
615
      if size > self.cin_maxsize - 0x10:
616
        blocklen = self.cin_maxsize - 0x10
617
 
618
      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 13, bitmask, blocklen, 0))
619
      response = self.__getbulk(self.handle, self.__cinep, blocklen + 0x10)
620
      self.__checkstatus(response)
621
 
108 theseven 622
      readbytes = struct.unpack("<III", response[4:])[0]
82 benedikt93 623
      out_data += response[0x10:0x10+readbytes]
624
      size -= blocklen
625
 
626
      if not readbytes > 0:   # no data read => wait a bit and prevent an infinite loop trying to read data when there is none
627
        timeoutcounter += 1
628
        time.sleep(0.1)
629
      else:
630
        timeoutcounter -= 3
631
        if timeoutcounter < 0:
632
          timeoutcounter = 0
633
 
634
    self.__myprint(" done\n", silent)
635
    self.__myprint("\nBytes read: 0x%x\n\n" % (len(out_data)), silent)
636
 
637
    if (outtype == "file"):
638
      f = open(file, "wb")
639
      f.write(out_data)
640
 
641
    elif (outtype == "printstring"):
642
      self.__myprint(out_data, silent)
643
      self.__myprint("\n\n", silent)
644
 
645
    elif (outtype == "printhex"):
646
      self.__myprint(self.__gethexviewprintout(out_data, "", 1), silent)
647
      self.__myprint("\n\n", silent)
648
 
649
    elif (outtype == ""):
650
      pass    # return only
651
 
652
    else:
653
      raise Exception ("Invalid argument for <outtype>: '%s'." % (outtype))
654
 
655
    return out_data
656
 
657
 
658
  def writedevcon(self, bitmask, data, silent = 0, *range):
659
    """ writes to USB console
660
      <bitmask>: bitmask of consoles to be written to
661
      <data>: the data to be written
662
      <range>: the range in <data> that should be written, in the from [offset, length]
663
      <silent>: if 0, nothing will be written to the console window
664
 
665
      if the data to be written exceeds the Command Out endpoint packet size - 0x10, it will be written in several steps
666
    """
667
    size = len(data)
668
    boffset = 0
669
 
670
    if len(range) > 0:
671
      boffset = range[0]
672
    if len(range) > 1:
673
      size = range[1]
674
 
675
    self.__myprint("Writing 0x%x bytes to device's console(s)..." % (size), silent)
676
 
677
    timeoutcounter = 0
678
 
679
    while size > 0:
680
      blocklen = size
681
      if blocklen > self.cout_maxsize - 0x10:
682
        blocklen = self.cout_maxsize - 0x10
683
 
684
      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 12, bitmask, size, 0) + data[boffset:boffset+blocklen])
685
      response = self.__getbulk(self.handle, self.__cinep, 0x10)
686
      self.__checkstatus(response)
687
 
688
      size -= blocklen
689
      boffset += blocklen
690
 
691
    self.__myprint(" done\n", silent)
692
 
693
 
56 benedikt93 694
  def flushconsolebuffers(self, bitmask, silent = 0):
695
    self.__myprint("Flushing device console('s) buffer('s)...")
696
 
697
    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 14, bitmask, 0, 0))
698
    response = self.__getbulk(self.handle, self.__cinep, 0x10)
699
    self.__checkstatus(response)
700
 
701
    self.__myprint(" done\n") 
702
 
703
 
704
#===================================================================================== 
705
 
706
 
707
  def freezescheduler(self, freeze, silent = 0):
708
    if (freeze):
709
      self.__myprint("Freezing scheduler...", silent)
710
      freeze = 1
64 benedikt93 711
    else:
56 benedikt93 712
      self.__myprint("Unfreezing scheduler...", silent)
713
      freeze = 0
714
 
715
    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 16, freeze, 0, 0))
716
    response = self.__getbulk(self.handle, self.__cinep, 0x10)
717
    self.__checkstatus(response)
718
 
719
    self.__myprint(" done\n", silent)    
720
 
721
 
722
  def suspendthread(self, suspend, threadid, silent = 0):
723
    if (suspend):
94 benedikt93 724
      self.__myprint("Suspending thread 0x%08x..." % threadid, silent)
56 benedikt93 725
      suspend = 1
64 benedikt93 726
    else:
94 benedikt93 727
      self.__myprint("Unsuspending thread 0x%08x..." % threadid, silent)
56 benedikt93 728
      suspend = 0
729
 
730
    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 17, suspend, threadid, 0))
731
    response = self.__getbulk(self.handle, self.__cinep, 0x10)
732
    self.__checkstatus(response)
733
 
734
    self.__myprint(" done\n", silent) 
735
 
736
 
737
  def killthread(self, threadid, silent = 0):
94 benedikt93 738
    self.__myprint("Killing thread 0x%08x..." % threadid, silent)
56 benedikt93 739
 
740
    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 18, threadid, 0, 0))
741
    response = self.__getbulk(self.handle, self.__cinep, 0x10)
742
    self.__checkstatus(response)
743
 
744
    self.__myprint(" done\n", silent) 
745
 
746
 
747
  def createthread(self, namepointer, entrypoint, stackpointer, stacksize, type, priority, state, silent = 0):
748
    self.__myprint("Creating thread...", silent)
749
 
750
    self.handle.bulkWrite(self.__coutep, struct.pack("<IIIIIIII", 19, namepointer, entrypoint, stackpointer, stacksize, type, priority, state))
751
    response = self.__getbulk(self.handle, self.__cinep, 0x10)
752
    self.__checkstatus(response)
753
 
106 benedikt93 754
    if (struct.unpack("<i", response[4:8])[0] < 0):
755
      self.__myprint(" failed, error code: 0x%x" % (struct.unpack("<i", response[4:8])[0]), silent)
64 benedikt93 756
    else:
106 benedikt93 757
      self.__myprint(" done\n, thread ID: 0x%x" % (struct.unpack("<I", response[4:8])[0]), silent)     
56 benedikt93 758
 
759
 
101 benedikt93 760
  def getprocinfo(self, silent = 0):
56 benedikt93 761
    """
762
      printout on console window:
763
        <silent> = 0: Process information struct version, Process information table size
764
        <silent> = 1: nothing
765
    """
137 benedikt93 766
    # inline functions ----------------------------------------------
102 benedikt93 767
    def procinfotolist(processinfo, structver):
101 benedikt93 768
      if (structver == 1):   # Process information struct version == 1
108 theseven 769
        ptr = 0
101 benedikt93 770
        process_n = 0
771
        retval = []
772
        while ptr < len(processinfo):
139 benedikt93 773
          if struct.unpack("<I", processinfo[ptr + 68:ptr + 72])[0] == 0:    # THREAD_FREE
774
            ptr += 120
775
            process_n += 1
776
            continue
137 benedikt93 777
 
101 benedikt93 778
          retval.append({})
56 benedikt93 779
 
108 theseven 780
          retval[process_n]['regs'] = struct.unpack("<IIIIIIIIIIIIIIII", processinfo[ptr:ptr + 64])
101 benedikt93 781
          ptr += 16 * 0x4
137 benedikt93 782
          retval[process_n]['cpsr'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
101 benedikt93 783
          ptr += 1 * 0x4
137 benedikt93 784
          retval[process_n]['state'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
101 benedikt93 785
          ptr += 1 * 0x4
137 benedikt93 786
          retval[process_n]['name_ptr'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
101 benedikt93 787
          ptr += 1 * 0x4
137 benedikt93 788
          retval[process_n]['cputime_current'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
101 benedikt93 789
          ptr += 1 * 0x4
108 theseven 790
          retval[process_n]['cputime_total'] = struct.unpack("<Q", processinfo[ptr:ptr + 8])[0]
101 benedikt93 791
          ptr += 1 * 0x8
137 benedikt93 792
          retval[process_n]['startusec'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
101 benedikt93 793
          ptr += 1 * 0x4
137 benedikt93 794
          retval[process_n]['queue_next_ptr'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
101 benedikt93 795
          ptr += 1 * 0x4
137 benedikt93 796
          retval[process_n]['timeout'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
101 benedikt93 797
          ptr += 1 * 0x4
137 benedikt93 798
          retval[process_n]['blocked_since'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
101 benedikt93 799
          ptr += 1 * 0x4
137 benedikt93 800
          retval[process_n]['blocked_by_ptr'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
101 benedikt93 801
          ptr += 1 * 0x4
137 benedikt93 802
          retval[process_n]['stack_ptr'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
101 benedikt93 803
          ptr += 1 * 0x4
137 benedikt93 804
          retval[process_n]['err_no'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
101 benedikt93 805
          ptr += 1 * 0x4
137 benedikt93 806
          retval[process_n]['block_type'] = struct.unpack("<B", processinfo[ptr:ptr + 1])[0]
101 benedikt93 807
          ptr += 1 * 0x1
137 benedikt93 808
          retval[process_n]['thread_type'] = struct.unpack("<B", processinfo[ptr:ptr + 1])[0]
101 benedikt93 809
          ptr += 1 * 0x1
137 benedikt93 810
          retval[process_n]['priority'] = struct.unpack("<B", processinfo[ptr:ptr + 1])[0]
101 benedikt93 811
          ptr += 1 * 0x1
137 benedikt93 812
          retval[process_n]['cpuload'] = struct.unpack("<B", processinfo[ptr:ptr + 1])[0]
101 benedikt93 813
          ptr += 1 * 0x1
56 benedikt93 814
 
101 benedikt93 815
          process_n += 1
56 benedikt93 816
 
101 benedikt93 817
        return retval
129 benedikt93 818
 
819
 
137 benedikt93 820
    def state2name(state, structver):
821
      if structver == 1:
822
        if state == 0: return "THREAD_FREE"
823
        elif state == 1: return "THREAD_SUSPENDED"
824
        elif state == 2: return "THREAD_READY"
825
        elif state == 3: return "THREAD_RUNNING"
826
        elif state == 4: return "THREAD_BLOCKED"
827
        elif state == 5: return "THREAD_DEFUNCT"
828
        elif state == 6: return "THREAD_DEFUNCT_ACK"
829
        else: return "UNKNOWN"
129 benedikt93 830
      else: return "UNKNOWN"
831
 
137 benedikt93 832
    def blocktype2name(blocktype, structver):
833
      if structver == 1:
834
        if blocktype == 0: return "THREAD_NOT_BLOCKED"
835
        elif blocktype == 1: return "THREAD_BLOCK_SLEEP"
836
        elif blocktype == 2: return "THREAD_BLOCK_MUTEX"
837
        elif blocktype == 3: return "THREAD_BLOCK_WAKEUP"
838
        elif blocktype == 4: return "THREAD_DEFUNCT_STKOV"
839
        elif blocktype == 5: return "THREAD_DEFUNCT_PANIC"
840
        else: return "UNKNOWN"
129 benedikt93 841
      else: return "UNKNOWN"
842
 
137 benedikt93 843
    def threadtype2name (threadtype, structver):
844
      if structver == 1:
845
        if threadtype == 0: return "USER_THREAD"
846
        elif threadtype == 1: return "OS_THREAD"
847
        elif threadtype == 2: return "CORE_THREAD"
848
        else: return "UNKNOWN"
129 benedikt93 849
      else: return "UNKNOWN"
850
 
102 benedikt93 851
    def procinfotostring(procinfolist, structver):
101 benedikt93 852
      processinfoprint = ""
853
      ptr = 0
854
      while structver == 1 and ptr < len(procinfolist):      # Process information struct version == 1
119 benedikt93 855
        processinfoprint += "--------------------------------------------------------------------------------\n"
856
        processinfoprint += "R0: 0x%08x,  R1: 0x%08x,  R2: 0x%08x,  R3: 0x%08x,\n"\
857
                            % (procinfolist[ptr]['regs'][0], procinfolist[ptr]['regs'][1], procinfolist[ptr]['regs'][2], procinfolist[ptr]['regs'][3])\
858
                            + "R4: 0x%08x,  R5: 0x%08x,  R6: 0x%08x,  R7: 0x%08x,\n"\
859
                            % (procinfolist[ptr]['regs'][4], procinfolist[ptr]['regs'][5], procinfolist[ptr]['regs'][6], procinfolist[ptr]['regs'][7])\
860
                            + "R8: 0x%08x,  R9: 0x%08x,  R10: 0x%08x, R11: 0x%08x,\n"\
861
                            % (procinfolist[ptr]['regs'][8], procinfolist[ptr]['regs'][9], procinfolist[ptr]['regs'][10], procinfolist[ptr]['regs'][11])\
862
                            + "R12: 0x%08x, SP: 0x%08x,  LR: 0x%08x,  PC: 0x%08x\n" \
863
                            % (procinfolist[ptr]['regs'][12], procinfolist[ptr]['regs'][13], procinfolist[ptr]['regs'][14], procinfolist[ptr]['regs'][15])
108 theseven 864
        processinfoprint += "cpsr: 0x%08x      " %             (procinfolist[ptr]['cpsr'])
137 benedikt93 865
        processinfoprint += "state: %s      " %                 (state2name([procinfolist[ptr]['state']], structver))
101 benedikt93 866
        processinfoprint += "nameptr: 0x%08x\n" %               (procinfolist[ptr]['name_ptr'])
867
        processinfoprint += "current cpu time: 0x%08x      " %  (procinfolist[ptr]['cputime_current'])
868
        processinfoprint += "total cpu time: 0x%016x\n" %       (procinfolist[ptr]['cputime_total'])
869
        processinfoprint += "startusec: 0x%08x      " %         (procinfolist[ptr]['startusec'])
870
        processinfoprint += "queue next ptr: 0x%08x\n" %        (procinfolist[ptr]['queue_next_ptr'])
871
        processinfoprint += "timeout: 0x%08x\n" %               (procinfolist[ptr]['timeout'])
872
        processinfoprint += "blocked since: 0x%08x      " %     (procinfolist[ptr]['blocked_since'])
873
        processinfoprint += "blocked by ptr: 0x%08x\n" %        (procinfolist[ptr]['blocked_by_ptr'])
874
        processinfoprint += "err_no: 0x%08x      " %            (procinfolist[ptr]['err_no'])
137 benedikt93 875
        processinfoprint += "block type: %s\n" %                (blocktype2name([procinfolist[ptr]['block_type']], structver))
876
        processinfoprint += "thread type: %s\n" %               (threadtype2name([procinfolist[ptr]['thread_type']], structver))
101 benedikt93 877
        processinfoprint += "priority: 0x%02x      " %          (procinfolist[ptr]['priority'])
878
        processinfoprint += "cpu load: 0x%02x\n" %              (procinfolist[ptr]['cpuload'])
119 benedikt93 879
 
880
        ptr += 1
67 benedikt93 881
 
119 benedikt93 882
      processinfoprint += "--------------------------------------------------------------------------------\n"
883
 
101 benedikt93 884
      return processinfoprint
102 benedikt93 885
 
137 benedikt93 886
    # reading code --------------------------------------------------
102 benedikt93 887
    self.__myprint("Retrieving process information...", silent)
56 benedikt93 888
 
102 benedikt93 889
    offset = 0
108 theseven 890
    blocklen = tablesize = self.cin_maxsize - 0x10
102 benedikt93 891
    procinfo = ""
892
    structversion = 0
56 benedikt93 893
 
102 benedikt93 894
    # reading loop
108 theseven 895
    while (offset < tablesize):
106 benedikt93 896
      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 15, offset, blocklen, 0))
897
      response = self.__getbulk(self.handle, self.__cinep, blocklen + 0x10)
102 benedikt93 898
      self.__checkstatus(response)
899
 
108 theseven 900
      tablesize = struct.unpack("<I", response[8:12])[0]
102 benedikt93 901
 
108 theseven 902
      if tablesize <= offset + blocklen:
119 benedikt93 903
        blocklen = tablesize - offset
904
        procinfo += response[0x10:0x10 + blocklen]
107 benedikt93 905
        structversion = struct.unpack("<I", response[4:8])[0]
906
        tablesize = struct.unpack("<I", response[8:12])[0]
119 benedikt93 907
      else:
908
        procinfo += response[0x10:0x10 + blocklen]
102 benedikt93 909
 
910
      offset += blocklen
911
 
912
      blocklen = self.cin_maxsize - 0x10
108 theseven 913
      if blocklen > tablesize - offset:
914
        blocklen = tablesize - offset
56 benedikt93 915
 
916
 
102 benedikt93 917
    out = (structversion, tablesize, procinfotolist(procinfo, structversion))
918
 
119 benedikt93 919
    self.__myprint(" done\n"\
920
                   + "Process information struct version: 0x%08x\n" % out[0]\
921
                   + "Total size of process information table: 0x%08x\n" % out[1]\
922
                   + procinfotostring(out[2], 1)\
923
                   + "\n\n")
102 benedikt93 924
 
925
    return out
926
 
927
 
96 benedikt93 928
  def execimage(self, offset, silent = 0):
94 benedikt93 929
    self.__myprint("Executing emBIOS executable image at 0x%08x..." % offset, silent)
930
 
99 theseven 931
    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 21, offset, 0, 0))
94 benedikt93 932
    response = self.__getbulk(self.handle, self.__cinep, 0x10)
933
    self.__checkstatus(response)
56 benedikt93 934
 
107 benedikt93 935
    self.__myprint(" done\n    execimage() return code: 0x%08x\n" % struct.unpack("<I", response[4:8])[0], silent)
94 benedikt93 936
 
107 benedikt93 937
    return struct.unpack("<I", response[4:8])[0]
94 benedikt93 938
 
939
 
135 benedikt93 940
  def execfirmware(self, offset, silent = 0):
941
    self.__myprint("Executing firmware image at 0x%08x..." % offset, silent)
942
 
943
    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 24, offset, 0, 0))
944
    response = self.__getbulk(self.handle, self.__cinep, 0x10)
945
    self.__checkstatus(response)
946
 
947
    self.__myprint(" done\n", silent)
948
 
949
    return
950
 
951
 
56 benedikt93 952
#===================================================================================== 
953
 
96 benedikt93 954
 
955
  def readrawbootflash(self, addr_bootflsh, addr_mem, size, silent = 0):
956
    self.__myprint("Reading 0x%x bytes from 0x%08x at bootflash to 0x%08x..." % (size, addr_bootflsh, addr_mem), silent)
957
 
958
    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 22, addr_mem, addr_bootflsh, size))
959
    response = self.__getbulk(self.handle, self.__cinep, 0x10)
960
    self.__checkstatus(response)
961
 
962
    self.__myprint(" done\n", silent)
963
 
964
 
965
  def writerawbootflash(self, addr_mem, addr_bootflsh, size, silent = 0):
966
    self.__myprint("Writing 0x%x bytes from 0x%08x to bootflash at 0x%08x..." % (size, addr_fmem, addr_bootflsh), silent)
967
 
968
    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 23, addr_mem, addr_bootflsh, size))
969
    response = self.__getbulk(self.handle, self.__cinep, 0x10)
970
    self.__checkstatus(response)
971
 
972
    self.__myprint(" done\n", silent)
973
 
974
 
975
#=====================================================================================
976
 
56 benedikt93 977
 
978
  def flushcaches(self, silent = 0):
979
    self.__myprint("Flushing caches...", silent)
980
 
981
    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 20, 0, 0, 0))
982
    response = self.__getbulk(self.handle, self.__cinep, 0x10)
983
    self.__checkstatus(response)
984
 
985
    self.__myprint(" done\n", silent) 
986
 
987
 
988
#======================================================================================
82 benedikt93 989
# backlight control, remnant from libibugger adjusted to work with libembios ==========
56 benedikt93 990
 
991
 
992
  def backlighton(self, fade, brightness, silent = 0):
993
    self.__myprint("Turning on backlight...", silent)
994
    if self.devtype == 2:
995
      self.i2csend(0, 0xe6, 0x2b, struct.pack("<B", fade), 1)
996
      self.i2csend(0, 0xe6, 0x28, struct.pack("<B", int(brightness * 46)), 1)
997
      self.i2csend(0, 0xe6, 0x29, struct.pack("<B", 1), 1)
998
      self.__myprint(" done\n", silent)
999
    elif self.devtype == 4:
1000
      self.i2csend(0, 0xe6, 0x30, struct.pack("<B", int(brightness * 250)), 1)
1001
      self.i2csend(0, 0xe6, 0x31, struct.pack("<B", 3), 1)
1002
      self.__myprint(" done\n", silent)
1003
    else: self.__myprint(" unsupported (%s)\n" % self.devtype2name(self.devtype), silent)
1004
 
1005
 
1006
  def backlightoff(self, fade, silent = 0):
1007
    self.__myprint("Turning off backlight...", silent)
1008
    if self.devtype == 2:
1009
      self.i2csend(0, 0xe6, 0x2b, struct.pack("<B", fade), 1)
1010
      self.i2csend(0, 0xe6, 0x29, struct.pack("<B", 0), 1)
1011
      self.__myprint(" done\n", silent)
1012
    elif self.devtype == 4:
1013
      self.i2csend(0, 0xe6, 0x31, struct.pack("<B", 2), 1)
1014
      self.__myprint(" done\n", silent)
1015
    else: self.__myprint(" unsupported (%s)\n" % self.devtype2name(self.devtype), silent)
123 cmwslw 1016