Linux : Reading the Mouse events datas from /dev/input/mouse0

A simple program to check the /dev/input/mouse0 datas

Tested on the raspberry PI with GPM installed

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <linux/input.h>

#define MOUSEFILE "/dev/input/mouse0"
//
int main()
{
    int fd;
    struct input_event ie;
    //
    unsigned char button,bLeft,bMiddle,bRight;
    char x,y;
    int absolute_x,absolute_y;

    if((fd = open(MOUSEFILE, O_RDONLY)) == -1) {
        printf("Device open ERROR\n");
        exit(EXIT_FAILURE);
    }
    else
    {
        printf("Device open OK\n");
    }
    //
    printf("right-click to set absolute x,y coordinates origin (0,0)\n");
    while(read(fd, &ie, sizeof(struct input_event)))
    {
        unsigned char *ptr = (unsigned char*)&ie;
        int i;       
        //
        button=ptr[0];
        bLeft = button & 0x1;
        bMiddle = ( button & 0x4 ) > 0;
        bRight = ( button & 0x2 ) > 0;
        x=(char) ptr[1];y=(char) ptr[2];
        printf("bLEFT:%d, bMIDDLE: %d, bRIGHT: %d, rx: %d  ry=%d\n",bLeft,bMiddle,bRight, x,y);
        //
        absolute_x+=x;
        absolute_y-=y;
        if (bRight==1)
        {
            absolute_x=0;
            absolute_y=0;
            printf("Absolute x,y coords origin recorded\n");
        }
        //
        printf("Absolute coords from TOP_LEFT= %i %i\n",absolute_x,absolute_y);
        //
        // comment to disable the display of raw event structure datas
        //
        for(i=0; i<sizeof(ie); i++)
        {
            printf("%02X ", *ptr++);
        }
        printf("\n");
    }

return 0;
}

The read() command is blocking for now.
The following C code does almost the same thing, with non-blocking option enabled this time:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <linux/input.h>

#define MOUSEFILE "/dev/input/mouse0\0"
//
int main()
{
    int fd;
    struct input_event ie;
    unsigned char *ptr = (unsigned char*)&ie;
    //
    unsigned char button,bLeft,bMiddle,bRight;
    char x,y;                                                            // the relX , relY datas
    int absolute_x,absolute_y;

    if((fd = open(MOUSEFILE, O_RDONLY | O_NONBLOCK )) == -1)
    {
        printf("NonBlocking %s open ERROR\n",MOUSEFILE);
        exit(EXIT_FAILURE);
    }
    else
    {
        printf("NonBlocking %s open OK\n",MOUSEFILE);
    }
    //
    printf("--------------------------------------------------------\n");
    printf("right-click to set absolute x,y coordinates origin (0,0)\n");
    printf("left+right click to EXIT\n");
    printf("--------------------------------------------------------\n");
    //
    while(1)
    {       
        if(read(fd, &ie, sizeof(struct input_event))!=-1)
        {
            //
            button=ptr[0];
            bLeft = button & 0x1;
            bMiddle = ( button & 0x4 ) > 0;
            bRight = ( button & 0x2 ) > 0;
            x=(char) ptr[1];y=(char) ptr[2];
            if(bLeft&bRight) { printf("\nright+left ,EXIT\n");break;}
            // computes absolute x,y coordinates
            absolute_x+=x;
            absolute_y-=y;
            // set absolute reference ?
            if (bRight==1)
            {
                absolute_x=0;
                absolute_y=0;
                printf("Absolute x,y coords origin recorded\n");
            }
            // show it!
            printf("X%i Y%i\n",absolute_x,absolute_y);
            fflush(stdout);
        }
    }
    //
    close(fd);
return 0;
}

 

A mouse only sends relative movement, not absolute position. You have to keep track of it yourself, and when you receive a mouse-button event you have to check your own coordinates for the position.

 


I am using this code to read mouse events from the dev/input/event* in linux .

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <linux/input.h>
#include <fcntl.h>

#define MOUSEFILE "/dev/input/event4"

int main()
{
    int fd;
    struct input_event ie;

    if((fd = open(MOUSEFILE, O_RDONLY)) == -1) {
        perror("opening device");
        exit(EXIT_FAILURE);
    }

    while(read(fd, &ie, sizeof(struct input_event))) {
        printf("time %ld.%06ld\ttype %d\tcode %d\tvalue %d\n",
               ie.time.tv_sec, ie.time.tv_usec, ie.type, ie.code, ie.value);

}
    return 0;
}

It gives me the results in the format :

time 1342517261.840285 type 2 code 0 value -1

‘time’ is the timestamp, it returns the time at which the event happened.

‘code’ is event code, for example REL_X or KEY_BACKSPACE, complete list is in include/linux/input.h.

‘value’ is the value the event carries. Either a relative change for EV_REL, absolute new value for EV_ABS (joysticks …), or 0 for EV_KEY for release, 1 for keypress and 2 for autorepeat.

when i click , i get the event but i don’t get the position of the mouse on the screen , what is the way to get the position of the mouse on screen .


Edit 1:So as it turns out that i have to use the relative co-ordinates to get the mouse co-ordinates .I believe this is a common requirement so there might be libraries/pre-existing code that you can use to get the co-ordinates. Any info on this topic will be very useful .


Edit2 : SOLUTION

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <linux/input.h>
#include <fcntl.h>
#include <X11/Xlib.h>

#define MOUSEFILE "/dev/input/event4"

