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
 
171 farthen 29
class Error(Exception):
30
    def __init__(self, value=None):
31
        self.value = value
32
    def __str__(self):
33
        if self.value != None:
34
            return repr(self.value)
56 benedikt93 35
 
171 farthen 36
class ArgumentError(Error):
37
    pass
56 benedikt93 38
 
171 farthen 39
class DeviceNotFoundError(Error):
40
    pass
56 benedikt93 41
 
171 farthen 42
class DeviceError(Error):
43
    pass
56 benedikt93 44
 
171 farthen 45
class SendError(Error):
46
    pass
56 benedikt93 47
 
171 farthen 48
class ReceiveError(Error):
49
    pass
56 benedikt93 50
 
51
 
171 farthen 52
class Bunch(dict):
56 benedikt93 53
    """
171 farthen 54
        This is a dict whose items can also be accessed with
55
        bunchinstance.something.
56 benedikt93 56
    """
171 farthen 57
    def __init__(self, **kw):
58
        dict.__init__(self, kw)
59
        self.__dict__ = self
56 benedikt93 60
 
171 farthen 61
    def __getstate__(self):
62
        return self
56 benedikt93 63
 
171 farthen 64
    def __setstate__(self, state):
65
        self.update(state)
66
        self.__dict__ = self
56 benedikt93 67
 
68
 
171 farthen 69
class Embios(object):
176 farthen 70
    """
71
        Class for all embios functions.
72
    """
171 farthen 73
    def __init__(self):
176 farthen 74
        self.lib = Lib()
75
        self.getpacketsizeinfo()
56 benedikt93 76
 
171 farthen 77
    @staticmethod
78
    def _alignsplit(addr, size, blksize, align):
79
        end = addr + size
80
        if addr & (align - 1):
81
            bodyaddr = (addr + min(size, blksize)) & ~(align - 1)
82
        else: bodyaddr = addr
83
        headsize = bodyaddr - addr
84
        if (size - headsize) & (align - 1):
85
            tailaddr = (end - min(end - bodyaddr, blksize) + align - 1) & ~(align - 1)
86
        else: tailaddr = end
87
        tailsize = end - tailaddr
88
        return (headsize, tailaddr - bodyaddr, tailsize)
56 benedikt93 89
 
171 farthen 90
    def getversioninfo(self):
91
        """ This returns the emBIOS version and device information. """
92
        return self.lib.monitorcommand(struct.pack("IIII", 1, 0, 0, 0), "IBBBBI", ("revision", "majorv", "minorv", "patchv", "swtypeid", "hwtypeid"))
56 benedikt93 93
 
171 farthen 94
    def getpacketsizeinfo(self):
95
        """ This returns the emBIOS max packet size information.
96
            It also sets the properties of the device object accordingly.
97
        """
98
        resp = self.lib.monitorcommand(struct.pack("IIII", 1, 1, 0, 0), "HHII", ("coutmax", "cinmax", "doutmax", "dinmax"))
99
        self.lib.dev.packetsizelimit['cout'] = resp.coutmax
100
        self.lib.dev.packetsizelimit['cin'] = resp.cinmax
101
        self.lib.dev.packetsizelimit['din'] = resp.dinmax
102
        self.lib.dev.packetsizelimit['dout'] = resp.doutmax
103
        return resp
56 benedikt93 104
 
171 farthen 105
    def getusermemrange(self):
106
        """ This returns the memory range the user has access to. """
107
        return self.lib.monitorcommand(struct.pack("IIII", 1, 2, 0, 0), "III", ("lower", "upper", None))
56 benedikt93 108
 
171 farthen 109
    def reset(self, force=False):
110
        """ Reboot the device """
111
        if force:
112
            return self.lib.monitorcommand(struct.pack("IIII", 2, 0, 0, 0))
113
        else:
114
            return self.lib.monitorcommand(struct.pack("IIII", 2, 1, 0, 0), "III", (None, None, None))
56 benedikt93 115
 
171 farthen 116
    def poweroff(self, force=False):
117
        """ Powers the device off. """
