Posting Source Code in WordPress

Posting Source Code

While WordPress.com doesn’t allow you to use potentially dangerous code on your blog, there is a way to post source code for viewing. We have created a shortcode you can wrap around source code that preserves its formatting and even provides syntax highlighting for certain languages, like so:

1
2
3
4
#button {
    font-weight: bold;
    border: 2pxsolid#fff;
}

To accomplish the above, just wrap your code in these tags:

your code here

The language (or lang) parameter controls how the code is syntax highlighted. The following languages are supported:

  • actionscript3
  • bash
  • clojure
  • coldfusion
  • cpp
  • csharp
  • css
  • delphi
  • diff
  • erlang
  • fsharp
  • go
  • groovy
  • html
  • java
  • javafx
  • javascript
  • latex (you can also render LaTeX)
  • matlab (keywords only)
  • objc
  • perl
  • php
  • powershell
  • python
  • r
  • ruby
  • scala
  • sql
  • text
  • vb
  • xml

If the language parameter is not set, it will default to “text” (no syntax highlighting).

Code in between the source code tags will automatically be encoded for display, you don’t need to worry about HTML entities or anything.

Configuration Parameters

The shortcodes also accept a variety of configuration parameters that you may use to customize the output. All are completely optional.

  • autolinks (true/false) — Makes all URLs in your posted code clickable. Defaults to true.
  • collapse (true/false) — If true, the code box will be collapsed when the page loads, requiring the visitor to click to expand it. Good for large code posts. Defaults to false.
  • firstline (number) — Use this to change what number the line numbering starts at. It defaults to 1.
  • gutter (true/false) — If false, the line numbering on the left side will be hidden. Defaults to true.
  • highlight (comma-seperated list of numbers) — You can list the line numbers you want to be highlighted. For example “4,7,19”.
  • htmlscript (true/false) — If true, any HTML/XML in your code will be highlighted. This is useful when you are mixing code into HTML, such as PHP inside of HTML. Defaults to false and will only work with certain code languages.
  • light (true/false) — If true, the gutter (line numbering) and margin (see below) will be hidden. This is helpful when posting only one or two lines of code. Defaults to false.
  • padlinenumbers (true/false/integer) — Allows you to control the line number padding. true will result in automatic padding, false will result in no padding, and entering a number will force a specific amount of padding.
  • title (string) — Set a label for your code block. Can be useful when combined with the collapseparameter.

 

Ref.:

https://en.support.wordpress.com/code/posting-source-code/#toc

Advertisements

cross-compile node.js for QNX

I was able to cross-compile the node-0-10-ver from this link.

FYI. my build-script was abit differ from the original one as follow:


#!/bin/bash#!/bin/bash
if [ ! -d "${QNX_HOST}" ]; then  echo "QNX_HOST must be set to the path of the QNX host toolchain."  exit 1fi
if [ ! -d "${QNX_TARGET}" ]; then  echo "QNX_TARGET must be set to the path of the QNX target toolchain."  exit 1fi
if [ "${QCONF_OVERRIDE}" != "" ]; then  cp -p $QCONF_OVERRIDE /tmp/owbqsk$$.mk  echo "all:" >>/tmp/owbqsk$$.mk  echo ' echo $(INSTALL_ROOT_nto)' >>/tmp/owbqsk$$.mk  STAGE_DIR=`make -s -f /tmp/owbqsk$$.mk`  rm /tmp/owbqsk$$.mkfi
if [ "${STAGE_DIR}" == "" ]; then  echo Staging directory could not be determined. Using NDK.else  echo Using staging directory: ${STAGE_DIR}fi
if [ "${1}" == "clean" ]; then  make -f Makefile clean  exit 1fi

echo Building for aarch64 #CPU="aarch64"CPU="arm"CPUDIR="${CPU}le-v7"CPUTYPE="${CPU}v7le"BUSUFFIX="${CPU}v7"CPU_VER="cortex-a9"#CPU_CFLAGS="-mtune=${CPU_VER} -mfpu=vfpv3"CPU_CFLAGS="-mtune=${CPU_VER} -mfpu=vfpv3-d16"

