Re: Preliminary enV2/VX9100 Support

Nathan Hjelm <[email protected]>
Newsgroups gmane.comp.mobile.bitpim.devel
Message-ID <[email protected]>
I have determined how the XOR key bytes are rotated in keys 1-4 of the  
0xfe 03 command. I am 99.99% certain that the attached update to the  
DMv6 scheme will work with all DMv6 phones (including the Dare).  
Experimental Dare support is also attached.

Joe, would you be ok with going to a scheme where DMv6 is detected. I  
am fairly certain LG does this in their Dll and I know that both the  
Dare and the VX-9100 respond to the shorter DMv5 0xff 00 command  
properly with the 0xfe 02 response. I can write up a patch that uses  
your DMv6 packet for the 0xfe 03 command.



-Nathan

On Jun 29, 2008, at 10:01 PM, Joe Pham wrote:

>> Attached are patches which implement the suggestion from my
>> previous email (setting all the bytes of keys 1-4).
>
> That's a very good idea, this should cover most if not all cases.   
> Committed.
>
> -Joe Pham
>
>
> ____________________________________________________________
> Summer Spa Sweepstakes
> Enter for your chance to WIN a Summer Spa Vacation!
> http://thirdpartyoffers.netzero.net/TGL2231/fc/JKFkuJO6pXuLlCZZ1ebIBfYiTLZO2D1YYVwSjsanyrLNnLau2HpPzG/
>
> -------------------------------------------------------------------------
> Check out the new SourceForge.net Marketplace.
> It's the best place to buy or sell services for
> just about anything Open Source.
> http://sourceforge.net/services/buy/index.php
> _______________________________________________
> BitPim-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/bitpim-devel

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php

_______________________________________________
BitPim-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bitpim-devel
DMv6_update.diff (application/octet-stream, 21.1 KB)
Index: src/phones/p_lg.py
===================================================================
--- src/phones/p_lg.py	(revision 4624)
+++ src/phones/p_lg.py	(working copy)
@@ -3,6 +3,7 @@
 """Various descriptions of data specific to LG phones"""
 
 from prototypes import *
+import re
 
 # We use LSB for all integer like fields
 UINT=UINTlsb
@@ -2641,7 +2642,7 @@
         if self.unlock_code==3:
             try: self.__field_unlock_key2
             except:
-                self.__field_unlock_key2=LIST(**{'elementclass': _gen_p_lg_179,  'createdefault': True,                 'length': 16 })
+                self.__field_unlock_key2=LIST(**{'elementclass': _gen_p_lg_180,  'createdefault': True,                 'length': 16 })
             self.__field_unlock_key2.writetobuffer(buf)
         self._bufferendoffset=buf.getcurrentoffset()
         if autolog and self._bufferstartoffset==0: self.autologwrite(buf, logtitle=logtitle)
@@ -2662,7 +2663,7 @@
         self.__field_option=UINT(**{'sizeinbytes': 1,  'default': 0x00 })
         self.__field_option.readfrombuffer(buf)
         if self.unlock_code==3:
-            self.__field_unlock_key2=LIST(**{'elementclass': _gen_p_lg_179,  'createdefault': True,                 'length': 16 })
+            self.__field_unlock_key2=LIST(**{'elementclass': _gen_p_lg_180,  'createdefault': True,                 'length': 16 })
             self.__field_unlock_key2.readfrombuffer(buf)
         self._bufferendoffset=buf.getcurrentoffset()
 
@@ -2750,14 +2751,14 @@
     def __getfield_unlock_key2(self):
         try: self.__field_unlock_key2
         except:
-            self.__field_unlock_key2=LIST(**{'elementclass': _gen_p_lg_179,  'createdefault': True,                 'length': 16 })
+            self.__field_unlock_key2=LIST(**{'elementclass': _gen_p_lg_180,  'createdefault': True,                 'length': 16 })
         return self.__field_unlock_key2.getvalue()
 
     def __setfield_unlock_key2(self, value):
         if isinstance(value,LIST):
             self.__field_unlock_key2=value
         else:
-            self.__field_unlock_key2=LIST(value,**{'elementclass': _gen_p_lg_179,  'createdefault': True,                 'length': 16 })
+            self.__field_unlock_key2=LIST(value,**{'elementclass': _gen_p_lg_180,  'createdefault': True,                 'length': 16 })
 
     def __delfield_unlock_key2(self): del self.__field_unlock_key2
 
