Subversion Repositories freemyipod

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
56 benedikt93 1
#!/usr/bin/env python
2
#
3
#
171 farthen 4
#    Copyright 2010 TheSeven, benedikt93, Farthen
56 benedikt93 5
#
6
#
7
#    This file is part of emBIOS.
8
#
9
#    emBIOS is free software: you can redistribute it and/or
10
#    modify it under the terms of the GNU General Public License as
11
#    published by the Free Software Foundation, either version 2 of the
12
#    License, or (at your option) any later version.
13
#
14
#    emBIOS is distributed in the hope that it will be useful,
15
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
16
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
#    See the GNU General Public License for more details.
18
#
19
#    You should have received a copy of the GNU General Public License
20
#    along with emBIOS.  If not, see <http://www.gnu.org/licenses/>.
21
#
22
#
23
 
24
import sys
25
import struct
171 farthen 26
import usb.core
27
import libembiosdata
56 benedikt93 28
 
394 farthen 29
from functools import wraps
30
 
171 farthen 31
class Error(Exception):
32
    def __init__(self, value=None):
33
        self.value = value
34
    def __str__(self):
35
        if self.value != None:
36
            return repr(self.value)
56 benedikt93 37
 
171 farthen 38
class ArgumentError(Error):
39
    pass
56 benedikt93 40
 
171 farthen 41
class DeviceNotFoundError(Error):
42
    pass
56 benedikt93 43
 
171 farthen 44
class DeviceError(Error):
45
    pass
56 benedikt93 46
 
171 farthen 47
class SendError(Error):
48
    pass
56 benedikt93 49
 
171 farthen 50
class ReceiveError(Error):
51
    pass
56 benedikt93 52
 
53
 
171 farthen 54
class Bunch(dict):
56 benedikt93 55
    """
171 farthen 56
        This is a dict whose items can also be accessed with
57
        bunchinstance.something.
56 benedikt93 58
    """
171 farthen 59
    def __init__(self, **kw):
60
        dict.__init__(self, kw)
61
        self.__dict__ = self
56 benedikt93 62
 
171 farthen 63
    def __getstate__(self):
64
        return self
56 benedikt93 65
 
171 farthen 66
    def __setstate__(self, state):
67
        self.update(state)
68
        self.__dict__ = self
56 benedikt93 69
 
70
 
394 farthen 71
def command(timeout = None):
72
    """
73
        Decorator for all commands.
74
        It adds the "timeout" variable to all commands.
75
        It also provides the possibility to set the timeout directly in the decorator.
76
        It also includes some dirty hacks to not learn from.
77
    """
78
    time = timeout # dirty hack because otherwise it would raise a scoping problem.
79
                   # The reason is probably because I suck but I can't find any good explanation of this.
80
    def decorator(func):
81
        @wraps(func)
82
        def wrapper(*args, **kwargs):
83
            # precommand stuff
84
            self = args[0] # little cheat as it expects self being always the first argument
85
            timeout = None
86
            if "timeout" in kwargs.keys():
87
                timeout = kwargs['timeout']
88
            elif time is not None:
89
                timeout = time
90
            if timeout is not None:
91
                oldtimeout = self.lib.dev.timeout
92
                self.lib.dev.timeout = timeout
93
            # function call
94
            ret = func(*args)
95
            # postcommand stuff
96
            if timeout is not None:
97
                self.lib.dev.timeout = oldtimeout
98
            return ret
99
        return wrapper
100
    return decorator
101
 
102
 
171 farthen 103
class Embios(object):
176 farthen 104
    """
105
        Class for all embios functions.
394 farthen 106
        They all get the "@command()" decorator.
107
        This decorator has a timeout variable that can be set to change the
108
        device timeout for the duration of the function.
109
        It also adds a "timeout" argument to every function to access this
110
        feature from external. So DON'T EVER use a parameter called 'timeout'
111
        in your commands. Variables are ok.
176 farthen 112
    """
171 farthen 113
    def __init__(self):
176 farthen 114
        self.lib = Lib()
343 farthen 115
 
116
        self.getversioninfo()
176 farthen 117
        self.getpacketsizeinfo()
343 farthen 118
        self.getusermemrange()
56 benedikt93 119
 
171 farthen 120
    @staticmethod
121
    def _alignsplit(addr, size, blksize, align):
177 farthen 122
        if size <= blksize: return (size, 0, 0)
171 farthen 123
        end = addr + size
124
        if addr & (align - 1):
125
            bodyaddr = (addr + min(size, blksize)) & ~(align - 1)
126
        else: bodyaddr = addr
127
        headsize = bodyaddr - addr
128
        if (size - headsize) & (align - 1):
129
            tailaddr = (end - min(end - bodyaddr, blksize) + align - 1) & ~(align - 1)
130
        else: tailaddr = end
131
        tailsize = end - tailaddr
132
        return (headsize, tailaddr - bodyaddr, tailsize)
56 benedikt93 133
 
394 farthen 134
    @command()
178 farthen 135
    def _readmem(self, addr, size):
136
        """ Reads the memory from location 'addr' with size 'size'
137
            from the device.
138
        """
139
        resp = self.lib.monitorcommand(struct.pack("IIII", 4, addr, size, 0), "III%ds" % size, (None, None, None, "data"))
140
        return resp.data
394 farthen 141
 
142
    @command()
178 farthen 143
    def _writemem(self, addr, data):
144
        """ Writes the data in 'data' to the location 'addr'
145
            in the memory of the device.
146
        """
147
        return self.lib.monitorcommand(struct.pack("IIII%ds" % len(data), 5, addr, len(data), 0, data), "III", (None, None, None))
148
 
394 farthen 149
    @command()
178 farthen 150
    def _readdma(self, addr, size):
151
        """ Reads the memory from location 'addr' with size 'size'
152
            from the device. This uses DMA and the data in endpoint.
153
        """
154
        self.lib.monitorcommand(struct.pack("IIII", 6, addr, size, 0), "III", (None, None, None))
155
        return struct.unpack("%ds" % size, self.lib.dev.din(size))[0]
156
 
394 farthen 157
    @command()
178 farthen 158
    def _writedma(self, addr, data):
159
        """ Writes the data in 'data' to the location 'addr'
160
            in the memory of the device. This uses DMA and the data out endpoint.
161
        """
162
        self.lib.monitorcommand(struct.pack("IIII", 7, addr, len(data), 0), "III", (None, None, None))
163
        return self.lib.dev.dout(data)
164
 
394 farthen 165
    @command()
171 farthen 166
    def getversioninfo(self):
167
        """ This returns the emBIOS version and device information. """
