drivers/media/rc/ttusbir.c

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

File Facts

System
Linux kernel
Corpus path
drivers/media/rc/ttusbir.c
Extension
.c
Size
9950 bytes
Lines
440
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 ttusbir {
	struct rc_dev *rc;
	struct device *dev;
	struct usb_device *udev;

	struct urb *urb[NUM_URBS];

	struct led_classdev led;
	struct urb *bulk_urb;
	u8 *bulk_buffer;
	int bulk_out_endp, iso_in_endp;
	bool led_on, is_led_on;
	atomic_t led_complete;

	char phys[64];
};

static enum led_brightness ttusbir_brightness_get(struct led_classdev *led_dev)
{
	struct ttusbir *tt = container_of(led_dev, struct ttusbir, led);

	return tt->led_on ? LED_FULL : LED_OFF;
}

static void ttusbir_set_led(struct ttusbir *tt)
{
	int ret;

	smp_mb();

	if (tt->led_on != tt->is_led_on && tt->udev &&
				atomic_add_unless(&tt->led_complete, 1, 1)) {
		tt->bulk_buffer[4] = tt->is_led_on = tt->led_on;
		ret = usb_submit_urb(tt->bulk_urb, GFP_ATOMIC);
		if (ret) {
			dev_warn(tt->dev, "failed to submit bulk urb: %d\n",
									ret);
			atomic_dec(&tt->led_complete);
		}
	}
}

static void ttusbir_brightness_set(struct led_classdev *led_dev, enum
						led_brightness brightness)
{
	struct ttusbir *tt = container_of(led_dev, struct ttusbir, led);

	tt->led_on = brightness != LED_OFF;

	ttusbir_set_led(tt);
}

/*
 * The urb cannot be reused until the urb completes
 */
static void ttusbir_bulk_complete(struct urb *urb)
{
	struct ttusbir *tt = urb->context;

	atomic_dec(&tt->led_complete);

	switch (urb->status) {
	case 0:
		break;
	case -ECONNRESET:
	case -ENOENT:
	case -ESHUTDOWN:
		return;
	case -EPIPE:
	default:
		dev_dbg(tt->dev, "Error: urb status = %d\n", urb->status);
		break;
	}

	ttusbir_set_led(tt);
}

/*
 * The data is one bit per sample, a set bit signifying silence and samples
 * being MSB first. Bit 0 can contain garbage so take it to be whatever
 * bit 1 is, so we don't have unexpected edges.
 */
static void ttusbir_process_ir_data(struct ttusbir *tt, uint8_t *buf)
{
	struct ir_raw_event rawir = {};
	unsigned i, v, b;
	bool event = false;

	for (i = 0; i < 128; i++) {
		v = buf[i] & 0xfe;

Annotation

Implementation Notes