drivers/media/rc/igorplugusb.c

Source file repositories/reference/linux-study-clean/drivers/media/rc/igorplugusb.c

File Facts

System
Linux kernel
Corpus path
drivers/media/rc/igorplugusb.c
Extension
.c
Size
6723 bytes
Lines
277
Domain
Driver Families
Bucket
drivers/media
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 igorplugusb {
	struct rc_dev *rc;
	struct device *dev;

	struct urb *urb;
	struct usb_ctrlrequest *request;

	struct timer_list timer;

	u8 *buf_in;

	char phys[64];
};

static void igorplugusb_cmd(struct igorplugusb *ir, int cmd);

static void igorplugusb_irdata(struct igorplugusb *ir, unsigned len)
{
	struct ir_raw_event rawir = {};
	unsigned i, start, overflow;

	dev_dbg(ir->dev, "irdata: %*ph (len=%u)", len, ir->buf_in, len);

	/*
	 * If more than 36 pulses and spaces follow each other, the igorplugusb
	 * overwrites its buffer from the beginning. The overflow value is the
	 * last offset which was not overwritten. Everything from this offset
	 * onwards occurred before everything until this offset.
	 */
	overflow = ir->buf_in[2];
	i = start = overflow + HEADERLEN;

	if (start >= len) {
		dev_err(ir->dev, "receive overflow invalid: %u", overflow);
	} else {
		if (overflow > 0) {
			dev_warn(ir->dev, "receive overflow, at least %u lost",
								overflow);
			ir_raw_event_overflow(ir->rc);
		}

		do {
			rawir.duration = ir->buf_in[i] * 85;
			rawir.pulse = i & 1;

			ir_raw_event_store_with_filter(ir->rc, &rawir);

			if (++i == len)
				i = HEADERLEN;
		} while (i != start);

		/* add a trailing space */
		rawir.duration = ir->rc->timeout;
		rawir.pulse = false;
		ir_raw_event_store_with_filter(ir->rc, &rawir);

		ir_raw_event_handle(ir->rc);
	}

	igorplugusb_cmd(ir, SET_INFRABUFFER_EMPTY);
}

static void igorplugusb_callback(struct urb *urb)
{
	struct usb_ctrlrequest *req;
	struct igorplugusb *ir = urb->context;

	req = (struct usb_ctrlrequest *)urb->setup_packet;

	switch (urb->status) {
	case 0:
		if (req->bRequest == GET_INFRACODE &&
					urb->actual_length > HEADERLEN)
			igorplugusb_irdata(ir, urb->actual_length);
		else /* request IR */
			mod_timer(&ir->timer, jiffies + msecs_to_jiffies(50));
		break;
	case -EPROTO:
	case -ECONNRESET:
	case -ENOENT:
	case -ESHUTDOWN:
		return;
	default:
		dev_warn(ir->dev, "Error: urb status = %d\n", urb->status);
		igorplugusb_cmd(ir, SET_INFRABUFFER_EMPTY);
		break;
	}
}

static void igorplugusb_cmd(struct igorplugusb *ir, int cmd)

Annotation

Implementation Notes