int main()
{
  int fd;
  struct input_event ie;
  Display *dpy;
  Window root, child;
  int rootX, rootY, winX, winY;
  unsigned int mask;

  dpy = XOpenDisplay(NULL);
  XQueryPointer(dpy,DefaultRootWindow(dpy),&root,&child,
              &rootX,&rootY,&winX,&winY,&mask);

  if((fd = open(MOUSEFILE, O_RDONLY)) == -1) {
    perror("opening device");
    exit(EXIT_FAILURE);
  }

  while(read(fd, &ie, sizeof(struct input_event))) {
    if (ie.type == 2) {
      if (ie.code == 0) {
          XQueryPointer(dpy,DefaultRootWindow(dpy),&root,&child,
                        &rootX,&rootY,&winX,&winY,&mask);
          //rootX += ie.value;
          }
      else if (ie.code == 1) {
          XQueryPointer(dpy,DefaultRootWindow(dpy),&root,&child,
                        &rootX,&rootY,&winX,&winY,&mask);
         // rootY += ie.value;
          }
      printf("time%ld.%06ld\tx %d\ty %d\n",
         ie.time.tv_sec, ie.time.tv_usec, rootX, rootY);
    } else
      printf("time %ld.%06ld\ttype %d\tcode %d\tvalue %d\n",
          ie.time.tv_sec, ie.time.tv_usec, ie.type, ie.code, ie.value);
  }
  return 0;
}

you need to compile with X11 lib: gcc main.c -lX11

XQueryPointer seems more convenient solution . Thanks , @perreal for the guidance .

P.S. Never worked for me CK, but keep it for later clue.

Tip: to check the mouse event use following command.

# cat /proc/bus/input/devices | grep mouse
H: Handlers=mouse0 event15

 

Ref.:

http://blog.eihis.com/2014/06/26/linux-reading-the-mouse-events-datas/

 

adb in Android

Overview of adb in Android:

adb

Three Elements of adb:

  • adb clients
    • executable with subcommand
    • ”adb shell”, ”adb logcat” : the end point of host side
  • adb server
    • running on host on back-ground
    • act as proxy between adb clients and adbd
  • adb daemon (adbd)
    • running on target device
    • started by init, if die, restarted by init again

Sequence chart:

adb2

When does adb server start?

  • Explicitly, “adb start-server”
    • It starts adb server as back ground process
  • Usually it does automatically on demand. You don’t have to do “adb start-server”
  • When you want to restart adb server, do “adb kill-server” && “sudo adb start-server
  • Actually, adb clients and adb server shares same executable
    • adb start-server” equals “adb fork-server server &”

 

ADB Source code:

  • system/core/adb in Android source tree
    • From this directory adb and adbd are built
  • common files between adb and adbd
    • adb.c, fdevent.c, transort.c, transport_local.c, tansport_usb.c, service.c, sockets.c, util.c
  • files only for adbd
    • backup_service.c, file_sync_service.c, jdwp_service.c, framebuffer_service.c, remount_services.c, usb_linux_clients.c, log_service.c
  • files only for adb
    • console.c, adb_clients.c, file_sync_client.c, usb_vendors.c, get_my_path_{linux,darwin,windows,freebsd}.c, usb_{linux,macos,libusb,windows}.c

 

USB Vendor ID:

  • When connecting USB device, adb checks USB Vendor ID
  • Many USB Vendor IDs are hard coded in adb. (But not enough)
  • To add USB Vendor ID, make ”$HOME/.android/adb_usb.ini” and write one ID in one line or add rules to the file /etc/udev/rules.d/99-adb.rules

For e.g.:

$ adb devices
List of devices attached 
4df15d6e02a55f15    device
????????????    no permissions

First check with lsusb:

$ lsusb
...
Bus 002 Device 050: ID 04e8:6860 Samsung Electronics Co., Ltd GT-I9100 Phone ...
Bus 002 Device 049: ID 18d1:4e42 Google Inc. 

Checking the permissions on those:

$ ls -l /dev/bus/usb/002/{049,050}
crw-rw-r--  1 root root    189, 176 Oct 10 10:09 /dev/bus/usb/002/049
crw-rw-r--+ 1 root plugdev 189, 177 Oct 10 10:12 /dev/bus/usb/002/050

Where did that “plugdev” group come from?

$ cd /lib/udev/rules.d/
$ grep -R "6860.*plugdev" .
./40-libgphoto2-2.rules:ATTRS{idVendor}=="0bb4", ATTRS{idProduct}=="6860", \
  ENV{ID_GPHOTO2}="1", ENV{GPHOTO2_DRIVER}="proprietary", \
  ENV{ID_MEDIA_PLAYER}="1", MODE="0664", GROUP="plugdev"
./40-libgphoto2-2.rules:ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="6860", \
  ENV{ID_GPHOTO2}="1", ENV{GPHOTO2_DRIVER}="proprietary", \
  ENV{ID_MEDIA_PLAYER}="1", MODE="0664", GROUP="plugdev"

(I’ve wrapped those lines)

Note the GROUP="plugdev" lines. Also note that this doesn’t work for the other device ID:

$ grep -Ri "4e42.*plugdev" .

(nothing is returned)

Create a file /etc/udev/rules.d/99-adb.rules containing the following line:

ATTRS{idVendor}=="18d1", ATTRS{idProduct}=="4e42", ENV{ID_GPHOTO2}="1",
  ENV{GPHOTO2_DRIVER}="proprietary", ENV{ID_MEDIA_PLAYER}="1",
  MODE="0664", GROUP="plugdev"

This should be a single line, I’ve wrapped it here for readability

Restart udev

$ sudo udevadm control --reload-rules
$ sudo service udev restart

That’s it

Unplug/replug your device.

Try it

