Sunday, September 8, 2013

Digital photo frame: Kindle Touch vs Kindle Keyboard

In the midst of hacking my newly acquired Kindle keyboard I got myself another Kindle: this time a Kindle Touch 3G. I intended to use one as the photo frame and another as my ebook reader.

Now, which to use for my digital photo frame?

The Touch, being slimmer without a keyboard, would be easier to conceal within a frame. Not to mention that my Keyboard came with a leather case and I like it a lot. The Touch seems like a natural choice.

Until I got down to hacking it. After the usual jailbreaking and stuff, I found out that the Touch only supports PNG. This, while my Kindle keyboard can support jpg, gif and images of all shapes and sizes. Ended up using the Kindle Touch anyway.

Kindle digital photo frame part 2

Now that I can SSH into the Kindle I need to figure out the functions that I need. I want the Kindle to cycle through me and my gf's photos every 3 hours. Apart from that, I want to be able to upload photos of cute cats or love messages onto the internet, and those will show up, ONLY ONCE, on the Kindle.

For cycling photos, I need to:
  1. Wake up the Kindle from sleeping
  2. Put it to sleep again.

(1) is easy to find. The command, lipc-set-prop com.lab126.powerd wakeUp 1, will wake up the Kindle. (http://www.mobileread.com/. forums/archive/index.php/t-160328.html) Fortunately, cron works even when the Kindle is sleeping, so cycling photos is definitely possible.

(2) took me a while to find. The command is, /usr/bin/powerd_test -p . (http://www.mobileread.com/forums/showthread.php?t=220810) It works for waking up the Kindle as well, so now I can simply cycle my photos by running this command twice!

For displaying my uploaded pictures, I need to:
  1. Setup a server backend for uploading images
  2. Periodically downloading them into the Kindle
  3. Display the images occasionally, deleting them after they've been displayed.

For (1), I can simply use OpenShift and CakePHP to setup a backend for uploading and storing images. I've familiarized myself with that setup thanks to a previous competition, so no worries here.

(2), I can simply write a script for downloading the images from my backend and add it to crontab. I can even turn on wireless using cron, no issues here.

(3), I had no idea to detect which image is being displayed on screen. Thankfully, I found this page https://github.com/yifanlu/OpenBlanket/blob/master/screensaver.c, line 363 of the code shows that the last screensaver displayed is stored at "/var/local/blanket/screensaver/last_ss". I can use this while waking up the Kindle, to delete the images shown before.

Stay tuned to the next part!

Kindle digital photo frame part 1

Weeks ago I found out that my girlfriend would look at our pictures to relax herself when she is bored/stressed. I had the idea of putting a digital photo frame at her desk at work, that would cycle through our photos on a regular basis. She would be so delighted.

So I went to search for some digital photo frames on Qoo10.sg. Lots of choices, but there's a major problem. They're all using LED/LCD screens. This means: either they have an annoyingly short battery life (this item - 4 to 5 hours only?! Seriously?) or AC adaptor cables. I want a frame that is portable, not entangled by wires, and have a battery life counted in weeks, not hours.

So, the Kindle suits my purposes well. It does not consume power when displaying pictures, only when changing them. Suppose I change the images only once per hour... how much power can I save? The Kindle will last weeks!

I was lucky enough to find a seller on Hardwarezone selling his old Kindle keyboard WiFi at $70. He posted his offer just 3 hours before I saw it. And, coincidentally, he was visiting my office on the next day. I don't even need to arrange a pickup point! ^^

The next part: hacking the kindle. I followed a series of guides:

  1. http://anoved.net/2012/02/custom-kindle-screensaver-images-with-kite/ to enable custom screensavers.
  2. http://speely.wordpress.com/tag/3-4/ to enable ssh, and used this to figure out the root password
More to come!

Kindle lipc property list

=~=~=~=~=~=~=~=~=~=~=~= PuTTY log 2013.08.30 15:54:14 =~=~=~=~=~=~=~=~=~=~=~=
login as: root


Welcome to Kindle!

root@192.168.43.115's password: 
#################################################
#  N O T I C E  *  N O T I C E  *  N O T I C E  # 
#################################################
Rootfs is mounted read-only. Invoke mntroot rw to
switch back to a writable rootfs.
#################################################
[root@kindle root]# k   lipc-probe -a -v
com.lab126.pmond
 r  Str summary [name[pid] - state - mem_limit - mem_curr
----------------------------------------
tmd[13086] - started - 9000 - 2728
mcsd[13088] - started - 5000 - 1180
syslog[964] - started - 5000 - 808
netwatchd[0] - stopped - 5000 - 0
phd[13090] - started - 5000 - 2800
cvm[14228] - started - 103424 - 68272
wifid[13272] - started - 5000 - 3468
browserd[14055] - started - 90000 - 8408
webreader[14013] - started - 80000 - 15668
audioserver[15975] - started - 50000 - 4144
ttsd[13790] - started - 150000 - 6388
powerd[13143] - started - 5000 - 1456
volumd[13095] - started - 5000 - 1348
wand[0] - stopped - 5000 - 0
cmd[13267] - started - 5000 - 1516
]
 w Str start
 w Str restart
 w Str stop
 rw Str logMask [0xffff0000]
 w Str kill
 w Str heartbeat_start
 w Str mem_limit
 rw Str logLevel [Current log level=info
(Possible levels: all, perf, debug[9-0], info, warn, error, crit, none)]
 w Str heartbeat_stop
com.lab126.audio
 rw  Str URI []
 w Str PlayerStop
 rw Int Control [0]
 rw Int GstrLatency [10000]
 r Int ManagerInitialize [1]
 rw Str logLevel [Current log level=none
(Possible levels: all, perf, debug[9-0], info, warn, error, crit, none)]
 rw Int CmdIVolume [14]
 r Int CmdISpeakerMax [15]
 w Str SendEvent
 w Int ThreadUp
 rw Str logMask [0x00000000]
 w Str PlayerDataReady
 w Str PlayerRelease
 r Int ManagerCleanup [1]
 w Str PlayerResume
WARNING: Failed to get value of Seek <0x213>
 rw Int Seek
 w Str PlayerCreate
 w Str PlayerPrefetch
 r Int CmdINSinks [2]
 rw Int Chapter [0]
WARNING: Failed to get value of ManagerSuspend <0xf>
 r Int ManagerSuspend
 w Str PlayerLoop
 w Str PlayerSeek
 w Str PlayerPause
 r Int CmdICurrentMax [15]
 w Str PlayerSuspend
 w Int ResetVolume
 rw Int GstrBufferTime [200000]
 w Str PlayerStart
 r Int ManagerShutdown [-4]
 w Int Kill
 rw Int Volume [70]
 r Int ManagerResume [1]
com.lab126.ttsd
 rw  Has enqueueSnippet [*NOT SHOWN*]
 w Int unpause2
 w Int cancelSnippetPlayback
 rw Has playSnippetNow [*NOT SHOWN*]
 w Int pause2
com.lab126.tts
 rw  Str TtsSVoice [Tom]
 w Int CtrlBookmark
 rw Has playFile [*NOT SHOWN*]
 rw Int TextToProcess [10]
 w Int stop
 rw Str logMask [0xffff0000]
 w Int pause
 rw Str logLevel [Current log level=info
(Possible levels: all, perf, debug[9-0], info, warn, error, crit, none)]
 w Int unpause
 rw Str TtsSModel [full_155mrf22]
 rw Int TtsISpeed [100]
com.lab126.powerd
 w  Int addSuspendLevels
 r Str status [Powerd state: Active
Remaining time in this state: 308.400766
defer_suspend:0
suspend_grace:0
prevent_screen_saver:0
drive_mode:off
Battery Level: 97%
Last batt event at: 97%
Charging: No
batt_full=1
Battery logging: On
]
 w Int wakeUp
 rw Int preventScreenSaver [0]
 rw Str logMask [0xffff0000]
 w Int suspendGrace
 w Int deferSuspend
 rw Str logLevel [Current log level=info
(Possible levels: all, perf, debug[9-0], info, warn, error, crit, none)]
 w Int touchScreenSaverTimeout
 r Str state [active]
 w Int abortSuspend
 r Int isCharging [0]
 r Int battLevel [97]
 w Int rtcWakeup
com.lab126.system
 w  Str date
 r Str version [System Software Version: 040-S4_luigi-172597 Sat Sep 1 14:29:41 PDT 2012]
 r Str boardid []
 r Str waveformversion [V220_C024_60_WJ7501_D (M24, S/N 1301, 85Hz)]
 r Str usid [B008A0A004357F9E]
 r Str orientation []
 w Str sendEvent
com.lab126.wifid
 rw  Has createProfile [*NOT SHOWN*]
 r Str signalStrength [5/5
]
 rw Has cmNWProperties [*NOT SHOWN*]
 rw Has netConfig [*NOT SHOWN*]
 r Str manufacturerCode [53GRADB9SMRC2WEX5DF4]
 rw Has profileData [*NOT SHOWN*]
 r Str feelingLuckyProfile [CBTL]
 w Str cmDisconnect
 rw Has currentEssid [*NOT SHOWN*]
 r Str 711 [********* 1- Connection *********
1.1 MAC: 28:EF:01:A8:69:3B
1.2 Wireless: On(1)
1.3 AP: A (02:08:22:d2:18:87)
1.3.1   Signal strength: 5/5
1.3.2   Captive: no
1.3.3   Security: WPA2-PSK
1.3.4   Channel: 1
1.6 Country: CN

********* 2- Wireless Configuration *********
2.1   A 0 [WPA2-PSK][CCMP] (6) 

********* 3- Interface Configuration *********
3.1 IP Address: 192.168.43.115
3.2 Netmask   : 255.255.255.0
3.3 Broadcast : 192.168.43.255
3.4 Gateway   : 192.168.43.1
3.5 Config    : DHCP
3.6 DNS       : 192.168.43.1, 
3.7 Sponsored    : no

********* 4- Last DHCP Session *********
Sending discover...
Offer from server xxx.xxx.43.1 received
Sending select for xxx.xxx.43.115...
Lease of xxx.xxx.43.115 obtained, lease time 43200

5 Device Time: Fri Aug 30 07:54:38 2013

]
 r Int profileCount [2]
 w Str cmConnMode
 r Str cmState [CONNECTED]
 w Str scan
 rw Str logMask [0xffff0000]
 rw Has createNetConfig [*NOT SHOWN*]
 w Str cmCheckConnection
 r Str cmProfile [A]
 r Int cmIntfInUse [1]
 rw Int enable [1]
 r Str macAddress [28:EF:01:A8:69:3B]
 rw Str logLevel [Current log level=info
(Possible levels: all, perf, debug[9-0], info, warn, error, crit, none)]
 w Str deleteProfile
 r Str scanState [idle]
 w Str cmConnect
 rw Has scanList [*NOT SHOWN*]
 rw Has cmIntfInfo [*NOT SHOWN*]
 r Str macSecret [53GRADB9SMRC2WEX5DF4]
com.lab126.framework
 rw  Has transfer_status [*NOT SHOWN*]
 w Int insertKeystroke
 r Str xfsn [ELVvgP9mY0kDCu9gkeNQNYZqmnIHyNbJ9uP9xltY1/eJ3IvONcTj3bGDy7UE1w4Wb2yV3F0K9J4IFWBv9D8tGJXYHZgXqF5gXJG8eYsgooKWWH5iaa3vADv04BEdO29ecIIPVfUVejk=]
 rw Str logMask [crit | error | warn | info | event | perf | test | journal | debug0 | debug1 | debug2 | debug3 | debug4 | debug5 | debug6 | debug7 | debug8 | debug9 (0xffffff0)]
 w Int logContent
 rw Str logLevel [debug9]
 r Int wirelessSwitch [1]
 w Int read
 r Int isRegistered [0]
 r Int wanSwitch [1]
 w Int dismissDialog
com.lab126.transfer
 rw  Has dump_queues [*NOT SHOWN*]
 rw Has modify [*NOT SHOWN*]
 rw Has get_info [*NOT SHOWN*]
 rw Has request_upload [*NOT SHOWN*]
 rw Has dequeue [*NOT SHOWN*]
 rw Str logMask [0xffff0000]
 rw Str logLevel [Current log level=info
(Possible levels: all, perf, debug[9-0], info, warn, error, crit, none)]
 rw Has send_status [*NOT SHOWN*]
 rw Has request_download [*NOT SHOWN*]
 rw Has obliterate [*NOT SHOWN*]
com.lab126.phd
 w  Str newSPHSchedule
 rw Str logMask [0xffff0000]
 rw Str logLevel [Current log level=info
(Possible levels: all, perf, debug[9-0], info, warn, error, crit, none)]
com.lab126.volumd
 r  Int mmcIsAvailable [0]
 r Int userstoreFreeSpace [3127952]
 r Int driveModeState [0]
 r Int mmcFreeSpace [-1]
 rw Int useUsbForSerial [0]
 w Int userstoreReadyToUnMount
 rw Str logMask [0xffff0000]
 r Int mmcTotalSpace [-1]
 rw Int useUsbForNetwork [0]
 r Int userstoreTotalSpace [3201936]
 rw Str logLevel [Current log level=info
(Possible levels: all, perf, debug[9-0], info, warn, error, crit, none)]
 r Int userstoreIsAvailable [1]
com.lab126.webreaderListener
com.lab126.cmd
 r  Str activeInterface [wifi]
 w Str ensureConnection
 rw Str logMask [0xffff0000]
 rw Str logLevel [Current log level=info
(Possible levels: all, perf, debug[9-0], info, warn, error, crit, none)]
 rw Has availableInterfaces [*NOT SHOWN*]
 rw Has interfaceProperties [*NOT SHOWN*]
com.lab126.cvm
 rw  Str logMask [0xffff0000]
 rw Str logLevel [Current log level=info
(Possible levels: all, perf, debug[9-0], info, warn, error, crit, none)]
com.lab126.mcsd
 w  Int performScan
 w Int selectAutomaticMode
 r Int getManagementState [0]
 w Int enableManagementState
 w Int requestCurrentState
 w Int abortScan
 w Str selectNetwork
[root@kindle root]# exit

Monday, July 15, 2013

Codechef July 2013 Prob: the ultimate troll question

First, I had no idea how to solve this at all. There is no way to brute force it for such extremely large numbers.

Then, I saw this comment:
I was trolled by this question in two phases : First after solving for two hours I was like "oh man, awesome question. So one part of the question remains" then after 5 hours of PnC and probability, when I saw it I was like "mother of all trolls" serious mindfuck question.
I knew there had to be a shortcut somewhere. Hence, I worked out the first sample test case for t4=1. Yielded the result of 0.5. Could it be that the output is the same regardless of how many tickets Chef discards?

Investigating further, I made a program that calculates the probability of every single combination, a.k.a brute forcing the solution. Code here. Of course, I would only load the program with small inputs. The result:

Input:


Output:


I found the shortcut! Indeed, the probability is the same regardless of how many tickets Chef discarded. Happily discarded T4 from my program, submitted it, only to get a runtime error. Turns out my stack has run out of space due to too many recursive calls from T3. Hmm, I thought, I could make the calculation non-recursive, but it is still up to 1000000000 calculations for a single test. Another shortcut must exist!

Went back to the question to look for more patterns. Discovered than 0.5 = 2/(2+2) for first sample test case, and 0.4 = 2/(2+3) for second test case. T3 is also not needed!

Submitted a program consisting of just these few lines:



ANDDDDDDDDDDDDDDDDD


Ultimate troll question.



Codechef July 2013 Galactik

First, to find out where to build the bridges, I had to find out what islands/isolated pockets of planets are there. This can be done by a connected components algorithm, simple enough.

Next step, to choose which islands to build the teleporters on....I had no idea. Dug through the comments on the question page for hints. I found this big one:
Can GFA create more than one teleport on a planet?
Please specify if GFA can construct more than one teleport ending on a planet.
@zwolf10003 ,@qwaker00: yes.

Hence, I could just build one end of all teleporters on the same planet. And of course, that planet would offer the cheapest rate in the galaxy for building one!

The other end would go to each individual island/component. And for each island, the best place to end the teleporter would be the cheapest planet in the island.

With the solution planned out I proceeded to code it out in Python. Code here. Worked perfectly, but when submitted:


Sigh.

Time for port over to C++ again. But before that, I made a search for the fastest I/O operation I can achieve on C++. I landed upon this blog post. Tried the last method, but found that Windows does not have getchar_unlocked(). Replaced it with getchar() instead.

The result:


It's accepted!


Tuesday, July 2, 2013

Codechef Jun 2013 Collect

Coded first in Python, time limit exceeded.

Then ported over to C++, time limited exceeded again.

Reviewed the editorial, added segment trees to facilitate range querying, but still exceeded time limit!

=_=U