342 farthen 168
        resp = self.lib.monitorcommand(struct.pack("IIII", 1, 0, 0, 0), "IBBBBI", ("revision", "majorv", "minorv", "patchv", "swtypeid", "hwtypeid"))
169
        self.lib.dev.version.revision = resp.revision
170
        self.lib.dev.version.majorv = resp.majorv
171
        self.lib.dev.version.minorv = resp.minorv
172
        self.lib.dev.version.patchv = resp.patchv
173
        self.lib.dev.swtypeid = resp.swtypeid
174
        self.lib.dev.hwtypeid = resp.hwtypeid
175
        return resp
56 benedikt93 176
 
394 farthen 177
    @command()
171 farthen 178
    def getpacketsizeinfo(self):
179
        """ This returns the emBIOS max packet size information.
180
            It also sets the properties of the device object accordingly.
181
        """
182
        resp = self.lib.monitorcommand(struct.pack("IIII", 1, 1, 0, 0), "HHII", ("coutmax", "cinmax", "doutmax", "dinmax"))
343 farthen 183
        self.lib.dev.packetsizelimit.cout = resp.coutmax
184
        self.lib.dev.packetsizelimit.cin = resp.cinmax
185
        self.lib.dev.packetsizelimit.din = resp.dinmax
186
        self.lib.dev.packetsizelimit.dout = resp.doutmax
171 farthen 187
        return resp
56 benedikt93 188
 
394 farthen 189
    @command()
171 farthen 190
    def getusermemrange(self):
191
        """ This returns the memory range the user has access to. """
342 farthen 192
        resp = self.lib.monitorcommand(struct.pack("IIII", 1, 2, 0, 0), "III", ("lower", "upper", None))
193
        self.lib.dev.usermem.lower = resp.lower
194
        self.lib.dev.usermem.upper = resp.upper
195
        return resp
56 benedikt93 196
 
394 farthen 197
    @command()
171 farthen 198
    def reset(self, force=False):
199
        """ Reboot the device """
200
        if force:
201
            return self.lib.monitorcommand(struct.pack("IIII", 2, 0, 0, 0))
202
        else:
203
            return self.lib.monitorcommand(struct.pack("IIII", 2, 1, 0, 0), "III", (None, None, None))
56 benedikt93 204
 
394 farthen 205
    @command()
171 farthen 206
    def poweroff(self, force=False):
207
        """ Powers the device off. """
208
        if force:
209
            return self.lib.monitorcommand(struct.pack("IIII", 3, 0, 0, 0))
210
        else:
211
            return self.lib.monitorcommand(struct.pack("IIII", 3, 1, 0, 0), "III", (None, None, None))
56 benedikt93 212
 
394 farthen 213
    @command()
171 farthen 214
    def read(self, addr, size):
215
        """ Reads the memory from location 'addr' with size 'size'
216
            from the device. This cares about too long packages
217
            and decides whether to use DMA or not.
218
        """
343 farthen 219
        cin_maxsize = self.lib.dev.packetsizelimit.cin - self.lib.headersize
220
        din_maxsize = self.lib.dev.packetsizelimit.din
171 farthen 221
        data = ""
222
        (headsize, bodysize, tailsize) = self._alignsplit(addr, size, cin_maxsize, 16)
223
        if headsize != 0:
178 farthen 224
            data += self._readmem(addr, headsize)
171 farthen 225
            addr += headsize
226
        while bodysize > 0:
227
            if bodysize >= 2 * cin_maxsize:
228
                readsize = min(bodysize, din_maxsize)
178 farthen 229
                data += self._readdma(addr, readsize)
171 farthen 230
            else:
231
                readsize = min(bodysize, cin_maxsize)
178 farthen 232
                data += self._readmem(addr, readsize)
171 farthen 233
            addr += readsize
234
            bodysize -= readsize
235
        if tailsize != 0:
178 farthen 236
            data += self._readmem(addr, tailsize)
171 farthen 237
        return data
56 benedikt93 238
 
394 farthen 239
    @command()
171 farthen 240
    def write(self, addr, data):
241
        """ Writes the data in 'data' to the location 'addr'
242
            in the memory of the device. This cares about too long packages
243
            and decides whether to use DMA or not.
244
        """
343 farthen 245
        cout_maxsize = self.lib.dev.packetsizelimit.cout - self.lib.headersize
246
        dout_maxsize = self.lib.dev.packetsizelimit.dout
171 farthen 247
        (headsize, bodysize, tailsize) = self._alignsplit(addr, len(data), cout_maxsize, 16)
248
        offset = 0
249
        if headsize != 0:
178 farthen 250
            self._writemem(addr, data[offset:offset+headsize])
171 farthen 251
            offset += headsize
252
            addr += headsize
253
        while bodysize > 0:
254
            if bodysize >= 2 * cout_maxsize:
255
                writesize = min(bodysize, dout_maxsize)
178 farthen 256
                self._writedma(addr, data[offset:offset+writesize])
171 farthen 257
            else:
258
                writesize = min(bodysize, cout_maxsize)
178 farthen 259
                self._writemem(addr, data[offset:offset+writesize])
171 farthen 260
            offset += writesize
261
            addr += writesize
262
            bodysize -= writesize
263
        if tailsize != 0:
178 farthen 264
            self._writemem(addr, data[offset:offset+tailsize])
171 farthen 265
        return data
56 benedikt93 266
 
394 farthen 267
    @command()
173 farthen 268
    def readstring(self, addr, maxlength = 256):
269
        """ Reads a zero terminated string from memory 
270
            Reads only a maximum of 'maxlength' chars.
271
        """
343 farthen 272
        cin_maxsize = self.lib.dev.packetsizelimit.cin - self.lib.headersize
173 farthen 273
        string = ""
274
        while (len(string) < maxlength or maxlength < 0):
178 farthen 275
            data = self._readmem(addr, min(maxlength - len(string), cin_maxsize))
173 farthen 276
            length = data.find("\0")
277
            if length >= 0:
278
                string += data[:length]
279
                break
280
            else:
281
                string += data
282
            addr += cin_maxsize
283
        return string
284
 
394 farthen 285
    @command()
171 farthen 286
    def i2cread(self, index, slaveaddr, startaddr, size):
287
        """ Reads data from an i2c slave """
236 farthen 288
        data = ""
289
        for i in range(size):
290
            resp = self.lib.monitorcommand(struct.pack("IBBBBII", 8, index, slaveaddr, startaddr + i, 1, 0, 0), "III1s", (None, None, None, "data"))
291
            data += resp.data
292
        return data
56 benedikt93 293
 
394 farthen 294
    @command()
171 farthen 295
    def i2cwrite(self, index, slaveaddr, startaddr, data):
296
        """ Writes data to an i2c slave """
176 farthen 297
        size = len(data)
298
        if size > 256 or size < 1:
