static int sensors__get_sensors_list(struct sensors_module_t* module,
        struct sensor_t const** list)
{
    int  fd = qemud_channel_open(SENSORS_SERVICE_NAME);
    char buffer[12];
    int  mask, nn, count;

    int  ret;
    if (fd < 0) {
        E("%s: no qemud connection", __FUNCTION__);
        return 0;
    }
    ret = qemud_channel_send(fd, "list-sensors", -1);
    if (ret < 0) {
        E("%s: could not query sensor list: %s", __FUNCTION__,
          strerror(errno));
        close(fd);
        return 0;
    }
    ret = qemud_channel_recv(fd, buffer, sizeof buffer-1);
    if (ret < 0) {
        E("%s: could not receive sensor list: %s", __FUNCTION__,
          strerror(errno));
        close(fd);
        return 0;
    }
    buffer[ret] = 0;
    close(fd);

    /* the result is a integer used as a mask for available sensors */
    mask  = atoi(buffer);
    count = 0;
    for (nn = 0; nn < MAX_NUM_SENSORS; nn++) {
        if (((1 << nn) & mask) == 0)
            continue;

        sSensorList[count++] = sSensorListInit[nn];
    }
    D("%s: returned %d sensors (mask=%d)", __FUNCTION__, count, mask);
    *list = sSensorList;
    return count;
}
Exemplo n.º 2
0
static void emu_sensors_list(int qfd)
{
	char buffer[12];
	int  mask, nn, count;

	int  ret;
	if (qfd < 0) {
		err("no qemud connection");
		return;
	}
	ret = qemud_channel_send(qfd, "list-sensors", -1);
	if (ret < 0) {
		err("could not query sensor list: %s", strerror(errno));
		return;
	}
	ret = qemud_channel_recv(qfd, buffer, sizeof(buffer)-1);
	if (ret < 0) {
		err("could not receive sensor list: %s", strerror(errno));
		return;
	}
	buffer[ret] = 0;

	/* the result is a integer used as a mask for available sensors */
	mask  = atoi(buffer);
	count = 0;
	for (nn = 0; nn < MAX_NUM_SENSORS; nn++) {
		const struct sensor_t *s;
		if (((1 << nn) & mask) == 0)
			continue;
		/* print info about the enabled sensor */
		s = &s_availableSensors[nn];
		info("\tSensorID: %d", s->handle);
		info("\t%s (%s)", s->name, s->vendor);
		info("\tmax=%0.2f, resolution=%0.2f\n", s->maxRange,
			s->resolution);
	}

	return;
}
static int
data__poll(struct sensors_poll_device_t *dev, sensors_event_t* values)
{
    SensorPoll*  data = (void*)dev;
    int fd = data->events_fd;

    D("%s: data=%p", __FUNCTION__, dev);

    // there are pending sensors, returns them now...
    if (data->pendingSensors) {
        return pick_sensor(data, values);
    }

    // wait until we get a complete event for an enabled sensor
    uint32_t new_sensors = 0;

    while (1) {
        /* read the next event */
        char     buff[256];
        int      len = qemud_channel_recv(data->events_fd, buff, sizeof buff-1);
        float    params[3];
        int64_t  event_time;

        if (len < 0) {
            E("%s: len=%d, errno=%d: %s", __FUNCTION__, len, errno, strerror(errno));
            return -errno;
        }

        buff[len] = 0;

        /* "wake" is sent from the emulator to exit this loop. */
        if (!strcmp((const char*)data, "wake")) {
            return 0x7FFFFFFF;
        }

        /* "acceleration:<x>:<y>:<z>" corresponds to an acceleration event */
        if (sscanf(buff, "acceleration:%g:%g:%g", params+0, params+1, params+2) == 3) {
            new_sensors |= SENSORS_ACCELERATION;
            data->sensors[ID_ACCELERATION].acceleration.x = params[0];
            data->sensors[ID_ACCELERATION].acceleration.y = params[1];
            data->sensors[ID_ACCELERATION].acceleration.z = params[2];
            continue;
        }

        /* "orientation:<azimuth>:<pitch>:<roll>" is sent when orientation changes */
        if (sscanf(buff, "orientation:%g:%g:%g", params+0, params+1, params+2) == 3) {
            new_sensors |= SENSORS_ORIENTATION;
            data->sensors[ID_ORIENTATION].orientation.azimuth = params[0];
            data->sensors[ID_ORIENTATION].orientation.pitch   = params[1];
            data->sensors[ID_ORIENTATION].orientation.roll    = params[2];
            data->sensors[ID_ORIENTATION].orientation.status  = SENSOR_STATUS_ACCURACY_HIGH;
            continue;
        }

        /* "magnetic:<x>:<y>:<z>" is sent for the params of the magnetic field */
        if (sscanf(buff, "magnetic:%g:%g:%g", params+0, params+1, params+2) == 3) {
            new_sensors |= SENSORS_MAGNETIC_FIELD;
            data->sensors[ID_MAGNETIC_FIELD].magnetic.x = params[0];
            data->sensors[ID_MAGNETIC_FIELD].magnetic.y = params[1];
            data->sensors[ID_MAGNETIC_FIELD].magnetic.z = params[2];
            data->sensors[ID_MAGNETIC_FIELD].magnetic.status = SENSOR_STATUS_ACCURACY_HIGH;
            continue;
        }

        /* "temperature:<celsius>" */
        if (sscanf(buff, "temperature:%g", params+0) == 1) {
            new_sensors |= SENSORS_TEMPERATURE;
            data->sensors[ID_TEMPERATURE].temperature = params[0];
            continue;
        }

        /* "proximity:<value>" */
        if (sscanf(buff, "proximity:%g", params+0) == 1) {
            new_sensors |= SENSORS_PROXIMITY;
            data->sensors[ID_PROXIMITY].distance = params[0];
            continue;
        }

        /* "sync:<time>" is sent after a series of sensor events.
         * where 'time' is expressed in micro-seconds and corresponds
         * to the VM time when the real poll occured.
         */
        if (sscanf(buff, "sync:%lld", &event_time) == 1) {
            if (new_sensors) {
                data->pendingSensors = new_sensors;
                int64_t t = event_time * 1000LL;  /* convert to nano-seconds */

                /* use the time at the first sync: as the base for later
                 * time values */
                if (data->timeStart == 0) {
                    data->timeStart  = data__now_ns();
                    data->timeOffset = data->timeStart - t;
                }
                t += data->timeOffset;

                while (new_sensors) {
                    uint32_t i = 31 - __builtin_clz(new_sensors);
                    new_sensors &= ~(1<<i);
                    data->sensors[i].timestamp = t;
                }
                return pick_sensor(data, values);
            } else {
                D("huh ? sync without any sensor data ?");
            }
            continue;
        }
        D("huh ? unsupported command");
    }
    return -1;
}
Exemplo n.º 4
0
/* Block until new sensor events are reported by the emulator, or if a
 * 'wake' command is received through the service. On succes, return 0
 * and updates the |pendingEvents| and |sensors| fields of |dev|.
 * On failure, return -errno.
 *
 * Note: The device lock must be acquired when calling this function, and
 *       will still be held on return. However, the function releases the
 *       lock temporarily during the blocking wait.
 */
