| 
      
        Package phones ::
        Module com_lgvx9100
      
     | 
    
      
     | 
  
  1   
  2   
  3   
  4   
  5   
  6   
  7   
  8   
  9   
 10  """ 
 11  Communicate with the LG VX9100 (enV2) cell phone.  This is based on the enV model 
 12  """ 
 13   
 14   
 15  import common 
 16  import com_brew 
 17  import com_lg 
 18  import com_lgvx8550 
 19  import p_lgvx9100 
 20  import prototypes 
 21  import helpids 
 22  import sms 
 23   
 24  DEBUG1=False 
 25  DEBUG2=False 
 26   
 27  parentphone=com_lgvx8550.Phone 
 29      "Talk to the LG VX9100 cell phone" 
 30   
 31      desc="LG-VX9100" 
 32      helpid=helpids.ID_PHONE_LGVX9100 
 33      protocolclass=p_lgvx9100 
 34      serialsname='lgvx9100' 
 35      my_model='VX9100' 
 36   
 37       
 38       
 39      external_storage_root='mmc1/' 
 40      builtinringtones= ('Low Beep Once', 'Low Beeps', 'Loud Beep Once', 'Loud Beeps', 'Door Bell', 'VZW Default Tone') + \ 
 41                        tuple(['Ringtone '+`n` for n in range(1,17)]) + \ 
 42                        ('No Ring',) 
 43   
 44      ringtonelocations= ( 
 45           
 46          ( 'ringers',    'dload/myringtone.dat','brew/mod/10889/ringtones','mmc1/ringers', 100, protocolclass.INDEX_RT_TYPE, 100), 
 47          ( 'sounds',     'dload/mysound.dat',   'brew/mod/18067',   '',             100, protocolclass.INDEX_SOUND_TYPE, None), 
 48          ( 'sounds(sd)', 'dload/sd_sound.dat',  'mmc1/my_sounds',  '',             100, protocolclass.INDEX_SDSOUND_TYPE, None), 
 49   
 50   
 51          ) 
 52   
 53      wallpaperlocations= ( 
 54           
 55          ( 'images',     'dload/image.dat',    'brew/mod/10888', '',          100, protocolclass.INDEX_IMAGE_TYPE, 100), 
 56          ( 'images(sd)', 'dload/sd_image.dat', 'mmc1/my_pix',   '',           100, protocolclass.INDEX_SDIMAGE_TYPE, None), 
 57          ( 'video',      'dload/video.dat',    'brew/mod/10890', '',          100, protocolclass.INDEX_VIDEO_TYPE, None), 
 58          ( 'video(sd)',  'dload/sd_video.dat', 'mmc1/my_flix',  '',           100, protocolclass.INDEX_SDVIDEO_TYPE, None), 
 59          ) 
 60   
 61 -    def __init__(self, logtarget, commport): 
  63   
 65          self._DMv6=True 
 66          self._DMv5=False 
  67   
 68       
 69       
 70       
 71       
 72       
 73       
 74   
 75       
 76       
 77       
 78       
 79   
 80       
 95   
115   
130   
147   
158   
160          """Reads the phonebook data.  The L{getfundamentals} information will 
161          already be in result.""" 
162           
163          _speeds=self._get_speeddials() 
164   
165           
166          self.log("Reading ICE entries") 
167          _ices=self._build_ice_dict() 
168   
169          self.log("Reading phonebook entries") 
170          pb_entries=self.readobject(self.protocolclass.pb_file_name, 
171                                     self.protocolclass.pbfile, 
172                                     logtitle='Reading phonebook entries') 
173   
174          self.log("Reading phone numbers") 
175          pb_numbers=self.readobject(self.protocolclass.pn_file_name, 
176                                     self.protocolclass.pnfile, 
177                                     logtitle='Reading phonebook numbers') 
178   
179          self.log("Reading Ringtone IDs") 
180          ring_pathf=self._get_path_index(self.protocolclass.RTPathIndexFile) 
181          _rt_ids=self._build_media_dict(result, ring_pathf, 'ringtone-index') 
182   
183          self.log("Reading Picture IDs") 
184          picid_pathf=self._get_path_index(self.protocolclass.WPPathIndexFile) 
185          _wp_ids=self._build_media_dict(result, picid_pathf, 'wallpaper-index') 
186   
187          pbook={} 
188          for _cnt in range(self.protocolclass.NUMPHONEBOOKENTRIES): 
189              pb_entry=pb_entries.items[_cnt] 
190              if not pb_entry.valid(): 
191                  continue 
192              try: 
193                  self.log("Parse entry "+`_cnt`+" - " + pb_entry.name) 
194                  pbook[_cnt]=self.extractphonebookentry(pb_entry, pb_numbers, 
195                                                         _speeds, _ices, result, 
196                                                         _rt_ids.get(ring_pathf.items[_cnt].pathname, None), 
197                                                         _wp_ids.get(picid_pathf.items[_cnt].pathname, None)) 
198   
199                  self.progress(_cnt, self.protocolclass.NUMPHONEBOOKENTRIES, pb_entry.name) 
200              except common.PhoneBookBusyException: 
201                  raise 
202              except Exception, e: 
203                   
204                  self.log('Failed to parse entry %d'%_cnt) 
205                  self.log('Exception %s raised'%`e`) 
206                  if __debug__: 
207                      raise 
208               
209          self.progress(self.protocolclass.NUMPHONEBOOKENTRIES, 
210                        self.protocolclass.NUMPHONEBOOKENTRIES, 
211                        "Phone book read completed") 
212   
213          result['phonebook']=pbook 
214          cats=[] 
215          for i in result['groups']: 
216              if result['groups'][i]['name']!='No Group': 
217                  cats.append(result['groups'][i]['name']) 
218          result['categories']=cats 
219          return pbook 
 220   
