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

Commit d8d1721c authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull media fixes from Mauro Carvalho Chehab:
 "A series of fixup patches meant to fix the usage of DMA on stack, plus
  one warning fixup"

* tag 'media/v4.9-3' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (32 commits)
  [media] radio-bcm2048: don't ignore errors
  [media] pctv452e: fix semicolon.cocci warnings
  [media] flexcop-usb: don't use stack for DMA
  [media] stk-webcam: don't use stack for DMA
  [media] s2255drv: don't use stack for DMA
  [media] cpia2_usb: don't use stack for DMA
  [media] digitv: handle error code on RC query
  [media] dw2102: return error if su3000_power_ctrl() fails
  [media] nova-t-usb2: handle error code on RC query
  [media] technisat-usb2: use DMA buffers for I2C transfers
  [media] pctv452e: don't call BUG_ON() on non-fatal error
  [media] pctv452e: don't do DMA on stack
  [media] nova-t-usb2: don't do DMA on stack
  [media] gp8psk: don't go past the buffer size
  [media] gp8psk: don't do DMA on stack
  [media] dtv5100: don't do DMA on stack
  [media] dtt200u: handle USB control message errors
  [media] dtt200u: don't do DMA on stack
  [media] dtt200u-fe: handle errors on USB control messages
  [media] dtt200u-fe: don't do DMA on stack
  ...
parents 41e6410e 1aeb5b61
Loading
Loading
Loading
Loading
+68 −37
Original line number Original line Diff line number Diff line
@@ -73,23 +73,34 @@ static int flexcop_usb_readwrite_dw(struct flexcop_device *fc, u16 wRegOffsPCI,
	u8 request_type = (read ? USB_DIR_IN : USB_DIR_OUT) | USB_TYPE_VENDOR;
	u8 request_type = (read ? USB_DIR_IN : USB_DIR_OUT) | USB_TYPE_VENDOR;
	u8 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) |
	u8 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) |
		(read ? 0x80 : 0);
		(read ? 0x80 : 0);
	int ret;

	mutex_lock(&fc_usb->data_mutex);
	if (!read)
		memcpy(fc_usb->data, val, sizeof(*val));


	int len = usb_control_msg(fc_usb->udev,
	ret = usb_control_msg(fc_usb->udev,
			read ? B2C2_USB_CTRL_PIPE_IN : B2C2_USB_CTRL_PIPE_OUT,
			read ? B2C2_USB_CTRL_PIPE_IN : B2C2_USB_CTRL_PIPE_OUT,
			request,
			request,
			request_type, /* 0xc0 read or 0x40 write */
			request_type, /* 0xc0 read or 0x40 write */
			wAddress,
			wAddress,
			0,
			0,
			val,
			fc_usb->data,
			sizeof(u32),
			sizeof(u32),
			B2C2_WAIT_FOR_OPERATION_RDW * HZ);
			B2C2_WAIT_FOR_OPERATION_RDW * HZ);


	if (len != sizeof(u32)) {
	if (ret != sizeof(u32)) {
		err("error while %s dword from %d (%d).", read ? "reading" :
		err("error while %s dword from %d (%d).", read ? "reading" :
				"writing", wAddress, wRegOffsPCI);
				"writing", wAddress, wRegOffsPCI);
		return -EIO;
		if (ret >= 0)
			ret = -EIO;
	}
	}
	return 0;

	if (read && ret >= 0)
		memcpy(val, fc_usb->data, sizeof(*val));
	mutex_unlock(&fc_usb->data_mutex);

	return ret;
}
}
/*
/*
 * DKT 010817 - add support for V8 memory read/write and flash update
 * DKT 010817 - add support for V8 memory read/write and flash update
@@ -100,9 +111,14 @@ static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb,
{
{
	u8 request_type = USB_TYPE_VENDOR;
	u8 request_type = USB_TYPE_VENDOR;
	u16 wIndex;
	u16 wIndex;
	int nWaitTime, pipe, len;
	int nWaitTime, pipe, ret;
	wIndex = page << 8;
	wIndex = page << 8;


	if (buflen > sizeof(fc_usb->data)) {
		err("Buffer size bigger than max URB control message\n");
		return -EIO;
	}

	switch (req) {
	switch (req) {
	case B2C2_USB_READ_V8_MEM:
	case B2C2_USB_READ_V8_MEM:
		nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ;
		nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ;
@@ -127,17 +143,32 @@ static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb,
	deb_v8("v8mem: %02x %02x %04x %04x, len: %d\n", request_type, req,
	deb_v8("v8mem: %02x %02x %04x %04x, len: %d\n", request_type, req,
			wAddress, wIndex, buflen);
			wAddress, wIndex, buflen);


	len = usb_control_msg(fc_usb->udev, pipe,
	mutex_lock(&fc_usb->data_mutex);

	if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
		memcpy(fc_usb->data, pbBuffer, buflen);

	ret = usb_control_msg(fc_usb->udev, pipe,
			req,
			req,
			request_type,
			request_type,
			wAddress,
			wAddress,
			wIndex,
			wIndex,
			pbBuffer,
			fc_usb->data,
			buflen,
			buflen,
			nWaitTime * HZ);
			nWaitTime * HZ);
	if (ret != buflen)
		ret = -EIO;


	debug_dump(pbBuffer, len, deb_v8);
	if (ret >= 0) {
	return len == buflen ? 0 : -EIO;
		ret = 0;
		if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
			memcpy(pbBuffer, fc_usb->data, buflen);
	}

	mutex_unlock(&fc_usb->data_mutex);

	debug_dump(pbBuffer, ret, deb_v8);
	return ret;
}
}


#define bytes_left_to_read_on_page(paddr,buflen) \
#define bytes_left_to_read_on_page(paddr,buflen) \
@@ -196,29 +227,6 @@ static int flexcop_usb_get_mac_addr(struct flexcop_device *fc, int extended)
		fc->dvb_adapter.proposed_mac, 6);
		fc->dvb_adapter.proposed_mac, 6);
}
}


#if 0
static int flexcop_usb_utility_req(struct flexcop_usb *fc_usb, int set,
		flexcop_usb_utility_function_t func, u8 extra, u16 wIndex,
		u16 buflen, u8 *pvBuffer)
{
	u16 wValue;
	u8 request_type = (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR;
	int nWaitTime = 2,
	    pipe = set ? B2C2_USB_CTRL_PIPE_OUT : B2C2_USB_CTRL_PIPE_IN, len;
	wValue = (func << 8) | extra;

	len = usb_control_msg(fc_usb->udev,pipe,
			B2C2_USB_UTILITY,
			request_type,
			wValue,
			wIndex,
			pvBuffer,
			buflen,
			nWaitTime * HZ);
	return len == buflen ? 0 : -EIO;
}
#endif

/* usb i2c stuff */
/* usb i2c stuff */
static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
		flexcop_usb_request_t req, flexcop_usb_i2c_function_t func,
		flexcop_usb_request_t req, flexcop_usb_i2c_function_t func,
