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); |
