Subversion Repositories freemyipod

Rev

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

Rev 399 Rev 401
Line 24... Line 24...
24
import sys
24
import sys
25
import struct
25
import struct
26
import usb.core
26
import usb.core
27
import libembiosdata
27
import libembiosdata
28
 
28
 
29
from misc import Bunch, Error, gethwname
29
from misc import Logger, Bunch, Error, gethwname
30
from functools import wraps
30
from functools import wraps
31
 
31
 
32
class ArgumentError(Error):
32
class ArgumentError(Error):
33
    pass
33
    pass
34
 
34
 
Line 90... Line 90...
90
        device timeout for the duration of the function.
90
        device timeout for the duration of the function.
91
        It also adds a "timeout" argument to every function to access this
91
        It also adds a "timeout" argument to every function to access this
92
        feature from external. So DON'T EVER use a parameter called 'timeout'
92
        feature from external. So DON'T EVER use a parameter called 'timeout'
93
        in your commands. Variables are ok.
93
        in your commands. Variables are ok.
94
    """
94
    """
95
    def __init__(self):
95
    def __init__(self, loglevel = 2, logtarget = "stdout", logfile = "tools.log"):
-
 
96
        self.logger = Logger(loglevel, logtarget, logfile)
-
 
97
        self.logger.debug("Initializing Embios object\n")
96
        self.lib = Lib()
98
        self.lib = Lib(self.logger)
97
        
99
        
98
        self.getversioninfo()
100
        self.getversioninfo()
99
        self.getpacketsizeinfo()
101
        self.getpacketsizeinfo()
100
        self.getusermemrange()
102
        self.getusermemrange()
101
    
103
    
Line 150... Line 152...
150
        resp = self.lib.monitorcommand(struct.pack("IIII", 1, 0, 0, 0), "IBBBBI", ("revision", "majorv", "minorv", "patchv", "swtypeid", "hwtypeid"))
152
        resp = self.lib.monitorcommand(struct.pack("IIII", 1, 0, 0, 0), "IBBBBI", ("revision", "majorv", "minorv", "patchv", "swtypeid", "hwtypeid"))
151
        self.lib.dev.version.revision = resp.revision
153
        self.lib.dev.version.revision = resp.revision
152
        self.lib.dev.version.majorv = resp.majorv
154
        self.lib.dev.version.majorv = resp.majorv
153
        self.lib.dev.version.minorv = resp.minorv
155
        self.lib.dev.version.minorv = resp.minorv
154
        self.lib.dev.version.patchv = resp.patchv
156
        self.lib.dev.version.patchv = resp.patchv
-
 
157
        self.logger.debug("Device Software Type ID = " + str(resp.swtypeid) + "\n")
155
        self.lib.dev.swtypeid = resp.swtypeid
158
        self.lib.dev.swtypeid = resp.swtypeid
-
 
159
        self.logger.debug("Device Hardware Type ID = " + str(resp.hwtypeid) + "\n")
156
        self.lib.dev.hwtypeid = resp.hwtypeid
160
        self.lib.dev.hwtypeid = resp.hwtypeid
157
        return resp
161
        return resp
158
    
162
    
159
    @command()
163
    @command()
160
    def getpacketsizeinfo(self):
164
    def getpacketsizeinfo(self):
161
        """ This returns the emBIOS max packet size information.
165
        """ This returns the emBIOS max packet size information.
162
            It also sets the properties of the device object accordingly.
166
            It also sets the properties of the device object accordingly.
163
        """
167
        """
164
        resp = self.lib.monitorcommand(struct.pack("IIII", 1, 1, 0, 0), "HHII", ("coutmax", "cinmax", "doutmax", "dinmax"))
168
        resp = self.lib.monitorcommand(struct.pack("IIII", 1, 1, 0, 0), "HHII", ("coutmax", "cinmax", "doutmax", "dinmax"))
-
 
169
        self.logger.debug("Device cout packet size limit = " + str(resp.coutmax) + "\n")
165
        self.lib.dev.packetsizelimit.cout = resp.coutmax
170
        self.lib.dev.packetsizelimit.cout = resp.coutmax
-
 
171
        self.logger.debug("Device cin packet size limit = " + str(resp.cinmax) + "\n")
