0
点赞
收藏
分享

微信扫一扫

mtk平台sensor分析二:android的hal层如何控制和读取alsps框架下的sensor

蓝哆啦呀 2022-01-20 阅读 219

一、前言

本文主要分析mtk平台hal层如何获取alps框架下光距感数据和光距感的使能开关对应的hal层接口;

二、光距感上报数据的流程

应用层获取光感数据的方式通过open “/dev/m_als_misc”设备节点,调用read函数即可读取到alps架构下的光感数据;

参考第一章所讲的timer_als定时器触发流程,在机器开机的过程中,默认设置下hal层会操控/sys/class/sensor/m_als_misc/alsactive 节点,触发定时器,光感数据通过als_data_report->sensor_input_event函数将获取到的光感值添加到全局的缓存队列buffer中,同时唤醒sensor_event_poll函数中的client->wait等待队列;sensor_event_poll函数就会将对应应用层的休眠进程唤醒,表示这个设备有数据可读,最后调用对应的read函数来读取光感值;

//alsps.c
//light_fops
static int light_open(struct inode *inode, struct file *file)
{
	nonseekable_open(inode, file); //在 open 方法中调用 nonseekable_open() 时,它会通知内核设备不支持 llseek
	return 0;
}

static ssize_t light_read(struct file *file, char __user *buffer, size_t count,
			  loff_t *ppos)
{
	ssize_t read_cnt = 0;

	read_cnt = sensor_event_read(alsps_context_obj->als_mdev.minor, file,
				     buffer, count, ppos);

	return read_cnt;
}

static unsigned int light_poll(struct file *file, poll_table *wait)
{
	return sensor_event_poll(alsps_context_obj->als_mdev.minor, file, wait);
}
  

hal层中open ”/dev/m_als_misc“获取fd套接字,根据fd,调用read函数来读取内核中的数据;sensor_event_read函数就是该节点对应的内核读取数据的具体实现;

//sensors-1.0\hwmon\sensor_event\sensor_event.c
ssize_t sensor_event_read(unsigned char handle, struct file *file, char __user *buffer,
			  size_t count, loff_t *ppos)
{
	struct sensor_event_client *client = &event_obj->client[handle];
	struct sensor_event event;
	size_t read = 0;

	if (count != 0 && count < sizeof(struct sensor_event)) {
		SE_PR_ERR("sensor_event_read handle: %d err count(%d)\n", handle, (int)count);
		return -EINVAL;
	}

	for (;;) {

		if (client->head == client->tail) {
			return 0;
		}

		if (count == 0) {
			SE_LOG("sensor_event_read count: %d\n", (int)count);
			break;
		}

		while (read + sizeof(struct sensor_event) <= count &&
		       sensor_event_fetch_next(client, &event)) {

			if (copy_to_user(buffer + read, &event, sizeof(struct sensor_event)))
				return -EFAULT;

			read += sizeof(struct sensor_event);
		}

		if (read)
			break;
	}

	return read;
}

unsigned int sensor_event_poll(unsigned char handle, struct file *file, poll_table *wait)
{
	struct sensor_event_client *client = &event_obj->client[handle];
	unsigned int mask = 0;

	poll_wait(file, &client->wait, wait);

	if (client->head != client->tail) {
		/* SE_PR_ERR("sensor_event_poll handle:%d\n", handle); */
		mask |= POLLIN | POLLRDNORM;
	}

	return mask;
}

int sensor_input_event(unsigned char handle,
			 const struct sensor_event *event)
{
	struct sensor_event_client *client = &event_obj->client[handle];
	unsigned int dummy = 0;

	/* spin_lock safe, this function don't support interrupt context */
	spin_lock(&client->buffer_lock);

	if (unlikely(client->buffull == true)) {
		pr_err_ratelimited("input buffull, handle:%d, head:%d, tail:%d\n", handle, client->head, client->tail);
		spin_unlock(&client->buffer_lock);
		wake_up_interruptible(&client->wait);
		return -1;
	}
	client->buffer[client->head++] = *event;
	client->head &= client->bufsize - 1;
	/* remain 1 count */
	dummy = client->head + 1;
	dummy &= client->bufsize - 1;
	if (unlikely(dummy == client->tail))
		client->buffull = true;
	spin_unlock(&client->buffer_lock);

	wake_up_interruptible(&client->wait);
	return 0;
}

