def getphoneinfo(self, phone_info): self.log('Getting Phone Info') try: s=self.getfilecontents(self.brew_version_file) if s[0x5b1:0x5b1+len(self.my_model)]==self.my_model: phone_info.append('Model:', self.my_model) phone_info.append('ESN:', self.get_brew_esn()) req=p_brew.firmwarerequest() txt=self.getfilecontents("nvm/nvm/nvm_0000")[0x241:0x24b] phone_info.append('Phone Number:', txt) except: pass return "Talk to the LG 6200 cell phone"
def get_detect_data(self, res): try: req=p_brew.firmwarerequest() resp=self.sendbrewcommand(req, p_brew.data) res['firmwareresponse']=resp.bytes except com_brew.BrewBadBrewCommandException: pass
def getphoneinfo(self, phone_info): self.log('Getting Phone Info') try: s=self.getfilecontents('ams/version.txt') if s[:5]==self.my_model: phone_info.append('Model:', self.my_model) phone_info.append('ESN:', self.get_brew_esn()) req=p_brew.firmwarerequest() txt=self.getfilecontents("nvm/nvm/nvm_0000")[207:217] phone_info.append('Phone Number:', txt) except: pass return
def getphoneinfo(self, phone_info): self.log('Getting Phone Info') try: s = self.getfilecontents(self.brew_version_file) if s[0x5b1:0x5b1 + len(self.my_model)] == self.my_model: phone_info.append('Model:', self.my_model) phone_info.append('ESN:', self.get_brew_esn()) req = p_brew.firmwarerequest() #res=self.sendbrewcommand(req, self.protocolclass.firmwareresponse) #phone_info.append('Firmware Version:', res.firmware) txt = self.getfilecontents("nvm/nvm/nvm_0000")[0x241:0x24b] phone_info.append('Phone Number:', txt) except: pass return
def getphoneinfo(self, phone_info): self.log('Getting Phone Info') try: s=self.getfilecontents(self.brew_version_file) if s[0x5b1:0x5b1+len(self.my_model)]==self.my_model: phone_info.append('Model:', self.my_model) phone_info.append('ESN:', self.get_brew_esn()) req=p_brew.firmwarerequest() #res=self.sendbrewcommand(req, self.protocolclass.firmwareresponse) #phone_info.append('Firmware Version:', res.firmware) txt=self.getfilecontents("nvm/nvm/nvm_0000")[0x241:0x24b] phone_info.append('Phone Number:', txt) except: pass return
def getphoneinfo(self, phone_info): self.log('Getting Phone Info') try: s=self.getfilecontents('brew/version.txt') if s[:6]==self.my_model: phone_info.append('Model:', self.my_model) phone_info.append('ESN:', self.get_brew_esn()) req=p_brew.firmwarerequest() res=self.sendbrewcommand(req, self.protocolclass.firmwareresponse) phone_info.append('Firmware Version:', res.firmware) txt=self.getfilecontents("nvm/nvm/nvm_cdma")[180:190] phone_info.append('Phone Number:', txt) except: pass return
def getphoneinfo(self, phone_info): self.log('Getting Phone Info') try: s = self.getfilecontents('brew/version.txt') if s[:6] == self.my_model: phone_info.append('Model:', self.my_model) phone_info.append('ESN:', self.get_brew_esn()) req = p_brew.firmwarerequest() res = self.sendbrewcommand(req, self.protocolclass.firmwareresponse) phone_info.append('Firmware Version:', res.firmware) txt = self.getfilecontents("nvm/nvm/nvm_cdma")[180:190] phone_info.append('Phone Number:', txt) except: pass return
def getphoneinfo(self, phone_info): self.log('Getting Phone Info') try: s=self.getfilecontents('ams/version.txt') if s[:5]==self.my_model: phone_info.append('Model:', self.my_model+'/PM325') phone_info.append('ESN:', self.get_brew_esn()) req=p_brew.firmwarerequest() res=self.sendbrewcommand(req, self.protocolclass.firmwareresponse) phone_info.append('Firmware Version:', res.firmware) txt=self.getfilecontents("nvm/nvm/nvm_0000")[207:217] phone_info.append('Phone Number:', txt) except: self.log('Error Getting Phone Info') pass return
def _setmodebrew(self): req = p_brew.firmwarerequest() respc = p_brew.testing0cresponse 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 # send AT$QCDMG at various speeds for baud in (0, 115200, 19200, 230400): if baud: if not self.comm.setbaudrate(baud): continue print "Baud=" + ` baud ` try: self.comm.write("AT$QCDMG\r\n") except: # some issue during writing such as user pulling cable out self.mode = self.MODENONE self.comm.shouldloop = True raise try: # if we got OK back then it was success if self.comm.readsome().find("OK") >= 0: break except com_phone.modeignoreerrortypes: self.log("No response to setting QCDMG mode") # verify if we are in DM mode 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
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
def getphoneinfo(self, phone_info): self.log('Getting Phone Info') phone_info.model=self.my_model phone_info.manufacturer=Profile.phone_manufacturer phone_info.append('ESN:', self.get_brew_esn()) req=p_brew.firmwarerequest() res=self.sendbrewcommand(req, p_lglx260.firmwareresponse) phone_info.append('Firmware Version:', res.firmware) s=self.getfilecontents('pim/MyInformation.dat') phone_info.append('Phone Number:', s[363:373]) try: dirlisting=self.getfilesystem('', 1) keys = dirlisting.keys() keys.sort() #dirlisting=self.getfilesystem('nvm/') for i in keys: self.log('file: '+ i) #s=self.getfilecontents(i) except com_brew.BrewNoSuchDirectoryException: self.log('no such directory pim/')
def getphoneinfo(self, phone_info): self.log('Getting Phone Info') phone_info.model = self.my_model phone_info.manufacturer = Profile.phone_manufacturer phone_info.append('ESN:', self.get_brew_esn()) req = p_brew.firmwarerequest() res = self.sendbrewcommand(req, p_lglx260.firmwareresponse) phone_info.append('Firmware Version:', res.firmware) s = self.getfilecontents('pim/MyInformation.dat') phone_info.append('Phone Number:', s[363:373]) try: dirlisting = self.getfilesystem('', 1) keys = dirlisting.keys() keys.sort() #dirlisting=self.getfilesystem('nvm/') for i in keys: self.log('file: ' + i) #s=self.getfilecontents(i) except com_brew.BrewNoSuchDirectoryException: self.log('no such directory pim/')
def makeentry(self, counter, entry, dict): e=com_lgvx4400.Phone.makeentry(self, counter, entry, dict) e.entrysize=0x202 return e def getcameraindex(self): index={} try: buf=prototypes.buffer(self.getfilecontents("cam/pics.dat")) g=self.protocolclass.campicsdat() g.readfrombuffer(buf) for i in g.items: if len(i.name): index[i.index]={'name': "pic%02d.jpg"%(i.index,), 'date': i.taken, 'origin': 'camera' } except com_brew.BrewNoSuchFileException: pass 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 "Talk to the LG VX6100 cell phone"
def _setmodebrew(self): req=p_brew.firmwarerequest() respc=p_brew.testing0cresponse 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 for baud in (0, 115200, 19200, 230400): if baud: if not self.comm.setbaudrate(baud): continue print "Baud="+`baud` try: self.comm.write("AT$QCDMG\r\n") except: self.mode=self.MODENONE self.comm.shouldloop=True raise try: if self.comm.readsome().find("OK")>=0: break except com_phone.modeignoreerrortypes: self.log("No response to setting QCDMG mode") 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 def getfundamentals(self, results): """Gets information fundamental to interopating with the phone and UI.""" req=self.protocolclass.esnrequest() res=self.sendpbcommand(req, self.protocolclass.esnresponse) results['uniqueserial']=sha.new('%8.8X' % res.esn).hexdigest() self.getmediaindices(results) self.log("Fundamentals retrieved") return results "Talk to the Sanyo PM8300 cell phone" class Profile (com_sanyonewer.Profile) : protocolclass=Phone.protocolclass serialsname=Phone.serialsname phone_manufacturer='SANYO' phone_model='SCP-8300/US' WALLPAPER_WIDTH=176 WALLPAPER_HEIGHT=220 def __init__(self): com_sanyonewer.Profile.__init__(self) self.numbertypetab=numbertypetab
def makegcd(self,filename,size): "Build a GCD file for filename" ext=common.getext(filename.lower()) noextname=common.stripext(filename) try: mimetype=self.__mimetype[ext] gcdcontent="Content-Type: "+mimetype+"\nContent-Name: "+noextname+"\nContent-Version: 1.0\nContent-Vendor: BitPim\nContent-URL: file://"+filename+"\nContent-Size: "+`size`+"\nContent-Description: Content for V10044 LG PM225"+"\n\n\n" except: gcdcontent="Content-Name: "+noextname+"\nContent-Version: 1.0\nContent-Vendor: BitPim\nContent-URL: file://"+filename+"\nContent-Size: "+`size`+"\n\n\n" return gcdcontent def makejad(self,filename,size): "Build a JAD file for filename" ext=common.getext(filename.lower()) noextname=common.stripext(filename) jadcontent="MIDlet-1: "+noextname+", "+noextname+".png, BitPim\nMIDlet-Jar-Size: "+`size`+"\nMIDlet-Jar-URL: "+filename+"\nMIDlet-Name: "+noextname+"\nMIDlet-Vendor: Unknown\nMIDlet-Version: 1.0\nMicroEdition-Configuration: CLDC-1.0\nMicroEdition-Profile: MIDP-1.0\nContent-Folder: Games\n\n\n" return jadcontent brew_version_file='ams/version.txt' brew_version_txt_key='ams_version.txt' my_model='PM225' def getphoneinfo(self, phone_info): self.log('Getting Phone Info') try: s=self.getfilecontents('ams/version.txt') if s[:5]==self.my_model: phone_info.append('Model:', self.my_model) phone_info.append('ESN:', self.get_brew_esn()) req=p_brew.firmwarerequest() txt=self.getfilecontents("nvm/nvm/nvm_0000")[207:217] phone_info.append('Phone Number:', txt) except: pass return "Talk to the LG PM225 cell phone"
def getfirmwareinformation(self): self.log("Getting firmware information") req=p_brew.firmwarerequest() res=self.sendbrewcommand(req, self.protocolclass.firmwareresponse) return res
def savecalendar(self, dict, merge): # ::TODO:: # what will be written to the files eventsf = self.protocolclass.schedulefile() exceptionsf = self.protocolclass.scheduleexceptionfile() ringersf = self.protocolclass.scheduleringerfile() # what are we working with cal=dict['calendar'] newcal={} #sort into start order, makes it possible to see if the calendar has changed keys=[(x.start, k) for k,x in cal.items()] keys.sort() # apply limiter keys=keys[:self.protocolclass.NUMCALENDARENTRIES] # number of entries eventsf.numactiveitems=len(keys) ringersf.numringers = 0 pos = 0 # get phone firmware version for serial number try: req = p_brew.firmwarerequest() res = self.sendbrewcommand(req, self.protocolclass.firmwareresponse) _fwversion = res.firmware except: _fwversion = '00000000' # play with each entry for (_,k) in keys: # entry is what we will return to user entry=cal[k] data=self.protocolclass.scheduleevent() # using the packetsize() method here will fill the LIST with default entries data.pos = pos * data.packet_size + 2 self._schedulecommon(entry, data) alarm_set=self.setalarm(entry, data) if alarm_set: if entry.ringtone=="No Ring" and not entry.vibrate: alarm_name="Low Beep Once" #ringtone coming up as "Select:" would be the same as "No Ring", so we should check for it also elif entry.ringtone==phonebookentryeditor.RingtoneEditor.unnamed and not entry.vibrate: alarm_name="Low Beep Once" else: alarm_name=entry.ringtone else: # set alarm to "No Ring" gets rid of alarm icon on phone alarm_name="No Ring" for i in dict['ringtone-index']: self.log ('ringtone ' + str(i) + ': ' + dict['ringtone-index'][i]['name'] + ' alarm-name = ' + alarm_name) if dict['ringtone-index'][i]['name']==alarm_name: if dict['ringtone-index'][i].get('filename', None): data.ringtone = 100 + ringersf.numringers ringersf.ringerpaths.append(dict['ringtone-index'][i]['filename']) ringersf.numringers = ringersf.numringers + 1 else: # builtin ringer data.ringtone=i # Set to proper index break # check for exceptions and add them to the exceptions list self._scheduleexceptions(entry, data, exceptionsf) self._scheduleextras(data, _fwversion) # put entry in nice shiny new dict we are building entry=copy.copy(entry) newcal[data.pos]=entry eventsf.events.append(data) pos = pos + 1 buf=prototypes.buffer() eventsf.writetobuffer(buf, logtitle="New Calendar") self.writefile(self.calendarlocation, buf.getvalue()) self.log("Your phone has to be rebooted due to the calendar changing") dict["rebootphone"]=True buf=prototypes.buffer() exceptionsf.writetobuffer(buf, logtitle="Writing calendar exceptions") self.writefile(self.calendarexceptionlocation, buf.getvalue()) buf = prototypes.buffer() ringersf.writetobuffer(buf, logtitle="Writing calendar ringers") self.writefile(self.calendarringerlocation, buf.getvalue()) # fix passed in dict dict['calendar']=newcal return dict
def get_firmware_version(self): # return the firmware version req = p_brew.firmwarerequest() res = self.sendbrewcommand(req, self.protocolclass.firmwareresponse) return res.firmware
def savecalendar(self, dict, merge): # ::TODO:: # what will be written to the files eventsf = self.protocolclass.schedulefile() exceptionsf = self.protocolclass.scheduleexceptionfile() ringersf = self.protocolclass.scheduleringerfile() # what are we working with cal=dict['calendar'] newcal={} #sort into start order, makes it possible to see if the calendar has changed keys=[(x.start, k) for k,x in cal.items()] keys.sort() # apply limiter keys=keys[:self.protocolclass.NUMCALENDARENTRIES] # number of entries eventsf.numactiveitems=len(keys) ringersf.numringers = 0 pos = 0 # get phone firmware version for serial number try: req = p_brew.firmwarerequest() res = self.sendbrewcommand(req, self.protocolclass.firmwareresponse) _fwversion = res.firmware except: _fwversion = '00000000' # play with each entry for (_,k) in keys: # entry is what we will return to user entry=cal[k] data=self.protocolclass.scheduleevent() # using the packetsize() method here will fill the LIST with default entries data.pos = pos * data.packet_size + 2 self._schedulecommon(entry, data) alarm_set=self.setalarm(entry, data) if alarm_set: if entry.ringtone=="No Ring" and not entry.vibrate: alarm_name="Low Beep Once" else: alarm_name=entry.ringtone else: # set alarm to "No Ring" gets rid of alarm icon on phone alarm_name="No Ring" for i in dict['ringtone-index']: self.log ('ringtone ' + str(i) + ': ' + dict['ringtone-index'][i]['name'] + ' alarm-name = ' + alarm_name) if dict['ringtone-index'][i]['name']==alarm_name: if dict['ringtone-index'][i].get('filename', None): data.ringtone = 100 + ringersf.numringers ringersf.ringerpaths.append(dict['ringtone-index'][i]['filename']) ringersf.numringers = ringersf.numringers + 1 else: # builtin ringer data.ringtone=i # Set to proper index break # check for exceptions and add them to the exceptions list self._scheduleexceptions(entry, data, exceptionsf) self._scheduleextras(data, _fwversion) # put entry in nice shiny new dict we are building entry=copy.copy(entry) newcal[data.pos]=entry eventsf.events.append(data) pos = pos + 1 buf=prototypes.buffer() eventsf.writetobuffer(buf, logtitle="New Calendar") self.writefile(self.calendarlocation, buf.getvalue()) self.log("Your phone has to be rebooted due to the calendar changing") dict["rebootphone"]=True buf=prototypes.buffer() exceptionsf.writetobuffer(buf, logtitle="Writing calendar exceptions") self.writefile(self.calendarexceptionlocation, buf.getvalue()) buf = prototypes.buffer() ringersf.writetobuffer(buf, logtitle="Writing calendar ringers") self.writefile(self.calendarringerlocation, buf.getvalue()) # fix passed in dict dict['calendar']=newcal return dict
def get_firmware_version(self): # return the firmware version req=p_brew.firmwarerequest() res=self.sendbrewcommand(req, self.protocolclass.firmwareresponse) return res.firmware
def getfirmwareinformation(self): self.log("Getting firmware information") req=p_brew.firmwarerequest() res=self.sendbrewcommand(req, p_brew.firmwareresponse) def get_brew_esn(self): return '%0X'%self.sendbrewcommand(p_brew.ESN_req(), p_brew.ESN_resp).esn def explore0c(self): self.log("Trying stuff with command 0x0c") req=p_brew.testing0crequest() res=self.sendbrewcommand(req, p_brew.testing0cresponse) def offlinerequest(self, reset=False): req=p_brew.setmoderequest() req.request=1 self.log("Taking phone offline") self.sendbrewcommand(req, p_brew.setmoderesponse) if reset: req=p_brew.setmoderequest() req.request=2 self.log("Resetting phone") self.sendbrewcommand(req, p_brew.setmoderesponse) def modemmoderequest(self): self.log("Attempting to put phone in modem mode") req=p_brew.setmodemmoderequest() buffer=prototypes.buffer() req.writetobuffer(buffer) data=buffer.getvalue() self.logdata("brew request", data, req) data=common.pppescape(data+common.crcs(data))+common.pppterminator self.comm.write(data) self.comm.readsome(numchars=5) self.mode=self.MODENONE def mkdir(self, name): self.log("Making directory '"+name+"'") req=p_brew.mkdirrequest() req.dirname=name self.sendbrewcommand(req, p_brew.mkdirresponse) def mkdirs(self, directory): if len(directory)<1: return dirs=directory.split('/') for i in range(0,len(dirs)): try: self.mkdir("/".join(dirs[:i+1])) except: pass def rmdir(self,name): self.log("Deleting directory '"+name+"'") req=p_brew.rmdirrequest() req.dirname=name self.sendbrewcommand(req, p_brew.rmdirresponse) def rmfile(self,name): self.log("Deleting file '"+name+"'") req=p_brew.rmfilerequest() req.filename=name self.sendbrewcommand(req, p_brew.rmfileresponse) file_cache.clear(name) def rmdirs(self, path): self.progress(0,1, "Listing child files and directories") all=self.getfilesystem(path, 100) keys=all.keys() keys.sort() keys.reverse() count=0 for k in keys: self.progress(count, len(keys), "Deleting "+k) count+=1 if all[k]['type']=='directory': self.rmdir(k) else: self.rmfile(k) self.rmdir(path) def exists(self, path): req=p_brew.listfilerequest() req.dirname=path req.entrynumber=0 try: res=self.sendbrewcommand(req,p_brew.listfileresponse) except (BrewBadPathnameException, BrewNoSuchDirectoryException, ValueError): return False except: if __debug__: raise return False return True def listsubdirs(self, dir='', recurse=0): results={} self.log("Listing subdirs in dir: '"+dir+"'") req=p_brew.listdirectoryrequest() req.dirname=dir for i in xrange(10000): try: req.entrynumber=i res=self.sendbrewcommand(req,p_brew.listdirectoryresponse) f=res.subdir.rfind("/") if f>=0: subdir=res.subdir[f+1:] else: subdir=res.subdir if len(dir): subdir=dir+"/"+subdir results[subdir]={ 'name': subdir, 'type': 'directory' } except BrewNoMoreEntriesException: break except (BrewBadPathnameException, ValueError): self.log('Failed to list dir '+dir) return {} if recurse: for k,_subdir in results.items(): results.update(self.listsubdirs(_subdir['name'], recurse-1)) return results def hassubdirs(self, dir=''): self.log('Checking for subdirs in dir: "'+dir+'"') req=p_brew.listdirectoryrequest() req.dirname=dir req.entrynumber=0 try: res=self.sendbrewcommand(req,p_brew.listdirectoryresponse) return True except BrewNoMoreEntriesException: return False except: if __debug__: raise return False def listfiles(self, dir=''): results={} self.log("Listing files in dir: '"+dir+"'") req=p_brew.listfilerequest() req.dirname=dir for i in xrange(10000): try: req.entrynumber=i res=self.sendbrewcommand(req,p_brew.listfileresponse) results[res.filename]={ 'name': res.filename, 'type': 'file', 'size': res.size } if res.date==0: results[res.filename]['date']=(0, "") else: try: date=res.date+self._brewepochtounix results[res.filename]['date']=(date, time.strftime("%x %X", time.gmtime(date))) except: results[res.filename]['date']=(0, "") except BrewNoMoreEntriesException: break except (BrewBadPathnameException, ValueError): self.log('Failed to list files in dir '+dir) return {} return results def getfilesystem(self, dir="", recurse=0): self.log("Getting file system in dir '"+dir+"'") results=self.listsubdirs(dir) subdir_list=[x['name'] for k,x in results.items()] results.update(self.listfiles(dir)) if recurse: for _subdir in subdir_list: results.update(self.getfilesystem(_subdir, recurse-1)) return results def statfile(self, name): try: self.log('stat file '+name) req=p_brew.statfilerequest() req.filename=name res=self.sendbrewcommand(req, p_brew.statfileresponse) results={ 'name': name, 'type': 'file', 'size': res.size, 'datevalue': res.date } if res.date==0: results['date']=(0, '') else: try: date=res.date+self._brewepochtounix results['date']=(date, time.strftime("%x %X", time.gmtime(date))) except: results['date']=(0, '') return results except BrewNoSuchFileException: return None except: if __debug__: raise return None def setfileattr(self, filename, date): self.log('set file date '+filename +`date`) req=p_brew.setfileattrrequest() req.date=date-self._brewepochtounix req.filename=filename self.sendbrewcommand(req, p_brew.setfileattrresponse) def writefile(self, name, contents): start=time.time() self.log("Writing file '"+name+"' bytes "+`len(contents)`) desc="Writing "+name req=p_brew.writefilerequest() req.filesize=len(contents) req.data=contents[:0x100] req.filename=name self.sendbrewcommand(req, p_brew.writefileresponse) numblocks=len(contents)/0x100 count=0 for offset in range(0x100, len(contents), 0x100): req=p_brew.writefileblockrequest() count+=1 if count>=0x100: count=1 if count % 5==0: self.progress(offset>>8,numblocks,desc) req.blockcounter=count req.thereismore=offset+0x100<len(contents) block=contents[offset:] l=min(len(block), 0x100) block=block[:l] req.data=block self.sendbrewcommand(req, p_brew.writefileblockresponse) end=time.time() if end-start>3: self.log("Wrote "+`len(contents)`+" bytes at "+`int(len(contents)/(end-start))`+" bytes/second") def getfilecontents(self, file, use_cache=False): if use_cache: node=self.statfile(file) if node and file_cache.hit(file, node['date'][0], node['size']): self.log('Reading from cache: '+file) _data=file_cache.data(file) if _data: return _data self.log('Cache file corrupted and discarded') start=time.time() self.log("Getting file contents '"+file+"'") desc="Reading "+file data=cStringIO.StringIO() req=p_brew.readfilerequest() req.filename=file res=self.sendbrewcommand(req, p_brew.readfileresponse) filesize=res.filesize data.write(res.data) counter=0 while res.thereismore: counter+=1 if counter>0xff: counter=0x01 if counter%5==0: self.progress(data.tell(), filesize, desc) req=p_brew.readfileblockrequest() req.blockcounter=counter res=self.sendbrewcommand(req, p_brew.readfileblockresponse) data.write(res.data) self.progress(1,1,desc) data=data.getvalue() end=time.time() if end-start>3: self.log("Read "+`filesize`+" bytes at "+`int(filesize/(end-start))`+" bytes/second") if filesize!=len(data): self.log("expected size "+`filesize`+" actual "+`len(data)`) self.raisecommsexception("Brew file read is incorrect size", common.CommsDataCorruption) if use_cache and node: file_cache.add(file, node.get('date', [0])[0], data) return data DirCache=_DirCache def _setmodebrew(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 modeignoreerrortypes: pass for baud in (0, 115200, 19200, 230400): if baud: if not self.comm.setbaudrate(baud): continue print "Baud="+`baud` try: for line in self.comm.sendatcommand("+GMM"): if line.find("SPH-A700")>0: raise BrewNotSupported("This phone is not supported by BitPim", self.desc) except modeignoreerrortypes: self.log("No response to AT+GMM") except: print "GMM Exception" self.mode=self.MODENONE self.comm.shouldloop=True raise try: self.comm.write("AT$QCDMG\r\n") except: self.mode=self.MODENONE self.comm.shouldloop=True raise try: if self.comm.readsome().find("OK")>=0: break except modeignoreerrortypes: self.log("No response to setting QCDMG mode") 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 modeignoreerrortypes: pass return False def sendbrewcommand(self, request, responseclass, callsetmode=True): if callsetmode: self.setmode(self.MODEBREW) buffer=prototypes.buffer() request.writetobuffer(buffer) data=buffer.getvalue() self.logdata("brew request", data, request) data=common.pppescape(data+common.crcs(data))+common.pppterminator firsttwo=data[:2] try: data=self.comm.writethenreaduntil(data, False, common.pppterminator, logreaduntilsuccess=False) except modeignoreerrortypes: self.mode=self.MODENONE self.raisecommsdnaexception("manipulating the filesystem") self.comm.success=True origdata=data d=data.rfind(common.pppterminator,0,-1) if d>=0: self.log("Multiple packets in data - taking last one starting at "+`d+1`) self.logdata("Original data", origdata, None) data=data[d+1:] data=common.pppunescape(data) d=data.find(firsttwo) if d>0: self.log("Junk at begining of packet, data at "+`d`) self.logdata("Original data", origdata, None) self.logdata("Working on data", data, None) data=data[d:] crc=data[-3:-1] data=data[:-3] calccrc=common.crcs(data) if calccrc!=crc: self.logdata("Original data", origdata, None) self.logdata("Working on data", data, None) raise common.CommsDataCorruption("Brew packet failed CRC check", self.desc) self.logdata("brew response", data, responseclass) if firsttwo=="Y\x0c" and data==firsttwo: raise common.CommsWrongPort("The port you are using is echoing data back, and is not valid for Brew data. Most likely you have selected the modem interface when you should be using the diagnostic interface.", self.desc) if data[0]=="Y" and data[2]!="\x00": err=ord(data[2]) if err==0x1c: raise BrewNoMoreEntriesException() if err==0x08: raise BrewNoSuchDirectoryException() if err==0x06: raise BrewNoSuchFileException() if err==0x1a: raise BrewBadPathnameException() if err==0x0b: raise BrewFileLockedException() if err==0x0d: raise BrewNameTooLongException() if err==0x07: raise BrewDirectoryExistsException() raise BrewCommandException(err) buffer=prototypes.buffer(data) res=responseclass() try: res.readfrombuffer(buffer) except: self.log(formatpacketerrorlog("Error decoding response", origdata, data, responseclass)) raise return res "Talk to a phone using the 'brew' protocol" class RealBrewProtocol2 : """Talk to a phone using the 'brew' protocol This class uses the new filesystem commands which are supported by newer qualcomm chipsets used in phones like the LG vx8100 """ def exists(self, name): try: self.statfile(name) except BrewNoSuchFileException: return False return True def reconfig_directory(self): req=p_brew.new_reconfigfilesystemrequest() self.sendbrewcommand(req, p_brew.new_reconfigfilesystemresponse) def rmfile(self,name): self.log("Deleting file '"+name+"'") if self.exists(name): req=p_brew.new_rmfilerequest() req.filename=name self.sendbrewcommand(req, p_brew.new_rmfileresponse) file_cache.clear(name) def rmdir(self,name): self.log("Deleting directory '"+name+"'") if self.exists(name): req=p_brew.new_rmdirrequest() req.dirname=name self.sendbrewcommand(req, p_brew.new_rmdirresponse) self.reconfig_directory() def mkdir(self, name): self.log("Making directory '"+name+"'") if self.exists(name): raise BrewDirectoryExistsException req=p_brew.new_mkdirrequest() req.dirname=name self.sendbrewcommand(req, p_brew.new_mkdirresponse) self.reconfig_directory() def openfile(self, name, mode, flags=p_brew.new_fileopen_flag_existing): self.log("Open file '"+name+"'") req=p_brew.new_openfilerequest() req.filename=name req.mode=mode req.flags=flags res=self.sendbrewcommand(req, p_brew.new_openfileresponse) return res.handle def closefile(self, handle): self.log("Close file") req=p_brew.new_closefilerequest() req.handle=handle self.sendbrewcommand(req, p_brew.new_closefileresponse) def writefile(self, name, contents): start=time.time() self.log("Writing file '"+name+"' bytes "+`len(contents)`) desc="Writing "+name size=len(contents) exists=self.exists(name) if exists: info=self.statfile(name) current_size=info['size'] else: current_size=0 if exists and size<current_size: self.rmfile(name) exists=False if exists: handle=self.openfile(name, p_brew.new_fileopen_mode_write, p_brew.new_fileopen_flag_existing) else: handle=self.openfile(name, p_brew.new_fileopen_mode_write, p_brew.new_fileopen_flag_create) if not handle: raise BrewNoSuchFileException try: remain=size pos=0 count=0 while remain: req=p_brew.new_writefilerequest() req.handle=handle if remain>243: req.bytes=243 else: req.bytes=remain req.position=size-remain req.data=contents[req.position:(req.position+req.bytes)] count=(count&0xff)+1 if count % 5==0: self.progress(req.position,size,desc) res=self.sendbrewcommand(req, p_brew.new_writefileresponse) if res.bytes!=req.bytes: self.raisecommsexception("Brew file write error", common.CommsDataCorruption) remain-=req.bytes except Exception, e: self.closefile(handle) raise Exception, e self.closefile(handle) self.progress(1,1,desc) end=time.time() if end-start>3: self.log("Wrote "+`len(contents)`+" bytes at "+`int(len(contents)/(end-start))`+" bytes/second") def getfilecontents(self, file, use_cache=False): node=self.statfile(file) if use_cache: if node and file_cache.hit(file, node['date'][0], node['size']): self.log('Reading from cache: '+file) _data=file_cache.data(file) if _data: return _data self.log('Cache file corrupted and discarded') start=time.time() self.log("Getting file contents '"+file+"'") desc="Reading "+file data=cStringIO.StringIO() handle=self.openfile(file, p_brew.new_fileopen_mode_read) if not handle: raise BrewNoSuchFileException try: filesize=node['size'] read=0 counter=0 while True: counter=(counter&0xff)+1 if counter%5==0: self.progress(data.tell(), filesize, desc) req=p_brew.new_readfilerequest() req.handle=handle req.bytes=0xEB req.position=read res=self.sendbrewcommand(req, p_brew.new_readfileresponse) if res.bytes: data.write(res.data) read+=res.bytes else: break if read==filesize: break except Exception, e: self.closefile(handle) raise Exception, e self.closefile(handle) self.progress(1,1,desc) data=data.getvalue() end=time.time() if end-start>3: self.log("Read "+`filesize`+" bytes at "+`int(filesize/(end-start))`+" bytes/second") if filesize!=len(data): self.log("expected size "+`filesize`+" actual "+`len(data)`) self.raisecommsexception("Brew file read is incorrect size", common.CommsDataCorruption) if use_cache and node: file_cache.add(file, node.get('date', [0])[0], data) return data def listfiles(self, dir=''): self.log("Listing files in dir: '"+dir+"'") return self.getfilesystem(dir, recurse=0, directories=0) def getfilesystem(self, dir="", recurse=0, directories=1, files=1): results={} self.log("Listing dir '"+dir+"'") req=p_brew.new_opendirectoryrequest() if dir=="": req.dirname="/" else: req.dirname=dir res=self.sendbrewcommand(req, p_brew.new_opendirectoryresponse) handle=res.handle if handle==0: raise BrewNoSuchDirectoryException dirs={} count=0 try: for i in xrange(1, 10000): req=p_brew.new_listentryrequest() req.entrynumber=i req.handle=handle res=self.sendbrewcommand(req, p_brew.new_listentryresponse) if len(res.entryname) == 0: break if len(dir): direntry=dir+"/"+res.entryname else: direntry=res.entryname if files and res.type==0: results[direntry]={ 'name': direntry, 'type': 'file', 'size': res.size } if res.date==0: results[direntry]['date']=(0, "") else: results[direntry]['date']=(res.date, time.strftime("%x %X", time.localtime(res.date))) elif directories and res.type: results[direntry]={ 'name': direntry, 'type': 'directory' } if recurse>0: dirs[count]=direntry count+=1 except Exception, e: req=p_brew.new_closedirectoryrequest() req.handle=handle res=self.sendbrewcommand(req, p_brew.new_closedirectoryresponse) raise Exception, e req=p_brew.new_closedirectoryrequest() req.handle=handle res=self.sendbrewcommand(req, p_brew.new_closedirectoryresponse) for i in range(count): results.update(self.getfilesystem(dirs[i], recurse-1)) return results def statfile(self, name): self.log('stat file '+name) req=p_brew.new_statfilerequest() req.filename=name res=self.sendbrewcommand(req, p_brew.new_statfileresponse) if res.flags==2: raise BrewNoSuchFileException if res.type==1: results={ 'name': name, 'type': 'file', 'size': res.size } if res.created_date==0: results['date']=(0, '') else: results['date']=(res.created_date, time.strftime("%x %X", time.localtime(res.created_date))) else: results={ 'name': name, 'type': 'directory' } return results """Talk to a phone using the 'brew' protocol This class uses the new filesystem commands which are supported by newer qualcomm chipsets used in phones like the LG vx8100 """ class BrewProtocol (RealBrewProtocol) : """This is just a wrapper class that allows the manipulation between RealBrewProtocol and DebugBrewProtocol classes. """ def __init__(self): phone_path=os.environ.get('PHONE_FS', None) if __debug__ and phone_path: print 'Debug Phone File System:',phone_path DebugBrewProtocol._fs_path=os.path.normpath(phone_path) self._update_base_class(self.__class__) elif __debug__ and getattr(self, "protocolclass", 0) and \ getattr(self.protocolclass, "BREW_FILE_SYSTEM", 0) == 2: print '_set_new_brew', self.protocolclass def _update_base_class(self, klass): _bases=[] found=False for e in klass.__bases__: if e==RealBrewProtocol: _bases.append(DebugBrewProtocol) found=True else: _bases.append(e) if found: klass.__bases__=tuple(_bases) else: for e in _bases: self._update_base_class(e) def _set_new_brew(self, klass): _bases=[] found=False for e in klass.__bases__: if e==RealBrewProtocol: _bases.append(RealBrewProtocol2) found=True _bases.append(e) if found: klass.__bases__=tuple(_bases) else: for e in _bases: self._set_new_brew(e) """This is just a wrapper class that allows the manipulation between RealBrewProtocol and DebugBrewProtocol classes. """ def formatpacketerrorlog(str, origdata, data, klass): hd="" if data is not None: hd="Data - "+`len(data)`+" bytes\n" if klass is not None: try: hd+="<#! %s.%s !#>\n" % (klass.__module__, klass.__name__) except: klass=klass.__class__ hd+="<#! %s.%s !#>\n" % (klass.__module__, klass.__name__) hd+=common.datatohexstring(data) if origdata is not None: hd+="\nOriginal Data - "+`len(data)`+" bytes\n"+common.datatohexstring(origdata) return str+" "+hd def brewbasename(str): "returns basename of str" if str.rfind("/")>0: return str[str.rfind("/")+1:] return str def brewdirname(str): "returns dirname of str" if str.rfind("/")>0: return str[:str.rfind("/")] return str class SPURIOUSZERO (prototypes.BaseProtogenClass) : """This is a special class used to consume the spurious zero in some p_brew.listfileresponse The three bytes are formatted as follows: - An optional 'null' byte (this class) - A byte specifying how long the directory name portion is, including trailing slash - A byte specifying the length of the whole name - The bytes of the filename (which includes the full directory name) Fun and games ensue because files in the root directory have a zero length directory name, so we have some heuristics to try and distinguish if the first byte is the spurious zero or not Also allow for zero length filenames. """ def __init__(self, *args, **kwargs): super(SPURIOUSZERO,self).__init__(*args, **kwargs) self._value=None if self._ismostderived(SPURIOUSZERO): self._update(args, kwargs) def _update(self, args, kwargs): super(SPURIOUSZERO, self)._update(args, kwargs) self._complainaboutunusedargs(SPURIOUSZERO, kwargs) if len(args): raise TypeError("Unexpected arguments "+`args`) def readfrombuffer(self, buf): self._bufferstartoffset=buf.getcurrentoffset() while True: if buf.peeknextbyte()!=0: self._value=-1 break if buf.peeknextbyte(1)==0: if buf.howmuchmore()==2: break self._value=buf.getnextbyte() break all=buf.peeknextbytes(min(max(2+buf.peeknextbyte(1), 3+buf.peeknextbyte(2)), buf.howmuchmore())) ddirlen=ord(all[1]) dfulllen=ord(all[2]) if ddirlen<dfulllen and ddirlen<len(all)-3 and all[3+ddirlen-1]=='/': self._value=buf.getnextbyte() break self._value=-2 break self._bufferendoffset=buf.getcurrentoffset() def writetobuffer(self, buf): raise NotImplementedError() def packetsize(self): raise NotImplementedError() def getvalue(self): "Returns the string we are" if self._value is None: raise prototypes.ValueNotSetException() return self._value """This is a special class used to consume the spurious zero in some p_brew.listfileresponse The three bytes are formatted as follows: - An optional 'null' byte (this class) - A byte specifying how long the directory name portion is, including trailing slash - A byte specifying the length of the whole name - The bytes of the filename (which includes the full directory name) Fun and games ensue because files in the root directory have a zero length directory name, so we have some heuristics to try and distinguish if the first byte is the spurious zero or not Also allow for zero length filenames. """ file_cache=None class EmptyFileCache (object) : def __init__(self, bitpim_path): self._path=None self._cache_file_name=None self._data={ 'file_index': 0 } self.esn=None def hit(self, file_name, datetime, data_len): return False def data(self, file_name): return None def add(self, file_name, datetime, data): pass def clear(self, file_name): pass def set_path(self, bitpim_path): try: print 'setting path to',`bitpim_path` if not bitpim_path: raise ValueError self.__class__=FileCache self._path=os.path.join(bitpim_path, 'cache') self._cache_file_name=os.path.join(self._path, self._cache_index_file_name) self._check_path() self._read_index() self._write_index() except: self.__class__=EmptyFileCache class FileCache (object) : _cache_index_file_name='index.idx' current_version=1 def __init__(self, bitpim_path): self._path=os.path.join(bitpim_path, 'cache') self._cache_file_name=os.path.join(self._path, self._cache_index_file_name) self._data={ 'file_index': 0 } self.esn=None try: if not bitpim_path: raise ValueError self._check_path() self._read_index() self._write_index() except: self.__class__=EmptyFileCache def _check_path(self): try: os.makedirs(self._path) except: pass if not os.path.isdir(self._path): raise Exception("Bad cache directory: '"+self._path+"'") def _read_index(self): self._check_path() d={ 'result': {} } try: common.readversionedindexfile(self._cache_file_name, d, None, self.current_version) self._data.update(d['result']) except: print 'failed to read cache index file' def _write_index(self): self._check_path() common.writeversionindexfile(self._cache_file_name, self._data, self.current_version) def _entry(self, file_name): k=self._data.get(self.esn, None) if k: return k.get(file_name, None) def hit(self, file_name, datetime, data_len): try: e=self._entry(file_name) if e: return e['datetime'] and e['datetime']==datetime and \ e['size']==data_len return False except: if __debug__: raise return False def data(self, file_name): try: e=self._entry(file_name) if e: _data=file(os.path.join(self._path, e['cache']), 'rb').read() if len(_data)==e['size']: return _data except IOError: return None except: if __debug__: raise return None def add(self, file_name, datetime, data): try: if self.esn: e=self._entry(file_name) if not e: self._data.setdefault(self.esn, {})[file_name]={} e=self._data[self.esn][file_name] e['cache']='F%05d'%self._data['file_index'] self._data['file_index']+=1 e['datetime']=datetime e['size']=len(data) _cache_file_name=os.path.join(self._path, e['cache']) try: file(_cache_file_name, 'wb').write(data) self._write_index() except IOError: self._read_index() except: if __debug__: raise def clear(self, file_name): try: e=self._entry(file_name) if e: try: os.remove(os.path.join(self._path, e['cache'])) except: pass del self._data[self.esn][file_name] self._write_index() except: if __debug__: raise def set_path(self, bitpim_path): try: print 'setting path to',`bitpim_path` if not bitpim_path: raise ValueError self.__class__=FileCache self._path=os.path.join(bitpim_path, 'cache') self._cache_file_name=os.path.join(self._path, self._cache_index_file_name) self._check_path() self._read_index() self._write_index() except: raise self.__class__=EmptyFileCache
def getfirmwareinformation(self): self.log("Getting firmware information") req=p_brew.firmwarerequest() res=self.sendbrewcommand(req, p_brew.firmwareresponse)
def getrepeattype(self, entry, exceptions): repeat_entry=bpcalendar.RepeatEntry() interval2=0 if entry.repeat.repeat_type==repeat_entry.monthly: dow=entry.repeat.dow interval2=entry.repeat.interval2 if entry.repeat.dow==0: interval=entry.start[2] type=3 else: interval=entry.repeat.interval type=6 elif entry.repeat.repeat_type==repeat_entry.daily: dow=entry.repeat.dow interval=entry.repeat.interval if entry.repeat.interval==0: type=5 else: type=1 elif entry.repeat.repeat_type==repeat_entry.weekly: dow=entry.repeat.dow interval=entry.repeat.interval type=2 elif entry.repeat.repeat_type==repeat_entry.yearly: interval=entry.start[2] dow=entry.start[1] type=4 return (type, dow, interval, interval2, exceptions) def setalarm(self, entry, data): rc=True if entry.alarm>=2880: entry.alarm=2880 data.alarmminutes=0 data.alarmhours=48 data.alarmindex_vibrate=0x10 elif entry.alarm>=1440: entry.alarm=1440 data.alarmminutes=0 data.alarmhours=24 data.alarmindex_vibrate=0xe elif entry.alarm>=120: entry.alarm=120 data.alarmminutes=0 data.alarmhours=2 data.alarmindex_vibrate=0xc elif entry.alarm>=60: entry.alarm=60 data.alarmminutes=0 data.alarmhours=1 data.alarmindex_vibrate=0xa elif entry.alarm>=15: entry.alarm=15 data.alarmminutes=15 data.alarmhours=0 data.alarmindex_vibrate=0x8 elif entry.alarm>=10: entry.alarm=10 data.alarmminutes=10 data.alarmhours=0 data.alarmindex_vibrate=0x6 elif entry.alarm>=5: entry.alarm=5 data.alarmminutes=5 data.alarmhours=0 data.alarmindex_vibrate=0x4 elif entry.alarm>=0: entry.alarm=0 data.alarmminutes=0 data.alarmhours=0 data.alarmindex_vibrate=0x2 else: data.alarmminutes=0x64 data.alarmhours=0x64 data.alarmindex_vibrate=1 rc=False if data.alarmindex_vibrate > 1 and entry.vibrate==0: data.alarmindex_vibrate+=1 return rc my_model='VX8100' def getphoneinfo(self, phone_info): self.log('Getting Phone Info') try: s=self.getfilecontents('brew/version.txt') if s[:6]==self.my_model: phone_info.append('Model:', self.my_model) phone_info.append('ESN:', self.get_brew_esn()) req=p_brew.firmwarerequest() res=self.sendbrewcommand(req, self.protocolclass.firmwareresponse) phone_info.append('Firmware Version:', res.firmware) txt=self.getfilecontents("nvm/nvm/nvm_cdma")[180:190] phone_info.append('Phone Number:', txt) except: pass return def _is_rs_file(self, filename): return filename.startswith(self._rs_path) def getmedia(self, maps, results, key): media={} for type, indexfile, sizefile, directory, lowestindex, maxentries, typemajor, def_icon, idx_ofs in maps: for item in self.getindex(indexfile): try: if not self._is_rs_file(item.filename): media[common.basename(item.filename)]=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 ValueError: self.log('Failed to read file: '+item.filename) media[common.basename(item.filename)]='' results[key]=media return results 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: _files.update(self.listfiles(_rs_dir)) except (com_brew.BrewNoSuchDirectoryException, com_brew.BrewBadPathnameException): pass _idx_keys={} for _i in xrange(_index, _index+_maxsize): _idx_keys[_i]=True for _item in self.getindex(indexfile): if _files.has_key(_item.filename): _files[_item.filename]['index']=_item.index _idx_keys[_item.index]=False _idx_keys_list=[k for k,x in _idx_keys.items() if x] _idx_keys_list.sort() _idx_cnt=0 _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 _res_list=[(x['index'],k) for k,x in _files.items() if x.get('index', None)] _res_list.sort() _res_list.reverse() 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: _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) self.logdata("Index file "+indexfile, buf.getvalue(), ifile) self.log("Writing index file "+indexfile+" for type "+type+" with "+`len(_res_list)`+" entries.") self.writefile(indexfile, buf.getvalue()) if sizefile: szfile=self.protocolclass.sizefile() szfile.size=_file_size buf=prototypes.buffer() szfile.writetobuffer(buf) 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 """ wp=results[mediakey].copy() wpi=results[mediaindexkey].copy() for k in wpi.keys(): if wpi[k].get('origin', "")=='builtin': del wpi[k] 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(): if wp[w]['name']==name: data=wp[w]['data'] del wp[w] if not merge and data is None: continue init[type][index]={'name': name, 'data': data, 'filename': fullname, 'vtype': vtype, 'icon': icon} assert len(wpi)==0 print init.keys() 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] for type,_,_,_,lowestindex,maxentries,typemajor,def_icon,_ in maps: 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] for type, indexfile, sizefile, directory, lowestindex, maxentries,typemajor,def_icon,_ in maps: 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) fixups=[k for k in init[type].keys() if k<lowestindex] fixups.sort() for f in fixups: for ii in xrange(lowestindex, lowestindex+maxentries): if ii not in init[type]: init[type][ii]=init[type][f] del init[type][f] break 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] 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: 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 data=entry['data'] if data is None: assert merge continue elif not data: self.log('Not writing file: '+filename) continue 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) self._write_index_file(type) return reindexfunction(results) "Talk to the LG VX8100 cell phone" parentprofile=com_lgvx7000.Profile class Profile (parentprofile) : protocolclass=Phone.protocolclass serialsname=Phone.serialsname BP_Calendar_Version=3 phone_manufacturer='LG Electronics Inc' phone_model='VX8100' WALLPAPER_WIDTH=160 WALLPAPER_HEIGHT=120 MAX_WALLPAPER_BASENAME_LENGTH=32 WALLPAPER_FILENAME_CHARS="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789()_ .-" WALLPAPER_CONVERT_FORMAT="jpg" DIALSTRING_CHARS="[^0-9PW#*]" MAX_RINGTONE_BASENAME_LENGTH=32 RINGTONE_FILENAME_CHARS="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789()_ .-" bluetooth_mfg_id="001256" imageorigins={} imageorigins.update(common.getkv(parentprofile.stockimageorigins, "images")) def GetImageOrigins(self): return self.imageorigins imagetargets={} imagetargets.update(common.getkv(parentprofile.stockimagetargets, "wallpaper", {'width': 320, 'height': 240, 'format': "JPEG"})) def GetTargetsForImageOrigin(self, origin): return self.imagetargets def __init__(self): parentprofile.__init__(self) _supportedsyncs=( ('phonebook', 'read', None), ('calendar', 'read', None), ('wallpaper', 'read', None), ('ringtone', 'read', None), ('call_history', 'read', None), ('sms', 'read', None), ('memo', 'read', None), ('phonebook', 'write', 'OVERWRITE'), ('calendar', 'write', 'OVERWRITE'), ('wallpaper', 'write', 'MERGE'), ('wallpaper', 'write', 'OVERWRITE'), ('ringtone', 'write', 'MERGE'), ('ringtone', 'write', 'OVERWRITE'), ('sms', 'write', 'OVERWRITE'), ('memo', 'write', 'OVERWRITE'), ) field_color_data={ 'phonebook': { 'name': { 'first': 1, 'middle': 1, 'last': 1, 'full': 1, 'nickname': 0, 'details': 1 }, 'number': { 'type': 5, 'speeddial': 5, 'number': 5, 'details': 5 }, 'email': 2, 'address': { 'type': 0, 'company': 0, 'street': 0, 'street2': 0, 'city': 0, 'state': 0, 'postalcode': 0, 'country': 0, 'details': 0 }, 'url': 0, 'memo': 1, 'category': 1, 'wallpaper': 1, 'ringtone': 2, 'storage': 0, }, 'calendar': { 'description': True, 'location': True, 'allday': True, 'start': True, 'end': True, 'priority': False, 'alarm': True, 'vibrate': True, 'repeat': True, 'memo': False, 'category': False, 'wallpaper': False, 'ringtone': True, }, 'memo': { 'subject': True, 'date': True, 'secret': False, 'category': False, 'memo': True, }, 'todo': { 'summary': False, 'status': False, 'due_date': False, 'percent_complete': False, 'completion_date': False, 'private': False, 'priority': False, 'category': False, 'memo': False, }, } imageorigins.update(common.getkv(parentprofile.stockimageorigins, "images")) imagetargets.update(common.getkv(parentprofile.stockimagetargets, "wallpaper", {'width': 320, 'height': 240, 'format': "JPEG"}))