0001 ### BITPIM 0002 ### 0003 ### Copyright (C) 2005 Joe Pham <djpham@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_lgg4015.py 4365 2007-08-17 21:11:59Z djpham $ 0009 0010 """Communicate with the LG G4015 cell phone 0011 """ 0012 0013 # standard modules 0014 import base64 0015 import sha 0016 import time 0017 0018 # BitPim modules 0019 import bpcalendar 0020 import common 0021 import commport 0022 import com_etsi 0023 import guihelper 0024 import helpids 0025 import memo 0026 import nameparser 0027 import p_lgg4015 0028 import prototypes 0029 import sms 0030 0031 class Phone(com_etsi.Phone): 0032 """ Talk to the LG G4015 Phone""" 0033 0034 desc='LG-G4015' 0035 helpid=helpids.ID_PHONE_LGG4015 0036 protocolclass=p_lgg4015 0037 serialsname='lgg4015' 0038 0039 def __init__(self, logtarget, commport): 0040 super(Phone,self).__init__(logtarget, commport) 0041 self.mode=self.MODENONE 0042 0043 def getfundamentals(self, results): 0044 0045 """Gets information fundamental to interoperating with the phone and UI. 0046 0047 Currently this is: 0048 0049 - 'uniqueserial' a unique serial number representing the phone 0050 - 'groups' the phonebook groups 0051 - 'wallpaper-index' map index numbers to names 0052 - 'ringtone-index' map index numbers to ringtone names 0053 0054 This method is called before we read the phonebook data or before we 0055 write phonebook data. 0056 """ 0057 # use a hash of ESN and other stuff (being paranoid) 0058 self.setmode(self.MODEMODEM) 0059 self.log("Retrieving fundamental phone information") 0060 self.log("Reading phone serial number") 0061 results['uniqueserial']=sha.new(self.get_sim_id()).hexdigest() 0062 # now read groups 0063 self.log("Reading group information") 0064 results['groups']=self._get_groups() 0065 # getting rintone-index 0066 self.log('Reading Ringtone Index') 0067 results['ringtone-index']=self._get_ringtone_index() 0068 # getting wallpaper-index 0069 self.log('Reading Wallpaper Index') 0070 results['wallpaper-index']=self._get_wallpaper_index() 0071 # All done 0072 self.log("Fundamentals retrieved") 0073 return results 0074 0075 def _get_groups(self): 0076 res={} 0077 self.charset_ascii() 0078 _req=self.protocolclass.list_group_req() 0079 for i in self.protocolclass.GROUP_INDEX_RANGE: 0080 _req.start_index=i 0081 _req.end_index=i 0082 try: 0083 _res=self.sendATcommand(_req, self.protocolclass.list_group_resp) 0084 if _res and _res[0].group_name: 0085 res[i]={ 'name': _res[0].group_name } 0086 except: 0087 if __debug__: 0088 raise 0089 return res 0090 0091 def _ringtone_mode(self): 0092 _req=self.protocolclass.media_selector_set() 0093 _req.media_type=self.protocolclass.MEDIA_RINGTONE 0094 self.sendATcommand(_req, None) 0095 0096 def _get_ringtone_index(self): 0097 """ Return the ringtone index""" 0098 res={} 0099 # Set the media type to be sound (ringtone) 0100 self.charset_ascii() 0101 self._ringtone_mode() 0102 # and read the list 0103 _req=self.protocolclass.media_list_req() 0104 _req.start_index=self.protocolclass.MIN_RINGTONE_INDEX 0105 _req.end_index=self.protocolclass.MAX_RINGTONE_INDEX 0106 _res=self.sendATcommand(_req, self.protocolclass.media_list_resp) 0107 for i,e in enumerate(_res): 0108 res[i]={ 'name': e.file_name, 'origin': 'ringtone' } 0109 return res 0110 0111 def _wallpaper_mode(self): 0112 _req=self.protocolclass.media_selector_set() 0113 _req.media_type=self.protocolclass.MEDIA_WALLPAPER 0114 self.sendATcommand(_req, None) 0115 0116 def _get_wallpaper_index(self): 0117 """ Return the wallpaper index""" 0118 res={} 0119 # Set the media type to be pic (wallpaper) 0120 self.charset_ascii() 0121 self._wallpaper_mode() 0122 # and read the list 0123 _req=self.protocolclass.media_list_req() 0124 _req.start_index=self.protocolclass.MIN_WALLPAPER_INDEX 0125 _req.end_index=self.protocolclass.MAX_WALLPAPER_INDEX 0126 _res=self.sendATcommand(_req, self.protocolclass.media_list_resp) 0127 for i,e in enumerate(_res): 0128 res[i]={ 'name': e.file_name, 'origin': 'wallpaper' } 0129 return res 0130 0131 # Calendar stuff----------------------------------------------------------- 0132 cal_repeat_value={ 0133 protocolclass.CAL_REP_DAILY: bpcalendar.RepeatEntry.daily, 0134 protocolclass.CAL_REP_WEEKLY: bpcalendar.RepeatEntry.weekly, 0135 protocolclass.CAL_REP_MONTHLY: bpcalendar.RepeatEntry.monthly, 0136 protocolclass.CAL_REP_YEARLY: bpcalendar.RepeatEntry.yearly } 0137 cal_repeat_value_r={ 0138 bpcalendar.RepeatEntry.daily: protocolclass.CAL_REP_DAILY, 0139 bpcalendar.RepeatEntry.weekly: protocolclass.CAL_REP_WEEKLY, 0140 bpcalendar.RepeatEntry.monthly: protocolclass.CAL_REP_MONTHLY, 0141 bpcalendar.RepeatEntry.yearly: protocolclass.CAL_REP_YEARLY } 0142 0143 def _build_bpcalendar_entry(self, phone_entry): 0144 entry=bpcalendar.CalendarEntry() 0145 entry.start=phone_entry.date+phone_entry.time 0146 entry.end=phone_entry.date+phone_entry.time 0147 entry.description=phone_entry.description 0148 entry.serials.append({ 'sourcetype': 'phone', 0149 'id': phone_entry.index }) 0150 entry.alarm=self.protocolclass.CAL_ALARM_VALUE.get(phone_entry.alarm, -1) 0151 _rpt_type=self.cal_repeat_value.get(phone_entry.repeat, None) 0152 if _rpt_type: 0153 # this is a recurrent event 0154 rpt=bpcalendar.RepeatEntry(_rpt_type) 0155 if _rpt_type!=bpcalendar.RepeatEntry.yearly: 0156 rpt.interval=1 0157 # repeat forever 0158 entry.end=bpcalendar.CalendarEntry.no_end_date 0159 entry.repeat=rpt 0160 return entry 0161 0162 def getcalendar(self, result): 0163 self.log("Getting calendar entries") 0164 self.setmode(self.MODEMODEM) 0165 self.charset_ascii() 0166 res={} 0167 _req=self.protocolclass.calendar_read_req() 0168 _req.start_index=self.protocolclass.CAL_MIN_INDEX 0169 _req.end_index=self.protocolclass.CAL_MAX_INDEX 0170 _res=self.sendATcommand(_req, self.protocolclass.calendar_read_resp) 0171 for e in _res: 0172 try: 0173 _entry=self._build_bpcalendar_entry(e) 0174 res[_entry.id]=_entry 0175 except: 0176 if __debug__: 0177 raise 0178 result['calendar']=res 0179 return result 0180 0181 def _build_phone_cal_entry(self, entry_count, bpentry): 0182 entry=self.protocolclass.calendar_write_req() 0183 entry.index=entry_count 0184 entry.date=bpentry.start[:3] 0185 if bpentry.allday: 0186 entry.time=(0,0) 0187 else: 0188 entry.time=bpentry.start[3:] 0189 entry.description=bpentry.description 0190 # setting the alarm 0191 _alarm=self.protocolclass.CAL_ALARM_NONE 0192 for e in self.protocolclass.CAL_ALARM_LIST: 0193 if bpentry.alarm>=e[0]: 0194 _alarm=e[1] 0195 break 0196 entry.alarm=_alarm 0197 # setting repeat value 0198 if bpentry.repeat: 0199 _rpt_type=self.cal_repeat_value_r.get(bpentry.repeat.repeat_type, 0200 self.protocolclass.CAL_REP_NONE) 0201 else: 0202 _rpt_type=self.protocolclass.CAL_REP_NONE 0203 entry.repeat=_rpt_type 0204 return entry 0205 0206 def savecalendar(self, dict, merge): 0207 self.log('Saving calendar entries') 0208 self.setmode(self.MODEMODEM) 0209 self.charset_ascii() 0210 _cal_dict=dict['calendar'] 0211 _cal_list=[(x.start, k) for k,x in _cal_dict.items()] 0212 _cal_list.sort() 0213 _cal_list=_cal_list[:self.protocolclass.CAL_TOTAL_ENTRIES] 0214 _pre_write=self.protocolclass.calendar_write_check_req() 0215 for i,e in enumerate(_cal_list): 0216 _entry=self._build_phone_cal_entry(i, _cal_dict[e[1]]) 0217 self.progress(i, self.protocolclass.CAL_TOTAL_ENTRIES, 0218 'Writing entry %d: %s'%(i, _entry.description)) 0219 try: 0220 try: 0221 self.sendATcommand(_entry, None) 0222 _success=True 0223 except: 0224 _success=False 0225 if not _success: 0226 try: 0227 self.sendATcommand(_pre_write, None) 0228 except: 0229 pass 0230 self.sendATcommand(_entry, None) 0231 except: 0232 if __debug__: 0233 raise 0234 _req=self.protocolclass.calendar_del_req() 0235 for i in range(len(_cal_list), self.protocolclass.CAL_TOTAL_ENTRIES): 0236 self.progress(i, self.protocolclass.CAL_TOTAL_ENTRIES, 0237 'Deleting entry %d'%i) 0238 _req.index=i 0239 try: 0240 self.sendATcommand(_req, None) 0241 except: 0242 break 0243 return dict 0244 0245 def charset_ascii(self): 0246 """ Set the phone charset to some form of ascii""" 0247 _req=self.protocolclass.charset_set_req() 0248 _req.charset=self.protocolclass.CHARSET_IRA 0249 self.sendATcommand(_req, None) 0250 def charset_base64(self): 0251 """ Set the phone charset to Base64 (for binary transmission)""" 0252 _req=self.protocolclass.charset_set_req() 0253 _req.charset=self.protocolclass.CHARSET_BASE64 0254 self.sendATcommand(_req, None) 0255 0256 # Detect Phone-------------------------------------------------------------- 0257 def is_mode_modem(self): 0258 try: 0259 self.comm.sendatcommand("Z") 0260 self.comm.sendatcommand('E0V1') 0261 return True 0262 except: 0263 return False 0264 0265 def get_detect_data(self, r): 0266 # get detection data 0267 r['manufacturer']=self.get_manufacturer_id() 0268 r['model']=self.get_model_id() 0269 r['firmware_version']=self.get_firmware_version() 0270 r['esn']=self.get_sim_id() 0271 0272 @classmethod 0273 def detectphone(_, coms, likely_ports, res, _module, _log): 0274 if not len(likely_ports): 0275 return None 0276 for port in likely_ports: 0277 if not res.has_key(port): 0278 res[port]={ 'mode_modem': None, 'mode_brew': None, 0279 'manufacturer': None, 'model': None, 0280 'firmware_version': None, 'esn': None, 0281 'firmwareresponse': None } 0282 try: 0283 if res[port]['mode_modem']==False or \ 0284 res[port]['model']: 0285 continue 0286 p=Phone(_log, commport.CommConnection(_log, port, timeout=1)) 0287 if p.is_mode_modem(): 0288 res[port]['mode_modem']=True 0289 p.get_detect_data(res[port]) 0290 else: 0291 res[port]['mode_modem']=False 0292 except: 0293 # this port is not available 0294 if __debug__: 0295 raise 0296 0297 # Phonebook stuff----------------------------------------------------------- 0298 def _build_bp_entry(self, entry, groups, in_sim=False): 0299 res={ 'names': [ { 'full': entry.name } ] } 0300 _numbers=[] 0301 if entry.mobile: 0302 _numbers.append({ 'number': entry.mobile, 0303 'type': 'cell' }) 0304 if entry.home: 0305 _numbers.append({ 'number': entry.home, 0306 'type': 'home' }) 0307 if entry.office: 0308 _numbers.append({ 'number': entry.office, 0309 'type': 'office'}) 0310 if _numbers: 0311 res['numbers']=_numbers 0312 if entry.email: 0313 res['emails']=[{ 'email': entry.email }] 0314 if entry.memo: 0315 res['memos']=[{ 'memo': entry.memo }] 0316 _group=groups.get(entry.group, None) 0317 if _group and _group.get('name', None): 0318 res['categories']=[{ 'category': _group['name'] }] 0319 if entry.sim: 0320 res['flags']=[{ 'sim': in_sim }] 0321 return res 0322 0323 def _get_main_phonebook(self, groups): 0324 """return a dict of contacts read off the phone storage area""" 0325 # switch to the phone storage 0326 _req=self.protocolclass.select_storage_req() 0327 _req.storage=self.protocolclass.PB_MEMORY_MAIN 0328 self.sendATcommand(_req, None) 0329 # read the entries 0330 _req=self.protocolclass.read_phonebook_req() 0331 _req.start_index=self.protocolclass.PB_MAIN_MIN_INDEX 0332 _req.end_index=self.protocolclass.PB_MAIN_MAX_INDEX 0333 _res=self.sendATcommand(_req, self.protocolclass.read_phonebook_resp) 0334 res={} 0335 for e in _res: 0336 res[e.index]=self._build_bp_entry(e, groups) 0337 return res 0338 0339 def _get_sim_phonebook(self, groups): 0340 """return a dict of contacts read off the phone SIM card""" 0341 # switch to the phone storage 0342 _req=self.protocolclass.select_storage_req() 0343 _req.storage=self.protocolclass.PB_MEMORY_SIM 0344 self.sendATcommand(_req, None) 0345 # read the entries 0346 _req=self.protocolclass.read_phonebook_req() 0347 _req.start_index=self.protocolclass.PB_SIM_MIN_INDEX 0348 _req.end_index=self.protocolclass.PB_SIM_MAX_INDEX 0349 _res=self.sendATcommand(_req, self.protocolclass.read_sim_phonebook_resp) 0350 res={} 0351 for e in _res: 0352 res[1000+e.index]=self._build_bp_entry(e, groups, in_sim=True) 0353 return res 0354 0355 def getphonebook(self,result): 0356 """Reads the phonebook data. The L{getfundamentals} information will 0357 already be in result.""" 0358 self.log('Getting phonebook') 0359 self.setmode(self.MODEMODEM) 0360 self.charset_ascii() 0361 _groups=result.get('groups', {}) 0362 pb_book=self._get_main_phonebook(_groups) 0363 pb_book.update(self._get_sim_phonebook(_groups)) 0364 result['phonebook']=pb_book 0365 return pb_book 0366 0367 def _in_sim(self, entry): 0368 """ Return True if this entry has the sim flag set, indicating that 0369 it should be stored on the SIM card. 0370 """ 0371 for l in entry.get('flags', []): 0372 if l.has_key('sim'): 0373 return l['sim'] 0374 return False 0375 0376 def _lookup_group(self, entry, groups): 0377 try: 0378 _name=entry['categories'][0]['category'] 0379 except: 0380 return 0 0381 for k,e in groups.items(): 0382 if e['name']==_name: 0383 return k 0384 return 0 0385 0386 def _build_main_entry(self, entry, groups): 0387 _req=self.protocolclass.write_phonebook_req() 0388 _req.group=self._lookup_group(entry, groups) 0389 _req.name=nameparser.getfullname(entry['names'][0]) 0390 _req.email=entry.get('emails', [{'email': ''}])[0]['email'] 0391 _req.memo=entry.get('memos', [{'memo': ''}])[0]['memo'] 0392 for n in entry.get('numbers', []): 0393 _type=n['type'] 0394 _number=n['number'] 0395 if _type=='cell': 0396 _req.mobile=_number 0397 _req.mobile_type=129 0398 elif _type=='home': 0399 _req.home=_number 0400 _req.home_type=129 0401 elif _type=='office': 0402 _req.office=_number 0403 _req.office_type=129 0404 return _req 0405 0406 def _build_sim_entry(self, entry, groups): 0407 _req=self.protocolclass.write_sim_phonebook_req() 0408 _req.group=self._lookup_group(entry, groups) 0409 _req.name=nameparser.getfullname(entry['names'][0]) 0410 _number=entry.get('numbers', [{'number': ''}])[0]['number'] 0411 if _number: 0412 _req.number=_number 0413 _req.number_type=129 0414 return _req 0415 0416 def _save_main_phonebook(self, entries, groups): 0417 """ got the the phonebook dict and write them out to the phone""" 0418 # build the full names & SIM keys 0419 _pb_list=[(nameparser.getfullname(e['names'][0]), k) \ 0420 for k,e in entries.items() if not self._in_sim(e)] 0421 # sort alphabetical order 0422 _pb_list.sort() 0423 # switch to the main phone storage 0424 _req=self.protocolclass.select_storage_req() 0425 _req.storage=self.protocolclass.PB_MEMORY_MAIN 0426 self.sendATcommand(_req, None) 0427 _del_entry=self.protocolclass.del_phonebook_req() 0428 # send each entry to the phone 0429 _index=self.protocolclass.PB_MAIN_MIN_INDEX 0430 for l in _pb_list: 0431 _del_entry.index=_index 0432 _index+=1 0433 self.sendATcommand(_del_entry, None) 0434 time.sleep(0.2) 0435 _req=self._build_main_entry(entries[l[1]], groups) 0436 self.progress(_index, self.protocolclass.PB_MAIN_MAX_INDEX, 0437 'Writing entry %d: %s'%(_index, _req.name)) 0438 try: 0439 self.sendATcommand(_req, None) 0440 _retry=False 0441 except: 0442 _retry=True 0443 if _retry: 0444 try: 0445 self.sendATcommand(_req, None) 0446 except: 0447 self.log('Failed to write entry %d: %s'%(_index, _req.name)) 0448 time.sleep(0.2) 0449 # clear out the rest of the phonebook 0450 for i in range(_index, self.protocolclass.PB_MAIN_MAX_INDEX+1): 0451 self.progress(i, self.protocolclass.PB_MAIN_MAX_INDEX, 0452 'Deleting entry %d'%i) 0453 try: 0454 _del_entry.index=i 0455 self.sendATcommand(_del_entry, None) 0456 continue 0457 except: 0458 self.log('Trying to delete entry %d'%i) 0459 try: 0460 self.sendATcommand(_del_entry, None) 0461 except: 0462 self.log('Failed to delete entry %d'%i) 0463 0464 def _save_sim_phonebook(self, entries, groups): 0465 """ got the the phonebook dict and write them out to the phone""" 0466 # build the full names & SIM keys 0467 _pb_list=[(nameparser.getfullname(e['names'][0]), k) \ 0468 for k,e in entries.items() if self._in_sim(e)] 0469 # sort alphabetical order 0470 _pb_list.sort() 0471 # switch to the main phone storage 0472 _req=self.protocolclass.select_storage_req() 0473 _req.storage=self.protocolclass.PB_MEMORY_SIM 0474 self.sendATcommand(_req, None) 0475 _del_entry=self.protocolclass.del_phonebook_req() 0476 # send each entry to the phone 0477 _index=self.protocolclass.PB_SIM_MIN_INDEX 0478 for l in _pb_list: 0479 _del_entry.index=_index 0480 _index+=1 0481 self.sendATcommand(_del_entry, None) 0482 time.sleep(0.2) 0483 _req=self._build_sim_entry(entries[l[1]], groups) 0484 self.progress(_index, self.protocolclass.PB_SIM_MAX_INDEX, 0485 'Writing SIM entry %d: %s'%(_index, _req.name)) 0486 try: 0487 self.sendATcommand(_req, None) 0488 _retry=False 0489 except: 0490 _retry=True 0491 if _retry: 0492 try: 0493 self.sendATcommand(_req, None) 0494 except: 0495 self.log('Failed to write SIM entry %d: %s'%(_index, _req.name)) 0496 time.sleep(0.2) 0497 # clear out the rest of the phonebook 0498 for i in range(_index, self.protocolclass.PB_SIM_MAX_INDEX+1): 0499 self.progress(i, self.protocolclass.PB_SIM_MAX_INDEX, 0500 'Deleting SIM entry %d'%i) 0501 try: 0502 _del_entry.index=i 0503 self.sendATcommand(_del_entry, None) 0504 continue 0505 except: 0506 self.log('Trying to delete entry %d'%i) 0507 try: 0508 self.sendATcommand(_del_entry, None) 0509 except: 0510 self.log('Failed to delete entry %d'%i) 0511 0512 def savephonebook(self, data): 0513 "Saves out the phonebook" 0514 self.log('Writing phonebook') 0515 self.setmode(self.MODEMODEM) 0516 self.charset_ascii() 0517 0518 pb_book=data.get('phonebook', {}) 0519 pb_groups=data.get('groups', {}) 0520 self._save_main_phonebook(pb_book, pb_groups) 0521 self._save_sim_phonebook(pb_book, pb_groups) 0522 return data 0523 0524 # Ringtone stuff------------------------------------------------------------ 0525 def _del_media_files(self, names): 0526 self.charset_ascii() 0527 _req=self.protocolclass.del_media_req() 0528 for n in names: 0529 self.log('Deleting media %s'%n) 0530 _req.file_name=n 0531 try: 0532 self.sendATcommand(_req, None) 0533 except: 0534 self.log('Failed to delete media %s'%n) 0535 0536 def _add_media_file(self, file_name, media_name, media_code, data): 0537 """ Add one media ringtone 0538 """ 0539 if not file_name or not media_name or not data: 0540 return False 0541 self.log('Writing media %s'%file_name) 0542 _media_name='' 0543 for s in media_name: 0544 _media_name+=s+'\x00' 0545 _cmd='AT+DDLW=0,"%s","%s",%d,%d,0,0,0,0\r' % \ 0546 (file_name, base64.encodestring(_media_name), len(data), 0547 media_code) 0548 _data64=base64.encodestring(data) 0549 self.comm.write(str(_cmd)) 0550 if self.comm.read(4)!='\r\n> ': 0551 return False 0552 for l in _data64.split('\n'): 0553 if l: 0554 self.comm.write(l+'\n') 0555 time.sleep(0.01) 0556 self.comm.write(str('\x1A')) 0557 return self.comm.read(6)=='\r\nOK\r\n' 0558 0559 def _add_ringtones(self, names, name_dict, media): 0560 self.charset_base64() 0561 for n in names: 0562 _media_key=name_dict[n] 0563 if not self._add_media_file(n, common.stripext(n), 20, 0564 media[_media_key].get('data', '')): 0565 self.log('Failed to send ringtone %s'%n) 0566 self.charset_ascii() 0567 0568 def saveringtones(self, result, merge): 0569 self.log('Saving ringtones') 0570 self.setmode(self.MODEMODEM) 0571 self.charset_ascii() 0572 self._ringtone_mode() 0573 0574 media=result.get('ringtone', {}) 0575 media_index=result.get('ringtone-index', {}) 0576 media_names=[x['name'] for x in media.values()] 0577 index_names=[x['name'] for x in media_index.values()] 0578 del_names=[x for x in index_names if x not in media_names] 0579 new_names=[x for x in media_names if x not in index_names] 0580 # deleting files 0581 self._del_media_files(del_names) 0582 # and add new files 0583 names_to_keys={} 0584 for k,e in media.items(): 0585 names_to_keys[e['name']]=k 0586 self._add_ringtones(new_names, names_to_keys, media) 0587 return result 0588 0589 def getringtones(self, result): 0590 self.log('Reading ringtones index') 0591 self.setmode(self.MODEMODEM) 0592 self.charset_ascii() 0593 self._ringtone_mode() 0594 0595 media={} 0596 media_index=self._get_ringtone_index() 0597 for e in media_index.values(): 0598 media[e['name']]='dummy data' 0599 result['ringtone']=media 0600 result['ringtone-index']=media_index 0601 return result 0602 0603 # Wallpaper stuff----------------------------------------------------------- 0604 def getwallpapers(self, result): 0605 self.log('Reading wallpaper index') 0606 self.setmode(self.MODEMODEM) 0607 self.charset_ascii() 0608 self._wallpaper_mode() 0609 0610 media={} 0611 media_index=self._get_wallpaper_index() 0612 _dummy_data=file(guihelper.getresourcefile('wallpaper.png'),'rb').read() 0613 for e in media_index.values(): 0614 media[e['name']]=_dummy_data 0615 result['wallpapers']=media 0616 result['wallpaper-index']=media_index 0617 return result 0618 0619 def _add_wallpapers(self, names, name_dict, media): 0620 self.charset_base64() 0621 for n in names: 0622 _media_key=name_dict[n] 0623 if not self._add_media_file(n, common.stripext(n), 12, 0624 media[_media_key].get('data', '')): 0625 self.log('Failed to send wallpaper %s'%n) 0626 self.charset_ascii() 0627 0628 def savewallpapers(self, result, merge): 0629 self.log('Saving wallpapers') 0630 self.setmode(self.MODEMODEM) 0631 self.charset_ascii() 0632 self._wallpaper_mode() 0633 0634 media=result.get('wallpapers', {}) 0635 media_index=result.get('wallpaper-index', {}) 0636 media_names=[x['name'] for x in media.values()] 0637 index_names=[x['name'] for x in media_index.values()] 0638 del_names=[x for x in index_names if x not in media_names] 0639 new_names=[x for x in media_names if x not in index_names] 0640 # deleting files 0641 self._del_media_files(del_names) 0642 # and add new files 0643 names_to_keys={} 0644 for k,e in media.items(): 0645 names_to_keys[e['name']]=k 0646 self._add_wallpapers(new_names, names_to_keys, media) 0647 return result 0648 0649 # Memo stuff---------------------------------------------------------------- 0650 def getmemo(self, result): 0651 self.log('Reading Memo') 0652 self.setmode(self.MODEMODEM) 0653 self.charset_ascii() 0654 _req=self.protocolclass.memo_read_req() 0655 _res=self.sendATcommand(_req, self.protocolclass.memo_read_resp) 0656 res={} 0657 for e in _res: 0658 _memo=memo.MemoEntry() 0659 _memo.text=e.text 0660 res[_memo.id]=_memo 0661 result['memo']=res 0662 return res 0663 0664 def savememo(self, result, merge): 0665 self.log('Writing Memo') 0666 self.setmode(self.MODEMODEM) 0667 self.charset_ascii() 0668 # first, delete all existing memos 0669 _req=self.protocolclass.memo_del_req() 0670 for i in range(self.protocolclass.MEMO_MIN_INDEX, 0671 self.protocolclass.MEMO_MAX_INDEX+1): 0672 _req.index=i 0673 try: 0674 self.sendATcommand(_req, None) 0675 except: 0676 pass 0677 # then update with new ones 0678 _memo_dict=result.get('memo', {}) 0679 _keys=_memo_dict.keys() 0680 _keys.sort() 0681 _req=self.protocolclass.memo_write_req() 0682 for k in _keys: 0683 _req.text=_memo_dict[k].text 0684 try: 0685 self.sendATcommand(_req, None) 0686 except: 0687 self.log('Failed to write memo %s'%_req.text) 0688 return _memo_dict 0689 0690 # SMS Stuff----------------------------------------------------------------- 0691 def _process_sms(self, _resp, res): 0692 # extract the SMS messages from the respons string & update the dict 0693 for i in range(0, len(_resp), 2): 0694 try: 0695 _entry=self.protocolclass.sms_msg_list_header() 0696 _buf=prototypes.buffer(_resp[i]) 0697 _entry.readfrombuffer(_buf, logtitle="SMS #"+i) 0698 _sms=sms.SMSEntry() 0699 if _entry.msg_type==self.protocolclass.SMS_MSG_REC_UNREAD or \ 0700 _entry.msg_type==self.protocolclass.SMS_MSG_REC_READ: 0701 # unread/read inbox 0702 _sms._from=_entry.address 0703 _sms.folder=sms.SMSEntry.Folder_Inbox 0704 _sms.read=_entry.msg_type==self.protocolclass.SMS_MSG_REC_READ 0705 elif _entry.msg_type==self.protocolclass.SMS_MSG_STO_SENT: 0706 # outbox 0707 _sms.add_recipient(_entry.address) 0708 _sms.folder=sms.SMSEntry.Folder_Sent 0709 elif _entry.msg_type==self.protocolclass.SMS_MSG_STO_UNSENT: 0710 # saved 0711 _sms.folder=sms.SMSEntry.Folder_Saved 0712 _sms.add_recipient(_entry.address) 0713 else: 0714 self.log('Unknown message type: %s'%_entry.msg_type) 0715 _sms=None 0716 if _sms: 0717 if _entry.timestamp: 0718 _sms.datetime=_entry.timestamp 0719 _sms.text=_resp[i+1] 0720 res[_sms.id]=_sms 0721 except: 0722 if __debug__: 0723 raise 0724 return res 0725 0726 def getsms(self, result): 0727 self.log('Getting SMS Messages') 0728 self.setmode(self.MODEMODEM) 0729 self.charset_ascii() 0730 res={} 0731 # set format to text 0732 _req=self.protocolclass.sms_format_req() 0733 self.sendATcommand(_req, None) 0734 self.log('Getting SMS messages from the phone memory') 0735 _sms_mem=self.protocolclass.sms_memory_select_req() 0736 _sms_mem.list_memory=self.protocolclass.SMS_MEMORY_PHONE 0737 self.sendATcommand(_sms_mem, None) 0738 _list_sms=self.protocolclass.sms_msg_list_req() 0739 _resp=self.sendATcommand(_list_sms, None) 0740 self._process_sms(_resp, res) 0741 self.log('Getting SMS message from the SIM card') 0742 _sms_mem.list_memory=self.protocolclass.SMS_MEMORY_SIM 0743 self.sendATcommand(_sms_mem, None) 0744 _resp=self.sendATcommand(_list_sms, None) 0745 self._process_sms(_resp, res) 0746 try: 0747 # this is to clear the next error 0748 self.sendATcommand(_sms_mem, None) 0749 except commport.ATError: 0750 pass 0751 result['sms']=res 0752 return result 0753 0754 # Call History stuff-------------------------------------------------------- 0755 def _get_history_calls(self, log_str, call_type, min_idx, max_idx): 0756 self.log(log_str) 0757 _sel_mem=self.protocolclass.select_storage_req() 0758 _sel_mem.storage=call_type 0759 self.sendATcommand(_sel_mem, None) 0760 _list_pb=self.protocolclass.read_phonebook_req() 0761 _list_pb.start_index=min_idx 0762 _list_pb.end_index=max_idx 0763 self.sendATcommand(_list_pb, None) 0764 0765 def getcallhistory(self, result): 0766 self.log('Getting Call History') 0767 self.setmode(self.MODEMODEM) 0768 self.charset_ascii() 0769 res={} 0770 for l in self.protocolclass.PB_CALL_HISTORY_INFO: 0771 self._get_history_calls(*l) 0772 result['call_history']=res 0773 return result 0774 0775 #------------------------------------------------------------------------------- 0776 parent_profile=com_etsi.Profile 0777 class Profile(parent_profile): 0778 0779 serialsname=Phone.serialsname 0780 0781 WALLPAPER_WIDTH=128 0782 WALLPAPER_HEIGHT=128 0783 MAX_WALLPAPER_BASENAME_LENGTH=19 0784 WALLPAPER_FILENAME_CHARS="abcdefghijklmnopqrstuvwxyz0123456789_ ." 0785 WALLPAPER_CONVERT_FORMAT="jpg" 0786 MAX_RINGTONE_BASENAME_LENGTH=19 0787 RINGTONE_FILENAME_CHARS="abcdefghijklmnopqrstuvwxyz0123456789_ ." 0788 RINGTONE_LIMITS= { 0789 'MAXSIZE': 20480 0790 } 0791 # use for auto-detection 0792 phone_manufacturer='LGE' 0793 phone_model='G4015' 0794 0795 usbids=( ( 0x10AB, 0x10C5, 1), 0796 ) 0797 deviceclasses=("serial",) 0798 0799 imageorigins={} 0800 imageorigins.update(common.getkv(parent_profile.stockimageorigins, "images")) 0801 0802 imagetargets={} 0803 imagetargets.update(common.getkv(parent_profile.stockimagetargets, "wallpaper", 0804 {'width': 128, 'height': 128, 'format': "JPEG"})) 0805 0806 def GetImageOrigins(self): 0807 # Note: only return origins that you can write back to the phone 0808 return self.imageorigins 0809 0810 def GetTargetsForImageOrigin(self, origin): 0811 # right now, supporting just 'images' origin 0812 if origin=='images': 0813 return self.imagetargets 0814 0815 def __init__(self): 0816 parent_profile.__init__(self) 0817 0818 _supportedsyncs=( 0819 ('phonebook', 'read', None), # all phonebook reading 0820 ('phonebook', 'write', 'OVERWRITE'), # only overwriting phonebook 0821 ('calendar', 'read', None), # all calendar reading 0822 ('calendar', 'write', 'OVERWRITE'), # only overwriting calendar 0823 ('ringtone', 'read', None), # all ringtone reading 0824 ('ringtone', 'write', 'OVERWRITE'), 0825 ('wallpaper', 'read', None), # all wallpaper reading 0826 ('wallpaper', 'write', 'OVERWRITE'), 0827 ('memo', 'read', None), # all memo list reading DJP 0828 ('memo', 'write', 'OVERWRITE'), # all memo list writing DJP 0829 ('sms', 'read', None), # all SMS list reading DJP 0830 ('call_history', 'read', None), 0831 ) 0832 0833 def convertphonebooktophone(self, helper, data): 0834 return data 0835
Generated by PyXR 0.9.4