QNX_TOOL_DIR="${QNX_HOST}/usr/bin"QNX_COMPILER="${QNX_TOOL_DIR}/ntoarmv7-gcc"QNX_COMPILER="${QNX_TOOL_DIR}/qcc"QNX_TOOL_PREFIX="${QNX_TOOL_DIR}/nto${BUSUFFIX}"
if [ "${STAGE_DIR}" == "" ]; then   QNX_LIB="${QNX_TARGET}/${CPUDIR}/lib"  QNX_USR_LIB="${QNX_TARGET}/${CPUDIR}/usr/lib"  QNX_INC="${QNX_TARGET}/usr/include"else  QNX_LIB="${STAGE_DIR}/${CPUDIR}/lib"  QNX_USR_LIB="${STAGE_DIR}/${CPUDIR}/usr/lib"  QNX_INC="${STAGE_DIR}/usr/include"fi
COMP_PATHS=" \  -Wl,-rpath-link,${QNX_LIB} \  -Wl,-rpath-link,${QNX_USR_LIB} \  -L${QNX_LIB} \  -L${QNX_USR_LIB} \  -I${QNX_INC}"
export CC="${QNX_COMPILER}"export CFLAGS="-V5.4.0,gcc_ntoarmv7le -g -Wformat -Wformat-security -Werror=format-security -Wl,-z,relro -fPIE -pie ${COMP_PATHS} ${CPU_CFLAGS}"#export CFLAGS="-V5.4.0,gcc_ntoarmv7le -g -Wformat -Wformat-security -Werror=format-security -Wl,-z,relro -fPIE -pie -D__QNXNTO__ ${COMP_PATHS} ${CPU_CFLAGS}"#export CFLAGS="-V5.4.0,gcc_ntoaarch64le -g -Wformat -Wformat-security -Werror=format-security -Wl,-z,relro -fPIE -pie ${COMP_PATHS} ${CPU_CFLAGS}"#export CFLAGS="-Vgcc_nto${CPUTYPE} -Wformat -Wformat-security -Werror=format-security -Wl,-z,relro -fPIE -pie ${COMP_PATHS} ${CPU_CFLAGS}"#export CFLAGS="-Vgcc_nto${CPUTYPE} -g -Wformat -Wformat-security -Werror=format-security -Wl,-z,relro -fPIE -pie ${COMP_PATHS} ${CPU_CFLAGS}"#export CFLAGS="-Vgcc_nto${CPUTYPE} -g -Wformat -Wformat-security -Werror=format-security -Wl,-z,relro -fPIE -D__QNXNTO65__ ${COMP_PATHS} ${CPU_CFLAGS}" for QNX650export CXX="${QNX_COMPILER}"#export CXXFLAGS="-Vgcc_nto${CPUTYPE}_cpp-ne -g -lang-c++ -Wformat -Wformat-security -Werror=format-security -Wl,-z,relro -fPIE -pie ${COMP_PATHS} ${CPU_CFLAGS}"#export CXXFLAGS="-Vgcc_nto${CPUTYPE}_cpp-ne -g -lang-c++ -Wformat -Wformat-security -Werror=format-security -Wl,-z,relro -fPIE -Wl,--export-dynamic ${COMP_PATHS} ${CPU_CFLAGS}"#export CXXFLAGS="-Vgcc_nto${CPUTYPE}_cpp-ne -lang-c++ -Wformat -Wformat-security -Werror=format-security -Wl,-z,relro -fPIE -Wl,--export-dynamic ${COMP_PATHS} ${CPU_CFLAGS}"#export CXXFLAGS="-V5.4.0,gcc_ntoaarch64le -g -lang-c++ -Wformat -Wformat-security -Werror=format-security -Wl,-z,relro -fPIE -Wl,--export-dynamic ${COMP_PATHS} ${CPU_CFLAGS}"export CXXFLAGS="-V5.4.0,gcc_ntoarmv7le -g -lang-c++ -Wformat -Wformat-security -Werror=format-security -Wl,-z,relro -fPIE -Wl,--export-dynamic ${COMP_PATHS} ${CPU_CFLAGS}"export AR="${QNX_TOOL_PREFIX}-ar"export LINK="${QNX_COMPILER}"export LDFLAGS="${CXXFLAGS} -lcrypto -lssl"export RANLIB="${QNX_TOOL_PREFIX}-ranlib"
export __QNXNTO=1
# The set of GYP_DEFINES to pass to gyp.export GYP_DEFINES="OS=qnx want_separate_host_toolset=0"#export GYP_GENERATORS="make-linux"
CONFIGURE_OPTIONS=""