118
        if force:
119
            return self.lib.monitorcommand(struct.pack("IIII", 3, 0, 0, 0))
120
        else:
121
            return self.lib.monitorcommand(struct.pack("IIII", 3, 1, 0, 0), "III", (None, None, None))
56 benedikt93 122
 
171 farthen 123
    def read(self, addr, size):
124
        """ Reads the memory from location 'addr' with size 'size'
125
            from the device. This cares about too long packages
126
            and decides whether to use DMA or not.
127
        """
176 farthen 128
        cin_maxsize = self.lib.dev.packetsizelimit["cin"] - self.lib.headersize
171 farthen 129
        din_maxsize = self.lib.dev.packetsizelimit["din"]
130
        data = ""
131
        (headsize, bodysize, tailsize) = self._alignsplit(addr, size, cin_maxsize, 16)
132
        if headsize != 0:
133
            data += self.readmem(addr, headsize)
134
            addr += headsize
135
        while bodysize > 0:
136
            if bodysize >= 2 * cin_maxsize:
137
                readsize = min(bodysize, din_maxsize)
138
                data += self.readdma(addr, readsize)
139
            else:
140
                readsize = min(bodysize, cin_maxsize)
141
                data += self.readmem(addr, readsize)
142
            addr += readsize
143
            bodysize -= readsize
144
        if tailsize != 0:
145
            data += self.readmem(addr, tailsize)
146
        return data
56 benedikt93 147
 
171 farthen 148
    def write(self, addr, data):
149
        """ Writes the data in 'data' to the location 'addr'
150
            in the memory of the device. This cares about too long packages
151
            and decides whether to use DMA or not.
152
        """
176 farthen 153
        cout_maxsize = self.lib.dev.packetsizelimit["cout"] - self.lib.headersize
171 farthen 154
        dout_maxsize = self.lib.dev.packetsizelimit["dout"]
155
        (headsize, bodysize, tailsize) = self._alignsplit(addr, len(data), cout_maxsize, 16)
156
        offset = 0
157
        if headsize != 0:
158
            self.writemem(addr, headsize)
159
            offset += headsize
160
            addr += headsize
161
        while bodysize > 0:
162
            if bodysize >= 2 * cout_maxsize:
163
                writesize = min(bodysize, dout_maxsize)
164
                self.writedma(addr, data[offset:offset+writesize])
165
            else:
166
                writesize = min(bodysize, cout_maxsize)
167
                self.writemem(addr, data[offset:offset+writesize])
168
            offset += writesize
169
            addr += writesize
170
            bodysize -= writesize
171
        if tailsize != 0:
172
            self.writemem(addr, data[offset:offset+tailsize])
173
        return data
56 benedikt93 174
 
171 farthen 175
    def readmem(self, addr, size):
176
        """ Reads the memory from location 'addr' with size 'size'
177
            from the device.
178
        """
179
        resp = self.lib.monitorcommand(struct.pack("IIII", 4, addr, size, 0), "III%ds" % size, (None, None, None, "data"))
180
        return resp.data
181
 
182
    def writemem(self, addr, data):
183
        """ Writes the data in 'data' to the location 'addr'
184
            in the memory of the device.
185
        """
186
        return self.lib.monitorcommand(struct.pack("IIII%ds" % len(data), 5, addr, len(data), 0, data), "III", (None, None, None))
56 benedikt93 187
 
171 farthen 188
    def readdma(self, addr, size):
189
        """ Reads the memory from location 'addr' with size 'size'
190
            from the device. This uses DMA and the data in endpoint.
191
        """
192
        self.lib.monitorcommand(struct.pack("IIII", 6, addr, size, 0), "III", (None, None, None))
193
        return struct.unpack("%ds" % size, self.lib.dev.din(size))[0]
56 benedikt93 194
 
171 farthen 195
    def writedma(self, addr, data):
196
        """ Writes the data in 'data' to the location 'addr'
197
            in the memory of the device. This uses DMA and the data out endpoint.
198
        """
199
        self.lib.monitorcommand(struct.pack("IIII", 7, addr, len(data), 0), "III", (None, None, None))
