Skip to content

Commit

Permalink
Add fw_path param to avl62x1
Browse files Browse the repository at this point in the history
Make string handling in avl68x2 a little safer
  • Loading branch information
Tom Richardson committed Jul 1, 2020
1 parent bdb9cc2 commit 1dcebc1
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 64 deletions.
138 changes: 93 additions & 45 deletions availink/avl62x1/avl62x1_top.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,14 @@
}

static struct avl62x1_bs_state bs_states[AVL_MAX_NUM_DEMODS] = {0};
static struct avl62x1_priv *global_priv; //just for debug
static struct avl62x1_priv *global_priv = NULL;
static char sel_fw[256] = {0};

//--- module params ---
static int debug = 0;
static unsigned short bs_mode = 0;
static int bs_min_sr = 1000000;
char fw_path[256] = {0};
//-------------------

//---- character device stuff ----
Expand Down Expand Up @@ -504,15 +506,16 @@ static int acquire_dvbs_s2(struct dvb_frontend *fe)
}

static int set_dvb_mode(struct dvb_frontend *fe,
enum fe_delivery_system delsys)
enum fe_delivery_system delsys,
bool force_reload)
{
struct avl62x1_priv *priv = fe->demodulator_priv;
uint16_t ret = AVL_EC_OK;
uint16_t r = AVL_EC_OK;
struct avl62x1_ver_info ver_info;

/* already in desired mode */
if (priv->delivery_system == delsys)
if (!force_reload && (priv->delivery_system == delsys))
return 0;

p_debug("initing demod for delsys=%d", delsys);
Expand Down Expand Up @@ -1583,14 +1586,50 @@ static struct dvb_frontend_ops avl62x1_ops = {
.get_frontend = get_frontend,
};

static int avl62x1_get_firmware(struct dvb_frontend *fe) {
unsigned int fw_maj, fw_min, fw_build;
int fw_status;
struct avl62x1_priv *priv = fe->demodulator_priv;

fw_status = request_firmware(&priv->fw,
sel_fw,
priv->i2c->dev.parent);
if (fw_status != 0)
{
p_error("firmware file %s not found",sel_fw);
return fw_status;
}

priv->chip->chip_priv->patch_data = (unsigned char *)(priv->fw->data);
fw_maj = priv->chip->chip_priv->patch_data[24]; //major rev
fw_min = priv->chip->chip_priv->patch_data[25]; //SDK-FW API rev
fw_build = (priv->chip->chip_priv->patch_data[26] << 8) |
priv->chip->chip_priv->patch_data[27]; //internal rev
if(fw_min != AVL62X1_VER_MINOR)
{
//SDK-FW API rev must match
p_error("Firmware version %d.%d.%d incompatible with this driver version",
fw_maj, fw_min, fw_build);
p_error("Firmware minor version must be %d",
AVL62X1_VER_MINOR);
release_firmware(priv->fw);
return 1;
}
else
{
p_info("Firmware version %d.%d.%d found",
fw_maj, fw_min, fw_build);
}

return 0;
}

struct dvb_frontend *avl62x1_attach(struct avl62x1_config *config,
struct i2c_adapter *i2c)
{
struct avl62x1_priv *priv;
uint16_t ret;
uint32_t id;
int fw_status;
unsigned int fw_maj, fw_min, fw_build;

p_info("driver version %s\n", AVL62X1_VERSION);

Expand Down Expand Up @@ -1663,51 +1702,20 @@ struct dvb_frontend *avl62x1_attach(struct avl62x1_config *config,

p_info("found AVL62x1 id=0x%x", id);

fw_status = request_firmware(&priv->fw,
AVL62X1_FIRMWARE,
i2c->dev.parent);
if (fw_status != 0)
{
p_error("firmware file not found");
goto err4;
}
else
{
priv->chip->chip_priv->patch_data = (unsigned char *)(priv->fw->data);
fw_maj = priv->chip->chip_priv->patch_data[24]; //major rev
fw_min = priv->chip->chip_priv->patch_data[25]; //SDK-FW API rev
fw_build = (priv->chip->chip_priv->patch_data[26] << 8) |
priv->chip->chip_priv->patch_data[27]; //internal rev
if(fw_min != AVL62X1_VER_MINOR)
{
//SDK-FW API rev must match
p_error("Firmware version %d.%d.%d incompatible with this driver version",
fw_maj, fw_min, fw_build);
p_error("Firmware minor version must be %d",
AVL62X1_VER_MINOR);
goto err5;
}
else
if(!avl62x1_get_firmware(&priv->frontend)) {
if(!set_dvb_mode(&priv->frontend, SYS_DVBS2, false))
{
p_info("Firmware version %d.%d.%d found",
fw_maj, fw_min, fw_build);
}
}

if (!set_dvb_mode(&priv->frontend, SYS_DVBS2))
{
p_info("Firmware booted");
release_firmware(priv->fw);
init_avl62x1_i2cctl_device(priv);
p_info("Firmware booted");
release_firmware(priv->fw);
init_avl62x1_i2cctl_device(priv);
#if INCLUDE_STDOUT
init_avl62x1_stdout_device(priv);
init_avl62x1_stdout_device(priv);
#endif

return &priv->frontend;

return &priv->frontend;
}
}

err5:
release_firmware(priv->fw);
err4:
kfree(priv->chip->chip_pub);
err3:
Expand All @@ -1726,6 +1734,8 @@ static int __init mod_init(void) {

p_debug("");

global_priv = NULL;

for(i=0; i<AVL_MAX_NUM_DEMODS; i++) {
bs_states[i].bs_mode = (bs_mode>>i) & 1;
bs_states[i].num_carriers = 0;
Expand All @@ -1734,6 +1744,11 @@ static int __init mod_init(void) {
bs_states[i].carriers = NULL;
bs_states[i].streams = NULL;
}

if(strlen(sel_fw) == 0) {
strscpy(sel_fw, AVL62X1_FIRMWARE, sizeof(sel_fw));
}

return 0;
}
module_init(mod_init);
Expand Down Expand Up @@ -1794,6 +1809,39 @@ static const struct kernel_param_ops bs_min_sr_ops = {
module_param_cb(bs_min_sr, &bs_min_sr_ops, &bs_min_sr, 0644);
MODULE_PARM_DESC(bs_min_sr, " minimum symbol rate (Hz) for blindscan mode [1000000:55000000]");

static int fw_path_set(const char *val, const struct kernel_param *kp)
{
char *clean_val = strim((char *)val);
strscpy(sel_fw, clean_val, sizeof(sel_fw));
strscpy(fw_path, clean_val, sizeof(fw_path));

if (global_priv != NULL)
{
if (!avl62x1_get_firmware(&global_priv->frontend))
{
if (!set_dvb_mode(&global_priv->frontend, SYS_DVBS2, true))
{
p_info("New firmware %s booted",sel_fw);
release_firmware(global_priv->fw);
}
}
}

return 0;
}
static int fw_path_get(char *buffer, const struct kernel_param *kp)
{
sprintf(buffer, "%s",sel_fw);
return strlen(buffer);
}
static const struct kernel_param_ops fw_path_ops = {
.set = fw_path_set,
.get = fw_path_get
};
module_param_cb(fw_path, &fw_path_ops, fw_path, 0644);
MODULE_PARM_DESC(fw_path, "<path>");


MODULE_DESCRIPTION("Availink AVL62X1 DVB-S/S2/S2X demodulator driver");
MODULE_AUTHOR("Availink, Inc. ([email protected])");
MODULE_LICENSE("GPL");
Expand Down
2 changes: 1 addition & 1 deletion availink/avl62x1/sdk_src/avl62x1_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
//build number = increment on every change to implementation
#define AVL62X1_VER_MAJOR 3
#define AVL62X1_VER_MINOR 8
#define AVL62X1_VER_BUILD 4
#define AVL62X1_VER_BUILD 5

#define AVL62X1_CHIP_ID 0x62615ca8

Expand Down
44 changes: 26 additions & 18 deletions availink/avl68x2/avl68x2_top.c
Original file line number Diff line number Diff line change
Expand Up @@ -628,19 +628,19 @@ static int avl68x2_get_firmware(struct dvb_frontend *fe, int force_fw)
{
case SYS_DVBS:
case SYS_DVBS2:
strncpy(fw_path, sel_dvbsx_fw, 255);
strscpy(fw_path, sel_dvbsx_fw, sizeof(fw_path));
break;
case SYS_ISDBT:
strncpy(fw_path, sel_isdbt_fw, 255);
strscpy(fw_path, sel_isdbt_fw, sizeof(fw_path));
break;
case SYS_DVBC_ANNEX_A: //"DVB-C"
case SYS_DVBC_ANNEX_B: //J.83-B
strncpy(fw_path, sel_dvbc_fw, 255);
strscpy(fw_path, sel_dvbc_fw, sizeof(fw_path));
break;
case SYS_DVBT:
case SYS_DVBT2:
default:
strncpy(fw_path, sel_dvbtx_fw, 255);
strscpy(fw_path, sel_dvbtx_fw, sizeof(fw_path));
}

fw_status = request_firmware(&priv->fw, fw_path, priv->i2c->dev.parent);
Expand Down Expand Up @@ -2029,28 +2029,28 @@ struct dvb_frontend *avl68x2_attach(struct avl68x2_config *config,
//C, I, S, T
memcpy(&avl68x2_ops.delsys,
delsys_b, sizeof(delsys_b));
strncpy(feat_str,"DVB-C/Sx/Tx, J.83B, and ISDB-T",255);
strscpy(feat_str,"DVB-C/Sx/Tx, J.83B, and ISDB-T",sizeof(feat_str));
part_num = 6882;
break;
case 0xd:
//C, I, S
memcpy(&avl68x2_ops.delsys,
delsys_d, sizeof(delsys_d));
strncpy(feat_str,"DVB-C/Sx, J.83B, and ISDB-T",255);
strscpy(feat_str,"DVB-C/Sx, J.83B, and ISDB-T",sizeof(feat_str));
part_num = 6812;
break;
case 0xe:
//C, T
memcpy(&avl68x2_ops.delsys,
delsys_e, sizeof(delsys_e));
strncpy(feat_str,"DVB-C/Tx and J.83B",255);
strscpy(feat_str,"DVB-C/Tx and J.83B",sizeof(feat_str));
part_num = 6762;
break;
case 0xf:
//C, S, T
memcpy(&avl68x2_ops.delsys,
delsys_f, sizeof(delsys_f));
strncpy(feat_str,"DVB-C/Sx/Tx and J.83B",255);
strscpy(feat_str,"DVB-C/Sx/Tx and J.83B",sizeof(feat_str));
part_num = 6862;
break;
default:
Expand Down Expand Up @@ -2117,16 +2117,16 @@ static int __init mod_init(void) {
}

if(strlen(sel_dvbsx_fw) == 0) {
strncpy(sel_dvbsx_fw, AVL68X2_DVBSX_FW, 255);
strscpy(sel_dvbsx_fw, AVL68X2_DVBSX_FW, sizeof(sel_dvbsx_fw));
}
if(strlen(sel_dvbtx_fw) == 0) {
strncpy(sel_dvbtx_fw, AVL68X2_DVBTX_FW, 255);
strscpy(sel_dvbtx_fw, AVL68X2_DVBTX_FW, sizeof(sel_dvbtx_fw));
}
if(strlen(sel_dvbc_fw) == 0) {
strncpy(sel_dvbc_fw, AVL68X2_DVBC_FW, 255);
strscpy(sel_dvbc_fw, AVL68X2_DVBC_FW, sizeof(sel_dvbc_fw));
}
if(strlen(sel_isdbt_fw) == 0) {
strncpy(sel_isdbt_fw, AVL68X2_ISDBT_FW, 255);
strscpy(sel_isdbt_fw, AVL68X2_ISDBT_FW, sizeof(sel_isdbt_fw));
}

return 0;
Expand Down Expand Up @@ -2254,7 +2254,7 @@ MODULE_PARM_DESC(diseqc_voltage, " voltage control");
size_t get_fw_path(const char *val, const char *prefix, char **begin) {
char *b = NULL;
size_t len = 0;
b = strstr(val,prefix);
b = strstr(strim((char *)val),prefix);
if(b != NULL) {
len = strcspn(b,";");
p_debug("len %d",(int)len);
Expand All @@ -2276,7 +2276,9 @@ static int fw_paths_set(const char *val, const struct kernel_param *kp)
len = get_fw_path(val,"C=",&b);
if(len != 0) {
memset(sel_dvbc_fw,0,sizeof(sel_dvbc_fw));
strncpy(sel_dvbc_fw,&b[2],len-2);
strscpy(sel_dvbc_fw,
&b[2],
min(len - 2, sizeof(sel_dvbc_fw)));
p_info("set C=%s",sel_dvbc_fw);
mode = AVL_DVBC;
delsys = SYS_DVBC_ANNEX_A;
Expand All @@ -2285,7 +2287,9 @@ static int fw_paths_set(const char *val, const struct kernel_param *kp)
len = get_fw_path(val,"I=",&b);
if(len != 0) {
memset(sel_isdbt_fw,0,sizeof(sel_isdbt_fw));
strncpy(sel_isdbt_fw,&b[2],len-2);
strscpy(sel_isdbt_fw,
&b[2],
min(len - 2, sizeof(sel_isdbt_fw)));
p_info("set I=%s",sel_isdbt_fw);
mode = AVL_ISDBT;
delsys = SYS_ISDBT;
Expand All @@ -2294,7 +2298,9 @@ static int fw_paths_set(const char *val, const struct kernel_param *kp)
len = get_fw_path(val,"S=",&b);
if(len != 0) {
memset(sel_dvbsx_fw,0,sizeof(sel_dvbsx_fw));
strncpy(sel_dvbsx_fw,&b[2],len-2);
strscpy(sel_dvbsx_fw,
&b[2],
min(len - 2, sizeof(sel_dvbsx_fw)));
p_info("set S=%s",sel_dvbsx_fw);
mode = AVL_DVBSX;
delsys = SYS_DVBS2;
Expand All @@ -2303,12 +2309,14 @@ static int fw_paths_set(const char *val, const struct kernel_param *kp)
len = get_fw_path(val,"T=",&b);
if(len != 0) {
memset(sel_dvbtx_fw,0,sizeof(sel_dvbtx_fw));
strncpy(sel_dvbtx_fw,&b[2],len-2);
strscpy(sel_dvbtx_fw,
&b[2],
min(len - 2, sizeof(sel_dvbtx_fw)));
p_info("set T=%s",sel_dvbtx_fw);
mode = AVL_DVBTX;
delsys = SYS_DVBT2;
}
strcpy(fw_paths,val);
strscpy(fw_paths,val,sizeof(fw_paths));

if(global_priv != NULL) {
if(avl68x2_get_firmware(&global_priv->frontend,delsys))
Expand Down

0 comments on commit 1dcebc1

Please sign in to comment.