drivers/char/dtlk.c

Source file repositories/reference/linux-study-clean/drivers/char/dtlk.c

File Facts

System
Linux kernel
Corpus path
drivers/char/dtlk.c
Extension
.c
Size
16738 bytes
Lines
664
Domain
Driver Families
Bucket
drivers/char
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct file_operations dtlk_fops =
{
	.owner		= THIS_MODULE,
	.read		= dtlk_read,
	.write		= dtlk_write,
	.poll		= dtlk_poll,
	.unlocked_ioctl	= dtlk_ioctl,
	.open		= dtlk_open,
	.release	= dtlk_release,
};

/* local prototypes */
static int dtlk_dev_probe(void);
static struct dtlk_settings *dtlk_interrogate(void);
static int dtlk_readable(void);
static char dtlk_read_lpc(void);
static char dtlk_read_tts(void);
static int dtlk_writeable(void);
static char dtlk_write_bytes(const char *buf, int n);
static char dtlk_write_tts(char);
/*
   static void dtlk_handle_error(char, char, unsigned int);
 */

static ssize_t dtlk_read(struct file *file, char __user *buf,
			 size_t count, loff_t * ppos)
{
	unsigned int minor = iminor(file_inode(file));
	char ch;
	int i = 0, retries;

	TRACE_TEXT("(dtlk_read");
	/*  printk("DoubleTalk PC - dtlk_read()\n"); */

	if (minor != DTLK_MINOR || !dtlk_has_indexing)
		return -EINVAL;

	for (retries = 0; retries < loops_per_jiffy; retries++) {
		while (i < count && dtlk_readable()) {
			ch = dtlk_read_lpc();
			/*        printk("dtlk_read() reads 0x%02x\n", ch); */
			if (put_user(ch, buf++))
				return -EFAULT;
			i++;
		}
		if (i)
			return i;
		if (file->f_flags & O_NONBLOCK)
			break;
		msleep_interruptible(100);
	}
	if (retries == loops_per_jiffy)
		printk(KERN_ERR "dtlk_read times out\n");
	TRACE_RET;
	return -EAGAIN;
}

static ssize_t dtlk_write(struct file *file, const char __user *buf,
			  size_t count, loff_t * ppos)
{
	int i = 0, retries = 0, ch;

	TRACE_TEXT("(dtlk_write");
#ifdef TRACING
	printk(" \"");
	{
		int i, ch;
		for (i = 0; i < count; i++) {
			if (get_user(ch, buf + i))
				return -EFAULT;
			if (' ' <= ch && ch <= '~')
				printk("%c", ch);
			else
				printk("\\%03o", ch);
		}
		printk("\"");
	}
#endif

	if (iminor(file_inode(file)) != DTLK_MINOR)
		return -EINVAL;

	while (1) {
		while (i < count && !get_user(ch, buf) &&
		       (ch == DTLK_CLEAR || dtlk_writeable())) {
			dtlk_write_tts(ch);
			buf++;
			i++;
			if (i % 5 == 0)
				/* We yield our time until scheduled

Annotation

Implementation Notes