diff --git a/drivers/lcd/pcf8574_lcd_backpack.c b/drivers/lcd/pcf8574_lcd_backpack.c
index c06a0951dd8ececaabc45f64fec95c5b82e79c2a..a8e288c6cc372dab379bf8420432aab26b4503cc 100644
--- a/drivers/lcd/pcf8574_lcd_backpack.c
+++ b/drivers/lcd/pcf8574_lcd_backpack.c
@@ -86,6 +86,8 @@
 #  define lcdvdbg(x...)
 #endif
 
+#define MAX_OPENCNT     (255)                  /* Limit of uint8_t */
+
 /****************************************************************************
  * Private Types
  ****************************************************************************/
@@ -95,6 +97,8 @@ struct pcf8574_lcd_dev_s
   FAR struct i2c_master_s *i2c;               /* I2C interface */
   struct pcf8574_lcd_backpack_config_s cfg;   /* gpio configuration */
   uint8_t bl_bit;                             /* current backlight bit */
+  uint8_t refs;                               /* Number of references */
+  uint8_t unlinked;                           /* We are unlinked, so teardown on last close */
   sem_t sem_excl;                             /* mutex */
 };
 
@@ -117,12 +121,16 @@ static ssize_t pcf8574_lcd_read(FAR struct file *filep, FAR char *buffer,
                                 size_t buflen);
 static ssize_t pcf8574_lcd_write(FAR struct file *filep,
                                  FAR const char *buffer, size_t buflen);
+static off_t pcf8574_lcd_seek(FAR struct file *filep, off_t offset, int whence);
 static int pcf8574_lcd_ioctl(FAR struct file *filep, int cmd,
                              unsigned long arg);
 #ifndef CONFIG_DISABLE_POLL
 static int pcf8574lcd_poll(FAR struct file *filep, FAR struct pollfd *fds,
                            bool setup);
 #endif
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+static int pcf8574_lcd_unlink(FAR struct inode *inode);
+#endif
 
 /****************************************************************************
  * Private Data
@@ -134,12 +142,14 @@ static const struct file_operations g_pcf8574_lcd_fops =
   pcf8574_lcd_close,           /* close */
   pcf8574_lcd_read,            /* read */
   pcf8574_lcd_write,           /* write */
-  0,                           /* seek */
+  pcf8574_lcd_seek,            /* seek */
   pcf8574_lcd_ioctl,           /* ioctl */
 #ifndef CONFIG_DISABLE_POLL
   pcf8574lcd_poll,             /* poll */
 #endif
-  0                            /* unlink */
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+  pcf8574_lcd_unlink           /* unlink */
+#endif
 };
 
 /****************************************************************************
@@ -1000,6 +1010,53 @@ static int lcd_getstream(FAR struct lib_instream_s *instream)
   return EOF;
 }
 
+/****************************************************************************
+ * Name: lcd_fpos_to_curpos
+ *
+ * Description:
+ *   Convert a file logical offset to a screen cursor pos (row,col).  This
+ *   discounts 'synthesized' line feeds at the end of screen lines.
+ *
+ ****************************************************************************/
+
+static void lcd_fpos_to_curpos(FAR struct pcf8574_lcd_dev_s *priv,
+                              off_t fpos, uint8_t *row, uint8_t *col, bool* onlf)
+{
+  int virtcols;
+  
+  virtcols = (priv->cfg.cols + 1);
+  
+  /* Determine if this is a 'virtual' position (on the synthetic LF) */
+
+  *onlf = (priv->cfg.cols == fpos % virtcols);
+
+  /* Adjust off any preceding synthetic LF's to get linear position */
+  
+  fpos -= fpos / virtcols;
+  
+  /* Compute row/col from linear position */
+  
+  *row = fpos / priv->cfg.cols;
+  *col = fpos % priv->cfg.cols;
+}
+
+/****************************************************************************
+ * Name: lcd_curpos_to_fpos
+ *
+ * Description:
+ *   Convert a screen cursor pos (row,col) to a file logical offset.  This
+ *   includes 'synthesized' line feeds at the end of screen lines.
+ *
+ ****************************************************************************/
+
+static void lcd_curpos_to_fpos(FAR struct pcf8574_lcd_dev_s *priv,
+                              uint8_t row, uint8_t col, off_t* fpos)
+{
+  /* the logical file position is the linear position plus any synthetic LF */
+  
+  *fpos = (row * priv->cfg.cols) + col + row;
+}
+
 /****************************************************************************
  * Name: pcf8574_lcd_open
  *
@@ -1010,6 +1067,22 @@ static int lcd_getstream(FAR struct lib_instream_s *instream)
 
 static int pcf8574_lcd_open(FAR struct file *filep)
 {
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct pcf8574_lcd_dev_s *priv = (FAR struct pcf8574_lcd_dev_s *)inode->i_private;
+
+  /* Increment the reference count */
+
+  sem_wait(&priv->sem_excl);
+  if (priv->refs == MAX_OPENCNT)
+    {
+      return -EMFILE;
+    }
+  else
+    {
+      priv->refs++;
+    }
+
+  sem_post(&priv->sem_excl);
   return OK;
 }
 
