Monday, May 4, 2015

Guide to Recovery your TF600T!




I recently got a TF600T. Sadly, I lost its password! So it's practically useless, as I can't get pass the lockscreen. There are some ways to recover the device: factory reset and re-flashing. Unfortunately, factory reset failed me for some reasons, while re-flashing wouldn't work as I didn't back up the original image.

After spending 2 weeks trying to understand Windows RT recovery system (most of the regards go to xda-developers forum), I've finally figured out how to restore my TF600T! :)

This post summarizes what I learned and provides the steps to recover your TF600T. Hope you can benefit from this

Important Notes:

  1. You can restore your TF600 even if you forgot to make a recovery image. For this, you'll have to use someone else's image. And fortunately, it's available here.
  2. You may not be able to use TF600TG or other variants' images on TF600T. How'd you check if you're using a proper image? Just try it! If it's incompatible, your device will simply refuse to boot with a certain error code. I spent a week to realize I was using a wrong image! The tricky part is that you'd still be able to enter recovery mode even with an incompatible image! Looks like the recovery image uses some kind of generic drivers?
  3. The USB drive that you would use for recovery has to have GPT partition table and is formatted to FAT32. I personally used GParted on Linux for this. How'd you check that you do this properly? Try getting into USB recovery mode. If you can't, chances are you didn't format your drive correctly.


Different modes and how to enter them:

1. Normal Mode:
a. Push power button

2. USB Recovery Mode:
a. Plug in a properly partitioned USB drive that has a proper image
b. Press and hold vol-down button when powering the device on. Keep holding the vol-button down until ASUS logo is shown. If you do this correctly, you'll get to a screen that prompts you for a language. If you don't see this, maybe there's a problem with your USB drive or the image on it.

3. Recovery Mode:
a. You can only go here if you have a proper installed OS
b. Push power button
c. Wait until you get to login screen
d. While holding the "Shift" keyboard-button, tap the power icon, and select restart

P.S. Recovery Mode is useful if you have a working operating system and also a recovery image specific to it. In this guide, we'll be using USB Recovery Mode to restore the device.

Steps:
1. Download the image that apatcas (from xda-developers) generously provided:
http://www.alexpatcas.com/vivort.rar
or from my mirror:
https://drive.google.com/open?id=0B7ufsmtTr_EjbVdQbVVJS19wX1U

2. Prepare a recovery USB drive
a. The image from (1) is 4.2GB, so you need at least that much of space
b. Format and partition your drive as GPT. If you're using Linux, I suggest using GParted. Instruction is as follow:

  1. Open GParted
  2. Select your USB drive from the dropdown on top right.
  3. Select "Device" -> "Create partition table" -> "GPT"
  4. Format the partition to FAT32 filesystem

c. Extract and paste the image from (1) onto the drive. You should see "boot", "sources", and "efi" directories on the top-level directory.

3. Prepare partitioning script to be run on your TF600T "USB Recovery Mode"

Save the script below as "X:\recovery.txt" (change X to your USB drive):
select disk 0
clean
convert gpt
create partition primary size=350
format quick fs=ntfs label="Windows RE tools"
assign letter="T"
set id="de94bba4-06d1-4d40-a16a-bfd50179d6ac"
gpt attributes=0x8000000000000001
create partition efi size=260
format quick fs=fat32 label="System"
assign letter="S"
create partition msr size=128
create partition primary 
shrink minimum=3072
format quick fs=ntfs label="Windows"
assign letter="W"
create partition primary
format quick fs=ntfs label="Recovery image"
assign letter="R"
set id="de94bba4-06d1-4d40-a16a-bfd50179d6ac"
gpt attributes=0x8000000000000001
list volume

4. Enter "USB Recovery Mode" on your TF600T
5. Select English, select "Troubleshoot", select "Advanced", and select "Command Prompt"
6. Type: "diskpart"
7. On diskpart terminal, type: "list volume".
8. Remember the letter for your USB drive, on this tutorial, we'll refer to this as "X".
9. Quit from diskpart terminal by pressing "ctrl+c"
10. Format and partition your TF600T properly. Type: "diskpart /s X:\recovery.txt" (replace X with your USB drive)
11. Flash the image on your USB drive onto your TF600T:
  1. Type: "dism /apply-image /imagefile:X:\sources\install.wim /index:1 /applydir:W:"
  2. Grab a cup of coffee or two while waiting.
12. Fix your TF600T partition table
  1. Type: BOOTREC /FIXMBR
  2. Type: BOOTREC /FIXBOOT
  3. Type: BOOTREC /SCANOS
  4. Type: BOOTREC /REBUILDBCD
  5. Type: bcdboot w:\windows
13. Exit the command prompt. Type: "exit"
14. Boot to windows normally! Enjoy!

