// SPDX-License-Identifier: GPL-2.0-only /* Linux driver for devices based on the DiBcom DiB0700 USB bridge * * Copyright (C) 2005-6 DiBcom, SA
*/ #include"dib0700.h"
staticint nb_packet_buffer_size = 21;
module_param(nb_packet_buffer_size, int, 0644);
MODULE_PARM_DESC(nb_packet_buffer_size, "Set the dib0700 driver data buffer size. This parameter corresponds to the number of TS packets. The actual size of the data buffer corresponds to this parameter multiplied by 188 (default: 21)");
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
u32 *romversion, u32 *ramversion, u32 *fwtype)
{ struct dib0700_state *st = d->priv; int ret;
if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
err("could not acquire lock"); return -EINTR;
}
if (txlen < 2) {
err("tx buffer length is smaller than 2. Makes no sense."); return -EINVAL;
} if (txlen > 4) {
err("tx buffer length is larger than 4. Not supported."); return -EINVAL;
}
deb_data(">>> ");
debug_dump(tx,txlen,deb_data);
value = ((txlen - 2) << 8) | tx[1];
index = 0; if (txlen > 2)
index |= (tx[2] << 8); if (txlen > 3)
index |= tx[3];
deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets);
ret = dib0700_ctrl_wr(d, st->buf, 3);
mutex_unlock(&d->usb_mutex);
} else {
deb_info("this firmware does not allow to change the USB xfer len\n");
ret = -EIO;
}
return ret;
}
/* * I2C master xfer function (supported in 1.20 firmware)
*/ staticint dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
{ /* The new i2c firmware messages are more reliable and in particular
properly support i2c read calls not preceded by a write */
/* Ensure nobody else hits the i2c bus while we're sending our
sequence of messages, (such as the remote control thread) */ if (mutex_lock_interruptible(&d->i2c_mutex) < 0) return -EINTR;
for (i = 0; i < num; i++) { if (i == 0) { /* First message in the transaction */
en_start = 1;
} elseif (!(msg[i].flags & I2C_M_NOSTART)) { /* Device supports repeated-start */
en_start = 1;
} else { /* Not the first packet and device doesn't support
repeated start */
en_start = 0;
} if (i == (num - 1)) { /* Last message in the transaction */
en_stop = 1;
}
/* * I2C master xfer function (pre-1.20 firmware)
*/ staticint dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
{ struct dvb_usb_device *d = i2c_get_adapdata(adap); struct dib0700_state *st = d->priv; int i, len, result;
if (mutex_lock_interruptible(&d->i2c_mutex) < 0) return -EINTR; if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
err("could not acquire lock");
mutex_unlock(&d->i2c_mutex); return -EINTR;
}
for (i = 0; i < num; i++) { /* fill in the address */
st->buf[1] = msg[i].addr << 1; /* fill the buffer */ if (msg[i].len > sizeof(st->buf) - 2) {
deb_info("i2c xfer to big: %d\n",
msg[i].len);
result = -EIO; goto unlock;
}
memcpy(&st->buf[2], msg[i].buf, msg[i].len);
/* write/read request */ if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
st->buf[0] = REQUEST_I2C_READ;
st->buf[1] |= 1;
/* special thing in the current firmware: when length is zero the read-failed */
len = dib0700_ctrl_rd(d, st->buf, msg[i].len + 2,
st->buf, msg[i + 1].len); if (len <= 0) {
deb_info("I2C read failed on address 0x%02x\n",
msg[i].addr);
result = -EIO; goto unlock;
}
if (msg[i + 1].len > sizeof(st->buf)) {
deb_info("i2c xfer buffer to small for %d\n",
msg[i].len);
result = -EIO; goto unlock;
}
memcpy(msg[i + 1].buf, st->buf, msg[i + 1].len);
msg[i+1].len = len;
i++;
} else {
st->buf[0] = REQUEST_I2C_WRITE;
result = dib0700_ctrl_wr(d, st->buf, msg[i].len + 2); if (result < 0) goto unlock;
}
}
result = i;
unlock:
mutex_unlock(&d->usb_mutex);
mutex_unlock(&d->i2c_mutex);
/* set the buffer size - DVB-USB is allocating URB buffers
* only after the firwmare download was successful */ for (i = 0; i < dib0700_device_count; i++) { for (adap_num = 0; adap_num < dib0700_devices[i].num_adapters;
adap_num++) { if (fw_version >= 0x10201) {
dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize = 188*nb_packet_buffer_size;
} else { /* for fw version older than 1.20.1,
* the buffersize has to be n times 512 */
dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize = ((188*nb_packet_buffer_size+188/2)/512)*512; if (dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize < 512)
dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize = 512;
}
}
}
out:
kfree(buf); return ret;
}
int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
{ struct dib0700_state *st = adap->dev->priv; int ret, adapt_nr;
if ((onoff != 0) && (st->fw_version >= 0x10201)) { /* for firmware later than 1.20.1,
* the USB xfer length can be set */
ret = dib0700_set_usb_xfer_len(adap->dev,
st->nb_packet_buffer_size); if (ret < 0) {
deb_info("can not set the USB xfer len\n"); return ret;
}
}
mutex_lock(&adap->dev->usb_mutex);
st->buf[0] = REQUEST_ENABLE_VIDEO; /* this bit gives a kind of command,
* rather than enabling something or not */
st->buf[1] = (onoff << 4) | 0x00;
if ((adap->fe_adap[0].stream.props.endpoint != 2)
&& (adap->fe_adap[0].stream.props.endpoint != 3)) {
deb_info("the endpoint number (%i) is not correct, use the adapter id instead\n",
adap->fe_adap[0].stream.props.endpoint);
adapt_nr = adap->id;
} else {
adapt_nr = adap->fe_adap[0].stream.props.endpoint - 2;
}
deb_info("%s()\n", __func__); if (d->rc_dev == NULL) { /* This will occur if disable_rc_polling=1 */
kfree(purb->transfer_buffer);
usb_free_urb(purb); return;
}
/* * Some devices like the Hauppauge NovaTD model 52009 use an interrupt * endpoint, while others use a bulk one.
*/
e = &intf->cur_altsetting->endpoint[rc_ep].desc; if (usb_endpoint_dir_in(e)) { if (usb_endpoint_xfer_bulk(e)) {
pipe = usb_rcvbulkpipe(d->udev, rc_ep);
usb_fill_bulk_urb(purb, d->udev, pipe,
purb->transfer_buffer,
RC_MSG_SIZE_V1_20,
dib0700_rc_urb_completion, d);
MODULE_FIRMWARE("dvb-usb-dib0700-1.20.fw");
MODULE_AUTHOR("Patrick Boettcher ");
MODULE_DESCRIPTION("Driver for devices based on DiBcom DiB0700 - USB bridge");
MODULE_VERSION("1.0");
MODULE_LICENSE("GPL");
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.