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