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