drivers/timer: backport the latest upper-half driver
authorHeesub Shin <heesub.shin@samsung.com>
Fri, 31 Mar 2017 04:04:42 +0000 (13:04 +0900)
committerHeesub Shin <heesub.shin@samsung.com>
Tue, 18 Apr 2017 03:02:04 +0000 (12:02 +0900)
The upper-half timer drvier has been left abandoned in TizenRT, though
there were many changes at upstream. This commit backports the latest
upper-half driver of timer from NuttX, so that users can implement
their lower-half driver more easily.

This commit is introducing huge changes, but it does not cause any harm
because in TizenRT there is no lower-half timer driver or user
application based on it.

All credits should go to many other contributors who wrote the original
commits for NuttX. Sorry for not listing their names here.

Change-Id: Ib57c1ac259d4c1163c42ac3b08a25bf59a2fa2dc
Signed-off-by: Heesub Shin <heesub.shin@samsung.com>
os/drivers/timer.c
os/include/tinyara/timer.h

index a6eda10..953a1d8 100644 (file)
@@ -63,6 +63,7 @@
 #include <string.h>
 #include <semaphore.h>
 #include <fcntl.h>
+#include <signal.h>
 #include <assert.h>
 #include <errno.h>
 #include <debug.h>
 /* This structure describes the state of the upper half driver */
 
 struct timer_upperhalf_s {
-       uint8_t crefs;                          /* The number of times the device has been opened */
-//sem_t     exclsem;  /* Supports mutual exclusion */
-       FAR char *path;                         /* Registration path */
+       uint8_t   crefs; /* The number of times the device has been opened */
+       uint8_t   signo; /* The signal number to use in the notification */
+       pid_t     pid;   /* The ID of the task/thread to receive the signal */
+       FAR void *arg;   /* An argument to pass with the signal */
+       FAR char *path;  /* Registration path */
 
        /* The contained lower-half driver */
 
@@ -112,25 +115,32 @@ struct timer_upperhalf_s {
  * Private Function Prototypes
  ****************************************************************************/
 
-static int timer_open(FAR struct file *filep);
-static int timer_close(FAR struct file *filep);
-static ssize_t timer_read(FAR struct file *filep, FAR char *buffer, size_t buflen);
-static ssize_t timer_write(FAR struct file *filep, FAR const char *buffer, size_t buflen);
-static int timer_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
+static bool    timer_notifier(FAR uint32_t *next_interval_us, FAR void *arg);
+static int     timer_open(FAR struct file *filep);
+static int     timer_close(FAR struct file *filep);
+static ssize_t timer_read(FAR struct file *filep, FAR char *buffer,
+               size_t buflen);
+static ssize_t timer_write(FAR struct file *filep, FAR const char *buffer,
+               size_t buflen);
+static int     timer_ioctl(FAR struct file *filep, int cmd,
+               unsigned long arg);
 
 /****************************************************************************
  * Private Data
  ****************************************************************************/
 
 static const struct file_operations g_timerops = {
-       timer_open,                                     /* open */
-       timer_close,                            /* close */
-       timer_read,                                     /* read */
-       timer_write,                            /* write */
-       0,                                                      /* seek */
-       timer_ioctl                                     /* ioctl */
+       timer_open,     /* open */
+       timer_close,    /* close */
+       timer_read,     /* read */
+       timer_write,    /* write */
+       NULL,           /* seek */
+       timer_ioctl     /* ioctl */
 #ifndef CONFIG_DISABLE_POLL
-       , 0                                             /* poll */
+       , NULL          /* poll */
+#endif
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+       , NULL          /* unlink */
 #endif
 };
 
@@ -138,34 +148,58 @@ static const struct file_operations g_timerops = {
  * Private Functions
  ****************************************************************************/
 
-/************************************************************************************
+/****************************************************************************
+ * Name: timer_notifier
+ *
+ * Description:
+ *   Notify the application via a signal when the timer interrupt occurs
+ *
+ * REVISIT: This function prototype is insufficient to support signaling
+ *
+ ****************************************************************************/
+
+static bool timer_notifier(FAR uint32_t *next_interval_us, FAR void *arg)
+{
+       FAR struct timer_upperhalf_s *upper = (FAR struct timer_upperhalf_s *)arg;
+#ifdef CONFIG_CAN_PASS_STRUCTS
+       union sigval value;
+#endif
+
+       DEBUGASSERT(upper != NULL);
+
+       /* Signal the waiter.. if there is one */
+
+#ifdef CONFIG_CAN_PASS_STRUCTS
+       value.sival_ptr = upper->arg;
+       (void)sigqueue(upper->pid, upper->signo, value);
+#else
+       (void)sigqueue(upper->pid, upper->signo, upper->arg);
+#endif
+
+       return true;
+}
+
+/****************************************************************************
  * Name: timer_open
  *
  * Description:
  *   This function is called whenever the timer device is opened.
  *
- ************************************************************************************/
+ ****************************************************************************/
 
 static int timer_open(FAR struct file *filep)
 {
-       FAR struct inode *inode = filep->f_inode;
+       FAR struct inode             *inode = filep->f_inode;
        FAR struct timer_upperhalf_s *upper = inode->i_private;
-       uint8_t tmp;
-       int ret;
-
-       tmrvdbg("crefs: %d\n", upper->crefs);
+       uint8_t                       tmp;
+       int                           ret;
 
-       /* Get exclusive access to the device structures */
+       tmrinfo("crefs: %d\n", upper->crefs);
 
-       ret = 1;                                        //sem_wait(&upper->exclsem);
-       if (ret < 0) {
-               ret = -get_errno();
-               goto errout;
-       }
-
-       /* Increment the count of references to the device.  If this the first
-        * time that the driver has been opened for this device, then initialize
-        * the device.
+       /*
+        * Increment the count of references to the device. If this the first
+        * time that the driver has been opened for this device, then
+        * initialize the device.
         */
 
        tmp = upper->crefs + 1;
@@ -173,7 +207,7 @@ static int timer_open(FAR struct file *filep)
                /* More than 255 opens; uint8_t overflows to zero */
 
                ret = -EMFILE;
-               goto errout_with_sem;
+               goto errout;
        }
 
        /* Save the new open count */
@@ -181,109 +215,92 @@ static int timer_open(FAR struct file *filep)
        upper->crefs = tmp;
        ret = OK;
 
-errout_with_sem:
-       /* sem_post(&upper->exclsem); */
-
 errout:
        return ret;
 }
 
-/************************************************************************************
+/****************************************************************************
  * Name: timer_close
  *
  * Description:
  *   This function is called when the timer device is closed.
  *
- ************************************************************************************/
+ ****************************************************************************/
 
 static int timer_close(FAR struct file *filep)
 {
        FAR struct inode *inode = filep->f_inode;
        FAR struct timer_upperhalf_s *upper = inode->i_private;
-       int ret;
-
-       tmrvdbg("crefs: %d\n", upper->crefs);
-
-       /* Get exclusive access to the device structures */
 
-       ret = 1;                                        //sem_wait(&upper->exclsem);
-       if (ret < 0) {
-               ret = -get_errno();
-               goto errout;
-       }
+       tmrinfo("crefs: %d\n", upper->crefs);
 
-       /* Decrement the references to the driver.  If the reference count will
-        * decrement to 0, then uninitialize the driver.
+       /*
+        * Decrement the references to the driver. If the reference count
+        * will decrement to 0, then uninitialize the driver.
         */
 
        if (upper->crefs > 0) {
                upper->crefs--;
        }
-       //sem_post(&upper->exclsem);
-       ret = OK;
 
-errout:
-       return ret;
+       return OK;
 }
 
-/************************************************************************************
+/****************************************************************************
  * Name: timer_read
  *
  * Description:
  *   A dummy read method.  This is provided only to satisfy the VFS layer.
  *
- ************************************************************************************/
+ ****************************************************************************/
 
-static ssize_t timer_read(FAR struct file *filep, FAR char *buffer, size_t buflen)
+static ssize_t timer_read(FAR struct file *filep, FAR char *buffer,
+                         size_t buflen)
 {
-       /* Return zero -- usually meaning end-of-file */
+       /* Return zero - usually meaning end-of-file */
 
        return 0;
 }
 
-/************************************************************************************
+/****************************************************************************
  * Name: timer_write
  *
  * Description:
  *   A dummy write method.  This is provided only to satisfy the VFS layer.
  *
- ************************************************************************************/
+ ****************************************************************************/
 
-static ssize_t timer_write(FAR struct file *filep, FAR const char *buffer, size_t buflen)
+static ssize_t timer_write(FAR struct file *filep, FAR const char *buffer,
+                          size_t buflen)
 {
        return 0;
 }
 
-/************************************************************************************
+/****************************************************************************
  * Name: timer_ioctl
  *
  * Description:
  *   The standard ioctl method.  This is where ALL of the timer work is
  *   done.
  *
- ************************************************************************************/
+ ****************************************************************************/
 
 static int timer_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
 {
-       FAR struct inode *inode = filep->f_inode;
+       FAR struct inode             *inode = filep->f_inode;
        FAR struct timer_upperhalf_s *upper = inode->i_private;
        FAR struct timer_lowerhalf_s *lower = upper->lower;
-       int ret;
+       int                           ret;
 
-       tmrvdbg("cmd: %d arg: %ld\n", cmd, arg);
+       tmrinfo("cmd: %d arg: %ld\n", cmd, arg);
        DEBUGASSERT(upper && lower);
 
-       /* Get exclusive access to the device structures */
-
-       ret = 1;                                        //sem_wait(&upper->exclsem);
-       if (ret < 0) {
-               return ret;
-       }
-
        /* Handle built-in ioctl commands */
 
        switch (cmd) {
-       /* cmd:         TCIOC_START
+
+       /*
+        * cmd:         TCIOC_START
         * Description: Start the timer
         * Argument:    Ignored
         */
@@ -299,7 +316,8 @@ static int timer_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
        }
        break;
 
-       /* cmd:         TCIOC_STOP
+       /*
+        * cmd:         TCIOC_STOP
         * Description: Stop the timer
         * Argument:    Ignored
         */
@@ -307,7 +325,7 @@ static int timer_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
        case TCIOC_STOP: {
                /* Stop the timer */
 
-               if (lower->ops->start) {
+               if (lower->ops->stop) {
                        ret = lower->ops->stop(lower);
                } else {
                        ret = -ENOSYS;
@@ -315,7 +333,8 @@ static int timer_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
        }
        break;
 
-       /* cmd:         TCIOC_GETSTATUS
+       /*
+        * cmd:         TCIOC_GETSTATUS
         * Description: Get the status of the timer.
         * Argument:    A writeable pointer to struct timer_status_s.
         */
@@ -325,7 +344,7 @@ static int timer_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
 
                /* Get the current timer status */
 
-               if (lower->ops->getstatus) {    /* Optional */
+               if (lower->ops->getstatus) { /* Optional */
                        status = (FAR struct timer_status_s *)((uintptr_t)arg);
                        if (status) {
                                ret = lower->ops->getstatus(lower, status);
@@ -338,7 +357,8 @@ static int timer_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
        }
        break;
 
-       /* cmd:         TCIOC_SETTIMEOUT
+       /*
+        * cmd:         TCIOC_SETTIMEOUT
         * Description: Reset the timeout to this value
         * Argument:    A 32-bit timeout value in microseconds.
         *
@@ -357,49 +377,45 @@ static int timer_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
        }
        break;
 
-               /* cmd:         TCIOC_SETHANDLER
-                * Description: Call this handler on timeout
-                * Argument:    A pointer to struct timer_sethandler_s.
-                *
-                * NOTE: This ioctl cannot be support in the kernel build mode. In that
-                * case direct callbacks from kernel space into user space is forbidden.
-                */
+       /*
+        * cmd:         TCIOC_NOTIFICATION
+        * Description: Notify application via a signal when the timer expires.
+        * Argument:    signal number
+        *
+        * NOTE: This ioctl cannot be support in the kernel build mode. In
+        * that case direct callbacks from kernel space into user space is
+        * forbidden.
+        */
 
-#if !defined(CONFIG_BUILD_PROTECTED) && !defined(CONFIG_BUILD_KERNEL)
-       case TCIOC_SETHANDLER: {
-               FAR struct timer_sethandler_s *sethandler;
+       case TCIOC_NOTIFICATION: {
+               FAR struct timer_notify_s *notify =
+                       (FAR struct timer_notify_s *)((uintptr_t)arg);
 
-               /* Don't reset on timer timeout; instead, call this user
-                * provider timeout handler.  NOTE:  Providing handler==NULL will
-                * restore the reset behavior.
-                */
+               if (notify != NULL) {
+                       upper->signo = notify->signo;
+                       upper->pid   = notify->pid;
+                       upper->arg   = notify->arg;
 
-               if (lower->ops->sethandler) {   /* Optional */
-                       sethandler = (FAR struct timer_sethandler_s *)((uintptr_t)arg);
-                       if (sethandler) {
-                               sethandler->oldhandler = lower->ops->sethandler(lower, sethandler->newhandler);
-                               ret = OK;
-                       } else {
-                               ret = -EINVAL;
-                       }
+                       ret = timer_setcallback((FAR void *)upper,
+                                       timer_notifier, upper);
                } else {
-                       ret = -ENOSYS;
+                       ret = -EINVAL;
                }
-       }
-       break;
-#endif
+        }
+        break;
 
        /* Any unrecognized IOCTL commands might be platform-specific ioctl commands */
 
        default: {
-               tmrvdbg("Forwarding unrecognized cmd: %d arg: %ld\n", cmd, arg);
+               tmrinfo("Forwarding unrecognized cmd: %d arg: %ld\n", cmd, arg);
 
-               /* An ioctl commands that are not recognized by the "upper-half"
-                * driver are forwarded to the lower half driver through this
-                * method.
+               /*
+                * An ioctl commands that are not recognized by the
+                * "upper-half" driver are forwarded to the lower half driver
+                * through this method.
                 */
 
-               if (lower->ops->ioctl) {        /* Optional */
+               if (lower->ops->ioctl) { /* Optional */
                        ret = lower->ops->ioctl(lower, cmd, arg);
                } else {
                        ret = -ENOSYS;
@@ -408,7 +424,6 @@ static int timer_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
        break;
        }
 
-       //sem_post(&upper->exclsem);
        return ret;
 }
 
@@ -442,35 +457,36 @@ static int timer_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
  *
  ****************************************************************************/
 
-FAR void *timer_register(FAR const char *path, FAR struct timer_lowerhalf_s *lower)
+FAR void *timer_register(FAR const char *path,
+                        FAR struct timer_lowerhalf_s *lower)
 {
        FAR struct timer_upperhalf_s *upper;
        int ret;
 
        DEBUGASSERT(path && lower);
-       tmrvdbg("Entry: path=%s\n", path);
+       tmrinfo("Entry: path=%s\n", path);
 
        /* Allocate the upper-half data structure */
 
        upper = (FAR struct timer_upperhalf_s *)
                        kmm_zalloc(sizeof(struct timer_upperhalf_s));
        if (!upper) {
-               tmrdbg("Upper half allocation failed\n");
+               tmrerr("ERROR: Upper half allocation failed\n");
                goto errout;
        }
 
-       /* Initialize the timer device structure (it was already zeroed
+       /*
+        * Initialize the timer device structure (it was already zeroed
         * by kmm_zalloc()).
         */
 
-       //sem_init(&upper->exclsem, 0, 1);
        upper->lower = lower;
 
        /* Copy the registration path */
 
        upper->path = strdup(path);
        if (!upper->path) {
-               tmrdbg("Path allocation failed\n");
+               tmrerr("ERROR: Path allocation failed\n");
                goto errout_with_upper;
        }
 
@@ -478,7 +494,7 @@ FAR void *timer_register(FAR const char *path, FAR struct timer_lowerhalf_s *low
 
        ret = register_driver(path, &g_timerops, 0666, upper);
        if (ret < 0) {
-               tmrdbg("register_driver failed: %d\n", ret);
+               tmrerr("ERROR: register_driver failed: %d\n", ret);
                goto errout_with_path;
        }
 
@@ -488,7 +504,6 @@ errout_with_path:
        kmm_free(upper->path);
 
 errout_with_upper:
-       //sem_destroy(&upper->exclsem);
        kmm_free(upper);
 
 errout:
@@ -518,14 +533,14 @@ void timer_unregister(FAR void *handle)
        /* Recover the pointer to the upper-half driver state */
 
        upper = (FAR struct timer_upperhalf_s *)handle;
+       DEBUGASSERT(upper != NULL && upper->lower != NULL);
        lower = upper->lower;
-       DEBUGASSERT(upper && lower);
 
-       tmrvdbg("Unregistering: %s\n", upper->path);
+       tmrinfo("Unregistering: %s\n", upper->path);
 
        /* Disable the timer */
 
-       DEBUGASSERT(lower->ops->stop);  /* Required */
+       DEBUGASSERT(lower->ops->stop); /* Required */
        (void)lower->ops->stop(lower);
 
        /* Unregister the timer device */
@@ -535,8 +550,46 @@ void timer_unregister(FAR void *handle)
        /* Then free all of the driver resources */
 
        kmm_free(upper->path);
-       //sem_destroy(&upper->exclsem);
        kmm_free(upper);
 }
 
-#endif                                                 /* CONFIG_TIMER */
+/****************************************************************************
+ * Name: timer_setcallback
+ *
+ * Description:
+ *   This function can be called to add a callback into driver-related code
+ *   to handle timer expirations. This is a strictly OS internal interface
+ *   and may NOT be used by application code.
+ *
+ * Input parameters:
+ *   handle   - This is the handle that was returned by timer_register()
+ *   callback - The new timer interrupt callback
+ *   arg      - Argument to be provided with the callback
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+int timer_setcallback(FAR void *handle, tccb_t callback, FAR void *arg)
+{
+       FAR struct timer_upperhalf_s *upper;
+       FAR struct timer_lowerhalf_s *lower;
+
+       /* Recover the pointer to the upper-half driver state */
+
+       upper = (FAR struct timer_upperhalf_s *)handle;
+       DEBUGASSERT(upper != NULL && upper->lower != NULL);
+       lower = upper->lower;
+       DEBUGASSERT(lower->ops != NULL);
+
+       /* Check if the lower half driver supports the setcallback method */
+
+       if (lower->ops->setcallback != NULL) { /* Optional */
+               /* Yes.. Defer the handler attachment to the lower half driver */
+               lower->ops->setcallback(lower, callback, arg);
+               return OK;
+       }
+
+       return -ENOSYS;
+}
+#endif /* CONFIG_TIMER */
index f5f6152..bde14a5 100644 (file)
 #include <tinyara/compiler.h>
 #include <tinyara/irq.h>
 #include <tinyara/fs/ioctl.h>
+#include <stdbool.h>
+#include <sys/types.h>
 
 #ifdef CONFIG_TIMER
 
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
+
 /* IOCTL Commands ***********************************************************/
 /* The timer driver uses a standard character driver framework.  However,
  * since the timer driver is a device control interface and not a data
  *
  * These are detected and handled by the "upper half" timer driver.
  *
- * TCIOC_START      - Start the timer
- *                    Argument: Ignored
- * TCIOC_STOP       - Stop the timer
- *                    Argument: Ignored
- * TCIOC_GETSTATUS  - Get the status of the timer.
- *                    Argument:  A writeable pointer to struct timer_status_s.
- * TCIOC_SETTIMEOUT - Reset the timer timeout to this value
- *                    Argument: A 32-bit timeout value in microseconds.
- * TCIOC_SETHANDLER - Call this handler on timer expiration
- *                    Argument: A pointer to struct timer_sethandler_s.
+ * TCIOC_START        - Start the timer
+ *                      Argument: Ignored
+ * TCIOC_STOP         - Stop the timer
+ *                      Argument: Ignored
+ * TCIOC_GETSTATUS    - Get the status of the timer.
+ *                      Argument:  A writeable pointer to struct timer_status_s.
+ * TCIOC_SETTIMEOUT   - Reset the timer timeout to this value
+ *                      Argument: A 32-bit timeout value in microseconds.
+ * TCIOC_NOTIFICATION - Set up to notify an application via a signal when
+ *                      the timer expires.
+ *                      Argument: A read-only pointer to an instance of
+ *                      struct timer_notify_s.
  *
  * WARNING: May change TCIOC_SETTIMEOUT to pass pointer to 64bit nanoseconds
  * or timespec structure.
  * NOTE: The TCIOC_SETHANDLER ioctl cannot be supported in the kernel build
  * mode. In that case direct callbacks from kernel space into user space is
  * forbidden.
+ *
+ * NOTE: _TCIOC(0x0001) through _TCIOC(0x001f) are reserved for use by the
+ * timer driver to assure that the values are unique. Other timer drivers,
+ * such as the oneshot timer, must not use IOCTL commands in this numeric
+ * range.
  */
 
-#define TCIOC_START      _TCIOC(0x001)
-#define TCIOC_STOP       _TCIOC(0x002)
-#define TCIOC_GETSTATUS  _TCIOC(0x003)
-#define TCIOC_SETTIMEOUT _TCIOC(0x004)
-#define TCIOC_SETHANDLER _TCIOC(0x005)
+#define TCIOC_START            _TCIOC(0x0001)
+#define TCIOC_STOP             _TCIOC(0x0002)
+#define TCIOC_GETSTATUS                _TCIOC(0x0003)
+#define TCIOC_SETTIMEOUT       _TCIOC(0x0004)
+#define TCIOC_NOTIFICATION     _TCIOC(0x0005)
 
 /* Bit Settings *************************************************************/
 /* Bit settings for the struct timer_status_s flags field */
 
-#define TCFLAGS_ACTIVE   (1 << 0)      /* 1=The timer is running */
-#define TCFLAGS_HANDLER  (1 << 1)      /* 1=Call the user function when the
-                                                                        *   timer expires */
+#define TCFLAGS_ACTIVE         (1 << 0) /* 1=The timer is running */
+#define TCFLAGS_HANDLER                (1 << 1) /* 1=Call the user function when the
+                                         * timer expires */
 
 /****************************************************************************
  * Public Types
  ****************************************************************************/
 
-/* User function prototype. Returns true to reload the timer, and the
+/* Upper half callback prototype. Returns true to reload the timer, and the
  * function can modify the next interval if desired.
  */
 
-typedef bool(*tccb_t)(FAR uint32_t *next_interval_us);
-
-/* This is the type of the argument passed to the TCIOC_SETHANDLER ioctl */
-
-struct timer_sethandler_s {
-       CODE tccb_t newhandler;         /* The new timer interrupt handler */
-       CODE tccb_t oldhandler;         /* The previous timer interrupt handler (if any) */
-};
+typedef CODE bool (*tccb_t)(FAR uint32_t *next_interval_us, FAR void *arg);
 
 /* This is the type of the argument passed to the TCIOC_GETSTATUS ioctl and
  * and returned by the "lower half" getstatus() method.
  */
 
 struct timer_status_s {
-       uint32_t flags;                         /* See TCFLAGS_* definitions above */
-       uint32_t timeout;                       /* The current timeout setting (in microseconds) */
-       uint32_t timeleft;                      /* Time left until the timer expiration
-                                                                * (in microseconds) */
+       uint32_t flags;    /* See TCFLAGS_* definitions above */
+       uint32_t timeout;  /* The current timeout setting (in microseconds) */
+       uint32_t timeleft; /* Time left until the timer expiration
+                           * (in microseconds) */
+};
+
+/* This is the type of the argument passed to the TCIOC_NOTIFICATION ioctl */
+
+struct timer_notify_s
+{
+       FAR void *arg;   /* An argument to pass with the signal */
+       pid_t     pid;   /* The ID of the task/thread to receive the signal */
+       uint8_t   signo; /* The signal number to use in the notification */
 };
 
 /* This structure provides the "lower-half" driver operations available to
@@ -141,7 +153,7 @@ struct timer_status_s {
 
 struct timer_lowerhalf_s;
 struct timer_ops_s {
-       /* Required methods ******************************************************* */
+       /* Required methods *************************************************/
        /* Start the timer, resetting the time to the current timeout */
 
        CODE int (*start)(FAR struct timer_lowerhalf_s *lower);
@@ -152,23 +164,28 @@ struct timer_ops_s {
 
        /* Get the current timer status */
 
-       CODE int (*getstatus)(FAR struct timer_lowerhalf_s *lower, FAR struct timer_status_s *status);
+       CODE int (*getstatus)(FAR struct timer_lowerhalf_s *lower,
+                             FAR struct timer_status_s *status);
 
        /* Set a new timeout value (and reset the timer) */
 
-       CODE int (*settimeout)(FAR struct timer_lowerhalf_s *lower, uint32_t timeout);
+       CODE int (*settimeout)(FAR struct timer_lowerhalf_s *lower,
+                              uint32_t timeout);
 
-       /* Call this user provider timeout handler on timeout.
-        * NOTE:  Providing handler==NULL disable.
+       /* Call the TinyARA INTERNAL timeout callback on timeout.
+        * NOTE:  Providing callback==NULL disable.
+        * NOT to call back into applications.
         */
 
-       CODE tccb_t (*sethandler)(FAR struct timer_lowerhalf_s *lower, CODE tccb_t handler);
+       CODE void (*setcallback)(FAR struct timer_lowerhalf_s *lower,
+                                CODE tccb_t callback, FAR void *arg);
 
-       /* Any ioctl commands that are not recognized by the "upper-half" driver
-        * are forwarded to the lower half driver through this method.
+       /* Any ioctl commands that are not recognized by the "upper-half"
+        * driver are forwarded to the lower half driver through this method.
         */
 
-       CODE int (*ioctl)(FAR struct timer_lowerhalf_s *lower, int cmd, unsigned long arg);
+       CODE int (*ioctl)(FAR struct timer_lowerhalf_s *lower, int cmd,
+                         unsigned long arg);
 };
 
 /* This structure provides the publicly visible representation of the
@@ -180,7 +197,7 @@ struct timer_ops_s {
 struct timer_lowerhalf_s {
        /* Publicly visible portion of the "lower-half" driver state structure. */
 
-       FAR const struct timer_ops_s *ops;      /* Lower half operations */
+       FAR const struct timer_ops_s *ops; /* Lower half operations */
 
        /* The remainder of the structure is used by the "lower-half" driver
         * for whatever state storage that it may need.
@@ -197,7 +214,8 @@ struct timer_lowerhalf_s {
 
 #ifdef __cplusplus
 #define EXTERN extern "C"
-extern "C" {
+extern "C"
+{
 #else
 #define EXTERN extern
 #endif
@@ -235,7 +253,8 @@ extern "C" {
  *
  ****************************************************************************/
 
-FAR void *timer_register(FAR const char *path, FAR struct timer_lowerhalf_s *lower);
+FAR void *timer_register(FAR const char *path,
+                        FAR struct timer_lowerhalf_s *lower);
 
 /****************************************************************************
  * Name: timer_unregister
@@ -255,6 +274,32 @@ FAR void *timer_register(FAR const char *path, FAR struct timer_lowerhalf_s *low
 void timer_unregister(FAR void *handle);
 
 /****************************************************************************
+ * Kernel internal interfaces. These may not be used by application logic.
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: timer_setcallback
+ *
+ * Description:
+ *   This function can be called to add a callback into driver-related code
+ *   to handle timer expirations. This is a strictly OS internal interface
+ *   and may NOT be used by application code.
+ *
+ * Input parameters:
+ *   handle   - This is the handle that was returned by timer_register()
+ *   callback - The new timer interrupt callback
+ *   arg      - Argument provided when the callback is called.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+#ifdef __KERNEL__
+int timer_setcallback(FAR void *handle, tccb_t callback, FAR void *arg);
+#endif
+
+/****************************************************************************
  * Platform-Independent "Lower-Half" Timer Driver Interfaces
  ****************************************************************************/
 
@@ -267,5 +312,5 @@ void timer_unregister(FAR void *handle);
 }
 #endif
 
-#endif                                                 /* CONFIG_TIMER */
-#endif                                                 /* __INCLUDE_TIMER_H */
+#endif /* CONFIG_TIMER */
+#endif /* __INCLUDE_TIMER_H */