drivers/input/joystick/spaceorb.c
Source file repositories/reference/linux-study-clean/drivers/input/joystick/spaceorb.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/input/joystick/spaceorb.c- Extension
.c- Size
- 5566 bytes
- Lines
- 221
- 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/slab.hlinux/module.hlinux/input.hlinux/serio.h
Detected Declarations
struct spaceorbfunction spaceorb_process_packetfunction spaceorb_interruptfunction spaceorb_disconnectfunction spaceorb_connect
Annotated Snippet
struct spaceorb {
struct input_dev *dev;
int idx;
unsigned char data[SPACEORB_MAX_LENGTH];
char phys[32];
};
static unsigned char spaceorb_xor[] = "SpaceWare";
static unsigned char *spaceorb_errors[] = { "EEPROM storing 0 failed", "Receive queue overflow", "Transmit queue timeout",
"Bad packet", "Power brown-out", "EEPROM checksum error", "Hardware fault" };
/*
* spaceorb_process_packet() decodes packets the driver receives from the
* SpaceOrb.
*/
static void spaceorb_process_packet(struct spaceorb *spaceorb)
{
struct input_dev *dev = spaceorb->dev;
unsigned char *data = spaceorb->data;
unsigned char c = 0;
int axes[6];
int i;
if (spaceorb->idx < 2) return;
for (i = 0; i < spaceorb->idx; i++) c ^= data[i];
if (c) return;
switch (data[0]) {
case 'R': /* Reset packet */
spaceorb->data[spaceorb->idx - 1] = 0;
for (i = 1; i < spaceorb->idx && spaceorb->data[i] == ' '; i++);
printk(KERN_INFO "input: %s [%s] is %s\n",
dev->name, spaceorb->data + i, spaceorb->phys);
break;
case 'D': /* Ball + button data */
if (spaceorb->idx != 12) return;
for (i = 0; i < 9; i++) spaceorb->data[i+2] ^= spaceorb_xor[i];
axes[0] = ( data[2] << 3) | (data[ 3] >> 4);
axes[1] = ((data[3] & 0x0f) << 6) | (data[ 4] >> 1);
axes[2] = ((data[4] & 0x01) << 9) | (data[ 5] << 2) | (data[4] >> 5);
axes[3] = ((data[6] & 0x1f) << 5) | (data[ 7] >> 2);
axes[4] = ((data[7] & 0x03) << 8) | (data[ 8] << 1) | (data[7] >> 6);
axes[5] = ((data[9] & 0x3f) << 4) | (data[10] >> 3);
for (i = 0; i < 6; i++)
input_report_abs(dev, spaceorb_axes[i], axes[i] - ((axes[i] & 0x200) ? 1024 : 0));
for (i = 0; i < 6; i++)
input_report_key(dev, spaceorb_buttons[i], (data[1] >> i) & 1);
break;
case 'K': /* Button data */
if (spaceorb->idx != 5) return;
for (i = 0; i < 6; i++)
input_report_key(dev, spaceorb_buttons[i], (data[2] >> i) & 1);
break;
case 'E': /* Error packet */
if (spaceorb->idx != 4) return;
printk(KERN_ERR "spaceorb: Device error. [ ");
for (i = 0; i < 7; i++) if (data[1] & (1 << i)) printk("%s ", spaceorb_errors[i]);
printk("]\n");
break;
}
input_sync(dev);
}
static irqreturn_t spaceorb_interrupt(struct serio *serio,
unsigned char data, unsigned int flags)
{
struct spaceorb* spaceorb = serio_get_drvdata(serio);
if (~data & 0x80) {
if (spaceorb->idx) spaceorb_process_packet(spaceorb);
spaceorb->idx = 0;
}
if (spaceorb->idx < SPACEORB_MAX_LENGTH)
spaceorb->data[spaceorb->idx++] = data & 0x7f;
return IRQ_HANDLED;
}
/*
* spaceorb_disconnect() is the opposite of spaceorb_connect()
*/
static void spaceorb_disconnect(struct serio *serio)
Annotation
- Immediate include surface: `linux/kernel.h`, `linux/slab.h`, `linux/module.h`, `linux/input.h`, `linux/serio.h`.
- Detected declarations: `struct spaceorb`, `function spaceorb_process_packet`, `function spaceorb_interrupt`, `function spaceorb_disconnect`, `function spaceorb_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.