| 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 |