Subversion Repositories freemyipod

Rev

Rev 807 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 807 Rev 891
Line 1... Line 1...
1
#!/usr/bin/env python
1
#!/usr/bin/env python
2
#
2
#
3
#
3
#
4
#    Copyright 2010 TheSeven, benedikt93, Farthen
4
#    Copyright 2013 TheSeven, benedikt93, Farthen
5
#
5
#
6
#
6
#
7
#    This file is part of emCORE.
7
#    This file is part of emCORE.
8
#
8
#
9
#    emCORE is free software: you can redistribute it and/or
9
#    emCORE is free software: you can redistribute it and/or
Line 106... Line 106...
106
        self.logger.debug("Initializing Emcore object\n")
106
        self.logger.debug("Initializing Emcore object\n")
107
        self.lib = Lib(self.logger)
107
        self.lib = Lib(self.logger)
108
        
108
        
109
        self.getversioninfo()
109
        self.getversioninfo()
110
        if self.lib.dev.swtypeid != 2:
110
        if self.lib.dev.swtypeid != 2:
111
            if self.lib.dev.swtypeid == 1:
-
 
112
                raise DeviceError("Connected to emBIOS. emBIOS is not supported by libemcore")
-
 
113
            else:
-
 
114
                raise DeviceError("Connected to unknown software type. Exiting")
111
            raise DeviceError("Connected to unknown software type. Exiting")
115
        
112
        
116
        self.getpacketsizeinfo()
-
 
117
        self.getmallocpoolbounds()
113
        self.getmallocpoolbounds()
118
    
114
    
119
    @staticmethod
-
 
120
    def _alignsplit(addr, size, blksize, align):
-
 
121
        if size <= blksize: return (size, 0, 0)
-
 
122
        end = addr + size
-
 
123
        if addr & (align - 1):
-
 
124
            bodyaddr = (addr + min(size, blksize)) & ~(align - 1)
-
 
125
        else: bodyaddr = addr
-
 
126
        headsize = bodyaddr - addr
-
 
127
        if (size - headsize) & (align - 1):
-
 
128
            tailaddr = (end - min(end - bodyaddr, blksize) + align - 1) & ~(align - 1)
-
 
129
        else: tailaddr = end
-
 
130
        tailsize = end - tailaddr
-
 
131
        return (headsize, tailaddr - bodyaddr, tailsize)
-
 
132
    
-
 
133
    @command()
115
    @command()
134
    def _readmem(self, addr, size):
116
    def _readmem(self, addr, size):
135
        """ Reads the memory from location 'addr' with size 'size'
117
        """ Reads the memory from location 'addr' with size 'size'
136
            from the device.
118
            from the device. Can handle up to 0xff0 bytes.
137
        """
119
        """
138
        resp = self.lib.monitorcommand(struct.pack("<IIII", 4, addr, size, 0), "III%ds" % size, (None, None, None, "data"))
120
        resp = self.lib.monitorcommand(struct.pack("<IIII", 4, addr, size, 0), "III%ds" % size, (None, None, None, "data"))
139
        return resp.data
121
        return resp.data
140
    
122
    
141
    @command()
123
    @command()
142
    def _writemem(self, addr, data):
124
    def _writemem(self, addr, data):
143
        """ Writes the data in 'data' to the location 'addr'
125
        """ Writes the data in 'data' to the location 'addr'
144
            in the memory of the device.
126
            in the memory of the device. Can handle up to 0xff0 bytes.
145
        """
127
        """
146
        return self.lib.monitorcommand(struct.pack("<IIII%ds" % len(data), 5, addr, len(data), 0, data), "III", (None, None, None))
128
        return self.lib.monitorcommand(struct.pack("<IIII%ds" % len(data), 5, addr, len(data), 0, data), "III", (None, None, None))
147
    
129
    
148
    @command()
130
    @command()
149
    def _readdma(self, addr, size):
-
 
150
        """ Reads the memory from location 'addr' with size 'size'
-
 
151
            from the device. This uses DMA and the data in endpoint.
-
 
152
        """
-
 
153
        self.lib.monitorcommand(struct.pack("<IIII", 6, addr, size, 0), "III", (None, None, None))
-
 
154
        return struct.unpack("<%ds" % size, self.lib.dev.din(size))[0]
-
 
155
    
-
 
156
    @command()
-
 
157
    def _writedma(self, addr, data):
-
 
158
        """ Writes the data in 'data' to the location 'addr'
-
 
159
            in the memory of the device. This uses DMA and the data out endpoint.
-
 
160
        """
-
 
161
        self.lib.monitorcommand(struct.pack("<IIII", 7, addr, len(data), 0), "III", (None, None, None))
-
 
162
        return self.lib.dev.dout(data)
-
 
163
    
-
 
164
    @command()
-
 
165
    def getversioninfo(self):
131
    def getversioninfo(self):
166
        """ This returns the emCORE version and device information. """
132
        """ This returns the emCORE version and device information. """
167
        resp = self.lib.monitorcommand(struct.pack("<IIII", 1, 0, 0, 0), "IBBBBI", ("revision", "majorv", "minorv", "patchv", "swtypeid", "hwtypeid"))
133
        resp = self.lib.monitorcommand(struct.pack("<IIII", 1, 0, 0, 0), "IBBBBI", ("revision", "majorv", "minorv", "patchv", "swtypeid", "hwtypeid"))
168
        self.lib.dev.version.revision = resp.revision
134
        self.lib.dev.version.revision = resp.revision
169
        self.lib.dev.version.majorv = resp.majorv
135
        self.lib.dev.version.majorv = resp.majorv
Line 174... Line 140...
174
        self.logger.debug("Device Hardware Type ID = 0x%X\n" % resp.hwtypeid)
