Subversion Repositories freemyipod

Rev

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

Rev 949 Rev 951
Line 126... Line 126...
126
            in the memory of the device. Can handle up to 0xff0 bytes.
126
            in the memory of the device. Can handle up to 0xff0 bytes.
127
        """
127
        """
128
        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))
129
    
129
    
130
    @command()
130
    @command()
-
 
131
    def _readmem_bulk(self, addr, size):
-
 
132
        """ Reads the memory from location 'addr' with size 'size'
-
 
133
            from the device. Can handle unlimited amounts of bytes,
-
 
134
            however the address and size should be cacheline aligned.
-
 
135
        """
-
 
136
        return self.lib.recvbulk(struct.pack("<III", 1, addr, size), size)
-
 
137
    
-
 
138
    @command()
-
 
139
    def _writemem_bulk(self, addr, data):
-
 
140
        """ Writes the data in 'data' to the location 'addr'
-
 
141
            in the memory of the device. Can handle unlimited amounts of bytes,
-
 
142
            however the address and size should be cacheline aligned.
-
 
143
 
-
 
144
        """
-
 
145
        return self.lib.sendbulk(struct.pack("<III", 1, addr, len(data)), data)
-
 
146
    
-
 
147
    @command()
131
    def getversioninfo(self):
148
    def getversioninfo(self):
132
        """ This returns the emCORE version and device information. """
149
        """ This returns the emCORE version and device information. """
133
        resp = self.lib.monitorcommand(struct.pack("<IIII", 1, 0, 0, 0), "IBBBBI", ("revision", "majorv", "minorv", "patchv", "swtypeid", "hwtypeid"))
150
        resp = self.lib.monitorcommand(struct.pack("<IIII", 1, 0, 0, 0), "IBBBBI", ("revision", "majorv", "minorv", "patchv", "swtypeid", "hwtypeid"))
134
        self.lib.dev.version.revision = resp.revision
151
        self.lib.dev.version.revision = resp.revision
135
        self.lib.dev.version.majorv = resp.majorv
152
        self.lib.dev.version.majorv = resp.majorv
Line 171... Line 188...
171
        """ Reads the memory from location 'addr' with size 'size'
188
        """ Reads the memory from location 'addr' with size 'size'
172
            from the device. This takes care of splitting long requests.
189
            from the device. This takes care of splitting long requests.
173
        """
190
        """
174
        data = b""
191
        data = b""
175
        self.logger.debug("Downloading %d bytes from 0x%X\n" % (size, addr))
192
        self.logger.debug("Downloading %d bytes from 0x%X\n" % (size, addr))
-
 
193
        try:
-
 
194
            if self.lib.bulkin and size > 0x800:
-
 
195
                if addr & 63:
-
 
196
                    align = 64 - (addr & 63)
-
 
197
                    data += self._readmem(addr, align)
-
 
198
                    addr += align
-
 
199
                    size -= align
-
 
200
                align = size & 63
-
 
201
                size -= align
-
 
202
                data += self._readmem_bulk(addr, size)
-
 
203
                addr += size
-
 
204
                size = align
-
 
205
        except: self.logger.warn("Bulk read interface failed, falling back to slow reads\n")
176
        while size > 0:
206
        while size > 0:
177
            readsize = min(size, 0xf00)
207
            readsize = min(size, 0xf00)
178
            data += self._readmem(addr, readsize)
208
            data += self._readmem(addr, readsize)
179
            addr += readsize
209
            addr += readsize
180
            size -= readsize
210
            size -= readsize
Line 186... Line 216...
186
            in the memory of the device. This takes care of splitting long requests.
216
            in the memory of the device. This takes care of splitting long requests.
187
        """
217
        """
188
        size = len(data)
218
        size = len(data)
189
        self.logger.debug("Uploading %d bytes to 0x%X\n" % (size, addr))
219
        self.logger.debug("Uploading %d bytes to 0x%X\n" % (size, addr))
190
        offset = 0
220
        offset = 0
-
 
221
        try:
-
 
222
            if self.lib.bulkin and size > 0x800:
-
 
223
                if addr & 63:
-
 
224
                    align = 64 - (addr & 63)
-
 
225
                    self._writemem(addr, data[offset:offset+align])
-
 
226
                    offset += align
-
 
227
                    addr += align
-
 
228
                    size -= align
-
 
229
                align = size & 63
-
 