200
        return self.lib.dev.dout(data)
56 benedikt93 201
 
173 farthen 202
    def readstring(self, addr, maxlength = 256):
203
        """ Reads a zero terminated string from memory 
204
            Reads only a maximum of 'maxlength' chars.
205
        """
176 farthen 206
        cin_maxsize = self.lib.dev.packetsizelimit["cin"] - self.lib.headersize
173 farthen 207
        string = ""
208
        while (len(string) < maxlength or maxlength < 0):
209
            data = self.readmem(addr, min(maxlength - len(string), cin_maxsize))
210
            length = data.find("\0")
211
            if length >= 0:
212
                string += data[:length]
213
                break
214
            else:
215
                string += data
216
            addr += cin_maxsize
217
        return string
218
 
171 farthen 219
    def i2cread(self, index, slaveaddr, startaddr, size):
220
        """ Reads data from an i2c slave """
176 farthen 221
        if size > 256 or size < 1:
222
            raise ValueError("Size must be a number between 1 and 256")
223
        if size == 256:
224
            size = 0
225
        resp = self.lib.monitorcommand(struct.pack("IBBBBII", 8, index, slaveaddr, startaddr, size, 0, 0), "III%ds" % size, (None, None, None, "data"))
226
        return resp.data
56 benedikt93 227
 
171 farthen 228
    def i2cwrite(self, index, slaveaddr, startaddr, data):
229
        """ Writes data to an i2c slave """
176 farthen 230
        size = len(data)
231
        if size > 256 or size < 1:
232
            raise ValueError("Size must be a number between 1 and 256")
233
        if size == 256:
234
            size = 0
235
        return self.lib.monitorcommand(struct.pack("IBBBBII%ds" % size, 9, index, slaveaddr, startaddr, size, 0, 0, data), "III" % size, (None, None, None))
56 benedikt93 236
 
176 farthen 237
    def usbcread(self):
238
        """ Reads one packet with the maximal cin size """
239
        cin_maxsize = self.lib.dev.packetsizelimit["cin"] - self.lib.headersize
240
        resp = self.lib.monitorcommand(struct.pack("IIII", 10, cin_maxsize, 0, 0), "III%ds" % cin_maxsize, ("validsize", "buffersize", "queuesize", "data"))
241
        resp.data = resp.data[:resp.validsize]
242
        resp.maxsize = cin_maxsize
243
        return resp
56 benedikt93 244
 
171 farthen 245
    def usbcwrite(self, data):
246
        """ Writes data to the USB console """
176 farthen 247
        cin_maxsize = self.lib.dev.packetsizelimit["cin"] - self.lib.headersize
248
        size = len(data)
249
        while len(data) > 0:
250
            writesize = min(cin_maxsize, len(data))
251
            resp = self.lib.monitorcommand(struct.pack("IIII%ds" % writesize, 11, writesize, 0, 0, data[:writesize]), "III", ("validsize", "buffersize", "freesize"))
252
            data = data[resp.validsize:]
253
        return size
56 benedikt93 254
 
176 farthen 255
    def cread(self, bitmask=0x1):
256
        """ Reads one packet with the maximal cin size from the device consoles
171 farthen 257
            identified with the specified bitmask
258
        """
176 farthen 259
        cin_maxsize = self.lib.dev.packetsizelimit["cin"] - self.lib.headersize
260
        resp = self.lib.monitorcommand(struct.pack("IIII", 14, cin_maxsize, 0, 0), "III%ds" % cin_maxsize, ("size", None, None))
261
        resp.data = resp.data[size:]
262
        resp.maxsize = cin_maxsize
263
        return resp
56 benedikt93 264
 
176 farthen 265
    def cwrite(self, data, bitmask=0x1):
171 farthen 266
        """ Writes data to the device consoles 
267
            identified with the specified bitmask.
268
        """
176 farthen 269
        cin_maxsize = self.lib.dev.packetsizelimit["cin"] - self.lib.headersize
270
        size = len(data)
271
        while len(data) > 0:
