Embedded Linux Encounters

A peek in to the world of Embedded Linux and stuff

  • Linux is addictive, I'm hooked!

         Geek@WastingTime>

Making Android gadget work on PXA270

Posted by Vaisakh P S On 10:33 PM 1 comments

Hi Everyone,

Was busy in some other work (other than Linux), so my Android porting activity got stalled for few months. Now I am back in to it.

Back to the topic, I was able to make Android Gadget and ADB work in my PXA270 board. Here are the changes that needs to made:
  1. Modified drivers/usb/gadget/android.c , to move usb_configuration structure from init data section to bss. Previously this used to create a fatal crash as this configuration is getting added in to linked list which will be later traversed during endpoint configuration setup phase, at which this will show up as a NULL reference.

diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c

index c431131..f14fedf 100644

--- a/drivers/usb/gadget/android.c

+++ b/drivers/usb/gadget/android.c

@@ -113,7 +113,7 @@ static int __init android_bind_config(struct usb_configuration *c)

return adb_function_add(c);

}

-static struct usb_configuration android_config __initdata = {

+static struct usb_configuration android_config = {

.label = "android",

.bind = android_bind_config,

.bConfigurationValue = 1,


  1. Change the USB Endpoint setup array in drivers/usb/gadget/pxa27x_udc.c, to make two sets of Bulk Endpoints(IN and out) available to android gadget driver. (I removed rest of the configurations, just because only I didn't need them)

diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c

index 7cbc78a..037e435 100644

--- a/drivers/usb/gadget/pxa27x_udc.c

+++ b/drivers/usb/gadget/pxa27x_udc.c

@@ -2171,36 +2171,19 @@ static struct pxa_udc memory = {

USB_EP_CTRL,

USB_EP_OUT_BULK(1),

USB_EP_IN_BULK(2),

- USB_EP_IN_ISO(3),

- USB_EP_OUT_ISO(4),

- USB_EP_IN_INT(5),

+ USB_EP_OUT_BULK(3),

+ USB_EP_IN_BULK(4),

+

},

.pxa_ep = {

PXA_EP_CTRL,

/* Endpoints for gadget zero */

- PXA_EP_OUT_BULK(1, 1, 3, 0, 0),

- PXA_EP_IN_BULK(2, 2, 3, 0, 0),

+ PXA_EP_OUT_BULK(1, 1, 1, 0, 0),

+ PXA_EP_IN_BULK(2, 2, 1, 0, 0),

/* Endpoints for ether gadget, file storage gadget */

- PXA_EP_OUT_BULK(3, 1, 1, 0, 0),

- PXA_EP_IN_BULK(4, 2, 1, 0, 0),

- PXA_EP_IN_ISO(5, 3, 1, 0, 0),

- PXA_EP_OUT_ISO(6, 4, 1, 0, 0),

- PXA_EP_IN_INT(7, 5, 1, 0, 0),

- /* Endpoints for RNDIS, serial */

- PXA_EP_OUT_BULK(8, 1, 2, 0, 0),

- PXA_EP_IN_BULK(9, 2, 2, 0, 0),

- PXA_EP_IN_INT(10, 5, 2, 0, 0),

- /*

- * All the following endpoints are only for completion. They

- * won't never work, as multiple interfaces are really broken on

- * the pxa.

- */

- PXA_EP_OUT_BULK(11, 1, 2, 1, 0),

- PXA_EP_IN_BULK(12, 2, 2, 1, 0),

- /* Endpoint for CDC Ether */

- PXA_EP_OUT_BULK(13, 1, 1, 1, 1),

- PXA_EP_IN_BULK(14, 2, 1, 1, 1),

+ PXA_EP_OUT_BULK(3, 3, 1, 0, 0),

+ PXA_EP_IN_BULK(4, 4, 1, 0, 0),

}

};


diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h

index 1d1b793..7a42932 100644

--- a/drivers/usb/gadget/pxa27x_udc.h

+++ b/drivers/usb/gadget/pxa27x_udc.h

@@ -409,8 +409,8 @@ struct udc_stats {

unsigned long irqs_reconfig;

};

-#define NR_USB_ENDPOINTS (1 + 5) /* ep0 + ep1in-bulk + .. + ep3in-iso */

-#define NR_PXA_ENDPOINTS (1 + 14) /* ep0 + epA + epB + .. + epX */

+#define NR_USB_ENDPOINTS (1 + 4) /* ep0 + ep1in-bulk + .. + ep3in-iso */

+#define NR_PXA_ENDPOINTS (1 + 4) /* ep0 + epA + epB + .. + epX */


  1. After these two steps, your PXA gadget will be recognized by PC. Now change the INF file in Android Windows USB Driver (available along with SDK), to recognize your device.
  2. Now I am facing some crashes because of NULL reference in Mass Storage profile of android. For recognizing in Windows, both ADB and Storage profile of Android gadget needs to be active. For development in Linux, you need not have Storage. That can be commented off in android.c
  3. Make sure that you have "UNIX PTY Support" enabled in kernel, as ADB client and server makes use of those devices for process creation and some other operations.

PXAFB Android Patch

Posted by Vaisakh P S On 8:10 PM 0 comments

PXA Frame Buffer driver Patch for Android - http://androidzaurus.seesaa.net/article/105551643.html


Great work by the Ando.

During booting of kernel, these are the possible error messages that may show. Here are the reasons for the same:

Kernel completely up but console is not shown
  • This could have been because of various reasons. Either the console device specified in boot arguments would be different
  • There might not be a device instance corresponding to the specified device under /dev directory.

Init not found or Failure in executing init
  • Init program might not be given execution privileges or root might not be the owner of the init executable.
  • If BusyBox is not compiled as a static binary, then failure in loading the dynamic libraries can also result this error.


Failed in mounting root file system
  • The device such as MMC card or USB will require certain amount time to be made accessible or mounted. So use the 'rootdelay' boot argument to introduce a delay before kernel tries to mount the file system.
  • If the file system is corrupted then also this error would come up. So it is advisable to maintain a back up file system image to re-flash your storage if this happens.
  • Periodically run a fsck command on the file systems used including root file system.

Porting Android

Posted by Vaisakh P S On 7:54 PM 1 comments

Android build system by default generates few YAFF2 File system Images, which can be flashed on devices running in NAND flash. Since the platform which I was working on did not have a NAND flash on board. The images had be made available to Kernel in some other storage devices like NOR flash, SDCARD or USB Memory Stick.


There will be three out put images of the build process:
  • Root - A small image in order kilo bytes, with basic utilities and init script to bring rest of the system up.
  • System - Contains the Android specific programs and related libraries. The size will be some where around 40 to 50 Mega Bytes (for default configuration) depending on the build configuration.
  • Data - Will be a blank file system initially, but as system boots up, relevant information will added.
Like every other Linux Root file system image, there is an init script, (format is different from standard init script). Here comment out of the portion of script which mounts the yaffs2 file system like this:
#mount yaffs2 mtd@system /system
#mount yaffs2 mtd@system /system ro remount
#mount yaffs2 mtd@userdata /data nosuid nodev

For bringing up the required file system, an SDCARD base storage system was decided. The sdcard was partitioned in to four ext2 partitions. Here is the partition layout
Partition #1 : Root file system generated from BuildRoot
Partition #2 : Root file system generated from Android
Partition #3 : System partitions generated from Android
Partition #4 : Data partition to be used to Android.

The Linux system was be booted up with Partition#1 as root. Then Partitions 2, 3 and 4 are mounted like this
mount /dev/mmcblk0p2 /media/mmc
mount /dev/mmcblk0p3 /media/mmc/system
mount /dev/mmcblk0p4 /media/mmc/data
Using the 'chroot' command the root will be changed to Partition#2 hence initiating startup of Android:
chroot /media/mmc /init
NOTE

  • Ensure that the system and data directories are given global read, write and execute permission.
  • To interface touch screen with Android, make use modifications in Android Input System code to make use of the calibration corrections obtained using TsLib. (Refer previous post)

AT91SAM9g24 Board that was provided for hands-on





AT91SAM9g24 Board running MatchBox Window Manager

Making TsLib work in Android

Posted by Vaisakh P S On 7:47 AM 0 comments


For my initial porting of Android, I had to work on a PXA270 board with a WM9713 Codec IC. So here are the steps that I followed to make touch screen working properly. Initially, touchscreen values were not accepting properly by Android even though ts_calibrate and ts_test were working properly.

Modifying Touch Drivers
Modify the WM97XX and WM9713 driver to report pen down event properly to the event system.
diff --git a/drivers/input/touchscreen/wm9713.c b/drivers/input/touchscreen/wm9713.c
index 781ee83..055db86 100644
--- a/drivers/input/touchscreen/wm9713.c
+++ b/drivers/input/touchscreen/wm9713.c
@@ -14,6 +14,7 @@
* option) any later version.
*
*/
+#define DEBUG

#include

#include

@@ -54,7 +55,7 @@ MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect.");
* This is used to increase the range of values returned by the adc
* when measureing touchpanel pressure.
*/
-static int pil;
+static int pil = 1;
module_param(pil, int, 0);
MODULE_PARM_DESC(pil, "Set current used for pressure measurement.");

@@ -395,7 +396,6 @@ err:
static int wm9713_poll_touch(struct wm97xx *wm, struct wm97xx_data *data)
{
int rc;
-
if (coord) {
rc = wm9713_poll_coord(wm, data);
if (rc != RC_VALID)


diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c
index d589ab0..6859078 100644
--- a/drivers/input/touchscreen/wm97xx-core.c
+++ b/drivers/input/touchscreen/wm97xx-core.c
@@ -34,7 +34,7 @@
* - Support for async sampling control for noisy LCDs.
*
*/
-
+#define DEBUG
#include

#include

#include

@@ -392,7 +392,8 @@ static int wm97xx_init_pen_irq(struct wm97xx *wm)

return 0;
}

static int wm97xx_read_samples(struct wm97xx *wm)
{
struct wm97xx_data data;
@@ -410,6 +411,7 @@ static int wm97xx_read_samples(struct wm97xx *wm)
wm->pen_is_down = 0;
dev_dbg(wm->dev, "pen up\n");
input_report_abs(wm->input_dev, ABS_PRESSURE, 0);
+ input_report_key(wm->input_dev, BTN_TOUCH, wm->pen_is_down);
input_sync(wm->input_dev);
} else if (!(rc & RC_AGAIN)) {
/* We need high frequency updates only while
@@ -427,13 +429,30 @@ static int wm97xx_read_samples(struct wm97xx *wm)
}

} else if (rc & RC_VALID) {
input_report_abs(wm->input_dev, ABS_X, data.x & 0xfff);
input_report_abs(wm->input_dev, ABS_Y, data.y & 0xfff);
input_report_abs(wm->input_dev, ABS_PRESSURE, data.p & 0xfff);
+ wm->pen_is_down = 1;
+ input_report_key(wm->input_dev, BTN_TOUCH, wm->pen_is_down);
input_sync(wm->input_dev);
wm->pen_is_down = 1;
wm->ts_reader_interval = wm->ts_reader_min_interval;
@@ -630,9 +649,11 @@ static int wm97xx_probe(struct device *dev)
wm->input_dev->open = wm97xx_ts_input_open;
wm->input_dev->close = wm97xx_ts_input_close;
set_bit(EV_ABS, wm->input_dev->evbit);
+ set_bit(EV_KEY, wm->input_dev->evbit);
set_bit(ABS_X, wm->input_dev->absbit);
set_bit(ABS_Y, wm->input_dev->absbit);
set_bit(ABS_PRESSURE, wm->input_dev->absbit);
+ set_bit(BTN_TOUCH, wm->input_dev->keybit);
input_set_abs_params(wm->input_dev, ABS_X, abs_x[0], abs_x[1],
abs_x[2], 0);
input_set_abs_params(wm->input_dev, ABS_Y, abs_y[0], abs_y[1],


Use TsLib
Compile tslib using buildroot or something else and run it on the board with the parameters set:
export TSLIB_CONSOLEDEVICE=none
export TSLIB_FBDEVICE=/dev/fb0
export TSLIB_TSDEVICE=/dev/event0
export TSLIB_CALIBFILE=/etc/pointercal
export TSLIB_CONFFILE=/etc/ts.conf
export TSLIB_PLUGINDIR=/usr/lib/ts

After running ts_calibrate you will obtain 'pointercal' file with the corrections that needed to be applied for touchscreen values.






Modify Kernel Code
Change the kernel configuration to enable the following functionalities:

# Power management options
#
CONFIG_PM=y
CONFIG_PM_DEBUG=y
CONFIG_PM_VERBOSE=y
CONFIG_CAN_PM_TRACE=y
CONFIG_PM_SLEEP=y
CONFIG_SUSPEND=y
CONFIG_PM_TEST_SUSPEND=y
CONFIG_SUSPEND_FREEZER=y
CONFIG_HAS_WAKELOCK=y
CONFIG_HAS_EARLYSUSPEND=y
CONFIG_WAKELOCK=y
CONFIG_WAKELOCK_STAT=y
CONFIG_USER_WAKELOCK=y
CONFIG_EARLYSUSPEND=y

CONFIG_ANDROID_PMEM=y
CONFIG_ANDROID_TIMED_GPIO=y
CONFIG_BINDER_IPC=y

CONFIG_LOW_MEMORY_KILLER=y
CONFIG_LOGGER=y
CONFIG_ANDROID_RAM_CONSOLE=y
CONFIG_ANDROID_RAM_CONSOLE_ENABLE_VERBOSE=y
Modify Android Code
Apply the following patch to the Android Input management code. Copy the pointrecal file that you obtained from ts_calibrate to /system/etc/pointrecal
diff --git a/services/java/com/android/server/InputDevice.java b/services/java/com/android/server/InputDevice.java
index 6eb6242..f1ed013 100644
--- a/services/java/com/android/server/InputDevice.java
+++ b/services/java/com/android/server/InputDevice.java
@@ -22,6 +22,9 @@ import android.view.MotionEvent;
import android.view.Surface;
import android.view.WindowManagerPolicy;

+import java.io.FileInputStream;
+import java.util.StringTokenizer;
+
public class InputDevice {
static final boolean DEBUG_POINTERS = false;
static final boolean DEBUG_HACKS = false;
@@ -29,8 +32,10 @@ public class InputDevice {
/** Amount that trackball needs to move in order to generate a key event. */
static final int TRACKBALL_MOVEMENT_THRESHOLD = 6;

+ static final String CALIBRATION_FILE = "/system/etc/pointercal";
+
/** Maximum number of pointers we will track and report. */
- static final int MAX_POINTERS = 10;
+ static final int MAX_POINTERS = 2;

final int id;
final int classes;
@@ -39,6 +44,7 @@ public class InputDevice {
final AbsoluteInfo absY;
final AbsoluteInfo absPressure;
final AbsoluteInfo absSize;
+ final TransformInfo tInfo;

long mKeyDownTime = 0;
int mMetaKeysState = 0;
@@ -595,15 +601,29 @@ public class InputDevice {
final AbsoluteInfo absSize = device.absSize;
for (int i=0; i 0) {
+ int i;
+ for (i = 0 ; i < len =" i;" st =" new" t =" new" x1 =" Integer.parseInt(" y1 =" Integer.parseInt(" z1 =" Integer.parseInt(" x2 =" Integer.parseInt(" y2 =" Integer.parseInt(" z2 =" Integer.parseInt(" s =" Integer.parseInt(" tinfo =" t;" debug =" false;" debug_virtual_keys =" false;" debug_pointers =" false;" debug_pointers =" true;" bad_touch_hack =" true;" bad_touch_hack =" false;" excluded_devices_path = "etc/excluded-input-devices.xml" max_processes =" 2;" max_processes =" 10;">

There you have it a calibrated touchscreen working in Android.

I was able to make this work because of lot of work I found online in discussion forums and blogs. Here are the reference to their work:

  • http://groups.google.com/group/android-internals/browse_thread/thread/25a8ccefeb362fd1/8705c88c4b68ab8a?#8705c88c4b68ab8a
  • http://groups.google.com/group/android-porting/browse_thread/thread/fd1bb870ce8d7b2d/45be0fd8eb43d59a?#45be0fd8eb43d59a
  • http://groups.google.com/group/android-porting/browse_thread/thread/211d654dbd0f3f99/2d34279ae278f135?lnk=gst&q=touch+calibration#2d34279ae278f135
  • http://groups.google.com/group/android-porting/browse_thread/thread/fb64af66b1f877fa/8708ab0ea2b9b545?hl=en&lnk=gst&q=touch+screen+top+bar#
  • http://groups.google.com/group/android-porting/browse_thread/thread/9ea3b46fe87d1e3/589c7c6ebd238755?lnk=gst&q=touch+calibration#
  • http://groups.google.com/group/android-porting/browse_thread/thread/9ea3b46fe87d1e3/589c7c6ebd238755?lnk=gst&q=touch+calibration#
  • http://www.opentom.org/Tslib
  • http://androidzaurus.seesaa.net/article/96581331.html

  • Boot loader Porting

    Posted by Vaisakh P S On 6:13 AM 0 comments

    In comparison to Windows CE, in Linux, we have many choices of boot loaders available today. U-Boot [V] is one of most commonly used boot loader in development phase, as it provides with a wide array of features which a developer can make use of. Before starting off with kernel porting these are the features that needs to bring up in U-boot.

    · Debug Consoles – Preferably a serial UART. In u-boot configuration header, the stdin, stdout and stderr need to be specified. In case of our platform, the debug console has been directed to FFUART. Also baud rate of the serial UART connection needs to be configured.

    · Ethernet connection – In initial stages of porting, the kernel image can be transferred over Ethernet instead of flashing on to a ROM. In case of our platform, Ethernet connectivity is provided through the debug card. Enable the use of SMC911X driver in configuration header and set the associated configurations such as Ethernet MAC, Base address, 16-bit or 32-bit Bus mode etc too.

    · Initialization of Memory System – Both boot loader and operating system will be executing in RAM. So RAM needs to initialized to proper timings and U-Boot should be made aware of available RAM though the configuration header.

    · TFTP Server Settings – The IP address of TFTP server along needs to be specified to fetch the kernel image.

    · Kernel Boot arguments – All information of hardware like available RAM, MTD partitions etc are passed on to the kernel as ATAG list. Some of the major arguments that needs to be passed on the kernel are:

    ◦ Kernel default console

    ◦ Root file system path

    ◦ Initrd to use (optional)

    ◦ Display

    ◦ Init Path

    The purpose of each of these arguments will be explained in subsequent sections.

    Notes

    · While loading OS Image and other File system images over Ethernet or any other medium, pay attention to the load address, make sure that they are not over lapping.

    · It is advisable to make the root file system as Read-only while mounting or in Bootargs to avoid corruption. This will enable bringing up the system with a basic environment.