static int sensor_device_poll_event_locked(SensorDevice* dev)
{
    D("%s: dev=%p", __FUNCTION__, dev);

    int fd = sensor_device_get_fd_locked(dev);
    if (fd < 0) {
        E("%s: Could not get pipe channel: %s", __FUNCTION__, strerror(-fd));
        return fd;
    }

    // Accumulate pending events into |events| and |new_sensors| mask
    // until a 'sync' or 'wake' command is received. This also simplifies the
    // code a bit.
    uint32_t new_sensors = 0U;
    sensors_event_t* events = dev->sensors;

    int64_t event_time = -1;
    int ret = 0;

    for (;;) {
        /* Release the lock since we're going to block on recv() */
        pthread_mutex_unlock(&dev->lock);

        /* read the next event */
        char buff[256];
        int len = qemud_channel_recv(fd, buff, sizeof(buff) - 1U);
        /* re-acquire the lock to modify the device state. */
        pthread_mutex_lock(&dev->lock);

        if (len < 0) {
            ret = -errno;
            E("%s(fd=%d): Could not receive event data len=%d, errno=%d: %s",
              __FUNCTION__, fd, len, errno, strerror(errno));
            break;
        }
        buff[len] = 0;
        D("%s(fd=%d): received [%s]", __FUNCTION__, fd, buff);


        /* "wake" is sent from the emulator to exit this loop. */
        /* TODO(digit): Is it still needed? */
        if (!strcmp((const char*)buff, "wake")) {
            ret = 0x7FFFFFFF;
            break;
        }

        float params[3];

        /* "acceleration:<x>:<y>:<z>" corresponds to an acceleration event */
        if (sscanf(buff, "acceleration:%g:%g:%g", params+0, params+1, params+2)
                == 3) {
            new_sensors |= SENSORS_ACCELERATION;
            events[ID_ACCELERATION].acceleration.x = params[0];
            events[ID_ACCELERATION].acceleration.y = params[1];
            events[ID_ACCELERATION].acceleration.z = params[2];
            events[ID_ACCELERATION].type = SENSOR_TYPE_ACCELEROMETER;
            continue;
        }

        /* "orientation:<azimuth>:<pitch>:<roll>" is sent when orientation
         * changes */
        if (sscanf(buff, "orientation:%g:%g:%g", params+0, params+1, params+2)
                == 3) {
            new_sensors |= SENSORS_ORIENTATION;
            events[ID_ORIENTATION].orientation.azimuth = params[0];
            events[ID_ORIENTATION].orientation.pitch   = params[1];
            events[ID_ORIENTATION].orientation.roll    = params[2];
            events[ID_ORIENTATION].orientation.status  =
                    SENSOR_STATUS_ACCURACY_HIGH;
            events[ID_ACCELERATION].type = SENSOR_TYPE_ORIENTATION;
            continue;
        }

        /* "magnetic:<x>:<y>:<z>" is sent for the params of the magnetic
         * field */
        if (sscanf(buff, "magnetic:%g:%g:%g", params+0, params+1, params+2)
                == 3) {
            new_sensors |= SENSORS_MAGNETIC_FIELD;
            events[ID_MAGNETIC_FIELD].magnetic.x = params[0];
            events[ID_MAGNETIC_FIELD].magnetic.y = params[1];
            events[ID_MAGNETIC_FIELD].magnetic.z = params[2];
            events[ID_MAGNETIC_FIELD].magnetic.status =
                    SENSOR_STATUS_ACCURACY_HIGH;
            events[ID_ACCELERATION].type = SENSOR_TYPE_MAGNETIC_FIELD;
            continue;
        }

        /* "temperature:<celsius>" */
        if (sscanf(buff, "temperature:%g", params+0) == 1) {
            new_sensors |= SENSORS_TEMPERATURE;
            events[ID_TEMPERATURE].temperature = params[0];
            events[ID_ACCELERATION].type = SENSOR_TYPE_TEMPERATURE;
            continue;
        }

        /* "proximity:<value>" */
        if (sscanf(buff, "proximity:%g", params+0) == 1) {
            new_sensors |= SENSORS_PROXIMITY;
            events[ID_PROXIMITY].distance = params[0];
            events[ID_ACCELERATION].type = SENSOR_TYPE_PROXIMITY;
            continue;
        }

        /* "sync:<time>" is sent after a series of sensor events.
         * where 'time' is expressed in micro-seconds and corresponds
         * to the VM time when the real poll occured.
         */
        if (sscanf(buff, "sync:%lld", &event_time) == 1) {
            if (new_sensors) {
                goto out;
            }
            D("huh ? sync without any sensor data ?");
            continue;
        }
        D("huh ? unsupported command");
    }
out:
    if (new_sensors) {
        /* update the time of each new sensor event. */
        dev->pendingSensors |= new_sensors;
        int64_t t = (event_time < 0) ? 0 : event_time * 1000LL;

        /* use the time at the first sync: as the base for later
         * time values */
        if (dev->timeStart == 0) {
            dev->timeStart  = now_ns();
            dev->timeOffset = dev->timeStart - t;
        }
        t += dev->timeOffset;

        while (new_sensors) {
            uint32_t i = 31 - __builtin_clz(new_sensors);
            new_sensors &= ~(1U << i);
            dev->sensors[i].timestamp = t;
        }
    }
    return ret;
}
/**
 * This a very simple event loop for the fingerprint sensor. For a given state (enroll, scan),
 * this would receive events from the sensor and forward them to fingerprintd using the
 * notify() method.
 *
 * In this simple example, we open a qemu channel (a pipe) where the developer can inject events to
 * exercise the API and test application code.
 *
 * The scanner should remain in the scanning state until either an error occurs or the operation
 * completes.
 *
 * Recoverable errors such as EINTR should be handled locally;  they should not
 * be propagated unless there's something the user can do about it (e.g. "clean sensor"). Such
 * messages should go through the onAcquired() interface.
 *
 * If an unrecoverable error occurs, an acquired message (e.g. ACQUIRED_PARTIAL) should be sent,
 * followed by an error message (e.g. FINGERPRINT_ERROR_UNABLE_TO_PROCESS).
 *
 * Note that this event loop would typically run in TEE since it must interact with the sensor
 * hardware and handle raw fingerprint data and encrypted templates.  It is expected that
 * this code monitors the TEE for resulting events, such as enrollment and authentication status.
 * Here we just have a very simple event loop that monitors a qemu channel for pseudo events.
 */
