GrabDuck

Android系统移植技术详解_木子的忧伤_新浪博客

:

,为挂载参数,距离如下:
    mount ubifs ubi1_0 /data nosuid nodev

setkey
暂时未定义

setprop
设置名为的系统属性的值为

setrlimit
设置资源限制,举例:
# set RLIMIT_NICE to allow priorities from 19 to -20
   setrlimit 13 40 40
没看懂是什么意思。

start
启动服务(如果服务未运行)

stop
停止服务(如果服务正在运行)

symlink
创建一个从指向的符号链接,举例:
   symlink /system/etc /etc

write [ ]*
打开路径为的文件并将一个多这多个字符串写入到该文件中。

(g)系统属性(Property)
android初始化过程中会修改一些属性,通过getprop命令我们可以看到属性值,这些属性指示了某些动作或者服务的状态,主要如下:
init.action      如果当前某个动作正在执行则init.action属性的值等于该动作的名称,否则为""
init.command     如果当前某个命令正在执行则init.command属性的值等于该命令的名称,否则为""
init.svc.  此属性指示个名为的服务的状态("stopped", "running", 或者 "restarting").

android系统开发(四)-触摸屏tslib移植(内核)和原理分析
首先了解一下tslib的运行原理,tslib的运行分成两部分
(1)校验
在LCD固定坐标位置依次显示出5个坐标让用户触摸,把LCD坐标和用户触摸时驱动屏驱动底层的坐标总共5组值保存起来
运行tslib库的算法对其进行运算,得出校准用7个值

(2)校准
每次触摸屏驱动读取到硬件坐标时应用校准用的7个值对该坐标进行一次运算,然后将运算后的坐标作为正常坐标即可。

按照上面的原理,
(1)我们先修改内核部分,我的平台用的触摸屏幕驱动是tsc2007,驱动文件为内核/drivers/input/touchscreen
目录下的tsc2007.c和ts_linear.c
其中,ts_linear.c中定义的是校准模块,该模块在proc文件系统中建立了7个文件,用来存放校准用的7个点,7的点的默认值
为1,0,0,0,1,0,1,对应的目标平台文件系统的位置为/proc/sys/dev/ts_device目录下a0,a1,a2,a3,a4,a5,a6等7个文件
此模块中还定义了一个校准函数ts_linear_scale,此函数的主要内容是读取a0,a1,a2,a3,a4,a5,a6等7个文件中的值作为7个
校准值与传入的触摸平坐标值进行运算,返回运算结果。
ts_linear_scale函数定义如下:
int ts_linear_scale(int *x, int *y, int swap_xy)
{
   int xtemp, ytemp;

    xtemp = *x;
   ytemp = *y;

    if (cal.a[6] == 0)
       return -EINVAL;

    *x = (cal.a[2] + cal.a[0] * xtemp + cal.a[1] * ytemp) / cal.a[6];
   *y = (cal.a[5] + cal.a[3] * xtemp + cal.a[4] * ytemp) / cal.a[6];

    if (swap_xy) {
       int tmp = *x;
       *x = *y;
       *y = tmp;
   }
   return 0;
}

ts2007.c为触摸屏驱,与其他驱动不同的地方是在取得硬件坐标值发送之前先调用了ts_linear_scale函数对坐标值进行了校准
           if (x > 0 && y > 0)
           {
               ts_linear_scale(&x, &y, invert);
               input_report_abs(input, ABS_X, x);
               input_report_abs(input, ABS_Y, y);
               input_report_abs(input, ABS_PRESSURE, 255);
               input_report_abs(input, ABS_TOOL_WIDTH, 1);
               input_report_key(input, BTN_TOUCH, 1);
               input_sync(input);
           }

(2)在android源代码/system/core/rootdir/init.rc文件中添加tslib相关的宏定义如下:
# touchscreen parameters
   export TSLIB_FBDEVICE /dev/graphics/fb0
   export TSLIB_CALIBFILE /data/etc/pointercal
   export TSLIB_CONFFILE  /system/etc/ts.conf
   export TSLIB_TRIGGERDEV /dev/input/event0
   export TSLIB_TSDEVICE /dev/input/event1

(2)移植tslib库到android系统,比较麻烦,看下一节的内容。

(3)校验程序完成后会将生成的7个校准值写入到环境变量TSLIB_CALIBFILE对应的路径/data/etc/pointercal文件中

(4)校验完后将pointercal文件中的7个值分别写入到/proc/sys/dev/ts_device目录下a0,a1,a2,a3,a4,a5,a6文件即可。

(5)开机启动的时候我们编写一个应用程序,首先判断环境变量TSLIB_CALIBFILE对应的路径/data/etc/pointercal文件是否存在,如果
文件存在而且非空,则将该文件中的7个值取出来分别写入到/proc/sys/dev/ts_device目录下a0,a1,a2,a3,a4,a5,a6文件

(6)为了确保未校验前触摸屏可用,我们将一次校验后得出的7个坐标值作为初始值,修改到内核ts_linear.c文件中。

下面是源代码:
ts_linear.c文件

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include


static struct ts_calibration {

    int a[7];
} cal;

static ctl_table ts_proc_calibration_table[] = {
   {
    .ctl_name = CTL_UNNUMBERED,
    .procname = "a0",
    .data = &cal.a[0],
    .maxlen = sizeof(int),
    .mode = 0666,
    .proc_handler = &proc_dointvec,
    },
   {
    .ctl_name = CTL_UNNUMBERED,
    .procname = "a1",
    .data = &cal.a[1],
    .maxlen = sizeof(int),
    .mode = 0666,
    .proc_handler = &proc_dointvec,
    },
   {
    .ctl_name = CTL_UNNUMBERED,
    .procname = "a2",
    .data = &cal.a[2],
    .maxlen = sizeof(int),
    .mode = 0666,
    .proc_handler = &proc_dointvec,
    },
   {
    .ctl_name = CTL_UNNUMBERED,
    .procname = "a3",
    .data = &cal.a[3],
    .maxlen = sizeof(int),
    .mode = 0666,
    .proc_handler = &proc_dointvec,
    },
   {
    .ctl_name = CTL_UNNUMBERED,
    .procname = "a4",
    .data = &cal.a[4],
    .maxlen = sizeof(int),
    .mode = 0666,
    .proc_handler = &proc_dointvec,
    },
   {
    .ctl_name = CTL_UNNUMBERED,
    .procname = "a5",
    .data = &cal.a[5],
    .maxlen = sizeof(int),
    .mode = 0666,
    .proc_handler = &proc_dointvec,
    },
   {
    .ctl_name = CTL_UNNUMBERED,
    .procname = "a6",
    .data = &cal.a[6],
    .maxlen = sizeof(int),
    .mode = 0666,
    .proc_handler = &proc_dointvec,
    },

    {.ctl_name = 0}
};

static ctl_table ts_proc_root[] = {
   {
    .ctl_name = CTL_UNNUMBERED,
    .procname = "ts_device",
    .mode = 0555,
    .child = ts_proc_calibration_table,
    },
   {.ctl_name = 0}
};

static ctl_table ts_dev_root[] = {
   {
    .ctl_name = CTL_DEV,
    .procname = "dev",
    .mode = 0555,
    .child = ts_proc_root,
    },
   {.ctl_name = 0}
};

static struct ctl_table_header *ts_sysctl_header;

int ts_linear_scale(int *x, int *y, int swap_xy)
{
   int xtemp, ytemp;

    xtemp = *x;
   ytemp = *y;

    if (cal.a[6] == 0)
       return -EINVAL;

    *x = (cal.a[2] + cal.a[0] * xtemp + cal.a[1] * ytemp) / cal.a[6];
   *y = (cal.a[5] + cal.a[3] * xtemp + cal.a[4] * ytemp) / cal.a[6];

    if (swap_xy) {
       int tmp = *x;
       *x = *y;
       *y = tmp;
   }
   return 0;
}

EXPORT_SYMBOL(ts_linear_scale);

static int __init ts_linear_init(void)
{
   ts_sysctl_header = register_sysctl_table(ts_dev_root);
  
   cal.a[0] = 1;
   cal.a[1] = 0;
   cal.a[2] = 0;
   cal.a[3] = 0;
   cal.a[4] = 1;
   cal.a[5] = 0;
   cal.a[6] = 1;
   return 0;
}

static void __exit ts_linear_cleanup(void)
{
   unregister_sysctl_table(ts_sysctl_header);
}

module_init(ts_linear_init);
module_exit(ts_linear_cleanup);

MODULE_DESCRIPTION("touch screen linear scaling driver");
MODULE_LICENSE("GPL");

 

ts2007.c文件

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#include
#include

extern int ts_linear_scale(int *x, int *y, int swap_xy);


#define TSC_CMD_SETUP 0xb0


#define TSC_CMD_X 0xc0
#define TSC_CMD_PLATEX 0x80
#define TSC_CMD_Y 0xd0
#define TSC_CMD_PLATEY 0x90