272
            writesize = min(cin_maxsize, len(data))
273
            resp = self.lib.monitorcommand(struct.pack("IIII%ds" % writesize, 13, writesize, 0, 0, data[:writesize]), "III", (None, None, None))
274
            data = data[writesize:]
275
        return size
56 benedikt93 276
 
171 farthen 277
    def cflush(self, bitmask):
278
        """ Flushes the consoles specified with 'bitmask' """
279
        return self.lib.monitorcommand(struct.pack("IIII", 14, bitmask, 0, 0), "III", (None, None, None))
56 benedikt93 280
 
173 farthen 281
    def getprocinfo(self):
171 farthen 282
        """ Gets current state of the scheduler """
176 farthen 283
        cin_maxsize = self.lib.dev.packetsizelimit["cin"] - self.lib.headersize
173 farthen 284
        # Get the size
285
        schedulerstate = self.lockscheduler()
286
        resp = self.lib.monitorcommand(struct.pack("IIII", 15, 0, 0, 0), "III", ("structver", "tablesize", None))
287
        tablesize = resp.tablesize
288
        size = tablesize
289
        structver = resp.structver
290
        offset = 0
291
        data = ""
292
        while size > 0:
293
            if size > cin_maxsize:
294
                readsize = cin_maxsize
295
            else:
296
                readsize = size
297
            resp = self.lib.monitorcommand(struct.pack("IIII", 15, offset, readsize, 0), "III%ds" % readsize, ("structver", "tablesize", None, "data"))
298
            data += resp.data
299
            offset += readsize
300
            size -= readsize
301
        self.lockscheduler(schedulerstate)
302
        threadstructsize = 120
303
        registersize = 32
304
        if len(data) % threadstructsize != 0:
305
            raise DeviceError("The thread struct is not a multiple of "+str(threadsturcsize)+"!")
306
        threadcount = len(data) / threadstructsize
307
        threads = []
308
        id = 0
309
        for thread in range(threadcount):
310
            offset = threadstructsize * thread
311
            threaddata = struct.unpack("<16IIIIIQIIIIIIIBBBB", data[offset:offset+threadstructsize])
312
            info = Bunch()
313
            info.id = id
314
            state = threaddata[17]
315
            info.state = libembiosdata.thread_state[state]
316
            if info.state == "THREAD_FREE":
317
                id += 1
318
                continue
319
            info.regs = Bunch()
320
            for register in range(16):
321
                info.regs["r"+str(register)] = threaddata[register]
322
            info.regs.cpsr = threaddata[16]
323
            info.nameptr = threaddata[18]
324
            if info.nameptr == 0:
325
                info.name = "Thread %d" % info.id
326
            else:
327
                info.name = self.readstring(info.nameptr)
328
            info.cputime_current = threaddata[19]
329
            info.cputime_total = threaddata[20]
330
            info.startusec = threaddata[21]
331
            info.queue_next_ptr = threaddata[22]
332
            info.timeout = threaddata[23]
333
            info.blocked_since = threaddata[24]
334
            info.blocked_by_ptr = threaddata[25]
335
            info.stackaddr = threaddata[26]
336
            info.err_no = threaddata[27]
337
            info.block_type = libembiosdata.thread_block[threaddata[28]]
338
            info.type = libembiosdata.thread_type[threaddata[29]]
339
            info.priority = threaddata[30]
340
            info.cpuload = threaddata[31]
341
            threads.append(info)
342
            id += 1
343
        return threads
344
 
345
 
346
        return self.lib.monitorcommand(struct.pack("IIII", 15, offset, size, 0), "III%ds" % size, ("structver", "tablesize", None, "data"))
56 benedikt93 347
 
173 farthen 348
    def lockscheduler(self, freeze=True):
171 farthen 349
        """ Freezes/Unfreezes the scheduler """
173 farthen 350
        resp = self.lib.monitorcommand(struct.pack("IIII", 16, 1 if freeze else 0, 0, 0), "III", ("before", None, None))
351
        return True if resp.before == 1 else False
67 benedikt93 352
 