$ adb devices
List of devices attached 
4df15d6e02a55f15    device
015d2109ce67fa0c    device

 

Switching transport mode: (USB->TCP)

Switching USB mode to TCP mode 

$ adb shell netcfg 

lo UP 127.0.0.1 255.0.0.0 0x00000049 

eth0 UP 192.168.1.139 255.255.255.0 0x00001043 

$ adb tcpip 5555 

restarting in TCP mode port : 5555 

$ adb devices 

List of devices attached 

$

disconnected from USB. Then restart adb server with specifying target IP address.

$ adb kill-server 

$ ADBHOST=192.168.1.139 adb devices 

* daemon not running. starting it now on port 5037 * 

* daemon started successfully * 

List of devices attached 

emulator-5554 device 

$

 

Other Case:

=========================================
# adb devices
List of devices attached
4d00f9169907301b        unauthorized
=========================================
  • Get the public key from the client phone (adb host)

    cat /data/.android/adbkey.pub

  • copy the above public key to the target phone’s /data/misc/adb/adb_keys location. (you may need to stop the adb daemon first with stop adbd)

    cat /data/misc/adb/adb_keys

verify both cat outputs match.

try restarting adb daemon on target start adbd or just reboot them.

If you are having problems reading or writing to ADB KEYS in above steps, try setting environment variable ADB_KEYS_PATH with a temporary path (eg: /data/local/tmp). Refer to that link it goes intomore details

    "On the host, the user public/private key pair is automatically generated,
    if it does not exist, when the adb daemon starts and is stored in
    $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed,
    the ADB_KEYS_PATH env variable may be set to a :-separated (; under
    Windows) list of private keys, e.g. company-wide or vendor keys.

    On the device, vendors public keys are installed at build time in
    /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys"

 

adb from root to user mode:

If you used – “adb root”, you would have got the following message:

$ adb root
* daemon not running. starting it now on port 5037 *
* daemon started successfully *
restarting adbd as root

to get out of the root mode, you can use:

$ adb unroot
restarting adbd as non root

adb kill-server and adb start-server only control the adb daemon on the PC side. You need to restart adbd daemon on the device itself after reverting the service.adb.root property change done by adb root:

~$ adb shell id
uid=2000(shell) gid=2000(shell)

~$ adb root
restarting adbd as root

~$ adb shell id
uid=0(root) gid=0(root)

~$ adb shell 'setprop service.adb.root 0; setprop ctl.restart adbd'

~$ adb shell id
uid=2000(shell) gid=2000(shell)

OR

stop adbd && setprop service.adb.root 0 && start adbd &

This command will stop adbd, then setprop service.adb.root 0 if adbd has been successfully stopped, and finally restart adbd should the .root property have successfully been set to 0. And all this will be done in the background thanks to the last &.

 

 

 Ref.:

https://events.linuxfoundation.org/images/stories/pdf/lf_abs12_kobayashi.pdf

http://stackoverflow.com/questions/14460656/android-debug-bridge-adb-device-no-permissions/19291975#19291975

http://stackoverflow.com/questions/26213954/how-to-solve-adb-device-unauthorized-in-android-adb-host-device

http://stackoverflow.com/questions/15336215/how-to-restart-adb-from-root-to-user-mode

라이브러리 이해하기

유닉스나 리눅스 환경에서 라이브러리는 크게 세가지로 나눌 수 있다.

– 정적 라이브러리
– 공유 라이브러리
– 동적 적재 라이브러리

정적 라이브러리는 .a로 끝나는 파일로 빌드 시 실행 파일에 포함되게 된다. 정적 라이브러리를 사용하는 프로그램을 만들기 위해서는 해당 라이브러리가 extern하는 함수가 선언된 헤더 파일과 해당 라이브러리가 필요하다.

공유 라이브러리는 .so로 끝나는 파일로 빌드 시 실행 파일에 포함되지 않는다. 따라서 여러 프로그램이 공유하는 기능을 공유 라이브러리로 만들 경우 디스크 공간을 아낄수 있고 공유 라이브러리에 버그가 존재할 경우 공유 라이브러리만 재배포하여 문제를 수정할 수 있다. 또한 공유 라이브러리가 이를 사용하는 프로세스에 의해 메모리에 로드되면, 해당 공유 라이브러리를 사용하는 또다른 프로세스가 실행되었을 때 이전 프로세스가 로딩해 놓은 내용을 공유하여 사용하기 때문에 메모리 사용량 또한 절약된다.
공유 라이브러리를 사용하는 프로그램을 만들기 위해서는 해당 라이브러리가 extern하는 함수가 선언된 헤더 파일과 해당 공유 라이브러리가 필요하다. 공유 라이브러리는 실행 파일이 실제로 시스템에서 실행되는 시점에 프로그램 링커 로더가 /lib, /usr/lib, 그리고 LD_LIBRARY_PATH등에서 해당 파일의 존재유무를 확인하고 이를 사용되게 된다. 공유 라이브러리는 앞서 말한바와 같이 링크되는 시점(해당 공유 라이브러리를 사용하는 어플리케이션을 빌드하는 시점)에 공유 라이브러리의 헤더와 라이브러리( .so)파일이 필요하다. 왜 실행파일에 포함되지 않는 라이브러리 파일이 필요한 것인까? 이는 빌드되는 어플리케이션이 실행될 때 찾아야 할 라이브러리의 이름이 공유 라이브러리 파일 안에 적혀있기 때문인데 이를 soname이라고 하고 이 soname은 라이브러리의 파일명하고 다를 수 있으므로 서로 구분하여야 한다. 공유 라이브러리를 컴파일할 때에는 아래와 같이 –fPIC (Position Independent Code)옵션이 필요하다.

