0001 ### BITPIM 0002 ### 0003 ### Copyright (C) 2005 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_samsungsphn200.py 2533 2005-09-23 02:49:11Z sawecw $ 0009 0010 """Communicate with a Samsung SPH-N200""" 0011 0012 import sha 0013 import re 0014 import struct 0015 0016 import common 0017 import commport 0018 import time 0019 import p_samsungsphn200 0020 import p_brew 0021 import com_brew 0022 import com_phone 0023 import com_samsung_packet 0024 import prototypes 0025 0026 numbertypetab=('home','office','cell','pager','fax','none') 0027 0028 class Phone(com_samsung_packet.Phone): 0029 "Talk to a Samsung SPH-N200 phone" 0030 0031 desc="SPH-N200" 0032 0033 protocolclass=p_samsungsphn200 0034 serialsname='sphn200' 0035 __groups_range=xrange(5) 0036 0037 imagelocations=() 0038 # offset, index file, files location, type, maximumentries 0039 0040 __ams_index_file="ams/AmsRegistry" 0041 0042 def __init__(self, logtarget, commport): 0043 com_samsung_packet.Phone.__init__(self, logtarget, commport) 0044 self.numbertypetab=numbertypetab 0045 self.mode=self.MODENONE 0046 0047 def getfundamentals(self, results): 0048 """Gets information fundamental to interopating with the phone and UI.""" 0049 0050 # use a hash of ESN and other stuff (being paranoid) 0051 self.log("Retrieving fundamental phone information") 0052 self.log("Phone serial number") 0053 print "Calling setmode MODEMODEM" 0054 self.setmode(self.MODEMODEM) 0055 print "Getting serial number" 0056 results['uniqueserial']=sha.new(self.get_esn()).hexdigest() 0057 0058 self.log("Fundamentals retrieved") 0059 return results 0060 0061 def _setmodemodem(self): 0062 self.log("_setmodemodem") 0063 0064 # Just try waking phone up first 0065 try: 0066 self.comm.sendatcommand("Z") 0067 self.comm.sendatcommand('E0V1') 0068 return True 0069 except: 0070 pass 0071 0072 # Should be in modem mode. Wake up the interface 0073 for baud in (0, 19200, 38400, 115200): 0074 self.log("Baud="+`baud`) 0075 if baud: 0076 if not self.comm.setbaudrate(baud): 0077 continue 0078 0079 try: 0080 self.comm.sendatcommand("Z") 0081 self.comm.sendatcommand('E0V1') 0082 return True 0083 except: 0084 pass 0085 0086 return False 0087 0088 def getphonebook(self, result): 0089 """Read the phonebook data.""" 0090 pbook={} 0091 self.setmode(self.MODEPHONEBOOK) 0092 0093 count=0 0094 req=self.protocolclass.phonebookslotrequest() 0095 for slot in range(2,self.protocolclass.NUMPHONEBOOKENTRIES+1): 0096 req.slot=slot 0097 res=self.sendpbcommand(req, self.protocolclass.phonebookslotresponse, fixup=self.pblinerepair) 0098 if len(res) > 0: 0099 lastname=res[0].entry.name 0100 self.log(`slot`+": "+lastname) 0101 entry=self.extractphonebookentry(res[0].entry, result) 0102 pbook[count]=entry 0103 count+=1 0104 self.progress(slot, self.protocolclass.NUMPHONEBOOKENTRIES, lastname) 0105 result['phonebook']=pbook 0106 0107 return pbook 0108 0109 def extractphonebookentry(self, entry, fundamentals): 0110 res={} 0111 0112 res['serials']=[ {'sourcetype': self.serialsname, 0113 'slot': entry.slot, 0114 'sourceuniqueid': fundamentals['uniqueserial']} ] 0115 # only one name 0116 res['names']=[ {'full': entry.name} ] 0117 0118 res['numbers']=[] 0119 secret=0 0120 0121 for i in range(len(entry.numbers)): 0122 type = self.numbertypetab[entry.numbers[i].numbertype - 1] 0123 numhash = {'number': entry.numbers[i].number, 'type': type } 0124 res['numbers'].append(numhash) 0125 0126 # Field after each number is secret flag. Setting secret on 0127 # phone sets secret flag for every defined phone number 0128 res['flags']=[ {'secret': secret} ] 0129 0130 return res 0131 0132 def savephonebook(self, data): 0133 "Saves out the phonebook" 0134 0135 self.setmode(self.MODEPHONEBOOK) 0136 pb=data['phonebook'] 0137 keys=pb.keys() 0138 keys.sort() 0139 0140 keys=keys[:self.protocolclass.NUMPHONEBOOKENTRIES+1] 0141 0142 # 0143 # Read the existing phonebook so that we cache birthdays 0144 # Erase all entries, being carefull to modify entries with 0145 # with URL's first 0146 # 0147 uslots={} 0148 names={} 0149 0150 req=self.protocolclass.phonebooksloterase() 0151 self.log('Erasing '+self.desc+' phonebook') 0152 progressmax=self.protocolclass.NUMPHONEBOOKENTRIES+len(keys) 0153 for slot in range(2,self.protocolclass.NUMPHONEBOOKENTRIES+1): 0154 req.slot = slot 0155 self.progress(slot,progressmax,"Erasing "+`slot`) 0156 res=self.sendpbcommand(req, self.protocolclass.phonebookslotupdateresponse) 0157 0158 0159 for i in range(len(keys)): 0160 slot=keys[i] 0161 req=self.protocolclass.phonebookslotupdaterequest() 0162 req.entry=self.makeentry(pb[slot],data) 0163 self.log('Writing entry '+`slot`+" - "+req.entry.name) 0164 self.progress(i+self.protocolclass.NUMPHONEBOOKENTRIES,progressmax,"Writing "+req.entry.name) 0165 self.sendpbcommand(req, self.protocolclass.phonebookslotupdateresponse) 0166 self.progress(progressmax+1,progressmax+1, "Phone book write completed") 0167 return data 0168 0169 def makeentry(self, entry, data): 0170 e=self.protocolclass.pbentry() 0171 0172 for k in entry: 0173 # special treatment for lists 0174 if k=='numbertypes' or k=='secrets': 0175 continue 0176 if k=='ringtone': 0177 # e.ringtone=self._findmediaindex(data['ringtone-index'], entry['ringtone'], entry['name'], 'ringtone') 0178 continue 0179 elif k=='wallpaper': 0180 # e.wallpaper=self._findmediaindex(data['wallpaper-index'], entry['wallpaper'], entry['name'], 'wallpaper') 0181 continue 0182 elif k=='numbers': 0183 #l=getattr(e,k) 0184 nnum=len(entry[k]) 0185 for i in range(nnum): 0186 enpn=self.protocolclass.phonenumber() 0187 if i+1 == nnum: 0188 enpn.last_number=True 0189 enpn.numbertype=entry['numbertypes'][i]+1 0190 enpn.number=entry[k][i] 0191 e.numbers.append(enpn) 0192 continue 0193 # everything else we just set 0194 setattr(e, k, entry[k]) 0195 return e 0196 0197 0198 getwallpapers=None 0199 getringtones=None 0200 0201 class Profile(com_samsung_packet.Profile): 0202 protocolclass=Phone.protocolclass 0203 serialsname=Phone.serialsname 0204 phone_manufacturer='SAMSUNG' 0205 phone_model='SPH-N200' 0206 deviceclasses=("serial",) 0207 0208 def __init__(self): 0209 com_samsung_packet.Profile.__init__(self) 0210 self.numbertypetab=numbertypetab 0211 0212 _supportedsyncs=( 0213 ('phonebook', 'read', None), # all phonebook reading 0214 ('phonebook', 'write', 'OVERWRITE'), # only overwriting phonebook 0215 ) 0216 0217 def convertphonebooktophone(self, helper, data): 0218 """Converts the data to what will be used by the phone 0219 0220 @param data: contains the dict returned by getfundamentals 0221 as well as where the results go""" 0222 0223 results={} 0224 0225 # find which entries are already known to this phone 0226 pb=data['phonebook'] 0227 # decorate list with (slot, pbkey) tuples 0228 slots=[ (helper.getserial(pb[pbentry].get("serials", []), self.serialsname, data['uniqueserial'], "slot", None), pbentry) 0229 for pbentry in pb] 0230 slots.sort() # numeric order 0231 # make two lists - one contains known slots, one doesn't 0232 newones=[(pbentry,slot) for slot,pbentry in slots if slot is None] 0233 existing=[(pbentry,slot) for slot,pbentry in slots if slot is not None] 0234 0235 uslotsused={} 0236 0237 tempslot=0 # Temporarily just pick slots and speed dial in order 0238 for pbentry,slot in existing+newones: 0239 0240 if len(results)==self.protocolclass.NUMPHONEBOOKENTRIES: 0241 break 0242 0243 try: 0244 0245 e={} # entry out 0246 0247 entry=data['phonebook'][pbentry] 0248 0249 secret=helper.getflag(entry.get('flags', []), 'secret', False) 0250 if secret: 0251 secret=1 0252 else: 0253 secret=0 0254 0255 # name 0256 e['name']=helper.getfullname(entry.get('names', []),1,1,12)[0] 0257 0258 cat=helper.makeone(helper.getcategory(entry.get('cagetgories',[]),0,1,12), None) 0259 0260 # phone numbers 0261 # there must be at least one phone number 0262 minnumbers=1 0263 numbers=helper.getnumbers(entry.get('numbers', []),minnumbers,self.protocolclass.NUMPHONENUMBERS) 0264 e['numbertypes']=[] 0265 e['numbers']=[] 0266 e['secrets']=[] 0267 unusednumbers=[] # Hold duplicate types here 0268 typesused={} 0269 defaulttypenum=0 0270 for num in numbers: 0271 typename=num['type'] 0272 if typesused.has_key(typename): 0273 unusednumbers.append(num) 0274 continue 0275 typesused[typename]=1 0276 for typenum,tnsearch in enumerate(self.numbertypetab): 0277 if typename==tnsearch: 0278 if defaulttypenum==0: 0279 defaulttypenum=typenum 0280 number=self.phonize(num['number']) 0281 if len(number)>self.protocolclass.MAXNUMBERLEN: 0282 # :: TODO:: number is too long and we have to either truncate it or ignore it? 0283 number=number[:self.protocolclass.MAXNUMBERLEN] 0284 e['numbers'].append(number) 0285 if(num.has_key('speeddial')): 0286 # Only one number per name can be a speed dial 0287 # Should make speed dial be the first that 0288 # we come accross 0289 e['speeddial']=typenum 0290 tryuslot = num['speeddial'] 0291 e['numbertypes'].append(typenum) 0292 e['secrets'].append(secret) 0293 0294 break 0295 0296 # Should print to log when a requested speed dial slot is 0297 # not available 0298 if e.has_key('speeddial'): 0299 if tryuslot>=1 and tryuslot<=self.protocolclass.NUMPHONEBOOKENTRIES and not uslotsused.has_key(tryuslot): 0300 uslotsused[tryuslot]=1 0301 e['uslot']=tryuslot 0302 else: 0303 e['speeddial']=defaulttypenum 0304 0305 # find the right slot 0306 if slot is None or slot<2 or slot>self.protocolclass.NUMPHONEBOOKENTRIES or slot in results: 0307 for i in range(2,100000): 0308 if i not in results: 0309 slot=i 0310 break 0311 0312 e['slot']=slot 0313 0314 results[slot]=e 0315 except helper.ConversionFailed: 0316 continue 0317 0318 # Fill in uslot for entries that don't have it. 0319 0320 tryuslot=1 0321 for slot in results.keys(): 0322 0323 e=results[slot] 0324 if not e.has_key('uslot'): 0325 while tryuslot<self.protocolclass.NUMPHONEBOOKENTRIES and uslotsused.has_key(tryuslot): 0326 tryuslot += 1 0327 uslotsused[tryuslot]=1 0328 e['uslot'] = tryuslot 0329 results[slot] = e 0330 0331 data['phonebook']=results 0332 return data 0333 0334 def phonize(self,str): 0335 """Convert the phone number into something the phone understands 0336 All digits, P, T, * and # are kept, everything else is removed""" 0337 0338 return re.sub("[^0-9PT#*]", "", str)[:self.protocolclass.MAXNUMBERLEN] 0339 0340
Generated by PyXR 0.9.4