2015년 6월 3일 수요일

How to install GAppsInstaller(Lollipop) on ODROID-XU3 CM version

Download GAppsInstaller for Lollipop.
http://dn.odroid.com/GAPPS/GAppsInstaller_lollipop.apk



Install GAppsInstaller.




But failed.


Get root permission.
Click Build number many times.


Now find Developer options.


Root access.



go back Setting and enter Privacy.


Privacy Guard.
Check 'Enabled by default and Gapps Installer item'


Now Can install.



Reboot and go 'Play Store'.



2015년 5월 19일 화요일

GIT: unpack failed: error Missing tree

git push 할 경우 아래와 같은 나오면서 안되는 경우가 있었습니다.

error: unpack failed: error Missing tree 8fe84b8d352eedc3acd46a17de0531d38d5de4c2
fatal: Unpack error, check server log
To ssh://codewalker@xxxxxx.or.kr:29418/android_external_wpa_supplicant_8
 ! [remote rejected] HEAD -> refs/for/4412_4.4.4_master (n/a (unpacker error))

딱히 googling하여도 답을 못 찾겠더군요.

https://www.google.co.kr/webhp?sourceid=chrome-instant&ion=1&espv=2&es_th=1&ie=UTF-8#q=%22Error:+unpack+failed:+error+Missing+tree%22&newwindow=1&start=10

수정한 파일이 특이하게 아래 포맷으로 되어 있었습니다.
$ file android.config
android.config: ISO-8859 text

일반적으로 ASCII text인데 말이죠.
wifi_display.c:               C source, ASCII text
wifi_display.h:               ASCII text

그래서 파일을 지우고 다시 만들어 ASCII text로 만들고 수정하고 push 하니 문제가 없더군요.

$ file android.config
android.config: ASCII text

결론: unpack failed가 나면 file의 속성을 확인하고 ASCII text로 만들어 보자.


2015년 4월 22일 수요일

apk unpack and repack

기존에 누군가가 만들어준 GAppsInstaller_kk.apk가 문제가 있다는 글이 포럼에 올라 왔다.

http://forum.odroid.com/viewtopic.php?f=113&t=11854&start=50

여기서 링크에 있는 GAPPs를 사용하면 문제가 해결 된다는 글이 있다.

http://wiki.cyanogenmod.org/w/Google_Apps

그래서 GAppsInstaller_kk.apk 를 풀어 위에 아래 파일로 대체 하려고 한다.

https://goo.im/gapps/gapps-kk-20140105-signed.zip/

gapps-kk-20140105-signed.zip 압축을 푼다.


 system 폴더에서 모든 파일을 선택한다.


우측 클릭 메뉴에서 Compress...를 선택한다.
gapps.tar.xz로 압축한다.



gapps.tar.xz를 gapps.xz로 변경한다.

이제 apk를 풀고 묶는 툴을 설치한다.

http://ibotpeaches.github.io/Apktool/

Apktool 2.x 버전과 Java 1.7 을 사용하였다.

http://ibotpeaches.github.io/Apktool/install/

저는 안드로이드 빌드를 위하여 1.6과 1.7 두가지 모두 설치 되어 있어서 아래와 같이 openjdk로 변경합니다.

$ sudo update-alternatives --config java

There are 3 choices for the alternative java (providing /usr/bin/java).

  Selection    Path                                            Priority   Status
------------------------------------------------------------
  0            /usr/lib/jvm/java-6-oracle/jre/bin/java          1073      auto mode
  1            /usr/lib/jvm/java-6-oracle/jre/bin/java          1073      manual mode
  2            /usr/lib/jvm/java-6-sun/jre/bin/java             63        manual mode
* 3            /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java   1071      manual mode

Press enter to keep the current choice[*], or type selection number:

apktool로 압축을 푼다.

