drivers/media/cec/core/cec-adap.c

Source file repositories/reference/linux-study-clean/drivers/media/cec/core/cec-adap.c

File Facts

System
Linux kernel
Corpus path
drivers/media/cec/core/cec-adap.c
Extension
.c
Size
69646 bytes
Lines
2374
Domain
Driver Families
Bucket
drivers/media
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

if (fh->queued_events[ev_idx] < max_events[ev_idx]) {
			/* Add new msg at the end of the queue */
			list_add_tail(&entry->list, &fh->events[ev_idx]);
			fh->queued_events[ev_idx]++;
			fh->total_queued_events++;
			goto unlock;
		}

		if (ev_idx >= CEC_NUM_CORE_EVENTS) {
			list_add_tail(&entry->list, &fh->events[ev_idx]);
			/* drop the oldest event */
			entry = list_first_entry(&fh->events[ev_idx],
						 struct cec_event_entry, list);
			list_del(&entry->list);
			kfree(entry);
		}
	}
	/* Mark that events were lost */
	entry = list_first_entry_or_null(&fh->events[ev_idx],
					 struct cec_event_entry, list);
	if (entry)
		entry->ev.flags |= CEC_EVENT_FL_DROPPED_EVENTS;

unlock:
	mutex_unlock(&fh->lock);
	wake_up_interruptible(&fh->wait);
}

/* Queue a new event for all open filehandles. */
static void cec_queue_event(struct cec_adapter *adap,
			    const struct cec_event *ev)
{
	u64 ts = ktime_get_ns();
	struct cec_fh *fh;

	mutex_lock(&adap->devnode.lock_fhs);
	list_for_each_entry(fh, &adap->devnode.fhs, list)
		cec_queue_event_fh(fh, ev, ts);
	mutex_unlock(&adap->devnode.lock_fhs);
}

/* Notify userspace that the CEC pin changed state at the given time. */
void cec_queue_pin_cec_event(struct cec_adapter *adap, bool is_high,
			     bool dropped_events, ktime_t ts)
{
	struct cec_event ev = {
		.event = is_high ? CEC_EVENT_PIN_CEC_HIGH :
				   CEC_EVENT_PIN_CEC_LOW,
		.flags = dropped_events ? CEC_EVENT_FL_DROPPED_EVENTS : 0,
	};
	struct cec_fh *fh;

	mutex_lock(&adap->devnode.lock_fhs);
	list_for_each_entry(fh, &adap->devnode.fhs, list) {
		if (fh->mode_follower == CEC_MODE_MONITOR_PIN)
			cec_queue_event_fh(fh, &ev, ktime_to_ns(ts));
	}
	mutex_unlock(&adap->devnode.lock_fhs);
}
EXPORT_SYMBOL_GPL(cec_queue_pin_cec_event);

/* Notify userspace that the HPD pin changed state at the given time. */
void cec_queue_pin_hpd_event(struct cec_adapter *adap, bool is_high, ktime_t ts)
{
	struct cec_event ev = {
		.event = is_high ? CEC_EVENT_PIN_HPD_HIGH :
				   CEC_EVENT_PIN_HPD_LOW,
	};
	struct cec_fh *fh;

	mutex_lock(&adap->devnode.lock_fhs);
	list_for_each_entry(fh, &adap->devnode.fhs, list)
		cec_queue_event_fh(fh, &ev, ktime_to_ns(ts));
	mutex_unlock(&adap->devnode.lock_fhs);
}
EXPORT_SYMBOL_GPL(cec_queue_pin_hpd_event);

/* Notify userspace that the 5V pin changed state at the given time. */
void cec_queue_pin_5v_event(struct cec_adapter *adap, bool is_high, ktime_t ts)
{
	struct cec_event ev = {
		.event = is_high ? CEC_EVENT_PIN_5V_HIGH :
				   CEC_EVENT_PIN_5V_LOW,
	};
	struct cec_fh *fh;

	mutex_lock(&adap->devnode.lock_fhs);
	list_for_each_entry(fh, &adap->devnode.fhs, list)
		cec_queue_event_fh(fh, &ev, ktime_to_ns(ts));
	mutex_unlock(&adap->devnode.lock_fhs);

Annotation

Implementation Notes