gcc –fPIC –c MyLibrary.c
gcc –shared –Wl,-soname libMyLibrary.so.1 –o libMyLibrary.so.1.2.3 MyLibrary.o

동적 적재 라이브러리는 실행 중에 동적으로 로딩되는 라이브러리며, 프로그램 실행시가 아닌 해당 라이브러리에 포함된 함수가 사용되는 시점에 불려와 사용되게 된다. 따라서 동적 라이브러리를 사용하는 프로그램은 첫 실행이 정적 혹은 공유 라이브러리를 사용할 때 보다 빠르다는 장점이 있다. 또한 동적 적재 라이브러리는 실행 시 동적으로 라이브러리에서 직접 정보를 얻어와 실행한다. 따라서 동적 적재 라이브러리를 사용한 어플리케이션을 빌드하는 시점에서는 해당 라이브러리에 대한 헤더 파일이나 심지어 해당 라이브러리 자체도 필요 없다. 리눅스에서는 일반 공유 라이브러리를 동적으로 적재가 가능하므로 공유 라이브러리와 동적 적재 라이브러리가 같다고 할 수 있다. 다만 이를 사용하는 방법으로 구분될 뿐이다. 즉 so파일을 공유 라이브러리도 사용할 수도 동적 적재 라이브러리로 사용할 수도 있으며 동적 적재 라이브러리로 사용하려면 라이브러리를 사용하고자 하는 프로그램에서 dlopen, dlsym등을 사용하여 원하는 심볼을 불러오도록 처리하면 된다.

대부분의 unix/linux 시스템에서 LD_LIBRARY_PATH가 사용 가능하지만 모든 시스템에서 그런 것은 아니다. 리눅스에서는 LD_LIBRARY_PATH 사용이 가능하지만, /etc/ld.so.conf 파일과 ldconfig을 사용하여 /etc/ld.so.cache 파일을 생성하는 방법이 더 권장된다.

또다른 방법으로는 rpath를 지정하는 방법이 있다. rpath는 실행 파일을 compile할때 지정해 주면 된다.

gcc -Wall -o myexefile -Wl,rpath,. main.o -L. -lMyLibrary

위 예제에서는 rpath를 현재 디렉토리 [.]로 설정하였으며 이는 실행할 때 MyLibrary를 찾는 위치에 현재 디렉토리를 추가한 것이다.  -L옵션은 링크시에 MyLibrary를 찾는 위치를 지정하는 옵션으로 역시 [.] 현재 디렉토리로 지정하였다. 굳이 -l 옵션으로 라이브러리를 지정할 필요 없이 경로를 포함한 파일 이름을 사용하여도 된다.

gcc -Wall -o myexefile -Wl,rpath,. main.o ./libMyLibrary.so.1.2.3

 

공유 라이브러리는 보통 아래와 같이 명명된다.

libMyLibrary.so.1.2.3

라이브러리는 용도에 따라 몇가지 서로 다른 이름을 가지고 있는데 혼돈되기 쉬우니 주의가 필요하다.

1. 링커 이름.(linker name)

링커 이름은 라이브러리 파일 명에서 버젼을 나타내는 숫자를 뺀 so까지의 이름이다. 즉 위에서는libMyLibrary.so까지가 linker name이 된다. 링커 이름은 해당 라이브러리를 사용하는 프로그램을 빌드 할 때 사용되는 이름이다. 더 정확히 말하면, 프로그램이 빌드될 때 해당 프로그램이 사용하는 공유 라이브러리를 찾기 위해 링커 이름을 가진 파일이 빌드하는 시스템에 있어야 한다. 예를들어 어떤 어플리케이션이 libMyLibrary.so.1.2.3을 사용하여 컴파일 할 경우 빌드 옵션에 -lMyLibrary를 추가하게 되는데 이때 기본 라이브러리 경로나 혹은 –L 옵션을 사용하여 지정한 디렉토리에 libMyLibrary.so 파일, 즉 링커 이름으로 된 라이브러리 파일이 있어야 한다. (보통은 libMyLibrary.so.1.2.3에 대한 심볼링 링크로 이 파일을 만든다 이렇게 하는 이유는 호스트 개발 환경에 해당 라이브러리의 여러 버젼이 존재할 경우 이를 관리하기 위함이다. ) 크로스 컴파일을 하는 환경에서는 빌드시에만 링커 이름을 가진 파일이 필요하며, 타겟에서 실행 시에는 이 파일이 필요치 않다. 즉 개발하는 호스트 컴퓨터에는 라이브러리 파일 이름이 링커 이름으로 되어 있거나 이를 심볼링 링크로 만들어야 한다. 컴파일러/링커는 링커 이름을 가진 파일에서 이 라이브러리의 soname을 읽어오게 된다. 따라서 공유 라이브러리는 빌드시 실행 파일에 포함되지는 않지만 soname을 읽어와야 하기 때문에 공유 라이브러리가 빌드하는 호스트 시스템에 없으면 빌드가 되지 않는다.

2. soname

이 이름은 로더가 라이브러리를 실행할 때 찾는 이름으로 타겟에는 soname을 가진 파일이 반드시 있어야 한다. 때때로 이 파일은 심볼릭 링크로 다른 파일로 링크되어 있다.

일반적으로 soname은 so뒤에 숫자 하나를 추가하여 만든다.  예를 들어  libMyLibrary.so.1 가 위 라이브러리의 soname으로 적합하다. 아래와 같은 명령으로  soname을 지정할 수 있다.

