1*b05ff100SMaximilian Luz /* SPDX-License-Identifier: GPL-2.0+ */
2*b05ff100SMaximilian Luz /*
3*b05ff100SMaximilian Luz  * Common/core components for the Surface System Aggregator Module (SSAM) HID
4*b05ff100SMaximilian Luz  * transport driver. Provides support for integrated HID devices on Microsoft
5*b05ff100SMaximilian Luz  * Surface models.
6*b05ff100SMaximilian Luz  *
7*b05ff100SMaximilian Luz  * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
8*b05ff100SMaximilian Luz  */
9*b05ff100SMaximilian Luz 
10*b05ff100SMaximilian Luz #ifndef SURFACE_HID_CORE_H
11*b05ff100SMaximilian Luz #define SURFACE_HID_CORE_H
12*b05ff100SMaximilian Luz 
13*b05ff100SMaximilian Luz #include <linux/hid.h>
14*b05ff100SMaximilian Luz #include <linux/pm.h>
15*b05ff100SMaximilian Luz #include <linux/types.h>
16*b05ff100SMaximilian Luz 
17*b05ff100SMaximilian Luz #include <linux/surface_aggregator/controller.h>
18*b05ff100SMaximilian Luz #include <linux/surface_aggregator/device.h>
19*b05ff100SMaximilian Luz 
20*b05ff100SMaximilian Luz enum surface_hid_descriptor_entry {
21*b05ff100SMaximilian Luz 	SURFACE_HID_DESC_HID    = 0,
22*b05ff100SMaximilian Luz 	SURFACE_HID_DESC_REPORT = 1,
23*b05ff100SMaximilian Luz 	SURFACE_HID_DESC_ATTRS  = 2,
24*b05ff100SMaximilian Luz };
25*b05ff100SMaximilian Luz 
26*b05ff100SMaximilian Luz struct surface_hid_descriptor {
27*b05ff100SMaximilian Luz 	__u8 desc_len;			/* = 9 */
28*b05ff100SMaximilian Luz 	__u8 desc_type;			/* = HID_DT_HID */
29*b05ff100SMaximilian Luz 	__le16 hid_version;
30*b05ff100SMaximilian Luz 	__u8 country_code;
31*b05ff100SMaximilian Luz 	__u8 num_descriptors;		/* = 1 */
32*b05ff100SMaximilian Luz 
33*b05ff100SMaximilian Luz 	__u8 report_desc_type;		/* = HID_DT_REPORT */
34*b05ff100SMaximilian Luz 	__le16 report_desc_len;
35*b05ff100SMaximilian Luz } __packed;
36*b05ff100SMaximilian Luz 
37*b05ff100SMaximilian Luz static_assert(sizeof(struct surface_hid_descriptor) == 9);
38*b05ff100SMaximilian Luz 
39*b05ff100SMaximilian Luz struct surface_hid_attributes {
40*b05ff100SMaximilian Luz 	__le32 length;
41*b05ff100SMaximilian Luz 	__le16 vendor;
42*b05ff100SMaximilian Luz 	__le16 product;
43*b05ff100SMaximilian Luz 	__le16 version;
44*b05ff100SMaximilian Luz 	__u8 _unknown[22];
45*b05ff100SMaximilian Luz } __packed;
46*b05ff100SMaximilian Luz 
47*b05ff100SMaximilian Luz static_assert(sizeof(struct surface_hid_attributes) == 32);
48*b05ff100SMaximilian Luz 
49*b05ff100SMaximilian Luz struct surface_hid_device;
50*b05ff100SMaximilian Luz 
51*b05ff100SMaximilian Luz struct surface_hid_device_ops {
52*b05ff100SMaximilian Luz 	int (*get_descriptor)(struct surface_hid_device *shid, u8 entry, u8 *buf, size_t len);
53*b05ff100SMaximilian Luz 	int (*output_report)(struct surface_hid_device *shid, u8 rprt_id, u8 *buf, size_t len);
54*b05ff100SMaximilian Luz 	int (*get_feature_report)(struct surface_hid_device *shid, u8 rprt_id, u8 *buf, size_t len);
55*b05ff100SMaximilian Luz 	int (*set_feature_report)(struct surface_hid_device *shid, u8 rprt_id, u8 *buf, size_t len);
56*b05ff100SMaximilian Luz };
57*b05ff100SMaximilian Luz 
58*b05ff100SMaximilian Luz struct surface_hid_device {
59*b05ff100SMaximilian Luz 	struct device *dev;
60*b05ff100SMaximilian Luz 	struct ssam_controller *ctrl;
61*b05ff100SMaximilian Luz 	struct ssam_device_uid uid;
62*b05ff100SMaximilian Luz 
63*b05ff100SMaximilian Luz 	struct surface_hid_descriptor hid_desc;
64*b05ff100SMaximilian Luz 	struct surface_hid_attributes attrs;
65*b05ff100SMaximilian Luz 
66*b05ff100SMaximilian Luz 	struct ssam_event_notifier notif;
67*b05ff100SMaximilian Luz 	struct hid_device *hid;
68*b05ff100SMaximilian Luz 
69*b05ff100SMaximilian Luz 	struct surface_hid_device_ops ops;
70*b05ff100SMaximilian Luz };
71*b05ff100SMaximilian Luz 
72*b05ff100SMaximilian Luz int surface_hid_device_add(struct surface_hid_device *shid);
73*b05ff100SMaximilian Luz void surface_hid_device_destroy(struct surface_hid_device *shid);
74*b05ff100SMaximilian Luz 
75*b05ff100SMaximilian Luz extern const struct dev_pm_ops surface_hid_pm_ops;
76*b05ff100SMaximilian Luz 
77*b05ff100SMaximilian Luz #endif /* SURFACE_HID_CORE_H */
78