CONFIGURE_OPTIONS="--dest-cpu=arm --dest-os=qnx --with-arm-float-abi=softfp --without-snapshot --without-dtrace"
./configure --shared-openssl --shared-zlib ${CONFIGURE_OPTIONS}
if [ "${1}" == "test" ]; then  make testelse  make -j4fi

 

Anyway I couldn’t to make it run on aarch64 since I’m running out of time.

 

 

 

Ref.:

http://blog.hemnik.com/2014/06/nodejs-for-qnx-source-code.html

http://fastr.github.io/articles/cross-compiling-node.js-for-arm.html

Streaming media on Web

Conventional video playback (also known as Progressive) involves a single video file at a single quality that is transferred as it is being played. If the user’s playback has caught up to how much of the video has been downloaded, the player pauses and buffers. YouTube subscribes to this method of playback but offers different quality levels that you manually select. You only watch a single quality unless you manually switch it.

With adaptive media streaming, a high quality base video source (often called a Mezzanine) is converted into a set of video files of varying qualities. This process is known as encoding. For example, you can take a mezzanine file and encode low, medium, high, and ultra quality versions of a video. These encoded files are then stored for distribution on a Server or Content Delivery Network (CDN).

When the user attempts to play a video adaptively, they are given a Manifest file that lists information for all these different video qualities. Adaptive streaming technologies then alternate between the different qualities (bitrates) depending on a user’s varying connection while playing the video in order to ensure that buffering is minimized. In order to start playback as soon as possible, adaptive streaming technologies usually begin playback at the lowest quality and then scale upwards after a few seconds. You may have noticed this happening when you start watching a movie or episode on NetFlix.

A video player (often referred to as a Client) that supports an adaptive media streaming technology will handle this process of switching between qualities automatically without a user’s involvement.

AMS&Progressive

What are some adaptive streaming technologies?

The two biggest smooth streaming technologies I’ve worked with in my time at Digiflare are Apple’s HTTP Live Streaming (HLS) and Microsoft’s Smooth Streaming (MSS) technologies. These technologies differ in terms of the video and audio formats they support as well as how they go about delivering the video content optimally.

Streaming – What does HLS, HDS and MPEG-DASH mean?

These are all ‘chunked HTTP’ streaming protocols. These work by breaking the content in small (a few seconds) chunks that can be delivered as separate files rather than a constant stream of content.  The advantage of this method is that it allows the client to make use of the ‘bursty’ nature of the internet and does not rely on a constant bandwidth being available.

Apple’s HTTP Live Streaming (HLS)

HLS stands for HTTP Live Streaming and was developed by Apple to serve its iOS and MAC OS devices.  It is also widely available for other devices notably Android.  Apple made the specification public by publishing it as a draft IEEE RFC. HLS usually makes use of MPEG -2 transport stream technology which carries a separate licensing cost which deters some manufacturers from implementing it in their devices.  It is a simple protocol that is quite easy to implement.

Summary:

  • Manifest: M3U8 playlist
  • Video: H.264
  • Audio: MP3 or HE-AAC
  • Container: MPEG-2
  • Server: No special server software

Microsoft’s Smooth Streaming (MSS)

Microsoft’s Smooth Streaming technology also involves encoding a mezzanine into various quality levels but MSS supports slightly different formats in the encoding process. Video can be encoded using H.264 or VC-1 and audio is encoded to AAC or WMA. The encoded quality level video is wrapped in an MP4 container with a *.ismv or *.isma file extension.

During the encoding process, XML manifest files are also generated. An *.ism file is generated for use by the server in describing the available bitrates while a *.ismc file is used by the client to inform it of available bit rates and other information required in presenting the content. One such piece of information is the chunk duration.

Unlike HLS, Microsoft’s Smooth Streaming doesn’t encode the individual qualities into a series of chunks. Instead, the server cuts the full content into chunks as it’s being delivered. This requires a specially set up server using Microsoft’s Internet Information Services (IIS).

For more information regarding the setup of IIS Servers and MSS manifest formatting see Microsoft’s guide on Getting Started with IIS Smooth Streaming and Smooth Streaming Deployment guides.

Summary:

  • Manifest: XML file with *.ism/ismc file extension
  • Video: VC-1 or H.264
  • Audio: AAC or WMA
  • Container: MP4 (with *.ismv/isma file extension)
  • Server: IIS (Internet Information Services) server
  • Additional: Only quality files are stored but server virtually splits them up into chunks at playback

