You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by GitBox <gi...@apache.org> on 2018/07/10 21:30:43 UTC

[GitHub] ccollins476ad closed pull request #1255: hw/sensor: Report read errors

ccollins476ad closed pull request #1255: hw/sensor: Report read errors
URL: https://github.com/apache/mynewt-core/pull/1255
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/hw/sensor/include/sensor/sensor.h b/hw/sensor/include/sensor/sensor.h
index 57c59b858c..215946a125 100644
--- a/hw/sensor/include/sensor/sensor.h
+++ b/hw/sensor/include/sensor/sensor.h
@@ -245,6 +245,20 @@ typedef int
 typedef int
 (*sensor_notifier_func_t)(struct sensor *, void *, sensor_event_type_t);
 
+/**
+ * Callback for reporting a sensor read error.  Specified in a sensor error
+ * listener.
+ *
+ * @param sensor The sensor for which a read failed.
+ * @param arg The optional argument associated with the error listener.
+ * @param status Indicates the cause of the read failure.  Determined by the
+ *               underlying sensor driver.
+ * @param type The type of sensor data for which a read was attempted.
+ */
+typedef void
+(*sensor_error_func_t)(struct sensor *sensor, void *arg, int status,
+                       sensor_type_t type);
+
 /**
  *
  */
@@ -267,6 +281,29 @@ struct sensor_listener {
     SLIST_ENTRY(sensor_listener) sl_next;
 };
 
+/**
+ * Reports failed reads of specific kinds of sensor data.
+ */
+struct sensor_err_listener {
+
+    /* The type of sensor reads to report errors for.  This is interpreted as a
+     * mask; this listener is called for failed reads of all sensor types on
+     * this sensor that match the mask.
+     */
+    sensor_type_t sel_sensor_type;
+
+    /* Sensor error handler function.  Called when a read fails. */
+    sensor_error_func_t sel_func;
+
+    /* Optional argument for the error callback. */
+    void *sel_arg;
+
+    /* Next item in the sensor error listener list.  The head of this list is
+     * contained within the sensor object.
+     */
+    SLIST_ENTRY(sensor_err_listener) sel_next;
+};
+
 /**
  * Registration for sensor event notifications
  */
