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

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

File Facts

System
Linux kernel
Corpus path
drivers/media/usb/dvb-usb-v2/dvbsky.c
Extension
.c
Size
22551 bytes
Lines
830
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 dvbsky_state {
	u8 ibuf[DVBSKY_BUF_LEN];
	u8 obuf[DVBSKY_BUF_LEN];
	u8 last_lock;
	struct i2c_client *i2c_client_demod;
	struct i2c_client *i2c_client_tuner;
	struct i2c_client *i2c_client_ci;

	/* fe hook functions*/
	int (*fe_set_voltage)(struct dvb_frontend *fe,
		enum fe_sec_voltage voltage);
	int (*fe_read_status)(struct dvb_frontend *fe,
		enum fe_status *status);
};

static int dvbsky_usb_generic_rw(struct dvb_usb_device *d,
		u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
{
	int ret;
	struct dvbsky_state *state = d_to_priv(d);

	mutex_lock(&d->usb_mutex);
	if (wlen != 0)
		memcpy(state->obuf, wbuf, wlen);

	ret = dvb_usbv2_generic_rw_locked(d, state->obuf, wlen,
			state->ibuf, rlen);

	if (!ret && (rlen != 0))
		memcpy(rbuf, state->ibuf, rlen);

	mutex_unlock(&d->usb_mutex);
	return ret;
}

static int dvbsky_stream_ctrl(struct dvb_usb_device *d, u8 onoff)
{
	struct dvbsky_state *state = d_to_priv(d);
	static const u8 obuf_pre[3] = { 0x37, 0, 0 };
	static const u8 obuf_post[3] = { 0x36, 3, 0 };
	int ret;

	mutex_lock(&d->usb_mutex);
	memcpy(state->obuf, obuf_pre, 3);
	ret = dvb_usbv2_generic_write_locked(d, state->obuf, 3);
	if (!ret && onoff) {
		msleep(20);
		memcpy(state->obuf, obuf_post, 3);
		ret = dvb_usbv2_generic_write_locked(d, state->obuf, 3);
	}
	mutex_unlock(&d->usb_mutex);
	return ret;
}

static int dvbsky_streaming_ctrl(struct dvb_frontend *fe, int onoff)
{
	struct dvb_usb_device *d = fe_to_d(fe);

	return dvbsky_stream_ctrl(d, (onoff == 0) ? 0 : 1);
}

/* GPIO */
static int dvbsky_gpio_ctrl(struct dvb_usb_device *d, u8 gport, u8 value)
{
	int ret;
	u8 obuf[3], ibuf[2];

	obuf[0] = 0x0e;
	obuf[1] = gport;
	obuf[2] = value;
	ret = dvbsky_usb_generic_rw(d, obuf, 3, ibuf, 1);
	return ret;
}

/* I2C */
static int dvbsky_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
	int num)
{
	struct dvb_usb_device *d = i2c_get_adapdata(adap);
	int ret = 0;
	u8 ibuf[64], obuf[64];

	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
		return -EAGAIN;

	if (num > 2) {
		dev_err(&d->udev->dev,
		"too many i2c messages[%d], max 2.", num);
		ret = -EOPNOTSUPP;
		goto i2c_error;

Annotation

Implementation Notes