|
MythTV
0.26-pre
|
00001 /* 00002 * hdhomerun_device.c 00003 * 00004 * Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>. 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 3 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 00018 * 00019 * As a special exception to the GNU Lesser General Public License, 00020 * you may link, statically or dynamically, an application with a 00021 * publicly distributed version of the Library to produce an 00022 * executable file containing portions of the Library, and 00023 * distribute that executable file under terms of your choice, 00024 * without any of the additional requirements listed in clause 4 of 00025 * the GNU Lesser General Public License. 00026 * 00027 * By "a publicly distributed version of the Library", we mean 00028 * either the unmodified Library as distributed by Silicondust, or a 00029 * modified version of the Library that is distributed under the 00030 * conditions defined in the GNU Lesser General Public License. 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; /* clear cached model string */ 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; /* -30dBmV */ 00436 ss_green_min = 75; /* -15dBmV */ 00437 } else { 00438 ss_yellow_min = 80; /* -12dBmV */ 00439 ss_green_min = 90; /* -6dBmV */ 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 /* Remove trailing space. */ 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 /* Set target. */ 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 /* Delay for SS reading to be valid (signal present). */ 01177 msleep_minimum(250); 01178 01179 /* Wait for up to 2.5 seconds for lock. */ 01180 uint64_t timeout = getcurrenttime() + 2500; 01181 while (1) { 01182 /* Get status to check for lock. Quality numbers will not be valid yet. */ 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 /* Set target. */ 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 /* Flush video buffer. */ 01227 msleep_minimum(64); 01228 hdhomerun_video_flush(hd->vs); 01229 01230 /* Success. */ 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) { /* Free scan if normal finish or fatal error */ 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) { /* Free scan if fatal error */ 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 }
1.7.6.1