Subversion Repositories freemyipod

Rev

Go to most recent revision | 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
 
178 farthen 91
    def _readmem(self, addr, size):
92
        """ Reads the memory from location 'addr' with size 'size'
93
            from the device.
94
        """
95
        resp = self.lib.monitorcommand(struct.pack("IIII", 4, addr, size, 0), "III%ds" % size, (None, None, None, "data"))
96
        return resp.data
97
 
98
    def _writemem(self, addr, data):
99
        """ Writes the data in 'data' to the location 'addr'
100
            in the memory of the device.
101
        """
102
        return self.lib.monitorcommand(struct.pack("IIII%ds" % len(data), 5, addr, len(data), 0, data), "III", (None, None, None))
103
 
104
    def _readdma(self, addr, size):
105
        """ Reads the memory from location 'addr' with size 'size'
106
            from the device. This uses DMA and the data in endpoint.
107
        """
108
        self.lib.monitorcommand(struct.pack("IIII", 6, addr, size, 0), "III", (None, None, None))
109
        return struct.unpack("%ds" % size, self.lib.dev.din(size))[0]
110
 
111
    def _writedma(self, addr, data):
112
        """ Writes the data in 'data' to the location 'addr'
113
            in the memory of the device. This uses DMA and the data out endpoint.
114
        """
115
        self.lib.monitorcommand(struct.pack("IIII", 7, addr, len(data), 0), "III", (None, None, None))
116
        return self.lib.dev.dout(data)
117
 
171 farthen 118
    def getversioninfo(self):
119
        """ This returns the emBIOS version and device information. """
120
        return self.lib.monitorcommand(struct.pack("IIII", 1, 0, 0, 0), "IBBBBI", ("revision", "majorv", "minorv", "patchv", "swtypeid", "hwtypeid"))
56 benedikt93 121
 
171 farthen 122
    def getpacketsizeinfo(self):
123
        """ This returns the emBIOS max packet size information.
124
            It also sets the properties of the device object accordingly.
125
        """
126
        resp = self.lib.monitorcommand(struct.pack("IIII", 1, 1, 0, 0), "HHII", ("coutmax", "cinmax", "doutmax", "dinmax"))
127
        self.lib.dev.packetsizelimit['cout'] = resp.coutmax
128
        self.lib.dev.packetsizelimit['cin'] = resp.cinmax
129
        self.lib.dev.packetsizelimit['din'] = resp.dinmax
130
        self.lib.dev.packetsizelimit['dout'] = resp.doutmax
131
        return resp
56 benedikt93 132
 
171 farthen 133
    def getusermemrange(self):
134
        """ This returns the memory range the user has access to. """
135
        return self.lib.monitorcommand(struct.pack("IIII", 1, 2, 0, 0), "III", ("lower", "upper", None))
56 benedikt93 136
 
171 farthen 137
    def reset(self, force=False):
138
        """ Reboot the device """
139
        if force:
140
            return self.lib.monitorcommand(struct.pack("IIII", 2, 0, 0, 0))
141
        else:
142
            return self.lib.monitorcommand(struct.pack("IIII", 2, 1, 0, 0), "III", (None, None, None))
56 benedikt93 143
 
171 farthen 144
    def poweroff(self, force=False):
145
        """ Powers the device off. """
146
        if force:
147
            return self.lib.monitorcommand(struct.pack("IIII", 3, 0, 0, 0))
148
        else:
149
            return self.lib.monitorcommand(struct.pack("IIII", 3, 1, 0, 0), "III", (None, None, None))
56 benedikt93 150
 
171 farthen 151
    def read(self, addr, size):
152
        """ Reads the memory from location 'addr' with size 'size'
153
            from the device. This cares about too long packages
154
            and decides whether to use DMA or not.
155
        """
176 farthen 156
        cin_maxsize = self.lib.dev.packetsizelimit["cin"] - self.lib.headersize
171 farthen 157
        din_maxsize = self.lib.dev.packetsizelimit["din"]
158
        data = ""
159
        (headsize, bodysize, tailsize) = self._alignsplit(addr, size, cin_maxsize, 16)
160
        if headsize != 0:
178 farthen 161
            data += self._readmem(addr, headsize)
171 farthen 162
            addr += headsize