#define TSC_X_MAX 4096
#define TSC_Y_MAX 4096
#define TSC_X_MIN 0
#define TSC_Y_MIN 0

#define DEBUG
#ifdef DEBUG
#define TS_DEBUG(fmt,args...) printk(KERN_DEBUG fmt, ##args )
#else
#define TS_DEBUG(fmt,args...)
#endif
static int x_min=TSC_X_MIN;
static int y_min=TSC_Y_MIN;
static int x_max=TSC_X_MAX;
static int y_max=TSC_Y_MAX;
static int invert = 0;
static int debounce_time  = 150;
static int init_debounce = true;
static int delay_time = 1;

enum tsc2007_status {
   PEN_UP,
   PEN_DOWN,
};

struct _tsc2007 {
   struct input_dev *dev;
   int x;       
   int y;       

    int status;
   struct work_struct irq_work;
   struct i2c_client *client;
   unsigned long last_touch;
};
struct _tsc2007 *g_tsc2007;


int tsc2007_proc_minmax(struct ctl_table *table, int write, struct file *filp,
                    void __user *buffer, size_t *lenp, loff_t *ppos)
{
   struct _tsc2007 *tsc2007= g_tsc2007;
   struct input_dev *input = tsc2007->dev;

   
   int ret = proc_dointvec(table, write, filp, buffer, lenp, ppos);

   
   if (input) {
       TS_DEBUG(KERN_DEBUG "update x_min %d x_max %d"
           " y_min %d y_max %d\n", x_min, x_max,
           y_min, y_max);
       input_set_abs_params(input, ABS_X, x_min, x_max, 0, 0);
       input_set_abs_params(input, ABS_Y, y_min, y_max, 0, 0);
   }
   return ret;
}

static ctl_table tsc2007_proc_table[] = {
   {
       .ctl_name    = CTL_UNNUMBERED,
       .procname    = "x-max",
       .data        = &x_max,
       .maxlen        = sizeof(int),
       .mode        = 0666,
       .proc_handler    = &tsc2007_proc_minmax,
   },
   {
       .ctl_name    = CTL_UNNUMBERED,
       .procname    = "y-max",
       .data        = &y_max,
       .maxlen        = sizeof(int),
       .mode        = 0666,
       .proc_handler    = &tsc2007_proc_minmax,
   },
   {
       .ctl_name    = CTL_UNNUMBERED,
       .procname    = "x-min",
       .data        = &x_min,
       .maxlen        = sizeof(int),
       .mode        = 0666,
       .proc_handler    = &tsc2007_proc_minmax,
   },
   {
       .ctl_name    = CTL_UNNUMBERED,
       .procname    = "y-min",
       .data        = &y_min,
       .maxlen        = sizeof(int),
       .mode        = 0666,
       .proc_handler    = &tsc2007_proc_minmax,
   },
   {
       .ctl_name    = CTL_UNNUMBERED,
       .procname    = "invert_xy",
       .data        = &invert,
       .maxlen        = sizeof(int),
       .mode        = 0666,
       .proc_handler    = &proc_dointvec,
   },
   {
       .ctl_name    = CTL_UNNUMBERED,
       .procname    = "debounce_time",
       .data        = &debounce_time,
       .maxlen        = sizeof(int),
       .mode        = 0666,
       .proc_handler    = &proc_dointvec,
   },
   {
       .ctl_name    = CTL_UNNUMBERED,
       .procname    = "delay_time",
       .data        = &delay_time,
       .maxlen        = sizeof(int),
       .mode        = 0666,
       .proc_handler    = &proc_dointvec,
   },
   { .ctl_name = 0 }
};

static ctl_table tsc2007_proc_root[] = {
   {
       .ctl_name    = CTL_UNNUMBERED,
       .procname    = "ts_device",
       .mode        = 0555,
       .child        = tsc2007_proc_table,
   },
   { .ctl_name = 0 }
};

static ctl_table tsc2007_proc_dev_root[] = {
   {
       .ctl_name    = CTL_DEV,
       .procname    = "dev",
       .mode        = 0555,
       .child        = tsc2007_proc_root,
   },
   { .ctl_name = 0 }
};

static struct ctl_table_header *sysctl_header;

static int __init init_sysctl(void)
{
   sysctl_header = register_sysctl_table(tsc2007_proc_dev_root);
   return 0;
}

static void __exit cleanup_sysctl(void)
{
   unregister_sysctl_table(sysctl_header);
}

static int tsc2007_measure(struct i2c_client *client, int *x, int * y)
{
   u8 x_buf[2] = {0, 0};
   u8 y_buf[2] = {0, 0};

    i2c_smbus_write_byte(client, TSC_CMD_PLATEX);
   msleep_interruptible(delay_time);

    i2c_smbus_write_byte(client, TSC_CMD_X);
   i2c_master_recv(client, x_buf, 2);
   *x = (x_buf[0]<<4) | (x_buf[1] >>4);

    i2c_smbus_write_byte(client, TSC_CMD_PLATEY);
   msleep_interruptible(delay_time);

    i2c_smbus_write_byte(client, TSC_CMD_Y);
   i2c_master_recv(client, y_buf, 2);
   *y = (y_buf[0]<<4) | (y_buf[1] >>4);
   *y = 4096 - *y; //added by allen
   printk("\ntouchscreen x = 0x%x, y = 0x%x\n",*x,*y);
   return 0;
}

static void tsc2007_irq_work(struct work_struct *work)
{
   struct _tsc2007 *tsc2007= g_tsc2007;
   struct i2c_client *client = tsc2007-> client;
   struct input_dev *input = tsc2007->dev;

    int x = -1, y = -1, is_valid = 0;
   int tmp_x = 0, tmp_y = 0;

    int gpio = irq_to_gpio(client->irq);


  
   if(PEN_UP == tsc2007->status){

        if (gpio_request(gpio, "tsc2007 touch detect")) {
           printk(KERN_ERR "Request GPIO failed, gpio: %X\n", gpio);
           return;
       }
       gpio_direction_input(gpio);   
      
       while(0 == gpio_get_value(gpio)){

                        if ((jiffies_to_msecs(
                               ((long)jiffies - (long)tsc2007->last_touch)) <<BR>                 debounce_time &&
               tsc2007->status == PEN_DOWN) ||
               init_debounce)
                       {
               init_debounce = false;
                               tsc2007_measure(client, &tmp_x, &tmp_y);
                               TS_DEBUG(KERN_DEBUG
               "dropping pen touch %lu %lu (%u)\n",
                               jiffies, tsc2007->last_touch,
                               jiffies_to_msecs(
               (long)jiffies - (long)tsc2007->last_touch));
                               schedule();
               continue;
                       }


          
           if (x > 0 && y > 0)
           {
               ts_linear_scale(&x, &y, invert);
               input_report_abs(input, ABS_X, x);
               input_report_abs(input, ABS_Y, y);
               input_report_abs(input, ABS_PRESSURE, 255);
               input_report_abs(input, ABS_TOOL_WIDTH, 1);
               input_report_key(input, BTN_TOUCH, 1);
               input_sync(input);
           }

            tsc2007->status = PEN_DOWN;
           tsc2007_measure(client, &x, &y);
           TS_DEBUG(KERN_DEBUG "pen down x=%d y=%d!\n", x, y);
           is_valid = 1;
           schedule();
       }

        if (is_valid)
       {
          
           tsc2007->status = PEN_UP;
           input_report_abs(input, ABS_PRESSURE, 0);
           input_report_abs(input, ABS_TOOL_WIDTH, 1);
           input_report_key(input, BTN_TOUCH, 0);
           input_sync(input);
           tsc2007->last_touch = jiffies;
           TS_DEBUG(KERN_DEBUG "pen up!\n");
       }

        gpio_free(gpio);   
   }
}

static irqreturn_t tsc2007_interrupt(int irq, void *dev_id)
  
   schedule_work(&g_tsc2007->irq_work);
  
   return IRQ_HANDLED;
}

