media: usb/dvb-usb: Replace strlcpy() with strscpy()

This commit is contained in:
CrazyCat
2024-03-10 21:00:07 +02:00
parent 804a1febcc
commit 508dae75e4
24 changed files with 1592 additions and 1592 deletions

View File

@@ -259,7 +259,7 @@ static int tbsqboxs1_frontend_attach(struct dvb_usb_adapter *d)
tbsqboxs1_op_rw(u->udev, 0x8a, 0, 0,
buf, 2, TBSQBOX_WRITE_MSG);
strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
strscpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
return 0;
}
}

View File

@@ -278,7 +278,7 @@ static int tbsqbox2_frontend_attach(struct dvb_usb_adapter *d)
tbsqbox2_op_rw(u->udev, 0x8a, 0, 0,
buf, 2, TBSQBOX_WRITE_MSG);
strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
strscpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
return 0;
}
}

View File

@@ -224,7 +224,7 @@ static int tbsqbox22_frontend_attach(struct dvb_usb_adapter *d)
buf[1] = 1;
tbsqbox22_op_rw(u->udev, 0x8a, 0, 0, buf, 2, TBSQBOX_WRITE_MSG);
strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
strscpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
return 0;
err:

View File

@@ -601,7 +601,7 @@ static int tbsqbox2ci_frontend_attach(struct dvb_usb_adapter *d)
tbsqbox2ci_init(d);
strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
strscpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
return 0;
}
}

View File

@@ -272,7 +272,7 @@ static int tbsqboxs2_frontend_attach(struct dvb_usb_adapter *d)
tbsqboxs2_op_rw(u->udev, 0x8a, 0, 0,
buf, 2, TBSQBOX_WRITE_MSG);
strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
strscpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
return 0;
}

View File

@@ -188,7 +188,7 @@ static int tbs5220_frontend_attach(struct dvb_usb_adapter *adap)
si2168_config.ts_mode = SI2168_TS_PARALLEL;
si2168_config.ts_clock_gapped = true;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2168", I2C_NAME_SIZE);
strscpy(info.type, "si2168", I2C_NAME_SIZE);
info.addr = 0x64;
info.platform_data = &si2168_config;
request_module(info.type);
@@ -206,7 +206,7 @@ static int tbs5220_frontend_attach(struct dvb_usb_adapter *adap)
si2157_config.fe = adap->fe_adap[0].fe;
si2157_config.if_port = 1;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
strscpy(info.type, "si2157", I2C_NAME_SIZE);
info.addr = 0x60;
info.platform_data = &si2157_config;
request_module(info.type);
@@ -245,7 +245,7 @@ static int tbs5220_frontend_attach(struct dvb_usb_adapter *adap)
tbs5220_op_rw(d->udev, 0x8a, 0, 0,
buf, 2, TBS5220_WRITE_MSG);
strlcpy(adap->fe_adap->fe->ops.info.name,d->props.devices[0].name,52);
strscpy(adap->fe_adap->fe->ops.info.name,d->props.devices[0].name,52);
return 0;
}

View File

@@ -1,319 +1,319 @@
/*
* TurboSight TBS 5230 driver
*
* Copyright (c) 2022/06 Davin zhang<Davin@tbsdtv.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, version 2.
*
*/
#include <linux/version.h>
#include "tbs5230.h"
#include "cxd2878.h"
#define TBS5230_READ_MSG 0
#define TBS5230_WRITE_MSG 1
struct tbs5230_state {
u8 initialized;
};
/* debug */
static int dvb_usb_tbs5230_debug;
module_param_named(debug, dvb_usb_tbs5230_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))."
DVB_USB_DEBUG_STATUS);
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static int tbs5230_op_rw(struct usb_device *dev, u8 request, u16 value,
u16 index, u8 * data, u16 len, int flags)
{
int ret;
void *u8buf;
unsigned int pipe = (flags == TBS5230_READ_MSG) ?
usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
u8 request_type = (flags == TBS5230_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
u8buf = kmalloc(len, GFP_KERNEL);
if (!u8buf)
return -ENOMEM;
if (flags == TBS5230_WRITE_MSG)
memcpy(u8buf, data, len);
ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
value, index , u8buf, len, 2000);
if (flags == TBS5230_READ_MSG)
memcpy(data, u8buf, len);
kfree(u8buf);
return ret;
}
/* I2C */
static int tbs5230_i2c_transfer(struct i2c_adapter *adap,
struct i2c_msg msg[], int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
int i = 0;
u8 buf6[35];
u8 inbuf[35];
if (!d)
return -ENODEV;
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
switch (num) {
case 2:
buf6[0]=msg[1].len;//lenth
buf6[1]=msg[0].addr<<1;//demod addr
//register
buf6[2] = msg[0].buf[0];
tbs5230_op_rw(d->udev, 0x90, 0, 0,
buf6, 3, TBS5230_WRITE_MSG);
//msleep(5);
tbs5230_op_rw(d->udev, 0x91, 0, 0,
inbuf, buf6[0], TBS5230_READ_MSG);
memcpy(msg[1].buf, inbuf, msg[1].len);
break;
case 1:
buf6[0] = msg[0].len+1;//lenth
buf6[1] = msg[0].addr<<1;//addr
for(i=0;i<msg[0].len;i++) {
buf6[2+i] = msg[0].buf[i];//register
}
tbs5230_op_rw(d->udev, 0x80, 0, 0,
buf6, msg[0].len+2, TBS5230_WRITE_MSG);
break;
}
mutex_unlock(&d->i2c_mutex);
return num;
}
static u32 tbs5230_i2c_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_I2C;
}
static struct i2c_algorithm tbs5230_i2c_algo = {
.master_xfer = tbs5230_i2c_transfer,
.functionality = tbs5230_i2c_func,
};
static int tbs5230_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
{
int i,ret;
u8 ibuf[3] = {0, 0,0};
u8 eeprom[256], eepromline[16];
for (i = 0; i < 256; i++) {
ibuf[0]=1;//lenth
ibuf[1]=0xa0;//eeprom addr
ibuf[2]=i;//register
ret = tbs5230_op_rw(d->udev, 0x90, 0, 0,
ibuf, 3, TBS5230_WRITE_MSG);
ret = tbs5230_op_rw(d->udev, 0x91, 0, 0,
ibuf, 1, TBS5230_READ_MSG);
if (ret < 0) {
err("read eeprom failed.");
return -1;
} else {
eepromline[i%16] = ibuf[0];
eeprom[i] = ibuf[0];
}
if ((i % 16) == 15) {
deb_xfer("%02x: ", i - 15);
debug_dump(eepromline, 16, deb_xfer);
}
}
memcpy(mac, eeprom + 16, 6);
return 0;
};
static struct dvb_usb_device_properties tbs5230_properties;
static struct cxd2878_config tbs5230_cfg = {
.addr_slvt = 0x64,
.xtal = SONY_DEMOD_XTAL_24000KHz,
.tuner_addr = 0x60,
.tuner_xtal = SONY_ASCOT3_XTAL_24000KHz,
.ts_mode = 1,
.ts_ser_data = 0,
.ts_clk = 1,
.ts_clk_mask= 1,
.ts_valid = 0,
.atscCoreDisable = 0,
.lock_flag = 1,
.write_properties = NULL,
.read_properties = NULL,
};
static int tbs5230_frontend_attach(struct dvb_usb_adapter*adap)
{
struct dvb_usb_device *d = adap->dev;
adap->fe_adap[0].fe = dvb_attach(cxd2878_attach, &tbs5230_cfg, &d->i2c_adap);
if(adap->fe_adap[0].fe!=NULL){
strlcpy(adap->fe_adap[0].fe->ops.info.name,d->props.devices[0].name,52);
return 0;
}
return -EIO;
}
static struct usb_device_id tbs5230_table[] = {
{USB_DEVICE(0x734c, 0x5230)},
{ }
};
MODULE_DEVICE_TABLE(usb, tbs5230_table);
static int tbs5230_load_firmware(struct usb_device *dev,
const struct firmware *frmwr)
{
u8 *b, *p;
int ret = 0, i;
u8 reset;
const struct firmware *fw;
switch (dev->descriptor.idProduct) {
case 0x5230:
ret = request_firmware(&fw, tbs5230_properties.firmware, &dev->dev);
if (ret != 0) {
err("did not find the firmware file. (%s) "
"Please see linux/Documentation/dvb/ for more details "
"on firmware-problems.", tbs5230_properties.firmware);
return ret;
}
break;
default:
fw = frmwr;
break;
}
info("start downloading TBS5230 firmware");
p = kmalloc(fw->size, GFP_KERNEL);
reset = 1;
/*stop the CPU*/
tbs5230_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, TBS5230_WRITE_MSG);
tbs5230_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, TBS5230_WRITE_MSG);
if (p != NULL) {
memcpy(p, fw->data, fw->size);
for (i = 0; i < fw->size; i += 0x40) {
b = (u8 *) p + i;
if (tbs5230_op_rw(dev, 0xa0, i, 0, b , 0x40,
TBS5230_WRITE_MSG) != 0x40) {
err("error while transferring firmware");
ret = -EINVAL;
break;
}
}
/* restart the CPU */
reset = 0;
if (ret || tbs5230_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,
TBS5230_WRITE_MSG) != 1) {
err("could not restart the USB controller CPU.");
ret = -EINVAL;
}
if (ret || tbs5230_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,
TBS5230_WRITE_MSG) != 1) {
err("could not restart the USB controller CPU.");
ret = -EINVAL;
}
msleep(100);
kfree(p);
}
return ret;
}
static struct dvb_usb_device_properties tbs5230_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = DEVICE_SPECIFIC,
.firmware = "dvb-usb-id5230.fw",
.size_of_priv = sizeof(struct tbs5230_state),
.no_reconnect = 1,
.i2c_algo = &tbs5230_i2c_algo,
.generic_bulk_ctrl_endpoint = 0x81,
.num_adapters = 1,
.download_firmware = tbs5230_load_firmware,
.read_mac_address = tbs5230_read_mac_address,
.adapter = {{
.num_frontends = 1,
.fe = {{
.frontend_attach = tbs5230_frontend_attach,
.streaming_ctrl = NULL,
.tuner_attach = NULL,
.stream = {
.type = USB_BULK,
.count = 8,
.endpoint = 0x82,
.u = {
.bulk = {
.buffersize = 4096,
}
}
},
}
},
}},
.num_device_descs = 1,
.devices = {
{"TurboSight TBS 5230 DVB-T2/T/C(j83-a/b/c),ISDB-T,ATSC1.0",
{&tbs5230_table[0], NULL},
{NULL},
}
}
};
static int tbs5230_probe(struct usb_interface *intf,
const struct usb_device_id*id)
{
if(0 == dvb_usb_device_init(intf,&tbs5230_properties,
THIS_MODULE,NULL,adapter_nr)){
return 0;
}
return -ENODEV;
}
static struct usb_driver tbs5230_driver ={
.name = "tbs5230",
.probe = tbs5230_probe,
.disconnect = dvb_usb_device_exit,
.id_table = tbs5230_table,
};
static int __init tbs5230_module_init(void)
{
int ret = usb_register(&tbs5230_driver);
if(ret)
err("usb_register failed.Error number %d",ret);
return ret;
}
static void __exit tbs5230_module_exit(void)
{
usb_deregister(&tbs5230_driver);
}
module_init(tbs5230_module_init);
module_exit(tbs5230_module_exit);
MODULE_AUTHOR("TBSDTV,Davin<Davin@tbsdtv.com>");
MODULE_DESCRIPTION("Turbosight TBS5230 drivers");
MODULE_VERSION("1.0");
MODULE_LICENSE("GPL");
/*
* TurboSight TBS 5230 driver
*
* Copyright (c) 2022/06 Davin zhang<Davin@tbsdtv.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, version 2.
*
*/
#include <linux/version.h>
#include "tbs5230.h"
#include "cxd2878.h"
#define TBS5230_READ_MSG 0
#define TBS5230_WRITE_MSG 1
struct tbs5230_state {
u8 initialized;
};
/* debug */
static int dvb_usb_tbs5230_debug;
module_param_named(debug, dvb_usb_tbs5230_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))."
DVB_USB_DEBUG_STATUS);
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static int tbs5230_op_rw(struct usb_device *dev, u8 request, u16 value,
u16 index, u8 * data, u16 len, int flags)
{
int ret;
void *u8buf;
unsigned int pipe = (flags == TBS5230_READ_MSG) ?
usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
u8 request_type = (flags == TBS5230_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
u8buf = kmalloc(len, GFP_KERNEL);
if (!u8buf)
return -ENOMEM;
if (flags == TBS5230_WRITE_MSG)
memcpy(u8buf, data, len);
ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
value, index , u8buf, len, 2000);
if (flags == TBS5230_READ_MSG)
memcpy(data, u8buf, len);
kfree(u8buf);
return ret;
}
/* I2C */
static int tbs5230_i2c_transfer(struct i2c_adapter *adap,
struct i2c_msg msg[], int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
int i = 0;
u8 buf6[35];
u8 inbuf[35];
if (!d)
return -ENODEV;
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
switch (num) {
case 2:
buf6[0]=msg[1].len;//lenth
buf6[1]=msg[0].addr<<1;//demod addr
//register
buf6[2] = msg[0].buf[0];
tbs5230_op_rw(d->udev, 0x90, 0, 0,
buf6, 3, TBS5230_WRITE_MSG);
//msleep(5);
tbs5230_op_rw(d->udev, 0x91, 0, 0,
inbuf, buf6[0], TBS5230_READ_MSG);
memcpy(msg[1].buf, inbuf, msg[1].len);
break;
case 1:
buf6[0] = msg[0].len+1;//lenth
buf6[1] = msg[0].addr<<1;//addr
for(i=0;i<msg[0].len;i++) {
buf6[2+i] = msg[0].buf[i];//register
}
tbs5230_op_rw(d->udev, 0x80, 0, 0,
buf6, msg[0].len+2, TBS5230_WRITE_MSG);
break;
}
mutex_unlock(&d->i2c_mutex);
return num;
}
static u32 tbs5230_i2c_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_I2C;
}
static struct i2c_algorithm tbs5230_i2c_algo = {
.master_xfer = tbs5230_i2c_transfer,
.functionality = tbs5230_i2c_func,
};
static int tbs5230_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
{
int i,ret;
u8 ibuf[3] = {0, 0,0};
u8 eeprom[256], eepromline[16];
for (i = 0; i < 256; i++) {
ibuf[0]=1;//lenth
ibuf[1]=0xa0;//eeprom addr
ibuf[2]=i;//register
ret = tbs5230_op_rw(d->udev, 0x90, 0, 0,
ibuf, 3, TBS5230_WRITE_MSG);
ret = tbs5230_op_rw(d->udev, 0x91, 0, 0,
ibuf, 1, TBS5230_READ_MSG);
if (ret < 0) {
err("read eeprom failed.");
return -1;
} else {
eepromline[i%16] = ibuf[0];
eeprom[i] = ibuf[0];
}
if ((i % 16) == 15) {
deb_xfer("%02x: ", i - 15);
debug_dump(eepromline, 16, deb_xfer);
}
}
memcpy(mac, eeprom + 16, 6);
return 0;
};
static struct dvb_usb_device_properties tbs5230_properties;
static struct cxd2878_config tbs5230_cfg = {
.addr_slvt = 0x64,
.xtal = SONY_DEMOD_XTAL_24000KHz,
.tuner_addr = 0x60,
.tuner_xtal = SONY_ASCOT3_XTAL_24000KHz,
.ts_mode = 1,
.ts_ser_data = 0,
.ts_clk = 1,
.ts_clk_mask= 1,
.ts_valid = 0,
.atscCoreDisable = 0,
.lock_flag = 1,
.write_properties = NULL,
.read_properties = NULL,
};
static int tbs5230_frontend_attach(struct dvb_usb_adapter*adap)
{
struct dvb_usb_device *d = adap->dev;
adap->fe_adap[0].fe = dvb_attach(cxd2878_attach, &tbs5230_cfg, &d->i2c_adap);
if(adap->fe_adap[0].fe!=NULL){
strscpy(adap->fe_adap[0].fe->ops.info.name,d->props.devices[0].name,52);
return 0;
}
return -EIO;
}
static struct usb_device_id tbs5230_table[] = {
{USB_DEVICE(0x734c, 0x5230)},
{ }
};
MODULE_DEVICE_TABLE(usb, tbs5230_table);
static int tbs5230_load_firmware(struct usb_device *dev,
const struct firmware *frmwr)
{
u8 *b, *p;
int ret = 0, i;
u8 reset;
const struct firmware *fw;
switch (dev->descriptor.idProduct) {
case 0x5230:
ret = request_firmware(&fw, tbs5230_properties.firmware, &dev->dev);
if (ret != 0) {
err("did not find the firmware file. (%s) "
"Please see linux/Documentation/dvb/ for more details "
"on firmware-problems.", tbs5230_properties.firmware);
return ret;
}
break;
default:
fw = frmwr;
break;
}
info("start downloading TBS5230 firmware");
p = kmalloc(fw->size, GFP_KERNEL);
reset = 1;
/*stop the CPU*/
tbs5230_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, TBS5230_WRITE_MSG);
tbs5230_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, TBS5230_WRITE_MSG);
if (p != NULL) {
memcpy(p, fw->data, fw->size);
for (i = 0; i < fw->size; i += 0x40) {
b = (u8 *) p + i;
if (tbs5230_op_rw(dev, 0xa0, i, 0, b , 0x40,
TBS5230_WRITE_MSG) != 0x40) {
err("error while transferring firmware");
ret = -EINVAL;
break;
}
}
/* restart the CPU */
reset = 0;
if (ret || tbs5230_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,
TBS5230_WRITE_MSG) != 1) {
err("could not restart the USB controller CPU.");
ret = -EINVAL;
}
if (ret || tbs5230_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,
TBS5230_WRITE_MSG) != 1) {
err("could not restart the USB controller CPU.");
ret = -EINVAL;
}
msleep(100);
kfree(p);
}
return ret;
}
static struct dvb_usb_device_properties tbs5230_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = DEVICE_SPECIFIC,
.firmware = "dvb-usb-id5230.fw",
.size_of_priv = sizeof(struct tbs5230_state),
.no_reconnect = 1,
.i2c_algo = &tbs5230_i2c_algo,
.generic_bulk_ctrl_endpoint = 0x81,
.num_adapters = 1,
.download_firmware = tbs5230_load_firmware,
.read_mac_address = tbs5230_read_mac_address,
.adapter = {{
.num_frontends = 1,
.fe = {{
.frontend_attach = tbs5230_frontend_attach,
.streaming_ctrl = NULL,
.tuner_attach = NULL,
.stream = {
.type = USB_BULK,
.count = 8,
.endpoint = 0x82,
.u = {
.bulk = {
.buffersize = 4096,
}
}
},
}
},
}},
.num_device_descs = 1,
.devices = {
{"TurboSight TBS 5230 DVB-T2/T/C(j83-a/b/c),ISDB-T,ATSC1.0",
{&tbs5230_table[0], NULL},
{NULL},
}
}
};
static int tbs5230_probe(struct usb_interface *intf,
const struct usb_device_id*id)
{
if(0 == dvb_usb_device_init(intf,&tbs5230_properties,
THIS_MODULE,NULL,adapter_nr)){
return 0;
}
return -ENODEV;
}
static struct usb_driver tbs5230_driver ={
.name = "tbs5230",
.probe = tbs5230_probe,
.disconnect = dvb_usb_device_exit,
.id_table = tbs5230_table,
};
static int __init tbs5230_module_init(void)
{
int ret = usb_register(&tbs5230_driver);
if(ret)
err("usb_register failed.Error number %d",ret);
return ret;
}
static void __exit tbs5230_module_exit(void)
{
usb_deregister(&tbs5230_driver);
}
module_init(tbs5230_module_init);
module_exit(tbs5230_module_exit);
MODULE_AUTHOR("TBSDTV,Davin<Davin@tbsdtv.com>");
MODULE_DESCRIPTION("Turbosight TBS5230 drivers");
MODULE_VERSION("1.0");
MODULE_LICENSE("GPL");

