Package phones ::
Module com_toshibavm4050
|
|
1
2
3
4
5
6
7
8
9
10 """Communicate with the toshiba CDM 8900 cell phone"""
11
12
13 import sha
14 import re
15 import time
16
17
18 import common
19 import com_phone
20 import com_brew
21 import prototypes
22 import commport
23 import p_brew
24 import p_toshibavm4050
25 import helpids
26
27 -class Phone(com_phone.Phone, com_brew.BrewProtocol):
28 "Talk to Toshiba VM4050 cell phone"
29
30 desc="Toshiba VM4050"
31 helpid=helpids.ID_PHONE_TOSHIBAVM4050
32 protocolclass=p_toshibavm4050
33 serialsname='toshibavm4050'
34
35 builtinimages=()
36
37 builtinringtones=( 'Common', 'Ring 1', 'Ring 2', 'Ring 3', 'Ring 4', 'Ring 5',
38 'Ring 6', 'Ring 7', 'Ring 8', 'Ring 9',
39 'Alarm 1', 'Alarm 2', 'Alarm 3', 'Alarm 4', 'Alarm 5',
40 'Alarm 6', 'Alarm 7', 'Alarm 8', 'Alarm 9',
41 'Stars & Stripes', 'When the Saints', 'Bach',
42 'William Tell', 'Nachtmusik', 'Str Serenade', 'Toccata',
43 'Meistersinger', 'Blue Danube')
44
45 - def __init__(self, logtarget, commport):
51
53 """Gets information fundamental to interopating with the phone and UI.
54
55 Currently this is:
56
57 - 'uniqueserial' a unique serial number representing the phone
58 - 'groups' the phonebook groups
59 - 'wallpaper-index' map index numbers to names
60 - 'ringtone-index' map index numbers to ringtone names
61
62 This method is called before we read the phonebook data or before we
63 write phonebook data.
64 """
65 self.log("Getting fundamentals")
66
67 self.log("Retrieving fundamental phone information")
68 self.setmode(self.MODEBREW)
69 self.log("Phone serial number")
70 results['uniqueserial']=sha.new(self.get_esn()).hexdigest()
71
72 results['groups']={}
73
74 self.getringtoneindices(results)
75 self.log("Fundamentals retrieved")
76 return results
77
99
102
105
107 self.log("Getting file system in dir '"+dir+"'")
108 res=com_brew.BrewProtocol.listsubdirs(self, dir, recurse)
109
110
111 if not len(dir):
112 res['C']={ 'name': 'C', 'type': 'directory' }
113 res['D']={ 'name': 'D', 'type': 'directory' }
114 res['G']={ 'name': 'G', 'type': 'directory' }
115 return res
116
122
126
129
132
136
138 raise NotImplementedError()
139
141 raise NotImplementedError()
142
144 raise NotImplementedError()
145
179
180 _type_map={
181 0: 'phone',
182 1: 'home',
183 2: 'office',
184 3: 'cell',
185 4: 'pager',
186 5: 'fax',
187 }
188
189 _ringer_pattern1_map={
190 0x0100: 'Ring 1',
191 0x0101: 'Ring 2',
192 0x0102: 'Ring 3',
193 0x0103: 'Ring 4',
194 0x0104: 'Ring 5',
195 0x0105: 'Ring 6',
196 0x0106: 'Ring 7',
197 0x0107: 'Ring 8',
198 0x0108: 'Ring 9',
199 }
200
201 _ringer_pattern2_map={
202 0x0009: 'Alarm 1',
203 0x000A: 'Alarm 2',
204 0x000B: 'Alarm 3',
205 0x000C: 'Alarm 4',
206 0x000D: 'Alarm 5',
207 0x000E: 'Alarm 6',
208 0x000F: 'Alarm 7',
209 0x0010: 'Alarm 8',
210 0x0011: 'Alarm 9',
211 }
212
213 _ringer_melody_map={
214 0x0000: 'Stars & Stripes',
215 0x0001: 'When the Saints',
216 0x0002: 'Bach',
217 0x0003: 'William Tell',
218 0x0004: 'Nachtmusik',
219 0x0005: 'Str Serenade',
220 0x0006: 'Toccata',
221 0x0007: 'Meistersinger',
222 0x0008: 'Blue Danube',
223 }
224
239
241 for k, v in map.iteritems():
242 if v==ringer:
243 return k
244 return -1
245
257
259 """Return a phonebook entry in BitPim format. This is called from getphonebook."""
260 res={}
261
262 res['serials']=[ {'sourcetype': self.serialsname, 'serial1': entry.slot,
263 'sourceuniqueid': result['uniqueserial']} ]
264
265 set=False
266 secret=False
267 ringtone='Common'
268 numbers=[]
269 for i in range(self.protocolclass.MAXPHONENUMBERS):
270 if entry.numbers[i].valid and len(entry.numbers[i].number):
271 type=self._type_map[entry.numbers[i].type]
272 numbers.append( {'number': entry.numbers[i].number, 'type': type} )
273
274
275
276 if not secret and entry.numbers[i].secret:
277 secret=True
278 if ringtone=='Common' and entry.numbers[i].ringer_group!=5:
279 ringtone=self._get_ringtone(entry.numbers[i].ringer_group, entry.numbers[i].ringer_index)
280 if len(numbers):
281 res['numbers']=numbers
282 if secret:
283 res['flags']=[{'secret': True}]
284 res['ringtones']=[{'ringtone': ringtone, 'use': 'call'}]
285
286 if len(entry.name):
287 res['names']=[{'full': entry.name}]
288
289 emails=[]
290 for i in range(self.protocolclass.MAXEMAILS):
291 if entry.emails[i].valid and len(entry.emails[i].email):
292 emails.append( {'email': entry.emails[i].email} )
293 if len(emails):
294 res['emails']=emails
295
296 if len(entry.web_page):
297 res['urls']=[ {'url': entry.web_page} ]
298 return res
299
300 - def makephonebookentry(self, fields):
301 e=self.protocolclass.pbentry()
302
303 secret=False
304 if fields['secret']!=None:
305 secret=fields['secret']
306 ringtone='Common'
307 if fields['ringtone']!=None:
308 ringtone=fields['ringtone']
309 ringer_group, ringer_index=self._getringtone_group_index(ringtone)
310 if fields['name']:
311 e.name=fields['name']
312 else:
313 e.name=''
314 for i in range(len(fields['numbers'])):
315 n=self.protocolclass.pbnumber()
316 n.valid=1
317 n.number=fields['numbers'][i]
318 n.type=fields['numbertypes'][i]
319 n.secret=secret
320 n.ringer_group=ringer_group
321 n.ringer_index=ringer_index
322 e.numbers.append(n)
323 for i in range(len(fields['emails'])):
324 n=self.protocolclass.pbemail()
325 n.valid=1
326 n.email=fields['emails'][i]
327 e.emails.append(n)
328 if fields['web_page']:
329 e.web_page=fields['web_page']
330 e.slot=fields['slot']
331 return e
332
363
364 - def sendpbentrytophone(self, entry):
365
366 buf=prototypes.buffer()
367 entry.writetobuffer(buf, logtitle="Sending pbentrytophone")
368 data=buf.getvalue()
369 self.writedatarecord(data)
370 req=self.protocolclass.tosh_setpbentryrequest()
371 req.entry_index=entry.slot
372 if __debug__:
373 open("c:/projects/temp/record_out"+`entry.slot`, "wb").write(data)
374 res=self.sendpbcommand(req, self.protocolclass.tosh_setpbentryresponse)
375 if res.swap_ok:
376 self.log("Error writing phonebook entry")
377
378 - def deletepbentry(self, slot):
382
384 self.setmode(self.MODEBREW)
385 buffer=prototypes.buffer()
386 request.writetobuffer(buffer, logtitle="toshiba vm4050 phonebook request")
387 data=buffer.getvalue()
388 data=common.pppescape(data+common.crcs(data))+common.pppterminator
389 first=data[0]
390 try:
391 data=self.comm.writethenreaduntil(data, False, common.pppterminator, logreaduntilsuccess=False)
392 except com_phone.modeignoreerrortypes:
393 self.mode=self.MODENONE
394 self.raisecommsdnaexception("manipulating the phonebook")
395 self.comm.success=True
396
397 origdata=data
398
399
400
401
402 d=data.rfind(common.pppterminator,0,-1)
403 if d>=0:
404 self.log("Multiple PB packets in data - taking last one starting at "+`d+1`)
405 self.logdata("Original pb data", origdata, None)
406 data=data[d+1:]
407
408
409 data=common.pppunescape(data)
410
411
412 d=data.find(first)
413 if d>0:
414 self.log("Junk at begining of pb packet, data at "+`d`)
415 self.logdata("Original pb data", origdata, None)
416 self.logdata("Working on pb data", data, None)
417 data=data[d:]
418
419 crc=data[-3:-1]
420 data=data[:-3]
421 if common.crcs(data)!=crc:
422 self.logdata("Original pb data", origdata, None)
423 self.logdata("Working on pb data", data, None)
424 raise common.CommsDataCorruption("toshiba phonebook packet failed CRC check", self.desc)
425
426
427 buffer=prototypes.buffer(data)
428 res=responseclass()
429 res.readfrombuffer(buffer, logtitle="toshiba phonebook response")
430 return res
431
441
442 @classmethod
443 - def detectphone(_, coms, likely_ports, res, _module, _log):
444 if not likely_ports:
445
446 return None
447 for port in likely_ports:
448 if not res.has_key(port):
449 res[port]={ 'mode_modem': None, 'mode_brew': None,
450 'manufacturer': None, 'model': None,
451 'firmware_version': None, 'esn': None,
452 'firmwareresponse': None }
453 try:
454 if res[port]['model']:
455
456
457 continue
458 p=_module.Phone(_log, commport.CommConnection(_log, port, timeout=1))
459
460 res[port]['mode_brew']=p._setmodebrew()
461 if res[port]['mode_brew']:
462 p.get_detect_data(res[port])
463 p.comm.close()
464 except:
465 if __debug__:
466 raise
467
469
470 protocolclass=Phone.protocolclass
471 serialsname=Phone.serialsname
472
473
474 phone_manufacturer='Audiovox Communications Corporation'
475 phone_model='VM4050'
476
477
478 usbids=((0x05C6, 0x3100, 1),
479 )
480
481 deviceclasses=("modem",)
482
483
484 _supportedsyncs=(
485 ('phonebook', 'read', None),
486 ('phonebook', 'write', 'OVERWRITE'),
487 )
488
490 """Converts the data to what will be used by the phone
491
492 @param data: contains the dict returned by getfundamentals
493 as well as where the results go"""
494 results={}
495 slotsused={}
496
497 for pbentry in data['phonebook']:
498 entry=data['phonebook'][pbentry]
499 serial1=helper.getserial(entry.get('serials', []), self.serialsname, data['uniqueserial'], 'serial1', -1)
500 if(serial1 >= 0 and serial1 < self.protocolclass.NUMSLOTS):
501 slotsused[serial1]=1
502
503 lastunused=0
504
505 for pbentry in data['phonebook']:
506 if len(results)==self.protocolclass.NUMSLOTS:
507 break
508 e={}
509 entry=data['phonebook'][pbentry]
510 try:
511
512 e['name']=helper.getfullname(entry.get('names', []),1,1,36)[0]
513
514 serial1=helper.getserial(entry.get('serials', []), self.serialsname, data['uniqueserial'], 'serial1', -1)
515
516 if(serial1 >= 0 and serial1 < self.protocolclass.NUMSLOTS):
517 e['slot']=serial1
518 else:
519 while(slotsused.has_key(lastunused)):
520 lastunused+=1
521 if(lastunused >= self.protocolclass.NUMSLOTS):
522 helper.add_error_message("Name: %s. Unable to add, phonebook full" % e['name'])
523 raise helper.ConversionFailed()
524 e['slot']=lastunused
525 slotsused[lastunused]=1
526
527
528 emails=helper.getemails(entry.get('emails', []) ,0,self.protocolclass.MAXEMAILS,self.protocolclass.MAXEMAILLEN)
529 e['emails']=helper.filllist(emails, self.protocolclass.MAXEMAILS, "")
530
531
532 e['web_page']=helper.makeone(helper.geturls(entry.get('urls', []), 0,1,48), "")
533
534
535 numbers=helper.getnumbers(entry.get('numbers', []),0,self.protocolclass.MAXPHONENUMBERS)
536 e['numbertypes']=[]
537 e['numbers']=[]
538 typesused={}
539 for num in numbers:
540 type=num['type']
541 if(typesused.has_key(type)):
542 continue
543 typesused[type]=1
544 for typenum,tnsearch in enumerate(self.protocolclass.numbertypetab):
545 if type==tnsearch:
546 number=self.phonize(num['number'])
547 if len(number)==0:
548
549 continue
550 if len(number)>self.protocolclass.MAXPHONENUMBERLEN:
551
552 number=number[:self.protocolclass.MAXPHONENUMBERLEN]
553 e['numbers'].append(number)
554 e['numbertypes'].append(typenum)
555 break
556
557
558 e['ringtone']=helper.getringtone(entry.get('ringtones', []), 'call', None)
559
560
561 e['secret']=helper.getflag(entry.get('flags',[]), 'secret', False)
562
563 results[pbentry]=e
564
565 except helper.ConversionFailed:
566 continue
567 data['phonebook']=results
568 return data
569
570
572 """Convert the phone number into something the phone understands
573
574 All digits, P, T, *, # are kept, everything else is removed.
575 In theory the phone can store a dash in the phonebook, but that
576 is not normal."""
577 return re.sub("[^0-9PT#*]", "", str)[:self.protocolclass.MAXPHONENUMBERLEN]
578