gcc –shared –Wl,-soname libMyLibrary.so.1 –o libMyLibrary.so.1.2.3 MyLibrary.o

so뒤에 오는 첫번째 숫자는 라이브러리의 Major version number로 일반적으로 호환성이 변경되는 경우에 증가시킨다. 이렇게 라이브러리를 빌드하고 또 이 라이브러리를 사용하는 프로그램을 빌드하면 해당 프로그램 실행 시 로더에 의해서 soname을 가진 파일을 라이브러리 경로에서 찾게 된다. 즉 프로그램이 실행될 때에는 soname을 가진 라이브러리 파일이 필요하다. 크로스 컴파일을 하는 환경에서는 빌드 시에는 soname을 가진 파일이 아닌 링커이름을 가지는 파일(일반적으로 xxx.so로 끝나는 파일)이 필요하고 실행시에는 soname을 가지는 라이브러리(혹은 이에 대한 심볼릭 링크 )가 필요한 것이다.

라이브러리 full name에서 두번째 숫자는 라이브러리의 minor version number로 호환성에는 변경이 없지만 새로운 함수등이 추가되는 경우에 변경되며, 세번째 자리는 release 버전으로 버그 수정 등으로 라이브러리가 새로 릴리즈되는 경우에 변경된다.

따라서 크로스 컴파일 환경에서, 호스트에서 공유 라이브러리 libMyLibrary.so.1.2.3 를 만들어 타겟 시스템에 넣을 경우 타켓 시스템에는 아래와 같이 soft link file을 만들어 soname을 가진 파일을 만들어야 한다.

ln –s libMyLibrary.so.1.2.3 libMyLibrary.so.1
or
mv libMyLibrary.so.1.2.3 libMyLibrary.so.1

또한 해당 라이브러리를 사용하여 프로그램을 만드는 모든 개발자는 자신의 빌드 환경에 아래와 같이 공유 라이브러리가 링커 이름을 가지도록 설정하여야 한다. (즉 .so.1 파일은 호스트(빌드)시스템에서는 필요 없다)

ln –s libMyLibrary.so.1.2.3 libMyLibrary.so
or
mv libMyLibrary.so.1.2.3 libMyLibrary.so

특정 라이브러리의 soname을 확인하기 위해서는 아래와 같은 명령을 사용할 수 있다.

objdump -p libMyLibrary.so.1.2.3 | grep SONAME

더 자세한 내용은…
http://wiki.kldp.org/wiki.php/DocbookSgml/Program-Library-HOWTO#DL-LIBRARIES

 

 

 

 

 

Ref.:

http://dooeui.blogspot.kr/search?updated-max=2009-06-07T08:26:00%2B09:00&max-results=10&start=30&by-date=false

 

 

 

 

How to Daemonize in Linux

One of the things I keep running across is Linux daemons that don’t properly daemonize themselves. To properly daemonize, the following steps must be followed.

  • The fork() call is used to create a separate process.
  • The setsid() call is used to detach the process from the parent (normally a shell).
  • The file mask should be reset.
  • The current directory should be changed to something benign.
  • The standard files (stdin,stdout and stderr) need to be reopened.

Failure to do any of these steps will lead to a daemon process that can misbehave. The typical symptoms are as follows.

  • Starting the daemon and then logging out will cause the terminal to hang. This is particularly nasty with ssh.
  • The directory from which the daemon was launched remains locked.
  • Spurious output appears in the shell from which the daemon was started.

Simple Example

The following example program performs the bare minimum steps required to launch a daemon process.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1

static void daemonize(void)
{
    pid_t pid, sid;

    /* already a daemon */
    if ( getppid() == 1 ) return;

    /* Fork off the parent process */
    pid = fork();
    if (pid < 0) {
        exit(EXIT_FAILURE);
    }
    /* If we got a good PID, then we can exit the parent process. */
    if (pid > 0) {
        exit(EXIT_SUCCESS);
    }

    /* At this point we are executing as the child process */

    /* Change the file mode mask */
    umask(0);

    /* Create a new SID for the child process */
    sid = setsid();
    if (sid < 0) {
        exit(EXIT_FAILURE);
    }

    /* Change the current working directory.  This prevents the current
       directory from being locked; hence not being able to remove it. */
    if ((chdir("/")) < 0) {
        exit(EXIT_FAILURE);
    }

    /* Redirect standard files to /dev/null */
    freopen( "/dev/null", "r", stdin);
    freopen( "/dev/null", "w", stdout);
    freopen( "/dev/null", "w", stderr);
}

int main( int argc, char *argv[] ) {
    daemonize();

    /* Now we are a daemon -- do the work for which we were paid */


    return 0;
}
It has been brought to my attention that a second call to fork() may be required to fully detach the process from the controller terminal (in other words: fork, setsid, fork). This does not seem to be required in Linux. A second fork would not cause any problems, although it would complicate the child/parent signalling below.

A More Useful Example

The following program extends the basic daemon by adding the following features.

  • Logs messages to the system log (via syslog).
  • Creates a lock file to prevent the daemon from being run twice.
  • Changes the effective user (drops privileges).
  • Startup errors are reported to the main process.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <syslog.h>
#include <errno.h>
#include <pwd.h>
#include <signal.h>

/* Change this to whatever your daemon is called */
#define DAEMON_NAME "mydaemon"

/* Change this to the user under which to run */
#define RUN_AS_USER "daemon"

#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1


static void child_handler(int signum)
{
    switch(signum) {
    case SIGALRM: exit(EXIT_FAILURE); break;
    case SIGUSR1: exit(EXIT_SUCCESS); break;
    case SIGCHLD: exit(EXIT_FAILURE); break;
    }
}

