drivers/accessibility/speakup/speakup_decpc.c

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

File Facts

System
Linux kernel
Corpus path
drivers/accessibility/speakup/speakup_decpc.c
Extension
.c
Size
16049 bytes
Lines
524
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;
		}
		ch = synth_buffer_peek();
		set_current_state(TASK_INTERRUPTIBLE);
		delay_time_val = delay_time->u.n.value;
		spin_unlock_irqrestore(&speakup_info.spinlock, flags);
		if (ch == '\n')
			ch = 0x0D;
		if (dt_sendchar(ch)) {
			schedule_timeout(msecs_to_jiffies(delay_time_val));
			continue;
		}
		set_current_state(TASK_RUNNING);
		spin_lock_irqsave(&speakup_info.spinlock, flags);
		synth_buffer_getc();
		spin_unlock_irqrestore(&speakup_info.spinlock, flags);
		if (ch == '[') {
			in_escape = 1;
		} else if (ch == ']') {
			in_escape = 0;
		} else if (ch <= SPACE) {
			if (!in_escape && strchr(",.!?;:", last))
				dt_sendchar(PROCSPEECH);
			if (time_after_eq(jiffies, jiff_max)) {
				if (!in_escape)
					dt_sendchar(PROCSPEECH);
				spin_lock_irqsave(&speakup_info.spinlock,
						  flags);
				jiffy_delta_val = jiffy_delta->u.n.value;
				delay_time_val = delay_time->u.n.value;
				spin_unlock_irqrestore(&speakup_info.spinlock,
						       flags);
				schedule_timeout(msecs_to_jiffies
						 (delay_time_val));
				jiff_max = jiffies + jiffy_delta_val;
			}
		}
		last = ch;
		ch = 0;
	}
	if (!in_escape)
		dt_sendchar(PROCSPEECH);
}

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

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

static int synth_probe(struct spk_synth *synth)
{
	int i = 0, failed = 0;

	pr_info("Probing for %s.\n", synth->long_name);
	for (i = 0; synth_portlist[i]; i++) {
		if (synth_request_region(synth_portlist[i], SYNTH_IO_EXTENT)) {
			pr_warn("request_region: failed with 0x%x, %d\n",
				synth_portlist[i], SYNTH_IO_EXTENT);
			continue;
		}
		speakup_info.port_tts = synth_portlist[i];
		failed = testkernel();
		if (failed == 0)
			break;
	}
	if (failed) {
		pr_info("%s: not found\n", synth->long_name);
		return -ENODEV;
	}
	pr_info("%s: %03x-%03x, Driver Version %s,\n", synth->long_name,
		speakup_info.port_tts, speakup_info.port_tts + 7,
		synth->version);

Annotation

Implementation Notes