summaryrefslogtreecommitdiff
path: root/drivers/input/joystick/iforce/iforce-serio.c
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2018-08-10 03:28:35 +0300
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2019-06-23 09:55:23 +0300
commit6ac0aec6b0a651d64eef759fddf17d9145b51033 (patch)
tree64e8b5f744e8ccaed644cb8282b11abae7a41ae6 /drivers/input/joystick/iforce/iforce-serio.c
parent633354d1910262f2a3262797572ff72da461379e (diff)
downloadlinux-6ac0aec6b0a651d64eef759fddf17d9145b51033.tar.xz
Input: iforce - allow callers supply data buffer when fetching device IDs
We want to move buffer handling into transport layers as the properties of buffers (DMA-safety, alignment, etc) are different for different transports. To allow this, let's allow caller to specify their own buffers for the results of iforce_get_id_packet() and let transport drivers to figure what buffers they need to use for transfers. Tested-by: Tim Schumacher <timschumi@gmx.de> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input/joystick/iforce/iforce-serio.c')
-rw-r--r--drivers/input/joystick/iforce/iforce-serio.c28
1 files changed, 20 insertions, 8 deletions
diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c
index 8d7eba9c9f0e..be44aed551f7 100644
--- a/drivers/input/joystick/iforce/iforce-serio.c
+++ b/drivers/input/joystick/iforce/iforce-serio.c
@@ -31,6 +31,8 @@ struct iforce_serio {
int idx, pkt, len, id;
u8 csum;
u8 expect_packet;
+ u8 cmd_response[IFORCE_MAX_LENGTH];
+ u8 cmd_response_len;
};
static void iforce_serio_xmit(struct iforce *iforce)
@@ -81,24 +83,34 @@ again:
spin_unlock_irqrestore(&iforce->xmit_lock, flags);
}
-static int iforce_serio_get_id(struct iforce *iforce, u8 *packet)
+static int iforce_serio_get_id(struct iforce *iforce, u8 id,
+ u8 *response_data, size_t *response_len)
{
struct iforce_serio *iforce_serio = container_of(iforce,
struct iforce_serio,
iforce);
iforce_serio->expect_packet = HI(FF_CMD_QUERY);
- iforce_send_packet(iforce, FF_CMD_QUERY, packet);
+ iforce_serio->cmd_response_len = 0;
+
+ iforce_send_packet(iforce, FF_CMD_QUERY, &id);
wait_event_interruptible_timeout(iforce->wait,
!iforce_serio->expect_packet, HZ);
if (iforce_serio->expect_packet) {
iforce_serio->expect_packet = 0;
- return -EIO;
+ return -ETIMEDOUT;
}
- return -(iforce->edata[0] != packet[0]);
+ if (iforce_serio->cmd_response[0] != id)
+ return -EIO;
+
+ memcpy(response_data, iforce_serio->cmd_response,
+ iforce_serio->cmd_response_len);
+ *response_len = iforce_serio->cmd_response_len;
+
+ return 0;
}
static int iforce_serio_start_io(struct iforce *iforce)
@@ -127,7 +139,7 @@ static void iforce_serio_write_wakeup(struct serio *serio)
}
static irqreturn_t iforce_serio_irq(struct serio *serio,
- unsigned char data, unsigned int flags)
+ unsigned char data, unsigned int flags)
{
struct iforce_serio *iforce_serio = serio_get_drvdata(serio);
struct iforce *iforce = &iforce_serio->iforce;
@@ -166,9 +178,9 @@ static irqreturn_t iforce_serio_irq(struct serio *serio,
/* Handle command completion */
if (iforce_serio->expect_packet == iforce_serio->id) {
iforce_serio->expect_packet = 0;
- iforce->ecmd = (iforce_serio->id << 8) |
- iforce_serio->idx;
- memcpy(iforce->edata, iforce->data, IFORCE_MAX_LENGTH);
+ memcpy(iforce_serio->cmd_response, iforce->data,
+ IFORCE_MAX_LENGTH);
+ iforce_serio->cmd_response_len = iforce_serio->len;
/* Signal that command is done */
wake_up(&iforce->wait);