HAL层分析

编者:厦门大学航空航天学院机电系2015级研究生王凯,能源学院能效工程2015级研究生王猛

目录:bdk/hardware/bsp/intel/peripheral/light/mraa

1.open_lights函数

函数目的:打开背光灯
    static int open_lights(const struct hw_module_t *module, char const *name,
        struct hw_device_t **device)
    {
    struct light_device_ext_t *dev;
    int rc = 0, type = -1;

ALOGV("%s: Opening %s lights module", __func__, name);

首先定义了一个struct light_device_ext_t *dev;

ALOGV("%s: Opening %s lights module", __func__, name);

这个是打印相关的信息,首先我们需要定义一个TAG;

比如:

#define LOG_TAG "lights"

这个LOG_TAG在21行定义过。这样将来logcat出来的东西就是这样的:

V/lights(422):hardware/bsp/intel/peripheral/light/mraa/lights.c: Opening ... lights module

这里的就是传进来的name参数。

//

if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name)) {
        type = NOTIFICATIONS_TYPE;
    } else {
        return EINVAL;
    }

接着看传进来的name参数是不是LIGHT_ID_NOTIFICATIONS,这个定义为:

#define LIGHT_ID_NOTIFICATIONS      "notifications"

如果不相等,那么直接返回打开不成功标志EINVAL。

//

然后初始化dev变量
    dev = (struct light_device_ext_t *)(light_devices + type);

    pthread_mutex_lock(&dev->write_mutex);

    if (dev->refs != 0) {
        /* already opened; nothing to do */
        goto inc_refs;
    }

接下来是先将线程互斥锁定,然后在进行操作,这样比较安全,最后记得取消锁定。 之后就判断dev是否已经打开了,判断的方法是判断refs的引用次数,如果引用次数大于0,那么就表示已经打开了,然后直接引用加1返回打开成功标志。

//

接下来是模型初始化
    rc = init_module(type);
    if (rc != 0) {
        ALOGE("%s: Failed to initialize lights module", __func__);
        goto mutex_unlock;
    }

模型初始化是将全局变量

struct light_device_ext_t light_devices[] = {[ 0 ... (LIGHTS_TYPE_NUM - 1) ] = { .write_mutex = PTHREAD_MUTEX_INITIALIZER}};

给初始化。如果初始化失败,那么打印出失败信息,同时返回rc失败标志。

//

接下来是背光灯同步源初始化,也就是创建一个新的线程
   rc = init_light_sync_resources(&dev->flash_cond,&dev->flash_signal_mutex);
      if (rc != 0)
      {
        goto mutex_unlock;
      }

同样如果没有成功就返回rc失败标志。

//

接下来是设备信息更新,给dev变量赋值。接下来是引用加1,然后线程锁解锁。
    dev->base_dev.common.tag = HARDWARE_DEVICE_TAG;
    dev->base_dev.common.version = 0;
    dev->base_dev.common.module = (struct hw_module_t *)module;
    dev->base_dev.common.close = (int (*)(struct hw_device_t *))close_lights;
    dev->base_dev.set_light = set_light_generic;
    inc_refs:
    dev->refs++;
    *device = (struct hw_device_t *)dev;
    mutex_unlock:
    pthread_mutex_unlock(&dev->write_mutex);
    return rc;

2.close_lights函数

函数目的:关闭背光灯

//