140
        self.logger.debug("Device Hardware Type ID = 0x%X\n" % resp.hwtypeid)
175
        self.lib.dev.hwtypeid = resp.hwtypeid
141
        self.lib.dev.hwtypeid = resp.hwtypeid
176
        return resp
142
        return resp
177
    
143
    
178
    @command()
144
    @command()
179
    def getpacketsizeinfo(self):
-
 
180
        """ This returns the emCORE max packet size information.
-
 
181
            It also sets the properties of the device object accordingly.
-
 
182
        """
-
 
183
        resp = self.lib.monitorcommand(struct.pack("<IIII", 1, 1, 0, 0), "HHII", ("coutmax", "cinmax", "doutmax", "dinmax"))
-
 
184
        self.logger.debug("Device cout packet size limit = %d\n" % resp.coutmax)
-
 
185
        self.lib.dev.packetsizelimit.cout = resp.coutmax
-
 
186
        self.logger.debug("Device cin packet size limit = %d\n" % resp.cinmax)
-
 
187
        self.lib.dev.packetsizelimit.cin = resp.cinmax
-
 
188
        self.logger.debug("Device din packet size limit = %d\n" % resp.doutmax)
-
 
189
        self.lib.dev.packetsizelimit.din = resp.dinmax
-
 
190
        self.logger.debug("Device dout packet size limit = %d\n" % resp.dinmax)
-
 
191
        self.lib.dev.packetsizelimit.dout = resp.doutmax
-
 
192
        return resp
-
 
193
    
-
 
194
    @command()
-
 
195
    def getmallocpoolbounds(self):
145
    def getmallocpoolbounds(self):
196
        """ This returns the memory range of the malloc pool """
146
        """ This returns the memory range of the malloc pool """
197
        resp = self.lib.monitorcommand(struct.pack("<IIII", 1, 2, 0, 0), "III", ("lower", "upper", None))
147
        resp = self.lib.monitorcommand(struct.pack("<IIII", 1, 1, 0, 0), "III", ("lower", "upper", None))
198
        self.logger.debug("Malloc pool bounds = 0x%X - 0x%X\n" % (resp.lower, resp.upper))
148
        self.logger.debug("Malloc pool bounds = 0x%X - 0x%X\n" % (resp.lower, resp.upper))
199
        self.lib.dev.mallocpool.lower = resp.lower
149
        self.lib.dev.mallocpool.lower = resp.lower
200
        self.lib.dev.mallocpool.upper = resp.upper
150
        self.lib.dev.mallocpool.upper = resp.upper
201
        return resp
151
        return resp
202
    
152
    
203
    @command()
153
    @command()
204
    def reset(self, force=False):
154
    def reset(self, force=False):
205
        """ Reboot the device """
155
        """ Reboot the device """
206
        if force:
-
 
207
            return self.lib.monitorcommand(struct.pack("<IIII", 2, 0, 0, 0))
156
        return self.lib.monitorcommand(struct.pack("<IIII", 2, 0 if force else 1, 0, 0))
208
        else:
-
 
209
            return self.lib.monitorcommand(struct.pack("<IIII", 2, 1, 0, 0), "III", (None, None, None))
-
 
210
    
157
    
211
    @command()
158
    @command()
212
    def poweroff(self, force=False):
159
    def poweroff(self, force=False):
213
        """ Powers the device off. """
160
        """ Powers the device off. """
214
        if force:
-
 
215
            return self.lib.monitorcommand(struct.pack("<IIII", 3, 0, 0, 0))
161
        return self.lib.monitorcommand(struct.pack("<IIII", 3, 0 if force else 1, 0, 0))
216
        else:
-
 
217
            return self.lib.monitorcommand(struct.pack("<IIII", 3, 1, 0, 0), "III", (None, None, None))
-
 
218
    
162
    
219
    @command()
163
    @command()
220
    def read(self, addr, size):
164
    def read(self, addr, size):
221
        """ Reads the memory from location 'addr' with size 'size'
165
        """ Reads the memory from location 'addr' with size 'size'
222
            from the device. This cares about too long packages
166
            from the device. This takes care of splitting long requests.
223
            and decides whether to use DMA or not.
-
 
224
        """
167
        """
225
        cin_maxsize = self.lib.dev.packetsizelimit.cin - self.lib.headersize
-
 
226
        din_maxsize = self.lib.dev.packetsizelimit.din
-
 
227
        data = b""
168
        data = b""
228
        (headsize, bodysize, tailsize) = self._alignsplit(addr, size, cin_maxsize, 16)
-
 
229
        self.logger.debug("Downloading %d bytes from 0x%X, split as (%d/%d/%d)\n" % (size, addr, headsize, bodysize, tailsize))
169
        self.logger.debug("Downloading %d bytes from 0x%X\n" % (size, addr))
230
        if headsize != 0:
-
 
231
            data += self._readmem(addr, headsize)
-
 
232
            addr += headsize
-
 
233
        while bodysize > 0:
170
        while size > 0:
234
            if bodysize >= 2 * cin_maxsize:
-
 
235
                readsize = min(bodysize, din_maxsize)
-
 
236
                data += self._readdma(addr, readsize)
-
 
237
            else:
-
 
238
                readsize = min(bodysize, cin_maxsize)
171
            readsize = min(size, 0xf00)
239
                data += self._readmem(addr, readsize)
172
            data += self._readmem(addr, readsize)
240
            addr += readsize
173
            addr += readsize
241
            bodysize -= readsize
174
            size -= readsize
242
        if tailsize != 0:
-
 
243
            data += self._readmem(addr, tailsize)
-
 
244
        return data
175
        return data
245
    
176
    
246
    @command()
177
    @command()
247
    def write(self, addr, data):
178
    def write(self, addr, data):