static void daemonize( const char *lockfile )
{
    pid_t pid, sid, parent;
    int lfp = -1;

    /* already a daemon */
    if ( getppid() == 1 ) return;

    /* Create the lock file as the current user */
    if ( lockfile && lockfile[0] ) {
        lfp = open(lockfile,O_RDWR|O_CREAT,0640);
        if ( lfp < 0 ) {
            syslog( LOG_ERR, "unable to create lock file %s, code=%d (%s)",
                    lockfile, errno, strerror(errno) );
            exit(EXIT_FAILURE);
        }
    }

    /* Drop user if there is one, and we were run as root */
    if ( getuid() == 0 || geteuid() == 0 ) {
        struct passwd *pw = getpwnam(RUN_AS_USER);
        if ( pw ) {
            syslog( LOG_NOTICE, "setting user to " RUN_AS_USER );
            setuid( pw->pw_uid );
        }
    }

    /* Trap signals that we expect to recieve */
    signal(SIGCHLD,child_handler);
    signal(SIGUSR1,child_handler);
    signal(SIGALRM,child_handler);

    /* Fork off the parent process */
    pid = fork();
    if (pid < 0) {
        syslog( LOG_ERR, "unable to fork daemon, code=%d (%s)",
                errno, strerror(errno) );
        exit(EXIT_FAILURE);
    }
    /* If we got a good PID, then we can exit the parent process. */
    if (pid > 0) {

        /* Wait for confirmation from the child via SIGTERM or SIGCHLD, or
           for two seconds to elapse (SIGALRM).  pause() should not return. */
        alarm(2);
        pause();

        exit(EXIT_FAILURE);
    }

    /* At this point we are executing as the child process */
    parent = getppid();

    /* Cancel certain signals */
    signal(SIGCHLD,SIG_DFL); /* A child process dies */
    signal(SIGTSTP,SIG_IGN); /* Various TTY signals */
    signal(SIGTTOU,SIG_IGN);
    signal(SIGTTIN,SIG_IGN);
    signal(SIGHUP, SIG_IGN); /* Ignore hangup signal */
    signal(SIGTERM,SIG_DFL); /* Die on SIGTERM */

    /* Change the file mode mask */
    umask(0);

    /* Create a new SID for the child process */
    sid = setsid();
    if (sid < 0) {
        syslog( LOG_ERR, "unable to create a new session, code %d (%s)",
                errno, strerror(errno) );
        exit(EXIT_FAILURE);
    }

    /* Change the current working directory.  This prevents the current
       directory from being locked; hence not being able to remove it. */
    if ((chdir("/")) < 0) {
        syslog( LOG_ERR, "unable to change directory to %s, code %d (%s)",
                "/", errno, strerror(errno) );
        exit(EXIT_FAILURE);
    }

    /* Redirect standard files to /dev/null */
    freopen( "/dev/null", "r", stdin);
    freopen( "/dev/null", "w", stdout);
    freopen( "/dev/null", "w", stderr);

    /* Tell the parent process that we are A-okay */
    kill( parent, SIGUSR1 );
}

int main( int argc, char *argv[] ) {
    /* Initialize the logging interface */
    openlog( DAEMON_NAME, LOG_PID, LOG_LOCAL5 );
    syslog( LOG_INFO, "starting" );

    /* One may wish to process command line arguments here */

    /* Daemonize */
    daemonize( "/var/lock/subsys/" DAEMON_NAME );

    /* Now we are a daemon -- do the work for which we were paid */


    /* Finish up */
    syslog( LOG_NOTICE, "terminated" );
    closelog();
    return 0;
}

Android Boot Process

Mainly there are 6 partitions in Android phones, tablets and any other Android devices. Below is the list of partition for Android File System.

  • /boot
  • /system
  • /recovery
  • /data
  • /cache
  • /misc

Note from author: There might be some other partitions available & may also differs from Model to Model. But baseline partitions mention above do not change in any Android devices.

 

Note to User(s):Boot.img, System.img, & recovery.img are all flashable partitions with a unlocked boot loader.

For SD Card Fie System Partitions.

  • /sdcard
  • /sd-ext

Note to User(s):Only /sdcard partition can be found in all Android devices and SD-Ext is present only in select devices.

Now that we know the partitions avalable of our device, we can see what can be changed or wiped or erased. To illustrate: Wiping stock recovery and install TWRP recovery means just changing the recovery partition is all.

Now Let us start with the brief intro for each partition. I would be dwelling much on each of these but just brief intro to each for wider audience.

/boot

Boot partition of your Android device, as the name suggests. It includes the android kernel and the ramdisk.  The device will not boot without this partition. Wiping this partition from recovery should only be done if absolutely required and once done, the device must NOT be rebooted before installing a new one, which can be done by installing a ROM that includes a /boot partition.

/system

As the name suggests, this partition contains the entire Android OS, other than the kernel and the ramdisk. This includes the Android GUI and all the system applications that come pre-installed on the device. Wiping this partition will remove Android from the device without rendering it unbootable, and you will still be able to put the phone into recovery or bootloader mode to install a new ROM.

/recovery

This is specially designed for backup. The recovery partition can be considered as an alternative boot partition, that lets the device boot into a recovery console for performing advanced recovery and maintenance operations on it.

/data

As the name suggest, it is userdata partition. This partition contains the user’s data like your contacts, sms, settings and all android applications that you have installed. While you are doing factory reset on your device, this partition will wipe out, Then your device will be in the state, when you use for he first time, or the way it was after the last official or custom ROM installation.

/cache