341 farthen 299
            raise ArgumentError("Size must be a number between 1 and 256")
176 farthen 300
        if size == 256:
301
            size = 0
215 theseven 302
        return self.lib.monitorcommand(struct.pack("IBBBBII%ds" % size, 9, index, slaveaddr, startaddr, size, 0, 0, data), "III", (None, None, None))
56 benedikt93 303
 
394 farthen 304
    @command()
176 farthen 305
    def usbcread(self):
306
        """ Reads one packet with the maximal cin size """
343 farthen 307
        cin_maxsize = self.lib.dev.packetsizelimit.cin - self.lib.headersize
176 farthen 308
        resp = self.lib.monitorcommand(struct.pack("IIII", 10, cin_maxsize, 0, 0), "III%ds" % cin_maxsize, ("validsize", "buffersize", "queuesize", "data"))
309
        resp.data = resp.data[:resp.validsize]
310
        resp.maxsize = cin_maxsize
311
        return resp
56 benedikt93 312
 
394 farthen 313
    @command()
171 farthen 314
    def usbcwrite(self, data):
315
        """ Writes data to the USB console """
343 farthen 316
        cin_maxsize = self.lib.dev.packetsizelimit.cin - self.lib.headersize
176 farthen 317
        size = len(data)
318
        while len(data) > 0:
319
            writesize = min(cin_maxsize, len(data))
320
            resp = self.lib.monitorcommand(struct.pack("IIII%ds" % writesize, 11, writesize, 0, 0, data[:writesize]), "III", ("validsize", "buffersize", "freesize"))
321
            data = data[resp.validsize:]
322
        return size
56 benedikt93 323
 
394 farthen 324
    @command()
176 farthen 325
    def cread(self, bitmask=0x1):
326
        """ Reads one packet with the maximal cin size from the device consoles
171 farthen 327
            identified with the specified bitmask
328
        """
343 farthen 329
        cin_maxsize = self.lib.dev.packetsizelimit.cin - self.lib.headersize
217 theseven 330
        resp = self.lib.monitorcommand(struct.pack("IIII", 13, bitmask, cin_maxsize, 0), "III%ds" % cin_maxsize, ("size", None, None))
176 farthen 331
        resp.data = resp.data[size:]
332
        resp.maxsize = cin_maxsize
333
        return resp
394 farthen 334
 
335
    @command()
176 farthen 336
    def cwrite(self, data, bitmask=0x1):
171 farthen 337
        """ Writes data to the device consoles 
338
            identified with the specified bitmask.
339
        """
343 farthen 340
        cin_maxsize = self.lib.dev.packetsizelimit.cin - self.lib.headersize
176 farthen 341
        size = len(data)
342
        while len(data) > 0:
343
            writesize = min(cin_maxsize, len(data))
217 theseven 344
            resp = self.lib.monitorcommand(struct.pack("IIII%ds" % writesize, 12, bitmask, writesize, 0, data[:writesize]), "III", (None, None, None))
176 farthen 345
            data = data[writesize:]
346
        return size
56 benedikt93 347
 
394 farthen 348
    @command()
171 farthen 349
    def cflush(self, bitmask):
350
        """ Flushes the consoles specified with 'bitmask' """
351
        return self.lib.monitorcommand(struct.pack("IIII", 14, bitmask, 0, 0), "III", (None, None, None))
56 benedikt93 352
 
394 farthen 353
    @command()
173 farthen 354
    def getprocinfo(self):
171 farthen 355
        """ Gets current state of the scheduler """
343 farthen 356
        cin_maxsize = self.lib.dev.packetsizelimit.cin - self.lib.headersize
173 farthen 357
        # Get the size
358
        schedulerstate = self.lockscheduler()
359
        resp = self.lib.monitorcommand(struct.pack("IIII", 15, 0, 0, 0), "III", ("structver", "tablesize", None))
360
        tablesize = resp.tablesize
361
        size = tablesize
362
        structver = resp.structver
363
        offset = 0
364
        data = ""
365
        while size > 0:
366
            if size > cin_maxsize:
367
                readsize = cin_maxsize
368
            else:
369
                readsize = size
370
            resp = self.lib.monitorcommand(struct.pack("IIII", 15, offset, readsize, 0), "III%ds" % readsize, ("structver", "tablesize", None, "data"))
371
            data += resp.data
372
            offset += readsize
373
            size -= readsize
374
        self.lockscheduler(schedulerstate)
375
        threadstructsize = 120
376
        registersize = 32
377
        if len(data) % threadstructsize != 0:
378
            raise DeviceError("The thread struct is not a multiple of "+str(threadsturcsize)+"!")
379
        threadcount = len(data) / threadstructsize
380
        threads = []
381
        id = 0
382
        for thread in range(threadcount):
383
            offset = threadstructsize * thread
384
            threaddata = struct.unpack("<16IIIIIQIIIIIIIBBBB", data[offset:offset+threadstructsize])
385
            info = Bunch()
386
            info.id = id
387
            state = threaddata[17]
388
            info.state = libembiosdata.thread_state[state]
389
            if info.state == "THREAD_FREE":
390
                id += 1
391
                continue
392
            info.regs = Bunch()
393
            for register in range(16):
394
                info.regs["r"+str(register)] = threaddata[register]
395
            info.regs.cpsr = threaddata[16]
396
            info.nameptr = threaddata[18]
397
            if info.nameptr == 0:
398
                info.name = "Thread %d" % info.id
399
            else:
400
                info.name = self.readstring(info.nameptr)
401
            info.cputime_current = threaddata[19]
402
            info.cputime_total = threaddata[20]
403
            info.startusec = threaddata[21]
404
            info.queue_next_ptr = threaddata[22]
405
            info.timeout = threaddata[23]
406
            info.blocked_since = threaddata[24]
407
            info.blocked_by_ptr = threaddata[25]
408
            info.stackaddr = threaddata[26]
409
            info.err_no = threaddata[27]
410
            info.block_type = libembiosdata.thread_block[threaddata[28]]
411
            info.type = libembiosdata.thread_type[threaddata[29]]
412
            info.priority = threaddata[30]
413
            info.cpuload = threaddata[31]
414
            threads.append(info)
415
            id += 1
416
        return threads
56 benedikt93 417
 
394 farthen 418
    @command()
173 farthen 419
    def lockscheduler(self, freeze=True):
171 farthen 420
        """ Freezes/Unfreezes the scheduler """
173 farthen 421
        resp = self.lib.monitorcommand(struct.pack("IIII", 16, 1 if freeze else 0, 0, 0), "III", ("before", None, None))
422
        return True if resp.before == 1 else False
67 benedikt93 423
 
394 farthen 424
    @command()
