drivers/spi/spi-ch341.c
Source file repositories/reference/linux-study-clean/drivers/spi/spi-ch341.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/spi/spi-ch341.c- Extension
.c- Size
- 6369 bytes
- Lines
- 255
- Domain
- Driver Families
- Bucket
- drivers/spi
- 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.
- 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/module.hlinux/usb.hlinux/spi/spi.h
Detected Declarations
struct ch341_spi_devfunction ch341_set_csfunction ch341_transfer_onefunction ch341_recvfunction ch341_config_streamfunction ch341_enable_pinsfunction ch341_probefunction ch341_disconnect
Annotated Snippet
struct ch341_spi_dev {
struct spi_controller *ctrl;
struct usb_device *udev;
unsigned int write_pipe;
unsigned int read_pipe;
int rx_len;
void *rx_buf;
u8 *tx_buf;
struct urb *rx_urb;
struct spi_device *spidev;
};
static void ch341_set_cs(struct spi_device *spi, bool is_high)
{
struct ch341_spi_dev *ch341 =
spi_controller_get_devdata(spi->controller);
int err;
memset(ch341->tx_buf, 0, CH341_PACKET_LENGTH);
ch341->tx_buf[0] = CH341A_CMD_UIO_STREAM;
ch341->tx_buf[1] = CH341A_CMD_UIO_STM_OUT | (is_high ? 0x36 : 0x37);
if (is_high) {
ch341->tx_buf[2] = CH341A_CMD_UIO_STM_DIR | 0x3f;
ch341->tx_buf[3] = CH341A_CMD_UIO_STM_END;
} else {
ch341->tx_buf[2] = CH341A_CMD_UIO_STM_END;
}
err = usb_bulk_msg(ch341->udev, ch341->write_pipe, ch341->tx_buf,
(is_high ? 4 : 3), NULL, CH341_DEFAULT_TIMEOUT);
if (err)
dev_err(&spi->dev,
"error sending USB message for setting CS (%d)\n", err);
}
static int ch341_transfer_one(struct spi_controller *host,
struct spi_device *spi,
struct spi_transfer *trans)
{
struct ch341_spi_dev *ch341 =
spi_controller_get_devdata(spi->controller);
int len;
int ret;
len = min(CH341_PACKET_LENGTH, trans->len + 1);
memset(ch341->tx_buf, 0, CH341_PACKET_LENGTH);
ch341->tx_buf[0] = CH341A_CMD_SPI_STREAM;
memcpy(ch341->tx_buf + 1, trans->tx_buf, len - 1);
ret = usb_bulk_msg(ch341->udev, ch341->write_pipe, ch341->tx_buf, len,
NULL, CH341_DEFAULT_TIMEOUT);
if (ret)
return ret;
return usb_bulk_msg(ch341->udev, ch341->read_pipe, trans->rx_buf,
len - 1, NULL, CH341_DEFAULT_TIMEOUT);
}
static void ch341_recv(struct urb *urb)
{
struct ch341_spi_dev *ch341 = urb->context;
struct usb_device *udev = ch341->udev;
switch (urb->status) {
case 0:
/* success */
break;
case -ENOENT:
case -ECONNRESET:
case -EPIPE:
case -ESHUTDOWN:
dev_dbg(&udev->dev, "rx urb terminated with status: %d\n",
urb->status);
return;
default:
dev_dbg(&udev->dev, "rx urb error: %d\n", urb->status);
break;
}
}
static int ch341_config_stream(struct ch341_spi_dev *ch341)
{
memset(ch341->tx_buf, 0, CH341_PACKET_LENGTH);
ch341->tx_buf[0] = CH341A_CMD_I2C_STREAM;
ch341->tx_buf[1] = CH341A_CMD_I2C_STM_SET | CH341A_STM_I2C_100K;
ch341->tx_buf[2] = CH341A_CMD_I2C_STM_END;
Annotation
- Immediate include surface: `linux/module.h`, `linux/usb.h`, `linux/spi/spi.h`.
- Detected declarations: `struct ch341_spi_dev`, `function ch341_set_cs`, `function ch341_transfer_one`, `function ch341_recv`, `function ch341_config_stream`, `function ch341_enable_pins`, `function ch341_probe`, `function ch341_disconnect`.
- Atlas domain: Driver Families / drivers/spi.
- Implementation status: source implementation candidate.
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.