173 farthen 353
    def unlockscheduler(self):
171 farthen 354
        """ Unfreezes the scheduler """
355
        return self.lib.monitorcommand(struct.pack("IIII", 16, 0, 0, 0), "III", ("before", None, None))
56 benedikt93 356
 
171 farthen 357
    def suspendthread(self, id, suspend=True):
358
        """ Suspends the thread with the specified id """
173 farthen 359
        resp = self.lib.monitorcommand(struct.pack("IIII", 17, 1 if suspend else 0, id, 0), "III", ("before", None, None))
360
        return True if resp.before == 1 else False
56 benedikt93 361
 
173 farthen 362
    def resumethread(self, id):
363
        """ Resumes the thread with the specified id """
171 farthen 364
        return self.lib.monitorcommand(struct.pack("IIII", 17, 0, id, 0), "III", ("before", None, None))
56 benedikt93 365
 
171 farthen 366
    def killthread(self, id):
367
        """ Kills the thread with the specified id """
368
        return self.lib.monitorcommand(struct.pack("IIII", 18, id, 0, 0), "III", ("before", None, None))
56 benedikt93 369
 
171 farthen 370
    def createthread(self, nameptr, entrypoint, stackptr, stacksize, threadtype, priority, state):
371
        """ Creates a thread with the specified attributes """
372
        if threadtype == "user":
373
            threadtype = 0
374
        elif threadtype == "system":
375
            threadtype = 1
376
        else:
176 farthen 377
            raise ValueError("Threadtype must be either 'system' or 'user'")
171 farthen 378
        if priority > 256 or priority < 0:
176 farthen 379
            raise ValueError("Priority must be a number between 0 and 256")
171 farthen 380
        if state == "ready":
381
            state = 0
382
        elif state == "suspended":
383
            state = 1
384
        else:
176 farthen 385
            raise ValueError("State must be either 'ready' or 'suspended'")
171 farthen 386
        resp = self.lib.monitorcommand(struct.pack("IIIIIIII", 19, nameptr, entrypoint, stackptr, stacksize, threadtype, priority, state), "III", (id, None, None))
387
        if resp.id < 0:
388
            raise DeviceError("The device returned the error code "+str(resp.id))
389
        return resp
56 benedikt93 390
 
172 farthen 391
    def flushcaches(self):
171 farthen 392
        """ Flushes the CPU instruction and data cache """
393
        return self.lib.monitorcommand(struct.pack("IIII", 20, 0, 0, 0), "III", (None, None, None))
56 benedikt93 394
 
172 farthen 395
    def execimage(self, addr):
171 farthen 396
        """ Runs the emBIOS app at 'addr' """
397
        return self.lib.monitorcommand(struct.pack("IIII", 21, addr, 0, 0), "III", ("excecimage", None, None))
56 benedikt93 398
 
171 farthen 399
    def bootflashread(self, memaddr, flashaddr, size):
400
        """ Copies the data in the bootflash at 'flashaddr' of the specified size
401
            to the memory at addr 'memaddr'
402
        """
174 farthen 403
        return self.lib.monitorcommand(struct.pack("IIII", 22, memaddr, flashaddr, size), "III", (None, None, None))
82 benedikt93 404
 
171 farthen 405
    def bootflashwrite(self, memaddr, flashaddr, size):
406
        """ Copies the data in the memory at 'memaddr' of the specified size
407
            to the boot flash at addr 'flashaddr'
408
        """
174 farthen 409
        return self.lib.monitorcommand(struct.pack("IIII", 23, memaddr, flashaddr, size), "III", (None, None, None))
56 benedikt93 410
 
171 farthen 411
    def execfirmware(self, addr):
412
        """ Executes the firmware at 'addr' and passes all control to it. """
413
        return self.lib.monitorcommand(struct.pack("IIII", 24, addr, 0, 0), "III", (None, None, None))
56 benedikt93 414
 
171 farthen 415
    def aesencrypt(self, addr, size, keyindex):
416
        """ Encrypts the buffer at 'addr' with the specified size
417
            with the hardware AES key index 'keyindex'
418
        """
