Example #1
0
    def sendpbcommand(self, request, responseclass):
        self.setmode(self.MODEBREW)
        buffer = prototypes.buffer()
        request.writetobuffer(buffer,
                              logtitle="audiovox cdm8900 phonebook request")
        data = buffer.getvalue()
        data = common.pppescape(data +
                                common.crcs(data)) + common.pppterminator
        first = data[0]
        try:
            data = self.comm.writethenreaduntil(data,
                                                False,
                                                common.pppterminator,
                                                logreaduntilsuccess=False)
        except com_phone.modeignoreerrortypes:
            self.mode = self.MODENONE
            self.raisecommsdnaexception("manipulating the phonebook")
        self.comm.success = True

        origdata = data
        # sometimes there is junk at the begining, eg if the user
        # turned off the phone and back on again.  So if there is more
        # than one 7e in the escaped data we should start after the
        # second to last one
        d = data.rfind(common.pppterminator, 0, -1)
        if d >= 0:
            self.log(
                "Multiple PB packets in data - taking last one starting at " +
                ` d + 1 `)
            self.logdata("Original pb data", origdata, None)
            data = data[d + 1:]

        # turn it back to normal
        data = common.pppunescape(data)

        # sometimes there is other crap at the begining
        d = data.find(first)
        if d > 0:
            self.log("Junk at begining of pb packet, data at " + ` d `)
            self.logdata("Original pb data", origdata, None)
            self.logdata("Working on pb data", data, None)
            data = data[d:]
        # take off crc and terminator
        crc = data[-3:-1]
        data = data[:-3]
        if common.crcs(data) != crc:
            self.logdata("Original pb data", origdata, None)
            self.logdata("Working on pb data", data, None)
            raise common.CommsDataCorruption(
                "Audiovox phonebook packet failed CRC check", self.desc)

        # parse data
        buffer = prototypes.buffer(data)
        res = responseclass()
        res.readfrombuffer(buffer, logtitle="Audiovox phonebook response")
        return res
    def sendpbcommand(self, request, responseclass):
        self.setmode(self.MODEBREW)
        buffer=prototypes.buffer()
        request.writetobuffer(buffer, logtitle="audiovox cdm8900 phonebook request")
        data=buffer.getvalue()
        data=common.pppescape(data+common.crcs(data))+common.pppterminator
        first=data[0]
        try:
            data=self.comm.writethenreaduntil(data, False, common.pppterminator, logreaduntilsuccess=False)
        except com_phone.modeignoreerrortypes:
            self.mode=self.MODENONE
            self.raisecommsdnaexception("manipulating the phonebook")
        self.comm.success=True

        origdata=data
        # sometimes there is junk at the begining, eg if the user
        # turned off the phone and back on again.  So if there is more
        # than one 7e in the escaped data we should start after the
        # second to last one
        d=data.rfind(common.pppterminator,0,-1)
        if d>=0:
            self.log("Multiple PB packets in data - taking last one starting at "+`d+1`)
            self.logdata("Original pb data", origdata, None)
            data=data[d+1:]

        # turn it back to normal
        data=common.pppunescape(data)

        # sometimes there is other crap at the begining
        d=data.find(first)
        if d>0:
            self.log("Junk at begining of pb packet, data at "+`d`)
            self.logdata("Original pb data", origdata, None)
            self.logdata("Working on pb data", data, None)
            data=data[d:]
        # take off crc and terminator
        crc=data[-3:-1]
        data=data[:-3]
        if common.crcs(data)!=crc:
            self.logdata("Original pb data", origdata, None)
            self.logdata("Working on pb data", data, None)
            raise common.CommsDataCorruption("Audiovox phonebook packet failed CRC check", self.desc)
        
        # parse data
        buffer=prototypes.buffer(data)
        res=responseclass()
        res.readfrombuffer(buffer, logtitle="Audiovox phonebook response")
        return res
 def sendpbcommand(self, request, responseclass, callsetmode=True):
     if callsetmode:
         self.setmode(self.MODEPHONEBOOK)
     buffer=prototypes.buffer()
     request.header.sequence=self.pbseq
     self.pbseq+=1
     if self.pbseq>0xff:
         self.pbseq=0
     request.writetobuffer(buffer, logtitle="lg phonebook request")
     data=buffer.getvalue()
     data=common.pppescape(data+common.crcs(data))+common.pppterminator
     firsttwo=data[:2]
     try:
         data=self.comm.writethenreaduntil(data, False, common.pppterminator, logreaduntilsuccess=False)
     except com_phone.modeignoreerrortypes:
         self.mode=self.MODENONE
         self.raisecommsdnaexception("manipulating the phonebook")
     self.comm.success=True
     origdata=data
     d=data.rfind(common.pppterminator,0,-1)
     if d>=0:
         self.log("Multiple LG packets in data - taking last one starting at "+`d+1`)
         self.logdata("Original LG data", origdata, None)
         data=data[d+1:]
     data=common.pppunescape(data)
     crc=data[-3:-1]
     data=data[:-3]
     calccrc=common.crcs(data)
     if calccrc!=crc:
         d=data.find(firsttwo)
         if d>0:
             self.log("Junk at begining of LG packet, data at "+`d`)
             self.logdata("Original LG data", origdata, None)
             self.logdata("Working on LG data", data, None)
             data=data[d:]
             calccrc=common.crcs(data)
         if calccrc!=crc:
             self.logdata("Original LG data", origdata, None)
             self.logdata("Working on LG data", data, None)
             raise common.CommsDataCorruption("LG packet failed CRC check", self.desc)
     if ord(data[0])==0x13:
         raise com_brew.BrewBadBrewCommandException()
     if ord(data[0])==0x14:
         raise com_brew.BrewMalformedBrewCommandException()
     buffer=prototypes.buffer(data)
     res=responseclass()
     res.readfrombuffer(buffer, logtitle="lg phonebook response")
     return res
 def sendpbcommand(self, request, responseclass):
     self.setmode(self.MODEBREW)
     buffer=prototypes.buffer()
     request.writetobuffer(buffer)
     data=buffer.getvalue()
     self.logdata("toshiba vm4050 phonebook request", data, request)
     data=common.pppescape(data+common.crcs(data))+common.pppterminator
     first=data[0]
     try:
         data=self.comm.writethenreaduntil(data, False, common.pppterminator, logreaduntilsuccess=False)
     except com_phone.modeignoreerrortypes:
         self.mode=self.MODENONE
         self.raisecommsdnaexception("manipulating the phonebook")
     self.comm.success=True
     origdata=data
     d=data.rfind(common.pppterminator,0,-1)
     if d>=0:
         self.log("Multiple PB packets in data - taking last one starting at "+`d+1`)
         self.logdata("Original pb data", origdata, None)
         data=data[d+1:]
     data=common.pppunescape(data)
     d=data.find(first)
     if d>0:
         self.log("Junk at begining of pb packet, data at "+`d`)
         self.logdata("Original pb data", origdata, None)
         self.logdata("Working on pb data", data, None)
         data=data[d:]
     crc=data[-3:-1]
     data=data[:-3]
     if common.crcs(data)!=crc:
         self.logdata("Original pb data", origdata, None)
         self.logdata("Working on pb data", data, None)
         raise common.CommsDataCorruption("toshiba phonebook packet failed CRC check", self.desc)
     self.logdata("toshiba phonebook response", data, responseclass)
     buffer=prototypes.buffer(data)
     res=responseclass()
     res.readfrombuffer(buffer)
     return res
 def readfrombuffer(self, buf):
     self._bufferstartoffset=buf.getcurrentoffset()
     if self._terminator is None:
         self._value=buf.getremainingbytes()
     else:
         self._value=chr(buf.getnextbyte())
         if self._value == ',':
             self._value = ''
         else:
             inquotes=False
             if self._quotechar is not None:
                 if self._value[0]==chr(self._quotechar):
                     inquotes=True
             while buf.hasmore():
                 self._value+=chr(buf.getnextbyte())
                 if inquotes:
                     if self._value[-1]==chr(self._quotechar):
                         inquotes=False
                 else:
                     if self._value[-1]==chr(self._terminator):
                         break
             if self._value[-1]==self._terminator:
                 if self._raiseonunterminatedread:
                     raise NotTerminatedException()
             else:
                 self._value=self._value[:-1]
     if self._quotechar is not None and self._value:
         if self._value[0]==chr(self._quotechar) and self._value[-1]==chr(self._quotechar):
             self._value=self._value[1:-1]
         else:
             raise MissingQuotesException()
     if self._readescape:
         self._value=common.pppunescape(self._value)
     if self._constant is not None and self._value!=self._constant:
         raise ValueException("The value read was not the constant")
     self._bufferendoffset=buf.getcurrentoffset()
 def sendbrewcommand(self, request, responseclass, callsetmode=True):
     if callsetmode:
         self.setmode(self.MODEBREW)
     buffer=prototypes.buffer()
     request.writetobuffer(buffer, logtitle="sendbrewcommand")
     data=buffer.getvalue()
     data=common.pppescape(data+common.crcs(data))+common.pppterminator
     firsttwo=data[:2]
     try:
         data=self.comm.writethenreaduntil(data, False, common.pppterminator, logreaduntilsuccess=False) 
     except modeignoreerrortypes:
         self.mode=self.MODENONE
         self.raisecommsdnaexception("manipulating the filesystem")
     self.comm.success=True
     origdata=data
     d=data.rfind(common.pppterminator,0,-1)
     if d>=0:
         self.log("Multiple packets in data - taking last one starting at "+`d+1`)
         self.logdata("Original data", origdata, None)
         data=data[d+1:]
     data=common.pppunescape(data)
     crc=data[-3:-1]
     data=data[:-3]
     calccrc=common.crcs(data)
     if calccrc!=crc:
         d=data.find(firsttwo)
         if d>0:
             self.log("Junk at begining of packet, data at "+`d`)
             self.logdata("Original data", origdata, None)
             self.logdata("Working on data", data, None)
             data=data[d:]
             calccrc=common.crcs(data)
         if calccrc!=crc:
             self.logdata("Original data", origdata, None)
             self.logdata("Working on data", data, None)
             raise common.CommsDataCorruption("Brew packet failed CRC check", self.desc)
     self.logdata("brew response", data, responseclass)
     if firsttwo=="Y\x0c" and data==firsttwo:
         raise common.CommsWrongPort("The port you are using is echoing data back, and is not valid for Brew data.  Most likely you have selected the modem interface when you should be using the diagnostic interface.", self.desc)
     if data[0]=="Y" and data[2]!="\x00":  # Y is 0x59 which is brew command prefix
             err=ord(data[2])
             if err==0x1c:
                 raise BrewNoMoreEntriesException()
             if err==0x08:
                 raise BrewNoSuchDirectoryException()
             if err==0x06:
                 raise BrewNoSuchFileException()
             if err==0x1a:
                 raise BrewBadPathnameException()
             if err==0x0b:
                 raise BrewFileLockedException()
             if err==0x0d:
                 raise BrewNameTooLongException()
             if err==0x07:
                 raise BrewDirectoryExistsException()
             if err==0x04:
                 raise BrewAccessDeniedException()
             if err==0x16:
                 raise BrewFileSystemFullException()
             raise BrewCommandException(err)
     if ord(data[0])==0x13:
         if firsttwo[0]=="Y": # brew command
             raise BrewAccessDeniedException()
         else:
             raise BrewBadBrewCommandException()
     if ord(data[0])==0x14:
         raise BrewMalformedBrewCommandException()
     buffer=prototypes.buffer(data)
     res=responseclass()
     try:
         res.readfrombuffer(buffer, autolog=False)
     except:
         self.log(formatpacketerrorlog("Error decoding response", origdata, data, responseclass))
         raise
     return res
	def sendpbcommand(self, request, responseclass):

        self.setmode(self.MODEBREW)

        buffer=prototypes.buffer()

        request.writetobuffer(buffer)

        data=buffer.getvalue()

        self.logdata("toshiba vm4050 phonebook request", data, request)

        data=common.pppescape(data+common.crcs(data))+common.pppterminator

        first=data[0]

        try:

            data=self.comm.writethenreaduntil(data, False, common.pppterminator, logreaduntilsuccess=False)

        except com_phone.modeignoreerrortypes:

            self.mode=self.MODENONE

            self.raisecommsdnaexception("manipulating the phonebook")

        self.comm.success=True

        origdata=data

        d=data.rfind(common.pppterminator,0,-1)

        if d>=0:

            self.log("Multiple PB packets in data - taking last one starting at "+`d+1`)

            self.logdata("Original pb data", origdata, None)

            data=data[d+1:]

        data=common.pppunescape(data)

        d=data.find(first)

        if d>0:

            self.log("Junk at begining of pb packet, data at "+`d`)

            self.logdata("Original pb data", origdata, None)

            self.logdata("Working on pb data", data, None)

            data=data[d:]

        crc=data[-3:-1]

        data=data[:-3]

        if common.crcs(data)!=crc:

            self.logdata("Original pb data", origdata, None)

            self.logdata("Working on pb data", data, None)

            raise common.CommsDataCorruption("toshiba phonebook packet failed CRC check", self.desc)

        self.logdata("toshiba phonebook response", data, responseclass)

        buffer=prototypes.buffer(data)

        res=responseclass()

        res.readfrombuffer(buffer)

        return res

	def get_detect_data(self, res):

        self.modemmoderequest()

        res['manufacturer']=self.comm.sendatcommand('+GMI')[0]

        res['model']=self.comm.sendatcommand('+GMM')[0]

        res['firmware_version']=self.comm.sendatcommand('+GMR')[0]

        res['esn']=self.comm.sendatcommand('+GSN')[0][2:] 

        return

	def detectphone(coms, likely_ports, res, _module, _log):

        if not likely_ports:

            return None

        for port in likely_ports:

            if not res.has_key(port):

                res[port]={ 'mode_modem': None, 'mode_brew': None,
                            'manufacturer': None, 'model': None,
                            'firmware_version': None, 'esn': None,
                            'firmwareresponse': None }

            try:

                if res[port]['model']:

                    continue

                p=_module.Phone(_log, commport.CommConnection(_log, port, timeout=1))

                res[port]['mode_brew']=p._setmodebrew()

                if res[port]['mode_brew']:

                    p.get_detect_data(res[port])

                p.comm.close()

            except:

                if __debug__:

                    raise

	detectphone=staticmethod(detectphone)
	"Talk to Toshiba VM4050 cell phone"

