summaryrefslogtreecommitdiff
path: root/drivers/hid/surface-hid/surface_hid_core.h
blob: 4b1a7b57e035c38a4e037cd3c3322d48b9a177dc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * Common/core components for the Surface System Aggregator Module (SSAM) HID
 * transport driver. Provides support for integrated HID devices on Microsoft
 * Surface models.
 *
 * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
 */

#ifndef SURFACE_HID_CORE_H
#define SURFACE_HID_CORE_H

#include <linux/hid.h>
#include <linux/pm.h>
#include <linux/types.h>

#include <linux/surface_aggregator/controller.h>
#include <linux/surface_aggregator/device.h>

enum surface_hid_descriptor_entry {
	SURFACE_HID_DESC_HID    = 0,
	SURFACE_HID_DESC_REPORT = 1,
	SURFACE_HID_DESC_ATTRS  = 2,
};

struct surface_hid_descriptor {
	__u8 desc_len;			/* = 9 */
	__u8 desc_type;			/* = HID_DT_HID */
	__le16 hid_version;
	__u8 country_code;
	__u8 num_descriptors;		/* = 1 */

	__u8 report_desc_type;		/* = HID_DT_REPORT */
	__le16 report_desc_len;
} __packed;

static_assert(sizeof(struct surface_hid_descriptor) == 9);

struct surface_hid_attributes {
	__le32 length;
	__le16 vendor;
	__le16 product;
	__le16 version;
	__u8 _unknown[22];
} __packed;

static_assert(sizeof(struct surface_hid_attributes) == 32);

struct surface_hid_device;

struct surface_hid_device_ops {
	int (*get_descriptor)(struct surface_hid_device *shid, u8 entry, u8 *buf, size_t len);
	int (*output_report)(struct surface_hid_device *shid, u8 rprt_id, u8 *buf, size_t len);
	int (*get_feature_report)(struct surface_hid_device *shid, u8 rprt_id, u8 *buf, size_t len);
	int (*set_feature_report)(struct surface_hid_device *shid, u8 rprt_id, u8 *buf, size_t len);
};

struct surface_hid_device {
	struct device *dev;
	struct ssam_controller *ctrl;
	struct ssam_device_uid uid;

	struct surface_hid_descriptor hid_desc;
	struct surface_hid_attributes attrs;

	struct ssam_event_notifier notif;
	struct hid_device *hid;

	struct surface_hid_device_ops ops;
};

int surface_hid_device_add(struct surface_hid_device *shid);
void surface_hid_device_destroy(struct surface_hid_device *shid);

extern const struct dev_pm_ops surface_hid_pm_ops;

#endif /* SURFACE_HID_CORE_H */