static void* listenerFunction(void* data) {
    ALOGD("----------------> %s ----------------->", __FUNCTION__);
    qemu_fingerprint_device_t* qdev = (qemu_fingerprint_device_t*)data;

    int fd = qemud_channel_open(FINGERPRINT_LISTEN_SERVICE_NAME);
    pthread_mutex_lock(&qdev->lock);
    qdev->qchanfd = fd;
    if (qdev->qchanfd < 0) {
        ALOGE("listener cannot open fingerprint listener service exit");
        pthread_mutex_unlock(&qdev->lock);
        return NULL;
    }
    qdev->listener.state = STATE_IDLE;
    pthread_mutex_unlock(&qdev->lock);

    const char* cmd = "listen";
    if (qemud_channel_send(qdev->qchanfd, cmd, strlen(cmd)) < 0) {
        ALOGE("cannot write fingerprint 'listen' to host");
        goto done_quiet;
    }

    int comm_errors = 0;
    struct pollfd pfd = {
        .fd = qdev->qchanfd,
        .events = POLLIN,
    };
    while (1) {
        int size = 0;
        int fid = 0;
        char buffer[MAX_COMM_CHARS] = {0};
        bool disconnected = false;
        while (1) {
            if (getListenerState(qdev) == STATE_EXIT) {
                ALOGD("Received request to exit listener thread");
                goto done;
            }

            // Reset revents before poll() (just to be safe)
            pfd.revents = 0;

            // Poll qemud channel for 5 seconds
            // TODO: Eliminate the timeout so that polling can be interrupted
            // instantly. One possible solution is to follow the example of
            // android::Looper ($AOSP/system/core/include/utils/Looper.h and
            // $AOSP/system/core/libutils/Looper.cpp), which makes use of an
            // additional file descriptor ("wake event fd").
            int nfds = poll(&pfd, 1, 5000);
            if (nfds < 0) {
                ALOGE("Could not poll qemud channel: %s", strerror(errno));
                goto done;
            }

            if (!nfds) {
                // poll() timed out - try again
                continue;
            }

            // assert(nfds == 1)
            if (pfd.revents & POLLIN) {
                // Input data being available doesn't rule out a disconnection
                disconnected = pfd.revents & (POLLERR | POLLHUP);
                break;  // Exit inner while loop
            } else {
                // Some event(s) other than "input data available" occurred,
                // i.e. POLLERR or POLLHUP, indicating a disconnection
                ALOGW("Lost connection to qemud channel");
                goto done;
            }
        }

        // Shouldn't block since we were just notified of a POLLIN event
        if ((size = qemud_channel_recv(qdev->qchanfd, buffer,
                                       sizeof(buffer) - 1)) > 0) {
            buffer[size] = '\0';
            if (sscanf(buffer, "on:%d", &fid) == 1) {
                if (fid > 0 && fid <= MAX_FID_VALUE) {
                    switch (qdev->listener.state) {
                        case STATE_ENROLL:
                            send_enroll_notice(qdev, fid);
                            break;
                        case STATE_SCAN:
                            send_scan_notice(qdev, fid);
                            break;
                        default:
                            ALOGE("fingerprint event listener at unexpected "
                                  "state 0%x",
                                  qdev->listener.state);
                    }
                } else {
                    ALOGE("fingerprintid %d not in valid range [%d, %d] and "
                          "will be "
                          "ignored",
                          fid, 1, MAX_FID_VALUE);
                    continue;
                }
            } else if (strncmp("off", buffer, 3) == 0) {
                // TODO: Nothing to do here ? Looks valid
                ALOGD("fingerprint ID %d off", fid);
            } else {
                ALOGE("Invalid command '%s' to fingerprint listener", buffer);
            }

            if (disconnected) {
                ALOGW("Connection to qemud channel has been lost");
                break;
            }
        } else {
            ALOGE("fingerprint listener receive failure");
            if (comm_errors > MAX_COMM_ERRORS)
                break;
        }
    }

done:
    ALOGD("Listener exit with %d receive errors", comm_errors);
done_quiet:
    close(qdev->qchanfd);
    return NULL;
}