class  Profile (com_phone.Profile) :
	protocolclass=Phone.protocolclass
	    serialsname=Phone.serialsname
	    phone_manufacturer='Audiovox Communications Corporation'
	    phone_model='VM4050'
	    usbids=((0x05C6, 0x3100, 1), 
        )
	    deviceclasses=("modem",)
	    _supportedsyncs=(
        ('phonebook', 'read', None),         
        ('phonebook', 'write', 'OVERWRITE'), 
        )
	    def convertphonebooktophone(self, helper, data):

        """Converts the data to what will be used by the phone
        @param data: contains the dict returned by getfundamentals
                 as well as where the results go"""

        results={}

        slotsused={}

        for pbentry in data['phonebook']:

            entry=data['phonebook'][pbentry]

            serial1=helper.getserial(entry.get('serials', []), self.serialsname, data['uniqueserial'], 'serial1', -1)

            if(serial1 >= 0 and serial1 < self.protocolclass.NUMSLOTS):

                slotsused[serial1]=1

        lastunused=0 

        for pbentry in data['phonebook']:

            if len(results)==self.protocolclass.NUMSLOTS:

                break

            e={} 

            entry=data['phonebook'][pbentry] 

            try:

                e['name']=helper.getfullname(entry.get('names', []),1,1,36)[0]

                serial1=helper.getserial(entry.get('serials', []), self.serialsname, data['uniqueserial'], 'serial1', -1)

                if(serial1 >= 0 and serial1 < self.protocolclass.NUMSLOTS):

                    e['slot']=serial1

                else:  

                    while(slotsused.has_key(lastunused)):

                        lastunused+=1

                        if(lastunused >= self.protocolclass.NUMSLOTS):

                            helper.add_error_message("Name: %s. Unable to add, phonebook full" % e['name'])

                            raise helper.ConversionFailed()

                    e['slot']=lastunused

                    slotsused[lastunused]=1

                emails=helper.getemails(entry.get('emails', []) ,0,self.protocolclass.MAXEMAILS,self.protocolclass.MAXEMAILLEN)

                e['emails']=helper.filllist(emails, self.protocolclass.MAXEMAILS, "")

                e['web_page']=helper.makeone(helper.geturls(entry.get('urls', []), 0,1,48), "")

                numbers=helper.getnumbers(entry.get('numbers', []),0,self.protocolclass.MAXPHONENUMBERS)

                e['numbertypes']=[]

                e['numbers']=[]

                typesused={}

                for num in numbers:

                    type=num['type']

                    if(typesused.has_key(type)):

                        continue

                    typesused[type]=1

                    for typenum,tnsearch in enumerate(self.protocolclass.numbertypetab):

                        if type==tnsearch:

                            number=self.phonize(num['number'])

                            if len(number)==0:

                                continue

                            if len(number)>self.protocolclass.MAXPHONENUMBERLEN: 

                                number=number[:self.protocolclass.MAXPHONENUMBERLEN]

                            e['numbers'].append(number)

                            e['numbertypes'].append(typenum)

                            break

                e['ringtone']=helper.getringtone(entry.get('ringtones', []), 'call', None)

                e['secret']=helper.getflag(entry.get('flags',[]), 'secret', False)

                results[pbentry]=e

            except helper.ConversionFailed:

                continue

        data['phonebook']=results

        return data

	def phonize(self, str):

        """Convert the phone number into something the phone understands
        All digits, P, T, *, #  are kept, everything else is removed.
        In theory the phone can store a dash in the phonebook, but that
        is not normal."""

        return re.sub("[^0-9PT#*]", "", str)[:self.protocolclass.MAXPHONENUMBERLEN]
 def sendpbcommand(self, request, responseclass, callsetmode=True, writemode=False, numsendretry=0, returnerror=False):
     if writemode:
         numretry=3
     else:
         numretry=0
     if callsetmode:
         self.setmode(self.MODEPHONEBOOK)
     buffer=prototypes.buffer()
     request.writetobuffer(buffer)
     data=buffer.getvalue()
     firsttwo=data[:2]
     data=common.pppescape(data+common.crcs(data))+common.pppterminator
     self.logdata("N400 phonebook request", data, request)
     isendretry=numsendretry
     while isendretry>=0:
         try:
             rdata=self.comm.writethenreaduntil(data, False, common.pppterminator, logreaduntilsuccess=False, numfailures=numretry)
             break
         except com_phone.modeignoreerrortypes:
             if isendretry>0:
                 self.log("Resending request packet...")
                 time.sleep(0.3)
             else:
                 self.comm.success=False
                 self.mode=self.MODENONE
                 self.raisecommsdnaexception("manipulating the phonebook")
             isendretry-=1
     self.comm.success=True
     origdata=rdata
     d=rdata.rfind(common.pppterminator,0,-1)
     if d>=0:
         self.log("Multiple N400 packets in data - taking last one starting at "+`d+1`)
         self.logdata("Original N400 data", origdata, None)
         rdata=rdata[d+1:]
     data=common.pppunescape(rdata)
     d=data.find(firsttwo)
     crc=data[-3:-1]
     crcok=False
     for i in range(0,d+1):
         trydata=data[i:-3]
         if common.crcs(trydata)==crc:
             crcok=True
             break
     if not crcok:
         self.logdata("first two",firsttwo, None)
         self.logdata("Original N400 data", origdata, None)
         self.logdata("Working on N400 data", data, None)
         raise common.CommsDataCorruption("N400 packet failed CRC check", self.desc)
     res=responseclass()
     if d>0:
         if d==i:
             self.log("Junk at beginning of N400 packet, data at "+`d`)
             self.logdata("Original N400 data", origdata, None)
             self.logdata("Working on N400 data", data, None)
         else:
             if returnerror:
                 res=self.protocolclass.sanyoerror()
             else:
                 self.log("N400 Error code "+`ord(data[0])`)
                 self.logdata("Samsung phonebook response", data, None)
                 raise N400CommandException(ord(data[0]))
     data=trydata
     self.logdata("sanyo phonebook response", data, responseclass)
     buffer=prototypes.buffer(data)
     res.readfrombuffer(buffer)
     return res
	def sendpbcommand(self, request, responseclass, callsetmode=True, writemode=False, numsendretry=0, returnerror=False):

        if writemode:

            numretry=3

        else:

            numretry=0

        if callsetmode:

            self.setmode(self.MODEPHONEBOOK)

        buffer=prototypes.buffer()

        request.writetobuffer(buffer)

        data=buffer.getvalue()

        firsttwo=data[:2]

        data=common.pppescape(data+common.crcs(data))+common.pppterminator

        self.logdata("N400 phonebook request", data, request)

        isendretry=numsendretry

        while isendretry>=0:

            try:

                rdata=self.comm.writethenreaduntil(data, False, common.pppterminator, logreaduntilsuccess=False, numfailures=numretry)

                break

            except com_phone.modeignoreerrortypes:

                if isendretry>0:

                    self.log("Resending request packet...")

                    time.sleep(0.3)

                else:

                    self.comm.success=False

                    self.mode=self.MODENONE

                    self.raisecommsdnaexception("manipulating the phonebook")

                isendretry-=1

        self.comm.success=True

        origdata=rdata

        d=rdata.rfind(common.pppterminator,0,-1)

        if d>=0:

            self.log("Multiple N400 packets in data - taking last one starting at "+`d+1`)

            self.logdata("Original N400 data", origdata, None)

            rdata=rdata[d+1:]

        data=common.pppunescape(rdata)

        d=data.find(firsttwo)

        crc=data[-3:-1]

        crcok=False

        for i in range(0,d+1):

            trydata=data[i:-3]

            if common.crcs(trydata)==crc:

                crcok=True

                break

        if not crcok:

            self.logdata("first two",firsttwo, None)

            self.logdata("Original N400 data", origdata, None)

            self.logdata("Working on N400 data", data, None)

            raise common.CommsDataCorruption("N400 packet failed CRC check", self.desc)

        res=responseclass()

        if d>0:

            if d==i:

                self.log("Junk at beginning of N400 packet, data at "+`d`)

                self.logdata("Original N400 data", origdata, None)

                self.logdata("Working on N400 data", data, None)

            else:

                if returnerror:

                    res=self.protocolclass.sanyoerror()

                else:

                    self.log("N400 Error code "+`ord(data[0])`)

                    self.logdata("Samsung phonebook response", data, None)

                    raise N400CommandException(ord(data[0]))

        data=trydata

        self.logdata("sanyo phonebook response", data, responseclass)

        buffer=prototypes.buffer(data)

        res.readfrombuffer(buffer)

        return res

	def getphonebook(self, result):

        pbook={}

        reqname=self.protocolclass.phonebooknamerequest()

        reqnumbers=self.protocolclass.phonebooknumbersrequest()

        count = 0

        for i in range(2, 251):

            reqname.slot=i

            resname=self.sendpbcommand(reqname, self.protocolclass.phonebooknameresponse)

            if resname.entry.nonzeroifused:

                entry={}

                entry['serials']=[ {'sourcetype': self.serialsname,
                          'slot': i,
                          'sourceuniqueid': result['uniqueserial']} ]

                entry['names']=[{'full': resname.entry.name} ]

                entry['numbers'] = []

                for i in range(7):

                    numptr = resname.entry.numbers[i].pnumber

                    if numptr:

                        reqnumbers.slot=numptr

                        resnumbers=self.sendpbcommand(reqnumbers, self.protocolclass.phonebooknumbersresponse)

                        numhash={'number': resnumbers.entry.number, 'type': numbertypetab[i]}

                        if numptr==resname.entry.pspeed:

                            numhash['speeddial']=i

                        entry['numbers'].append(numhash)

                if resname.entry.pemail:

                    reqnumbers.slot=resname.entry.pemail

                    resnumbers=self.sendpbcommand(reqnumbers, self.protocolclass.phonebooknumbersresponse)

                    entry['emails']=[{'email': resnumbers.entry.number}]

                if resname.entry.purl:

                    reqnumbers.slot=resname.entry.purl

                    resnumbers=self.sendpbcommand(reqnumbers, self.protocolclass.phonebooknumbersresponse)

                    entry['urls']=[{'url': resnumbers.entry.number}]

                self.log("Read entry "+`i`+": "+resname.entry.name)

                pbook[count]=entry

                count+=1

        result['phonebook']=pbook

        return result

	def getcalendar(self, result):

        pbook={}

        result['calendar']=pbook

        return result

	def getwallpapers(self, results):

        pass

	def getringtones(self, results):

        pass

	"Talk to a Samsung SPH-N400 cell phone"