static int __devinit tsc2007_probe(struct i2c_client *client,
               const struct i2c_device_id *id)
{
   struct _tsc2007 *tsc2007;
   struct input_dev *input_dev;
   int ret;

    tsc2007 = kzalloc(sizeof(struct _tsc2007), GFP_KERNEL);
   input_dev = input_allocate_device();

    g_tsc2007 = tsc2007;

    if (!tsc2007 || !input_dev) {
       ret = -ENOMEM;
       goto fail1;
   }

    i2c_set_clientdata(client, tsc2007);

    tsc2007->dev = input_dev;

    input_dev->name = "tsc2007";
   input_dev->phys = "tsc2007/input0";

    //input_dev->id.bustype = BUS_HOST;
   input_dev->dev.parent = &client->dev;

    __set_bit(EV_KEY, input_dev->evbit);
   __set_bit(BTN_TOUCH, input_dev->keybit);

    __set_bit(EV_ABS, input_dev->evbit);
   __set_bit(ABS_PRESSURE, input_dev->evbit);
   __set_bit(ABS_X, input_dev->evbit);
   __set_bit(ABS_Y, input_dev->evbit);

    input_set_abs_params(input_dev, ABS_X, x_min, x_max, 0, 0);
   input_set_abs_params(input_dev, ABS_Y, y_min, y_max, 0, 0);
   input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0);

    ret = request_irq(client->irq, tsc2007_interrupt,
       IRQF_DISABLED | IRQF_TRIGGER_FALLING,
        "tsc2007 irq", NULL);
   if (ret){
       printk(KERN_ERR "tsc2007 request irq failed\n");
       goto fail2;
   }

    ret = input_register_device(tsc2007->dev);
   if (ret){
       printk(KERN_ERR "tsc2007 register device fail\n");
       goto fail2;
   }

   
   tsc2007->status = PEN_UP;
   tsc2007->client = client;
   tsc2007->last_touch = jiffies;

    INIT_WORK(&tsc2007->irq_work, tsc2007_irq_work);

   
   i2c_smbus_write_byte(client, TSC_CMD_SETUP);

    return 0;

 fail2:
   free_irq(client->irq, client);
fail1:
   i2c_set_clientdata(client, NULL);
   input_free_device(input_dev);
   kfree(tsc2007);
   return ret;
}

static int __devexit tsc2007_remove(struct i2c_client *client)
{
   struct _tsc2007 *tsc2007 = i2c_get_clientdata(client);

    if(client->irq)
       free_irq(client->irq, client);
  
   i2c_set_clientdata(client, NULL);
   input_unregister_device(tsc2007->dev);
   kfree(tsc2007);

    return 0;
}

static struct i2c_device_id tsc2007_idtable[] = {
   { "tsc2007", 0 },
   { }
};

MODULE_DEVICE_TABLE(i2c, tsc2007_idtable);

static struct i2c_driver tsc2007_driver = {
   .driver = {
       .name     = "tsc2007",
   },
   .id_table       = tsc2007_idtable,
   .probe        = tsc2007_probe,
   .remove        = __devexit_p(tsc2007_remove),
};

static int __init tsc2007_ts_init(void)
{
   init_sysctl();
   return i2c_add_driver(&tsc2007_driver);    
}

static void __exit tsc2007_ts_exit(void)
{
   cleanup_sysctl();
   i2c_del_driver(&tsc2007_driver);
}

module_init(tsc2007_ts_init);
module_exit(tsc2007_ts_exit);

MODULE_DESCRIPTION("tsc2007 touch screen driver");
MODULE_LICENSE("GPL");

android系统开发(五)-tslib移植
(1)切换至tslib目录然后执行如下命令(以marvell平台为例)
./autogen.sh
echo "ac_cv_func_malloc_0_nonnull=yes" > arm-marvell-linux.cache
./configure --host=arm-marvell-linux-gnueabi --prefix=/work/svn/ts_build --cache-file=arm-marvell-linux.cache
上面三步仅仅是为了取得tslib目录下的config.h文件

(2)将tslib复制到android源代码vendor//目录下

(3)修改vendor//目录下的AndroidBoard.mk文件,加入如下内容
include $(LOCAL_PATH)/tslib/Mdroid.mk
一定要主义LOCAL_PATH这个宏的时效性

(4)在tslib目录下创建Mdroid.mk,内容如下:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

TS_PATH := $(LOCAL_PATH)

include $(TS_PATH)/src/Mdroid.mk
include $(TS_PATH)/plugins/Mdroid.mk
include $(TS_PATH)/tests/Mdroid.mk

include $(CLEAR_VARS)
file := $(TARGET_OUT_ETC)/ts.conf
$(file) : $(TS_PATH)/etc/ts.conf | $(ACP)
   $(transform-prebuilt-to-target)
ALL_PREBUILT += $(file)


(5)在tslib/src目录下创建Mdroid.mk,内容如下:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= ts_attach.c ts_close.c ts_config.c \
   ts_error.c ts_fd.c ts_load_module.c ts_open.c ts_parse_vars.c \
   ts_read.c ts_read_raw.c ts_option.c

LOCAL_C_INCLUDES += \
       $(LOCAL_PATH)/../

LOCAL_SHARED_LIBRARIES += libutils libcutils

LOCAL_SHARED_LIBRARIES += libdl
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := libts

include $(BUILD_SHARED_LIBRARY)


(6)在tslib/plugins目录下创建Mdroid.mk,内容如下:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= input-raw.c

LOCAL_C_INCLUDES += \
       $(LOCAL_PATH)/../ \
       $(LOCAL_PATH)/../src

LOCAL_SHARED_LIBRARIES := libts
LOCAL_MODULE := input
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)


include $(CLEAR_VARS)
LOCAL_SRC_FILES:= pthres.c

LOCAL_C_INCLUDES += \
       $(LOCAL_PATH)/../ \
       $(LOCAL_PATH)/../src

LOCAL_SHARED_LIBRARIES := libts
LOCAL_MODULE := pthres
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)


include $(CLEAR_VARS)
LOCAL_SRC_FILES:= variance.c

LOCAL_C_INCLUDES += \
       $(LOCAL_PATH)/../ \
       $(LOCAL_PATH)/../src

LOCAL_SHARED_LIBRARIES := libts
LOCAL_MODULE := variance
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)


include $(CLEAR_VARS)
LOCAL_SRC_FILES:= dejitter.c

LOCAL_C_INCLUDES += \
       $(LOCAL_PATH)/../ \
       $(LOCAL_PATH)/../src

LOCAL_SHARED_LIBRARIES := libts
LOCAL_MODULE := dejitter
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_SRC_FILES:= linear.c

LOCAL_C_INCLUDES += \
       $(LOCAL_PATH)/../ \
       $(LOCAL_PATH)/../src

LOCAL_SHARED_LIBRARIES := libts
LOCAL_MODULE := linear
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)


(7)在tslib/tests目录下创建Mdroid.mk,内容如下:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= ts_calibrate.c fbutils.c testutils.c font_8x8.c font_8x16.c

LOCAL_C_INCLUDES += \
       $(LOCAL_PATH)/../ \
       $(LOCAL_PATH)/../src

LOCAL_SHARED_LIBRARIES := libts

LOCAL_SHARED_LIBRARIES += libutils libcutils

LOCAL_MODULE := tscalibrate

include $(BUILD_EXECUTABLE)


(8)在tslib/config.h文件中加入如下定义:
#define TS_CONF  "/system/etc/ts.conf"
#define PLUGIN_DIR "/system/lib"
#define TS_POINTERCAL "/data/etc/pointercal"


(9)将下面路径文件
tslib/src/ts_open.c
tslib/tests/ts_calibrate.c
tslib/tests/fbutils.c
中的
#include
修改成
#include

(10)将tslib/tests/ts_calibrate.c文件中
static int clearbuf(struct tsdev *ts)
修改为
static void clearbuf(struct tsdev *ts)

(11)修改tslib/etc/ts.conf内容如下:
module_raw input
module pthres pmin=1
module variance delta=30
module dejitter delta=100
module linear

(12)在android源代码init.rc中声明tslib相关的宏如下:
# touchscreen parameters
   export TSLIB_FBDEVICE /dev/graphics/fb0
   export TSLIB_CALIBFILE /data/etc/pointercal
   export TSLIB_CONFFILE  /system/etc/ts.conf
   export TSLIB_TRIGGERDEV /dev/input/event0
   export TSLIB_TSDEVICE /dev/input/event1

(13)重新编译后即可调用tscalibrate命令来校验触摸屏,校验后产生一个/data/etc/pointercal文件

Ubuntu下svn安装和使用
1 第一步:安装软件。
安装客户端
sudo apt-get install subversion
安装服务器端
sudo apt-get install libapache2-svn


2 svn的基本操作
(1)从服务器上下载代码:svn checkout
举例:
svn checkout svn://192.168.6.10/project/Source_code/trunk/src
svn checkout可以所写成svn co

(2)添加新的文件或者文件夹到本地版本控制中
svn add 文件(夹)
如果指定的是一个文件夹,则会将文件夹的所有内容都添加进来,如果你只想要添加文件夹而不是文件夹里面的内容,则用如下参数
svn add --non-recursive 目录名

(3)提交本地更改到服务器
svn commit -m "说明信息" [-N] [--no-unlock] [文件(夹)]
文件(夹)不填写则代码提交当前目录下(包含子目录)的所有更改
举例:
svn commit -m "modify some code"

(4)显示本地修改状态
svn status [path]缩写成svn st [path]
path为空则代码显示当前目录下的所有修改文件(递归到子目录)的状态,状态显示如下:
? 不在svn控制中
M 内容被修改
C 发生冲突
A 预定加入到版本库中
K 被锁定
举例:svn st