@@ -1023,7 +1096,35 @@ static int pcf8574_lcd_open(FAR struct file *filep)
 
 static int pcf8574_lcd_close(FAR struct file *filep)
 {
-  return OK;
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct pcf8574_lcd_dev_s *priv = (FAR struct pcf8574_lcd_dev_s *)inode->i_private;
+  int ret;
+
+  /* Decrement the reference count */
+
+  sem_wait(&priv->sem_excl);
+
+  if (priv->refs == 0)
+    {
+      ret = -EIO;
+    }
+  else
+    {
+      priv->refs--;
+
+      /* If we had previously unlinked, but there were open references at the
+       * time, we need to do the final teardown now.
+       */
+      
+      if (priv->refs == 0 && priv->unlinked)
+        {
+          /* We have no real teardown at present */
+        }
+      ret = OK;
+    }
+
+  sem_post(&priv->sem_excl);
+  return ret;
 }
 
 /****************************************************************************
@@ -1031,7 +1132,8 @@ static int pcf8574_lcd_close(FAR struct file *filep)
  *
  * Description:
  *  This simply reads as much of the display memory as possible.  This is
- *  probably not very interesting.
+ *  generally not very interesting, but we do it in a way that allows us to
+ *  'cat' the LCD contents via the shell.
  *
  ****************************************************************************/
 