HDS

HDS stands for HTTP Dynamic Streaming and was developed by Adobe to serve its Flash platform.  The BBC uses this protocol for its desktop browser presentations using the BBC Standard Media Player (SMP) which implements the Flash playback client.  Adobe has published the HDS protocol to register developers.  It is a more complex protocol and is harder than HLS to implement.

MPEG Dynamic Adaptive Streaming over HTTP (DASH)

MPEG-DASH stands for Motion Pictures Expert Group Dynamic Adaptive Streaming over HTTP.  This is a new completely open source protocol that is just starting to be adopted by content producers and client implementations.  It has the simplicity of HLS whilst being free of additional licencing other than that required by the codecs.

Unlike, HLS, HDS and Smooth Streaming, DASH is codec-agnostic.
DASH is audio/video codec agnostic. One or more representations (i.e., versions at different resolutions or bit rates) of multimedia files are typically available, and selection can be made based on network conditions, device capabilities and user preferences, enabling adaptive bitrate streaming[10] and QoE (Quality of Experience) fairness.

Summary:

  • Manifest: Media Presentation Description (MPD)
  • Video: Codec agnostic
  • Audio: Codec agnostic
  • Container MP4 or MPEG-2

MPEG DASH is the result of a collaborative effort from some of the biggest players (ie. Adobe, Apple, and Microsoft) of adaptive bitrate streaming. From a bird’s eye view it functions similarly to the technologies previously described, but differs in the details of its delivery to end users.

In DASH, the entirety of an available stream, made up of a media portion and a metadata manifest, is known as a Media Presentation. The manifest portion of this is called a Media Presentation Description (MPD). Much like an M3U8 or Smooth Streaming manifest, an MPD contains metadata for the media available.

The media portion of a presentation is made up of different quality levels of the same media. Each quality level is known as a Period. A period is a set of time-aligned contents (audio, video, captions, etc.) which form one entire viewing of the content at a single quality level. Each period consists of a collection of different media forms, each known as an Adaptation. So a period may consist of a separate video adaptation and audio adaptation. Each encoding of a particular adaptation is known as a Representation. Each representation is split into short chunks, dubbed segments. Using the terminology at hand, the entire stream consists of a set of periods where each period will typically contain a representation of each type of adaptation being delivered to a user in the presentation. Adaptive playback is facilitated appropriate quality as segments are downloaded as playback is taking place and connection speed is being monitored.

As confusing as that may have been to sort out, there is a significant theoretical advantage to this approach of different adaptations to build up a period versus the approaches previously described for MSS and HLS. This advantage is the codec agnostic nature of DASH. The media is served in either an MP4 or MPEG-2 container using whatever video and audio formats and the onus is put on players to be able to decode and render the video/audio/captions/etc. This eases up effort for content creators and distributors to prepare their content for adaptive streaming and also removes a lot of restrictions associated with proprietary solutions. That includes the IIS server set up for MSS and the proprietary encoding software for HLS.

However, this large scope of supported codecs does make for more complex player development. Communities have banded together to provide a plethora of player framework options for developing for DASH on a variety of platforms and for an assortment codecs. These frameworks vary in their supported platforms and features so a good amount investigation must be done in advance to find the right fit for the feature requirements of the player as well as the platform.

This is where subscribing to MPEG DASH as a solution may become problematic on more obscure platforms, and even on some of the more popular ones. This means MPEG DASH is not yet the answer to the segregation issue that exists with adaptive bitrate streaming.

hls_pro_con.png

DASH_pro_con.png

AdaptiveBitrateComparison

 

Sample data flow of MS video streaming service

streaming-diagram

Ref.:

http://iplayerhelp.external.bbc.co.uk/radio/other/streaming_hls_hds_mpeg

http://www.digiflare.com/adaptive-media-streaming-hls-vs-mss-vs-dash/

https://www.sitepoint.com/html5-video-understanding-compression-drm/

http://streaminglearningcenter.com/blogs/dash-or-hls-which-is-the-best-format-today.html

http://www.internetvideoarchive.com/documentation/video-api/progressive-download-vs-adaptive-bitrate/

https://bitmovin.com/mpeg-dash-vs-apple-hls-vs-microsoft-smooth-streaming-vs-adobe-hds/

https://en.wikipedia.org/wiki/Dynamic_Adaptive_Streaming_over_HTTP

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;
}