248
        """ Writes the data in 'data' to the location 'addr'
179
        """ Writes the data in 'data' to the location 'addr'
249
            in the memory of the device. This cares about too long packages
180
            in the memory of the device. This takes care of splitting long requests.
250
            and decides whether to use DMA or not.
-
 
251
        """
181
        """
252
        cout_maxsize = self.lib.dev.packetsizelimit.cout - self.lib.headersize
-
 
253
        dout_maxsize = self.lib.dev.packetsizelimit.dout
-
 
254
        (headsize, bodysize, tailsize) = self._alignsplit(addr, len(data), cout_maxsize, 16)
-
 
255
        self.logger.debug("Uploading %d bytes to 0x%X, split as (%d/%d/%d)\n" % (len(data), addr, headsize, bodysize, tailsize))
182
        self.logger.debug("Uploading %d bytes to 0x%X\n" % (len(data), addr))
256
        offset = 0
183
        offset = 0
257
        if headsize != 0:
-
 
258
            self._writemem(addr, data[offset:offset+headsize])
-
 
259
            offset += headsize
-
 
260
            addr += headsize
-
 
261
        while bodysize > 0:
184
        while size > 0:
262
            if bodysize >= 2 * cout_maxsize:
-
 
263
                writesize = min(bodysize, dout_maxsize)
-
 
264
                self._writedma(addr, data[offset:offset+writesize])
-
 
265
            else:
-
 
266
                writesize = min(bodysize, cout_maxsize)
185
            writesize = min(size, 0xf00)
267
                self._writemem(addr, data[offset:offset+writesize])
186
            self._writemem(addr, data[offset:offset+writesize])
268
            offset += writesize
187
            offset += writesize
269
            addr += writesize
188
            addr += writesize
270
            bodysize -= writesize
189
            size -= writesize
271
        if tailsize != 0:
-
 
272
            self._writemem(addr, data[offset:offset+tailsize])
-
 
273
        return data
190
        return data
274
    
191
    
275
    @command()
192
    @command()
276
    def upload(self, data):
193
    def upload(self, data):
277
        """ Allocates memory of the size of 'data' and uploads 'data' to that memory region.
194
        """ Allocates memory of the size of 'data' and uploads 'data' to that memory region.
Line 285... Line 202...
285
    def readstring(self, addr, maxlength = 256, replacement = "."):
202
    def readstring(self, addr, maxlength = 256, replacement = "."):
286
        """ Reads a zero terminated string from memory 
203
        """ Reads a zero terminated string from memory 
287
            Reads only a maximum of 'maxlength' chars.
204
            Reads only a maximum of 'maxlength' chars.
288
        """
205
        """
289
        if addr == 0: return "<NULL>"
206
        if addr == 0: return "<NULL>"
290
        cin_maxsize = self.lib.dev.packetsizelimit.cin - self.lib.headersize
207
        cin_maxsize = 1024
291
        string = ""
208
        string = ""
292
        done = False
209
        done = False
293
        while not done and (len(string) < maxlength or maxlength < 0):
210
        while not done and (len(string) < maxlength or maxlength < 0):
294
            data = self._readmem(addr, min(maxlength - len(string), cin_maxsize))
211
            data = self._readmem(addr, min(maxlength - len(string), cin_maxsize))
295
            length = data.find(b"\0")
212
            length = data.find(b"\0")
Line 314... Line 231...
314
    
231
    
315
    @command()
232
    @command()
316
    def i2cwrite(self, index, slaveaddr, startaddr, data):
233
    def i2cwrite(self, index, slaveaddr, startaddr, data):
317
        """ Writes data to an i2c slave """
234
        """ Writes data to an i2c slave """
318
        size = len(data)
235
        size = len(data)
319
        if size > 256 or size < 1:
236
        if size > 48 or size < 1:
320
            raise ArgumentError("Size must be a number between 1 and 256")
237
            raise ArgumentError("Size must be a number between 1 and 48")
321
        if size == 256:
-
 
322
            size = 0
-
 
323
        return self.lib.monitorcommand(struct.pack("<IBBBBII%ds" % size, 9, index, slaveaddr, startaddr, size, 0, 0, data), "III", (None, None, None))
238
        return self.lib.monitorcommand(struct.pack("<IBBBBII%ds" % size, 9, index, slaveaddr, startaddr, size, 0, 0, data), "III", (None, None, None))
324
    
239
    
325
    @command()
240
    @command()
326
    def usbcread(self):
241
    def usbcread(self):
327
        """ Reads one packet with the maximal cin size from the console """
242
        """ Reads one packet with the maximal cin size from the console """
328
        cin_maxsize = self.lib.dev.packetsizelimit.cin - self.lib.headersize
243
        cin_maxsize = 48
329
        resp = self.lib.monitorcommand(struct.pack("<IIII", 10, cin_maxsize, 0, 0), "III%ds" % cin_maxsize, ("validsize", "buffersize", "queuesize", "data"))
244
        resp = self.lib.monitorcommand(struct.pack("<IIII", 10, cin_maxsize, 0, 0), "III%ds" % cin_maxsize, ("validsize", "buffersize", "queuesize", "data"))
330
        resp.data = resp.data[:resp.validsize].decode("latin_1")
245
        resp.data = resp.data[:resp.validsize].decode("latin_1")
331
        resp.maxsize = cin_maxsize
246
        resp.maxsize = cin_maxsize
332
        return resp
247
        return resp
333
    
248
    
334
    @command()
249
    @command()
335
    def usbcwrite(self, data):
250
    def usbcwrite(self, data):
336
        """ Writes data to the USB console """
251
        """ Writes data to the USB console """
337
        cin_maxsize = self.lib.dev.packetsizelimit.cin - self.lib.headersize