class  Profile (com_phone.Profile) :
	protocolclass=Phone.protocolclass
	    serialsname=Phone.serialsname
	    phone_manufacturer='SAMSUNG'
	    phone_model='SPH-N400'
	    usbids_usbtoserial=(
        ( 0x067b, 0x2303, None), 
        ( 0x0403, 0x6001, None), 
        ( 0x0731, 0x2003, None), 
        )
	    usbids=usbids_usbtoserial
	    deviceclasses=("serial",)
	    def __init__(self):

        com_phone.Profile.__init__(self)

	_supportedsyncs=(
        ('phonebook', 'read', None),
        )
	def readfrombuffer(self, buf):

        self._bufferstartoffset=buf.getcurrentoffset()

        if self._terminator is None:

            self._value=buf.getremainingbytes()

        else:

            self._value=chr(buf.getnextbyte())

            if self._value == ',':

                self._value = ''

            else:

                inquotes=False

                if self._quotechar is not None:

                    if self._value[0]==chr(self._quotechar):

                        inquotes=True

                while buf.hasmore():

                    self._value+=chr(buf.getnextbyte())

                    if inquotes:

                        if self._value[-1]==chr(self._quotechar):

                            inquotes=False

                    else:

                        if self._value[-1]==chr(self._terminator):

                            break

                if self._value[-1]==self._terminator:

                    if self._raiseonunterminatedread:

                        raise NotTerminatedException()

                else:

                    self._value=self._value[:-1]

        if self._quotechar is not None and self._value:

            if self._value[0]==chr(self._quotechar) and self._value[-1]==chr(self._quotechar):

                self._value=self._value[1:-1]

            else:

                raise MissingQuotesException()

        if self._readescape:

            self._value=common.pppunescape(self._value)

        if self._constant is not None and self._value!=self._constant:

            raise ValueException("The value read was not the constant")

        self._bufferendoffset=buf.getcurrentoffset()

	def writetobuffer(self, buf):

        if self._value is None:

            raise ValueNotSetException()

        self._bufferstartoffset=buf.getcurrentoffset()

        if self._quotechar is not None:

            buf.appendbyte(self._quotechar)

        buf.appendbytes(self._value)

        if self._quotechar is not None:

            buf.appendbyte(self._quotechar)

        if self._terminator is not None:

            buf.appendbyte(self._terminator)

        self._bufferendoffset=buf.getcurrentoffset()

	def packetsize(self):

        if self._sizeinbytes is not None:

            return self._sizeinbytes

        if self._value is None:

            raise ValueNotSetException()

        l=len(self._value)

        if self._terminator is not None:

            l+=1

        return l

	def getvalue(self):

        """Returns the string we are"""

        if self._value is None:

            raise ValueNotSetException()

        return self._value

	"""A text string enclosed in quotes, with a way to escape quotes that a supposed
    to be part of the string.  Typical of Samsung phones."""

class  CSVINT (CSVSTRING) :
	"""Integers in CSV lines"""
	    def __init__(self, *args, **kwargs):

        super(CSVINT,self).__init__(*args, **kwargs)

        self._quotechar=None

        if self._ismostderived(CSVINT):

            self._update(args,kwargs)

	def _update(self, args, kwargs):

        for k in 'constant', 'default', 'value':

            if kwargs.has_key(k):

                kwargs[k]=str(kwargs[k])

        if len(args)==0:

            pass

        elif len(args)==1:

            args=(str(args[0]),)

        else:

            raise TypeError("expected integer as arg")

        super(CSVINT,self)._update(args,kwargs)

        self._complainaboutunusedargs(CSVINT,kwargs)

	def getvalue(self):

        """Convert the string into an integer
        @rtype: integer
        """

        val=super(CSVINT,self).getvalue()

        try:

            ival=int(val)

        except:

            try:

                ival=int(self._default)

            except:

                raise ValueException("The field '%s' is not an integer" % (val))

        return ival

	"""Integers in CSV lines"""

class  CSVDATE (CSVSTRING) :
	"""Dates in CSV lines"""
	    def __init__(self, *args, **kwargs):

        super(CSVDATE,self).__init__(*args, **kwargs)

        self._valuedate=(0,0,0) 

        self._quotechar=None

        if self._ismostderived(CSVDATE):

            self._update(args,kwargs)

	def _update(self, args, kwargs):

        for k in 'constant', 'default', 'value':

            if kwargs.has_key(k):

                kwargs[k]=self._converttostring(kwargs[k])

        if len(args)==0:

            pass

        elif len(args)==1:

            args=(self._converttostring(args[0]),)

        else:

            raise TypeError("expected (year,month,day) as arg")

        super(CSVDATE,self)._update(args, kwargs) 

        self._complainaboutunusedargs(CSVDATE,kwargs)

	def getvalue(self):

        """Unpack the string into the date
        @rtype: tuple
        @return: (year, month, day)
        """

        s=super(CSVDATE,self).getvalue()

        val=s.split("/") 

        if len(val)<2:

            year = 0

            month = 0

            day = 0

        else:

            year=int(val[2])

            month=int(val[0])

            day=int(val[1])

        return (year, month, day)

	def _converttostring(self, date):

        if len(date)>=3:

            year,month,day=date[:3]

            if month>0 or day>0 or year>0:

                s='%2.2d/%2.2d/%4.4d'%(month, day, year)

            else:

                s=""

        else:

            s=""

        return s

	"""Dates in CSV lines"""

class  CSVTIME (CSVSTRING) :
	"""Timestamp in CSV lines"""
	    def __init__(self, *args, **kwargs):

        super(CSVTIME,self).__init__(*args, **kwargs)

        self._valuetime=(0,0,0,0,0,0) 

        self._quotechar=None

        if self._ismostderived(CSVTIME):

            self._update(args,kwargs)

	def _update(self, args, kwargs):

        for k in 'constant', 'default', 'value':

            if kwargs.has_key(k):

                kwargs[k]=self._converttostring(kwargs[k])

        if len(args)==0:

            pass

        elif len(args)==1:

            args=(self._converttostring(args[0]),)

        else:

            raise TypeError("expected (year,month,day) as arg")

        super(CSVTIME,self)._update(args, kwargs) 

        self._complainaboutunusedargs(CSVTIME,kwargs)

	def getvalue(self):

        """Unpack the string into the date
        @rtype: tuple
        @return: (year, month, day)
        """

        s=super(CSVTIME,self).getvalue()

        year=int(s[0:4])

        month=int(s[4:6])

        day=int(s[6:8])

        hour=int(s[9:11])

        minute=int(s[11:13])

        second=int(s[13:15])

        return (year, month, day, hour, minute, second)

	def _converttostring(self, time):

        if len(time)>=6:

            year,month,day,hour,minute,second=time[:6]

            s='%4.4d%2.2d%2.2dT%2.2d%2.2d%2.2d'%(year, month, day, hour, minute, second)

        else:

            s=""

        return s

	"""Timestamp in CSV lines"""

class  COUNTEDBUFFEREDSTRING (BaseProtogenClass) :
	"""A string as used on Audiovox.  There is a one byte header saying how long the string
    is, followed by the string in a fixed sized buffer"""
	    def __init__(self, *args, **kwargs):

        """
        A string value can be specified to this constructor, or in the value keyword arg.
        @keyword constant: (Optional) A constant value.  All reads must have this value
        @keyword pad: (Default=32 - space) When writing, what to pad the rest of the buffer with
        @keyword default: (Optional) Our default value
        @keyword raiseontruncate: (Default True) raise L{ValueLengthException} if the supplied
             value is too large to fit within the buffer.
        @keyword value: (Optional) Value
        @keyword sizeinbytes: (Mandatory) Size of the buffer, including the count byte
        """

        super(COUNTEDBUFFEREDSTRING,self).__init__(*args, **kwargs)

        self._constant=None

        self._pad=32

        self._sizeinbytes=None

        self._default=None

        self._raiseontruncate=True

        self._value=None

        if self._ismostderived(COUNTEDBUFFEREDSTRING):

            self._update(args, kwargs)

	def _update(self, args, kwargs):

        super(COUNTEDBUFFEREDSTRING,self)._update(args, kwargs)

        self._consumekw(kwargs, ("constant", "pad", "sizeinbytes", "default", "raiseontruncate", "value"))

        self._complainaboutunusedargs(COUNTEDBUFFEREDSTRING,kwargs)

        if len(args)==0:

            pass

        elif len(args)==1:

            self._value=str(args[0])

            if self._constant is not None and self._constant!=self._value:

                raise ValueException("This field is a constant of '%s'.  You tried setting it to '%s'" % (self._constant, self._value))

        else:

            raise TypeError("Unexpected arguments "+`args`)

        if self._value is None and self._default is not None:

            self._value=self._default

        if self._sizeinbytes is None:

            raise ValueException("sizeinbytes must be specified for COUNTEDBUFFEREDSTRING")

        if self._value is not None:

            l=len(self._value)

            if l>self._sizeinbytes-1:

                if self._raiseontruncate:

                    raise ValueLengthException(l, self._sizeinbytes-1)

                self._value=self._value[:self._sizeinbytes-1]

	def readfrombuffer(self, buf):

        assert self._sizeinbytes is not None

        self._bufferstartoffset=buf.getcurrentoffset()

        strlen=buf.getnextbyte()

        if strlen>self._sizeinbytes-1:

            raise ValueException("counter specifies size of %d which is greater than remaining stringbuffer size of %d!" % (strlen, self._sizeinbytes-1))

        self._value=buf.getnextbytes(self._sizeinbytes-1) 

        self._value=self._value[:strlen]

        if self._constant is not None and self._value!=self._constant:

            raise ValueException("The value read was not the constant")

        self._bufferendoffset=buf.getcurrentoffset()

	def writetobuffer(self, buf):

        assert self._sizeinbytes is not None

        if self._value is None:

            raise ValueNotSetException()

        self._bufferstartoffset=buf.getcurrentoffset()

        buf.appendbyte(len(self._value))

        buf.appendbytes(self._value)

        if len(self._value)+1<self._sizeinbytes:

            buf.appendbytes(chr(self._pad)*(self._sizeinbytes-1-len(self._value)))

        self._bufferendoffset=buf.getcurrentoffset()

	def packetsize(self):

        assert self._sizeinbytes is not None

        return self._sizeinbytes

	def getvalue(self):

        """Returns the string we are"""

        if self._value is None:

            raise ValueNotSetException()

        return self._value

	"""A string as used on Audiovox.  There is a one byte header saying how long the string
    is, followed by the string in a fixed sized buffer"""