173 farthen 425
    def unlockscheduler(self):
171 farthen 426
        """ Unfreezes the scheduler """
427
        return self.lib.monitorcommand(struct.pack("IIII", 16, 0, 0, 0), "III", ("before", None, None))
56 benedikt93 428
 
394 farthen 429
    @command()
171 farthen 430
    def suspendthread(self, id, suspend=True):
431
        """ Suspends the thread with the specified id """
173 farthen 432
        resp = self.lib.monitorcommand(struct.pack("IIII", 17, 1 if suspend else 0, id, 0), "III", ("before", None, None))
433
        return True if resp.before == 1 else False
56 benedikt93 434
 
394 farthen 435
    @command()
173 farthen 436
    def resumethread(self, id):
437
        """ Resumes the thread with the specified id """
171 farthen 438
        return self.lib.monitorcommand(struct.pack("IIII", 17, 0, id, 0), "III", ("before", None, None))
56 benedikt93 439
 
394 farthen 440
    @command()
171 farthen 441
    def killthread(self, id):
442
        """ Kills the thread with the specified id """
443
        return self.lib.monitorcommand(struct.pack("IIII", 18, id, 0, 0), "III", ("before", None, None))
56 benedikt93 444
 
394 farthen 445
    @command()
171 farthen 446
    def createthread(self, nameptr, entrypoint, stackptr, stacksize, threadtype, priority, state):
447
        """ Creates a thread with the specified attributes """
448
        if threadtype == "user":
449
            threadtype = 0
450
        elif threadtype == "system":
451
            threadtype = 1
452
        else:
341 farthen 453
            raise ArgumentError("Threadtype must be either 'system' or 'user'")
171 farthen 454
        if priority > 256 or priority < 0:
341 farthen 455
            raise ArgumentError("Priority must be a number between 0 and 256")
171 farthen 456
        if state == "ready":
457
            state = 0
458
        elif state == "suspended":
459
            state = 1
460
        else:
341 farthen 461
            raise ArgumentError("State must be either 'ready' or 'suspended'")
171 farthen 462
        resp = self.lib.monitorcommand(struct.pack("IIIIIIII", 19, nameptr, entrypoint, stackptr, stacksize, threadtype, priority, state), "III", (id, None, None))
463
        if resp.id < 0:
464
            raise DeviceError("The device returned the error code "+str(resp.id))
465
        return resp
56 benedikt93 466
 
394 farthen 467
    @command()
172 farthen 468
    def flushcaches(self):
171 farthen 469
        """ Flushes the CPU instruction and data cache """
470
        return self.lib.monitorcommand(struct.pack("IIII", 20, 0, 0, 0), "III", (None, None, None))
56 benedikt93 471
 
394 farthen 472
    @command()
172 farthen 473
    def execimage(self, addr):
171 farthen 474
        """ Runs the emBIOS app at 'addr' """
346 theseven 475
        return self.lib.monitorcommand(struct.pack("IIII", 21, addr, 0, 0), "III", ("rc", None, None))
56 benedikt93 476
 
394 farthen 477
    @command()
238 farthen 478
    def run(self, app):
479
        """ Uploads and runs the emBIOS app in the string 'app' """
480
        try:
481
            appheader = struct.unpack("<8sIIIIIIIIII", app[:48])
482
        except struct.error:
341 farthen 483
            raise ArgumentError("The specified app is not an emBIOS application")
238 farthen 484
        header = appheader[0]
485
        if header != "emBIexec":
341 farthen 486
            raise ArgumentError("The specified app is not an emBIOS application")
238 farthen 487
        baseaddr = appheader[2]
488
        threadnameptr = appheader[8]
489
        nameptr = threadnameptr - baseaddr
490
        name = ""
491
        while True:
492
            char = app[nameptr:nameptr+1]
493
            try:
494
                if ord(char) == 0:
495
                    break
496
            except TypeError:
341 farthen 497
                raise ArgumentError("The specified app is not an emBIOS application")
238 farthen 498
            name += char
499
            nameptr += 1
500
        usermem = self.getusermemrange()
501
        if usermem.lower > baseaddr or usermem.upper < baseaddr + len(app):
502
            raise ArgumentError("The baseaddress of the specified emBIOS application is out of range of the user memory range on the device. Are you sure that this application is compatible with your device?")
503
        self.write(baseaddr, app)
504
        self.execimage(baseaddr)
505
        return Bunch(baseaddr=baseaddr, name=name)
506
 
395 farthen 507
    @command(timeout = 5000)
171 farthen 508
    def bootflashread(self, memaddr, flashaddr, size):
509
        """ Copies the data in the bootflash at 'flashaddr' of the specified size
510
            to the memory at addr 'memaddr'
511
        """
174 farthen 512
        return self.lib.monitorcommand(struct.pack("IIII", 22, memaddr, flashaddr, size), "III", (None, None, None))
82 benedikt93 513
 
395 farthen 514
    @command(timeout = 30000)
171 farthen 515
    def bootflashwrite(self, memaddr, flashaddr, size):
516
        """ Copies the data in the memory at 'memaddr' of the specified size
517
            to the boot flash at addr 'flashaddr'
518
        """
174 farthen 519
        return self.lib.monitorcommand(struct.pack("IIII", 23, memaddr, flashaddr, size), "III", (None, None, None))
56 benedikt93 520
 
394 farthen 521
    @command()
171 farthen 522
    def execfirmware(self, addr):
523
        """ Executes the firmware at 'addr' and passes all control to it. """
269 farthen 524
        return self.lib.monitorcommand(struct.pack("IIII", 24, addr, 0, 0))
56 benedikt93 525
 
395 farthen 526
    @command(timeout = 30000)
171 farthen 527
    def aesencrypt(self, addr, size, keyindex):
528
        """ Encrypts the buffer at 'addr' with the specified size
529
            with the hardware AES key index 'keyindex'
530
        """
531
        return self.lib.monitorcommand(struct.pack("IBBHII", 25, 1, 0, keyindex, addr, size), "III", (None, None, None))
82 benedikt93 532
 
395 farthen 533
    @command(timeout = 30000)
171 farthen 534
    def aesdecrypt(self, addr, size, keyindex):
535
        """ Decrypts the buffer at 'addr' with the specified size
536
            with the hardware AES key index 'keyindex'
537
        """
538
        return self.lib.monitorcommand(struct.pack("IBBHII", 25, 0, 0, keyindex, addr, size), "III", (None, None, None))
82 benedikt93 539
 
395 farthen 540
    @command(timeout = 30000)
171 farthen 541
    def hmac_sha1(self, addr, size, destination):
542
        """ Generates a HMAC-SHA1 hash of the buffer and saves it to 'destination' """