$ apktool d GAppsInstaller_kk.apk 
I: Using Apktool 2.0.0 on GAppsInstaller_kk.apk
I: Loading resource table...
I: Decoding AndroidManifest.xml with resources...
I: Loading resource table from file: /home/codewalker/apktool/framework/1.apk
I: Regular manifest package...
I: Decoding file-resources...
I: Decoding values */* XMLs...
I: Baksmaling classes.dex...
I: Copying assets and libs...
I: Copying unknown files...
I: Copying original files...

그리고 gpapps.xz를 덮어쓴다.
$ cp gapps.xz GAppsInstaller_kk/res/raw/gapps.xz

기존 GAppsInstaller_kk.apk를 지운다.
$ rm -rf GAppsInstaller_kk.apk

apktool로 묶는다.
$ apktool b GAppsInstaller_kk/
I: Using Apktool 2.0.0
I: Checking whether sources has changed...
I: Smaling smali folder into classes.dex...
I: Checking whether resources has changed...
I: Building resources...
I: Building apk file...

새로 만든 GAppsInstaller_kk.apk
http://dn.odroid.com/GAPPS/new/GAppsInstaller_kk.apk


2015년 4월 10일 금요일

WiringPi on ODROID-C1(Android)

WiringPi on ODROID-C1(Android)



ODROID-C1 Ubuntu에서 Raspberry Pi에서 사용되는 WiringPi를 사용할 수 있도록 porting 하였습니다.

http://odroid.com/dokuwiki/doku.php?id=en:c1_tinkering

wiringPi를 사용한 example-led 예제를 Android 에서도 사용할 수 있도록 작업을 해 보았습니다.

먼저 소스를 다운 받습니다.

git clone https://github.com/codewalkerster/example-led

다운 받은 소스를 eclipse에서 import 시킵니다.


그리고 NDK를 이용하여 wiringPi를 build합니다.

$ cd example-led/jni
$ ndk-build
Android NDK: WARNING: APP_PLATFORM android-16 is larger than android:minSdkVersion 7 in /media/codewalker/92fc070a-3bc1-43e0-af27-03d08ba9dd3e/home/codewalker/workspace/xxxx/example-led/AndroidManifest.xml  
[armeabi] Compile thumb  : wiringPi <= wiringPi.c
/media/codewalker/92fc070a-3bc1-43e0-af27-03d08ba9dd3e/home/codewalker/workspace/xxxx/example-led/jni/wiringPi/wiringPi.c:147:0: warning: "PAGE_SIZE" redefined [enabled by default]
 #define PAGE_SIZE   (4*1024)
 ^
In file included from /home/codewalker/projects/android-ndk-r10d/platforms/android-21/arch-arm/usr/include/signal.h:34:0,
                 from /home/codewalker/projects/android-ndk-r10d/platforms/android-21/arch-arm/usr/include/poll.h:34,
                 from /media/codewalker/92fc070a-3bc1-43e0-af27-03d08ba9dd3e/home/codewalker/workspace/xxxx/example-led/jni/wiringPi/wiringPi.c:59:
/home/codewalker/projects/android-ndk-r10d/platforms/android-21/arch-arm/usr/include/limits.h:119:0: note: this is the location of the previous definition
 #define PAGE_SIZE 4096
 ^
/media/codewalker/92fc070a-3bc1-43e0-af27-03d08ba9dd3e/home/codewalker/workspace/xxxx/example-led/jni/wiringPi/wiringPi.c: In function 'interruptHandler':
/media/codewalker/92fc070a-3bc1-43e0-af27-03d08ba9dd3e/home/codewalker/workspace/xxxx/example-led/jni/wiringPi/wiringPi.c:1865:7: warning: return makes pointer from integer without a cast [enabled by default]
       return wiringPiFailure (WPI_FATAL, "wiringPiISR: wiringPi has not been initialised. Unable to continue.\n") ;
       ^
[armeabi] Compile thumb  : wiringPi <= wiringShift.c
[armeabi] Compile thumb  : wiringPi <= piHiPri.c
[armeabi] Compile thumb  : wiringPi <= piThread.c
[armeabi] Compile thumb  : wiringPi <= wiringPiSPI.c
[armeabi] Compile thumb  : wiringPi <= wiringPiI2C.c
[armeabi] Compile thumb  : wiringPi <= softPwm.c
[armeabi] Compile thumb  : wiringPi <= softTone.c
[armeabi] Compile thumb  : wiringPi <= mcp23008.c
[armeabi] Compile thumb  : wiringPi <= mcp23016.c
[armeabi] Compile thumb  : wiringPi <= mcp23017.c
[armeabi] Compile thumb  : wiringPi <= mcp23s08.c
[armeabi] Compile thumb  : wiringPi <= mcp23s17.c
[armeabi] Compile thumb  : wiringPi <= sr595.c
[armeabi] Compile thumb  : wiringPi <= pcf8574.c
[armeabi] Compile thumb  : wiringPi <= pcf8591.c
[armeabi] Compile thumb  : wiringPi <= mcp3002.c
[armeabi] Compile thumb  : wiringPi <= mcp3004.c
[armeabi] Compile thumb  : wiringPi <= mcp4802.c
[armeabi] Compile thumb  : wiringPi <= mcp3422.c
[armeabi] Compile thumb  : wiringPi <= max31855.c
[armeabi] Compile thumb  : wiringPi <= max5322.c
[armeabi] Compile thumb  : wiringPi <= sn3218.c
[armeabi] SharedLibrary  : libwiringPi.so
[armeabi] Install        : libwiringPi.so => libs/armeabi/libwiringPi.so
[armeabi] Compile thumb  : wiringPiDev <= ds1302.c
[armeabi] Compile thumb  : wiringPiDev <= maxdetect.c
[armeabi] Compile thumb  : wiringPiDev <= piNes.c
[armeabi] Compile thumb  : wiringPiDev <= gertboard.c
[armeabi] Compile thumb  : wiringPiDev <= piFace.c
[armeabi] Compile thumb  : wiringPiDev <= lcd128x64.c
[armeabi] Compile thumb  : wiringPiDev <= lcd.c
[armeabi] Compile thumb  : wiringPiDev <= piGlow.c
[armeabi] SharedLibrary  : libwiringPiDev.so
[armeabi] Install        : libwiringPiDev.so => libs/armeabi/libwiringPiDev.so
[armeabi] Compile thumb  : wpi_android <= wpi_android.c
[armeabi] SharedLibrary  : libwpi_android.so
[armeabi] Install        : libwpi_android.so => libs/armeabi/libwpi_android.so 



jni/Android.mk 에 libwingPi.so와 libwingPiDev.so 빌드하도록 추가 하였습니다.

include $(CLEAR_VARS)
LOCAL_C_INCLUDES += \
    $(NDK_PATH)/platforms/android-21/arch-arm/usr/include \
    $(LOCAL_PATH)/wiringPi

LOCAL_MODULE    := wiringPi
LOCAL_SRC_FILES := \
    wiringPi/wiringPi.c \
    wiringPi/wiringShift.c \
    wiringPi/piHiPri.c \
    wiringPi/piThread.c \
    wiringPi/wiringPiSPI.c \
    wiringPi/wiringPiI2C.c \
    wiringPi/softPwm.c \
    wiringPi/softTone.c \
    wiringPi/mcp23008.c \
    wiringPi/mcp23016.c \
    wiringPi/mcp23017.c \
    wiringPi/mcp23s08.c \
    wiringPi/mcp23s17.c \
    wiringPi/sr595.c \
    wiringPi/pcf8574.c \
    wiringPi/pcf8591.c \
    wiringPi/mcp3002.c \
    wiringPi/mcp3004.c \
    wiringPi/mcp4802.c \
    wiringPi/mcp3422.c \
    wiringPi/max31855.c \
    wiringPi/max5322.c \
    wiringPi/sn3218.c

LOCAL_CFLAGS    += -UNDEBUG -DANDROID

LOCAL_LDLIBS    := -ldl -llog
include $(BUILD_SHARED_LIBRARY)


include $(CLEAR_VARS)
LOCAL_C_INCLUDES += \
    $(NDK_PATH)/platforms/android-21/arch-arm/usr/include \
    $(LOCAL_PATH)/wiringPi

LOCAL_MODULE    := wiringPiDev
LOCAL_SRC_FILES := \
    devLib/ds1302.c \
    devLib/maxdetect.c \
    devLib/piNes.c \
    devLib/gertboard.c \
    devLib/piFace.c \
    devLib/lcd128x64.c \
    devLib/lcd.c \
    devLib/piGlow.c

LOCAL_SHARED_LIBRARIES := libwiringPi

LOCAL_CFLAGS    += -UNDEBUG
include $(BUILD_SHARED_LIBRARY)

그리고 wirinPi에서 사용해야 하는 function을 jni 형식으로 만듭니다.

jint Java_com_hardkernel_wiringpi_MainActivity_analogRead(JNIEnv* env, jobject obj, jint port) {
    return analogRead(port);
}

void Java_com_hardkernel_wiringpi_MainActivity_digitalWrite(JNIEnv* env, jobject obj, jint port, jint onoff) {
    digitalWrite(port, onoff);
}

int Java_com_hardkernel_wiringpi_MainActivity_wiringPiSetupSys(JNIEnv* env, jobject obj) {
    wiringPiSetupSys();
    return 0;
}

사용한 GPIO를 선언합니다.

    private final int ledPorts[] = {
        97, // GPIOX.BIT0(#97)
        108, // GPIOX.BIT11(#108)
        100, // GPIOX.BIT3(#100)
        101, // GPIOX.BIT4(#101)
        105, // GPIOX.BIT8(#105)
        106, // GPIOX.BIT9(#106)
        107, // GPIOX.BIT10(#107)
        115,  // GPIOX.BIT18(#115)
        116,  // GPIOX.BIT19(#116)
        88,  // GPIOY.BIT8(#88)
        83,  // GPIOY.BIT3(#83)
        87,  // GPIOY.BIT7(#87)
        104,  // GPIOX.BIT7(#104)
        102,  // GPIOX.BIT5(#102)
        103,  // GPIOX.BIT6(#103)
        117, // GPIOX.BIT20(#117)
        99, // GPIOX.BIT2(#99)
        118, // GPIOX.BIT21(#118)
        98, // GPIOX.BIT1(#98)
    };

MainActivity에 jni function들을 선언합니다.

    public native int wiringPiSetupSys();
    public native int analogRead(int port);
    public native void digitalWrite(int port, int onoff);

    static {
        System.loadLibrary("wpi_android");
    }

/sys/class/gpio/export를 이용하여 GPIO sysfs 노드를 만듭니다.
sysfs 방식은 pinMode()를 사용할 수 없기 때문에 directionout으로 설정 합니다.
그리고 value, direction의 접근 권한을 바꿉니다.

    boolean exportGPIO() {
        try {
            DataOutputStream os = new DataOutputStream(mProcess.getOutputStream());
            for (int port: ledPorts) {
                os.writeBytes("echo " +  port + " > /sys/class/gpio/export\n");
                os.writeBytes("chmod 666 /sys/class/gpio/gpio" + port + "/direction\n");
                os.writeBytes("echo out > /sys/class/gpio/gpio" + port + "/direction\n");
                os.writeBytes("chmod 666 /sys/class/gpio/gpio" + port + "/value\n");
            }
            os.flush();
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
            return false;
        }

        return true;
    }

wiringPi의 "/dev/mem"을 open 하여 mmap을 사용하는 방식으로 만들려고 하였으니 "/dev/mem"은 root가 아니면 접근을 제한하도록 되어 있어서 불가능합니다.
jni의 library에는 root 권한을 줄 방법이 없습니다.

그래서 wiringPiSetupSys()를 호출 하여 wiringPi library를 초기화 합니다.


주기적으로 update()를 호출 하도록 만들고 UI와 LED를 control 합니다.

    public void update() {
        int i = 0;
        int adcValue = 0;
        int ledPos = 0;
        if ((adcValue = analogRead (PORT_ADC1)) > 0) {
            ledPos = (adcValue * ledPorts.length * 1000) / 1024;
            ledPos = (ledPorts.length - (ledPos / 1000));
            mADC.setProgress(adcValue);
        } else
            ledPos = 0;

        for (i = 0; i < ledPorts.length; i++) {
            digitalWrite (ledPorts[i], 0);
            mLeds.get(i).setChecked(false);
        }

        for (i = 0; i < ledPos; i++) {
            digitalWrite (ledPorts[i], 1);
            mLeds.get(i).setChecked(true);
        }

        if (!mStop)
            handler.postDelayed(runnable, 100);
    }


2015년 3월 19일 목요일

android에서 USB GPS Module 확인 방법

hardkernel에서 판매 중인 USB GPS Module입니다.

ODROID에 연결하면 아래와 같이 /dev/ttyACM0 노드가 생깁니다.

root@odroidxu3:/ # ls -l /dev/ttyACM0                                        
crw-rw-rw- gps      gps      166,   0 2015-03-19 16:46 ttyACM0

cat으로 노드를 읽어 보면 NMEA 값이 출력이 됩니다.

root@odroidxu3:/ # cat /dev/ttyACM0                                            
$GPRMC,,V,,,,,,,,,,N*53
$GPVTG,,,,,,,,,N*30
$GPGGA,,,,,,0,00,99.99,,,,,,*48
$GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
$GPGSV,1,1,04,06,,,22,16,,,21,18,,,23,23,,,28*7C
$GPGLL,,,,,,V,N*64
$GPRMC,,V,,,,,,,,,,N*53
$GPVTG,,,,,,,,,N*30
$GPGGA,,,,,,0,00,99.99,,,,,,*48
$GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
$GPGSV,1,1,04,06,,,22,16,,,21,18,,,22,22,,,22*76
$GPGLL,,,,,,V,N*64
$GPRMC,,V,,,,,,,,,,N*53
$GPVTG,,,,,,,,,N*30
$GPGGA,,,,,,0,00,99.99,,,,,,*48
$GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
$GPGSV,1,1,04,06,,,22,16,,,21,18,,,22,22,,,21*75
$GPGLL,,,,,,V,N*64
$GPRMC,,V,,,,,,,,,,N*53
^C
130|root@odroidxu3:/ # 

google apps을 설치하고 GPS를 사용하는 app을 실행하면 adb logcat으로도 GPS 정보가 올라오는지 확인이 가능합니다.


D/libmbm-gps( 3167): Got an nmea string, parsing.
D/libmbm-gps( 3167): Received: $GPRMC,,V,,,,,,,,,,N*53
D/libmbm-gps( 3167): RMC
D/libmbm-gps( 3167): Got an nmea string, parsing.
D/libmbm-gps( 3167): Received: $GPVTG,,,,,,,,,N*30
D/libmbm-gps( 3167): unknown sentence 'GPVTG
D/libmbm-gps( 3167): Got an nmea string, parsing.
D/libmbm-gps( 3167): Received: $GPGGA,,,,,,0,00,99.99,,,,,,*48
D/libmbm-gps( 3167): GGA
D/libmbm-gps( 3167): Got an nmea string, parsing.
D/libmbm-gps( 3167): Received: $GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
D/libmbm-gps( 3167): GSA
D/libmbm-gps( 3167): Got an nmea string, parsing.
D/libmbm-gps( 3167): Received: $GPGSV,1,1,00*79
D/libmbm-gps( 3167): GSV
D/libmbm-gps( 3167): NR sat: 'GSV'
D/libmbm-gps( 3167): Got an nmea string, parsing.
D/libmbm-gps( 3167): Received: $GPGLL,,,,,,V,N*64
D/libmbm-gps( 3167): GLL
D/libmbm-gps( 3167): Got an nmea string, parsing.
D/libmbm-gps( 3167): Received: $GPRMC,,V,,,,,,,,,,N*53
D/libmbm-gps( 3167): RMC
D/libmbm-gps( 3167): Got an nmea string, parsing.
D/libmbm-gps( 3167): Received: $GPVTG,,,,,,,,,N*30
D/libmbm-gps( 3167): unknown sentence 'GPVTG
D/libmbm-gps( 3167): Got an nmea string, parsing.
D/libmbm-gps( 3167): Received: $GPGGA,,,,,,0,00,99.99,,,,,,*48
D/libmbm-gps( 3167): GGA
D/libmbm-gps( 3167): Got an nmea string, parsing.
D/libmbm-gps( 3167): Received: $GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
D/libmbm-gps( 3167): GSA
D/libmbm-gps( 3167): Got an nmea string, parsing.
D/libmbm-gps( 3167): Received: $GPGSV,1,1,01,18,,,28*7B
D/libmbm-gps( 3167): GSV
D/libmbm-gps( 3167): NR sat: 'GSV'
D/libmbm-gps( 3167): nmea_reader_parse: GSV message with total satellites 1
D/libmbm-gps( 3167): update sv status
D/libmbm-gps( 3167): Got an nmea string, parsing.
D/libmbm-gps( 3167): Received: $GPGLL,,,,,,V,N*64
D/libmbm-gps( 3167): GLL
D/libmbm-gps( 3167): Got an nmea string, parsing.
D/libmbm-gps( 3167): Received: $GPRMC,,V,,,,,,,,,,N*53
D/libmbm-gps( 3167): RMC
D/libmbm-gps( 3167): Got an nmea string, parsing.
D/libmbm-gps( 3167): Received: $GPVTG,,,,,,,,,N*30
D/libmbm-gps( 3167): unknown sentence 'GPVTG
D/libmbm-gps( 3167): Got an nmea string, parsing.
D/libmbm-gps( 3167): Received: $GPGGA,,,,,,0,00,99.99,,,,,,*48
D/libmbm-gps( 3167): GGA
D/libmbm-gps( 3167): Got an nmea string, parsing.
D/libmbm-gps( 3167): Received: $GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
D/libmbm-gps( 3167): GSA
D/libmbm-gps( 3167): Got an nmea string, parsing.
D/libmbm-gps( 3167): Received: $GPGSV,1,1,01,17,,,21*7D
D/libmbm-gps( 3167): GSV
D/libmbm-gps( 3167): NR sat: 'GSV'
D/libmbm-gps( 3167): nmea_reader_parse: GSV message with total satellites 1
D/libmbm-gps( 3167): update sv status
D/libmbm-gps( 3167): Got an nmea string, parsing.
D/libmbm-gps( 3167): Received: $GPGLL,,,,,,V,N*64
D/libmbm-gps( 3167): GLL


소스 코드는 아래에서 확인이 가능합니다.


GPS 노드 이름이 다르거나 baud rate가 다르면 build.prop에 아래 부분을 수정 하시면 GPS library에서 두 정보를 읽어 처리 하도록 되어 있습니다.

ro.kernel.android.gps=/dev/ttyACM0
ro.kernel.android.gps.speed=9600

2015년 2월 5일 목요일

KODI for ODROID-C1


KODI is pre-installed on ODROID-C1 1.2 version.



But KODI is not working well because KODI is denied by Superuser.

KODI need SuperSU apps instead Supersuser app.


Settings => Language & input


Turn off Hardware Physical keyboard.
It you want to work IR remote, Turn on after settings.


Download GApps Installer for KitKat.


Install GApps Installer app.





Allow and wait to reboot.


Market installed.


Install SuperSU app.


Continue


Normal


Remember choice forever and Allow.



Grant



2014년 11월 11일 화요일

ODROID-W vs Raspberry Pi A+ vs Raspberry Pi B+




Raspberry Pi
Model B+
Raspberry Pi
Model A+
ODROID-W
SoCBroadcom BCM2835 ARM11 processor @ 700MHz with VideoCore IV GPU
System Memory512 MB (PoP)256 MB (PoP)512 MB (PoP)
Storagemicro SD card slotmicro SD card slot
eMMC module socket
AV OutputHDMI and 3.5 mm AV jackHDMI
Connectivity10/100M EthernetN/A
USB4x USB 2.0 host port +
micro USB port
1x USB 2.0 host port +
micro USB port
1x USB 2.0 host port +
micro USB port
Expansion40-pin header for GPIO
CSI interface
DSI interface
40-pin header for GPIO
CSI interface
Power5V via micro USB port
Power Consumption600 mA to 1.8 A @ 5VTBD but lower150 mA to 1.8 A @ 5V
Dimensions85 x 56 mm65 x 56 mm60 x 36 mm
Price$35$20$30
PMICN/ARicoh RC5T619 includes DCDCs, LDOs, ADCs, RTC, Battery charger and Fuel gauge
RTC powerN/ABackup battery connector (Molex 53398-0271)