Where I originally post this:
http://forum.xda-developers.com/showpost.php?p=60536721&postcount=127

Sunday, April 19, 2015

Using OpenCV 3.0

1. Generate OpenCV makefile using cmake (e.g. cmake CMakeLists.txt)
2. Compile using makefile generated at (1) (e.g. make -j8)
3. Install generated files (e.g. make install)
4. Export opencv shared library path:
 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
5. Compile your program like this: "g++ [source file goes here] `pkg-list opencv --config`"


Wednesday, April 15, 2015

TCP/IP Programming in GO

Out of curiosity I googled around TCP/IP programming in Go! And guess what? It looks really beautiful! I found this great article explaining how to build a simple chat server in Go:
http://www.badgerr.co.uk/2011/06/20/golang-away-tcp-chat-server/

What's very interesting to me is the concept of "channel". In Android programming world, it's like a Handler. You can have any function posts something to it and it will magically get received by the handler function. And yes, channel posting and receiving is in a single thread, just like the default behavior of Handler in Android. Check out the article above, it explains many of the basic concepts really well.

Monday, April 13, 2015

Synergy on ARM

I just recently got myself an NVIDIA Jetson TK1. Exciting! While developing using it, unfortunately it's quite slow to browse the website or listening to music through it.

So I had an idea to install Synergy client to it, while the server is on my laptop that's connected to it through Ethernet.

As there's no prebuilt Synergy for ARM 32bit, here's how you build it:
1. Download the source code from official synergy site
2. Download cmake, curl, and x11 dev libraries:
sudo apt-get install cmake libcurl4-openssl-dev libx11-dev libxtst-dev build-essential
3. After (2), compilation will still fail. You have to edit the include directory path on CMakeList.txt: Search for /usr/local/include and modify it to /usr/include
4. If you happened to had a compilation failure, try removing CMakeCache.txt and re-compile
5. If you encounter problem related to gmock, go to ext folder and extract gmock..zip to appropriate folder. There will be another cmake inside of it, build.
5. Enjoy!

Resource:
http://www.rootusers.com/compiling-synergy-from-source-on-the-raspberry-pi/

Sunday, March 29, 2015

Compiling AOSP gingerbread on Ubuntu 14.04

I've finally succeeded compiling Gingerbread (2.4)  build on Ubuntu 14.04 and I think I wanna share the steps :)

1. Follow the steps to setup build env at Google's AOSP official site:
http://source.android.com/source/initializing.html

2. Download the source code:
http://source.android.com/source/downloading.html
The TAG for for Gingerbread I used is: android-2.3.6_r1, which is the version supported on Nexus One

3. Compile:
http://source.android.com/source/building-running.html
Here's the tricky part. Compilation will work seamlessly (without modding the source code) on GCC-4.4. Newer version of GCC has stricter code formatting, causing some parts of the project to fail.

One nice work-around I found online:
1. Download gcc-4.4: sudo apt-get install gcc-4.4-multilib g++-4.4-multilib
2. Make a folder where you create symlinks for gcc, g++, and cpp to gcc-4.4, g++-4.4, and g++-4.4 respectively
3. Override the PATH env, e.g. export PATH=$PWD:$PATH

This work-around is nice because you don't have to change your default gcc onto older version. Well, at least I don't want to :p
One caveat though, I find one project that still failed after this, which turned out to hard-code gcc path onto /usr/bin/gcc! Dang...  So don't forget to modify this also:
diff --git a/WebCore/dom/make_names.pl b/WebCore/dom/make_names.pl
index 083e309..b6c942f 100755
--- a/WebCore/dom/make_names.pl
+++ b/WebCore/dom/make_names.pl
@@ -47,7 +47,7 @@ my %tags = ();
 my %attrs = ();
 my %parameters = ();
 my $extraDefines = 0;
-my $preprocessor = "/usr/bin/gcc -E -P -x c++";
+my $preprocessor = "/usr/bin/gcc-4.4 -E -P -x c++";

Now compilation should succeed flawlessly! :)

Tuesday, September 9, 2014

Corner cases of Ubuntu 14.04 on Lenovo ThinkPad x201

I've been using Ubuntu 14.04 for a couple months now.


1. CPU got stucked on 1.2GhZ
Recently I installed a handy utility called indicator-cpufreq, which gives a system status bar icon indicating the currently used CPU governor and the current cpu frequency.  I noticed that my CPU always got stucked on 1.2Ghz, no matter what I did. I have tried modifying it manually by echo-ing the sysfs node and using cpufreq-utils, without much luck. I then came across this page:

http://askubuntu.com/questions/340626/permanently-change-maximum-cpu-frequency
This page explains that there is a CPU bios_limit that if set wrongly, may prevent the CPU from going above the frequency threshold that's set there.

