Skip to content

Commit c7c2889

Browse files
marcanjannau
authored andcommitted
HID: transport: spi: Implement GET FEATURE
This is used for fetching trackpad dimensions. Signed-off-by: Hector Martin <marcan@marcan.st>
1 parent 5b53159 commit c7c2889

1 file changed

Lines changed: 48 additions & 3 deletions

File tree

drivers/hid/spi-hid/spi-hid-apple-core.c

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ struct spihid_interface {
6565
u32 max_input_report_len;
6666
u32 max_output_report_len;
6767
u8 name[32];
68+
u8 reply_buf[SPIHID_DESC_MAX];
69+
u32 reply_len;
6870
bool ready;
6971
};
7072

@@ -327,14 +329,33 @@ static int apple_ll_raw_request(struct hid_device *hdev,
327329
{
328330
struct spihid_interface *idev = hdev->driver_data;
329331
struct spihid_apple *spihid = spihid_get_data(idev);
332+
int ret;
330333

331334
dev_dbg(&spihid->spidev->dev,
332335
"apple_ll_raw_request: device:%u reportnum:%hhu rtype:%hhu",
333336
idev->id, reportnum, rtype);
334337

335338
switch (reqtype) {
336339
case HID_REQ_GET_REPORT:
337-
return -EINVAL; // spihid_get_raw_report();
340+
if (rtype != HID_FEATURE_REPORT)
341+
return -EINVAL;
342+
343+
idev->reply_len = 0;
344+
ret = spihid_apple_request(spihid, idev->id, 0x32, reportnum, 0x00, len, NULL, 0);
345+
if (ret < 0)
346+
return ret;
347+
348+
ret = wait_event_interruptible_timeout(spihid->wait, idev->reply_len,
349+
SPIHID_DEF_WAIT);
350+
if (ret == 0)
351+
ret = -ETIMEDOUT;
352+
if (ret < 0) {
353+
dev_err(&spihid->spidev->dev, "waiting for get report failed: %d", ret);
354+
return ret;
355+
}
356+
memcpy(buf, idev->reply_buf, max_t(size_t, len, idev->reply_len));
357+
return idev->reply_len;
358+
338359
case HID_REQ_SET_REPORT:
339360
if (buf[0] != reportnum)
340361
return -EINVAL;
@@ -606,7 +627,27 @@ static bool spihid_process_iface_hid_report_desc(struct spihid_apple *spihid,
606627
return true;
607628
}
608629

609-
static bool spihid_process_response(struct spihid_apple *spihid,
630+
static bool spihid_process_iface_get_report(struct spihid_apple *spihid,
631+
u32 device, u8 report,
632+
u8 *payload, size_t len)
633+
{
634+
struct spihid_interface *iface = spihid_get_iface(spihid, device);
635+
636+
if (!iface)
637+
return false;
638+
639+
if (len > sizeof(iface->reply_buf) || len < 1)
640+
return false;
641+
642+
memcpy(iface->reply_buf, payload, len);
643+
iface->reply_len = len;
644+
645+
wake_up_interruptible(&spihid->wait);
646+
647+
return true;
648+
}
649+
650+
static bool spihid_process_response(struct spihid_apple *spihid, u32 device,
610651
struct spihid_msg_hdr *hdr, u8 *payload,
611652
size_t len)
612653
{
@@ -626,6 +667,10 @@ static bool spihid_process_response(struct spihid_apple *spihid,
626667
}
627668
}
628669

670+
if (hdr->unknown0 == 0x32) {
671+
return spihid_process_iface_get_report(spihid, device, hdr->unknown1, payload, len);
672+
}
673+
629674
return false;
630675
}
631676

@@ -653,7 +698,7 @@ static void spihid_process_message(struct spihid_apple *spihid, u8 *data,
653698
payload, le16_to_cpu(hdr->length));
654699
break;
655700
case SPIHID_WRITE_PACKET:
656-
handled = spihid_process_response(spihid, hdr, payload,
701+
handled = spihid_process_response(spihid, device, hdr, payload,
657702
le16_to_cpu(hdr->length));
658703
break;
659704
default:

0 commit comments

Comments
 (0)