drivers/accessibility/speakup/speakup_dtlk.c

Source file repositories/reference/linux-study-clean/drivers/accessibility/speakup/speakup_dtlk.c

File Facts

System
Linux kernel
Corpus path
drivers/accessibility/speakup/speakup_dtlk.c
Extension
.c
Size
12306 bytes
Lines
419
Domain
Driver Families
Bucket
drivers/accessibility
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

if (speakup_info.flushing) {
			speakup_info.flushing = 0;
			spin_unlock_irqrestore(&speakup_info.spinlock, flags);
			synth->flush(synth);
			continue;
		}
		synth_buffer_skip_nonlatin1();
		if (synth_buffer_empty()) {
			spin_unlock_irqrestore(&speakup_info.spinlock, flags);
			break;
		}
		set_current_state(TASK_INTERRUPTIBLE);
		delay_time_val = delay_time->u.n.value;
		spin_unlock_irqrestore(&speakup_info.spinlock, flags);
		if (synth_full()) {
			schedule_timeout(msecs_to_jiffies(delay_time_val));
			continue;
		}
		set_current_state(TASK_RUNNING);
		spin_lock_irqsave(&speakup_info.spinlock, flags);
		ch = synth_buffer_getc();
		spin_unlock_irqrestore(&speakup_info.spinlock, flags);
		if (ch == '\n')
			ch = PROCSPEECH;
		spk_out(ch);
		if (time_after_eq(jiffies, jiff_max) && (ch == SPACE)) {
			spk_out(PROCSPEECH);
			spin_lock_irqsave(&speakup_info.spinlock, flags);
			delay_time_val = delay_time->u.n.value;
			jiffy_delta_val = jiffy_delta->u.n.value;
			spin_unlock_irqrestore(&speakup_info.spinlock, flags);
			schedule_timeout(msecs_to_jiffies(delay_time_val));
			jiff_max = jiffies + jiffy_delta_val;
		}
	}
	spk_out(PROCSPEECH);
}

static const char *synth_immediate(struct spk_synth *synth, const char *buf)
{
	u_char ch;

	while ((ch = (u_char)*buf)) {
		if (synth_full())
			return buf;
		if (ch == '\n')
			ch = PROCSPEECH;
		spk_out(ch);
		buf++;
	}
	return NULL;
}

static void synth_flush(struct spk_synth *synth)
{
	outb_p(SYNTH_CLEAR, speakup_info.port_tts);
	while (synth_writable())
		cpu_relax();
}

static char synth_read_tts(void)
{
	u_char ch;

	while (!synth_readable())
		cpu_relax();
	ch = synth_status & 0x7f;
	outb_p(ch, speakup_info.port_tts);
	while (synth_readable())
		cpu_relax();
	return (char)ch;
}

/* interrogate the DoubleTalk PC and return its settings */
static struct synth_settings *synth_interrogate(struct spk_synth *synth)
{
	u_char *t;
	static char buf[sizeof(struct synth_settings) + 1];
	int total, i;
	static struct synth_settings status;

	synth_immediate(synth, "\x18\x01?");
	for (total = 0, i = 0; i < 50; i++) {
		buf[total] = synth_read_tts();
		if (total > 2 && buf[total] == 0x7f)
			break;
		if (total < sizeof(struct synth_settings))
			total++;
	}
	t = buf;

Annotation

Implementation Notes