166
        self.lib.dev.packetsizelimit.cin = resp.cinmax
172
        self.lib.dev.packetsizelimit.cin = resp.cinmax
-
 
173
        self.logger.debug("Device din packet size limit = " + str(resp.doutmax) + "\n")
167
        self.lib.dev.packetsizelimit.din = resp.dinmax
174
        self.lib.dev.packetsizelimit.din = resp.dinmax
-
 
175
        self.logger.debug("Device dout packet size limit = " + str(resp.dinmax) + "\n")
168
        self.lib.dev.packetsizelimit.dout = resp.doutmax
176
        self.lib.dev.packetsizelimit.dout = resp.doutmax
169
        return resp
177
        return resp
170
    
178
    
171
    @command()
179
    @command()
172
    def getusermemrange(self):
180
    def getusermemrange(self):
173
        """ This returns the memory range the user has access to. """
181
        """ This returns the memory range the user has access to. """
174
        resp = self.lib.monitorcommand(struct.pack("IIII", 1, 2, 0, 0), "III", ("lower", "upper", None))
182
        resp = self.lib.monitorcommand(struct.pack("IIII", 1, 2, 0, 0), "III", ("lower", "upper", None))
-
 
183
        self.logger.debug("Device user memory = 0x%x - 0x%x\n" % (resp.lower, resp.upper))
175
        self.lib.dev.usermem.lower = resp.lower
184
        self.lib.dev.usermem.lower = resp.lower
176
        self.lib.dev.usermem.upper = resp.upper
185
        self.lib.dev.usermem.upper = resp.upper
177
        return resp
186
        return resp
178
    
187
    
179
    @command()
188
    @command()
Line 800... Line 809...
800
            raise DeviceError("disk_unmount(volume=%d) failed with RC=0x%08X, errno=%d" % (volume, result.rc, self.errno()))
809
            raise DeviceError("disk_unmount(volume=%d) failed with RC=0x%08X, errno=%d" % (volume, result.rc, self.errno()))
801
        return result.rc
810
        return result.rc
802
    
811
    
803
 
812
 
804
class Lib(object):
813
class Lib(object):
805
    def __init__(self):
814
    def __init__(self, logger):
-
 
815
        self.logger = logger
-
 
816
        self.logger.debug("Initializing Lib object\n")
806
        self.idVendor = 0xFFFF
817
        self.idVendor = 0xFFFF
807
        self.idProduct = 0xE000
818
        self.idProduct = 0xE000
808
        
819
        
809
        self.headersize = 0x10
820
        self.headersize = 0x10
810
        
821
        
811
        self.connect()
822
        self.connect()
812
    
823
    
813
    def connect(self):
824
    def connect(self):
814
        self.dev = Dev(self.idVendor, self.idProduct)
825
        self.dev = Dev(self.idVendor, self.idProduct, self.logger)
815
        self.connected = True
826
        self.connected = True
816
    
827
    
817
    def monitorcommand(self, cmd, rcvdatatypes=None, rcvstruct=None):
828
    def monitorcommand(self, cmd, rcvdatatypes=None, rcvstruct=None):
-
 
829
        self.logger.debug("Sending monitorcommand\n")
818
        writelen = self.dev.cout(cmd)
830
        writelen = self.dev.cout(cmd)
819
        if rcvdatatypes:
831
        if rcvdatatypes:
820
            rcvdatatypes = "I" + rcvdatatypes # add the response
832
            rcvdatatypes = "I" + rcvdatatypes # add the response
821
            data = self.dev.cin(struct.calcsize(rcvdatatypes))
833
            data = self.dev.cin(struct.calcsize(rcvdatatypes))
822
            data = struct.unpack(rcvdatatypes, data)
834
            data = struct.unpack(rcvdatatypes, data)
823
            response = data[0]
835
            response = data[0]
824
            if libembiosdata.responsecodes[response] == "ok":
836
            if libembiosdata.responsecodes[response] == "ok":
-
 
837
                self.logger.debug("Response: OK\n")
825
                if rcvstruct:
838
                if rcvstruct:
826
                    datadict = Bunch()
839
                    datadict = Bunch()
827
                    counter = 1 # start with 1, 0 is the id
