drivers/gpio/gpio-mpsse.c
Source file repositories/reference/linux-study-clean/drivers/gpio/gpio-mpsse.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/gpio/gpio-mpsse.c- Extension
.c- Size
- 18812 bytes
- Lines
- 730
- Domain
- Driver Families
- Bucket
- drivers/gpio
- 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.
- 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/cleanup.hlinux/gpio/driver.hlinux/mutex.hlinux/spinlock.hlinux/usb.h
Detected Declarations
struct mpsse_privstruct mpsse_workerstruct bulk_descstruct mpsse_quirkfunction mpsse_bulk_xferfunction mpsse_writefunction mpsse_readfunction gpio_mpsse_set_bankfunction gpio_mpsse_get_bankfunction mpsse_ensure_supportedfunction gpio_mpsse_set_multiplefunction gpio_mpsse_get_multiplefunction gpio_mpsse_gpio_getfunction gpio_mpsse_gpio_setfunction gpio_mpsse_direction_outputfunction gpio_mpsse_direction_inputfunction gpio_mpsse_get_directionfunction gpio_mpsse_stop_all_exceptfunction scoped_guardfunction list_for_each_entry_safefunction gpio_mpsse_pollfunction gpio_mpsse_set_irq_typefunction gpio_mpsse_irq_disablefunction gpio_mpsse_irq_enablefunction gpio_mpsse_ida_removefunction mpsse_init_valid_maskfunction mpsse_irq_init_valid_maskfunction gpio_mpsse_probefunction gpio_mpsse_disconnect
Annotated Snippet
struct mpsse_priv {
struct gpio_chip gpio;
struct usb_device *udev; /* USB device encompassing all MPSSEs */
struct usb_interface *intf; /* USB interface for this MPSSE */
u8 intf_id; /* USB interface number for this MPSSE */
struct list_head workers; /* polling work threads */
struct mutex irq_mutex; /* lock over irq_data */
struct mutex irq_race; /* race for polling worker teardown */
raw_spinlock_t irq_spin; /* protects worker list */
atomic_t irq_type[16]; /* pin -> edge detection type */
atomic_t irq_enabled;
int id;
u8 gpio_outputs[2]; /* Output states for GPIOs [L, H] */
u8 gpio_dir[2]; /* Directions for GPIOs [L, H] */
unsigned long dir_in; /* Bitmask of valid input pins */
unsigned long dir_out; /* Bitmask of valid output pins */
u8 *bulk_in_buf; /* Extra recv buffer to grab status bytes */
struct usb_endpoint_descriptor *bulk_in;
struct usb_endpoint_descriptor *bulk_out;
struct mutex io_mutex; /* sync I/O with disconnect */
};
struct mpsse_worker {
struct mpsse_priv *priv;
struct work_struct work;
atomic_t cancelled;
struct list_head list; /* linked list */
struct list_head destroy; /* teardown linked list */
};
struct bulk_desc {
bool tx; /* direction of bulk transfer */
u8 *data; /* input (tx) or output (rx) */
int len; /* Length of `data` if tx, or length of */
/* Data to read if rx */
int len_actual; /* Length successfully transferred */
int timeout;
};
#define MPSSE_NGPIO 16
struct mpsse_quirk {
const char *names[MPSSE_NGPIO]; /* Pin names, if applicable */
unsigned long dir_in; /* Bitmask of valid input pins */
unsigned long dir_out; /* Bitmask of valid output pins */
};
static struct mpsse_quirk bryx_brik_quirk = {
.names = {
[3] = "Push to Talk",
[5] = "Channel Activity",
},
.dir_out = BIT(3), /* Push to Talk */
.dir_in = BIT(5), /* Channel Activity */
};
static const struct usb_device_id gpio_mpsse_table[] = {
{ USB_DEVICE(0x0c52, 0xa064) }, /* SeaLevel Systems, Inc. */
{ USB_DEVICE(0x0403, 0x6988), /* FTDI, assigned to Bryx */
.driver_info = (kernel_ulong_t)&bryx_brik_quirk},
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, gpio_mpsse_table);
static DEFINE_IDA(gpio_mpsse_ida);
/* MPSSE commands */
#define SET_BITS_CMD 0x80
#define GET_BITS_CMD 0x81
#define SET_BITMODE_REQUEST 0x0B
#define MODE_MPSSE (2 << 8)
#define MODE_RESET 0
/* Arbitrarily decided. This could probably be much less */
#define MPSSE_WRITE_TIMEOUT 5000
#define MPSSE_READ_TIMEOUT 5000
/* 1 millisecond, also pretty arbitrary */
#define MPSSE_POLL_INTERVAL 1000
static int mpsse_bulk_xfer(struct usb_interface *intf, struct bulk_desc *desc)
{
struct mpsse_priv *priv = usb_get_intfdata(intf);
Annotation
- Immediate include surface: `linux/cleanup.h`, `linux/gpio/driver.h`, `linux/mutex.h`, `linux/spinlock.h`, `linux/usb.h`.
- Detected declarations: `struct mpsse_priv`, `struct mpsse_worker`, `struct bulk_desc`, `struct mpsse_quirk`, `function mpsse_bulk_xfer`, `function mpsse_write`, `function mpsse_read`, `function gpio_mpsse_set_bank`, `function gpio_mpsse_get_bank`, `function mpsse_ensure_supported`.
- Atlas domain: Driver Families / drivers/gpio.
- Implementation status: source 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.