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