230
                size -= align
-
 
231
                self._writemem_bulk(addr, data[offset:offset+size])
-
 
232
                offset += size
-
 
233
                addr += size
-
 
234
                size = align
-
 
235
        except: self.logger.warn("Bulk write interface failed, falling back to slow writes\n")
191
        while size > 0:
236
        while size > 0:
192
            writesize = min(size, 0xf00)
237
            writesize = min(size, 0xf00)
193
            self._writemem(addr, data[offset:offset+writesize])
238
            self._writemem(addr, data[offset:offset+writesize])
194
            offset += writesize
239
            offset += writesize
195
            addr += writesize
240
            addr += writesize
Line 1017... Line 1062...
1017
        self.connect()
1062
        self.connect()
1018
    
1063
    
1019
    def connect(self):
1064
    def connect(self):
1020
        self.dev = Dev(self.idVendor, self.idProduct, self.idProductMask, self.logger)
1065
        self.dev = Dev(self.idVendor, self.idProduct, self.idProductMask, self.logger)
1021
        self.connected = True
1066
        self.connected = True
-
 
1067
        self.bulkout = True if self.dev.bulkout else False
-
 
1068
        self.bulkin = True if self.dev.bulkin else False
1022
    
1069
    
1023
    def monitorcommand(self, cmd, rcvdatatypes=None, rcvstruct=None):
1070
    def monitorcommand(self, cmd, rcvdatatypes=None, rcvstruct=None):
1024
        self.logger.debug("Sending monitorcommand [0x%s]\n" % base64.b16encode(cmd[3::-1]).decode("ascii"))
1071
        self.logger.debug("Sending monitorcommand [0x%s]\n" % base64.b16encode(cmd[3::-1]).decode("ascii"))
1025
        writelen = self.dev.send(cmd)
1072
        writelen = self.dev.send(cmd)
1026
        if rcvdatatypes:
1073
        if rcvdatatypes:
Line 1053... Line 1100...
1053
            elif response == "BUSY":
1100
            elif response == "BUSY":
1054
                self.logger.debug("Response: BUSY\n")
1101
                self.logger.debug("Response: BUSY\n")
1055
                raise DeviceError("Device busy")
1102
                raise DeviceError("Device busy")
1056
        else:
1103
        else:
1057
            return writelen
1104
            return writelen
-
 
1105
            
-
 
1106
    def sendbulk(self, cmd, data):
-
 
1107
        self.logger.debug("Sending bulk command [0x%s]\n" % base64.b16encode(cmd[3::-1]).decode("ascii"))
-
 
1108
        return self.dev.sendbulk(cmd, data)
-
 
1109
            
-
 
1110
    def recvbulk(self, cmd, size):
-
 
1111
        self.logger.debug("Receiving bulk command [0x%s]\n" % base64.b16encode(cmd[3::-1]).decode("ascii"))
-
 
1112
        return self.dev.recvbulk(cmd, size)
1058
 
1113
 
1059
 
1114
 
1060
class Dev(object):
1115
class Dev(object):
1061
    def __init__(self, idVendor, idProduct, idProductMask, logger):
1116
    def __init__(self, idVendor, idProduct, idProductMask, logger):
1062
        self.idVendor = idVendor
1117
        self.idVendor = idVendor
Line 1066... Line 1121...
1066
        self.logger = logger
1121
        self.logger = logger
1067
        self.logger.debug("Initializing Dev object\n")
1122
        self.logger.debug("Initializing Dev object\n")
1068
        
1123
        
1069
        self.dev = None
1124
        self.dev = None
1070
        self.interface = None
1125
        self.interface = None
-
 
1126
        self.bulkout = None
-
 
1127
        self.bulkin = None
1071
        self.claimed = False
1128
        self.claimed = False
1072
        self.timeout = 1000
1129
        self.timeout = 1000
1073
        
1130
        
1074
        self.connect()
1131
        self.connect()
1075
        
1132
        
Line 1106... Line 1163...
1106
        for cfg in self.dev:
1163
        for cfg in self.dev:
1107
            for intf in cfg:
1164
            for intf in cfg:
1108
                self.logger.debug("%02x:%02x:%02x\n" % (intf.bInterfaceClass, intf.bInterfaceSubClass, intf.bInterfaceProtocol))
1165
                self.logger.debug("%02x:%02x:%02x\n" % (intf.bInterfaceClass, intf.bInterfaceSubClass, intf.bInterfaceProtocol))
