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 |