Re: LG-VX code cleanup

Nathan Hjelm <[email protected]>
Newsgroups gmane.comp.mobile.bitpim.devel
Message-ID <[email protected]>

On Jun 3, 2007, at 8:36 AM, David Ritter wrote:

> Nathan,
> I am testing this patch with some files I am try to write for the  
> Alltel AX8600.
> My ax8600, seems to be stuck in the middle between the verizon  
> models. It uses the indexed media and indexsize files like the  
> vx9800, but also uses the DM modes from the vx8700.
> If I try using the 8500 as the parentphone, the media index read is  
> attempted using  LGUncountedIndexedMedia resulting in an error. The  
> structure of this phones .dat files and size files suggests that I  
> should be reading media indexes using  LGNewIndexedMedia2.
> I have tried modifying __init__ to include   
> "com_lg.LGNewIndexedMedia2.__init__(self)", but bitpim seems to  
> ignore this when I am using the vx8500 as a parentphone.
> If I use the svn 4260 version of bitpim  I can use the 9800 as a  
> parentphone and bypass the 8500 problems. This required the  
> "enter_DM()" to be added. But with the changed inheritance, on the  
> 9800 that no longer works.

I screwed up the patch somewhat as I forgot the double check the  
indexed media inheritance. Attached is a new version of the patch  
that fixes just this. Figures I would screw up something in the  
inheritance while trying to clean it up.

> Does this patch limit mixing DM v5 and LGNewIndexedMedia2 somehow?  
> It seems that the phones (9900,8700,8300) using the new DM v5 all  
> use the media files without index entries in the .dat files.

Nope, you should be able to inherit from the VX-9800 or use multiple  
inheritance to use the correct index file format.

Hope this helps.



-Nathan

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/

_______________________________________________
BitPim-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bitpim-devel
lgvx.patch (application/octet-stream, 65.4 KB)
Index: src/helpids.py
===================================================================
--- src/helpids.py	(revision 4260)
+++ src/helpids.py	(working copy)
@@ -53,6 +53,7 @@
 ID_PHONE_LGVX8500="phone-lgvx8500.htm"
 ID_PHONE_LGVX8600="phone-lgvx8600.htm"
 ID_PHONE_LGVX8700="phone-lgvx8700.htm"
+ID_PHONE_LGVX9400="phone-lgvx9400.htm"
 ID_PHONE_LGVX9800="phone-lgvx9800.htm"
 ID_PHONE_LGVX9900="phone-lgvx9900.htm"
 ID_PHONE_MOTOE815="phone-motoe815.htm"
Index: src/phones/__init__.py
===================================================================
--- src/phones/__init__.py	(revision 4260)
+++ src/phones/__init__.py	(working copy)
@@ -149,6 +149,11 @@
                              'brand': b_lg,
                              'helpid': helpids.ID_PHONE_LGVX8700,
                              },
+              'LG-VX9400': { 'module': 'com_lgvx9400',
+                             'carrier': [c_vzw],
+                             'brand': b_lg,
+                             'helpid': helpids.ID_PHONE_LGVX9400,
+                             },
               'LG-VX9800': { 'module': 'com_lgvx9800',
                              'carrier': [c_vzw],
                              'brand': b_lg,
Index: src/phones/com_lgvx8600.py
===================================================================
--- src/phones/com_lgvx8600.py	(revision 4260)
+++ src/phones/com_lgvx8600.py	(working copy)
@@ -30,6 +30,12 @@
 
     my_model='VX8600'
 
+    def __init__(self, logtarget, commport):
+        parentphone.__init__(self, logtarget, commport)
+        if self.my_model=='VX8600':
+            # it might be a good idea to use DMv5 on the VX-8600
+            self._DM_vers=4
+            
 #-------------------------------------------------------------------------------
 parentprofile=com_lgvx8500.Profile
 class Profile(parentprofile):
Index: src/phones/com_lgvx9800.py
===================================================================
--- src/phones/com_lgvx9800.py	(revision 4260)
+++ src/phones/com_lgvx9800.py	(working copy)
@@ -23,7 +23,8 @@
 import com_lgvx4400
 import p_brew
 import p_lgvx9800
-import com_lgvx8100
+import com_lgvx8300
+import com_lgvx8500
 import com_brew
 import com_phone
 import com_lg
@@ -35,7 +36,8 @@
 import playlist
 import helpids
 
-class Phone(com_lgvx8100.Phone):
+parentphone=com_lgvx8500.Phone
+class Phone(com_lg.LGNewIndexedMedia2, parentphone):
     "Talk to the LG VX9800 cell phone"
 
     desc="LG-VX9800"
@@ -67,367 +69,13 @@
         ( 'video', 'dload/video.dat', None, 'brew/16452/mf', 1000, 50, 0x0304, 0, 0),
         )
 
-    # for removable media (miniSD cards)
-    _rs_path='mmc1/'
-    _rs_ringers_path=_rs_path+'ringers'
-    _rs_images_path=_rs_path+'images'
-    media_info={ 'ringers': {
-            'localpath': 'brew/16452/lk/mr',
-            'rspath': _rs_ringers_path,
-            'vtype': protocolclass.MEDIA_TYPE_RINGTONE,
-            'icon': protocolclass.MEDIA_RINGTONE_DEFAULT_ICON,
-            'index': 100,  # starting index
-            'maxsize': 155,
-            'indexfile': 'dload/my_ringtone.dat',
-            'sizefile': 'dload/my_ringtonesize.dat',
-            'dunno': 0, 'date': False,
-        },
-         'sounds': {
-             'localpath': 'brew/16452/ms',
-             'rspath': None,
-             'vtype': protocolclass.MEDIA_TYPE_SOUND,
-             'icon': protocolclass.MEDIA_IMAGE_DEFAULT_ICON,
-             'index': 100,
-             'maxsize': 155,
-             'indexfile': 'dload/mysound.dat',
-             'sizefile': 'dload/mysoundsize.dat',
-             'dunno': 0, 'date': False },
-         'images': {
-             'localpath': 'brew/16452/mp',
-             'rspath': _rs_images_path,
-             'vtype': protocolclass.MEDIA_TYPE_IMAGE,
-             'icon': protocolclass.MEDIA_IMAGE_DEFAULT_ICON,
-             'index': 100,
-             'maxsize': 155,
-             'indexfile': 'dload/image.dat',
-             'sizefile': 'dload/imagesize.dat',
-             'dunno': 0, 'date': False },
-         'video': {
-             'localpath': 'brew/16452/mf',
-             'rspath': None,
-             'vtype': protocolclass.MEDIA_TYPE_VIDEO,
-             'icon': protocolclass.MEDIA_VIDEO_DEFAULT_ICON,
-             'index': 1000,
-             'maxsize': 155,
-             'indexfile': 'dload/video.dat',
-             'sizefile': 'dload/videosize.dat',
-             'dunno': 0, 'date': True },
-         }
-        
-    def __init__(self, logtarget, commport):
-        com_lgvx8100.Phone.__init__(self, logtarget, commport)
-        p_brew.PHONE_ENCODING=self.protocolclass.PHONE_ENCODING
-        self.mode=self.MODENONE
+# these methods are inherited from VX-8100 -- removed
+#    def _is_rs_file(self, filename):
+#    def getmedia(self, maps, results, key):
+#    def _mark_files(self, local_files, rs_files, local_dir):
+#    def _write_index_file(self, type):
+#    def savemedia(self, mediakey, mediaindexkey, maps, results, merge, reindexfunction):
 