I hope you have some idea about cache, as you are expert on internet browsing. This is the partition where Android stores frequently accessed data and app components. Wiping the cache doesn’t effect your personal data but simply gets rid of the existing data there, which gets automatically rebuilt as you continue using the device.

/misc

This partition contains miscellaneous system settings in form of on/off switches. These settings may include CID (Carrier or Region ID), USB configuration and certain hardware settings etc. This is an important partition and if it is corrupt or missing, several of the device’s features will will not function normally.

Android device execute following steps when you press power switch

Android Boot Sequence / Process

Step 1 : Power On and System Startup

When power start Boot ROM code start execution from pre defined location which is hardwired on ROM. It load Bootloader into RAM and start execution

Step 2 : Bootloader

Bootloader is small program which runs before Android operating system running. Bootloader is first program to run so It is specific for board and processor. Device manufacturer either use popular bootloaders like redboot,uboot, qi bootloader or they develop own bootloaders, It’s not part of Android Operating System. bootloader is the place where OEMs and Carriers put there locks and restrictions.

Bootloader perform execution in two stages, first stage It to detect external RAM and load program which helps in second stage, In second stage bootloader setup network, memory, etc. which requires to run kernel, bootloader is able to provide configuration parameters or inputs to the kernel for specific purpose.

Android bootloader can be found at

<Android Source>\bootable\bootloader\legacy\usbloaderlegacy loader contain two important files that need to address here.

  • init.s – Initializes stacks, zeros the BSS segments, call _main() in main.c
  • main.c – Initializes hardware (clocks, board, keypad, console), creates Linux tags

If you are interested in more info, you can refer to Android 101: What Is A Bootloader?

Step 3: Kernel

Android kernel start similar way as desktop linux kernel starts, as kernel launch it start setup cache, protected memory, scheduling, loads drivers. When kernel finish system setup first thing it look for “init” in system files and launch root process or first process of system.

Step 4: init process

init it very first process, we can say it is root process or BOSS of all processes. init process has two responsibilities

  • mount directories like /sys, /dev, /proc
  • run init.rc script.

init process can be found at init : <android source>/system/core/init
init.rc file can be found in source tree at <android source>/system/core/rootdir/init.rc
readme.txt file can be found in source tree at <andorid source>/system/core/init/readme.txt

Android has specific format and rules for init.rc files. In Android we call it as “Android Init Language

The Android Init Language consists of four broad classes of statements,which are Actions, Commands, Services, and Options.
Action : Actions are named sequences of commands.  Actions have a trigger which is used to determine when the action should occur.
Syntax
on <trigger>
<command>
<command>
<command>

Service :  Services are programs which init launches and (optionally) restarts when they exit.  Syntax
service <name> <pathname> [ <argument> ]*
<option>
<option>

Options : Options are modifiers to services.  They affect how and when init runs the service.

Looking @ default init.rc file; listed are some major events and services.

Action  / Service
Description
on  early-init
Set  init and its forked children’s oom_adj.
Set  the security context for the init process.
on  init
setup  the global environment
Create  cgroup mount point for cpu accounting
and  many
on  fs
mount  mtd partitions
on  post-fs
change  permissions of system directories
on  post-fs-data
change  permission of /data folders and sub folders
on  boot
basic  network init ,Memory Management ,etc
service  servicemanager
start  system manager to manage all native services like location, audio, shared  preference etc..
service  zygote
start  zygote as app_process

At this stage you can see “Android/OEM” logo on device screen.

Step 5: Zygote and Dalvik

In a Java, We know that separate Virtual Machine(VMs) instance will popup in memory for separate per app, In case of Android app should launch as quick as possible, If Android os launch different instance of Dalvik VM for every app then it consume lots of memory and time. so, to overcome this problem Android OS as system named “Zygote”. Zygote enable shared code across Dalvik VM, lower memory footprint and minimal startup time. Zygote is a VM process that starts at system boot time as we know in previous step. Zygote preloads and initialize core library classes.  Normally there core classes are read-only and part of Android SDK or Core frameworks. In Java VM each instance has it’s own copy of core library class files and heap objects.

Zygote loading process

Source Code :<Android Source> /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

  • registerZygoteSocket() –  Registers a server socket for zygote command connections
  • preloadClasses() – “preloaded-classes” is simple text file contains list of classes that need to be preloaded, you cna find “preloaded-classes” file at <Android Source>/frameworks/base
  • preloadResources() – preloadReaources means native themes and layouts, everything that include android.R file will be load using this method.

At this time you can see bootanimation

Step 6: System  Service or Services

After complete above steps, runtime request Zygote to launch system servers. System Servers are written in native and java both, System servers we can consider as process, The same system server is available as System Services in Android SDK. System server contain all system services.

Zygote fork new process to launch system services. You can find source code in ZygoteInit class and “startSystemServer” method.

Core Services which gets started along with the boot process

  • Starting Power Manager
  • Creating Activity Manager
  • Starting Telephony Registry
  • Starting Package Manager
  • Set Activity Manager Service as System Process
  • Starting Context Manager
  • Starting System Context Providers
  • Starting Battery Service
  • Starting Alarm Manager
  • Starting Sensor Service
  • Starting Window Manager
  • Starting Bluetooth Service
  • Starting Mount Service

Other services after booting process are

  • Starting Status Bar Service
  • Starting Hardware Service
  • Starting NetStat Service
  • Starting Connectivity Service
  • Starting Notification Manager
  • Starting DeviceStorageMonitor Service
  • Starting Location Manager
  • Starting Search Service
  • Starting Clipboard Service
  • Starting Checkin Service
  • Starting Wallpaper Service
  • Starting Audio Service
  • Starting HeadsetObserver
  • Starting AdbSettingsObserver