@@ -2782,7 +2783,7 @@
             for _idx in range(16):
                 self.unlock_key2.append(0)
 
-    def convert_to_key2(self):  
+    def convert_to_key2(self,shift):  
         """Convert the key value to key2"""
         if self.unlock_code!=3:
             return
@@ -2791,7 +2792,7 @@
         UINT(sizeinbytes=4, value=~self.unlock_key).writetobuffer(_buf)
         _key=_buf.getvalue()
         for _idx in range(4):
-            _nth_key=ord(_key[_idx])
+            _nth_key=ord(_key[(_idx + 4 - shift) % 4])
             for _idy in range(4):
                 self.unlock_key2[_idx*4+_idy]=_nth_key
 
@@ -2799,7 +2800,7 @@
 
 
 
-class _gen_p_lg_179(BaseProtogenClass):
+class _gen_p_lg_180(BaseProtogenClass):
     'Anonymous inner class'
     __fields=['data']
 
@@ -2808,8 +2809,8 @@
         # What was supplied to this function
         dict.update(kwargs)
         # Parent constructor
-        super(_gen_p_lg_179,self).__init__(**dict)
-        if self.__class__ is _gen_p_lg_179:
+        super(_gen_p_lg_180,self).__init__(**dict)
+        if self.__class__ is _gen_p_lg_180:
             self._update(args,dict)
 
 
@@ -2818,7 +2819,7 @@
 
 
     def _update(self, args, kwargs):
-        super(_gen_p_lg_179,self)._update(args,kwargs)
+        super(_gen_p_lg_180,self)._update(args,kwargs)
         keys=kwargs.keys()
         for key in keys:
             if key in self.__fields:
@@ -2826,7 +2827,7 @@
                 del kwargs[key]
         # Were any unrecognized kwargs passed in?
         if __debug__:
-            self._complainaboutunusedargs(_gen_p_lg_179,kwargs)
+            self._complainaboutunusedargs(_gen_p_lg_180,kwargs)
         if len(args):
             dict2={'sizeinbytes': 1,  'default': 0 }
             dict2.update(kwargs)
@@ -3002,6 +3003,399 @@
 
 
 
