Skip to content

Commit

Permalink
drivers: ps2: Add resend callback to ps/2 interface
Browse files Browse the repository at this point in the history
When the PS/2 driver detects an error in an incoming transmission, it’s supposed to send 0xfe to the device to ask it to resend the last packet.

But a PS/2 packet can be more than one byte (such as a 3 or 4-byte mouse packet).

So, on reception of the 0xfe resend command, the PS/2 device resends ALL bytes in the packet and not just the one where the transmission failed.

This can cause the higher level driver’s packet buffer to become misaligned.

This PR adds a callback that notifies the higher level driver when the PS/2 driver requested a resend so that the higher level driver can expect a new packet and doesn’t get misaligned.
  • Loading branch information
infused-kim committed Oct 4, 2023
1 parent 6f349d0 commit 3d0d1bf
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 8 deletions.
8 changes: 6 additions & 2 deletions drivers/ps2/ps2_handlers.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@
#include <zephyr/syscall_handler.h>

static inline int z_vrfy_ps2_config(const struct device *dev,
ps2_callback_t callback_isr)
ps2_callback_t callback_isr,
ps2_resend_callback_t resend_callback_isr)

{
Z_OOPS(Z_SYSCALL_DRIVER_PS2(dev, config));
Z_OOPS(Z_SYSCALL_VERIFY_MSG(callback_isr == NULL,
"callback not be set from user mode"));
return z_impl_ps2_config(dev, callback_isr);
Z_OOPS(Z_SYSCALL_VERIFY_MSG(resend_callback_isr == NULL,
"resend callback not be set from user mode"));
return z_impl_ps2_config(dev, callback_isr, resend_callback_isr);
}
#include <syscalls/ps2_config_mrsh.c>

Expand Down
3 changes: 2 additions & 1 deletion drivers/ps2/ps2_mchp_xec.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ static inline void ps2_xec_girq_en(const struct device *dev)
#endif /* CONFIG_SOC_SERIES_MEC172X */

static int ps2_xec_configure(const struct device *dev,
ps2_callback_t callback_isr)
ps2_callback_t callback_isr,
ps2_resend_callback_t resend_callback_isr)
{
const struct ps2_xec_config * const config = dev->config;
struct ps2_xec_data * const data = dev->data;
Expand Down
3 changes: 2 additions & 1 deletion drivers/ps2/ps2_npcx_channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ struct ps2_npcx_ch_config {

/* PS/2 api functions */
static int ps2_npcx_ch_configure(const struct device *dev,
ps2_callback_t callback_isr)
ps2_callback_t callback_isr,
ps2_resend_callback_t resend_callback_isr)
{
const struct ps2_npcx_ch_config *const config = dev->config;
int ret;
Expand Down
24 changes: 20 additions & 4 deletions include/zephyr/drivers/ps2.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,18 @@ extern "C" {
*/
typedef void (*ps2_callback_t)(const struct device *dev, uint8_t data);

/**
* @brief PS/2 callback that is called when the PS/2 driver detects a
* transmission error and instructs the PS/2 device to re-send the last PS/2
* packet. A PS/2 packet can be more than one byte and when the device is
* instructed to resend the last packet, it will resend all the bytes. This
* can cause the PS/2 driver to become misaligned. This callback lets the PS/2
* driver know that it should expect a resend of an entire packet.
*
* @param dev Pointer to the device structure for the driver instance.
*/
typedef void (*ps2_resend_callback_t)(const struct device *dev);

/**
* @cond INTERNAL_HIDDEN
*
Expand All @@ -45,7 +57,8 @@ typedef void (*ps2_callback_t)(const struct device *dev, uint8_t data);
* (Internal use only.)
*/
typedef int (*ps2_config_t)(const struct device *dev,
ps2_callback_t callback_isr);
ps2_callback_t callback_isr,
ps2_resend_callback_t resend_callback_isr);
typedef int (*ps2_read_t)(const struct device *dev, uint8_t *value);
typedef int (*ps2_write_t)(const struct device *dev, uint8_t value);
typedef int (*ps2_disable_callback_t)(const struct device *dev);
Expand Down Expand Up @@ -73,15 +86,18 @@ __subsystem struct ps2_driver_api {
* @retval Negative errno code if failure.
*/
__syscall int ps2_config(const struct device *dev,
ps2_callback_t callback_isr);
ps2_callback_t callback_isr,
ps2_resend_callback_t resend_callback_isr);

static inline int z_impl_ps2_config(const struct device *dev,
ps2_callback_t callback_isr)
ps2_callback_t callback_isr,
ps2_resend_callback_t resend_callback_isr)

{
const struct ps2_driver_api *api =
(struct ps2_driver_api *)dev->api;

return api->config(dev, callback_isr);
return api->config(dev, callback_isr, resend_callback_isr);
}

/**
Expand Down

0 comments on commit 3d0d1bf

Please sign in to comment.