vx6100 sms changes

"Simon C" <[email protected]>
Newsgroups gmane.comp.mobile.bitpim.devel
Message-ID <001101c5ad01$8e196a50$6400a8c0@HOME>
Support for vx6100 sms attached with diffs. Requires updates to 4400 I sent
out earlier today.
Also bug fix for image index and added exception handler for phone info that
was accidently commented out.

Simon
com_lgvx6100.py (application/octet-stream, 7.2 KB)
### BITPIM
###
### Copyright (C) 2003-2004 Roger Binns <[email protected]>
### Copyright (C) 2004 John O'Shaughnessy <[email protected]>
###
### This program is free software; you can redistribute it and/or modify
### it under the terms of the BitPim license as detailed in the LICENSE file.
###
### $Id: com_lgvx6100.py,v 1.10 2005/08/24 04:14:43 djpham Exp $

"""Communicate with the LG VX6100 cell phone

The VX6100 is substantially similar to the VX4400 except that it supports more
image formats, has wallpapers in no less than 5 locations and puts things in
slightly different directories.

The code in this file mainly inherits from VX4400 code and then extends where
the 6100 has extra functionality

"""

# standard modules
import time
import cStringIO
import sha

# my modules
import common
import commport
import copy
import p_brew
import p_lgvx6100
import com_lgvx4400
import com_brew
import com_phone
import com_lg
import prototypes
import call_history

class Phone(com_lgvx4400.Phone):
    "Talk to the LG VX6100 cell phone"

    desc="LG-VX6100"

    protocolclass=p_lgvx6100
    serialsname='lgvx6100'

    # more VX6100 indices
    imagelocations=(
        # offset, index file, files location, type, maximumentries
        ( 16, "download/dloadindex/brewImageIndex.map", "brew/shared", "images", 60) ,
        ( 200, "download/dloadindex/mmsImageIndex.map", "brew/shared/mms", "mms", 30),
        ( 240, "download/dloadindex/mmsDrmImageIndex.map", "brew/shared/mms/d", "drm", 20), 
        ( 130, None, None, "camera", 60) # nb camera must be last
        )

    ringtonelocations=(
        # offset, index file, files location, type, maximumentries
        ( 50, "download/dloadindex/brewRingerIndex.map", "user/sound/ringer", "ringers", 60),
        ( 150, "download/dloadindex/mmsRingerIndex.map", "mms/sound", "mms", 20),
        ( 180, "download/dloadindex/mmsDrmRingerIndex.map", "mms/sound/drm", "drm", 20)
        )

    builtinimages= ('Sport', 'Butterfly', 'Cake', 'Niagara Falls', 'Rockefeller', 
    				'Statue of Liberty', 'The Capital', 'Scenary','White Bear', 'Yacht' ) 
    
    builtinringtones= ('Ring 1', 'Ring 2', 'Ring 3', 'Ring 4', 'Ring 5', 'VZW Default Tone',
                       'Farewell', 'Arabesque',
                       'Piano Sonata', 'Latin', 'When The Saints', 'Bach Cello Suite',
                       'Speedy Way', 'Cancan', 'Sting', 'Toccata and Fugue',
                       'Mozart Symphony 40', 'Nutcracker March', 'Funiculi', 'Polka', 	
                       'Hallelujah', 'Mozart Aria',
                       'Leichte', 'Spring', 'Slavonic', 'Fantasy', 'Chimes High',
                       'Chimes Low', 'Ding', 'Tada', 'Notify', 'Drum', 'Claps', 'Fanfare', 
                       'Chord High', 'Chord Low')
                       
    
    def __init__(self, logtarget, commport):
        com_lgvx4400.Phone.__init__(self,logtarget,commport)
        self.mode=self.MODENONE
        
    def makeentry(self, counter, entry, dict):
        e=com_lgvx4400.Phone.makeentry(self, counter, entry, dict)
        e.entrysize=0x202
        return e

    def getcameraindex(self):
        buf=prototypes.buffer(self.getfilecontents("cam/pics.dat"))
        index={}
        g=self.protocolclass.campicsdat()
        g.readfrombuffer(buf)
        for i in g.items:
            if len(i.name):
                # index[i.index]={'name': i.name, 'date': i.taken, 'origin': 'camera' }
                # we currently use the filesystem name rather than rename in camera
                # since the latter doesn't include the file extension which then makes
                # life less pleasant once the file ends up on the computer
                index[i.index]={'name': "pic%02d.jpg"%(i.index,), 'date': i.taken, 'origin': 'camera' }
        return index

    my_model='VX6100'

    def getphoneinfo(self, phone_info):
        self.log('Getting Phone Info')
        try:
            s=self.getfilecontents('brew/version.txt')
            if s[:6]=='VX6100':
                phone_info.append('Model:', "VX6100")
                req=p_brew.firmwarerequest()
                res=self.sendbrewcommand(req, self.protocolclass.firmwareresponse)
                phone_info.append('Firmware Version:', res.firmware)
                s=self.getfilecontents("nvm/$SYS.ESN")[85:89]
                txt='%02X%02X%02X%02X'%(ord(s[3]), ord(s[2]), ord(s[1]), ord(s[0]))
                phone_info.append('ESN:', txt)
                txt=self.getfilecontents("nvm/nvm/nvm_0000")[577:587]
                phone_info.append('Phone Number:', txt)
        except:
            pass
        return