View File

@@ -1,10 +1,10 @@
#ifndef __TBS5230__
#define __TBS5230__
#include "dvb-usb.h"
#define DVB_USB_LOG_PREFIX "tbs5230"
#define deb_xfer(args...) dprintk(dvb_usb_tbs5230_debug, 0x02, args)
#endif
#ifndef __TBS5230__
#define __TBS5230__
#include "dvb-usb.h"
#define DVB_USB_LOG_PREFIX "tbs5230"
#define deb_xfer(args...) dprintk(dvb_usb_tbs5230_debug, 0x02, args)
#endif

View File

@@ -283,7 +283,7 @@ static int tbs5301_frontend_attach(struct dvb_usb_adapter *d)
ret = tbs5301_op_rw(u->udev, 0x80, 0, 0,
buf, 4, TBS5301_WRITE_MSG);
strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
strscpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
return 0;
err:

View File

@@ -284,7 +284,7 @@ static int tbs5520_frontend_attach(struct dvb_usb_adapter *d)
tbs5520_op_rw(d->dev->udev, 0x8a, 0, 0,
buf, 2, TBS5520_WRITE_MSG);
strlcpy(d->fe_adap->fe->ops.info.name,d->dev->props.devices[0].name,52);
strscpy(d->fe_adap->fe->ops.info.name,d->dev->props.devices[0].name,52);
return 0;
err:
printk("TBS5520: frontend attach failed\n");

View File

@@ -230,7 +230,7 @@ static int tbs5520se_frontend_attach(struct dvb_usb_adapter *adap)
si2183_config.RF_switch = NULL;
si2183_config.agc_mode = 0x5 ;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2183", I2C_NAME_SIZE);
strscpy(info.type, "si2183", I2C_NAME_SIZE);
info.addr = 0x67;
info.platform_data = &si2183_config;
request_module(info.type);
@@ -264,7 +264,7 @@ static int tbs5520se_frontend_attach(struct dvb_usb_adapter *adap)
si2157_config.fe = adap->fe_adap[0].fe;
si2157_config.if_port = 1;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
strscpy(info.type, "si2157", I2C_NAME_SIZE);
info.addr = 0x61;
info.platform_data = &si2157_config;
request_module(info.type);
@@ -312,9 +312,9 @@ static int tbs5520se_frontend_attach(struct dvb_usb_adapter *adap)
tbs5520se_op_rw(d->udev, 0x8a, 0, 0,
buf, 2, TBS5520SE_WRITE_MSG);
strlcpy(adap->fe_adap[0].fe->ops.info.name,d->props.devices[0].name,52);
strscpy(adap->fe_adap[0].fe->ops.info.name,d->props.devices[0].name,52);
strcat(adap->fe_adap[0].fe->ops.info.name," DVB-T/T2/C/C2/ISDB-T");
strlcpy(adap->fe_adap[0].fe2->ops.info.name,d->props.devices[0].name,52);
strscpy(adap->fe_adap[0].fe2->ops.info.name,d->props.devices[0].name,52);
strcat(adap->fe_adap[0].fe2->ops.info.name," DVB-S/S2/S2X");
return 0;

View File

