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

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

File Facts

System
Linux kernel
Corpus path
drivers/media/usb/dvb-usb-v2/af9015.c
Extension
.c
Size
44222 bytes
Lines
1557
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 af9015_rc_setup {
	unsigned int id;
	char *rc_codes;
};

static char *af9015_rc_setup_match(unsigned int id,
				   const struct af9015_rc_setup *table)
{
	for (; table->rc_codes; table++)
		if (table->id == id)
			return table->rc_codes;
	return NULL;
}

static const struct af9015_rc_setup af9015_rc_setup_modparam[] = {
	{ AF9015_REMOTE_A_LINK_DTU_M, RC_MAP_ALINK_DTU_M },
	{ AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, RC_MAP_MSI_DIGIVOX_II },
	{ AF9015_REMOTE_MYGICTV_U718, RC_MAP_TOTAL_MEDIA_IN_HAND },
	{ AF9015_REMOTE_DIGITTRADE_DVB_T, RC_MAP_DIGITTRADE },
	{ AF9015_REMOTE_AVERMEDIA_KS, RC_MAP_AVERMEDIA_RM_KS },
	{ }
};

static const struct af9015_rc_setup af9015_rc_setup_hashes[] = {
	{ 0xb8feb708, RC_MAP_MSI_DIGIVOX_II },
	{ 0xa3703d00, RC_MAP_ALINK_DTU_M },
	{ 0x9b7dc64e, RC_MAP_TOTAL_MEDIA_IN_HAND }, /* MYGICTV U718 */
	{ 0x5d49e3db, RC_MAP_DIGITTRADE }, /* LC-Power LC-USB-DVBT */
	{ }
};

static int af9015_rc_query(struct dvb_usb_device *d)
{
	struct af9015_state *state = d_to_priv(d);
	struct usb_interface *intf = d->intf;
	int ret;
	u8 buf[17];

	/* read registers needed to detect remote controller code */
	ret = regmap_bulk_read(state->regmap, 0x98d9, buf, sizeof(buf));
	if (ret)
		goto error;

	/* If any of these are non-zero, assume invalid data */
	if (buf[1] || buf[2] || buf[3]) {
		dev_dbg(&intf->dev, "invalid data\n");
		return 0;
	}

	/* Check for repeat of previous code */
	if ((state->rc_repeat != buf[6] || buf[0]) &&
	    !memcmp(&buf[12], state->rc_last, 4)) {
		dev_dbg(&intf->dev, "key repeated\n");
		rc_repeat(d->rc_dev);
		state->rc_repeat = buf[6];
		return 0;
	}

	/* Only process key if canary killed */
	if (buf[16] != 0xff && buf[0] != 0x01) {
		enum rc_proto proto;

		dev_dbg(&intf->dev, "key pressed %*ph\n", 4, buf + 12);

		/* Reset the canary */
		ret = regmap_write(state->regmap, 0x98e9, 0xff);
		if (ret)
			goto error;

		/* Remember this key */
		memcpy(state->rc_last, &buf[12], 4);
		if (buf[14] == (u8)~buf[15]) {
			if (buf[12] == (u8)~buf[13]) {
				/* NEC */
				state->rc_keycode = RC_SCANCODE_NEC(buf[12],
								    buf[14]);
				proto = RC_PROTO_NEC;
			} else {
				/* NEC extended*/
				state->rc_keycode = RC_SCANCODE_NECX(buf[12] << 8 |
								     buf[13],
								     buf[14]);
				proto = RC_PROTO_NECX;
			}
		} else {
			/* 32 bit NEC */
			state->rc_keycode = RC_SCANCODE_NEC32(buf[12] << 24 |
							      buf[13] << 16 |
							      buf[14] << 8  |
							      buf[15]);

Annotation

Implementation Notes