-    def get_esn(self, data=None):
-        # return the ESN of this phone
-        return self.get_brew_esn()
-
-    def get_detect_data(self, res):
-        com_lgvx8100.Phone.get_detect_data(self, res)
-        res[self.esn_file_key]=self.get_esn()
-
-    def getfundamentals(self, results):
-        """Gets information fundamental to interopating with the phone and UI.
-
-        Currently this is:
-
-          - 'uniqueserial'     a unique serial number representing the phone
-          - 'groups'           the phonebook groups
-          - 'wallpaper-index'  map index numbers to names
-          - 'ringtone-index'   map index numbers to ringtone names
-
-        This method is called before we read the phonebook data or before we
-        write phonebook data.
-        """
-
-        # use a hash of ESN and other stuff (being paranoid)
-        self.log("Retrieving fundamental phone information")
-        self.log("Phone serial number")
-        results['uniqueserial']=sha.new(self.get_esn()).hexdigest()
-        # now read groups
-        self.log("Reading group information")
-        buf=prototypes.buffer(self.getfilecontents("pim/pbgroup.dat"))
-        g=self.protocolclass.pbgroups()
-        g.readfrombuffer(buf, logtitle="Groups read")
-        groups={}
-        for i in range(len(g.groups)):
-            if len(g.groups[i].name): # sometimes have zero length names
-                groups[i]={'name': g.groups[i].name }
-        results['groups']=groups
-        self.getwallpaperindices(results)
-        self.getringtoneindices(results)
-        self.log("Fundamentals retrieved")
-        return results
-
-    # Media stuff---------------------------------------------------------------
-    def _is_rs_file(self, filename):
-        return filename.startswith(self._rs_path)
-
-    def getmedia(self, maps, results, key):
-        origins={}
-        # signal that we are using the new media storage that includes the origin and timestamp
-        origins['new_media_version']=1
-
-        for type, indexfile, sizefile, directory, lowestindex, maxentries, typemajor, def_icon, idx_ofs  in maps:
-            media={}
-            for item in self.getindex(indexfile):
-                data=None
-                timestamp=None
-                try:
-                    stat_res=self.statfile(item.filename)
-                    if stat_res!=None:
-                        timestamp=stat_res['date'][0]
-                    if not self._is_rs_file(item.filename):
-                        data=self.getfilecontents(item.filename, True)
-                except (com_brew.BrewNoSuchFileException,com_brew.BrewBadPathnameException,com_brew.BrewNameTooLongException):
-                    self.log("It was in the index, but not on the filesystem")
-                except com_brew.BrewAccessDeniedException:
-                    # firmware wouldn't let us read this file, just mark it then
-                    self.log('Failed to read file: '+item.filename)
-                    data=''
-                except:
-                    if __debug__:
-                        raise
-                    self.log('Failed to read file: '+item.filename)
-                    data=''
-                if data!=None:
-                    media[common.basename(item.filename)]={ 'data': data, 'timestamp': timestamp}
-            origins[type]=media
-
-        results[key]=origins
-        return results
-
-    def _mark_files(self, local_files, rs_files, local_dir):
-        # create empty local files as markers for remote files
-        _empty_files=[common.basename(x) for x,_entry in local_files.items() \
-                      if not _entry['size']]
-        _remote_files=[common.basename(x) for x in rs_files]
-        for _file in _remote_files:
-            if _file not in _empty_files:
-                # mark this one
-                self.writefile(local_dir+'/'+_file, '')
-        for _file in _empty_files:
-            if _file not in _remote_files:
-                # remote file no longer exists, del the marker
-                self.rmfile(local_dir+'/'+_file)
-                
-    def _write_index_file(self, type):
-        _info=self.media_info.get(type, None)
-        if not _info:
-            return
-        _files={}
-        _local_dir=_info['localpath']
-        _rs_dir=_info['rspath']
-        _vtype=_info['vtype']
-        _icon=_info['icon']
-        _index=_info['index']
-        _maxsize=_info['maxsize']
-        _dunno=_info['dunno']
-        indexfile=_info['indexfile']
-        sizefile=_info['sizefile']
-        _need_date=_info['date']
-        try:
-            _files=self.listfiles(_local_dir)
-        except (com_brew.BrewNoSuchDirectoryException,
-                com_brew.BrewBadPathnameException):
-            pass
-        try:
-            if _rs_dir:
-                _rs_files=self.listfiles(_rs_dir)
-                if type=='ringers':
-                    self._mark_files(_files, _rs_files, _local_dir)
-                _files.update(_rs_files)
-        except (com_brew.BrewNoSuchDirectoryException,
-                com_brew.BrewBadPathnameException):
-            # dir does not exist, no media files available
-            pass
-        # del all the markers (empty files) ringers
-        if type=='ringers':
-            _keys=_files.keys()
-            for _key in _keys:
-                if not _files[_key]['size']:
-                    del _files[_key]
-        # dict of all indices
-        _idx_keys={}
-        for _i in xrange(_index, _index+_maxsize):
-            _idx_keys[_i]=True
-        # assign existing indices
-        for _item in self.getindex(indexfile):
-            if _files.has_key(_item.filename):
-                _files[_item.filename]['index']=_item.index
-                _idx_keys[_item.index]=False
-        # available new indices
-        _idx_keys_list=[k for k,x in _idx_keys.items() if x]
-        _idx_keys_list.sort()
-        _idx_cnt=0
-        # assign new indices
-        _file_list=[x for x in _files if not _files[x].get('index', None)]
-        _file_list.sort()
-        if len(_file_list)>len(_idx_keys_list):
-            _file_list=_file_list[:len(_idx_keys_list)]
-        for i in _file_list:
-            _files[i]['index']=_idx_keys_list[_idx_cnt]
-            _idx_cnt+=1
-        # (index, file name) list for writing
-        _res_list=[(x['index'],k) for k,x in _files.items() if x.get('index', None)]
-        _res_list.sort()
-        _res_list.reverse()
-        # writing the index file
-        ifile=self.protocolclass.indexfile()
-        _file_size=0
-        for index,idx in _res_list:
-            _fs_size=_files[idx]['size']
-            ie=self.protocolclass.indexentry()
-            ie.index=index
-            ie.type=_vtype
-            ie.filename=idx
-            if _need_date:
-                # need to fill in the date value
-                _stat=self.statfile(_files[idx]['name'])
-                if _stat:
-                    ie.date=_stat['datevalue']-time.timezone
-            ie.dunno=_dunno
-            ie.icon=_icon
-            ie.size=_fs_size
-            ifile.items.append(ie)
-            if not self._is_rs_file(idx):
-                _file_size+=_fs_size
-        buf=prototypes.buffer()
-        ifile.writetobuffer(buf, logtitle="Index file "+indexfile)
-        self.log("Writing index file "+indexfile+" for type "+type+" with "+`len(_res_list)`+" entries.")
-        self.writefile(indexfile, buf.getvalue())
-        # writing the size file
-        if sizefile:
-            szfile=self.protocolclass.sizefile()
-            szfile.size=_file_size
-            buf=prototypes.buffer()
-            szfile.writetobuffer(buf, logtitle="Updated size file for "+type)
-            self.log("You are using a total of "+`_file_size`+" bytes for "+type)
-            self.writefile(sizefile, buf.getvalue())
-
-    def savemedia(self, mediakey, mediaindexkey, maps, results, merge, reindexfunction):
-        """Actually saves out the media
-
-        @param mediakey: key of the media (eg 'wallpapers' or 'ringtones')
-        @param mediaindexkey:  index key (eg 'wallpaper-index')
-        @param maps: list index files and locations
-        @param results: results dict
-        @param merge: are we merging or overwriting what is there?
-        @param reindexfunction: the media is re-indexed at the end.  this function is called to do it
-        """
-
-        # take copies of the lists as we modify them
-        wp=results[mediakey].copy()  # the media we want to save
-        wpi=results[mediaindexkey].copy() # what is already in the index files
-
-        # remove builtins
-        for k in wpi.keys():
-            if wpi[k].get('origin', "")=='builtin':
-                del wpi[k]
-
-        # build up list into init
-        init={}
-        for type,_,_,_,lowestindex,_,typemajor,_,_ in maps:
-            init[type]={}
-            for k in wpi.keys():
-                if wpi[k]['origin']==type:
-                    index=k
-                    name=wpi[k]['name']
-                    fullname=wpi[k]['filename']
-                    vtype=wpi[k]['vtype']
-                    icon=wpi[k]['icon']
-                    data=None
-                    del wpi[k]
-                    for w in wp.keys():
-                        # does wp contain a reference to this same item?
-                        if wp[w]['name']==name and wp[w]['origin']==type:
-                            data=wp[w]['data']
-                            del wp[w]
-                    if not merge and data is None:
-                        # delete the entry
-                        continue
-##                    assert index>=lowestindex
-                    init[type][index]={'name': name, 'data': data, 'filename': fullname, 'vtype': vtype, 'icon': icon}
-
-        # init now contains everything from wallpaper-index
-        # wp contains items that we still need to add, and weren't in the existing index
-        assert len(wpi)==0
-        print init.keys()
-        
-        # now look through wallpapers and see if anything was assigned a particular
-        # origin
-        for w in wp.keys():
-            o=wp[w].get("origin", "")
-            if o is not None and len(o) and o in init:
-                idx=-1
-                while idx in init[o]:
-                    idx-=1
-                init[o][idx]=wp[w]
-                del wp[w]
-
-        # wp will now consist of items that weren't assigned any particular place
-        # so put them in the first available space
-        for type,_,_,_,lowestindex,maxentries,typemajor,def_icon,_ in maps:
-            # fill it up
-            for w in wp.keys():
-                if len(init[type])>=maxentries:
-                    break
-                idx=-1
-                while idx in init[type]:
-                    idx-=1
-                init[type][idx]=wp[w]
-                del wp[w]
-
-        # time to write the files out
-        for type, indexfile, sizefile, directory, lowestindex, maxentries,typemajor,def_icon,_  in maps:
-            # get the index file so we can work out what to delete
-            names=[init[type][x]['name'] for x in init[type]]
-            for item in self.getindex(indexfile):
-                if common.basename(item.filename) not in names and \
-                   not self._is_rs_file(item.filename):
-                    self.log(item.filename+" is being deleted")
-                    self.rmfile(item.filename)
-            # fixup the indices
-            fixups=[k for k in init[type].keys() if k<lowestindex]
-            fixups.sort()
-            for f in fixups:
-                for ii in xrange(lowestindex, lowestindex+maxentries):
-                    # allocate an index
-                    if ii not in init[type]:
-                        init[type][ii]=init[type][f]
-                        del init[type][f]
-                        break
-            # any left over?
-            fixups=[k for k in init[type].keys() if k<lowestindex]
-            for f in fixups:
-                self.log("There is no space in the index for "+type+" for "+init[type][f]['name'])
-                del init[type][f]
-            # write each entry out
-            for idx in init[type].keys():
-                entry=init[type][idx]
-                filename=entry.get('filename', directory+"/"+entry['name'])
-                entry['filename']=filename
-                fstat=self.statfile(filename)
-                if 'data' not in entry:
-                    # must be in the filesystem already
-                    if fstat is None:
-                        self.log("Entry "+entry['name']+" is in index "+indexfile+" but there is no data for it and it isn't in the filesystem.  The index entry will be removed.")
-                        del init[type][idx]
-                        continue
-                # check len(data) against fstat->length
-                data=entry['data']
-                if data is None:
-                    assert merge 
-                    continue # we are doing an add and don't have data for this existing entry
-                if fstat is not None and len(data)==fstat['size']:
-                    self.log("Not writing "+filename+" as a file of the same name and length already exists.")
-                else:
-                    self.writefile(filename, data)
-            # write out index
-            self._write_index_file(type)
-        return reindexfunction(results)
-
     # Phonebook stuff-----------------------------------------------------------
     def savephonebook(self, data):
         "Saves out the phonebook"