class  DATA (BaseProtogenClass) :
	"A block of bytes"
	    def __init__(self, *args, **kwargs):

        """
        A data value can be specified to this constructor or in the value keyword arg
        @keyword constant: (Optional) A constant value.  All reads must have this value
        @keyword pad: (Default=0) The padding byte if fixed length when writing and the
             value isn't long enough
        @keyword sizeinbytes: (Optional) Set if fixed length.
             If not set, then the rest of the packet will be consumed on reads.
        @keyword default: (Optional) Our default value
        @keyword raiseonwrongsize: (Default True) raise L{ValueLengthException} if the supplied
             value is too large to fit within sizeinbytes.
        """

        super(DATA, self).__init__(*args, **kwargs)

        self._constant=None

        self._pad=0

        self._sizeinbytes=None

        self._default=None

        self._raiseonwrongsize=True

        self._value=None

        if self._ismostderived(DATA):

            self._update(args,kwargs)

	def _update(self, args, kwargs):

        super(DATA,self)._update(args, kwargs)

        self._consumekw(kwargs, ("constant", "pad", "sizeinbytes", "default", "raiseonwrongsize", "value"))

        self._complainaboutunusedargs(DATA,kwargs)

        if len(args)==0:

            pass

        elif len(args)==1:

            self._value=args[0]

            if self._constant is not None and self._constant!=self._value:

                raise ValueException("This field is a constant and you set it to a different value")

        else:

            raise TypeError("Unexpected arguments "+`args`)

        if self._value is None and self._default is not None:

            self._value=self._default

        if self._value is not None:

            if self._sizeinbytes is not None:

                l=len(self._value)

                if l<self._sizeinbytes:

                    if self._pad is not None:

                        self._value+=chr(self._pad)*(self._sizeinbytes-l)

                l=len(self._value)

                if l!=self._sizeinbytes:

                    if self._raiseonwrongsize:

                        raise ValueLengthException(l, self._sizeinbytes)

                    else:

                        self._value=self._value[:self._sizeinbytes]

	def readfrombuffer(self, buf):

        self._bufferstartoffset=buf.getcurrentoffset()

        if self._sizeinbytes is not None:

            self._value=buf.getnextbytes(self._sizeinbytes)

        else:

            self._value=buf.getremainingbytes()

        if self._constant is not None and self._value!=self._constant:

            raise ValueException("The value read was not the constant")

        self._bufferendoffset=buf.getcurrentoffset()

	def writetobuffer(self, buf):

        if self._value is None:

            raise ValueNotSetException()

        self._bufferstartoffset=buf.getcurrentoffset()

        buf.appendbytes(self._value)

        self._bufferendoffset=buf.getcurrentoffset()

	def packetsize(self):

        if self._sizeinbytes is not None:

            return self._sizeinbytes

        if self._value is None:

            raise ValueNotSetException()

        l=len(self._value)

        return l

	def getvalue(self):

        """Returns the bytes we are"""

        if self._value is None:

            raise ValueNotSetException()

        return self._value

	"A block of bytes"

class  UNKNOWN (DATA) :
	"A block of bytes whose purpose we don't know"
	    def __init__(self, *args, **kwargs):

        """
        Same arguments as L{DATA.__init__}.  We default to a block
        of pad chars (usually \x00)
        """

        dict={'pad':0 , 'default': ""}

        dict.update(kwargs)

        super(UNKNOWN,self).__init__(*args, **dict)

        if self._ismostderived(UNKNOWN):

            self._update(args,dict)

	def _update(self, args, kwargs):

        super(UNKNOWN,self)._update(args, kwargs)

        self._complainaboutunusedargs(UNKNOWN,kwargs)

        if len(args)==1:

            self._value=args[0]

        elif len(args)>1:

            raise TypeError("Unexpected arguments "+`args`)

	"A block of bytes whose purpose we don't know"

class  LIST (BaseProtogenClass) :
	"""A list of items
    You can generally treat this class as though it is a list.  Note that some
    list like methods haven't been implemented (there are so darn many!)  If you
    are missing one you want to use, please add it to this class.
    """
	    def __init__(self, *args, **kwargs):

        """
        You can pass objects to start the list with, or to the value keyword arg
        @keyword createdefault:  (Default False) Creates default members of the list if enough
            were not supplied before writing.
        @keyword length:  (Optional) How many items there are in the list
        @keyword raiseonbadlength: (Default True) raises L{ValueLengthException} if there are
            the wrong number of items in the list.  Note that this checking is only done
            when writing or reading from a buffer.  length must be set for this to have any
            effect.  If you have createdefault set then having less than length elements will
            not cause the exception.
        @keyword elementclass: (Mandatory) The class of each element
        @keyword elementinitkwargs: (Optional) KWargs for the constructor of each element
        @keyword value: (Optional) Value
        """

        self._thelist=[]

        super(LIST, self).__init__(*args, **kwargs)

        self._createdefault=False

        self._length=None

        self._raiseonbadlength=True

        self._elementclass=None

        self._elementinitkwargs={}

        if self._ismostderived(LIST):

            self._update(args,kwargs)

	def _update(self, args, kwargs):

        super(LIST,self)._update(args, kwargs)

        self._consumekw(kwargs, ("createdefault","length","raiseonbadlength","elementclass","elementinitkwargs"))

        if kwargs.has_key("value"):

            self._thelist=list(kwargs['value'])

            del kwargs['value']

        self._complainaboutunusedargs(LIST,kwargs)

        if self._elementclass is None:

            raise TypeError("elementclass argument was not supplied")

        if len(args):

            self.extend(args)

	def readfrombuffer(self,buf):

        self._bufferstartoffset=buf.getcurrentoffset()

        self._thelist=[]

        if self._length is None:

            while buf.hasmore():

                x=self._makeitem()

                x.readfrombuffer(buf)

                self._thelist.append(x)

        else:

            for dummy in range(self._length):

                x=self._makeitem()

                x.readfrombuffer(buf)

                self._thelist.append(x)

        self._bufferendoffset=buf.getcurrentoffset()

	def writetobuffer(self, buf):

        self._bufferstartoffset=buf.getcurrentoffset()

        self._ensurelength()

        for i in self:

            i.writetobuffer(buf)

        self._bufferendoffset=buf.getcurrentoffset()

	def packetsize(self):

        self._ensurelength()

        sz=0

        for item in self:

            sz+=item.packetsize()

        return sz

	def iscontainer(self):

        return True

	def containerelements(self):

        self._ensurelength()

        for i,v in enumerate(self._thelist):

            yield "["+`i`+"]",v,None

	def append(self, item):

        self._thelist.append(self._makeitem(item))

	def extend(self, items):

        self._thelist.extend(map(self._makeitem, items))

	def insert(self, index, item):

        self._thelist.insert(index, self._makeitem(item))

	def __getitem__(self, index):

        return self._thelist[index]

	def __iter__(self):

        try:

            return self._thelist.__iter__()

        except:

            return self.__fallbackiter()

	def __fallbackiter(self):

        for item in self._thelist:

            yield item

	def __len__(self):

        return self._thelist.__len__()

	def __setitem__(self, index, value):

        self._thelist.__setitem__(index, self._makeitem(value))

	def __delitem__(self, index):

        self._thelist.__delitem__(index)

	def _makeitem(self, *args, **kwargs):

        "Creates a child element"

        if len(args)==1 and isinstance(args[0], self._elementclass):

            return args[0]

        d={}

        d.update(self._elementinitkwargs)

        d.update(kwargs)

        return self._elementclass(*args, **d)

	def _ensurelength(self):

        "Ensures we are the correct length"

        if self._createdefault and self._length is not None and len(self._thelist)<self._length:

            while len(self._thelist)<self._length:

                x=self._makeitem()

                self._thelist.append(x)

            return

        if self._length is not None and self._raiseonbadlength and len(self._thelist)!=self._length:

            raise ValueLengthException(len(self), self._length)

	"""A list of items
    You can generally treat this class as though it is a list.  Note that some
    list like methods haven't been implemented (there are so darn many!)  If you
    are missing one you want to use, please add it to this class.
    """

class  buffer :
	"This is used for reading and writing byte data"
	    def __init__(self, data=None):

        "Call with data to read from it, or with None to write to it"

        if data is not None:

            self._data=data

        else:

            self._buffer=cStringIO.StringIO()

        self._offset=0

	def getcurrentoffset(self):

        "Returns distance into data we are"

        return self._offset

	def peeknextbyte(self, howmuch=0):

        "Returns value of next byte, but doesn't advance position"

        if self._offset+howmuch>=len(self._data):

            return None

        return ord(self._data[self._offset+howmuch])

	def getnextbyte(self):

        "Returns next byte"

        if self._offset>=len(self._data):

            raise IndexError("trying to read one byte beyond end of "+`len(self._data)`+" byte buffer")

        res=ord(self._data[self._offset])

        self._offset+=1

        return res

	def getnextbytes(self, howmany):

        "Returns howmany bytes"

        assert howmany>=0

        if self._offset+howmany>len(self._data):

            raise IndexError("Trying to read "+`howmany`+" bytes starting at "+`self._offset`+" which will go beyond end of "+`len(self._data)`+" byte buffer")

        res=self._data[self._offset:self._offset+howmany]

        self._offset+=howmany

        return res

	def peeknextbytes(self, howmany):

        if self._offset+howmany>len(self._data):

            return None

        return self._data[self._offset:self._offset+howmany]

	def getremainingbytes(self):

        "Returns rest of buffer"

        sz=len(self._data)-self._offset

        return self.getnextbytes(sz)

	def hasmore(self):

        "Is there any data left?"

        return self._offset<len(self._data)

	def howmuchmore(self):

        "Returns how many bytes left"

        return len(self._data)-self._offset

	def appendbyte(self, val):

        """Appends byte to data.
        @param val: a number 0 <= val <=255
        """

        assert val>=0 and val<=255

        self._buffer.write(chr(val))

        self._offset+=1

        assert self._offset==len(self._buffer.getvalue())

	def appendbytes(self, bytes):

        "Adds bytes to end"

        self._buffer.write(bytes)

        self._offset+=len(bytes)

        assert self._offset==len(self._buffer.getvalue())

	def getvalue(self):

        "Returns the buffer being built"

        return self._buffer.getvalue()

	def getdata(self):

        "Returns the data passed in"

        return self._data

	"This is used for reading and writing byte data"