543
        return self.lib.monitorcommand(struct.pack("IIII", 26, addr, size, destination), "III", (None, None, None))
56 benedikt93 544
 
394 farthen 545
    @command()
227 theseven 546
    def ipodnano2g_getnandinfo(self):
547
        """ Target-specific function: ipodnano2g
548
            Gathers some information about the NAND chip used
549
        """
346 theseven 550
        if self.lib.dev.hwtypeid != 0x47324e49: raise DeviceError("Wrong device for target-specific command.")
227 theseven 551
        return self.lib.monitorcommand(struct.pack("IIII", 0xffff0001, 0, 0, 0), "IHHHH", ("type", "pagesperblock", "banks", "userblocks", "blocks"))
552
 
395 farthen 553
    @command(timeout = 30000)
227 theseven 554
    def ipodnano2g_nandread(self, addr, start, count, doecc, checkempty):
555
        """ Target-specific function: ipodnano2g
556
            Reads data from the NAND chip into memory
557
        """
346 theseven 558
        if self.lib.dev.hwtypeid != 0x47324e49: raise DeviceError("Wrong device for target-specific command.")
227 theseven 559
        return self.lib.monitorcommand(struct.pack("IIII", 0xffff0002, addr | (0x80000000 if doecc != 0 else 0) | (0x40000000 if checkempty != 0 else 0), start, count), "III", (None, None, None))
560
 
395 farthen 561
    @command(timeout = 30000)
227 theseven 562
    def ipodnano2g_nandwrite(self, addr, start, count, doecc):
563
        """ Target-specific function: ipodnano2g
564
            Writes data to the NAND chip
565
        """
346 theseven 566
        if self.lib.dev.hwtypeid != 0x47324e49: raise DeviceError("Wrong device for target-specific command.")
227 theseven 567
        return self.lib.monitorcommand(struct.pack("IIII", 0xffff0003, addr | (0x80000000 if doecc != 0 else 0), start, count), "III", (None, None, None))
568
 
395 farthen 569
    @command(timeout = 30000)
227 theseven 570
    def ipodnano2g_nanderase(self, addr, start, count):
571
        """ Target-specific function: ipodnano2g
572
            Erases blocks on the NAND chip and stores the results to memory
573
        """
346 theseven 574
        if self.lib.dev.hwtypeid != 0x47324e49: raise DeviceError("Wrong device for target-specific command.")
227 theseven 575
        return self.lib.monitorcommand(struct.pack("IIII", 0xffff0004, addr, start, count), "III", (None, None, None))
576
 
394 farthen 577
    @command()
346 theseven 578
    def ipodclassic_gethddinfo(self):
579
        """ Target-specific function: ipodclassic
580
            Gather information about the hard disk drive
581
        """
582
        if self.lib.dev.hwtypeid != 0x4c435049: raise DeviceError("Wrong device for target-specific command.")
583
        return self.lib.monitorcommand(struct.pack("IIII", 0xffff0001, 0, 0, 0), "IQQII", ("identifyptr", "totalsectors", "virtualsectors", "bbtptr", "bbtsize"))
584
 
395 farthen 585
    @command(timeout = 30000)
346 theseven 586
    def ipodclassic_hddaccess(self, type, sector, count, addr):
587
        """ Target-specific function: ipodclassic
588
            Access the hard disk, type = 0 (read) / 1 (write)
589
        """
590
        if self.lib.dev.hwtypeid != 0x4c435049: raise DeviceError("Wrong device for target-specific command.")
591
        rc = self.lib.monitorcommand(struct.pack("IIQIIII", 0xffff0002, type, sector, count, addr, 0, 0), "III", ("rc", None, None))
592
        if (rc > 0x80000000):
593
            raise DeviceError("HDD access (type=%d, sector=%d, count=%d, addr=0x%08X) failed with RC 0x%08X" % (type, sector, count, addr, rc))
594
 
394 farthen 595
    @command()
346 theseven 596
    def ipodclassic_writebbt(self, bbt, tempaddr):
597
        """ Target-specific function: ipodclassic
598
            Write hard drive bad block table
599
        """
600
        if self.lib.dev.hwtypeid != 0x4c435049: raise DeviceError("Wrong device for target-specific command.")
601
        try:
602
            bbtheader = struct.unpack("<8s2024sQII512I", bbt[:4096])
603
        except struct.error:
604
            raise ArgumentError("The specified file is not an emBIOS hard disk BBT")
605
        if bbtheader[0] != "emBIbbth":
606
            raise ArgumentError("The specified file is not an emBIOS hard disk BBT")
607
        virtualsectors = bbtheader[2]
608
        bbtsectors = bbtheader[3]
609
        self.write(tempaddr, bbt)
610
        sector = 0
611
        count = 1
612
        offset = 0
613
        for i in range(bbtsectors):
614
            if bbtheader[4][i] == sector + count:
615
                count = count + 1
616
            else:
617
                self.ipodclassic_hddaccess(1, sector, count, tempaddr + offset)
618
                offset = offset + count * 4096
619
                sector = bbtheader[4][i]
620
                count = 1
621
        self.ipodclassic_hddaccess(1, sector, count, tempaddr + offset)
622
 
394 farthen 623
    @command()
379 theseven 624
    def storage_get_info(self, volume):
346 theseven 625
        """ Get information about a storage device """
379 theseven 626
        result = self.lib.monitorcommand(struct.pack("IIII", 27, volume, 0, 0), "IIIIIIII", ("version", None, None, "sectorsize", "numsectors", "vendorptr", "productptr", "revisionptr"))
346 theseven 627
        if result.version != 1:
628
            raise ValueError("Unknown version of storage_info struct: %d" % result.version)
379 theseven 629
        result.vendor = self.readstring(result.vendorptr)
630
        result.product = self.readstring(result.productptr)
631
        result.revision = self.readstring(result.revisionptr)
346 theseven 632
        return result
633
 
395 farthen 634
    @command(timeout = 50000)
346 theseven 635
    def storage_read_sectors_md(self, volume, sector, count, addr):
636
        """ Read sectors from as storage device """
637
        result = self.lib.monitorcommand(struct.pack("IIQIIII", 28, volume, sector, count, addr, 0, 0), "III", ("rc", None, None, None))
638
        if result.rc > 0x80000000:
639
            raise DeviceError("storage_read_sectors_md(volume=%d, sector=%d, count=%d, addr=0x%08X) failed with RC 0x%08X" % (volume, sector, count, addr, rc))
394 farthen 640
 
395 farthen 641
    @command(timeout = 50000)
346 theseven 642
    def storage_write_sectors_md(self, volume, sector, count, addr):
643
        """ Read sectors from as storage device """
