May 27, 2015

ath9k create multiple interfaces

  • To create/delete virtual interfaces:
    iw dev wlan0 interface add [virtual-sta-name] type station
    iw dev wlan0 interface add [virtual-ap-name] type __ap
    ip link set [interface-name] address [unique-mac-addr]
  • To delete virtual interface:
    iw dev [dev-name] del
  • use iw to check wlan device status

    $ cat /proc/net/wireless 
    Inter-| sta-|   Quality        |   Discarded packets               | Missed | WE
     face | tus | link level noise |  nwid  crypt   frag  retry   misc | beacon | 22
     wlan0: 0000   56.  -54.  -256        0      0      0      0      0        0
    
    
    
    
    OR
    
    
    $ iw dev wlan0 link
    Connected to 00:10:7A:93:AE:BF (on wlan0)
        SSID: SECRETSSID
        freq: 2462
        RX: 89045514 bytes (194863 packets)
        TX: 34783321 bytes (164504 packets)
        signal: -54 dBm
        tx bitrate: 48.0 MBit/s

    May 26, 2015

    openwrt unbind led gpios

    # Turn off the LEDs
    root@OpenWrt:/# echo "leds-gpio" > /sys/bus/platform/drivers/leds-gpio/unbind
    root@OpenWrt:/# cat /sys/kernel/debug/gpio
    GPIOs 0-21, ar2315-gpio:
    gpio-0   (sysfs               ) in  lo
    gpio-5   (reset               ) in  hi
    gpio-6   (sysfs               ) in  lo

    Now you can use gpio export (i.e echo 11 > /sys/class/gpio/export), and change 'direction' and 'value'  of the gpio to directly control it.

    use time to test multiple commans

    /usr/bin/time /bin/sh -c 'ls;pwd;ls'

    May 20, 2015

    cross compile openJDK for ARM

    Source: http://mail.openjdk.java.net/pipermail/zero-dev/2014-December/000538.html

    when I cross-compile OpenJDK 9 for ARM32 I pass the following configure 
    options
    
    configure
    # these options tell openjdk to do a cross compile build.
    --build=x86_64-unknown-linux-gnu
    --host=arm-buildroot-linux-gnueabi
    --target=arm-buildroot-linux-gnueabi
    
    # these two options enable zero
    --with-jvm-interpreter=cpp
    --with-jvm-variants=zero
    
    # specific options to make the build find the X and freetype headers and 
    librarys found on the ARM32 root filesystem.
    --disable-freetype-bundling
    --with-freetype-include=/home/xranby/rpi-buildroot/output/host/usr/arm-buildroot-linux-gnueabi/sysroot/usr/include/freetype2
    --with-freetype-lib=/home/xranby/rpi-buildroot/output/host/usr/arm-buildroot-linux-gnueabi/sysroot/usr/lib
    --with-freetype=/home/xranby/rpi-buildroot/output/host/usr/arm-buildroot-linux-gnueabi/sysroot/usr/
    --with-x=/home/xranby/rpi-buildroot/output/host/usr/arm-buildroot-linux-gnueabi/sysroot/usr/include
    
    # the sysroot shall point to the ARM32 root file system, the build will 
    use librarys inside the sys root during linking native libraries.
    --with-sys-root=/home/xranby/rpi-buildroot/output/host/usr/arm-buildroot-linux-gnueabi/sysroot
    # The tools dir contains binarys to run on the host x86 system, you may 
    point this to your system root dir /
    # in my case the tools i use have been compiled by buildroot thus I use 
    the buildroot tools dir.
    --with-tools-dir=/home/xranby/rpi-buildroot/output/host
    # OpenJDK 9 require OpenJDK 8, i point with boot jdk to an OpenJDK 8 
    image that can be run on the host x86 system.
    --with-boot-jdk=/home/xranby/images-jdk8/j2sdk-image/
    
    # some parts of the openjdk build still expect that the cross compile 
    tools are found in the system PATH
    # on my system i have to explicitly tell where the tools are located 
    because my cross compile toolchain is not found on the path.
    # i use gcc to do the linking instead of ld because the openjdk build 
    passes -Xlinker -z
    OBJCOPY=/home/xranby/rpi-buildroot/output/host/usr/bin/arm-buildroot-linux-gnueabi-objcopy
    STRIP=/home/xranby/rpi-buildroot/output/host/usr/bin/arm-buildroot-linux-gnueabi-strip
    CPP=/home/xranby/rpi-buildroot/output/host/usr/bin/arm-buildroot-linux-gnueabi-cpp
    CXX=/home/xranby/rpi-buildroot/output/host/usr/bin/arm-buildroot-linux-gnueabi-g++
    CC=/home/xranby/rpi-buildroot/output/host/usr/bin/arm-buildroot-linux-gnueabi-gcc
    LD=/home/xranby/rpi-buildroot/output/host/usr/bin/arm-buildroot-linux-gnueabi-gcc
    CPP_FLAGS=-lstdc++
    CXX_FLAGS=-lstdc++
    
    
    when running make i pass the following options to make
    # BUILD_CC and BUILD_LD shall point to host x86 executables.
    BUILD_CC=gcc
    BUILD_LD=gcc
    OBJCOPY=/home/xranby/rpi-buildroot/output/host/usr/bin/arm-buildroot-linux-gnueabi-objcopy
    STRIP=/home/xranby/rpi-buildroot/output/host/usr/bin/arm-buildroot-linux-gnueabi-strip
    CPP=/home/xranby/rpi-buildroot/output/host/usr/bin/arm-buildroot-linux-gnueabi-cpp
    CXX=/home/xranby/rpi-buildroot/output/host/usr/bin/arm-buildroot-linux-gnueabi-g++
    CC=/home/xranby/rpi-buildroot/output/host/usr/bin/arm-buildroot-linux-gnueabi-gcc
    LD=/home/xranby/rpi-buildroot/output/host/usr/bin/arm-buildroot-linux-gnueabi-gcc
    #and finally the target, this will build compact profiles, jre and jdk 
    images.
    all images profiles CONF=linux-arm-normal-zero-release
    
    
    I have automated these configure and make options for openjdk 9 into 
    buildroot build scripts
    https://github.com/xranby/rpi-buildroot/tree/openjdk
    
    >
    > I've done Zero builds before but have never used OpenJDK's cross-compile
    > feature to build it on ARMv7. There is an Arm32 bit JIT in IcedTea[1],
    > but I don't know if that can be cross-compiled.
    
    If you cross compile icedtea then you need to make sure that the 
    bytecode generator tool is compiled by the host x86 toolchain.
    openembedded meta-java contains buildscripts that can cross compile the 
    Arm32 JIT found in IcedTea.
    https://github.com/woglinde/meta-java
    
    Cheers
    Xerxes

    May 6, 2015

    hg change history

    hg rebase, hg histedit, hg graft, hg strip, hg strip --keep, and hg commit --amend.

    April 30, 2015

    vim ctags tags path

    This line in your ~/.vimrc should help:
    set tags=./tags,tags;$HOME
    

    It tells Vim to look for a tags file in the directory of the current file, in the current directory and up and up until your $HOME (that's the meaning of the semicolon), stopping on the first hit.

    April 27, 2015

    golang win32 UI

    https://github.com/lxn/walk

    OR

    https://github.com/AllenDang/gform

    OR

    https://github.com/andlabs/ui

    April 23, 2015

    USB terms

    In the USB world, the most basic data transfer is done in packet, but to understand the on-the-wire protocol, there are other things to understand.

    Packet
    USB Packet types: (Source: http://www.usbmadesimple.co.uk/ums_3.htm)

    PID Type PID Name PID<3:0>*
    Token OUT 0001b
    IN 1001b
    SOF 0101b
    SETUP 1101b
    Data DATA0 0011b
    DATA1 1011b
    DATA2 0111b
    MDATA 1111b
    Handshake ACK 0010b
    NAK 1010b
    STALL 1110b
    NYET 0110b
    Special PRE 1100b
    ERR 1100b
    SPLIT 1000b
    PING 0100b
    Reserved 0000b

    Transaction: 
       
    One transaction has 3 packets: Token + Data + Handshake for a successful transaction. (*). Nak and Stall error condition could happen after Token when no data is available.

    There are 3 types of transactions: IN, OUT, SETUP

     *: For IN and OUT transactions used for isochronous transfers, there are only 2 packets; there is no handshake packet.

    Transfer:
    There are 4 types of transfer:

    • Control 
    • Interrupt
    • Bulk
    • Isochronous (such as audio data)
    HID device only uses Control and Interrupt

    Control transfer = 3 transactions: SETUP + IN/OUT DATA + STATUS(IN/OUT transaction)
    Other transfers has just one transaction: IN/OUT data.

    In general, you want to pay attention to Transfer or Transaction level, not packet level. 

    April 22, 2015

    prevent ssh client timeout

    Add this in /etc/ssh/ssh_config for Linux and ~/.ssh/config for Mac:

    
    
    Host *
    ServerAliveInterval 120
    

    linux cp without overwrite

    You can use "-n" option.

    If you are on a embedded linux box with busybox, it does not have that option. You can this instead:

    false | cp -i source destination 2>/dev/null

    April 16, 2015

    Vim show C function name

    Put this in your .vimrc file, and use key "f" to show current function name:

    fun! ShowFuncName()
      let lnum = line(".")
      let col = col(".")
      echohl ModeMsg
      echo getline(search("^[^ \t#/]\\{2}.*[^:]\s*$", 'bW'))
      echohl None
      call search("\\%" . lnum . "l" . "\\%" . col . "c")
    endfun
    map f :call ShowFuncName() <CR>

    April 15, 2015

    golang combine static data (css/js/images/) with binary file

    https://github.com/tiebingzhang/statik (zip the contents and compiled it into go source code, very small code base, this is a github fork with the slash fix)

    https://github.com/jteeuwen/go-bindata

    https://github.com/GeertJohan/go.rice (can either compile zip into go source, or append the zip to existing go EXE, more flexible but code base is a little larger)

    April 14, 2015

    script to detected unused C files

    If you have a large project with a lot of C files, once you compiled them, you will end up with a lot of .o files. Then you can use the .o files to find out which .c files is not used (conditionally compiled/not compiled). To do this, follow the steps below:

    1. cd subdir
    2. ls -1 > ../1.out
    3. gawk -f lsnu.awk ../1.out

    The lsnu.awk script
    {
            if ($1 ~ /\.c$/){
                    cfiles[$1]=1;
                    print $1;
                    next;
            }
            if ($1 ~ /\.o$/){
                    ofiles[$1]=1;
                    #printf("%s\n",$1);
                    next;
            }

    }

    END{
            printf("-------------\n");
            for ( i in  cfiles){
                    f=i;
                    gsub(/\.c$/,".o",i);
                    if (ofiles[i]!=1){
                            printf("%s ",f);
                            }
            }
            printf("\n");
    }

    March 12, 2015

    cmake add include path and library path

    Some tips for cMake beginners. This is done on Linux.

    How to use cMake

    cmake generates a bunch of intermediate files, including the final Makefile. To make things clean, make a separate directory for the build process:

    mkdir build
    cd build
    cmake ..

    To re-run cmake after changing the CMakeLists.txt, do:

    cd build
    rm -rf *
    cmake ..

    Cross Compile to ARM

    To cross compile to an embedded target, add the following lines to you CMakeLists.txt at the very top (after VERSION)
    SET(CMAKE_SYSTEM_NAME Linux)
    SET(CMAKE_C_COMPILER arm-none-linux-gnueabi-gcc)

    Add include paths

    include_directories("${PROJECT_SOURCE_DIR}/../" "${PROJECT_SOURCE_DIR}/build/" "${PROJECT_SOURCE_DIR}")

    Add a library

    FIND_LIBRARY(json json-c json)

    1st parameter: output,  The variable that will hold the results of FIND_LIBRARY
    2nd parameter: the library to look for (in this case, libjson-c.so)
    3rd parameter: the path to look, starting with ${PROJECT_SOURCE_DIR}

    The returned varilable can be used in the following statement to add the library to link time:
    TARGET_LINK_LIBRARIES(${json})

    Assign a variable

    SET(LIBS ${ubox} ${blobmsg_json} ${json})

    assigns the concatenated value of ubox, blobmsg_json and json to the variable LIBS



    March 11, 2015

    AT&T Data plan web page

    https://buyasession.att.com

    Linux running 4G LTE modem

    The modem I have is Sierra Wireless Air Prime MC7453 Mini PCI Express Module.  The carrier I tested is AT&T.

    Before running on Linux, I had to install the card on a regular Laptop that supports 4G card, and run Windows 7 on the laptop, install all the drivers and the Sierra Wireless Connect Manager to try out the card. This confirmed that the card has the latest firmware, and the carrier setting is correct, etc.

    Next I run it on Linux. Instead of using the Gobi driver from Sierra Wireless, I used the qmi_wwan driver in the latest Linux (after kernel version 3.14).  An user land utility is also needed. libqmi seems to be popular, but it depends on a fairly new version of glib, which itself depends on a bunch of libraries. It becomes a hassle to compile everything. Then I discovered uqmi, a small utility developed and used by the openwrt project. It's much more lightweight, and seems to be pretty mature. I was able to get my modem to connect and ping with the following commands.

    device="/dev/cdc-wdm1"
    modes="lte"
    uqmi -s -d "$device" --get-pin-status
    uqmi -s -d "$device" --get-serving-system
    uqmi -s -d "$device" --set-data-format 802.3
    uqmi -s -d "$device" --wda-set-data-format 802.3
    uqmi -s -d "$device" --set-network-modes "$modes"
    wds=`uqmi -s -d "$device" --get-client-id wds`
    uqmi -s -d "$device" --set-client-id wds,"$wds" --start-network "ISP.CINGULAR" --autoconnect
    uqmi -s -d "$device" --get-signal-info
    uqmi -s -d "$device" --get-data-status
    dhclient wwan1

    Now I can ping

    To disconnect:
    uqmi -s -d "$device" --stop-network 0xffffffff    --autoconnect > /dev/null


    [1] The home page of uqmi:  http://nbd.name/gitweb.cgi?p=uqmi.git;a=summary
    [2] A list of useful commands of how to use uqmi: http://trac.gateworks.com/wiki/modem
    [3] The official Openwrt qmi script that uses uqmi:  https://dev.openwrt.org/browser/trunk/package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh
    [4] Another useful link: https://lists.openwrt.org/pipermail/openwrt-devel/2014-April/025046.html

    March 5, 2015

    How to get Linux USB Report Descriptor when it says UNAVAILABLE

    Start by plugging in your USB device and running dmesg to get the kernel output for the event. It will look something like this:

    input: Sony PLAYSTATION(R)3 Controller as /devices/pci0000:00/0000:00:04.1/usb2/2-4/2-4.2/2-4.2:1.0/input/input16
    
    
    
    The first line input: ... is what we want. It contains the full device path and in this case we are interested in third last component of the path: 2-4.2:1.0.

    To get the USB report Descriptor with "lsusb -v", we need to unbind the device first (as root).
    $ sudo bash -c "echo -n 2-4.2:1.0 >/sys/bus/usb/drivers/usbhid/unbind"
    

    Now run lsusb again for the device and you should see the report descriptor in the output!

    Patch Linux kernel to support Esterline Medigenic keyboard

    The Esterline Medigenic keyboard does not work under stock Linux kernel (as of kernel version 4.0RC). This is because the HID Report Descriptor of the keyboard is wrong for Linux (and Mac OS). Under Linux kernel tree driver/hid there are a bunch of "special" drivers for different hid devices, and we can create one for the medigenic keyboard to fix up the HID report descriptor so that it works under Linux.

    1. Create a file under driver/hid called hid-medigenic.c with the following content:
    /*
     * This program is free software; you can redistribute it and/or modify it
     * under the terms of the GNU General Public License as published by the Free
     * Software Foundation; either version 2 of the License, or (at your option)
     * any later version.
     */

    #include <linux/device.h>
    #include <linux/hid.h>
    #include <linux/module.h>

    #include "hid-ids.h"

    /* the fixups that need to be done:
     *   - change keyboard Usage Mininum from 1 to 0
     */
    static __u8 *medigenic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                    unsigned int *rsize)
    {
            if (*rsize >= 59 &&
                    rdesc[24] == 0x19 && rdesc[25] == 0x01 &&
                    rdesc[26] == 0x29 && rdesc[27] == 0x65 ) {
                    dev_info(&hdev->dev, "fixing up medigenic keyboard report descriptor\n");
                    rdesc[25] = 0x00;
            }
            return rdesc;
    }

    static const struct hid_device_id medigenic_devices[] = {
            { HID_USB_DEVICE(USB_VENDOR_ID_ESTERLINE, USB_DEVICE_ID_MEDIGENIC) },
            { }
    };
    MODULE_DEVICE_TABLE(hid, medigenic_devices);

    static struct hid_driver medigenic_driver = {
            .name = "medigenic",
            .id_table = medigenic_devices,
            .report_fixup = medigenic_report_fixup,
    };

    static int __init medigenic_init(void)
    {
            return hid_register_driver(&medigenic_driver);
    }

    static void __exit medigenic_exit(void)
    {
            hid_unregister_driver(&medigenic_driver);
    }

    module_init(medigenic_init);
    module_exit(medigenic_exit);
    MODULE_LICENSE("GPL");

    2. Edit file driver/hid/hid-ids.h to add the following two lines:
    #define USB_VENDOR_ID_ESTERLINE 0x059d
    #define USB_DEVICE_ID_MEDIGENIC 0x0708


    3. Edit file driver/hid/Kconfig to add the following lines:
    config HID_MEDIGENIC
        tristate "Medigenic Keyboard Support" if EMBEDDED
        depends on USB_HID
        default !EMBEDDED
        ---help---
        Support for Medigenic keyboard.

    4. Edit file driver/hid/Makefile to add the following line:
    obj-$(CONFIG_HID_MEDIGENIC)     += hid-medigenic.o

    Then in top directory of kernel, do make menuconfig, and exit, and save (somehow medigenic is automatically set to Y when you do this). Check .config to make sure you have the following line:
    CONFIG_HID_MEDIGENIC=y

    The build your kernel and the keyboard should work now.

    memdump function in kernel

    void memdump(unsigned char *rdesc, int *rsize){
        int i,pos=0;
        unsigned char outbuf[256];
        printk(KERN_WARNING "rsize=%d\n",*rsize);
        for (i=0;i<*rsize;i++){
            pos+=sprintf(outbuf+pos,"%02x ",rdesc[i]);
            if (i>0 && ((i+1)%16)==0){
                printk(KERN_WARNING "%04x dump %s\n",(i/16)*16,outbuf);
                pos=0;
            }
        }
        if (pos>0){
            printk(KERN_WARNING "%04x dump %s\n",(i/16)*16,outbuf);
        }
    }