Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5ef8ed0e authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab
Browse files

[media] cinergyT2-core: don't do DMA on stack



The USB control messages require DMA to work. We cannot pass
a stack-allocated buffer, as it is not warranted that the
stack would be into a DMA enabled area.

Reviewed-by: default avatarPatrick Boettcher <patrick.boettcher@posteo.de>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent c58b84ee
Loading
Loading
Loading
Loading
+61 −23
Original line number Original line Diff line number Diff line
@@ -41,6 +41,8 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);


struct cinergyt2_state {
struct cinergyt2_state {
	u8 rc_counter;
	u8 rc_counter;
	unsigned char data[64];
	struct mutex data_mutex;
};
};


/* We are missing a release hook with usb_device data */
/* We are missing a release hook with usb_device data */
@@ -50,33 +52,52 @@ static struct dvb_usb_device_properties cinergyt2_properties;


static int cinergyt2_streaming_ctrl(struct dvb_usb_adapter *adap, int enable)
static int cinergyt2_streaming_ctrl(struct dvb_usb_adapter *adap, int enable)
{
{
	char buf[] = { CINERGYT2_EP1_CONTROL_STREAM_TRANSFER, enable ? 1 : 0 };
	struct dvb_usb_device *d = adap->dev;
	char result[64];
	struct cinergyt2_state *st = d->priv;
	return dvb_usb_generic_rw(adap->dev, buf, sizeof(buf), result,
	int ret;
				sizeof(result), 0);

	mutex_lock(&st->data_mutex);
	st->data[0] = CINERGYT2_EP1_CONTROL_STREAM_TRANSFER;
	st->data[1] = enable ? 1 : 0;

	ret = dvb_usb_generic_rw(d, st->data, 2, st->data, 64, 0);
	mutex_unlock(&st->data_mutex);

	return ret;
}
}


static int cinergyt2_power_ctrl(struct dvb_usb_device *d, int enable)
static int cinergyt2_power_ctrl(struct dvb_usb_device *d, int enable)
{
{
	char buf[] = { CINERGYT2_EP1_SLEEP_MODE, enable ? 0 : 1 };
	struct cinergyt2_state *st = d->priv;
	char state[3];
	int ret;
	return dvb_usb_generic_rw(d, buf, sizeof(buf), state, sizeof(state), 0);

	mutex_lock(&st->data_mutex);
	st->data[0] = CINERGYT2_EP1_SLEEP_MODE;
	st->data[1] = enable ? 0 : 1;

	ret = dvb_usb_generic_rw(d, st->data, 2, st->data, 3, 0);
	mutex_unlock(&st->data_mutex);

	return ret;
}
}


static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap)
static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap)
{
{
	char query[] = { CINERGYT2_EP1_GET_FIRMWARE_VERSION };
	struct dvb_usb_device *d = adap->dev;
	char state[3];
	struct cinergyt2_state *st = d->priv;
	int ret;
	int ret;


	adap->fe_adap[0].fe = cinergyt2_fe_attach(adap->dev);
	adap->fe_adap[0].fe = cinergyt2_fe_attach(adap->dev);


	ret = dvb_usb_generic_rw(adap->dev, query, sizeof(query), state,
	mutex_lock(&st->data_mutex);
				sizeof(state), 0);
	st->data[0] = CINERGYT2_EP1_GET_FIRMWARE_VERSION;

	ret = dvb_usb_generic_rw(d, st->data, 1, st->data, 3, 0);
	if (ret < 0) {
	if (ret < 0) {
		deb_rc("cinergyt2_power_ctrl() Failed to retrieve sleep "
		deb_rc("cinergyt2_power_ctrl() Failed to retrieve sleep "
			"state info\n");
			"state info\n");
	}
	}
	mutex_unlock(&st->data_mutex);


	/* Copy this pointer as we are gonna need it in the release phase */
	/* Copy this pointer as we are gonna need it in the release phase */
	cinergyt2_usb_device = adap->dev;
	cinergyt2_usb_device = adap->dev;
@@ -141,13 +162,16 @@ static int repeatable_keys[] = {
static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
{
{
	struct cinergyt2_state *st = d->priv;
	struct cinergyt2_state *st = d->priv;
	u8 key[5] = {0, 0, 0, 0, 0}, cmd = CINERGYT2_EP1_GET_RC_EVENTS;
	int i;
	int i;


	*state = REMOTE_NO_KEY_PRESSED;
	*state = REMOTE_NO_KEY_PRESSED;


	dvb_usb_generic_rw(d, &cmd, 1, key, sizeof(key), 0);
	mutex_lock(&st->data_mutex);
	if (key[4] == 0xff) {
	st->data[0] = CINERGYT2_EP1_GET_RC_EVENTS;

	dvb_usb_generic_rw(d, st->data, 1, st->data, 5, 0);

	if (st->data[4] == 0xff) {
		/* key repeat */
		/* key repeat */
		st->rc_counter++;
		st->rc_counter++;
		if (st->rc_counter > RC_REPEAT_DELAY) {
		if (st->rc_counter > RC_REPEAT_DELAY) {
@@ -157,31 +181,45 @@ static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
					*event = d->last_event;
					*event = d->last_event;
					deb_rc("repeat key, event %x\n",
					deb_rc("repeat key, event %x\n",
						   *event);
						   *event);
					return 0;
					goto ret;
				}
				}
			}
			}
			deb_rc("repeated key (non repeatable)\n");
			deb_rc("repeated key (non repeatable)\n");
		}
		}
		return 0;
		goto ret;
	}
	}


	/* hack to pass checksum on the custom field */
	/* hack to pass checksum on the custom field */
	key[2] = ~key[1];
	st->data[2] = ~st->data[1];
	dvb_usb_nec_rc_key_to_event(d, key, event, state);
	dvb_usb_nec_rc_key_to_event(d, st->data, event, state);
	if (key[0] != 0) {
	if (st->data[0] != 0) {
		if (*event != d->last_event)
		if (*event != d->last_event)
			st->rc_counter = 0;
			st->rc_counter = 0;


		deb_rc("key: %*ph\n", 5, key);
		deb_rc("key: %*ph\n", 5, st->data);
	}
	}
	return 0;

ret:
	mutex_unlock(&st->data_mutex);
	return ret;
}
}


static int cinergyt2_usb_probe(struct usb_interface *intf,
static int cinergyt2_usb_probe(struct usb_interface *intf,
				const struct usb_device_id *id)
				const struct usb_device_id *id)
{
{
	return dvb_usb_device_init(intf, &cinergyt2_properties,
	struct dvb_usb_device *d;
					THIS_MODULE, NULL, adapter_nr);
	struct cinergyt2_state *st;
	int ret;

	ret = dvb_usb_device_init(intf, &cinergyt2_properties,
				  THIS_MODULE, &d, adapter_nr);
	if (ret < 0)
		return ret;

	st = d->priv;
	mutex_init(&st->data_mutex);

	return 0;
}
}