Package phones ::
Module com_lgg4015
|
|
1
2
3
4
5
6
7
8
9
10 """Communicate with the LG G4015 cell phone
11 """
12
13
14 import base64
15 import sha
16 import time
17
18
19 import bpcalendar
20 import common
21 import commport
22 import com_etsi
23 import guihelper
24 import helpids
25 import memo
26 import nameparser
27 import p_lgg4015
28 import prototypes
29 import sms
30
31 -class Phone(com_etsi.Phone):
32 """ Talk to the LG G4015 Phone"""
33
34 desc='LG-G4015'
35 helpid=helpids.ID_PHONE_LGG4015
36 protocolclass=p_lgg4015
37 serialsname='lgg4015'
38
39 - def __init__(self, logtarget, commport):
42
44
45 """Gets information fundamental to interoperating with the phone and UI.
46
47 Currently this is:
48
49 - 'uniqueserial' a unique serial number representing the phone
50 - 'groups' the phonebook groups
51 - 'wallpaper-index' map index numbers to names
52 - 'ringtone-index' map index numbers to ringtone names
53
54 This method is called before we read the phonebook data or before we
55 write phonebook data.
56 """
57
58 self.setmode(self.MODEMODEM)
59 self.log("Retrieving fundamental phone information")
60 self.log("Reading phone serial number")
61 results['uniqueserial']=sha.new(self.get_sim_id()).hexdigest()
62
63 self.log("Reading group information")
64 results['groups']=self._get_groups()
65
66 self.log('Reading Ringtone Index')
67 results['ringtone-index']=self._get_ringtone_index()
68
69 self.log('Reading Wallpaper Index')
70 results['wallpaper-index']=self._get_wallpaper_index()
71
72 self.log("Fundamentals retrieved")
73 return results
74
90
95
110
115
130
131
132 cal_repeat_value={
133 protocolclass.CAL_REP_DAILY: bpcalendar.RepeatEntry.daily,
134 protocolclass.CAL_REP_WEEKLY: bpcalendar.RepeatEntry.weekly,
135 protocolclass.CAL_REP_MONTHLY: bpcalendar.RepeatEntry.monthly,
136 protocolclass.CAL_REP_YEARLY: bpcalendar.RepeatEntry.yearly }
137 cal_repeat_value_r={
138 bpcalendar.RepeatEntry.daily: protocolclass.CAL_REP_DAILY,
139 bpcalendar.RepeatEntry.weekly: protocolclass.CAL_REP_WEEKLY,
140 bpcalendar.RepeatEntry.monthly: protocolclass.CAL_REP_MONTHLY,
141 bpcalendar.RepeatEntry.yearly: protocolclass.CAL_REP_YEARLY }
142
143 - def _build_bpcalendar_entry(self, phone_entry):
144 entry=bpcalendar.CalendarEntry()
145 entry.start=phone_entry.date+phone_entry.time
146 entry.end=phone_entry.date+phone_entry.time
147 entry.description=phone_entry.description
148 entry.serials.append({ 'sourcetype': 'phone',
149 'id': phone_entry.index })
150 entry.alarm=self.protocolclass.CAL_ALARM_VALUE.get(phone_entry.alarm, -1)
151 _rpt_type=self.cal_repeat_value.get(phone_entry.repeat, None)
152 if _rpt_type:
153
154 rpt=bpcalendar.RepeatEntry(_rpt_type)
155 if _rpt_type!=bpcalendar.RepeatEntry.yearly:
156 rpt.interval=1
157
158 entry.end=bpcalendar.CalendarEntry.no_end_date
159 entry.repeat=rpt
160 return entry
161
180
181 - def _build_phone_cal_entry(self, entry_count, bpentry):
182 entry=self.protocolclass.calendar_write_req()
183 entry.index=entry_count
184 entry.date=bpentry.start[:3]
185 if bpentry.allday:
186 entry.time=(0,0)
187 else:
188 entry.time=bpentry.start[3:]
189 entry.description=bpentry.description
190
191 _alarm=self.protocolclass.CAL_ALARM_NONE
192 for e in self.protocolclass.CAL_ALARM_LIST:
193 if bpentry.alarm>=e[0]:
194 _alarm=e[1]
195 break
196 entry.alarm=_alarm
197
198 if bpentry.repeat:
199 _rpt_type=self.cal_repeat_value_r.get(bpentry.repeat.repeat_type,
200 self.protocolclass.CAL_REP_NONE)
201 else:
202 _rpt_type=self.protocolclass.CAL_REP_NONE
203 entry.repeat=_rpt_type
204 return entry
205
207 self.log('Saving calendar entries')
208 self.setmode(self.MODEMODEM)
209 self.charset_ascii()
210 _cal_dict=dict['calendar']
211 _cal_list=[(x.start, k) for k,x in _cal_dict.items()]
212 _cal_list.sort()
213 _cal_list=_cal_list[:self.protocolclass.CAL_TOTAL_ENTRIES]
214 _pre_write=self.protocolclass.calendar_write_check_req()
215 for i,e in enumerate(_cal_list):
216 _entry=self._build_phone_cal_entry(i, _cal_dict[e[1]])
217 self.progress(i, self.protocolclass.CAL_TOTAL_ENTRIES,
218 'Writing entry %d: %s'%(i, _entry.description))
219 try:
220 try:
221 self.sendATcommand(_entry, None)
222 _success=True
223 except:
224 _success=False
225 if not _success:
226 try:
227 self.sendATcommand(_pre_write, None)
228 except:
229 pass
230 self.sendATcommand(_entry, None)
231 except:
232 if __debug__:
233 raise
234 _req=self.protocolclass.calendar_del_req()
235 for i in range(len(_cal_list), self.protocolclass.CAL_TOTAL_ENTRIES):
236 self.progress(i, self.protocolclass.CAL_TOTAL_ENTRIES,
237 'Deleting entry %d'%i)
238 _req.index=i
239 try:
240 self.sendATcommand(_req, None)
241 except:
242 break
243 return dict
244
255
256
264
271
272 @classmethod
273 - def detectphone(_, coms, likely_ports, res, _module, _log):
274 if not len(likely_ports):
275 return None
276 for port in likely_ports:
277 if not res.has_key(port):
278 res[port]={ 'mode_modem': None, 'mode_brew': None,
279 'manufacturer': None, 'model': None,
280 'firmware_version': None, 'esn': None,
281 'firmwareresponse': None }
282 try:
283 if res[port]['mode_modem']==False or \
284 res[port]['model']:
285 continue
286 p=Phone(_log, commport.CommConnection(_log, port, timeout=1))
287 if p.is_mode_modem():
288 res[port]['mode_modem']=True
289 p.get_detect_data(res[port])
290 else:
291 res[port]['mode_modem']=False
292 except:
293
294 if __debug__:
295 raise
296
297
298 - def _build_bp_entry(self, entry, groups, in_sim=False):
299 res={ 'names': [ { 'full': entry.name } ] }
300 _numbers=[]
301 if entry.mobile:
302 _numbers.append({ 'number': entry.mobile,
303 'type': 'cell' })
304 if entry.home:
305 _numbers.append({ 'number': entry.home,
306 'type': 'home' })
307 if entry.office:
308 _numbers.append({ 'number': entry.office,
309 'type': 'office'})
310 if _numbers:
311 res['numbers']=_numbers
312 if entry.email:
313 res['emails']=[{ 'email': entry.email }]
314 if entry.memo:
315 res['memos']=[{ 'memo': entry.memo }]
316 _group=groups.get(entry.group, None)
317 if _group and _group.get('name', None):
318 res['categories']=[{ 'category': _group['name'] }]
319 if entry.sim:
320 res['flags']=[{ 'sim': in_sim }]
321 return res
322
323 - def _get_main_phonebook(self, groups):
324 """return a dict of contacts read off the phone storage area"""
325
326 _req=self.protocolclass.select_storage_req()
327 _req.storage=self.protocolclass.PB_MEMORY_MAIN
328 self.sendATcommand(_req, None)
329
330 _req=self.protocolclass.read_phonebook_req()
331 _req.start_index=self.protocolclass.PB_MAIN_MIN_INDEX
332 _req.end_index=self.protocolclass.PB_MAIN_MAX_INDEX
333 _res=self.sendATcommand(_req, self.protocolclass.read_phonebook_resp)
334 res={}
335 for e in _res:
336 res[e.index]=self._build_bp_entry(e, groups)
337 return res
338
354
366
368 """ Return True if this entry has the sim flag set, indicating that
369 it should be stored on the SIM card.
370 """
371 for l in entry.get('flags', []):
372 if l.has_key('sim'):
373 return l['sim']
374 return False
375
377 try:
378 _name=entry['categories'][0]['category']
379 except:
380 return 0
381 for k,e in groups.items():
382 if e['name']==_name:
383 return k
384 return 0
385
386 - def _build_main_entry(self, entry, groups):
387 _req=self.protocolclass.write_phonebook_req()
388 _req.group=self._lookup_group(entry, groups)
389 _req.name=nameparser.getfullname(entry['names'][0])
390 _req.email=entry.get('emails', [{'email': ''}])[0]['email']
391 _req.memo=entry.get('memos', [{'memo': ''}])[0]['memo']
392 for n in entry.get('numbers', []):
393 _type=n['type']
394 _number=n['number']
395 if _type=='cell':
396 _req.mobile=_number
397 _req.mobile_type=129
398 elif _type=='home':
399 _req.home=_number
400 _req.home_type=129
401 elif _type=='office':
402 _req.office=_number
403 _req.office_type=129
404 return _req
405
406 - def _build_sim_entry(self, entry, groups):
407 _req=self.protocolclass.write_sim_phonebook_req()
408 _req.group=self._lookup_group(entry, groups)
409 _req.name=nameparser.getfullname(entry['names'][0])
410 _number=entry.get('numbers', [{'number': ''}])[0]['number']
411 if _number:
412 _req.number=_number
413 _req.number_type=129
414 return _req
415
416 - def _save_main_phonebook(self, entries, groups):
417 """ got the the phonebook dict and write them out to the phone"""
418
419 _pb_list=[(nameparser.getfullname(e['names'][0]), k) \
420 for k,e in entries.items() if not self._in_sim(e)]
421
422 _pb_list.sort()
423
424 _req=self.protocolclass.select_storage_req()
425 _req.storage=self.protocolclass.PB_MEMORY_MAIN
426 self.sendATcommand(_req, None)
427 _del_entry=self.protocolclass.del_phonebook_req()
428
429 _index=self.protocolclass.PB_MAIN_MIN_INDEX
430 for l in _pb_list:
431 _del_entry.index=_index
432 _index+=1
433 self.sendATcommand(_del_entry, None)
434 time.sleep(0.2)
435 _req=self._build_main_entry(entries[l[1]], groups)
436 self.progress(_index, self.protocolclass.PB_MAIN_MAX_INDEX,
437 'Writing entry %d: %s'%(_index, _req.name))
438 try:
439 self.sendATcommand(_req, None)
440 _retry=False
441 except:
442 _retry=True
443 if _retry:
444 try:
445 self.sendATcommand(_req, None)
446 except:
447 self.log('Failed to write entry %d: %s'%(_index, _req.name))
448 time.sleep(0.2)
449
450 for i in range(_index, self.protocolclass.PB_MAIN_MAX_INDEX+1):
451 self.progress(i, self.protocolclass.PB_MAIN_MAX_INDEX,
452 'Deleting entry %d'%i)
453 try:
454 _del_entry.index=i
455 self.sendATcommand(_del_entry, None)
456 continue
457 except:
458 self.log('Trying to delete entry %d'%i)
459 try:
460 self.sendATcommand(_del_entry, None)
461 except:
462 self.log('Failed to delete entry %d'%i)
463
465 """ got the the phonebook dict and write them out to the phone"""
466
467 _pb_list=[(nameparser.getfullname(e['names'][0]), k) \
468 for k,e in entries.items() if self._in_sim(e)]
469
470 _pb_list.sort()
471
472 _req=self.protocolclass.select_storage_req()
473 _req.storage=self.protocolclass.PB_MEMORY_SIM
474 self.sendATcommand(_req, None)
475 _del_entry=self.protocolclass.del_phonebook_req()
476
477 _index=self.protocolclass.PB_SIM_MIN_INDEX
478 for l in _pb_list:
479 _del_entry.index=_index
480 _index+=1
481 self.sendATcommand(_del_entry, None)
482 time.sleep(0.2)
483 _req=self._build_sim_entry(entries[l[1]], groups)
484 self.progress(_index, self.protocolclass.PB_SIM_MAX_INDEX,
485 'Writing SIM entry %d: %s'%(_index, _req.name))
486 try:
487 self.sendATcommand(_req, None)
488 _retry=False
489 except:
490 _retry=True
491 if _retry:
492 try:
493 self.sendATcommand(_req, None)
494 except:
495 self.log('Failed to write SIM entry %d: %s'%(_index, _req.name))
496 time.sleep(0.2)
497
498 for i in range(_index, self.protocolclass.PB_SIM_MAX_INDEX+1):
499 self.progress(i, self.protocolclass.PB_SIM_MAX_INDEX,
500 'Deleting SIM entry %d'%i)
501 try:
502 _del_entry.index=i
503 self.sendATcommand(_del_entry, None)
504 continue
505 except:
506 self.log('Trying to delete entry %d'%i)
507 try:
508 self.sendATcommand(_del_entry, None)
509 except:
510 self.log('Failed to delete entry %d'%i)
511
523
524
535
558
567
569 self.log('Saving ringtones')
570 self.setmode(self.MODEMODEM)
571 self.charset_ascii()
572 self._ringtone_mode()
573
574 media=result.get('ringtone', {})
575 media_index=result.get('ringtone-index', {})
576 media_names=[x['name'] for x in media.values()]
577 index_names=[x['name'] for x in media_index.values()]
578 del_names=[x for x in index_names if x not in media_names]
579 new_names=[x for x in media_names if x not in index_names]
580
581 self._del_media_files(del_names)
582
583 names_to_keys={}
584 for k,e in media.items():
585 names_to_keys[e['name']]=k
586 self._add_ringtones(new_names, names_to_keys, media)
587 return result
588
590 self.log('Reading ringtones index')
591 self.setmode(self.MODEMODEM)
592 self.charset_ascii()
593 self._ringtone_mode()
594
595 media={}
596 media_index=self._get_ringtone_index()
597 for e in media_index.values():
598 media[e['name']]='dummy data'
599 result['ringtone']=media
600 result['ringtone-index']=media_index
601 return result
602
603
618
627
629 self.log('Saving wallpapers')
630 self.setmode(self.MODEMODEM)
631 self.charset_ascii()
632 self._wallpaper_mode()
633
634 media=result.get('wallpapers', {})
635 media_index=result.get('wallpaper-index', {})
636 media_names=[x['name'] for x in media.values()]
637 index_names=[x['name'] for x in media_index.values()]
638 del_names=[x for x in index_names if x not in media_names]
639 new_names=[x for x in media_names if x not in index_names]
640
641 self._del_media_files(del_names)
642
643 names_to_keys={}
644 for k,e in media.items():
645 names_to_keys[e['name']]=k
646 self._add_wallpapers(new_names, names_to_keys, media)
647 return result
648
649
663
689
690
725
753
754
755 - def _get_history_calls(self, log_str, call_type, min_idx, max_idx):
756 self.log(log_str)
757 _sel_mem=self.protocolclass.select_storage_req()
758 _sel_mem.storage=call_type
759 self.sendATcommand(_sel_mem, None)
760 _list_pb=self.protocolclass.read_phonebook_req()
761 _list_pb.start_index=min_idx
762 _list_pb.end_index=max_idx
763 self.sendATcommand(_list_pb, None)
764
765 - def getcallhistory(self, result):
766 self.log('Getting Call History')
767 self.setmode(self.MODEMODEM)
768 self.charset_ascii()
769 res={}
770 for l in self.protocolclass.PB_CALL_HISTORY_INFO:
771 self._get_history_calls(*l)
772 result['call_history']=res
773 return result
774
775
776 parent_profile=com_etsi.Profile
778
779 serialsname=Phone.serialsname
780
781 WALLPAPER_WIDTH=128
782 WALLPAPER_HEIGHT=128
783 MAX_WALLPAPER_BASENAME_LENGTH=19
784 WALLPAPER_FILENAME_CHARS="abcdefghijklmnopqrstuvwxyz0123456789_ ."
785 WALLPAPER_CONVERT_FORMAT="jpg"
786 MAX_RINGTONE_BASENAME_LENGTH=19
787 RINGTONE_FILENAME_CHARS="abcdefghijklmnopqrstuvwxyz0123456789_ ."
788 RINGTONE_LIMITS= {
789 'MAXSIZE': 20480
790 }
791
792 phone_manufacturer='LGE'
793 phone_model='G4015'
794
795 usbids=( ( 0x10AB, 0x10C5, 1),
796 )
797 deviceclasses=("serial",)
798
799 imageorigins={}
800 imageorigins.update(common.getkv(parent_profile.stockimageorigins, "images"))
801
802 imagetargets={}
803 imagetargets.update(common.getkv(parent_profile.stockimagetargets, "wallpaper",
804 {'width': 128, 'height': 128, 'format': "JPEG"}))
805
809
814
817
818 _supportedsyncs=(
819 ('phonebook', 'read', None),
820 ('phonebook', 'write', 'OVERWRITE'),
821 ('calendar', 'read', None),
822 ('calendar', 'write', 'OVERWRITE'),
823 ('ringtone', 'read', None),
824 ('ringtone', 'write', 'OVERWRITE'),
825 ('wallpaper', 'read', None),
826 ('wallpaper', 'write', 'OVERWRITE'),
827 ('memo', 'read', None),
828 ('memo', 'write', 'OVERWRITE'),
829 ('sms', 'read', None),
830 ('call_history', 'read', None),
831 )
832
835