@@ -581,7 +229,7 @@
         return result
 
 #-------------------------------------------------------------------------------
-parentprofile=com_lgvx8100.Profile
+parentprofile=com_lgvx8300.Profile
 class Profile(parentprofile):
     protocolclass=Phone.protocolclass
     serialsname=Phone.serialsname
@@ -605,7 +253,7 @@
     # there is an origin named 'aod' - no idea what it is for except maybe
     # 'all other downloads'
 
-    # the vx8100 supports bluetooth for connectivity to the PC, define the "bluetooth_mgd_id"
+    # the vx9800 supports bluetooth for connectivity to the PC, define the "bluetooth_mgd_id"
     # to enable bluetooth discovery during phone detection
     # the bluetooth address starts with LG's the three-octet OUI, all LG phone
     # addresses start with this, it provides a way to identify LG bluetooth devices
@@ -614,7 +262,7 @@
     # see http://standards.ieee.org/regauth/oui/index.shtml for more info
     bluetooth_mfg_id="001256"
 
-    # the 8100 doesn't have seperate origins - they are all dumped in "images"
+    # the 9800 doesn't have seperate origins - they are all dumped in "images"
     imageorigins={}
     imageorigins.update(common.getkv(parentprofile.stockimageorigins, "images"))
     imageorigins.update(common.getkv(parentprofile.stockimageorigins, "video"))
@@ -657,4 +305,6 @@
         ('memo', 'write', 'OVERWRITE'),       # all memo list writing
         ('playlist', 'read', 'OVERWRITE'),
         ('playlist', 'write', 'OVERWRITE'),
+#        ('t9_udb', 'read', 'OVERWRITE'), # Not supported
+#        ('t9_udb', 'write', 'OVERWRITE'), # Not supported
         )
Index: src/phones/com_lgvx8300.py
===================================================================
--- src/phones/com_lgvx8300.py	(revision 4260)
+++ src/phones/com_lgvx8300.py	(working copy)
@@ -90,39 +90,6 @@
 
     my_model='VX8300'
 
-    def getfundamentals(self, results):
-        """Gets information fundamental to interopating with the phone and UI.
-
-        Currently this is:
-
-          - 'uniqueserial'     a unique serial number representing the phone
-          - 'groups'           the phonebook groups
-          - 'wallpaper-index'  map index numbers to names
-          - 'ringtone-index'   map index numbers to ringtone names
-
-        This method is called before we read the phonebook data or before we
-        write phonebook data.
-        """
-
-        # use a hash of ESN and other stuff (being paranoid)
-        self.log("Retrieving fundamental phone information")
-        self.log("Phone serial number")
-        results['uniqueserial']=sha.new(self.get_esn()).hexdigest()
-        # now read groups
-        self.log("Reading group information")
-        buf=prototypes.buffer(self.getfilecontents("pim/pbgroup.dat"))
-        g=self.protocolclass.pbgroups()
-        g.readfrombuffer(buf, logtitle="Groups read")
-        groups={}
-        for i in range(len(g.groups)):
-            if len(g.groups[i].name): # sometimes have zero length names
-                groups[i]={'name': g.groups[i].name }
-        results['groups']=groups
-        self.getwallpaperindices(results)
-        self.getringtoneindices(results)
-        self.log("Fundamentals retrieved")
-        return results
-
 parentprofile=com_lgvx8100.Profile
 class Profile(parentprofile):
     protocolclass=Phone.protocolclass
Index: src/phones/p_lgvx9900.p
===================================================================
--- src/phones/p_lgvx9900.p	(revision 4260)
+++ src/phones/p_lgvx9900.p	(working copy)
@@ -43,6 +43,10 @@
 from p_lgvx8500 import SMSINBOXMSGFRAGMENT
 from p_lgvx8500 import sms_in
 from p_lgvx8500 import sms_quick_text
+from p_lgvx8500 import DMKeyReq
+from p_lgvx8500 import DMKeyResp
+from p_lgvx8500 import DMReq
+from p_lgvx8500 import DMResp
 
 %}
 
Index: src/phones/com_lgvx8500.py
===================================================================
--- src/phones/com_lgvx8500.py	(revision 4260)
+++ src/phones/com_lgvx8500.py	(working copy)
@@ -31,10 +31,6 @@
 import prototypes
 import prototypeslg
 import t9editor
-try:
-    import pyvx8500
-except ImportError:
-    pyvx8500=None
 
 parentphone=com_lgvx8300.Phone
 class Phone(parentphone):
@@ -70,23 +66,16 @@
         parentphone.__init__(self, logtarget, commport)
         self._in_DM=False
 
-    def getfundamentals(self, results):
-        """Gets information fundamental to interopating with the phone and UI.
+        if self.my_model=='VX8500':
+            _fw_version=self.get_firmware_version()[-1]
+            if _fw_version > '4':
+                self._DM_vers=5
+            else:
+                self._DM_vers=4
+        else:
+            # don't set DM mode
+            self._DM_vers=-1
 
-        Currently this is:
-
-          - 'uniqueserial'     a unique serial number representing the phone
-          - 'groups'           the phonebook groups
-          - 'wallpaper-index'  map index numbers to names
-          - 'ringtone-index'   map index numbers to ringtone names
-
-        This method is called before we read phone data or before we
-        write phone data.
-        """
-        if not self._in_DM:
-            self.enter_DM()
-        return parentphone.getfundamentals(self, results)
-
     # Phonebook stuff-----------------------------------------------------------
     def _build_pb_info(self, fundamentals):
         # build a dict of info to update pbentry
@@ -419,11 +408,28 @@
             _req.key=_k
             self.sendbrewcommand(_req, self.protocolclass.data)
 
+    # Download mode------------------------------------------------------------
+    # need DM mode to read/write files on a VX-8500 with firmware newer than v4
+    # trap read/write here to enter DM
+    def getfilecontents(self, name, use_cache=False):
+        if self._in_DM==False:
+            self.enter_DM()
+        return parentphone.getfilecontents (self, name, use_cache)
+
+    def writefile(self, name, contents):
+        if self._in_DM==False:
+            self.enter_DM()
+        return parentphone.writefile (self, name, contents)
+
+    def statfile(self, name):
+        if self._in_DM==False:
+            self.enter_DM()
+        return parentphone.statfile(self, name)
+
     def _enter_DMv4(self):
         self._lock_key()
         self._press_key('\x06\x513733929\x51')
         self._unlock_key()
-        self._in_DM=True
 
     def _rotate_left(self, value, nbits):
         return ((value << nbits) | (value >> (32-nbits))) & 0xffffffffL
@@ -482,31 +488,34 @@
         return 0x80000000L | (hash_result[4] & 0x00ffffffL)
 
     def _enter_DMv5(self):
-        self._in_DM=True
         # request the seed
         _req=self.protocolclass.DMKeyReq()
         _resp=self.sendbrewcommand(_req, self.protocolclass.DMKeyResp)
+
         # respond with the key
         _key=self.get_challenge_response(_resp.key)
         if _key is None:
             self.log('Failed to get the key.')
-            return
+            raise
+
         _req=self.protocolclass.DMReq(key=_key)