419
        return self.lib.monitorcommand(struct.pack("IBBHII", 25, 1, 0, keyindex, addr, size), "III", (None, None, None))
82 benedikt93 420
 
171 farthen 421
    def aesdecrypt(self, addr, size, keyindex):
422
        """ Decrypts the buffer at 'addr' with the specified size
423
            with the hardware AES key index 'keyindex'
424
        """
425
        return self.lib.monitorcommand(struct.pack("IBBHII", 25, 0, 0, keyindex, addr, size), "III", (None, None, None))
82 benedikt93 426
 
171 farthen 427
    def hmac_sha1(self, addr, size, destination):
428
        """ Generates a HMAC-SHA1 hash of the buffer and saves it to 'destination' """
429
        return self.lib.monitorcommand(struct.pack("IIII", 26, addr, size, destination), "III", (None, None, None))
56 benedikt93 430
 
431
 
171 farthen 432
class Lib(object):
176 farthen 433
    def __init__(self):
171 farthen 434
        self.idVendor = 0xFFFF
435
        self.idProduct = 0xE000
176 farthen 436
 
437
        self.headersize = 0x10
438
 
439
        self.connect()
56 benedikt93 440
 
171 farthen 441
    def connect(self):
442
        self.dev = Dev(self.idVendor, self.idProduct)
443
        self.connected = True
56 benedikt93 444
 
171 farthen 445
    def monitorcommand(self, cmd, rcvdatatypes=None, rcvstruct=None):
446
        self.dev.cout(cmd)
447
        if rcvdatatypes:
448
            rcvdatatypes = "I" + rcvdatatypes # add the response
449
            data = self.dev.cin(struct.calcsize(rcvdatatypes))
450
            data = struct.unpack(rcvdatatypes, data)
451
            response = data[0]
452
            if libembiosdata.responsecodes[response] == "ok":
453
                if rcvstruct:
454
                    datadict = Bunch()
455
                    counter = 1 # start with 1, 0 is the id
456
                    for item in rcvstruct:
457
                        if item != None: # else the data is undefined
458
                            datadict[item] = data[counter]
459
                        counter += 1
460
                    return datadict
461
                else:
462
                    return data
463
            elif libembiosdata.responsecodes[response] == "unsupported":
464
                raise DeviceError("The device does not support this command.")
465
            elif libembiosdata.responsecodes[response] == "invalid":
466
                raise DeviceError("Invalid command! This should NOT happen!")
467
            elif libembiosdata.responsecodes[response] == "busy":
468
                raise DeviceError("Device busy")
56 benedikt93 469
 
470
 
171 farthen 471
class Dev(object):
472
    def __init__(self, idVendor, idProduct):
473
        self.idVendor = idVendor
474
        self.idProduct = idProduct
67 benedikt93 475
 
171 farthen 476
        self.interface = 0
477
        self.timeout = 100
176 farthen 478
 
171 farthen 479
        self.connect()
480
        self.findEndpoints()
481
 
482
        self.packetsizelimit = {}
483
        self.packetsizelimit['cout'] = None
484
        self.packetsizelimit['cin'] = None
485
        self.packetsizelimit['dout'] = None
486
        self.packetsizelimit['din'] = None
56 benedikt93 487
 
171 farthen 488
    def __del__(self):
489
        self.disconnect()
56 benedikt93 490
 
171 farthen 491
    def findEndpoints(self):
492
        epcounter = 0
493
        self.endpoint = {}
494
        for cfg in self.dev:
495
            for intf in cfg:
496
                for ep in intf:
497
                    if epcounter == 0:
498
                        self.endpoint['cout'] = ep.bEndpointAddress
499
                    elif epcounter == 1:
500
                        self.endpoint['cin'] = ep.bEndpointAddress
501
                    elif epcounter == 2:
502
                        self.endpoint['dout'] = ep.bEndpointAddress
503
                    elif epcounter == 3:
504
                        self.endpoint['din'] = ep.bEndpointAddress
505
                    epcounter += 1
506
        if epcounter <= 3:
