android sendor 2

 

 

Android sensor subsystem overview

 

·  Application Framework

o Sensor Applications uses the Sensor application framework to get the sensor data. It communicates with C++ layer through sensor Java native interface (JNI)

·  Sensor Libraries

o Sensor middle layer mainly consists of Sensor Manager, Sensor service and Sensor hardware abstraction layer.

·  Input Subsystem

o This is a generic Linux framework for all input devices like keyboard, mouse, touchscreen and defines a standard set of events. It interfaces to user space through /sys/class/input interface.

·  Evdev

o Evdev provides a generic way for input device events to be accessible under /dev/input/eventX .

·  LIS331DLH Accelerometer Driver

o This driver communicates with LIS331DLH accelerometer chip via GPIO and I2C bus. GPIO line is used for generating interrupts while I2C bus for accessing and configuring accelerometer registers.

 

1.     创建sensor Manager --à 加载sensor list和service

2.      注册一个registerListener() 创建一个新的ListenerDelegate,并对应handler

3.     启动sensorthread startlocked

4.     在步骤3中创建一个新的sensorThreadRunnable线程并启动

5.     SensorThreadRunable线程运行,并开始查询sensor状态sensor_data_poll()

6.     有数据的话,触发ListenerDelegate中的onsensorchangedLocked()

7.     发送消息至ListenerDelegate的handler中处理,分别触发onSensorChanged(), onAccuraryChanged()

 

C++语言阶段的调用关系

(Native)SensorService.cpp ----à

SensorInterface.cpp ----à

SensorDevice.cpp ----à

(HAL)Sensors.cpp ----à

 (具体的sensor)ProximitySensor.cpp ----àsyscall

(kernel) -----à

 

/* SensorDevice.cpp 中根据module的id:SENSORS_HARDWARE_MODULE_ID 来加载模块*/

 SensorDevice::SensorDevice()

    :  mSensorDevice(0),

       mSensorModule(0)

{

    status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,

            (hw_module_t const**)&mSensorModule); /*加载模块*/

    LOGE_IF(err, "couldn't load %s module (%s)",

            SENSORS_HARDWARE_MODULE_ID, strerror(-err));

    if (mSensorModule) {

        err = sensors_open(&mSensorModule->common, &mSensorDevice); /*调用module中的open函数*/

        LOGE_IF(err, "couldn't open device for module %s (%s)",

                SENSORS_HARDWARE_MODULE_ID, strerror(-err));

        if (mSensorDevice) {

            sensor_t const* list;

            ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list); /*获取module中的sensor列表*/

            mActivationCount.setCapacity(count);

            Info model;

            for (size_t i=0 ; i<size_t(count) ; i++) {

                mActivationCount.add(list[i].handle, model);

                mSensorDevice->activate(mSensorDevice, list[i].handle, 0); /*调用对应的active函数*/

            }

        }

    }

}

 

HAL分析

关键数据结构:

struct hw_module_t  ---------对应到-------à struct sensors_module_t

struct hw_device_t  -----------对应到-------à struct sensors_poll_device_t

下面分别列出sensor对应的数据结构:

/* Every hardware module must have a data structure named HAL_MODULE_INFO_SYM

 * and the fields of this data structure must begin with hw_module_t

 * followed by module specific information.

 */

struct sensors_module_t {

    struct hw_module_t common;

    /**

     * Enumerate all available sensors. The list is returned in "list".

     * @return number of sensors in the list

     */

    int (*get_sensors_list)(struct sensors_module_t* module,

            struct sensor_t const** list);

};

 

/**

 * Every device data structure must begin with hw_device_t

 * followed by module specific public methods and attributes.

 */

struct sensors_poll_device_t {

    struct hw_device_t common;

    /** Activate/deactivate one sensor.

     * @param handle is the handle of the sensor to change.

     * @param enabled set to 1 to enable, or 0 to disable the sensor.

     * @return 0 on success, negative errno code otherwise

     */

    int (*activate)(struct sensors_poll_device_t *dev,

            int handle, int enabled);

    /* Set the delay between sensor events in nanoseconds for a given sensor.

     * It is an error to set a delay inferior to the value defined by

     * sensor_t::minDelay. If sensor_t::minDelay is zero, setDelay() is

     * ignored and returns 0.

     * @return 0 if successful, < 0 on error  */

    int (*setDelay)(struct sensors_poll_device_t *dev,

            int handle, int64_t ns);

