drivers/comedi/drivers/ni_usb6501.c

Source file repositories/reference/linux-study-clean/drivers/comedi/drivers/ni_usb6501.c

File Facts

System
Linux kernel
Corpus path
drivers/comedi/drivers/ni_usb6501.c
Extension
.c
Size
14593 bytes
Lines
597
Domain
Driver Families
Bucket
drivers/comedi
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 ni6501_private {
	struct usb_endpoint_descriptor *ep_rx;
	struct usb_endpoint_descriptor *ep_tx;
	struct mutex mut;
	u8 *usb_rx_buf;
	u8 *usb_tx_buf;
};

static int ni6501_port_command(struct comedi_device *dev, int command,
			       unsigned int val, u8 *bitmap)
{
	struct usb_device *usb = comedi_to_usb_dev(dev);
	struct ni6501_private *devpriv = dev->private;
	int request_size, response_size;
	u8 *tx = devpriv->usb_tx_buf;
	int ret;

	if (command != SET_PORT_DIR && !bitmap)
		return -EINVAL;

	mutex_lock(&devpriv->mut);

	switch (command) {
	case READ_PORT:
		request_size = sizeof(READ_PORT_REQUEST);
		response_size = sizeof(READ_PORT_RESPONSE);
		memcpy(tx, READ_PORT_REQUEST, request_size);
		tx[14] = val & 0xff;
		break;
	case WRITE_PORT:
		request_size = sizeof(WRITE_PORT_REQUEST);
		response_size = sizeof(GENERIC_RESPONSE);
		memcpy(tx, WRITE_PORT_REQUEST, request_size);
		tx[14] = val & 0xff;
		tx[17] = *bitmap;
		break;
	case SET_PORT_DIR:
		request_size = sizeof(SET_PORT_DIR_REQUEST);
		response_size = sizeof(GENERIC_RESPONSE);
		memcpy(tx, SET_PORT_DIR_REQUEST, request_size);
		tx[14] = val & 0xff;
		tx[15] = (val >> 8) & 0xff;
		tx[16] = (val >> 16) & 0xff;
		break;
	default:
		ret = -EINVAL;
		goto end;
	}

	ret = usb_bulk_msg(usb,
			   usb_sndbulkpipe(usb,
					   devpriv->ep_tx->bEndpointAddress),
			   devpriv->usb_tx_buf,
			   request_size,
			   NULL,
			   NI6501_TIMEOUT);
	if (ret)
		goto end;

	ret = usb_bulk_msg(usb,
			   usb_rcvbulkpipe(usb,
					   devpriv->ep_rx->bEndpointAddress),
			   devpriv->usb_rx_buf,
			   response_size,
			   NULL,
			   NI6501_TIMEOUT);
	if (ret)
		goto end;

	/* Check if results are valid */

	if (command == READ_PORT) {
		*bitmap = devpriv->usb_rx_buf[14];
		/* mask bitmap for comparing */
		devpriv->usb_rx_buf[14] = 0x00;

		if (memcmp(devpriv->usb_rx_buf, READ_PORT_RESPONSE,
			   sizeof(READ_PORT_RESPONSE))) {
			ret = -EINVAL;
		}
	} else if (memcmp(devpriv->usb_rx_buf, GENERIC_RESPONSE,
			  sizeof(GENERIC_RESPONSE))) {
		ret = -EINVAL;
	}
end:
	mutex_unlock(&devpriv->mut);

	return ret;
}

Annotation

Implementation Notes