162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/* Common methods for dibusb-based-receivers.
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de)
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include "dibusb.h"
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci/* Max transfer size done by I2C transfer functions */
1262306a36Sopenharmony_ci#define MAX_XFER_SIZE  64
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_cistatic int debug;
1562306a36Sopenharmony_cimodule_param(debug, int, 0644);
1662306a36Sopenharmony_ciMODULE_PARM_DESC(debug, "set debugging level (1=info (|-able))." DVB_USB_DEBUG_STATUS);
1762306a36Sopenharmony_ciMODULE_LICENSE("GPL");
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#define deb_info(args...) dprintk(debug,0x01,args)
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci/* common stuff used by the different dibusb modules */
2262306a36Sopenharmony_ciint dibusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
2362306a36Sopenharmony_ci{
2462306a36Sopenharmony_ci	if (adap->priv != NULL) {
2562306a36Sopenharmony_ci		struct dibusb_state *st = adap->priv;
2662306a36Sopenharmony_ci		if (st->ops.fifo_ctrl != NULL)
2762306a36Sopenharmony_ci			if (st->ops.fifo_ctrl(adap->fe_adap[0].fe, onoff)) {
2862306a36Sopenharmony_ci				err("error while controlling the fifo of the demod.");
2962306a36Sopenharmony_ci				return -ENODEV;
3062306a36Sopenharmony_ci			}
3162306a36Sopenharmony_ci	}
3262306a36Sopenharmony_ci	return 0;
3362306a36Sopenharmony_ci}
3462306a36Sopenharmony_ciEXPORT_SYMBOL(dibusb_streaming_ctrl);
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ciint dibusb_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff)
3762306a36Sopenharmony_ci{
3862306a36Sopenharmony_ci	if (adap->priv != NULL) {
3962306a36Sopenharmony_ci		struct dibusb_state *st = adap->priv;
4062306a36Sopenharmony_ci		if (st->ops.pid_ctrl != NULL)
4162306a36Sopenharmony_ci			st->ops.pid_ctrl(adap->fe_adap[0].fe,
4262306a36Sopenharmony_ci					 index, pid, onoff);
4362306a36Sopenharmony_ci	}
4462306a36Sopenharmony_ci	return 0;
4562306a36Sopenharmony_ci}
4662306a36Sopenharmony_ciEXPORT_SYMBOL(dibusb_pid_filter);
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ciint dibusb_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
4962306a36Sopenharmony_ci{
5062306a36Sopenharmony_ci	if (adap->priv != NULL) {
5162306a36Sopenharmony_ci		struct dibusb_state *st = adap->priv;
5262306a36Sopenharmony_ci		if (st->ops.pid_parse != NULL)
5362306a36Sopenharmony_ci			if (st->ops.pid_parse(adap->fe_adap[0].fe, onoff) < 0)
5462306a36Sopenharmony_ci				err("could not handle pid_parser");
5562306a36Sopenharmony_ci	}
5662306a36Sopenharmony_ci	return 0;
5762306a36Sopenharmony_ci}
5862306a36Sopenharmony_ciEXPORT_SYMBOL(dibusb_pid_filter_ctrl);
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ciint dibusb_power_ctrl(struct dvb_usb_device *d, int onoff)
6162306a36Sopenharmony_ci{
6262306a36Sopenharmony_ci	u8 *b;
6362306a36Sopenharmony_ci	int ret;
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	b = kmalloc(3, GFP_KERNEL);
6662306a36Sopenharmony_ci	if (!b)
6762306a36Sopenharmony_ci		return -ENOMEM;
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	b[0] = DIBUSB_REQ_SET_IOCTL;
7062306a36Sopenharmony_ci	b[1] = DIBUSB_IOCTL_CMD_POWER_MODE;
7162306a36Sopenharmony_ci	b[2] = onoff ? DIBUSB_IOCTL_POWER_WAKEUP : DIBUSB_IOCTL_POWER_SLEEP;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	ret = dvb_usb_generic_write(d, b, 3);
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	kfree(b);
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	msleep(10);
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	return ret;
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ciEXPORT_SYMBOL(dibusb_power_ctrl);
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ciint dibusb2_0_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
8462306a36Sopenharmony_ci{
8562306a36Sopenharmony_ci	int ret;
8662306a36Sopenharmony_ci	u8 *b;
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	b = kmalloc(3, GFP_KERNEL);
8962306a36Sopenharmony_ci	if (!b)
9062306a36Sopenharmony_ci		return -ENOMEM;
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	if ((ret = dibusb_streaming_ctrl(adap,onoff)) < 0)
9362306a36Sopenharmony_ci		goto ret;
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	if (onoff) {
9662306a36Sopenharmony_ci		b[0] = DIBUSB_REQ_SET_STREAMING_MODE;
9762306a36Sopenharmony_ci		b[1] = 0x00;
9862306a36Sopenharmony_ci		ret = dvb_usb_generic_write(adap->dev, b, 2);
9962306a36Sopenharmony_ci		if (ret  < 0)
10062306a36Sopenharmony_ci			goto ret;
10162306a36Sopenharmony_ci	}
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	b[0] = DIBUSB_REQ_SET_IOCTL;
10462306a36Sopenharmony_ci	b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM;
10562306a36Sopenharmony_ci	ret = dvb_usb_generic_write(adap->dev, b, 3);
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ciret:
10862306a36Sopenharmony_ci	kfree(b);
10962306a36Sopenharmony_ci	return ret;
11062306a36Sopenharmony_ci}
11162306a36Sopenharmony_ciEXPORT_SYMBOL(dibusb2_0_streaming_ctrl);
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ciint dibusb2_0_power_ctrl(struct dvb_usb_device *d, int onoff)
11462306a36Sopenharmony_ci{
11562306a36Sopenharmony_ci	u8 *b;
11662306a36Sopenharmony_ci	int ret;
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	if (!onoff)
11962306a36Sopenharmony_ci		return 0;
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	b = kmalloc(3, GFP_KERNEL);
12262306a36Sopenharmony_ci	if (!b)
12362306a36Sopenharmony_ci		return -ENOMEM;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	b[0] = DIBUSB_REQ_SET_IOCTL;
12662306a36Sopenharmony_ci	b[1] = DIBUSB_IOCTL_CMD_POWER_MODE;
12762306a36Sopenharmony_ci	b[2] = DIBUSB_IOCTL_POWER_WAKEUP;
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci	ret = dvb_usb_generic_write(d, b, 3);
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	kfree(b);
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	return ret;
13462306a36Sopenharmony_ci}
13562306a36Sopenharmony_ciEXPORT_SYMBOL(dibusb2_0_power_ctrl);
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_cistatic int dibusb_i2c_msg(struct dvb_usb_device *d, u8 addr,
13862306a36Sopenharmony_ci			  u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
13962306a36Sopenharmony_ci{
14062306a36Sopenharmony_ci	u8 *sndbuf;
14162306a36Sopenharmony_ci	int ret, wo, len;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	/* write only ? */
14462306a36Sopenharmony_ci	wo = (rbuf == NULL || rlen == 0);
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	len = 2 + wlen + (wo ? 0 : 2);
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	sndbuf = kmalloc(MAX_XFER_SIZE, GFP_KERNEL);
14962306a36Sopenharmony_ci	if (!sndbuf)
15062306a36Sopenharmony_ci		return -ENOMEM;
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	if (4 + wlen > MAX_XFER_SIZE) {
15362306a36Sopenharmony_ci		warn("i2c wr: len=%d is too big!\n", wlen);
15462306a36Sopenharmony_ci		ret = -EOPNOTSUPP;
15562306a36Sopenharmony_ci		goto ret;
15662306a36Sopenharmony_ci	}
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci	sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ;
15962306a36Sopenharmony_ci	sndbuf[1] = (addr << 1) | (wo ? 0 : 1);
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	memcpy(&sndbuf[2], wbuf, wlen);
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	if (!wo) {
16462306a36Sopenharmony_ci		sndbuf[wlen + 2] = (rlen >> 8) & 0xff;
16562306a36Sopenharmony_ci		sndbuf[wlen + 3] = rlen & 0xff;
16662306a36Sopenharmony_ci	}
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	ret = dvb_usb_generic_rw(d, sndbuf, len, rbuf, rlen, 0);
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ciret:
17162306a36Sopenharmony_ci	kfree(sndbuf);
17262306a36Sopenharmony_ci	return ret;
17362306a36Sopenharmony_ci}
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci/*
17662306a36Sopenharmony_ci * I2C master xfer function
17762306a36Sopenharmony_ci */
17862306a36Sopenharmony_cistatic int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
17962306a36Sopenharmony_ci{
18062306a36Sopenharmony_ci	struct dvb_usb_device *d = i2c_get_adapdata(adap);
18162306a36Sopenharmony_ci	int i;
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
18462306a36Sopenharmony_ci		return -EAGAIN;
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci	for (i = 0; i < num; i++) {
18762306a36Sopenharmony_ci		/* write/read request */
18862306a36Sopenharmony_ci		if (i+1 < num && (msg[i].flags & I2C_M_RD) == 0
18962306a36Sopenharmony_ci					  && (msg[i+1].flags & I2C_M_RD)) {
19062306a36Sopenharmony_ci			if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,
19162306a36Sopenharmony_ci						msg[i+1].buf,msg[i+1].len) < 0)
19262306a36Sopenharmony_ci				break;
19362306a36Sopenharmony_ci			i++;
19462306a36Sopenharmony_ci		} else if ((msg[i].flags & I2C_M_RD) == 0) {
19562306a36Sopenharmony_ci			if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0)
19662306a36Sopenharmony_ci				break;
19762306a36Sopenharmony_ci		} else if (msg[i].addr != 0x50) {
19862306a36Sopenharmony_ci			/* 0x50 is the address of the eeprom - we need to protect it
19962306a36Sopenharmony_ci			 * from dibusb's bad i2c implementation: reads without
20062306a36Sopenharmony_ci			 * writing the offset before are forbidden */
20162306a36Sopenharmony_ci			if (dibusb_i2c_msg(d, msg[i].addr, NULL, 0, msg[i].buf, msg[i].len) < 0)
20262306a36Sopenharmony_ci				break;
20362306a36Sopenharmony_ci		}
20462306a36Sopenharmony_ci	}
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	mutex_unlock(&d->i2c_mutex);
20762306a36Sopenharmony_ci	return i;
20862306a36Sopenharmony_ci}
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_cistatic u32 dibusb_i2c_func(struct i2c_adapter *adapter)
21162306a36Sopenharmony_ci{
21262306a36Sopenharmony_ci	return I2C_FUNC_I2C;
21362306a36Sopenharmony_ci}
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_cistruct i2c_algorithm dibusb_i2c_algo = {
21662306a36Sopenharmony_ci	.master_xfer   = dibusb_i2c_xfer,
21762306a36Sopenharmony_ci	.functionality = dibusb_i2c_func,
21862306a36Sopenharmony_ci};
21962306a36Sopenharmony_ciEXPORT_SYMBOL(dibusb_i2c_algo);
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ciint dibusb_read_eeprom_byte(struct dvb_usb_device *d, u8 offs, u8 *val)
22262306a36Sopenharmony_ci{
22362306a36Sopenharmony_ci	u8 *buf;
22462306a36Sopenharmony_ci	int rc;
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	buf = kzalloc(2, GFP_KERNEL);
22762306a36Sopenharmony_ci	if (!buf)
22862306a36Sopenharmony_ci		return -ENOMEM;
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	buf[0] = offs;
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci	rc = dibusb_i2c_msg(d, 0x50, &buf[0], 1, &buf[1], 1);
23362306a36Sopenharmony_ci	*val = buf[1];
23462306a36Sopenharmony_ci	kfree(buf);
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	return rc;
23762306a36Sopenharmony_ci}
23862306a36Sopenharmony_ciEXPORT_SYMBOL(dibusb_read_eeprom_byte);
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci/*
24162306a36Sopenharmony_ci * common remote control stuff
24262306a36Sopenharmony_ci */
24362306a36Sopenharmony_cistruct rc_map_table rc_map_dibusb_table[] = {
24462306a36Sopenharmony_ci	/* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */
24562306a36Sopenharmony_ci	{ 0x0016, KEY_POWER },
24662306a36Sopenharmony_ci	{ 0x0010, KEY_MUTE },
24762306a36Sopenharmony_ci	{ 0x0003, KEY_1 },
24862306a36Sopenharmony_ci	{ 0x0001, KEY_2 },
24962306a36Sopenharmony_ci	{ 0x0006, KEY_3 },
25062306a36Sopenharmony_ci	{ 0x0009, KEY_4 },
25162306a36Sopenharmony_ci	{ 0x001d, KEY_5 },
25262306a36Sopenharmony_ci	{ 0x001f, KEY_6 },
25362306a36Sopenharmony_ci	{ 0x000d, KEY_7 },
25462306a36Sopenharmony_ci	{ 0x0019, KEY_8 },
25562306a36Sopenharmony_ci	{ 0x001b, KEY_9 },
25662306a36Sopenharmony_ci	{ 0x0015, KEY_0 },
25762306a36Sopenharmony_ci	{ 0x0005, KEY_CHANNELUP },
25862306a36Sopenharmony_ci	{ 0x0002, KEY_CHANNELDOWN },
25962306a36Sopenharmony_ci	{ 0x001e, KEY_VOLUMEUP },
26062306a36Sopenharmony_ci	{ 0x000a, KEY_VOLUMEDOWN },
26162306a36Sopenharmony_ci	{ 0x0011, KEY_RECORD },
26262306a36Sopenharmony_ci	{ 0x0017, KEY_FAVORITES }, /* Heart symbol - Channel list. */
26362306a36Sopenharmony_ci	{ 0x0014, KEY_PLAY },
26462306a36Sopenharmony_ci	{ 0x001a, KEY_STOP },
26562306a36Sopenharmony_ci	{ 0x0040, KEY_REWIND },
26662306a36Sopenharmony_ci	{ 0x0012, KEY_FASTFORWARD },
26762306a36Sopenharmony_ci	{ 0x000e, KEY_PREVIOUS }, /* Recall - Previous channel. */
26862306a36Sopenharmony_ci	{ 0x004c, KEY_PAUSE },
26962306a36Sopenharmony_ci	{ 0x004d, KEY_SCREEN }, /* Full screen mode. */
27062306a36Sopenharmony_ci	{ 0x0054, KEY_AUDIO }, /* MTS - Switch to secondary audio. */
27162306a36Sopenharmony_ci	/* additional keys TwinHan VisionPlus, the Artec seemingly not have */
27262306a36Sopenharmony_ci	{ 0x000c, KEY_CANCEL }, /* Cancel */
27362306a36Sopenharmony_ci	{ 0x001c, KEY_EPG }, /* EPG */
27462306a36Sopenharmony_ci	{ 0x0000, KEY_TAB }, /* Tab */
27562306a36Sopenharmony_ci	{ 0x0048, KEY_INFO }, /* Preview */
27662306a36Sopenharmony_ci	{ 0x0004, KEY_LIST }, /* RecordList */
27762306a36Sopenharmony_ci	{ 0x000f, KEY_TEXT }, /* Teletext */
27862306a36Sopenharmony_ci	/* Key codes for the KWorld/ADSTech/JetWay remote. */
27962306a36Sopenharmony_ci	{ 0x8612, KEY_POWER },
28062306a36Sopenharmony_ci	{ 0x860f, KEY_SELECT }, /* source */
28162306a36Sopenharmony_ci	{ 0x860c, KEY_UNKNOWN }, /* scan */
28262306a36Sopenharmony_ci	{ 0x860b, KEY_EPG },
28362306a36Sopenharmony_ci	{ 0x8610, KEY_MUTE },
28462306a36Sopenharmony_ci	{ 0x8601, KEY_1 },
28562306a36Sopenharmony_ci	{ 0x8602, KEY_2 },
28662306a36Sopenharmony_ci	{ 0x8603, KEY_3 },
28762306a36Sopenharmony_ci	{ 0x8604, KEY_4 },
28862306a36Sopenharmony_ci	{ 0x8605, KEY_5 },
28962306a36Sopenharmony_ci	{ 0x8606, KEY_6 },
29062306a36Sopenharmony_ci	{ 0x8607, KEY_7 },
29162306a36Sopenharmony_ci	{ 0x8608, KEY_8 },
29262306a36Sopenharmony_ci	{ 0x8609, KEY_9 },
29362306a36Sopenharmony_ci	{ 0x860a, KEY_0 },
29462306a36Sopenharmony_ci	{ 0x8618, KEY_ZOOM },
29562306a36Sopenharmony_ci	{ 0x861c, KEY_UNKNOWN }, /* preview */
29662306a36Sopenharmony_ci	{ 0x8613, KEY_UNKNOWN }, /* snap */
29762306a36Sopenharmony_ci	{ 0x8600, KEY_UNDO },
29862306a36Sopenharmony_ci	{ 0x861d, KEY_RECORD },
29962306a36Sopenharmony_ci	{ 0x860d, KEY_STOP },
30062306a36Sopenharmony_ci	{ 0x860e, KEY_PAUSE },
30162306a36Sopenharmony_ci	{ 0x8616, KEY_PLAY },
30262306a36Sopenharmony_ci	{ 0x8611, KEY_BACK },
30362306a36Sopenharmony_ci	{ 0x8619, KEY_FORWARD },
30462306a36Sopenharmony_ci	{ 0x8614, KEY_UNKNOWN }, /* pip */
30562306a36Sopenharmony_ci	{ 0x8615, KEY_ESC },
30662306a36Sopenharmony_ci	{ 0x861a, KEY_UP },
30762306a36Sopenharmony_ci	{ 0x861e, KEY_DOWN },
30862306a36Sopenharmony_ci	{ 0x861f, KEY_LEFT },
30962306a36Sopenharmony_ci	{ 0x861b, KEY_RIGHT },
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci	/* Key codes for the DiBcom MOD3000 remote. */
31262306a36Sopenharmony_ci	{ 0x8000, KEY_MUTE },
31362306a36Sopenharmony_ci	{ 0x8001, KEY_TEXT },
31462306a36Sopenharmony_ci	{ 0x8002, KEY_HOME },
31562306a36Sopenharmony_ci	{ 0x8003, KEY_POWER },
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	{ 0x8004, KEY_RED },
31862306a36Sopenharmony_ci	{ 0x8005, KEY_GREEN },
31962306a36Sopenharmony_ci	{ 0x8006, KEY_YELLOW },
32062306a36Sopenharmony_ci	{ 0x8007, KEY_BLUE },
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	{ 0x8008, KEY_DVD },
32362306a36Sopenharmony_ci	{ 0x8009, KEY_AUDIO },
32462306a36Sopenharmony_ci	{ 0x800a, KEY_IMAGES },      /* Pictures */
32562306a36Sopenharmony_ci	{ 0x800b, KEY_VIDEO },
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	{ 0x800c, KEY_BACK },
32862306a36Sopenharmony_ci	{ 0x800d, KEY_UP },
32962306a36Sopenharmony_ci	{ 0x800e, KEY_RADIO },
33062306a36Sopenharmony_ci	{ 0x800f, KEY_EPG },
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	{ 0x8010, KEY_LEFT },
33362306a36Sopenharmony_ci	{ 0x8011, KEY_OK },
33462306a36Sopenharmony_ci	{ 0x8012, KEY_RIGHT },
33562306a36Sopenharmony_ci	{ 0x8013, KEY_UNKNOWN },    /* SAP */
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	{ 0x8014, KEY_TV },
33862306a36Sopenharmony_ci	{ 0x8015, KEY_DOWN },
33962306a36Sopenharmony_ci	{ 0x8016, KEY_MENU },       /* DVD Menu */
34062306a36Sopenharmony_ci	{ 0x8017, KEY_LAST },
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci	{ 0x8018, KEY_RECORD },
34362306a36Sopenharmony_ci	{ 0x8019, KEY_STOP },
34462306a36Sopenharmony_ci	{ 0x801a, KEY_PAUSE },
34562306a36Sopenharmony_ci	{ 0x801b, KEY_PLAY },
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	{ 0x801c, KEY_PREVIOUS },
34862306a36Sopenharmony_ci	{ 0x801d, KEY_REWIND },
34962306a36Sopenharmony_ci	{ 0x801e, KEY_FASTFORWARD },
35062306a36Sopenharmony_ci	{ 0x801f, KEY_NEXT},
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	{ 0x8040, KEY_1 },
35362306a36Sopenharmony_ci	{ 0x8041, KEY_2 },
35462306a36Sopenharmony_ci	{ 0x8042, KEY_3 },
35562306a36Sopenharmony_ci	{ 0x8043, KEY_CHANNELUP },
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	{ 0x8044, KEY_4 },
35862306a36Sopenharmony_ci	{ 0x8045, KEY_5 },
35962306a36Sopenharmony_ci	{ 0x8046, KEY_6 },
36062306a36Sopenharmony_ci	{ 0x8047, KEY_CHANNELDOWN },
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci	{ 0x8048, KEY_7 },
36362306a36Sopenharmony_ci	{ 0x8049, KEY_8 },
36462306a36Sopenharmony_ci	{ 0x804a, KEY_9 },
36562306a36Sopenharmony_ci	{ 0x804b, KEY_VOLUMEUP },
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci	{ 0x804c, KEY_CLEAR },
36862306a36Sopenharmony_ci	{ 0x804d, KEY_0 },
36962306a36Sopenharmony_ci	{ 0x804e, KEY_ENTER },
37062306a36Sopenharmony_ci	{ 0x804f, KEY_VOLUMEDOWN },
37162306a36Sopenharmony_ci};
37262306a36Sopenharmony_ciEXPORT_SYMBOL(rc_map_dibusb_table);
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ciint dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
37562306a36Sopenharmony_ci{
37662306a36Sopenharmony_ci	u8 *buf;
37762306a36Sopenharmony_ci	int ret;
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci	buf = kmalloc(5, GFP_KERNEL);
38062306a36Sopenharmony_ci	if (!buf)
38162306a36Sopenharmony_ci		return -ENOMEM;
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	buf[0] = DIBUSB_REQ_POLL_REMOTE;
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	ret = dvb_usb_generic_rw(d, buf, 1, buf, 5, 0);
38662306a36Sopenharmony_ci	if (ret < 0)
38762306a36Sopenharmony_ci		goto ret;
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_ci	dvb_usb_nec_rc_key_to_event(d, buf, event, state);
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci	if (buf[0] != 0)
39262306a36Sopenharmony_ci		deb_info("key: %*ph\n", 5, buf);
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ciret:
39562306a36Sopenharmony_ci	kfree(buf);
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	return ret;
39862306a36Sopenharmony_ci}
39962306a36Sopenharmony_ciEXPORT_SYMBOL(dibusb_rc_query);
400