644
        result = self.lib.monitorcommand(struct.pack("IIQIIII", 29, volume, sector, count, addr, 0, 0), "III", ("rc", None, None, None))
645
        if result.rc > 0x80000000:
646
            raise DeviceError("storage_read_sectors_md(volume=%d, sector=%d, count=%d, addr=0x%08X) failed with RC 0x%08X" % (volume, sector, count, addr, rc))
394 farthen 647
 
395 farthen 648
    @command(timeout = 30000)
346 theseven 649
    def file_open(self, filename, mode):
650
        """ Opens a file and returns the handle """
651
        result = self.lib.monitorcommand(struct.pack("IIII%dsB" % len(filename), 30, mode, 0, 0, filename, 0), "III", ("fd", None, None))
652
        if result.fd > 0x80000000:
653
            raise DeviceError("file_open(filename=\"%s\", mode=0x%X) failed with RC=0x%08X, errno=%d" % (filename, mode, result.fd, self.errno()))
654
        return result.fd
655
 
395 farthen 656
    @command(timeout = 30000)
346 theseven 657
    def file_size(self, fd):
658
        """ Gets the size of a file referenced by a handle """
659
        result = self.lib.monitorcommand(struct.pack("IIII", 31, fd, 0, 0), "III", ("size", None, None))
660
        if result.size > 0x80000000:
661
            raise DeviceError("file_size(fd=%d) failed with RC=0x%08X, errno=%d" % (fd, result.size, self.errno()))
662
        return result.size
394 farthen 663
 
395 farthen 664
    @command(timeout = 30000)
346 theseven 665
    def file_read(self, fd, addr, size):
666
        """ Reads data from a file referenced by a handle """
667
        result = self.lib.monitorcommand(struct.pack("IIII", 32, fd, addr, size), "III", ("rc", None, None))
668
        if result.rc > 0x80000000:
669
            raise DeviceError("file_read(fd=%d, addr=0x%08X, size=0x%08X) failed with RC=0x%08X, errno=%d" % (fd, addr, size, result.rc, self.errno()))
670
        return result.rc
394 farthen 671
 
395 farthen 672
    @command(timeout = 30000)
346 theseven 673
    def file_write(self, fd, addr, size):
674
        """ Writes data from a file referenced by a handle """
675
        result = self.lib.monitorcommand(struct.pack("IIII", 33, fd, addr, size), "III", ("rc", None, None))
676
        if result.rc > 0x80000000:
677
            raise DeviceError("file_write(fd=%d, addr=0x%08X, size=0x%08X) failed with RC=0x%08X, errno=%d" % (fd, addr, size, result.rc, self.errno()))
678
        return result.rc
679
 
395 farthen 680
    @command(timeout = 30000)
346 theseven 681
    def file_seek(self, fd, offset, whence):
682
        """ Seeks the file handle to the specified position in the file """
683
        result = self.lib.monitorcommand(struct.pack("IIII", 34, fd, offset, whence), "III", ("rc", None, None))
684
        if result.rc > 0x80000000:
685
            raise DeviceError("file_seek(fd=%d, offset=0x%08X, whence=%d) failed with RC=0x%08X, errno=%d" % (fd, offset, whence, result.rc, self.errno()))
686
        return result.rc
687
 
395 farthen 688
    @command(timeout = 30000)
346 theseven 689
    def file_truncate(self, fd, length):
690
        """ Truncates a file referenced by a handle to a specified length """
691
        result = self.lib.monitorcommand(struct.pack("IIII", 35, fd, offset, 0), "III", ("rc", None, None))
692
        if result.rc > 0x80000000:
693
            raise DeviceError("file_truncate(fd=%d, length=0x%08X) failed with RC=0x%08X, errno=%d" % (fd, length, result.rc, self.errno()))
694
        return result.rc
695
 
395 farthen 696
    @command(timeout = 30000)
346 theseven 697
    def file_sync(self, fd):
698
        """ Flushes a file handles' buffers """
699
        result = self.lib.monitorcommand(struct.pack("IIII", 36, fd, 0, 0), "III", ("rc", None, None))
700
        if result.rc > 0x80000000:
701
            raise DeviceError("file_sync(fd=%d) failed with RC=0x%08X, errno=%d" % (fd, result.rc, self.errno()))
702
        return result.rc
703
 
395 farthen 704
    @command(timeout = 30000)
346 theseven 705
    def file_close(self, fd):
706
        """ Closes a file handle """
707
        result = self.lib.monitorcommand(struct.pack("IIII", 37, fd, 0, 0), "III", ("rc", None, None))
708
        if result.rc > 0x80000000:
709
            raise DeviceError("file_close(fd=%d) failed with RC=0x%08X, errno=%d" % (fd, result.rc, self.errno()))
710
        return result.rc
711
 
395 farthen 712
    @command(timeout = 30000)
346 theseven 713
    def file_close_all(self):
714
        """ Closes all file handles opened through the debugger """
715
        result = self.lib.monitorcommand(struct.pack("IIII", 38, 0, 0, 0), "III", ("rc", None, None))
716
        if result.rc > 0x80000000:
717
            raise DeviceError("file_close_all() failed with RC=0x%08X, errno=%d" % (result.rc, self.errno()))
718
        return result.rc
719
 
395 farthen 720
    @command(timeout = 30000)
346 theseven 721
    def file_kill_all(self):
722
        """ Kills all file handles (in the whole system) """
723
        result = self.lib.monitorcommand(struct.pack("IIII", 39, 0, 0, 0), "III", ("rc", None, None))
724
        if result.rc > 0x80000000:
725
            raise DeviceError("file_kill_all() failed with RC=0x%08X, errno=%d" % (result.rc, self.errno()))
726
        return result.rc
727
 
395 farthen 728
    @command(timeout = 30000)
346 theseven 729
    def file_unlink(self, filename):
730
        """ Removes a file """
731
        result = self.lib.monitorcommand(struct.pack("IIII%dsB" % len(filename), 40, 0, 0, 0, filename, 0), "III", ("rc", None, None))
732
        if result.rc > 0x80000000:
733
            raise DeviceError("file_unlink(filename=\"%s\") failed with RC=0x%08X, errno=%d" % (filename, result.rc, self.errno()))
734
        return result.rc
735
 
395 farthen 736
    @command(timeout = 30000)
346 theseven 737
    def file_rename(self, oldname, newname):
738
        """ Renames a file """
739
        result = self.lib.monitorcommand(struct.pack("IIII248s%dsB" % min(247, len(newname)), 41, 0, 0, 0, oldname, newname, 0), "III", ("rc", None, None))
740
        if result.rc > 0x80000000:
741
            raise DeviceError("file_rename(oldname=\"%s\", newname=\"%s\") failed with RC=0x%08X, errno=%d" % (oldname, newname, result.rc, self.errno()))
