mirror of
https://github.com/DigitalDevices/dddvb.git
synced 2025-03-01 10:35:23 +00:00
add support for license setting via MCI commands (only FSM cards for now)
This commit is contained in:
parent
63f693946c
commit
5fef324ea0
@ -1,4 +1,4 @@
|
||||
TARGETS = cit ddtest setmod1 setmod2 modconfig ddinfo getiq modtest
|
||||
TARGETS = cit ddtest setmod1 setmod2 modconfig ddinfo getiq modtest ddlicense
|
||||
|
||||
all: $(TARGETS)
|
||||
|
||||
|
@ -30,7 +30,7 @@ char *Rolloff[8] = {
|
||||
"rsvd",
|
||||
};
|
||||
|
||||
void dump(const uint8_t *b, int l)
|
||||
void dump(uint8_t *b, int l)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
@ -45,6 +45,15 @@ void dump(const uint8_t *b, int l)
|
||||
}
|
||||
}
|
||||
|
||||
void ldump(uint8_t *b, int l)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < l; i++)
|
||||
printf("%02X", b[i]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void print_temp(struct mci_result *res)
|
||||
{
|
||||
printf("Die temperature = %u\n", res->sx8_bist.temperature);
|
||||
@ -344,17 +353,18 @@ int readreg(int dev, uint32_t reg, uint32_t link, uint32_t *val)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mci_firmware(int dev, uint32_t link)
|
||||
void mci_firmware(int dev, uint32_t link, uint32_t base)
|
||||
{
|
||||
union {
|
||||
uint32_t u[4];
|
||||
char s[16];
|
||||
} version;
|
||||
|
||||
readreg(dev, MIC_INTERFACE_VER , link, &version.u[0]);
|
||||
readreg(dev, MIC_INTERFACE_VER + 4, link, &version.u[1]);
|
||||
readreg(dev, MIC_INTERFACE_VER + 8, link, &version.u[2]);
|
||||
readreg(dev, MIC_INTERFACE_VER + 12, link, &version.u[3]);
|
||||
|
||||
base += 0xf0;
|
||||
readreg(dev, base , link, &version.u[0]);
|
||||
readreg(dev, base + 4, link, &version.u[1]);
|
||||
readreg(dev, base + 8, link, &version.u[2]);
|
||||
readreg(dev, base + 12, link, &version.u[3]);
|
||||
|
||||
printf("MCI firmware: %s.%d\n", &version.s, version.s[15]);
|
||||
}
|
||||
@ -368,7 +378,6 @@ int mci_info(int dev, uint32_t link, uint8_t demod)
|
||||
.cmd.demod = demod
|
||||
};
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg);
|
||||
if (ret < 0) {
|
||||
@ -380,6 +389,35 @@ int mci_info(int dev, uint32_t link, uint8_t demod)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void print_license(int dev, struct mci_result *res)
|
||||
{
|
||||
if (res->license.serial_number[0] == 0xff)
|
||||
res->license.serial_number[0] = 0;
|
||||
printf("SERNBR:%s\n", (char *) &res->license.serial_number);
|
||||
printf("ID:");
|
||||
ldump(res->license.ID, 8);
|
||||
printf("LK:");
|
||||
ldump(res->license.LK, 24);
|
||||
}
|
||||
|
||||
int mci_license(int dev)
|
||||
{
|
||||
struct ddb_mci_msg msg = {
|
||||
.link = 0,
|
||||
.cmd.command = CMD_GET_SERIALNUMBER,
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg);
|
||||
if (ret < 0) {
|
||||
printf("Error: %d %d\n", ret, errno);
|
||||
return ret;
|
||||
}
|
||||
|
||||
print_license(dev, &msg.res);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int get_id(int fd, int link, struct ddb_id *id)
|
||||
{
|
||||
struct ddb_reg ddbreg;
|
||||
@ -416,6 +454,8 @@ static int get_id(int fd, int link, struct ddb_id *id)
|
||||
static char *id2name(uint16_t id)
|
||||
{
|
||||
switch (id) {
|
||||
case 0x210:
|
||||
return "FSM";
|
||||
case 0x222:
|
||||
return "MOD";
|
||||
case 0x0009:
|
||||
@ -476,7 +516,7 @@ static int card_info(int ddbnum, int demod)
|
||||
num = 4;
|
||||
if (id.device == 0x0014)
|
||||
num = 2;
|
||||
mci_firmware(ddb, link);
|
||||
mci_firmware(ddb, link, 0x600);
|
||||
if (demod >= 0)
|
||||
mci_info(ddb, link, demod);
|
||||
else {
|
||||
@ -484,6 +524,14 @@ static int card_info(int ddbnum, int demod)
|
||||
mci_info(ddb, link, i);
|
||||
}
|
||||
break;
|
||||
case 0x0210:
|
||||
if (!(id.hw & 0x01000000))
|
||||
break;
|
||||
mci_firmware(ddb, link, 0x300);
|
||||
printf("VEN:DD01\n");
|
||||
printf("DEV:0210\n");
|
||||
mci_license(ddb);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
255
apps/ddlicense.c
Normal file
255
apps/ddlicense.c
Normal file
@ -0,0 +1,255 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <linux/types.h>
|
||||
#include <getopt.h>
|
||||
#include <ctype.h>
|
||||
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef int16_t s16;
|
||||
typedef uint32_t u32;
|
||||
typedef uint64_t u64;
|
||||
|
||||
#include "../ddbridge/ddbridge-mci.h"
|
||||
#include "../ddbridge/ddbridge-ioctl.h"
|
||||
|
||||
static void dump(const uint8_t *b, int l)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (j = 0; j < l; j += 16, b += 16) {
|
||||
printf("%04x: ", j);
|
||||
for (i = 0; i < 16; i++)
|
||||
if (i + j < l)
|
||||
printf("%02x ", b[i]);
|
||||
else
|
||||
printf(" ");
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void ldump(FILE *f, uint8_t *b, int l)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < l; i++)
|
||||
fprintf(f, "%02X", b[i]);
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
|
||||
static int mci_get_license(int dev, uint8_t *ID, uint8_t *LK, uint8_t *SN)
|
||||
{
|
||||
struct ddb_mci_msg msg = {
|
||||
.link = 0,
|
||||
.cmd.command = CMD_GET_SERIALNUMBER,
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg);
|
||||
if (ret < 0) {
|
||||
dprintf(2, "Error: %d\n", ret, errno);
|
||||
return ret;
|
||||
}
|
||||
if (msg.res.status != 0x00) {
|
||||
dprintf(2, "MCI error: %02x, check firmware and license file.\n", msg.res.status);
|
||||
return -1;
|
||||
}
|
||||
memcpy(ID, msg.res.license.ID, 8);
|
||||
memcpy(LK, msg.res.license.LK, 24);
|
||||
memcpy(SN, msg.res.license.serial_number, 24);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mci_set_license(int dev, uint8_t *ID, uint8_t *LK)
|
||||
{
|
||||
struct ddb_mci_msg msg = {
|
||||
.link = 0,
|
||||
.cmd.command = CMD_IMPORT_LICENSE,
|
||||
};
|
||||
int ret;
|
||||
|
||||
memcpy(msg.cmd.license.ID, ID, 8);
|
||||
memcpy(msg.cmd.license.LK, LK, 24);
|
||||
|
||||
ret = ioctl(dev, IOCTL_DDB_MCI_CMD, &msg);
|
||||
if (ret < 0) {
|
||||
printf("Error: %d %d\n", ret, errno);
|
||||
return ret;
|
||||
}
|
||||
if (msg.res.status != 0x00) {
|
||||
dprintf(2, "MCI error: %02x, check firmware and license file.\n", msg.res.status);
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int GetHex(char* s, uint32_t nBytes, uint8_t *Buffer)
|
||||
{
|
||||
int i;
|
||||
|
||||
if( strlen(s) < (nBytes * 2) )
|
||||
return -1;
|
||||
for (i = 0; i < nBytes; i += 1) {
|
||||
char d0, d1;
|
||||
d0 = s[i*2];
|
||||
if( !isxdigit(d0) ) return -1;
|
||||
d1 = s[i*2+1];
|
||||
if( !isxdigit(d1) ) return -1;
|
||||
d0 = toupper(d0);
|
||||
d1 = toupper(d1);
|
||||
Buffer[i] =(uint8_t) ((d0 > '9' ? d0 - 'A' + 10 : d0 - '0') << 4) | ((d1 > '9' ? d1 - 'A' + 10 : d1 - '0'));
|
||||
}
|
||||
return (nBytes * 2);
|
||||
}
|
||||
|
||||
static int get_id_lk(char *fn, uint8_t *ID, uint8_t *LK)
|
||||
{
|
||||
FILE *fin = fopen(fn, "r");
|
||||
|
||||
if (!fin) {
|
||||
printf("License file not found\n");
|
||||
return -1;
|
||||
}
|
||||
memset(ID, 0, 8);
|
||||
memset(LK, 0xff, 24);
|
||||
while (1) {
|
||||
char s[128];
|
||||
if (fgets(s, sizeof(s), fin) == NULL)
|
||||
break;
|
||||
if (strncmp(s,"ID:",3) == 0) {
|
||||
if (GetHex(&s[3], 8, ID) < 0 )
|
||||
return -1;
|
||||
}
|
||||
if (strncmp(s,"LK:",3) == 0) {
|
||||
if (GetHex(&s[3],24, LK) < 0 )
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
//dump(ID, 8);
|
||||
//dump(LK, 24);
|
||||
fclose(fin);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_license(int ddb, struct ddb_id *id, char *ename)
|
||||
{
|
||||
uint8_t ID[8], LK[24], SN[17];
|
||||
int stat;
|
||||
FILE *f = fopen(ename, "w+");
|
||||
|
||||
if (!f) {
|
||||
dprintf(2, "Could not write to output file.\n");
|
||||
return -1;
|
||||
}
|
||||
stat = mci_get_license(ddb, ID, LK, SN);
|
||||
if (stat < 0) {
|
||||
dprintf(2, "Could not read license.\n");
|
||||
return stat;
|
||||
}
|
||||
if (SN[0] == 0xff)
|
||||
SN[0] = 0;
|
||||
fprintf(f, "VEN:%04X\n", id->vendor);
|
||||
fprintf(f, "DEV:%04X\n", id->device);
|
||||
fprintf(f, "SERNBR:%s\n", (char *) SN);
|
||||
fprintf(f, "ID:");
|
||||
ldump(f, ID, 8);
|
||||
fprintf(f, "LK:");
|
||||
ldump(f, LK, 24);
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_license(int ddb, char *iname)
|
||||
{
|
||||
uint8_t ID[8], LK[24];
|
||||
int stat=0;
|
||||
|
||||
stat = get_id_lk(iname, ID, LK);
|
||||
if (stat < 0)
|
||||
return stat;
|
||||
return mci_set_license(ddb, ID, LK);
|
||||
}
|
||||
|
||||
static int get_set_license(int ddbnum, char *ename, char *iname)
|
||||
{
|
||||
int ddb, stat = 0;
|
||||
char ddbname[80];
|
||||
struct ddb_id id;
|
||||
|
||||
sprintf(ddbname, "/dev/ddbridge/card%d", ddbnum);
|
||||
ddb = open(ddbname, O_RDWR);
|
||||
if (ddb < 0) {
|
||||
dprintf(2, "Error opening device %s\n", ddbname);
|
||||
return -3;
|
||||
}
|
||||
if (ioctl(ddb, IOCTL_DDB_ID, &id) < 0) {
|
||||
dprintf(2, "Unsupported device %s.\n", ddbname);
|
||||
return -1;
|
||||
}
|
||||
if (id.device != 0x210) {
|
||||
dprintf(2, "Unsupported device %s with ID %04x.\n", ddbname, id.device);
|
||||
return -1;
|
||||
}
|
||||
if (ename)
|
||||
stat = get_license(ddb, &id, ename);
|
||||
if (iname)
|
||||
stat = set_license(ddb, iname);
|
||||
close(ddb);
|
||||
return stat;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char*argv[])
|
||||
{
|
||||
int fd = -1, all = 1, i, ret = 0;
|
||||
char fn[128];
|
||||
int32_t device = 0;
|
||||
char *iname = 0, *ename = 0;
|
||||
|
||||
while (1) {
|
||||
int cur_optind = optind ? optind : 1;
|
||||
int option_index = 0;
|
||||
int c;
|
||||
static struct option long_options[] = {
|
||||
{"device", required_argument, 0, 'd'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
c = getopt_long(argc, argv, "ad:i:e:",
|
||||
long_options, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
switch (c) {
|
||||
case 'd':
|
||||
device = strtoul(optarg, NULL, 0);
|
||||
break;
|
||||
case 'a':
|
||||
all = 1;
|
||||
break;
|
||||
case 'i':
|
||||
iname = optarg;
|
||||
break;
|
||||
case 'e':
|
||||
ename = optarg;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (optind < argc) {
|
||||
printf("too many arguments\n");
|
||||
exit(1);
|
||||
}
|
||||
if (!ename && !iname) {
|
||||
dprintf(2, "Neither export nor import file name provided.\n");
|
||||
return -1;
|
||||
}
|
||||
get_set_license(device, ename, iname);
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user