@@ -1,425 +1,425 @@
/*
* TurboSight TBS 5530 driver
*
* Copyright (c) 2022 Davin <Davin@tbsdtv.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, version 2.
*
*/
#include <linux/version.h>
#include "tbs5530.h"
#include "cxd2878.h"
#include "m88rs6060.h"
#define tbs5530_READ_MSG 0
#define tbs5530_WRITE_MSG 1
struct tbs5530_state {
struct i2c_client *i2c_client_demod;
struct i2c_client *i2c_client_tuner;
u32 last_key_pressed;
};
/* debug */
static int dvb_usb_tbs5530_debug;
module_param_named(debug, dvb_usb_tbs5530_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))."
DVB_USB_DEBUG_STATUS);
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static int tbs5530_op_rw(struct usb_device *dev, u8 request, u16 value,
u16 index, u8 * data, u16 len, int flags)
{
int ret;
void *u8buf;
unsigned int pipe = (flags == tbs5530_READ_MSG) ?
usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
u8 request_type = (flags == tbs5530_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
u8buf = kmalloc(len, GFP_KERNEL);
if (!u8buf)
return -ENOMEM;
if (flags == tbs5530_WRITE_MSG)
memcpy(u8buf, data, len);
ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
value, index , u8buf, len, 2000);
if (flags == tbs5530_READ_MSG)
memcpy(data, u8buf, len);
kfree(u8buf);
return ret;
}
/* I2C */
static int tbs5530_i2c_transfer(struct i2c_adapter *adap,
struct i2c_msg msg[], int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
int i = 0;
u8 buf6[50];
u8 inbuf[50];
if (!d)
return -ENODEV;
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
switch (num) {
case 2:
buf6[0]=msg[1].len;//lenth
buf6[1]=msg[0].addr<<1;//demod addr
//register
buf6[2] = msg[0].buf[0];
tbs5530_op_rw(d->udev, 0x90, 0, 0,
buf6, 3, tbs5530_WRITE_MSG);
//msleep(5);
tbs5530_op_rw(d->udev, 0x91, 0, 0,
inbuf, buf6[0], tbs5530_READ_MSG);
memcpy(msg[1].buf, inbuf, msg[1].len);
break;
case 1:
buf6[0] = msg[0].len+1;//lenth
buf6[1] = msg[0].addr<<1;//addr
for(i=0;i<msg[0].len;i++) {
buf6[2+i] = msg[0].buf[i];//register
}
tbs5530_op_rw(d->udev, 0x80, 0, 0,
buf6, msg[0].len+2, tbs5530_WRITE_MSG);
break;
}
mutex_unlock(&d->i2c_mutex);
return num;
}
static u32 tbs5530_i2c_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_I2C;
}
static struct i2c_algorithm tbs5530_i2c_algo = {
.master_xfer = tbs5530_i2c_transfer,
.functionality = tbs5530_i2c_func,
};
static int tbs5530_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
{
int i,ret;
u8 ibuf[3] = {0, 0,0};
u8 eeprom[256], eepromline[16];
for (i = 0; i < 256; i++) {
ibuf[0]=1;//lenth
ibuf[1]=0xa0;//eeprom addr
ibuf[2]=i;//register
ret = tbs5530_op_rw(d->udev, 0x90, 0, 0,
ibuf, 3, tbs5530_WRITE_MSG);
ret = tbs5530_op_rw(d->udev, 0x91, 0, 0,
ibuf, 1, tbs5530_READ_MSG);
if (ret < 0) {
err("read eeprom failed.");
return -1;
} else {
eepromline[i%16] = ibuf[0];
eeprom[i] = ibuf[0];
}
if ((i % 16) == 15) {
deb_xfer("%02x: ", i - 15);
debug_dump(eepromline, 16, deb_xfer);
}
}
memcpy(mac, eeprom + 16, 6);
return 0;
};
static struct dvb_usb_device_properties tbs5530_properties;
static struct cxd2878_config tbs5530_cfg = {
.addr_slvt = 0x64,
.xtal = SONY_DEMOD_XTAL_24000KHz,
.tuner_addr = 0x60,
.tuner_xtal = SONY_ASCOT3_XTAL_24000KHz,
.ts_mode = 1,
.ts_ser_data = 0,
.ts_clk = 1,
.ts_clk_mask= 1,
.ts_valid = 0,
.atscCoreDisable = 0,
.lock_flag = 1,
.write_properties = NULL,
.read_properties = NULL,
};
static int tbs5530_sat_streaming_ctrl(struct dvb_usb_adapter*adap,int onoff) //for open dvbs ts switch
{
struct dvb_usb_device *d = adap->dev;
u8 buf[20];
buf[0] = 10;
buf[1] = 1;
tbs5530_op_rw(d->udev, 0x8a, 0, 0,
buf, 2, tbs5530_WRITE_MSG);
return 0;
}
static int tbs5530_ter_cable_streaming_ctrl(struct dvb_usb_adapter*adap,int onoff)//for open dvbt/c ts
{
struct dvb_usb_device *d = adap->dev;
u8 buf[20];
buf[0] = 10;
buf[1] = 0;
tbs5530_op_rw(d->udev, 0x8a, 0, 0,
buf, 2, tbs5530_WRITE_MSG);
return 0;
}
static int tbs5530_frontend_cxd2878_attach(struct dvb_usb_adapter *adap)
{
struct dvb_usb_device *d = adap->dev;
//u8 buf[20];
/* attach frontend */
adap->fe_adap[0].fe = dvb_attach(cxd2878_attach, &tbs5530_cfg, &d->i2c_adap);
if(adap->fe_adap[0].fe!=NULL){
strlcpy(adap->fe_adap[0].fe->ops.info.name,d->props.devices[0].name,60);
strcat(adap->fe_adap[0].fe->ops.info.name," DVB-T/T2/C/C2,ISDB-T/C,ATSC1.0");
return 0;
}
// strlcpy(adap->fe_adap[0].fe->ops.info.name,d->props.devices[0].name,52);
// strlcpy(adap->fe_adap[0].fe2->ops.info.name,d->props.devices[0].name,52);
// strcat(adap->fe_adap[0].fe2->ops.info.name," DVB-S/S2/S2X");
return -EIO;
}
static int tbs5930_frontend_m88rs6060_attach(struct dvb_usb_adapter *adap)
{
struct dvb_usb_device *d = adap->dev;
struct i2c_client *client;
struct i2c_board_info info;
struct m88rs6060_cfg m88rs6060_config;
u8 buf[20];
/* attach frontend */
memset(&m88rs6060_config,0,sizeof(m88rs6060_config));
m88rs6060_config.fe = &adap->fe_adap[1].fe;
m88rs6060_config.clk = 27000000;
m88rs6060_config.i2c_wr_max = 33;
m88rs6060_config.ts_mode = MtFeTsOutMode_Common;
m88rs6060_config.ts_pinswitch = 0;
m88rs6060_config.envelope_mode = 0;
m88rs6060_config.demod_adr = 0x69;
m88rs6060_config.tuner_adr = 0x2c;
m88rs6060_config.repeater_value = 0x11;
m88rs6060_config.read_properties = NULL;
m88rs6060_config.write_properties = NULL;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "m88rs6060", I2C_NAME_SIZE);
info.addr = 0x69;
info.platform_data = &m88rs6060_config;
request_module(info.type);
client = i2c_new_client_device(&d->i2c_adap,&info);
if(!i2c_client_has_driver(client))
return -ENODEV;
if (!try_module_get(client->dev.driver->owner)) {
i2c_unregister_device(client);
return -ENODEV;
}
buf[0] = 0;
buf[1] = 0;
tbs5530_op_rw(d->udev, 0xb7, 0, 0,
buf, 2, tbs5530_WRITE_MSG);
buf[0] = 8;
buf[1] = 1;
tbs5530_op_rw(d->udev, 0x8a, 0, 0,
buf, 2, tbs5530_WRITE_MSG);
msleep(10);
strlcpy(adap->fe_adap[1].fe->ops.info.name,d->props.devices[0].name,52);
strcat(adap->fe_adap[1].fe->ops.info.name," DVB-S/S2/S2X");
return 0;
}
static struct usb_device_id tbs5530_table[] = {
{USB_DEVICE(0x734c, 0x5530)},
{ }
};
MODULE_DEVICE_TABLE(usb, tbs5530_table);
static int tbs5530_load_firmware(struct usb_device *dev,
const struct firmware *frmwr)
{
u8 *b, *p;
int ret = 0, i;
u8 reset;
const struct firmware *fw;
switch (dev->descriptor.idProduct) {
case 0x5530:
ret = request_firmware(&fw, tbs5530_properties.firmware, &dev->dev);
if (ret != 0) {
err("did not find the firmware file. (%s) "
"Please see linux/Documentation/dvb/ for more details "
"on firmware-problems.", tbs5530_properties.firmware);
return ret;
}
break;
default:
fw = frmwr;
break;
}
info("start downloading tbs5530 firmware");
p = kmalloc(fw->size, GFP_KERNEL);
reset = 1;
/*stop the CPU*/
tbs5530_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, tbs5530_WRITE_MSG);
tbs5530_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, tbs5530_WRITE_MSG);
if (p != NULL) {
memcpy(p, fw->data, fw->size);
for (i = 0; i < fw->size; i += 0x40) {
b = (u8 *) p + i;
if (tbs5530_op_rw(dev, 0xa0, i, 0, b , 0x40,
tbs5530_WRITE_MSG) != 0x40) {
err("error while transferring firmware");
ret = -EINVAL;
break;
}
}
/* restart the CPU */
reset = 0;
if (ret || tbs5530_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,
tbs5530_WRITE_MSG) != 1) {
err("could not restart the USB controller CPU.");
ret = -EINVAL;
}
if (ret || tbs5530_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,
tbs5530_WRITE_MSG) != 1) {
err("could not restart the USB controller CPU.");
ret = -EINVAL;
}
msleep(100);
kfree(p);
}
return ret;
}
static struct dvb_usb_device_properties tbs5530_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = DEVICE_SPECIFIC,
.firmware = "dvb-usb-id5530.fw",
.size_of_priv = sizeof(struct tbs5530_state),
.no_reconnect = 1,
.i2c_algo = &tbs5530_i2c_algo,
.generic_bulk_ctrl_endpoint = 0x81,
/* parameter for the MPEG2-data transfer */
.num_adapters = 1,
.download_firmware = tbs5530_load_firmware,
.read_mac_address = tbs5530_read_mac_address,
.adapter = {{
.num_frontends = 2,
.fe = {{
.frontend_attach = tbs5530_frontend_cxd2878_attach,
.streaming_ctrl = tbs5530_ter_cable_streaming_ctrl,
.tuner_attach = NULL,
.stream = {
.type = USB_BULK,
.count = 8,
.endpoint = 0x82,
.u = {
.bulk = {
.buffersize = 4096,
}
}
},
},{
.frontend_attach = tbs5930_frontend_m88rs6060_attach,
.streaming_ctrl = tbs5530_sat_streaming_ctrl,
.tuner_attach = NULL,
.stream = {
.type = USB_BULK,
.count = 8,
.endpoint = 0x82,
.u = {
.bulk = {
.buffersize = 4096,
}
}
},
}
},
}},
.num_device_descs = 1,
.devices = {
{"TurboSight TBS 5530 DVB-T2/T/C/S/S2/S2x,ISDB-T,ATSC1.0",
{&tbs5530_table[0], NULL},
{NULL},
}
}
};
static int tbs5530_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
if (0 == dvb_usb_device_init(intf, &tbs5530_properties,
THIS_MODULE, NULL, adapter_nr)) {
return 0;
}
return -ENODEV;
}
static struct usb_driver tbs5530_driver = {
.name = "tbs5530",
.probe = tbs5530_probe,
.disconnect = dvb_usb_device_exit,
.id_table = tbs5530_table,
};
static int __init tbs5530_module_init(void)
{
int ret = usb_register(&tbs5530_driver);
if (ret)
err("usb_register failed. Error number %d", ret);
return ret;
}
static void __exit tbs5530_module_exit(void)
{
usb_deregister(&tbs5530_driver);
}
module_init(tbs5530_module_init);
module_exit(tbs5530_module_exit);
MODULE_AUTHOR("Davin <Davin@tbsdtv.com>");
MODULE_DESCRIPTION("TurboSight TBS 5530 driver");
MODULE_VERSION("1.0");
MODULE_LICENSE("GPL");
/*
* TurboSight TBS 5530 driver
*
* Copyright (c) 2022 Davin <Davin@tbsdtv.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, version 2.
*
*/
#include <linux/version.h>
#include "tbs5530.h"
#include "cxd2878.h"
#include "m88rs6060.h"
#define tbs5530_READ_MSG 0
#define tbs5530_WRITE_MSG 1
struct tbs5530_state {
struct i2c_client *i2c_client_demod;
struct i2c_client *i2c_client_tuner;
u32 last_key_pressed;
};
/* debug */
static int dvb_usb_tbs5530_debug;
module_param_named(debug, dvb_usb_tbs5530_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))."
DVB_USB_DEBUG_STATUS);
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static int tbs5530_op_rw(struct usb_device *dev, u8 request, u16 value,
u16 index, u8 * data, u16 len, int flags)
{
int ret;
void *u8buf;
unsigned int pipe = (flags == tbs5530_READ_MSG) ?
usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
u8 request_type = (flags == tbs5530_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
u8buf = kmalloc(len, GFP_KERNEL);
if (!u8buf)
return -ENOMEM;
if (flags == tbs5530_WRITE_MSG)
memcpy(u8buf, data, len);
ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
value, index , u8buf, len, 2000);
if (flags == tbs5530_READ_MSG)
memcpy(data, u8buf, len);
kfree(u8buf);
return ret;
}
/* I2C */
static int tbs5530_i2c_transfer(struct i2c_adapter *adap,
struct i2c_msg msg[], int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
int i = 0;
u8 buf6[50];
u8 inbuf[50];
if (!d)
return -ENODEV;
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
switch (num) {
case 2:
buf6[0]=msg[1].len;//lenth
buf6[1]=msg[0].addr<<1;//demod addr
//register
buf6[2] = msg[0].buf[0];
tbs5530_op_rw(d->udev, 0x90, 0, 0,
buf6, 3, tbs5530_WRITE_MSG);
//msleep(5);
tbs5530_op_rw(d->udev, 0x91, 0, 0,
inbuf, buf6[0], tbs5530_READ_MSG);
memcpy(msg[1].buf, inbuf, msg[1].len);
break;
case 1:
buf6[0] = msg[0].len+1;//lenth
buf6[1] = msg[0].addr<<1;//addr
for(i=0;i<msg[0].len;i++) {
buf6[2+i] = msg[0].buf[i];//register
}
tbs5530_op_rw(d->udev, 0x80, 0, 0,
buf6, msg[0].len+2, tbs5530_WRITE_MSG);
break;
}
mutex_unlock(&d->i2c_mutex);
return num;
}
static u32 tbs5530_i2c_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_I2C;
}
static struct i2c_algorithm tbs5530_i2c_algo = {
.master_xfer = tbs5530_i2c_transfer,
.functionality = tbs5530_i2c_func,
};
static int tbs5530_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
{
int i,ret;
u8 ibuf[3] = {0, 0,0};
u8 eeprom[256], eepromline[16];
for (i = 0; i < 256; i++) {
ibuf[0]=1;//lenth
ibuf[1]=0xa0;//eeprom addr
ibuf[2]=i;//register
ret = tbs5530_op_rw(d->udev, 0x90, 0, 0,
ibuf, 3, tbs5530_WRITE_MSG);
ret = tbs5530_op_rw(d->udev, 0x91, 0, 0,
ibuf, 1, tbs5530_READ_MSG);
if (ret < 0) {
err("read eeprom failed.");
return -1;
} else {
eepromline[i%16] = ibuf[0];
eeprom[i] = ibuf[0];
}
if ((i % 16) == 15) {
deb_xfer("%02x: ", i - 15);
debug_dump(eepromline, 16, deb_xfer);
}
}
memcpy(mac, eeprom + 16, 6);
return 0;
};
static struct dvb_usb_device_properties tbs5530_properties;
static struct cxd2878_config tbs5530_cfg = {
.addr_slvt = 0x64,
.xtal = SONY_DEMOD_XTAL_24000KHz,
.tuner_addr = 0x60,
.tuner_xtal = SONY_ASCOT3_XTAL_24000KHz,
.ts_mode = 1,
.ts_ser_data = 0,
.ts_clk = 1,
.ts_clk_mask= 1,
.ts_valid = 0,
.atscCoreDisable = 0,
.lock_flag = 1,
.write_properties = NULL,
.read_properties = NULL,
};
static int tbs5530_sat_streaming_ctrl(struct dvb_usb_adapter*adap,int onoff) //for open dvbs ts switch
{
struct dvb_usb_device *d = adap->dev;
u8 buf[20];
buf[0] = 10;
buf[1] = 1;
tbs5530_op_rw(d->udev, 0x8a, 0, 0,
buf, 2, tbs5530_WRITE_MSG);
return 0;
}
static int tbs5530_ter_cable_streaming_ctrl(struct dvb_usb_adapter*adap,int onoff)//for open dvbt/c ts
{
struct dvb_usb_device *d = adap->dev;
u8 buf[20];
buf[0] = 10;
buf[1] = 0;
tbs5530_op_rw(d->udev, 0x8a, 0, 0,
buf, 2, tbs5530_WRITE_MSG);
return 0;
}
static int tbs5530_frontend_cxd2878_attach(struct dvb_usb_adapter *adap)
{
struct dvb_usb_device *d = adap->dev;
//u8 buf[20];
/* attach frontend */
adap->fe_adap[0].fe = dvb_attach(cxd2878_attach, &tbs5530_cfg, &d->i2c_adap);
if(adap->fe_adap[0].fe!=NULL){
strscpy(adap->fe_adap[0].fe->ops.info.name,d->props.devices[0].name,60);
strcat(adap->fe_adap[0].fe->ops.info.name," DVB-T/T2/C/C2,ISDB-T/C,ATSC1.0");
return 0;
}
// strscpy(adap->fe_adap[0].fe->ops.info.name,d->props.devices[0].name,52);
// strscpy(adap->fe_adap[0].fe2->ops.info.name,d->props.devices[0].name,52);
// strcat(adap->fe_adap[0].fe2->ops.info.name," DVB-S/S2/S2X");
return -EIO;
}
static int tbs5930_frontend_m88rs6060_attach(struct dvb_usb_adapter *adap)
{
struct dvb_usb_device *d = adap->dev;
struct i2c_client *client;
struct i2c_board_info info;
struct m88rs6060_cfg m88rs6060_config;
u8 buf[20];
/* attach frontend */
memset(&m88rs6060_config,0,sizeof(m88rs6060_config));
m88rs6060_config.fe = &adap->fe_adap[1].fe;
m88rs6060_config.clk = 27000000;
m88rs6060_config.i2c_wr_max = 33;
m88rs6060_config.ts_mode = MtFeTsOutMode_Common;
m88rs6060_config.ts_pinswitch = 0;
m88rs6060_config.envelope_mode = 0;
m88rs6060_config.demod_adr = 0x69;
m88rs6060_config.tuner_adr = 0x2c;
m88rs6060_config.repeater_value = 0x11;
m88rs6060_config.read_properties = NULL;
m88rs6060_config.write_properties = NULL;
memset(&info, 0, sizeof(struct i2c_board_info));
strscpy(info.type, "m88rs6060", I2C_NAME_SIZE);
info.addr = 0x69;
info.platform_data = &m88rs6060_config;
request_module(info.type);
client = i2c_new_client_device(&d->i2c_adap,&info);
if(!i2c_client_has_driver(client))
return -ENODEV;
if (!try_module_get(client->dev.driver->owner)) {
i2c_unregister_device(client);
return -ENODEV;
}
buf[0] = 0;
buf[1] = 0;
tbs5530_op_rw(d->udev, 0xb7, 0, 0,
buf, 2, tbs5530_WRITE_MSG);
buf[0] = 8;
buf[1] = 1;
tbs5530_op_rw(d->udev, 0x8a, 0, 0,
buf, 2, tbs5530_WRITE_MSG);
msleep(10);
strscpy(adap->fe_adap[1].fe->ops.info.name,d->props.devices[0].name,52);
strcat(adap->fe_adap[1].fe->ops.info.name," DVB-S/S2/S2X");
return 0;
}
static struct usb_device_id tbs5530_table[] = {
{USB_DEVICE(0x734c, 0x5530)},
{ }
};
MODULE_DEVICE_TABLE(usb, tbs5530_table);
static int tbs5530_load_firmware(struct usb_device *dev,
const struct firmware *frmwr)
{
u8 *b, *p;
int ret = 0, i;
u8 reset;
const struct firmware *fw;
switch (dev->descriptor.idProduct) {
case 0x5530:
ret = request_firmware(&fw, tbs5530_properties.firmware, &dev->dev);
if (ret != 0) {
err("did not find the firmware file. (%s) "
"Please see linux/Documentation/dvb/ for more details "
"on firmware-problems.", tbs5530_properties.firmware);
return ret;
}
break;
default:
fw = frmwr;
break;
}
info("start downloading tbs5530 firmware");
p = kmalloc(fw->size, GFP_KERNEL);
reset = 1;
/*stop the CPU*/
tbs5530_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, tbs5530_WRITE_MSG);
tbs5530_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, tbs5530_WRITE_MSG);
if (p != NULL) {
memcpy(p, fw->data, fw->size);
for (i = 0; i < fw->size; i += 0x40) {
b = (u8 *) p + i;
if (tbs5530_op_rw(dev, 0xa0, i, 0, b , 0x40,
tbs5530_WRITE_MSG) != 0x40) {
err("error while transferring firmware");
ret = -EINVAL;
break;
}
}
/* restart the CPU */
reset = 0;
if (ret || tbs5530_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,
tbs5530_WRITE_MSG) != 1) {
err("could not restart the USB controller CPU.");
ret = -EINVAL;
}
if (ret || tbs5530_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,
tbs5530_WRITE_MSG) != 1) {
err("could not restart the USB controller CPU.");
ret = -EINVAL;
}
msleep(100);
kfree(p);
}
return ret;
}
static struct dvb_usb_device_properties tbs5530_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = DEVICE_SPECIFIC,
.firmware = "dvb-usb-id5530.fw",
.size_of_priv = sizeof(struct tbs5530_state),
.no_reconnect = 1,
.i2c_algo = &tbs5530_i2c_algo,
.generic_bulk_ctrl_endpoint = 0x81,
/* parameter for the MPEG2-data transfer */
.num_adapters = 1,
.download_firmware = tbs5530_load_firmware,
.read_mac_address = tbs5530_read_mac_address,
.adapter = {{
.num_frontends = 2,
.fe = {{
.frontend_attach = tbs5530_frontend_cxd2878_attach,
.streaming_ctrl = tbs5530_ter_cable_streaming_ctrl,
.tuner_attach = NULL,
.stream = {
.type = USB_BULK,
.count = 8,
.endpoint = 0x82,
.u = {
.bulk = {
.buffersize = 4096,
}
}
},
},{
.frontend_attach = tbs5930_frontend_m88rs6060_attach,
.streaming_ctrl = tbs5530_sat_streaming_ctrl,
.tuner_attach = NULL,
.stream = {
.type = USB_BULK,
.count = 8,
.endpoint = 0x82,
.u = {
.bulk = {
.buffersize = 4096,
}
}
},
}
},
}},
.num_device_descs = 1,
.devices = {
{"TurboSight TBS 5530 DVB-T2/T/C/S/S2/S2x,ISDB-T,ATSC1.0",
{&tbs5530_table[0], NULL},
{NULL},
}
}
};
static int tbs5530_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
if (0 == dvb_usb_device_init(intf, &tbs5530_properties,
THIS_MODULE, NULL, adapter_nr)) {
return 0;
}
return -ENODEV;
}
static struct usb_driver tbs5530_driver = {
.name = "tbs5530",
.probe = tbs5530_probe,
.disconnect = dvb_usb_device_exit,
.id_table = tbs5530_table,
};
static int __init tbs5530_module_init(void)
{
int ret = usb_register(&tbs5530_driver);
if (ret)
err("usb_register failed. Error number %d", ret);
return ret;
}
static void __exit tbs5530_module_exit(void)
{
usb_deregister(&tbs5530_driver);
}
module_init(tbs5530_module_init);
module_exit(tbs5530_module_exit);
MODULE_AUTHOR("Davin <Davin@tbsdtv.com>");
MODULE_DESCRIPTION("TurboSight TBS 5530 driver");
MODULE_VERSION("1.0");
MODULE_LICENSE("GPL");