@@ -226,9 +234,14 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
{
{
	struct flexcop_usb *fc_usb = i2c->fc->bus_specific;
	struct flexcop_usb *fc_usb = i2c->fc->bus_specific;
	u16 wValue, wIndex;
	u16 wValue, wIndex;
	int nWaitTime,pipe,len;
	int nWaitTime, pipe, ret;
	u8 request_type = USB_TYPE_VENDOR;
	u8 request_type = USB_TYPE_VENDOR;


	if (buflen > sizeof(fc_usb->data)) {
		err("Buffer size bigger than max URB control message\n");
		return -EIO;
	}

	switch (func) {
	switch (func) {
	case USB_FUNC_I2C_WRITE:
	case USB_FUNC_I2C_WRITE:
	case USB_FUNC_I2C_MULTIWRITE:
	case USB_FUNC_I2C_MULTIWRITE:
@@ -257,15 +270,32 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
			wValue & 0xff, wValue >> 8,
			wValue & 0xff, wValue >> 8,
			wIndex & 0xff, wIndex >> 8);
			wIndex & 0xff, wIndex >> 8);


	len = usb_control_msg(fc_usb->udev,pipe,
	mutex_lock(&fc_usb->data_mutex);

	if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
		memcpy(fc_usb->data, buf, buflen);

	ret = usb_control_msg(fc_usb->udev, pipe,
			req,
			req,
			request_type,
			request_type,
			wValue,
			wValue,
			wIndex,
			wIndex,
			buf,
			fc_usb->data,
			buflen,
			buflen,
			nWaitTime * HZ);
			nWaitTime * HZ);
	return len == buflen ? 0 : -EREMOTEIO;

	if (ret != buflen)
		ret = -EIO;

	if (ret >= 0) {
		ret = 0;
		if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
			memcpy(buf, fc_usb->data, buflen);
	}

	mutex_unlock(&fc_usb->data_mutex);

	return 0;
}
}


