aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/misc/sony-laptop.c81
1 files changed, 62 insertions, 19 deletions
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c
index d7b5330a7bcd..cabbed0015e4 100644
--- a/drivers/misc/sony-laptop.c
+++ b/drivers/misc/sony-laptop.c
@@ -58,13 +58,17 @@ static ssize_t sony_acpi_show(struct device *, struct device_attribute *,
58 char *); 58 char *);
59static ssize_t sony_acpi_store(struct device *, struct device_attribute *, 59static ssize_t sony_acpi_store(struct device *, struct device_attribute *,
60 const char *, size_t); 60 const char *, size_t);
61static int boolean_validate(const int, const int);
62static int brightness_default_validate(const int, const int);
63
64#define SNC_VALIDATE_IN 0
65#define SNC_VALIDATE_OUT 1
61 66
62struct sony_acpi_value { 67struct sony_acpi_value {
63 char *name; /* name of the entry */ 68 char *name; /* name of the entry */
64 char **acpiget; /* names of the ACPI get function */ 69 char **acpiget; /* names of the ACPI get function */
65 char **acpiset; /* names of the ACPI set function */ 70 char **acpiset; /* names of the ACPI set function */
66 int min; /* minimum allowed value or -1 */ 71 int (*validate)(const int, const int); /* input/output validation */
67 int max; /* maximum allowed value or -1 */
68 int value; /* current setting */ 72 int value; /* current setting */
69 int valid; /* Has ever been set */ 73 int valid; /* Has ever been set */
70 int debug; /* active only in debug mode ? */ 74 int debug; /* active only in debug mode ? */
@@ -74,13 +78,12 @@ struct sony_acpi_value {
74#define HANDLE_NAMES(_name, _values...) \ 78#define HANDLE_NAMES(_name, _values...) \
75 static char *snc_##_name[] = { _values, NULL } 79 static char *snc_##_name[] = { _values, NULL }
76 80
77#define SONY_ACPI_VALUE(_name, _getters, _setters, _min, _max, _debug) \ 81#define SONY_ACPI_VALUE(_name, _getters, _setters, _validate, _debug) \
78 { \ 82 { \
79 .name = __stringify(_name), \ 83 .name = __stringify(_name), \
80 .acpiget = _getters, \ 84 .acpiget = _getters, \
81 .acpiset = _setters, \ 85 .acpiset = _setters, \
82 .min = _min, \ 86 .validate = _validate, \
83 .max = _max, \
84 .debug = _debug, \ 87 .debug = _debug, \
85 .devattr = __ATTR(_name, 0, sony_acpi_show, sony_acpi_store), \ 88 .devattr = __ATTR(_name, 0, sony_acpi_show, sony_acpi_store), \
86 } 89 }
@@ -114,17 +117,18 @@ HANDLE_NAMES(CMI_set, "SCMI");
114 117
115static struct sony_acpi_value sony_acpi_values[] = { 118static struct sony_acpi_value sony_acpi_values[] = {
116 SONY_ACPI_VALUE(brightness_default, snc_brightness_def_get, 119 SONY_ACPI_VALUE(brightness_default, snc_brightness_def_get,
117 snc_brightness_def_set, 1, SONY_MAX_BRIGHTNESS, 0), 120 snc_brightness_def_set, brightness_default_validate, 0),
118 SONY_ACPI_VALUE(fnkey, snc_fnkey_get, NULL, -1, -1, 0), 121 SONY_ACPI_VALUE(fnkey, snc_fnkey_get, NULL, NULL, 0),
119 SONY_ACPI_VALUE(cdpower, snc_cdpower_get, snc_cdpower_set, 0, 1, 0), 122 SONY_ACPI_VALUE(cdpower, snc_cdpower_get, snc_cdpower_set, boolean_validate, 0),
120 SONY_ACPI_VALUE(audiopower, snc_audiopower_get, snc_audiopower_set, 0, 123 SONY_ACPI_VALUE(audiopower, snc_audiopower_get, snc_audiopower_set,
121 1, 0), 124 boolean_validate, 0),
122 SONY_ACPI_VALUE(lanpower, snc_lanpower_get, snc_lanpower_set, 0, 1, 1), 125 SONY_ACPI_VALUE(lanpower, snc_lanpower_get, snc_lanpower_set,
126 boolean_validate, 1),
123 /* unknown methods */ 127 /* unknown methods */
124 SONY_ACPI_VALUE(PID, snc_PID_get, NULL, -1, -1, 1), 128 SONY_ACPI_VALUE(PID, snc_PID_get, NULL, NULL, 1),
125 SONY_ACPI_VALUE(CTR, snc_CTR_get, snc_CTR_set, -1, -1, 1), 129 SONY_ACPI_VALUE(CTR, snc_CTR_get, snc_CTR_set, NULL, 1),
126 SONY_ACPI_VALUE(PCR, snc_PCR_get, snc_PCR_set, -1, -1, 1), 130 SONY_ACPI_VALUE(PCR, snc_PCR_get, snc_PCR_set, NULL, 1),
127 SONY_ACPI_VALUE(CMI, snc_CMI_get, snc_CMI_set, -1, -1, 1), 131 SONY_ACPI_VALUE(CMI, snc_CMI_get, snc_CMI_set, NULL, 1),
128 SONY_ACPI_VALUE_NULL 132 SONY_ACPI_VALUE_NULL
129}; 133};
130 134
@@ -190,6 +194,41 @@ static int acpi_callsetfunc(acpi_handle handle, char *name, int value,
190} 194}
191 195
192/* 196/*
197 * sony_acpi_values input/output validate functions
198 */
199
200/* brightness_default_validate:
201 *
202 * manipulate input output values to keep consistency with the
203 * backlight framework for which brightness values are 0-based.
204 */
205static int brightness_default_validate(const int direction, const int value)
206{
207 switch (direction) {
208 case SNC_VALIDATE_OUT:
209 return value - 1;
210 case SNC_VALIDATE_IN:
211 if (value >= 0 && value < SONY_MAX_BRIGHTNESS)
212 return value + 1;
213 }
214 return -EINVAL;
215}
216
217/* boolean_validate:
218 *
219 * on input validate boolean values 0/1, on output just pass the
220 * received value.
221 */
222static int boolean_validate(const int direction, const int value)
223{
224 if (direction == SNC_VALIDATE_IN) {
225 if (value != 0 && value != 1)
226 return -EINVAL;
227 }
228 return value;
229}
230
231/*
193 * Sysfs show/store common to all sony_acpi_values 232 * Sysfs show/store common to all sony_acpi_values
194 */ 233 */
195static ssize_t sony_acpi_show(struct device *dev, struct device_attribute *attr, 234static ssize_t sony_acpi_show(struct device *dev, struct device_attribute *attr,
@@ -205,6 +244,9 @@ static ssize_t sony_acpi_show(struct device *dev, struct device_attribute *attr,
205 if (acpi_callgetfunc(sony_acpi_handle, *item->acpiget, &value) < 0) 244 if (acpi_callgetfunc(sony_acpi_handle, *item->acpiget, &value) < 0)
206 return -EIO; 245 return -EIO;
207 246
247 if (item->validate)
248 value = item->validate(SNC_VALIDATE_OUT, value);
249
208 return snprintf(buffer, PAGE_SIZE, "%d\n", value); 250 return snprintf(buffer, PAGE_SIZE, "%d\n", value);
209} 251}
210 252
@@ -224,10 +266,11 @@ static ssize_t sony_acpi_store(struct device *dev,
224 266
225 value = simple_strtoul(buffer, NULL, 10); 267 value = simple_strtoul(buffer, NULL, 10);
226 268
227 if (item->min != -1 && value < item->min) 269 if (item->validate)
228 return -EINVAL; 270 value = item->validate(SNC_VALIDATE_IN, value);
229 if (item->max != -1 && value > item->max) 271
230 return -EINVAL; 272 if (value < 0)
273 return value;
231 274
232 if (acpi_callsetfunc(sony_acpi_handle, *item->acpiset, value, NULL) < 0) 275 if (acpi_callsetfunc(sony_acpi_handle, *item->acpiset, value, NULL) < 0)
233 return -EIO; 276 return -EIO;