freemyipod r56 - Code Review

Jump to: navigation, search
Repository:freemyipod
Revision:r55‎ | r56 | r57 >
Date:22:23, 8 August 2010
Author:benedikt93
Status:new
Tags:
Comment:
commit libembios.py
Modified paths:
  • /embios/trunk/tools/libembios.py (added) (history)

Diff [purge]

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