@@ -579,6 +616,11 @@ struct sensor {
      */
     SLIST_HEAD(, sensor_listener) s_listener_list;
 
+    /* A list of listeners that are registered to report read errors for this
+     * sensor
+     */
+    SLIST_HEAD(, sensor_err_listener) s_err_listener_list;
+
     /* A list of notifiers that are registered to receive events from this
      * sensor
      */
@@ -670,9 +712,32 @@ int sensor_register_listener(struct sensor *sensor, struct sensor_listener *list
  *
  * @return 0 on success, non-zero error code on failure.
  */
-
 int sensor_unregister_listener(struct sensor *sensor, struct sensor_listener *listener);
 
+/**
+ * Register a sensor error listener.  The listener is executed when the sensor
+ * manager fails to read from the given sensor.
+ *
+ * @param sensor The sensor to register an error listener on.
+ * @param err_listener The error listener to register.
+ *
+ * @return 0 on success, non-zero error code on failure.
+ */
+int sensor_register_err_listener(struct sensor *sensor,
+        struct sensor_err_listener *err_listener);
+
+/**
+ * Un-register a sensor error listener. This allows a calling application to
+ * clear error callbacks for a given sensor object.
+ *
+ * @param sensor The sensor object.
+ * @param err_listener The error listener to remove from the sensor.
+ *
+ * @return 0 on success, non-zero error code on failure.
+ */
+int sensor_unregister_err_listener(struct sensor *sensor,
+        struct sensor_err_listener *err_listener);
+
 /**
  * @} SensorListenerAPI
  */
diff --git a/hw/sensor/src/sensor.c b/hw/sensor/src/sensor.c
index 36d85ef84a..310acaea80 100644
--- a/hw/sensor/src/sensor.c
+++ b/hw/sensor/src/sensor.c
@@ -1028,6 +1028,54 @@ sensor_unregister_listener(struct sensor *sensor,
     return (rc);
 }
 
+int
+sensor_register_err_listener(struct sensor *sensor,
+        struct sensor_err_listener *err_listener)
+{
+    int rc;
+
+    rc = sensor_lock(sensor);
+    if (rc != 0) {
+        goto err;
+    }
+
+    SLIST_INSERT_HEAD(&sensor->s_err_listener_list, err_listener, sel_next);
+
+    sensor_unlock(sensor);
+
+    return (0);
+err:
+    return (rc);
+}
+
+int
+sensor_unregister_err_listener(struct sensor *sensor,
+        struct sensor_err_listener *err_listener)
+{
+    struct sensor_err_listener *cur;
+    int rc;
+
+    rc = sensor_lock(sensor);
+    if (rc != 0) {
+        goto err;
+    }
+
+    SLIST_FOREACH(cur, &sensor->s_err_listener_list, sel_next) {
+        if (cur == err_listener) {
+            /* Remove this entry from the list */
+            SLIST_REMOVE(&sensor->s_err_listener_list, cur,
+                         sensor_err_listener, sel_next);
+            break;
+        }
+    }
+
+    sensor_unlock(sensor);
+
+    return (0);
+err:
+    return (rc);
+}
+
 static int
 sensor_set_notification(struct sensor *sensor, struct sensor_notifier *notifier)
 {
@@ -1158,6 +1206,27 @@ sensor_read_data_func(struct sensor *sensor, void *arg, void *data,
     return (0);
 }
 
+/**
+ * Reports a read error for the specified sensor and data type.
+ *
+ * @param sensor The sensor for which a read failed.
+ * @param status The status code to pass to error listeners.  This should be
+ *               the error reported by the underlying driver.
+ * @param type The data type being read when the failure occurred.
+ */
+static void
+sensor_read_error_func(struct sensor *sensor, int status, sensor_type_t type)
+{
+    struct sensor_err_listener *err_listener;
+
+    SLIST_FOREACH(err_listener, &sensor->s_err_listener_list, sel_next) {
+        if (err_listener->sel_sensor_type & type) {
+            err_listener->sel_func(sensor, err_listener->sel_arg, status,
+                                   type);
+        }
+    }
+}
+
 /**
  * Puts a interrupt event on the sensor manager evq
  *
@@ -2163,6 +2232,7 @@ sensor_read(struct sensor *sensor, sensor_type_t type,
     rc = sensor->s_funcs->sd_read(sensor, type, sensor_read_data_func, &src,
                                   timeout);
     if (rc) {
+        sensor_read_error_func(sensor, rc, type);
         goto err;
     }
 
diff --git a/hw/sensor/test/pkg.yml b/hw/sensor/test/pkg.yml
new file mode 100644
index 0000000000..1c34dd9a22
--- /dev/null
+++ b/hw/sensor/test/pkg.yml
@@ -0,0 +1,32 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+pkg.name: hw/sensor/test
+pkg.type: unittest
+pkg.description: "Sensor manager unit tests."
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps: 
+    - hw/sensor
+    - test/testutil
+
+pkg.deps.SELFTEST:
+    - sys/console/stub
+    - sys/log/full
+    - sys/stats/stub
diff --git a/hw/sensor/test/src/sensor_test.c b/hw/sensor/test/src/sensor_test.c
new file mode 100644
index 0000000000..5f75b21603
--- /dev/null
+++ b/hw/sensor/test/src/sensor_test.c
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "os/mynewt.h"
+#include "sensor_test.h"
+
+TEST_SUITE(sensor_test_suite_poll)
+{
+    sensor_test_case_poll_err();
+}
+
+#if MYNEWT_VAL(SELFTEST)
+
+int
+main(int argc, char **argv)
+{
+    sensor_test_suite_poll();
+
+    return tu_any_failed;
+}
+
+#endif
diff --git a/hw/sensor/test/src/sensor_test.h b/hw/sensor/test/src/sensor_test.h
new file mode 100644
index 0000000000..90cf00f1c2
--- /dev/null
+++ b/hw/sensor/test/src/sensor_test.h
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_SENSOR_TEST_
+#define H_SENSOR_TEST_
+
+#include "os/mynewt.h"
+#include "testutil/testutil.h"
+
+TEST_SUITE_DECL(sensor_test_suite_poll);
+TEST_CASE_DECL(sensor_test_case_poll_err);
+
+#endif
diff --git a/hw/sensor/test/src/testcases/sensor_test_case_poll_err.c b/hw/sensor/test/src/testcases/sensor_test_case_poll_err.c
new file mode 100644
index 0000000000..f9f75bfb8e
--- /dev/null
+++ b/hw/sensor/test/src/testcases/sensor_test_case_poll_err.c
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "os/mynewt.h"
+#include "sensor/sensor.h"
+#include "sensor_test.h"
+
+struct stcpe_error_rec {
+    struct sensor *sensor;
+    void *arg;
+    int status;
+    sensor_type_t type;
+};
+
+#define STCPE_MAX_ERROR_RECS    16
+
+static struct stcpe_error_rec stcpe_error_recs[STCPE_MAX_ERROR_RECS];
+static int stcpe_num_error_recs;
+
+/** Specifies the return code of subsequent sensor reads. */
+static int stcpe_sensor_read_status;
+
+/**
+ * Sensor read error callback.  Adds an error record to the global
+ * `stcpe_error_recs` array.
+ */
+static void
+stcpe_sensor_err(struct sensor *sensor, void *arg, int status,
+                 sensor_type_t type)
+{
+    struct stcpe_error_rec *rec;
+
+    TEST_ASSERT_FATAL(stcpe_num_error_recs < STCPE_MAX_ERROR_RECS);
+
+    rec = &stcpe_error_recs[stcpe_num_error_recs++];
+    rec->sensor = sensor;
+    rec->arg = arg;
+    rec->status = status;
+    rec->type = type;
+}
+
+/**
+ * Sensor read function.
+ */
+static int
+stcpe_sensor_read(struct sensor *sensor, sensor_type_t type,
+                  sensor_data_func_t data_func, void *arg, uint32_t timeout)
+{
+    return stcpe_sensor_read_status;
+}
+
+TEST_CASE(sensor_test_case_poll_err)
+{
+    static struct sensor_driver driver = {
+        .sd_read = stcpe_sensor_read,
+    };
+
+    struct sensor_err_listener sel1;
+    struct sensor_err_listener sel2;
+    struct sensor sn;
+    int rc;
+
+    sysinit();
+
+    /***
+     * Register the sensor and error listeners.
+     * Listener 1: light
+     * Listener 2: all types
+     */
+
+    rc = sensor_init(&sn, NULL);
+    TEST_ASSERT_FATAL(rc == 0);
+
+    rc = sensor_set_driver(&sn,
+                           SENSOR_TYPE_ACCELEROMETER | SENSOR_TYPE_LIGHT,
+                           &driver);
+    TEST_ASSERT_FATAL(rc == 0);
+
+    sensor_set_type_mask(&sn, SENSOR_TYPE_ALL);
+
+    rc = sensor_mgr_register(&sn);
+    TEST_ASSERT_FATAL(rc == 0);
+
+    sel1.sel_sensor_type = SENSOR_TYPE_LIGHT;
+    sel1.sel_func = stcpe_sensor_err;
+    sel1.sel_arg = NULL;
+    rc = sensor_register_err_listener(&sn, &sel1);
+    TEST_ASSERT_FATAL(rc == 0);
+
+    sel2.sel_sensor_type = SENSOR_TYPE_ALL;
+    sel2.sel_func = stcpe_sensor_err;
+    sel2.sel_arg = NULL;
+    rc = sensor_register_err_listener(&sn, &sel2);
+    TEST_ASSERT_FATAL(rc == 0);
+
+    /*** Successful accelerometer read; ensure no error. */
+
+    stcpe_sensor_read_status = 0;
+    rc = sensor_read(&sn, SENSOR_TYPE_ACCELEROMETER, NULL, NULL,
+                     OS_TIMEOUT_NEVER);
+    TEST_ASSERT_FATAL(rc == 0);
+    TEST_ASSERT_FATAL(stcpe_num_error_recs == 0);
+
+    /*** Failed acceleromter read; ensure one error record. */
+
+    stcpe_sensor_read_status = 1;
+    rc = sensor_read(&sn, SENSOR_TYPE_ACCELEROMETER, NULL, NULL,
+                     OS_TIMEOUT_NEVER);
+    TEST_ASSERT_FATAL(rc == 1);
+    TEST_ASSERT_FATAL(stcpe_num_error_recs == 1);
+    TEST_ASSERT_FATAL(stcpe_error_recs[0].sensor == &sn);
+    TEST_ASSERT_FATAL(stcpe_error_recs[0].arg == NULL);
+    TEST_ASSERT_FATAL(stcpe_error_recs[0].status == 1);
+    TEST_ASSERT_FATAL(stcpe_error_recs[0].type == SENSOR_TYPE_ACCELEROMETER);
+
+    /** Failed light read; ensure two additional error records. */
+
+    stcpe_sensor_read_status = 2;
+    rc = sensor_read(&sn, SENSOR_TYPE_LIGHT, NULL, NULL, OS_TIMEOUT_NEVER);
+    TEST_ASSERT_FATAL(rc == 2);
+    TEST_ASSERT_FATAL(stcpe_num_error_recs == 3);
+    TEST_ASSERT_FATAL(stcpe_error_recs[1].sensor == &sn);
+    TEST_ASSERT_FATAL(stcpe_error_recs[1].arg == NULL);
+    TEST_ASSERT_FATAL(stcpe_error_recs[1].status == 2);
+    TEST_ASSERT_FATAL(stcpe_error_recs[1].type == SENSOR_TYPE_LIGHT);
+    TEST_ASSERT_FATAL(stcpe_error_recs[2].sensor == &sn);
+    TEST_ASSERT_FATAL(stcpe_error_recs[2].arg == NULL);
+    TEST_ASSERT_FATAL(stcpe_error_recs[2].status == 2);
+    TEST_ASSERT_FATAL(stcpe_error_recs[2].type == SENSOR_TYPE_LIGHT);
+}
diff --git a/hw/sensor/test/syscfg.yml b/hw/sensor/test/syscfg.yml
new file mode 100644
index 0000000000..de6c2f1c7a
--- /dev/null
+++ b/hw/sensor/test/syscfg.yml
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+syscfg.vals:
+    SENSOR_OIC: 0


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services