Working with the Radio Layer Interface (RIL) in Android

Requirements:

Android source tree (rowboat)

Linux kernel (2.6.37)

Ubuntu

adb

RIL (https://github.com/aferre/sierra-ril)

Beware: I did this work in Froyo (2.2) and I got to the point where I could start a ppp (Point to Point Protocol) but I couldn’t have a network access. I don’t know whether the bug came from Android or my work. I then decided to use Gingerbread (2.3.4), so the work here is targeting Ginger, but you could try it on Froyo as weel or any other version. If you got it working, I’d be glad to put your work here or link to it.

Intro

Google made it “easy” for vendors to integrate their modem into Android. Indeed, it would have been a pain if HTC, Samsung, … would have had to create a complete library and work on the low level system layers in Android. Everything one has to do to be able to use a modem (either with a 2G, 3G, or another access technology) is included in the directory /hardware/ril/ (provded that the java framework doesn’t have any bug, but if it does i’ll try to point them out).

Actually, apart from a few bug fixes in the RIL sources, from what I understand you’ll only have to modify the libreference-ril.c file. Google and the Android team provide a typical RIL (called libreference-ril) implementing the functions needed, and providing some kind of low level documentation (documentation in Android, for the system parts and not the application dev part, is really, REALLY, light).

In order to make it easier to compile and debug the RIL for the steps that are coming, i’ll put some tips and scripts.

Setup Android before building it

You should read this entire post before doing anything, as you’ll have to do a couple of things before actually building Android.

First of all, you need to add PPP support to the linux kernel. Here are the things you need to set:

  • Device drivers
    • network device support
      • enable PPP support
        • enable ppp suport for async serial line
        • enable ppp support for sync serial line
      • enable SLIP (TBD)
    • Enable telephony support (TBD)
    • USB support
      • USB Modem (CDC ACM) support
      • USB Serial Converter support

Also, in Gingerbread I am not able to get a USB/RS232 converter to be mounted as the system boots. So when booted, I just do a

insmod /sdcard/ftdi_sio.ko

to load the ftdi kernel module. I previously had to enable ftdi support in device drivers/usb support/usb serial converter/. I added it as a module, and after building it, moved it to the sdcard.

Building the ril

The first script will first compile the RIL with the Android build system, and push the library to the target using adb (so you need to be connected to your target with adb). Be carefull here: I spent a few days debugging a non working RIL because I didn’t use the Android build system to compile it. The system didn’t give me any error when building/using the RIL, but the RIL was indeed buggy as it didn’t output the messages in the good order, and was reseting every 15 seconds … I have to thank vrb (from rowboat IRC channel on irc.freenode.net): vrb, love ya.

During the development, I used to put the Android source tree in the directory /home/<whatever_your_session_name_is>/bin/gingerbread. The RIL provided here is on my github page.

#!/bin/sh
echo "Using defaults"
ANDSOURCES=~/bin
GINGER=$ANDSOURCES/gingerbread
SIERRA=~/sierra-ril
PRODUCT=beagleboard

cp $SIERRA/Android.mk $GINGER/hardware/ril/reference-ril/
cp $SIERRA/atchannel.c $GINGER/hardware/ril/reference-ril/
cp $SIERRA/atchannel.h $GINGER/hardware/ril/reference-ril/
cp $SIERRA/at_tok.c $GINGER/hardware/ril/reference-ril/
cp $SIERRA/at_tok.h $GINGER/hardware/ril/reference-ril/
cp $SIERRA/misc.c $GINGER/hardware/ril/reference-ril/
cp $SIERRA/misc.h $GINGER/hardware/ril/reference-ril/
cp $SIERRA/sierra-ril.c $GINGER/hardware/ril/reference-ril/

cd $ANDSOURCES/gingerbread/
source build/envsetup.sh
make clean
mm libreference-ril TARGET_PRODUCT=beagleboard -j8

adb push $GINGER/out/target/product/$PRODUCT/system/lib/libril.so /system/lib/
adb push $GINGER/out/target/product/$PRODUCT/system/lib/libreference-ril.so /system/lib/

Note that when pushing the new RIL to the target device, you can use it right away without having to reboot. Simply kill the rild process by using the ps command, finding out the rild PID (process identifier) and using the command kill <rild_PID>.

Fixing the base RIL

As I said the base RIL is buggy.

First, you need to explicitly set your modem speed in Android, so that you don't have problems when talking to your device. You do this in the reference-ril.c file, located in ../hardware/ril/libreference-ril/. In the static void mainLoop function replace the following:

else if (s_device_path != NULL) {
                fd = open (s_device_path, O_RDWR);
                if ( fd >= 0 && !memcmp( s_device_path, "/dev/ttyS", 9 ) ) {
                    /* disable echo on serial ports */
                    struct termios  ios;
                    tcgetattr( fd, &ios );
                    ios.c_lflag = 0;  /* disable ECHO, ICANON, etc... */
			tcsetattr( fd, TCSANOW, &ios );
                }

by the following

else if (s_device_path != NULL) {
                fd = open (s_device_path, O_RDWR);
                if ( fd >= 0 && !memcmp( s_device_path, "/dev/ttyS", 9 ) ) {
                    /* disable echo on serial ports */
                    struct termios  ios;
                    tcgetattr( fd, &ios );
                    ios.c_lflag = 0;  /* disable ECHO, ICANON, etc... */
                    LOGI("Setting speed");
                   if( cfsetispeed( &ios, B115200) != 0 )
                       LOGE("Failed to set in speed");
                   if ( cfsetospeed( &ios, B115200) != 0 )
                       LOGE("Failed to set out speed");
			tcsetattr( fd, TCSANOW, &ios );
                }

In the file ril.cpp (../hardware/ril/libril/ril.cpp), you have to remove a couple of things. First, find this part:

// start listen socket
#if 0
    ret = socket_local_server (SOCKET_NAME_RIL,
            ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);

    if (ret < 0) {
        LOGE("Unable to bind socket errno:%d", errno);
        exit (-1);
    }
    s_fdListen = ret;

#else
    s_fdListen = android_get_control_socket(SOCKET_NAME_RIL);
    if (s_fdListen < 0) {
        LOGE("Failed to get socket '" SOCKET_NAME_RIL "'");
        exit(-1);
    }

    ret = listen(s_fdListen, 4);

    if (ret < 0) {
        LOGE("Failed to listen on control socket '%d': %s",
             s_fdListen, strerror(errno));
        exit(-1);
    }
#endif

and change #if 0 to #if 1, and also remove the #else. You should have this

  // start listen socket

#if 1
    ret = socket_local_server (SOCKET_NAME_RIL,
            ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);

    if (ret < 0) {
        LOGE("Unable to bind socket errno:%d", errno);
        exit (-1);
    }
    s_fdListen = ret;

//#else
    s_fdListen = android_get_control_socket(SOCKET_NAME_RIL);
    if (s_fdListen < 0) {
        LOGE("Failed to get socket '" SOCKET_NAME_RIL "'");
        exit(-1);
    }

    ret = listen(s_fdListen, 4);

    if (ret < 0) {
        LOGE("Failed to listen on control socket '%d': %s",
             s_fdListen, strerror(errno));
        exit(-1);
    }
#endif

Right below this part is another thing you need to change: the #if 1 to #if 0. This is to prevent the debug socket interface from being setup

In the file hardware/ril/rild/rild.c, change this part

/* special override when in the emulator */
 #if 1
 {
to
/* special override when in the emulator */
 #if 0
 {

Fixing Android

Now you have to make Android be aware that the modem is on whatever device (/dev/<something>) you put it on. I used a Sierra Wireless Q26 modem, with a USB and 2 RS232 interfaces (they will allow me not to use the AT commands software multiplexer). When connecting the modem with the USB interface, I have to add both the cdc_acm driver and the sierra wireless driver that are available in the linux kernel. The modem will then show up as a ttyACMx device node. The RIL needs this information to figure out where to send commands, and we'll provide this information in the init.rc file located in the root directory of your Android system.

init.rc

What you need is to add or modify these lines:

loglevel 4

setprop ro.radio.noril no
setprop hw.nophone false
service ril-daemon /system/bin/rild -l /system/lib/libreference-ril.so -- -d /dev/ttyACM0
   socket rild stream 660 root radio
   socket rild-debug stream 660 radio system
   user root
   group radio cache inet misc audio vpn net_admin

service pppd_gprs /etc/ppp/init.gprs-pppd
   user root
   group radio cache inet misc
   disabled

The first line increases the debug level so that you can see at commands being sent and answered. Then, we tell Android it must use the RIL and after that, that it has a phone device.

The next part defines the ril-daemon service. You have to provide here the device node you'll use, the ril library, and the groups allowed to use the daemon. Permissions are very important in Android, and you'll see that there are a few things you'll have to do to make it all work.

The last part defines the pppd_gprs service, which will allow you to get a data connection. Now, I have seen a few ways to get the data connection: using the Point to Point Protocol, which you will see here, using RMNET, a Qualcomm proprietary implementation.

ueventd.rc

You also need to set permissions for the device node. The RIL and all radio frequency related devices, daemons and libraries are in the radio group. So, at boot time or when you connect the modem, Android should auto magically set the correct permissions. This will be done in the file ueventd.rc in the root dir of Gingerbread. Note that this is only for Android 2.3 and above. With earlier versions, you need to add those permissions in a file called devices.c.

So in ueventd.rc, add the following, with /dev/ttyACM0 and/dev/ttyUSB0 pointing to whatever device nodes you want:

 /dev/ttyACM0  0660   radio      radio
 /dev/ttyUSB0  0660   radio      radio

From now on, you should be able to start the RIL successfully.

You'll also have to set the init.gprs_pppd permission to 755 once you put it in its directory. Plus, to add it to the radio group, you'll have to modify the file called property_service.c located in the Android source tree at ../system/core/init/property_service.c.

/*
 * White list of UID that are allowed to start/stop services.
 * Currently there are no user apps that require.
 */
struct {
    const char *service;
    unsigned int uid;
    unsigned int gid;
} control_perms[] = {
    { "dumpstate", AID_SHELL, AID_LOG },
    { "pppd_gprs", AID_RADIO, AID_LOG },
     {NULL, 0, 0 }
};

PPP files

For this part, you should go to Use PPP In Android.

36 thoughts on “Working with the Radio Layer Interface (RIL) in Android

  1. Devindrappa

    thanks a lot….
    i have gone through this blog its awsome………….
    But I want know that does it work on gingerbread……..
    Because am using gingerbread but not able to achieve.

    So in your case is it working?

    Reply
    1. adrienferre Post author

      Hi,

      Most of the information available here should work “out of the box” for gingerbread.

      Beware that some mappings differ amongst Android releases (GPRS can be coded as 1 in Froyo, and 2 in Gingerbread, this is not those exact values, but you get my drift…).

      Reply
  2. Kumar

    Hi,

    Thank you, for this blog……..
    There is not much info about RIL. But thank god i found this blog.
    Its a very good blog.
    Hey i followed this blog and now I am able to make a call,sms,signal strength….
    But I am not getting gprs connection.I followed this and ppp blog. But I am not able to make a Internet access.

    I am getting Connect script failed… error. Can anybody have any solution for this.

    Thanks in advance.

    Reply
  3. Kumar

    Hi,
    when i run the init.gprs-pppd, it is showing connect script failed.
    i have checked 3-4 different connect scripts, but getting same error.Connect script failed

    Reply
  4. Vender ouro

    I found your weblog site on google and verify just a few of your early posts. Continue to maintain up the superb operate. I simply additional up your RSS feed to my MSN Information Reader. Looking for ahead to studying extra from you in a while!…

    Reply
  5. Ivette Kym

    Hi there! Would you mind if I share your blog with my zynga group? There’s a lot of people that I think would really enjoy your content. Please let me know. Thanks

    Reply
  6. Amit Bag

    HI,
    I find few thing difficult to understand in this blog. Till Fixing Android I can understand everything. I checked in ril its taking the path of the device it will communicate from system.prop in the line: rild.libargs=-d /dev/ttyUSB2. When I comment my modem to the snowball board its detected Detected FT2232C on ttyUSB1 so I changed the value in the system.prop to rild.libargs=-d /dev/ttyUSB1. Is it the same thing what you are trying to do in init.rc.
    And the next step
    changes in the file ueventd.rc
    I checked in my android source code it like below

    # AT USB device – used by ATC
    /dev/ttyGS0 0060 root radio

    # modem storage pipe
    /dev/rpc 0600 radio radio

    So Do I need to change like what you mentioned, but I do not understand why there are 2 device for radio?

    One more thing for the modem I need to communicate with the snowball its required CAIF protocol for communication. So please suggest me how to achieve that by changing the android source code.

    Thanks,
    Amit Bag

    Reply
    1. adrienferre Post author

      Hi,

      ueventd.rc means you are targeting gingerbread right? If so I mention in the introduction that the modifications are targeted for froyo and not gingerbread and this may be why you find it difficult to understand.

      I think the ttyGS0 is a serial gadget, but you definetly use the node name you get when connecting your modem (use dmesg after you plugged in the modem and check the last few lines).

      For the CAIF part I don’t know.

      Reply
  7. Pingback: For Discussion of Development for CM7 Only - Page 2 - Android Forums

  8. John Newby

    Hi,

    I am working on a u300-ril package and have looked at your code for ideas. However, I am greatly constrained by a lack of documentation on the Ericsson specific AT commands. For example, I can not find anything on AT*EGNCI. It shows up on the supported command list for the f5521gw, but I get a CME error when trying to implement.

    It seems like you have access to the Ericsson command reference documents. Can you provide a copy/link?

    Thanks,
    John

    Reply
  9. Olivier G-M

    Hi adrien. This is some very good information and it’s helping me a lot on my work. If you want, i’d like your opinion on something i’m doing. I’m currently doing an application that works with the phonestatelistener. And since my application is a tool, i need it to be very precise and sensitive. But it looks like the listener doesnt change often like its not enough sensitive or the refresh rare isn’t high enough. i’m currently trying to mod the ril to increase the sensitivity of the listener on sate change. So far i looked at all the ril libraries and it seems i can’t find where to tweek. Do you know something about that ?

    Reply
    1. adrienferre Post author

      I am sorry i am not familiar with the phone state change listener. Could you elaborate? What sensitivity are you talking about? Signal quality?

      Reply
  10. Olivier G-M

    Hi, if you want i need some help because i browsed trough all the ril libraries and i can’t find the information i want. I’m trying to increase the refresh rate/sensivity for android.telephony.statelistener. as i am sure the hardware can detect faster change but it’s set differently to (probably) save on batteries. One thing sure the information on your blog helped me get the closest from my goal. :)

    Reply
  11. kanak

    Hi ,
    It was the great post , i have never seen like this before about the RIL .
    As i worked on Ril i know alll the RIL files but i have not seen any where about this file ueventd.rc
    What us this file ?
    Can u explain more about this?

    Regards,
    Kanak

    Reply
    1. adrienferre Post author

      AFAIK ueventd.rc is the equivalent of udev for android. This will allow to mount peripherals like tty, … and to launch some scripts when those peripherals are plugged in.

      For instance I use udev (in linux) to auto magically map my modem ports to specific nodes so that I can use those nodes without having to check if the modem is mounted on ttyUSB0, ttyUSB1, ttyUSB10 or whatever…

      Reply
  12. Pingback: A nice blog post we found about the RIL (Radio Interface Layer) | Team Gelato's Blog

  13. diandeh

    I have ported Android Gingerbread 2.3.4 on Beagleboard xM version.

    I have made modifications in the Radio Interface Layer(RIL) given by
    Android.

    Now i am able to successfully communicate with the modem(using USB-
    RS232 converter) and also i am able to send and receive the SMS.

    But when i am trying to make a call i get an error

    “The process android.process.acore has stopped unexpectedly.Please try
    again. Force Close”

    Reply
  14. bill

    hi !
    I am trying to port 3G telephony to a ti card using rowbat ICS project.
    I am able now to receive sms and calls but when I try to make an outgoing call I am having an alert saying “Mobile network not availabe”.

    I think that this issue is related to “checkIfOkToInitiateOutgoingCall: ServiceState = 1″ which corresponds to STATE_OUT_OF_SERVICE.
    is there any document that could help me to understand the origin of this value or a configuration that should be done to avoid such errors in outgoing calls ?
    are the incoming and outgoing calls independants in android RIL ? ( I could receive calls and I could call nobody !).

    Thank you !

    Reply
    1. adrienferre Post author

      Hi,

      It seems weird that you are able to receive calls/text messages and are not able to emit anything. Do you have the output of the radio logcat? I do not know if the incoming/outgoing calls are not related, sorry.

      I am sorry to say that the point of the android related articles on this blog is that there is not much info/docs on those parts of android. You could take a look at the source code commentaries or check out Karim Yagmour’s book (Embedded Android) but I doubt that Karim is talking about the RIL part.

      Reply
  15. vinod kumar

    Hi,

    I want to use GSM/GPRS services in AM3354 standard board. I am using Norway GSM/GPRS module as an externel module which is connected through UART0. I also able to get the node namely mux1, mux2,mux3. I am able to make call/sms through AT commands in picocom terminal. I had also installed Dialer-One.APK to make calls form android application.But I am unable to make calls as well as message from android application.However GPRS and TCP/IP AT commands are also not working in picocom.

    I have done some modification in following lib file as vendor send me:

    1) /devices/ti/am335xevm_sk/system.pro

    2) /devices/ti/am335xevm_sk/init.rc

    3) /external/ppp/pppd/pathnames.h

    4) /system/core/init/property_service.c

    5) /system/core/include/private/android_filesystem_config.h

    6 Place libreference-ril.so to system / lib of out folder;
    7 Place the chat and gsm0710muxd to system / bin in out folder

    To enable the Telephony manager I did the following changes in :

    1) /device/ti/am335xevm_sk/device.mk

    PRODUCT_COPY_FILES += \
    device/ti/am335xevm/android.hardware.screen.xml:system/etc/permissions/android.hardware.screen.xml \
    frameworks/native/data/etc/android.hardware.telephony.gsm.xml:system/etc/permissions/android.hardware.telephony.gsm.xml

    PRODUCT_PACKAGES += \
    rild

    PRODUCT_COPY_FILES += \
    device/ti/am335xevm/ppp/ip-up:system/etc/ppp/ip-up \
    device/ti/am335xevm/ppp/ip-down:system/etc/ppp/ip-down

    2) /device/ti/am335xevm_sk/ueventd.am335xevm.rc

    /dev/ttyUSB0 0660 radio radio

    Please help me so that I can make calls as well sms from android application.

    Reply
  16. winton.chen

    Can you tell me pppd in Android4.0 or 4.1,4.2?
    There are not chat binary file in Android4.0,how do use pppd? thx!

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s