Skip to content

Commit 5298ab1

Browse files
committed
Dynamically fetching the HID descriptor.
1 parent bc57164 commit 5298ab1

File tree

1 file changed

+108
-1
lines changed

1 file changed

+108
-1
lines changed

module/surface_sam_sid_vhf.c

Lines changed: 108 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -614,9 +614,116 @@ static void sid_vhf_hid_close(struct hid_device *hid)
614614
hid_dbg(hid, "%s\n", __func__);
615615
}
616616

617+
struct surface_sam_sid_vhf_meta_rqst {
618+
u8 id;
619+
u32 offset;
620+
u32 limit;
621+
u8 end; // 0x01 if end was reached
622+
} __packed;
623+
624+
struct vhf_meta_info_resp {
625+
u8 _1;
626+
u8 _2;
627+
u8 _3;
628+
u8 _4;
629+
u8 _5;
630+
u8 _6;
631+
u8 _7;
632+
u16 len;
633+
} __packed;
634+
635+
union vhf_buffer_data {
636+
struct vhf_meta_info_resp info;
637+
u8 pld[0x76];
638+
};
639+
640+
struct surface_sam_sid_vhf_meta_resp {
641+
struct surface_sam_sid_vhf_meta_rqst rqst;
642+
union vhf_buffer_data data;
643+
} __packed;
644+
645+
646+
// TODO: need to return pointer + len
647+
static int vhf_get_hid_descriptor(struct hid_device *hid, u8 **desc, int *size)
648+
{
649+
int status;
650+
int len;
651+
u8 *buf;
652+
653+
struct surface_sam_ssh_rqst rqst = {};
654+
struct surface_sam_sid_vhf_meta_resp resp = {};
655+
struct surface_sam_ssh_buf result = {};
656+
657+
resp.rqst.id = 0;
658+
resp.rqst.offset = 0;
659+
resp.rqst.limit = 0x76;
660+
resp.rqst.end = 0;
661+
662+
rqst.tc = 0x15;
663+
rqst.cid = 0x04;
664+
rqst.iid = 0x03;
665+
rqst.pri = 0x02;
666+
rqst.snc = 0x01;
667+
rqst.cdl = sizeof(struct surface_sam_sid_vhf_meta_rqst);
668+
rqst.pld = (u8*)&resp.rqst;
669+
670+
result.cap = sizeof(struct surface_sam_sid_vhf_meta_resp);
671+
result.len = 0;
672+
result.data = (u8*)&resp;
673+
674+
// first fetch 01 to get the total length
675+
status = surface_sam_ssh_rqst(&rqst, &result);
676+
if (status) {
677+
return status;
678+
}
679+
680+
len = resp.data.info.len;
681+
682+
// allocate a buffer for the descriptor
683+
buf = kzalloc(len * sizeof(u8), GFP_KERNEL);
684+
685+
// then, iterate and write into buffer, copying out resp.rqst.len bytes
686+
// (it gets set to the length of data read)
687+
688+
resp.rqst.id = 1;
689+
resp.rqst.offset = 0;
690+
resp.rqst.end = 0;
691+
692+
while (resp.rqst.end != 0x01) {
693+
status = surface_sam_ssh_rqst(&rqst, &result);
694+
if (status) {
695+
kfree(buf);
696+
return status;
697+
}
698+
memcpy(buf + resp.rqst.offset, resp.data.pld, resp.rqst.limit);
699+
700+
resp.rqst.offset += resp.rqst.limit;
701+
}
702+
703+
*desc = buf;
704+
*size = len;
705+
706+
return 0;
707+
}
708+
617709
static int sid_vhf_hid_parse(struct hid_device *hid)
618710
{
619-
return hid_parse_report(hid, (u8 *)sid_vhf_hid_desc, ARRAY_SIZE(sid_vhf_hid_desc));
711+
712+
int ret = 0, size;
713+
u8 *buf;
714+
715+
ret = vhf_get_hid_descriptor(hid, &buf, &size);
716+
if (ret != 0) {
717+
hid_dbg(hid, "vhf_get_hid_descriptor ret %d\n", ret);
718+
return -EIO;
719+
}
720+
print_hex_dump_debug("descriptor:", DUMP_PREFIX_OFFSET, 16, 1, buf, size, false);
721+
722+
ret = hid_parse_report(hid, (u8 *)sid_vhf_hid_desc, ARRAY_SIZE(sid_vhf_hid_desc));
723+
/* ret = hid_parse_report(hid, buf, size); */
724+
kfree(buf);
725+
return ret;
726+
620727
}
621728

622729
static int sid_vhf_hid_raw_request(struct hid_device *hid, unsigned char reportnum,

0 commit comments

Comments
 (0)