Example #11
0
    def sendpbcommand(self, request, responseclass, callsetmode=True, writemode=False, numsendretry=0, returnerror=False):
        if writemode:
            numretry=3
        else:
            numretry=0
            
        if callsetmode:
            self.setmode(self.MODEPHONEBOOK)
        buffer=prototypes.buffer()

        request.writetobuffer(buffer, logtitle="Samsung phonebook request")
        data=buffer.getvalue()
        firsttwo=data[:2]
        data=common.pppescape(data+common.crcs(data))+common.pppterminator
        isendretry=numsendretry
        while isendretry>=0:
            try:
                rdata=self.comm.writethenreaduntil(data, False, common.pppterminator, logreaduntilsuccess=False, numfailures=numretry)
                break
            except com_phone.modeignoreerrortypes:
                if isendretry>0:
                    self.log("Resending request packet...")
                    time.sleep(0.3)
                else:
                    self.comm.success=False
                    self.mode=self.MODENONE
                    self.raisecommsdnaexception("manipulating the phonebook")
                isendretry-=1

        self.comm.success=True

        origdata=rdata
        # sometimes there is junk at the beginning, eg if the user
        # turned off the phone and back on again.  So if there is more
        # than one 7e in the escaped data we should start after the
        # second to last one
        d=rdata.rfind(common.pppterminator,0,-1)
        if d>=0:
            self.log("Multiple Samsung packets in data - taking last one starting at "+`d+1`)
            self.logdata("Original Samsung data", origdata, None)
            rdata=rdata[d+1:]

        # turn it back to normal
        data=common.pppunescape(rdata)

        # Sometimes there is other crap at the beginning.  But it might
        # be a Sanyo error byte.  So strip off bytes from the beginning
        # until the crc agrees, or we get to the first two bytes of the
        # request packet.
        d=data.find(firsttwo)
        crc=data[-3:-1]
        crcok=False
        for i in range(0,d+1):
            trydata=data[i:-3]
            if common.crcs(trydata)==crc:
                crcok=True
                break

        if not crcok:
            self.logdata("first two",firsttwo, None)
            self.logdata("Original Sanyo data", origdata, None)
            self.logdata("Working on Sanyo data", data, None)
            raise common.CommsDataCorruption("Sanyo packet failed CRC check", self.desc)

        res=responseclass()
        if d>0:
            if d==i:
                self.log("Junk at beginning of Sanyo packet, data at "+`d`)
                self.logdata("Original Sanyo data", origdata, None)
                self.logdata("Working on Sanyo data", data, None)
            else:
                if returnerror:
                    res=self.protocolclass.sanyoerror()
                else:
                    self.log("Sanyo Error code "+`ord(data[0])`)
                    self.logdata("sanyo phonebook response", data, None)
                    raise SanyoCommandException(ord(data[0]))
            
        data=trydata

        # parse data
        buffer=prototypes.buffer(data)
        res.readfrombuffer(buffer, logtitle="sanyo phonebook response")
        return res
	def sendpbcommand(self, request, responseclass, callsetmode=True, writemode=False, numsendretry=0, returnerror=False):

        if writemode:

            numretry=3

        else:

            numretry=0

        if callsetmode:

            self.setmode(self.MODEPHONEBOOK)

        buffer=prototypes.buffer()

        request.writetobuffer(buffer)

        data=buffer.getvalue()

        self.logdata("Sanyo phonebook request", data, request)

        firsttwo=data[:2]

        data=common.pppescape(data+common.crcs(data))+common.pppterminator

        isendretry=numsendretry

        while isendretry>=0:

            try:

                rdata=self.comm.writethenreaduntil(data, False, common.pppterminator, logreaduntilsuccess=False, numfailures=numretry)

                break

            except com_phone.modeignoreerrortypes:

                if isendretry>0:

                    self.log("Resending request packet...")

                    time.sleep(0.3)

                else:

                    self.comm.success=False

                    self.mode=self.MODENONE

                    self.raisecommsdnaexception("manipulating the phonebook")

                isendretry-=1

        self.comm.success=True

        origdata=rdata

        d=rdata.rfind(common.pppterminator,0,-1)

        if d>=0:

            self.log("Multiple Sanyo packets in data - taking last one starting at "+`d+1`)

            self.logdata("Original Sanyo data", origdata, None)

            rdata=rdata[d+1:]

        data=common.pppunescape(rdata)

        d=data.find(firsttwo)

        crc=data[-3:-1]

        crcok=False

        for i in range(0,d+1):

            trydata=data[i:-3]

            if common.crcs(trydata)==crc:

                crcok=True

                break

        if not crcok:

            self.logdata("first two",firsttwo, None)

            self.logdata("Original Sanyo data", origdata, None)

            self.logdata("Working on Sanyo data", data, None)

            raise common.CommsDataCorruption("Sanyo packet failed CRC check", self.desc)

        res=responseclass()

        if d>0:

            if d==i:

                self.log("Junk at beginning of Sanyo packet, data at "+`d`)

                self.logdata("Original Sanyo data", origdata, None)

                self.logdata("Working on Sanyo data", data, None)

            else:

                if returnerror:

                    res=self.protocolclass.sanyoerror()

                else:

                    self.log("Sanyo Error code "+`ord(data[0])`)

                    self.logdata("sanyo phonebook response", data, None)

                    raise SanyoCommandException(ord(data[0]))

        data=trydata

        self.logdata("sanyo phonebook response", data, responseclass)

        buffer=prototypes.buffer(data)

        res.readfrombuffer(buffer)

        return res

	def getfundamentals(self, results):

        """Gets information fundamental to interopating with the phone and UI."""

        print "HASRINGPICBUF=",self.protocolclass.HASRINGPICBUF

        self.log("Retrieving fundamental phone information")

        self.log("Phone serial number")

        results['uniqueserial']=sha.new(self.getfilecontents("nvm/$SYS.ESN")).hexdigest()

        self.getmediaindices(results)

        self.log("Fundamentals retrieved")

        return results

	def sanyosort(self, a, b):

        "Sanyo sort order.  Case insensitive, letters first"

        x=a[1]

        y=b[1]

        if(x[0:1].isalpha() and not y[0:1].isalpha()):

            return -1

        if(y[0:1].isalpha() and not x[0:1].isalpha()):

            return 1

        return cmp(x.lower(), y.lower())

	def getsms(self, result):

        gsms = {}

        self.log("Getting sms entries")

        req=self.protocolclass.messagerequest()

        for slot in range(self.protocolclass.NUMMESSAGESLOTS):

            req.slot=slot

            res=self.sendpbcommand(req, self.protocolclass.messageresponse)

            if res.entry.dunno4==2:

                entry=sms.SMSEntry()

                entry.folder=entry.Folder_Inbox

                entry.datetime="200%d%02d%02dT%02d%02d%02d" % ((res.entry.year, res.entry.month, res.entry.day, res.entry.hour,res.entry.minute, res.entry.second))

                if res.entry.read==17:

                    entry.read=1

                else:

                    entry.read=0

                entry._from=res.entry.phonenum

                entry.callback=res.entry.callback

                entry.subject="%d-%s-%s" % ((res.entry.counter, res.entry.phonenum, res.entry.message[:12]))

                self.log(res.entry.message[:8])

                if res.entry.priority==100:

                    entry.priority=sms.SMSEntry.Priority_Normal

                if res.entry.priority==200:

                    entry.priority=sms.SMSEntry.Priority_High

                entry.text=unicode(res.entry.message, errors='ignore')

                gsms[entry.id]=entry

                result['sms']=gsms

        return result

	def gettodo(self, result):

        gtodo = {}

        self.log("Getting todo entries")

        req=self.protocolclass.todorequest()

        for slot in range(self.protocolclass.NUMTODOSLOTS):

            req.slot=slot

            res=self.sendpbcommand(req, self.protocolclass.todoresponse)

            entry=todo.TodoEntry()

            if res.entry.flag:

                entry.summary=res.entry.todo

                if res.entry.priority==2:

                    entry.status=4

                if res.entry.priority==0:

                    entry.priority=5

                if res.entry.priority==1:

                    entry.priority=1

                gtodo[entry.id]=entry

                result['todo']=gtodo

        return result

	def getphonebook(self,result):

        pbook={}

        sortstuff = self.getsanyobuffer(self.protocolclass.pbsortbuffer)

        if self.protocolclass.HASRINGPICBUF:

            ringpic = self.getsanyobuffer(self.protocolclass.ringerpicbuffer)

        speedslot=[]

        speedtype=[]

        for i in range(self.protocolclass._NUMSPEEDDIALS):

            speedslot.append(sortstuff.speeddialindex[i].pbslotandtype & 0xfff)

            numtype=(sortstuff.speeddialindex[i].pbslotandtype>>12)-1

            if(numtype >= 0 and numtype <= len(self.numbertypetab)):

                speedtype.append(self.numbertypetab[numtype])

            else:

                speedtype.append("")

        numentries=sortstuff.slotsused

        self.log("There are %d entries" % (numentries,))

        count = 0 

        numcount = 0 

        numemail = 0 

        numurl = 0 

        res=self.protocolclass.phonebookentry()

        usedefaultnum = 'defaultnum' in res.getfields()

        print "usedefaultnum =",usedefaultnum

        req=self.protocolclass.phonebookslotrequest()

        for i in range(0, self.protocolclass._NUMPBSLOTS):

            if sortstuff.usedflags[i].used:

                req.slot = i

                res=self.sendpbcommand(req, self.protocolclass.phonebookslotresponse)

                self.log("Read entry "+`i`+" - "+res.entry.name)

                entry=self.extractphonebookentry(res.entry, result)

                for j in range(len(speedslot)):

                    if(speedslot[j]==req.slot):

                        for k in range(len(entry['numbers'])):

                            if(entry['numbers'][k]['type']==speedtype[j]):

                                entry['numbers'][k]['speeddial']=j+2

                                break

                if self.protocolclass.HASRINGPICBUF:

                    if ringpic.ringtones[i].ringtone>0:

                        try:

                            tone=result['ringtone-index'][ringpic.ringtones[i].ringtone]['name']

                        except:

                            tone=self.serialsname+"Index_"+`ringpic.ringtones[i].ringtone`

                        entry['ringtones']=[{'ringtone': tone, 'use': 'call'}]

                    if ringpic.wallpapers[i].wallpaper>0:

                        try:

                            paper=result['wallpaper-index'][ringpic.wallpapers[i].wallpaper]['name']

                        except:

                            paper=self.serialsname+"Index_"+`ringpic.wallpapers[i].wallpaper`

                        entry['wallpapers']=[{'wallpaper': paper, 'use': 'call'}]

                if usedefaultnum:

                    firsttype=res.entry.defaultnum-1

                    if firsttype < len(self.numbertypetab):

                        defaulttype=self.numbertypetab[firsttype]

                        k=0

                        for j in range(len(entry['numbers'])):

                            if entry['numbers'][j]['type'] == defaulttype:

                                k=j

                                break

                        if k>0:

                            exchange=entry['numbers'][k]

                            for kk in range(k,0,-1):

                                entry['numbers'][kk]=entry['numbers'][kk-1]

                            entry['numbers'][0]=exchange

                pbook[count]=entry 

                self.progress(count, numentries, res.entry.name)

                count+=1

                numcount+=len(entry['numbers'])

                if entry.has_key('emails'):

                    numemail+=len(entry['emails'])

                if entry.has_key('urls'):

                    numurl+=len(entry['urls'])

        self.progress(numentries, numentries, "Phone book read completed")

        self.log("Phone contains "+`count`+" contacts, "+`numcount`+" phone numbers, "+`numemail`+" Emails, "+`numurl`+" URLs")

        result['phonebook']=pbook

        return pbook

	def extractphonebookentry(self, entry, fundamentals):

        """Return a phonebook entry in BitPim format"""

        res={}

        res['serials']=[ {'sourcetype': self.serialsname, 'serial1': entry.slot, 'serial2': entry.slotdup,
                          'sourceuniqueid': fundamentals['uniqueserial']} ]

        res['names']=[ {'full': entry.name} ]

        if len(entry.email):

            res['emails']=[ {'email': entry.email} ]

        if len(entry.url):

            res['urls']=[ {'url': entry.url} ]

        res['flags']=[ {'secret': entry.secret } ]

        res['numbers']=[]

        numberindex = 0

        for type in self.numbertypetab:

            if len(entry.numbers[numberindex].number):

                res['numbers'].append({'number': entry.numbers[numberindex].number, 'type': type })

            numberindex+=1

        return res

	def _findmediaindex(self, index, name, pbentryname, type):

        if name is None:

            return 0

        for i in index:

            if index[i]['name']==name:

                return i

        pos=name.find('_')

        if(pos>=0):

            i=int(name[pos+1:])

            return i

        return 0

	def makeentry(self, entry, dict):

        e=self.protocolclass.phonebookentry()

        for k in entry:

            if k=='ringtones' or k=='wallpapers' or k=='numbertypes':

                continue

            if k=='numbers':

                for numberindex in range(self.protocolclass.NUMPHONENUMBERS):

                    enpn=self.protocolclass.phonenumber()

                    e.numbers.append(enpn)

                for i in range(len(entry[k])):

                    numberindex=entry['numbertypes'][i]

                    e.numbers[numberindex].number=entry[k][i]

                    e.numbers[numberindex].number_len=len(e.numbers[numberindex].number)

                continue

            setattr(e,k,entry[k])

        return e

	def writewait(self):

        """Loop until phone status indicates ready to write"""

        for i in range(100):

            req=self.protocolclass.statusrequest()

            res=self.sendpbcommand(req, self.protocolclass.statusresponse)

            if res.ready==res.readyvalue:

                return

            time.sleep(0.1)

        self.log("Phone did not transfer to ready to write state")

        self.log("Waiting a bit longer and trying anyway")

        return

	def savephonebook(self, data):

        newphonebook={}

        self.mode=self.MODENONE

        self.setmode(self.MODEBREW) 

        self.setmode(self.MODEPHONEBOOK)

        sortstuff=self.protocolclass.pbsortbuffer()

        ringpic=self.protocolclass.ringerpicbuffer()

        callerid=self.protocolclass.calleridbuffer()

        res=self.protocolclass.phonebookentry()

        usedefaultnum = 'defaultnum' in res.getfields()

        for i in range(self.protocolclass._NUMPBSLOTS):

            sortstuff.usedflags.append(0)

            sortstuff.firsttypes.append(0)

            sortstuff.sortorder.append(0xffff)

            sortstuff.sortorder2.append(0xffff)

            sortstuff.emails.append(0xffff)

            sortstuff.urls.append(0xffff)

            ringpic.ringtones.append(0)

            ringpic.wallpapers.append(0)

        for i in range(self.protocolclass._NUMSPEEDDIALS):

            sortstuff.speeddialindex.append(0xffff)

        for i in range(self.protocolclass._NUMLONGNUMBERS):

            sortstuff.longnumbersindex.append(0xffff)

        namemap=[]

        emailmap=[]

        urlmap=[]

        callerid.numentries=0

        pbook=data['phonephonebook'] 

        self.log("Putting phone into write mode")

        req=self.protocolclass.beginendupdaterequest()

        req.beginend=1 

        res=self.sendpbcommand(req, self.protocolclass.beginendupdateresponse, writemode=True)

        self.writewait()

        keys=pbook.keys()

        keys.sort()

        sortstuff.slotsused=len(keys)

        sortstuff.numemail=0

        sortstuff.numurl=0

        progresscur=0

        progressmax=len(keys)

        self.log("Writing %d entries to phone" % (len(keys),))

        nlongphonenumbers=0

        nonumbercount=0

        for ikey in keys:

            ii=pbook[ikey]

            slot=ii['slot'] 

            progresscur+=1

            self.progress(progresscur, progressmax, "Writing "+ii['name'])

            self.log("Writing entry "+`slot`+" - "+ii['name'])

            entry=self.makeentry(ii, data)

            if not usedefaultnum:

                delattr(entry,'defaultnum')

            req=self.protocolclass.phonebookslotupdaterequest()

            req.entry=entry

            res=self.sendpbcommand(req, self.protocolclass.phonebookslotresponse, writemode=True)

            entry=self.extractphonebookentry(entry, data)

            entry['ringtones']=[{'ringtone': ii['ringtone'], 'use': 'call'}]

            entry['wallpapers']=[{'wallpaper': ii['wallpaper'], 'use': 'call'}]

            sortstuff.usedflags[slot].used=1

            if(len(ii['numbers'])):

                sortstuff.firsttypes[slot].firsttype=min(ii['numbertypes'])+1

            else:

                if(len(ii['email'])):

                    sortstuff.firsttypes[slot].firsttype=8

                    nonumbercount+=1

                elif(len(ii['url'])):

                    sortstuff.firsttypes[slot].firsttype=9

                    nonumbercount+=1

                else:

                    sortstuff.firsttypes[slot].firsttype=0

            for i in range(len(ii['numbers'])):

                nindex=ii['numbertypes'][i]

                speeddial=ii['speeddials'][i]

                code=slot+((nindex+1)<<12)

                if(speeddial>=2 and speeddial<=self.protocolclass._NUMSPEEDDIALS+1):

                    sortstuff.speeddialindex[speeddial-2]=code

                    for k in range(len(entry['numbers'])):

                        if(entry['numbers'][k]['type']==nindex):

                            entry['numbers'][k]['speeddial']=speeddial

                            break

                if(callerid.numentries<callerid.maxentries):

                    phonenumber=ii['numbers'][i]

                    cidentry=self.makecidentry(phonenumber,slot,nindex)

                    callerid.items.append(cidentry)

                    callerid.numentries+=1

                    if(len(phonenumber)>self.protocolclass._LONGPHONENUMBERLEN):

                        if(nlongphonenumbers<self.protocolclass._NUMLONGNUMBERS):

                            sortstuff.longnumbersindex[nlongphonenumbers].pbslotandtype=code

            namemap.append((slot,ii['name']))

            if(len(ii['email'])):

                emailmap.append((slot,ii['email']))

                sortstuff.numemail+=1

            if(len(ii['url'])):

                urlmap.append((slot,ii['url']))

                sortstuff.numurl+=1

            ringpic.ringtones[slot].ringtone=self._findmediaindex(data['ringtone-index'], ii['ringtone'],ii['name'],'ringtone')

            ringpic.wallpapers[slot].wallpaper=self._findmediaindex(data['wallpaper-index'], ii['wallpaper'],ii['name'],'wallpaper')

            newphonebook[slot]=entry

        sortstuff.slotsused2=len(keys)-nonumbercount

        i=0

        j=0

        sortstuff.pbfirstletters=""

        namemap.sort(self.sanyosort)

        for (slot, name) in namemap:

            sortstuff.sortorder[i].pbslot=slot

            if sortstuff.firsttypes[slot].firsttype<=7:

                sortstuff.sortorder2[j].pbslot=slot

                j+=1

            if name:

                sortstuff.pbfirstletters+=name[0]

            else:

                sortstuff.pbfirstletters+=chr(0)

            i+=1

        i=0

        sortstuff.emailfirstletters=""

        emailmap.sort(self.sanyosort)

        for (slot, email) in emailmap:

            sortstuff.emails[i].pbslot=slot

            sortstuff.emailfirstletters+=email[0]

            i+=1

        i=0

        sortstuff.urlfirstletters=""

        urlmap.sort(self.sanyosort)

        for (slot, url) in urlmap:

            sortstuff.urls[i].pbslot=slot

            sortstuff.urlfirstletters+=url[0]

            i+=1

        self.sendsanyobuffer(sortstuff)

        if self.protocolclass.HASRINGPICBUF:

            self.sendsanyobuffer(ringpic)

        self.sendsanyobuffer(callerid)

        time.sleep(1.0)

        data['phonebook']=newphonebook

        del data['phonephonebook']

        data['rebootphone'] = 1

	def makecidentry(self, number, slot, nindex):

        "Prepare entry for caller ID lookup buffer"

        numstripped=re.sub("[^0-9PT#*]", "", number)

        numonly=re.sub("^(\\d*).*$", "\\1", numstripped)

        cidentry=self.protocolclass.calleridentry()

        cidentry.pbslotandtype=slot+((nindex+1)<<12)

        cidentry.actualnumberlen=len(numonly)

        cidentry.numberfragment=numonly[-10:]

        return cidentry

	def savewallpapers(self, results, merge):

        return self.savemedia('wallpapers', 'wallpaper-index', 'images', results, merge)

	def saveringtones(self, results, merge):

        return self.savemedia('ringtone', 'ringtone-index', 'ringers', results, merge)

	def savemedia(self, mediakey, mediaindexkey, mediatype, results, merge):

        """Actually saves out the media
        @param mediakey: key of the media (eg 'wallpapers' or 'ringtones')
                         Index of media in wallpaper or ringer tab
        @param mediaindexkey:  index key (eg 'wallpaper-index')
                         Index of media on the phone
        @param results: results dict
        """

        wp=results[mediakey].copy()

        wpi=results[mediaindexkey].copy()

        for k in wpi.keys():

            if wpi[k]['origin']=='builtin':

                del wpi[k]

        for w in wp.keys():

            name=wp[w]['name']

            if wp[w].get("origin", "")=='camera':

                self.log("Not transferring camera picture "+name+" to phone")

                del wp[w]

            else:

                for k in wpi.keys():

                    if name==wpi[k]['name']:

                        self.log("Not transferring "+name+" as it is already on the phone")

                        del wp[w]

                        break

        init={}

        init[mediatype]={}

        idx=0

        for w in wp.keys():

            idx-=1

            data=wp[w]['data']

            name=wp[w]['name']

            init[mediatype][idx]={'name': name, 'data': data}

        index=init[mediatype]

        errors=False

        for key in index:

            efile=index[key]['name']

            content=index[key]['data']

            if content is None:

                continue 

            if mediatype=='images':

                content = conversions.convertto8bitpng(content,16383)

            if not self.writesanyofile(efile, content):

                errors=True

        if errors:

            self.log("One or more files were rejected by the phone, due to")

            self.log("invalid file type (only PNG or MIDI are allowed), file")

            self.log("size too big, or too many ringers or wallpaper on the phone")

            self.log("See Sanyo Error Codes section of the Sanyh Phone Notes")

            self.log("in the help for more information")

        return results

	def writesanyofile(self, name, contents):

        start=time.time()

        self.log("Writing file '"+name+"' bytes "+`len(contents)`)

        desc="Writing "+name

        try:

            name=name[:name.index(".mid")]

        except:

            try:

                name=name[:name.index(".png")]

            except:

                pass

        if hasattr(self.protocolclass,"sanyomediathingyrequest"):

            req=self.protocolclass.sanyomediathingyrequest()

            req.faset = 0x10

            res=self.sendpbcommand(req, self.protocolclass.sanyomediathingyresponse)

            time.sleep(10.0)

            req.faset = 0x13

            res=self.sendpbcommand(req, self.protocolclass.sanyomediathingyresponse)

	req=self.protocolclass.sanyosendfilename()

	req.filename=name

        res=self.sendpbcommand(req, self.protocolclass.sanyosendfileresponse, returnerror=True)

        if 'errorcode' in res.getfields():

            if res.errorcode==0x65:

                self.alert("Please put your phone into PC Sync Mode", False)

            else:

                raise SanyoCommandException(res.errorcode)

            waitcount=120

            while waitcount>0:

                time.sleep(1.0)

                res=self.sendpbcommand(req, self.protocolclass.sanyosendfileresponse, returnerror=True)

                if not 'errorcode' in res.getfields():

                    break

                waitcount-=1

            if waitcount==0:

                raise SanyoCommandException(res.errorcode)

        req=self.protocolclass.sanyosendfilesize()

        req.filesize=len(contents)

        self.sendpbcommand(req, self.protocolclass.sanyosendfileresponse)

        req=self.protocolclass.sanyosendfilefragment()

        packetsize=req.payloadsize

        offset=0

        count=0

        numblocks=len(contents)/packetsize+1

        for offset in range(0, len(contents), packetsize):

            count+=1

            if count % 5==0:

                self.progress(count,numblocks,desc)

            req.header.command=offset

            req.data=contents[offset:min(offset+packetsize,len(contents))]

            self.sendpbcommand(req, self.protocolclass.sanyosendfileresponse, writemode=True, returnerror=True)

            if 'errorcode' in res.getfields():

                self.log(name+" not written due to error code "+`res.errorcode`)

                return False

        req=self.protocolclass.sanyosendfileterminator()

        try:

            res=self.sendpbcommand(req, self.protocolclass.sanyosendfileresponse, writemode=True, returnerror=True)

            if 'errorcode' in res.getfields():

                self.log(name+" not written due to error code "+`res.errorcode`)

                return False

        except:

            self.log("Exception on writing terminator for file "+name)

            self.log("Continuing...")

        end=time.time()

        if end-start>3:

            self.log("Wrote "+`len(contents)`+" bytes at "+`int(len(contents)/(end-start))`+" bytes/second")

        return True

	def getcalendar(self,result):

        calres={}

        progressmax=self.protocolclass._NUMEVENTSLOTS+self.protocolclass._NUMCALLALARMSLOTS

        req=self.protocolclass.eventrequest()

        count=0

        try:

            reqflag=self.protocolclass.eventslotinuserequest()

        except:

            reqflag=0

        for i in range(0, self.protocolclass._NUMEVENTSLOTS):

            self.progress(i,progressmax,"Events")

            if reqflag:

                reqflag.slot=i

                resflag=self.sendpbcommand(reqflag, self.protocolclass.eventslotinuseresponse)

                if not resflag.flag:

                    continue

            req.slot = i

            res=self.sendpbcommand(req, self.protocolclass.eventresponse)

            if not reqflag:

                if not res.entry.flag:

                    continue

            self.log("Read calendar event "+`i`+" - "+res.entry.eventname+", alarm ID "+`res.entry.ringtone`)

            entry=bpcalendar.CalendarEntry()

            entry.changeserial=res.entry.serial

            entry.description=res.entry.eventname

            entry.location=res.entry.location

            starttime=res.entry.start

            entry.start=self.decodedate(starttime)

            entry.end=self.decodedate(res.entry.end)

            repeat=self._calrepeatvalues[res.entry.period]

            entry.repeat = self.makerepeat(repeat,entry.start)

            if res.entry.alarm==0xffffffff:

                entry.alarm=res.entry.alarmdiff/60

            else:

                alarmtime=res.entry.alarm

                entry.alarm=(starttime-alarmtime)/60

            ringtone=res.entry.ringtone

            if ringtone in self.calendar_tonerange:

                ringtone-=self.calendar_toneoffset

            if ringtone!=self.calendar_defaultringtone:

                if result['ringtone-index'].has_key(ringtone):

                    entry.ringtone=result['ringtone-index'][ringtone]['name']

            entry.snoozedelay=0

            calres[entry.id]=entry

            count+=1

        req=self.protocolclass.callalarmrequest()

        for i in range(0, self.protocolclass._NUMCALLALARMSLOTS):

            self.progress(self.protocolclass._NUMEVENTSLOTS,progressmax,"Call Alarms")

            req.slot=i

            res=self.sendpbcommand(req, self.protocolclass.callalarmresponse)

            if res.entry.flag and res.entry.date:

                self.log("Read call alarm entry "+`i`+" - "+res.entry.phonenum+", alarm ID "+`res.entry.ringtone`)

                entry=bpcalendar.CalendarEntry()

                entry.changeserial=res.entry.serial

                entry.description=res.entry.phonenum

                starttime=res.entry.date

                entry.start=self.decodedate(starttime)

                entry.end=entry.start

                repeat=self._calrepeatvalues[res.entry.period]

                entry.repeat = self.makerepeat(repeat,entry.start)

                entry.alarm=0

                if res.entry.ringtone!=self.calendar_defaultcaringtone:

                    entry.ringtone=result['ringtone-index'][res.entry.ringtone]['name']

                entry.snoozedelay=0

                calres[entry.id]=entry

                count+=1

        result['calendar']=calres

        return result

	def makerepeat(self, repeatword, startdate):

        if repeatword is None:

            repeat_entry=None

        else:

            repeat_entry=bpcalendar.RepeatEntry()

            if repeatword=='daily':

                repeat_entry.repeat_type=repeat_entry.daily

                repeat_entry.interval=1

            elif repeatword=='monfri':

                repeat_entry.repeat_type=repeat_entry.daily

                repeat_entry.interval=0

            elif repeatword=='weekly':

                repeat_entry.repeat_type=repeat_entry.weekly

                repeat_entry.interval=1

                dow=datetime.date(*startdate[:3]).isoweekday()%7

                repeat_entry.dow=1<<dow

            elif repeatword=='monthly':

                repeat_entry.repeat_type=repeat_entry.monthly

            else:

                repeat_entry.repeat_type=repeat_entry.yearly

        return repeat_entry

	def savecalendar(self, dict, merge):

        cal=dict['calendar']

        newcal={}

        keys=cal.keys()

        zonedif=time.mktime(time.gmtime(0))-time.mktime(time.localtime(0))

        try:

            reqflag=self.protocolclass.eventslotinuseupdaterequest()

        except:

            reqflag=0

        eventslot=0

        callslot=0

        progressmax=self.protocolclass._NUMEVENTSLOTS+self.protocolclass._NUMCALLALARMSLOTS

        for k in keys:

            entry=cal[k]

            descloc=entry.description

            self.progress(eventslot+callslot, progressmax, "Writing "+descloc)

            rp=entry.repeat

            if rp is None:

                repeat=0

            else:

                repeatname=None

                if rp.repeat_type==rp.daily:

                    repeatname='daily'

                elif rp.repeat_type==rp.weekly:

                    repeatname='weekly'

                elif rp.repeat_type==rp.monthly:

                    repeatname='monthly'

                elif rp.repeat_type==rp.yearly:

                    repeatname='yearly'

                for k,v in self._calrepeatvalues.items():

                    if repeatname==v:

                        repeat=k

                        break

                    if repeatname is None:

                        self.log(descloc+": Repeat type "+`entry.repeat`+" not valid for this phone")

                        repeat=0

            phonenum=re.sub("\-","",descloc)

            now=time.mktime(time.localtime(time.time()))-zonedif

            if(phonenum.isdigit()):  

                self.log("Write calendar call alarm slot "+`callslot`+ " - "+descloc)

                e=self.protocolclass.callalarmentry()

                e.slot=callslot

                e.phonenum=phonenum

                e.phonenum_len=len(e.phonenum)

                timearray=list(entry.start)+[0,0,0,0]

                starttimelocal=time.mktime(timearray)-zonedif

                if(starttimelocal<now and repeat==0):

                    e.flag=2 

                else:

                    e.flag=1 

                e.date=starttimelocal-self._sanyoepochtounix

                e.datedup=e.date

                e.phonenumbertype=0

                e.phonenumberslot=0

                e.name="" 

                e.name_len=len(e.name)

                e.ringtone=self.calendar_defaultcaringtone

                print "Setting ringtone "+`e.ringtone`

                req=self.protocolclass.callalarmupdaterequest()

                callslot+=1

                respc=self.protocolclass.callalarmresponse

            else: 

                self.log("Write calendar event slot "+`eventslot`+ " - "+descloc)

                e=self.protocolclass.evententry()

                e.slot=eventslot

                slashpos=descloc.find('/')

                if(slashpos >= 0):

                    eventname=descloc[0:slashpos]

                    location=descloc[slashpos+1:]

                else:

                    eventname=descloc

                    location=''

                e.eventname=descloc

                e.eventname_len=len(e.eventname)

                e.location=entry.location

                e.location_len=len(e.location)

                timearray=list(entry.start)+[0,0,0,0]

                starttimelocal=time.mktime(timearray)-zonedif

                e.start=starttimelocal-self._sanyoepochtounix

                try:

                    timearray=list(entry.end)+[0,0,0,0]

                    endtimelocal=time.mktime(timearray)-zonedif

                    e.end=endtimelocal-self._sanyoepochtounix

                except: 

                    e.end=e.start+60 

                alarmdiff=entry.alarm

                if alarmdiff<0:

                    alarmdiff=0

                alarmdiff=max(alarmdiff,0)*60

                e.alarmdiff=alarmdiff

                e.alarm=starttimelocal-self._sanyoepochtounix-alarmdiff

                if reqflag:

                    reqflag.slot=eventslot

                    if(e.alarm+self._sanyoepochtounix<now and repeat==0):

                        reqflag.flag=4 

                    else:

                        reqflag.flag=1 

                    res=self.sendpbcommand(reqflag, self.protocolclass.eventslotinuseresponse)

                else:

                    if(starttimelocal<now and repeat==0):

                        e.flag=2 

                    else:

                        e.flag=1 

                try:

                    timearray=list(entry.end)+[0,0,0,0]

                    endtimelocal=time.mktime(timearray)-zonedif

                    e.end=endtimelocal-self._sanyoepochtounix

                except: 

                    e.end=e.start+60 

                e.ringtone=self.calendar_defaultringtone

                print "Setting ringtone "+`e.ringtone`

                req=self.protocolclass.eventupdaterequest()

                eventslot+=1

                respc=self.protocolclass.eventresponse

            e.period=repeat

            e.dom=entry.start[2]

            if entry.id>=0 and entry.id<256:

                e.serial=entry.id

            else:

                e.serial=0

            req.entry=e

            res=self.sendpbcommand(req, respc, writemode=True)

        if reqflag:

            req=reqflag

            req.flag=0

        else:

            e=self.protocolclass.evententry()

            e.flag=0 

            e.eventname=""

            e.eventname_len=0

            e.location=""

            e.location_len=0

            e.start=0

            e.end=0

            e.period=0

            e.dom=0

            e.ringtone=0

            e.alarm=0

            e.alarmdiff=0

            req=self.protocolclass.eventupdaterequest()

            req.entry=e

        for eventslot in range(eventslot,self.protocolclass._NUMEVENTSLOTS):

            self.progress(eventslot+callslot, progressmax, "Writing unused")

            self.log("Write calendar event slot "+`eventslot`+ " - Unused")

            if reqflag:

                req.slot=eventslot

            else:

                req.entry.slot=eventslot

            res=self.sendpbcommand(req, self.protocolclass.eventresponse, writemode=True)

        e=self.protocolclass.callalarmentry()

        e.flag=0 

        e.name=""

        e.name_len=0

        e.phonenum=""

        e.phonenum_len=0

        e.date=0

        e.datedup=0

        e.period=0

        e.dom=0

        e.ringtone=0

        e.phonenumbertype=0

        e.phonenumberslot=0

        req=self.protocolclass.callalarmupdaterequest()

        req.entry=e

        for callslot in range(callslot,self.protocolclass._NUMCALLALARMSLOTS):

            self.progress(eventslot+callslot, progressmax, "Writing unused")

            self.log("Write calendar call alarm slot "+`callslot`+ " - Unused")

            req.entry.slot=callslot

            res=self.sendpbcommand(req, self.protocolclass.callalarmresponse, writemode=True)

        self.progress(progressmax, progressmax, "Calendar write done")

        dict['rebootphone'] = True

        return dict

	def getcallhistory(self, result):

        res={}

        self._readhistory(self.protocolclass.OUTGOING,'Outgoing',res)

        self._readhistory(self.protocolclass.MISSED,'Missed',res)

        self._readhistory(self.protocolclass.INCOMING,'Incoming',res)

        result['call_history']=res

        return result

	def _readhistory(self, type, folder, res):

        req=self.protocolclass.historyrequest()

        req.type=type

        for slot in range(self.protocolclass.NUMCALLHISTORY):

            req.slot=slot

            call=self.sendpbcommand(req, self.protocolclass.historyresponse)

            if call.entry.phonenum=='' and call.entry.name=='':

                continue

            entry=call_history.CallHistoryEntry()

            entry.folder=folder

            entry.name=call.entry.name

            entry.number=call.entry.phonenum

            entry.datetime=((call.entry.date))

            res[entry.id]=entry

	def decodedate(self,val):

        """Unpack 32 bit value into date/time
        @rtype: tuple
        @return: (year, month, day, hour, minute)
        """

        return list(time.gmtime(val+self._sanyoepochtounix)[:5])

	_calrepeatvalues={
        0: None,
        1: 'daily',
        2: 'weekly',
        3: 'monthly',
        4: 'yearly'
        }
	"Talk to a Sanyo Sprint Phone such as SCP-4900, SCP-5300, or SCP-8100"

