drivers/leds/trigger/ledtrig-tty.c

Source file repositories/reference/linux-study-clean/drivers/leds/trigger/ledtrig-tty.c

File Facts

System
Linux kernel
Corpus path
drivers/leds/trigger/ledtrig-tty.c
Extension
.c
Size
8163 bytes
Lines
358
Domain
Driver Families
Bucket
drivers/leds
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct ledtrig_tty_data {
	struct led_classdev *led_cdev;
	struct delayed_work dwork;
	struct completion sysfs;
	const char *ttyname;
	struct tty_struct *tty;
	int rx, tx;
	bool mode_rx;
	bool mode_tx;
	bool mode_cts;
	bool mode_dsr;
	bool mode_dcd;
	bool mode_rng;
};

/* Indicates which state the LED should now display */
enum led_trigger_tty_state {
	TTY_LED_BLINK,
	TTY_LED_ENABLE,
	TTY_LED_DISABLE,
};

enum led_trigger_tty_modes {
	TRIGGER_TTY_RX = 0,
	TRIGGER_TTY_TX,
	TRIGGER_TTY_CTS,
	TRIGGER_TTY_DSR,
	TRIGGER_TTY_DCD,
	TRIGGER_TTY_RNG,
};

static int ledtrig_tty_wait_for_completion(struct device *dev)
{
	struct ledtrig_tty_data *trigger_data = led_trigger_get_drvdata(dev);
	int ret;

	ret = wait_for_completion_timeout(&trigger_data->sysfs,
					  msecs_to_jiffies(LEDTRIG_TTY_INTERVAL * 20));
	if (ret == 0)
		return -ETIMEDOUT;

	return ret;
}

static ssize_t ttyname_show(struct device *dev,
			    struct device_attribute *attr, char *buf)
{
	struct ledtrig_tty_data *trigger_data = led_trigger_get_drvdata(dev);
	ssize_t len = 0;
	int completion;

	reinit_completion(&trigger_data->sysfs);
	completion = ledtrig_tty_wait_for_completion(dev);
	if (completion < 0)
		return completion;

	if (trigger_data->ttyname)
		len = sprintf(buf, "%s\n", trigger_data->ttyname);

	return len;
}

static ssize_t ttyname_store(struct device *dev,
			     struct device_attribute *attr, const char *buf,
			     size_t size)
{
	struct ledtrig_tty_data *trigger_data = led_trigger_get_drvdata(dev);
	char *ttyname;
	ssize_t ret = size;
	int completion;

	if (size > 0 && buf[size - 1] == '\n')
		size -= 1;

	if (size) {
		ttyname = kmemdup_nul(buf, size, GFP_KERNEL);
		if (!ttyname)
			return -ENOMEM;
	} else {
		ttyname = NULL;
	}

	reinit_completion(&trigger_data->sysfs);
	completion = ledtrig_tty_wait_for_completion(dev);
	if (completion < 0)
		return completion;

	kfree(trigger_data->ttyname);
	tty_kref_put(trigger_data->tty);
	trigger_data->tty = NULL;

Annotation

Implementation Notes