Transplantation of android2.3.4 Gyroscope

Source: Internet
Author: User
Tags array definition

Background

1. Requirements

The gyroscope hardware is not connected to the android CPU, so there is no gyroscope driver, and the gyroscope data is transmitted through a user space C program.

2. Ideas

Modify the Hal layer of the gyroscope, build a socket client on the Hal layer, and build a socket server on the C program of the data source. Once data exists, the C program sends data to the Hal layer of the gyroscope through socket and reports the data.


Step 2

1. Copy the device/Samsung/Crespo/libsensors directory to the hardware/libhardware/modules directory.

2. Modify the sensor array definition in the sensors. cpp file.

Because only gyroscope sensors are used, other sensor definitions are deleted.

static const struct sensor_t sSensorList[] = {/*        { "KR3DM 3-axis Accelerometer",          "STMicroelectronics",          1, SENSORS_ACCELERATION_HANDLE,          SENSOR_TYPE_ACCELEROMETER, RANGE_A, CONVERT_A, 0.23f, 20000, { } },        { "AK8973 3-axis Magnetic field sensor",          "Asahi Kasei Microdevices",          1, SENSORS_MAGNETIC_FIELD_HANDLE,          SENSOR_TYPE_MAGNETIC_FIELD, 2000.0f, CONVERT_M, 6.8f, 16667, { } },        { "AK8973 Orientation sensor",          "Asahi Kasei Microdevices",          1, SENSORS_ORIENTATION_HANDLE,          SENSOR_TYPE_ORIENTATION, 360.0f, CONVERT_O, 7.8f, 16667, { } },        { "GP2A Light sensor",          "Sharp",          1, SENSORS_LIGHT_HANDLE,          SENSOR_TYPE_LIGHT, 3000.0f, 1.0f, 0.75f, 0, { } },        { "GP2A Proximity sensor",          "Sharp",          1, SENSORS_PROXIMITY_HANDLE,          SENSOR_TYPE_PROXIMITY, 5.0f, 5.0f, 0.75f, 0, { } },*/        { "K3G Gyroscope sensor",          "STMicroelectronics",          1, SENSORS_GYROSCOPE_HANDLE,          SENSOR_TYPE_GYROSCOPE, RANGE_GYRO, CONVERT_GYRO, 6.1f, 1190, { } },};


3. Modify the sensors. cpp sensors_poll_context_t struct and delete other sensor definitions.