223          """Return a phonebook entry in BitPim format.  This is called from getphonebook.""" 
224          res={} 
225           
226          res['serials']=[ {'sourcetype': self.serialsname, 
227                            'sourceuniqueid': fundamentals['uniqueserial'], 
228                            'serial1': entry.entry_number1, 
229                            'serial2': entry.entry_number1 } ]  
230   
231           
232          res['names']=[ {'full': entry.name} ] 
233   
234           
235          cat=fundamentals['groups'].get(entry.group, {'name': "No Group"})['name'] 
236          if cat!="No Group": 
237              res['categories']=[ {'category': cat} ] 
238   
239           
240          res['emails']=[] 
241          for i in entry.emails: 
242              if len(i.email): 
243                  res['emails'].append( {'email': i.email} ) 
244          if not len(res['emails']): del res['emails']  
245   
246           
247          if entry.wallpaper!=self.protocolclass.NOWALLPAPER: 
248              try: 
249                  if entry.wallpaper == 0x64: 
250                      paper = wp_name 
251                  else: 
252                      paper = fundamentals['wallpaper-index'][entry.wallpaper]['name'] 
253                  res['wallpapers']=[ {'wallpaper': paper, 'use': 'call'} ]                 
254              except: 
255                  print "can't find wallpaper for index",entry.wallpaper 
256               
257           
258          if entry.ringtone != self.protocolclass.NORINGTONE: 
259              try: 
260                  if entry.ringtone == 0x64: 
261                      tone = rt_name 
262                  else: 
263                      tone=fundamentals['ringtone-index'][entry.ringtone]['name'] 
264                  if tone: 
265                      res['ringtones']=[ {'ringtone': tone, 'use': 'call'} ] 
266              except: 
267                  print "can't find ringtone for index",entry.ringtone 
268           
269          res=self._assignpbtypeandspeeddialsbytype(entry, numbers, speeds, res) 
270   
271           
272          res=self._assigniceentry(entry, numbers, ices, res) 
273   
274          return res 
 275                       
277           
278          res['numbers']=[] 
279          for i in range(self.protocolclass.NUMPHONENUMBERS): 
280              if entry.numberindices[i].numberindex>=\ 
281                 self.protocolclass.NUMPHONENUMBERENTRIES: 
282                   
283                  continue 
284              _pnentry=numbers.items[entry.numberindices[i].numberindex] 
285              num=_pnentry.phone_number 
286              num_type=_pnentry.type 
287              if len(num): 
288                  t=self.protocolclass.numbertypetab[num_type] 
289                  if t[-1]=='2': 
290                      t=t[:-1] 
291                  res['numbers'].append({'number': num, 'type': t}) 
292                   
293                  if speeds.has_key(entry.entry_number0) and \ 
294                     speeds[entry.entry_number0].has_key(num_type): 
295                      res['numbers'][i]['speeddial']=speeds[entry.entry_number0][num_type] 
296          return res 
 297   
298 -    def _assigniceentry(self, entry, numbers, ices, res): 
 299          if ices.has_key(entry.entry_number0): 
