-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathmain.c
150 lines (121 loc) · 3.7 KB
/
main.c
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// SPDX-License-Identifier: GPL-2.0
/* ========================================================================== */
/* https://www.intel.com/content/dam/support/us/en/documents/laptops/whitebook/QC71_PROD_SPEC.pdf
*
*
* based on the following resources:
* - https://lwn.net/Articles/391230/
* - http://blog.nietrzeba.pl/2011/12/mof-decompilation.html
* - https://github.com/tuxedocomputers/tuxedo-cc-wmi/
* - https://github.com/tuxedocomputers/tuxedo-keyboard/
* - Control Center for Microsoft Windows
* - http://forum.notebookreview.com/threads/tongfang-gk7cn6s-gk7cp0s-gk7cp7s.825461/page-54
*/
/* ========================================================================== */
#include "pr.h"
#include <linux/dmi.h>
#include <linux/init.h>
#include <linux/kconfig.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/wmi.h>
#include "ec.h"
#include "features.h"
#include "wmi.h"
/* submodules */
#include "pdev.h"
#include "events.h"
#include "hwmon.h"
#include "battery.h"
#include "led_lightbar.h"
#include "debugfs.h"
/* ========================================================================== */
#define SUBMODULE_ENTRY(_name, _req) { .name = #_name, .init = qc71_ ## _name ## _setup, .cleanup = qc71_ ## _name ## _cleanup, .required = _req }
static struct qc71_submodule {
const char *name;
bool required : 1,
initialized : 1;
int (*init)(void);
void (*cleanup)(void);
} qc71_submodules[] __refdata = {
SUBMODULE_ENTRY(pdev, true), /* must be first */
SUBMODULE_ENTRY(wmi_events, false),
SUBMODULE_ENTRY(hwmon, false),
SUBMODULE_ENTRY(battery, false),
SUBMODULE_ENTRY(led_lightbar, false),
SUBMODULE_ENTRY(debugfs, false),
};
#undef SUBMODULE_ENTRY
static void do_cleanup(void)
{
int i;
for (i = ARRAY_SIZE(qc71_submodules) - 1; i >= 0; i--) {
const struct qc71_submodule *sm = &qc71_submodules[i];
if (sm->initialized)
sm->cleanup();
}
}
static int __init qc71_laptop_module_init(void)
{
int err = 0, i;
if (!wmi_has_guid(QC71_WMI_WMBC_GUID)) {
pr_err("WMI GUID not found\n");
err = -ENODEV; goto out;
}
err = ec_read_byte(PROJ_ID_ADDR);
if (err < 0) {
pr_err("failed to query project id: %d\n", err);
goto out;
}
pr_info("project id: %d\n", err);
err = ec_read_byte(PLATFORM_ID_ADDR);
if (err < 0) {
pr_err("failed to query platform id: %d\n", err);
goto out;
}
pr_info("platform id: %d\n", err);
err = qc71_check_features();
if (err) {
pr_err("cannot check system features: %d\n", err);
goto out;
}
pr_info("supported features:");
if (qc71_features.super_key_lock) pr_cont(" super-key-lock");
if (qc71_features.lightbar) pr_cont(" lightbar");
if (qc71_features.fan_boost) pr_cont(" fan-boost");
if (qc71_features.fn_lock) pr_cont(" fn-lock");
if (qc71_features.batt_charge_limit) pr_cont(" charge-limit");
if (qc71_features.fan_extras) pr_cont(" fan-extras");
pr_cont("\n");
for (i = 0; i < ARRAY_SIZE(qc71_submodules); i++) {
struct qc71_submodule *sm = &qc71_submodules[i];
err = sm->init();
if (err) {
pr_warn("failed to initialize %s submodule: %d\n", sm->name, err);
if (sm->required)
goto out;
} else {
sm->initialized = true;
}
}
err = 0;
out:
if (err)
do_cleanup();
else
pr_info("module loaded\n");
return err;
}
static void __exit qc71_laptop_module_cleanup(void)
{
do_cleanup();
pr_info("module unloaded\n");
}
/* ========================================================================== */
module_init(qc71_laptop_module_init);
module_exit(qc71_laptop_module_cleanup);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Barnabás Pőcze <[email protected]>");
MODULE_DESCRIPTION("QC71 laptop platform driver");
MODULE_ALIAS("wmi:" QC71_WMI_WMBC_GUID);