Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0b5adf92 authored by Bruno Prémont's avatar Bruno Prémont Committed by Jiri Kosina
Browse files

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: default avatarBruno Prémont <bonbons@linux-vserver.org>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent 76d17e6c
Loading
Loading
Loading
Loading
+13 −4
Original line number Diff line number Diff line
@@ -8,12 +8,21 @@ Description: Make it possible to switch the PicoLCD device between LCD
		enclosed in brackets ('[' and ']')

		Writing: causes operation mode switch. Permitted values are
		the non-active mode names listed when read, optionally followed
		by a delay value expressed in ms.
		the non-active mode names listed when read.

		Note: when switching mode the current PicoLCD HID device gets
		disconnected and reconnects after above delay (default value
		is 5 seconds though this default should not be relied on).
		disconnected and reconnects after above delay (see attribute
		operation_mode_delay for its value).


What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/operation_mode_delay
Date:		April 2010
Contact:	Bruno Prémont <bonbons@linux-vserver.org>
Description:	Delay PicoLCD waits before restarting in new mode when
		operation_mode has changed.

		Reading/Writing: It is expressed in ms and permitted range is
		0..30000ms.


What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/fb_update_rate
+45 −17
Original line number Diff line number Diff line
@@ -177,6 +177,7 @@ struct picolcd_data {
	int addr_sz;
#endif
	u8 version[2];
	unsigned short opmode_delay;
	/* input stuff */
	u8 pressed_keys[2];
	struct input_dev *input_keys;
@@ -1270,8 +1271,7 @@ static ssize_t picolcd_operation_mode_store(struct device *dev,
	struct picolcd_data *data = dev_get_drvdata(dev);
	struct hid_report *report = NULL;
	size_t cnt = count;
	int timeout = 5000;
	unsigned u;
	int timeout = data->opmode_delay;
	unsigned long flags;

	if (cnt >= 3 && strncmp("lcd", buf, 3) == 0) {
@@ -1288,20 +1288,10 @@ static ssize_t picolcd_operation_mode_store(struct device *dev,
	if (!report)
		return -EINVAL;

	while (cnt > 0 && (*buf == ' ' || *buf == '\t')) {
		buf++;
		cnt--;
	}
	while (cnt > 0 && (buf[cnt-1] == '\n' || buf[cnt-1] == '\r'))
		cnt--;
	if (cnt > 0) {
		if (sscanf(buf, "%u", &u) != 1)
	if (cnt != 0)
		return -EINVAL;
		if (u > 30000)
			return -EINVAL;
		else
			timeout = u;
	}

	spin_lock_irqsave(&data->lock, flags);
	hid_set_field(report->field[0], 0, timeout & 0xff);
@@ -1314,6 +1304,34 @@ static ssize_t picolcd_operation_mode_store(struct device *dev,
static DEVICE_ATTR(operation_mode, 0644, picolcd_operation_mode_show,
		picolcd_operation_mode_store);

/*
 * The "operation_mode_delay" sysfs attribute
 */
static ssize_t picolcd_operation_mode_delay_show(struct device *dev,
		struct device_attribute *attr, char *buf)
{
	struct picolcd_data *data = dev_get_drvdata(dev);

	return snprintf(buf, PAGE_SIZE, "%hu\n", data->opmode_delay);
}

static ssize_t picolcd_operation_mode_delay_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t count)
{
	struct picolcd_data *data = dev_get_drvdata(dev);
	unsigned u;
	if (sscanf(buf, "%u", &u) != 1)
		return -EINVAL;
	if (u > 30000)
		return -EINVAL;
	else
		data->opmode_delay = u;
	return count;
}

static DEVICE_ATTR(operation_mode_delay, 0644, picolcd_operation_mode_delay_show,
		picolcd_operation_mode_delay_store);


#ifdef CONFIG_DEBUG_FS
/*
@@ -2409,6 +2427,7 @@ static int picolcd_probe(struct hid_device *hdev,
	spin_lock_init(&data->lock);
	mutex_init(&data->mutex);
	data->hdev = hdev;
	data->opmode_delay = 5000;
	if (hdev->product == USB_DEVICE_ID_PICOLCD_BOOTLOADER)
		data->status |= PICOLCD_BOOTLOADER;
	hid_set_drvdata(hdev, data);
@@ -2436,24 +2455,32 @@ static int picolcd_probe(struct hid_device *hdev,
		goto err_cleanup_hid_hw;
	}

	error = device_create_file(&hdev->dev, &dev_attr_operation_mode);
	error = device_create_file(&hdev->dev, &dev_attr_operation_mode_delay);
	if (error) {
		dev_err(&hdev->dev, "failed to create sysfs attributes\n");
		goto err_cleanup_hid_ll;
	}

	error = device_create_file(&hdev->dev, &dev_attr_operation_mode);
	if (error) {
		dev_err(&hdev->dev, "failed to create sysfs attributes\n");
		goto err_cleanup_sysfs1;
	}

	if (data->status & PICOLCD_BOOTLOADER)
		error = picolcd_probe_bootloader(hdev, data);
	else
		error = picolcd_probe_lcd(hdev, data);
	if (error)
		goto err_cleanup_sysfs;
		goto err_cleanup_sysfs2;

	dbg_hid(PICOLCD_NAME " activated and initialized\n");
	return 0;

err_cleanup_sysfs:
err_cleanup_sysfs2:
	device_remove_file(&hdev->dev, &dev_attr_operation_mode);
err_cleanup_sysfs1:
	device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay);
err_cleanup_hid_ll:
	hdev->ll_driver->close(hdev);
err_cleanup_hid_hw:
@@ -2478,6 +2505,7 @@ static void picolcd_remove(struct hid_device *hdev)

	picolcd_exit_devfs(data);
	device_remove_file(&hdev->dev, &dev_attr_operation_mode);
	device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay);
	hdev->ll_driver->close(hdev);
	hid_hw_stop(hdev);
	hid_set_drvdata(hdev, NULL);