首先是sensor这个模块的id定义,主要是实现了一个sensors_module_t结构:
struct sensors_module_t HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
.version_major = 1,
.version_minor = 0,
.id = SENSORS_HARDWARE_MODULE_ID,
.name = "MMA8451Q & AK8973A & gyro Sensors Module",
.author = "The RKdroid Project",
.methods = &sensors_module_methods,
},
.get_sensors_list = sensors__get_sensors_list
};
sensors__get_sensors_list函数返回这个平台的所有sensor
static int sensors__get_sensors_list(struct sensors_module_t* module,
struct sensor_t const** list)
{
*list = sSensorList;
return ARRAY_SIZE(sSensorList);
}
对应sSensorList是一个sensor_t的结构
static const struct sensor_t sSensorList[] = {
{ "MMA8452Q 3-axis Accelerometer",
"Freescale Semiconductor",
1, SENSORS_HANDLE_BASE+ID_A,
SENSOR_TYPE_ACCELEROMETER, 4.0f*9.81f, (4.0f*9.81f)/256.0f, 0.2f, 0, { } },
{ "AK8975 3-axis Magnetic field sensor",
"Asahi Kasei",
1, SENSORS_HANDLE_BASE+ID_M,
SENSOR_TYPE_MAGNETIC_FIELD, 2000.0f, 1.0f/16.0f, 6.8f, 0, { } },
{ "AK8975 Orientation sensor",
"Asahi Kasei",
1, SENSORS_HANDLE_BASE+ID_O,
SENSOR_TYPE_ORIENTATION, 360.0f, 1.0f, 7.0f, 0, { } },
{ "ST 3-axis Gyroscope sensor",
"STMicroelectronics",
1, SENSORS_HANDLE_BASE+ID_GY,
SENSOR_TYPE_GYROSCOPE, RANGE_GYRO, CONVERT_GYRO, 6.1f, 1190, { } },
{ "AL3006Proximity sensor",
"Dyna Image Corporation",
1, SENSORS_HANDLE_BASE+ID_P,
SENSOR_TYPE_PROXIMITY,
PROXIMITY_THRESHOLD_CM, PROXIMITY_THRESHOLD_CM,
0.5f, 0, { } },
{ "AL3006 light sensor",
"Dyna Image Corporation",
1, SENSORS_HANDLE_BASE+ID_L,
SENSOR_TYPE_LIGHT, 10240.0f, 1.0f, 0.5f, 0, { } },
};
这个是我手头上的这块板子所提供的sensor
open_sensors用来打开所有的sensor,并返回一个hw_device_t
static int open_sensors(const struct hw_module_t* module, const char* name,
struct hw_device_t** device)
{
return init_nusensors(module, device);
}
对应init_nusensors
int init_nusensors(hw_module_t const* module, hw_device_t** device)
{
D("Entered.");
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;
}
首先new 了一个sensors_poll_context_t,然后设置device,并返回
对应new sensors_poll_context_t我们看一下其实现sensors_poll_context_t::sensors_poll_context_t()
{
D("Entered.");
mSensors[light] = new LightSensor();
mPollFds[light].fd = mSensors[light]->getFd();
mPollFds[light].events = POLLIN;
mPollFds[light].revents = 0;
mSensors[proximity] = new ProximitySensor();
mPollFds[proximity].fd = mSensors[proximity]->getFd();
mPollFds[proximity].events = POLLIN;
mPollFds[proximity].revents = 0;
mSensors[mma] = new MmaSensor();
mPollFds[mma].fd = mSensors[mma]->getFd();
mPollFds[mma].events = POLLIN;
mPollFds[mma].revents = 0;
mSensors[akm] = new AkmSensor();
mPollFds[akm].fd = mSensors[akm]->getFd();
mPollFds[akm].events = POLLIN;
mPollFds[akm].revents = 0;
mSensors[gyro] = new GyroSensor();
mPollFds[gyro].fd = mSensors[gyro]->getFd();
mPollFds[gyro].events = POLLIN;
mPollFds[gyro].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;
}
mSensors是一个SensorBase类型的类,而mPollFds是一个pollfd的结构。
mSensors保存了各个打开的sensor,mPollFds用来监听sensor的时候用的。
我们以打开陀螺仪为例,看一下其打开过程
GyroSensor::GyroSensor()
: SensorBase(GY_DEVICE_NAME, "gyro"),
mEnabled(0),
mInputReader(32)
{
mPendingEvent.version = sizeof(sensors_event_t);
mPendingEvent.sensor = ID_GY;
mPendingEvent.type = SENSOR_TYPE_GYROSCOPE;
mPendingEvent.gyro.status = SENSOR_STATUS_ACCURACY_HIGH;
memset(mPendingEvent.data, 0x00, sizeof(mPendingEvent.data));
int err = 0;
err = open_device();
err = err<0 ? -errno : 0;
if(err)
{
LOGD("%s:%s\n",__func__,strerror(-err));
return;
}
int flags = 0;
if (!ioctl(dev_fd, L3G4200D_IOCTL_GET_ENABLE, &flags)) {
if (flags) {
mEnabled = 1;
}
}
if (!mEnabled) {
close_device();
}
}
mPendingEvent是一个 sensors_event_t结构,首先对其sensor、type等赋值,然后调用open_device打开陀螺仪设备,然后调用ioctlL3G4200D_IOCTL_GET_ENABLE查看sensor是否启用
注意这里不要忽略了SensorBase(GY_DEVICE_NAME, "gyro")
我们看一下它做了什么。
这里GY_DEVICE_NAME对应"/dev/gyrosensor"
SensorBase::SensorBase(
const char* dev_name,
const char* data_name)
: dev_name(dev_name), data_name(data_name),
dev_fd(-1), data_fd(-1)
{
data_fd = openInput(data_name);
}
设置dev_name和data_name后调用openInput打开设备
int SensorBase::openInput(const char* inputName) {
int fd = -1;
const char *dirname = "/dev/input";
char devname[PATH_MAX];
char *filename;
DIR *dir;
struct dirent *de;
return getInput(inputName);
}
再继续看一下getInput
static int getInput(const char *inputName)
{
int fd = -1;
unsigned i;
static bool first = true;
static struct input_dev dev[255];
if (first) {
int fd = -1;
const char *dirname = "/dev/input";
char devname[PATH_MAX];
char *filename;
DIR *dir;
struct dirent *de;
first = false;
for (i = 0; i < sizeof(dev)/sizeof(dev[0]); i++) {
dev[i].fd = -1;
dev[i].name[0] = '\0';
}
i = 0;
dir = opendir(dirname);
if (dir == NULL)
return -1;
strcpy(devname, dirname);
filename = devname + strlen(devname);
*filename++ = '/';
while ((de = readdir(dir))) {
if (de->d_name[0] == '.' &&
(de->d_name[1] == '\0' || (de->d_name[1] == '.' && de->d_name[2] == '\0')))
continue;
strcpy(filename, de->d_name);
fd = open(devname, O_RDONLY);
if (fd >= 0) {
char name[80];
if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) >= 1) {
dev[i].fd = fd;
strncpy(dev[i].name, name, sizeof(dev[i].name));
}
}
i++;
}
closedir(dir);
}
for (i = 0; i < sizeof(dev)/sizeof(dev[0]); i++) {
if (!strncmp(inputName, dev[i].name, sizeof(dev[i].name))) {
fd = dev[i].fd;
break;
}
}
LOGE_IF(fd < 0, "couldn't find '%s' input device", inputName);
return fd;
}
这个函数的作用就是打开"/dev/input",查找其中的输入设备名字与传入参数匹配的那一个,这里是"gyro",并返回相应的打开句柄。
再回到open_device
int SensorBase::open_device() {
if (dev_fd<0 && dev_name) {
dev_fd = open(dev_name, O_RDONLY);
if(dev_fd<0)
{
LOGD("Couldn't open %s (%s)", dev_name, strerror(errno));
return -errno;
}
}
return 0;
}
这里只是简单的打开设备,对应"/dev/gyrosensor"
这样,再回到sensors_poll_context_t的构造函数,就把各个sensor设备都打开了,注意这里的mPollFds. Fd是data_fd,即打开“/dev/input/*”设备的句柄
到这里,sensor就已经打开了。
再看一下其它的函数。
Activate、setDelay都是直接调用相应的sensor接口直接调用相应sensor的接口,主要是pollEvents
int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count)
{
D("Entered : count = %d", count);
int nbEvents = 0;
int n = 0;
do {
// see if we have some leftover from the last poll()
for (int i=0 ; count && i<numSensorDrivers ; i++) {//调用各个sensor的readEvents读取数据
SensorBase* const sensor(mSensors[i]);
if ((mPollFds[i].revents & POLLIN) || (sensor->hasPendingEvents())) {
int nb = sensor->readEvents(data, count); // num of evens received.
D("nb = %d.", nb);
if (nb < count) {
// no more data for this sensor
mPollFds[i].revents = 0;
}
count -= nb;
nbEvents += nb;
data += nb;
D("count = %d, nbEvents = %d, data = 0x%p.", count, nbEvents, data);
}
}
if (count) {
// we still have some room, so try to see if we can get
// some events immediately or just wait if we don't have
// anything to return
n = poll(mPollFds, numFds, nbEvents ? 0 : -1);
if (n<0) {
LOGE("poll() failed (%s)", strerror(errno));
return -errno;
}
if (mPollFds[wake].revents & POLLIN) {
char msg;
int result = read(mPollFds[wake].fd, &msg, 1);
LOGE_IF(result<0, "error reading from wake pipe (%s)", strerror(errno));
LOGE_IF(msg != WAKE_MESSAGE, "unknown message on wake queue (0x%02x)", int(msg));
mPollFds[wake].revents = 0;
}
}
// if we have events and space, go read them
D("n =0x%x, count = 0x%x.", n, count);
} while (n && count);
D("to return : nbEvents = %d", nbEvents);
return nbEvents;
}
我们这里看一下GyroSensor的readEvents
int GyroSensor::readEvents(sensors_event_t* data, int count)
{
//LOGD("*******************Gyro readEvents");
//LOGD("count: %d, mHasPendingEvent: %d", count, mHasPendingEvent);
static int64_t prev_time;
int64_t time;
if (count < 1)
return -EINVAL;
if (mHasPendingEvent) {
mHasPendingEvent = false;
mPendingEvent.timestamp = getTimestamp();
*data = mPendingEvent;
return mEnabled ? 1 : 0;
}
ssize_t n = mInputReader.fill(data_fd);//从输入设备中读取数据
if (n < 0)
return n;
int numEventReceived = 0;
input_event const* event;
float gyrox = 0, gyroy = 0, gyroz = 0;
#if FETCH_FULL_EVENT_BEFORE_RETURN
again:
#endif
while (count && mInputReader.readEvent(&event)) {//读取当前一个event,返回还有的数据大小
//LOGD("GyroSensor::readEvents() coutn = %d, event->value = %f", count, event->value);
int type = event->type;
if (type == EV_REL) {//为事件相对坐标
float value = event->value;
if (event->code == EVENT_TYPE_GYRO_X) {
gyrox = value;
} else if (event->code == EVENT_TYPE_GYRO_Y) {
gyroy = value;
} else if (event->code == EVENT_TYPE_GYRO_Z) {
gyroz = value;
}
NineAxisTypeDef nineInput;
nineInput.ax = 1;
nineInput.ay = 1;
nineInput.az = 1000;
nineInput.mx = 300;
nineInput.my = 300;
nineInput.mz = 300;
nineInput.gx = gyrox;
nineInput.gy = gyroy;
nineInput.gz = gyroz;
nineInput.time = getTimestamp()/1000000;
FusionTypeDef fusionData = MEMSAlgLib_Fusion_Update(nineInput);
float offx, offy, offz;
MEMSAlgLib_Fusion_Get_GyroOffset(&offx,&offy,&offz);
//LOGD("gyro offset: %f, %f, %f", offx, offy, offz);
mPendingEvent.data[0] = (gyrox-offx) * CONVERT_GYRO_X;
mPendingEvent.data[1] = (gyroy-offy) * CONVERT_GYRO_Y;
mPendingEvent.data[2] = (gyroz-offz) * CONVERT_GYRO_Z;
mPendingEvent.gyro.x = mPendingEvent.data[0];
mPendingEvent.gyro.y = mPendingEvent.data[1];
mPendingEvent.gyro.z = mPendingEvent.data[2];
//LOGD("mPendingEvent: %f, %f, %f", mPendingEvent.gyro.x, mPendingEvent.gyro.y, mPendingEvent.gyro.z);
}else if (type == EV_SYN) {//表示Motion的一系列动作结束
time = timevalToNano(event->time);
if(mEnabled) {
mPendingEvent.timestamp = time;
*data++ = mPendingEvent;
count--;
numEventReceived++;
}
}else {
LOGE("GyroSensor: unknown event (type=%d, code=%d)", type, event->code);
}
mInputReader.next();
}
#if FETCH_FULL_EVENT_BEFORE_RETURN
/* if we didn't read a complete event, see if we can fill and
try again instead of returning with nothing and redoing poll. */
if (numEventReceived == 0 && mEnabled == 1) {
n = mInputReader.fill(data_fd);
if (n)
goto again;
}
#endif
return numEventReceived;
}
这里看一下mInputReader,是一个InputEventCircularReader结构,表示的是一个环形的读入数据缓冲区
ssize_t InputEventCircularReader::fill(int fd)
{
size_t numEventsRead = 0;
if (mFreeSpace) {
const ssize_t nread = read(fd, mHead, mFreeSpace * sizeof(input_event));//读取数据
if (nread<0 || nread % sizeof(input_event)) {
// we got a partial event!!
return nread<0 ? -errno : -EINVAL;
}
numEventsRead = nread / sizeof(input_event);
// dumpEvents(mHead, numEventsRead);
D("nread = %ld, numEventsRead = %d.", nread, numEventsRead);
if (numEventsRead) {
mHead += numEventsRead;
mFreeSpace -= numEventsRead;
if (mHead > mBufferEnd) {
size_t s = mHead - mBufferEnd;
memcpy(mBuffer, mBufferEnd, s * sizeof(input_event));
mHead = mBuffer + s;
}
}
}
return numEventsRead;
}
mCurr表示未读事件的第一个,初始为缓冲区首部
Fill函数是把调用read从相应的输入设备读入数据mHead位置
readEvent函数返回mCurr和剩余的数据大小
next函数让mCurr移一个input_event
到这里,sensor HAL层就分析完了