drivers/media/usb/dvb-usb-v2/lmedm04.c

Source file repositories/reference/linux-study-clean/drivers/media/usb/dvb-usb-v2/lmedm04.c

File Facts

System
Linux kernel
Corpus path
drivers/media/usb/dvb-usb-v2/lmedm04.c
Extension
.c
Size
30054 bytes
Lines
1275
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 lme2510_state {
	unsigned long int_urb_due;
	enum fe_status lock_status;
	u8 id;
	u8 tuner_config;
	u8 signal_level;
	u8 signal_sn;
	u8 time_key;
	u8 i2c_talk_onoff;
	u8 i2c_gate;
	u8 i2c_tuner_gate_w;
	u8 i2c_tuner_gate_r;
	u8 i2c_tuner_addr;
	u8 stream_on;
	u8 pid_size;
	u8 pid_off;
	u8 int_buffer[128];
	struct urb *lme_urb;
	u8 usb_buffer[64];
	/* Frontend original calls */
	int (*fe_read_status)(struct dvb_frontend *, enum fe_status *);
	int (*fe_read_signal_strength)(struct dvb_frontend *, u16 *);
	int (*fe_read_snr)(struct dvb_frontend *, u16 *);
	int (*fe_read_ber)(struct dvb_frontend *, u32 *);
	int (*fe_read_ucblocks)(struct dvb_frontend *, u32 *);
	int (*fe_set_voltage)(struct dvb_frontend *, enum fe_sec_voltage);
	u8 dvb_usb_lme2510_firmware;
};

static int lme2510_usb_talk(struct dvb_usb_device *d,
			    u8 *wbuf, int wlen, u8 *rbuf, int rlen)
{
	struct lme2510_state *st = d->priv;
	int ret = 0;

	if (max(wlen, rlen) > sizeof(st->usb_buffer))
		return -EINVAL;

	ret = mutex_lock_interruptible(&d->usb_mutex);
	if (ret < 0)
		return -EAGAIN;

	memcpy(st->usb_buffer, wbuf, wlen);

	ret = dvb_usbv2_generic_rw_locked(d, st->usb_buffer, wlen,
					  st->usb_buffer, rlen);

	if (rlen)
		memcpy(rbuf, st->usb_buffer, rlen);

	mutex_unlock(&d->usb_mutex);

	return ret;
}

static int lme2510_stream_restart(struct dvb_usb_device *d)
{
	struct lme2510_state *st = d->priv;
	u8 all_pids[] = LME_ALL_PIDS;
	u8 stream_on[] = LME_ST_ON_W;
	u8 rbuff[1];
	if (st->pid_off)
		lme2510_usb_talk(d, all_pids, sizeof(all_pids),
				 rbuff, sizeof(rbuff));
	/*Restart Stream Command*/
	return lme2510_usb_talk(d, stream_on, sizeof(stream_on),
				rbuff, sizeof(rbuff));
}

static int lme2510_enable_pid(struct dvb_usb_device *d, u8 index, u16 pid_out)
{
	struct lme2510_state *st = d->priv;
	static u8 pid_buff[] = LME_ZERO_PID;
	static u8 rbuf[1];
	u8 pid_no = index * 2;
	u8 pid_len = pid_no + 2;
	int ret = 0;
	deb_info(1, "PID Setting Pid %04x", pid_out);

	if (st->pid_size == 0)
		ret |= lme2510_stream_restart(d);

	pid_buff[2] = pid_no;
	pid_buff[3] = (u8)pid_out & 0xff;
	pid_buff[4] = pid_no + 1;
	pid_buff[5] = (u8)(pid_out >> 8);

	if (pid_len > st->pid_size)
		st->pid_size = pid_len;
	pid_buff[7] = 0x80 + st->pid_size;

Annotation

Implementation Notes