(5)显示指定目录下所有文件(递归到子目录)的状态
svn status -v [path] 缩写成svn st -v [path]

(6)同步服务器代码到本地仓库
svn up

(7)显示指定目录下的文件和目录
svn list [path]缩写成svn ls [path]

(8)恢复本地修改(撤销指定目录下的未提交的所有修改)
svn revert path [--depth infinity]

(9)删除文件(夹)
svn delete 文件(夹)


3 svn的配置文件
修改/root/.subversion目录下的config文件。
比如说修改svn所控制的文件类型,则可以修改config文件中的global-ignores参数,这个参数是指定了svn版本控制忽略的
文件类型,举例如下:
global-ignores = *.o *.lo *.la *.al .[0-9]* *.a *.pyc *.pyo

android系统开发(六)-HAL层开发基础

 


Android HAL层,即硬件抽象层,是Google响应厂家“希望不公开源码”的要求推出的新概念

1,源代码和目标位置

源代码: /hardware/libhardware目录,该目录的目录结构如下:

/hardware/libhardware/hardware.c编译成libhardware.so,目标位置为/system/lib目录

/hardware/libhardware/include/hardware目录下包含如下头文件:

hardware.h 通用硬件模块头文件

copybit.h copybit模块头文件

gralloc.h gralloc模块头文件

lights.h 背光模块头文件

overlay.h overlay模块头文件

qemud.h qemud模块头文件

sensors.h 传感器模块头文件

/hardware/libhardware/modules目录下定义了很多硬件模块

这些硬件模块都编译成xxx.xxx.so,目标位置为/system/lib/hw目录

 


2,HAL层的实现方式

JNI->通用硬件模块->硬件模块->内核驱动接口

具体一点:JNI->libhardware.so->xxx.xxx.so->kernel

具体来说:android frameworks中JNI调用/hardware/libhardware/hardware.c中定义的hw_get_module函数来获取硬件模块,

然后调用硬件模块中的方法,硬件模块中的方法直接调用内核接口完成相关功能

 


3,通用硬件模块(libhardware.so)

(1)头文件为:/hardware/libhardware/include/hardware/hardware.h

头文件中主要定义了通用硬件模块结构体hw_module_t,声明了JNI调用的接口函数hw_get_module

hw_module_t定义如下:

typedef struct hw_module_t {

uint32_t tag;

 

uint16_t version_major;

 

uint16_t version_minor;

 

const char *id;

 

const char *name;

 

const char *author;

 

struct hw_module_methods_t* methods; //硬件模块的方法

 

void* dso;

 

uint32_t reserved[32-7];

 


} hw_module_t;

硬件模块方法结构体hw_module_methods_t定义如下:

typedef struct hw_module_methods_t {

int (*open)(const struct hw_module_t* module, const char* id,

struct hw_device_t** device);

 


} hw_module_methods_t;

只定义了一个open方法,其中调用的设备结构体参数hw_device_t定义如下:

typedef struct hw_device_t {

uint32_t tag;

 

uint32_t version;

 

struct hw_module_t* module;

 

uint32_t reserved[12];

 

int (*close)(struct hw_device_t* device);

 


} hw_device_t;

hw_get_module函数声明如下:

int hw_get_module(const char *id, const struct hw_module_t **module);

参数id为模块标识,定义在/hardware/libhardware/include/hardware目录下的硬件模块头文件中,

参数module是硬件模块地址,定义了/hardware/libhardware/include/hardware/hardware.h中

 


(2)hardware.c中主要是定义了hw_get_module函数如下:

#define HAL_LIBRARY_PATH "/system/lib/hw"

static const char *variant_keys[] = {

"ro.hardware",

"ro.product.board",

"ro.board.platform",

"ro.arch"

};

static const int HAL_VARIANT_KEYS_COUNT =

(sizeof(variant_keys)/sizeof(variant_keys[0]));

 


int hw_get_module(const char *id, const struct hw_module_t **module)

{

int status;

int i;

const struct hw_module_t *hmi = NULL;

char prop[PATH_MAX];

char path[PATH_MAX];

for (i=0 ; i

{

if (i < HAL_VARIANT_KEYS_COUNT)

{

if (property_get(variant_keys[i], prop, NULL) == 0)

{

continue;

}

snprintf(path, sizeof(path), "%s/%s.%s.so",

HAL_LIBRARY_PATH, id, prop);

}

else

{

snprintf(path, sizeof(path), "%s/%s.default.so",

HAL_LIBRARY_PATH, id);

}

if (access(path, R_OK))

{

continue;

}

break;

}

 


status = -ENOENT;

if (i < HAL_VARIANT_KEYS_COUNT+1) {

status = load(id, path, module);

}

 


return status;

}

从源代码我们可以看出,hw_get_module完成的主要工作是根据模块id寻找硬件模块动态连接库地址,然后调用load函数去打开动态连接库

并从动态链接库中获取硬件模块结构体地址。硬件模块路径格式如下:

HAL_LIBRARY_PATH/id.prop.so

HAL_LIBRARY_PATH定义为/system/lib/hw

id是hw_get_module函数的第一个参数所传入,prop部分首先按照variant_keys数组中的名称逐一调用property_get获取对应的系统属性,

然后访问HAL_LIBRARY_PATH/id.prop.so,如果找到能访问的就结束,否则就访问HAL_LIBRARY_PATH/id.default.so

举例如下:

假定访问的是背光模块,id定义为"lights"则系统会按照如下的顺序去访问文件:

/system/lib/hw/lights.[ro.hardware属性值].so

/system/lib/hw/lights.[ro.product.board属性值].so

/system/lib/hw/lights.[ro.board.platform属性值].so

/system/lib/hw/lights.[ro.arch属性值].so

/system/lib/hw/lights.default.so

所以开发硬件模块的时候Makefile文件(Android.mk)中模块的命名LOCAL_MODULE要参考上面的内容,否则就会访问不到没作用了。

 


load函数的关键部分代码如下:

handle = dlopen(path, RTLD_NOW); //打开动态链接库

if (handle == NULL) {

char const *err_str = dlerror();

LOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");

status = -EINVAL;

goto done;

}

 


const char *sym = HAL_MODULE_INFO_SYM_AS_STR;

hmi = (struct hw_module_t *)dlsym(handle, sym); //从动态链接库中获取硬件模块结构体的指针

if (hmi == NULL) {

LOGE("load: couldn't find symbol %s", sym);

status = -EINVAL;

goto done;

}

HAL_MODULE_INFO_SYM_AS_STR是硬件模块在动态链接库中的标志,定义在hardware.h中如下:

#define HAL_MODULE_INFO_SYM HMI

#define HAL_MODULE_INFO_SYM_AS_STR "HMI"

 


4,硬件模块

硬件模块的开发主要是完成/hardware/libhardware/include/hardware目录下对应的头文件中的内容,主要是硬件模块头文件和hardware.h中

的结构体中定义了一些函数指针,调用内核提供的接口将具体的函数实现,然后编译成指定名称的动态链接库放到/system/lib/hw目录下即可。

用一句话来概括:硬件模块的开发就是定义一个hardware.h中定义的hw_module_t结构体,结构体名称为宏HAL_MODULE_INFO_SYM,然后实现结构体

的相关内容即可。

 


5,内核驱动

主要是要向用户层开放接口,让硬件模块和内核可以交互。

 


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jiajie961/archive/2010/11/22/6026585.aspx

 


android系统开发(七)-背光模块
1,总论

背光模块属于HAL层开发,HAL层开发,用一句话来概括就是定义一个hardware.h中定义的名称为宏HAL_MODULE_INFO_SYM的hw_module_t结构体,

然后实现结构体的相关内容

 


2,驱动方面的准备

简单的嵌入式linux驱动,编写LCD背光驱动,并提供接口给上层修改,我所用的是直接修改接口文件,接口如下:

/sys/class/backlight/pwm-backlight/brightness 这个是亮度调节

/sys/class/backlight/pwm-backlight/max_brightness 这个是最大亮度,按照android系统的要求应该设置成255

控制亮度直接写brightness文件即可

背光驱动主要是通过PWM来完成,这里不详细说明。

 


3,需要包含的头文件

/hardware/libhardware/include/hardware目录下的hardware.h和lights.h

其中hardware.h中定义了通用硬件模块,lights.h中定义了背光设备相关的内容

 


4,android已有的硬件模块在/hardware/libhardware/modules目录下,为了区分,我们开发的背光模块放置在如下的目录:

vendor/ardent/merlin/lights目录下,编译成lights.default.so放置到/system/lib/hw目录下,模块命名规则可以

参考上一节的内容。

 


5,修改vendor/ardent/merlin目录下AndroidBoard.mk文件,添加如下内容:

include $(LOCAL_PATH)/lights/Mdroid.mk

 


6,lights目录新建Mdroid.mk文件,内容如下:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

 


LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw

LOCAL_SRC_FILES:= lights.c

 


LOCAL_SHARED_LIBRARIES := \

libutils \

libcutils \

libhardware

 


LOCAL_PRELINK_MODULE := false

 


LOCAL_MODULE := lights.default

 


include $(BUILD_SHARED_LIBRARY)

 


7,lights目录下新建一个lights.c文件,如下:

const struct hw_module_t HAL_MODULE_INFO_SYM = {

.tag = HARDWARE_MODULE_TAG,

.version_major = 1,

.version_minor = 0,

.id = LIGHTS_HARDWARE_MODULE_ID,

.name = "lights module",

.author = "allen",

.methods = NULL,

};

 


8,上面的内容可以直接编译通过,但是因为我将其methods部分指向了空指针,因此没有任何功能,下面来实现此部分

hw_module_t机构体的methods成员是一个指向hw_module_methods_t结构体的一个指针,hw_module_methods_t结构体定义如下:

typedef struct hw_module_methods_t {

int (*open)(const struct hw_module_t* module, const char* id,struct hw_device_t** device);

} hw_module_methods_t;

据此我们定义一个hw_module_methods_t类型的参数lights_module_methods如下:

struct hw_module_methods_t lights_module_methods = {

.open = lights_device_open

};

然后将上面的methods由NULL改成lights_module_methods

 


9,接下来就是定义lights_device_open函数了,此函数的参数和返回值由hw_module_methods_t结构体的open成员决定,此函数定义如下:

static int lights_device_open(const struct hw_module_t *module,const char *id, struct hw_device_t **device)

从lights_device_open函数的参数来看,第一个参数和第二个参数是常量,第三个参数是一个指向hw_device_t结构体的指针,因此可以断定

实现此函数也就是要完成第三个参数的内容,详细的内容我们可以参考直接调用该函数的内容,在frameworks/base/services/jni目录下的

com_android_server_LightsService.cpp文件中,内容如下:

static light_device_t* get_device(hw_module_t* module, char const* name)

{

int err;

hw_device_t* device;

err = module->methods->open(module, name, &device);

if (err == 0) {

return (light_device_t*)device;//device由hw_device_t指针强制转换成light_device_t指针

} else {

return NULL;

}

}

 


static jint init_native(JNIEnv *env, jobject clazz)

{

int err;

hw_module_t* module;

Devices* devices;


devices = (Devices*)malloc(sizeof(Devices));

 


err = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);

if (err == 0) {

devices->lights[LIGHT_INDEX_BACKLIGHT]

= get_device(module, LIGHT_ID_BACKLIGHT);

devices->lights[LIGHT_INDEX_KEYBOARD]

= get_device(module, LIGHT_ID_KEYBOARD);

devices->lights[LIGHT_INDEX_BUTTONS]

= get_device(module, LIGHT_ID_BUTTONS);

devices->lights[LIGHT_INDEX_BATTERY]

= get_device(module, LIGHT_ID_BATTERY);

devices->lights[LIGHT_INDEX_NOTIFICATIONS]

= get_device(module, LIGHT_ID_NOTIFICATIONS);

devices->lights[LIGHT_INDEX_ATTENTION]

= get_device(module, LIGHT_ID_ATTENTION);

devices->lights[LIGHT_INDEX_BLUETOOTH]

= get_device(module, LIGHT_ID_BLUETOOTH);

devices->lights[LIGHT_INDEX_WIFI]

= get_device(module, LIGHT_ID_WIFI);

} else {

memset(devices, 0, sizeof(Devices));

}

 


return (jint)devices;

}