/* actual bus specific access functions,
/* actual bus specific access functions,
@@ -516,6 +546,7 @@ static int flexcop_usb_probe(struct usb_interface *intf,
	/* general flexcop init */
	/* general flexcop init */
	fc_usb = fc->bus_specific;
	fc_usb = fc->bus_specific;
	fc_usb->fc_dev = fc;
	fc_usb->fc_dev = fc;
	mutex_init(&fc_usb->data_mutex);


	fc->read_ibi_reg  = flexcop_usb_read_ibi_reg;
	fc->read_ibi_reg  = flexcop_usb_read_ibi_reg;
	fc->write_ibi_reg = flexcop_usb_write_ibi_reg;
	fc->write_ibi_reg = flexcop_usb_write_ibi_reg;
+4 −0
Original line number Original line Diff line number Diff line
@@ -29,6 +29,10 @@ struct flexcop_usb {


	u8 tmp_buffer[1023+190];
	u8 tmp_buffer[1023+190];
	int tmp_buffer_length;
	int tmp_buffer_length;

	/* for URB control messages */
	u8 data[80];
	struct mutex data_mutex;
};
};


#if 0
#if 0
+30 −4
Original line number Original line Diff line number Diff line
@@ -545,18 +545,30 @@ static void free_sbufs(struct camera_data *cam)
static int write_packet(struct usb_device *udev,
static int write_packet(struct usb_device *udev,
			u8 request, u8 * registers, u16 start, size_t size)
			u8 request, u8 * registers, u16 start, size_t size)
{
{
	unsigned char *buf;
	int ret;

	if (!registers || size <= 0)
	if (!registers || size <= 0)
		return -EINVAL;
		return -EINVAL;


	return usb_control_msg(udev,
	buf = kmalloc(size, GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

	memcpy(buf, registers, size);

	ret = usb_control_msg(udev,
			       usb_sndctrlpipe(udev, 0),
			       usb_sndctrlpipe(udev, 0),
			       request,
			       request,
			       USB_TYPE_VENDOR | USB_RECIP_DEVICE,
			       USB_TYPE_VENDOR | USB_RECIP_DEVICE,
			       start,	/* value */
			       start,	/* value */
			       0,	/* index */
			       0,	/* index */
			       registers,	/* buffer */
			       buf,	/* buffer */
			       size,
			       size,
			       HZ);
			       HZ);

	kfree(buf);
	return ret;
}
}


/****************************************************************************
/****************************************************************************
@@ -567,18 +579,32 @@ static int write_packet(struct usb_device *udev,
static int read_packet(struct usb_device *udev,
static int read_packet(struct usb_device *udev,
		       u8 request, u8 * registers, u16 start, size_t size)
		       u8 request, u8 * registers, u16 start, size_t size)
{
{
	unsigned char *buf;
	int ret;

	if (!registers || size <= 0)
	if (!registers || size <= 0)
		return -EINVAL;
		return -EINVAL;


	return usb_control_msg(udev,
	buf = kmalloc(size, GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

	ret = usb_control_msg(udev,
			       usb_rcvctrlpipe(udev, 0),
			       usb_rcvctrlpipe(udev, 0),
			       request,
			       request,
			       USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_DEVICE,
			       USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_DEVICE,
			       start,	/* value */
			       start,	/* value */
			       0,	/* index */
			       0,	/* index */
			       registers,	/* buffer */
			       buf,	/* buffer */
			       size,
			       size,
			       HZ);
			       HZ);

	if (ret >= 0)
		memcpy(registers, buf, size);

	kfree(buf);

	return ret;
}
}


