Dev Log: Moving contacts from Android to MaxCom MM721
2023-1-3 08:12:40 Author: gynvael.coldwind.pl(查看原文) 阅读量:12 收藏

As the old IT joke goes, in holiday season all IT workers visit their families to fix their computer. This time for me however it wasn't about fixing a computer, but copying contacts from an old Sony Ericsson (SE) Android phone to a new MaxCom* MM721 comfort phone. I'm not really sure what OS its running, but the whole idea behind that device is that it's supposed to be really simple to use, with the target audience being e.g. older people. And the MM721 indeed is simple to the extreme. Simple enough that moving ~200 contacts from the old phone to the new one proved to be an interesting (programming) challenge, mostly because I definitely didn't want to do it manually.
* As an editor I try to always get capitalization of company/product names correct, but MaxCom is not making it easy. In the official User Manual for said phone the logo says "MaxCom", the title says "Maxcom", and the official company address says "MAXCOM". I will stick with MaxCom.

On paper the whole thing should go like this:

  1. Write contacts on the old phone to the SIM card.
  2. Put the SIM card in the new phone.
  3. Optionally agree to copy the contacts from the SIM card to the new phone.

If you're used to smartphones and stick only with a given family – be it iOS or Android – this whole concept of using the SIM card might sound weird, since contacts are copied via the cloud, right? This device is just too simple for that – there is no cloud sync. Actually there's no web browser on it either.

In any case the issue was that the SIM card I had could only hold 150 contacts. And I had 200 to move. Well then.

Of course one might rightfully point out, that I could first move half of the contacts, use the aforementioned "copy the contacts from SIM to phone memory" option, and then move the second half. Unfortunately the automatic backup function on the device auto-selected always the first 150 entries, and then threw an error. I could have perhaps manually removed the first 150 contacts or manually marked the last 50 contacts as "stored on SIM" (I didn't check if that was an option on the SE device, but I'm guessing it was), but I really wanted to avoid having to stuff manually.

So instead I decided to look for a more automated solution. Was it faster in the end? Not sure to be completely honest. But at least it was pretty fun!

In the manual I found that while the MM721 is a really simple device, you can actually connect it to a computer using USB. Once you do that, you have two options:

  1. Mass Storage Device
  2. COM Port

In the Mass Storage Device (MSD) mode you get access to part of the directory structure of the device. Unfortunately the phone book doesn't seem to be there. This was a bit unlucky, since I'm pretty sure I could have dealt even with a custom contact list format.

This left the COM Port option, which actually spawned /dev/ttyUSB0 and /dev/ttyUSB1 devices in my device tree (a serial connection, as expected). Or /dev/ttyACM0 and /dev/ttyACM1 (a USB modem, which does make sense). Wait, so which one is it? A serial port or a modem? Well, that turned out to be pretty random. Sometimes when I connected it it was the first one, and sometimes it was the other. I am also not sure why exactly were there two serial ports (or two modems). Oh well. Eventually I did disable the cdc_acm kernel module so that it doesn't interfere with what I wanted to do.

And what I wanted to do is chat with the modem. You see, what I somewhat remembered from the olden days is that the AT modem commands for cellphones could do a lot more than just initiate a modem connection. I figured it's possible they can modify the internal phone book. And it turned out I was correct!

Given this feature the plan was pretty simple: export all the contacts from SE to the pretty universal vCard format, read it into Python with some library, and convert to a set of AT commands to execute using /dev/ttyUSBx on the phone. Easy.

The first issue turned out to be reading in the exported vCard format. I've tried one or two libraries and both failed on multiline entries – usually base64 encoded photos (which I didn't need) or really long names (which I had to truncate to 20 characters anyway, since MM721 doesn't display more). Now, the vCard format is pretty simple, it looks somewhat like this:

BEGIN:VCARD VERSION:2.1 N:Lastname;Firstname;;; FN:Displayed Name TEL;CELL:+493023125123 END:VCARD

It can contain some additional fields like EMAIL, ADR, or aforementioned PHOTO, and it can also use non-plain-text encoding like ENCODING=QUOTED-PRINTABLE or ENCODING=BASE64, but at the end of the day it's not bad. Which meant I ended up writing my own mini-parser (I've linked the source code at the end of this blog post).

Now that I had the parser I could focus on the conversion part, which also included some minor filtering like removing redundant spaces, removing artifacts left from some previous move years back, and truncating names to 20 characters. As for the AT commands, the funny thing was related to encoding, since when calling AT+CPBR to read an entry from the phone (to see the exact format they want an entry in) it would randomly – for the same entry! – reply with one of three variants:

  • +CPBR: 1,"+493023125123",129,"Displayed Name" – that's just plain text.
  • +CPBR: 1,"+493023125123",129,"446973706c61796564204e616d65" – ASCII (or maybe UTF-8?) hex encoded.
  • +CPBR: 1,"+493023125123",129,"0044006900730070006c00610079006500640020004e0061006d0065" – UTF-16-BE hex encoded.

For my purpose I had a strong preference for the last variant, since some of the contacts I had to move were non-ASCII, i.e. contained Polish diacritized characters like ą, ę, ł, ś, ć, ż, or ź, and these are easier to encode in UTF-16 than with a random ASCII code page (I wasn't sure it was really UTF-8). Thankfully the phone seemed to accept this encoding no problem.

Having generated the AT command list I opened a connection with the modem (screen /dev/ttyUSB0), copied all the entries to the clipboard and pasted them to the modem.

And the modem died.

Screenshot of the USB device randomly disconnecting and connecting, with the kernel finally saying 'unable to enumerate USB device'

OK then. Disconnecting and connecting the cable thankfully brought the /dev/ttyUSB0 device back online, but it would keep disconnecting after a few entries. Usually I would try it with another USB cable, but since this was at my parents place I didn't really have a drawer full of random USB cables. And it was the OEM cable, so I kinda trusted it.

Thinking about it I decided it might be that the sending pace is just too much for the MM721 and wrote another Python script which would send a command character by character really really slowly. And it would also remember which command was accepted last, so it could pick up filling the phone book from that place.

This unfortunately wasn't it. It wasn't also the cdc_acm kernel module. And in all fairness I haven't figured out what it really was. I was considering just making a script that would cut off the USB connection on my laptop's side and bringing it up again after some time to just automate this whole disconnect USB cable / reconnect USB cable process, but it would still require selecting the COM port option on the phone each time.

That said two things seemed to help. First was to let the device fully charge while being connected to the laptop. And secondly, once it disconnected once, if I patiently waited a few minutes for it to be picked up again, it looked more stable. Eventually I managed to transfer over 130 contacts in one go, around 40 in another, and 3-4 contacts at a time with reconnecting the cable to top everything up.

Redacted screenshot of sending the contacts, with mutlple AT and AT+CPBW commands visible.

Source code for both the vCard parser/converter and the sending app is available on my GitHub.

All in all it was a pretty interesting exercise. I also don't believe I've played with AT commands for years, so it was fun to learn they are still around.


文章来源: https://gynvael.coldwind.pl/?id=760
如有侵权请联系:admin#unsafe.sh