    /* * Returns an array of sensor data.

     * This function must block until events are available.

     * @return the number of events read on success, or -errno in case of an error.

     * This function should never return 0 (no event).

     */

    int (*poll)(struct sensors_poll_device_t *dev,

            sensors_event_t* data, int count);

}

 

 

struct sensors_module_t HAL_MODULE_INFO_SYM = {

        common: {

                tag: HARDWARE_MODULE_TAG,

                version_major: 3,

                version_minor: 0,

                id: SENSORS_HARDWARE_MODULE_ID,/*在SensorDevice中调用hw_get_module,将依次为第一个参数*/

                name: "ALPS 3-axis Magnetic field sensor",

                author: "alps electric co., ltd.",

                methods: &sensors_module_methods,

        },

        get_sensors_list: sensors__get_sensors_list,

};

 

static struct hw_module_methods_t  sensors_module_methods = {

        open: open_sensors

};

 

/** Open a new instance of a sensor device using name */

static int open_sensors(const struct hw_module_t* module, const char* id,

                        struct hw_device_t** device)

{        int status = -EINVAL;

        sensors_poll_context_t *dev = new sensors_poll_context_t();

        memset(&dev->device, 0, sizeof(sensors_poll_device_t));

        dev->device.common.tag = HARDWARE_DEVICE_TAG;

        dev->device.common.version  = 0;

        dev->device.common.module   = const_cast<hw_module_t*>(module);

        dev->device.common.close    = poll__close;

        dev->device.activate        = poll__activate;

        dev->device.setDelay        = poll__setDelay;

        dev->device.poll            = poll__poll;

        *device = &dev->device.common;

        status = 0;

        return status;

}

 

static int sensors__get_sensors_list(struct sensors_module_t* module,

                                     struct sensor_t const** list)

{

        *list = sSensorList; /*该数组在下面列出*/

        return ARRAY_SIZE(sSensorList);

}

 

static const struct sensor_t sSensorList[] = {

        { "3-axis Accelerometer",

          "",

          1, SENSORS_ACCELERATION_HANDLE,

          SENSOR_TYPE_ACCELEROMETER, 39.2f, CONVERT_A, 0.7f, 10000, { } },

        { "ALPS 3-axis Magnetic field sensor",

          "alps electric co., ltd.",

          1, SENSORS_MAGNETIC_FIELD_HANDLE,

          SENSOR_TYPE_MAGNETIC_FIELD, 2200.0f, CONVERT_M, 0.2f, 10000, { } },

        { "ALPS Orientation sensor",

          "alps electric co., ltd.",

          1, SENSORS_ORIENTATION_HANDLE,

          SENSOR_TYPE_ORIENTATION, 360.0f, 1.0f, 0.2f, 10000, { } },

      { "GP2A Proximity Sensor",

               "Shrap",

               1, SENSORS_PROXIMITY_HANDLE,

               SENSOR_TYPE_PROXIMITY, 5.0f, 5.0f, 0.75f, 0, { } }

#ifdef ACDOPT_USEGYRO

        { "ALPS Gyroscope sensor",

          "alps electric co., ltd.",

          1, SENSORS_GYROSCOPE_HANDLE,

          SENSOR_TYPE_GYROSCOPE, 4000.0f*CONVERT_G, CONVERT_G, 0.2f, 20000, { } },

#endif

};

 

 

 

/** Open a new instance of a sensor device using name */

static int open_sensors(const struct hw_module_t* module, const char* id,

                        struct hw_device_t** device)

{

        int status = -EINVAL;

        sensors_poll_context_t *dev = new sensors_poll_context_t(); /*创建sensors_poll_context_t(),在其构造函数中,初始化了mSensors,如下所示*/

        memset(&dev->device, 0, sizeof(sensors_poll_device_t));

        dev->device.common.tag = HARDWARE_DEVICE_TAG;

        dev->device.common.version  = 0;

        dev->device.common.module   = const_cast<hw_module_t*>(module);

        dev->device.common.close    = poll__close;

        dev->device.activate        = poll__activate;

        dev->device.setDelay        = poll__setDelay;

        dev->device.poll            = poll__poll;

        *device = &dev->device.common;

        status = 0;

        return status;

}

 

sensors_poll_context_t::sensors_poll_context_t()