-        self.sendbrewcommand(_req, self.protocolclass.DMResp)
+        _resp=self.sendbrewcommand(_req, self.protocolclass.DMResp)
+        if _resp.zero2one!=1:
+            raise
 
     def enter_DM(self):
-        try:
-            _fw_version=self.get_firmware_version()[-1]
-            if self.my_model=='VX8500' and _fw_version>'4':
-                self._enter_DMv5()
-            else:
-                self._enter_DMv4()
-            self.log('Now in DM')
-        except:
-            if __debug__:
-                raise
-            self.log('Failed to enter DM')
-            self._in_DM=True
+        if self._DM_vers != -1:
+            try:
+                if self._DM_vers == 5:
+                    self._enter_DMv5()
+                elif self._DM_vers == 4:
+                    self._enter_DMv4()
+                self.log('Now in download mode (DM)')
+                self._in_DM=True
+            except:
+                if __debug__:
+                    raise
+                self.log('Failed to enter download mode (DM)')
 
 #-------------------------------------------------------------------------------
 parentprofile=com_lgvx8300.Profile
@@ -533,6 +542,15 @@
         'MAXSIZE': 200000
     }
 
+    # the vx8500 supports bluetooth for connectivity to the PC, define the "bluetooth_mgd_id"
+    # to enable bluetooth discovery during phone detection
+    # the bluetooth address starts with LG's the three-octet OUI, all LG phone
+    # addresses start with this, it provides a way to identify LG bluetooth devices
+    # during phone discovery
+    # OUI=Organizationally Unique Identifier
+    # see http://standards.ieee.org/regauth/oui/index.shtml for more info
+    bluetooth_mfg_id="0019A1"
+
     imageorigins={}
     imageorigins.update(common.getkv(parentprofile.stockimageorigins, "images"))
     imageorigins.update(common.getkv(parentprofile.stockimageorigins, "video"))
Index: src/phones/p_lgvx8700.p
===================================================================
--- src/phones/p_lgvx8700.p	(revision 4260)
+++ src/phones/p_lgvx8700.p	(working copy)
@@ -15,8 +15,12 @@
 
 # we are the same as lgvx9900 except as noted below
 from p_lgvx9900 import *
-from p_lgvx8500 import t9udbfile
 
+from p_lgvx8500 import DMKeyReq
+from p_lgvx8500 import DMKeyResp
+from p_lgvx8500 import DMReq
+from p_lgvx8500 import DMResp
+
 # We use LSB for all integer like fields
 UINT=UINTlsb
 BOOL=BOOLlsb
@@ -29,6 +33,11 @@
 pb_file_name='pim/pbentry.dat'
 
 T9USERDBFILENAME='t9udb/t9udb_eng.dat'
+Default_Header='\x36\x00' \
+               '\x00\x00\x00\x00\x00\x00\x00\x00'
+Default_Header2=        '\xFB\x07\xF6\x0F\xF1\x17' \
+                '\xEC\x1F\xE7\x27\xE2\x2F\xDD\x37' \
+                '\xD8\x3F\xD3\x47'
 
 %}
 
@@ -88,16 +97,18 @@
     2 UINT numactiveitems
     * LIST {'elementclass': scheduleevent} +events
 
-PACKET ULReq:
-    ""
-    1 UINT { 'default': 0xFE } +cmd
-    1 UINT { 'default': 0x00 } +unlock_code
-    4 UINT unlock_key
-    1 UINT { 'default': 0x00 } +zero
-    
-PACKET ULRes:
-    ""
-    1 UINT cmd
-    1 UINT unlock_code
-    4 UINT unlock_key
-    1 UINT unlock_ok
+PACKET t9udbfile:
+    2 UINT { 'default': 0x5000 } +file_length
+    6 DATA { 'default': '\x7B\x1B\x00\x00\x01\x00' } +unknown1
+    2 UINT word_count
+    2 UINT { 'default': 0x00 } +unknown2
+    2 UINT free_space
+    10 DATA { 'default': Default_Header } +unknown3
+    2 UINT { 'default': 0 } +extra_cnt
+    18 DATA { 'default': Default_Header2 } +unknown4
+    if self.extra_cnt:
+        * LIST { 'length': self.extra_cnt } +extras:
+            1 UINT { 'default': 0 } +extra
+    1 UINT { 'default': 0 } +unk0
+    * LIST { 'createdefault': True } +blocks:
+        * T9USERDBBLOCK block
Index: src/phones/com_lgvx8700.py
===================================================================
--- src/phones/com_lgvx8700.py	(revision 4260)
+++ src/phones/com_lgvx8700.py	(working copy)
@@ -26,6 +26,7 @@
 
 #-------------------------------------------------------------------------------
 parentphone=com_lgvx8500.Phone
+# Use brew2 filesystem commands
 class Phone(com_brew.RealBrewProtocol2, parentphone):
     "Talk to LG VX-8700 cell phone"
 
@@ -59,28 +60,8 @@
 
     def __init__(self, logtarget, commport):
         parentphone.__init__(self, logtarget, commport)
-        self._in_DM = False
-
-    def getfundamentals(self, results):
-        """Gets information fundamental to interopating with the phone and UI.
-
-        Currently this is:
-
-          - 'uniqueserial'     a unique serial number representing the phone
-          - 'groups'           the phonebook groups
-          - 'wallpaper-index'  map index numbers to names
-          - 'ringtone-index'   map index numbers to ringtone names
-
-        This method is called before we read the phonebook data or before we
-        write phonebook data.
-        """
-        if not self._in_DM:
-            self.enter_DM()
-        results = parentphone.getfundamentals(self, results)
-
         if self.my_model=='VX8700':
-            self.getgroups(results)
-        return results
+            self._DM_vers=5
 
     # phonebook
     def _update_pb_file(self, pb, fundamentals, pbinfo):
@@ -154,46 +135,25 @@
         g.writetobuffer(buffer, logtitle="New group file")
         self.writefile("pim/pbgroup.dat", buffer.getvalue())
 
-    def is_mode_brew(self):
-        req=p_brew.memoryconfigrequest()
-        respc=p_brew.memoryconfigresponse
-
-        for baud in 0, 38400, 115200:
-            if baud:
-                if not self.comm.setbaudrate(baud):
-                    continue
-            try:
-                self.sendbrewcommand(req, respc, callsetmode=False)
-                return True
-            except com_phone.modeignoreerrortypes:
-                pass
-        return False
-
+    # Use brew2 filesystem commands
     def listsubdirs(self, dir='', recurse=0):
         return com_brew.RealBrewProtocol2.getfilesystem(self, dir, recurse, directories=1, files=0)
 
-    def listfiles(self, dir=''):
-        if self._in_DM==False and self.my_model=='VX8700':
-            # enter DM to enable file reading/writing
+    def getfilecontents(self, name, use_cache=False):
+        if self._in_DM==False:
             self.enter_DM()
-        return com_brew.RealBrewProtocol2.listfiles(self, dir)
-    
-    def enter_DM (self):
-        # request challenge
-        req = self.protocolclass.ULReq(unlock_key=0)
-        res = self.sendbrewcommand(req, self.protocolclass.ULRes)
+        return com_brew.RealBrewProtocol2.getfilecontents (self, name, use_cache)
 
-        # generate and send response
-        key = self.get_challenge_response(res.unlock_key);
-        req = self.protocolclass.ULReq(unlock_code=1, unlock_key=key)
-        res = self.sendbrewcommand(req, self.protocolclass.ULRes)
+    def writefile(self, name, contents):
+        if self._in_DM==False:
+            self.enter_DM()
+        return com_brew.RealBrewProtocol2.writefile (self, name, contents)
 
-        if res.unlock_ok == 1:
-            self.log('Phone is now in DM mode')
-            self._in_DM=True
-        else:
-            self.log('Failed to enter DM mode')
-
+    def statfile(self, name):
+        if self._in_DM==False:
+            self.enter_DM()
+        return com_brew.RealBrewProtocol2.statfile(self, name)
+    
 #-------------------------------------------------------------------------------
 parentprofile=com_lgvx8500.Profile
 class Profile(parentprofile):
@@ -215,14 +175,8 @@
 
     # our targets are the same for all origins
     imagetargets={}
