drivers/input/joystick/magellan.c
Source file repositories/reference/linux-study-clean/drivers/input/joystick/magellan.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/input/joystick/magellan.c- Extension
.c- Size
- 4808 bytes
- Lines
- 206
- Domain
- Driver Families
- Bucket
- drivers/input
- 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.
- 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.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- 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/kernel.hlinux/module.hlinux/slab.hlinux/input.hlinux/serio.h
Detected Declarations
struct magellanfunction magellan_crunch_nibblesfunction magellan_process_packetfunction magellan_interruptfunction magellan_disconnectfunction magellan_connect
Annotated Snippet
struct magellan {
struct input_dev *dev;
int idx;
unsigned char data[MAGELLAN_MAX_LENGTH];
char phys[32];
};
/*
* magellan_crunch_nibbles() verifies that the bytes sent from the Magellan
* have correct upper nibbles for the lower ones, if not, the packet will
* be thrown away. It also strips these upper halves to simplify further
* processing.
*/
static int magellan_crunch_nibbles(unsigned char *data, int count)
{
static const unsigned char nibbles[16] __nonstring = "0AB3D56GH9:K<MN?";
do {
if (data[count] == nibbles[data[count] & 0xf])
data[count] = data[count] & 0xf;
else
return -1;
} while (--count);
return 0;
}
static void magellan_process_packet(struct magellan* magellan)
{
struct input_dev *dev = magellan->dev;
unsigned char *data = magellan->data;
int i, t;
if (!magellan->idx) return;
switch (magellan->data[0]) {
case 'd': /* Axis data */
if (magellan->idx != 25) return;
if (magellan_crunch_nibbles(data, 24)) return;
for (i = 0; i < 6; i++)
input_report_abs(dev, magellan_axes[i],
(data[(i << 2) + 1] << 12 | data[(i << 2) + 2] << 8 |
data[(i << 2) + 3] << 4 | data[(i << 2) + 4]) - 32768);
break;
case 'k': /* Button data */
if (magellan->idx != 4) return;
if (magellan_crunch_nibbles(data, 3)) return;
t = (data[1] << 1) | (data[2] << 5) | data[3];
for (i = 0; i < 9; i++) input_report_key(dev, magellan_buttons[i], (t >> i) & 1);
break;
}
input_sync(dev);
}
static irqreturn_t magellan_interrupt(struct serio *serio,
unsigned char data, unsigned int flags)
{
struct magellan* magellan = serio_get_drvdata(serio);
if (data == '\r') {
magellan_process_packet(magellan);
magellan->idx = 0;
} else {
if (magellan->idx < MAGELLAN_MAX_LENGTH)
magellan->data[magellan->idx++] = data;
}
return IRQ_HANDLED;
}
/*
* magellan_disconnect() is the opposite of magellan_connect()
*/
static void magellan_disconnect(struct serio *serio)
{
struct magellan* magellan = serio_get_drvdata(serio);
serio_close(serio);
serio_set_drvdata(serio, NULL);
input_unregister_device(magellan->dev);
kfree(magellan);
}
/*
* magellan_connect() is the routine that is called when someone adds a
* new serio device that supports Magellan protocol and registers it as
Annotation
- Immediate include surface: `linux/kernel.h`, `linux/module.h`, `linux/slab.h`, `linux/input.h`, `linux/serio.h`.
- Detected declarations: `struct magellan`, `function magellan_crunch_nibbles`, `function magellan_process_packet`, `function magellan_interrupt`, `function magellan_disconnect`, `function magellan_connect`.
- Atlas domain: Driver Families / drivers/input.
- Implementation status: source implementation candidate.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
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.