从上面的内容我们可以看出lights_device_open的第一个参数是JNI层用hw_get_module所获得,第二个参数根据设备的不同有很多种情况

该参数的内容定义在lights.h中,全部情况如下:

#define LIGHT_ID_BACKLIGHT "backlight"

#define LIGHT_ID_KEYBOARD "keyboard"

#define LIGHT_ID_BUTTONS "buttons"

#define LIGHT_ID_BATTERY "battery"

#define LIGHT_ID_NOTIFICATIONS "notifications"

#define LIGHT_ID_ATTENTION "attention"

#define LIGHT_ID_BLUETOOTH "bluetooth"

#define LIGHT_ID_WIFI "wifi"

lights调节有背光,键盘,按键,电池,通知,提醒,蓝牙和WIF

第三个参数是一个指向一个hw_device_t的指针,但是com_android_server_LightsService.cpp文件中的背光调节函数定义如下:

static void setLight_native(JNIEnv *env, jobject clazz, int ptr,

int light, int colorARGB, int flashMode, int onMS, int offMS, int brightnessMode)

{

Devices* devices = (Devices*)ptr;

light_state_t state;

 


if (light < 0 || light >= LIGHT_COUNT || devices->lights[light] == NULL) {

return ;

}

 


memset(&state, 0, sizeof(light_state_t));

state.color = colorARGB;

state.flashMode = flashMode;

state.flashOnMS = onMS;

state.flashOffMS = offMS;

state.brightnessMode = brightnessMode;

 


devices->lights[light]->set_light(devices->lights[light], &state);

}

get_device函数中将hw_device_t指针强制转换成light_device_t指针给调节背光用,而light_device_t定义如下:

struct light_device_t {

struct hw_device_t common;

int (*set_light)(struct light_device_t* dev,

struct light_state_t const* state);

};

因此在实现lights_device_open的第三个参数的时候,我们应该定义一个light_device_t类型结构体,然后

将起common域的指针地址传递过去。这样虽然传递的是一个hw_device_t指针地址,但是JNI层可以将其强制转换

成light_device_t指针地址用,否则devices->lights[light]->set_light就会起不到作用了。实现如下:

static int lights_device_open(const struct hw_module_t *module,const char *id, struct hw_device_t **device)

{

struct light_device_t *dev = NULL;

int resvalue = -1;

dev = calloc(sizeof(struct light_device_t),1);

dev->common.tag = HARDWARE_DEVICE_TAG;

dev->common.version = 0;

dev->common.module = (struct hw_module_t *)module;

dev->common.close = lights_device_close;

if(!strcmp(id, LIGHT_ID_BACKLIGHT))

{

dev->set_light = lcd_set_light;

resvalue = 0;

}

else

{

dev->set_light = other_set_light;

resvalue = 0;

}

*device = &dev->common;

return resvalue;

}

 


10,实现lights_device_close,lcd_set_light和other_set_light,这个主要是调用驱动提供的接口直接控制硬件,举例如下:

static int lights_device_close(struct hw_device_t* device)

{

struct light_device_t *m_device = (struct light_device_t *)device;

if(m_device)

free(m_device);

return 0;

}

static int lcd_set_light(struct light_device_t* dev,struct light_state_t const* state)

{

int fd = -1;

int bytes = 0;

int rlt = -1;

unsigned char brightness = ((77*((state->color>>16)&0x00ff))

+ (150*((state->color>>8)&0x00ff))

+ (29*(state->color&0x00ff))) >> 8;

fd = open("/sys/class/backlight/pwm-backlight/brightness", O_RDWR);

if(fd>0)

{

char buffer[20];

memset(buffer, 0, 20);

bytes = sprintf(buffer, "%d", brightness);

rlt = write(fd, buffer, bytes);

if(rlt>0)

{

close(fd);

return 0;

}

}

close(fd);

return -1;

}

 


static int other_set_light(struct light_device_t* dev,struct light_state_t const* state)

{

return 0;

}

 


11,因为上面调节背光是通过写/sys/class/backlight/pwm-backlight/brightness文件来完成,因此一定要设置该文件的权限,

在init.xxx.rc文件中添加如下的内容:

# for control LCD backlight

chown system system /sys/class/backlight/pwm-backlight/brightness

chmod 0666 /sys/class/backlight/pwm-backlight/brightness

 


12,修改完成后经验证亮度调节可用,上面的例子只是实现了lights部分功能,如果需要完成所有的功能,请参考hardware.h, lights.h和com_android_server_LightsService.cpp文件中的内容。

 

 

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jiajie961/archive/2010/11/23/6030405.aspx

 


android系统开发(八)-SDCARD
关于android系统开发sdcard移植,主要有如下工作:

1,内核驱动开发,完成后每次插入和拔出sdcard系统都会有相关的信息显示,而且sdcard可以手动挂载。

 


2,android的sdcard挂载主要是vold来完成,vold的源代码在/system/vold目录下,编译成/system/bin/vold

init.rc文件中有vold系统服务,确保android系统开机后vold有正常运行。

 


3,添加vold的配置文件,先查看/system/bin/vold/main.cpp文件中的process_config函数,发现配置文件路径如下:

/etc/vold.fstab

android2.2下/etc目录指向了/system/etc目录,因此我们要新建一个vold.fstab文件,目标路径为/system/etc/vold.fstab

 


