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