首先对传进来的参数进行正确性判断,如果是NULL就打印失败信息,同时返回关闭失败标志。
    static int close_lights(struct light_device_t *base_dev)
      {
    struct light_device_ext_t *dev = (struct light_device_ext_t *)base_dev;
      int rc = 0;

      if (dev == NULL) 
      {
          ALOGE("%s: Cannot deallocate a NULL light device", __func__);
          return EINVAL;
      }

//

接下来是判断引用.
if (dev->refs == 0)  
 /* the light device is not open */
  { 
          rc = EINVAL;
          goto mutex_unlock;
  }
  else if (dev->refs > 1) 
  {
          goto dec_refs;
  }

如果refs引用次数为0表示设备根本没打开。这样可以直接返回。 否则如果被引用次数大于1,那么只需要减少一次引用次数,然后直接返回。 否则,也就是如果只被一个程序打开,那就就需要关闭设备了。

//

接下来就关闭设备,如果是闪烁模式,那么则销毁闪烁线程,将flashMode设置为未闪烁模式。
  if (dev->state.flashMode)
         {
          /* destroy flashing thread */
          pthread_mutex_lock(&dev->flash_signal_mutex);
          dev->state.flashMode = LIGHT_FLASH_NONE;
          pthread_cond_signal(&dev->flash_cond);
          pthread_mutex_unlock(&dev->flash_signal_mutex); 
          pthread_join(dev->flash_thread, NULL);
         }
     free_light_sync_resources(&dev->flash_cond,&dev->flash_signal_mutex);

然后将相关的设置更新,接着释放背光灯同步源。实质上就是销毁线程。

    static void free_light_sync_resources(pthread_cond_t *cond,pthread_mutex_t *signal_mutex)
      {
          pthread_mutex_destroy(signal_mutex);
          pthread_cond_destroy(cond);
      }

//

然后将引用次数减1,再取消线程互斥锁,然后返回成功标志。

3.set_light_generic函数

函数目的:设置背光灯状态

//

      static int set_light_generic(struct light_device_t *base_dev,struct light_state_t const *state)
      {
        struct light_device_ext_t *dev = (struct light_device_ext_t *)base_dev;
        struct light_state_t *current_state;
        int rc = 0;
      if (dev == NULL)
        {
          ALOGE("%s: Cannot set state for NULL device", __func__);
          return EINVAL;
        }
      current_state = &dev->state;
      pthread_mutex_lock(&dev->write_mutex);
      if (dev->refs == 0)
        {
          ALOGE("%s: The light device is not opened", __func__);
          pthread_mutex_unlock(&dev->write_mutex);
          return EINVAL;
        }

首先还是检查设备信息,如果传入参数是无效参数,或者设备没有打开,那么则进行相关的错误处理。 //

接下来直接打印设备的信息,包括闪烁模式,颜色
  ALOGV("%s: flashMode:%x, color:%x", __func__, state->flashMode, state->color);

//

接下来如果现在的状态是闪烁模式,那么销毁闪烁线程,更新状态。
if (current_state->flashMode) 
       {
           /* destroy flashing thread */ 
           pthread_mutex_lock(&dev->flash_signal_mutex); 
           current_state->flashMode = LIGHT_FLASH_NONE; 
           pthread_cond_signal(&dev->flash_cond); 
           pthread_mutex_unlock(&dev->flash_signal_mutex);   
           pthread_join(dev->flash_thread, NULL);  
       }

//

接着对灯光进行设置。
    *current_state = *state;
    if (dev->transform != NULL) 
       {
        current_state->color = dev->transform(current_state->color);
        }
    if (current_state->flashMode) 
        {
          /* start flashing thread */
          if (check_flash_state(current_state) == 0) 
            {
              rc = pthread_create(&dev->flash_thread, NULL,flash_routine, (void *)dev);
                if (rc != 0)
                {
                    ALOGE("%s: Cannot create flashing thread", __func__);
                    current_state->flashMode = LIGHT_FLASH_NONE;
                }
            } else
         {
            ALOGE("%s: Flash state is invalid", __func__);
            current_state->flashMode = LIGHT_FLASH_NONE;
        }
        } 
    else
        {
            rc = set_gpio_value(dev->pin, current_state->color);
            if (rc != 0)
            {
                ALOGE("%s: Cannot set light color.", __func__);
            }
        }

如果需要设置的是闪烁状态,那么先创建一个闪烁的线程。否则如果不需要闪烁,那么直接就设置颜色就好。

//

    pthread_mutex_unlock(&dev->write_mutex);

    return rc;
}
最后解锁互斥锁,然后返回设置成功标志rc。

results matching ""

    No results matching ""