742
        return result.rc
743
 
395 farthen 744
    @command(timeout = 30000)
346 theseven 745
    def dir_open(self, dirname):
746
        """ Opens a directory and returns the handle """
747
        result = self.lib.monitorcommand(struct.pack("IIII%dsB" % len(dirname), 42, 0, 0, 0, dirname, 0), "III", ("handle", None, None))
748
        if result.handle == 0:
749
            raise DeviceError("dir_open(dirname=\"%s\") failed with RC=0x%08X, errno=%d" % (dirname, result.handle, self.errno()))
750
        return result.handle
751
 
395 farthen 752
    @command(timeout = 30000)
346 theseven 753
    def dir_read(self, handle):
754
        """ Reads the next entry from a directory """
755
        result = self.lib.monitorcommand(struct.pack("IIII", 43, handle, 0, 0), "III", ("version", "maxpath", "ptr"))
756
        if result.ptr == 0:
757
            raise DeviceError("dir_read(handle=0x%08X) failed with RC=0x%08X, errno=%d" % (handle, result.ptr, self.errno()))
758
        if result.version != 1:
759
            raise ValueError("Unknown version of dirent struct: %d" % result.version)
760
        dirent = self.read(result.ptr, result.maxpath + 16)
761
        ret = Bunch()
762
        (ret.name, ret.attributes, ret.size, ret.startcluster, ret.wrtdate, ret.wrttime) = struct.unpack("%dsIIIHH" % result.maxpath, dirent)
763
        ret.name = ret.name[:ret.name.index('\x00')]
764
        return ret
765
 
395 farthen 766
    @command(timeout = 30000)
346 theseven 767
    def dir_close(self, handle):
768
        """ Closes a directory handle """
769
        result = self.lib.monitorcommand(struct.pack("IIII", 44, handle, 0, 0), "III", ("rc", None, None))
770
        if result.rc > 0x80000000:
771
            raise DeviceError("dir_close(handle=0x%08X) failed with RC=0x%08X, errno=%d" % (handle, result.rc, self.errno()))
772
        return result.rc
773
 
395 farthen 774
    @command(timeout = 30000)
346 theseven 775
    def dir_close_all(self):
776
        """ Closes all directory handles opened through the debugger """
777
        result = self.lib.monitorcommand(struct.pack("IIII", 45, 0, 0, 0), "III", ("rc", None, None))
778
        if result.rc > 0x80000000:
779
            raise DeviceError("dir_close_all() failed with RC=0x%08X, errno=%d" % (result.rc, self.errno()))
780
        return result.rc
781
 
395 farthen 782
    @command(timeout = 30000)
346 theseven 783
    def dir_kill_all(self):
784
        """ Kills all directory handles (in the whole system) """
785
        result = self.lib.monitorcommand(struct.pack("IIII", 46, 0, 0, 0), "III", ("rc", None, None))
786
        if result.rc > 0x80000000:
787
            raise DeviceError("dir_kill_all() failed with RC=0x%08X, errno=%d" % (result.rc, self.errno()))
788
        return result.rc
789
 
395 farthen 790
    @command(timeout = 30000)
346 theseven 791
    def dir_create(self, dirname):
792
        """ Creates a directory """
793
        result = self.lib.monitorcommand(struct.pack("IIII%dsB" % len(dirname), 47, 0, 0, 0, dirname, 0), "III", ("rc", None, None))
794
        if result.rc > 0x80000000:
795
            raise DeviceError("dir_create(dirname=\"%s\") failed with RC=0x%08X, errno=%d" % (dirname, result.rc, self.errno()))
796
        return result.rc
797
 
395 farthen 798
    @command(timeout = 30000)
346 theseven 799
    def dir_remove(self, dirname):
800
        """ Removes an (empty) directory """
801
        result = self.lib.monitorcommand(struct.pack("IIII%dsB" % len(dirname), 48, 0, 0, 0, dirname, 0), "III", ("rc", None, None))
802
        if result.rc > 0x80000000:
803
            raise DeviceError("dir_remove(dirname=\"%s\") failed with RC=0x%08X, errno=%d" % (dirname, result.rc, self.errno()))
804
        return result.rc
805
 
394 farthen 806
    @command()
346 theseven 807
    def errno(self):
808
        """ Returns the number of the last error that happened """
809
        result = self.lib.monitorcommand(struct.pack("IIII", 49, 0, 0, 0), "III", ("errno", None, None))
810
        return result.errno
811
 
394 farthen 812
    @command()
346 theseven 813
    def disk_mount(self, volume):
814
        """ Mounts a volume """
815
        result = self.lib.monitorcommand(struct.pack("IIII", 50, volume, 0, 0), "III", ("rc", None, None))
816
        if result.rc > 0x80000000:
817
            raise DeviceError("disk_mount(volume=%d) failed with RC=0x%08X, errno=%d" % (volume, result.rc, self.errno()))
818
        return result.rc
819
 
394 farthen 820
    @command()
346 theseven 821
    def disk_unmount(self, volume):
822
        """ Unmounts a volume """
823
        result = self.lib.monitorcommand(struct.pack("IIII", 51, volume, 0, 0), "III", ("rc", None, None))
824
        if result.rc > 0x80000000:
825
            raise DeviceError("disk_unmount(volume=%d) failed with RC=0x%08X, errno=%d" % (volume, result.rc, self.errno()))
826
        return result.rc
827
 
828
 
171 farthen 829
class Lib(object):
176 farthen 830
    def __init__(self):
171 farthen 831
        self.idVendor = 0xFFFF
832
        self.idProduct = 0xE000
176 farthen 833
 
834
        self.headersize = 0x10
835
 
836
        self.connect()
56 benedikt93 837
 
171 farthen 838
    def connect(self):
839
        self.dev = Dev(self.idVendor, self.idProduct)
840
        self.connected = True
56 benedikt93 841
 
171 farthen 842
    def monitorcommand(self, cmd, rcvdatatypes=None, rcvstruct=None):
269 farthen 843
        writelen = self.dev.cout(cmd)
171 farthen 844
        if rcvdatatypes:
845
            rcvdatatypes = "I" + rcvdatatypes # add the response
846
            data = self.dev.cin(struct.calcsize(rcvdatatypes))
847
            data = struct.unpack(rcvdatatypes, data)
848
            response = data[0]
849
            if libembiosdata.responsecodes[response] == "ok":
850
                if rcvstruct:
851
                    datadict = Bunch()
852
                    counter = 1 # start with 1, 0 is the id
853
                    for item in rcvstruct:
854
                        if item != None: # else the data is undefined
855
                            datadict[item] = data[counter]
856
                        counter += 1
857
                    return datadict