-    imagetargets.update(common.getkv(parentprofile.stockimagetargets, "fullscreen",
-                                      {'width': 176, 'height': 220, 'format': "JPEG"}))
     imagetargets.update(common.getkv(parentprofile.stockimagetargets, "wallpaper",
-                                      {'width': 176, 'height': 184, 'format': "JPEG"}))
-    imagetargets.update(common.getkv(parentprofile.stockimagetargets, "outsidelcd",
-                                      {'width': 128, 'height': 160, 'format': "JPEG"}))
-    imagetargets.update(common.getkv(parentprofile.stockimagetargets, "pictureid",
-                                      {'width': 128, 'height': 142, 'format': "JPEG"}))
+                                      {'width': 240, 'height': 275, 'format': "JPEG"}))
 
     _supportedsyncs=(
         ('phonebook', 'read', None),  # all phonebook reading
Index: src/phones/com_lgvx9900.py
===================================================================
--- src/phones/com_lgvx9900.py	(revision 4260)
+++ src/phones/com_lgvx9900.py	(working copy)
@@ -56,7 +56,12 @@
 
     def __init__(self, logtarget, commport):
         parentphone.__init__(self, logtarget, commport)
-
+        if self.my_model=='VX9900':
+            _fw_version=self.get_firmware_version()[-1]
+            if _fw_version > '1':
+                # newer versions of the VX-9900 firmware require the phone to be in DM for file access
+                self._DM_vers=5
+    
 #-------------------------------------------------------------------------------
 parentprofile=com_lgvx9800.Profile
 class Profile(parentprofile):
Index: src/phones/p_lgvx8700.py
===================================================================
--- src/phones/p_lgvx8700.py	(revision 4260)
+++ src/phones/p_lgvx8700.py	(working copy)
@@ -7,8 +7,12 @@
 
 # we are the same as lgvx9900 except as noted below
 from p_lgvx9900 import *
-from p_lgvx8500 import t9udbfile
 
+from p_lgvx8500 import DMKeyReq
+from p_lgvx8500 import DMKeyResp
+from p_lgvx8500 import DMReq
+from p_lgvx8500 import DMResp
+
 # We use LSB for all integer like fields
 UINT=UINTlsb
 BOOL=BOOLlsb
@@ -21,6 +25,11 @@
 pb_file_name='pim/pbentry.dat'
 
 T9USERDBFILENAME='t9udb/t9udb_eng.dat'
+Default_Header='\x36\x00' \
+               '\x00\x00\x00\x00\x00\x00\x00\x00'
+Default_Header2=        '\xFB\x07\xF6\x0F\xF1\x17' \
+                '\xEC\x1F\xE7\x27\xE2\x2F\xDD\x37' \
+                '\xD8\x3F\xD3\x47'
 
 class pbgroup(BaseProtogenClass):
     __fields=['name', 'groupid', 'unknown0']
@@ -1050,17 +1059,16 @@
 
 
 
-class ULReq(BaseProtogenClass):
-    ""
-    __fields=['cmd', 'unlock_code', 'unlock_key', 'zero']
+class t9udbfile(BaseProtogenClass):
+    __fields=['file_length', 'unknown1', 'word_count', 'unknown2', 'free_space', 'unknown3', 'extra_cnt', 'unknown4', 'extras', 'unk0', 'blocks']
 
     def __init__(self, *args, **kwargs):
         dict={}
         # What was supplied to this function
         dict.update(kwargs)
         # Parent constructor
-        super(ULReq,self).__init__(**dict)
-        if self.__class__ is ULReq:
+        super(t9udbfile,self).__init__(**dict)
+        if self.__class__ is t9udbfile:
             self._update(args,dict)
 
 
@@ -1069,7 +1077,7 @@
 
 
     def _update(self, args, kwargs):
-        super(ULReq,self)._update(args,kwargs)
+        super(t9udbfile,self)._update(args,kwargs)
         keys=kwargs.keys()
         for key in keys:
             if key in self.__fields:
@@ -1077,7 +1085,7 @@
                 del kwargs[key]
         # Were any unrecognized kwargs passed in?
         if __debug__:
-            self._complainaboutunusedargs(ULReq,kwargs)
+            self._complainaboutunusedargs(t9udbfile,kwargs)
         if len(args): raise TypeError('Unexpected arguments supplied: '+`args`)
         # Make all P fields that haven't already been constructed
 
@@ -1085,19 +1093,45 @@
     def writetobuffer(self,buf,autolog=True,logtitle="<written data>"):
         'Writes this packet to the supplied buffer'
         self._bufferstartoffset=buf.getcurrentoffset()
-        try: self.__field_cmd
+        try: self.__field_file_length
         except:
-            self.__field_cmd=UINT(**{'sizeinbytes': 1,  'default': 0xFE })
-        self.__field_cmd.writetobuffer(buf)
-        try: self.__field_unlock_code
+            self.__field_file_length=UINT(**{'sizeinbytes': 2,  'default': 0x5000 })
+        self.__field_file_length.writetobuffer(buf)
+        try: self.__field_unknown1
         except:
-            self.__field_unlock_code=UINT(**{'sizeinbytes': 1,  'default': 0x00 })
-        self.__field_unlock_code.writetobuffer(buf)
-        self.__field_unlock_key.writetobuffer(buf)
-        try: self.__field_zero
+            self.__field_unknown1=DATA(**{'sizeinbytes': 6,  'default': '\x7B\x1B\x00\x00\x01\x00' })
+        self.__field_unknown1.writetobuffer(buf)
+        self.__field_word_count.writetobuffer(buf)
+        try: self.__field_unknown2
         except:
-            self.__field_zero=UINT(**{'sizeinbytes': 1,  'default': 0x00 })
-        self.__field_zero.writetobuffer(buf)
+            self.__field_unknown2=UINT(**{'sizeinbytes': 2,  'default': 0x00 })
+        self.__field_unknown2.writetobuffer(buf)
+        self.__field_free_space.writetobuffer(buf)
+        try: self.__field_unknown3
+        except:
+            self.__field_unknown3=DATA(**{'sizeinbytes': 10,  'default': Default_Header })
+        self.__field_unknown3.writetobuffer(buf)
+        try: self.__field_extra_cnt
+        except:
+            self.__field_extra_cnt=UINT(**{'sizeinbytes': 2,  'default': 0 })
+        self.__field_extra_cnt.writetobuffer(buf)
+        try: self.__field_unknown4
+        except:
+            self.__field_unknown4=DATA(**{'sizeinbytes': 18,  'default': Default_Header2 })
+        self.__field_unknown4.writetobuffer(buf)
+        if self.extra_cnt:
+            try: self.__field_extras
+            except:
+                self.__field_extras=LIST(**{'elementclass': _gen_p_lgvx8700_111,  'length': self.extra_cnt })
+            self.__field_extras.writetobuffer(buf)
+        try: self.__field_unk0
+        except:
+            self.__field_unk0=UINT(**{'sizeinbytes': 1,  'default': 0 })
+        self.__field_unk0.writetobuffer(buf)
+        try: self.__field_blocks
+        except:
+            self.__field_blocks=LIST(**{'elementclass': _gen_p_lgvx8700_114,  'createdefault': True })
+        self.__field_blocks.writetobuffer(buf)
         self._bufferendoffset=buf.getcurrentoffset()
         if autolog and self._bufferstartoffset==0: self.autologwrite(buf, logtitle=logtitle)
 
@@ -1106,101 +1140,233 @@
         'Reads this packet from the supplied buffer'
         self._bufferstartoffset=buf.getcurrentoffset()
         if autolog and self._bufferstartoffset==0: self.autologread(buf, logtitle=logtitle)
-        self.__field_cmd=UINT(**{'sizeinbytes': 1,  'default': 0xFE })
-        self.__field_cmd.readfrombuffer(buf)
-        self.__field_unlock_code=UINT(**{'sizeinbytes': 1,  'default': 0x00 })
-        self.__field_unlock_code.readfrombuffer(buf)
-        self.__field_unlock_key=UINT(**{'sizeinbytes': 4})
-        self.__field_unlock_key.readfrombuffer(buf)
-        self.__field_zero=UINT(**{'sizeinbytes': 1,  'default': 0x00 })
-        self.__field_zero.readfrombuffer(buf)
+        self.__field_file_length=UINT(**{'sizeinbytes': 2,  'default': 0x5000 })
+        self.__field_file_length.readfrombuffer(buf)
+        self.__field_unknown1=DATA(**{'sizeinbytes': 6,  'default': '\x7B\x1B\x00\x00\x01\x00' })
+        self.__field_unknown1.readfrombuffer(buf)
+        self.__field_word_count=UINT(**{'sizeinbytes': 2})
+        self.__field_word_count.readfrombuffer(buf)
+        self.__field_unknown2=UINT(**{'sizeinbytes': 2,  'default': 0x00 })
+        self.__field_unknown2.readfrombuffer(buf)
+        self.__field_free_space=UINT(**{'sizeinbytes': 2})
+        self.__field_free_space.readfrombuffer(buf)
+        self.__field_unknown3=DATA(**{'sizeinbytes': 10,  'default': Default_Header })
+        self.__field_unknown3.readfrombuffer(buf)
+        self.__field_extra_cnt=UINT(**{'sizeinbytes': 2,  'default': 0 })
+        self.__field_extra_cnt.readfrombuffer(buf)
+        self.__field_unknown4=DATA(**{'sizeinbytes': 18,  'default': Default_Header2 })
+        self.__field_unknown4.readfrombuffer(buf)
+        if self.extra_cnt:
+            self.__field_extras=LIST(**{'elementclass': _gen_p_lgvx8700_111,  'length': self.extra_cnt })
+            self.__field_extras.readfrombuffer(buf)
+        self.__field_unk0=UINT(**{'sizeinbytes': 1,  'default': 0 })
+        self.__field_unk0.readfrombuffer(buf)
+        self.__field_blocks=LIST(**{'elementclass': _gen_p_lgvx8700_114,  'createdefault': True })
+        self.__field_blocks.readfrombuffer(buf)
         self._bufferendoffset=buf.getcurrentoffset()
 
 
-    def __getfield_cmd(self):
-        try: self.__field_cmd
+    def __getfield_file_length(self):
+        try: self.__field_file_length
         except:
-            self.__field_cmd=UINT(**{'sizeinbytes': 1,  'default': 0xFE })
-        return self.__field_cmd.getvalue()
+            self.__field_file_length=UINT(**{'sizeinbytes': 2,  'default': 0x5000 })
+        return self.__field_file_length.getvalue()
 
-    def __setfield_cmd(self, value):
+    def __setfield_file_length(self, value):
         if isinstance(value,UINT):
-            self.__field_cmd=value
+            self.__field_file_length=value
         else:
-            self.__field_cmd=UINT(value,**{'sizeinbytes': 1,  'default': 0xFE })
+            self.__field_file_length=UINT(value,**{'sizeinbytes': 2,  'default': 0x5000 })
 
-    def __delfield_cmd(self): del self.__field_cmd
+    def __delfield_file_length(self): del self.__field_file_length
 
-    cmd=property(__getfield_cmd, __setfield_cmd, __delfield_cmd, None)
+    file_length=property(__getfield_file_length, __setfield_file_length, __delfield_file_length, None)
 
-    def __getfield_unlock_code(self):
-        try: self.__field_unlock_code
+    def __getfield_unknown1(self):
+        try: self.__field_unknown1
         except:
-            self.__field_unlock_code=UINT(**{'sizeinbytes': 1,  'default': 0x00 })
-        return self.__field_unlock_code.getvalue()
+            self.__field_unknown1=DATA(**{'sizeinbytes': 6,  'default': '\x7B\x1B\x00\x00\x01\x00' })
+        return self.__field_unknown1.getvalue()
 
-    def __setfield_unlock_code(self, value):
+    def __setfield_unknown1(self, value):
+        if isinstance(value,DATA):
+            self.__field_unknown1=value
+        else:
+            self.__field_unknown1=DATA(value,**{'sizeinbytes': 6,  'default': '\x7B\x1B\x00\x00\x01\x00' })
+
+    def __delfield_unknown1(self): del self.__field_unknown1
+
+    unknown1=property(__getfield_unknown1, __setfield_unknown1, __delfield_unknown1, None)
+
+    def __getfield_word_count(self):
+        return self.__field_word_count.getvalue()
+
+    def __setfield_word_count(self, value):
         if isinstance(value,UINT):
-            self.__field_unlock_code=value
+            self.__field_word_count=value
         else:
-            self.__field_unlock_code=UINT(value,**{'sizeinbytes': 1,  'default': 0x00 })
+            self.__field_word_count=UINT(value,**{'sizeinbytes': 2})
 
-    def __delfield_unlock_code(self): del self.__field_unlock_code
+    def __delfield_word_count(self): del self.__field_word_count
 
-    unlock_code=property(__getfield_unlock_code, __setfield_unlock_code, __delfield_unlock_code, None)
+    word_count=property(__getfield_word_count, __setfield_word_count, __delfield_word_count, None)
 
-    def __getfield_unlock_key(self):
-        return self.__field_unlock_key.getvalue()
+    def __getfield_unknown2(self):
+        try: self.__field_unknown2
+        except:
+            self.__field_unknown2=UINT(**{'sizeinbytes': 2,  'default': 0x00 })
+        return self.__field_unknown2.getvalue()
 
-    def __setfield_unlock_key(self, value):
+    def __setfield_unknown2(self, value):
         if isinstance(value,UINT):
-            self.__field_unlock_key=value
+            self.__field_unknown2=value
         else:
-            self.__field_unlock_key=UINT(value,**{'sizeinbytes': 4})
+            self.__field_unknown2=UINT(value,**{'sizeinbytes': 2,  'default': 0x00 })
 
-    def __delfield_unlock_key(self): del self.__field_unlock_key
+    def __delfield_unknown2(self): del self.__field_unknown2
 
-    unlock_key=property(__getfield_unlock_key, __setfield_unlock_key, __delfield_unlock_key, None)
+    unknown2=property(__getfield_unknown2, __setfield_unknown2, __delfield_unknown2, None)
 
-    def __getfield_zero(self):
-        try: self.__field_zero
+    def __getfield_free_space(self):
+        return self.__field_free_space.getvalue()
+
+    def __setfield_free_space(self, value):
+        if isinstance(value,UINT):
+            self.__field_free_space=value
+        else:
+            self.__field_free_space=UINT(value,**{'sizeinbytes': 2})
+
+    def __delfield_free_space(self): del self.__field_free_space
+
+    free_space=property(__getfield_free_space, __setfield_free_space, __delfield_free_space, None)
+
+    def __getfield_unknown3(self):
+        try: self.__field_unknown3
         except:
-            self.__field_zero=UINT(**{'sizeinbytes': 1,  'default': 0x00 })
-        return self.__field_zero.getvalue()
+            self.__field_unknown3=DATA(**{'sizeinbytes': 10,  'default': Default_Header })
+        return self.__field_unknown3.getvalue()
 
-    def __setfield_zero(self, value):
+    def __setfield_unknown3(self, value):
+        if isinstance(value,DATA):
+            self.__field_unknown3=value
+        else:
+            self.__field_unknown3=DATA(value,**{'sizeinbytes': 10,  'default': Default_Header })
+
+    def __delfield_unknown3(self): del self.__field_unknown3
+
+    unknown3=property(__getfield_unknown3, __setfield_unknown3, __delfield_unknown3, None)
+
+    def __getfield_extra_cnt(self):
+        try: self.__field_extra_cnt
+        except:
+            self.__field_extra_cnt=UINT(**{'sizeinbytes': 2,  'default': 0 })
+        return self.__field_extra_cnt.getvalue()
+
+    def __setfield_extra_cnt(self, value):
         if isinstance(value,UINT):
-            self.__field_zero=value
+            self.__field_extra_cnt=value
         else:
-            self.__field_zero=UINT(value,**{'sizeinbytes': 1,  'default': 0x00 })
+            self.__field_extra_cnt=UINT(value,**{'sizeinbytes': 2,  'default': 0 })
 
-    def __delfield_zero(self): del self.__field_zero
+    def __delfield_extra_cnt(self): del self.__field_extra_cnt
 
-    zero=property(__getfield_zero, __setfield_zero, __delfield_zero, None)
+    extra_cnt=property(__getfield_extra_cnt, __setfield_extra_cnt, __delfield_extra_cnt, None)
 
+    def __getfield_unknown4(self):
+        try: self.__field_unknown4
+        except:
+            self.__field_unknown4=DATA(**{'sizeinbytes': 18,  'default': Default_Header2 })
+        return self.__field_unknown4.getvalue()
+
+    def __setfield_unknown4(self, value):
+        if isinstance(value,DATA):
+            self.__field_unknown4=value
+        else:
+            self.__field_unknown4=DATA(value,**{'sizeinbytes': 18,  'default': Default_Header2 })
+
+    def __delfield_unknown4(self): del self.__field_unknown4
+
+    unknown4=property(__getfield_unknown4, __setfield_unknown4, __delfield_unknown4, None)
+
+    def __getfield_extras(self):
+        try: self.__field_extras
+        except:
+            self.__field_extras=LIST(**{'elementclass': _gen_p_lgvx8700_111,  'length': self.extra_cnt })
+        return self.__field_extras.getvalue()
+
+    def __setfield_extras(self, value):
+        if isinstance(value,LIST):
+            self.__field_extras=value
+        else:
+            self.__field_extras=LIST(value,**{'elementclass': _gen_p_lgvx8700_111,  'length': self.extra_cnt })
+
+    def __delfield_extras(self): del self.__field_extras
+
+    extras=property(__getfield_extras, __setfield_extras, __delfield_extras, None)
+
+    def __getfield_unk0(self):
+        try: self.__field_unk0
+        except:
+            self.__field_unk0=UINT(**{'sizeinbytes': 1,  'default': 0 })
+        return self.__field_unk0.getvalue()
+
+    def __setfield_unk0(self, value):
+        if isinstance(value,UINT):
+            self.__field_unk0=value
+        else:
+            self.__field_unk0=UINT(value,**{'sizeinbytes': 1,  'default': 0 })
+
+    def __delfield_unk0(self): del self.__field_unk0
+
+    unk0=property(__getfield_unk0, __setfield_unk0, __delfield_unk0, None)
+
+    def __getfield_blocks(self):
+        try: self.__field_blocks
+        except:
+            self.__field_blocks=LIST(**{'elementclass': _gen_p_lgvx8700_114,  'createdefault': True })
+        return self.__field_blocks.getvalue()
+
+    def __setfield_blocks(self, value):
+        if isinstance(value,LIST):
+            self.__field_blocks=value
+        else:
+            self.__field_blocks=LIST(value,**{'elementclass': _gen_p_lgvx8700_114,  'createdefault': True })
+
+    def __delfield_blocks(self): del self.__field_blocks
+
+    blocks=property(__getfield_blocks, __setfield_blocks, __delfield_blocks, None)
+
     def iscontainer(self):
         return True
 
     def containerelements(self):
-        yield ('cmd', self.__field_cmd, None)
-        yield ('unlock_code', self.__field_unlock_code, None)
-        yield ('unlock_key', self.__field_unlock_key, None)
-        yield ('zero', self.__field_zero, None)
+        yield ('file_length', self.__field_file_length, None)
+        yield ('unknown1', self.__field_unknown1, None)
+        yield ('word_count', self.__field_word_count, None)
+        yield ('unknown2', self.__field_unknown2, None)
+        yield ('free_space', self.__field_free_space, None)
+        yield ('unknown3', self.__field_unknown3, None)
+        yield ('extra_cnt', self.__field_extra_cnt, None)
+        yield ('unknown4', self.__field_unknown4, None)
+        if self.extra_cnt:
+            yield ('extras', self.__field_extras, None)
+        yield ('unk0', self.__field_unk0, None)
+        yield ('blocks', self.__field_blocks, None)
 
 
 
 
-class ULRes(BaseProtogenClass):
-    ""
-    __fields=['cmd', 'unlock_code', 'unlock_key', 'unlock_ok']
+class _gen_p_lgvx8700_111(BaseProtogenClass):
+    'Anonymous inner class'
+    __fields=['extra']
 
     def __init__(self, *args, **kwargs):
         dict={}
         # What was supplied to this function
         dict.update(kwargs)
         # Parent constructor
-        super(ULRes,self).__init__(**dict)
-        if self.__class__ is ULRes:
+        super(_gen_p_lgvx8700_111,self).__init__(**dict)
+        if self.__class__ is _gen_p_lgvx8700_111:
             self._update(args,dict)
 
 
@@ -1209,7 +1375,7 @@
 
 
     def _update(self, args, kwargs):
-        super(ULRes,self)._update(args,kwargs)
+        super(_gen_p_lgvx8700_111,self)._update(args,kwargs)
         keys=kwargs.keys()
         for key in keys:
             if key in self.__fields:
@@ -1217,18 +1383,22 @@
                 del kwargs[key]
         # Were any unrecognized kwargs passed in?
         if __debug__:
-            self._complainaboutunusedargs(ULRes,kwargs)
-        if len(args): raise TypeError('Unexpected arguments supplied: '+`args`)
+            self._complainaboutunusedargs(_gen_p_lgvx8700_111,kwargs)
+        if len(args):
+            dict2={'sizeinbytes': 1,  'default': 0 }
+            dict2.update(kwargs)
+            kwargs=dict2
+            self.__field_extra=UINT(*args,**dict2)
         # Make all P fields that haven't already been constructed
 
 
     def writetobuffer(self,buf,autolog=True,logtitle="<written data>"):
         'Writes this packet to the supplied buffer'
         self._bufferstartoffset=buf.getcurrentoffset()
-        self.__field_cmd.writetobuffer(buf)
-        self.__field_unlock_code.writetobuffer(buf)
-        self.__field_unlock_key.writetobuffer(buf)
-        self.__field_unlock_ok.writetobuffer(buf)
+        try: self.__field_extra
+        except:
+            self.__field_extra=UINT(**{'sizeinbytes': 1,  'default': 0 })
+        self.__field_extra.writetobuffer(buf)
         self._bufferendoffset=buf.getcurrentoffset()
         if autolog and self._bufferstartoffset==0: self.autologwrite(buf, logtitle=logtitle)
 
@@ -1237,77 +1407,107 @@
         'Reads this packet from the supplied buffer'
         self._bufferstartoffset=buf.getcurrentoffset()
         if autolog and self._bufferstartoffset==0: self.autologread(buf, logtitle=logtitle)
-        self.__field_cmd=UINT(**{'sizeinbytes': 1})
-        self.__field_cmd.readfrombuffer(buf)
-        self.__field_unlock_code=UINT(**{'sizeinbytes': 1})
-        self.__field_unlock_code.readfrombuffer(buf)
-        self.__field_unlock_key=UINT(**{'sizeinbytes': 4})
-        self.__field_unlock_key.readfrombuffer(buf)
-        self.__field_unlock_ok=UINT(**{'sizeinbytes': 1})
-        self.__field_unlock_ok.readfrombuffer(buf)
+        self.__field_extra=UINT(**{'sizeinbytes': 1,  'default': 0 })
+        self.__field_extra.readfrombuffer(buf)
         self._bufferendoffset=buf.getcurrentoffset()
 
 
-    def __getfield_cmd(self):
-        return self.__field_cmd.getvalue()
+    def __getfield_extra(self):
+        try: self.__field_extra
+        except:
+            self.__field_extra=UINT(**{'sizeinbytes': 1,  'default': 0 })
+        return self.__field_extra.getvalue()
 
-    def __setfield_cmd(self, value):
+    def __setfield_extra(self, value):
         if isinstance(value,UINT):
-            self.__field_cmd=value
+            self.__field_extra=value
         else:
-            self.__field_cmd=UINT(value,**{'sizeinbytes': 1})
+            self.__field_extra=UINT(value,**{'sizeinbytes': 1,  'default': 0 })
 
-    def __delfield_cmd(self): del self.__field_cmd
+    def __delfield_extra(self): del self.__field_extra
 
-    cmd=property(__getfield_cmd, __setfield_cmd, __delfield_cmd, None)
+    extra=property(__getfield_extra, __setfield_extra, __delfield_extra, None)
 
-    def __getfield_unlock_code(self):
-        return self.__field_unlock_code.getvalue()
+    def iscontainer(self):
+        return True
 
-    def __setfield_unlock_code(self, value):
-        if isinstance(value,UINT):
-            self.__field_unlock_code=value
-        else:
-            self.__field_unlock_code=UINT(value,**{'sizeinbytes': 1})
+    def containerelements(self):
+        yield ('extra', self.__field_extra, None)
 
-    def __delfield_unlock_code(self): del self.__field_unlock_code
 
-    unlock_code=property(__getfield_unlock_code, __setfield_unlock_code, __delfield_unlock_code, None)
 
-    def __getfield_unlock_key(self):
-        return self.__field_unlock_key.getvalue()
 
-    def __setfield_unlock_key(self, value):
-        if isinstance(value,UINT):
-            self.__field_unlock_key=value
-        else:
-            self.__field_unlock_key=UINT(value,**{'sizeinbytes': 4})
+class _gen_p_lgvx8700_114(BaseProtogenClass):
+    'Anonymous inner class'
+    __fields=['block']
 
-    def __delfield_unlock_key(self): del self.__field_unlock_key
+    def __init__(self, *args, **kwargs):
+        dict={}
+        # What was supplied to this function
+        dict.update(kwargs)
+        # Parent constructor
+        super(_gen_p_lgvx8700_114,self).__init__(**dict)
+        if self.__class__ is _gen_p_lgvx8700_114:
+            self._update(args,dict)
 
-    unlock_key=property(__getfield_unlock_key, __setfield_unlock_key, __delfield_unlock_key, None)
 
-    def __getfield_unlock_ok(self):
-        return self.__field_unlock_ok.getvalue()
+    def getfields(self):
+        return self.__fields
 
-    def __setfield_unlock_ok(self, value):
-        if isinstance(value,UINT):
-            self.__field_unlock_ok=value
+
+    def _update(self, args, kwargs):
+        super(_gen_p_lgvx8700_114,self)._update(args,kwargs)
+        keys=kwargs.keys()
+        for key in keys:
+            if key in self.__fields:
+                setattr(self, key, kwargs[key])
+                del kwargs[key]
+        # Were any unrecognized kwargs passed in?
+        if __debug__:
+            self._complainaboutunusedargs(_gen_p_lgvx8700_114,kwargs)
+        if len(args):
+            dict2={}
+            dict2.update(kwargs)
+            kwargs=dict2
+            self.__field_block=T9USERDBBLOCK(*args,**dict2)
+        # Make all P fields that haven't already been constructed
+
+
+    def writetobuffer(self,buf,autolog=True,logtitle="<written data>"):
+        'Writes this packet to the supplied buffer'
+        self._bufferstartoffset=buf.getcurrentoffset()
+        self.__field_block.writetobuffer(buf)
+        self._bufferendoffset=buf.getcurrentoffset()
+        if autolog and self._bufferstartoffset==0: self.autologwrite(buf, logtitle=logtitle)
+
+
+    def readfrombuffer(self,buf,autolog=True,logtitle="<read data>"):
+        'Reads this packet from the supplied buffer'
+        self._bufferstartoffset=buf.getcurrentoffset()
+        if autolog and self._bufferstartoffset==0: self.autologread(buf, logtitle=logtitle)
+        self.__field_block=T9USERDBBLOCK()
+        self.__field_block.readfrombuffer(buf)
+        self._bufferendoffset=buf.getcurrentoffset()
+
+
+    def __getfield_block(self):
+        return self.__field_block.getvalue()
+
+    def __setfield_block(self, value):
+        if isinstance(value,T9USERDBBLOCK):
+            self.__field_block=value
         else:
-            self.__field_unlock_ok=UINT(value,**{'sizeinbytes': 1})
+            self.__field_block=T9USERDBBLOCK(value,)
 
-    def __delfield_unlock_ok(self): del self.__field_unlock_ok
+    def __delfield_block(self): del self.__field_block
 
-    unlock_ok=property(__getfield_unlock_ok, __setfield_unlock_ok, __delfield_unlock_ok, None)
+    block=property(__getfield_block, __setfield_block, __delfield_block, None)
 
     def iscontainer(self):
         return True
 
     def containerelements(self):
-        yield ('cmd', self.__field_cmd, None)
-        yield ('unlock_code', self.__field_unlock_code, None)
-        yield ('unlock_key', self.__field_unlock_key, None)
-        yield ('unlock_ok', self.__field_unlock_ok, None)
+        yield ('block', self.__field_block, None)
 
 
 
Index: src/phones/p_lgvx9900.py
===================================================================
--- src/phones/p_lgvx9900.py	(revision 4260)
+++ src/phones/p_lgvx9900.py	(working copy)
@@ -33,6 +33,10 @@
 from p_lgvx8500 import SMSINBOXMSGFRAGMENT
 from p_lgvx8500 import sms_in
 from p_lgvx8500 import sms_quick_text
+from p_lgvx8500 import DMKeyReq
+from p_lgvx8500 import DMKeyResp
+from p_lgvx8500 import DMReq
+from p_lgvx8500 import DMResp
 
 class textmemo(BaseProtogenClass):
     __fields=['text', 'dunno', 'memotime']
Index: src/phones/com_lgvx4400.py
===================================================================
--- src/phones/com_lgvx4400.py	(revision 4260)
+++ src/phones/com_lgvx4400.py	(working copy)
@@ -93,17 +93,9 @@
         # use a hash of ESN and other stuff (being paranoid)
         self.log("Retrieving fundamental phone information")
         self.log("Phone serial number")
-        results['uniqueserial']=sha.new(self.getfilecontents("nvm/$SYS.ESN")).hexdigest()
+        results['uniqueserial']=sha.new(self.get_esn()).hexdigest()
         # now read groups
-        self.log("Reading group information")
-        buf=prototypes.buffer(self.getfilecontents("pim/pbgroup.dat"))
-        g=self.protocolclass.pbgroups()
-        g.readfrombuffer(buf, logtitle="Groups read")
-        groups={}
-        for i in range(len(g.groups)):
-            if len(g.groups[i].name): # sometimes have zero length names
-                groups[i]={ 'icon': g.groups[i].icon, 'name': g.groups[i].name }
-        results['groups']=groups
+        self.getgroups(results)
         self.getwallpaperindices(results)
         self.getringtoneindices(results)
         self.log("Fundamentals retrieved")
@@ -416,6 +408,18 @@
         print "returning keys",result.keys()
         return pbook
 
+    def getgroups(self, results):
+        self.log("Reading group information")
+        buf=prototypes.buffer(self.getfilecontents("pim/pbgroup.dat"))
+        g=self.protocolclass.pbgroups()
+        g.readfrombuffer(buf, logtitle="Groups read")
+        groups={}
+        for i in range(len(g.groups)):
+            if len(g.groups[i].name): # sometimes have zero length names
+                groups[i]={ 'icon': g.groups[i].icon, 'name': g.groups[i].name }
+        results['groups']=groups
+        return groups
+        
     def savegroups(self, data):
         groups=data['groups']
         keys=groups.keys()
Index: src/phones/com_lgvx5300.py
===================================================================
--- src/phones/com_lgvx5300.py	(revision 4260)
+++ src/phones/com_lgvx5300.py	(working copy)
@@ -25,10 +25,9 @@
 import common
 import commport
 import copy
-import com_lgvx4400
 import p_brew
 import p_lgvx5300
-import com_lgvx8100
+import com_lgvx8300
 import com_brew
 import com_phone
 import com_lg
@@ -40,7 +39,8 @@
 import fileinfo
 import helpids
 
-class Phone(com_lg.LGUncountedIndexedMedia, com_lgvx8100.Phone):
+parentphone=com_lgvx8300.Phone
+class Phone(com_lg.LGNewIndexedMedia2, parentphone):
     "Talk to the LG VX5300 cell phone"
 
     desc="LG-VX5300"
@@ -74,55 +74,9 @@
         ( 'video',      'dload/video.dat',    'brew/16452/mf', '',           100, 0x03, None),
         )
 