def phonize(str):

    """Convert the phone number into something the phone understands
    All digits, P, T, * and # are kept, everything else is removed"""

    return re.sub("[^0-9PT#*]", "", str)

class  Profile (com_phone.Profile) :
	serialsname='sanyo'
	    WALLPAPER_WIDTH=120
	    WALLPAPER_HEIGHT=128
	    OVERSIZE_PERCENTAGE=100
	    MAX_WALLPAPER_BASENAME_LENGTH=19
	    WALLPAPER_FILENAME_CHARS="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 .`~!@#$%^&()-_=+[{]};\'"
	    WALLPAPER_CONVERT_FORMAT="png"
	    MAX_RINGTONE_BASENAME_LENGTH=19
	    RINGTONE_FILENAME_CHARS="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 .`~!@#$%^&()-_=+[{]};\'"
	    usbids=( ( 0x0474, 0x0701, 1),  
        )
	    deviceclasses=("modem",)
	    BP_Calendar_Version=3
	    def __init__(self):

        self.numbertypetab=numbertypetab

        com_phone.Profile.__init__(self)

	_supportedsyncs=(
        ('phonebook', 'read', None),  
        ('calendar', 'read', None),   
        ('phonebook', 'write', 'OVERWRITE'),  
        ('calendar', 'write', 'OVERWRITE'),   
        ('wallpaper', 'write', 'MERGE'),
        ('ringtone', 'write', 'MERGE'),
        ('call_history', 'read', None),
        ('sms', 'read', None),
        )
	    def convertphonebooktophone(self, helper, data):

        "Converts the data to what will be used by the phone"

        results={}

        slotsused={}

        for pbentry in data['phonebook']:

            entry=data['phonebook'][pbentry]

            serial1=helper.getserial(entry.get('serials', []), self.serialsname, data['uniqueserial'], 'serial1', -1)

            if(serial1 >= 0 and serial1 < self.protocolclass._NUMPBSLOTS):

                slotsused[serial1]=1

        lastunused=0 

        for pbentry in data['phonebook']:

            e={} 

            entry=data['phonebook'][pbentry] 

            try:

                try:

                    e['name']=helper.getfullname(entry.get('names', []),1,1,16)[0]

                except:

                    e['name']=''

                e['name_len']=len(e['name'])

                serial1=helper.getserial(entry.get('serials', []), self.serialsname, data['uniqueserial'], 'serial1', -1)

                if(serial1 >= 0 and serial1 < self.protocolclass._NUMPBSLOTS):

                    e['slot']=serial1

                else:  

                    while(slotsused.has_key(lastunused)):

                        lastunused+=1

                        if(lastunused >= self.protocolclass._NUMPBSLOTS):

                            raise helper.ConversionFailed()

                    e['slot']=lastunused

                    slotsused[lastunused]=1

                e['slotdup']=e['slot']

                e['email']=helper.makeone(helper.getemails(entry.get('emails', []),0,1,self.protocolclass._MAXEMAILLEN), "")

                e['email_len']=len(e['email'])

                e['url']=helper.makeone(helper.geturls(entry.get('urls', []), 0,1,self.protocolclass._MAXEMAILLEN), "")

                e['url_len']=len(e['url'])

                numbers=helper.getnumbers(entry.get('numbers', []),0,7)

                e['numbertypes']=[]

                e['numbers']=[]

                e['speeddials']=[]

                unusednumbers=[] 

                typesused={}

                defaultnum=0

                for num in numbers:

                    typename=num['type']

                    if(typesused.has_key(typename)):

                        unusednumbers.append(num)

                        continue

                    typesused[typename]=1

                    for typenum,tnsearch in enumerate(self.numbertypetab):

                        if typename==tnsearch:

                            if defaultnum==0:

                                defaultnum=typenum+1

                            number=phonize(num['number'])

                            if len(number)>self.protocolclass._MAXNUMBERLEN: 

                                number=number[:self.protocolclass._MAXNUMBERLEN]

                            e['numbers'].append(number)

                            if(num.has_key('speeddial')):

                                e['speeddials'].append(num['speeddial'])

                            else:

                                e['speeddials'].append(-1)

                            e['numbertypes'].append(typenum)

                            break

                trytype=len(self.numbertypetab)

                for num in unusednumbers:

                    while trytype>0:

                        trytype-=1

                        if not typesused.has_key(self.numbertypetab[trytype]):

                            break

                    else:

                        break

                    if defaultnum==0:

                        defaultnum=trytype+1

                    number=phonize(num['number'])

                    if len(number)>self.protocolclass._MAXNUMBERLEN: 

                        number=number[:self.protocolclass._MAXNUMBERLEN]

                    e['numbers'].append(number)

                    e['numbertypes'].append(trytype)

                    if(num.has_key('speeddial')):

                        e['speeddials'].append(num['speeddial'])

                    else:

                        e['speeddials'].append(-1)

                if defaultnum==0:

                    if e['url_len'] > 0:

                        defaultnum=8

                    elif e['email_len'] > 0:

                        defaultnum=9

                e['ringtone']=helper.getringtone(entry.get('ringtones', []), 'call', None)

                e['wallpaper']=helper.getwallpaper(entry.get('wallpapers', []), 'call', None)

                e['secret']=helper.getflag(entry.get('flags', []), 'secret', False)

                e['defaultnum']=defaultnum

                results[pbentry]=e

            except helper.ConversionFailed:

                print "No Free Slot for "+e['name']

                continue

        data['phonephonebook']=results

        return data


