00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "hdhomerun.h"
00034
00035 struct hdhomerun_device_t {
00036 struct hdhomerun_control_sock_t *cs;
00037 struct hdhomerun_video_sock_t *vs;
00038 struct hdhomerun_debug_t *dbg;
00039 struct hdhomerun_channelscan_t *scan;
00040 uint32_t multicast_ip;
00041 uint16_t multicast_port;
00042 uint32_t device_id;
00043 unsigned int tuner;
00044 uint32_t lockkey;
00045 char name[32];
00046 char model[32];
00047 };
00048
00049 static int hdhomerun_device_set_device_normal(struct hdhomerun_device_t *hd, uint32_t device_id, uint32_t device_ip)
00050 {
00051 if (!hd->cs) {
00052 hd->cs = hdhomerun_control_create(0, 0, hd->dbg);
00053 if (!hd->cs) {
00054 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_device: failed to create control object\n");
00055 return -1;
00056 }
00057 }
00058
00059 hdhomerun_control_set_device(hd->cs, device_id, device_ip);
00060
00061 if ((device_id == 0) || (device_id == HDHOMERUN_DEVICE_ID_WILDCARD)) {
00062 device_id = hdhomerun_control_get_device_id(hd->cs);
00063 }
00064
00065 hd->multicast_ip = 0;
00066 hd->multicast_port = 0;
00067 hd->device_id = device_id;
00068 hd->tuner = 0;
00069 hd->lockkey = 0;
00070
00071 sprintf(hd->name, "%08lX-%u", (unsigned long)hd->device_id, hd->tuner);
00072 hd->model[0] = 0;
00073
00074 return 1;
00075 }
00076
00077 static int hdhomerun_device_set_device_multicast(struct hdhomerun_device_t *hd, uint32_t multicast_ip)
00078 {
00079 if (hd->cs) {
00080 hdhomerun_control_destroy(hd->cs);
00081 hd->cs = NULL;
00082 }
00083
00084 hd->multicast_ip = multicast_ip;
00085 hd->multicast_port = 0;
00086 hd->device_id = 0;
00087 hd->tuner = 0;
00088 hd->lockkey = 0;
00089
00090 unsigned long ip = multicast_ip;
00091 sprintf(hd->name, "%lu.%lu.%lu.%lu", (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, (ip >> 0) & 0xFF);
00092 sprintf(hd->model, "multicast");
00093
00094 return 1;
00095 }
00096
00097 int hdhomerun_device_set_device(struct hdhomerun_device_t *hd, uint32_t device_id, uint32_t device_ip)
00098 {
00099 if ((device_id == 0) && (device_ip == 0)) {
00100 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_device: device not specified\n");
00101 return -1;
00102 }
00103
00104 if (hdhomerun_discover_is_ip_multicast(device_ip)) {
00105 return hdhomerun_device_set_device_multicast(hd, device_ip);
00106 }
00107
00108 return hdhomerun_device_set_device_normal(hd, device_id, device_ip);
00109 }
00110
00111 int hdhomerun_device_set_tuner(struct hdhomerun_device_t *hd, unsigned int tuner)
00112 {
00113 if (hd->multicast_ip != 0) {
00114 if (tuner != 0) {
00115 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner: tuner cannot be specified in multicast mode\n");
00116 return -1;
00117 }
00118
00119 return 1;
00120 }
00121
00122 hd->tuner = tuner;
00123 sprintf(hd->name, "%08lX-%u", (unsigned long)hd->device_id, hd->tuner);
00124
00125 return 1;
00126 }
00127
00128 struct hdhomerun_device_t *hdhomerun_device_create(uint32_t device_id, uint32_t device_ip, unsigned int tuner, struct hdhomerun_debug_t *dbg)
00129 {
00130 struct hdhomerun_device_t *hd = (struct hdhomerun_device_t *)calloc(1, sizeof(struct hdhomerun_device_t));
00131 if (!hd) {
00132 hdhomerun_debug_printf(dbg, "hdhomerun_device_create: failed to allocate device object\n");
00133 return NULL;
00134 }
00135
00136 hd->dbg = dbg;
00137
00138 if ((device_id == 0) && (device_ip == 0) && (tuner == 0)) {
00139 return hd;
00140 }
00141
00142 if (hdhomerun_device_set_device(hd, device_id, device_ip) <= 0) {
00143 free(hd);
00144 return NULL;
00145 }
00146 if (hdhomerun_device_set_tuner(hd, tuner) <= 0) {
00147 free(hd);
00148 return NULL;
00149 }
00150
00151 return hd;
00152 }
00153
00154 void hdhomerun_device_destroy(struct hdhomerun_device_t *hd)
00155 {
00156 if (hd->scan) {
00157 channelscan_destroy(hd->scan);
00158 }
00159
00160 if (hd->vs) {
00161 hdhomerun_video_destroy(hd->vs);
00162 }
00163
00164 if (hd->cs) {
00165 hdhomerun_control_destroy(hd->cs);
00166 }
00167
00168 free(hd);
00169 }
00170
00171 static bool_t is_hex_char(char c)
00172 {
00173 if ((c >= '0') && (c <= '9')) {
00174 return TRUE;
00175 }
00176 if ((c >= 'A') && (c <= 'F')) {
00177 return TRUE;
00178 }
00179 if ((c >= 'a') && (c <= 'f')) {
00180 return TRUE;
00181 }
00182 return FALSE;
00183 }
00184
00185 static struct hdhomerun_device_t *hdhomerun_device_create_from_str_device_id(const char *device_str, struct hdhomerun_debug_t *dbg)
00186 {
00187 int i;
00188 const char *ptr = device_str;
00189 for (i = 0; i < 8; i++) {
00190 if (!is_hex_char(*ptr++)) {
00191 return NULL;
00192 }
00193 }
00194
00195 if (*ptr == 0) {
00196 unsigned long device_id;
00197 if (sscanf(device_str, "%lx", &device_id) != 1) {
00198 return NULL;
00199 }
00200 return hdhomerun_device_create((uint32_t)device_id, 0, 0, dbg);
00201 }
00202
00203 if (*ptr == '-') {
00204 unsigned long device_id;
00205 unsigned int tuner;
00206 if (sscanf(device_str, "%lx-%u", &device_id, &tuner) != 2) {
00207 return NULL;
00208 }
00209 return hdhomerun_device_create((uint32_t)device_id, 0, tuner, dbg);
00210 }
00211
00212 return NULL;
00213 }
00214
00215 static struct hdhomerun_device_t *hdhomerun_device_create_from_str_ip_result(unsigned long a[4], unsigned int port, unsigned int tuner, struct hdhomerun_debug_t *dbg)
00216 {
00217 unsigned long device_ip = (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | (a[3] << 0);
00218 struct hdhomerun_device_t *hd = hdhomerun_device_create(HDHOMERUN_DEVICE_ID_WILDCARD, (uint32_t)device_ip, tuner, dbg);
00219 if (!hd) {
00220 return NULL;
00221 }
00222
00223 if (hd->multicast_ip != 0) {
00224 hd->multicast_port = (uint16_t)port;
00225 }
00226
00227 return hd;
00228 }
00229
00230 static struct hdhomerun_device_t *hdhomerun_device_create_from_str_ip(const char *device_str, struct hdhomerun_debug_t *dbg)
00231 {
00232 unsigned long a[4];
00233 unsigned int port = 0;
00234 unsigned int tuner = 0;
00235
00236 if (sscanf(device_str, "%lu.%lu.%lu.%lu:%u", &a[0], &a[1], &a[2], &a[3], &port) == 5) {
00237 return hdhomerun_device_create_from_str_ip_result(a, port, tuner, dbg);
00238 }
00239 if (sscanf(device_str, "%lu.%lu.%lu.%lu-%u", &a[0], &a[1], &a[2], &a[3], &tuner) == 5) {
00240 return hdhomerun_device_create_from_str_ip_result(a, port, tuner, dbg);
00241 }
00242 if (sscanf(device_str, "%lu.%lu.%lu.%lu", &a[0], &a[1], &a[2], &a[3]) == 4) {
00243 return hdhomerun_device_create_from_str_ip_result(a, port, tuner, dbg);
00244 }
00245
00246 return NULL;
00247 }
00248
00249 static struct hdhomerun_device_t *hdhomerun_device_create_from_str_dns(const char *device_str, struct hdhomerun_debug_t *dbg)
00250 {
00251 #if defined(__CYGWIN__)
00252 return NULL;
00253 #else
00254 struct addrinfo hints;
00255 memset(&hints, 0, sizeof(hints));
00256 hints.ai_family = AF_INET;
00257 hints.ai_socktype = SOCK_STREAM;
00258 hints.ai_protocol = IPPROTO_TCP;
00259
00260 struct addrinfo *sock_info;
00261 if (getaddrinfo(device_str, "65001", &hints, &sock_info) != 0) {
00262 return NULL;
00263 }
00264
00265 struct sockaddr_in *sock_addr = (struct sockaddr_in *)sock_info->ai_addr;
00266 uint32_t device_ip = ntohl(sock_addr->sin_addr.s_addr);
00267 freeaddrinfo(sock_info);
00268
00269 if (device_ip == 0) {
00270 return NULL;
00271 }
00272
00273 return hdhomerun_device_create(HDHOMERUN_DEVICE_ID_WILDCARD, (uint32_t)device_ip, 0, dbg);
00274 #endif
00275 }
00276
00277 struct hdhomerun_device_t *hdhomerun_device_create_from_str(const char *device_str, struct hdhomerun_debug_t *dbg)
00278 {
00279 struct hdhomerun_device_t *device = hdhomerun_device_create_from_str_device_id(device_str, dbg);
00280 if (device) {
00281 return device;
00282 }
00283
00284 device = hdhomerun_device_create_from_str_ip(device_str, dbg);
00285 if (device) {
00286 return device;
00287 }
00288
00289 device = hdhomerun_device_create_from_str_dns(device_str, dbg);
00290 if (device) {
00291 return device;
00292 }
00293
00294 return NULL;
00295 }
00296
00297 int hdhomerun_device_set_tuner_from_str(struct hdhomerun_device_t *hd, const char *tuner_str)
00298 {
00299 unsigned int tuner;
00300 if (sscanf(tuner_str, "%u", &tuner) == 1) {
00301 hdhomerun_device_set_tuner(hd, tuner);
00302 return 1;
00303 }
00304 if (sscanf(tuner_str, "/tuner%u", &tuner) == 1) {
00305 hdhomerun_device_set_tuner(hd, tuner);
00306 return 1;
00307 }
00308
00309 return -1;
00310 }
00311
00312 const char *hdhomerun_device_get_name(struct hdhomerun_device_t *hd)
00313 {
00314 return hd->name;
00315 }
00316
00317 uint32_t hdhomerun_device_get_device_id(struct hdhomerun_device_t *hd)
00318 {
00319 return hd->device_id;
00320 }
00321
00322 uint32_t hdhomerun_device_get_device_ip(struct hdhomerun_device_t *hd)
00323 {
00324 if (hd->multicast_ip != 0) {
00325 return hd->multicast_ip;
00326 }
00327 if (hd->cs) {
00328 return hdhomerun_control_get_device_ip(hd->cs);
00329 }
00330
00331 return 0;
00332 }
00333
00334 uint32_t hdhomerun_device_get_device_id_requested(struct hdhomerun_device_t *hd)
00335 {
00336 if (hd->multicast_ip != 0) {
00337 return 0;
00338 }
00339 if (hd->cs) {
00340 return hdhomerun_control_get_device_id_requested(hd->cs);
00341 }
00342
00343 return 0;
00344 }
00345
00346 uint32_t hdhomerun_device_get_device_ip_requested(struct hdhomerun_device_t *hd)
00347 {
00348 if (hd->multicast_ip != 0) {
00349 return hd->multicast_ip;
00350 }
00351 if (hd->cs) {
00352 return hdhomerun_control_get_device_ip_requested(hd->cs);
00353 }
00354
00355 return 0;
00356 }
00357
00358 unsigned int hdhomerun_device_get_tuner(struct hdhomerun_device_t *hd)
00359 {
00360 return hd->tuner;
00361 }
00362
00363 struct hdhomerun_control_sock_t *hdhomerun_device_get_control_sock(struct hdhomerun_device_t *hd)
00364 {
00365 return hd->cs;
00366 }
00367
00368 struct hdhomerun_video_sock_t *hdhomerun_device_get_video_sock(struct hdhomerun_device_t *hd)
00369 {
00370 if (hd->vs) {
00371 return hd->vs;
00372 }
00373
00374 bool_t allow_port_reuse = (hd->multicast_port != 0);
00375
00376 hd->vs = hdhomerun_video_create(hd->multicast_port, allow_port_reuse, VIDEO_DATA_BUFFER_SIZE_1S * 2, hd->dbg);
00377 if (!hd->vs) {
00378 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_video_sock: failed to create video object\n");
00379 return NULL;
00380 }
00381
00382 return hd->vs;
00383 }
00384
00385 uint32_t hdhomerun_device_get_local_machine_addr(struct hdhomerun_device_t *hd)
00386 {
00387 if (hd->cs) {
00388 return hdhomerun_control_get_local_addr(hd->cs);
00389 }
00390
00391 return 0;
00392 }
00393
00394 static uint32_t hdhomerun_device_get_status_parse(const char *status_str, const char *tag)
00395 {
00396 const char *ptr = strstr(status_str, tag);
00397 if (!ptr) {
00398 return 0;
00399 }
00400
00401 unsigned long value = 0;
00402 sscanf(ptr + strlen(tag), "%lu", &value);
00403
00404 return (uint32_t)value;
00405 }
00406
00407 static bool_t hdhomerun_device_get_tuner_status_lock_is_bcast(struct hdhomerun_tuner_status_t *status)
00408 {
00409 if (strcmp(status->lock_str, "8vsb") == 0) {
00410 return TRUE;
00411 }
00412 if (strncmp(status->lock_str, "t8", 2) == 0) {
00413 return TRUE;
00414 }
00415 if (strncmp(status->lock_str, "t7", 2) == 0) {
00416 return TRUE;
00417 }
00418 if (strncmp(status->lock_str, "t6", 2) == 0) {
00419 return TRUE;
00420 }
00421
00422 return FALSE;
00423 }
00424
00425 uint32_t hdhomerun_device_get_tuner_status_ss_color(struct hdhomerun_tuner_status_t *status)
00426 {
00427 unsigned int ss_yellow_min;
00428 unsigned int ss_green_min;
00429
00430 if (!status->lock_supported) {
00431 return HDHOMERUN_STATUS_COLOR_NEUTRAL;
00432 }
00433
00434 if (hdhomerun_device_get_tuner_status_lock_is_bcast(status)) {
00435 ss_yellow_min = 50;
00436 ss_green_min = 75;
00437 } else {
00438 ss_yellow_min = 80;
00439 ss_green_min = 90;
00440 }
00441
00442 if (status->signal_strength >= ss_green_min) {
00443 return HDHOMERUN_STATUS_COLOR_GREEN;
00444 }
00445 if (status->signal_strength >= ss_yellow_min) {
00446 return HDHOMERUN_STATUS_COLOR_YELLOW;
00447 }
00448
00449 return HDHOMERUN_STATUS_COLOR_RED;
00450 }
00451
00452 uint32_t hdhomerun_device_get_tuner_status_snq_color(struct hdhomerun_tuner_status_t *status)
00453 {
00454 if (status->signal_to_noise_quality >= 70) {
00455 return HDHOMERUN_STATUS_COLOR_GREEN;
00456 }
00457 if (status->signal_to_noise_quality >= 50) {
00458 return HDHOMERUN_STATUS_COLOR_YELLOW;
00459 }
00460
00461 return HDHOMERUN_STATUS_COLOR_RED;
00462 }
00463
00464 uint32_t hdhomerun_device_get_tuner_status_seq_color(struct hdhomerun_tuner_status_t *status)
00465 {
00466 if (status->symbol_error_quality >= 100) {
00467 return HDHOMERUN_STATUS_COLOR_GREEN;
00468 }
00469
00470 return HDHOMERUN_STATUS_COLOR_RED;
00471 }
00472
00473 int hdhomerun_device_get_tuner_status(struct hdhomerun_device_t *hd, char **pstatus_str, struct hdhomerun_tuner_status_t *status)
00474 {
00475 if (!hd->cs) {
00476 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_status: device not set\n");
00477 return -1;
00478 }
00479
00480 memset(status, 0, sizeof(struct hdhomerun_tuner_status_t));
00481
00482 char name[32];
00483 sprintf(name, "/tuner%u/status", hd->tuner);
00484
00485 char *status_str;
00486 int ret = hdhomerun_control_get(hd->cs, name, &status_str, NULL);
00487 if (ret <= 0) {
00488 return ret;
00489 }
00490
00491 if (pstatus_str) {
00492 *pstatus_str = status_str;
00493 }
00494
00495 if (status) {
00496 char *channel = strstr(status_str, "ch=");
00497 if (channel) {
00498 sscanf(channel + 3, "%31s", status->channel);
00499 }
00500
00501 char *lock = strstr(status_str, "lock=");
00502 if (lock) {
00503 sscanf(lock + 5, "%31s", status->lock_str);
00504 }
00505
00506 status->signal_strength = (unsigned int)hdhomerun_device_get_status_parse(status_str, "ss=");
00507 status->signal_to_noise_quality = (unsigned int)hdhomerun_device_get_status_parse(status_str, "snq=");
00508 status->symbol_error_quality = (unsigned int)hdhomerun_device_get_status_parse(status_str, "seq=");
00509 status->raw_bits_per_second = hdhomerun_device_get_status_parse(status_str, "bps=");
00510 status->packets_per_second = hdhomerun_device_get_status_parse(status_str, "pps=");
00511
00512 status->signal_present = status->signal_strength >= 45;
00513
00514 if (strcmp(status->lock_str, "none") != 0) {
00515 if (status->lock_str[0] == '(') {
00516 status->lock_unsupported = TRUE;
00517 } else {
00518 status->lock_supported = TRUE;
00519 }
00520 }
00521 }
00522
00523 return 1;
00524 }
00525
00526 int hdhomerun_device_get_oob_status(struct hdhomerun_device_t *hd, char **pstatus_str, struct hdhomerun_tuner_status_t *status)
00527 {
00528 if (!hd->cs) {
00529 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_oob_status: device not set\n");
00530 return -1;
00531 }
00532
00533 memset(status, 0, sizeof(struct hdhomerun_tuner_status_t));
00534
00535 char *status_str;
00536 int ret = hdhomerun_control_get(hd->cs, "/oob/status", &status_str, NULL);
00537 if (ret <= 0) {
00538 return ret;
00539 }
00540
00541 if (pstatus_str) {
00542 *pstatus_str = status_str;
00543 }
00544
00545 if (status) {
00546 char *channel = strstr(status_str, "ch=");
00547 if (channel) {
00548 sscanf(channel + 3, "%31s", status->channel);
00549 }
00550
00551 char *lock = strstr(status_str, "lock=");
00552 if (lock) {
00553 sscanf(lock + 5, "%31s", status->lock_str);
00554 }
00555
00556 status->signal_strength = (unsigned int)hdhomerun_device_get_status_parse(status_str, "ss=");
00557 status->signal_to_noise_quality = (unsigned int)hdhomerun_device_get_status_parse(status_str, "snq=");
00558 status->signal_present = status->signal_strength >= 45;
00559 status->lock_supported = (strcmp(status->lock_str, "none") != 0);
00560 }
00561
00562 return 1;
00563 }
00564
00565 int hdhomerun_device_get_tuner_vstatus(struct hdhomerun_device_t *hd, char **pvstatus_str, struct hdhomerun_tuner_vstatus_t *vstatus)
00566 {
00567 if (!hd->cs) {
00568 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_vstatus: device not set\n");
00569 return -1;
00570 }
00571
00572 memset(vstatus, 0, sizeof(struct hdhomerun_tuner_vstatus_t));
00573
00574 char var_name[32];
00575 sprintf(var_name, "/tuner%u/vstatus", hd->tuner);
00576
00577 char *vstatus_str;
00578 int ret = hdhomerun_control_get(hd->cs, var_name, &vstatus_str, NULL);
00579 if (ret <= 0) {
00580 return ret;
00581 }
00582
00583 if (pvstatus_str) {
00584 *pvstatus_str = vstatus_str;
00585 }
00586
00587 if (vstatus) {
00588 char *vch = strstr(vstatus_str, "vch=");
00589 if (vch) {
00590 sscanf(vch + 4, "%31s", vstatus->vchannel);
00591 }
00592
00593 char *name = strstr(vstatus_str, "name=");
00594 if (name) {
00595 sscanf(name + 5, "%31s", vstatus->name);
00596 }
00597
00598 char *auth = strstr(vstatus_str, "auth=");
00599 if (auth) {
00600 sscanf(auth + 5, "%31s", vstatus->auth);
00601 }
00602
00603 char *cci = strstr(vstatus_str, "cci=");
00604 if (cci) {
00605 sscanf(cci + 4, "%31s", vstatus->cci);
00606 }
00607
00608 char *cgms = strstr(vstatus_str, "cgms=");
00609 if (cgms) {
00610 sscanf(cgms + 5, "%31s", vstatus->cgms);
00611 }
00612
00613 if (strncmp(vstatus->auth, "not-subscribed", 14) == 0) {
00614 vstatus->not_subscribed = TRUE;
00615 }
00616
00617 if (strncmp(vstatus->auth, "error", 5) == 0) {
00618 vstatus->not_available = TRUE;
00619 }
00620 if (strncmp(vstatus->auth, "dialog", 6) == 0) {
00621 vstatus->not_available = TRUE;
00622 }
00623
00624 if (strncmp(vstatus->cci, "protected", 9) == 0) {
00625 vstatus->copy_protected = TRUE;
00626 }
00627 if (strncmp(vstatus->cgms, "protected", 9) == 0) {
00628 vstatus->copy_protected = TRUE;
00629 }
00630 }
00631
00632 return 1;
00633 }
00634
00635 int hdhomerun_device_get_tuner_streaminfo(struct hdhomerun_device_t *hd, char **pstreaminfo)
00636 {
00637 if (!hd->cs) {
00638 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_streaminfo: device not set\n");
00639 return -1;
00640 }
00641
00642 char name[32];
00643 sprintf(name, "/tuner%u/streaminfo", hd->tuner);
00644 return hdhomerun_control_get(hd->cs, name, pstreaminfo, NULL);
00645 }
00646
00647 int hdhomerun_device_get_tuner_channel(struct hdhomerun_device_t *hd, char **pchannel)
00648 {
00649 if (!hd->cs) {
00650 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_channel: device not set\n");
00651 return -1;
00652 }
00653
00654 char name[32];
00655 sprintf(name, "/tuner%u/channel", hd->tuner);
00656 return hdhomerun_control_get(hd->cs, name, pchannel, NULL);
00657 }
00658
00659 int hdhomerun_device_get_tuner_vchannel(struct hdhomerun_device_t *hd, char **pvchannel)
00660 {
00661 if (!hd->cs) {
00662 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_vchannel: device not set\n");
00663 return -1;
00664 }
00665
00666 char name[32];
00667 sprintf(name, "/tuner%u/vchannel", hd->tuner);
00668 return hdhomerun_control_get(hd->cs, name, pvchannel, NULL);
00669 }
00670
00671 int hdhomerun_device_get_tuner_channelmap(struct hdhomerun_device_t *hd, char **pchannelmap)
00672 {
00673 if (!hd->cs) {
00674 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_channelmap: device not set\n");
00675 return -1;
00676 }
00677
00678 char name[32];
00679 sprintf(name, "/tuner%u/channelmap", hd->tuner);
00680 return hdhomerun_control_get(hd->cs, name, pchannelmap, NULL);
00681 }
00682
00683 int hdhomerun_device_get_tuner_filter(struct hdhomerun_device_t *hd, char **pfilter)
00684 {
00685 if (!hd->cs) {
00686 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_filter: device not set\n");
00687 return -1;
00688 }
00689
00690 char name[32];
00691 sprintf(name, "/tuner%u/filter", hd->tuner);
00692 return hdhomerun_control_get(hd->cs, name, pfilter, NULL);
00693 }
00694
00695 int hdhomerun_device_get_tuner_program(struct hdhomerun_device_t *hd, char **pprogram)
00696 {
00697 if (!hd->cs) {
00698 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_program: device not set\n");
00699 return -1;
00700 }
00701
00702 char name[32];
00703 sprintf(name, "/tuner%u/program", hd->tuner);
00704 return hdhomerun_control_get(hd->cs, name, pprogram, NULL);
00705 }
00706
00707 int hdhomerun_device_get_tuner_target(struct hdhomerun_device_t *hd, char **ptarget)
00708 {
00709 if (!hd->cs) {
00710 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_target: device not set\n");
00711 return -1;
00712 }
00713
00714 char name[32];
00715 sprintf(name, "/tuner%u/target", hd->tuner);
00716 return hdhomerun_control_get(hd->cs, name, ptarget, NULL);
00717 }
00718
00719 static int hdhomerun_device_get_tuner_plotsample_internal(struct hdhomerun_device_t *hd, const char *name, struct hdhomerun_plotsample_t **psamples, size_t *pcount)
00720 {
00721 char *result;
00722 int ret = hdhomerun_control_get(hd->cs, name, &result, NULL);
00723 if (ret <= 0) {
00724 return ret;
00725 }
00726
00727 struct hdhomerun_plotsample_t *samples = (struct hdhomerun_plotsample_t *)result;
00728 *psamples = samples;
00729 size_t count = 0;
00730
00731 while (1) {
00732 char *ptr = strchr(result, ' ');
00733 if (!ptr) {
00734 break;
00735 }
00736 *ptr++ = 0;
00737
00738 unsigned long raw;
00739 if (sscanf(result, "%lx", &raw) != 1) {
00740 break;
00741 }
00742
00743 uint16_t real = (raw >> 12) & 0x0FFF;
00744 if (real & 0x0800) {
00745 real |= 0xF000;
00746 }
00747
00748 uint16_t imag = (raw >> 0) & 0x0FFF;
00749 if (imag & 0x0800) {
00750 imag |= 0xF000;
00751 }
00752
00753 samples->real = (int16_t)real;
00754 samples->imag = (int16_t)imag;
00755 samples++;
00756 count++;
00757
00758 result = ptr;
00759 }
00760
00761 *pcount = count;
00762 return 1;
00763 }
00764
00765 int hdhomerun_device_get_tuner_plotsample(struct hdhomerun_device_t *hd, struct hdhomerun_plotsample_t **psamples, size_t *pcount)
00766 {
00767 if (!hd->cs) {
00768 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_plotsample: device not set\n");
00769 return -1;
00770 }
00771
00772 char name[32];
00773 sprintf(name, "/tuner%u/plotsample", hd->tuner);
00774 return hdhomerun_device_get_tuner_plotsample_internal(hd, name, psamples, pcount);
00775 }
00776
00777 int hdhomerun_device_get_oob_plotsample(struct hdhomerun_device_t *hd, struct hdhomerun_plotsample_t **psamples, size_t *pcount)
00778 {
00779 if (!hd->cs) {
00780 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_oob_plotsample: device not set\n");
00781 return -1;
00782 }
00783
00784 return hdhomerun_device_get_tuner_plotsample_internal(hd, "/oob/plotsample", psamples, pcount);
00785 }
00786
00787 int hdhomerun_device_get_tuner_lockkey_owner(struct hdhomerun_device_t *hd, char **powner)
00788 {
00789 if (!hd->cs) {
00790 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_lockkey_owner: device not set\n");
00791 return -1;
00792 }
00793
00794 char name[32];
00795 sprintf(name, "/tuner%u/lockkey", hd->tuner);
00796 return hdhomerun_control_get(hd->cs, name, powner, NULL);
00797 }
00798
00799 int hdhomerun_device_get_ir_target(struct hdhomerun_device_t *hd, char **ptarget)
00800 {
00801 if (!hd->cs) {
00802 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_ir_target: device not set\n");
00803 return -1;
00804 }
00805
00806 return hdhomerun_control_get(hd->cs, "/ir/target", ptarget, NULL);
00807 }
00808
00809 int hdhomerun_device_get_lineup_location(struct hdhomerun_device_t *hd, char **plocation)
00810 {
00811 if (!hd->cs) {
00812 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_lineup_location: device not set\n");
00813 return -1;
00814 }
00815
00816 return hdhomerun_control_get(hd->cs, "/lineup/location", plocation, NULL);
00817 }
00818
00819 int hdhomerun_device_get_version(struct hdhomerun_device_t *hd, char **pversion_str, uint32_t *pversion_num)
00820 {
00821 if (!hd->cs) {
00822 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_version: device not set\n");
00823 return -1;
00824 }
00825
00826 char *version_str;
00827 int ret = hdhomerun_control_get(hd->cs, "/sys/version", &version_str, NULL);
00828 if (ret <= 0) {
00829 return ret;
00830 }
00831
00832 if (pversion_str) {
00833 *pversion_str = version_str;
00834 }
00835
00836 if (pversion_num) {
00837 unsigned long version_num;
00838 if (sscanf(version_str, "%lu", &version_num) != 1) {
00839 *pversion_num = 0;
00840 } else {
00841 *pversion_num = (uint32_t)version_num;
00842 }
00843 }
00844
00845 return 1;
00846 }
00847
00848 int hdhomerun_device_get_supported(struct hdhomerun_device_t *hd, char *prefix, char **pstr)
00849 {
00850 if (!hd->cs) {
00851 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_channel: device not set\n");
00852 return -1;
00853 }
00854
00855 char *features;
00856 int ret = hdhomerun_control_get(hd->cs, "/sys/features", &features, NULL);
00857 if (ret <= 0) {
00858 return ret;
00859 }
00860
00861 if (!prefix) {
00862 *pstr = features;
00863 return 1;
00864 }
00865
00866 char *ptr = strstr(features, prefix);
00867 if (!ptr) {
00868 return 0;
00869 }
00870
00871 ptr += strlen(prefix);
00872 *pstr = ptr;
00873
00874 ptr = strchr(ptr, '\n');
00875 if (ptr) {
00876 *ptr = 0;
00877 }
00878
00879 return 1;
00880 }
00881
00882 int hdhomerun_device_set_tuner_channel(struct hdhomerun_device_t *hd, const char *channel)
00883 {
00884 if (!hd->cs) {
00885 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_channel: device not set\n");
00886 return -1;
00887 }
00888
00889 char name[32];
00890 sprintf(name, "/tuner%u/channel", hd->tuner);
00891 return hdhomerun_control_set_with_lockkey(hd->cs, name, channel, hd->lockkey, NULL, NULL);
00892 }
00893
00894 int hdhomerun_device_set_tuner_vchannel(struct hdhomerun_device_t *hd, const char *vchannel)
00895 {
00896 if (!hd->cs) {
00897 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_vchannel: device not set\n");
00898 return -1;
00899 }
00900
00901 char name[32];
00902 sprintf(name, "/tuner%u/vchannel", hd->tuner);
00903 return hdhomerun_control_set_with_lockkey(hd->cs, name, vchannel, hd->lockkey, NULL, NULL);
00904 }
00905
00906 int hdhomerun_device_set_tuner_channelmap(struct hdhomerun_device_t *hd, const char *channelmap)
00907 {
00908 if (!hd->cs) {
00909 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_channelmap: device not set\n");
00910 return -1;
00911 }
00912
00913 char name[32];
00914 sprintf(name, "/tuner%u/channelmap", hd->tuner);
00915 return hdhomerun_control_set_with_lockkey(hd->cs, name, channelmap, hd->lockkey, NULL, NULL);
00916 }
00917
00918 int hdhomerun_device_set_tuner_filter(struct hdhomerun_device_t *hd, const char *filter)
00919 {
00920 if (!hd->cs) {
00921 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_filter: device not set\n");
00922 return -1;
00923 }
00924
00925 char name[32];
00926 sprintf(name, "/tuner%u/filter", hd->tuner);
00927 return hdhomerun_control_set_with_lockkey(hd->cs, name, filter, hd->lockkey, NULL, NULL);
00928 }
00929
00930 static int hdhomerun_device_set_tuner_filter_by_array_append(char **pptr, char *end, uint16_t range_begin, uint16_t range_end)
00931 {
00932 char *ptr = *pptr;
00933
00934 size_t available = end - ptr;
00935 size_t required;
00936
00937 if (range_begin == range_end) {
00938 required = snprintf(ptr, available, "0x%04x ", range_begin) + 1;
00939 } else {
00940 required = snprintf(ptr, available, "0x%04x-0x%04x ", range_begin, range_end) + 1;
00941 }
00942
00943 if (required > available) {
00944 return FALSE;
00945 }
00946
00947 *pptr = strchr(ptr, 0);
00948 return TRUE;
00949 }
00950
00951 int hdhomerun_device_set_tuner_filter_by_array(struct hdhomerun_device_t *hd, unsigned char filter_array[0x2000])
00952 {
00953 char filter[1024];
00954 char *ptr = filter;
00955 char *end = filter + sizeof(filter);
00956
00957 uint16_t range_begin = 0xFFFF;
00958 uint16_t range_end = 0xFFFF;
00959
00960 uint16_t i;
00961 for (i = 0; i <= 0x1FFF; i++) {
00962 if (!filter_array[i]) {
00963 if (range_begin == 0xFFFF) {
00964 continue;
00965 }
00966 if (!hdhomerun_device_set_tuner_filter_by_array_append(&ptr, end, range_begin, range_end)) {
00967 return 0;
00968 }
00969 range_begin = 0xFFFF;
00970 range_end = 0xFFFF;
00971 continue;
00972 }
00973
00974 if (range_begin == 0xFFFF) {
00975 range_begin = i;
00976 range_end = i;
00977 continue;
00978 }
00979
00980 range_end = i;
00981 }
00982
00983 if (range_begin != 0xFFFF) {
00984 if (!hdhomerun_device_set_tuner_filter_by_array_append(&ptr, end, range_begin, range_end)) {
00985 return 0;
00986 }
00987 }
00988
00989
00990 if (ptr > filter) {
00991 ptr--;
00992 }
00993 *ptr = 0;
00994
00995 return hdhomerun_device_set_tuner_filter(hd, filter);
00996 }
00997
00998 int hdhomerun_device_set_tuner_program(struct hdhomerun_device_t *hd, const char *program)
00999 {
01000 if (!hd->cs) {
01001 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_program: device not set\n");
01002 return -1;
01003 }
01004
01005 char name[32];
01006 sprintf(name, "/tuner%u/program", hd->tuner);
01007 return hdhomerun_control_set_with_lockkey(hd->cs, name, program, hd->lockkey, NULL, NULL);
01008 }
01009
01010 int hdhomerun_device_set_tuner_target(struct hdhomerun_device_t *hd, const char *target)
01011 {
01012 if (!hd->cs) {
01013 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_target: device not set\n");
01014 return -1;
01015 }
01016
01017 char name[32];
01018 sprintf(name, "/tuner%u/target", hd->tuner);
01019 return hdhomerun_control_set_with_lockkey(hd->cs, name, target, hd->lockkey, NULL, NULL);
01020 }
01021
01022 static int hdhomerun_device_set_tuner_target_to_local(struct hdhomerun_device_t *hd, const char *protocol)
01023 {
01024 if (!hd->cs) {
01025 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_target_to_local: device not set\n");
01026 return -1;
01027 }
01028 if (!hd->vs) {
01029 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_target_to_local: video not initialized\n");
01030 return -1;
01031 }
01032
01033
01034 char target[64];
01035 uint32_t local_ip = hdhomerun_control_get_local_addr(hd->cs);
01036 uint16_t local_port = hdhomerun_video_get_local_port(hd->vs);
01037 sprintf(target, "%s://%u.%u.%u.%u:%u",
01038 protocol,
01039 (unsigned int)(local_ip >> 24) & 0xFF, (unsigned int)(local_ip >> 16) & 0xFF,
01040 (unsigned int)(local_ip >> 8) & 0xFF, (unsigned int)(local_ip >> 0) & 0xFF,
01041 (unsigned int)local_port
01042 );
01043
01044 return hdhomerun_device_set_tuner_target(hd, target);
01045 }
01046
01047 int hdhomerun_device_set_ir_target(struct hdhomerun_device_t *hd, const char *target)
01048 {
01049 if (!hd->cs) {
01050 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_ir_target: device not set\n");
01051 return -1;
01052 }
01053
01054 return hdhomerun_control_set(hd->cs, "/ir/target", target, NULL, NULL);
01055 }
01056
01057 int hdhomerun_device_set_lineup_location(struct hdhomerun_device_t *hd, const char *location)
01058 {
01059 if (!hd->cs) {
01060 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_lineup_location: device not set\n");
01061 return -1;
01062 }
01063
01064 return hdhomerun_control_set(hd->cs, "/lineup/location", location, NULL, NULL);
01065 }
01066
01067 int hdhomerun_device_set_sys_dvbc_modulation(struct hdhomerun_device_t *hd, const char *modulation_list)
01068 {
01069 if (!hd->cs) {
01070 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_sys_dvbc_modulation: device not set\n");
01071 return -1;
01072 }
01073
01074 return hdhomerun_control_set(hd->cs, "/sys/dvbc_modulation", modulation_list, NULL, NULL);
01075 }
01076
01077 int hdhomerun_device_get_var(struct hdhomerun_device_t *hd, const char *name, char **pvalue, char **perror)
01078 {
01079 if (!hd->cs) {
01080 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_var: device not set\n");
01081 return -1;
01082 }
01083
01084 return hdhomerun_control_get(hd->cs, name, pvalue, perror);
01085 }
01086
01087 int hdhomerun_device_set_var(struct hdhomerun_device_t *hd, const char *name, const char *value, char **pvalue, char **perror)
01088 {
01089 if (!hd->cs) {
01090 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_var: device not set\n");
01091 return -1;
01092 }
01093
01094 return hdhomerun_control_set_with_lockkey(hd->cs, name, value, hd->lockkey, pvalue, perror);
01095 }
01096
01097 int hdhomerun_device_tuner_lockkey_request(struct hdhomerun_device_t *hd, char **perror)
01098 {
01099 if (hd->multicast_ip != 0) {
01100 return 1;
01101 }
01102 if (!hd->cs) {
01103 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_tuner_lockkey_request: device not set\n");
01104 return -1;
01105 }
01106
01107 uint32_t new_lockkey = random_get32();
01108
01109 char name[32];
01110 sprintf(name, "/tuner%u/lockkey", hd->tuner);
01111
01112 char new_lockkey_str[64];
01113 sprintf(new_lockkey_str, "%u", (unsigned int)new_lockkey);
01114
01115 int ret = hdhomerun_control_set_with_lockkey(hd->cs, name, new_lockkey_str, hd->lockkey, NULL, perror);
01116 if (ret <= 0) {
01117 hd->lockkey = 0;
01118 return ret;
01119 }
01120
01121 hd->lockkey = new_lockkey;
01122 return ret;
01123 }
01124
01125 int hdhomerun_device_tuner_lockkey_release(struct hdhomerun_device_t *hd)
01126 {
01127 if (hd->multicast_ip != 0) {
01128 return 1;
01129 }
01130 if (!hd->cs) {
01131 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_tuner_lockkey_release: device not set\n");
01132 return -1;
01133 }
01134
01135 if (hd->lockkey == 0) {
01136 return 1;
01137 }
01138
01139 char name[32];
01140 sprintf(name, "/tuner%u/lockkey", hd->tuner);
01141 int ret = hdhomerun_control_set_with_lockkey(hd->cs, name, "none", hd->lockkey, NULL, NULL);
01142
01143 hd->lockkey = 0;
01144 return ret;
01145 }
01146
01147 int hdhomerun_device_tuner_lockkey_force(struct hdhomerun_device_t *hd)
01148 {
01149 if (hd->multicast_ip != 0) {
01150 return 1;
01151 }
01152 if (!hd->cs) {
01153 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_tuner_lockkey_force: device not set\n");
01154 return -1;
01155 }
01156
01157 char name[32];
01158 sprintf(name, "/tuner%u/lockkey", hd->tuner);
01159 int ret = hdhomerun_control_set(hd->cs, name, "force", NULL, NULL);
01160
01161 hd->lockkey = 0;
01162 return ret;
01163 }
01164
01165 void hdhomerun_device_tuner_lockkey_use_value(struct hdhomerun_device_t *hd, uint32_t lockkey)
01166 {
01167 if (hd->multicast_ip != 0) {
01168 return;
01169 }
01170
01171 hd->lockkey = lockkey;
01172 }
01173
01174 int hdhomerun_device_wait_for_lock(struct hdhomerun_device_t *hd, struct hdhomerun_tuner_status_t *status)
01175 {
01176
01177 msleep_minimum(250);
01178
01179
01180 uint64_t timeout = getcurrenttime() + 2500;
01181 while (1) {
01182
01183 int ret = hdhomerun_device_get_tuner_status(hd, NULL, status);
01184 if (ret <= 0) {
01185 return ret;
01186 }
01187
01188 if (!status->signal_present) {
01189 return 1;
01190 }
01191 if (status->lock_supported || status->lock_unsupported) {
01192 return 1;
01193 }
01194
01195 if (getcurrenttime() >= timeout) {
01196 return 1;
01197 }
01198
01199 msleep_approx(250);
01200 }
01201 }
01202
01203 int hdhomerun_device_stream_start(struct hdhomerun_device_t *hd)
01204 {
01205 hdhomerun_device_get_video_sock(hd);
01206 if (!hd->vs) {
01207 return -1;
01208 }
01209
01210
01211 if (hd->multicast_ip != 0) {
01212 int ret = hdhomerun_video_join_multicast_group(hd->vs, hd->multicast_ip, 0);
01213 if (ret <= 0) {
01214 return ret;
01215 }
01216 } else {
01217 int ret = hdhomerun_device_set_tuner_target_to_local(hd, HDHOMERUN_TARGET_PROTOCOL_RTP);
01218 if (ret == 0) {
01219 ret = hdhomerun_device_set_tuner_target_to_local(hd, HDHOMERUN_TARGET_PROTOCOL_UDP);
01220 }
01221 if (ret <= 0) {
01222 return ret;
01223 }
01224 }
01225
01226
01227 msleep_minimum(64);
01228 hdhomerun_video_flush(hd->vs);
01229
01230
01231 return 1;
01232 }
01233
01234 uint8_t *hdhomerun_device_stream_recv(struct hdhomerun_device_t *hd, size_t max_size, size_t *pactual_size)
01235 {
01236 if (!hd->vs) {
01237 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_stream_recv: video not initialized\n");
01238 return NULL;
01239 }
01240
01241 return hdhomerun_video_recv(hd->vs, max_size, pactual_size);
01242 }
01243
01244 void hdhomerun_device_stream_flush(struct hdhomerun_device_t *hd)
01245 {
01246 if (!hd->vs) {
01247 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_stream_flush: video not initialized\n");
01248 return;
01249 }
01250
01251 hdhomerun_video_flush(hd->vs);
01252 }
01253
01254 void hdhomerun_device_stream_stop(struct hdhomerun_device_t *hd)
01255 {
01256 if (!hd->vs) {
01257 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_stream_stop: video not initialized\n");
01258 return;
01259 }
01260
01261 if (hd->multicast_ip != 0) {
01262 hdhomerun_video_leave_multicast_group(hd->vs);
01263 } else {
01264 hdhomerun_device_set_tuner_target(hd, "none");
01265 }
01266 }
01267
01268 int hdhomerun_device_channelscan_init(struct hdhomerun_device_t *hd, const char *channelmap)
01269 {
01270 if (hd->scan) {
01271 channelscan_destroy(hd->scan);
01272 }
01273
01274 hd->scan = channelscan_create(hd, channelmap);
01275 if (!hd->scan) {
01276 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_channelscan_init: failed to create scan object\n");
01277 return -1;
01278 }
01279
01280 return 1;
01281 }
01282
01283 int hdhomerun_device_channelscan_advance(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result)
01284 {
01285 if (!hd->scan) {
01286 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_channelscan_advance: scan not initialized\n");
01287 return 0;
01288 }
01289
01290 int ret = channelscan_advance(hd->scan, result);
01291 if (ret <= 0) {
01292 channelscan_destroy(hd->scan);
01293 hd->scan = NULL;
01294 }
01295
01296 return ret;
01297 }
01298
01299 int hdhomerun_device_channelscan_detect(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result)
01300 {
01301 if (!hd->scan) {
01302 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_channelscan_detect: scan not initialized\n");
01303 return 0;
01304 }
01305
01306 int ret = channelscan_detect(hd->scan, result);
01307 if (ret < 0) {
01308 channelscan_destroy(hd->scan);
01309 hd->scan = NULL;
01310 }
01311
01312 return ret;
01313 }
01314
01315 uint8_t hdhomerun_device_channelscan_get_progress(struct hdhomerun_device_t *hd)
01316 {
01317 if (!hd->scan) {
01318 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_channelscan_get_progress: scan not initialized\n");
01319 return 0;
01320 }
01321
01322 return channelscan_get_progress(hd->scan);
01323 }
01324
01325 const char *hdhomerun_device_get_model_str(struct hdhomerun_device_t *hd)
01326 {
01327 if (*hd->model) {
01328 return hd->model;
01329 }
01330
01331 if (!hd->cs) {
01332 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_model_str: device not set\n");
01333 return NULL;
01334 }
01335
01336 char *model_str;
01337 int ret = hdhomerun_control_get(hd->cs, "/sys/model", &model_str, NULL);
01338 if (ret < 0) {
01339 return NULL;
01340 }
01341 if (ret == 0) {
01342 strncpy(hd->model, "hdhomerun_atsc", sizeof(hd->model) - 1);
01343 hd->model[sizeof(hd->model) - 1] = 0;
01344 return hd->model;
01345 }
01346
01347 strncpy(hd->model, model_str, sizeof(hd->model) - 1);
01348 hd->model[sizeof(hd->model) - 1] = 0;
01349 return hd->model;
01350 }
01351
01352 int hdhomerun_device_upgrade(struct hdhomerun_device_t *hd, FILE *upgrade_file)
01353 {
01354 if (!hd->cs) {
01355 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_upgrade: device not set\n");
01356 return -1;
01357 }
01358
01359 hdhomerun_control_set(hd->cs, "/tuner0/lockkey", "force", NULL, NULL);
01360 hdhomerun_control_set(hd->cs, "/tuner0/channel", "none", NULL, NULL);
01361
01362 hdhomerun_control_set(hd->cs, "/tuner1/lockkey", "force", NULL, NULL);
01363 hdhomerun_control_set(hd->cs, "/tuner1/channel", "none", NULL, NULL);
01364
01365 return hdhomerun_control_upgrade(hd->cs, upgrade_file);
01366 }
01367
01368 void hdhomerun_device_debug_print_video_stats(struct hdhomerun_device_t *hd)
01369 {
01370 if (!hdhomerun_debug_enabled(hd->dbg)) {
01371 return;
01372 }
01373
01374 if (hd->cs) {
01375 char name[32];
01376 sprintf(name, "/tuner%u/debug", hd->tuner);
01377
01378 char *debug_str;
01379 char *error_str;
01380 int ret = hdhomerun_control_get(hd->cs, name, &debug_str, &error_str);
01381 if (ret < 0) {
01382 hdhomerun_debug_printf(hd->dbg, "video dev: communication error getting debug stats\n");
01383 return;
01384 }
01385
01386 if (error_str) {
01387 hdhomerun_debug_printf(hd->dbg, "video dev: %s\n", error_str);
01388 } else {
01389 hdhomerun_debug_printf(hd->dbg, "video dev: %s\n", debug_str);
01390 }
01391 }
01392
01393 if (hd->vs) {
01394 hdhomerun_video_debug_print_stats(hd->vs);
01395 }
01396 }
01397
01398 void hdhomerun_device_get_video_stats(struct hdhomerun_device_t *hd, struct hdhomerun_video_stats_t *stats)
01399 {
01400 if (!hd->vs) {
01401 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_stream_flush: video not initialized\n");
01402 memset(stats, 0, sizeof(struct hdhomerun_video_stats_t));
01403 return;
01404 }
01405
01406 hdhomerun_video_get_stats(hd->vs, stats);
01407 }