aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-driver-hid-picolcd17
-rw-r--r--drivers/hid/hid-picolcd.c62
2 files changed, 58 insertions, 21 deletions
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-picolcd b/Documentation/ABI/testing/sysfs-driver-hid-picolcd
index 14f52d70621..08579e7e1e8 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-picolcd
+++ b/Documentation/ABI/testing/sysfs-driver-hid-picolcd
@@ -8,12 +8,21 @@ Description: Make it possible to switch the PicoLCD device between LCD
8 enclosed in brackets ('[' and ']') 8 enclosed in brackets ('[' and ']')
9 9
10 Writing: causes operation mode switch. Permitted values are 10 Writing: causes operation mode switch. Permitted values are
11 the non-active mode names listed when read, optionally followed 11 the non-active mode names listed when read.
12 by a delay value expressed in ms.
13 12
14 Note: when switching mode the current PicoLCD HID device gets 13 Note: when switching mode the current PicoLCD HID device gets
15 disconnected and reconnects after above delay (default value 14 disconnected and reconnects after above delay (see attribute
16 is 5 seconds though this default should not be relied on). 15 operation_mode_delay for its value).
16
17
18What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/operation_mode_delay
19Date: April 2010
20Contact: Bruno Prémont <bonbons@linux-vserver.org>
21Description: Delay PicoLCD waits before restarting in new mode when
22 operation_mode has changed.
23
24 Reading/Writing: It is expressed in ms and permitted range is
25 0..30000ms.
17 26
18 27
19What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/fb_update_rate 28What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/fb_update_rate
diff --git a/drivers/hid/hid-picolcd.c b/drivers/hid/hid-picolcd.c
index 6f71c60bf65..aa6f2e18d4a 100644
--- a/drivers/hid/hid-picolcd.c
+++ b/drivers/hid/hid-picolcd.c
@@ -177,6 +177,7 @@ struct picolcd_data {
177 int addr_sz; 177 int addr_sz;
178#endif 178#endif
179 u8 version[2]; 179 u8 version[2];
180 unsigned short opmode_delay;
180 /* input stuff */ 181 /* input stuff */
181 u8 pressed_keys[2]; 182 u8 pressed_keys[2];
182 struct input_dev *input_keys; 183 struct input_dev *input_keys;
@@ -1270,8 +1271,7 @@ static ssize_t picolcd_operation_mode_store(struct device *dev,
1270 struct picolcd_data *data = dev_get_drvdata(dev); 1271 struct picolcd_data *data = dev_get_drvdata(dev);
1271 struct hid_report *report = NULL; 1272 struct hid_report *report = NULL;
1272 size_t cnt = count; 1273 size_t cnt = count;
1273 int timeout = 5000; 1274 int timeout = data->opmode_delay;
1274 unsigned u;
1275 unsigned long flags; 1275 unsigned long flags;
1276 1276
1277 if (cnt >= 3 && strncmp("lcd", buf, 3) == 0) { 1277 if (cnt >= 3 && strncmp("lcd", buf, 3) == 0) {
@@ -1288,20 +1288,10 @@ static ssize_t picolcd_operation_mode_store(struct device *dev,
1288 if (!report) 1288 if (!report)
1289 return -EINVAL; 1289 return -EINVAL;
1290 1290
1291 while (cnt > 0 && (*buf == ' ' || *buf == '\t')) {
1292 buf++;
1293 cnt--;
1294 }
1295 while (cnt > 0 && (buf[cnt-1] == '\n' || buf[cnt-1] == '\r')) 1291 while (cnt > 0 && (buf[cnt-1] == '\n' || buf[cnt-1] == '\r'))
1296 cnt--; 1292 cnt--;
1297 if (cnt > 0) { 1293 if (cnt != 0)
1298 if (sscanf(buf, "%u", &u) != 1) 1294 return -EINVAL;
1299 return -EINVAL;
1300 if (u > 30000)
1301 return -EINVAL;
1302 else
1303 timeout = u;
1304 }
1305 1295
1306 spin_lock_irqsave(&data->lock, flags); 1296 spin_lock_irqsave(&data->lock, flags);
1307 hid_set_field(report->field[0], 0, timeout & 0xff); 1297 hid_set_field(report->field[0], 0, timeout & 0xff);
@@ -1314,6 +1304,34 @@ static ssize_t picolcd_operation_mode_store(struct device *dev,
1314static DEVICE_ATTR(operation_mode, 0644, picolcd_operation_mode_show, 1304static DEVICE_ATTR(operation_mode, 0644, picolcd_operation_mode_show,
1315 picolcd_operation_mode_store); 1305 picolcd_operation_mode_store);
1316 1306
1307/*
1308 * The "operation_mode_delay" sysfs attribute
1309 */
1310static ssize_t picolcd_operation_mode_delay_show(struct device *dev,
1311 struct device_attribute *attr, char *buf)
1312{
1313 struct picolcd_data *data = dev_get_drvdata(dev);
1314
1315 return snprintf(buf, PAGE_SIZE, "%hu\n", data->opmode_delay);
1316}
1317
1318static ssize_t picolcd_operation_mode_delay_store(struct device *dev,
1319 struct device_attribute *attr, const char *buf, size_t count)
1320{
1321 struct picolcd_data *data = dev_get_drvdata(dev);
1322 unsigned u;
1323 if (sscanf(buf, "%u", &u) != 1)
1324 return -EINVAL;
1325 if (u > 30000)
1326 return -EINVAL;
1327 else
1328 data->opmode_delay = u;
1329 return count;
1330}
1331
1332static DEVICE_ATTR(operation_mode_delay, 0644, picolcd_operation_mode_delay_show,
1333 picolcd_operation_mode_delay_store);
1334
1317 1335
1318#ifdef CONFIG_DEBUG_FS 1336#ifdef CONFIG_DEBUG_FS
1319/* 1337/*
@@ -2409,6 +2427,7 @@ static int picolcd_probe(struct hid_device *hdev,
2409 spin_lock_init(&data->lock); 2427 spin_lock_init(&data->lock);
2410 mutex_init(&data->mutex); 2428 mutex_init(&data->mutex);
2411 data->hdev = hdev; 2429 data->hdev = hdev;
2430 data->opmode_delay = 5000;
2412 if (hdev->product == USB_DEVICE_ID_PICOLCD_BOOTLOADER) 2431 if (hdev->product == USB_DEVICE_ID_PICOLCD_BOOTLOADER)
2413 data->status |= PICOLCD_BOOTLOADER; 2432 data->status |= PICOLCD_BOOTLOADER;
2414 hid_set_drvdata(hdev, data); 2433 hid_set_drvdata(hdev, data);
@@ -2436,24 +2455,32 @@ static int picolcd_probe(struct hid_device *hdev,
2436 goto err_cleanup_hid_hw; 2455 goto err_cleanup_hid_hw;
2437 } 2456 }
2438 2457
2439 error = device_create_file(&hdev->dev, &dev_attr_operation_mode); 2458 error = device_create_file(&hdev->dev, &dev_attr_operation_mode_delay);
2440 if (error) { 2459 if (error) {
2441 dev_err(&hdev->dev, "failed to create sysfs attributes\n"); 2460 dev_err(&hdev->dev, "failed to create sysfs attributes\n");
2442 goto err_cleanup_hid_ll; 2461 goto err_cleanup_hid_ll;
2443 } 2462 }
2444 2463
2464 error = device_create_file(&hdev->dev, &dev_attr_operation_mode);
2465 if (error) {
2466 dev_err(&hdev->dev, "failed to create sysfs attributes\n");
2467 goto err_cleanup_sysfs1;
2468 }
2469
2445 if (data->status & PICOLCD_BOOTLOADER) 2470 if (data->status & PICOLCD_BOOTLOADER)
2446 error = picolcd_probe_bootloader(hdev, data); 2471 error = picolcd_probe_bootloader(hdev, data);
2447 else 2472 else
2448 error = picolcd_probe_lcd(hdev, data); 2473 error = picolcd_probe_lcd(hdev, data);
2449 if (error) 2474 if (error)
2450 goto err_cleanup_sysfs; 2475 goto err_cleanup_sysfs2;
2451 2476
2452 dbg_hid(PICOLCD_NAME " activated and initialized\n"); 2477 dbg_hid(PICOLCD_NAME " activated and initialized\n");
2453 return 0; 2478 return 0;
2454 2479
2455err_cleanup_sysfs: 2480err_cleanup_sysfs2:
2456 device_remove_file(&hdev->dev, &dev_attr_operation_mode); 2481 device_remove_file(&hdev->dev, &dev_attr_operation_mode);
2482err_cleanup_sysfs1:
2483 device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay);
2457err_cleanup_hid_ll: 2484err_cleanup_hid_ll:
2458 hdev->ll_driver->close(hdev); 2485 hdev->ll_driver->close(hdev);
2459err_cleanup_hid_hw: 2486err_cleanup_hid_hw:
@@ -2478,6 +2505,7 @@ static void picolcd_remove(struct hid_device *hdev)
2478 2505
2479 picolcd_exit_devfs(data); 2506 picolcd_exit_devfs(data);
2480 device_remove_file(&hdev->dev, &dev_attr_operation_mode); 2507 device_remove_file(&hdev->dev, &dev_attr_operation_mode);
2508 device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay);
2481 hdev->ll_driver->close(hdev); 2509 hdev->ll_driver->close(hdev);
2482 hid_hw_stop(hdev); 2510 hid_hw_stop(hdev);
2483 hid_set_drvdata(hdev, NULL); 2511 hid_set_drvdata(hdev, NULL);