840
                    counter = 1 # start with 1, 0 is the id
828
                    for item in rcvstruct:
841
                    for item in rcvstruct:
829
                        if item != None: # else the data is undefined
842
                        if item != None: # else the data is undefined
Line 831... Line 844...
831
                        counter += 1
844
                        counter += 1
832
                    return datadict
845
                    return datadict
833
                else:
846
                else:
834
                    return data
847
                    return data
835
            elif libembiosdata.responsecodes[response] == "unsupported":
848
            elif libembiosdata.responsecodes[response] == "unsupported":
-
 
849
                self.logger.debug("Response: UNSUPPORTED\n")
836
                raise DeviceError("The device does not support this command.")
850
                raise DeviceError("The device does not support this command.")
837
            elif libembiosdata.responsecodes[response] == "invalid":
851
            elif libembiosdata.responsecodes[response] == "invalid":
-
 
852
                self.logger.debug("Response: INVALID\n")
838
                raise DeviceError("Invalid command! This should NOT happen!")
853
                raise DeviceError("Invalid command! This should NOT happen!")
839
            elif libembiosdata.responsecodes[response] == "busy":
854
            elif libembiosdata.responsecodes[response] == "busy":
-
 
855
                self.logger.debug("Response: BUSY\n")
840
                raise DeviceError("Device busy")
856
                raise DeviceError("Device busy")
-
 
857
            else:
-
 
858
                self.logger.debug("Response: UNKOWN\n")
-
 
859
                raise DeviceError("Invalid response! This should NOT happen!")
841
        else:
860
        else:
842
            return writelen
861
            return writelen
843
 
862
 
844
 
863
 
845
class Dev(object):
864
class Dev(object):
846
    def __init__(self, idVendor, idProduct):
865
    def __init__(self, idVendor, idProduct, logger):
847
        self.idVendor = idVendor
866
        self.idVendor = idVendor
848
        self.idProduct = idProduct
867
        self.idProduct = idProduct
849
        
868
        
-
 
869
        self.logger = logger
-
 
870
        self.logger.debug("Initializing Dev object\n")
-
 
871
        
850
        self.interface = 0
872
        self.interface = 0
851
        self.timeout = 100
873
        self.timeout = 100
852
 
874
 
853
        self.connect()
875
        self.connect()
854
        self.findEndpoints()
876
        self.findEndpoints()
855
        
877
        
-
 
878
        self.logger.debug("Successfully connected to device\n")
856
        
879
        
857
        # Device properties
880
        # Device properties
858
        self.packetsizelimit = Bunch()
881
        self.packetsizelimit = Bunch()
859
        self.packetsizelimit.cout = None
882
        self.packetsizelimit.cout = None
860
        self.packetsizelimit.cin = None
883
        self.packetsizelimit.cin = None
Line 875... Line 898...
875
    
898
    
876
    def __del__(self):
899
    def __del__(self):
877
        self.disconnect()
900
        self.disconnect()
878
    
901
    
879
    def findEndpoints(self):
902
    def findEndpoints(self):
-
 
903
        self.logger.debug("Searching for device endpoints:\n")
880
        epcounter = 0
904
        epcounter = 0
881
        self.endpoint = Bunch()
905
        self.endpoint = Bunch()
882
        for cfg in self.dev:
906
        for cfg in self.dev:
883
            for intf in cfg:
907
            for intf in cfg:
884
                for ep in intf:
908
                for ep in intf:
885
                    if epcounter == 0:
909
                    if epcounter == 0:
-
 
910
                        self.logger.debug("Found cout endpoint at 0x%x\n" % ep.bEndpointAddress)
886
                        self.endpoint.cout = ep.bEndpointAddress
911
                        self.endpoint.cout = ep.bEndpointAddress
887
                    elif epcounter == 1:
912
                    elif epcounter == 1:
-
 
913
                        self.logger.debug("Found cin endpoint at 0x%x\n" % ep.bEndpointAddress)
888
                        self.endpoint.cin = ep.bEndpointAddress
914
                        self.endpoint.cin = ep.bEndpointAddress
889
                    elif epcounter == 2:
915
                    elif epcounter == 2:
-
 