163
        while bodysize > 0:
164
            if bodysize >= 2 * cin_maxsize:
165
                readsize = min(bodysize, din_maxsize)
178 farthen 166
                data += self._readdma(addr, readsize)
171 farthen 167
            else:
168
                readsize = min(bodysize, cin_maxsize)
178 farthen 169
                data += self._readmem(addr, readsize)
171 farthen 170
            addr += readsize
171
            bodysize -= readsize
172
        if tailsize != 0:
178 farthen 173
            data += self._readmem(addr, tailsize)
171 farthen 174
        return data
56 benedikt93 175
 
171 farthen 176
    def write(self, addr, data):
177
        """ Writes the data in 'data' to the location 'addr'
178
            in the memory of the device. This cares about too long packages
179
            and decides whether to use DMA or not.
180
        """
176 farthen 181
        cout_maxsize = self.lib.dev.packetsizelimit["cout"] - self.lib.headersize
171 farthen 182
        dout_maxsize = self.lib.dev.packetsizelimit["dout"]
183
        (headsize, bodysize, tailsize) = self._alignsplit(addr, len(data), cout_maxsize, 16)
184
        offset = 0
185
        if headsize != 0:
178 farthen 186
            self._writemem(addr, data[offset:offset+headsize])
171 farthen 187
            offset += headsize
188
            addr += headsize
189
        while bodysize > 0:
190
            if bodysize >= 2 * cout_maxsize:
191
                writesize = min(bodysize, dout_maxsize)
178 farthen 192
                self._writedma(addr, data[offset:offset+writesize])
171 farthen 193
            else:
194
                writesize = min(bodysize, cout_maxsize)
178 farthen 195
                self._writemem(addr, data[offset:offset+writesize])
171 farthen 196
            offset += writesize
197
            addr += writesize
198
            bodysize -= writesize
199
        if tailsize != 0:
178 farthen 200
            self._writemem(addr, data[offset:offset+tailsize])
171 farthen 201
        return 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):
178 farthen 210
            data = self._readmem(addr, min(maxlength - len(string), cin_maxsize))