300               
301              res['ice']=[ { 'iceindex': ices[entry.entry_number0] } ] 
302              self.log('Entry %d is ICE %d'%(entry.entry_number0, 
303                                             ices[entry.entry_number0])) 
304          return res 
 305   
318          "Saves out the phonebook" 
319          self.savegroups (data) 
320   
321          ring_pathf=self.protocolclass.PathIndexFile() 
322          picid_pathf=self.protocolclass.PathIndexFile() 
323   
324           
325          pbook = data.get('phonebook', {}) 
326          keys = pbook.keys () 
327          keys.sort () 
328   
329          _rt_index=data.get('ringtone-index', {}) 
330          _wp_index=data.get('wallpaper-index', {}) 
331   
332          entry_num0 = 0 
333          entry_num1=self._get_next_pb_id() 
334          pb_entries = self.protocolclass.pbfile() 
335          pn_entries=self.protocolclass.pnfile() 
336          ice_entries = self.protocolclass.iceentryfile() 
337          for i in range(self.protocolclass.NUMEMERGENCYCONTACTS): 
338              ice_entries.items.append (self.protocolclass.iceentry()) 
339          speeddials={} 
340          for i in keys: 
341              pb_entries.items.append(self.make_entry (pn_entries, speeddials, ice_entries, 
342                                                       entry_num0, entry_num1, 
343                                                       pbook[i], data, 
344                                                       ring_pathf,_rt_index, 
345                                                       picid_pathf, _wp_index)) 
346              entry_num0 += 1 
347              if entry_num0 >= self.protocolclass.NUMPHONEBOOKENTRIES: 
348                  self.log ("Maximum number of phonebook entries reached") 
349                  break 
350              if entry_num1==0xffffffff: 
351                  entry_num1=0 
352              else: 
353                  entry_num1+=1 
354   
355           
356          self.log ("Writing phonebook entries") 
357          self.writeobject(self.protocolclass.pb_file_name, 
358                           pb_entries, 
359                           logtitle='Writing phonebook entries', 
360                           uselocalfs=DEBUG1) 
361           
362          self.log ("Writing phone numbers") 
363          self.writeobject(self.protocolclass.pn_file_name, 
364                           pn_entries, logtitle='Writing phonebook numbers', 
365                           uselocalfs=DEBUG1) 
366           
367          self.log('Writing ringtone ID') 
368          self.writeobject(self.protocolclass.RTPathIndexFile, 
369                           ring_pathf, logtitle='Writing ringtone paths', 
370                           uselocalfs=DEBUG1) 
371           
372          self.log('Writing pciture ID') 
373          self.writeobject(self.protocolclass.WPPathIndexFile, 
374                           picid_pathf, logtitle='Writing wallpaper paths', 
375                           uselocalfs=DEBUG1) 
376           
377          self.log('Writing ICE entries') 
378          self.writeobject(self.protocolclass.pb_ice_file_name, 
379                           ice_entries, logtitle='Writing ICE entries', 
380                           uselocalfs=DEBUG1) 
381   
382           
383          req=self.protocolclass.speeddials() 
384           
385          req.speeddials.append(self.protocolclass.speeddial()) 
386           
387          if speeddials.has_key(1): 
388              req.speeddials.append(self.protocolclass.speeddial(entry=speeddials[1]['entry'], 
389                                                                 number=speeddials[1]['type'])) 
390          else: 
391              req.speeddials.append(self.protocolclass.speeddial(entry=1000, 
392                                                                 number=6)) 
393          for i in range(2, self.protocolclass.NUMSPEEDDIALS): 
394              sd=self.protocolclass.speeddial() 
395              if speeddials.has_key(i): 
396                  sd.entry=speeddials[i]['entry'] 
397                  sd.number=speeddials[i]['type'] 
398              req.speeddials.append(sd) 
399          self.log('Writing speed dials') 
400          self.writeobject(self.protocolclass.speed_file_name, 
401                           req, logtitle='Writing speed dials data', 
402                           uselocalfs=DEBUG1) 
403           
404          self._save_next_pb_id(entry_num1) 
405          data["rebootphone"]=True 
406   
407          return data 
 408   
409 -    def make_pn_entry (self, phone_number, number_type, pn_id, pbpn_id, pe_id): 
 410          """ Create a non-blank pnfileentry frome a phone number string """ 
411          if len(phone_number) == 0: 
412              raise 
413           
414          new_entry = self.protocolclass.pnfileentry(entry_tag=self.protocolclass.PB_NUMBER_SOR) 
415          new_entry.pn_id = pn_id 
416          new_entry.pe_id = pe_id 
417          new_entry.phone_number = phone_number 
418          new_entry.type = number_type 
419          new_entry.pn_order = pbpn_id 
420   
421          return new_entry 
 422   