916
                        self.logger.debug("Found dout endpoint at 0x%x\n" % ep.bEndpointAddress)
890
                        self.endpoint.dout = ep.bEndpointAddress
917
                        self.endpoint.dout = ep.bEndpointAddress
891
                    elif epcounter == 3:
918
                    elif epcounter == 3:
-
 
919
                        self.logger.debug("Found din endpoint at 0x%x\n" % ep.bEndpointAddress)
892
                        self.endpoint.din = ep.bEndpointAddress
920
                        self.endpoint.din = ep.bEndpointAddress
893
                    epcounter += 1
921
                    epcounter += 1
894
        if epcounter <= 3:
922
        if epcounter <= 3:
895
            raise DeviceError("Not all endpoints found in the descriptor. Only "+str(epcounter)+" found, we need 4")
923
            raise DeviceError("Not all endpoints found in the descriptor. Only "+str(epcounter)+" found, we need 4")
896
    
924
    
897
    def connect(self):
925
    def connect(self):
-
 
926
        self.logger.debug("Looking for emBIOS device\n")
898
        self.dev = usb.core.find(idVendor=self.idVendor, idProduct=self.idProduct)
927
        self.dev = usb.core.find(idVendor=self.idVendor, idProduct=self.idProduct)
899
        if self.dev is None:
928
        if self.dev is None:
900
            raise DeviceNotFoundError()
929
            raise DeviceNotFoundError()
-
 
930
        self.logger.debug("Device Found!\n")
-
 
931
        self.logger.debug("Setting first configuration\n")
901
        self.dev.set_configuration()
932
        self.dev.set_configuration()
902
    
933
    
903
    def disconnect(self):
934
    def disconnect(self):
904
        pass
935
        pass
905
    
936
    
Line 914... Line 945...
914
        if len(read) != size:
945
        if len(read) != size:
915
            raise ReceiveError("Requested size and read size don't match!")
946
            raise ReceiveError("Requested size and read size don't match!")
916
        return read
947
        return read
917
    
948
    
918
    def cout(self, data):
949
    def cout(self, data):
-
 
950
        self.logger.debug("Sending data to cout endpoint with the size " + str(len(data)) + "\n")
919
        if self.packetsizelimit.cout and len(data) > self.packetsizelimit.cout:
951
        if self.packetsizelimit.cout and len(data) > self.packetsizelimit.cout:
920
            raise SendError("Packet too big")
952
            raise SendError("Packet too big")
921
        return self.send(self.endpoint.cout, data)
953
        return self.send(self.endpoint.cout, data)
922
    
954
    
923
    def cin(self, size):
955
    def cin(self, size):
-
 
956
        self.logger.debug("Receiving data on the cin endpoint with the size " + str(size) + "\n")
924
        if self.packetsizelimit.cin and size > self.packetsizelimit.cin:
957
        if self.packetsizelimit.cin and size > self.packetsizelimit.cin:
925
            raise ReceiveError("Packet too big")
958
            raise ReceiveError("Packet too big")
926
        return self.receive(self.endpoint.cin, size)
959
        return self.receive(self.endpoint.cin, size)
927
    
960
    
928
    def dout(self, data):
961
    def dout(self, data):
-
 
962
        self.logger.debug("Sending data to cout endpoint with the size " + str(len(data)) + "\n")
929
        if self.packetsizelimit.dout and len(data) > self.packetsizelimit.dout:
963
        if self.packetsizelimit.dout and len(data) > self.packetsizelimit.dout:
930
            raise SendError("Packet too big")
964
            raise SendError("Packet too big")
931
        return self.send(self.endpoint.dout, data)
965
        return self.send(self.endpoint.dout, data)
932
    
966
    
933
    def din(self, size):
967
    def din(self, size):
-
 
968
        self.logger.debug("Receiving data on the din endpoint with the size " + str(size) + "\n")
934
        if self.packetsizelimit.din and size > self.packetsizelimit.din:
969
        if self.packetsizelimit.din and size > self.packetsizelimit.din:
935
            raise ReceiveError("Packet too big")
970
            raise ReceiveError("Packet too big")
936
        return self.receive(self.endpoint.din, size)
971
        return self.receive(self.endpoint.din, size)
937
 
972
 
938
 
973