View File

@@ -1,8 +1,8 @@
#ifndef _TBS5530_H_
#define _TBS5530_H_
#define DVB_USB_LOG_PREFIX "tbs5530"
#include "dvb-usb.h"
#define deb_xfer(args...) dprintk(dvb_usb_tbs5530_debug, 0x02, args)
#endif
#ifndef _TBS5530_H_
#define _TBS5530_H_
#define DVB_USB_LOG_PREFIX "tbs5530"
#include "dvb-usb.h"
#define deb_xfer(args...) dprintk(dvb_usb_tbs5530_debug, 0x02, args)
#endif

View File

@@ -528,7 +528,7 @@ static int tbs5580_frontend_attach(struct dvb_usb_adapter *adap)
si2183_config.RF_switch = NULL;
si2183_config.agc_mode = 0x5 ;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2183", I2C_NAME_SIZE);
strscpy(info.type, "si2183", I2C_NAME_SIZE);
info.addr = 0x67;
info.platform_data = &si2183_config;
request_module(info.type);
@@ -561,7 +561,7 @@ static int tbs5580_frontend_attach(struct dvb_usb_adapter *adap)
si2157_config.fe = adap->fe_adap[0].fe;
si2157_config.if_port = 1;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
strscpy(info.type, "si2157", I2C_NAME_SIZE);
info.addr = 0x61;
info.platform_data = &si2157_config;
request_module(info.type);
@@ -612,9 +612,9 @@ static int tbs5580_frontend_attach(struct dvb_usb_adapter *adap)
tbs5580_init(adap);
strlcpy(adap->fe_adap[0].fe->ops.info.name,d->props.devices[0].name,52);
strscpy(adap->fe_adap[0].fe->ops.info.name,d->props.devices[0].name,52);
strcat(adap->fe_adap[0].fe->ops.info.name," DVB-T/T2/C/C2/ISDB-T");
strlcpy(adap->fe_adap[0].fe2->ops.info.name,d->props.devices[0].name,52);
strscpy(adap->fe_adap[0].fe2->ops.info.name,d->props.devices[0].name,52);
strcat(adap->fe_adap[0].fe2->ops.info.name," DVB-S/S2/S2X");
return 0;