struct sensors_poll_context_t {    struct sensors_poll_device_t device; // must be first        sensors_poll_context_t();        ~sensors_poll_context_t();    int activate(int handle, int enabled);    int setDelay(int handle, int64_t ns);    int pollEvents(sensors_event_t* data, int count);private:    enum {        //light           = 0,        //proximity       = 1,        //akm             = 2,        //gyro            = 3,        gyro= 0,        numSensorDrivers,        numFds,    };    static const size_t wake = numFds - 1; //wake = 1    static const char WAKE_MESSAGE = 'W';    struct pollfd mPollFds[numFds];//2    int mWritePipeFd;    SensorBase* mSensors[numSensorDrivers];// 2    int handleToDriver(int handle) const {        switch (handle) {/*            case ID_A:            case ID_M:            case ID_O:                return akm;            case ID_P:                return proximity;            case ID_L:                return light;*/            case ID_GY:                return gyro;        }        return -EINVAL;    }};

Including constructors:

sensors_poll_context_t::sensors_poll_context_t(){/*    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[akm] = new AkmSensor();    mPollFds[akm].fd = mSensors[akm]->getFd();    mPollFds[akm].events = POLLIN;    mPollFds[akm].revents = 0;*///LOGD("sensors_poll_context_t");    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];//wake equals 1    mPollFds[wake].fd = wakeFds[0];//store the reading fd of the pipe    mPollFds[wake].events = POLLIN;    mPollFds[wake].revents = 0;}



3. Modify the getfd () function of gyrosensor. cpp and change the original file descriptor returned by the gyro device driver to the file descriptor returned by the socket.

 int GyroSensor::getFd(){if(mSocketFd == -1){socket_connect();}return mSocketFd;}


Msocketfd is the socket file descriptor defined in gyrosensor. h. The socket_connect () function is used to connect to the socket server.

Let's look back at the sensors. cpp file's sensors_poll_context_t constructor:

mSensors[gyro] = new GyroSensor();    mPollFds[gyro].fd = mSensors[gyro]->getFd();    mPollFds[gyro].events = POLLIN;    mPollFds[gyro].revents = 0;


After the gyro class is initialized here, the socket file descriptor is obtained through getfd (), and then the file descriptor can be read through the poll function. The poll is read in the sensors_poll_context_t: pollevents function, the Code does not need to be changed, like this:


int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count){//what does parameter count mean ? fuck     int nbEvents = 0;    int n = 0;//LOGD("sensors_poll_context_t::pollEvents");//LOGD("count=%d",count);    do {        // see if we have some leftover from the last poll()        for (int i=0 ; count && i<numSensorDrivers ; i++) {            SensorBase* const sensor(mSensors[i]);            if ((mPollFds[i].revents & POLLIN) || (sensor->hasPendingEvents())) {                int nb = sensor->readEvents(data, count);                if (nb < count) {                    // no more data for this sensor                    mPollFds[i].revents = 0;                }                count -= nb;                nbEvents += nb;                data += nb;            }        }        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;            }//read data from pipe            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    } while (n && count);    return nbEvents;}


4. Modify the gyro constructor to delete the Code related to the device driver:


GyroSensor::GyroSensor()    : SensorBase(NULL, "gyro"),      mEnabled(0),      mInputReader(4),      mHasPendingEvent(false),      mEnabledTime(0),      mSocketFd(-1){//LOGD("GyroSensor::GyroSensor");    mPendingEvent.version = sizeof(sensors_event_t);    mPendingEvent.sensor = ID_GY;    mPendingEvent.type = SENSOR_TYPE_GYROSCOPE;    memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));/*    if (data_fd) {        strcpy(input_sysfs_path, "/sys/class/input/");        strcat(input_sysfs_path, input_name);        strcat(input_sysfs_path, "/device/");        input_sysfs_path_len = strlen(input_sysfs_path);        enable(0, 1);    }*/}

5. modify other member functions of the gyro class, including setdelay, enable, setinitialstate, and other functions to delete all the code:

int GyroSensor::setInitialState() {/*    struct input_absinfo absinfo_x;    struct input_absinfo absinfo_y;    struct input_absinfo absinfo_z;    float value;    if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_GYRO_X), &absinfo_x) &&        !ioctl(data_fd, EVIOCGABS(EVENT_TYPE_GYRO_X), &absinfo_y) &&        !ioctl(data_fd, EVIOCGABS(EVENT_TYPE_GYRO_X), &absinfo_z)) {        value = absinfo_x.value;        mPendingEvent.data[0] = value * CONVERT_GYRO_X;        value = absinfo_x.value;        mPendingEvent.data[1] = value * CONVERT_GYRO_Y;        value = absinfo_x.value;        mPendingEvent.data[2] = value * CONVERT_GYRO_Z;        mHasPendingEvent = true;    }*///LOGD("GyroSensor::setInitialState");    return 0;}




int GyroSensor::enable(int32_t, int en) {/*    int flags = en ? 1 : 0;    if (flags != mEnabled) {        int fd;        strcpy(&input_sysfs_path[input_sysfs_path_len], "enable");        fd = open(input_sysfs_path, O_RDWR);        if (fd >= 0) {            char buf[2];            int err;            buf[1] = 0;            if (flags) {                buf[0] = '1';                mEnabledTime = getTimestamp() + IGNORE_EVENT_TIME;            } else {                buf[0] = '0';            }            err = write(fd, buf, sizeof(buf));            close(fd);            mEnabled = flags;            setInitialState();            return 0;        }        return -1;    }*///LOGD("GyroSensor::enable");    return 0;}

int GyroSensor::setDelay(int32_t handle, int64_t delay_ns){/*    int fd;    strcpy(&input_sysfs_path[input_sysfs_path_len], "poll_delay");    fd = open(input_sysfs_path, O_RDWR);    if (fd >= 0) {        char buf[80];        sprintf(buf, "%lld", delay_ns);        write(fd, buf, strlen(buf)+1);        close(fd);        return 0;    }return -1;*///LOGD("GyroSensor::setDelay");return 0;    }

6. Modify the readevents function of the gyro class. This function is the most important function and reads gyro data from the socket:

float value = 0;char buf[2];int nread = 0;nread = read(mSocketFd, buf, 2);if(nread <= 0){LOGE("GyroSensor::readEvents read error.");return 0;}float value = (float)((buf[0] << 8) + buf[1]);//LOGD("gyro_msg_handle, value=%f",value);value *= CONVERT_GYRO_X;mPendingEvent.data[0] = value;mPendingEvent.data[1] = value;mPendingEvent.data[2] = value;*data = *mPendingEvent;return 1;

The sokcet server sends two bytes of data each time. Because it is a single-axis gyroscope, there is only one data record. Fill the data of mpendingevent with three bytes of the same data and assign the value to * data, return 1, indicating that one data entry is read.


7. Modify the Android. mk file under libsensors:


LOCAL_MODULE := sensors.default


8. after compilation, generate sensors. default. to the LIB/HW directory, delete other so files with sensors text under the HW directory and leave only sensors. default. then you can test the so file on the simulator or device. The Java test program at the app layer is as follows:

Package COM. hase. ng102.sensors; import android. r. string; import android. app. activity; import android. content. context; import android. hardware. sensor; import android. hardware. sensorevent; import android. hardware. sensoreventlistener; import android. hardware. sensormanager; import android. OS. bundle; import android. util. log; import android. widget. textview; public class sensordemoactivity extends activity {// set the log label Private Static final string tag = "sensors"; private sensormanager Sm; private textview TV1;/** called when the activity is first created. * // @ override public void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. main); TV1 = (textview) This. findviewbyid (R. id. TV1); Sm = (sensormanager) getsystemservice (context. sensor_service); log. D (string. format ("Ge Tsystemservice % s ", Sm = NULL? "Sucess": "fail"), tag); int sensortype = sensor. type_gyroscope; SM. registerlistener (myaccelerometerlistener, SM. getdefasensensor (sensortype), sensormanager. sensor_delay_normal);}/** implementation of the sensoreventlistener interface, two methods need to be implemented * method 1 onsensorchanged is called when data changes * method 2 onaccuracychanged is called when the precision of the obtained data changes, for example, when the data cannot be obtained suddenly, **/FINAL sensoreventlistener myaccelerometerlistener = new sensoreventlistener () {// rewrite onse Nsorchanged method // public void onsensorchanged (sensorevent) {If (sensorevent. sensor. getType () = sensor. type_gyroscope) {log. I (TAG, "onsensorchanged"); // The meaning of the three values is explained in the illustration. Float x = sensorevent. values [0]; float y = sensorevent. values [1]; float z = sensorevent. values [2]; string MSG = string. format ("x = % F \ n y = % F \ N z = % F \ n", x, y, z); tv1.settext (MSG); log. I (TAG, MSG);} else {string MSG = "Other sens ORS data changed "; tv1.settext (MSG); log. I (TAG, MSG) ;}/// rewrite onaccuracychanged method public void onaccuracychanged (sensor, int accuracy) {log. I (TAG, "onaccuracychanged") ;}}; public void onpause () {/** is critical: note that even if the activity is invisible, the sensor will continue to work. During the test, we can find that there is no normal refresh frequency * which is also very high. Therefore, you must disable the trigger in the onpause method, otherwise, it will consume a lot of User power, which is not responsible. **/SM. unregisterlistener (myaccelerometerlistener); Super. onpause ();}}




Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.