drivers/accessibility/speakup/spk_ttyio.c
Source file repositories/reference/linux-study-clean/drivers/accessibility/speakup/spk_ttyio.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/accessibility/speakup/spk_ttyio.c- Extension
.c- Size
- 8970 bytes
- Lines
- 388
- Domain
- Driver Families
- Bucket
- drivers/accessibility
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration 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.
- 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.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/types.hlinux/tty.hlinux/tty_flip.hlinux/slab.hspeakup.hspk_types.hspk_priv.h
Detected Declarations
struct spk_ldisc_datafunction ser_to_devfunction get_dev_to_usefunction spk_ttyio_ldisc_openfunction spk_ttyio_ldisc_closefunction spk_ttyio_receive_buf2function get_termiosfunction spk_ttyio_initialise_ldiscfunction spk_ttyio_register_ldiscfunction spk_ttyio_unregister_ldiscfunction spk_ttyio_outfunction spk_ttyio_out_unicodefunction spk_ttyio_send_xcharfunction spk_ttyio_tiocmsetfunction spk_ttyio_wait_for_xmitrfunction ttyio_infunction usecs_to_jiffiesfunction spk_ttyio_infunction spk_ttyio_in_nowaitfunction spk_ttyio_flush_bufferfunction spk_ttyio_synth_probefunction spk_ttyio_releaseexport spk_ttyio_opsexport spk_ttyio_synth_probeexport spk_ttyio_releaseexport spk_ttyio_synth_immediate
Annotated Snippet
struct spk_ldisc_data {
char buf;
struct completion completion;
bool buf_free;
struct spk_synth *synth;
};
/*
* This allows to catch within spk_ttyio_ldisc_open whether it is getting set
* on for a speakup-driven device.
*/
static struct tty_struct *speakup_tty;
/* This mutex serializes the use of such global speakup_tty variable */
static DEFINE_MUTEX(speakup_tty_mutex);
static int ser_to_dev(int ser, dev_t *dev_no)
{
if (ser < 0 || ser > (255 - 64)) {
pr_err("speakup: Invalid ser param. Must be between 0 and 191 inclusive.\n");
return -EINVAL;
}
*dev_no = MKDEV(4, (64 + ser));
return 0;
}
static int get_dev_to_use(struct spk_synth *synth, dev_t *dev_no)
{
/* use ser only when dev is not specified */
if (strcmp(synth->dev_name, SYNTH_DEFAULT_DEV) ||
synth->ser == SYNTH_DEFAULT_SER)
return tty_dev_name_to_number(synth->dev_name, dev_no);
return ser_to_dev(synth->ser, dev_no);
}
static int spk_ttyio_ldisc_open(struct tty_struct *tty)
{
struct spk_ldisc_data *ldisc_data;
if (tty != speakup_tty)
/* Somebody tried to use this line discipline outside speakup */
return -ENODEV;
if (!tty->ops->write)
return -EOPNOTSUPP;
ldisc_data = kmalloc_obj(*ldisc_data);
if (!ldisc_data)
return -ENOMEM;
init_completion(&ldisc_data->completion);
ldisc_data->buf_free = true;
tty->disc_data = ldisc_data;
return 0;
}
static void spk_ttyio_ldisc_close(struct tty_struct *tty)
{
kfree(tty->disc_data);
}
static size_t spk_ttyio_receive_buf2(struct tty_struct *tty, const u8 *cp,
const u8 *fp, size_t count)
{
struct spk_ldisc_data *ldisc_data = tty->disc_data;
struct spk_synth *synth = ldisc_data->synth;
if (synth->read_buff_add) {
unsigned int i;
for (i = 0; i < count; i++)
synth->read_buff_add(cp[i]);
return count;
}
if (!ldisc_data->buf_free)
/* ttyio_in will tty_flip_buffer_push */
return 0;
/* Make sure the consumer has read buf before we have seen
* buf_free == true and overwrite buf
*/
mb();
ldisc_data->buf = cp[0];
ldisc_data->buf_free = false;
complete(&ldisc_data->completion);
Annotation
- Immediate include surface: `linux/types.h`, `linux/tty.h`, `linux/tty_flip.h`, `linux/slab.h`, `speakup.h`, `spk_types.h`, `spk_priv.h`.
- Detected declarations: `struct spk_ldisc_data`, `function ser_to_dev`, `function get_dev_to_use`, `function spk_ttyio_ldisc_open`, `function spk_ttyio_ldisc_close`, `function spk_ttyio_receive_buf2`, `function get_termios`, `function spk_ttyio_initialise_ldisc`, `function spk_ttyio_register_ldisc`, `function spk_ttyio_unregister_ldisc`.
- Atlas domain: Driver Families / drivers/accessibility.
- Implementation status: integration implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.