View File

@@ -422,7 +422,7 @@ static int tbs5590_frontend_attach(struct dvb_usb_adapter *adap)
si2183_config.LED_switch = tbs5590_LED_ctrl;
si2183_config.agc_mode = 0x5 ;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2183", I2C_NAME_SIZE);
strscpy(info.type, "si2183", I2C_NAME_SIZE);
info.addr = 0x67;
info.platform_data = &si2183_config;
request_module(info.type);
@@ -456,7 +456,7 @@ static int tbs5590_frontend_attach(struct dvb_usb_adapter *adap)
si2157_config.fe = adap->fe_adap[0].fe;
si2157_config.if_port = 1;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
strscpy(info.type, "si2157", I2C_NAME_SIZE);
info.addr = 0x61;
info.platform_data = &si2157_config;
request_module(info.type);
@@ -522,7 +522,7 @@ static int tbs5590_frontend_attach(struct dvb_usb_adapter *adap)
m88rs6060_config.LED_switch = tbs5590_LED_ctrl;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "m88rs6060", I2C_NAME_SIZE);
strscpy(info.type, "m88rs6060", I2C_NAME_SIZE);
info.addr = 0x69;
info.platform_data = &m88rs6060_config;
request_module(info.type);
@@ -552,9 +552,9 @@ static int tbs5590_frontend_attach(struct dvb_usb_adapter *adap)
strlcpy(adap->fe_adap[0].fe->ops.info.name,d->props.devices[0].name,52);
strscpy(adap->fe_adap[0].fe->ops.info.name,d->props.devices[0].name,52);
strcat(adap->fe_adap[0].fe->ops.info.name," DVB-T/T2/C/C2/ISDB-T");
strlcpy(adap->fe_adap[0].fe2->ops.info.name,d->props.devices[0].name,52);
strscpy(adap->fe_adap[0].fe2->ops.info.name,d->props.devices[0].name,52);
strcat(adap->fe_adap[0].fe2->ops.info.name," DVB-S/S2/S2X");
return 0;
@@ -570,7 +570,7 @@ static int tbs5590_ASI_attach(struct dvb_usb_adapter *adap)
return -ENODEV;
}
strlcpy(adap->fe_adap[0].fe->ops.info.name,u->props.devices[0].name,52);
strscpy(adap->fe_adap[0].fe->ops.info.name,u->props.devices[0].name,52);
strcat(adap->fe_adap[0].fe->ops.info.name," ASI-IN");
return 0;

View File

@@ -590,7 +590,7 @@ static int tbs5880_frontend_attach(struct dvb_usb_adapter *d)
buf, 2, TBS5880_WRITE_MSG);
tbs5880_init(d);
strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
strscpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
return 0;
}
}

View File

@@ -507,7 +507,7 @@ static int tbs5881_frontend_attach(struct dvb_usb_adapter *adap)
si2168_config.ts_clock_gapped = true;
si2168_config.ts_clock_inv = true;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2168", I2C_NAME_SIZE);
strscpy(info.type, "si2168", I2C_NAME_SIZE);
info.addr = 0x64;
info.platform_data = &si2168_config;
request_module(info.type);
@@ -525,7 +525,7 @@ static int tbs5881_frontend_attach(struct dvb_usb_adapter *adap)
si2157_config.fe = adap->fe_adap[0].fe;
si2157_config.if_port = 1;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
strscpy(info.type, "si2157", I2C_NAME_SIZE);
info.addr = 0x60;
info.platform_data = &si2157_config;
request_module(info.type);
@@ -566,7 +566,7 @@ static int tbs5881_frontend_attach(struct dvb_usb_adapter *adap)
buf, 2, TBS5881_WRITE_MSG);
tbs5881_init(adap);
strlcpy(adap->fe_adap->fe->ops.info.name,d->props.devices[0].name,52);
strscpy(adap->fe_adap->fe->ops.info.name,d->props.devices[0].name,52);
return 0;
}

View File

@@ -223,7 +223,7 @@ static int tbs5922se_frontend_attach(struct dvb_usb_adapter *d)
buf[1] = 1;
tbs5922se_op_rw(u->udev, 0x8a, 0, 0, buf, 2, TBS5922SE_WRITE_MSG);
strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
strscpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
return 0;
err:

View File

@@ -289,7 +289,7 @@ static int tbs5925_frontend_attach(struct dvb_usb_adapter *d)
tbs5925_op_rw(u->udev, 0x8a, 0, 0,
buf, 2, TBS5925_WRITE_MSG);
strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
strscpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
return 0;
}

View File

@@ -295,7 +295,7 @@ static int tbs5927_frontend_attach(struct dvb_usb_adapter *d)
tbs5927_op_rw(d->dev->udev, 0x8a, 0, 0,
buf, 2, TBS5927_WRITE_MSG);
strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
strscpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
return 0;
}

View File

