PyXR

c:\projects\bitpim\src \ phones \ com_samsungsphn400.py



0001 ### BITPIM
0002 ###
0003 ### Copyright (C) 2006 Stephen Wood <saw@bitpim.org>
0004 ###
0005 ### This program is free software; you can redistribute it and/or modify
0006 ### it under the terms of the BitPim license as detailed in the LICENSE file.
0007 ###
0008 ### $Id: com_samsungsphn400.py 3918 2007-01-19 05:15:12Z djpham $
0009 
0010 """Communicate with a Samsung SPH-N400"""
0011 
0012 # standard modules
0013 import sha
0014 
0015 # Bitpim modules
0016 import p_brew
0017 import p_samsungsphn400
0018 import com_brew
0019 import com_phone
0020 import prototypes
0021 import common
0022 import commport
0023 import helpids
0024 
0025 class N400CommandException(Exception):
0026     def __init__(self, errnum, str=None):
0027         if str is None:
0028             str="N400 Packet Error 0x%02x" % (errnum,)
0029         Exception.__init__(self, str)
0030         self.errnum=errnum
0031 
0032 numbertypetab=( 'home', 'office', 'cell', 'pager', 'fax', 'none' )
0033 
0034 class Phone(com_phone.Phone,com_brew.BrewProtocol):
0035     "Talk to a Samsung SPH-N400 cell phone"
0036 
0037     desc="SPH-N400"
0038     helpid=helpids.ID_PHONE_SAMSUNGOTHERS
0039     MODEPHONEBOOK="modephonebook"
0040     
0041     protocolclass=p_samsungsphn400
0042     serialsname='sphn400'
0043 
0044     def __init__(self, logtarget, commport):
0045         com_phone.Phone.__init__(self, logtarget, commport)
0046         com_brew.BrewProtocol.__init__(self)
0047         self.mode=self.MODENONE
0048 
0049     def getfundamentals(self, results):
0050         self.log("Retrieving fundamental phone information")
0051         self.log("Phone serial number")
0052 
0053         self.setmode(self.MODEPHONEBOOK)
0054 
0055         req=p_brew.ESN_req()
0056         res=self.sendpbcommand(req, p_brew.ESN_resp)
0057         results['uniqueserial']=sha.new('%8.8X' % res.esn).hexdigest()
0058 
0059         return results
0060  
0061     def _setmodephonebook(self):
0062         req=self.protocolclass.firmwarerequest()
0063         respc=self.protocolclass.firmwareresponse
0064 
0065         for baud in 38400, 57600:
0066             if not self.comm.setbaudrate(baud):
0067                 continue
0068 
0069             # Perhaps overkill.  Will experiment more
0070             self.comm.setrts(1)
0071             self.comm.setdtr(1)
0072 
0073             self.comm.setbaudrate(baud)
0074             self.comm.setrts(0)
0075             self.comm.setdtr(1)
0076 
0077             self.comm.setbaudrate(baud)
0078             self.comm.setrts(0)
0079             self.comm.setdtr(0)
0080 
0081             self.comm.setbaudrate(baud)
0082             self.comm.setrts(0)
0083             self.comm.setdtr(0)
0084 
0085             self.comm.setbaudrate(baud)
0086             self.comm.setrts(0)
0087             self.comm.setdtr(0)
0088 
0089             try:
0090                 self.sendpbcommand(req, respc, callsetmode=False)
0091                 return True
0092             except com_phone.modeignoreerrortypes:
0093                 pass
0094             
0095         return 0
0096 
0097     def sendpbcommand(self, request, responseclass, callsetmode=True, writemode=False, numsendretry=0, returnerror=False):
0098         if writemode:
0099             numretry=3
0100         else:
0101             numretry=0
0102             
0103         if callsetmode:
0104             self.setmode(self.MODEPHONEBOOK)
0105         buffer=prototypes.buffer()
0106 
0107         request.writetobuffer(buffer, logtitle="N400 phonebook request")
0108         data=buffer.getvalue()
0109         firsttwo=data[:2]
0110         data=common.pppescape(data+common.crcs(data))+common.pppterminator
0111         isendretry=numsendretry
0112         while isendretry>=0:
0113             try:
0114                 rdata=self.comm.writethenreaduntil(data, False, common.pppterminator, logreaduntilsuccess=False, numfailures=numretry)
0115                 break
0116             except com_phone.modeignoreerrortypes:
0117                 if isendretry>0:
0118                     self.log("Resending request packet...")
0119                     time.sleep(0.3)
0120                 else:
0121                     self.comm.success=False
0122                     self.mode=self.MODENONE
0123                     self.raisecommsdnaexception("manipulating the phonebook")
0124                 isendretry-=1
0125 
0126         self.comm.success=True
0127 
0128         origdata=rdata
0129         # sometimes there is junk at the beginning, eg if the user
0130         # turned off the phone and back on again.  So if there is more
0131         # than one 7e in the escaped data we should start after the
0132         # second to last one
0133         d=rdata.rfind(common.pppterminator,0,-1)
0134         if d>=0:
0135             self.log("Multiple N400 packets in data - taking last one starting at "+`d+1`)
0136             self.logdata("Original N400 data", origdata, None)
0137             rdata=rdata[d+1:]
0138 
0139         # turn it back to normal
0140         data=common.pppunescape(rdata)
0141 
0142         # Sometimes there is other crap at the beginning.  But it might
0143         # be a N400 error byte.  So strip off bytes from the beginning
0144         # until the crc agrees, or we get to the first two bytes of the
0145         # request packet.
0146         d=data.find(firsttwo)
0147         crc=data[-3:-1]
0148         crcok=False
0149         for i in range(0,d+1):
0150             trydata=data[i:-3]
0151             if common.crcs(trydata)==crc:
0152                 crcok=True
0153                 break
0154 
0155         if not crcok:
0156             self.logdata("first two",firsttwo, None)
0157             self.logdata("Original N400 data", origdata, None)
0158             self.logdata("Working on N400 data", data, None)
0159             raise common.CommsDataCorruption("N400 packet failed CRC check", self.desc)
0160 
0161         res=responseclass()
0162         if d>0:
0163             if d==i:
0164                 self.log("Junk at beginning of N400 packet, data at "+`d`)
0165                 self.logdata("Original N400 data", origdata, None)
0166                 self.logdata("Working on N400 data", data, None)
0167             else:
0168                 if returnerror:
0169                     res=self.protocolclass.sanyoerror()
0170                 else:
0171                     self.log("N400 Error code "+`ord(data[0])`)
0172                     self.logdata("Samsung phonebook response", data, None)
0173                     raise N400CommandException(ord(data[0]))
0174             
0175         data=trydata
0176 
0177         # parse data
0178         buffer=prototypes.buffer(data)
0179         res.readfrombuffer(buffer, logtitle="sanyo phonebook response")
0180         return res
0181 
0182     def getphonebook(self, result):
0183         pbook={}
0184 
0185         reqname=self.protocolclass.phonebooknamerequest()
0186         reqnumbers=self.protocolclass.phonebooknumbersrequest()
0187         count = 0
0188         for i in range(2, 251):
0189             reqname.slot=i
0190             resname=self.sendpbcommand(reqname, self.protocolclass.phonebooknameresponse)
0191             if resname.entry.nonzeroifused:
0192                 entry={}
0193                 entry['serials']=[ {'sourcetype': self.serialsname,
0194                           'slot': i,
0195                           'sourceuniqueid': result['uniqueserial']} ]
0196                 entry['names']=[{'full': resname.entry.name} ]
0197                 entry['numbers'] = []
0198                 for i in range(7):
0199                     numptr = resname.entry.numbers[i].pnumber
0200                     if numptr:
0201                         reqnumbers.slot=numptr
0202                         resnumbers=self.sendpbcommand(reqnumbers, self.protocolclass.phonebooknumbersresponse)
0203                         numhash={'number': resnumbers.entry.number, 'type': numbertypetab[i]}
0204                         if numptr==resname.entry.pspeed:
0205                             numhash['speeddial']=i
0206                         entry['numbers'].append(numhash)
0207 
0208                 if resname.entry.pemail:
0209                     reqnumbers.slot=resname.entry.pemail
0210                     resnumbers=self.sendpbcommand(reqnumbers, self.protocolclass.phonebooknumbersresponse)
0211                     entry['emails']=[{'email': resnumbers.entry.number}]
0212 
0213                 if resname.entry.purl:
0214                     reqnumbers.slot=resname.entry.purl
0215                     resnumbers=self.sendpbcommand(reqnumbers, self.protocolclass.phonebooknumbersresponse)
0216                     entry['urls']=[{'url': resnumbers.entry.number}]
0217                 
0218                 self.log("Read entry "+`i`+": "+resname.entry.name)
0219                 pbook[count]=entry
0220                 count+=1
0221 
0222         result['phonebook']=pbook
0223         return result
0224 
0225     def getcalendar(self, result):
0226         pbook={}
0227         result['calendar']=pbook
0228         return result
0229 
0230     def getwallpapers(self, results):
0231         pass
0232         
0233     def getringtones(self, results):
0234         pass
0235 
0236 
0237 class Profile(com_phone.Profile):
0238     protocolclass=Phone.protocolclass
0239     serialsname=Phone.serialsname
0240     phone_manufacturer='SAMSUNG'
0241     phone_model='SPH-N400'
0242     usbids_usbtoserial=(
0243         ( 0x067b, 0x2303, None), # VID=Prolific, PID=USB to serial
0244         ( 0x0403, 0x6001, None), # VID=FTDI, PID=USB to serial
0245         ( 0x0731, 0x2003, None), # VID=Susteen, PID=Universal USB to serial
0246         )
0247     usbids=usbids_usbtoserial
0248     
0249     deviceclasses=("serial",)
0250 
0251     def __init__(self):
0252         com_phone.Profile.__init__(self)
0253         
0254     _supportedsyncs=(
0255         ('phonebook', 'read', None),
0256         )
0257 
0258 

Generated by PyXR 0.9.4