drivers/usb/serial/cyberjack.c

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

File Facts

System
Linux kernel
Corpus path
drivers/usb/serial/cyberjack.c
Extension
.c
Size
11715 bytes
Lines
423
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 cyberjack_private {
	spinlock_t	lock;		/* Lock for SMP */
	short		rdtodo;		/* Bytes still to read */
	unsigned char	wrbuf[5*64];	/* Buffer for collecting data to write */
	short		wrfilled;	/* Overall data size we already got */
	short		wrsent;		/* Data already sent */
};

static int cyberjack_port_probe(struct usb_serial_port *port)
{
	struct cyberjack_private *priv;
	int result;

	priv = kmalloc_obj(struct cyberjack_private);
	if (!priv)
		return -ENOMEM;

	spin_lock_init(&priv->lock);
	priv->rdtodo = 0;
	priv->wrfilled = 0;
	priv->wrsent = 0;

	usb_set_serial_port_data(port, priv);

	result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
	if (result)
		dev_err(&port->dev, "usb_submit_urb(read int) failed\n");

	return 0;
}

static void cyberjack_port_remove(struct usb_serial_port *port)
{
	struct cyberjack_private *priv;

	usb_kill_urb(port->interrupt_in_urb);

	priv = usb_get_serial_port_data(port);
	kfree(priv);
}

static int  cyberjack_open(struct tty_struct *tty,
					struct usb_serial_port *port)
{
	struct cyberjack_private *priv;
	unsigned long flags;

	dev_dbg(&port->dev, "%s - usb_clear_halt\n", __func__);
	usb_clear_halt(port->serial->dev, port->write_urb->pipe);

	priv = usb_get_serial_port_data(port);
	spin_lock_irqsave(&priv->lock, flags);
	priv->rdtodo = 0;
	priv->wrfilled = 0;
	priv->wrsent = 0;
	spin_unlock_irqrestore(&priv->lock, flags);

	return 0;
}

static void cyberjack_close(struct usb_serial_port *port)
{
	usb_kill_urb(port->write_urb);
	usb_kill_urb(port->read_urb);
}

static int cyberjack_write(struct tty_struct *tty,
	struct usb_serial_port *port, const unsigned char *buf, int count)
{
	struct device *dev = &port->dev;
	struct cyberjack_private *priv = usb_get_serial_port_data(port);
	unsigned long flags;
	int result;
	int wrexpected;

	if (count == 0) {
		dev_dbg(dev, "%s - write request of 0 bytes\n", __func__);
		return 0;
	}

	if (!test_and_clear_bit(0, &port->write_urbs_free)) {
		dev_dbg(dev, "%s - already writing\n", __func__);
		return 0;
	}

	spin_lock_irqsave(&priv->lock, flags);

	if (count+priv->wrfilled > sizeof(priv->wrbuf)) {
		/* To much data for buffer. Reset buffer. */
		priv->wrfilled = 0;

Annotation

Implementation Notes