252
        cin_maxsize = 48
338
        size = len(data)
253
        size = len(data)
339
        while len(data) > 0:
254
        while len(data) > 0:
340
            writesize = min(cin_maxsize, len(data))
255
            writesize = min(cin_maxsize, len(data))
341
            resp = self.lib.monitorcommand(struct.pack("<IIII%ds" % writesize, 11, writesize, 0, 0, data[:writesize]), "III", ("validsize", "buffersize", "freesize"))
256
            resp = self.lib.monitorcommand(struct.pack("<IIII%ds" % writesize, 11, writesize, 0, 0, data[:writesize]), "III", ("validsize", "buffersize", "freesize"))
342
            data = data[resp.validsize:]
257
            data = data[resp.validsize:]
Line 345... Line 260...
345
    @command()
260
    @command()
346
    def cread(self, bitmask=0x1):
261
    def cread(self, bitmask=0x1):
347
        """ Reads one packet with the maximal cin size from the device consoles
262
        """ Reads one packet with the maximal cin size from the device consoles
348
            identified with the specified bitmask
263
            identified with the specified bitmask
349
        """
264
        """
350
        cin_maxsize = self.lib.dev.packetsizelimit.cin - self.lib.headersize
265
        cin_maxsize = 48
351
        resp = self.lib.monitorcommand(struct.pack("<IIII", 13, bitmask, cin_maxsize, 0), "III%ds" % cin_maxsize, ("size", None, None))
266
        resp = self.lib.monitorcommand(struct.pack("<IIII", 13, bitmask, cin_maxsize, 0), "III%ds" % cin_maxsize, ("size", None, None))
352
        resp.data = resp.data[size:]
267
        resp.data = resp.data[size:]
353
        resp.maxsize = cin_maxsize
268
        resp.maxsize = cin_maxsize
354
        return resp
269
        return resp
355
    
270
    
356
    @command()
271
    @command()
357
    def cwrite(self, data, bitmask=0x1):
272
    def cwrite(self, data, bitmask=0x1):
358
        """ Writes data to the device consoles 
273
        """ Writes data to the device consoles 
359
            identified with the specified bitmask.
274
            identified with the specified bitmask.
360
        """
275
        """
361
        cin_maxsize = self.lib.dev.packetsizelimit.cin - self.lib.headersize
276
        cin_maxsize = 48
362
        size = len(data)
277
        size = len(data)
363
        while len(data) > 0:
278
        while len(data) > 0:
364
            writesize = min(cin_maxsize, len(data))
279
            writesize = min(cin_maxsize, len(data))
365
            resp = self.lib.monitorcommand(struct.pack("<IIII%ds" % writesize, 12, bitmask, writesize, 0, data[:writesize]), "III", (None, None, None))
280
            resp = self.lib.monitorcommand(struct.pack("<IIII%ds" % writesize, 12, bitmask, writesize, 0, data[:writesize]), "III", (None, None, None))
366
            data = data[writesize:]
281
            data = data[writesize:]
Line 383... Line 298...
383
        structptr = resp.structptr
298
        structptr = resp.structptr
384
        id = 0
299
        id = 0
385
        while structptr != 0:
300
        while structptr != 0:
386
            threadstruct = scheduler_thread()
301
            threadstruct = scheduler_thread()
387
            self.logger.debug("Reading thread struct of thread at 0x%X\n" % structptr)
302
            self.logger.debug("Reading thread struct of thread at 0x%X\n" % structptr)
388
            threaddata = self.read(structptr, ctypes.sizeof(scheduler_thread))
303
            threaddata = self._readmem(structptr, ctypes.sizeof(scheduler_thread))
389
            threadstruct._from_string(threaddata)
304
            threadstruct._from_string(threaddata)
390
            threadstruct = threadstruct._to_bunch()
305
            threadstruct = threadstruct._to_bunch()
391
            threadstruct.id = id # only for the purpose of detecting the idle thread as it is always the first one
306
            threadstruct.id = id # only for the purpose of detecting the idle thread as it is always the first one
392
            threadstruct.addr = structptr
307
            threadstruct.addr = structptr
393
            if threadstruct.name != 0:
308
            if threadstruct.name != 0:
Line 472... Line 387...
472
    def flushcaches(self):
387
    def flushcaches(self):
473
        """ Flushes the CPU instruction and data cache """
388
        """ Flushes the CPU instruction and data cache """
474
        return self.lib.monitorcommand(struct.pack("<IIII", 20, 0, 0, 0), "III", (None, None, None))
389
        return self.lib.monitorcommand(struct.pack("<IIII", 20, 0, 0, 0), "III", (None, None, None))
475
    
390
    
476
    @command()
391
    @command()
477
    def execimage(self, addr):
392
    def execimage(self, addr, args = [], copy = False):
478
        """ Runs the emCORE app at 'addr' """
393
        """ Runs the emCORE app at 'addr' with command line arguments 'args' """
-
 
394
        flags = 1 if copy else 0
-
 
395
        argptr = b""
-
 
396
        argdata = b""
-
 
397
        ptr = len(args) * 4
-
 
398
        for arg in args:
-
 
399
           arg = arg.encode("utf_8") + "\0"
-
 
400
           argptr += struct.pack("<I", ptr);
-
 
401
           argdata += arg
-
 
402
           ptr += len(arg)
-
 
403
        if ptr > 48:
-
 
404
            buf = self.malloc(ptr)
-
 
405
            try:
-
 
406
                self._writemem(buf, argptr + argdata)
479
        return self.lib.monitorcommand(struct.pack("<IIII", 21, addr, 0, 0), "III", ("thread", None, None))
407
                result = self.lib.monitorcommand(struct.pack("<IIBBBBI", 21, addr, 0, 0, flags, len(args), buf), "III", ("thread", None, None))