1109
                if intf.bInterfaceClass == 0xff and intf.bInterfaceSubClass == 0 and intf.bInterfaceProtocol == 0:
1166
                if intf.bInterfaceClass == 0xff and intf.bInterfaceSubClass == 0 and intf.bInterfaceProtocol == 0:
1110
                    self.interface = intf.bInterfaceNumber
1167
                    self.interface = intf.bInterfaceNumber
-
 
1168
                    for ep in intf:
-
 
1169
                        if not ep.bEndpointAddress & 0x80:
-
 
1170
                            self.bulkout = ep
-
 
1171
                            break
-
 
1172
                    for ep in intf:
-
 
1173
                        if ep.bEndpointAddress & 0x80:
-
 
1174
                            self.bulkin = ep
-
 
1175
                            break
1111
                    break
1176
                    break
1112
        if self.interface is None:
1177
        if self.interface is None:
1113
            raise DeviceNotFoundError()
1178
            raise DeviceNotFoundError()
1114
        self.logger.debug("Debugger interface found!\n")
1179
        self.logger.debug("Debugger interface found!\n")
1115
        self.logger.debug("Claiming interface...\n")
1180
        self.logger.debug("Claiming interface...\n")
Line 1121... Line 1186...
1121
        self.claimed = False
1186
        self.claimed = False
1122
    
1187
    
1123
    def send(self, data):
1188
    def send(self, data):
1124
        if len(data) > 0x1000: raise DeviceError("Attempting to send a message that is too big!")
1189
        if len(data) > 0x1000: raise DeviceError("Attempting to send a message that is too big!")
1125
        size = self.dev.ctrl_transfer(0x41, 0x00, 0, self.interface, data, self.timeout)
1190
        size = self.dev.ctrl_transfer(0x41, 0x00, 0, self.interface, data, self.timeout)
1126
        if size != len(data):
-
 
1127
            raise SendError("Not all data was written!")
1191
        if size != len(data): raise SendError("Not all data was written!")
1128
        return len
1192
        return size
1129
    
1193
    
1130
    def receive(self, size):
1194
    def receive(self, size):
1131
        if size > 0x1000: raise DeviceError("Attempting to receive a message that is too big!")
1195
        if size > 0x1000: raise DeviceError("Attempting to receive a message that is too big!")
1132
        read = self.dev.ctrl_transfer(0xc1, 0x00, 0, self.interface, size, self.timeout)
1196
        data = self.dev.ctrl_transfer(0xc1, 0x00, 0, self.interface, size, self.timeout)
-
 
1197
        if len(data) != size: raise ReceiveError("Requested size and read size don't match!")
-
 
1198
        return data
-
 
1199
    
-
 
1200
    def sendbulk(self, cmd, data):
-
 
1201
        size = self.dev.ctrl_transfer(0x42, 0x00, 0, self.bulkout.bEndpointAddress, cmd, self.timeout)
-
 
1202
        if size != len(cmd):
-
 
1203
            raise SendError("Bulk send command could not be fully sent (%d of %d)!" % (size, len(cmd)))
-
 
1204
        size = self.bulkout.write(data, self.timeout)
-
 
1205
        if size != len(data):
-
 
1206
            raise SendError("Bulk data could not be fully sent (%d of %d)!" % (size, len(data)))
-
 
1207
        return size
-
 
1208
    
-
 
1209
    def recvbulk(self, cmd, size):
-
 
1210
        size = self.dev.ctrl_transfer(0x42, 0x00, 0, self.bulkin.bEndpointAddress, cmd, self.timeout)
-
 
1211
        if size != len(cmd):
-
 
1212
            raise ReceiveError("Bulk receive command could not be fully sent (%d of %d)!" % (size, len(cmd)))
-
 
1213
        data = self.bulkin.read(size, self.timeout)
1133
        if len(read) != size:
1214
        if len(data) != size:
1134
            raise ReceiveError("Requested size and read size don't match!")
1215
            raise SendError("Bulk data could not be fully received (%d of %d)!" % (len(cmd), size))
1135
        return read
1216
        return data
1136
    
1217
    
1137
 
1218
 
1138
if __name__ == "__main__":
1219
if __name__ == "__main__":
1139
    from misc import Logger
1220
    from misc import Logger
1140
    logger = Logger()
1221
    logger = Logger()