4,vold.fstab文件的写法,参考/system/core/rootdir/etc目录下的vold.fstab,里面有详细的说明和例子,写法如下:

dev_mount

dev_mount命令 标签 挂载点 子分区 设备在sysfs文件系统下的路径(可多个)

按照上面的要求和我的平台的实际情况,在vold.fstab中添加如下内容:

dev_mount sdcard /mnt/sdcard auto /block/mmcblk0

上面的/block/mmcblk0表示sysfs下的路径,由于linux的sysfs文件系统是在sys目录下,所以对应到/sys/block/mmcblk0目录

 


5,完成后发现android系统中sdcard可用了,总结下载,sdcard部分很简单,主要是找到sdcard设备对应的sysfs文件系统路径

 

 

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jiajie961/archive/2010/11/25/6035369.aspx

 


android系统开发(九)-Audio部分准备工作alsa移植
1,audio内核部分的开发,包含codec驱动,cpu的声音驱动和内核alsa驱动等,

这个是完全的嵌入式linux的开发内容,这里跳过,请确保这几部分正确。

 


2,从alsa的官方网站下载最新的alsa-lib-1.0.23和alsa-utils-1.0.23

官方网站:http://www.alsa-project.org

alsa-lib基于内核alsa驱动,它将对内核alsa接口的操作封装成libasound库

alsa-utils是一个工具包,基于alsa-lib来控制底层alsa驱动,包含aplay/amixer/control等工具

alsa的系统架构如下:

alsa应用

|

alsa-utils

|

alsa-lib

|

alsa-driver

alsa-driver已经集成在linux内核中,alsa应用直接调用alsa-utils工具包的工具来控制底层驱动以操作声卡

 


3,在vendor/ardent/merlin目录下新建一个alsa目录,然后将下载的alsa-lib-1.0.23和alsa-utils-1.0.23

解压缩到alsa目录下,将解压缩后的文件夹去掉版本号改成alsa-lib和alsa-utils

 


4,在vendor/ardent/merlin/AndroidBoard.mk文件中加入如下内容:

L_PATH := $(LOCAL_PATH)

include $(L_PATH)/alsa/Mdroid.mk

 


5,在vendor/ardent/merlin/alsa目录下新建Mdroid.mk文件,内容如下:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

ALSA_PATH := $(LOCAL_PATH)

include $(ALSA_PATH)/alsa-lib/Mdroid.mk

include $(ALSA_PATH)/alsa-utils/Mdroid.mk

 


6,在vendor/ardent/merlin/alsa/alsa-lib目录下新建Mdroid.mk文件,内容如下:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

include $(LOCAL_PATH)/src/Mdroid.mk

 


7,在vendor/ardent/merlin/alsa/alsa-lib/src目录下新建Mdroid.mk文件,内容在文章后面。

 

 

 

注:alsa-lib中编译的内容很多,我们可以先将alsa-lib当成普通的linux库来编译,编译完成后通过查找lo文件的方法

看那些文件被编译到了,同而找到需要编译的c文件,通过make install到指定目录找到需要复制的库和其它文件。代码中

的很多部分是不需要用到了,目前暂时未作详细处理,alsa-lib/modules/mixer/simple目录下的内容编译成了另外的几个

动态库(smixer-ac97,smixer-hda.so,smixer-sbase.so),alsa-lib/aserver目录下的内容编译成aserver,

这两部分因为不会用到,所以未加入到android编译系统中。

 


8,找个目录将alsa-lib当成普通的linux库编译一次,在include目录下会生成config.h文件,将该文件复制到

vendor/ardent/merlin/alsa/alsa-lib/include目录下并修改config.h的部分内容如下:

#define ALOAD_DEVICE_DIRECTORY "/dev/snd"

#define ALSA_CONFIG_DIR "/etc"

#define ALSA_DEVICE_DIRECTORY "/dev/snd/"

//#define HAVE_WORDEXP_H 1

//#define VERSIONED_SYMBOLS

 


9,修改alsa-lib/include/global.h文件,删除如下内容:

#if !defined(_POSIX_C_SOURCE) && !defined(_POSIX_SOURCE)

struct timeval {

time_t tv_sec;

long tv_usec;

};

 


struct timespec {

time_t tv_sec;

long tv_nsec;

};

#endif

 


10,将源代码中所有的

#include

改成

#include

类似

#include

改成

#include

 


11,修改alsa-lib/src/alisp/alisp.c,在obj_type_str函数最后面位置加上如下内容:

return NULL;

 


12,将alsa-lib当普通linux库编译时alsa-lib/src/control目录下生成的ctl_symbols_list.c文件和

alsa-lib/src/pcm目录下生成的pcm_symbols_list.c文件复制到android中alsa-lib对应位置。

 


13,修改alsa-lib/src/pcm/pcm_direct.c文件,删除如下内容:

union semun {

int val;

struct semid_ds *buf;

unsigned short *array;

struct seminfo *__buf;

};

 


14,查找alsa-lib源代码所有文件,确保

#include 的前面有

#include

没有的自己加上,否则会报告错误说size_t未定义

 


15,修改alsa-lib/src/pcm/pcm_ladspa.c文件,将

*strrchr (labellocale, '.') = *lc->decimal_point;

改成

*strrchr (labellocale, '.') = ".";

屏蔽掉如下内容:

//lc = localeconv ();

这个是因为android用的C库是bionic,和标准C库不同,对应的locale.h文件中的lconv结构体定义不同所导致。

 


16,修改alsa-lib/src/pcm/pcm_mmap.c文件中的snd_pcm_mmap函数,将switch (i->type)语句下SND_PCM_AREA_SHM分支的内容

屏蔽掉,同时修改该文件中snd_pcm_munmap函数,将switch (i->type)语句下的SND_PCM_AREA_SHM分支内容屏蔽掉。

 


17,搜索alsa-lib/src目录下的所有文件,搜索shmctl,shmget,shmat,shmdt等4个函数的调用处,将调用到的地方删除。

这个主要是因为android的bionic libc库不支持System V IPC所导致,具体的可以从头文件中看出来。System V IPC通过共享

内存的方式来实现,GNU C库对应共享内存头文件为linux pc的/usr/include/sys/shm.h文件,在此文件中,你可以看到

shmctl,shmget,shmat,shmdt等4个函数的声明,bionic libc库也有一个同样的头文件,在android源代码目录的

bionic/libc/kernel/common/linux目录下,但是文件中的内容却没有上面4个函数的声明。上面16所作的修改也是基于这个原因。

 


18,按照16和17的结论,由于bionic libc所引发的System V IPC功能的缺失,导致alsa库中的相关功能不能正常实现,所以最好的

方法是将相关的部分不编译进来,以免找成不必要的错误。据此将一些文件从编译中删除,修改alsa-lib/src/Mdroid.mk文件即可

alsa-lib/src/control/control_shm.c

alsa-lib/src/pcm/pcm_direct.c

alsa-lib/src/pcm/pcm_dmix.c

alsa-lib/src/pcm/pcm_dshare.c

alsa-lib/src/pcm/pcm_dsnoop.c

alsa-lib/src/pcm/pcm_ladspa.c

alsa-lib/src/pcm/pcm_shm.c

alsa-lib/src/shmarea.c

删除了这几个模块后要将alsa-lib/src/control目录下的ctl_symbols_list.c文件和

alsa-lib/src/pcm目录下的pcm_symbols_list.c文件中的相关内容删除,否则会编译不过。

 


19,最后要实现的功能当然是复制alsa-lib的配置文件了,在alsa-lib/src/conf目录下,复制操作在alsa-lib/src/Mdroid.mk中实现,

最终的Mdroid.mk文件内容如下:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \

async.c conf.c confmisc.c dlmisc.c error.c input.c \

names.c output.c socket.c userfile.c \

alisp/alisp.c \

control/cards.c control/control.c control/control_ext.c \

control/control_hw.c control/control_symbols.c \

control/hcontrol.c control/namehint.c control/setup.c control/tlv.c \

hwdep/hwdep.c hwdep/hwdep_hw.c hwdep/hwdep_symbols.c \

mixer/bag.c mixer/mixer.c mixer/simple.c mixer/simple_abst.c mixer/simple_none.c \

pcm/atomic.c pcm/interval.c pcm/mask.c pcm/pcm.c pcm/pcm_adpcm.c \

pcm/pcm_alaw.c pcm/pcm_asym.c pcm/pcm_copy.c pcm/pcm_empty.c \

pcm/pcm_extplug.c pcm/pcm_file.c pcm/pcm_generic.c pcm/pcm_hooks.c \

pcm/pcm_hw.c pcm/pcm_iec958.c pcm/pcm_ioplug.c \

pcm/pcm_lfloat.c pcm/pcm_linear.c pcm/pcm_meter.c pcm/pcm_misc.c \

pcm/pcm_mmap.c pcm/pcm_mmap_emul.c pcm/pcm_mulaw.c pcm/pcm_multi.c \