parentprofile=com_lgvx4400.Profile
class Profile(parentprofile):
    protocolclass=Phone.protocolclass
    serialsname=Phone.serialsname
    phone_manufacturer='LG Electronics Inc'
    phone_model='VX6100'

    WALLPAPER_WIDTH=132
    WALLPAPER_HEIGHT=148
    MAX_WALLPAPER_BASENAME_LENGTH=24
    WALLPAPER_FILENAME_CHARS="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_ ."
    WALLPAPER_CONVERT_FORMAT="jpg"
   
    MAX_RINGTONE_BASENAME_LENGTH=24
    RINGTONE_FILENAME_CHARS="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_ ."

    # nb we don't allow save to camera so it isn't listed here
    imageorigins={}
    imageorigins.update(common.getkv(parentprofile.stockimageorigins, "images"))
    imageorigins.update(common.getkv(parentprofile.stockimageorigins, "mms"))
    imageorigins.update(common.getkv(parentprofile.stockimageorigins, "drm"))
    def GetImageOrigins(self):
        return self.imageorigins

    # our targets are the same for all origins
    imagetargets={}
    imagetargets.update(common.getkv(parentprofile.stockimagetargets, "wallpaper",
                                      {'width': 132, 'height': 148, 'format': "JPEG"}))
    imagetargets.update(common.getkv(parentprofile.stockimagetargets, "pictureid",
                                      {'width': 132, 'height': 148, 'format': "JPEG"}))
    imagetargets.update(common.getkv(parentprofile.stockimagetargets, "fullscreen",
                                      {'width': 128, 'height': 160, 'format': "JPEG"}))
    # can the outside lcd display images?
    #imagetargets.update(common.getkv(parentprofile.stockimagetargets, "outsidelcd",
    #                                  {'width': 96, 'height': 64, 'format': "JPEG"}))
    

    _supportedsyncs=(
        ('phonebook', 'read', None),  # all phonebook reading
        ('calendar', 'read', None),   # all calendar reading
        ('wallpaper', 'read', None),  # all wallpaper reading
        ('ringtone', 'read', None),   # all ringtone reading
        ('phonebook', 'write', 'OVERWRITE'),  # only overwriting phonebook
        ('call_history', 'read', None),# all call history list reading
        ('sms', 'read', None),         # all SMS list reading
        # ('calendar', 'write', 'OVERWRITE'),  # only overwriting calendar
        ('wallpaper', 'write', 'MERGE'),     # merge and overwrite wallpaper
        ('wallpaper', 'write', 'OVERWRITE'),
        ('ringtone', 'write', 'MERGE'),      # merge and overwrite ringtone
        ('ringtone', 'write', 'OVERWRITE'),
        ('sms', 'write', 'OVERWRITE'),       # all SMS list writing
        )
 
    def __init__(self):
        parentprofile.__init__(self)
com_lgvx6100.py.diff (application/octet-stream, 3.3 KB)
Index: com_lgvx6100.py
===================================================================
RCS file: /cvsroot/bitpim/bitpim/com_lgvx6100.py,v
retrieving revision 1.10
diff -u -r1.10 com_lgvx6100.py
--- com_lgvx6100.py	24 Aug 2005 04:14:43 -0000	1.10
+++ com_lgvx6100.py	29 Aug 2005 20:01:36 -0000
@@ -49,7 +49,7 @@
     imagelocations=(
         # offset, index file, files location, type, maximumentries
         ( 16, "download/dloadindex/brewImageIndex.map", "brew/shared", "images", 60) ,
-        ( 202, "download/dloadindex/mmsImageIndex.map", "brew/shared/mms", "mms", 30),
+        ( 200, "download/dloadindex/mmsImageIndex.map", "brew/shared/mms", "mms", 30),
         ( 240, "download/dloadindex/mmsDrmImageIndex.map", "brew/shared/mms/d", "drm", 20), 
         ( 130, None, None, "camera", 60) # nb camera must be last
         )