+class NVReq(BaseProtogenClass):
+    __fields=['cmd', 'field', 'data']
+
+    def __init__(self, *args, **kwargs):
+        dict={}
+        # What was supplied to this function
+        dict.update(kwargs)
+        # Parent constructor
+        super(NVReq,self).__init__(**dict)
+        if self.__class__ is NVReq:
+            self._update(args,dict)
+
+
+    def getfields(self):
+        return self.__fields
+
+
+    def _update(self, args, kwargs):
+        super(NVReq,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(NVReq,kwargs)
+        if len(args): raise TypeError('Unexpected arguments supplied: '+`args`)
+        # 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()
+        try: self.__field_cmd
+        except:
+            self.__field_cmd=UINT(**{'sizeinbytes': 1,  'constant': 0x26 })
+        self.__field_cmd.writetobuffer(buf)
+        self.__field_field.writetobuffer(buf)
+        try: self.__field_data
+        except:
+            self.__field_data=DATA(**{'sizeinbytes': 130,  'default': '\x00'*130 })
+        self.__field_data.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_cmd=UINT(**{'sizeinbytes': 1,  'constant': 0x26 })
+        self.__field_cmd.readfrombuffer(buf)
+        self.__field_field=UINT(**{'sizeinbytes': 2})
+        self.__field_field.readfrombuffer(buf)
+        self.__field_data=DATA(**{'sizeinbytes': 130,  'default': '\x00'*130 })
+        self.__field_data.readfrombuffer(buf)
+        self._bufferendoffset=buf.getcurrentoffset()
+
+
+    def __getfield_cmd(self):
+        try: self.__field_cmd
+        except:
+            self.__field_cmd=UINT(**{'sizeinbytes': 1,  'constant': 0x26 })
+        return self.__field_cmd.getvalue()
+
+    def __setfield_cmd(self, value):
+        if isinstance(value,UINT):
+            self.__field_cmd=value
+        else:
+            self.__field_cmd=UINT(value,**{'sizeinbytes': 1,  'constant': 0x26 })
+
+    def __delfield_cmd(self): del self.__field_cmd
+
+    cmd=property(__getfield_cmd, __setfield_cmd, __delfield_cmd, None)
+
+    def __getfield_field(self):
+        return self.__field_field.getvalue()
+
+    def __setfield_field(self, value):
+        if isinstance(value,UINT):
+            self.__field_field=value
+        else:
+            self.__field_field=UINT(value,**{'sizeinbytes': 2})
+
+    def __delfield_field(self): del self.__field_field
+
+    field=property(__getfield_field, __setfield_field, __delfield_field, None)
+
+    def __getfield_data(self):
+        try: self.__field_data
+        except:
+            self.__field_data=DATA(**{'sizeinbytes': 130,  'default': '\x00'*130 })
+        return self.__field_data.getvalue()
+
+    def __setfield_data(self, value):
+        if isinstance(value,DATA):
+            self.__field_data=value
+        else:
+            self.__field_data=DATA(value,**{'sizeinbytes': 130,  'default': '\x00'*130 })
+
+    def __delfield_data(self): del self.__field_data
+
+    data=property(__getfield_data, __setfield_data, __delfield_data, None)
+
+    def iscontainer(self):
+        return True
+
+    def containerelements(self):
+        yield ('cmd', self.__field_cmd, None)
+        yield ('field', self.__field_field, None)
+        yield ('data', self.__field_data, None)
+
+
+
+
+class NVRes(BaseProtogenClass):
+    __fields=['cmd', 'field', 'data']
+
+    def __init__(self, *args, **kwargs):
+        dict={}
+        # What was supplied to this function
+        dict.update(kwargs)
+        # Parent constructor
+        super(NVRes,self).__init__(**dict)
+        if self.__class__ is NVRes:
+            self._update(args,dict)
+
+
+    def getfields(self):
+        return self.__fields
+
+
+    def _update(self, args, kwargs):
+        super(NVRes,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(NVRes,kwargs)
+        if len(args): raise TypeError('Unexpected arguments supplied: '+`args`)
+        # 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_field.writetobuffer(buf)
+        self.__field_data.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_cmd=UINT(**{'sizeinbytes': 1,  'constant': 0x26 })
+        self.__field_cmd.readfrombuffer(buf)
+        self.__field_field=UINT(**{'sizeinbytes': 2})
+        self.__field_field.readfrombuffer(buf)
+        self.__field_data=DATA(**{'sizeinbytes': 130})
+        self.__field_data.readfrombuffer(buf)
+        self._bufferendoffset=buf.getcurrentoffset()
+
+
+    def __getfield_cmd(self):
+        return self.__field_cmd.getvalue()
+
+    def __setfield_cmd(self, value):
+        if isinstance(value,UINT):
+            self.__field_cmd=value
+        else:
+            self.__field_cmd=UINT(value,**{'sizeinbytes': 1,  'constant': 0x26 })
+
+    def __delfield_cmd(self): del self.__field_cmd
+
+    cmd=property(__getfield_cmd, __setfield_cmd, __delfield_cmd, None)
+
+    def __getfield_field(self):
+        return self.__field_field.getvalue()
+
+    def __setfield_field(self, value):
+        if isinstance(value,UINT):
+            self.__field_field=value
+        else:
+            self.__field_field=UINT(value,**{'sizeinbytes': 2})
+
+    def __delfield_field(self): del self.__field_field
+
+    field=property(__getfield_field, __setfield_field, __delfield_field, None)
+
+    def __getfield_data(self):
+        return self.__field_data.getvalue()
+
+    def __setfield_data(self, value):
+        if isinstance(value,DATA):
+            self.__field_data=value
+        else:
+            self.__field_data=DATA(value,**{'sizeinbytes': 130})
+
+    def __delfield_data(self): del self.__field_data
+
+    data=property(__getfield_data, __setfield_data, __delfield_data, None)
+
+    def iscontainer(self):
+        return True
+
+    def containerelements(self):
+        yield ('cmd', self.__field_cmd, None)
+        yield ('field', self.__field_field, None)
+        yield ('data', self.__field_data, None)
+
+
+
+
+class FWInfoReq(BaseProtogenClass):
+    __fields=['cmd']
+
+    def __init__(self, *args, **kwargs):
+        dict={}
+        # What was supplied to this function
+        dict.update(kwargs)
+        # Parent constructor
+        super(FWInfoReq,self).__init__(**dict)
+        if self.__class__ is FWInfoReq:
+            self._update(args,dict)
+
+
+    def getfields(self):
+        return self.__fields
+
+
+    def _update(self, args, kwargs):
+        super(FWInfoReq,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(FWInfoReq,kwargs)
+        if len(args):
+            dict2={'sizeinbytes': 1,  'constant': 0x00}
+            dict2.update(kwargs)
+            kwargs=dict2
+            self.__field_cmd=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()
+        try: self.__field_cmd
+        except:
+            self.__field_cmd=UINT(**{'sizeinbytes': 1,  'constant': 0x00})
+        self.__field_cmd.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_cmd=UINT(**{'sizeinbytes': 1,  'constant': 0x00})
+        self.__field_cmd.readfrombuffer(buf)
+        self._bufferendoffset=buf.getcurrentoffset()
+
+
+    def __getfield_cmd(self):
+        try: self.__field_cmd
+        except:
+            self.__field_cmd=UINT(**{'sizeinbytes': 1,  'constant': 0x00})
+        return self.__field_cmd.getvalue()
+
+    def __setfield_cmd(self, value):
+        if isinstance(value,UINT):
+            self.__field_cmd=value
+        else:
+            self.__field_cmd=UINT(value,**{'sizeinbytes': 1,  'constant': 0x00})
+
+    def __delfield_cmd(self): del self.__field_cmd
+
+    cmd=property(__getfield_cmd, __setfield_cmd, __delfield_cmd, None)
+
+    def iscontainer(self):
+        return True
+
+    def containerelements(self):
+        yield ('cmd', self.__field_cmd, None)
+
+
+
+
+class FWInfoRes(BaseProtogenClass):
+    __fields=['cmd', 'fw_data']
+
+    def __init__(self, *args, **kwargs):
+        dict={}
+        # What was supplied to this function
+        dict.update(kwargs)
+        # Parent constructor
+        super(FWInfoRes,self).__init__(**dict)
+        if self.__class__ is FWInfoRes:
+            self._update(args,dict)
+
+
+    def getfields(self):
+        return self.__fields
+
+
+    def _update(self, args, kwargs):
+        super(FWInfoRes,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(FWInfoRes,kwargs)
+        if len(args): raise TypeError('Unexpected arguments supplied: '+`args`)
+        # 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_fw_data.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_cmd=UINT(**{'sizeinbytes': 1,  'constant': 0x00})
+        self.__field_cmd.readfrombuffer(buf)
+        self.__field_fw_data=DATA(**{'sizeinbytes': 53})
+        self.__field_fw_data.readfrombuffer(buf)
+        self._bufferendoffset=buf.getcurrentoffset()
+
+
+    def __getfield_cmd(self):
+        return self.__field_cmd.getvalue()
+
+    def __setfield_cmd(self, value):
+        if isinstance(value,UINT):
+            self.__field_cmd=value
+        else:
+            self.__field_cmd=UINT(value,**{'sizeinbytes': 1,  'constant': 0x00})
+
+    def __delfield_cmd(self): del self.__field_cmd
+
+    cmd=property(__getfield_cmd, __setfield_cmd, __delfield_cmd, None)
+
+    def __getfield_fw_data(self):
+        return self.__field_fw_data.getvalue()
+
+    def __setfield_fw_data(self, value):
+        if isinstance(value,DATA):
+            self.__field_fw_data=value
+        else:
+            self.__field_fw_data=DATA(value,**{'sizeinbytes': 53})
+
+    def __delfield_fw_data(self): del self.__field_fw_data
+
+    fw_data=property(__getfield_fw_data, __setfield_fw_data, __delfield_fw_data, None)
+
+    def iscontainer(self):
+        return True
+
+    def containerelements(self):
+        yield ('cmd', self.__field_cmd, None)
+        yield ('fw_data', self.__field_fw_data, None)
+
+
+    def get_compile_time(self):
+        _comptime = re.findall(r'(\d\d):(\d\d):(\d\d)', self.fw_data)[0]
+        return int(_comptime[0]) * 100 + int (_comptime[1])
+
+
+
+
+
 class data(BaseProtogenClass):
     __fields=['bytes']
 
Index: src/phones/com_lg.py
===================================================================
--- src/phones/com_lg.py	(revision 4624)
+++ src/phones/com_lg.py	(working copy)
@@ -17,6 +17,7 @@
 import p_lg
 import prototypes
 import common
+import struct
 
 class LGPhonebook:
 
@@ -1603,6 +1604,24 @@
         if _resp.unlock_ok!=1:
             raise EnterDMError('Bad response - unlock_ok: %d'%_resp.unlock_ok)
 
+    def _DMv6_get_esn(self):
+        _req=self.protocolclass.NVReq(field=0x0000)
+        _res=self.sendbrewcommand(_req, self.protocolclass.NVRes)
+
+        return struct.unpack_from ('<L', _res.data, 0)[0]
+
+    def _DMv6_get_extra_data(self):
+        _req=self.protocolclass.NVReq(field=0x13d7)
+        _res=self.sendbrewcommand(_req, self.protocolclass.NVRes)
+
+        return struct.unpack_from ('<L', _res.data, 0)[0]
+
+    def _DMv6_get_compile_time(self):
+        _req=self.protocolclass.FWInfoReq()
+        _res=self.sendbrewcommand(_req, self.protocolclass.FWInfoRes)
+
+        return _res.get_compile_time()
+
     def _enter_DMv6(self):
         # similar but slightly different from v5, the enV2 started this!
         # request the seed
@@ -1612,12 +1631,21 @@
         if _key is None:
             self.log('Failed to get the key.')
             raise EnterDMError('Failed to get the key')
+
+        _esn=self._DMv6_get_esn()
+        _extra=self._DMv6_get_extra_data()
+        _ctime=self._DMv6_get_compile_time()
+
+        # determine how many bytes the key needs be be shifted
+        _shift_bytes = (_esn + ((_extra >> 16) & 0xf) + ((_extra >> 11) & 0x1f) + _ctime) % 16
+        _shift = _shift_bytes / 4
+
         _req=self.protocolclass.DMEnterReq(unlock_key=_key)
         if _resp.unlock_code==0:
             _req.unlock_code=1
         elif _resp.unlock_code==2:
             _req.unlock_code=3
-            _req.convert_to_key2()
+            _req.convert_to_key2(_shift)
         else:
             raise EnterDMError('Unknown unlock_code: %d'%_resp.unlock_code)
         _resp=self.sendbrewcommand(_req, self.protocolclass.DMEnterResp)
Index: src/phones/p_lg.p
===================================================================
--- src/phones/p_lg.p	(revision 4624)
+++ src/phones/p_lg.p	(working copy)
@@ -12,6 +12,7 @@
 """Various descriptions of data specific to LG phones"""
 
 from prototypes import *
+import re
 
 # We use LSB for all integer like fields
 UINT=UINTlsb
@@ -185,7 +186,7 @@
             for _idx in range(16):
                 self.unlock_key2.append(0)
 
-    def convert_to_key2(self):  
+    def convert_to_key2(self,shift):  
         """Convert the key value to key2"""
         if self.unlock_code!=3:
             return
@@ -194,7 +195,7 @@
         UINT(sizeinbytes=4, value=~self.unlock_key).writetobuffer(_buf)
         _key=_buf.getvalue()
         for _idx in range(4):
-            _nth_key=ord(_key[_idx])
+            _nth_key=ord(_key[(_idx + 4 - shift) % 4])
             for _idy in range(4):
                 self.unlock_key2[_idx*4+_idy]=_nth_key
 
@@ -206,6 +207,30 @@
     1 UINT unlock_code
     4 UINT unlock_key
     1 UINT result "0=Failure, 1=Success"
-    
+
+PACKET NVReq:
+    1 UINT { 'constant': 0x26 } +cmd
+    2 UINT field
+    130 DATA { 'default': '\x00'*130 } +data
+
+PACKET NVRes:
+    1 UINT { 'constant': 0x26 } cmd
+    2 UINT field
+    130 DATA data
+
+PACKET FWInfoReq:
+    1 UINT { 'constant': 0x00} +cmd
+
+PACKET FWInfoRes:
+    1 UINT { 'constant': 0x00} cmd
+    53 DATA fw_data
+    %{
+
+    def get_compile_time(self):
+        _comptime = re.findall(r'(\d\d):(\d\d):(\d\d)', self.fw_data)[0]
+        return int(_comptime[0]) * 100 + int (_comptime[1])
+
+    %}
+
 PACKET data:
     * DATA bytes
dare.tgz (application/octet-stream, 1.8 KB) - not displayed
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.