pcm/pcm_null.c pcm/pcm_params.c pcm/pcm_plug.c pcm/pcm_plugin.c \

pcm/pcm_rate.c pcm/pcm_rate_linear.c pcm/pcm_route.c pcm/pcm_share.c \

pcm/pcm_simple.c pcm/pcm_softvol.c pcm/pcm_symbols.c \

rawmidi/rawmidi.c rawmidi/rawmidi_hw.c rawmidi/rawmidi_symbols.c \

rawmidi/rawmidi_virt.c \

seq/seq.c seq/seq_event.c seq/seq_hw.c seq/seqmid.c \

seq/seq_midi_event.c seq/seq_old.c seq/seq_symbols.c \

timer/timer.c timer/timer_hw.c timer/timer_query.c \

timer/timer_query_hw.c timer/timer_symbols.c

 


LOCAL_C_INCLUDES += \

$(LOCAL_PATH)/../include

 


LOCAL_SHARED_LIBRARIES := libdl

 


LOCAL_ARM_MODE := arm

 


LOCAL_PRELINK_MODULE := false

LOCAL_MODULE := libasound

include $(BUILD_SHARED_LIBRARY)

 


TARGET_ALSA_CONF_DIR := $(TARGET_OUT)/usr/share/alsa

LOCAL_ALSA_CONF_DIR := $(LOCAL_PATH)/conf

 


copy_from := \

alsa.conf \

pcm/dsnoop.conf \

pcm/modem.conf \

pcm/dpl.conf \

pcm/default.conf \

pcm/surround51.conf \

pcm/surround41.conf \

pcm/surround50.conf \

pcm/dmix.conf \

pcm/center_lfe.conf \

pcm/surround40.conf \

pcm/side.conf \

pcm/iec958.conf \

pcm/rear.conf \

pcm/surround71.conf \

pcm/front.conf \

cards/aliases.conf

 


copy_to := $(addprefix $(TARGET_ALSA_CONF_DIR)/,$(copy_from))

copy_from := $(addprefix $(LOCAL_ALSA_CONF_DIR)/,$(copy_from))

 


$(copy_to) : $(TARGET_ALSA_CONF_DIR)/% : $(LOCAL_ALSA_CONF_DIR)/% | $(ACP)

$(transform-prebuilt-to-target)

 


ALL_PREBUILT += $(copy_to)

 


20,alsa-utils的移植方法也类似,这里就不再介绍,上面的过程只是体验了一下android下开源库的移植方法,

实际上google服务器上已经有alsa的代码,直接下载下载便可用,下载方法如下:

git clone git://android.git.kernel.org/platform/external/alsa-lib.git

git clone git://android.git.kernel.org/platform/external/alsa-utils.git

将下载的alsa-lib和alsa-utils部分复制到vendor/ardent/merlin/alsa目录下参考上面的方法只需对以上

的4和5部分稍作修改即可。

 

 

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jiajie961/archive/2010/11/30/6045507.aspx

 


android系统开发编译过程中的汇编错误
android系统开发移植alsa-lib库的过程中编译的时候出现了如下的错误:

错误1

/tmp/cckyaR40.s: Assembler messages:

/tmp/cckyaR40.s:2763: Error: selected processor does not support `mrs ip,cpsr'

/tmp/cckyaR40.s:2764: Error: unshifted register required -- `orr r2,ip,#128'

/tmp/cckyaR40.s:2765: Error: selected processor does not support `msr cpsr_c,r2'

/tmp/cckyaR40.s:2777: Error: selected processor does not support `msr cpsr_c,ip'

/tmp/cckyaR40.s:2945: Error: selected processor does not support `mrs r3,cpsr'

/tmp/cckyaR40.s:2946: Error: unshifted register required -- `orr r2,r3,#128'

/tmp/cckyaR40.s:2947: Error: selected processor does not support `msr cpsr_c,r2'

/tmp/cckyaR40.s:2959: Error: selected processor does not support `msr cpsr_c,r3'

/tmp/cckyaR40.s:3551: Error: selected processor does not support `mrs ip,cpsr'

/tmp/cckyaR40.s:3552: Error: unshifted register required -- `orr r1,ip,#128'

/tmp/cckyaR40.s:3553: Error: selected processor does not support `msr cpsr_c,r1'

/tmp/cckyaR40.s:3564: Error: selected processor does not support `msr cpsr_c,ip'

字面的意思报的是汇编错误,选择的处理器不支持mrs和msr指令。

原来的ARM指令有32位和16位两种指令模式,16位为thumb指令集,thumb指令集编译出的代码占用空间小,

而且效率也高,所以android的arm编译器默认用的是thumb模式编译,问题在于alsa的代码中有部分的内容

用到了32位的指令,所以才会报如下的错误,修改的方法也很简单,在Android.mk中加入如下内容即可:

LOCAL_ARM_MODE := arm

android的编译系统中LOCAL_ARM_MODE变量的取值为arm或者thumb,代表32位和16位两种arm指令集,

默认为thumb

 


错误2

target SharedLib: libasound (out/target/product/merlin/obj/SHARED_LIBRARIES/libasound_intermediates/LINKED/libasound.so)

/work/android-froyo-r3/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/bin/ld: out/target/product/merlin/obj/SHARED_LIBRARIES/libasound_intermediates/LINKED/libasound.so: version node not found for symbol snd_pcm_sw_params_get_start_threshold@ALSA_0.9

/work/android-froyo-r3/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/bin/ld: failed to set dynamic section sizes: Bad value

collect2: ld returned 1 exit status

make: *** [out/target/product/merlin/obj/SHARED_LIBRARIES/libasound_intermediates/LINKED/libasound.so] 错误 1

解决此问题将alsa-lib/include/config.h文件中的如下宏定义去掉即可:

#define VERSIONED_SYMBOLS

 

 

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jiajie961/archive/2010/11/30/6045513.aspx

 


android系统开发(十)-audio移植
1,移植基础:

(1)内核声音驱动和alsa驱动

(2)alsa-lib和alsa-utils库移植

这两部分上一节已经介绍过了。

 


2,android的audio最核心的部分是audioflinger,audioflinger向上处理来自于应用程序的声音相关的所有请求

向下通过AudioHardwareInterface访问硬件,android的audio架构如下所示:

Applications

|

Frameworks

|

JNI

|

AudioFlinger

|

AudioHardwareInterface

| | |

专有audio库 | alsa用户库

| |