static int fingerprint_close(hw_device_t* device) {
    ALOGD("----------------> %s ----------------->", __FUNCTION__);
    if (device == NULL) {
        ALOGE("fingerprint hw device is NULL");
        return -1;
    }

    qemu_fingerprint_device_t* qdev = (qemu_fingerprint_device_t*)device;
    pthread_mutex_lock(&qdev->lock);
    // Ask listener thread to exit
    qdev->listener.state = STATE_EXIT;
    pthread_mutex_unlock(&qdev->lock);

    pthread_join(qdev->listener.thread, NULL);
    pthread_mutex_destroy(&qdev->lock);
    free(qdev);

    return 0;
}
Exemplo n.º 6
0
int  main(void)
{
    int  qemud_fd, count = 0;

    /* try to connect to the qemud service */
    {
        int  tries = MAX_TRIES;

        while (1) {
            qemud_fd = qemud_channel_open( "boot-properties" );
            if (qemud_fd >= 0)
                break;

            if (--tries <= 0) {
                DD("Could not connect after too many tries. Aborting");
                return 1;
            }

            DD("waiting 1s to wait for qemud.");
            sleep(1);
        }
    }

    DD("connected to '%s' qemud service.", QEMUD_SERVICE);

    /* send the 'list' command to the service */
    if (qemud_channel_send(qemud_fd, "list", -1) < 0) {
        DD("could not send command to '%s' service", QEMUD_SERVICE);
        return 1;
    }

    /* read each system property as a single line from the service,
     * until exhaustion.
     */
    for (;;)
    {
#define  BUFF_SIZE   (PROPERTY_KEY_MAX + PROPERTY_VALUE_MAX + 2)

        char* q;
        char  temp[BUFF_SIZE];
        int   len = qemud_channel_recv(qemud_fd, temp, sizeof temp - 1);

        if (len < 0 || len > BUFF_SIZE-1)
            break;

        temp[len] = '\0';  /* zero-terminate string */

        DD("received: %.*s", len, temp);

        /* separate propery name from value */
        q = strchr(temp, '=');
        if (q == NULL) {
            DD("invalid format, ignored.");
            continue;
        }
        *q++ = '\0';

        if (property_set(temp, q) < 0) {
            DD("could not set property '%s' to '%s'", temp, q);
        } else {
            count += 1;
        }
    }

    /* finally, close the channel and exit */
    close(qemud_fd);
    DD("exiting (%d properties set).", count);
    return 0;
}
Exemplo n.º 7
0
int  main(void)
{
    int  qemud_fd, count = 0;

    /* try to connect to the qemud service */
    {
        int  tries = MAX_TRIES;

        while (1) {
            qemud_fd = qemud_channel_open( "boot-properties" );
            if (qemud_fd >= 0)
                break;

            if (--tries <= 0) {
                DD("Could not connect after too many tries. Aborting");
                return 1;
            }

            DD("waiting 1s to wait for qemud.");
            sleep(1);
        }
    }

    DD("connected to '%s' qemud service.", QEMUD_SERVICE);

    /* send the 'list' command to the service */
    if (qemud_channel_send(qemud_fd, "list", -1) < 0) {
        DD("could not send command to '%s' service", QEMUD_SERVICE);
        return 1;
    }

    /* read each system property as a single line from the service,
     * until exhaustion.
     */
    for (;;)
    {
#define  BUFF_SIZE   (PROPERTY_KEY_MAX + PROPERTY_VALUE_MAX + 2)
        DD("receiving..");
        char* q;
        char  temp[BUFF_SIZE];
        int   len = qemud_channel_recv(qemud_fd, temp, sizeof temp - 1);

        /* lone NUL-byte signals end of properties */
        if (len < 0 || len > BUFF_SIZE-1 || temp[0] == '\0')
            break;

        temp[len] = '\0';  /* zero-terminate string */

        DD("received: %.*s", len, temp);

        /* separate propery name from value */
        q = strchr(temp, '=');
        if (q == NULL) {
            DD("invalid format, ignored.");
            continue;
        }
        *q++ = '\0';

        if (property_set(temp, q) < 0) {
            DD("could not set property '%s' to '%s'", temp, q);
        } else {
            count += 1;
        }
    }

    char temp[BUFF_SIZE];
    for (;;) {
        usleep(5000000); /* 5 seconds */
        property_get("sys.boot_completed", temp, "");
        int is_boot_completed = (strncmp(temp, "1", 1) == 0) ? 1 : 0;
        if (is_boot_completed) {
            notifyHostBootComplete();
            break;
        }
    }

    /* HACK start adbd periodically every minute, if adbd is already running, this is a no-op */
    for(;;) {
        usleep(60000000); /* 1 minute */
        property_set("qemu.adbd", "start");
    }

    /* finally, close the channel and exit */
    if (s_QemuMiscPipe >= 0) {
        close(s_QemuMiscPipe);
        s_QemuMiscPipe = -1;
    }
    close(qemud_fd);
    DD("exiting (%d properties set).", count);
    return 0;
}