423 -    def make_ice_entry (self, ice_id, pb_id): 
 424          """ Create a iceentry from a pb_id and ice_id """ 
425          new_entry = self.protocolclass.iceentry() 
426           
427          new_entry.entry_assigned = 1 
428          new_entry.entry_number = ice_id 
429          new_entry.pb_index = pb_id 
430   
431          return new_entry 
 432   
433 -    def make_entry (self, pn_entries, speeddials, ice_entries, 
434                      entry_num0, entry_num1, 
435                      pb_entry, data, ring_pathf, 
436                      rt_index, picid_pathf, wp_index): 
 437          """ Create a pbfileentry from a bitpim phonebook entry """ 
438          new_entry = self.protocolclass.pbfileentry(entry_tag=self.protocolclass.PB_ENTRY_SOR) 
439           
440          new_entry.entry_number0 = entry_num0 
441          new_entry.entry_number1 = entry_num1 
442   
443          for key in pb_entry: 
444              if key in ('emails', 'numbertypes'): 
445                  l = getattr (new_entry, key) 
446                  for item in pb_entry[key]: 
447                      l.append(item) 
448              elif key == 'numbers': 
449                  l = getattr (new_entry, 'numberindices') 
450                  for i in range(0, self.protocolclass.NUMPHONENUMBERS): 
451                      new_pn_id = len (pn_entries.items) 
452                      if new_pn_id == self.protocolclass.NUMPHONENUMBERENTRIES: 
453                           
454                          self.log ("Maximum number of phone numbers reached") 
455                          break 
456   
457                      try: 
458                          pn_entries.items.append(self.make_pn_entry (pb_entry[key][i],pb_entry['numbertypes'][i], new_pn_id, i, entry_num0)) 
459                          l.append (new_pn_id) 
460                      except: 
461                          l.append (0xffff) 
462              elif key == 'speeddials': 
463                  for _sd,_num_type in zip(pb_entry['speeddials'], pb_entry['numbertypes']): 
464                      if _sd is not None: 
465                          speeddials[_sd]={ 'entry': entry_num0, 
466                                            'type': _num_type } 
467              elif key == 'ice': 
468                   
469                  _ice = pb_entry['ice'] 
470                  if _ice is not None and len(_ice) > 0: 
471                      _ice_entry = _ice[0]['iceindex'] 
472                      ice_entries.items[_ice_entry] = self.make_ice_entry (_ice_entry, entry_num0) 
473              elif key == 'ringtone': 
474                  new_entry.ringtone = self._findmediainindex(data['ringtone-index'], pb_entry['ringtone'], pb_entry['name'], 'ringtone') 
475                  try: 
476                      _filename = rt_index[new_entry.ringtone]['filename'] 
477                      ring_pathf.items.append(self.protocolclass.PathIndexEntry(pathname=_filename)) 
478                      new_entry.ringtone = 0x64 
479                  except: 
480                      ring_pathf.items.append(self.protocolclass.PathIndexEntry()) 
481              elif key == 'wallpaper': 
482                  new_entry.wallpaper = self._findmediainindex(data['wallpaper-index'], pb_entry['wallpaper'], pb_entry['name'], 'wallpaper') 
483                  try: 
484                      _filename = wp_index[new_entry.wallpaper]['filename'] 
485                      picid_pathf.items.append(self.protocolclass.PathIndexEntry(pathname=_filename)) 
486                      new_entry.wallpaper = 0x64 
487                  except: 
488                      picid_pathf.items.append(self.protocolclass.PathIndexEntry()) 
489              elif key in new_entry.getfields(): 
490                  setattr (new_entry, key, pb_entry[key]) 
491   
492          return new_entry 
 493   
494   
495       
497          data.serial_number = '000000d1-00000000-00000000-' + fwversion 
498          data.unknown3 = 0x01fc 
 499   
500   
501       
507               
514   
515       
516       
525   
553   
 576   