{

    mSensors[accel] = new HSCDSensor (); /*创建加速度传感器实例*/

    mPollFds[accel].fd = mSensors[accel]->getFd();

    mPollFds[accel].events = POLLIN;

    mPollFds[accel].revents = 0;

 

    int wakeFds[2];

    int result = pipe(wakeFds);

    LOGE_IF(result<0, "error creating wake pipe (%s)", strerror(errno));

    fcntl(wakeFds[0], F_SETFL, O_NONBLOCK);

    fcntl(wakeFds[1], F_SETFL, O_NONBLOCK);

    mWritePipeFd = wakeFds[1];

 

    mPollFds[wake].fd = wakeFds[0];

    mPollFds[wake].events = POLLIN;

    mPollFds[wake].revents = 0;

}

HSCDSensor分析:

 

 

 

open_sensors中,被赋值给dev->device.activate = poll__activate的函数,通过调用sensors_poll_context_t中的activate函数,实际调用了各个传感器自己定义的activate函数,如加速度传感器定义为enable函数,分析如下:

static int poll__activate(struct sensors_poll_device_t *dev, int handle, int enabled) {

    sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;

    return ctx->activate(handle, enabled);

}

sensors_poll_context_t中的各个函数,调用了在其构造函数中实例化的传感器,如加速度传感器AccelSensor

int sensors_poll_context_t::activate(int handle, int enabled) {

    int index = handleToDriver(handle);

    int err =  mSensors[index]->enable(handle, enabled);

    if (enabled && !err) {

        const char wakeMessage(WAKE_MESSAGE);

        int result = write(mWritePipeFd, &wakeMessage, 1);

    }

    return err;

}

 

int HSCDSensor::enable(int32_t handle, int en)

{

   switch (handle) {

        case ID_A: what = Accelerometer; break;

    }

    switch (what) {

        case Accelerometer: sensor_type = SENSOR_TYPE_ACCELEROMETER;  break;

    }

      err = HSCD_activate_sensor(sensor_type, en);

}

 

int HSCDSensor::HSCD_activate_sensor(uint32_t sensor_type, int en)

