Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sony-laptop: add touchpad enable/disable function

This setting is stored in the EC and available across reboots.

[malattia@linux.it: group function specific variables in a struct, use
kstrtoul]

Signed-off-by: Marco Chiappero <marco@absence.it>
Signed-off-by: Mattia Dongili <malattia@linux.it>
Signed-off-by: Matthew Garrett <mjg@redhat.com>

authored by

Marco Chiappero and committed by
Matthew Garrett
2b8791c4 2e526311

+91
+91
drivers/platform/x86/sony-laptop.c
··· 159 159 static int sony_nc_highspeed_charging_setup(struct platform_device *pd); 160 160 static void sony_nc_highspeed_charging_cleanup(struct platform_device *pd); 161 161 162 + static int sony_nc_touchpad_setup(struct platform_device *pd, 163 + unsigned int handle); 164 + static void sony_nc_touchpad_cleanup(struct platform_device *pd); 165 + 162 166 enum sony_nc_rfkill { 163 167 SONY_WIFI, 164 168 SONY_BLUETOOTH, ··· 1294 1290 /* setup hotkeys */ 1295 1291 sony_call_snc_handle(handle, 0x100, &result); 1296 1292 break; 1293 + case 0x0105: 1294 + case 0x0148: 1295 + /* touchpad enable/disable */ 1296 + result = sony_nc_touchpad_setup(pf_device, handle); 1297 + if (result) 1298 + pr_err("couldn't set up touchpad control function (%d)\n", 1299 + result); 1300 + break; 1297 1301 case 0x0115: 1298 1302 case 0x0136: 1299 1303 case 0x013f: ··· 1371 1359 continue; 1372 1360 1373 1361 switch (handle) { 1362 + case 0x0105: 1363 + case 0x0148: 1364 + sony_nc_touchpad_cleanup(pd); 1365 + break; 1374 1366 case 0x0115: 1375 1367 case 0x0136: 1376 1368 case 0x013f: ··· 2389 2373 device_remove_file(&pd->dev, hsc_handle); 2390 2374 kfree(hsc_handle); 2391 2375 hsc_handle = NULL; 2376 + } 2377 + } 2378 + 2379 + /* Touchpad enable/disable */ 2380 + struct touchpad_control { 2381 + struct device_attribute attr; 2382 + int handle; 2383 + }; 2384 + static struct touchpad_control *tp_ctl; 2385 + 2386 + static ssize_t sony_nc_touchpad_store(struct device *dev, 2387 + struct device_attribute *attr, const char *buffer, size_t count) 2388 + { 2389 + unsigned int result; 2390 + unsigned long value; 2391 + 2392 + if (count > 31) 2393 + return -EINVAL; 2394 + 2395 + if (kstrtoul(buffer, 10, &value) || value > 1) 2396 + return -EINVAL; 2397 + 2398 + /* sysfs: 0 disabled, 1 enabled 2399 + * EC: 0 enabled, 1 disabled 2400 + */ 2401 + if (sony_call_snc_handle(tp_ctl->handle, 2402 + (!value << 0x10) | 0x100, &result)) 2403 + return -EIO; 2404 + 2405 + return count; 2406 + } 2407 + 2408 + static ssize_t sony_nc_touchpad_show(struct device *dev, 2409 + struct device_attribute *attr, char *buffer) 2410 + { 2411 + unsigned int result; 2412 + 2413 + if (sony_call_snc_handle(tp_ctl->handle, 0x000, &result)) 2414 + return -EINVAL; 2415 + 2416 + return snprintf(buffer, PAGE_SIZE, "%d\n", !(result & 0x01)); 2417 + } 2418 + 2419 + static int sony_nc_touchpad_setup(struct platform_device *pd, 2420 + unsigned int handle) 2421 + { 2422 + int ret = 0; 2423 + 2424 + tp_ctl = kzalloc(sizeof(struct touchpad_control), GFP_KERNEL); 2425 + if (!tp_ctl) 2426 + return -ENOMEM; 2427 + 2428 + tp_ctl->handle = handle; 2429 + 2430 + sysfs_attr_init(&tp_ctl->attr.attr); 2431 + tp_ctl->attr.attr.name = "touchpad"; 2432 + tp_ctl->attr.attr.mode = S_IRUGO | S_IWUSR; 2433 + tp_ctl->attr.show = sony_nc_touchpad_show; 2434 + tp_ctl->attr.store = sony_nc_touchpad_store; 2435 + 2436 + ret = device_create_file(&pd->dev, &tp_ctl->attr); 2437 + if (ret) { 2438 + kfree(tp_ctl); 2439 + tp_ctl = NULL; 2440 + } 2441 + 2442 + return ret; 2443 + } 2444 + 2445 + static void sony_nc_touchpad_cleanup(struct platform_device *pd) 2446 + { 2447 + if (tp_ctl) { 2448 + device_remove_file(&pd->dev, &tp_ctl->attr); 2449 + kfree(tp_ctl); 2450 + tp_ctl = NULL; 2392 2451 } 2393 2452 } 2394 2453