-
 
408
            finally: self.free(buf)
-
 
409
        else: return self.lib.monitorcommand(struct.pack("<IIBBBBI", 21, addr, 0, 0, flags, len(args), 0) + argptr + argdata, "III", ("thread", None, None))
480
    
410
    
481
    @command()
411
    @command()
482
    def run(self, app):
412
    def run(self, app, args = []):
483
        """ Uploads and runs the emCORE app in the string 'app' """
413
        """ Uploads and runs the emCORE app in the string 'app'
-
 
414
            with command line arguments 'args'
-
 
415
        """
484
        if app[:8].decode("latin_1") != "emCOexec":
416
        if app[:8].decode("latin_1") != "emCOexec":
485
            raise ArgumentError("The specified app is not an emCORE application")
417
            raise ArgumentError("The specified app is not an emCORE application")
486
        baseaddr = self.malloc(len(app))
418
        baseaddr = self.malloc(len(app))
487
        self.write(baseaddr, app)
419
        self.write(baseaddr, app)
488
        result = self.execimage(baseaddr)
420
        result = self.execimage(baseaddr, args)
489
        return Bunch(thread=result.thread)
421
        return Bunch(thread=result.thread)
490
    
422
    
491
    @command(timeout = 5000)
423
    @command(timeout = 5000)
492
    def bootflashread(self, memaddr, flashaddr, size):
424
    def bootflashread(self, memaddr, flashaddr, size):
493
        """ Copies the data in the bootflash at 'flashaddr' of the specified size
425
        """ Copies the data in the bootflash at 'flashaddr' of the specified size
Line 717... Line 649...
717
    @command(timeout = 30000)
649
    @command(timeout = 30000)
718
    def file_open(self, filename, mode):
650
    def file_open(self, filename, mode):
719
        """ Opens a file and returns the handle """
651
        """ Opens a file and returns the handle """
720
        fn = filename.encode("utf_8")
652
        fn = filename.encode("utf_8")
721
        self.logger.debug("Opening remote file %s with mode %d\n" % (filename, mode))
653
        self.logger.debug("Opening remote file %s with mode %d\n" % (filename, mode))
-
 
654
        bytes = len(fn) + 1
-
 
655
        if bytes > 48:
-
 
656
            buf = self.malloc(bytes)
-
 
657
            try:
-
 
658
                self._writemem(buf, fn + b"\0")
-
 
659
                result = self.lib.monitorcommand(struct.pack("<IIII", 30, mode, 0, buf), "III", ("fd", None, None))
-
 
660
            finally: self.free(buf)
722
        result = self.lib.monitorcommand(struct.pack("<IIII%dsB" % len(fn), 30, mode, 0, 0, fn, 0), "III", ("fd", None, None))
661
        else: result = self.lib.monitorcommand(struct.pack("<IIII%dsB" % len(fn), 30, mode, 0, 0, fn, 0), "III", ("fd", None, None))
723
        if result.fd > 0x80000000:
662
        if result.fd > 0x80000000:
724
            raise DeviceError("file_open(filename=\"%s\", mode=0x%X) failed with RC=0x%08X, errno=%d" % (filename, mode, result.fd, self.errno()))
663
            raise DeviceError("file_open(filename=\"%s\", mode=0x%X) failed with RC=0x%08X, errno=%d" % (filename, mode, result.fd, self.errno()))
725
        self.logger.debug("Opened file as handle 0x%X\n" % result.fd)
664
        self.logger.debug("Opened file as handle 0x%X\n" % result.fd)
726
        return result.fd
665
        return result.fd
727
    
666
    
Line 828... Line 767...
828
    @command(timeout = 30000)
767
    @command(timeout = 30000)
829
    def file_unlink(self, filename):
768
    def file_unlink(self, filename):
830
        """ Removes a file """
769
        """ Removes a file """
831
        fn = filename.encode("utf_8")
770
        fn = filename.encode("utf_8")
832
        self.logger.debug("Deleting file %s\n" % (filename))
771
        self.logger.debug("Deleting file %s\n" % (filename))
-
 
772
        bytes = len(fn)
-
 
773
        if bytes > 48:
-
 
774
            buf = self.malloc(bytes)
-
 
775
            try:
-
 
776
                self._writemem(buf, fn + b"\0")
-
 
777
                result = self.lib.monitorcommand(struct.pack("<IIII", 40, 0, 0, buf), "III", ("rc", None, None))
-
 
778
            finally: self.free(buf)
833
        result = self.lib.monitorcommand(struct.pack("<IIII%dsB" % len(fn), 40, 0, 0, 0, fn, 0), "III", ("rc", None, None))
779
        else: result = self.lib.monitorcommand(struct.pack("<IIII%dsB" % len(fn), 40, 0, 0, 0, fn, 0), "III", ("rc", None, None))
834
        if result.rc > 0x80000000:
780
        if result.rc > 0x80000000:
835
            raise DeviceError("file_unlink(filename=\"%s\") failed with RC=0x%08X, errno=%d" % (filename, result.rc, self.errno()))
781
            raise DeviceError("file_unlink(filename=\"%s\") failed with RC=0x%08X, errno=%d" % (filename, result.rc, self.errno()))
836
        self.logger.debug("Delete file result: 0x%X\n" % (result.rc))
782
        self.logger.debug("Delete file result: 0x%X\n" % (result.rc))
837
        return result.rc
783
        return result.rc
838
    
784
    
Line 840... Line 786...
840
    def file_rename(self, oldname, newname):
786
    def file_rename(self, oldname, newname):
841
        """ Renames a file """
787
        """ Renames a file """
842
        on = oldname.encode("utf_8")
788
        on = oldname.encode("utf_8")