@@ -1,346 +1,346 @@
/*
* TurboSight TBS 5930 driver
*
* Copyright (c) 2017 Davin <smailedavin@hotmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, version 2.
*
*/
#include <linux/version.h>
#include "tbs5930.h"
#include "m88rs6060.h"
#define TBS5930_READ_MSG 0
#define TBS5930_WRITE_MSG 1
#define TBS5930_RC_QUERY (0x1a00)
#define TBS5930_VOLTAGE_CTRL (0x1800)
struct tbs5930_state {
u8 initialized;
};
/* debug */
static int dvb_usb_tbs5930_debug;
module_param_named(debug, dvb_usb_tbs5930_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))."
DVB_USB_DEBUG_STATUS);
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static int tbs5930_op_rw(struct usb_device *dev, u8 request, u16 value,
u16 index, u8 * data, u16 len, int flags)
{
int ret;
void *u8buf;
unsigned int pipe = (flags == TBS5930_READ_MSG) ?
usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
u8 request_type = (flags == TBS5930_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
u8buf = kmalloc(len, GFP_KERNEL);
if (!u8buf)
return -ENOMEM;
if (flags == TBS5930_WRITE_MSG)
memcpy(u8buf, data, len);
ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
value, index , u8buf, len, 2000);
if (flags == TBS5930_READ_MSG)
memcpy(data, u8buf, len);
kfree(u8buf);
return ret;
}
/* I2C */
static int tbs5930_i2c_transfer(struct i2c_adapter *adap,
struct i2c_msg msg[], int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
int i = 0;
u8 buf6[35];
u8 inbuf[35];
if (!d)
return -ENODEV;
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
switch (num) {
case 2:
buf6[0]=msg[1].len;//lenth
buf6[1]=msg[0].addr<<1;//demod addr
//register
buf6[2] = msg[0].buf[0];
tbs5930_op_rw(d->udev, 0x90, 0, 0,
buf6, 3, TBS5930_WRITE_MSG);
//msleep(5);
tbs5930_op_rw(d->udev, 0x91, 0, 0,
inbuf, buf6[0], TBS5930_READ_MSG);
memcpy(msg[1].buf, inbuf, msg[1].len);
break;
case 1:
buf6[0] = msg[0].len+1;//lenth
buf6[1] = msg[0].addr<<1;//addr
for(i=0;i<msg[0].len;i++) {
buf6[2+i] = msg[0].buf[i];//register
}
tbs5930_op_rw(d->udev, 0x80, 0, 0,
buf6, msg[0].len+2, TBS5930_WRITE_MSG);
break;
}
mutex_unlock(&d->i2c_mutex);
return num;
}
static u32 tbs5930_i2c_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_I2C;
}
static struct i2c_algorithm tbs5930_i2c_algo = {
.master_xfer = tbs5930_i2c_transfer,
.functionality = tbs5930_i2c_func,
};
static int tbs5930_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
{
int i,ret;
u8 ibuf[3] = {0, 0,0};
u8 eeprom[256], eepromline[16];
for (i = 0; i < 256; i++) {
ibuf[0]=1;//lenth
ibuf[1]=0xa0;//eeprom addr
ibuf[2]=i;//register
ret = tbs5930_op_rw(d->udev, 0x90, 0, 0,
ibuf, 3, TBS5930_WRITE_MSG);
ret = tbs5930_op_rw(d->udev, 0x91, 0, 0,
ibuf, 1, TBS5930_READ_MSG);
if (ret < 0) {
err("read eeprom failed.");
return -1;
} else {
eepromline[i%16] = ibuf[0];
eeprom[i] = ibuf[0];
}
if ((i % 16) == 15) {
deb_xfer("%02x: ", i - 15);
debug_dump(eepromline, 16, deb_xfer);
}
}
memcpy(mac, eeprom + 16, 6);
return 0;
};
static struct dvb_usb_device_properties tbs5930_properties;
static int tbs5930_frontend_attach(struct dvb_usb_adapter *adap)
{
struct dvb_usb_device *d = adap->dev;
struct i2c_client *client;
struct i2c_board_info info;
struct m88rs6060_cfg m88rs6060_config;
u8 buf[20];
/* attach frontend */
memset(&m88rs6060_config,0,sizeof(m88rs6060_config));
m88rs6060_config.fe = &adap->fe_adap[0].fe;
m88rs6060_config.clk = 27000000;
m88rs6060_config.i2c_wr_max = 33;
m88rs6060_config.ts_mode = MtFeTsOutMode_Common;
m88rs6060_config.ts_pinswitch = 0;
m88rs6060_config.envelope_mode = 0;
m88rs6060_config.demod_adr = 0x69;
m88rs6060_config.tuner_adr = 0x2c;
m88rs6060_config.repeater_value = 0x11;
m88rs6060_config.read_properties = NULL;
m88rs6060_config.write_properties = NULL;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "m88rs6060", I2C_NAME_SIZE);
info.addr = 0x69;
info.platform_data = &m88rs6060_config;
request_module(info.type);
client = i2c_new_client_device(&d->i2c_adap,&info);
if(!i2c_client_has_driver(client))
return -ENODEV;
if (!try_module_get(client->dev.driver->owner)) {
i2c_unregister_device(client);
return -ENODEV;
}
buf[0] = 0;
buf[1] = 0;
tbs5930_op_rw(d->udev, 0xb7, 0, 0,
buf, 2, TBS5930_WRITE_MSG);
buf[0] = 8;
buf[1] = 1;
tbs5930_op_rw(d->udev, 0x8a, 0, 0,
buf, 2, TBS5930_WRITE_MSG);
msleep(10);
strlcpy(adap->fe_adap->fe->ops.info.name,d->props.devices[0].name,52);
return 0;
}
static struct usb_device_id tbs5930_table[] = {
{USB_DEVICE(0x734c, 0x5930)},
{ }
};
MODULE_DEVICE_TABLE(usb, tbs5930_table);
static int tbs5930_load_firmware(struct usb_device *dev,
const struct firmware *frmwr)
{
u8 *b, *p;
int ret = 0, i;
u8 reset;
const struct firmware *fw;
switch (dev->descriptor.idProduct) {
case 0x5930:
ret = request_firmware(&fw, tbs5930_properties.firmware, &dev->dev);
if (ret != 0) {
err("did not find the firmware file. (%s) "
"Please see linux/Documentation/dvb/ for more details "
"on firmware-problems.", tbs5930_properties.firmware);
return ret;
}
break;
default:
fw = frmwr;
break;
}
info("start downloading TBS5930 firmware");
p = kmalloc(fw->size, GFP_KERNEL);
reset = 1;
/*stop the CPU*/
tbs5930_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, TBS5930_WRITE_MSG);
tbs5930_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, TBS5930_WRITE_MSG);
if (p != NULL) {
memcpy(p, fw->data, fw->size);
for (i = 0; i < fw->size; i += 0x40) {
b = (u8 *) p + i;
if (tbs5930_op_rw(dev, 0xa0, i, 0, b , 0x40,
TBS5930_WRITE_MSG) != 0x40) {
err("error while transferring firmware");
ret = -EINVAL;
break;
}
}
/* restart the CPU */
reset = 0;
if (ret || tbs5930_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,
TBS5930_WRITE_MSG) != 1) {
err("could not restart the USB controller CPU.");
ret = -EINVAL;
}
if (ret || tbs5930_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,
TBS5930_WRITE_MSG) != 1) {
err("could not restart the USB controller CPU.");
ret = -EINVAL;
}
msleep(100);
kfree(p);
}
return ret;
}
static struct dvb_usb_device_properties tbs5930_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = DEVICE_SPECIFIC,
.firmware = "dvb-usb-id5930.fw",
.size_of_priv = sizeof(struct tbs5930_state),
.no_reconnect = 1,
.i2c_algo = &tbs5930_i2c_algo,
.generic_bulk_ctrl_endpoint = 0x81,
/* parameter for the MPEG2-data transfer */
.num_adapters = 1,
.download_firmware = tbs5930_load_firmware,
.read_mac_address = tbs5930_read_mac_address,
.adapter = {{
.num_frontends = 1,
.fe = {{
.frontend_attach = tbs5930_frontend_attach,
.streaming_ctrl = NULL,
.tuner_attach = NULL,
.stream = {
.type = USB_BULK,
.count = 8,
.endpoint = 0x82,
.u = {
.bulk = {
.buffersize = 4096,
}
}
},
}
},
}},
.num_device_descs = 1,
.devices = {
{"TurboSight TBS 5930 DVB-S/S2/S2x",
{&tbs5930_table[0], NULL},
{NULL},
}
}
};
static int tbs5930_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
if (0 == dvb_usb_device_init(intf, &tbs5930_properties,
THIS_MODULE, NULL, adapter_nr)) {
return 0;
}
return -ENODEV;
}
static struct usb_driver tbs5930_driver = {
.name = "tbs5930",
.probe = tbs5930_probe,
.disconnect = dvb_usb_device_exit,
.id_table = tbs5930_table,
};
static int __init tbs5930_module_init(void)
{
int ret = usb_register(&tbs5930_driver);
if (ret)
err("usb_register failed. Error number %d", ret);
return ret;
}
static void __exit tbs5930_module_exit(void)
{
usb_deregister(&tbs5930_driver);
}
module_init(tbs5930_module_init);
module_exit(tbs5930_module_exit);
MODULE_AUTHOR("Davin zhang<Davin@tbsdtv.com>");
MODULE_DESCRIPTION("TurboSight TBS 5930 driver");
MODULE_VERSION("1.0");
MODULE_LICENSE("GPL");
/*
* TurboSight TBS 5930 driver
*
* Copyright (c) 2017 Davin <smailedavin@hotmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, version 2.
*
*/
#include <linux/version.h>
#include "tbs5930.h"
#include "m88rs6060.h"
#define TBS5930_READ_MSG 0
#define TBS5930_WRITE_MSG 1
#define TBS5930_RC_QUERY (0x1a00)
#define TBS5930_VOLTAGE_CTRL (0x1800)
struct tbs5930_state {
u8 initialized;
};
/* debug */
static int dvb_usb_tbs5930_debug;
module_param_named(debug, dvb_usb_tbs5930_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))."
DVB_USB_DEBUG_STATUS);
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static int tbs5930_op_rw(struct usb_device *dev, u8 request, u16 value,
u16 index, u8 * data, u16 len, int flags)
{
int ret;
void *u8buf;
unsigned int pipe = (flags == TBS5930_READ_MSG) ?
usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
u8 request_type = (flags == TBS5930_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
u8buf = kmalloc(len, GFP_KERNEL);
if (!u8buf)
return -ENOMEM;
if (flags == TBS5930_WRITE_MSG)
memcpy(u8buf, data, len);
ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
value, index , u8buf, len, 2000);
if (flags == TBS5930_READ_MSG)
memcpy(data, u8buf, len);
kfree(u8buf);
return ret;
}
/* I2C */
static int tbs5930_i2c_transfer(struct i2c_adapter *adap,
struct i2c_msg msg[], int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
int i = 0;
u8 buf6[35];
u8 inbuf[35];
if (!d)
return -ENODEV;
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
switch (num) {
case 2:
buf6[0]=msg[1].len;//lenth
buf6[1]=msg[0].addr<<1;//demod addr
//register
buf6[2] = msg[0].buf[0];
tbs5930_op_rw(d->udev, 0x90, 0, 0,
buf6, 3, TBS5930_WRITE_MSG);
//msleep(5);
tbs5930_op_rw(d->udev, 0x91, 0, 0,
inbuf, buf6[0], TBS5930_READ_MSG);
memcpy(msg[1].buf, inbuf, msg[1].len);
break;
case 1:
buf6[0] = msg[0].len+1;//lenth
buf6[1] = msg[0].addr<<1;//addr
for(i=0;i<msg[0].len;i++) {
buf6[2+i] = msg[0].buf[i];//register
}
tbs5930_op_rw(d->udev, 0x80, 0, 0,
buf6, msg[0].len+2, TBS5930_WRITE_MSG);
break;
}
mutex_unlock(&d->i2c_mutex);
return num;
}
static u32 tbs5930_i2c_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_I2C;
}
static struct i2c_algorithm tbs5930_i2c_algo = {
.master_xfer = tbs5930_i2c_transfer,
.functionality = tbs5930_i2c_func,
};
static int tbs5930_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
{
int i,ret;
u8 ibuf[3] = {0, 0,0};
u8 eeprom[256], eepromline[16];
for (i = 0; i < 256; i++) {
ibuf[0]=1;//lenth
ibuf[1]=0xa0;//eeprom addr
ibuf[2]=i;//register
ret = tbs5930_op_rw(d->udev, 0x90, 0, 0,
ibuf, 3, TBS5930_WRITE_MSG);
ret = tbs5930_op_rw(d->udev, 0x91, 0, 0,
ibuf, 1, TBS5930_READ_MSG);
if (ret < 0) {
err("read eeprom failed.");
return -1;
} else {
eepromline[i%16] = ibuf[0];
eeprom[i] = ibuf[0];
}
if ((i % 16) == 15) {
deb_xfer("%02x: ", i - 15);
debug_dump(eepromline, 16, deb_xfer);
}
}
memcpy(mac, eeprom + 16, 6);
return 0;
};
static struct dvb_usb_device_properties tbs5930_properties;
static int tbs5930_frontend_attach(struct dvb_usb_adapter *adap)
{
struct dvb_usb_device *d = adap->dev;
struct i2c_client *client;
struct i2c_board_info info;
struct m88rs6060_cfg m88rs6060_config;
u8 buf[20];
/* attach frontend */
memset(&m88rs6060_config,0,sizeof(m88rs6060_config));
m88rs6060_config.fe = &adap->fe_adap[0].fe;
m88rs6060_config.clk = 27000000;
m88rs6060_config.i2c_wr_max = 33;
m88rs6060_config.ts_mode = MtFeTsOutMode_Common;
m88rs6060_config.ts_pinswitch = 0;
m88rs6060_config.envelope_mode = 0;
m88rs6060_config.demod_adr = 0x69;
m88rs6060_config.tuner_adr = 0x2c;
m88rs6060_config.repeater_value = 0x11;
m88rs6060_config.read_properties = NULL;
m88rs6060_config.write_properties = NULL;
memset(&info, 0, sizeof(struct i2c_board_info));
strscpy(info.type, "m88rs6060", I2C_NAME_SIZE);
info.addr = 0x69;
info.platform_data = &m88rs6060_config;
request_module(info.type);
client = i2c_new_client_device(&d->i2c_adap,&info);
if(!i2c_client_has_driver(client))
return -ENODEV;
if (!try_module_get(client->dev.driver->owner)) {
i2c_unregister_device(client);
return -ENODEV;
}
buf[0] = 0;
buf[1] = 0;
tbs5930_op_rw(d->udev, 0xb7, 0, 0,
buf, 2, TBS5930_WRITE_MSG);
buf[0] = 8;
buf[1] = 1;
tbs5930_op_rw(d->udev, 0x8a, 0, 0,
buf, 2, TBS5930_WRITE_MSG);
msleep(10);
strscpy(adap->fe_adap->fe->ops.info.name,d->props.devices[0].name,52);
return 0;
}
static struct usb_device_id tbs5930_table[] = {
{USB_DEVICE(0x734c, 0x5930)},
{ }
};
MODULE_DEVICE_TABLE(usb, tbs5930_table);
static int tbs5930_load_firmware(struct usb_device *dev,
const struct firmware *frmwr)
{
u8 *b, *p;
int ret = 0, i;
u8 reset;
const struct firmware *fw;
switch (dev->descriptor.idProduct) {
case 0x5930:
ret = request_firmware(&fw, tbs5930_properties.firmware, &dev->dev);
if (ret != 0) {
err("did not find the firmware file. (%s) "
"Please see linux/Documentation/dvb/ for more details "
"on firmware-problems.", tbs5930_properties.firmware);
return ret;
}
break;
default:
fw = frmwr;
break;
}
info("start downloading TBS5930 firmware");
p = kmalloc(fw->size, GFP_KERNEL);
reset = 1;
/*stop the CPU*/
tbs5930_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, TBS5930_WRITE_MSG);
tbs5930_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, TBS5930_WRITE_MSG);
if (p != NULL) {
memcpy(p, fw->data, fw->size);
for (i = 0; i < fw->size; i += 0x40) {
b = (u8 *) p + i;
if (tbs5930_op_rw(dev, 0xa0, i, 0, b , 0x40,
TBS5930_WRITE_MSG) != 0x40) {
err("error while transferring firmware");
ret = -EINVAL;
break;
}
}
/* restart the CPU */
reset = 0;
if (ret || tbs5930_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,
TBS5930_WRITE_MSG) != 1) {
err("could not restart the USB controller CPU.");
ret = -EINVAL;
}
if (ret || tbs5930_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,
TBS5930_WRITE_MSG) != 1) {
err("could not restart the USB controller CPU.");
ret = -EINVAL;
}
msleep(100);
kfree(p);
}
return ret;
}
static struct dvb_usb_device_properties tbs5930_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = DEVICE_SPECIFIC,
.firmware = "dvb-usb-id5930.fw",
.size_of_priv = sizeof(struct tbs5930_state),
.no_reconnect = 1,
.i2c_algo = &tbs5930_i2c_algo,
.generic_bulk_ctrl_endpoint = 0x81,
/* parameter for the MPEG2-data transfer */
.num_adapters = 1,
.download_firmware = tbs5930_load_firmware,
.read_mac_address = tbs5930_read_mac_address,
.adapter = {{
.num_frontends = 1,
.fe = {{
.frontend_attach = tbs5930_frontend_attach,
.streaming_ctrl = NULL,
.tuner_attach = NULL,
.stream = {
.type = USB_BULK,
.count = 8,
.endpoint = 0x82,
.u = {
.bulk = {
.buffersize = 4096,
}
}
},
}
},
}},
.num_device_descs = 1,
.devices = {
{"TurboSight TBS 5930 DVB-S/S2/S2x",
{&tbs5930_table[0], NULL},
{NULL},
}
}
};
static int tbs5930_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
if (0 == dvb_usb_device_init(intf, &tbs5930_properties,
THIS_MODULE, NULL, adapter_nr)) {
return 0;
}
return -ENODEV;
}
static struct usb_driver tbs5930_driver = {
.name = "tbs5930",
.probe = tbs5930_probe,
.disconnect = dvb_usb_device_exit,
.id_table = tbs5930_table,
};
static int __init tbs5930_module_init(void)
{
int ret = usb_register(&tbs5930_driver);
if (ret)
err("usb_register failed. Error number %d", ret);
return ret;
}
static void __exit tbs5930_module_exit(void)
{
usb_deregister(&tbs5930_driver);
}
module_init(tbs5930_module_init);
module_exit(tbs5930_module_exit);
MODULE_AUTHOR("Davin zhang<Davin@tbsdtv.com>");
MODULE_DESCRIPTION("TurboSight TBS 5930 driver");
MODULE_VERSION("1.0");
MODULE_LICENSE("GPL");

View File

@@ -1,8 +1,8 @@
#ifndef _TBS5930_H_
#define _TBS5930_H_
#define DVB_USB_LOG_PREFIX "tbs5930"
#include "dvb-usb.h"
#define deb_xfer(args...) dprintk(dvb_usb_tbs5930_debug, 0x02, args)
#endif
#ifndef _TBS5930_H_
#define _TBS5930_H_
#define DVB_USB_LOG_PREFIX "tbs5930"
#include "dvb-usb.h"
#define deb_xfer(args...) dprintk(dvb_usb_tbs5930_debug, 0x02, args)
#endif

View File