/******************************************************************************
/******************************************************************************
+181 −138
Original line number Original line Diff line number Diff line
@@ -52,17 +52,16 @@ u8 regmask[8] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
struct af9005_device_state {
struct af9005_device_state {
	u8 sequence;
	u8 sequence;
	int led_state;
	int led_state;
	unsigned char data[256];
	struct mutex data_mutex;
};
};


static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg,
static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg,
			      int readwrite, int type, u8 * values, int len)
			      int readwrite, int type, u8 * values, int len)
{
{
	struct af9005_device_state *st = d->priv;
	struct af9005_device_state *st = d->priv;
	u8 obuf[16] = { 0 };
	u8 command, seq;
	u8 ibuf[17] = { 0 };
	int i, ret;
	u8 command;
	int i;
	int ret;


	if (len < 1) {
	if (len < 1) {
		err("generic read/write, less than 1 byte. Makes no sense.");
		err("generic read/write, less than 1 byte. Makes no sense.");
@@ -73,16 +72,17 @@ static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg,
		return -EINVAL;
		return -EINVAL;
	}
	}


	obuf[0] = 14;		/* rest of buffer length low */
	mutex_lock(&st->data_mutex);
	obuf[1] = 0;		/* rest of buffer length high */
	st->data[0] = 14;		/* rest of buffer length low */
	st->data[1] = 0;		/* rest of buffer length high */


	obuf[2] = AF9005_REGISTER_RW;	/* register operation */
	st->data[2] = AF9005_REGISTER_RW;	/* register operation */
	obuf[3] = 12;		/* rest of buffer length */
	st->data[3] = 12;		/* rest of buffer length */


	obuf[4] = st->sequence++;	/* sequence number */
	st->data[4] = seq = st->sequence++;	/* sequence number */


	obuf[5] = (u8) (reg >> 8);	/* register address */
	st->data[5] = (u8) (reg >> 8);	/* register address */
	obuf[6] = (u8) (reg & 0xff);
	st->data[6] = (u8) (reg & 0xff);


	if (type == AF9005_OFDM_REG) {
	if (type == AF9005_OFDM_REG) {
		command = AF9005_CMD_OFDM_REG;
		command = AF9005_CMD_OFDM_REG;
@@ -96,51 +96,52 @@ static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg,
	command |= readwrite;
	command |= readwrite;
	if (readwrite == AF9005_CMD_WRITE)
	if (readwrite == AF9005_CMD_WRITE)
		for (i = 0; i < len; i++)
		for (i = 0; i < len; i++)
			obuf[8 + i] = values[i];
			st->data[8 + i] = values[i];
	else if (type == AF9005_TUNER_REG)
	else if (type == AF9005_TUNER_REG)
		/* read command for tuner, the first byte contains the i2c address */
		/* read command for tuner, the first byte contains the i2c address */
		obuf[8] = values[0];
		st->data[8] = values[0];
	obuf[7] = command;
	st->data[7] = command;


	ret = dvb_usb_generic_rw(d, obuf, 16, ibuf, 17, 0);
	ret = dvb_usb_generic_rw(d, st->data, 16, st->data, 17, 0);
	if (ret)
	if (ret)
		return ret;
		goto ret;


	/* sanity check */
	/* sanity check */
	if (ibuf[2] != AF9005_REGISTER_RW_ACK) {
	if (st->data[2] != AF9005_REGISTER_RW_ACK) {
		err("generic read/write, wrong reply code.");
		err("generic read/write, wrong reply code.");
		return -EIO;
		ret = -EIO;
		goto ret;
	}
	}
	if (ibuf[3] != 0x0d) {
	if (st->data[3] != 0x0d) {
		err("generic read/write, wrong length in reply.");
		err("generic read/write, wrong length in reply.");
		return -EIO;
		ret = -EIO;
		goto ret;
	}
	}
	if (ibuf[4] != obuf[4]) {
	if (st->data[4] != seq) {
		err("generic read/write, wrong sequence in reply.");
		err("generic read/write, wrong sequence in reply.");
		return -EIO;
		ret = -EIO;
		goto ret;
	}
	}
	/*
	/*
	   Windows driver doesn't check these fields, in fact sometimes
	 * In thesis, both input and output buffers should have
	   the register in the reply is different that what has been sent
	 * identical values for st->data[5] to st->data[8].

	 * However, windows driver doesn't check these fields, in fact
	   if (ibuf[5] != obuf[5] || ibuf[6] != obuf[6]) {
	 * sometimes the register in the reply is different that what
	   err("generic read/write, wrong register in reply.");
	 * has been sent
	   return -EIO;
	   }
	   if (ibuf[7] != command) {
	   err("generic read/write wrong command in reply.");
	   return -EIO;
	   }
	 */
	 */
	if (ibuf[16] != 0x01) {
	if (st->data[16] != 0x01) {
		err("generic read/write wrong status code in reply.");
		err("generic read/write wrong status code in reply.");
		return -EIO;
		ret = -EIO;
		goto ret;
	}
	}

	if (readwrite == AF9005_CMD_READ)
	if (readwrite == AF9005_CMD_READ)
		for (i = 0; i < len; i++)
		for (i = 0; i < len; i++)
			values[i] = ibuf[8 + i];
			values[i] = st->data[8 + i];


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


}
}