-    def __init__(self, logtarget, commport):
-        com_lgvx8100.Phone.__init__(self, logtarget, commport)
-        p_brew.PHONE_ENCODING=self.protocolclass.PHONE_ENCODING
-        self.mode=self.MODENONE
-
-    def get_esn(self, data=None):
-        # return the ESN of this phone
-        return self.get_brew_esn()
-
-    def get_detect_data(self, res):
-        com_lgvx8100.Phone.get_detect_data(self, res)
-        res[self.esn_file_key]=self.get_esn()
-
     my_model='VX5300'
 
-    def getfundamentals(self, results):
-        """Gets information fundamental to interopating with the phone and UI.
-
-        Currently this is:
-
-          - 'uniqueserial'     a unique serial number representing the phone
-          - 'groups'           the phonebook groups
-          - 'wallpaper-index'  map index numbers to names
-          - 'ringtone-index'   map index numbers to ringtone names
-
-        This method is called before we read the phonebook data or before we
-        write phonebook data.
-        """
-
-        # use a hash of ESN and other stuff (being paranoid)
-        self.log("Retrieving fundamental phone information")
-        self.log("Phone serial number")
-        results['uniqueserial']=sha.new(self.get_esn()).hexdigest()
-        # now read groups
-        self.log("Reading group information")
-        buf=prototypes.buffer(self.getfilecontents("pim/pbgroup.dat"))
-        g=self.protocolclass.pbgroups()
-        g.readfrombuffer(buf, logtitle="Groups read")
-        groups={}
-        for i in range(len(g.groups)):
-            if len(g.groups[i].name): # sometimes have zero length names
-                groups[i]={'name': g.groups[i].name }
-        results['groups']=groups
-        self.getwallpaperindices(results)
-        self.getringtoneindices(results)
-        self.log("Fundamentals retrieved")
-        return results
-
-parentprofile=com_lgvx8100.Profile
+parentprofile=com_lgvx8300.Profile
 class Profile(parentprofile):
     protocolclass=Phone.protocolclass
     serialsname=Phone.serialsname
