drivers/usb/serial/mxuport.c

Source file repositories/reference/linux-study-clean/drivers/usb/serial/mxuport.c

File Facts

System
Linux kernel
Corpus path
drivers/usb/serial/mxuport.c
Extension
.c
Size
33469 bytes
Lines
1327
Domain
Driver Families
Bucket
drivers/usb
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.

Dependency Surface

Detected Declarations

Annotated Snippet

struct mxuport_port {
	u8 mcr_state;		/* Last MCR state */
	u8 msr_state;		/* Last MSR state */
	struct mutex mutex;	/* Protects mcr_state */
	spinlock_t spinlock;	/* Protects msr_state */
};

/* Table of devices that work with this driver */
static const struct usb_device_id mxuport_idtable[] = {
	{ USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT1250_PID),
	  .driver_info = MX_UPORT_2_PORT },
	{ USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT1251_PID),
	  .driver_info = MX_UPORT_2_PORT },
	{ USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT1410_PID),
	  .driver_info = MX_UPORT_4_PORT },
	{ USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT1450_PID),
	  .driver_info = MX_UPORT_4_PORT },
	{ USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT1451_PID),
	  .driver_info = MX_UPORT_4_PORT },
	{ USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT1618_PID),
	  .driver_info = MX_UPORT_8_PORT },
	{ USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT1658_PID),
	  .driver_info = MX_UPORT_8_PORT },
	{ USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT1613_PID),
	  .driver_info = MX_UPORT_16_PORT },
	{ USB_DEVICE(MX_USBSERIAL_VID, MX_UPORT1653_PID),
	  .driver_info = MX_UPORT_16_PORT },
	{}			/* Terminating entry */
};

MODULE_DEVICE_TABLE(usb, mxuport_idtable);

/*
 * Add a four byte header containing the port number and the number of
 * bytes of data in the message. Return the number of bytes in the
 * buffer.
 */
static int mxuport_prepare_write_buffer(struct usb_serial_port *port,
					void *dest, size_t size)
{
	u8 *buf = dest;
	int count;

	count = kfifo_out_locked(&port->write_fifo, buf + HEADER_SIZE,
				 size - HEADER_SIZE,
				 &port->lock);

	put_unaligned_be16(port->port_number, buf);
	put_unaligned_be16(count, buf + 2);

	dev_dbg(&port->dev, "%s - size %zd count %d\n", __func__,
		size, count);

	return count + HEADER_SIZE;
}

/* Read the given buffer in from the control pipe. */
static int mxuport_recv_ctrl_urb(struct usb_serial *serial,
				 u8 request, u16 value, u16 index,
				 u8 *data, size_t size)
{
	int status;

	status = usb_control_msg(serial->dev,
				 usb_rcvctrlpipe(serial->dev, 0),
				 request,
				 (USB_DIR_IN | USB_TYPE_VENDOR |
				  USB_RECIP_DEVICE), value, index,
				 data, size,
				 USB_CTRL_GET_TIMEOUT);
	if (status < 0) {
		dev_err(&serial->interface->dev,
			"%s - usb_control_msg failed (%d)\n",
			__func__, status);
		return status;
	}

	if (status != size) {
		dev_err(&serial->interface->dev,
			"%s - short read (%d / %zd)\n",
			__func__, status, size);
		return -EIO;
	}

	return status;
}

/* Write the given buffer out to the control pipe.  */
static int mxuport_send_ctrl_data_urb(struct usb_serial *serial,
				      u8 request,

Annotation

Implementation Notes