@@ -464,8 +465,7 @@ int af9005_send_command(struct dvb_usb_device *d, u8 command, u8 * wbuf,
	struct af9005_device_state *st = d->priv;
	struct af9005_device_state *st = d->priv;


	int ret, i, packet_len;
	int ret, i, packet_len;
	u8 buf[64];
	u8 seq;
	u8 ibuf[64];


	if (wlen < 0) {
	if (wlen < 0) {
		err("send command, wlen less than 0 bytes. Makes no sense.");
		err("send command, wlen less than 0 bytes. Makes no sense.");
@@ -480,94 +480,97 @@ int af9005_send_command(struct dvb_usb_device *d, u8 command, u8 * wbuf,
		return -EINVAL;
		return -EINVAL;
	}
	}
	packet_len = wlen + 5;
	packet_len = wlen + 5;
	buf[0] = (u8) (packet_len & 0xff);

	buf[1] = (u8) ((packet_len & 0xff00) >> 8);
	mutex_lock(&st->data_mutex);


	buf[2] = 0x26;		/* packet type */
	st->data[0] = (u8) (packet_len & 0xff);
	buf[3] = wlen + 3;
	st->data[1] = (u8) ((packet_len & 0xff00) >> 8);
	buf[4] = st->sequence++;

	buf[5] = command;
	st->data[2] = 0x26;		/* packet type */
	buf[6] = wlen;
	st->data[3] = wlen + 3;
	st->data[4] = seq = st->sequence++;
	st->data[5] = command;
	st->data[6] = wlen;
	for (i = 0; i < wlen; i++)
	for (i = 0; i < wlen; i++)
		buf[7 + i] = wbuf[i];
		st->data[7 + i] = wbuf[i];
	ret = dvb_usb_generic_rw(d, buf, wlen + 7, ibuf, rlen + 7, 0);
	ret = dvb_usb_generic_rw(d, st->data, wlen + 7, st->data, rlen + 7, 0);
	if (ret)
	if (st->data[2] != 0x27) {
		return ret;
	if (ibuf[2] != 0x27) {
		err("send command, wrong reply code.");
		err("send command, wrong reply code.");
		return -EIO;
		ret = -EIO;
	}
	} else if (st->data[4] != seq) {
	if (ibuf[4] != buf[4]) {
		err("send command, wrong sequence in reply.");
		err("send command, wrong sequence in reply.");
		return -EIO;
		ret = -EIO;
	}
	} else if (st->data[5] != 0x01) {
	if (ibuf[5] != 0x01) {
		err("send command, wrong status code in reply.");
		err("send command, wrong status code in reply.");
		return -EIO;
		ret = -EIO;
	}
	} else if (st->data[6] != rlen) {
	if (ibuf[6] != rlen) {
		err("send command, invalid data length in reply.");
		err("send command, invalid data length in reply.");
		return -EIO;
		ret = -EIO;
	}
	}
	if (!ret) {
		for (i = 0; i < rlen; i++)
		for (i = 0; i < rlen; i++)
		rbuf[i] = ibuf[i + 7];
			rbuf[i] = st->data[i + 7];
	return 0;
	}

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


int af9005_read_eeprom(struct dvb_usb_device *d, u8 address, u8 * values,
int af9005_read_eeprom(struct dvb_usb_device *d, u8 address, u8 * values,
		       int len)
		       int len)
{
{
	struct af9005_device_state *st = d->priv;
	struct af9005_device_state *st = d->priv;
	u8 obuf[16], ibuf[14];
	u8 seq;
	int ret, i;
	int ret, i;


	memset(obuf, 0, sizeof(obuf));
	mutex_lock(&st->data_mutex);
	memset(ibuf, 0, sizeof(ibuf));


	obuf[0] = 14;		/* length of rest of packet low */
	memset(st->data, 0, sizeof(st->data));
	obuf[1] = 0;		/* length of rest of packer high */


	obuf[2] = 0x2a;		/* read/write eeprom */
	st->data[0] = 14;		/* length of rest of packet low */
	st->data[1] = 0;		/* length of rest of packer high */


	obuf[3] = 12;		/* size */
	st->data[2] = 0x2a;		/* read/write eeprom */


	obuf[4] = st->sequence++;
	st->data[3] = 12;		/* size */


	obuf[5] = 0;		/* read */
	st->data[4] = seq = st->sequence++;


	obuf[6] = len;
	st->data[5] = 0;		/* read */
	obuf[7] = address;

	ret = dvb_usb_generic_rw(d, obuf, 16, ibuf, 14, 0);
	st->data[6] = len;
	if (ret)
	st->data[7] = address;
		return ret;
	ret = dvb_usb_generic_rw(d, st->data, 16, st->data, 14, 0);
	if (ibuf[2] != 0x2b) {
	if (st->data[2] != 0x2b) {
		err("Read eeprom, invalid reply code");
		err("Read eeprom, invalid reply code");
		return -EIO;
		ret = -EIO;
	}
	} else if (st->data[3] != 10) {
	if (ibuf[3] != 10) {
		err("Read eeprom, invalid reply length");
		err("Read eeprom, invalid reply length");
		return -EIO;
		ret = -EIO;
	}
	} else if (st->data[4] != seq) {
	if (ibuf[4] != obuf[4]) {
		err("Read eeprom, wrong sequence in reply ");
		err("Read eeprom, wrong sequence in reply ");
		return -EIO;
		ret = -EIO;
	}
	} else if (st->data[5] != 1) {
	if (ibuf[5] != 1) {
		err("Read eeprom, wrong status in reply ");
		err("Read eeprom, wrong status in reply ");
		return -EIO;
		ret = -EIO;
	}
	}
	for (i = 0; i < len; i++) {

		values[i] = ibuf[6 + i];
	if (!ret) {
		for (i = 0; i < len; i++)
			values[i] = st->data[6 + i];
	}
	}
	return 0;
	mutex_unlock(&st->data_mutex);

	return ret;
}
}


static int af9005_boot_packet(struct usb_device *udev, int type, u8 * reply)
static int af9005_boot_packet(struct usb_device *udev, int type, u8 *reply,
			      u8 *buf, int size)
{
{
	u8 buf[FW_BULKOUT_SIZE + 2];
	u16 checksum;
	u16 checksum;
	int act_len, i, ret;
	int act_len, i, ret;
	memset(buf, 0, sizeof(buf));

	memset(buf, 0, size);
	buf[0] = (u8) (FW_BULKOUT_SIZE & 0xff);
	buf[0] = (u8) (FW_BULKOUT_SIZE & 0xff);
	buf[1] = (u8) ((FW_BULKOUT_SIZE >> 8) & 0xff);
	buf[1] = (u8) ((FW_BULKOUT_SIZE >> 8) & 0xff);
	switch (type) {
	switch (type) {
@@ -720,15 +723,21 @@ static int af9005_download_firmware(struct usb_device *udev, const struct firmwa
{
{
	int i, packets, ret, act_len;
	int i, packets, ret, act_len;


	u8 buf[FW_BULKOUT_SIZE + 2];
	u8 *buf;
	u8 reply;
	u8 reply;


	ret = af9005_boot_packet(udev, FW_CONFIG, &reply);
	buf = kmalloc(FW_BULKOUT_SIZE + 2, GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

	ret = af9005_boot_packet(udev, FW_CONFIG, &reply, buf,
				 FW_BULKOUT_SIZE + 2);
	if (ret)
	if (ret)
		return ret;
		goto err;
	if (reply != 0x01) {
	if (reply != 0x01) {
		err("before downloading firmware, FW_CONFIG expected 0x01, received 0x%x", reply);
		err("before downloading firmware, FW_CONFIG expected 0x01, received 0x%x", reply);
		return -EIO;
		ret = -EIO;
		goto err;
	}
	}
	packets = fw->size / FW_BULKOUT_SIZE;
	packets = fw->size / FW_BULKOUT_SIZE;
	buf[0] = (u8) (FW_BULKOUT_SIZE & 0xff);
	buf[0] = (u8) (FW_BULKOUT_SIZE & 0xff);
@@ -743,28 +752,35 @@ static int af9005_download_firmware(struct usb_device *udev, const struct firmwa
				   buf, FW_BULKOUT_SIZE + 2, &act_len, 1000);
				   buf, FW_BULKOUT_SIZE + 2, &act_len, 1000);
		if (ret) {
		if (ret) {
			err("firmware download failed at packet %d with code %d", i, ret);
			err("firmware download failed at packet %d with code %d", i, ret);
			return ret;
			goto err;
		}
		}
	}
	}
	ret = af9005_boot_packet(udev, FW_CONFIRM, &reply);
	ret = af9005_boot_packet(udev, FW_CONFIRM, &reply,
				 buf, FW_BULKOUT_SIZE + 2);
	if (ret)
	if (ret)
		return ret;
		goto err;
	if (reply != (u8) (packets & 0xff)) {
	if (reply != (u8) (packets & 0xff)) {
		err("after downloading firmware, FW_CONFIRM expected 0x%x, received 0x%x", packets & 0xff, reply);
		err("after downloading firmware, FW_CONFIRM expected 0x%x, received 0x%x", packets & 0xff, reply);
		return -EIO;
		ret = -EIO;
		goto err;
	}
	}
	ret = af9005_boot_packet(udev, FW_BOOT, &reply);
	ret = af9005_boot_packet(udev, FW_BOOT, &reply, buf,
				 FW_BULKOUT_SIZE + 2);
	if (ret)
	if (ret)
		return ret;
		goto err;
	ret = af9005_boot_packet(udev, FW_CONFIG, &reply);
	ret = af9005_boot_packet(udev, FW_CONFIG, &reply, buf,
				 FW_BULKOUT_SIZE + 2);
	if (ret)
	if (ret)
		return ret;
		goto err;
	if (reply != 0x02) {
	if (reply != 0x02) {
		err("after downloading firmware, FW_CONFIG expected 0x02, received 0x%x", reply);
		err("after downloading firmware, FW_CONFIG expected 0x02, received 0x%x", reply);
		return -EIO;
		ret = -EIO;
		goto err;
	}
	}


	return 0;
err:
	kfree(buf);
	return ret;


}
}


@@ -823,53 +839,59 @@ static int af9005_rc_query(struct dvb_usb_device *d, u32 * event, int *state)
{
{
	struct af9005_device_state *st = d->priv;
	struct af9005_device_state *st = d->priv;
	int ret, len;
	int ret, len;

	u8 seq;
	u8 obuf[5];
	u8 ibuf[256];


	*state = REMOTE_NO_KEY_PRESSED;
	*state = REMOTE_NO_KEY_PRESSED;
	if (rc_decode == NULL) {
	if (rc_decode == NULL) {
		/* it shouldn't never come here */
		/* it shouldn't never come here */
		return 0;
		return 0;
	}
	}

	mutex_lock(&st->data_mutex);

	/* deb_info("rc_query\n"); */
	/* deb_info("rc_query\n"); */
	obuf[0] = 3;		/* rest of packet length low */
	st->data[0] = 3;		/* rest of packet length low */
	obuf[1] = 0;		/* rest of packet lentgh high */
	st->data[1] = 0;		/* rest of packet lentgh high */
	obuf[2] = 0x40;		/* read remote */
	st->data[2] = 0x40;		/* read remote */
	obuf[3] = 1;		/* rest of packet length */
	st->data[3] = 1;		/* rest of packet length */
	obuf[4] = st->sequence++;	/* sequence number */
	st->data[4] = seq = st->sequence++;	/* sequence number */
	ret = dvb_usb_generic_rw(d, obuf, 5, ibuf, 256, 0);
	ret = dvb_usb_generic_rw(d, st->data, 5, st->data, 256, 0);
	if (ret) {
	if (ret) {
		err("rc query failed");
		err("rc query failed");
		return ret;
		goto ret;
	}
	}
	if (ibuf[2] != 0x41) {
	if (st->data[2] != 0x41) {
		err("rc query bad header.");
		err("rc query bad header.");
		return -EIO;
		ret = -EIO;
	}
		goto ret;
	if (ibuf[4] != obuf[4]) {
	} else if (st->data[4] != seq) {
		err("rc query bad sequence.");
		err("rc query bad sequence.");
		return -EIO;
		ret = -EIO;
		goto ret;
	}
	}
	len = ibuf[5];
	len = st->data[5];
	if (len > 246) {
	if (len > 246) {
		err("rc query invalid length");
		err("rc query invalid length");
		return -EIO;
		ret = -EIO;
		goto ret;
	}
	}
	if (len > 0) {
	if (len > 0) {
		deb_rc("rc data (%d) ", len);
		deb_rc("rc data (%d) ", len);
		debug_dump((ibuf + 6), len, deb_rc);
		debug_dump((st->data + 6), len, deb_rc);
		ret = rc_decode(d, &ibuf[6], len, event, state);
		ret = rc_decode(d, &st->data[6], len, event, state);
		if (ret) {
		if (ret) {
			err("rc_decode failed");
			err("rc_decode failed");
			return ret;
			goto ret;
		} else {
		} else {
			deb_rc("rc_decode state %x event %x\n", *state, *event);
			deb_rc("rc_decode state %x event %x\n", *state, *event);
			if (*state == REMOTE_KEY_REPEAT)
			if (*state == REMOTE_KEY_REPEAT)
				*event = d->last_event;
				*event = d->last_event;
		}
		}
	}
	}
	return 0;

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


static int af9005_power_ctrl(struct dvb_usb_device *d, int onoff)
static int af9005_power_ctrl(struct dvb_usb_device *d, int onoff)
@@ -953,10 +975,16 @@ static int af9005_identify_state(struct usb_device *udev,
				 int *cold)
				 int *cold)
{
{
	int ret;
	int ret;
	u8 reply;
	u8 reply, *buf;
	ret = af9005_boot_packet(udev, FW_CONFIG, &reply);

	buf = kmalloc(FW_BULKOUT_SIZE + 2, GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

	ret = af9005_boot_packet(udev, FW_CONFIG, &reply,
				 buf, FW_BULKOUT_SIZE + 2);
	if (ret)
	if (ret)
		return ret;
		goto err;
	deb_info("result of FW_CONFIG in identify state %d\n", reply);
	deb_info("result of FW_CONFIG in identify state %d\n", reply);
	if (reply == 0x01)
	if (reply == 0x01)
		*cold = 1;
		*cold = 1;
@@ -965,7 +993,10 @@ static int af9005_identify_state(struct usb_device *udev,
	else
	else
		return -EIO;
		return -EIO;
	deb_info("Identify state cold = %d\n", *cold);
	deb_info("Identify state cold = %d\n", *cold);
	return 0;

err:
	kfree(buf);
	return ret;
}
}


static struct dvb_usb_device_properties af9005_properties;
static struct dvb_usb_device_properties af9005_properties;
@@ -973,8 +1004,20 @@ static struct dvb_usb_device_properties af9005_properties;
static int af9005_usb_probe(struct usb_interface *intf,
static int af9005_usb_probe(struct usb_interface *intf,
			    const struct usb_device_id *id)
			    const struct usb_device_id *id)
{
{
	return dvb_usb_device_init(intf, &af9005_properties,
	struct dvb_usb_device *d;
				   THIS_MODULE, NULL, adapter_nr);
	struct af9005_device_state *st;
	int ret;

	ret = dvb_usb_device_init(intf, &af9005_properties,
				  THIS_MODULE, &d, adapter_nr);

	if (ret < 0)
		return ret;

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

	return 0;
}
}


enum af9005_usb_table_entry {
enum af9005_usb_table_entry {
+65 −25
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,38 +52,57 @@ 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;


	return 0;
	return ret;
}
}


static struct rc_map_table rc_map_cinergyt2_table[] = {
static struct rc_map_table rc_map_cinergyt2_table[] = {
@@ -141,13 +162,18 @@ 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, ret;
	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;

	ret = dvb_usb_generic_rw(d, st->data, 1, st->data, 5, 0);
	if (ret < 0)
		goto ret;

	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 +183,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;
}
}




Loading