1、hal层获取光感驱动层的数据流程

在sensors.cpp文件中init_sensors->dev->device.poll = poll__poll;初始化阶段定义了poll函数;
static int poll__poll(struct sensors_poll_device_t * /dev/,
sensors_event_t* data, int count) {
return mSensorManager->pollEvent(data, count);
}

上一章有分析到当驱动层中的光感上报定时器timer_als被触发时,最终会导致驱动的light_poll函数中client->wait等待队列被唤醒,同时给hal层的fd文件描述符fd.revents传入POLLIN | POLLRDNORM;

int sensors_poll_context_t::pollEvent(sensors_event_t* data, int count) {
    int nbEvents = 0;
    int n = 0;
    int averageCount = 0, loop = 0, loopcount = 0;
    int backupcount = count, backuploop = 0;

    do {
        loopcount++;
        computeCountForEachFd(count, &averageCount, &loop);
        backuploop = loop;
        for (int i = 0; count && loop && i < numFds; i++) {
            SensorBase* const sensor(mSensors[i]);
            //mPollFds[i].revents值根据内核的poll函数返回值决定的,当光距感light_poll中的队列被唤醒时,mPollFds[3].revents=POLLIN | POLLRDNORM;表示监听光感的文字描述符有相应,调用对应光感的AmbiLightSensor::readEvents方法;
            if (mPollFds[i].revents & POLLIN || sensor->pendingEvent()) {
                int nb = sensor->readEvents(data, averageCount);
                for (int j = 0; j < nb; j++) {
                    if (data[j].type == SENSOR_TYPE_META_DATA)
                        data[j].meta_data.sensor += ID_OFFSET;
                    else
                        data[j].sensor += ID_OFFSET;
                }
                count -= nb;
                nbEvents += nb;
                data += nb;
                loop--;
                if (count < 0) {
                }
            }
        }
        n = TEMP_FAILURE_RETRY(poll(mPollFds, numFds, nbEvents ? 0 : -1)); //poll阻塞,当nbEvents返回值为0时唤醒,调用readEvents方法来读取驱动层的光感值;
    } while (n && count);
    return nbEvents;
}
//SensorEventReader.cpp
#define DEVICE_PATH           "/dev/m_als_misc"
AmbiLightSensor::AmbiLightSensor()
   //将/dev/m_als_misc节点路径传入
  if (mSensorReader.selectSensorEventFd(DEVICE_PATH) >= 0) 
}
int SensorEventCircularReader::selectSensorEventFd(const char *path) {

        mReadFd = TEMP_FAILURE_RETRY(open(path, O_RDONLY));//打开path路径下的节点,成功返回mReadFd文字描述符;

}
ssize_t SensorEventCircularReader::fill() {
    size_t numEventsRead = 0;
    if (mFreeSpace) {
       //读取mReadFd文字描述符的对应节点值;那么这个mReadFd文字描述符来自哪里呢,在selectSensorEventFd方法中获取的;mReadFd是在SensorEventCircularReader类中定义私有属性;该类中的selectSensorEventFd和fill方法都可以设置和获取该类的属性;
       //mHead为内核上报数据存放的首地址
        const ssize_t nread = TEMP_FAILURE_RETRY(read(mReadFd, mHead, mFreeSpace * sizeof(struct sensor_event)));
        //mBuffer为上报数据的存放地址;
        memcpy(mBuffer, mBufferEnd, s * sizeof(struct sensor_event));

    return numEventsRead;
}
//AmbienteLight.cpp
int AmbiLightSensor::readEvents(sensors_event_t* data, int count)
{
    if (count < 1)
        return -EINVAL;

    ssize_t n = mSensorReader.fill(); //fill方法是根据驱动层的光感设备节点的路径,获取fd;
    while (count && mSensorReader.readEvent(&event)) {//event指向mCurr;
        processEvent(event);  //根据上报事件的event->handle来设置mPendingEvent,当是光感上报值,
        if (event->flush_action <= FLUSH_ACTION) {
            *data++ = mPendingEvent;
            numEventReceived++;
            count--;
        }
        mSensorReader.next();  //mCurr指向上报数据的地址mBuffer
    }
    return numEventReceived;
}
//SensorEventReader.cpp
ssize_t SensorEventCircularReader::fill() {
    size_t numEventsRead = 0;
    if (mFreeSpace) {
        const ssize_t nread = TEMP_FAILURE_RETRY(read(mReadFd, mHead, mFreeSpace * sizeof(struct sensor_event)));
        if (nread < 0 || nread % sizeof(struct sensor_event)) {
            return 0;
        }

        numEventsRead = nread / sizeof(struct sensor_event);
        if (numEventsRead) {
            mHead += numEventsRead;
            mFreeSpace -= numEventsRead;
            if (mHead > mBufferEnd) {
                size_t s = mHead - mBufferEnd;
                if (s < ULONG_MAX / sizeof(struct sensor_event)) {
                    memcpy(mBuffer, mBufferEnd, s * sizeof(struct sensor_event));
                    mHead = mBuffer + s;
                } else
                    ALOGE("SensorEventCircularReader fill data failed");
            }
        }
    }

    return numEventsRead;
}
//SensorEventReader.cpp
ssize_t SensorEventCircularReader::readEvent(struct sensor_event const** events) {
    *events = mCurr;
}
//SensorEventReader.cpp
void SensorEventCircularReader::next() {
        mCurr = mBuffer;  //mCurr指向上报数据的地址;
}

2、hal层控制光感驱动,对光感逻辑处理

//AmbienteLight.cpp
AmbiLightSensor::AmbiLightSensor()
{
      //当/dev/m_als_misc设备节点不存在时直接返回;
      if (mSensorReader.selectSensorEventFd(DEVICE_PATH) >= 0) {
        strlcpy(input_sysfs_path, "/sys/class/sensor/m_als_misc/", sizeof(input_sysfs_path));
        input_sysfs_path_len = strlen(input_sysfs_path);
    } else {
        ALOGE("couldn't find sensor device ");
        return;
    }
    char datapath[64]={"/sys/class/sensor/m_als_misc/alsactive"};
    fd = TEMP_FAILURE_RETRY(open(datapath, O_RDWR));  //打开alsactive节点,获取fd文件描述符
    TEMP_FAILURE_RETRY(read(fd, buf, sizeof(buf) - 1));//读取该节点值,buf为存放值的地址;
}
//当调用enable方法时
int AmbiLightSensor::enable(int32_t handle, int en)
{
    int fd = -1;
    char buf[8] = {0};

    ALOGI("enable: handle:%d, en:%d \r\n", handle, en);
    strlcpy(&input_sysfs_path[input_sysfs_path_len], "alsactive", sizeof(input_sysfs_path) - input_sysfs_path_len);
    fd = TEMP_FAILURE_RETRY(open(input_sysfs_path, O_RDWR));
    if(fd < 0) {
          ALOGE("no enable control attr\r\n" );
          return -1;
    }

    sprintf(buf, "%d,%d", handle, en);
    TEMP_FAILURE_RETRY(write(fd, buf, sizeof(buf)));
    close(fd);
    return 0;
}

int AmbiLightSensor::batch(int handle, int flags, int64_t samplingPeriodNs, int64_t maxBatchReportLatencyNs)
{
    int fd = -1;
    char buf[128] = {0};

    ALOGI("batch: handle:%d, flag:%d,samplingPeriodNs:%" PRId64 " maxBatchReportLatencyNs:%" PRId64 "\r\n",
        handle, flags,samplingPeriodNs, maxBatchReportLatencyNs);

    strlcpy(&input_sysfs_path[input_sysfs_path_len], "alsbatch", sizeof(input_sysfs_path) - input_sysfs_path_len);
    fd = TEMP_FAILURE_RETRY(open(input_sysfs_path, O_RDWR));
    if(fd < 0) {
        ALOGD("no batch control attr\r\n");
        return -1;
    }
    sprintf(buf, "%d,%d,%" PRId64 ",%" PRId64 "", handle, flags, samplingPeriodNs, maxBatchReportLatencyNs);
    TEMP_FAILURE_RETRY(write(fd, buf, sizeof(buf)));
    close(fd);
    return 0;
}
举报

相关推荐

0 条评论