@@ -1044,22 +1146,44 @@ static ssize_t pcf8574_lcd_read(FAR struct file *filep, FAR char *buffer,
   uint8_t addr;
   uint8_t row;
   uint8_t col;
+  bool onlf;
 
   sem_wait(&priv->sem_excl);
 
   /* Get current cursor position so we can restore it */
 
   (void)lcd_read_busy_addr(priv, &addr);
-  addr2rc(priv, addr, &row, &col);
 
-  /* Just read the entire display into the given buffer, as much as possible */
+  /* Convert file position to row/col address and position DDADDR there */
 
-  nIdx = 0;
-  row = 0;
-  col = 0;
+  lcd_fpos_to_curpos(priv, filep->f_pos, &row, &col, &onlf);
+  lcd_set_curpos(priv, row, col);
+
+  /* Read as much of the display as possible */
 
+  nIdx = 0;
   while (nIdx < buflen && row < priv->cfg.rows)
   {
+    /* Synthesize end-of-line LF and advance to start of next row */
+    
+    if (onlf)
+      {
+        /* Synthesize LF for all but last row */
+        
+        if ( row < priv->cfg.rows-1)
+          {
+            buffer[nIdx] = '\x0a';
+            onlf = false;
+            ++filep->f_pos;
+            ++nIdx;
+          }
+        ++row;
+        col = 0;
+        continue;
+      }
+
+    /* If we are at start of line we will need to update DDRAM address */
+
     if (0 == col)
       {
         lcd_set_curpos(priv, row, 0);
@@ -1067,12 +1191,15 @@ static ssize_t pcf8574_lcd_read(FAR struct file *filep, FAR char *buffer,
 
     buffer[nIdx] = lcd_getdata(priv);
 
+    ++filep->f_pos;
     ++nIdx;
     ++col;
+
+    /* If we are now at the end of a line, we setup for the synthetic LF */
+
     if (priv->cfg.cols == col)
       {
-        ++row;
-        col = 0;
+        onlf = true;
       }
   }
 
@@ -1226,10 +1353,62 @@ static ssize_t pcf8574_lcd_write(FAR struct file *filep,
         }
     }
 
+  /* Wherever we wound up, update our logical file pos to reflect it */
+
+  lcd_curpos_to_fpos(priv, row, col, &filep->f_pos);
+
   sem_post(&priv->sem_excl);
   return buflen;
 }
 
+/****************************************************************************
+ * Name: pcf8574_lcd_seek
+ *
+ * Description:
+ *   Seek the logical file pointer to the specified position.  This is
+ *   probably not very interesting except possibly for (SEEK_SET, 0) to
+ *   rewind the pointer for a subsequent read().
+ *   The file pointer is logical, and includes synthesized LF chars at the
+ *   end of the display lines.
+ *
+ ****************************************************************************/
+
+static off_t pcf8574_lcd_seek(FAR struct file *filep, off_t offset, int whence)
+{
+  FAR struct inode *inode = filep->f_inode;
+  FAR struct pcf8574_lcd_dev_s *priv = (FAR struct pcf8574_lcd_dev_s *)inode->i_private;
+  int maxpos;
+
+  sem_wait(&priv->sem_excl);
+
+  maxpos = priv->cfg.rows * priv->cfg.cols + (priv->cfg.rows - 1);
+  switch (whence)
+    {
+    case SEEK_CUR:
+      filep->f_pos += offset;
+      if (filep->f_pos > maxpos)
+        filep->f_pos = maxpos;
+      break;
+
+    case SEEK_SET:
+      filep->f_pos = offset;
+      if (filep->f_pos > maxpos)
+        filep->f_pos = maxpos;
+      break;
+
+    case SEEK_END:
+      filep->f_pos = maxpos;
+      break;
+
+    default:
+      /* Return EINVAL if the whence argument is invalid */
+      filep->f_pos = -EINVAL;
+    }
+
+  sem_post(&priv->sem_excl);
+  return filep->f_pos;
+}
+
 /****************************************************************************
  * Name: pcf8574_lcd_ioctl
  *
@@ -1349,6 +1528,32 @@ static int pcf8574lcd_poll(FAR struct file *filep, FAR struct pollfd *fds,
 }
 #endif
 
+/****************************************************************************
+ * Name: pcf8574_lcd_unlink
+ ****************************************************************************/
+
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+static int pcf8574_lcd_unlink(FAR struct inode *inode)
+{
+  FAR struct pcf8574_lcd_dev_s *priv = (FAR struct pcf8574_lcd_dev_s *)inode->i_private;
+  int ret = OK;
+
+  sem_wait(&priv->sem_excl);
+
+  priv->unlinked = true;
+
+  /* If there are no open references to the driver then tear it down now */
+  if (priv->refs == 0)
+    {
+      /* We have no real teardown at present */
+      ret = OK;
+    }
+
+  sem_post(&priv->sem_excl);
+  return ret;
+}
+#endif
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -1395,6 +1600,8 @@ int pcf8574_lcd_backpack_register(FAR const char *devpath,
   priv->i2c = i2c;
   priv->cfg = *cfg;
   priv->bl_bit = priv->cfg.bl_active_high ? 0 : (1 << priv->cfg.bl);
+  priv->refs = 0;
+  priv->unlinked = false;
   sem_init(&priv->sem_excl, 0, 1);
 
   /* Initialize */