class  Phone (SanyoPhonebook,com_phone.Phone,com_brew.BrewProtocol) :
	"Talk to a Sanyo Sprint Phone such as SCP-4900, SCP-5300, or SCP-8100"
	    desc="Sanyo"
	    imagelocations=()
	    ringtonelocations=()
	    builtinimages=()
	    builtinringtones=()
	    def __init__(self, logtarget, commport):

        "Call all the contructors and sets initial modes"

        com_phone.Phone.__init__(self, logtarget, commport)

        com_brew.BrewProtocol.__init__(self)

        SanyoPhonebook.__init__(self)

        self.log("Attempting to contact phone")

        self.mode=self.MODENONE

	getwallpapers=None
	    getringtones=None
	"Talk to a Sanyo Sprint Phone such as SCP-4900, SCP-5300, or SCP-8100"
Example #13
0
    def sendpbcommand(
        self, request, responseclass, callsetmode=True, writemode=False, numsendretry=0, returnerror=False
    ):
        if writemode:
            numretry = 3
        else:
            numretry = 0

        if callsetmode:
            self.setmode(self.MODEPHONEBOOK)
        buffer = prototypes.buffer()

        request.writetobuffer(buffer, logtitle="Samsung phonebook request")
        data = buffer.getvalue()
        firsttwo = data[:2]
        data = common.pppescape(data + common.crcs(data)) + common.pppterminator
        isendretry = numsendretry
        while isendretry >= 0:
            try:
                rdata = self.comm.writethenreaduntil(
                    data, False, common.pppterminator, logreaduntilsuccess=False, numfailures=numretry
                )
                break
            except com_phone.modeignoreerrortypes:
                if isendretry > 0:
                    self.log("Resending request packet...")
                    time.sleep(0.3)
                else:
                    self.comm.success = False
                    self.mode = self.MODENONE
                    self.raisecommsdnaexception("manipulating the phonebook")
                isendretry -= 1

        self.comm.success = True

        origdata = rdata
        # sometimes there is junk at the beginning, eg if the user
        # turned off the phone and back on again.  So if there is more
        # than one 7e in the escaped data we should start after the
        # second to last one
        d = rdata.rfind(common.pppterminator, 0, -1)
        if d >= 0:
            self.log("Multiple Samsung packets in data - taking last one starting at " + ` d + 1 `)
            self.logdata("Original Samsung data", origdata, None)
            rdata = rdata[d + 1 :]

        # turn it back to normal
        data = common.pppunescape(rdata)

        # Sometimes there is other crap at the beginning.  But it might
        # be a Sanyo error byte.  So strip off bytes from the beginning
        # until the crc agrees, or we get to the first two bytes of the
        # request packet.
        d = data.find(firsttwo)
        crc = data[-3:-1]
        crcok = False
        for i in range(0, d + 1):
            trydata = data[i:-3]
            if common.crcs(trydata) == crc:
                crcok = True
                break

        if not crcok:
            self.logdata("first two", firsttwo, None)
            self.logdata("Original Sanyo data", origdata, None)
            self.logdata("Working on Sanyo data", data, None)
            raise common.CommsDataCorruption("Sanyo packet failed CRC check", self.desc)

        res = responseclass()
        if d > 0:
            if d == i:
                self.log("Junk at beginning of Sanyo packet, data at " + ` d `)
                self.logdata("Original Sanyo data", origdata, None)
                self.logdata("Working on Sanyo data", data, None)
            else:
                if returnerror:
                    res = self.protocolclass.sanyoerror()
                else:
                    self.log("Sanyo Error code " + ` ord(data[0]) `)
                    self.logdata("sanyo phonebook response", data, None)
                    raise SanyoCommandException(ord(data[0]))

        data = trydata

        # parse data
        buffer = prototypes.buffer(data)
        res.readfrombuffer(buffer, logtitle="sanyo phonebook response")
        return res