diff options
author | Bruno Prémont <bonbons@linux-vserver.org> | 2010-04-25 15:29:16 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2010-04-27 09:31:26 -0400 |
commit | 0b5adf92ec793c665b0de63ac146d190a921c391 (patch) | |
tree | b2476d2a25ec313128f966e24236fd0af1acd5a0 | |
parent | 76d17e6ca30204532c631d092de41febb3f76b77 (diff) |
HID: split picolcd's operation_mode sysfs attribute
Original operation_mode sysfs attribute accepts the operation mode
as main value with an option delay as second value to change
the start-up delay on mode change.
As it is preferred to have exactly one value per sysfs attribute,
extract this delay into a separate sysfs attribute called
operation_mode_delay.
Signed-off-by: Bruno Prémont <bonbons@linux-vserver.org>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r-- | Documentation/ABI/testing/sysfs-driver-hid-picolcd | 17 | ||||
-rw-r--r-- | drivers/hid/hid-picolcd.c | 62 |
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 14f52d70621b..08579e7e1e89 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 | |||
18 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/operation_mode_delay | ||
19 | Date: April 2010 | ||
20 | Contact: Bruno Prémont <bonbons@linux-vserver.org> | ||
21 | Description: 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 | ||
19 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/fb_update_rate | 28 | What: /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 6f71c60bf653..aa6f2e18d4a6 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, | |||
1314 | static DEVICE_ATTR(operation_mode, 0644, picolcd_operation_mode_show, | 1304 | static 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 | */ | ||
1310 | static 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 | |||
1318 | static 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 | |||
1332 | static 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 | ||
2455 | err_cleanup_sysfs: | 2480 | err_cleanup_sysfs2: |
2456 | device_remove_file(&hdev->dev, &dev_attr_operation_mode); | 2481 | device_remove_file(&hdev->dev, &dev_attr_operation_mode); |
2482 | err_cleanup_sysfs1: | ||
2483 | device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay); | ||
2457 | err_cleanup_hid_ll: | 2484 | err_cleanup_hid_ll: |
2458 | hdev->ll_driver->close(hdev); | 2485 | hdev->ll_driver->close(hdev); |
2459 | err_cleanup_hid_hw: | 2486 | err_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); |