Step 7 : Boot Completed

Once System Services up and running in memory, Android has completed booting process, At this time “ACTION_BOOT_COMPLETED” standard broadcast action will fire.
You Smart Phone is now at your disposal.

 

Ref.:

https://community.nxp.com/docs/DOC-102546

http://en.miui.com/thread-15659-1-1.html

Android – create custom SeekBar

Custom red_scrubber_control.xml (add to res/drawable):

<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/red_scrubber_control_disabled_holo" android:state_enabled="false"/>
    <item android:drawable="@drawable/red_scrubber_control_pressed_holo" android:state_pressed="true"/>
    <item android:drawable="@drawable/red_scrubber_control_focused_holo" android:state_selected="true"/>
    <item android:drawable="@drawable/red_scrubber_control_normal_holo"/>
</selector>

Custom: red_scrubber_progress.xml

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >

    <item
        android:id="@android:id/background"
        android:drawable="@drawable/red_scrubber_track_holo_light"/>
    <item android:id="@android:id/secondaryProgress">
        <scale
            android:drawable="@drawable/red_scrubber_secondary_holo"
            android:scaleWidth="100%" />
    </item>
    <item android:id="@android:id/progress">
        <scale
            android:drawable="@drawable/red_scrubber_primary_holo"
            android:scaleWidth="100%" />
    </item>

</layer-list>

Then copy required drawables from Android source code, I took from this link

It is good to copy these drawables for each hdpi, mdpi, xhdpi. For example I use only mdpi:

Then using Photoshop change color from blue to red:

red_scrubber_control_disabled_holo.png: red_scrubber_control_disabled_holo

red_scrubber_control_focused_holo.png: red_scrubber_control_focused_holo

red_scrubber_control_normal_holo.png: red_scrubber_control_normal_holo

red_scrubber_control_pressed_holo.png: red_scrubber_control_pressed_holo

red_scrubber_primary_holo.9.png: red_scrubber_primary_holo.9

red_scrubber_secondary_holo.9.png: red_scrubber_secondary_holo.9

red_scrubber_track_holo_light.9.png: red_scrubber_track_holo_light.9

Add SeekBar to layout:

<SeekBar
    android:id="@+id/seekBar1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:progressDrawable="@drawable/red_scrubber_progress"
    android:thumb="@drawable/red_scrubber_control" />

Result:

enter image description here

Edited:

Here is nice resource Android Holo Colors Generator that will help to create elements with different colors much faster. Just select color and element and it will create required drawable for xhdpi, hdpi and mdpi.

 

 

1. To add the transparent feature for the Thumb of the SeekBar, you need to add following property:

When API level 21 is selected

When API level 19 is selected

<SeekBar
    ....
    android:splitTrack="false" 
/>

 

2. When using a custom thumb drawable with a SeekBar view, the thumb drawable is clipped at the left and right edges of the view.

You should be able to fix this by setting paddingLeft and paddingRight on your SeekBar to half the thumb width (remember to use density-independent units). You can also control the space allowed at the edges for a seek bar’s thumb by calling setThumbOffset.

 

3. To adjust the height of the SeekBar, add following two features to the red_scrubber_progress.xml:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >

    <item
        android:id="@android:id/background"
        android:height="4dp"
        android:gravity="center_vertical"
        android:drawable="@drawable/carpet_bar_bg_dim"/>

    <item
        android:id="@android:id/progress"
        android:height="4dp"
        android:gravity="center_vertical">
        <scale
            android:drawable="@drawable/carpet_bar_bg_dim_full"
            android:scaleWidth="100%"/>
    </item>

</layer-list>

 

 

 

 

Ref.:

http://stackoverflow.com/questions/16163215/android-styling-seek-bar

How to extract kernel configuration from android kernel or boot.img and build related kernel for the device

To build a new kernel for specified device, you need to make a configuration:

For example, all of configuration fiiles: KCONFIG will be placed at related folders.

When you type the command:

make def_config

or

make menuconfig

to configure the kernel.

Afterall, all the configuration will be written to the one file “.config” at <kernel_source_dir>

 

So if you wanna build a specified kernel for specified device, the simpliest way to get the kernel configuration is to extract it from the original kernel.

Usually, you will not be able to download the kernel image itself.

but it’s easy to get the boot.img which is consisted with kernel and ramdisk images.

 

After you get the boot.img

Decompress it:

$ unmkbootimg -i boot.img
kernel written to ‘kernel‘ (6682776 bytes)
ramdisk written to ‘ramdisk.cpio.gz’ (913311 bytes)

To rebuild this boot image, you can use the command:
mkbootimg –base 0 –pagesize 2048 –kernel_offset 0x80208000 –ramdisk_offset 0x82200000 –second_offset 0x81100000 –tags_offset 0x80200100 –cmdline ‘console=ttyHSL0,115200,n8 androidboot.hardware=flo user_debug=31 msm_rtb.filter=0x3F ehci-hcd.park=3 vmalloc=340M’ –kernel kernel –ramdisk ramdisk.cpio.gz -o boot.img

You will have kernel and ramdisk in your current folder.

 

Then you need a script named extract-ikconfig

you can download it from following link:

https://github.com/torvalds/linux/blob/master/scripts/extract-ikconfig

$ chmod +x extract-ikconfig

$ extract-ikconfig kernel > kernel_config

 

then you can put the kernel_config to the <kernel_source_dir> renaming it with “.config” and compile the kernel for the device.

 

For detailed steps of compiling the kernel, remaking the boot.img and flash to the device, you can follow my previous articles.

 

^___________________^