843
        nn = newname.encode("utf_8")
789
        nn = newname.encode("utf_8")
844
        self.logger.debug("Renaming file %s to %s\n" % (on, nn))
790
        self.logger.debug("Renaming file %s to %s\n" % (on, nn))
-
 
791
        obytes = len(on) + 1
-
 
792
        nbytes = len(nn) + 1
-
 
793
        buf = self.malloc(obytes + nbytes)
-
 
794
        try:
-
 
795
            self._writemem(buf, on + b"\0" + nn + b"\0")
845
        result = self.lib.monitorcommand(struct.pack("<IIII248s%dsB" % min(247, len(nn)), 41, 0, 0, 0, on, nn, 0), "III", ("rc", None, None))
796
            result = self.lib.monitorcommand(struct.pack("<IIII", 41, 0, buf, buf + obytes), "III", ("rc", None, None))
-
 
797
        finally: self.free(buf)
846
        if result.rc > 0x80000000:
798
        if result.rc > 0x80000000:
847
            raise DeviceError("file_rename(oldname=\"%s\", newname=\"%s\") failed with RC=0x%08X, errno=%d" % (oldname, newname, result.rc, self.errno()))
799
            raise DeviceError("file_rename(oldname=\"%s\", newname=\"%s\") failed with RC=0x%08X, errno=%d" % (oldname, newname, result.rc, self.errno()))
848
        self.logger.debug("Rename file result: 0x%X\n" % (result.rc))
800
        self.logger.debug("Rename file result: 0x%X\n" % (result.rc))
849
        return result.rc
801
        return result.rc
850
    
802
    
851
    @command(timeout = 30000)
803
    @command(timeout = 30000)
852
    def dir_open(self, dirname):
804
    def dir_open(self, dirname):
853
        """ Opens a directory and returns the handle """
805
        """ Opens a directory and returns the handle """
854
        dn = dirname.encode("utf_8")
806
        dn = dirname.encode("utf_8")
855
        self.logger.debug("Opening directory %s\n" % (dirname))
807
        self.logger.debug("Opening directory %s\n" % (dirname))
-
 
808
        bytes = len(dn)
-
 
809
        if bytes > 48:
-
 
810
            buf = self.malloc(bytes)
-
 
811
            try:
-
 
812
                self._writemem(buf, dn + b"\0")
-
 
813
                result = self.lib.monitorcommand(struct.pack("<IIII", 42, 0, 0, buf), "III", ("handle", None, None))
-
 
814
            finally: self.free(buf)
856
        result = self.lib.monitorcommand(struct.pack("<IIII%dsB" % len(dn), 42, 0, 0, 0, dn, 0), "III", ("handle", None, None))
815
        else: result = self.lib.monitorcommand(struct.pack("<IIII%dsB" % len(dn), 42, 0, 0, 0, dn, 0), "III", ("handle", None, None))
857
        if result.handle == 0:
816
        if result.handle == 0:
858
            raise DeviceError("dir_open(dirname=\"%s\") failed with RC=0x%08X, errno=%d" % (dirname, result.handle, self.errno()))
817
            raise DeviceError("dir_open(dirname=\"%s\") failed with RC=0x%08X, errno=%d" % (dirname, result.handle, self.errno()))
859
        self.logger.debug("Opened directory as handle 0x%X\n" % (result.handle))
818
        self.logger.debug("Opened directory as handle 0x%X\n" % (result.handle))
860
        return result.handle
819
        return result.handle
861
    
820
    
Line 914... Line 873...
914
    @command(timeout = 30000)
873
    @command(timeout = 30000)
915
    def dir_create(self, dirname):
874
    def dir_create(self, dirname):
916
        """ Creates a directory """
875
        """ Creates a directory """
917
        dn = dirname.encode("utf_8")
876
        dn = dirname.encode("utf_8")
918
        self.logger.debug("Creating directory %s\n" % (dirname))
877
        self.logger.debug("Creating directory %s\n" % (dirname))
-
 
878
        bytes = len(dn)
-
 
879
        if bytes > 48:
-
 
880
            buf = self.malloc(bytes)
-
 
881
            try:
-
 
882
                self._writemem(buf, dn + b"\0")
-
 
883
                result = self.lib.monitorcommand(struct.pack("<IIII", 47, 0, 0, buf), "III", ("rc", None, None))
-
 
884
            finally: self.free(buf)
919
        result = self.lib.monitorcommand(struct.pack("<IIII%dsB" % len(dn), 47, 0, 0, 0, dn, 0), "III", ("rc", None, None))
885
        else: result = self.lib.monitorcommand(struct.pack("<IIII%dsB" % len(dn), 47, 0, 0, 0, dn, 0), "III", ("rc", None, None))
920
        if result.rc > 0x80000000:
886
        if result.rc > 0x80000000:
921
            raise DeviceError("dir_create(dirname=\"%s\") failed with RC=0x%08X, errno=%d" % (dirname, result.rc, self.errno()))
887
            raise DeviceError("dir_create(dirname=\"%s\") failed with RC=0x%08X, errno=%d" % (dirname, result.rc, self.errno()))
922
        self.logger.debug("Create directory result: 0x%X\n" % (result.rc))
888
        self.logger.debug("Create directory result: 0x%X\n" % (result.rc))
923
        return result.rc
889
        return result.rc
924
    
890
    
925
    @command(timeout = 30000)
891
    @command(timeout = 30000)
926
    def dir_remove(self, dirname):
892
    def dir_remove(self, dirname):
927
        """ Removes an (empty) directory """
893
        """ Removes an (empty) directory """
928
        dn = dirname.encode("utf_8")
894
        dn = dirname.encode("utf_8")
929
        self.logger.debug("Removing directory %s\n" % (dirname))