577   
578   
579  parentprofile=com_lgvx8550.Profile 
581      protocolclass=Phone.protocolclass 
582      serialsname=Phone.serialsname 
583   
584      BP_Calendar_Version=3 
585      phone_manufacturer='LG Electronics Inc' 
586      phone_model='VX9100' 
587   
588      WALLPAPER_WIDTH=320 
589      WALLPAPER_HEIGHT=240 
590       
591   
592      imageorigins={} 
593      imageorigins.update(common.getkv(parentprofile.stockimageorigins, "images")) 
594      imageorigins.update(common.getkv(parentprofile.stockimageorigins, "video")) 
595      imageorigins.update(common.getkv(parentprofile.stockimageorigins, "images(sd)")) 
596      imageorigins.update(common.getkv(parentprofile.stockimageorigins, "video(sd)")) 
599   
600   
601   
602   
603      ringtoneorigins=('ringers', 'sounds', 'sounds(sd)') 
604      excluded_ringtone_origins=('sounds', 'sounds(sd)') 
605   
606       
607      imagetargets={} 
608      imagetargets.update(common.getkv(parentprofile.stockimagetargets, "wallpaper", 
609                                        {'width': 320, 'height': 215, 'format': "JPEG"})) 
610      imagetargets.update(common.getkv(parentprofile.stockimagetargets, "outsidelcd", 
611                                        {'width': 160, 'height': 64, 'format': "JPEG"})) 
612   
615   
616      _supportedsyncs=( 
617          ('phonebook', 'read', None),    
618          ('calendar', 'read', None),     
619          ('wallpaper', 'read', None),    
620          ('ringtone', 'read', None),     
621          ('call_history', 'read', None), 
622          ('sms', 'read', None),          
623          ('memo', 'read', None),         
624          ('phonebook', 'write', 'OVERWRITE'),   
625          ('calendar', 'write', 'OVERWRITE'),    
626          ('wallpaper', 'write', 'MERGE'),       
627   
628          ('ringtone', 'write', 'MERGE'),        
629   
630   
631          ('memo', 'write', 'OVERWRITE'),        
632   
633   
634          ) 
635   
637          "Assigns groups based on category data" 
638   
639          pad=[] 
640          keys=data['groups'].keys() 
641          keys.sort() 
642          for k in keys: 
643                  if k:  
644                      name=data['groups'][k]['name'] 
645                      pad.append(name) 
646   
647          groups=helper.getmostpopularcategories(self.protocolclass.MAX_PHONEBOOK_GROUPS, data['phonebook'], ["No Group"], 32, pad) 
648   
649           
650          groups.sort() 
651   
652           
653          newgroups={} 
654   
655           
656          newgroups[0]={'name': 'No Group', 'user_added': 0} 
657   
658           
659          for name in groups: 
660               
661              if name=="No Group": continue 
662              key,value=self._getgroup(name, data['groups']) 
663              if key is not None and key!=0: 
664                  newgroups[key]=value 
665           
666          for name in groups: 
667              key,value=self._getgroup(name, newgroups) 
668              if key is None: 
669                  for key in range(1,100000): 
670                      if key not in newgroups: 
671                          newgroups[key]={'name': name, 'user_added': 1} 
672                          break 
673                          
674           
675          if data['groups']!=newgroups: 
676              data['groups']=newgroups 
677              data['rebootphone']=True 
 678   