{

   while (1) { if (sensor_type == SENSOR_TYPE_ACCELEROMETER) {

           ret = HSCD_activate_Accelerometer(en);

}

 

int HSCDSensor::HSCD_activate_Accelerometer(int en)

{

   alps_io_fd = open("/dev/alps_io", O_RDONLY);

   ret = ioctl(alps_io_fd, ALPSIO_SET_ACCACTIVATE, &en);

 }

-------------------------------syscall---------------------------------------------------

static int alps_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)

{

         switch (cmd) {

         case ALPSIO_SET_ACCACTIVATE:

                            ret = copy_from_user(&tmpval, argp, sizeof(tmpval));

                            mutex_lock(&alps_lock);

                            flgA = tmpval;

                            accsns_activate(1, flgA, delay);/*flgA代表enable or disable*/

                            mutex_unlock(&alps_lock);

                            break;

}

 

void accsns_activate(int flgatm, int flg, int dtime)

{

         accsns_i2c_writem(buf, 2);

}

 

static int accsns_i2c_writem(u8 *txData, int length)

{

         struct i2c_msg msg[] = {

                   { .addr = client_accsns->addr,

                    .flags = 0,

                    .len = length,

                    .buf = txData,},};

        

         err = i2c_transfer(client_accsns->adapter, msg, 1);

}

 

 

 

Linux_driver

1.       I2C设备板级信息,包括设备名和I2C的地址,其中的设备名(似乎)要和对应的driver名一致。

static struct i2c_board_info sensor_devices[] = {

         #ifdef CONFIG_SENSORS_HSCD

{

         I2C_BOARD_INFO("accsns_i2c", 0x08),

},

{

         I2C_BOARD_INFO("hscd_i2c", 0x0d),

},

         #endif

         #ifdef CONFIG_PROXIMITY_SENSOR

{

         I2C_BOARD_INFO("gp2a", 0x44 ),

         .platform_data = &gp2a_pdata,

},

         #endif

};

其中I2C_BOARD_INFO定义如下:

/**

 * I2C_BOARD_INFO - macro used to list an i2c device and its address

 * @dev_type: identifies the device type

 * @dev_addr: the device's address on the bus.

 *

 * This macro initializes essential fields of a struct i2c_board_info,

 * declaring what has been provided on a particular board.  Optional

 * fields (such as associated irq, or device-specific platform_data)

 * are provided using conventional syntax.

 */

#define I2C_BOARD_INFO(dev_type, dev_addr) \

         .type = dev_type, .addr = (dev_addr)

 

struct i2c_board_info定义如下:

/**

 * struct i2c_board_info - template for device creation

 * @type: chip type, to initialize i2c_client.name

 * @flags: to initialize i2c_client.flags

 * @addr: stored in i2c_client.addr

 * @platform_data: stored in i2c_client.dev.platform_data

 * @archdata: copied into i2c_client.dev.archdata

 * @of_node: pointer to OpenFirmware device node

 * @irq: stored in i2c_client.irq

 *

 * I2C doesn't actually support hardware probing, although controllers and

 * devices may be able to use I2C_SMBUS_QUICK to tell whether or not there's

 * a device at a given address.  Drivers commonly need more information than

 * that, such as chip type, configuration, associated IRQ, and so on.

 *

 * i2c_board_info is used to build tables of information listing I2C devices

 * that are present.  This information is used to grow the driver model tree.

 * For mainboards this is done statically using i2c_register_board_info();

 * bus numbers identify adapters that aren't yet available.  For add-on boards,

 * i2c_new_device() does this dynamically with the adapter already known.

 */

struct i2c_board_info {

         char            type[I2C_NAME_SIZE];

         unsigned short    flags;

         unsigned short    addr;

         void            *platform_data;

         struct dev_archdata     *archdata;

#ifdef CONFIG_OF

         struct device_node *of_node;

#endif

         int              irq;

};

 

 

/*在linux的开机初始化中会调用board_init()函数,board_init()函数中调用i2c设备注册函数*/

static void __init board_init(void)

{

//……..

         register_i2c_devices();

//……..

}

 

 

/*该函数中调用i2c_register_board_info ()函数实现真正的注册*/

static void __init register_i2c_devices(void)

{

//注册各个I2C设备

//……..

/*参数分析:

* busnum =4,表示这些i2c设备属于4号总线;

* info = sensor_devices,指明i2c设备描述符数组为sensor_devices

* len = ARRAY_SIZE(sensor_devices),得到数组中的元素个数

*/

         i2c_register_board_info(4, sensor_devices, ARRAY_SIZE(sensor_devices));/*该函数分析见下面*/

//……..

}

 

/**

 * i2c_register_board_info - statically declare I2C devices

 * @busnum: identifies the bus to which these devices belong

 * @info: vector of i2c device descriptors

 * @len: how many descriptors in the vector; may be zero to reserve

 *     the specified bus number.

 *

 * Systems using the Linux I2C driver stack can declare tables of board info

 * while they initialize.  This should be done in board-specific init code

 * near arch_initcall() time, or equivalent, before any I2C adapter driver is

 * registered. (该函数要在任何一个I2C适配层驱动被注册之前被调用)

* For example, mainboard init code could define several devices,

 * as could the init code for each daughtercard in a board stack.

 *

 * The I2C devices will be created later, after the adapter for the relevant

 * bus has been registered.  After that moment, standard driver model tools

 * are used to bind "new style" I2C drivers to the devices.  The bus number

 * for any device declared using this routine is not available for dynamic

 * allocation.

 *

 * The board info passed can safely be __initdata, but be careful of embedded

 * pointers (for platform_data, functions, etc) since that won't be copied.

 */

int __init

i2c_register_board_info(int busnum,struct i2c_board_info const *info, unsigned len)

{

         int status;

         down_write(&__i2c_board_lock);

 

         /* dynamic bus numbers will be assigned after the last static one */

         if (busnum >= __i2c_first_dynamic_bus_num)

                   __i2c_first_dynamic_bus_num = busnum + 1;

 

         for (status = 0; len; len--, info++) {

                   struct i2c_devinfo        *devinfo;

                   devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);

                   if (!devinfo) {

                            pr_debug("i2c-core: can't register boardinfo!\n");

                            status = -ENOMEM;

                            break;                  }

 

                   devinfo->busnum = busnum;

                   devinfo->board_info = *info;

/*__i2c_board_list将各个i2c设备挂到这个list上面,它将在i2c-core.c中的i2c_scan_static_board_info()函数中被使用*/

                   list_add_tail(&devinfo->list, &__i2c_board_list);

         }

         up_write(&__i2c_board_lock);

         return status;

}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值