895
        self.logger.debug("Removing directory %s\n" % (dirname))
-
 
896
        bytes = len(dn)
-
 
897
        if bytes > 48:
-
 
898
            buf = self.malloc(bytes)
-
 
899
            try:
-
 
900
                self._writemem(buf, dn + b"\0")
-
 
901
                result = self.lib.monitorcommand(struct.pack("<IIII", 48, 0, 0, buf), "III", ("rc", None, None))
-
 
902
            finally: self.free(buf)
930
        result = self.lib.monitorcommand(struct.pack("<IIII%dsB" % len(dn), 48, 0, 0, 0, dn, 0), "III", ("rc", None, None))
903
        else: result = self.lib.monitorcommand(struct.pack("<IIII%dsB" % len(dn), 48, 0, 0, 0, dn, 0), "III", ("rc", None, None))
931
        if result.rc > 0x80000000:
904
        if result.rc > 0x80000000:
932
            raise DeviceError("dir_remove(dirname=\"%s\") failed with RC=0x%08X, errno=%d" % (dirname, result.rc, self.errno()))
905
            raise DeviceError("dir_remove(dirname=\"%s\") failed with RC=0x%08X, errno=%d" % (dirname, result.rc, self.errno()))
933
        self.logger.debug("Remove directory result: 0x%X\n" % (result.rc))
906
        self.logger.debug("Remove directory result: 0x%X\n" % (result.rc))
934
        return result.rc
907
        return result.rc
935
    
908
    
Line 1039... Line 1012...
1039
        self.dev = Dev(self.idVendor, self.idProduct, self.logger)
1012
        self.dev = Dev(self.idVendor, self.idProduct, self.logger)
1040
        self.connected = True
1013
        self.connected = True
1041
    
1014
    
1042
    def monitorcommand(self, cmd, rcvdatatypes=None, rcvstruct=None):
1015
    def monitorcommand(self, cmd, rcvdatatypes=None, rcvstruct=None):
1043
        self.logger.debug("Sending monitorcommand [0x%s]\n" % base64.b16encode(cmd[3::-1]).decode("ascii"))
1016
        self.logger.debug("Sending monitorcommand [0x%s]\n" % base64.b16encode(cmd[3::-1]).decode("ascii"))
1044
        writelen = self.dev.cout(cmd)
1017
        writelen = self.dev.send(cmd)
1045
        if rcvdatatypes:
1018
        if rcvdatatypes:
1046
            rcvdatatypes = "I" + rcvdatatypes # add the response
1019
            rcvdatatypes = "I" + rcvdatatypes # add the response
1047
            data = self.dev.cin(struct.calcsize(rcvdatatypes))
1020
            data = self.dev.receive(struct.calcsize(rcvdatatypes))
1048
            data = struct.unpack(rcvdatatypes, data)
1021
            data = struct.unpack(rcvdatatypes, data)
1049
            try:
1022
            try:
1050
                response = responsecode(data[0])
1023
                response = responsecode(data[0])
1051
            except IndexError:
1024
            except IndexError:
1052
                self.logger.debug("Response: UNKOWN\n")
1025
                self.logger.debug("Response: UNKOWN\n")
Line 1082... Line 1055...
1082
        self.idProduct = idProduct
1055
        self.idProduct = idProduct
1083
        
1056
        
1084
        self.logger = logger
1057
        self.logger = logger
1085
        self.logger.debug("Initializing Dev object\n")
1058
        self.logger.debug("Initializing Dev object\n")
1086
        
1059
        
1087
        self.interface = 0
1060
        self.interface = None
-
 
1061
        self.claimed = False
1088
        self.timeout = 1000
1062
        self.timeout = 1000
1089
        
1063
        
1090
        self.connect()
1064
        self.connect()
1091
        self.findEndpoints()
-
 
1092
        
1065
        
1093
        self.logger.debug("Successfully connected to device\n")
1066
        self.logger.debug("Successfully connected to device\n")
1094
        
1067
        
1095
        # Device properties
-
 
1096
        self.packetsizelimit = Bunch()
-
 
1097
        self.packetsizelimit.cout = None
-
 
1098
        self.packetsizelimit.cin = None
-
 
1099
        self.packetsizelimit.dout = None
-
 
1100
        self.packetsizelimit.din = None
-
 
1101
        
-
 
1102
        self.version = Bunch()
1068
        self.version = Bunch()
1103
        self.version.revision = None
1069
        self.version.revision = None
1104
        self.version.majorv = None
1070
        self.version.majorv = None
1105
        self.version.minorv = None
1071
        self.version.minorv = None
1106
        self.version.patchv = None
1072
        self.version.patchv = None
Line 1110... Line 1076...
1110
        self.mallocpool = Bunch()
1076
        self.mallocpool = Bunch()
1111
        self.mallocpool.lower = None
1077
        self.mallocpool.lower = None
1112
        self.mallocpool.upper = None
1078
        self.mallocpool.upper = None
1113
    
1079
    
1114
    def __del__(self):
1080
    def __del__(self):
1115
        self.disconnect()
1081
        if self.claimed: self.disconnect()
1116
    
-
 
1117
    def findEndpoints(self):
-
 
1118
        self.logger.debug("Searching for device endpoints:\n")
-
 
1119
        epcounter = 0
-
 
1120
        self.endpoint = Bunch()
-
 
1121
        for cfg in self.dev:
-
 
1122
            for intf in cfg:
-
 
1123
                for ep in intf:
-
 
1124
                    if epcounter == 0:
-
 
1125
                        self.logger.debug("Found cout endpoint at 0x%X\n" % ep.bEndpointAddress)
-
 
1126
                        self.endpoint.cout = ep.bEndpointAddress
-
 
