diff --git a/drivers/input/mxt.c b/drivers/input/mxt.c index fb771b3616..980920f3ce 100644 --- a/drivers/input/mxt.c +++ b/drivers/input/mxt.c @@ -80,8 +80,8 @@ */ #define MXT_GETUINT16(p) \ - (((uint16_t)(((FAR uint8_t*)(p))[0]) << 8) | \ - (uint16_t)(((FAR uint8_t*)(p))[1])) + (((uint16_t)(((FAR uint8_t*)(p))[1]) << 8) | \ + (uint16_t)(((FAR uint8_t*)(p))[0])) /**************************************************************************** * Private Types @@ -164,8 +164,6 @@ struct mxt_dev_s volatile bool event; /* True: An unreported event is buffered */ sem_t devsem; /* Manages exclusive access to this structure */ sem_t waitsem; /* Used to wait for the availability of data */ - uint16_t xres; /* X resolution */ - uint16_t yres; /* Y resolution */ uint32_t frequency; /* Current I2C frequency */ char phys[64]; /* Device physical location */ @@ -196,6 +194,15 @@ static int mxt_putreg(FAR struct mxt_dev_s *priv, uint16_t regaddr, static FAR struct mxt_object_s *mxt_object(FAR struct mxt_dev_s *priv, uint8_t type); +static int mxt_getmessage(FAR struct mxt_dev_s *priv, + FAR struct mxt_msg_s *msg); +static int mxt_putobject(FAR struct mxt_dev_s *priv, uint8_t type, + uint8_t offset, uint8_t value); +#if 0 /* Not used */ +static int mxt_getobject(FAR struct mxt_dev_s *priv, uint8_t type, + uint8_t offset, FAR uint8_t *value); +#endif +static int mxt_flushmsgs(FAR struct mxt_dev_s *priv); #ifdef CONFIG_I2C_RESET static inline bool mxt_nullmsg(FAR struct mxt_msg_s *msg); #endif @@ -236,7 +243,6 @@ static int mxt_poll(FAR struct file *filep, struct pollfd *fds, bool setup); static int mxt_getinfo(struct mxt_dev_s *priv); static int mxt_getobjtab(FAR struct mxt_dev_s *priv); -static int mxt_clrpending(FAR struct mxt_dev_s *priv); static int mxt_hwinitialize(FAR struct mxt_dev_s *priv); /**************************************************************************** @@ -415,13 +421,94 @@ static int mxt_putobject(FAR struct mxt_dev_s *priv, uint8_t type, uint16_t regaddr; object = mxt_object(priv, type); - if (!object || offset >= object->size + 1) + if (object == NULL || offset >= object->size + 1) { return -EINVAL; } regaddr = MXT_GETUINT16(object->addr); - return mxt_putreg(priv, regaddr + offset, (FAR const uint8_t *)&value, 1); + return mxt_putreg(priv, regaddr + offset, &value, 1); +} + +/**************************************************************************** + * Name: mxt_getobject + ****************************************************************************/ + +#if 0 /* Not used */ +static int mxt_getobject(FAR struct mxt_dev_s *priv, uint8_t type, + uint8_t offset, FAR uint8_t *value) +{ + FAR struct mxt_object_s *object; + uint16_t regaddr; + + object = mxt_object(priv, type); + if (object == NULL || offset >= object->size + 1) + { + return -EINVAL; + } + + regaddr = MXT_GETUINT16(object->addr); + return mxt_getreg(priv, regaddr + offset, value, 1); +} +#endif + +/**************************************************************************** + * Name: mxt_flushmsgs + * + * Clear any pending messages be reading messages until there are no + * pending messages. This will force the CHG pin to the high state and + * prevent spurious initial interrupts. + * + ****************************************************************************/ + +static int mxt_flushmsgs(FAR struct mxt_dev_s *priv) +{ + struct mxt_msg_s msg; + int retries = 16; + int ret; + + /* Read dummy message until there are no more to read (or until we have + * tried 10 times). + */ + + do + { + ret = mxt_getmessage(priv, &msg); + if (ret < 0) + { + idbg("ERROR: mxt_getmessage failed: %d\n", ret); + return ret; + } + +#ifdef CONFIG_I2C_RESET + /* A message of all zeroes probably means that the bus is hung */ + + if (mxt_nullmsg(&msg)) + { + /* Try to shake the bus free */ + + ivdbg("WARNING: Null message... resetting I2C\n"); + + ret = up_i2creset(priv->i2c); + if (ret < 0) + { + idbg("ERROR: up_i2creset failed: %d\n", ret); + return ret; + } + } +#endif + } + while (msg.id != 0xff && --retries > 0); + + /* Complain if we exceed the retry limit */ + + if (retries <= 0) + { + idbg("ERROR: Failed to clear messages: ID=%02x\n", msg.id); + return -EBUSY; + } + + return OK; } /**************************************************************************** @@ -865,7 +952,7 @@ static void mxt_worker(FAR void *arg) /* Any other message IDs are ignored */ - else + else if (msg.id != 0xff) { ivdbg("Ignored: id=%u message={%02x %02x %02x %02x %02x %02x %02x}\n", msg.id, msg.body[0], msg.body[1], msg.body[2], msg.body[3], @@ -978,6 +1065,23 @@ static int mxt_open(FAR struct file *filep) idbg("ERROR: Failed to enable touch: %d\n", ret); goto errout_with_sem; } + + /* Clear any pending messages by reading all messages. This will + * force the CHG interrupt pin to the high state and prevent spurious + * interrupts when they are enabled. + */ + + ret = mxt_flushmsgs(priv); + if (ret < 0) + { + idbg("ERROR: mxt_flushmsgs failed: %d\n", ret); + mxt_putobject(priv, MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0); + goto errout_with_sem; + } + + /* Enable touch interrupts */ + + MXT_ENABLE(priv->lower); } /* Save the new open count on success */ @@ -1025,6 +1129,10 @@ static int mxt_close(FAR struct file *filep) { if (--priv->crefs < 1) { + /* Disable touch interrupts */ + + MXT_ENABLE(priv->lower); + /* Touch disable */ ret = mxt_putobject(priv, MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0); @@ -1137,7 +1245,7 @@ static ssize_t mxt_read(FAR struct file *filep, FAR char *buffer, size_t len) sample->contact == CONTACT_MOVE) { int newcount = ncontacts + 1; - ssize_t newsize = SIZEOF_TOUCH_SAMPLE_S(ncontacts); + ssize_t newsize = SIZEOF_TOUCH_SAMPLE_S(newcount); /* Would this sample exceed the buffer size provided by the * caller? @@ -1521,66 +1629,6 @@ static int mxt_getobjtab(FAR struct mxt_dev_s *priv) return OK; } -/**************************************************************************** - * Name: mxt_clrpending - * - * Clear any pending messages be reading messages until there are no - * pending messages. This will force the CHG pin to the high state and - * prevent spurious initial interrupts. - * - ****************************************************************************/ - -static int mxt_clrpending(FAR struct mxt_dev_s *priv) -{ - struct mxt_msg_s msg; - int retries = 16; - int ret; - - /* Read dummy message until there are no more to read (or until we have - * tried 10 times). NOTE: The MXT748E seems to return msg.id == 0x00 - * when there are no pending messages. - */ - - do - { - ret = mxt_getmessage(priv, &msg); - if (ret < 0) - { - idbg("ERROR: mxt_getmessage failed: %d\n", ret); - return ret; - } - -#ifdef CONFIG_I2C_RESET - /* A message of all zeroes probably means that the bus is hung */ - - if (mxt_nullmsg(&msg)) - { - /* Try to shake the bus free */ - - ivdbg("WARNING: Null message... resetting I2C\n"); - - ret = up_i2creset(priv->i2c); - if (ret < 0) - { - idbg("ERROR: up_i2creset failed: %d\n", ret); - return ret; - } - } -#endif - } - while (msg.id != 0xff && --retries > 0); - - /* Complain if we exceed the retry limit */ - - if (retries <= 0) - { - idbg("ERROR: Failed to clear messages: ID=%02x\n", msg.id); - return -EBUSY; - } - - return OK; -} - /**************************************************************************** * Name: mxt_hwinitialize ****************************************************************************/ @@ -1589,8 +1637,6 @@ static int mxt_hwinitialize(FAR struct mxt_dev_s *priv) { struct mxt_info_s *info = &priv->info; unsigned int nslots; - uint16_t xres; - uint16_t yres; uint8_t regval; int ret; @@ -1655,28 +1701,12 @@ static int mxt_hwinitialize(FAR struct mxt_dev_s *priv) info->ysize = regval; - ivdbg("family: %u variant: %u version: %u.%u.%02x\n", - info->family, info->variant, info->version >> 4, info->version & 0xf, + ivdbg("Family: %u variant: %u version: %u.%u.%02x\n", + info->family, info->variant, info->version >> 4, info->version & 0x0f, info->build); ivdbg("Matrix size: (%u,%u) objects: %u\n", info->xsize, info->ysize, info->nobjects); - /* Set up the touchscreen resolution */ - - xres = info->xsize - 1; - yres = info->ysize - 1; - - if (priv->lower->swapxy) - { - priv->xres = yres; - priv->yres = xres; - } - else - { - priv->xres = xres; - priv->yres = yres; - } - /* How many multi touch "slots" */ nslots = priv->t9idmax - priv->t9idmin + 1; @@ -1694,25 +1724,10 @@ static int mxt_hwinitialize(FAR struct mxt_dev_s *priv) goto errout_with_objtab; } - /* Clear any pending messages. This will force the CHG pin to the high - * state and prevent spurious interrupts. - */ - - ret = mxt_clrpending(priv); - if (ret < 0) - { - idbg("ERROR: mxt_clrpending failed: %d\n", ret); - goto errout_with_sample; - } - return OK; /* Error exits */ -errout_with_sample: - kfree(priv->sample); - priv->sample = NULL; - errout_with_objtab: kfree(priv->objtab); priv->objtab = NULL; @@ -1809,31 +1824,14 @@ int mxt_register(FAR struct i2c_dev_s *i2c, goto errout_with_hwinit; } - /* Schedule work to perform the initial sampling and to set the data - * availability conditions. The worker will enable MXT interrupts - * when it completes its initialization. - * - * NOTE: At present, this really does nothing for the case of the MXT - * driver. This could be replaced with MXT_ENABLE(lower). Or, - * alternatively, eliminate mxt_clrpending() which does basically the - * same thing. + /* And return success. MXT interrupts will not be enable until the + * MXT device has been opened (see mxt_open). */ - ret = work_queue(HPWORK, &priv->work, mxt_worker, priv, 0); - if (ret != 0) - { - idbg("Failed to queue work: %d\n", ret); - goto errout_with_dev; - } - - /* And return success */ - return OK; /* Error clean-up exits */ -errout_with_dev: - (void)unregister_driver(devname); errout_with_hwinit: kfree(priv->objtab); kfree(priv->sample);