@@ -1,437 +1,437 @@
/*
* TurboSight TBS 5930 lite driver
*
* Copyright (c) 2017 Davin <davin@tbsdtv.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, version 2.
*
*/
#include <linux/version.h>
#include "tbs5931.h"
#include "gx1133.h"
#include "tas2101.h"
#include "av201x.h"
#define TBS5931_READ_MSG 0
#define TBS5931_WRITE_MSG 1
#define TBS5931_RC_QUERY (0x1a00)
#define TBS5931_VOLTAGE_CTRL (0x1800)
struct tbs5931_state {
u8 initialized;
};
static struct tas2101_config gx1132_cfg = {
.i2c_address = 0x60,
.id = ID_TAS2101,
.init = {0x10, 0x32, 0x54, 0x76, 0xA8, 0x9B, 0x33},
.init2 = 0,
};
static struct gx1133_config gx1133_cfg = {
.i2c_address = 0x52,
.ts_mode = 0,
.ts_cfg = {data_0,data_1,data_2,data_3,data_4,data_5,data_6, \
data_7,ts_sync,ts_err,ts_clk,ts_valid},
};
static struct av201x_config av201x_cfg = {
.i2c_address = 0x62,
.id = ID_AV2012,
.xtal_freq = 27000, /* kHz */
};
/* debug */
static int dvb_usb_tbs5931_debug;
module_param_named(debug, dvb_usb_tbs5931_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))."
DVB_USB_DEBUG_STATUS);
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static int tbs5931_op_rw(struct usb_device *dev, u8 request, u16 value,
u16 index, u8 * data, u16 len, int flags)
{
int ret;
void *u8buf;
unsigned int pipe = (flags == TBS5931_READ_MSG) ?
usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
u8 request_type = (flags == TBS5931_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
u8buf = kmalloc(len, GFP_KERNEL);
if (!u8buf)
return -ENOMEM;
if (flags == TBS5931_WRITE_MSG)
memcpy(u8buf, data, len);
ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
value, index , u8buf, len, 2000);
if (flags == TBS5931_READ_MSG)
memcpy(data, u8buf, len);
kfree(u8buf);
return ret;
}
/* I2C */
static int tbs5931_i2c_transfer(struct i2c_adapter *adap,
struct i2c_msg msg[], int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
int i = 0;
u8 buf6[35];
u8 inbuf[35];
if (!d)
return -ENODEV;
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
switch (num) {
case 2:
switch(msg[0].addr){
case 0x60:
case 0x62:
buf6[0]=msg[1].len;//lenth
buf6[1]=msg[0].addr<<1;//demod addr
//register
buf6[2] = msg[0].buf[0];
tbs5931_op_rw(d->udev, 0x90, 0, 0,
buf6, 3, TBS5931_WRITE_MSG);
msleep(1);
tbs5931_op_rw(d->udev, 0x91, 0, 0,
inbuf, buf6[0], TBS5931_READ_MSG);
memcpy(msg[1].buf, inbuf, msg[1].len);
break;
case 0x52:
buf6[0]=msg[1].len;//lenth
buf6[1]=msg[0].addr<<1;//demod addr
//register
memcpy(buf6+2,msg[0].buf,msg[0].len);
tbs5931_op_rw(d->udev, 0x92, 0, 0,
buf6, msg[0].len+2, TBS5931_WRITE_MSG);
msleep(1);
tbs5931_op_rw(d->udev, 0x91, 0, 0,
inbuf, msg[1].len, TBS5931_READ_MSG);
memcpy(msg[1].buf, inbuf, msg[1].len);
break;
}
break;
case 1:
buf6[0] = msg[0].len+1;//lenth
buf6[1] = msg[0].addr<<1;//addr
for(i=0;i<msg[0].len;i++) {
buf6[2+i] = msg[0].buf[i];//register
}
tbs5931_op_rw(d->udev, 0x80, 0, 0,
buf6, msg[0].len+2, TBS5931_WRITE_MSG);
break;
}
mutex_unlock(&d->i2c_mutex);
return num;
}
static u32 tbs5931_i2c_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_I2C;
}
static struct i2c_algorithm tbs5931_i2c_algo = {
.master_xfer = tbs5931_i2c_transfer,
.functionality = tbs5931_i2c_func,
};
static int tbs5931_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
{
int i,ret;
u8 ibuf[3] = {0, 0,0};
u8 eeprom[256], eepromline[16];
for (i = 0; i < 256; i++) {
ibuf[0]=1;//lenth
ibuf[1]=0xA0;//eeprom addr
ibuf[2]=i;//register
ret = tbs5931_op_rw(d->udev, 0x90, 0, 0,
ibuf, 3, TBS5931_WRITE_MSG);
ret = tbs5931_op_rw(d->udev, 0x91, 0, 0,
ibuf, 1, TBS5931_READ_MSG);
if (ret < 0) {
err("read eeprom failed.");
return -1;
} else {
eepromline[i%16] = ibuf[0];
eeprom[i] = ibuf[0];
}
if ((i % 16) == 15) {
deb_xfer("%02x: ", i - 15);
debug_dump(eepromline, 16, deb_xfer);
}
}
memcpy(mac, eeprom + 16, 6);
return 0;
};
static struct dvb_usb_device_properties tbs5931_properties;
static int tbs5931_frontend_attach(struct dvb_usb_adapter *adap)
{
struct dvb_usb_device *d = adap->dev;
u8 buf[20];
u8 a = 0,b = 0;
u16 id;
//read the id to deceted the chip
buf[0]= 1;//lenth
buf[1]= 0xC0;//demod addr
//register
buf[2] = 0x01;
tbs5931_op_rw(d->udev, 0x90, 0, 0,
buf, 3, TBS5931_WRITE_MSG);
msleep(1);
tbs5931_op_rw(d->udev, 0x91, 0, 0,
&a, buf[0], TBS5931_READ_MSG);
msleep(5);
buf[2] = 0x00;
tbs5931_op_rw(d->udev, 0x90, 0, 0,
buf, 3, TBS5931_WRITE_MSG);
msleep(1);
tbs5931_op_rw(d->udev, 0x91, 0, 0,
&b, buf[0], TBS5931_READ_MSG);
id = (b<<8|a);
if(id==0x444c){ //gx1132
adap->fe_adap->fe = dvb_attach(tas2101_attach,&gx1132_cfg,&d->i2c_adap);
if(adap->fe_adap->fe ==NULL)
goto err;
if(dvb_attach(av201x_attach,adap->fe_adap->fe,&av201x_cfg,
tas2101_get_i2c_adapter(adap->fe_adap->fe,2))==NULL){
dvb_frontend_detach(adap->fe_adap->fe);
adap->fe_adap->fe = NULL;
goto err;
}
}
else{
id = 0;
a = 0;
b = 0;
buf[0]= 1;//lenth
buf[1]= 0xA4;//demod addr
//register
buf[2] = 0xff;
buf[3] = 0xf1;
tbs5931_op_rw(d->udev, 0x92, 0, 0,
buf, 4, TBS5931_WRITE_MSG);
msleep(1);
tbs5931_op_rw(d->udev, 0x91, 0, 0,
&a, buf[0], TBS5931_READ_MSG);
msleep(5);
buf[3] = 0xf0;
tbs5931_op_rw(d->udev, 0x92, 0, 0,
buf, 4, TBS5931_WRITE_MSG);
msleep(1);
tbs5931_op_rw(d->udev, 0x91, 0, 0,
&b, buf[0], TBS5931_READ_MSG);
id = (b<<8|a);
if(id==0x444c){ //gx1133
adap->fe_adap->fe = dvb_attach(gx1133_attach,&gx1133_cfg,&d->i2c_adap);
if(adap->fe_adap->fe ==NULL)
goto err;
if(dvb_attach(av201x_attach,adap->fe_adap->fe,&av201x_cfg,
gx1133_get_i2c_adapter(adap->fe_adap->fe,2))==NULL){
dvb_frontend_detach(adap->fe_adap->fe);
adap->fe_adap->fe = NULL;
goto err;
}
}
else
goto err;
}
buf[0] = 0;
buf[1] = 0;
tbs5931_op_rw(d->udev, 0xb7, 0, 0,
buf, 2, TBS5931_WRITE_MSG);
buf[0] = 8;
buf[1] = 1;
tbs5931_op_rw(d->udev, 0x8a, 0, 0,
buf, 2, TBS5931_WRITE_MSG);
msleep(10);
strlcpy(adap->fe_adap->fe->ops.info.name,d->props.devices[0].name,52);
return 0;
err:
return -ENODEV;
}
static struct usb_device_id tbs5931_table[] = {
{USB_DEVICE(0x734c, 0x5931)},
{ }
};
MODULE_DEVICE_TABLE(usb, tbs5931_table);
static int tbs5931_load_firmware(struct usb_device *dev,
const struct firmware *frmwr)
{
u8 *b, *p;
int ret = 0, i;
u8 reset;
const struct firmware *fw;
switch (dev->descriptor.idProduct) {
case 0x5931:
ret = request_firmware(&fw, tbs5931_properties.firmware, &dev->dev);
if (ret != 0) {
err("did not find the firmware file. (%s) "
"Please see linux/Documentation/dvb/ for more details "
"on firmware-problems.", tbs5931_properties.firmware);
return ret;
}
break;
default:
fw = frmwr;
break;
}
info("start downloading TBS5931 firmware");
p = kmalloc(fw->size, GFP_KERNEL);
reset = 1;
/*stop the CPU*/
tbs5931_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, TBS5931_WRITE_MSG);
tbs5931_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, TBS5931_WRITE_MSG);
if (p != NULL) {
memcpy(p, fw->data, fw->size);
for (i = 0; i < fw->size; i += 0x40) {
b = (u8 *) p + i;
if (tbs5931_op_rw(dev, 0xa0, i, 0, b , 0x40,
TBS5931_WRITE_MSG) != 0x40) {
err("error while transferring firmware");
ret = -EINVAL;
break;
}
}
/* restart the CPU */
reset = 0;
if (ret || tbs5931_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,
TBS5931_WRITE_MSG) != 1) {
err("could not restart the USB controller CPU.");
ret = -EINVAL;
}
if (ret || tbs5931_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,
TBS5931_WRITE_MSG) != 1) {
err("could not restart the USB controller CPU.");
ret = -EINVAL;
}
msleep(100);
kfree(p);
}
return ret;
}
static struct dvb_usb_device_properties tbs5931_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = DEVICE_SPECIFIC,
.firmware = "dvb-usb-id5931.fw",
.size_of_priv = sizeof(struct tbs5931_state),
.no_reconnect = 1,
.i2c_algo = &tbs5931_i2c_algo,
.generic_bulk_ctrl_endpoint = 0x81,
/* parameter for the MPEG2-data transfer */
.num_adapters = 1,
.download_firmware = tbs5931_load_firmware,
.read_mac_address = tbs5931_read_mac_address,
.adapter = {{
.num_frontends = 1,
.fe = {{
.frontend_attach = tbs5931_frontend_attach,
.streaming_ctrl = NULL,
.tuner_attach = NULL,
.stream = {
.type = USB_BULK,
.count = 8,
.endpoint = 0x82,
.u = {
.bulk = {
.buffersize = 4096,
}
}
},
}
},
}},
.num_device_descs = 1,
.devices = {
{"TurboSight TBS 5930 lite DVB-S/S2",
{&tbs5931_table[0], NULL},
{NULL},
}
}
};
static int tbs5931_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
if (0 == dvb_usb_device_init(intf, &tbs5931_properties,
THIS_MODULE, NULL, adapter_nr)) {
return 0;
}
return -ENODEV;
}
static struct usb_driver tbs5931_driver = {
.name = "tbs5931",
.probe = tbs5931_probe,
.disconnect = dvb_usb_device_exit,
.id_table = tbs5931_table,
};
static int __init tbs5931_module_init(void)
{
int ret = usb_register(&tbs5931_driver);
if (ret)
err("usb_register failed. Error number %d", ret);
return ret;
}
static void __exit tbs5931_module_exit(void)
{
usb_deregister(&tbs5931_driver);
}
module_init(tbs5931_module_init);
module_exit(tbs5931_module_exit);
MODULE_AUTHOR("Davin zhang<Davin@tbsdtv.com>");
MODULE_DESCRIPTION("TurboSight TBS 5931/5903lite driver");
MODULE_VERSION("1.0");
MODULE_LICENSE("GPL");
/*
* TurboSight TBS 5930 lite driver
*
* Copyright (c) 2017 Davin <davin@tbsdtv.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, version 2.
*
*/
#include <linux/version.h>
#include "tbs5931.h"
#include "gx1133.h"
#include "tas2101.h"
#include "av201x.h"
#define TBS5931_READ_MSG 0
#define TBS5931_WRITE_MSG 1
#define TBS5931_RC_QUERY (0x1a00)
#define TBS5931_VOLTAGE_CTRL (0x1800)
struct tbs5931_state {
u8 initialized;
};
static struct tas2101_config gx1132_cfg = {
.i2c_address = 0x60,
.id = ID_TAS2101,
.init = {0x10, 0x32, 0x54, 0x76, 0xA8, 0x9B, 0x33},
.init2 = 0,
};
static struct gx1133_config gx1133_cfg = {
.i2c_address = 0x52,
.ts_mode = 0,
.ts_cfg = {data_0,data_1,data_2,data_3,data_4,data_5,data_6, \
data_7,ts_sync,ts_err,ts_clk,ts_valid},
};
static struct av201x_config av201x_cfg = {
.i2c_address = 0x62,
.id = ID_AV2012,
.xtal_freq = 27000, /* kHz */
};
/* debug */
static int dvb_usb_tbs5931_debug;
module_param_named(debug, dvb_usb_tbs5931_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))."
DVB_USB_DEBUG_STATUS);
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static int tbs5931_op_rw(struct usb_device *dev, u8 request, u16 value,
u16 index, u8 * data, u16 len, int flags)
{
int ret;
void *u8buf;
unsigned int pipe = (flags == TBS5931_READ_MSG) ?
usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
u8 request_type = (flags == TBS5931_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
u8buf = kmalloc(len, GFP_KERNEL);
if (!u8buf)
return -ENOMEM;
if (flags == TBS5931_WRITE_MSG)
memcpy(u8buf, data, len);
ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
value, index , u8buf, len, 2000);
if (flags == TBS5931_READ_MSG)
memcpy(data, u8buf, len);
kfree(u8buf);
return ret;
}
/* I2C */
static int tbs5931_i2c_transfer(struct i2c_adapter *adap,
struct i2c_msg msg[], int num)
{
struct dvb_usb_device *d = i2c_get_adapdata(adap);
int i = 0;
u8 buf6[35];
u8 inbuf[35];
if (!d)
return -ENODEV;
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
return -EAGAIN;
switch (num) {
case 2:
switch(msg[0].addr){
case 0x60:
case 0x62:
buf6[0]=msg[1].len;//lenth
buf6[1]=msg[0].addr<<1;//demod addr
//register
buf6[2] = msg[0].buf[0];
tbs5931_op_rw(d->udev, 0x90, 0, 0,
buf6, 3, TBS5931_WRITE_MSG);
msleep(1);
tbs5931_op_rw(d->udev, 0x91, 0, 0,
inbuf, buf6[0], TBS5931_READ_MSG);
memcpy(msg[1].buf, inbuf, msg[1].len);
break;
case 0x52:
buf6[0]=msg[1].len;//lenth
buf6[1]=msg[0].addr<<1;//demod addr
//register
memcpy(buf6+2,msg[0].buf,msg[0].len);
tbs5931_op_rw(d->udev, 0x92, 0, 0,
buf6, msg[0].len+2, TBS5931_WRITE_MSG);
msleep(1);
tbs5931_op_rw(d->udev, 0x91, 0, 0,
inbuf, msg[1].len, TBS5931_READ_MSG);
memcpy(msg[1].buf, inbuf, msg[1].len);
break;
}
break;
case 1:
buf6[0] = msg[0].len+1;//lenth
buf6[1] = msg[0].addr<<1;//addr
for(i=0;i<msg[0].len;i++) {
buf6[2+i] = msg[0].buf[i];//register
}
tbs5931_op_rw(d->udev, 0x80, 0, 0,
buf6, msg[0].len+2, TBS5931_WRITE_MSG);
break;
}
mutex_unlock(&d->i2c_mutex);
return num;
}
static u32 tbs5931_i2c_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_I2C;
}
static struct i2c_algorithm tbs5931_i2c_algo = {
.master_xfer = tbs5931_i2c_transfer,
.functionality = tbs5931_i2c_func,
};
static int tbs5931_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
{
int i,ret;
u8 ibuf[3] = {0, 0,0};
u8 eeprom[256], eepromline[16];
for (i = 0; i < 256; i++) {
ibuf[0]=1;//lenth
ibuf[1]=0xA0;//eeprom addr
ibuf[2]=i;//register
ret = tbs5931_op_rw(d->udev, 0x90, 0, 0,
ibuf, 3, TBS5931_WRITE_MSG);
ret = tbs5931_op_rw(d->udev, 0x91, 0, 0,
ibuf, 1, TBS5931_READ_MSG);
if (ret < 0) {
err("read eeprom failed.");
return -1;
} else {
eepromline[i%16] = ibuf[0];
eeprom[i] = ibuf[0];
}
if ((i % 16) == 15) {
deb_xfer("%02x: ", i - 15);
debug_dump(eepromline, 16, deb_xfer);
}
}
memcpy(mac, eeprom + 16, 6);
return 0;
};
static struct dvb_usb_device_properties tbs5931_properties;
static int tbs5931_frontend_attach(struct dvb_usb_adapter *adap)
{
struct dvb_usb_device *d = adap->dev;
u8 buf[20];
u8 a = 0,b = 0;
u16 id;
//read the id to deceted the chip
buf[0]= 1;//lenth
buf[1]= 0xC0;//demod addr
//register
buf[2] = 0x01;
tbs5931_op_rw(d->udev, 0x90, 0, 0,
buf, 3, TBS5931_WRITE_MSG);
msleep(1);
tbs5931_op_rw(d->udev, 0x91, 0, 0,
&a, buf[0], TBS5931_READ_MSG);
msleep(5);
buf[2] = 0x00;
tbs5931_op_rw(d->udev, 0x90, 0, 0,
buf, 3, TBS5931_WRITE_MSG);
msleep(1);
tbs5931_op_rw(d->udev, 0x91, 0, 0,
&b, buf[0], TBS5931_READ_MSG);
id = (b<<8|a);
if(id==0x444c){ //gx1132
adap->fe_adap->fe = dvb_attach(tas2101_attach,&gx1132_cfg,&d->i2c_adap);
if(adap->fe_adap->fe ==NULL)
goto err;
if(dvb_attach(av201x_attach,adap->fe_adap->fe,&av201x_cfg,
tas2101_get_i2c_adapter(adap->fe_adap->fe,2))==NULL){
dvb_frontend_detach(adap->fe_adap->fe);
adap->fe_adap->fe = NULL;
goto err;
}
}
else{
id = 0;
a = 0;
b = 0;
buf[0]= 1;//lenth
buf[1]= 0xA4;//demod addr
//register
buf[2] = 0xff;
buf[3] = 0xf1;
tbs5931_op_rw(d->udev, 0x92, 0, 0,
buf, 4, TBS5931_WRITE_MSG);
msleep(1);
tbs5931_op_rw(d->udev, 0x91, 0, 0,
&a, buf[0], TBS5931_READ_MSG);
msleep(5);
buf[3] = 0xf0;
tbs5931_op_rw(d->udev, 0x92, 0, 0,
buf, 4, TBS5931_WRITE_MSG);
msleep(1);
tbs5931_op_rw(d->udev, 0x91, 0, 0,
&b, buf[0], TBS5931_READ_MSG);
id = (b<<8|a);
if(id==0x444c){ //gx1133
adap->fe_adap->fe = dvb_attach(gx1133_attach,&gx1133_cfg,&d->i2c_adap);
if(adap->fe_adap->fe ==NULL)
goto err;
if(dvb_attach(av201x_attach,adap->fe_adap->fe,&av201x_cfg,
gx1133_get_i2c_adapter(adap->fe_adap->fe,2))==NULL){
dvb_frontend_detach(adap->fe_adap->fe);
adap->fe_adap->fe = NULL;
goto err;
}
}
else
goto err;
}
buf[0] = 0;
buf[1] = 0;
tbs5931_op_rw(d->udev, 0xb7, 0, 0,
buf, 2, TBS5931_WRITE_MSG);
buf[0] = 8;
buf[1] = 1;
tbs5931_op_rw(d->udev, 0x8a, 0, 0,
buf, 2, TBS5931_WRITE_MSG);
msleep(10);
strscpy(adap->fe_adap->fe->ops.info.name,d->props.devices[0].name,52);
return 0;
err:
return -ENODEV;
}
static struct usb_device_id tbs5931_table[] = {
{USB_DEVICE(0x734c, 0x5931)},
{ }
};
MODULE_DEVICE_TABLE(usb, tbs5931_table);
static int tbs5931_load_firmware(struct usb_device *dev,
const struct firmware *frmwr)
{
u8 *b, *p;
int ret = 0, i;
u8 reset;
const struct firmware *fw;
switch (dev->descriptor.idProduct) {
case 0x5931:
ret = request_firmware(&fw, tbs5931_properties.firmware, &dev->dev);
if (ret != 0) {
err("did not find the firmware file. (%s) "
"Please see linux/Documentation/dvb/ for more details "
"on firmware-problems.", tbs5931_properties.firmware);
return ret;
}
break;
default:
fw = frmwr;
break;
}
info("start downloading TBS5931 firmware");
p = kmalloc(fw->size, GFP_KERNEL);
reset = 1;
/*stop the CPU*/
tbs5931_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, TBS5931_WRITE_MSG);
tbs5931_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, TBS5931_WRITE_MSG);
if (p != NULL) {
memcpy(p, fw->data, fw->size);
for (i = 0; i < fw->size; i += 0x40) {
b = (u8 *) p + i;
if (tbs5931_op_rw(dev, 0xa0, i, 0, b , 0x40,
TBS5931_WRITE_MSG) != 0x40) {
err("error while transferring firmware");
ret = -EINVAL;
break;
}
}
/* restart the CPU */
reset = 0;
if (ret || tbs5931_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,
TBS5931_WRITE_MSG) != 1) {
err("could not restart the USB controller CPU.");
ret = -EINVAL;
}
if (ret || tbs5931_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,
TBS5931_WRITE_MSG) != 1) {
err("could not restart the USB controller CPU.");
ret = -EINVAL;
}
msleep(100);
kfree(p);
}
return ret;
}
static struct dvb_usb_device_properties tbs5931_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = DEVICE_SPECIFIC,
.firmware = "dvb-usb-id5931.fw",
.size_of_priv = sizeof(struct tbs5931_state),
.no_reconnect = 1,
.i2c_algo = &tbs5931_i2c_algo,
.generic_bulk_ctrl_endpoint = 0x81,
/* parameter for the MPEG2-data transfer */
.num_adapters = 1,
.download_firmware = tbs5931_load_firmware,
.read_mac_address = tbs5931_read_mac_address,
.adapter = {{
.num_frontends = 1,
.fe = {{
.frontend_attach = tbs5931_frontend_attach,
.streaming_ctrl = NULL,
.tuner_attach = NULL,
.stream = {
.type = USB_BULK,
.count = 8,
.endpoint = 0x82,
.u = {
.bulk = {
.buffersize = 4096,
}
}
},
}
},
}},
.num_device_descs = 1,
.devices = {
{"TurboSight TBS 5930 lite DVB-S/S2",
{&tbs5931_table[0], NULL},
{NULL},
}
}
};
static int tbs5931_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
if (0 == dvb_usb_device_init(intf, &tbs5931_properties,
THIS_MODULE, NULL, adapter_nr)) {
return 0;
}
return -ENODEV;
}
static struct usb_driver tbs5931_driver = {
.name = "tbs5931",
.probe = tbs5931_probe,
.disconnect = dvb_usb_device_exit,
.id_table = tbs5931_table,
};
static int __init tbs5931_module_init(void)
{
int ret = usb_register(&tbs5931_driver);
if (ret)
err("usb_register failed. Error number %d", ret);
return ret;
}
static void __exit tbs5931_module_exit(void)
{
usb_deregister(&tbs5931_driver);
}
module_init(tbs5931_module_init);
module_exit(tbs5931_module_exit);
MODULE_AUTHOR("Davin zhang<Davin@tbsdtv.com>");
MODULE_DESCRIPTION("TurboSight TBS 5931/5903lite driver");
MODULE_VERSION("1.0");
MODULE_LICENSE("GPL");

View File

@@ -1,8 +1,8 @@
#ifndef _TBS5931_H_
#define _TBS5931_H_
#define DVB_USB_LOG_PREFIX "tbs5931"
#include "dvb-usb.h"
#define deb_xfer(args...) dprintk(dvb_usb_tbs5931_debug, 0x02, args)
#endif
#ifndef _TBS5931_H_
#define _TBS5931_H_
#define DVB_USB_LOG_PREFIX "tbs5931"
#include "dvb-usb.h"
#define deb_xfer(args...) dprintk(dvb_usb_tbs5931_debug, 0x02, args)
#endif