@@ -101,22 +101,21 @@
     my_model='VX6100'
 
     def getphoneinfo(self, phone_info):
-        print "in phone info"
         self.log('Getting Phone Info')
-        #try:
-        s=self.getfilecontents('brew/version.txt')
-        if s[:6]=='VX6100':
-            phone_info.append('Model:', "VX6100")
-            req=p_brew.firmwarerequest()
-            res=self.sendbrewcommand(req, self.protocolclass.firmwareresponse)
-            phone_info.append('Firmware Version:', res.firmware)
-            s=self.getfilecontents("nvm/$SYS.ESN")[85:89]
-            txt='%02X%02X%02X%02X'%(ord(s[3]), ord(s[2]), ord(s[1]), ord(s[0]))
-            phone_info.append('ESN:', txt)
-            txt=self.getfilecontents("nvm/nvm/nvm_0000")[577:587]
-            phone_info.append('Phone Number:', txt)
-        #except:
-        #    pass
+        try:
+            s=self.getfilecontents('brew/version.txt')
+            if s[:6]=='VX6100':
+                phone_info.append('Model:', "VX6100")
+                req=p_brew.firmwarerequest()
+                res=self.sendbrewcommand(req, self.protocolclass.firmwareresponse)
+                phone_info.append('Firmware Version:', res.firmware)
+                s=self.getfilecontents("nvm/$SYS.ESN")[85:89]
+                txt='%02X%02X%02X%02X'%(ord(s[3]), ord(s[2]), ord(s[1]), ord(s[0]))
+                phone_info.append('ESN:', txt)
+                txt=self.getfilecontents("nvm/nvm/nvm_0000")[577:587]
+                phone_info.append('Phone Number:', txt)
+        except:
+            pass
         return
 
 parentprofile=com_lgvx4400.Profile
@@ -163,11 +162,13 @@
         ('ringtone', 'read', None),   # all ringtone reading
         ('phonebook', 'write', 'OVERWRITE'),  # only overwriting phonebook
         ('call_history', 'read', None),# all call history list reading
-        # ('calendar', 'write', 'OVERWRITE'),   # only overwriting calendar
-        ('wallpaper', 'write', 'MERGE'),      # merge and overwrite wallpaper
+        ('sms', 'read', None),         # all SMS list reading
+        # ('calendar', 'write', 'OVERWRITE'),  # only overwriting calendar
+        ('wallpaper', 'write', 'MERGE'),     # merge and overwrite wallpaper
         ('wallpaper', 'write', 'OVERWRITE'),
         ('ringtone', 'write', 'MERGE'),      # merge and overwrite ringtone
         ('ringtone', 'write', 'OVERWRITE'),
+        ('sms', 'write', 'OVERWRITE'),       # all SMS list writing
         )
  
     def __init__(self):
p_lgvx6100.p (application/octet-stream, 10.4 KB) - not displayed
p_lgvx6100.p.diff (application/octet-stream, 5.2 KB)
Index: p_lgvx6100.p
===================================================================
RCS file: /cvsroot/bitpim/bitpim/p_lgvx6100.p,v
retrieving revision 1.5
diff -u -r1.5 p_lgvx6100.p
--- p_lgvx6100.p	25 Aug 2005 05:20:52 -0000	1.5
+++ p_lgvx6100.p	30 Aug 2005 01:02:33 -0000
@@ -176,3 +176,109 @@
     11 STRING {'terminator': None}  date2
     8 STRING {'terminator': None}  time2
     8 STRING {'terminator': None}  firmware
