Fix HDHR device discovery
Fix HDHR device discovery code path:
dev_init()
discover_devices()
hdhomerun_discover_find_devices_custom()
get_dev_model_and_fw()
parse_http_page()
hdhomerun_parser()
Change-Id: Ib943026a73ed24ad289d286823983e34bd818e9c
diff --git a/hdhomerun_dev.c b/hdhomerun_dev.c
index 62e12fa..79356c5 100644
--- a/hdhomerun_dev.c
+++ b/hdhomerun_dev.c
@@ -93,24 +93,47 @@
static int hdhomerun_parser(void *context, char *buf, int bytes)
{
- char *p;
+ char *line, *nl, *p;
struct hdhr_tuner_t *ht = (struct hdhr_tuner_t *)context;
- p = strstr(buf, "Model:");
- if (p != NULL) {
- if (strlen(p + 6) < 10)
- return p - buf;
- if (get_string_by_name(p, "Model", ht->model, sizeof(ht->model), NULL)) {
- cleanup_txt(ht->model);
+
+ line = buf;
+ while ((nl = strchr(line, '\n')) != NULL) {
+ // replace \r\n with \0
+ *nl = '\0';
+ if (nl > line && *(nl - 1) == '\r') {
+ *(nl - 1) = '\0';
}
+
+ // process line
+ p = strstr(line, "Model:");
+ if (p) {
+ if (get_string_by_name(p, "Model", ht->model, sizeof(ht->model), NULL)) {
+ cleanup_txt(ht->model);
+ p = strstr(ht->model, "-CC");
+ if (p) {
+ ht->cc_tuner = 1;
+ }
+ p = strstr(ht->model, "HDTC");
+ if (p) {
+ ht->transcode_tuner = 1;
+ }
+ }
+ }
+
+ p = strstr(line, "Firmware:");
+ if (p) {
+ if (get_string_by_name(p, "Firmware", ht->firmware, sizeof(ht->firmware), NULL)) {
+ cleanup_txt(ht->firmware);
+ }
+ }
+
+ line = nl + 1;
}
- if (strstr(buf, "CableCARD Menu") != NULL) {
- ht->cc_tuner = 1;
- }
- return bytes;
+ return (line - buf);
}
-int get_dev_model(struct hdhr_tuner_t *ht)
+int get_dev_model_and_fw(struct hdhr_tuner_t *ht)
{
int ret = parse_http_page(ht->ip, "/", hdhomerun_parser, ht);
return ret;
diff --git a/hdhomerun_dev.h b/hdhomerun_dev.h
index 2848ce0..7e607ad 100644
--- a/hdhomerun_dev.h
+++ b/hdhomerun_dev.h
@@ -1,7 +1,7 @@
#ifndef _HDHOMERUN_DEV_H_
#define _HDHOMERUN_DEV_H_
-int get_dev_model(struct hdhr_tuner_t *ht);
+int get_dev_model_and_fw(struct hdhr_tuner_t *ht);
int get_vchannel_list(struct vchan_tbl_t *vt);
#endif
diff --git a/hdhomerun_plugin.c b/hdhomerun_plugin.c
index 98ea933..9edf076 100644
--- a/hdhomerun_plugin.c
+++ b/hdhomerun_plugin.c
@@ -24,27 +24,9 @@
struct hdhr_tuner_t *hdhrs;
};
-static int discover_hdhrs(struct hdhr_tuner_t *ht, int max_ht_num)
-{
- int i, ret = 0;
- ret = discover_device(ht, max_ht_num);
- if (ret > 0) {
- for (i = 0; i < ret; i++) {
- // if a unit shares a source input in a device, copy data.
- if (i > 0 && tuner_input_sharing(&ht[i - 1], &ht[i])) {
- ht[i].cc_tuner = ht[i - 1].cc_tuner;
- strncpy(ht[i].model, ht[i - 1].model, sizeof(ht[i].model));
- } else
- get_dev_model(&ht[i]);
- }
- return i;
- }
- return 0;
-}
-
void *dev_init(int *num)
{
- int i, index = 0, tuner_num;
+ int i;
struct device_list *devices;
sage_log((_LOG_TRACE, 3, "hdhr:hdhomerun device init"));
@@ -53,30 +35,23 @@
if (devices != NULL) {
devices->hdhrs = (struct hdhr_tuner_t *)malloc(sizeof(struct hdhr_tuner_t) *
MAX_TUNER_NUM);
- memset(devices->hdhrs, 0,
- sizeof(sizeof(struct hdhr_tuner_t) * MAX_TUNER_NUM));
if (devices->hdhrs == NULL) {
free(devices);
- return 0;
+ return NULL;
}
+ memset(devices->hdhrs, 0,
+ sizeof(sizeof(struct hdhr_tuner_t) * MAX_TUNER_NUM));
devices->list_num = MAX_TUNER_NUM;
- devices->tuner_num = 0;
- tuner_num = discover_hdhrs(devices->hdhrs, MAX_TUNER_NUM);
- for (i = 0; i < tuner_num; i++) {
- devices->hdhrs[i].tuner_id = index++;
- snprintf(devices->hdhrs[i].tuner_name,
- sizeof(devices->hdhrs[i].tuner_name), "%s-%s",
- devices->hdhrs[i].model, devices->hdhrs[i].name);
- devices->tuner_num++;
- sage_log((_LOG_TRACE, 3, "hdhr:%d %s %s %s", i,
+ devices->tuner_num = discover_devices(devices->hdhrs, MAX_TUNER_NUM);
+ for (i = 0; i < devices->tuner_num; i++) {
+ sage_log((_LOG_TRACE, 3, "hdhr:%d %s %s %s %s", i,
devices->hdhrs[i].tuner_name, devices->hdhrs[i].model,
- devices->hdhrs[i].cc_tuner ? "CableCard" : ""));
+ devices->hdhrs[i].cc_tuner ? "CableCard" : "ATSC",
+ devices->hdhrs[i].firmware));
}
- devices->tuner_num = tuner_num;
- *num = tuner_num;
- return devices;
+ *num = devices->tuner_num;
}
- return NULL;
+ return devices;
}
void dev_release(void *handle)
diff --git a/hdhomerun_tuner.c b/hdhomerun_tuner.c
index d220d64..e04052b 100644
--- a/hdhomerun_tuner.c
+++ b/hdhomerun_tuner.c
@@ -349,33 +349,43 @@
return buf;
}
-int discover_device(struct hdhr_tuner_t *ht, int max_ht_num)
+int discover_devices(struct hdhr_tuner_t *ht, int max_ht_num)
{
- int i, k, num = 0;
- struct hdhomerun_discover_device_t *device_info =
- malloc(max_ht_num * sizeof(struct hdhomerun_discover_device_t));
- int ret = hdhomerun_discover_find_devices_custom(
- 0, HDHOMERUN_DEVICE_TYPE_TUNER, -1, device_info, 16);
- if (ret <= 0) {
- free(device_info);
- return 0;
+ int i, k, count, num = 0;
+ struct hdhomerun_discover_device_t device_info[max_ht_num];
+ struct hdhr_tuner_t hdhr;
+
+ while (1) {
+ count = hdhomerun_discover_find_devices_custom(0,
+ HDHOMERUN_DEVICE_TYPE_TUNER, HDHOMERUN_DEVICE_ID_WILDCARD,
+ device_info, max_ht_num);
+ if (count > 0) {
+ break;
+ }
+ sleep(3);
}
- // printf( "found %d hdhomerun device\n", ret );
- for (i = 0; i < ret; i++) {
- // printf( "ip:%x type:%x id:%x num:%d\n", device_info[i].ip_addr,
- // device_info[i].device_type, device_info[i].device_id,
- // device_info[i].tuner_count );
+
+ for (i = 0; i < count; i++) {
+ memset(&hdhr, 0, sizeof(hdhr));
+ ip4_address(device_info[i].ip_addr, hdhr.ip, sizeof(hdhr.ip));
+ get_dev_model_and_fw(&hdhr);
+
for (k = 0; k < device_info[i].tuner_count && num < max_ht_num; k++) {
+ ht[num].tuner_id = num;
+ ht[num].type = device_info[i].device_type;
snprintf(ht[num].name, sizeof(ht[num].name), "%X-%d",
device_info[i].device_id, k);
- ip4_address(device_info[i].ip_addr, ht[num].ip, sizeof(ht[num].ip));
- ht[num].type = device_info[i].device_type;
- ht[num].cc_tuner = 0;
- ht[num].model[0] = 0;
+ snprintf(ht[num].ip, sizeof(ht[num].ip), "%s", hdhr.ip);
+ snprintf(ht[num].model, sizeof(ht[num].model), "%s", hdhr.model);
+ snprintf(ht[num].firmware, sizeof(ht[num].firmware), "%s", hdhr.firmware);
+ snprintf(ht[num].tuner_name, sizeof(ht[num].tuner_name), "%s-%s",
+ ht[num].model, ht[num].name);
+ ht[num].cc_tuner = hdhr.cc_tuner;
+ ht[num].transcode_tuner = hdhr.transcode_tuner;
num++;
}
}
- free(device_info);
+
return num;
}
@@ -552,13 +562,6 @@
return 1;
}
-int tuner_input_sharing(struct hdhr_tuner_t *ht1, struct hdhr_tuner_t *ht2)
-{
- if (ht1->cc_tuner == 1 && !strcmp(ht1->ip, ht2->ip))
- return 1;
- return 0;
-}
-
#ifdef TEST_APP
static int scan_channel(void *device, int index, struct channel_entry_t *ce,
int ce_channel_num, int ce_num)
@@ -773,17 +776,10 @@
int tuner_count = 0;
struct hdhr_tuner_t ht[16];
- ret = discover_device(ht, 16);
+ ret = discover_devices(ht, 16);
printf("found tuners:%d\n", ret);
if (ret > 0) {
for (i = 0; i < ret; i++) {
- // if a unit shares a source input in a device, copy data.
- if (i > 0 && tuner_input_sharing(&ht[i - 1], &ht[i])) {
- ht[i].cc_tuner = ht[i - 1].cc_tuner;
- strncpy(ht[i].model, ht[i - 1].model, sizeof(ht[i].model));
- } else
- get_dev_model(&ht[i]);
-
printf("%d tuner:%s ip:%s type:%d cc:%d model:%s\n", i, ht[i].name,
ht[i].ip, ht[i].type, ht[i].cc_tuner, ht[i].model);
}
diff --git a/hdhomerun_tuner.h b/hdhomerun_tuner.h
index 4f1ed2e..6ac2403 100644
--- a/hdhomerun_tuner.h
+++ b/hdhomerun_tuner.h
@@ -8,8 +8,10 @@
char name[16]; // internal used by hdhomerun device
char ip[16]; // device unit ip
char model[16]; // device model
+ char firmware[32]; // device firmware
int type; // device type 1:atsc 2:qam 3:dvb
int cc_tuner; // cable card tuner
+ int transcode_tuner; // transcoding tuner
void *channel_table; // channel scan private data
};
@@ -27,7 +29,7 @@
struct channel_entry_t;
-int discover_device(struct hdhr_tuner_t *ht, int max_ht_num);
+int discover_devices(struct hdhr_tuner_t *ht, int max_ht_num);
void *open_hdhr(char *name);
void close_hdhr(void *device);
char *get_unit_name(struct hdhr_tuner_t *ht, char *name, int size);
@@ -41,7 +43,6 @@
char *stream_target);
int stop_channel(void *device);
int scan_vchannel(void *device, int vchannel, struct channel_entry_t *ce);
-int tuner_input_sharing(struct hdhr_tuner_t *ht1, struct hdhr_tuner_t *ht2);
struct vchan_tbl_t *create_vchan_tbl(struct hdhr_tuner_t *ht);
void release_vchan_tbl(struct vchan_tbl_t *vt);
int grow_vhcan_tbl(struct vchan_tbl_t *vt);