Index: src/phones/com_lgvx8100.py
===================================================================
--- src/phones/com_lgvx8100.py	(revision 4260)
+++ src/phones/com_lgvx8100.py	(working copy)
@@ -126,25 +126,7 @@
         com_lgvx4400.Phone.__init__(self, logtarget, commport)
         self.mode=self.MODENONE
 
-    def getfundamentals(self, results):
-        """Gets information fundamental to interopating with the phone and UI.
-
-        Currently this is:
-
-          - 'uniqueserial'     a unique serial number representing the phone
-          - 'groups'           the phonebook groups
-          - 'wallpaper-index'  map index numbers to names
-          - 'ringtone-index'   map index numbers to ringtone names
-
-        This method is called before we read the phonebook data or before we
-        write phonebook data.
-        """
-
-        # use a hash of ESN and other stuff (being paranoid)
-        self.log("Retrieving fundamental phone information")
-        self.log("Phone serial number")
-        results['uniqueserial']=sha.new(self.getfilecontents("nvm/$SYS.ESN")).hexdigest()
-        # now read groups
+    def getgroups(self, results):
         self.log("Reading group information")
         buf=prototypes.buffer(self.getfilecontents("pim/pbgroup.dat"))
         g=self.protocolclass.pbgroups()
@@ -154,10 +136,7 @@
             if len(g.groups[i].name): # sometimes have zero length names
                 groups[i]={'name': g.groups[i].name }
         results['groups']=groups
-        self.getwallpaperindices(results)
-        self.getringtoneindices(results)
-        self.log("Fundamentals retrieved")
-        return results
+        return groups
 
     def savegroups(self, data):
         groups=data['groups']
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.