173 farthen 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 """
236 farthen 222
        data = ""
223
        for i in range(size):
224
            resp = self.lib.monitorcommand(struct.pack("IBBBBII", 8, index, slaveaddr, startaddr + i, 1, 0, 0), "III1s", (None, None, None, "data"))
225
            data += resp.data
226
        return 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
215 theseven 235
        return self.lib.monitorcommand(struct.pack("IBBBBII%ds" % size, 9, index, slaveaddr, startaddr, size, 0, 0, data), "III", (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
217 theseven 260
        resp = self.lib.monitorcommand(struct.pack("IIII", 13, bitmask, cin_maxsize, 0), "III%ds" % cin_maxsize, ("size", None, None))
176 farthen 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))
217 theseven 273
            resp = self.lib.monitorcommand(struct.pack("IIII%ds" % writesize, 12, bitmask, writesize, 0, data[:writesize]), "III", (None, None, None))
176 farthen 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
56 benedikt93 344
 
173 farthen 345
    def lockscheduler(self, freeze=True):
171 farthen 346
        """ Freezes/Unfreezes the scheduler """
173 farthen 347
        resp = self.lib.monitorcommand(struct.pack("IIII", 16, 1 if freeze else 0, 0, 0), "III", ("before", None, None))
348
        return True if resp.before == 1 else False
67 benedikt93 349
 
173 farthen 350
    def unlockscheduler(self):
171 farthen 351
        """ Unfreezes the scheduler """
352
        return self.lib.monitorcommand(struct.pack("IIII", 16, 0, 0, 0), "III", ("before", None, None))
56 benedikt93 353
 
171 farthen 354
    def suspendthread(self, id, suspend=True):
355
        """ Suspends the thread with the specified id """
173 farthen 356
        resp = self.lib.monitorcommand(struct.pack("IIII", 17, 1 if suspend else 0, id, 0), "III", ("before", None, None))
357
        return True if resp.before == 1 else False
56 benedikt93 358
 
173 farthen 359
    def resumethread(self, id):
360
        """ Resumes the thread with the specified id """
171 farthen 361
        return self.lib.monitorcommand(struct.pack("IIII", 17, 0, id, 0), "III", ("before", None, None))
56 benedikt93 362
 
171 farthen 363
    def killthread(self, id):
364
        """ Kills the thread with the specified id """
365
        return self.lib.monitorcommand(struct.pack("IIII", 18, id, 0, 0), "III", ("before", None, None))
56 benedikt93 366
 
171 farthen 367
    def createthread(self, nameptr, entrypoint, stackptr, stacksize, threadtype, priority, state):
368
        """ Creates a thread with the specified attributes """
369
        if threadtype == "user":
370
            threadtype = 0
371
        elif threadtype == "system":
372
            threadtype = 1
373
        else:
176 farthen 374
            raise ValueError("Threadtype must be either 'system' or 'user'")
171 farthen 375
        if priority > 256 or priority < 0:
176 farthen 376
            raise ValueError("Priority must be a number between 0 and 256")
171 farthen 377
        if state == "ready":
378
            state = 0
379
        elif state == "suspended":
380
            state = 1
381
        else:
176 farthen 382
            raise ValueError("State must be either 'ready' or 'suspended'")
171 farthen 383
        resp = self.lib.monitorcommand(struct.pack("IIIIIIII", 19, nameptr, entrypoint, stackptr, stacksize, threadtype, priority, state), "III", (id, None, None))
384
        if resp.id < 0:
385
            raise DeviceError("The device returned the error code "+str(resp.id))
386
        return resp
56 benedikt93 387
 
172 farthen 388
    def flushcaches(self):
171 farthen 389
        """ Flushes the CPU instruction and data cache """
390
        return self.lib.monitorcommand(struct.pack("IIII", 20, 0, 0, 0), "III", (None, None, None))
56 benedikt93 391
 
172 farthen 392
    def execimage(self, addr):
171 farthen 393
        """ Runs the emBIOS app at 'addr' """
394
        return self.lib.monitorcommand(struct.pack("IIII", 21, addr, 0, 0), "III", ("excecimage", None, None))
56 benedikt93 395
 
171 farthen 396
    def bootflashread(self, memaddr, flashaddr, size):
397
        """ Copies the data in the bootflash at 'flashaddr' of the specified size
398
            to the memory at addr 'memaddr'
399
        """
174 farthen 400
        return self.lib.monitorcommand(struct.pack("IIII", 22, memaddr, flashaddr, size), "III", (None, None, None))
82 benedikt93 401
 
171 farthen 402
    def bootflashwrite(self, memaddr, flashaddr, size):
403
        """ Copies the data in the memory at 'memaddr' of the specified size
404
            to the boot flash at addr 'flashaddr'
405
        """
174 farthen 406
        return self.lib.monitorcommand(struct.pack("IIII", 23, memaddr, flashaddr, size), "III", (None, None, None))
56 benedikt93 407
 
171 farthen 408
    def execfirmware(self, addr):
409
        """ Executes the firmware at 'addr' and passes all control to it. """
410
        return self.lib.monitorcommand(struct.pack("IIII", 24, addr, 0, 0), "III", (None, None, None))
56 benedikt93 411
 
171 farthen 412
    def aesencrypt(self, addr, size, keyindex):
413
        """ Encrypts the buffer at 'addr' with the specified size
414
            with the hardware AES key index 'keyindex'
415
        """
416
        return self.lib.monitorcommand(struct.pack("IBBHII", 25, 1, 0, keyindex, addr, size), "III", (None, None, None))
82 benedikt93 417
 
171 farthen 418
    def aesdecrypt(self, addr, size, keyindex):
419
        """ Decrypts the buffer at 'addr' with the specified size
420
            with the hardware AES key index 'keyindex'
421
        """
422
        return self.lib.monitorcommand(struct.pack("IBBHII", 25, 0, 0, keyindex, addr, size), "III", (None, None, None))
82 benedikt93 423
 
171 farthen 424
    def hmac_sha1(self, addr, size, destination):
425
        """ Generates a HMAC-SHA1 hash of the buffer and saves it to 'destination' """
426
        return self.lib.monitorcommand(struct.pack("IIII", 26, addr, size, destination), "III", (None, None, None))
56 benedikt93 427
 
227 theseven 428
    def ipodnano2g_getnandinfo(self):
429
        """ Target-specific function: ipodnano2g
