drivers/usb/serial/kobil_sct.c

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

File Facts

System
Linux kernel
Corpus path
drivers/usb/serial/kobil_sct.c
Extension
.c
Size
14837 bytes
Lines
514
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 kobil_private {
	unsigned char buf[KOBIL_BUF_LENGTH]; /* buffer for the APDU to send */
	int filled;  /* index of the last char in buf */
	int cur_pos; /* index of the next char to send in buf */
	__u16 device_type;
};

static int kobil_ctrl_send(struct usb_serial_port *port, u8 req, u16 val)
{
	return usb_control_msg(port->serial->dev,
			usb_sndctrlpipe(port->serial->dev, 0),
			req, USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
			val, 0, NULL, 0, KOBIL_TIMEOUT);
}

static int kobil_ctrl_recv(struct usb_serial_port *port, u8 req, u16 val, void *buf, u16 size)
{
	return usb_control_msg(port->serial->dev,
			usb_rcvctrlpipe(port->serial->dev, 0),
			req, USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_IN,
			val, 0, buf, size, KOBIL_TIMEOUT);
}

static int kobil_port_probe(struct usb_serial_port *port)
{
	struct usb_serial *serial = port->serial;
	struct kobil_private *priv;

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

	priv->filled = 0;
	priv->cur_pos = 0;
	priv->device_type = le16_to_cpu(serial->dev->descriptor.idProduct);

	switch (priv->device_type) {
	case KOBIL_ADAPTER_B_PRODUCT_ID:
		dev_dbg(&serial->dev->dev, "KOBIL B1 PRO / KAAN PRO detected\n");
		break;
	case KOBIL_ADAPTER_K_PRODUCT_ID:
		dev_dbg(&serial->dev->dev, "KOBIL KAAN Standard Plus / SecOVID Reader Plus detected\n");
		break;
	case KOBIL_USBTWIN_PRODUCT_ID:
		dev_dbg(&serial->dev->dev, "KOBIL USBTWIN detected\n");
		break;
	case KOBIL_KAAN_SIM_PRODUCT_ID:
		dev_dbg(&serial->dev->dev, "KOBIL KAAN SIM detected\n");
		break;
	}
	usb_set_serial_port_data(port, priv);

	return 0;
}


static void kobil_port_remove(struct usb_serial_port *port)
{
	struct kobil_private *priv;

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

static void kobil_init_termios(struct tty_struct *tty)
{
	/* Default to echo off and other sane device settings */
	tty->termios.c_lflag = 0;
	tty->termios.c_iflag = IGNBRK | IGNPAR | IXOFF;
	/* do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D) */
	tty->termios.c_oflag &= ~ONLCR;
}

static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port)
{
	struct device *dev = &port->dev;
	struct kobil_private *priv;
	unsigned char *transfer_buffer;
	int transfer_buffer_length = 8;
	int result;

	priv = usb_get_serial_port_data(port);

	/* allocate memory for transfer buffer */
	transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL);
	if (!transfer_buffer)
		return -ENOMEM;

	/* get hardware version */
	result = kobil_ctrl_recv(port, SUSBCRequest_GetMisc, SUSBCR_MSC_GetHWVersion,

Annotation

Implementation Notes