680          """Converts the data to what will be used by the phone 
681   
682          @param data: contains the dict returned by getfundamentals 
683                       as well as where the results go""" 
684          results={} 
685   
686          self.normalisegroups(helper, data) 
687   
688          for pbentry in data['phonebook']: 
689              if len(results)==self.protocolclass.NUMPHONEBOOKENTRIES: 
690                  break 
691              e={}  
692              entry=data['phonebook'][pbentry]  
693              try: 
694                   
695                  serial1=helper.getserial(entry.get('serials', []), self.serialsname, data['uniqueserial'], 'serial1', 0) 
696                  serial2=helper.getserial(entry.get('serials', []), self.serialsname, data['uniqueserial'], 'serial2', serial1) 
697   
698                  e['serial1']=serial1 
699                  e['serial2']=serial2 
700                  for ss in entry["serials"]: 
701                      if ss["sourcetype"]=="bitpim": 
702                          e['bitpimserial']=ss 
703                  assert e['bitpimserial'] 
704   
705                   
706                  e['name']=helper.getfullname(entry.get('names', []),1,1,32)[0] 
707   
708                   
709                  e['ice']=entry.get('ice', None) 
710   
711                   
712                  cat=helper.makeone(helper.getcategory(entry.get('categories', []),0,1,32), None) 
713                  if cat is None: 
714                      e['group']=0 
715                  else: 
716                      key,value=self._getgroup(cat, data['groups']) 
717                      if key is not None: 
718                          e['group']=key 
719                      else: 
720                           
721                          e['group']=0 
722   
723                   
724                  emails=helper.getemails(entry.get('emails', []) ,0,self.protocolclass.NUMEMAILS,48) 
725                  e['emails']=helper.filllist(emails, self.protocolclass.NUMEMAILS, "") 
726   
727                   
728                   
729                  minnumbers=1 
730                  if len(emails): minnumbers=0 
731                  numbers=helper.getnumbers(entry.get('numbers', []),minnumbers,self.protocolclass.NUMPHONENUMBERS) 
732                  e['numbertypes']=[] 
733                  e['numbers']=[] 
734                  e['speeddials']=[] 
735                  for numindex in range(len(numbers)): 
736                      num=numbers[numindex] 
737                       
738                      b4=len(e['numbertypes']) 
739                      type=num['type'] 
740                      for i,t in enumerate(self.protocolclass.numbertypetab): 
741                          if type==t: 
742                               
743                              if i in e['numbertypes'] and t[-1]!='2': 
744                                  type+='2' 
745                                  continue 
746                              e['numbertypes'].append(i) 
747                              break 
748                          if t=='none':  
749                              e['numbertypes'].append(i) 
750                              break 
751                      if len(e['numbertypes'])==b4: 
752                           
753                          helper.add_error_message('Number %s (%s/%s) not supported and ignored.'% 
754                                                   (num['number'], e['name'], num['type'])) 
755                          continue  
756                       
757                      number=self.phonize(num['number']) 
758                      if len(number)==0: 
759                           
760                          continue 
761                      if len(number)>24:  
762                           
763                          number=number[:24]  
764                      e['numbers'].append(number) 
765                       
766                      sd=num.get("speeddial", None) 
767                      if sd is not None and \ 
768                         sd>=self.protocolclass.FIRSTSPEEDDIAL and \ 
769                         sd<=self.protocolclass.LASTSPEEDDIAL: 
770                          e['speeddials'].append(sd) 
771                      else: 
772                          e['speeddials'].append(None) 
773   
774                  if len(e['numbers'])<minnumbers: 
775                       
776                       
777                      helper.add_error_message("Name: %s. No suitable numbers or emails found" % e['name']) 
778                      continue  
779                  e['numbertypes']=helper.filllist(e['numbertypes'], self.protocolclass.NUMPHONENUMBERS, 0) 
780                  e['numbers']=helper.filllist(e['numbers'], self.protocolclass.NUMPHONENUMBERS, "") 
781                  e['speeddials']=helper.filllist(e['speeddials'], self.protocolclass.NUMPHONENUMBERS, None) 
782   
783                   
784                  e['ringtone']=helper.getringtone(entry.get('ringtones', []), 'call', None) 
785                  e['wallpaper']=helper.getwallpaper(entry.get('wallpapers', []), 'call', None) 
786   
787                  results[pbentry]=e 
788                   
789              except helper.ConversionFailed: 
790                  continue 
791   
792          data['phonebook']=results 
793          return data 
 794       
795      field_color_data={ 
796          'phonebook': { 
797              'name': { 
798                  'first': 1, 'middle': 1, 'last': 1, 'full': 1, 
799                  'nickname': 0, 'details': 1 }, 
800              'number': { 
801                  'type': 5, 'speeddial': 5, 'number': 5, 'details': 5 }, 
802              'email': 2, 
803              'address': { 
804                  'type': 0, 'company': 0, 'street': 0, 'street2': 0, 
805                  'city': 0, 'state': 0, 'postalcode': 0, 'country': 0, 
806                  'details': 0 }, 
807              'url': 0, 
808              'memo': 0, 
809              'category': 1, 
810              'wallpaper': 1, 
811              'ringtone': 2, 
812              'storage': 0, 
813              'secret': 0, 
814              'ICE': 1, 
815              }, 
816          'calendar': { 
817              'description': True, 'location': False, 'allday': False, 
818              'start': True, 'end': True, 'priority': False, 
819              'alarm': True, 'vibrate': True, 
820              'repeat': True, 
821              'memo': False, 
822              'category': False, 
823              'wallpaper': False, 
824              'ringtone': True, 
825              }, 
826          'memo': { 
827              'subject': True, 
828              'date': True, 
829              'secret': False, 
830              'category': False, 
831              'memo': True, 
832              }, 
833          'todo': { 
834              'summary': False, 
835              'status': False, 
836              'due_date': False, 
837              'percent_complete': False, 
838              'completion_date': False, 
839              'private': False, 
840              'priority': False, 
841              'category': False, 
842              'memo': False, 
843              }, 
844          } 
 845