430
            Gathers some information about the NAND chip used
431
        """
432
        return self.lib.monitorcommand(struct.pack("IIII", 0xffff0001, 0, 0, 0), "IHHHH", ("type", "pagesperblock", "banks", "userblocks", "blocks"))
433
 
434
    def ipodnano2g_nandread(self, addr, start, count, doecc, checkempty):
435
        """ Target-specific function: ipodnano2g
436
            Reads data from the NAND chip into memory
437
        """
438
        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))
439
 
440
    def ipodnano2g_nandwrite(self, addr, start, count, doecc):
441
        """ Target-specific function: ipodnano2g
442
            Writes data to the NAND chip
443
        """
444
        return self.lib.monitorcommand(struct.pack("IIII", 0xffff0003, addr | (0x80000000 if doecc != 0 else 0), start, count), "III", (None, None, None))
445
 
446
    def ipodnano2g_nanderase(self, addr, start, count):
447
        """ Target-specific function: ipodnano2g
448
            Erases blocks on the NAND chip and stores the results to memory
449
        """
450
        return self.lib.monitorcommand(struct.pack("IIII", 0xffff0004, addr, start, count), "III", (None, None, None))
451
 
56 benedikt93 452
 
171 farthen 453
class Lib(object):
176 farthen 454
    def __init__(self):
171 farthen 455
        self.idVendor = 0xFFFF
456
        self.idProduct = 0xE000
176 farthen 457
 
458
        self.headersize = 0x10
459
 
460
        self.connect()
56 benedikt93 461
 
171 farthen 462
    def connect(self):
463
        self.dev = Dev(self.idVendor, self.idProduct)
464
        self.connected = True
56 benedikt93 465
 
171 farthen 466
    def monitorcommand(self, cmd, rcvdatatypes=None, rcvstruct=None):
467
        self.dev.cout(cmd)
468
        if rcvdatatypes:
469
            rcvdatatypes = "I" + rcvdatatypes # add the response
470
            data = self.dev.cin(struct.calcsize(rcvdatatypes))
471
            data = struct.unpack(rcvdatatypes, data)
472
            response = data[0]
473
            if libembiosdata.responsecodes[response] == "ok":
474
                if rcvstruct:
475
                    datadict = Bunch()
476
                    counter = 1 # start with 1, 0 is the id
477
                    for item in rcvstruct:
478
                        if item != None: # else the data is undefined
479
                            datadict[item] = data[counter]
480
                        counter += 1
481
                    return datadict
482
                else:
483
                    return data
484
            elif libembiosdata.responsecodes[response] == "unsupported":
485
                raise DeviceError("The device does not support this command.")
486
            elif libembiosdata.responsecodes[response] == "invalid":
487
                raise DeviceError("Invalid command! This should NOT happen!")
488
            elif libembiosdata.responsecodes[response] == "busy":
489
                raise DeviceError("Device busy")
56 benedikt93 490
 
491
 
171 farthen 492
class Dev(object):
493
    def __init__(self, idVendor, idProduct):
494
        self.idVendor = idVendor
495
        self.idProduct = idProduct
67 benedikt93 496
 
171 farthen 497
        self.interface = 0
498
        self.timeout = 100
176 farthen 499
 
171 farthen 500
        self.connect()
501
        self.findEndpoints()
502
 
503
        self.packetsizelimit = {}
504
        self.packetsizelimit['cout'] = None
505
        self.packetsizelimit['cin'] = None
506
        self.packetsizelimit['dout'] = None
507
        self.packetsizelimit['din'] = None
56 benedikt93 508
 
171 farthen 509
    def __del__(self):
510
        self.disconnect()
56 benedikt93 511
 
171 farthen 512
    def findEndpoints(self):
513
        epcounter = 0
514
        self.endpoint = {}
515
        for cfg in self.dev:
516
            for intf in cfg:
517
                for ep in intf:
518
                    if epcounter == 0:
519
                        self.endpoint['cout'] = ep.bEndpointAddress
520
                    elif epcounter == 1:
521
                        self.endpoint['cin'] = ep.bEndpointAddress
522
                    elif epcounter == 2:
523
                        self.endpoint['dout'] = ep.bEndpointAddress
524
                    elif epcounter == 3:
525
                        self.endpoint['din'] = ep.bEndpointAddress
526
                    epcounter += 1
527
        if epcounter <= 3:
528
            raise DeviceError("Not all endpoints found in the descriptor. Only "+str(epcounter)+" found, we need 4")
56 benedikt93 529
 
171 farthen 530
    def connect(self):
531
        self.dev = usb.core.find(idVendor=self.idVendor, idProduct=self.idProduct)
532
        if self.dev is None:
533
            raise DeviceNotFoundError()
534
        self.dev.set_configuration()
56 benedikt93 535
 
171 farthen 536
    def disconnect(self):
537
        pass
102 benedikt93 538
 
171 farthen 539
    def send(self, endpoint, data):
540
        size = self.dev.write(endpoint, data, self.interface, self.timeout)
541
        if size != len(data):
176 farthen 542
            raise SendError("Not all data was written!")
171 farthen 543
        return len
102 benedikt93 544
 
171 farthen 545
    def receive(self, endpoint, size):
546
        read = self.dev.read(endpoint, size, self.interface, self.timeout)
547
        if len(read) != size:
176 farthen 548
            raise ReceiveError("Requested size and read size don't match!")
171 farthen 549
        return read
56 benedikt93 550
 
171 farthen 551
    def cout(self, data):
552
        if self.packetsizelimit['cout'] and len(data) > self.packetsizelimit['cout']:
553
            raise SendError("Packet too big")
554
        return self.send(self.endpoint['cout'], data)
94 benedikt93 555
 
171 farthen 556
    def cin(self, size):
557
        if self.packetsizelimit['cin'] and size > self.packetsizelimit['cin']:
558
            raise ReceiveError("Packet too big")
559
        return self.receive(self.endpoint['cin'], size)
94 benedikt93 560
 
171 farthen 561
    def dout(self, data):
562
        if self.packetsizelimit['dout'] and len(data) > self.packetsizelimit['dout']:
563
            raise SendError("Packet too big")
564
        return self.send(self.endpoint['dout'], data)
94 benedikt93 565
 
171 farthen 566
    def din(self, size):
567
        if self.packetsizelimit['din'] and size > self.packetsizelimit['din']:
568
            raise ReceiveError("Packet too big")
569
        return self.receive(self.endpoint['din'], size)
56 benedikt93 570
 
96 benedikt93 571
 
171 farthen 572
if __name__ == "__main__":
573
    # Some tests
574
    import sys
575
    embios = Embios()
576
    resp = embios.getversioninfo()
577
    sys.stdout.write("Embios device version information: " + libembiosdata.swtypes[resp.swtypeid] + " v" + str(resp.majorv) + "." + str(resp.minorv) + 
578
                     "." + str(resp.patchv) + " r" + str(resp.revision) + " running on " + libembiosdata.hwtypes[resp.hwtypeid] + "\n")
579
    resp = embios.getusermemrange()
580
    sys.stdout.write("Usermemrange: "+hex(resp.lower)+" - "+hex(resp.upper)+"\n")
581
    memaddr = resp.lower
582
    maxlen = resp.upper - resp.lower
583
    f = open("./embios.py", "rb")
584
    sys.stdout.write("Loading test file (embios.py) to send over USB...\n")
585
    datastr = f.read()[:maxlen]
586
    sys.stdout.write("Sending data...\n")
587
    embios.write(memaddr, datastr)
588
    sys.stdout.write("Encrypting data with the hardware key...\n")
589
    embios.aesencrypt(memaddr, len(datastr), 0)
590
    sys.stdout.write("Reading data back and saving it to 'libembios-test-encrypted.bin'...\n")
591
    f = open("./libembios-test-encrypted.bin", "wb")
592
    f.write(embios.read(memaddr, len(datastr)))
593
    sys.stdout.write("Decrypting the data again...\n")
594
    embios.aesdecrypt(memaddr, len(datastr), 0)
595
    sys.stdout.write("Reading data back from device...\n")
596
    readdata = embios.read(memaddr, len(datastr))
597
    if readdata == datastr:
598
        sys.stdout.write("Data matches!")
599
    else:
600
        sys.stdout.write("Data does NOT match. Something got wrong")