507
            raise DeviceError("Not all endpoints found in the descriptor. Only "+str(epcounter)+" found, we need 4")
56 benedikt93 508
 
171 farthen 509
    def connect(self):
510
        self.dev = usb.core.find(idVendor=self.idVendor, idProduct=self.idProduct)
511
        if self.dev is None:
512
            raise DeviceNotFoundError()
513
        self.dev.set_configuration()
56 benedikt93 514
 
171 farthen 515
    def disconnect(self):
516
        pass
102 benedikt93 517
 
171 farthen 518
    def send(self, endpoint, data):
519
        size = self.dev.write(endpoint, data, self.interface, self.timeout)
520
        if size != len(data):
176 farthen 521
            raise SendError("Not all data was written!")
171 farthen 522
        return len
102 benedikt93 523
 
171 farthen 524
    def receive(self, endpoint, size):
525
        read = self.dev.read(endpoint, size, self.interface, self.timeout)
526
        if len(read) != size:
176 farthen 527
            raise ReceiveError("Requested size and read size don't match!")
171 farthen 528
        return read
56 benedikt93 529
 
171 farthen 530
    def cout(self, data):
531
        if self.packetsizelimit['cout'] and len(data) > self.packetsizelimit['cout']:
532
            raise SendError("Packet too big")
533
        return self.send(self.endpoint['cout'], data)
94 benedikt93 534
 
171 farthen 535
    def cin(self, size):
536
        if self.packetsizelimit['cin'] and size > self.packetsizelimit['cin']:
537
            raise ReceiveError("Packet too big")
538
        return self.receive(self.endpoint['cin'], size)
94 benedikt93 539
 
171 farthen 540
    def dout(self, data):
541
        if self.packetsizelimit['dout'] and len(data) > self.packetsizelimit['dout']:
542
            raise SendError("Packet too big")
543
        return self.send(self.endpoint['dout'], data)
94 benedikt93 544
 
171 farthen 545
    def din(self, size):
546
        if self.packetsizelimit['din'] and size > self.packetsizelimit['din']:
547
            raise ReceiveError("Packet too big")
548
        return self.receive(self.endpoint['din'], size)
56 benedikt93 549
 
96 benedikt93 550
 
171 farthen 551
if __name__ == "__main__":
552
    # Some tests
553
    import sys
554
    embios = Embios()
555
    resp = embios.getversioninfo()
556
    sys.stdout.write("Embios device version information: " + libembiosdata.swtypes[resp.swtypeid] + " v" + str(resp.majorv) + "." + str(resp.minorv) + 
557
                     "." + str(resp.patchv) + " r" + str(resp.revision) + " running on " + libembiosdata.hwtypes[resp.hwtypeid] + "\n")
558
    resp = embios.getusermemrange()
559
    sys.stdout.write("Usermemrange: "+hex(resp.lower)+" - "+hex(resp.upper)+"\n")
560
    memaddr = resp.lower
561
    maxlen = resp.upper - resp.lower
562
    f = open("./embios.py", "rb")
563
    sys.stdout.write("Loading test file (embios.py) to send over USB...\n")
564
    datastr = f.read()[:maxlen]
565
    sys.stdout.write("Sending data...\n")
566
    embios.write(memaddr, datastr)
567
    sys.stdout.write("Encrypting data with the hardware key...\n")
568
    embios.aesencrypt(memaddr, len(datastr), 0)
569
    sys.stdout.write("Reading data back and saving it to 'libembios-test-encrypted.bin'...\n")
570
    f = open("./libembios-test-encrypted.bin", "wb")
571
    f.write(embios.read(memaddr, len(datastr)))
572
    sys.stdout.write("Decrypting the data again...\n")
573
    embios.aesdecrypt(memaddr, len(datastr), 0)
574
    sys.stdout.write("Reading data back from device...\n")
575
    readdata = embios.read(memaddr, len(datastr))
576
    if readdata == datastr:
577
        sys.stdout.write("Data matches!")
578
    else:
579
        sys.stdout.write("Data does NOT match. Something got wrong")