cat /sys/devices/system/cpu/cpu0/cpufreq/bios_limit

Turned out it really was the culprit!! For some weird reason it got set to 1.2GHZ!!

This is how you worked around it:

echo 1 > /sys/module/processor/parameters/ignore_ppc

To make workaround permanent, we can edit the kernel command line argument, just like what's explained on the same page:

Modify /etc/default/grub to be like this:
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash processor.ignore_ppc=1"

Everything works like a charm afterwards!

I then installed cpufreqd, which is a daemon to customize CPU frequency based on the laptop's realtime battery status (e.g. power level, plug/unplugged, etc). Now my docked x201 is running buttery smooth at 2.67 GHZ :)

I want to check out how long will it take to build AOSP on this laptop now :)

2. Intermittent shutdown due to overheating
Another problem I was facing is that after a couple hours of running docked, my laptop would shut itself off! When this happened, I undocked my laptop and noticed that it's abnormally hot!
I then realized that x201's airflow is located on its bottom, which got blocked by the dock. (sigh.. guess the dock isn't poorly designed.... :( )

Don't fret out though! There's solution!
I found this handy tool to control the fan speed of the laptop's.

http://www.thinkwiki.org/wiki/How_to_control_fan_speed

Basically, x201's fan can be controlled by this node:
/proc/acpi/ibm/fan
There are several levels that can be set, which corresponds to the RPM of the fan.

With this in mind, thinkfan can be used to automate the RPM of the fan depending on the reading of the thermal sensors. This page kindly describes how to set it up. (including how to run thinkfan as a daemon, custom setup for x201, etc)

http://staff.science.uva.nl/~kholshei/thinkfan_guide/

Edit (10/06/2015):
The following steps are how I did it:
1. sudo apt-get install thinkfan
2. sudo echo "options thinkpad_acpi fan_control=1" > /etc/modprobe.d/thinkpad_acpi.conf
3. sudo vim /etc/default/thinkfan, change it to be the following (this is to load thinkfan on boot):
START=yes
4. sudo vim /etc/thinkfan.conf, change it to be the following (this is fan vs. sensor-reading):

# The way the config works is that it picks the highest value among all sysfs nodessensor /sys/devices/virtual/hwmon/hwmon0/temp1_input
sensor /sys/devices/platform/coretemp.0/hwmon/hwmon2/temp4_input
sensor /sys/devices/platform/coretemp.0/hwmon/hwmon2/temp2_input
#sensor /proc/acpi/ibm/thermal

(0, 0, 47)
(1, 46, 50)
(2, 49, 53)
(3, 52, 56)
(4, 55, 59)
(5, 58, 62)
(6, 61, 65)
(7, 64, 75)
#127 is for disengaged
(127, 74, 32767)

And for debugging:
1. To see how a new config file works:
sudo thinkfan -n
2. To check current temperature:
cat /sys/devices/virtual/hwmon/hwmon0/temp1_input && cat /sys/devices/platform/coretemp.0/hwmon/hwmon2/temp4_input && cat /sys/devices/platform/coretemp.0/hwmon/hwmon2/temp2_input
'or'
cat /proc/acpi/ibm/thermal (in ubuntu 14.04, only shows one temperature)
3. To check fan level:
cat /proc/acpi/ibm/fan
(level shouldn't be 'auto' if thinkfan is really running)
4. ps aux | grep thinkfan <- you should see the process running


Wednesday, January 29, 2014

Android Binder, AIDL, Service, and API

Android Binder is an IPC mechanism used in Android. Binder can be accessed through the native code (C++) and also through Java code.

Here are some places where Binder are used:
1. When you use system service through mContext.getSystemService(...)
2. When you start another application through Intent.
3. When you're implementing a public service that uses AIDL file (this is pretty obvious)
4. When you're implementing interacting through different services using Messenger class

To me, what's the most interesting is that Android abstracts it so well such that I didn't realize I've been doing IPC calls so many times! In fact, I began my first Android programming without having any idea what an IPC was.

For the work I've been doing, I need to implement a piece of code that talks to the driver layer. Since I don't want to re-write the tedious JNI code multiple times (in case of it's needed somewhere else), I decided to create a public Service using AIDL convention. This service is the one that interacts with the native layer, and will then be exposed as an API in the SDK.
After that, it will essentially be wrapped one more time, such that user wouldn't have to actually interact with the service directly. Sounds like I'm over-complicating it, huh? Not really.. This is exactly how InputManager is working under the hood. When you do  mContext.getSystemService(INPUT_MANAGER), under the hood, InputManager class is interacting with InputManagerService. On the whole system, there's only a single instance of InputManagerService. This service is interacting with some native piece of codes that are tightly coupled to a lower layer. This way, as an application developer, we can all simply use the handy interface exposed through InputManager :)