/dev/eac /dev/snd/*

| |

内核eac驱动 内核alsa驱动

AudioHardwareInterface是audioflinger和硬件驱动之间的桥梁,android默认编译的是generic audio,此时

AudioHardwareInterface直接指向了/dev/eac驱动,它通过eac驱动来操作声卡,android audio移植就是要让

AudioHardwareInterface直接或者间接指向我们自己定义的声音驱动,一般都采用alsa声音体系,所以我们的目的就是

要让AudioHardwareInterface指向alsa用户库。下面的内容开始移植alsa-audio

 


3,修改vendor/ardent/merlin/BoardConfig.mk文件内容如下:

BOARD_USES_GENERIC_AUDIO := false

BOARD_USES_ALSA_AUDIO := true

BUILD_WITH_ALSA_UTILS := true

上面配置的目的就是为了让要让AudioHardwareInterface指向alsa用户库

 


4,下面来添加audio库的编译

在vendor/ardent/merlin目录下新建一个libaudio目录,修改AndroidBoard.mk文件,添加编译路径如下:

LOCAL_PATH := $(call my-dir)

L_PATH := $(LOCAL_PATH)

include $(L_PATH)/libaudio/Mdroid.mk

 


5,vendor/ardent/merlin/libaudio目录下新建一个Mdroid.mk文件,内容如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

 


LOCAL_MODULE := libaudio

 


LOCAL_SHARED_LIBRARIES := \

libcutils \

libutils \

libmedia \

libhardware

 


LOCAL_SRC_FILES += AudioHardwareMerlin.cpp

 


LOCAL_CFLAGS +=

 


LOCAL_C_INCLUDES +=

 


LOCAL_STATIC_LIBRARIES += libaudiointerface

 


include $(BUILD_SHARED_LIBRARY)

 

 

 

6,android audio的实现方法,我们现看看接口部分,上面有说道audioflinger是通过AudioHardwareInterface指向驱动的

AudioHardwareInterface类的代码在frameworks/base/libs/audioflinger/AudioHardwareInterface.cpp文件中

该文件中的create函数中定义了AudioHardwareInterface指向驱动的代码如下:

AudioHardwareInterface* hw = 0;

char value[PROPERTY_VALUE_MAX];

 


#ifdef GENERIC_AUDIO

hw = new AudioHardwareGeneric();

#else

// if running in emulation - use the emulator driver

if (property_get("ro.kernel.qemu", value, 0)) {

LOGD("Running in emulation - using generic audio driver");

hw = new AudioHardwareGeneric();

}

else {

LOGV("Creating Vendor Specific AudioHardware");

hw = createAudioHardware();

}

#endif

return hw;

当系统为generic audio的时候此函数返回的是一个指向AudioHardwareGeneric对象的指针,其实是返回一个指向AudioHardwareInterface对象

的指针,因为AudioHardwareGeneric是AudioHardwareInterface的子类,继承关系如下:

AudioHardwareInterface->AudioHardwareBase->AudioHardwareGeneric

如果系统不是generic audio,则通过调用createAudioHardware函数来返回一个指向一个指向AudioHardwareInterface对象的指针,

所以,简单的将,我们要做的事情就是实现这个函数以及它相关的内容即可。createAudioHardware函数我们可以在

hardware/libhardware_legacy/include/hardware_legacy/AudioHardwareInterface.h中也就是AudioHardwareInterface

的声明中找到原型如下:

extern "C" AudioHardwareInterface* createAudioHardware(void);

 


7,通过6我们不难知道,我们实现自己的audio接口完全可以模仿generic audio的做法,只是要多实现一个createAudioHardware函数而已,

因此我们将frameworks/base/libs/audioflinger/AudioHardwareInterface.h文件复制到

vendor/ardent/merlin/libaudio目录下,改名为AudioHardwareMerlin.h,然后将此文件中所有的Generic字段通通替换成Merlin

然后将frameworks/base/libs/audioflinger/AudioHardwareInterface.cpp复制到

vendor/ardent/merlin/libaudio目录下,改名为AudioHardwareMerlin.cpp,然后将此文件中所有的Generic字段通通替换成Merlin

最后在AudioHardwareMerlin.cpp中定义createAudioHardware函数如下:

extern "C" AudioHardwareInterface* createAudioHardware(void)

{

return new AudioHardwareMerlin();

}

 


8,进行到7后直接编译,发现编译不过,错误如下

target thumb C++: libaudioflinger <= frameworks/base/libs/audioflinger/AudioFlinger.cpp

make: *** 没有规则可以创建“out/target/product/merlin/obj/SHARED_LIBRARIES/libaudioflinger_intermediates/LINKED/libaudioflinger.so”需要的目标“out/target/product/merlin/obj/lib/libaudiopolicy.so”。停止。

原来是编译audioflinger的时候需要libaudiopolicy.so的支持

查看frameworks/base/libs/audioflinger/Android.mk文件,发现有如下内容:

ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true)

LOCAL_STATIC_LIBRARIES += libaudiointerface libaudiopolicybase

LOCAL_CFLAGS += -DGENERIC_AUDIO

else

LOCAL_SHARED_LIBRARIES += libaudio libaudiopolicy

endif

看来generic audio的时候需要的是libaudiointerface和libaudiopolicybase静态库,否则需要libaudio和libaudiopolicy动态库

libaudio库上面我们已经实现,看来下面的内容就是要实现libaudiopolicy库了

 


9,audio policy接口的调用在frameworks/base/libs/audioflinger/AudioPolicyService.cpp文件中的AudioPolicyService类

的构造函数中,如下:

#if (defined GENERIC_AUDIO) || (defined AUDIO_POLICY_TEST)

mpPolicyManager = new AudioPolicyManagerBase(this);

LOGV("build for GENERIC_AUDIO - using generic audio policy");

#else

// if running in emulation - use the emulator driver

if (property_get("ro.kernel.qemu", value, 0)) {

LOGV("Running in emulation - using generic audio policy");

mpPolicyManager = new AudioPolicyManagerBase(this);

}

else {

LOGV("Using hardware specific audio policy");

mpPolicyManager = createAudioPolicyManager(this);

}

#endif

该目录下的AudioPolicyService.h文件中定义了mpPolicyManager如下:

AudioPolicyInterface* mpPolicyManager; // the platform specific policy manager

可见,当系统为generic audio或者运行在模拟器上时,mpPolicyManager是一个指向AudioPolicyManagerBase对象的指针

否则就要通过createAudioPolicyManager函数来返回。

AudioPolicyInterface类和AudioPolicyManagerBase类声明在hardware/libhardware_legacy/include/hardware_legacy

目录下的AudioPolicyInterface.h和AudioPolicyManagerBase.h文件中,而且AudioPolicyManagerBase类是AudioPolicyInterface

的子类。

 


10,实现libaudiopolicy库

libaudiopolicy库的实现我们也可以模仿generic audio的实现方式,从8我们可以看出,generic audio的时候audiopolicy用的是

静态的libaudiopolicybase库,从frameworks/base/libs/audioflinger/Android.mk文件可以找到该静态库的编译内容如下:

include $(CLEAR_VARS)

 


LOCAL_SRC_FILES:= \

AudioPolicyManagerBase.cpp

 


LOCAL_SHARED_LIBRARIES := \

libcutils \

libutils \

libmedia

 


ifeq ($(TARGET_SIMULATOR),true)

LOCAL_LDLIBS += -ldl

else

LOCAL_SHARED_LIBRARIES += libdl

endif

 


LOCAL_MODULE:= libaudiopolicybase

 


ifeq ($(BOARD_HAVE_BLUETOOTH),true)

LOCAL_CFLAGS += -DWITH_A2DP

endif

 


ifeq ($(AUDIO_POLICY_TEST),true)

LOCAL_CFLAGS += -DAUDIO_POLICY_TEST

endif

 


include $(BUILD_STATIC_LIBRARY)

由此可见,libaudiopolicybase静态库编译的就是frameworks/base/libs/audioflinger/AudioPolicyManagerBase.cpp文件

 


11,通过9和10的分析,结合libaudio库的写法,要完成libaudiopolicy库,我们可以将AudioPolicyManagerBase.cpp

和AudioPolicyManagerBase.h复制到vendor/ardent/merlin/libaudio目录下,然后将这两个文件名改成和其中的内容作

一定修改,让它变成两外一个类如AudioPolicyManagerMerlin类的定义,然后在cpp文件中定义接口函数createAudioPolicyManager如下:

extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)

{

return new AudioPolicyManagerMerlin(clientInterface);

}

然后再修改相关Mdroid.mk文件编译成libaudiopolicy.so即可

采用这种方法可以实现,但是却不必要,因为generic audio所用的AudioPolicyManagerBase已经非常完善,所以我们只需要直接继承这个类即可

下面来实现它。

 


12,在vendor/ardent/merlin/libaudio目录下创建一个AudioPolicyManagerMerlin.h文件,内容如下:

#include

#include

#include

#include

#include

#include

namespace android {

class AudioPolicyManagerMerlin: public AudioPolicyManagerBase

{

 


public:

AudioPolicyManagerMerlin(AudioPolicyClientInterface *clientInterface)

: AudioPolicyManagerBase(clientInterface) {}

 


virtual ~AudioPolicyManagerMerlin() {}

};

};

主要是声明我们所用的AudioPolicyManagerMerlin,通过直接继承generic audio所用AudioPolicyManagerBase类来实现

 


13,在vendor/ardent/merlin/libaudio目录下创建一个AudioPolicyManagerMerlin.cpp文件,内容如下:

#include "AudioPolicyManagerMerlin.h"

#include

namespace android {

extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)

{

return new AudioPolicyManagerMerlin(clientInterface);

}

}; // namespace android

主要就是定义了接口函数createAudioPolicyManager

 


14,修改vendor/ardent/merlin/libaudio/Mdroid.mk函数,添加libaudiopolicy的编译如下:

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \

AudioPolicyManagerMerlin.cpp

LOCAL_SHARED_LIBRARIES := \

libcutils \

libutils \

libmedia

LOCAL_STATIC_LIBRARIES += libaudiopolicybase

LOCAL_MODULE:= libaudiopolicy

include $(BUILD_SHARED_LIBRARY)

经过以上过程再修改一些小错误,基本上就能编译通过,声音的框架也已经起来了,但是系统还是没哟声音,因为还需要进一步的工作,

下一节继续。

 

 

 

 


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jiajie961/archive/2010/12/01/6047077.aspx

 


android系统开发小知识-启动脚本文件内部的执行顺序
我们知道android在启动的时候通过init进程来解析init.rc和init.xxx.rc文件,

然后执行这两个文件解析出来的内容,init.rc和init.xxx.rc文件中的内容却并不是

按照顺序来执行的,而是有固定的执行顺序,首先,init.rc和init.xxx.rc文件中的内容

全部会放在4个关键字下:

early-init, init, early-boot, boot

所以一个典型的rc文件的写法如下:

on early-init

--------------

 


on init

--------------

 


on early-boot

--------------

 


on boot

--------------

rc文件中这4个部分是可以打乱顺序随便写的,甚至可以有多个部分出现,但是解析完了以后的执行

顺序确实固定的,执行顺序如下:

early-init -> init -> early-boot -> boot