+
+###
+### SMS 
+###
+#
+#   There are 3 types of SMS records, The inbox, outbox and unsent (pending)
+#   Unlike other records in the phone each message is stored in a separate file
+#   All messages are in the 'sms' directory in the root of the phone
+#   Inbox messages are in files called 'inbox000.dat', the number 000 varies for
+#   each message, typically there are no gaps in the numbering, but gaps can appear
+#   if a message is deleted.
+#   Outbox message are named 'outbox000.dat', unsent messages are named 'sf00.dat',
+#   only two digit file name that suggests a max of 100 message for this type.
+#   Messages in the outbox get updated when the message is received by the recipient,
+#   they contain a delivery flag and a delivery time for all the possible 10 recipients.
+#   The vx8100 supports SMS contatination, this allows you to send text messages that are
+#   longer than 160 characters. The format is different for these type of messages, but
+#   it is supported by this implementation.
+#   The vx8100 also allows you to put small graphics, sounds and animations in a message.
+#   This implementation does not support these, if they are contained in a message they
+#   will be ignored and just the text will be shown when you view the message in bitpim.
+#   The text in the the messages is stored in 7-bit characters, so they have
+#   to be unpacked, in concatinated messages and messages with embeded graphics etc. the
+#   format uses the GSM 03.38 specified format, a good example of this can be found at
+#   "http://www.dreamfabric.com/sms/hello.html".
+#   For simple messages less than 161 characters with no graphics the format is simpler, 
+#   the 7-bit characters are just packed into memory in the order they appear in the
+#   message.
+
+PACKET recipient_record:
+    14 UINT unknown1
+    49 STRING number
+    1 UINT status   # 1 when sent, 5 when received, 2 failed to send
+    4 LGCALDATE timesent
+    4 LGCALDATE timereceived
+    40 DATA unknown2
+
+PACKET sms_saved:
+    4 UINT outboxmsg
+    4 GPSDATE GPStime   # num seconds since 0h 1-6-80
+    if self.outboxmsg:
+        * sms_out outbox
+    if not self.outboxmsg:
+        * sms_in inbox
+
+PACKET sms_out:
+    4 UINT index # starting from 1, unique
+    1 UINT locked # 1=locked
+    3 UINT unknown1 # zero
+    4 LGCALDATE timesent # time the message was sent
+    21 STRING subject
+    1 DATA unknown2
+    1 UINT num_msg_elements # up to 7
+    * LIST {'elementclass': msg_record, 'length': 7} +messages
+    2 UINT unknown6
+    1 UINT priority # 0=normal, 1=high
+    13 DATA unknown7
+    3 DATA unknown8 # set to 01,00,00 
+    23 STRING callback 
+    * LIST {'elementclass': recipient_record, 'length': 10} +recipients 
+
+PACKET SMSINBOXMSGFRAGMENT:
+    * LIST {'length': 181} +msg: # this size could be wrong
+        1 UINT byte "individual byte of message"
+
+PACKET sms_in:
+    4 UINT msg_index1
+    4 UINT msg_index2 
+    2 UINT unknown2 # set to 0 
+    4 UINT unknown3 # set to 0
+    6 SMSDATE timesent
+    3 UINT unknown
+    1 UINT callback_length # 0 for no callback number
+    38 STRING callback
+    1 UINT sender_length
+    * LIST {'length': 38} +sender:
+        1 UINT byte "individual byte of senders phone number"
+    15 DATA unknown4 # set to zeros
+    4 LGCALDATE lg_time # time the message was sent
+    4 GPSDATE GPStime # num seconds since 0h 1-6-80, time message received by phone
+    2 UINT unknown5 # zero
+    1 UINT read # 1 if message has been read, 0 otherwise
+    1 UINT locked # 1 if the message is locked, 0 otherwise
+    2 UINT unknown8 
+    1 UINT priority # 1 if the message is high priority, 0 otherwise
+    6 DATA flags # message flags
+    21 STRING subject
+    1 UINT bin_header1 # 0 in simple message 1 if the message contains a binary header
+    1 UINT bin_header2 # 0 in simple message 9 if the message contains a binary header
+    1 UINT multipartID # multi-part message ID, used for concatinated messages only
+    3 UINT unknown6 # zeros
+    1 UINT bin_header3 # 0 in simple message 2 if the message contains a binary header
+    1 UINT num_msg_elements # max 20 elements (guessing on max here)
+    * LIST {'length': 20} +msglengths:
+        1 UINT msglength "lengths of individual messages in septets"
+    * LIST {'length': 20, 'elementclass': SMSINBOXMSGFRAGMENT} +msgs 
+                # 181 bytes per message, 
+                # 20 messages, 7-bit ascii for simple text. for binary header 
+                # first byte is header length not including the length byte
+                # rest depends on content of header, not known at this time.
+                # text alway follows the header although the format it different
+                # than a simple SMS
+    68 DATA unknown5
+    33 STRING senders_name
+    169 DATA unknown6   # ?? inlcudes senders phone number in ascii
+
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.