1127
                    elif epcounter == 1:
-
 
1128
                        self.logger.debug("Found cin endpoint at 0x%X\n" % ep.bEndpointAddress)
-
 
1129
                        self.endpoint.cin = ep.bEndpointAddress
-
 
1130
                    elif epcounter == 2:
-
 
1131
                        self.logger.debug("Found dout endpoint at 0x%X\n" % ep.bEndpointAddress)
-
 
1132
                        self.endpoint.dout = ep.bEndpointAddress
-
 
1133
                    elif epcounter == 3:
-
 
1134
                        self.logger.debug("Found din endpoint at 0x%X\n" % ep.bEndpointAddress)
-
 
1135
                        self.endpoint.din = ep.bEndpointAddress
-
 
1136
                    epcounter += 1
-
 
1137
        if epcounter <= 3:
-
 
1138
            raise DeviceError("Not all endpoints found in the descriptor. Only %d endpoints found, at least 4 endpoints were expeceted" % epcounter)
-
 
1139
    
1082
    
1140
    def connect(self):
1083
    def connect(self):
1141
        self.logger.debug("Looking for emCORE device\n")
1084
        self.logger.debug("Looking for emCORE device\n")
1142
        self.dev = usb.core.find(idVendor=self.idVendor, idProduct=self.idProduct)
1085
        self.dev = usb.core.find(idVendor=self.idVendor, idProduct=self.idProduct)
1143
        if self.dev is None:
1086
        if self.dev is None:
1144
            raise DeviceNotFoundError()
1087
            raise DeviceNotFoundError()
1145
        self.logger.debug("Device Found!\n")
1088
        self.logger.debug("Device found!\n")
1146
        self.logger.debug("Setting first configuration\n")
1089
        self.logger.debug("Searching for device interface:\n")
-
 
1090
        for cfg in self.dev:
-
 
1091
            for intf in cfg:
-
 
1092
                if intf.bInterfaceClass == 0xff and intf.bInterfaceSubClass == 0 and intf.bInterfaceProtocol == 0:
-
 
1093
                    self.interface = intf.bInterfaceNumber
-
 
1094
                    break
1147
        self.dev.set_configuration()
1095
        if self.interface is None:
-
 
1096
            raise DeviceNotFoundError()
-
 
1097
        self.logger.debug("Debugger interface found!\n")
-
 
1098
        self.logger.debug("Claiming interface...\n")
-
 
1099
        usb.util.claim_interface(self.dev, self.interface)
-
 
1100
        self.claimed = True
1148
    
1101
    
1149
    def disconnect(self):
1102
    def disconnect(self):
-
 
1103
        usb.util.release_interface(self.dev, self.interface)
1150
        pass
1104
        self.claimed = False
1151
    
1105
    
1152
    def send(self, endpoint, data):
1106
    def send(self, data):
-
 
1107
        if len(data) > 0x1000: raise DeviceError("Attempting to send a message that is too big!")
1153
        size = self.dev.write(endpoint, data, self.interface, self.timeout)
1108
        size = self.dev.ctrl_transfer(0x41, 0x00, 0, self.interface, data, self.timeout)
1154
        if size != len(data):
1109
        if size != len(data):
1155
            raise SendError("Not all data was written!")
1110
            raise SendError("Not all data was written!")
1156
        return len
1111
        return len
1157
    
1112
    
1158
    def receive(self, endpoint, size):
1113
    def receive(self, size):
-
 
1114
        if size > 0x1000: raise DeviceError("Attempting to receive a message that is too big!")
1159
        read = self.dev.read(endpoint, size, self.interface, self.timeout)
1115
        read = self.dev.ctrl_transfer(0xc1, 0x00, 0, self.interface, size, self.timeout)
1160
        if len(read) != size:
1116
        if len(read) != size:
1161
            raise ReceiveError("Requested size and read size don't match!")
1117
            raise ReceiveError("Requested size and read size don't match!")
1162
        return read
1118
        return read
1163
    
1119
    
1164
    def cout(self, data):
-
 
1165
        self.logger.debug("Sending data to cout endpoint with the size %d\n" % len(data))
-
 
1166
        if self.packetsizelimit.cout and len(data) > self.packetsizelimit.cout:
-
 
1167
            raise SendError("Packet too big")
-
 
1168
        return self.send(self.endpoint.cout, data)
-
 
1169
    
-
 
1170
    def cin(self, size):
-
 
1171
        self.logger.debug("Receiving data on the cin endpoint with the size %d\n" % size)
-
 
1172
        if self.packetsizelimit.cin and size > self.packetsizelimit.cin:
-
 
1173
            raise ReceiveError("Packet too big")
-
 
1174
        return self.receive(self.endpoint.cin, size)
-
 
1175
    
-
 
1176
    def dout(self, data):
-
 
1177
        self.logger.debug("Sending data to cout endpoint with the size %d\n" % len(data))
-
 
1178
        if self.packetsizelimit.dout and len(data) > self.packetsizelimit.dout:
-
 
1179
            raise SendError("Packet too big")
-
 
1180
        return self.send(self.endpoint.dout, data)
-
 
1181
    
-
 
1182
    def din(self, size):
-
 
1183
        self.logger.debug("Receiving data on the din endpoint with the size %d\n" % size)
-
 
1184
        if self.packetsizelimit.din and size > self.packetsizelimit.din:
-
 
1185
            raise ReceiveError("Packet too big")
-
 
1186
        return self.receive(self.endpoint.din, size)
-
 
1187
 
-
 
1188
 
1120
 
1189
if __name__ == "__main__":
1121
if __name__ == "__main__":
1190
    from misc import Logger
1122
    from misc import Logger
1191
    logger = Logger()
1123
    logger = Logger()
1192
    
1124