858
                else:
859
                    return data
860
            elif libembiosdata.responsecodes[response] == "unsupported":
861
                raise DeviceError("The device does not support this command.")
862
            elif libembiosdata.responsecodes[response] == "invalid":
863
                raise DeviceError("Invalid command! This should NOT happen!")
864
            elif libembiosdata.responsecodes[response] == "busy":
865
                raise DeviceError("Device busy")
269 farthen 866
        else:
867
            return writelen
56 benedikt93 868
 
869
 
171 farthen 870
class Dev(object):
871
    def __init__(self, idVendor, idProduct):
872
        self.idVendor = idVendor
873
        self.idProduct = idProduct
67 benedikt93 874
 
171 farthen 875
        self.interface = 0
876
        self.timeout = 100
176 farthen 877
 
171 farthen 878
        self.connect()
879
        self.findEndpoints()
880
 
342 farthen 881
 
882
        # Device properties
343 farthen 883
        self.packetsizelimit = Bunch()
884
        self.packetsizelimit.cout = None
885
        self.packetsizelimit.cin = None
886
        self.packetsizelimit.dout = None
887
        self.packetsizelimit.din = None
342 farthen 888
 
343 farthen 889
        self.version = Bunch()
342 farthen 890
        self.version.revision = None
891
        self.version.majorv = None
892
        self.version.minorv = None
893
        self.version.patchv = None
894
        self.swtypeid = None
895
        self.hwtypeid = None
896
 
343 farthen 897
        self.usermem = Bunch()
342 farthen 898
        self.usermem.lower = None
899
        self.usermem.upper = None
56 benedikt93 900
 
171 farthen 901
    def __del__(self):
902
        self.disconnect()
56 benedikt93 903
 
171 farthen 904
    def findEndpoints(self):
905
        epcounter = 0
343 farthen 906
        self.endpoint = Bunch()
171 farthen 907
        for cfg in self.dev:
908
            for intf in cfg:
909
                for ep in intf:
910
                    if epcounter == 0:
343 farthen 911
                        self.endpoint.cout = ep.bEndpointAddress
171 farthen 912
                    elif epcounter == 1:
343 farthen 913
                        self.endpoint.cin = ep.bEndpointAddress
171 farthen 914
                    elif epcounter == 2:
343 farthen 915
                        self.endpoint.dout = ep.bEndpointAddress
171 farthen 916
                    elif epcounter == 3:
343 farthen 917
                        self.endpoint.din = ep.bEndpointAddress
171 farthen 918
                    epcounter += 1
919
        if epcounter <= 3:
920
            raise DeviceError("Not all endpoints found in the descriptor. Only "+str(epcounter)+" found, we need 4")
56 benedikt93 921
 
171 farthen 922
    def connect(self):
923
        self.dev = usb.core.find(idVendor=self.idVendor, idProduct=self.idProduct)
924
        if self.dev is None:
925
            raise DeviceNotFoundError()
926
        self.dev.set_configuration()
56 benedikt93 927
 
171 farthen 928
    def disconnect(self):
929
        pass
102 benedikt93 930
 
171 farthen 931
    def send(self, endpoint, data):
932
        size = self.dev.write(endpoint, data, self.interface, self.timeout)
933
        if size != len(data):
176 farthen 934
            raise SendError("Not all data was written!")
171 farthen 935
        return len
102 benedikt93 936
 
171 farthen 937
    def receive(self, endpoint, size):
938
        read = self.dev.read(endpoint, size, self.interface, self.timeout)
939
        if len(read) != size:
176 farthen 940
            raise ReceiveError("Requested size and read size don't match!")
171 farthen 941
        return read
56 benedikt93 942
 
171 farthen 943
    def cout(self, data):
343 farthen 944
        if self.packetsizelimit.cout and len(data) > self.packetsizelimit.cout:
171 farthen 945
            raise SendError("Packet too big")
343 farthen 946
        return self.send(self.endpoint.cout, data)
94 benedikt93 947
 
171 farthen 948
    def cin(self, size):
343 farthen 949
        if self.packetsizelimit.cin and size > self.packetsizelimit.cin:
171 farthen 950
            raise ReceiveError("Packet too big")
343 farthen 951
        return self.receive(self.endpoint.cin, size)
94 benedikt93 952
 
171 farthen 953
    def dout(self, data):
343 farthen 954
        if self.packetsizelimit.dout and len(data) > self.packetsizelimit.dout:
171 farthen 955
            raise SendError("Packet too big")
343 farthen 956
        return self.send(self.endpoint.dout, data)
94 benedikt93 957
 
171 farthen 958
    def din(self, size):
343 farthen 959
        if self.packetsizelimit.din and size > self.packetsizelimit.din:
171 farthen 960
            raise ReceiveError("Packet too big")
343 farthen 961
        return self.receive(self.endpoint.din, size)
56 benedikt93 962
 
96 benedikt93 963
 
171 farthen 964
if __name__ == "__main__":
965
    # Some tests
966
    import sys
967
    embios = Embios()
968
    resp = embios.getversioninfo()
969
    sys.stdout.write("Embios device version information: " + libembiosdata.swtypes[resp.swtypeid] + " v" + str(resp.majorv) + "." + str(resp.minorv) + 
970
                     "." + str(resp.patchv) + " r" + str(resp.revision) + " running on " + libembiosdata.hwtypes[resp.hwtypeid] + "\n")
971
    resp = embios.getusermemrange()
972
    sys.stdout.write("Usermemrange: "+hex(resp.lower)+" - "+hex(resp.upper)+"\n")
973
    memaddr = resp.lower
974
    maxlen = resp.upper - resp.lower
975
    f = open("./embios.py", "rb")
976
    sys.stdout.write("Loading test file (embios.py) to send over USB...\n")
977
    datastr = f.read()[:maxlen]
978
    sys.stdout.write("Sending data...\n")
979
    embios.write(memaddr, datastr)
980
    sys.stdout.write("Encrypting data with the hardware key...\n")
981
    embios.aesencrypt(memaddr, len(datastr), 0)
982
    sys.stdout.write("Reading data back and saving it to 'libembios-test-encrypted.bin'...\n")
983
    f = open("./libembios-test-encrypted.bin", "wb")
984
    f.write(embios.read(memaddr, len(datastr)))
985
    sys.stdout.write("Decrypting the data again...\n")
986
    embios.aesdecrypt(memaddr, len(datastr), 0)
987
    sys.stdout.write("Reading data back from device...\n")
988
    readdata = embios.read(memaddr, len(datastr))
989
    if readdata == datastr:
990
        sys.stdout.write("Data matches!")
991
    else:
346 theseven 992
        sys.stdout.write("Data does NOT match. Something went wrong")