Ticket #6672: 6672-v3.patch
File 6672-v3.patch, 221.2 KB (added by , 16 years ago) |
---|
-
libs/libmythtv/hdhomerun/hdhomerun_control.h
3 3 * 4 4 * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>. 5 5 * 6 * This library is free software; you can redistribute it and/or 6 * This library is free software; you can redistribute it and/or 7 7 * modify it under the terms of the GNU Lesser General Public 8 8 * License as published by the Free Software Foundation; either 9 * version 2.1of the License, or (at your option) any later version.9 * version 3 of the License, or (at your option) any later version. 10 10 * 11 11 * This library is distributed in the hope that it will be useful, 12 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of … … 14 14 * Lesser General Public License for more details. 15 15 * 16 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 * 19 * As a special exception to the GNU Lesser General Public License, 20 * you may link, statically or dynamically, an application with a 21 * publicly distributed version of the Library to produce an 22 * executable file containing portions of the Library, and 23 * distribute that executable file under terms of your choice, 24 * without any of the additional requirements listed in clause 4 of 25 * the GNU Lesser General Public License. 26 * 27 * By "a publicly distributed version of the Library", we mean 28 * either the unmodified Library as distributed by Silicondust, or a 29 * modified version of the Library that is distributed under the 30 * conditions defined in the GNU Lesser General Public License. 19 31 */ 20 32 #ifdef __cplusplus 21 33 extern "C" { … … 31 43 * 32 44 * uint32_t device_id = 32-bit device id of device. Set to HDHOMERUN_DEVICE_ID_WILDCARD to match any device ID. 33 45 * uint32_t device_ip = IP address of device. Set to 0 to auto-detect. 46 * struct hdhomerun_debug_t *dbg: Pointer to debug logging object. May be NULL. 34 47 * 35 48 * Returns a pointer to the newly created control socket. 36 49 * 37 50 * When no longer needed, the socket should be destroyed by calling hdhomerun_control_destroy. 38 51 */ 39 extern struct hdhomerun_control_sock_t *hdhomerun_control_create(uint32_t device_id, uint32_t device_ip);40 extern void hdhomerun_control_destroy(struct hdhomerun_control_sock_t *cs);52 extern LIBTYPE struct hdhomerun_control_sock_t *hdhomerun_control_create(uint32_t device_id, uint32_t device_ip, struct hdhomerun_debug_t *dbg); 53 extern LIBTYPE void hdhomerun_control_destroy(struct hdhomerun_control_sock_t *cs); 41 54 42 55 /* 56 * Get the actual device id or ip of the device. 57 * 58 * Returns 0 if the device id cannot be determined. 59 */ 60 extern LIBTYPE uint32_t hdhomerun_control_get_device_id(struct hdhomerun_control_sock_t *cs); 61 extern LIBTYPE uint32_t hdhomerun_control_get_device_ip(struct hdhomerun_control_sock_t *cs); 62 extern LIBTYPE uint32_t hdhomerun_control_get_device_id_requested(struct hdhomerun_control_sock_t *cs); 63 extern LIBTYPE uint32_t hdhomerun_control_get_device_ip_requested(struct hdhomerun_control_sock_t *cs); 64 65 extern LIBTYPE void hdhomerun_control_set_device(struct hdhomerun_control_sock_t *cs, uint32_t device_id, uint32_t device_ip); 66 67 /* 43 68 * Get the local machine IP address used when communicating with the device. 44 69 * 45 70 * This function is useful for determining the IP address to use with set target commands. 46 71 * 47 72 * Returns 32-bit IP address with native endianness, or 0 on error. 48 73 */ 49 extern uint32_t hdhomerun_control_get_local_addr(struct hdhomerun_control_sock_t *cs);74 extern LIBTYPE uint32_t hdhomerun_control_get_local_addr(struct hdhomerun_control_sock_t *cs); 50 75 51 76 /* 77 * Low-level communication. 78 */ 79 extern LIBTYPE int hdhomerun_control_send_recv(struct hdhomerun_control_sock_t *cs, struct hdhomerun_pkt_t *tx_pkt, struct hdhomerun_pkt_t *rx_pkt, uint16_t type); 80 81 /* 52 82 * Get/set a control variable on the device. 53 83 * 54 84 * const char *name: The name of var to get/set (c-string). The supported vars is device/firmware dependant. … … 65 95 * Returns 0 if the operation was rejected (pvalue NULL, perror set). 66 96 * Returns -1 if a communication error occurs. 67 97 */ 68 extern int hdhomerun_control_get(struct hdhomerun_control_sock_t *cs, const char *name, char **pvalue, char **perror); 69 extern int hdhomerun_control_set(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, char **pvalue, char **perror); 98 extern LIBTYPE int hdhomerun_control_get(struct hdhomerun_control_sock_t *cs, const char *name, char **pvalue, char **perror); 99 extern LIBTYPE int hdhomerun_control_set(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, char **pvalue, char **perror); 100 extern LIBTYPE int hdhomerun_control_set_with_lockkey(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, uint32_t lockkey, char **pvalue, char **perror); 70 101 71 102 /* 72 103 * Upload new firmware to the device. … … 77 108 * Returns 0 if the upload was rejected. 78 109 * Returns -1 if an error occurs. 79 110 */ 80 extern int hdhomerun_control_upgrade(struct hdhomerun_control_sock_t *cs, FILE *upgrade_file);111 extern LIBTYPE int hdhomerun_control_upgrade(struct hdhomerun_control_sock_t *cs, FILE *upgrade_file); 81 112 82 113 #ifdef __cplusplus 83 114 } -
libs/libmythtv/hdhomerun/hdhomerun.h
1 #ifndef __HDHOMERUN_INCLUDES__ 2 #define __HDHOMERUN_INCLUDES__ 1 3 /* 2 * hdhomerun _device.h4 * hdhomerun.h 3 5 * 4 * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.6 * Copyright © 2006-2008 Silicondust Engineering Ltd. <www.silicondust.com>. 5 7 * 6 * This library is free software; you can redistribute it and/or 8 * This library is free software; you can redistribute it and/or 7 9 * modify it under the terms of the GNU Lesser General Public 8 10 * License as published by the Free Software Foundation; either 9 * version 2.1of the License, or (at your option) any later version.11 * version 3 of the License, or (at your option) any later version. 10 12 * 11 13 * This library is distributed in the hope that it will be useful, 12 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of … … 14 16 * Lesser General Public License for more details. 15 17 * 16 18 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 20 * 21 * As a special exception to the GNU Lesser General Public License, 22 * you may link, statically or dynamically, an application with a 23 * publicly distributed version of the Library to produce an 24 * executable file containing portions of the Library, and 25 * distribute that executable file under terms of your choice, 26 * without any of the additional requirements listed in clause 4 of 27 * the GNU Lesser General Public License. 28 * 29 * By "a publicly distributed version of the Library", we mean 30 * either the unmodified Library as distributed by Silicondust, or a 31 * modified version of the Library that is distributed under the 32 * conditions defined in the GNU Lesser General Public License. 19 33 */ 20 34 21 35 #include "hdhomerun_os.h" 36 #include "hdhomerun_types.h" 22 37 #include "hdhomerun_pkt.h" 38 #include "hdhomerun_debug.h" 23 39 #include "hdhomerun_discover.h" 24 40 #include "hdhomerun_control.h" 25 41 #include "hdhomerun_video.h" 42 #include "hdhomerun_channels.h" 43 #include "hdhomerun_channelscan.h" 26 44 #include "hdhomerun_device.h" 45 46 #endif /* __HDHOMERUN_INCLUDES__ */ 47 -
libs/libmythtv/hdhomerun/hdhomerun_debug.c
1 /* 2 * hdhomerun_debug.c 3 * 4 * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 3 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 * 19 * As a special exception to the GNU Lesser General Public License, 20 * you may link, statically or dynamically, an application with a 21 * publicly distributed version of the Library to produce an 22 * executable file containing portions of the Library, and 23 * distribute that executable file under terms of your choice, 24 * without any of the additional requirements listed in clause 4 of 25 * the GNU Lesser General Public License. 26 * 27 * By "a publicly distributed version of the Library", we mean 28 * either the unmodified Library as distributed by Silicondust, or a 29 * modified version of the Library that is distributed under the 30 * conditions defined in the GNU Lesser General Public License. 31 */ 32 33 /* 34 * The debug logging includes optional support for connecting to the 35 * Silicondust support server. This option should not be used without 36 * being explicitly enabled by the user. Debug information should be 37 * limited to information useful to diagnosing a problem. 38 * - Silicondust. 39 */ 40 41 #include "hdhomerun.h" 42 43 #if !defined(HDHOMERUN_DEBUG_HOST) 44 #define HDHOMERUN_DEBUG_HOST "debug.silicondust.com" 45 #endif 46 #if !defined(HDHOMERUN_DEBUG_PORT) 47 #define HDHOMERUN_DEBUG_PORT "8002" 48 #endif 49 50 struct hdhomerun_debug_message_t 51 { 52 struct hdhomerun_debug_message_t *next; 53 struct hdhomerun_debug_message_t *prev; 54 char buffer[2048]; 55 }; 56 57 struct hdhomerun_debug_t 58 { 59 pthread_t thread; 60 volatile bool_t enabled; 61 volatile bool_t terminate; 62 char *prefix; 63 64 pthread_mutex_t print_lock; 65 pthread_mutex_t queue_lock; 66 pthread_mutex_t send_lock; 67 68 struct hdhomerun_debug_message_t *queue_head; 69 struct hdhomerun_debug_message_t *queue_tail; 70 uint32_t queue_depth; 71 72 uint64_t connect_delay; 73 74 char *file_name; 75 FILE *file_fp; 76 int sock; 77 }; 78 79 static THREAD_FUNC_PREFIX hdhomerun_debug_thread_execute(void *arg); 80 81 struct hdhomerun_debug_t *hdhomerun_debug_create(void) 82 { 83 struct hdhomerun_debug_t *dbg = (struct hdhomerun_debug_t *)calloc(1, sizeof(struct hdhomerun_debug_t)); 84 if (!dbg) { 85 return NULL; 86 } 87 88 dbg->sock = -1; 89 90 pthread_mutex_init(&dbg->print_lock, NULL); 91 pthread_mutex_init(&dbg->queue_lock, NULL); 92 pthread_mutex_init(&dbg->send_lock, NULL); 93 94 if (pthread_create(&dbg->thread, NULL, &hdhomerun_debug_thread_execute, dbg) != 0) { 95 free(dbg); 96 return NULL; 97 } 98 99 return dbg; 100 } 101 102 /* Send lock held by caller */ 103 static void hdhomerun_debug_close_file(struct hdhomerun_debug_t *dbg) 104 { 105 if (!dbg->file_fp) { 106 return; 107 } 108 109 fclose(dbg->file_fp); 110 dbg->file_fp = NULL; 111 } 112 113 /* Send lock held by caller */ 114 static void hdhomerun_debug_close_sock(struct hdhomerun_debug_t *dbg) 115 { 116 if (dbg->sock == -1) { 117 return; 118 } 119 120 close(dbg->sock); 121 dbg->sock = -1; 122 } 123 124 void hdhomerun_debug_destroy(struct hdhomerun_debug_t *dbg) 125 { 126 dbg->terminate = TRUE; 127 pthread_join(dbg->thread, NULL); 128 129 hdhomerun_debug_close_file(dbg); 130 hdhomerun_debug_close_sock(dbg); 131 132 if (dbg->prefix) { 133 free(dbg->prefix); 134 } 135 136 free(dbg); 137 } 138 139 void hdhomerun_debug_set_prefix(struct hdhomerun_debug_t *dbg, const char *prefix) 140 { 141 pthread_mutex_lock(&dbg->print_lock); 142 143 if (dbg->prefix) { 144 free(dbg->prefix); 145 dbg->prefix = NULL; 146 } 147 148 if (prefix) { 149 dbg->prefix = strdup(prefix); 150 } 151 152 pthread_mutex_unlock(&dbg->print_lock); 153 } 154 155 void hdhomerun_debug_set_filename(struct hdhomerun_debug_t *dbg, const char *filename) 156 { 157 pthread_mutex_lock(&dbg->send_lock); 158 159 if (!filename && !dbg->file_name) { 160 pthread_mutex_unlock(&dbg->send_lock); 161 return; 162 } 163 if (filename && dbg->file_name) { 164 if (strcmp(filename, dbg->file_name) == 0) { 165 pthread_mutex_unlock(&dbg->send_lock); 166 return; 167 } 168 } 169 170 hdhomerun_debug_close_file(dbg); 171 hdhomerun_debug_close_sock(dbg); 172 173 if (dbg->file_name) { 174 free(dbg->file_name); 175 dbg->file_name = NULL; 176 } 177 if (filename) { 178 dbg->file_name = strdup(filename); 179 } 180 181 pthread_mutex_unlock(&dbg->send_lock); 182 } 183 184 void hdhomerun_debug_enable(struct hdhomerun_debug_t *dbg) 185 { 186 pthread_mutex_lock(&dbg->send_lock); 187 188 dbg->enabled = TRUE; 189 190 pthread_mutex_unlock(&dbg->send_lock); 191 } 192 193 void hdhomerun_debug_disable(struct hdhomerun_debug_t *dbg) 194 { 195 pthread_mutex_lock(&dbg->send_lock); 196 197 dbg->enabled = FALSE; 198 hdhomerun_debug_close_file(dbg); 199 hdhomerun_debug_close_sock(dbg); 200 201 pthread_mutex_unlock(&dbg->send_lock); 202 } 203 204 bool_t hdhomerun_debug_enabled(struct hdhomerun_debug_t *dbg) 205 { 206 if (!dbg) { 207 return FALSE; 208 } 209 210 return dbg->enabled; 211 } 212 213 void hdhomerun_debug_flush(struct hdhomerun_debug_t *dbg, uint64_t timeout) 214 { 215 timeout = getcurrenttime() + timeout; 216 217 while (getcurrenttime() < timeout) { 218 pthread_mutex_lock(&dbg->queue_lock); 219 struct hdhomerun_debug_message_t *message = dbg->queue_tail; 220 pthread_mutex_unlock(&dbg->queue_lock); 221 222 if (!message) { 223 return; 224 } 225 226 msleep(10); 227 } 228 } 229 230 void hdhomerun_debug_printf(struct hdhomerun_debug_t *dbg, const char *fmt, ...) 231 { 232 va_list args; 233 va_start(args, fmt); 234 hdhomerun_debug_vprintf(dbg, fmt, args); 235 va_end(args); 236 } 237 238 void hdhomerun_debug_vprintf(struct hdhomerun_debug_t *dbg, const char *fmt, va_list args) 239 { 240 if (!dbg) { 241 return; 242 } 243 if (!dbg->enabled) { 244 return; 245 } 246 247 struct hdhomerun_debug_message_t *message = (struct hdhomerun_debug_message_t *)malloc(sizeof(struct hdhomerun_debug_message_t)); 248 if (!message) { 249 return; 250 } 251 252 char *ptr = message->buffer; 253 char *end = message->buffer + sizeof(message->buffer) - 2; 254 *end = 0; 255 256 /* 257 * Timestamp. 258 */ 259 time_t current_time = time(NULL); 260 ptr += strftime(ptr, end - ptr, "%Y%m%d-%H:%M:%S ", localtime(¤t_time)); 261 if (ptr > end) { 262 ptr = end; 263 } 264 265 /* 266 * Debug prefix. 267 */ 268 pthread_mutex_lock(&dbg->print_lock); 269 270 if (dbg->prefix) { 271 int len = snprintf(ptr, end - ptr, "%s ", dbg->prefix); 272 len = (len <= 0) ? 0 : len; 273 ptr += len; 274 if (ptr > end) { 275 ptr = end; 276 } 277 } 278 279 pthread_mutex_unlock(&dbg->print_lock); 280 281 /* 282 * Message text. 283 */ 284 int len = vsnprintf(ptr, end - ptr, fmt, args); 285 len = (len < 0) ? 0 : len; /* len does not include null */ 286 ptr += len; 287 if (ptr > end) { 288 ptr = end; 289 } 290 291 /* 292 * Force newline. 293 */ 294 if ((ptr[-1] != '\n') && (ptr + 1 <= end)) { 295 *ptr++ = '\n'; 296 } 297 298 /* 299 * Force NULL. 300 */ 301 if (ptr + 1 > end) { 302 ptr = end - 1; 303 } 304 *ptr++ = 0; 305 306 /* 307 * Enqueue. 308 */ 309 pthread_mutex_lock(&dbg->queue_lock); 310 311 message->prev = NULL; 312 message->next = dbg->queue_head; 313 dbg->queue_head = message; 314 if (message->next) { 315 message->next->prev = message; 316 } else { 317 dbg->queue_tail = message; 318 } 319 dbg->queue_depth++; 320 321 pthread_mutex_unlock(&dbg->queue_lock); 322 } 323 324 /* Send lock held by caller */ 325 static bool_t hdhomerun_debug_output_message_file(struct hdhomerun_debug_t *dbg, struct hdhomerun_debug_message_t *message) 326 { 327 if (!dbg->file_fp) { 328 uint64_t current_time = getcurrenttime(); 329 if (current_time < dbg->connect_delay) { 330 return FALSE; 331 } 332 dbg->connect_delay = current_time + 30*1000; 333 334 dbg->file_fp = fopen(dbg->file_name, "a"); 335 if (!dbg->file_fp) { 336 return FALSE; 337 } 338 } 339 340 fprintf(dbg->file_fp, "%s", message->buffer); 341 fflush(dbg->file_fp); 342 343 return TRUE; 344 } 345 346 /* Send lock held by caller */ 347 #if defined(__CYGWIN__) 348 static bool_t hdhomerun_debug_output_message_sock(struct hdhomerun_debug_t *dbg, struct hdhomerun_debug_message_t *message) 349 { 350 return TRUE; 351 } 352 #else 353 static bool_t hdhomerun_debug_output_message_sock(struct hdhomerun_debug_t *dbg, struct hdhomerun_debug_message_t *message) 354 { 355 if (dbg->sock == -1) { 356 uint64_t current_time = getcurrenttime(); 357 if (current_time < dbg->connect_delay) { 358 return FALSE; 359 } 360 dbg->connect_delay = current_time + 30*1000; 361 362 dbg->sock = (int)socket(AF_INET, SOCK_STREAM, 0); 363 if (dbg->sock == -1) { 364 return FALSE; 365 } 366 367 struct addrinfo hints; 368 memset(&hints, 0, sizeof(hints)); 369 hints.ai_family = AF_INET; 370 hints.ai_socktype = SOCK_STREAM; 371 hints.ai_protocol = IPPROTO_TCP; 372 373 struct addrinfo *sock_info; 374 if (getaddrinfo(HDHOMERUN_DEBUG_HOST, HDHOMERUN_DEBUG_PORT, &hints, &sock_info) != 0) { 375 hdhomerun_debug_close_sock(dbg); 376 return FALSE; 377 } 378 if (connect(dbg->sock, sock_info->ai_addr, (int)sock_info->ai_addrlen) != 0) { 379 freeaddrinfo(sock_info); 380 hdhomerun_debug_close_sock(dbg); 381 return FALSE; 382 } 383 freeaddrinfo(sock_info); 384 } 385 386 size_t length = strlen(message->buffer); 387 if (send(dbg->sock, (char *)message->buffer, (int)length, 0) != length) { 388 hdhomerun_debug_close_sock(dbg); 389 return FALSE; 390 } 391 392 return TRUE; 393 } 394 #endif 395 396 static bool_t hdhomerun_debug_output_message(struct hdhomerun_debug_t *dbg, struct hdhomerun_debug_message_t *message) 397 { 398 pthread_mutex_lock(&dbg->send_lock); 399 400 if (!dbg->enabled) { 401 pthread_mutex_unlock(&dbg->send_lock); 402 return TRUE; 403 } 404 405 bool_t ret; 406 if (dbg->file_name) { 407 ret = hdhomerun_debug_output_message_file(dbg, message); 408 } else { 409 ret = hdhomerun_debug_output_message_sock(dbg, message); 410 } 411 412 pthread_mutex_unlock(&dbg->send_lock); 413 return ret; 414 } 415 416 static void hdhomerun_debug_pop_and_free_message(struct hdhomerun_debug_t *dbg) 417 { 418 pthread_mutex_lock(&dbg->queue_lock); 419 420 struct hdhomerun_debug_message_t *message = dbg->queue_tail; 421 dbg->queue_tail = message->prev; 422 if (message->prev) { 423 message->prev->next = NULL; 424 } else { 425 dbg->queue_head = NULL; 426 } 427 dbg->queue_depth--; 428 429 pthread_mutex_unlock(&dbg->queue_lock); 430 431 free(message); 432 } 433 434 static THREAD_FUNC_PREFIX hdhomerun_debug_thread_execute(void *arg) 435 { 436 struct hdhomerun_debug_t *dbg = (struct hdhomerun_debug_t *)arg; 437 438 while (!dbg->terminate) { 439 440 pthread_mutex_lock(&dbg->queue_lock); 441 struct hdhomerun_debug_message_t *message = dbg->queue_tail; 442 uint32_t queue_depth = dbg->queue_depth; 443 pthread_mutex_unlock(&dbg->queue_lock); 444 445 if (!message) { 446 msleep(250); 447 continue; 448 } 449 450 if (queue_depth > 256) { 451 hdhomerun_debug_pop_and_free_message(dbg); 452 continue; 453 } 454 455 if (!hdhomerun_debug_output_message(dbg, message)) { 456 msleep(250); 457 continue; 458 } 459 460 hdhomerun_debug_pop_and_free_message(dbg); 461 } 462 463 return 0; 464 } -
libs/libmythtv/hdhomerun/hdhomerun_os.h
1 1 /* 2 2 * hdhomerun_os.h 3 3 * 4 * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.4 * Copyright © 2006-2008 Silicondust Engineering Ltd. <www.silicondust.com>. 5 5 * 6 * This library is free software; you can redistribute it and/or 6 * This library is free software; you can redistribute it and/or 7 7 * modify it under the terms of the GNU Lesser General Public 8 8 * License as published by the Free Software Foundation; either 9 * version 2.1of the License, or (at your option) any later version.9 * version 3 of the License, or (at your option) any later version. 10 10 * 11 11 * This library is distributed in the hope that it will be useful, 12 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of … … 14 14 * Lesser General Public License for more details. 15 15 * 16 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 * 19 * As a special exception to the GNU Lesser General Public License, 20 * you may link, statically or dynamically, an application with a 21 * publicly distributed version of the Library to produce an 22 * executable file containing portions of the Library, and 23 * distribute that executable file under terms of your choice, 24 * without any of the additional requirements listed in clause 4 of 25 * the GNU Lesser General Public License. 26 * 27 * By "a publicly distributed version of the Library", we mean 28 * either the unmodified Library as distributed by Silicondust, or a 29 * modified version of the Library that is distributed under the 30 * conditions defined in the GNU Lesser General Public License. 19 31 */ 20 32 21 #include <stdlib.h> 22 #include <stdio.h> 23 #include <string.h> 24 25 #if defined(WIN32) 33 #if defined(_WIN32) || defined(_WIN64) 26 34 #define __WINDOWS__ 27 35 #endif 28 36 29 37 #if defined(__WINDOWS__) 30 #include <windows.h> 31 #include <sys/types.h> 32 #include <sys/timeb.h> 38 #include "hdhomerun_os_windows.h" 33 39 #else 34 #include <unistd.h> 35 #include <errno.h> 36 #include <sys/types.h> 37 #include <sys/socket.h> 38 #include <netinet/in.h> 39 #include <arpa/inet.h> 40 #include <netdb.h> 41 #include <sys/time.h> 42 #include <sys/timeb.h> 43 #include <fcntl.h> 40 #include "hdhomerun_os_posix.h" 44 41 #endif 45 42 46 #include <pthread.h>47 48 43 #if !defined(TRUE) 49 44 #define TRUE 1 50 45 #endif 46 51 47 #if !defined(FALSE) 52 48 #define FALSE 0 53 49 #endif 54 55 #if defined(__WINDOWS__)56 57 typedef int bool_t;58 typedef unsigned __int8 uint8_t;59 typedef unsigned __int16 uint16_t;60 typedef unsigned __int32 uint32_t;61 typedef unsigned __int64 uint64_t;62 63 #define socklen_t int64 #define close closesocket65 #define sock_getlasterror WSAGetLastError()66 #define sock_getlasterror_socktimeout (WSAGetLastError() == WSAETIMEDOUT)67 #define atoll _atoi6468 #define strcasecmp _stricmp69 #define fseeko _fseeki6470 #define ftello _ftelli6471 #define usleep(us) Sleep((us)/1000)72 #define sleep(sec) Sleep((sec)*1000)73 74 static inline uint64_t getcurrenttime(void)75 {76 struct timeb tb;77 ftime(&tb);78 return ((uint64_t)tb.time * 1000) + tb.millitm;79 }80 81 static inline int setsocktimeout(int s, int level, int optname, uint64_t timeout)82 {83 int t = (int)timeout;84 return setsockopt(s, level, optname, (char *)&t, sizeof(t));85 }86 87 #else88 89 typedef int bool_t;90 91 #define sock_getlasterror errno92 #define sock_getlasterror_socktimeout (errno == EAGAIN)93 94 static inline uint64_t getcurrenttime(void)95 {96 struct timeval t;97 gettimeofday(&t, NULL);98 return ((uint64_t)t.tv_sec * 1000) + (t.tv_usec / 1000);99 }100 101 static inline int setsocktimeout(int s, int level, int optname, uint64_t timeout)102 {103 struct timeval t;104 t.tv_sec = timeout / 1000;105 t.tv_usec = (timeout % 1000) * 1000;106 return setsockopt(s, level, optname, (char *)&t, sizeof(t));107 }108 109 #endif110 -
libs/libmythtv/hdhomerun/hdhomerun_debug.h
1 /* 2 * hdhomerun_debug.h 3 * 4 * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 3 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 * 19 * As a special exception to the GNU Lesser General Public License, 20 * you may link, statically or dynamically, an application with a 21 * publicly distributed version of the Library to produce an 22 * executable file containing portions of the Library, and 23 * distribute that executable file under terms of your choice, 24 * without any of the additional requirements listed in clause 4 of 25 * the GNU Lesser General Public License. 26 * 27 * By "a publicly distributed version of the Library", we mean 28 * either the unmodified Library as distributed by Silicondust, or a 29 * modified version of the Library that is distributed under the 30 * conditions defined in the GNU Lesser General Public License. 31 */ 32 33 /* 34 * The debug logging includes optional support for connecting to the 35 * Silicondust support server. This option should not be used without 36 * being explicitly enabled by the user. Debug information should be 37 * limited to information useful to diagnosing a problem. 38 * - Silicondust. 39 */ 40 41 #ifdef __cplusplus 42 extern "C" { 43 #endif 44 45 struct hdhomerun_debug_t; 46 47 extern LIBTYPE struct hdhomerun_debug_t *hdhomerun_debug_create(void); 48 extern LIBTYPE void hdhomerun_debug_destroy(struct hdhomerun_debug_t *dbg); 49 50 extern LIBTYPE void hdhomerun_debug_set_prefix(struct hdhomerun_debug_t *dbg, const char *prefix); 51 extern LIBTYPE void hdhomerun_debug_set_filename(struct hdhomerun_debug_t *dbg, const char *filename); 52 extern LIBTYPE void hdhomerun_debug_enable(struct hdhomerun_debug_t *dbg); 53 extern LIBTYPE void hdhomerun_debug_disable(struct hdhomerun_debug_t *dbg); 54 extern LIBTYPE bool_t hdhomerun_debug_enabled(struct hdhomerun_debug_t *dbg); 55 56 extern LIBTYPE void hdhomerun_debug_flush(struct hdhomerun_debug_t *dbg, uint64_t timeout); 57 58 extern LIBTYPE void hdhomerun_debug_printf(struct hdhomerun_debug_t *dbg, const char *fmt, ...); 59 extern LIBTYPE void hdhomerun_debug_vprintf(struct hdhomerun_debug_t *dbg, const char *fmt, va_list args); 60 61 #ifdef __cplusplus 62 } 63 #endif -
libs/libmythtv/hdhomerun/hdhomerun_channels.c
1 /* 2 * hdhomerun_channels.c 3 * 4 * Copyright © 2007-2008 Silicondust Engineering Ltd. <www.silicondust.com>. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 3 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 * 19 * As a special exception to the GNU Lesser General Public License, 20 * you may link, statically or dynamically, an application with a 21 * publicly distributed version of the Library to produce an 22 * executable file containing portions of the Library, and 23 * distribute that executable file under terms of your choice, 24 * without any of the additional requirements listed in clause 4 of 25 * the GNU Lesser General Public License. 26 * 27 * By "a publicly distributed version of the Library", we mean 28 * either the unmodified Library as distributed by Silicondust, or a 29 * modified version of the Library that is distributed under the 30 * conditions defined in the GNU Lesser General Public License. 31 */ 32 33 #include "hdhomerun.h" 34 35 #define FREQUENCY_RESOLUTION 62500 36 37 struct hdhomerun_channel_entry_t { 38 struct hdhomerun_channel_entry_t *next; 39 struct hdhomerun_channel_entry_t *prev; 40 uint32_t frequency; 41 uint8_t channel_number; 42 char name[16]; 43 }; 44 45 struct hdhomerun_channel_list_t { 46 struct hdhomerun_channel_entry_t *head; 47 struct hdhomerun_channel_entry_t *tail; 48 }; 49 50 struct hdhomerun_channelmap_range_t { 51 uint8_t channel_range_start; 52 uint8_t channel_range_end; 53 uint32_t frequency; 54 uint32_t spacing; 55 }; 56 57 struct hdhomerun_channelmap_record_t { 58 const char *channelmap_prefix; 59 const char *channelmap; 60 const struct hdhomerun_channelmap_range_t *range_list; 61 const char *channelmap_scan_group; 62 const char *countrycodes; 63 }; 64 65 /* AU antenna channels. Channels {0, 1, 2, 6, 7, 8, 9, 9A} are numbered {2, 3, 4, 5, 6, 7, 8, 9} by the HDHomeRun. */ 66 static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_au_bcast[] = { 67 { 2, 2, 48500000, 7000000}, 68 { 3, 4, 59500000, 7000000}, 69 { 5, 12, 177500000, 7000000}, 70 { 28, 69, 529500000, 7000000}, 71 { 0, 0, 0, 0} 72 }; 73 74 /* AU cable channels. TBD. */ 75 static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_au_cable[] = { 76 { 0, 0, 0, 0} 77 }; 78 79 /* EU antenna channels. */ 80 static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_eu_bcast[] = { 81 { 2, 4, 50500000, 7000000}, 82 { 5, 12, 177500000, 7000000}, 83 { 21, 69, 474000000, 8000000}, 84 { 0, 0, 0, 0} 85 }; 86 87 /* EU cable channels. Channels do not have simple numbers - the HDHomeRun uses its own numbering scheme (subject to change). */ 88 static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_eu_cable[] = { 89 { 6, 7, 113000000, 8000000}, 90 { 9, 100, 138000000, 8000000}, 91 { 0, 0, 0, 0} 92 }; 93 94 /* US antenna channels. */ 95 static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_us_bcast[] = { 96 { 2, 4, 57000000, 6000000}, 97 { 5, 6, 79000000, 6000000}, 98 { 7, 13, 177000000, 6000000}, 99 { 14, 69, 473000000, 6000000}, 100 { 0, 0, 0, 0} 101 }; 102 103 /* US cable channels. */ 104 static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_us_cable[] = { 105 { 2, 4, 57000000, 6000000}, 106 { 5, 6, 79000000, 6000000}, 107 { 7, 13, 177000000, 6000000}, 108 { 14, 22, 123000000, 6000000}, 109 { 23, 94, 219000000, 6000000}, 110 { 95, 99, 93000000, 6000000}, 111 {100, 135, 651000000, 6000000}, 112 { 0, 0, 0, 0} 113 }; 114 115 /* US cable channels (HRC). */ 116 static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_us_hrc[] = { 117 { 2, 4, 55752700, 6000300}, 118 { 5, 6, 79753900, 6000300}, 119 { 7, 13, 175758700, 6000300}, 120 { 14, 22, 121756000, 6000300}, 121 { 23, 94, 217760800, 6000300}, 122 { 95, 99, 91754500, 6000300}, 123 {100, 135, 649782400, 6000300}, 124 { 0, 0, 0, 0} 125 }; 126 127 /* US cable channels (IRC). */ 128 static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_us_irc[] = { 129 { 2, 4, 57012500, 6000000}, 130 { 5, 6, 81012500, 6000000}, 131 { 7, 13, 177012500, 6000000}, 132 { 14, 22, 123012500, 6000000}, 133 { 23, 41, 219012500, 6000000}, 134 { 42, 42, 333025000, 6000000}, 135 { 43, 94, 339012500, 6000000}, 136 { 95, 97, 93012500, 6000000}, 137 { 98, 99, 111025000, 6000000}, 138 {100, 135, 651012500, 6000000}, 139 { 0, 0, 0, 0} 140 }; 141 142 static const struct hdhomerun_channelmap_record_t hdhomerun_channelmap_table[] = { 143 {"au", "au-bcast", hdhomerun_channelmap_range_au_bcast, "au-bcast", "AU"}, 144 {"au", "au-cable", hdhomerun_channelmap_range_au_cable, "au-cable", "AU"}, 145 {"eu", "eu-bcast", hdhomerun_channelmap_range_eu_bcast, "eu-bcast", "EU"}, 146 {"eu", "eu-cable", hdhomerun_channelmap_range_eu_cable, "eu-cable", "EU"}, 147 {"tw", "tw-bcast", hdhomerun_channelmap_range_us_bcast, "tw-bcast", "TW"}, 148 {"tw", "tw-cable", hdhomerun_channelmap_range_us_cable, "tw-cable", "TW"}, 149 {"us", "us-bcast", hdhomerun_channelmap_range_us_bcast, "us-bcast", "CA US"}, 150 {"us", "us-cable", hdhomerun_channelmap_range_us_cable, "us-cable us-hrc us-irc", "CA US"}, 151 {"us", "us-hrc", hdhomerun_channelmap_range_us_hrc , "us-cable us-hrc us-irc", "CA US"}, 152 {"us", "us-irc", hdhomerun_channelmap_range_us_irc, "us-cable us-hrc us-irc", "CA US"}, 153 {NULL, NULL, NULL, NULL, NULL} 154 }; 155 156 const char *hdhomerun_channelmap_convert_countrycode_to_channelmap_prefix(const char *countrycode) 157 { 158 const struct hdhomerun_channelmap_record_t *record = hdhomerun_channelmap_table; 159 while (record->channelmap) { 160 if (strstr(record->countrycodes, countrycode)) { 161 return record->channelmap_prefix; 162 } 163 record++; 164 } 165 166 return "eu"; 167 } 168 169 const char *hdhomerun_channelmap_get_channelmap_scan_group(const char *channelmap) 170 { 171 const struct hdhomerun_channelmap_record_t *record = hdhomerun_channelmap_table; 172 while (record->channelmap) { 173 if (strstr(channelmap, record->channelmap)) { 174 return record->channelmap_scan_group; 175 } 176 record++; 177 } 178 179 return NULL; 180 } 181 182 uint8_t hdhomerun_channel_entry_channel_number(struct hdhomerun_channel_entry_t *entry) 183 { 184 return entry->channel_number; 185 } 186 187 uint32_t hdhomerun_channel_entry_frequency(struct hdhomerun_channel_entry_t *entry) 188 { 189 return entry->frequency; 190 } 191 192 const char *hdhomerun_channel_entry_name(struct hdhomerun_channel_entry_t *entry) 193 { 194 return entry->name; 195 } 196 197 struct hdhomerun_channel_entry_t *hdhomerun_channel_list_first(struct hdhomerun_channel_list_t *channel_list) 198 { 199 return channel_list->head; 200 } 201 202 struct hdhomerun_channel_entry_t *hdhomerun_channel_list_last(struct hdhomerun_channel_list_t *channel_list) 203 { 204 return channel_list->tail; 205 } 206 207 struct hdhomerun_channel_entry_t *hdhomerun_channel_list_next(struct hdhomerun_channel_list_t *channel_list, struct hdhomerun_channel_entry_t *entry) 208 { 209 return entry->next; 210 } 211 212 struct hdhomerun_channel_entry_t *hdhomerun_channel_list_prev(struct hdhomerun_channel_list_t *channel_list, struct hdhomerun_channel_entry_t *entry) 213 { 214 return entry->prev; 215 } 216 217 uint32_t hdhomerun_channel_list_total_count(struct hdhomerun_channel_list_t *channel_list) 218 { 219 uint32_t count = 0; 220 221 struct hdhomerun_channel_entry_t *entry = hdhomerun_channel_list_first(channel_list); 222 while (entry) { 223 count++; 224 entry = hdhomerun_channel_list_next(channel_list, entry); 225 } 226 227 return count; 228 } 229 230 uint32_t hdhomerun_channel_list_frequency_count(struct hdhomerun_channel_list_t *channel_list) 231 { 232 uint32_t count = 0; 233 uint32_t last_frequency = 0; 234 235 struct hdhomerun_channel_entry_t *entry = hdhomerun_channel_list_first(channel_list); 236 while (entry) { 237 if (entry->frequency != last_frequency) { 238 last_frequency = entry->frequency; 239 count++; 240 } 241 242 entry = hdhomerun_channel_list_next(channel_list, entry); 243 } 244 245 return count; 246 } 247 248 uint32_t hdhomerun_channel_frequency_truncate(uint32_t frequency) 249 { 250 return (frequency / FREQUENCY_RESOLUTION) * FREQUENCY_RESOLUTION; 251 } 252 253 uint32_t hdhomerun_channel_number_to_frequency(struct hdhomerun_channel_list_t *channel_list, uint8_t channel_number) 254 { 255 struct hdhomerun_channel_entry_t *entry = hdhomerun_channel_list_first(channel_list); 256 while (entry) { 257 if (entry->channel_number == channel_number) { 258 return entry->frequency; 259 } 260 261 entry = hdhomerun_channel_list_next(channel_list, entry); 262 } 263 264 return 0; 265 } 266 267 uint8_t hdhomerun_channel_frequency_to_number(struct hdhomerun_channel_list_t *channel_list, uint32_t frequency) 268 { 269 frequency = hdhomerun_channel_frequency_truncate(frequency); 270 271 struct hdhomerun_channel_entry_t *entry = hdhomerun_channel_list_first(channel_list); 272 while (entry) { 273 if (entry->frequency == frequency) { 274 return entry->channel_number; 275 } 276 if (entry->frequency > frequency) { 277 return 0; 278 } 279 280 entry = hdhomerun_channel_list_next(channel_list, entry); 281 } 282 283 return 0; 284 } 285 286 static void hdhomerun_channel_list_build_insert(struct hdhomerun_channel_list_t *channel_list, struct hdhomerun_channel_entry_t *entry) 287 { 288 struct hdhomerun_channel_entry_t *prev = NULL; 289 struct hdhomerun_channel_entry_t *next = channel_list->head; 290 291 while (next) { 292 if (next->frequency > entry->frequency) { 293 break; 294 } 295 296 prev = next; 297 next = next->next; 298 } 299 300 entry->prev = prev; 301 entry->next = next; 302 303 if (prev) { 304 prev->next = entry; 305 } else { 306 channel_list->head = entry; 307 } 308 309 if (next) { 310 next->prev = entry; 311 } else { 312 channel_list->tail = entry; 313 } 314 } 315 316 static void hdhomerun_channel_list_build_range(struct hdhomerun_channel_list_t *channel_list, const char *channelmap, const struct hdhomerun_channelmap_range_t *range) 317 { 318 uint8_t channel_number; 319 for (channel_number = range->channel_range_start; channel_number <= range->channel_range_end; channel_number++) { 320 struct hdhomerun_channel_entry_t *entry = (struct hdhomerun_channel_entry_t *)calloc(1, sizeof(struct hdhomerun_channel_entry_t)); 321 if (!entry) { 322 return; 323 } 324 325 entry->channel_number = channel_number; 326 entry->frequency = range->frequency + ((uint32_t)(channel_number - range->channel_range_start) * range->spacing); 327 entry->frequency = hdhomerun_channel_frequency_truncate(entry->frequency); 328 sprintf(entry->name, "%s:%u", channelmap, entry->channel_number); 329 330 hdhomerun_channel_list_build_insert(channel_list, entry); 331 } 332 } 333 334 static void hdhomerun_channel_list_build_ranges(struct hdhomerun_channel_list_t *channel_list, const struct hdhomerun_channelmap_record_t *record) 335 { 336 const struct hdhomerun_channelmap_range_t *range = record->range_list; 337 while (range->frequency) { 338 hdhomerun_channel_list_build_range(channel_list, record->channelmap, range); 339 range++; 340 } 341 } 342 343 void hdhomerun_channel_list_destroy(struct hdhomerun_channel_list_t *channel_list) 344 { 345 while (channel_list->head) { 346 struct hdhomerun_channel_entry_t *entry = channel_list->head; 347 channel_list->head = entry->next; 348 free(entry); 349 } 350 351 free(channel_list); 352 } 353 354 struct hdhomerun_channel_list_t *hdhomerun_channel_list_create(const char *channelmap) 355 { 356 struct hdhomerun_channel_list_t *channel_list = (struct hdhomerun_channel_list_t *)calloc(1, sizeof(struct hdhomerun_channel_list_t)); 357 if (!channel_list) { 358 return NULL; 359 } 360 361 const struct hdhomerun_channelmap_record_t *record = hdhomerun_channelmap_table; 362 while (record->channelmap) { 363 if (!strstr(channelmap, record->channelmap)) { 364 record++; 365 continue; 366 } 367 368 hdhomerun_channel_list_build_ranges(channel_list, record); 369 record++; 370 } 371 372 if (!channel_list->head) { 373 free(channel_list); 374 return NULL; 375 } 376 377 return channel_list; 378 } -
libs/libmythtv/hdhomerun/hdhomerun_pkt.c
3 3 * 4 4 * Copyright © 2005-2006 Silicondust Engineering Ltd. <www.silicondust.com>. 5 5 * 6 * This library is free software; you can redistribute it and/or 6 * This library is free software; you can redistribute it and/or 7 7 * modify it under the terms of the GNU Lesser General Public 8 8 * License as published by the Free Software Foundation; either 9 * version 2.1of the License, or (at your option) any later version.9 * version 3 of the License, or (at your option) any later version. 10 10 * 11 11 * This library is distributed in the hope that it will be useful, 12 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of … … 14 14 * Lesser General Public License for more details. 15 15 * 16 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 * 19 * As a special exception to the GNU Lesser General Public License, 20 * you may link, statically or dynamically, an application with a 21 * publicly distributed version of the Library to produce an 22 * executable file containing portions of the Library, and 23 * distribute that executable file under terms of your choice, 24 * without any of the additional requirements listed in clause 4 of 25 * the GNU Lesser General Public License. 26 * 27 * By "a publicly distributed version of the Library", we mean 28 * either the unmodified Library as distributed by Silicondust, or a 29 * modified version of the Library that is distributed under the 30 * conditions defined in the GNU Lesser General Public License. 19 31 */ 20 32 21 #include "hdhomerun_os.h" 22 #include "hdhomerun_pkt.h" 33 #include "hdhomerun.h" 23 34 24 uint8_t hdhomerun_read_u8(uint8_t **pptr)35 struct hdhomerun_pkt_t *hdhomerun_pkt_create(void) 25 36 { 26 uint8_t *ptr = *pptr; 27 uint8_t v = *ptr++; 28 *pptr = ptr; 37 struct hdhomerun_pkt_t *pkt = (struct hdhomerun_pkt_t *)calloc(1, sizeof(struct hdhomerun_pkt_t)); 38 if (!pkt) { 39 return NULL; 40 } 41 42 hdhomerun_pkt_reset(pkt); 43 44 return pkt; 45 } 46 47 void hdhomerun_pkt_destroy(struct hdhomerun_pkt_t *pkt) 48 { 49 free(pkt); 50 } 51 52 void hdhomerun_pkt_reset(struct hdhomerun_pkt_t *pkt) 53 { 54 pkt->limit = pkt->buffer + sizeof(pkt->buffer) - 4; 55 pkt->start = pkt->buffer + 1024; 56 pkt->end = pkt->start; 57 pkt->pos = pkt->start; 58 } 59 60 static uint32_t hdhomerun_pkt_calc_crc(uint8_t *start, uint8_t *end) 61 { 62 uint8_t *pos = start; 63 uint32_t crc = 0xFFFFFFFF; 64 while (pos < end) { 65 uint8_t x = (uint8_t)(crc) ^ *pos++; 66 crc >>= 8; 67 if (x & 0x01) crc ^= 0x77073096; 68 if (x & 0x02) crc ^= 0xEE0E612C; 69 if (x & 0x04) crc ^= 0x076DC419; 70 if (x & 0x08) crc ^= 0x0EDB8832; 71 if (x & 0x10) crc ^= 0x1DB71064; 72 if (x & 0x20) crc ^= 0x3B6E20C8; 73 if (x & 0x40) crc ^= 0x76DC4190; 74 if (x & 0x80) crc ^= 0xEDB88320; 75 } 76 return crc ^ 0xFFFFFFFF; 77 } 78 79 uint8_t hdhomerun_pkt_read_u8(struct hdhomerun_pkt_t *pkt) 80 { 81 uint8_t v = *pkt->pos++; 29 82 return v; 30 83 } 31 84 32 uint16_t hdhomerun_ read_u16(uint8_t **pptr)85 uint16_t hdhomerun_pkt_read_u16(struct hdhomerun_pkt_t *pkt) 33 86 { 34 uint8_t *ptr = *pptr;35 87 uint16_t v; 36 v = (uint16_t)*ptr++ << 8; 37 v |= (uint16_t)*ptr++ << 0; 38 *pptr = ptr; 88 v = (uint16_t)*pkt->pos++ << 8; 89 v |= (uint16_t)*pkt->pos++ << 0; 39 90 return v; 40 91 } 41 92 42 uint32_t hdhomerun_ read_u32(uint8_t **pptr)93 uint32_t hdhomerun_pkt_read_u32(struct hdhomerun_pkt_t *pkt) 43 94 { 44 uint8_t *ptr = *pptr;45 95 uint32_t v; 46 v = (uint32_t)*ptr++ << 24; 47 v |= (uint32_t)*ptr++ << 16; 48 v |= (uint32_t)*ptr++ << 8; 49 v |= (uint32_t)*ptr++ << 0; 50 *pptr = ptr; 96 v = (uint32_t)*pkt->pos++ << 24; 97 v |= (uint32_t)*pkt->pos++ << 16; 98 v |= (uint32_t)*pkt->pos++ << 8; 99 v |= (uint32_t)*pkt->pos++ << 0; 51 100 return v; 52 101 } 53 102 54 size_t hdhomerun_ read_var_length(uint8_t **pptr, uint8_t *end)103 size_t hdhomerun_pkt_read_var_length(struct hdhomerun_pkt_t *pkt) 55 104 { 56 uint8_t *ptr = *pptr;57 105 size_t length; 58 106 59 if (p tr + 1 >end) {60 return -1;107 if (pkt->pos + 1 > pkt->end) { 108 return (size_t)-1; 61 109 } 62 110 63 length = (size_t)*p tr++;111 length = (size_t)*pkt->pos++; 64 112 if (length & 0x0080) { 65 if (p tr + 1 >end) {66 return -1;113 if (pkt->pos + 1 > pkt->end) { 114 return (size_t)-1; 67 115 } 68 116 69 117 length &= 0x007F; 70 length |= (size_t)*p tr++ << 7;118 length |= (size_t)*pkt->pos++ << 7; 71 119 } 72 120 73 *pptr = ptr;74 121 return length; 75 122 } 76 123 77 int hdhomerun_read_tlv(uint8_t **pptr, uint8_t *end, uint8_t *ptag, size_t *plength, uint8_t **pvalue)124 uint8_t *hdhomerun_pkt_read_tlv(struct hdhomerun_pkt_t *pkt, uint8_t *ptag, size_t *plength) 78 125 { 79 if ( end - *pptr < 2) {80 return -1;126 if (pkt->pos + 2 > pkt->end) { 127 return NULL; 81 128 } 82 129 83 *ptag = hdhomerun_read_u8(pptr); 84 *plength = hdhomerun_read_var_length(pptr, end); 85 *pvalue = *pptr; 86 87 if ((size_t)(end - *pptr) < *plength) { 88 return -1; 130 *ptag = hdhomerun_pkt_read_u8(pkt); 131 *plength = hdhomerun_pkt_read_var_length(pkt); 132 133 if (pkt->pos + *plength > pkt->end) { 134 return NULL; 89 135 } 90 136 91 *pptr += *plength; 92 return 0; 137 return pkt->pos + *plength; 93 138 } 94 139 95 void hdhomerun_ write_u8(uint8_t **pptr, uint8_t v)140 void hdhomerun_pkt_write_u8(struct hdhomerun_pkt_t *pkt, uint8_t v) 96 141 { 97 uint8_t *ptr = *pptr; 98 *ptr++ = v; 99 *pptr = ptr; 100 } 142 *pkt->pos++ = v; 101 143 102 void hdhomerun_write_u16(uint8_t **pptr, uint16_t v) 103 { 104 uint8_t *ptr = *pptr; 105 *ptr++ = (uint8_t)(v >> 8); 106 *ptr++ = (uint8_t)(v >> 0); 107 *pptr = ptr; 144 if (pkt->pos > pkt->end) { 145 pkt->end = pkt->pos; 146 } 108 147 } 109 148 110 void hdhomerun_ write_u32(uint8_t **pptr, uint32_t v)149 void hdhomerun_pkt_write_u16(struct hdhomerun_pkt_t *pkt, uint16_t v) 111 150 { 112 uint8_t *ptr = *pptr; 113 *ptr++ = (uint8_t)(v >> 24); 114 *ptr++ = (uint8_t)(v >> 16); 115 *ptr++ = (uint8_t)(v >> 8); 116 *ptr++ = (uint8_t)(v >> 0); 117 *pptr = ptr; 118 } 151 *pkt->pos++ = (uint8_t)(v >> 8); 152 *pkt->pos++ = (uint8_t)(v >> 0); 119 153 120 void hdhomerun_write_var_length(uint8_t **pptr, size_t v) 121 { 122 uint8_t *ptr = *pptr; 123 if (v <= 127) { 124 *ptr++ = (uint8_t)v; 125 } else { 126 *ptr++ = (uint8_t)(v | 0x80); 127 *ptr++ = (uint8_t)(v >> 7); 154 if (pkt->pos > pkt->end) { 155 pkt->end = pkt->pos; 128 156 } 129 *pptr = ptr;130 157 } 131 158 132 static void hdhomerun_write_mem(uint8_t **pptr, void *mem, size_t length)159 void hdhomerun_pkt_write_u32(struct hdhomerun_pkt_t *pkt, uint32_t v) 133 160 { 134 uint8_t *ptr = *pptr; 135 memcpy(ptr, mem, length); 136 ptr += length; 137 *pptr = ptr; 138 } 161 *pkt->pos++ = (uint8_t)(v >> 24); 162 *pkt->pos++ = (uint8_t)(v >> 16); 163 *pkt->pos++ = (uint8_t)(v >> 8); 164 *pkt->pos++ = (uint8_t)(v >> 0); 139 165 140 static uint32_t hdhomerun_calc_crc(uint8_t *start, uint8_t *end) 141 { 142 uint8_t *ptr = start; 143 uint32_t crc = 0xFFFFFFFF; 144 while (ptr < end) { 145 uint8_t x = (uint8_t)(crc) ^ *ptr++; 146 crc >>= 8; 147 if (x & 0x01) crc ^= 0x77073096; 148 if (x & 0x02) crc ^= 0xEE0E612C; 149 if (x & 0x04) crc ^= 0x076DC419; 150 if (x & 0x08) crc ^= 0x0EDB8832; 151 if (x & 0x10) crc ^= 0x1DB71064; 152 if (x & 0x20) crc ^= 0x3B6E20C8; 153 if (x & 0x40) crc ^= 0x76DC4190; 154 if (x & 0x80) crc ^= 0xEDB88320; 166 if (pkt->pos > pkt->end) { 167 pkt->end = pkt->pos; 155 168 } 156 return crc ^ 0xFFFFFFFF;157 169 } 158 170 159 static int hdhomerun_check_crc(uint8_t *start, uint8_t *end)171 void hdhomerun_pkt_write_var_length(struct hdhomerun_pkt_t *pkt, size_t v) 160 172 { 161 if (end - start < 8) { 162 return -1; 173 if (v <= 127) { 174 *pkt->pos++ = (uint8_t)v; 175 } else { 176 *pkt->pos++ = (uint8_t)(v | 0x80); 177 *pkt->pos++ = (uint8_t)(v >> 7); 163 178 } 164 uint8_t *ptr = end -= 4; 165 uint32_t actual_crc = hdhomerun_calc_crc(start, ptr); 166 uint32_t packet_crc; 167 packet_crc = (uint32_t)*ptr++ << 0; 168 packet_crc |= (uint32_t)*ptr++ << 8; 169 packet_crc |= (uint32_t)*ptr++ << 16; 170 packet_crc |= (uint32_t)*ptr++ << 24; 171 if (actual_crc != packet_crc) { 172 return -1; 179 180 if (pkt->pos > pkt->end) { 181 pkt->end = pkt->pos; 173 182 } 174 return 0;175 183 } 176 184 177 static void hdhomerun_write_header_length(uint8_t *ptr, size_t length)185 void hdhomerun_pkt_write_mem(struct hdhomerun_pkt_t *pkt, const void *mem, size_t length) 178 186 { 179 hdhomerun_write_u16(&ptr, (uint16_t)length);180 } 187 memcpy(pkt->pos, mem, length); 188 pkt->pos += length; 181 189 182 void hdhomerun_write_crc(uint8_t **pptr, uint8_t *start) 183 { 184 uint8_t *ptr = *pptr; 185 uint32_t crc = hdhomerun_calc_crc(start, ptr); 186 *ptr++ = (uint8_t)(crc >> 0); 187 *ptr++ = (uint8_t)(crc >> 8); 188 *ptr++ = (uint8_t)(crc >> 16); 189 *ptr++ = (uint8_t)(crc >> 24); 190 *pptr = ptr; 190 if (pkt->pos > pkt->end) { 191 pkt->end = pkt->pos; 192 } 191 193 } 192 194 193 void hdhomerun_write_discover_request(uint8_t **pptr, uint32_t device_type, uint32_t device_id)195 int hdhomerun_pkt_open_frame(struct hdhomerun_pkt_t *pkt, uint16_t *ptype) 194 196 { 195 uint8_t *start = *pptr; 196 hdhomerun_write_u16(pptr, HDHOMERUN_TYPE_DISCOVER_REQ); 197 hdhomerun_write_u16(pptr, 0); 197 pkt->pos = pkt->start; 198 198 199 hdhomerun_write_u8(pptr, HDHOMERUN_TAG_DEVICE_TYPE); 200 hdhomerun_write_var_length(pptr, 4); 201 hdhomerun_write_u32(pptr, device_type); 202 hdhomerun_write_u8(pptr, HDHOMERUN_TAG_DEVICE_ID); 203 hdhomerun_write_var_length(pptr, 4); 204 hdhomerun_write_u32(pptr, device_id); 199 if (pkt->pos + 4 > pkt->end) { 200 return 0; 201 } 205 202 206 hdhomerun_write_header_length(start + 2, (int)(*pptr - start - 4));207 hdhomerun_write_crc(pptr, start);208 } 203 *ptype = hdhomerun_pkt_read_u16(pkt); 204 size_t length = hdhomerun_pkt_read_u16(pkt); 205 pkt->pos += length; 209 206 210 void hdhomerun_write_get_set_request(uint8_t **pptr, const char *name, const char *value) 211 { 212 uint8_t *start = *pptr; 213 hdhomerun_write_u16(pptr, HDHOMERUN_TYPE_GETSET_REQ); 214 hdhomerun_write_u16(pptr, 0); 207 if (pkt->pos + 4 > pkt->end) { 208 pkt->pos = pkt->start; 209 return 0; 210 } 215 211 216 int name_len = (int)strlen(name) + 1; 217 hdhomerun_write_u8(pptr, HDHOMERUN_TAG_GETSET_NAME); 218 hdhomerun_write_var_length(pptr, name_len); 219 hdhomerun_write_mem(pptr, (void *)name, name_len); 212 uint32_t calc_crc = hdhomerun_pkt_calc_crc(pkt->start, pkt->pos); 220 213 221 if (value) { 222 int value_len = (int)strlen(value) + 1; 223 hdhomerun_write_u8(pptr, HDHOMERUN_TAG_GETSET_VALUE); 224 hdhomerun_write_var_length(pptr, value_len); 225 hdhomerun_write_mem(pptr, (void *)value, value_len); 214 uint32_t packet_crc; 215 packet_crc = (uint32_t)*pkt->pos++ << 0; 216 packet_crc |= (uint32_t)*pkt->pos++ << 8; 217 packet_crc |= (uint32_t)*pkt->pos++ << 16; 218 packet_crc |= (uint32_t)*pkt->pos++ << 24; 219 if (calc_crc != packet_crc) { 220 return -1; 226 221 } 227 222 228 hdhomerun_write_header_length(start + 2, (int)(*pptr - start - 4)); 229 hdhomerun_write_crc(pptr, start); 223 pkt->start += 4; 224 pkt->end = pkt->start + length; 225 pkt->pos = pkt->start; 226 return 1; 230 227 } 231 228 232 void hdhomerun_ write_upgrade_request(uint8_t **pptr, uint32_t sequence, void *data, size_t length)229 void hdhomerun_pkt_seal_frame(struct hdhomerun_pkt_t *pkt, uint16_t frame_type) 233 230 { 234 uint8_t *start = *pptr; 235 hdhomerun_write_u16(pptr, HDHOMERUN_TYPE_UPGRADE_REQ); 236 hdhomerun_write_u16(pptr, 0); 231 size_t length = pkt->end - pkt->start; 237 232 238 hdhomerun_write_u32(pptr, sequence);239 if (length > 0) {240 hdhomerun_write_mem(pptr, data, length);241 }233 pkt->start -= 4; 234 pkt->pos = pkt->start; 235 hdhomerun_pkt_write_u16(pkt, frame_type); 236 hdhomerun_pkt_write_u16(pkt, (uint16_t)length); 242 237 243 hdhomerun_write_header_length(start + 2, *pptr - start - 4); 244 hdhomerun_write_crc(pptr, start); 245 } 238 uint32_t crc = hdhomerun_pkt_calc_crc(pkt->start, pkt->end); 239 *pkt->end++ = (uint8_t)(crc >> 0); 240 *pkt->end++ = (uint8_t)(crc >> 8); 241 *pkt->end++ = (uint8_t)(crc >> 16); 242 *pkt->end++ = (uint8_t)(crc >> 24); 246 243 247 size_t hdhomerun_peek_packet_length(uint8_t *ptr) 248 { 249 ptr += 2; 250 return (size_t)hdhomerun_read_u16(&ptr) + 8; 244 pkt->pos = pkt->start; 251 245 } 252 253 int hdhomerun_process_packet(uint8_t **pptr, uint8_t **pend)254 {255 if (hdhomerun_check_crc(*pptr, *pend) < 0) {256 return -1;257 }258 *pend -= 4;259 260 uint16_t type = hdhomerun_read_u16(pptr);261 uint16_t length = hdhomerun_read_u16(pptr);262 if ((*pend - *pptr) < length) {263 return -1;264 }265 *pend = *pptr + length;266 return (int)type;267 }268 -
libs/libmythtv/hdhomerun/hdhomerun_device.c
1 1 /* 2 * hdhomerun_ record.c2 * hdhomerun_device.c 3 3 * 4 * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.4 * Copyright © 2006-2008 Silicondust Engineering Ltd. <www.silicondust.com>. 5 5 * 6 * This library is free software; you can redistribute it and/or 6 * This library is free software; you can redistribute it and/or 7 7 * modify it under the terms of the GNU Lesser General Public 8 8 * License as published by the Free Software Foundation; either 9 * version 2.1of the License, or (at your option) any later version.9 * version 3 of the License, or (at your option) any later version. 10 10 * 11 11 * This library is distributed in the hope that it will be useful, 12 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of … … 14 14 * Lesser General Public License for more details. 15 15 * 16 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 * 19 * As a special exception to the GNU Lesser General Public License, 20 * you may link, statically or dynamically, an application with a 21 * publicly distributed version of the Library to produce an 22 * executable file containing portions of the Library, and 23 * distribute that executable file under terms of your choice, 24 * without any of the additional requirements listed in clause 4 of 25 * the GNU Lesser General Public License. 26 * 27 * By "a publicly distributed version of the Library", we mean 28 * either the unmodified Library as distributed by Silicondust, or a 29 * modified version of the Library that is distributed under the 30 * conditions defined in the GNU Lesser General Public License. 19 31 */ 20 32 21 #include "hdhomerun_os.h" 22 #include "hdhomerun_pkt.h" 23 #include "hdhomerun_control.h" 24 #include "hdhomerun_video.h" 25 #include "hdhomerun_device.h" 33 #include "hdhomerun.h" 26 34 27 35 struct hdhomerun_device_t { 28 36 struct hdhomerun_control_sock_t *cs; 29 37 struct hdhomerun_video_sock_t *vs; 38 struct hdhomerun_debug_t *dbg; 39 struct hdhomerun_channelscan_t *scan; 30 40 unsigned int tuner; 31 char result_buffer[1024]; 41 uint32_t lockkey; 42 char name[32]; 43 char model[32]; 32 44 }; 33 45 34 st ruct hdhomerun_device_t *hdhomerun_device_create(uint32_t device_id, uint32_t device_ip, unsigned int tuner)46 static void hdhomerun_device_set_update(struct hdhomerun_device_t *hd) 35 47 { 48 /* Clear cached information. */ 49 *hd->model = 0; 50 51 /* New name. */ 52 sprintf(hd->name, "%08lX-%u", (unsigned long)hdhomerun_control_get_device_id(hd->cs), hd->tuner); 53 } 54 55 void hdhomerun_device_set_device(struct hdhomerun_device_t *hd, uint32_t device_id, uint32_t device_ip) 56 { 57 hdhomerun_control_set_device(hd->cs, device_id, device_ip); 58 hdhomerun_device_set_update(hd); 59 } 60 61 void hdhomerun_device_set_tuner(struct hdhomerun_device_t *hd, unsigned int tuner) 62 { 63 hd->tuner = tuner; 64 hdhomerun_device_set_update(hd); 65 } 66 67 struct hdhomerun_device_t *hdhomerun_device_create(uint32_t device_id, uint32_t device_ip, unsigned int tuner, struct hdhomerun_debug_t *dbg) 68 { 36 69 struct hdhomerun_device_t *hd = (struct hdhomerun_device_t *)calloc(1, sizeof(struct hdhomerun_device_t)); 37 70 if (!hd) { 71 hdhomerun_debug_printf(dbg, "hdhomerun_device_create: failed to allocate device object\n"); 38 72 return NULL; 39 73 } 40 74 41 hd-> tuner = tuner;75 hd->dbg = dbg; 42 76 43 hd->cs = hdhomerun_control_create( device_id, device_ip);77 hd->cs = hdhomerun_control_create(0, 0, hd->dbg); 44 78 if (!hd->cs) { 79 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_create: failed to create control object\n"); 45 80 free(hd); 46 81 return NULL; 47 82 } 48 83 84 hdhomerun_device_set_device(hd, device_id, device_ip); 85 hdhomerun_device_set_tuner(hd, tuner); 86 49 87 return hd; 50 88 } 51 89 52 90 void hdhomerun_device_destroy(struct hdhomerun_device_t *hd) 53 91 { 92 if (hd->scan) { 93 channelscan_destroy(hd->scan); 94 } 95 54 96 if (hd->vs) { 55 97 hdhomerun_video_destroy(hd->vs); 56 98 } … … 60 102 free(hd); 61 103 } 62 104 63 void hdhomerun_device_set_tuner(struct hdhomerun_device_t *hd, unsigned int tuner)105 static bool_t is_hex_char(char c) 64 106 { 65 hd->tuner = tuner; 107 if ((c >= '0') && (c <= '9')) { 108 return TRUE; 109 } 110 if ((c >= 'A') && (c <= 'F')) { 111 return TRUE; 112 } 113 if ((c >= 'a') && (c <= 'f')) { 114 return TRUE; 115 } 116 return FALSE; 66 117 } 67 118 119 static struct hdhomerun_device_t *hdhomerun_device_create_from_str_device_id(const char *device_str, struct hdhomerun_debug_t *dbg) 120 { 121 int i; 122 const char *ptr = device_str; 123 for (i = 0; i < 8; i++) { 124 if (!is_hex_char(*ptr++)) { 125 return NULL; 126 } 127 } 128 129 if (*ptr == 0) { 130 unsigned long device_id; 131 if (sscanf(device_str, "%lx", &device_id) != 1) { 132 return NULL; 133 } 134 return hdhomerun_device_create((uint32_t)device_id, 0, 0, dbg); 135 } 136 137 if (*ptr == '-') { 138 unsigned long device_id; 139 unsigned int tuner; 140 if (sscanf(device_str, "%lx-%u", &device_id, &tuner) != 2) { 141 return NULL; 142 } 143 return hdhomerun_device_create((uint32_t)device_id, 0, tuner, dbg); 144 } 145 146 return NULL; 147 } 148 149 static struct hdhomerun_device_t *hdhomerun_device_create_from_str_ip(const char *device_str, struct hdhomerun_debug_t *dbg) 150 { 151 unsigned long a[4]; 152 unsigned int tuner; 153 154 if (sscanf(device_str, "%lu.%lu.%lu.%lu-%u", &a[0], &a[1], &a[2], &a[3], &tuner) != 5) { 155 tuner = 0; 156 if (sscanf(device_str, "%lu.%lu.%lu.%lu", &a[0], &a[1], &a[2], &a[3]) != 4) { 157 return NULL; 158 } 159 } 160 161 unsigned long device_ip = (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | (a[3] << 0); 162 return hdhomerun_device_create(HDHOMERUN_DEVICE_ID_WILDCARD, (uint32_t)device_ip, tuner, dbg); 163 } 164 165 static struct hdhomerun_device_t *hdhomerun_device_create_from_str_dns(const char *device_str, struct hdhomerun_debug_t *dbg) 166 { 167 #if defined(__CYGWIN__) 168 return NULL; 169 #else 170 struct addrinfo hints; 171 memset(&hints, 0, sizeof(hints)); 172 hints.ai_family = AF_INET; 173 hints.ai_socktype = SOCK_STREAM; 174 hints.ai_protocol = IPPROTO_TCP; 175 176 struct addrinfo *sock_info; 177 if (getaddrinfo(device_str, "65001", &hints, &sock_info) != 0) { 178 return NULL; 179 } 180 181 struct sockaddr_in *sock_addr = (struct sockaddr_in *)sock_info->ai_addr; 182 uint32_t device_ip = ntohl(sock_addr->sin_addr.s_addr); 183 freeaddrinfo(sock_info); 184 185 if (device_ip == 0) { 186 return NULL; 187 } 188 189 return hdhomerun_device_create(HDHOMERUN_DEVICE_ID_WILDCARD, (uint32_t)device_ip, 0, dbg); 190 #endif 191 } 192 193 struct hdhomerun_device_t *hdhomerun_device_create_from_str(const char *device_str, struct hdhomerun_debug_t *dbg) 194 { 195 struct hdhomerun_device_t *device = hdhomerun_device_create_from_str_device_id(device_str, dbg); 196 if (device) { 197 return device; 198 } 199 200 device = hdhomerun_device_create_from_str_ip(device_str, dbg); 201 if (device) { 202 return device; 203 } 204 205 device = hdhomerun_device_create_from_str_dns(device_str, dbg); 206 if (device) { 207 return device; 208 } 209 210 return NULL; 211 } 212 213 int hdhomerun_device_set_tuner_from_str(struct hdhomerun_device_t *hd, const char *tuner_str) 214 { 215 unsigned int tuner; 216 if (sscanf(tuner_str, "%u", &tuner) == 1) { 217 hdhomerun_device_set_tuner(hd, tuner); 218 return 1; 219 } 220 if (sscanf(tuner_str, "/tuner%u", &tuner) == 1) { 221 hdhomerun_device_set_tuner(hd, tuner); 222 return 1; 223 } 224 225 return -1; 226 } 227 228 uint32_t hdhomerun_device_get_device_id(struct hdhomerun_device_t *hd) 229 { 230 return hdhomerun_control_get_device_id(hd->cs); 231 } 232 233 uint32_t hdhomerun_device_get_device_ip(struct hdhomerun_device_t *hd) 234 { 235 return hdhomerun_control_get_device_ip(hd->cs); 236 } 237 238 uint32_t hdhomerun_device_get_device_id_requested(struct hdhomerun_device_t *hd) 239 { 240 return hdhomerun_control_get_device_id_requested(hd->cs); 241 } 242 243 uint32_t hdhomerun_device_get_device_ip_requested(struct hdhomerun_device_t *hd) 244 { 245 return hdhomerun_control_get_device_ip_requested(hd->cs); 246 } 247 248 unsigned int hdhomerun_device_get_tuner(struct hdhomerun_device_t *hd) 249 { 250 return hd->tuner; 251 } 252 68 253 struct hdhomerun_control_sock_t *hdhomerun_device_get_control_sock(struct hdhomerun_device_t *hd) 69 254 { 70 255 return hd->cs; … … 72 257 73 258 struct hdhomerun_video_sock_t *hdhomerun_device_get_video_sock(struct hdhomerun_device_t *hd) 74 259 { 260 if (hd->vs) { 261 return hd->vs; 262 } 263 264 hd->vs = hdhomerun_video_create(0, VIDEO_DATA_BUFFER_SIZE_1S * 2, hd->dbg); 75 265 if (!hd->vs) { 76 hd->vs = hdhomerun_video_create(0, VIDEO_DATA_BUFFER_SIZE_1S); 266 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_video_sock: failed to create video object\n"); 267 return NULL; 77 268 } 269 78 270 return hd->vs; 79 271 } 80 272 … … 96 288 return (uint32_t)value; 97 289 } 98 290 99 int hdhomerun_device_get_tuner_status(struct hdhomerun_device_t *hd,struct hdhomerun_tuner_status_t *status)291 static bool_t hdhomerun_device_get_tuner_status_lock_is_bcast(struct hdhomerun_tuner_status_t *status) 100 292 { 293 if (strcmp(status->lock_str, "8vsb") == 0) { 294 return TRUE; 295 } 296 if (strncmp(status->lock_str, "t8", 2) == 0) { 297 return TRUE; 298 } 299 if (strncmp(status->lock_str, "t7", 2) == 0) { 300 return TRUE; 301 } 302 if (strncmp(status->lock_str, "t6", 2) == 0) { 303 return TRUE; 304 } 305 306 return FALSE; 307 } 308 309 uint32_t hdhomerun_device_get_tuner_status_ss_color(struct hdhomerun_tuner_status_t *status) 310 { 311 unsigned int ss_yellow_min; 312 unsigned int ss_green_min; 313 314 if (!status->lock_supported) { 315 return HDHOMERUN_STATUS_COLOR_NEUTRAL; 316 } 317 318 if (hdhomerun_device_get_tuner_status_lock_is_bcast(status)) { 319 ss_yellow_min = 50; /* -30dBmV */ 320 ss_green_min = 75; /* -15dBmV */ 321 } else { 322 ss_yellow_min = 80; /* -12dBmV */ 323 ss_green_min = 90; /* -6dBmV */ 324 } 325 326 if (status->signal_strength >= ss_green_min) { 327 return HDHOMERUN_STATUS_COLOR_GREEN; 328 } 329 if (status->signal_strength >= ss_yellow_min) { 330 return HDHOMERUN_STATUS_COLOR_YELLOW; 331 } 332 333 return HDHOMERUN_STATUS_COLOR_RED; 334 } 335 336 uint32_t hdhomerun_device_get_tuner_status_snq_color(struct hdhomerun_tuner_status_t *status) 337 { 338 if (status->signal_to_noise_quality >= 70) { 339 return HDHOMERUN_STATUS_COLOR_GREEN; 340 } 341 if (status->signal_to_noise_quality >= 50) { 342 return HDHOMERUN_STATUS_COLOR_YELLOW; 343 } 344 345 return HDHOMERUN_STATUS_COLOR_RED; 346 } 347 348 uint32_t hdhomerun_device_get_tuner_status_seq_color(struct hdhomerun_tuner_status_t *status) 349 { 350 if (status->symbol_error_quality >= 100) { 351 return HDHOMERUN_STATUS_COLOR_GREEN; 352 } 353 354 return HDHOMERUN_STATUS_COLOR_RED; 355 } 356 357 int hdhomerun_device_get_tuner_status(struct hdhomerun_device_t *hd, char **pstatus_str, struct hdhomerun_tuner_status_t *status) 358 { 101 359 memset(status, 0, sizeof(struct hdhomerun_tuner_status_t)); 102 360 103 361 char name[32]; … … 109 367 return ret; 110 368 } 111 369 370 if (pstatus_str) { 371 *pstatus_str = status_str; 372 } 373 112 374 char *channel = strstr(status_str, "ch="); 113 375 if (channel) { 114 sscanf(channel + 3, "% s", status->channel);376 sscanf(channel + 3, "%31s", status->channel); 115 377 } 116 378 379 char *lock = strstr(status_str, "lock="); 380 if (lock) { 381 sscanf(lock + 5, "%31s", status->lock_str); 382 } 383 117 384 status->signal_strength = (unsigned int)hdhomerun_device_get_status_parse(status_str, "ss="); 118 385 status->signal_to_noise_quality = (unsigned int)hdhomerun_device_get_status_parse(status_str, "snq="); 119 386 status->symbol_error_quality = (unsigned int)hdhomerun_device_get_status_parse(status_str, "seq="); 120 387 status->raw_bits_per_second = hdhomerun_device_get_status_parse(status_str, "bps="); 121 388 status->packets_per_second = hdhomerun_device_get_status_parse(status_str, "pps="); 122 389 390 status->signal_present = status->signal_strength >= 45; 391 392 if (strcmp(status->lock_str, "none") != 0) { 393 if (status->lock_str[0] == '(') { 394 status->lock_unsupported = TRUE; 395 } else { 396 status->lock_supported = TRUE; 397 } 398 } 399 123 400 return 1; 124 401 } 125 402 … … 151 428 return hdhomerun_control_get(hd->cs, name, pfilter, NULL); 152 429 } 153 430 154 int hdhomerun_device_get_tuner_program(struct hdhomerun_device_t *hd, uint16_t *pprogram_number)431 int hdhomerun_device_get_tuner_program(struct hdhomerun_device_t *hd, char **pprogram) 155 432 { 156 433 char name[32]; 157 434 sprintf(name, "/tuner%u/program", hd->tuner); 435 return hdhomerun_control_get(hd->cs, name, pprogram, NULL); 436 } 158 437 159 char *program_str; 160 int ret = hdhomerun_control_get(hd->cs, name, &program_str, NULL); 438 int hdhomerun_device_get_tuner_target(struct hdhomerun_device_t *hd, char **ptarget) 439 { 440 char name[32]; 441 sprintf(name, "/tuner%u/target", hd->tuner); 442 return hdhomerun_control_get(hd->cs, name, ptarget, NULL); 443 } 444 445 int hdhomerun_device_get_tuner_plotsample(struct hdhomerun_device_t *hd, struct hdhomerun_plotsample_t **psamples, size_t *pcount) 446 { 447 char name[32]; 448 sprintf(name, "/tuner%u/plotsample", hd->tuner); 449 450 char *result; 451 int ret = hdhomerun_control_get(hd->cs, name, &result, NULL); 161 452 if (ret <= 0) { 162 453 return ret; 163 454 } 164 455 165 *pprogram_number = (uint16_t)atol(program_str); 456 struct hdhomerun_plotsample_t *samples = (struct hdhomerun_plotsample_t *)result; 457 *psamples = samples; 458 size_t count = 0; 459 460 while (1) { 461 char *ptr = strchr(result, ' '); 462 if (!ptr) { 463 break; 464 } 465 *ptr++ = 0; 466 467 unsigned long raw; 468 if (sscanf(result, "%lx", &raw) != 1) { 469 break; 470 } 471 472 uint16_t real = (raw >> 12) & 0x0FFF; 473 if (real & 0x0800) { 474 real |= 0xF000; 475 } 476 477 uint16_t imag = (raw >> 0) & 0x0FFF; 478 if (imag & 0x0800) { 479 imag |= 0xF000; 480 } 481 482 samples->real = (int16_t)real; 483 samples->imag = (int16_t)imag; 484 samples++; 485 count++; 486 487 result = ptr; 488 } 489 490 *pcount = count; 166 491 return 1; 167 492 } 168 493 169 int hdhomerun_device_get_tuner_ target(struct hdhomerun_device_t *hd, char **ptarget)494 int hdhomerun_device_get_tuner_lockkey_owner(struct hdhomerun_device_t *hd, char **powner) 170 495 { 171 496 char name[32]; 172 sprintf(name, "/tuner%u/ target", hd->tuner);173 return hdhomerun_control_get(hd->cs, name, p target, NULL);497 sprintf(name, "/tuner%u/lockkey", hd->tuner); 498 return hdhomerun_control_get(hd->cs, name, powner, NULL); 174 499 } 175 500 176 501 int hdhomerun_device_get_ir_target(struct hdhomerun_device_t *hd, char **ptarget) … … 178 503 return hdhomerun_control_get(hd->cs, "/ir/target", ptarget, NULL); 179 504 } 180 505 506 int hdhomerun_device_get_lineup_location(struct hdhomerun_device_t *hd, char **plocation) 507 { 508 return hdhomerun_control_get(hd->cs, "/lineup/location", plocation, NULL); 509 } 510 181 511 int hdhomerun_device_get_version(struct hdhomerun_device_t *hd, char **pversion_str, uint32_t *pversion_num) 182 512 { 183 513 char *version_str; … … 206 536 { 207 537 char name[32]; 208 538 sprintf(name, "/tuner%u/channel", hd->tuner); 209 return hdhomerun_control_set (hd->cs, name, channel, NULL, NULL);539 return hdhomerun_control_set_with_lockkey(hd->cs, name, channel, hd->lockkey, NULL, NULL); 210 540 } 211 541 212 542 int hdhomerun_device_set_tuner_channelmap(struct hdhomerun_device_t *hd, const char *channelmap) 213 543 { 214 544 char name[32]; 215 545 sprintf(name, "/tuner%u/channelmap", hd->tuner); 216 return hdhomerun_control_set (hd->cs, name, channelmap, NULL, NULL);546 return hdhomerun_control_set_with_lockkey(hd->cs, name, channelmap, hd->lockkey, NULL, NULL); 217 547 } 218 548 219 549 int hdhomerun_device_set_tuner_filter(struct hdhomerun_device_t *hd, const char *filter) 220 550 { 221 551 char name[32]; 222 552 sprintf(name, "/tuner%u/filter", hd->tuner); 223 return hdhomerun_control_set (hd->cs, name, filter, NULL, NULL);553 return hdhomerun_control_set_with_lockkey(hd->cs, name, filter, hd->lockkey, NULL, NULL); 224 554 } 225 555 226 int hdhomerun_device_set_tuner_program(struct hdhomerun_device_t *hd, uint16_t program_number)556 static int hdhomerun_device_set_tuner_filter_by_array_append(char **pptr, char *end, uint16_t range_begin, uint16_t range_end) 227 557 { 228 char name[32], value[32]; 558 char *ptr = *pptr; 559 560 size_t available = end - ptr; 561 size_t required; 562 563 if (range_begin == range_end) { 564 required = snprintf(ptr, available, "0x%04x ", range_begin) + 1; 565 } else { 566 required = snprintf(ptr, available, "0x%04x-0x%04x ", range_begin, range_end) + 1; 567 } 568 569 if (required > available) { 570 return FALSE; 571 } 572 573 *pptr = strchr(ptr, 0); 574 return TRUE; 575 } 576 577 int hdhomerun_device_set_tuner_filter_by_array(struct hdhomerun_device_t *hd, unsigned char filter_array[0x2000]) 578 { 579 char filter[1024]; 580 char *ptr = filter; 581 char *end = filter + sizeof(filter); 582 583 uint16_t range_begin = 0xFFFF; 584 uint16_t range_end = 0xFFFF; 585 586 uint16_t i; 587 for (i = 0; i <= 0x1FFF; i++) { 588 if (!filter_array[i]) { 589 if (range_begin == 0xFFFF) { 590 continue; 591 } 592 if (!hdhomerun_device_set_tuner_filter_by_array_append(&ptr, end, range_begin, range_end)) { 593 return 0; 594 } 595 range_begin = 0xFFFF; 596 range_end = 0xFFFF; 597 continue; 598 } 599 600 if (range_begin == 0xFFFF) { 601 range_begin = i; 602 range_end = i; 603 continue; 604 } 605 606 range_end = i; 607 } 608 609 if (range_begin != 0xFFFF) { 610 if (!hdhomerun_device_set_tuner_filter_by_array_append(&ptr, end, range_begin, range_end)) { 611 return 0; 612 } 613 } 614 615 /* Remove trailing space. */ 616 if (ptr > filter) { 617 ptr--; 618 } 619 *ptr = 0; 620 621 return hdhomerun_device_set_tuner_filter(hd, filter); 622 } 623 624 int hdhomerun_device_set_tuner_program(struct hdhomerun_device_t *hd, const char *program) 625 { 626 char name[32]; 229 627 sprintf(name, "/tuner%u/program", hd->tuner); 230 sprintf(value, "%u", program_number); 231 return hdhomerun_control_set(hd->cs, name, value, NULL, NULL); 628 return hdhomerun_control_set_with_lockkey(hd->cs, name, program, hd->lockkey, NULL, NULL); 232 629 } 233 630 234 int hdhomerun_device_set_tuner_target(struct hdhomerun_device_t *hd, c har *target)631 int hdhomerun_device_set_tuner_target(struct hdhomerun_device_t *hd, const char *target) 235 632 { 236 633 char name[32]; 237 634 sprintf(name, "/tuner%u/target", hd->tuner); 238 return hdhomerun_control_set (hd->cs, name, target, NULL, NULL);635 return hdhomerun_control_set_with_lockkey(hd->cs, name, target, hd->lockkey, NULL, NULL); 239 636 } 240 637 241 static int hdhomerun_device_set_tuner_target_to_local(struct hdhomerun_device_t *hd)638 int hdhomerun_device_set_tuner_target_to_local_protocol(struct hdhomerun_device_t *hd, const char *protocol) 242 639 { 640 /* Create video socket. */ 641 hdhomerun_device_get_video_sock(hd); 642 if (!hd->vs) { 643 return -1; 644 } 645 646 /* Set target. */ 243 647 char target[64]; 244 648 uint32_t local_ip = hdhomerun_control_get_local_addr(hd->cs); 245 649 uint16_t local_port = hdhomerun_video_get_local_port(hd->vs); 246 sprintf(target, "%u.%u.%u.%u:%u", 650 sprintf(target, "%s://%u.%u.%u.%u:%u", 651 protocol, 247 652 (unsigned int)(local_ip >> 24) & 0xFF, (unsigned int)(local_ip >> 16) & 0xFF, 248 653 (unsigned int)(local_ip >> 8) & 0xFF, (unsigned int)(local_ip >> 0) & 0xFF, 249 654 (unsigned int)local_port … … 252 657 return hdhomerun_device_set_tuner_target(hd, target); 253 658 } 254 659 660 int hdhomerun_device_set_tuner_target_to_local(struct hdhomerun_device_t *hd) 661 { 662 return hdhomerun_device_set_tuner_target_to_local_protocol(hd, HDHOMERUN_TARGET_PROTOCOL_UDP); 663 } 664 255 665 int hdhomerun_device_set_ir_target(struct hdhomerun_device_t *hd, const char *target) 256 666 { 257 667 return hdhomerun_control_set(hd->cs, "/ir/target", target, NULL, NULL); 258 668 } 259 669 670 int hdhomerun_device_set_lineup_location(struct hdhomerun_device_t *hd, const char *location) 671 { 672 return hdhomerun_control_set(hd->cs, "/lineup/location", location, NULL, NULL); 673 } 674 260 675 int hdhomerun_device_get_var(struct hdhomerun_device_t *hd, const char *name, char **pvalue, char **perror) 261 676 { 262 677 return hdhomerun_control_get(hd->cs, name, pvalue, perror); … … 264 679 265 680 int hdhomerun_device_set_var(struct hdhomerun_device_t *hd, const char *name, const char *value, char **pvalue, char **perror) 266 681 { 267 return hdhomerun_control_set (hd->cs, name, value, pvalue, perror);682 return hdhomerun_control_set_with_lockkey(hd->cs, name, value, hd->lockkey, pvalue, perror); 268 683 } 269 684 270 int hdhomerun_device_ stream_start(struct hdhomerun_device_t *hd)685 int hdhomerun_device_tuner_lockkey_request(struct hdhomerun_device_t *hd, char **perror) 271 686 { 272 /* Create video socket. */ 273 hdhomerun_device_get_video_sock(hd); 274 if (!hd->vs) { 275 return -1; 687 uint32_t new_lockkey = (uint32_t)getcurrenttime(); 688 689 char name[32]; 690 sprintf(name, "/tuner%u/lockkey", hd->tuner); 691 692 char new_lockkey_str[64]; 693 sprintf(new_lockkey_str, "%u", (unsigned int)new_lockkey); 694 695 int ret = hdhomerun_control_set_with_lockkey(hd->cs, name, new_lockkey_str, hd->lockkey, NULL, perror); 696 if (ret <= 0) { 697 hd->lockkey = 0; 698 return ret; 276 699 } 277 700 701 hd->lockkey = new_lockkey; 702 return ret; 703 } 704 705 int hdhomerun_device_tuner_lockkey_release(struct hdhomerun_device_t *hd) 706 { 707 if (hd->lockkey == 0) { 708 return 1; 709 } 710 711 char name[32]; 712 sprintf(name, "/tuner%u/lockkey", hd->tuner); 713 int ret = hdhomerun_control_set_with_lockkey(hd->cs, name, "none", hd->lockkey, NULL, NULL); 714 715 hd->lockkey = 0; 716 return ret; 717 } 718 719 int hdhomerun_device_tuner_lockkey_force(struct hdhomerun_device_t *hd) 720 { 721 char name[32]; 722 sprintf(name, "/tuner%u/lockkey", hd->tuner); 723 int ret = hdhomerun_control_set(hd->cs, name, "force", NULL, NULL); 724 725 hd->lockkey = 0; 726 return ret; 727 } 728 729 void hdhomerun_device_tuner_lockkey_use_value(struct hdhomerun_device_t *hd, uint32_t lockkey) 730 { 731 hd->lockkey = lockkey; 732 } 733 734 int hdhomerun_device_wait_for_lock(struct hdhomerun_device_t *hd, struct hdhomerun_tuner_status_t *status) 735 { 736 /* Delay for SS reading to be valid (signal present). */ 737 msleep(250); 738 739 /* Wait for up to 2.5 seconds for lock. */ 740 uint64_t timeout = getcurrenttime() + 2500; 741 while (1) { 742 /* Get status to check for lock. Quality numbers will not be valid yet. */ 743 int ret = hdhomerun_device_get_tuner_status(hd, NULL, status); 744 if (ret <= 0) { 745 return ret; 746 } 747 748 if (!status->signal_present) { 749 return 1; 750 } 751 if (status->lock_supported || status->lock_unsupported) { 752 return 1; 753 } 754 755 if (getcurrenttime() >= timeout) { 756 return 1; 757 } 758 759 msleep(250); 760 } 761 } 762 763 int hdhomerun_device_stream_start(struct hdhomerun_device_t *hd) 764 { 278 765 /* Set target. */ 279 int ret = hdhomerun_device_s et_tuner_target_to_local(hd);766 int ret = hdhomerun_device_stream_refresh_target(hd); 280 767 if (ret <= 0) { 281 768 return ret; 282 769 } 283 770 284 771 /* Flush video buffer. */ 285 usleep(64000);772 msleep(64); 286 773 hdhomerun_video_flush(hd->vs); 287 774 288 775 /* Success. */ 289 776 return 1; 290 777 } 291 778 779 int hdhomerun_device_stream_refresh_target(struct hdhomerun_device_t *hd) 780 { 781 int ret = hdhomerun_device_set_tuner_target_to_local_protocol(hd, HDHOMERUN_TARGET_PROTOCOL_RTP); 782 if (ret <= 0) 783 ret = hdhomerun_device_set_tuner_target_to_local_protocol(hd, HDHOMERUN_TARGET_PROTOCOL_UDP); 784 return ret; 785 } 786 292 787 uint8_t *hdhomerun_device_stream_recv(struct hdhomerun_device_t *hd, size_t max_size, size_t *pactual_size) 293 788 { 789 if (!hd->vs) { 790 return NULL; 791 } 294 792 return hdhomerun_video_recv(hd->vs, max_size, pactual_size); 295 793 } 296 794 795 void hdhomerun_device_stream_flush(struct hdhomerun_device_t *hd) 796 { 797 hdhomerun_video_flush(hd->vs); 798 } 799 297 800 void hdhomerun_device_stream_stop(struct hdhomerun_device_t *hd) 298 801 { 299 802 hdhomerun_device_set_tuner_target(hd, "none"); 300 803 } 301 804 805 int hdhomerun_device_channelscan_init(struct hdhomerun_device_t *hd, const char *channelmap) 806 { 807 if (hd->scan) { 808 channelscan_destroy(hd->scan); 809 } 810 811 hd->scan = channelscan_create(hd, channelmap); 812 if (!hd->scan) { 813 return -1; 814 } 815 816 return 1; 817 } 818 819 int hdhomerun_device_channelscan_advance(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result) 820 { 821 if (!hd->scan) { 822 return 0; 823 } 824 825 int ret = channelscan_advance(hd->scan, result); 826 if (ret <= 0) { 827 channelscan_destroy(hd->scan); 828 hd->scan = NULL; 829 } 830 831 return ret; 832 } 833 834 int hdhomerun_device_channelscan_detect(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result) 835 { 836 if (!hd->scan) { 837 return 0; 838 } 839 840 int ret = channelscan_detect(hd->scan, result); 841 if (ret <= 0) { 842 channelscan_destroy(hd->scan); 843 hd->scan = NULL; 844 } 845 846 return ret; 847 } 848 849 uint8_t hdhomerun_device_channelscan_get_progress(struct hdhomerun_device_t *hd) 850 { 851 if (!hd->scan) { 852 return 0; 853 } 854 855 return channelscan_get_progress(hd->scan); 856 } 857 302 858 int hdhomerun_device_firmware_version_check(struct hdhomerun_device_t *hd, uint32_t features) 303 859 { 304 860 uint32_t version; … … 306 862 return -1; 307 863 } 308 864 309 if (version >= 20061213) {310 return 1;865 if (version < 20070219) { 866 return 0; 311 867 } 312 868 313 return 0;869 return 1; 314 870 } 315 871 872 const char *hdhomerun_device_get_model_str(struct hdhomerun_device_t *hd) 873 { 874 if (*hd->model) { 875 return hd->model; 876 } 877 878 char *model_str; 879 int ret = hdhomerun_control_get(hd->cs, "/sys/model", &model_str, NULL); 880 if (ret < 0) { 881 return NULL; 882 } 883 if (ret == 0) { 884 model_str = "hdhomerun_atsc"; 885 } 886 887 strncpy(hd->model, model_str, sizeof(hd->model) - 1); 888 hd->model[sizeof(hd->model) - 1] = 0; 889 890 return hd->model; 891 } 892 316 893 int hdhomerun_device_upgrade(struct hdhomerun_device_t *hd, FILE *upgrade_file) 317 894 { 895 hdhomerun_control_set(hd->cs, "/tuner0/lockkey", "force", NULL, NULL); 318 896 hdhomerun_control_set(hd->cs, "/tuner0/channel", "none", NULL, NULL); 897 898 hdhomerun_control_set(hd->cs, "/tuner1/lockkey", "force", NULL, NULL); 319 899 hdhomerun_control_set(hd->cs, "/tuner1/channel", "none", NULL, NULL); 900 320 901 return hdhomerun_control_upgrade(hd->cs, upgrade_file); 321 902 } 903 904 void hdhomerun_device_debug_print_video_stats(struct hdhomerun_device_t *hd) 905 { 906 if (!hdhomerun_debug_enabled(hd->dbg)) { 907 return; 908 } 909 910 char name[32]; 911 sprintf(name, "/tuner%u/debug", hd->tuner); 912 913 char *debug_str; 914 char *error_str; 915 int ret = hdhomerun_control_get(hd->cs, name, &debug_str, &error_str); 916 if (ret < 0) { 917 hdhomerun_debug_printf(hd->dbg, "video dev: communication error getting debug stats\n"); 918 return; 919 } 920 921 if (error_str) { 922 hdhomerun_debug_printf(hd->dbg, "video dev: %s\n", error_str); 923 } else { 924 hdhomerun_debug_printf(hd->dbg, "video dev: %s\n", debug_str); 925 } 926 927 if (hd->vs) { 928 hdhomerun_video_debug_print_stats(hd->vs); 929 } 930 } 931 932 void hdhomerun_device_get_video_stats(struct hdhomerun_device_t *hd, struct hdhomerun_video_stats_t *stats) 933 { 934 hdhomerun_video_get_stats(hd->vs, stats); 935 } -
libs/libmythtv/hdhomerun/hdhomerun_channels.h
1 /* 2 * hdhomerun_channels.h 3 * 4 * Copyright © 2007-2008 Silicondust Engineering Ltd. <www.silicondust.com>. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 3 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 * 19 * As a special exception to the GNU Lesser General Public License, 20 * you may link, statically or dynamically, an application with a 21 * publicly distributed version of the Library to produce an 22 * executable file containing portions of the Library, and 23 * distribute that executable file under terms of your choice, 24 * without any of the additional requirements listed in clause 4 of 25 * the GNU Lesser General Public License. 26 * 27 * By "a publicly distributed version of the Library", we mean 28 * either the unmodified Library as distributed by Silicondust, or a 29 * modified version of the Library that is distributed under the 30 * conditions defined in the GNU Lesser General Public License. 31 */ 32 33 #ifdef __cplusplus 34 extern "C" { 35 #endif 36 37 struct hdhomerun_channel_entry_t; 38 struct hdhomerun_channel_list_t; 39 40 extern LIBTYPE const char *hdhomerun_channelmap_convert_countrycode_to_channelmap_prefix(const char *countrycode); 41 extern LIBTYPE const char *hdhomerun_channelmap_get_channelmap_scan_group(const char *channelmap); 42 43 extern LIBTYPE uint8_t hdhomerun_channel_entry_channel_number(struct hdhomerun_channel_entry_t *entry); 44 extern LIBTYPE uint32_t hdhomerun_channel_entry_frequency(struct hdhomerun_channel_entry_t *entry); 45 extern LIBTYPE const char *hdhomerun_channel_entry_name(struct hdhomerun_channel_entry_t *entry); 46 47 extern LIBTYPE struct hdhomerun_channel_list_t *hdhomerun_channel_list_create(const char *channelmap); 48 extern LIBTYPE void hdhomerun_channel_list_destroy(struct hdhomerun_channel_list_t *channel_list); 49 50 extern LIBTYPE struct hdhomerun_channel_entry_t *hdhomerun_channel_list_first(struct hdhomerun_channel_list_t *channel_list); 51 extern LIBTYPE struct hdhomerun_channel_entry_t *hdhomerun_channel_list_last(struct hdhomerun_channel_list_t *channel_list); 52 extern LIBTYPE struct hdhomerun_channel_entry_t *hdhomerun_channel_list_next(struct hdhomerun_channel_list_t *channel_list, struct hdhomerun_channel_entry_t *entry); 53 extern LIBTYPE struct hdhomerun_channel_entry_t *hdhomerun_channel_list_prev(struct hdhomerun_channel_list_t *channel_list, struct hdhomerun_channel_entry_t *entry); 54 extern LIBTYPE uint32_t hdhomerun_channel_list_total_count(struct hdhomerun_channel_list_t *channel_list); 55 extern LIBTYPE uint32_t hdhomerun_channel_list_frequency_count(struct hdhomerun_channel_list_t *channel_list); 56 57 extern LIBTYPE uint32_t hdhomerun_channel_frequency_truncate(uint32_t frequency); 58 extern LIBTYPE uint32_t hdhomerun_channel_number_to_frequency(struct hdhomerun_channel_list_t *channel_list, uint8_t channel_number); 59 extern LIBTYPE uint8_t hdhomerun_channel_frequency_to_number(struct hdhomerun_channel_list_t *channel_list, uint32_t frequency); 60 61 #ifdef __cplusplus 62 } 63 #endif -
libs/libmythtv/hdhomerun/hdhomerun_os_windows.h
1 /* 2 * hdhomerun_os_windows.h 3 * 4 * Copyright © 2006-2008 Silicondust Engineering Ltd. <www.silicondust.com>. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 3 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 * 19 * As a special exception to the GNU Lesser General Public License, 20 * you may link, statically or dynamically, an application with a 21 * publicly distributed version of the Library to produce an 22 * executable file containing portions of the Library, and 23 * distribute that executable file under terms of your choice, 24 * without any of the additional requirements listed in clause 4 of 25 * the GNU Lesser General Public License. 26 * 27 * By "a publicly distributed version of the Library", we mean 28 * either the unmodified Library as distributed by Silicondust, or a 29 * modified version of the Library that is distributed under the 30 * conditions defined in the GNU Lesser General Public License. 31 */ 32 33 #define _WINSOCKAPI_ 34 #include <windows.h> 35 #include <winsock2.h> 36 #include <ws2tcpip.h> 37 #include <wspiapi.h> 38 #include <stdlib.h> 39 #include <stdio.h> 40 #include <stdarg.h> 41 #include <string.h> 42 #include <signal.h> 43 #include <time.h> 44 #include <sys/types.h> 45 #include <sys/timeb.h> 46 47 #if defined(DLL_IMPORT) 48 #define LIBTYPE __declspec( dllexport ) 49 #elif defined(DLL_EXPORT) 50 #define LIBTYPE __declspec( dllimport ) 51 #else 52 #define LIBTYPE 53 #endif 54 55 typedef int bool_t; 56 typedef signed __int8 int8_t; 57 typedef signed __int16 int16_t; 58 typedef signed __int32 int32_t; 59 typedef signed __int64 int64_t; 60 typedef unsigned __int8 uint8_t; 61 typedef unsigned __int16 uint16_t; 62 typedef unsigned __int32 uint32_t; 63 typedef unsigned __int64 uint64_t; 64 typedef HANDLE pthread_t; 65 typedef HANDLE pthread_mutex_t; 66 67 #define socklen_t int 68 #define close closesocket 69 #define sock_getlasterror WSAGetLastError() 70 #define sock_getlasterror_socktimeout (WSAGetLastError() == WSAETIMEDOUT) 71 #define va_copy(x, y) x = y 72 #define atoll _atoi64 73 #define strdup _strdup 74 #define strcasecmp _stricmp 75 #define snprintf _snprintf 76 #define fseeko _fseeki64 77 #define ftello _ftelli64 78 #define THREAD_FUNC_PREFIX DWORD WINAPI 79 #define SIGPIPE SIGABRT 80 81 static inline int msleep(unsigned int ms) 82 { 83 Sleep(ms); 84 return 0; 85 } 86 87 static inline int sleep(unsigned int sec) 88 { 89 Sleep(sec * 1000); 90 return 0; 91 } 92 93 static inline uint64_t getcurrenttime(void) 94 { 95 struct timeb tb; 96 ftime(&tb); 97 return ((uint64_t)tb.time * 1000) + tb.millitm; 98 } 99 100 static inline int setsocktimeout(int s, int level, int optname, uint64_t timeout) 101 { 102 int t = (int)timeout; 103 return setsockopt(s, level, optname, (char *)&t, sizeof(t)); 104 } 105 106 static inline int pthread_create(pthread_t *tid, void *attr, LPTHREAD_START_ROUTINE start, void *arg) 107 { 108 *tid = CreateThread(NULL, 0, start, arg, 0, NULL); 109 if (!*tid) { 110 return (int)GetLastError(); 111 } 112 return 0; 113 } 114 115 static inline int pthread_join(pthread_t tid, void **value_ptr) 116 { 117 while (1) { 118 DWORD ExitCode = 0; 119 if (!GetExitCodeThread(tid, &ExitCode)) { 120 return (int)GetLastError(); 121 } 122 if (ExitCode != STILL_ACTIVE) { 123 return 0; 124 } 125 } 126 } 127 128 static inline void pthread_mutex_init(pthread_mutex_t *mutex, void *attr) 129 { 130 *mutex = CreateMutex(NULL, FALSE, NULL); 131 } 132 133 static inline void pthread_mutex_lock(pthread_mutex_t *mutex) 134 { 135 WaitForSingleObject(*mutex, INFINITE); 136 } 137 138 static inline void pthread_mutex_unlock(pthread_mutex_t *mutex) 139 { 140 ReleaseMutex(*mutex); 141 } 142 143 /* 144 * The console output format should be set to UTF-8, however in XP and Vista this breaks batch file processing. 145 * Attempting to restore on exit fails to restore if the program is terminated by the user. 146 * Solution - set the output format each printf. 147 */ 148 static inline void console_vprintf(const char *fmt, va_list ap) 149 { 150 UINT cp = GetConsoleOutputCP(); 151 SetConsoleOutputCP(CP_UTF8); 152 vprintf(fmt, ap); 153 SetConsoleOutputCP(cp); 154 } 155 156 static inline void console_printf(const char *fmt, ...) 157 { 158 va_list ap; 159 va_start(ap, fmt); 160 console_vprintf(fmt, ap); 161 va_end(ap); 162 } -
libs/libmythtv/hdhomerun/hdhomerun_pkt.h
3 3 * 4 4 * Copyright © 2005-2006 Silicondust Engineering Ltd. <www.silicondust.com>. 5 5 * 6 * This library is free software; you can redistribute it and/or 6 * This library is free software; you can redistribute it and/or 7 7 * modify it under the terms of the GNU Lesser General Public 8 8 * License as published by the Free Software Foundation; either 9 * version 2.1of the License, or (at your option) any later version.9 * version 3 of the License, or (at your option) any later version. 10 10 * 11 11 * This library is distributed in the hope that it will be useful, 12 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of … … 14 14 * Lesser General Public License for more details. 15 15 * 16 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 * 19 * As a special exception to the GNU Lesser General Public License, 20 * you may link, statically or dynamically, an application with a 21 * publicly distributed version of the Library to produce an 22 * executable file containing portions of the Library, and 23 * distribute that executable file under terms of your choice, 24 * without any of the additional requirements listed in clause 4 of 25 * the GNU Lesser General Public License. 26 * 27 * By "a publicly distributed version of the Library", we mean 28 * either the unmodified Library as distributed by Silicondust, or a 29 * modified version of the Library that is distributed under the 30 * conditions defined in the GNU Lesser General Public License. 19 31 */ 20 32 #ifdef __cplusplus 21 33 extern "C" { … … 110 122 #define HDHOMERUN_DISCOVER_UDP_PORT 65001 111 123 #define HDHOMERUN_CONTROL_TCP_PORT 65001 112 124 125 #define HDHOMERUN_MAX_PACKET_SIZE 1460 126 #define HDHOMERUN_MAX_PAYLOAD_SIZE 1452 127 113 128 #define HDHOMERUN_TYPE_DISCOVER_REQ 0x0002 114 129 #define HDHOMERUN_TYPE_DISCOVER_RPY 0x0003 115 130 #define HDHOMERUN_TYPE_GETSET_REQ 0x0004 … … 121 136 #define HDHOMERUN_TAG_DEVICE_ID 0x02 122 137 #define HDHOMERUN_TAG_GETSET_NAME 0x03 123 138 #define HDHOMERUN_TAG_GETSET_VALUE 0x04 139 #define HDHOMERUN_TAG_GETSET_LOCKKEY 0x15 124 140 #define HDHOMERUN_TAG_ERROR_MESSAGE 0x05 125 141 126 142 #define HDHOMERUN_DEVICE_TYPE_WILDCARD 0xFFFFFFFF … … 129 145 130 146 #define HDHOMERUN_MIN_PEEK_LENGTH 4 131 147 132 extern uint8_t hdhomerun_read_u8(uint8_t **pptr); 133 extern uint16_t hdhomerun_read_u16(uint8_t **pptr); 134 extern uint32_t hdhomerun_read_u32(uint8_t **pptr); 135 extern size_t hdhomerun_read_var_length(uint8_t **pptr, uint8_t *end); 136 extern void hdhomerun_write_u8(uint8_t **pptr, uint8_t v); 137 extern void hdhomerun_write_u16(uint8_t **pptr, uint16_t v); 138 extern void hdhomerun_write_u32(uint8_t **pptr, uint32_t v); 139 extern void hdhomerun_write_var_length(uint8_t **pptr, size_t v); 140 extern void hdhomerun_write_crc(uint8_t **pptr, uint8_t *start); 148 struct hdhomerun_pkt_t { 149 uint8_t *pos; 150 uint8_t *start; 151 uint8_t *end; 152 uint8_t *limit; 153 uint8_t buffer[3074]; 154 }; 141 155 142 extern size_t hdhomerun_peek_packet_length(uint8_t *ptr);143 extern int hdhomerun_process_packet(uint8_t **pptr, uint8_t **pend);144 extern int hdhomerun_read_tlv(uint8_t **pptr, uint8_t *end, uint8_t *ptag, size_t *plength, uint8_t **pvalue);156 extern LIBTYPE struct hdhomerun_pkt_t *hdhomerun_pkt_create(void); 157 extern LIBTYPE void hdhomerun_pkt_destroy(struct hdhomerun_pkt_t *pkt); 158 extern LIBTYPE void hdhomerun_pkt_reset(struct hdhomerun_pkt_t *pkt); 145 159 146 extern void hdhomerun_write_discover_request(uint8_t **pptr, uint32_t device_type, uint32_t device_id); 147 extern void hdhomerun_write_get_set_request(uint8_t **pptr, const char *name, const char *value); 148 extern void hdhomerun_write_upgrade_request(uint8_t **pptr, uint32_t sequence, void *data, size_t length); 160 extern LIBTYPE uint8_t hdhomerun_pkt_read_u8(struct hdhomerun_pkt_t *pkt); 161 extern LIBTYPE uint16_t hdhomerun_pkt_read_u16(struct hdhomerun_pkt_t *pkt); 162 extern LIBTYPE uint32_t hdhomerun_pkt_read_u32(struct hdhomerun_pkt_t *pkt); 163 extern LIBTYPE size_t hdhomerun_pkt_read_var_length(struct hdhomerun_pkt_t *pkt); 164 extern LIBTYPE uint8_t *hdhomerun_pkt_read_tlv(struct hdhomerun_pkt_t *pkt, uint8_t *ptag, size_t *plength); 149 165 166 extern LIBTYPE void hdhomerun_pkt_write_u8(struct hdhomerun_pkt_t *pkt, uint8_t v); 167 extern LIBTYPE void hdhomerun_pkt_write_u16(struct hdhomerun_pkt_t *pkt, uint16_t v); 168 extern LIBTYPE void hdhomerun_pkt_write_u32(struct hdhomerun_pkt_t *pkt, uint32_t v); 169 extern LIBTYPE void hdhomerun_pkt_write_var_length(struct hdhomerun_pkt_t *pkt, size_t v); 170 extern LIBTYPE void hdhomerun_pkt_write_mem(struct hdhomerun_pkt_t *pkt, const void *mem, size_t length); 171 172 extern LIBTYPE bool_t hdhomerun_pkt_open_frame(struct hdhomerun_pkt_t *pkt, uint16_t *ptype); 173 extern LIBTYPE void hdhomerun_pkt_seal_frame(struct hdhomerun_pkt_t *pkt, uint16_t frame_type); 174 150 175 #ifdef __cplusplus 151 176 } 152 177 #endif 153 -
libs/libmythtv/hdhomerun/hdhomerun_device.h
1 1 /* 2 2 * hdhomerun_device.h 3 3 * 4 * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.4 * Copyright © 2006-2008 Silicondust Engineering Ltd. <www.silicondust.com>. 5 5 * 6 * This library is free software; you can redistribute it and/or 6 * This library is free software; you can redistribute it and/or 7 7 * modify it under the terms of the GNU Lesser General Public 8 8 * License as published by the Free Software Foundation; either 9 * version 2.1of the License, or (at your option) any later version.9 * version 3 of the License, or (at your option) any later version. 10 10 * 11 11 * This library is distributed in the hope that it will be useful, 12 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of … … 14 14 * Lesser General Public License for more details. 15 15 * 16 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 * 19 * As a special exception to the GNU Lesser General Public License, 20 * you may link, statically or dynamically, an application with a 21 * publicly distributed version of the Library to produce an 22 * executable file containing portions of the Library, and 23 * distribute that executable file under terms of your choice, 24 * without any of the additional requirements listed in clause 4 of 25 * the GNU Lesser General Public License. 26 * 27 * By "a publicly distributed version of the Library", we mean 28 * either the unmodified Library as distributed by Silicondust, or a 29 * modified version of the Library that is distributed under the 30 * conditions defined in the GNU Lesser General Public License. 19 31 */ 20 32 21 33 #ifdef __cplusplus … … 26 38 #define HDHOMERUN_DEVICE_MAX_LOCK_TO_DATA_TIME 2000 27 39 #define HDHOMERUN_DEVICE_MAX_TUNE_TO_DATA_TIME (HDHOMERUN_DEVICE_MAX_TUNE_TO_LOCK_TIME + HDHOMERUN_DEVICE_MAX_LOCK_TO_DATA_TIME) 28 40 29 struct hdhomerun_device_t; 41 #define HDHOMERUN_STATUS_COLOR_NEUTRAL 0xFFFFFFFF 42 #define HDHOMERUN_STATUS_COLOR_RED 0xFFFF0000 43 #define HDHOMERUN_STATUS_COLOR_YELLOW 0xFFFFFF00 44 #define HDHOMERUN_STATUS_COLOR_GREEN 0xFF00C000 30 45 31 struct hdhomerun_tuner_status_t { 32 char channel[32]; 33 unsigned int signal_strength; 34 unsigned int signal_to_noise_quality; 35 unsigned int symbol_error_quality; 36 uint32_t raw_bits_per_second; 37 uint32_t packets_per_second; 38 }; 46 #define HDHOMERUN_TARGET_PROTOCOL_UDP "udp" 47 #define HDHOMERUN_TARGET_PROTOCOL_RTP "rtp" 39 48 40 49 /* 41 50 * Create a device object. … … 53 62 * uint32_t device_id = 32-bit device id of device. Set to HDHOMERUN_DEVICE_ID_WILDCARD to match any device ID. 54 63 * uint32_t device_ip = IP address of device. Set to 0 to auto-detect. 55 64 * unsigned int tuner = tuner index (0 or 1). Can be changed later by calling hdhomerun_device_set_tuner. 65 * struct hdhomerun_debug_t *dbg: Pointer to debug logging object. May be NULL. 56 66 * 57 67 * Returns a pointer to the newly created device object. 58 68 * 59 69 * When no longer needed, the socket should be destroyed by calling hdhomerun_device_destroy. 70 * 71 * The hdhomerun_device_create_from_str function creates a device object from the given device_str. 72 * The device_str parameter can be any of the following forms: 73 * <device id> 74 * <device id>-<tuner index> 75 * <ip address> 76 * If the tuner index is not included in the device_str then it is set to zero. 77 * Use hdhomerun_device_set_tuner or hdhomerun_device_set_tuner_from_str to set the tuner. 78 * 79 * The hdhomerun_device_set_tuner_from_str function sets the tuner from the given tuner_str. 80 * The tuner_str parameter can be any of the following forms: 81 * <tuner index> 82 * /tuner<tuner index> 60 83 */ 61 extern struct hdhomerun_device_t *hdhomerun_device_create(uint32_t device_id, uint32_t device_ip, unsigned int tuner);62 extern void hdhomerun_device_destroy(struct hdhomerun_device_t *hd);63 extern void hdhomerun_device_set_tuner(struct hdhomerun_device_t *hd, unsigned int tuner);84 extern LIBTYPE struct hdhomerun_device_t *hdhomerun_device_create(uint32_t device_id, uint32_t device_ip, unsigned int tuner, struct hdhomerun_debug_t *dbg); 85 extern LIBTYPE struct hdhomerun_device_t *hdhomerun_device_create_from_str(const char *device_str, struct hdhomerun_debug_t *dbg); 86 extern LIBTYPE void hdhomerun_device_destroy(struct hdhomerun_device_t *hd); 64 87 65 88 /* 89 * Get the device id, ip, or tuner of the device instance. 90 */ 91 extern LIBTYPE uint32_t hdhomerun_device_get_device_id(struct hdhomerun_device_t *hd); 92 extern LIBTYPE uint32_t hdhomerun_device_get_device_ip(struct hdhomerun_device_t *hd); 93 extern LIBTYPE uint32_t hdhomerun_device_get_device_id_requested(struct hdhomerun_device_t *hd); 94 extern LIBTYPE uint32_t hdhomerun_device_get_device_ip_requested(struct hdhomerun_device_t *hd); 95 extern LIBTYPE unsigned int hdhomerun_device_get_tuner(struct hdhomerun_device_t *hd); 96 97 extern LIBTYPE void hdhomerun_device_set_device(struct hdhomerun_device_t *hd, uint32_t device_id, uint32_t device_ip); 98 extern LIBTYPE void hdhomerun_device_set_tuner(struct hdhomerun_device_t *hd, unsigned int tuner); 99 extern LIBTYPE int hdhomerun_device_set_tuner_from_str(struct hdhomerun_device_t *hd, const char *tuner_str); 100 101 /* 66 102 * Get the local machine IP address used when communicating with the device. 67 103 * 68 104 * This function is useful for determining the IP address to use with set target commands. 69 105 * 70 106 * Returns 32-bit IP address with native endianness, or 0 on error. 71 107 */ 72 extern uint32_t hdhomerun_device_get_local_machine_addr(struct hdhomerun_device_t *hd);108 extern LIBTYPE uint32_t hdhomerun_device_get_local_machine_addr(struct hdhomerun_device_t *hd); 73 109 74 110 /* 75 111 * Get operations. … … 82 118 * Returns 0 if the operation was rejected. 83 119 * Returns -1 if a communication error occurred. 84 120 */ 85 extern int hdhomerun_device_get_tuner_status(struct hdhomerun_device_t *hd, struct hdhomerun_tuner_status_t *status); 86 extern int hdhomerun_device_get_tuner_streaminfo(struct hdhomerun_device_t *hd, char **pstreaminfo); 87 extern int hdhomerun_device_get_tuner_channel(struct hdhomerun_device_t *hd, char **pchannel); 88 extern int hdhomerun_device_get_tuner_channelmap(struct hdhomerun_device_t *hd, char **pchannelmap); 89 extern int hdhomerun_device_get_tuner_filter(struct hdhomerun_device_t *hd, char **pfilter); 90 extern int hdhomerun_device_get_tuner_program(struct hdhomerun_device_t *hd, uint16_t *pprogram_number); 91 extern int hdhomerun_device_get_tuner_target(struct hdhomerun_device_t *hd, char **ptarget); 92 extern int hdhomerun_device_get_ir_target(struct hdhomerun_device_t *hd, char **ptarget); 93 extern int hdhomerun_device_get_version(struct hdhomerun_device_t *hd, char **pversion_str, uint32_t *pversion_num); 121 extern LIBTYPE int hdhomerun_device_get_tuner_status(struct hdhomerun_device_t *hd, char **pstatus_str, struct hdhomerun_tuner_status_t *status); 122 extern LIBTYPE int hdhomerun_device_get_tuner_streaminfo(struct hdhomerun_device_t *hd, char **pstreaminfo); 123 extern LIBTYPE int hdhomerun_device_get_tuner_channel(struct hdhomerun_device_t *hd, char **pchannel); 124 extern LIBTYPE int hdhomerun_device_get_tuner_channelmap(struct hdhomerun_device_t *hd, char **pchannelmap); 125 extern LIBTYPE int hdhomerun_device_get_tuner_filter(struct hdhomerun_device_t *hd, char **pfilter); 126 extern LIBTYPE int hdhomerun_device_get_tuner_program(struct hdhomerun_device_t *hd, char **pprogram); 127 extern LIBTYPE int hdhomerun_device_get_tuner_target(struct hdhomerun_device_t *hd, char **ptarget); 128 extern LIBTYPE int hdhomerun_device_get_tuner_plotsample(struct hdhomerun_device_t *hd, struct hdhomerun_plotsample_t **psamples, size_t *pcount); 129 extern LIBTYPE int hdhomerun_device_get_tuner_lockkey_owner(struct hdhomerun_device_t *hd, char **powner); 130 extern LIBTYPE int hdhomerun_device_get_ir_target(struct hdhomerun_device_t *hd, char **ptarget); 131 extern LIBTYPE int hdhomerun_device_get_lineup_location(struct hdhomerun_device_t *hd, char **plocation); 132 extern LIBTYPE int hdhomerun_device_get_version(struct hdhomerun_device_t *hd, char **pversion_str, uint32_t *pversion_num); 94 133 134 extern LIBTYPE uint32_t hdhomerun_device_get_tuner_status_ss_color(struct hdhomerun_tuner_status_t *status); 135 extern LIBTYPE uint32_t hdhomerun_device_get_tuner_status_snq_color(struct hdhomerun_tuner_status_t *status); 136 extern LIBTYPE uint32_t hdhomerun_device_get_tuner_status_seq_color(struct hdhomerun_tuner_status_t *status); 137 138 extern LIBTYPE const char *hdhomerun_device_get_model_str(struct hdhomerun_device_t *hd); 139 95 140 /* 96 141 * Set operations. 97 142 * … … 101 146 * Returns 0 if the operation was rejected. 102 147 * Returns -1 if a communication error occurred. 103 148 */ 104 extern int hdhomerun_device_set_tuner_channel(struct hdhomerun_device_t *hd, const char *channel); 105 extern int hdhomerun_device_set_tuner_channelmap(struct hdhomerun_device_t *hd, const char *channelmap); 106 extern int hdhomerun_device_set_tuner_filter(struct hdhomerun_device_t *hd, const char *filter); 107 extern int hdhomerun_device_set_tuner_program(struct hdhomerun_device_t *hd, uint16_t program_number); 108 extern int hdhomerun_device_set_tuner_target(struct hdhomerun_device_t *hd, char *target); 109 extern int hdhomerun_device_set_ir_target(struct hdhomerun_device_t *hd, const char *target); 149 extern LIBTYPE int hdhomerun_device_set_tuner_channel(struct hdhomerun_device_t *hd, const char *channel); 150 extern LIBTYPE int hdhomerun_device_set_tuner_channelmap(struct hdhomerun_device_t *hd, const char *channelmap); 151 extern LIBTYPE int hdhomerun_device_set_tuner_filter(struct hdhomerun_device_t *hd, const char *filter); 152 extern LIBTYPE int hdhomerun_device_set_tuner_filter_by_array(struct hdhomerun_device_t *hd, unsigned char filter_array[0x2000]); 153 extern LIBTYPE int hdhomerun_device_set_tuner_program(struct hdhomerun_device_t *hd, const char *program); 154 extern LIBTYPE int hdhomerun_device_set_tuner_target(struct hdhomerun_device_t *hd, const char *target); 155 extern LIBTYPE int hdhomerun_device_set_tuner_target_to_local_protocol(struct hdhomerun_device_t *hd, const char *protocol); 156 extern LIBTYPE int hdhomerun_device_set_tuner_target_to_local(struct hdhomerun_device_t *hd); 157 extern LIBTYPE int hdhomerun_device_set_ir_target(struct hdhomerun_device_t *hd, const char *target); 158 extern LIBTYPE int hdhomerun_device_set_lineup_location(struct hdhomerun_device_t *hd, const char *location); 110 159 111 160 /* 112 161 * Get/set a named control variable on the device. … … 125 174 * Returns 0 if the operation was rejected (pvalue NULL, perror set). 126 175 * Returns -1 if a communication error occurs. 127 176 */ 128 extern int hdhomerun_device_get_var(struct hdhomerun_device_t *hd, const char *name, char **pvalue, char **perror);129 extern int hdhomerun_device_set_var(struct hdhomerun_device_t *hd, const char *name, const char *value, char **pvalue, char **perror);177 extern LIBTYPE int hdhomerun_device_get_var(struct hdhomerun_device_t *hd, const char *name, char **pvalue, char **perror); 178 extern LIBTYPE int hdhomerun_device_set_var(struct hdhomerun_device_t *hd, const char *name, const char *value, char **pvalue, char **perror); 130 179 131 180 /* 181 * Tuner locking. 182 * 183 * The hdhomerun_device_tuner_lockkey_request function is used to obtain a lock 184 * or to verify that the hdhomerun_device object still holds the lock. 185 * Returns 1 if the lock request was successful and the lock was obtained. 186 * Returns 0 if the lock request was rejected. 187 * Returns -1 if a communication error occurs. 188 * 189 * The hdhomerun_device_tuner_lockkey_release function is used to release a 190 * previously held lock. If locking is used then this function must be called 191 * before destroying the hdhomerun_device object. 192 */ 193 extern LIBTYPE int hdhomerun_device_tuner_lockkey_request(struct hdhomerun_device_t *hd, char **perror); 194 extern LIBTYPE int hdhomerun_device_tuner_lockkey_release(struct hdhomerun_device_t *hd); 195 extern LIBTYPE int hdhomerun_device_tuner_lockkey_force(struct hdhomerun_device_t *hd); 196 197 /* 198 * Intended only for non persistent connections; eg, hdhomerun_config. 199 */ 200 extern LIBTYPE void hdhomerun_device_tuner_lockkey_use_value(struct hdhomerun_device_t *hd, uint32_t lockkey); 201 202 /* 203 * Wait for tuner lock after channel change. 204 * 205 * The hdhomerun_device_wait_for_lock function is used to detect/wait for a lock vs no lock indication 206 * after a channel change. 207 * 208 * It will return quickly if a lock is aquired. 209 * It will return quickly if there is no signal detected. 210 * Worst case it will time out after 1.5 seconds - the case where there is signal but no lock. 211 */ 212 extern LIBTYPE int hdhomerun_device_wait_for_lock(struct hdhomerun_device_t *hd, struct hdhomerun_tuner_status_t *status); 213 214 /* 132 215 * Stream a filtered program or the unfiltered stream. 133 216 * 134 217 * The hdhomerun_device_stream_start function initializes the process and tells the device to start streamin data. … … 144 227 * 145 228 * The hdhomerun_device_stream_stop function tells the device to stop streaming data. 146 229 */ 147 extern int hdhomerun_device_stream_start(struct hdhomerun_device_t *hd); 148 extern uint8_t *hdhomerun_device_stream_recv(struct hdhomerun_device_t *hd, size_t max_size, size_t *pactual_size); 149 extern void hdhomerun_device_stream_stop(struct hdhomerun_device_t *hd); 230 extern LIBTYPE int hdhomerun_device_stream_start(struct hdhomerun_device_t *hd); 231 extern LIBTYPE int hdhomerun_device_stream_refresh_target(struct hdhomerun_device_t *hd); 232 extern LIBTYPE uint8_t *hdhomerun_device_stream_recv(struct hdhomerun_device_t *hd, size_t max_size, size_t *pactual_size); 233 extern LIBTYPE void hdhomerun_device_stream_flush(struct hdhomerun_device_t *hd); 234 extern LIBTYPE void hdhomerun_device_stream_stop(struct hdhomerun_device_t *hd); 150 235 151 236 /* 237 * Channel scan API. 238 */ 239 extern LIBTYPE int hdhomerun_device_channelscan_init(struct hdhomerun_device_t *hd, const char *channelmap); 240 extern LIBTYPE int hdhomerun_device_channelscan_advance(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result); 241 extern LIBTYPE int hdhomerun_device_channelscan_detect(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result); 242 extern LIBTYPE uint8_t hdhomerun_device_channelscan_get_progress(struct hdhomerun_device_t *hd); 243 244 /* 152 245 * Check that the device is running the recommended firmware. 153 246 * 154 247 * uint32_t features: Reserved for future use. Set to zero. … … 157 250 * Returns 0 if th firmware does not meet the minimum requriements for all operations. 158 251 * Returns -1 if an error occurs. 159 252 */ 160 extern int hdhomerun_device_firmware_version_check(struct hdhomerun_device_t *hd, uint32_t features);253 extern LIBTYPE int hdhomerun_device_firmware_version_check(struct hdhomerun_device_t *hd, uint32_t features); 161 254 162 255 /* 163 256 * Upload new firmware to the device. … … 168 261 * Returns 0 if the upload was rejected. 169 262 * Returns -1 if an error occurs. 170 263 */ 171 extern int hdhomerun_device_upgrade(struct hdhomerun_device_t *hd, FILE *upgrade_file);264 extern LIBTYPE int hdhomerun_device_upgrade(struct hdhomerun_device_t *hd, FILE *upgrade_file); 172 265 173 266 /* 174 267 * Low level accessor functions. 175 268 */ 176 extern struct hdhomerun_control_sock_t *hdhomerun_device_get_control_sock(struct hdhomerun_device_t *hd);177 extern struct hdhomerun_video_sock_t *hdhomerun_device_get_video_sock(struct hdhomerun_device_t *hd);269 extern LIBTYPE struct hdhomerun_control_sock_t *hdhomerun_device_get_control_sock(struct hdhomerun_device_t *hd); 270 extern LIBTYPE struct hdhomerun_video_sock_t *hdhomerun_device_get_video_sock(struct hdhomerun_device_t *hd); 178 271 272 /* 273 * Debug print internal stats. 274 */ 275 extern LIBTYPE void hdhomerun_device_debug_print_video_stats(struct hdhomerun_device_t *hd); 276 extern LIBTYPE void hdhomerun_device_get_video_stats(struct hdhomerun_device_t *hd, struct hdhomerun_video_stats_t *stats); 277 179 278 #ifdef __cplusplus 180 279 } 181 280 #endif -
libs/libmythtv/hdhomerun/hdhomerun_config.c
1 1 /* 2 2 * hdhomerun_config.c 3 3 * 4 * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.4 * Copyright © 2006-2008 Silicondust Engineering Ltd. <www.silicondust.com>. 5 5 * 6 * This library is free software; you can redistribute it and/or 6 * This library is free software; you can redistribute it and/or 7 7 * modify it under the terms of the GNU Lesser General Public 8 8 * License as published by the Free Software Foundation; either 9 * version 2.1of the License, or (at your option) any later version.9 * version 3 of the License, or (at your option) any later version. 10 10 * 11 11 * This library is distributed in the hope that it will be useful, 12 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of … … 14 14 * Lesser General Public License for more details. 15 15 * 16 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 * 19 * As a special exception to the GNU Lesser General Public License, 20 * you may link, statically or dynamically, an application with a 21 * publicly distributed version of the Library to produce an 22 * executable file containing portions of the Library, and 23 * distribute that executable file under terms of your choice, 24 * without any of the additional requirements listed in clause 4 of 25 * the GNU Lesser General Public License. 26 * 27 * By "a publicly distributed version of the Library", we mean 28 * either the unmodified Library as distributed by Silicondust, or a 29 * modified version of the Library that is distributed under the 30 * conditions defined in the GNU Lesser General Public License. 19 31 */ 20 32 21 33 #include "hdhomerun.h" 22 34 35 /* 36 * The console output format should be set to UTF-8, however in XP and Vista this breaks batch file processing. 37 * Attempting to restore on exit fails to restore if the program is terminated by the user. 38 * Solution - set the output format each printf. 39 */ 40 #if defined(__WINDOWS__) 41 #define printf console_printf 42 #define vprintf console_vprintf 43 #endif 44 23 45 static const char *appname; 24 46 25 47 struct hdhomerun_device_t *hd; … … 31 53 printf("\t%s <id> get help\n", appname); 32 54 printf("\t%s <id> get <item>\n", appname); 33 55 printf("\t%s <id> set <item> <value>\n", appname); 34 printf("\t%s <id> scan <tuner> <starting channel>\n", appname); 56 printf("\t%s <id> scan <tuner> [<filename>]\n", appname); 57 printf("\t%s <id> save <tuner> <filename>\n", appname); 35 58 printf("\t%s <id> upgrade <filename>\n", appname); 36 59 return -1; 37 60 } … … 68 91 return FALSE; 69 92 } 70 93 71 static int discover_print(void)94 static uint32_t parse_ip_addr(const char *str) 72 95 { 96 unsigned long a[4]; 97 if (sscanf(str, "%lu.%lu.%lu.%lu", &a[0], &a[1], &a[2], &a[3]) != 4) { 98 return 0; 99 } 100 101 return (uint32_t)((a[0] << 24) | (a[1] << 16) | (a[2] << 8) | (a[3] << 0)); 102 } 103 104 static int discover_print(char *target_ip_str) 105 { 106 uint32_t target_ip = 0; 107 if (target_ip_str) { 108 target_ip = parse_ip_addr(target_ip_str); 109 if (target_ip == 0) { 110 fprintf(stderr, "invalid ip address: %s\n", target_ip_str); 111 return -1; 112 } 113 } 114 73 115 struct hdhomerun_discover_device_t result_list[64]; 74 int count = hdhomerun_discover_find_devices (HDHOMERUN_DEVICE_TYPE_TUNER, result_list, 64);116 int count = hdhomerun_discover_find_devices_custom(target_ip, HDHOMERUN_DEVICE_TYPE_TUNER, HDHOMERUN_DEVICE_ID_WILDCARD, result_list, 64); 75 117 if (count < 0) { 76 118 fprintf(stderr, "error sending discover request\n"); 77 119 return -1; … … 94 136 return count; 95 137 } 96 138 97 static bool_t parse_device_id_str(const char *s, uint32_t *pdevice_id, uint32_t *pdevice_ip)98 {99 unsigned long a[4];100 if (sscanf(s, "%lu.%lu.%lu.%lu", &a[0], &a[1], &a[2], &a[3]) == 4) {101 *pdevice_id = HDHOMERUN_DEVICE_ID_WILDCARD;102 *pdevice_ip = (uint32_t)((a[0] << 24) | (a[1] << 16) | (a[2] << 8) | (a[3] << 0));103 return TRUE;104 }105 106 unsigned long device_id_raw;107 if (sscanf(s, "%lx", &device_id_raw) != 1) {108 fprintf(stderr, "invalid device id: %s\n", s);109 return FALSE;110 }111 112 uint32_t device_id = (uint32_t)device_id_raw;113 if (!hdhomerun_discover_validate_device_id(device_id)) {114 fprintf(stderr, "invalid device id: %s\n", s);115 return FALSE;116 }117 118 *pdevice_id = device_id;119 *pdevice_ip = 0;120 return TRUE;121 }122 123 139 static int cmd_get(const char *item) 124 140 { 125 141 char *ret_value; … … 138 154 return 1; 139 155 } 140 156 141 static int cmd_set (const char *item, const char *value)157 static int cmd_set_internal(const char *item, const char *value) 142 158 { 143 159 char *ret_error; 144 160 if (hdhomerun_device_set_var(hd, item, value, NULL, &ret_error) < 0) { … … 154 170 return 1; 155 171 } 156 172 157 static int cmd_s treaminfo(const char *tuner_str)173 static int cmd_set(const char *item, const char *value) 158 174 { 159 fprintf(stderr, "streaminfo: use \"get /tuner<n>/streaminfo\"\n"); 160 return -1; 175 if (strcmp(value, "-") == 0) { 176 char *buffer = NULL; 177 size_t pos = 0; 178 179 while (1) { 180 buffer = (char *)realloc(buffer, pos + 1024); 181 if (!buffer) { 182 fprintf(stderr, "out of memory\n"); 183 return -1; 184 } 185 186 size_t size = fread(buffer + pos, 1, 1024, stdin); 187 pos += size; 188 189 if (size < 1024) { 190 break; 191 } 192 } 193 194 buffer[pos] = 0; 195 196 int ret = cmd_set_internal(item, buffer); 197 198 free(buffer); 199 return ret; 200 } 201 202 return cmd_set_internal(item, value); 161 203 } 162 204 163 static int cmd_scan(const char *tuner_str, const char *start_value)205 static void cmd_scan_printf(FILE *fp, const char *fmt, ...) 164 206 { 165 unsigned int tuner; 166 if (sscanf(tuner_str, "%u", &tuner) != 1) { 167 fprintf(stderr, "invalid tuner number\n"); 168 return -1; 207 va_list ap; 208 va_start(ap, fmt); 209 210 if (fp) { 211 va_list apc; 212 va_copy(apc, ap); 213 214 vfprintf(fp, fmt, apc); 215 fflush(fp); 216 217 va_end(apc); 169 218 } 170 219 171 hdhomerun_device_set_tuner(hd, tuner); 220 vprintf(fmt, ap); 221 fflush(stdout); 172 222 173 char channel_str[64]; 174 strncpy(channel_str, start_value, sizeof(channel_str)); 175 channel_str[sizeof(channel_str) - 8] = 0; 223 va_end(ap); 224 } 176 225 177 char *channel_number_ptr = strrchr(channel_str, ':'); 178 if (!channel_number_ptr){179 channel_number_ptr = channel_str;180 } else {181 channel_number_ptr++;226 static int cmd_scan(const char *tuner_str, const char *filename) 227 { 228 if (hdhomerun_device_set_tuner_from_str(hd, tuner_str) <= 0) { 229 fprintf(stderr, "invalid tuner number\n"); 230 return -1; 182 231 } 183 232 184 unsigned int channel_number = atol(channel_number_ptr);185 if ( channel_number == 0) {186 fprintf(stderr, " invalid starting channel\n");233 char *channelmap; 234 if (hdhomerun_device_get_tuner_channelmap(hd, &channelmap) <= 0) { 235 fprintf(stderr, "failed to query channelmap from device\n"); 187 236 return -1; 188 237 } 189 238 190 /* Test starting channel. */ 191 int ret = hdhomerun_device_set_tuner_channel(hd, channel_str); 192 if (ret < 0) { 193 fprintf(stderr, "communication error sending request to hdhomerun device\n"); 239 const char *channelmap_scan_group = hdhomerun_channelmap_get_channelmap_scan_group(channelmap); 240 if (!channelmap_scan_group) { 241 fprintf(stderr, "unknown channelmap '%s'\n", channelmap); 194 242 return -1; 195 243 } 196 if (ret == 0) { 197 fprintf(stderr, "invalid starting channel\n"); 244 245 if (hdhomerun_device_channelscan_init(hd, channelmap_scan_group) <= 0) { 246 fprintf(stderr, "failed to initialize channel scan\n"); 198 247 return -1; 199 248 } 200 249 201 while (1) { 202 /* Update channel value */ 203 sprintf(channel_number_ptr, "%u", channel_number); 204 205 /* Set channel. */ 206 ret = hdhomerun_device_set_tuner_channel(hd, channel_str); 207 if (ret < 0) { 208 fprintf(stderr, "communication error sending request to hdhomerun device\n"); 250 FILE *fp = NULL; 251 if (filename) { 252 fp = fopen(filename, "w"); 253 if (!fp) { 254 fprintf(stderr, "unable to create file: %s\n", filename); 209 255 return -1; 210 256 } 211 if (ret == 0) { 212 return 0; 257 } 258 259 int ret; 260 while (1) { 261 struct hdhomerun_channelscan_result_t result; 262 ret = hdhomerun_device_channelscan_advance(hd, &result); 263 if (ret <= 0) { 264 break; 213 265 } 214 266 215 /* Wait 1.5s for lock (qam auto is the slowest to lock). */ 216 usleep(HDHOMERUN_DEVICE_MAX_TUNE_TO_LOCK_TIME * 1000); 267 cmd_scan_printf(fp, "SCANNING: %lu (%s)\n", 268 result.frequency, result.channel_str 269 ); 217 270 218 /* Get status to check for signal. Quality numbers will not be valid yet. */ 219 struct hdhomerun_tuner_status_t status; 220 if (hdhomerun_device_get_tuner_status(hd, &status) < 0) { 221 fprintf(stderr, "communication error sending request to hdhomerun device\n"); 222 return -1; 271 ret = hdhomerun_device_channelscan_detect(hd, &result); 272 if (ret <= 0) { 273 break; 223 274 } 224 275 225 /* If no signal then advance to next channel. */ 226 if (status.signal_strength == 0) { 227 printf("%s: no signal\n", channel_str); 228 channel_number++; 229 continue; 276 cmd_scan_printf(fp, "LOCK: %s (ss=%u snq=%u seq=%u)\n", 277 result.status.lock_str, result.status.signal_strength, 278 result.status.signal_to_noise_quality, result.status.symbol_error_quality 279 ); 280 281 int i; 282 for (i = 0; i < result.program_count; i++) { 283 struct hdhomerun_channelscan_program_t *program = &result.programs[i]; 284 cmd_scan_printf(fp, "PROGRAM %s\n", program->program_str); 230 285 } 286 } 231 287 232 /* Wait for 2s. */ 233 usleep(HDHOMERUN_DEVICE_MAX_LOCK_TO_DATA_TIME * 1000); 288 if (fp) { 289 fclose(fp); 290 } 291 if (ret < 0) { 292 fprintf(stderr, "communication error sending request to hdhomerun device\n"); 293 } 294 return ret; 295 } 234 296 235 /* Get status to check quality numbers. */ 236 if (hdhomerun_device_get_tuner_status(hd, &status) < 0) { 237 fprintf(stderr, "communication error sending request to hdhomerun device\n"); 297 static bool_t cmd_saving = FALSE; 298 299 static void cmd_save_abort(int arg) 300 { 301 cmd_saving = FALSE; 302 } 303 304 static int cmd_save(const char *tuner_str, const char *filename) 305 { 306 if (hdhomerun_device_set_tuner_from_str(hd, tuner_str) <= 0) { 307 fprintf(stderr, "invalid tuner number\n"); 308 return -1; 309 } 310 311 FILE *fp; 312 if (strcmp(filename, "null") == 0) { 313 fp = NULL; 314 } else if (strcmp(filename, "-") == 0) { 315 fp = stdout; 316 } else { 317 fp = fopen(filename, "wb"); 318 if (!fp) { 319 fprintf(stderr, "unable to create file %s\n", filename); 238 320 return -1; 239 321 } 240 if (status.signal_strength == 0) { 241 printf("%s: no signal\n", channel_str); 242 channel_number++; 322 } 323 324 int ret = hdhomerun_device_stream_start(hd); 325 if (ret <= 0) { 326 fprintf(stderr, "unable to start stream\n"); 327 return ret; 328 } 329 330 signal(SIGINT, cmd_save_abort); 331 signal(SIGPIPE, cmd_save_abort); 332 333 struct hdhomerun_video_stats_t stats_old, stats_cur; 334 hdhomerun_device_get_video_stats(hd, &stats_old); 335 336 uint64_t next_progress = getcurrenttime() + 1000; 337 338 cmd_saving = TRUE; 339 while (cmd_saving) { 340 uint64_t loop_start_time = getcurrenttime(); 341 342 size_t actual_size; 343 uint8_t *ptr = hdhomerun_device_stream_recv(hd, VIDEO_DATA_BUFFER_SIZE_1S, &actual_size); 344 if (!ptr) { 345 msleep(64); 243 346 continue; 244 347 } 245 printf("%s: ss=%u snq=%u seq=%u\n", channel_str, status.signal_strength, status.signal_to_noise_quality, status.symbol_error_quality);246 348 247 /* Detect sub channels. */ 248 usleep(4 * 1000000); 249 char *streaminfo; 250 if (hdhomerun_device_get_tuner_streaminfo(hd, &streaminfo) <= 0) { 251 channel_number++; 252 continue; 349 if (fp) { 350 if (fwrite(ptr, 1, actual_size, fp) != actual_size) { 351 fprintf(stderr, "error writing output\n"); 352 return -1; 353 } 253 354 } 254 while (1) { 255 char *end = strchr(streaminfo, '\n'); 256 if (!end) { 257 break; 355 356 if (loop_start_time >= next_progress) { 357 next_progress += 1000; 358 if (loop_start_time >= next_progress) { 359 next_progress = loop_start_time + 1000; 258 360 } 259 361 260 *end++ = 0; 261 printf("program %s\n", streaminfo); 362 hdhomerun_device_get_video_stats(hd, &stats_cur); 262 363 263 streaminfo = end; 364 if (stats_cur.overflow_error_count > stats_old.overflow_error_count) { 365 fprintf(stderr, "o"); 366 } else if (stats_cur.network_error_count > stats_old.network_error_count) { 367 fprintf(stderr, "n"); 368 } else if (stats_cur.transport_error_count > stats_old.transport_error_count) { 369 fprintf(stderr, "t"); 370 } else if (stats_cur.sequence_error_count > stats_old.sequence_error_count) { 371 fprintf(stderr, "s"); 372 } else { 373 fprintf(stderr, "."); 374 } 375 376 stats_old = stats_cur; 377 fflush(stderr); 264 378 } 265 379 266 /* Advance to next channel. */ 267 channel_number++; 380 int32_t delay = 64 - (int32_t)(getcurrenttime() - loop_start_time); 381 if (delay <= 0) { 382 continue; 383 } 384 385 msleep(delay); 268 386 } 387 388 if (fp) { 389 fclose(fp); 390 } 391 392 hdhomerun_device_stream_stop(hd); 393 hdhomerun_device_get_video_stats(hd, &stats_cur); 394 395 fprintf(stderr, "\n"); 396 fprintf(stderr, "-- Video statistics --\n"); 397 fprintf(stderr, "%u packets received, %u overflow errors, %u network errors, %u transport errors, %u sequence errors\n", 398 (unsigned int)stats_cur.packet_count, 399 (unsigned int)stats_cur.overflow_error_count, 400 (unsigned int)stats_cur.network_error_count, 401 (unsigned int)stats_cur.transport_error_count, 402 (unsigned int)stats_cur.sequence_error_count); 403 404 return 0; 269 405 } 270 406 271 407 static int cmd_upgrade(const char *filename) … … 276 412 return -1; 277 413 } 278 414 415 printf("uploading firmware...\n"); 279 416 if (hdhomerun_device_upgrade(hd, fp) <= 0) { 280 417 fprintf(stderr, "error sending upgrade file to hdhomerun device\n"); 281 418 fclose(fp); 282 419 return -1; 283 420 } 421 sleep(2); 284 422 285 printf("upgrade complete\n"); 423 printf("upgrading firmware...\n"); 424 sleep(8); 425 426 printf("rebooting...\n"); 427 int count = 0; 428 char *version_str; 429 while (1) { 430 if (hdhomerun_device_get_version(hd, &version_str, NULL) >= 0) { 431 break; 432 } 433 434 count++; 435 if (count > 30) { 436 fprintf(stderr, "error finding device after firmware upgrade\n"); 437 fclose(fp); 438 return -1; 439 } 440 441 sleep(1); 442 } 443 444 printf("upgrade complete - now running firmware %s\n", version_str); 286 445 return 0; 287 446 } 288 447 448 static int cmd_execute(void) 449 { 450 char *ret_value; 451 char *ret_error; 452 if (hdhomerun_device_get_var(hd, "/sys/boot", &ret_value, &ret_error) < 0) { 453 fprintf(stderr, "communication error sending request to hdhomerun device\n"); 454 return -1; 455 } 456 457 if (ret_error) { 458 printf("%s\n", ret_error); 459 return 0; 460 } 461 462 char *end = ret_value + strlen(ret_value); 463 char *pos = ret_value; 464 465 while (1) { 466 if (pos >= end) { 467 break; 468 } 469 470 char *eol_r = strchr(pos, '\r'); 471 if (!eol_r) { 472 eol_r = end; 473 } 474 475 char *eol_n = strchr(pos, '\n'); 476 if (!eol_n) { 477 eol_n = end; 478 } 479 480 char *eol = min(eol_r, eol_n); 481 482 char *sep = strchr(pos, ' '); 483 if (!sep || sep > eol) { 484 pos = eol + 1; 485 continue; 486 } 487 488 *sep = 0; 489 *eol = 0; 490 491 char *item = pos; 492 char *value = sep + 1; 493 494 printf("set %s \"%s\"\n", item, value); 495 496 cmd_set_internal(item, value); 497 498 pos = eol + 1; 499 } 500 501 return 1; 502 } 503 289 504 static int main_cmd(int argc, char *argv[]) 290 505 { 291 506 if (argc < 1) { … … 294 509 295 510 char *cmd = *argv++; argc--; 296 511 512 if (contains(cmd, "key")) { 513 if (argc < 2) { 514 return help(); 515 } 516 uint32_t lockkey = strtoul(argv[0], NULL, 0); 517 hdhomerun_device_tuner_lockkey_use_value(hd, lockkey); 518 519 cmd = argv[1]; 520 argv+=2; argc-=2; 521 } 522 297 523 if (contains(cmd, "get")) { 298 524 if (argc < 1) { 299 525 return help(); … … 308 534 return cmd_set(argv[0], argv[1]); 309 535 } 310 536 311 if (contains(cmd, "s treaminfo")) {537 if (contains(cmd, "scan")) { 312 538 if (argc < 1) { 313 539 return help(); 314 540 } 315 return cmd_streaminfo(argv[0]); 541 if (argc < 2) { 542 return cmd_scan(argv[0], NULL); 543 } else { 544 return cmd_scan(argv[0], argv[1]); 545 } 316 546 } 317 547 318 if (contains(cmd, "s can")) {548 if (contains(cmd, "save")) { 319 549 if (argc < 2) { 320 550 return help(); 321 551 } 322 return cmd_s can(argv[0], argv[1]);552 return cmd_save(argv[0], argv[1]); 323 553 } 324 554 325 555 if (contains(cmd, "upgrade")) { … … 329 559 return cmd_upgrade(argv[0]); 330 560 } 331 561 562 if (contains(cmd, "execute")) { 563 return cmd_execute(); 564 } 565 332 566 return help(); 333 567 } 334 568 335 569 static int main_internal(int argc, char *argv[]) 336 570 { 337 571 #if defined(__WINDOWS__) 338 //Start pthreads 339 pthread_win32_process_attach_np(); 340 341 // Start WinSock 572 /* Initialize network socket support. */ 342 573 WORD wVersionRequested = MAKEWORD(2, 0); 343 574 WSADATA wsaData; 344 575 WSAStartup(wVersionRequested, &wsaData); … … 357 588 return help(); 358 589 } 359 590 if (contains(id_str, "discover")) { 360 return discover_print(); 591 if (argc < 1) { 592 return discover_print(NULL); 593 } else { 594 return discover_print(argv[0]); 595 } 361 596 } 362 597 363 /* Device ID. */364 uint32_t device_id, device_ip;365 if (!parse_device_id_str(id_str, &device_id, &device_ip)) {366 return -1;367 }368 369 598 /* Device object. */ 370 hd = hdhomerun_device_create (device_id, device_ip, 0);599 hd = hdhomerun_device_create_from_str(id_str, NULL); 371 600 if (!hd) { 372 fprintf(stderr, " unable to create device\n");601 fprintf(stderr, "invalid device id: %s\n", id_str); 373 602 return -1; 374 603 } 375 604 376 /* Connect to device and check firmware version. */ 377 int ret = hdhomerun_device_firmware_version_check(hd, 0); 378 if (ret < 0) { 605 /* Device ID check. */ 606 uint32_t device_id_requested = hdhomerun_device_get_device_id_requested(hd); 607 if (!hdhomerun_discover_validate_device_id(device_id_requested)) { 608 fprintf(stderr, "invalid device id: %08lX\n", (unsigned long)device_id_requested); 609 } 610 611 /* Connect to device and check model. */ 612 const char *model = hdhomerun_device_get_model_str(hd); 613 if (!model) { 379 614 fprintf(stderr, "unable to connect to device\n"); 380 615 hdhomerun_device_destroy(hd); 381 616 return -1; 382 617 } 383 if (ret == 0) {384 fprintf(stderr, "WARNING: firmware upgrade needed for all operations to function\n");385 }386 618 387 619 /* Command. */ 388 ret = main_cmd(argc, argv);620 int ret = main_cmd(argc, argv); 389 621 390 622 /* Cleanup. */ 391 623 hdhomerun_device_destroy(hd); -
libs/libmythtv/hdhomerun/hdhomerun_video.c
3 3 * 4 4 * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>. 5 5 * 6 * This library is free software; you can redistribute it and/or 6 * This library is free software; you can redistribute it and/or 7 7 * modify it under the terms of the GNU Lesser General Public 8 8 * License as published by the Free Software Foundation; either 9 * version 2.1of the License, or (at your option) any later version.9 * version 3 of the License, or (at your option) any later version. 10 10 * 11 11 * This library is distributed in the hope that it will be useful, 12 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of … … 14 14 * Lesser General Public License for more details. 15 15 * 16 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 * 19 * As a special exception to the GNU Lesser General Public License, 20 * you may link, statically or dynamically, an application with a 21 * publicly distributed version of the Library to produce an 22 * executable file containing portions of the Library, and 23 * distribute that executable file under terms of your choice, 24 * without any of the additional requirements listed in clause 4 of 25 * the GNU Lesser General Public License. 26 * 27 * By "a publicly distributed version of the Library", we mean 28 * either the unmodified Library as distributed by Silicondust, or a 29 * modified version of the Library that is distributed under the 30 * conditions defined in the GNU Lesser General Public License. 19 31 */ 20 32 21 #include "hdhomerun_os.h" 22 #include "hdhomerun_pkt.h" 23 #include "hdhomerun_video.h" 33 #include "hdhomerun.h" 24 34 25 35 struct hdhomerun_video_sock_t { 36 pthread_mutex_t lock; 26 37 uint8_t *buffer; 27 38 size_t buffer_size; 28 39 volatile size_t head; 29 40 volatile size_t tail; 30 41 size_t advance; 31 volatile bool_t running;32 42 volatile bool_t terminate; 33 43 pthread_t thread; 34 44 int sock; 45 uint32_t rtp_sequence; 46 struct hdhomerun_debug_t *dbg; 47 volatile uint32_t packet_count; 48 volatile uint32_t transport_error_count; 49 volatile uint32_t network_error_count; 50 volatile uint32_t sequence_error_count; 51 volatile uint32_t overflow_error_count; 52 volatile uint8_t sequence[0x2000]; 35 53 }; 36 54 37 static void *hdhomerun_video_thread(void *arg);55 static THREAD_FUNC_PREFIX hdhomerun_video_thread_execute(void *arg); 38 56 39 st atic bool_t hdhomerun_video_bind_sock_internal(struct hdhomerun_video_sock_t *vs, uint16_t listen_port)57 struct hdhomerun_video_sock_t *hdhomerun_video_create(uint16_t listen_port, size_t buffer_size, struct hdhomerun_debug_t *dbg) 40 58 { 41 struct sockaddr_in sock_addr;42 memset(&sock_addr, 0, sizeof(sock_addr));43 sock_addr.sin_family = AF_INET;44 sock_addr.sin_addr.s_addr = htonl(INADDR_ANY);45 sock_addr.sin_port = htons(listen_port);46 if (bind(vs->sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) {47 return FALSE;48 }49 return TRUE;50 }51 52 static bool_t hdhomerun_video_bind_sock(struct hdhomerun_video_sock_t *vs, uint16_t listen_port)53 {54 if (listen_port != 0) {55 return hdhomerun_video_bind_sock_internal(vs, listen_port);56 }57 58 #if defined(__CYGWIN__) || defined(__WINDOWS__)59 /* Windows firewall silently blocks a listening port if the port number is not explicitly given. */60 /* Workaround - pick a random port number. The port may already be in use to try multiple port numbers. */61 srand((int)getcurrenttime());62 int retry;63 for (retry = 8; retry > 0; retry--) {64 uint16_t listen_port = (uint16_t)((rand() % 32768) + 32768);65 if (hdhomerun_video_bind_sock_internal(vs, listen_port)) {66 return TRUE;67 }68 }69 return FALSE;70 #else71 return hdhomerun_video_bind_sock_internal(vs, listen_port);72 #endif73 }74 75 struct hdhomerun_video_sock_t *hdhomerun_video_create(uint16_t listen_port, size_t buffer_size)76 {77 59 /* Create object. */ 78 60 struct hdhomerun_video_sock_t *vs = (struct hdhomerun_video_sock_t *)calloc(1, sizeof(struct hdhomerun_video_sock_t)); 79 61 if (!vs) { 62 hdhomerun_debug_printf(dbg, "hdhomerun_video_create: failed to allocate video object\n"); 80 63 return NULL; 81 64 } 82 65 66 vs->dbg = dbg; 67 vs->sock = -1; 68 pthread_mutex_init(&vs->lock, NULL); 69 70 /* Reset sequence tracking. */ 71 hdhomerun_video_flush(vs); 72 83 73 /* Buffer size. */ 84 74 vs->buffer_size = (buffer_size / VIDEO_DATA_PACKET_SIZE) * VIDEO_DATA_PACKET_SIZE; 85 75 if (vs->buffer_size == 0) { 86 free(vs);87 return NULL;76 hdhomerun_debug_printf(dbg, "hdhomerun_video_create: invalid buffer size (%lu bytes)\n", (unsigned long)buffer_size); 77 goto error; 88 78 } 89 79 vs->buffer_size += VIDEO_DATA_PACKET_SIZE; 90 80 91 81 /* Create buffer. */ 92 82 vs->buffer = (uint8_t *)malloc(vs->buffer_size); 93 83 if (!vs->buffer) { 94 free(vs);95 return NULL;84 hdhomerun_debug_printf(dbg, "hdhomerun_video_create: failed to allocate buffer (%lu bytes)\n", (unsigned long)vs->buffer_size); 85 goto error; 96 86 } 97 87 98 88 /* Create socket. */ 99 89 vs->sock = (int)socket(AF_INET, SOCK_DGRAM, 0); 100 90 if (vs->sock == -1) { 101 free(vs->buffer); 102 free(vs); 103 return NULL; 91 hdhomerun_debug_printf(dbg, "hdhomerun_video_create: failed to allocate socket\n"); 92 goto error; 104 93 } 105 94 106 95 /* Expand socket buffer size. */ … … 112 101 setsocktimeout(vs->sock, SOL_SOCKET, SO_RCVTIMEO, 1000); 113 102 114 103 /* Bind socket. */ 115 if (!hdhomerun_video_bind_sock(vs, listen_port)) { 116 hdhomerun_video_destroy(vs); 117 return NULL; 104 struct sockaddr_in sock_addr; 105 memset(&sock_addr, 0, sizeof(sock_addr)); 106 sock_addr.sin_family = AF_INET; 107 sock_addr.sin_addr.s_addr = htonl(INADDR_ANY); 108 sock_addr.sin_port = htons(listen_port); 109 if (bind(vs->sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) { 110 hdhomerun_debug_printf(dbg, "hdhomerun_video_create: failed to bind socket (port %u)\n", listen_port); 111 goto error; 118 112 } 119 113 120 114 /* Start thread. */ 121 if (pthread_create(&vs->thread, NULL, &hdhomerun_video_thread , vs) != 0) {122 hdhomerun_ video_destroy(vs);123 return NULL;115 if (pthread_create(&vs->thread, NULL, &hdhomerun_video_thread_execute, vs) != 0) { 116 hdhomerun_debug_printf(dbg, "hdhomerun_video_create: failed to start thread\n"); 117 goto error; 124 118 } 125 vs->running = 1;126 119 127 120 /* Success. */ 128 121 return vs; 122 123 error: 124 if (vs->sock != -1) { 125 close(vs->sock); 126 } 127 if (vs->buffer) { 128 free(vs->buffer); 129 } 130 free(vs); 131 return NULL; 129 132 } 130 133 131 134 void hdhomerun_video_destroy(struct hdhomerun_video_sock_t *vs) 132 135 { 133 if (vs->running) { 134 vs->terminate = 1; 135 pthread_join(vs->thread, NULL); 136 } 136 vs->terminate = TRUE; 137 pthread_join(vs->thread, NULL); 138 137 139 close(vs->sock); 138 140 free(vs->buffer); 141 139 142 free(vs); 140 143 } 141 144 … … 144 147 struct sockaddr_in sock_addr; 145 148 socklen_t sockaddr_size = sizeof(sock_addr); 146 149 if (getsockname(vs->sock, (struct sockaddr*)&sock_addr, &sockaddr_size) != 0) { 150 hdhomerun_debug_printf(vs->dbg, "hdhomerun_video_get_local_port: getsockname failed (%d)\n", sock_getlasterror); 147 151 return 0; 148 152 } 153 149 154 return ntohs(sock_addr.sin_port); 150 155 } 151 156 152 int hdhomerun_video_get_sock(struct hdhomerun_video_sock_t *vs)157 static void hdhomerun_video_stats_ts_pkt(struct hdhomerun_video_sock_t *vs, uint8_t *ptr) 153 158 { 154 return vs->sock; 159 uint16_t packet_identifier = ((uint16_t)(ptr[1] & 0x1F) << 8) | (uint16_t)ptr[2]; 160 if (packet_identifier == 0x1FFF) { 161 return; 162 } 163 164 bool_t transport_error = ptr[1] >> 7; 165 if (transport_error) { 166 vs->transport_error_count++; 167 vs->sequence[packet_identifier] = 0xFF; 168 return; 169 } 170 171 uint8_t continuity_counter = ptr[3] & 0x0F; 172 uint8_t previous_sequence = vs->sequence[packet_identifier]; 173 174 if (continuity_counter == ((previous_sequence + 1) & 0x0F)) { 175 vs->sequence[packet_identifier] = continuity_counter; 176 return; 177 } 178 if (previous_sequence == 0xFF) { 179 vs->sequence[packet_identifier] = continuity_counter; 180 return; 181 } 182 if (continuity_counter == previous_sequence) { 183 return; 184 } 185 186 vs->sequence_error_count++; 187 vs->sequence[packet_identifier] = continuity_counter; 155 188 } 156 189 157 static void *hdhomerun_video_thread(void *arg)190 static void hdhomerun_video_parse_rtp(struct hdhomerun_video_sock_t *vs, struct hdhomerun_pkt_t *pkt) 158 191 { 192 pkt->pos += 2; 193 uint32_t rtp_sequence = hdhomerun_pkt_read_u16(pkt); 194 pkt->pos += 8; 195 196 if (rtp_sequence != ((vs->rtp_sequence + 1) & 0xFFFF)) { 197 if (vs->rtp_sequence != 0xFFFFFFFF) { 198 vs->network_error_count++; 199 200 /* restart pid sequence check */ 201 /* can't use memset bcs sequence is volatile */ 202 int i; 203 for (i = 0; i < sizeof(vs->sequence) / sizeof(uint8_t) ; i++) 204 vs->sequence[i] = 0xFF; 205 } 206 } 207 208 vs->rtp_sequence = rtp_sequence; 209 } 210 211 static THREAD_FUNC_PREFIX hdhomerun_video_thread_execute(void *arg) 212 { 159 213 struct hdhomerun_video_sock_t *vs = (struct hdhomerun_video_sock_t *)arg; 214 struct hdhomerun_pkt_t pkt_inst; 160 215 161 216 while (!vs->terminate) { 162 size_t head = vs->head; 217 struct hdhomerun_pkt_t *pkt = &pkt_inst; 218 hdhomerun_pkt_reset(pkt); 163 219 164 220 /* Receive. */ 165 int length = recv(vs->sock, (char *)vs->buffer + head, VIDEO_DATA_PACKET_SIZE, 0); 221 int length = recv(vs->sock, (char *)pkt->end, VIDEO_RTP_DATA_PACKET_SIZE, 0); 222 pkt->end += length; 223 224 if (length == VIDEO_RTP_DATA_PACKET_SIZE) { 225 hdhomerun_video_parse_rtp(vs, pkt); 226 length = (int)(pkt->end - pkt->pos); 227 } 228 166 229 if (length != VIDEO_DATA_PACKET_SIZE) { 167 230 if (length > 0) { 168 231 /* Data received but not valid - ignore. */ … … 172 235 /* Wait for more data. */ 173 236 continue; 174 237 } 175 vs->terminate = 1;238 vs->terminate = TRUE; 176 239 return NULL; 177 240 } 178 241 242 pthread_mutex_lock(&vs->lock); 243 244 /* Store in ring buffer. */ 245 size_t head = vs->head; 246 uint8_t *ptr = vs->buffer + head; 247 memcpy(ptr, pkt->pos, length); 248 249 /* Stats. */ 250 vs->packet_count++; 251 hdhomerun_video_stats_ts_pkt(vs, ptr + TS_PACKET_SIZE * 0); 252 hdhomerun_video_stats_ts_pkt(vs, ptr + TS_PACKET_SIZE * 1); 253 hdhomerun_video_stats_ts_pkt(vs, ptr + TS_PACKET_SIZE * 2); 254 hdhomerun_video_stats_ts_pkt(vs, ptr + TS_PACKET_SIZE * 3); 255 hdhomerun_video_stats_ts_pkt(vs, ptr + TS_PACKET_SIZE * 4); 256 hdhomerun_video_stats_ts_pkt(vs, ptr + TS_PACKET_SIZE * 5); 257 hdhomerun_video_stats_ts_pkt(vs, ptr + TS_PACKET_SIZE * 6); 258 179 259 /* Calculate new head. */ 180 260 head += length; 181 261 if (head >= vs->buffer_size) { … … 184 264 185 265 /* Check for buffer overflow. */ 186 266 if (head == vs->tail) { 267 vs->overflow_error_count++; 268 pthread_mutex_unlock(&vs->lock); 187 269 continue; 188 270 } 189 271 190 272 /* Atomic update. */ 191 273 vs->head = head; 274 275 pthread_mutex_unlock(&vs->lock); 192 276 } 193 277 194 278 return NULL; … … 196 280 197 281 uint8_t *hdhomerun_video_recv(struct hdhomerun_video_sock_t *vs, size_t max_size, size_t *pactual_size) 198 282 { 283 pthread_mutex_lock(&vs->lock); 284 199 285 size_t head = vs->head; 200 286 size_t tail = vs->tail; 201 287 … … 212 298 if (head == tail) { 213 299 vs->advance = 0; 214 300 *pactual_size = 0; 301 pthread_mutex_unlock(&vs->lock); 215 302 return NULL; 216 303 } 217 304 … … 219 306 if (size == 0) { 220 307 vs->advance = 0; 221 308 *pactual_size = 0; 309 pthread_mutex_unlock(&vs->lock); 222 310 return NULL; 223 311 } 224 312 … … 233 321 } 234 322 vs->advance = size; 235 323 *pactual_size = size; 236 return vs->buffer + tail; 324 uint8_t *result = vs->buffer + tail; 325 326 pthread_mutex_unlock(&vs->lock); 327 return result; 237 328 } 238 329 239 330 void hdhomerun_video_flush(struct hdhomerun_video_sock_t *vs) 240 331 { 241 /* Atomic update of tail. */ 332 pthread_mutex_lock(&vs->lock); 333 242 334 vs->tail = vs->head; 243 335 vs->advance = 0; 336 337 /* can't use memset bcs sequence is volatile */ 338 int i; 339 for (i = 0; i < sizeof(vs->sequence) / sizeof(uint8_t) ; i++) 340 vs->sequence[i] = 0xFF; 341 342 vs->rtp_sequence = 0xFFFFFFFF; 343 344 vs->packet_count = 0; 345 vs->transport_error_count = 0; 346 vs->network_error_count = 0; 347 vs->sequence_error_count = 0; 348 vs->overflow_error_count = 0; 349 350 pthread_mutex_unlock(&vs->lock); 244 351 } 245 352 353 void hdhomerun_video_debug_print_stats(struct hdhomerun_video_sock_t *vs) 354 { 355 struct hdhomerun_video_stats_t stats; 356 hdhomerun_video_get_stats(vs, &stats); 357 358 hdhomerun_debug_printf(vs->dbg, "video sock: pkt=%ld net=%ld te=%ld miss=%ld drop=%ld\n", 359 stats.packet_count, stats.network_error_count, 360 stats.transport_error_count, stats.sequence_error_count, 361 stats.overflow_error_count 362 ); 363 } 364 365 void hdhomerun_video_get_stats(struct hdhomerun_video_sock_t *vs, struct hdhomerun_video_stats_t *stats) 366 { 367 memset(stats, 0, sizeof(struct hdhomerun_video_stats_t)); 368 369 pthread_mutex_lock(&vs->lock); 370 371 stats->packet_count = vs->packet_count; 372 stats->network_error_count = vs->network_error_count; 373 stats->transport_error_count = vs->transport_error_count; 374 stats->sequence_error_count = vs->sequence_error_count; 375 stats->overflow_error_count = vs->overflow_error_count; 376 377 pthread_mutex_unlock(&vs->lock); 378 } -
libs/libmythtv/hdhomerun/hdhomerun_os_posix.h
1 /* 2 * hdhomerun_os_posix.h 3 * 4 * Copyright © 2006-2008 Silicondust Engineering Ltd. <www.silicondust.com>. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 3 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 * 19 * As a special exception to the GNU Lesser General Public License, 20 * you may link, statically or dynamically, an application with a 21 * publicly distributed version of the Library to produce an 22 * executable file containing portions of the Library, and 23 * distribute that executable file under terms of your choice, 24 * without any of the additional requirements listed in clause 4 of 25 * the GNU Lesser General Public License. 26 * 27 * By "a publicly distributed version of the Library", we mean 28 * either the unmodified Library as distributed by Silicondust, or a 29 * modified version of the Library that is distributed under the 30 * conditions defined in the GNU Lesser General Public License. 31 */ 32 33 #define _FILE_OFFSET_BITS 64 34 #include <stdlib.h> 35 #include <stdio.h> 36 #include <stdarg.h> 37 #include <string.h> 38 #include <unistd.h> 39 #include <errno.h> 40 #include <fcntl.h> 41 #include <sys/types.h> 42 #include <sys/socket.h> 43 #include <sys/time.h> 44 #include <sys/timeb.h> 45 #include <sys/wait.h> 46 #include <sys/signal.h> 47 #include <netinet/in.h> 48 #include <arpa/inet.h> 49 #include <netdb.h> 50 #include <pthread.h> 51 52 typedef int bool_t; 53 54 #define LIBTYPE 55 #define sock_getlasterror errno 56 #define sock_getlasterror_socktimeout (errno == EAGAIN) 57 #define console_vprintf vprintf 58 #define console_printf printf 59 #define THREAD_FUNC_PREFIX void * 60 61 static inline int msleep(unsigned int ms) 62 { 63 usleep(ms * 1000); 64 return 0; 65 } 66 67 static inline uint64_t getcurrenttime(void) 68 { 69 struct timeval t; 70 gettimeofday(&t, NULL); 71 return ((uint64_t)t.tv_sec * 1000) + (t.tv_usec / 1000); 72 } 73 74 static inline int setsocktimeout(int s, int level, int optname, uint64_t timeout) 75 { 76 struct timeval t; 77 t.tv_sec = timeout / 1000; 78 t.tv_usec = (timeout % 1000) * 1000; 79 return setsockopt(s, level, optname, (char *)&t, sizeof(t)); 80 } 81 82 #define min(a,b) (((a)<(b))?(a):(b)) 83 #define max(a,b) (((a)>(b))?(a):(b)) 84 -
libs/libmythtv/hdhomerun/hdhomerun_types.h
1 /* 2 * hdhomerun_types.h 3 * 4 * Copyright © 2008 Silicondust Engineering Ltd. <www.silicondust.com>. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 3 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 * 19 * As a special exception to the GNU Lesser General Public License, 20 * you may link, statically or dynamically, an application with a 21 * publicly distributed version of the Library to produce an 22 * executable file containing portions of the Library, and 23 * distribute that executable file under terms of your choice, 24 * without any of the additional requirements listed in clause 4 of 25 * the GNU Lesser General Public License. 26 * 27 * By "a publicly distributed version of the Library", we mean 28 * either the unmodified Library as distributed by Silicondust, or a 29 * modified version of the Library that is distributed under the 30 * conditions defined in the GNU Lesser General Public License. 31 */ 32 33 struct hdhomerun_device_t; 34 35 struct hdhomerun_tuner_status_t { 36 char channel[32]; 37 char lock_str[32]; 38 bool_t signal_present; 39 bool_t lock_supported; 40 bool_t lock_unsupported; 41 unsigned int signal_strength; 42 unsigned int signal_to_noise_quality; 43 unsigned int symbol_error_quality; 44 uint32_t raw_bits_per_second; 45 uint32_t packets_per_second; 46 }; 47 48 struct hdhomerun_channelscan_program_t { 49 char program_str[64]; 50 uint16_t program_number; 51 uint16_t virtual_major; 52 uint16_t virtual_minor; 53 uint16_t type; 54 char name[32]; 55 }; 56 57 #define HDHOMERUN_CHANNELSCAN_MAX_PROGRAM_COUNT 64 58 59 struct hdhomerun_channelscan_result_t { 60 char channel_str[64]; 61 uint32_t channelmap; 62 uint32_t frequency; 63 struct hdhomerun_tuner_status_t status; 64 int program_count; 65 struct hdhomerun_channelscan_program_t programs[HDHOMERUN_CHANNELSCAN_MAX_PROGRAM_COUNT]; 66 uint32_t pat_crc; 67 }; 68 69 struct hdhomerun_plotsample_t { 70 int16_t real; 71 int16_t imag; 72 }; -
libs/libmythtv/hdhomerun/hdhomerun_video.h
3 3 * 4 4 * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>. 5 5 * 6 * This library is free software; you can redistribute it and/or 6 * This library is free software; you can redistribute it and/or 7 7 * modify it under the terms of the GNU Lesser General Public 8 8 * License as published by the Free Software Foundation; either 9 * version 2.1of the License, or (at your option) any later version.9 * version 3 of the License, or (at your option) any later version. 10 10 * 11 11 * This library is distributed in the hope that it will be useful, 12 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of … … 14 14 * Lesser General Public License for more details. 15 15 * 16 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 * 19 * As a special exception to the GNU Lesser General Public License, 20 * you may link, statically or dynamically, an application with a 21 * publicly distributed version of the Library to produce an 22 * executable file containing portions of the Library, and 23 * distribute that executable file under terms of your choice, 24 * without any of the additional requirements listed in clause 4 of 25 * the GNU Lesser General Public License. 26 * 27 * By "a publicly distributed version of the Library", we mean 28 * either the unmodified Library as distributed by Silicondust, or a 29 * modified version of the Library that is distributed under the 30 * conditions defined in the GNU Lesser General Public License. 19 31 */ 20 32 #ifdef __cplusplus 21 33 extern "C" { … … 23 35 24 36 struct hdhomerun_video_sock_t; 25 37 38 struct hdhomerun_video_stats_t { 39 uint32_t packet_count; 40 uint32_t network_error_count; 41 uint32_t transport_error_count; 42 uint32_t sequence_error_count; 43 uint32_t overflow_error_count; 44 }; 45 26 46 #define TS_PACKET_SIZE 188 27 47 #define VIDEO_DATA_PACKET_SIZE (188 * 7) 28 48 #define VIDEO_DATA_BUFFER_SIZE_1S (20000000 / 8) 29 49 50 #define VIDEO_RTP_DATA_PACKET_SIZE ((188 * 7) + 12) 51 30 52 /* 31 53 * Create a video/data socket. 32 54 * 33 55 * uint16_t listen_port: Port number to listen on. Set to 0 to auto-select. 34 56 * size_t buffer_size: Size of receive buffer. For 1 second of buffer use VIDEO_DATA_BUFFER_SIZE_1S. 57 * struct hdhomerun_debug_t *dbg: Pointer to debug logging object. May be NULL. 35 58 * 36 59 * Returns a pointer to the newly created control socket. 37 60 * 38 61 * When no longer needed, the socket should be destroyed by calling hdhomerun_control_destroy. 39 62 */ 40 extern struct hdhomerun_video_sock_t *hdhomerun_video_create(uint16_t listen_port, size_t buffer_size);41 extern void hdhomerun_video_destroy(struct hdhomerun_video_sock_t *vs);63 extern LIBTYPE struct hdhomerun_video_sock_t *hdhomerun_video_create(uint16_t listen_port, size_t buffer_size, struct hdhomerun_debug_t *dbg); 64 extern LIBTYPE void hdhomerun_video_destroy(struct hdhomerun_video_sock_t *vs); 42 65 43 66 /* 44 67 * Get the port the socket is listening on. 45 68 * 46 69 * Returns 16-bit port with native endianness, or 0 on error. 47 70 */ 48 extern uint16_t hdhomerun_video_get_local_port(struct hdhomerun_video_sock_t *vs);71 extern LIBTYPE uint16_t hdhomerun_video_get_local_port(struct hdhomerun_video_sock_t *vs); 49 72 50 73 /* 51 * Get the low-level socket handle.52 */53 extern int hdhomerun_video_get_sock(struct hdhomerun_video_sock_t *vs);54 55 /*56 74 * Read data from buffer. 57 75 * 58 76 * size_t max_size: The maximum amount of data to be returned. … … 69 87 * The buffer is implemented as a ring buffer. It is possible for this function to return a small 70 88 * amount of data when more is available due to the wrap-around case. 71 89 */ 72 extern uint8_t *hdhomerun_video_recv(struct hdhomerun_video_sock_t *vs, size_t max_size, size_t *pactual_size);90 extern LIBTYPE uint8_t *hdhomerun_video_recv(struct hdhomerun_video_sock_t *vs, size_t max_size, size_t *pactual_size); 73 91 74 92 /* 75 93 * Flush the buffer. 76 94 */ 77 extern void hdhomerun_video_flush(struct hdhomerun_video_sock_t *vs);95 extern LIBTYPE void hdhomerun_video_flush(struct hdhomerun_video_sock_t *vs); 78 96 97 /* 98 * Debug print internal stats. 99 */ 100 extern LIBTYPE void hdhomerun_video_debug_print_stats(struct hdhomerun_video_sock_t *vs); 101 extern LIBTYPE void hdhomerun_video_get_stats(struct hdhomerun_video_sock_t *vs, struct hdhomerun_video_stats_t *stats); 102 79 103 #ifdef __cplusplus 80 104 } 81 105 #endif -
libs/libmythtv/hdhomerun/hdhomerun_channelscan.c
1 /* 2 * hdhomerun_channelscan.c 3 * 4 * Copyright © 2007-2008 Silicondust Engineering Ltd. <www.silicondust.com>. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 3 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 * 19 * As a special exception to the GNU Lesser General Public License, 20 * you may link, statically or dynamically, an application with a 21 * publicly distributed version of the Library to produce an 22 * executable file containing portions of the Library, and 23 * distribute that executable file under terms of your choice, 24 * without any of the additional requirements listed in clause 4 of 25 * the GNU Lesser General Public License. 26 * 27 * By "a publicly distributed version of the Library", we mean 28 * either the unmodified Library as distributed by Silicondust, or a 29 * modified version of the Library that is distributed under the 30 * conditions defined in the GNU Lesser General Public License. 31 */ 32 33 #include "hdhomerun.h" 34 35 struct hdhomerun_channelscan_t { 36 struct hdhomerun_device_t *hd; 37 uint32_t scanned_channels; 38 struct hdhomerun_channel_list_t *channel_list; 39 struct hdhomerun_channel_entry_t *next_channel; 40 }; 41 42 struct hdhomerun_channelscan_t *channelscan_create(struct hdhomerun_device_t *hd, const char *channelmap) 43 { 44 struct hdhomerun_channelscan_t *scan = (struct hdhomerun_channelscan_t *)calloc(1, sizeof(struct hdhomerun_channelscan_t)); 45 if (!scan) { 46 return NULL; 47 } 48 49 scan->hd = hd; 50 51 scan->channel_list = hdhomerun_channel_list_create(channelmap); 52 if (!scan->channel_list) { 53 free(scan); 54 return NULL; 55 } 56 57 scan->next_channel = hdhomerun_channel_list_last(scan->channel_list); 58 return scan; 59 } 60 61 void channelscan_destroy(struct hdhomerun_channelscan_t *scan) 62 { 63 free(scan); 64 } 65 66 static int channelscan_find_lock(struct hdhomerun_channelscan_t *scan, uint32_t frequency, struct hdhomerun_channelscan_result_t *result) 67 { 68 /* Set channel. */ 69 char channel_str[64]; 70 sprintf(channel_str, "auto:%ld", (unsigned long)frequency); 71 72 int ret = hdhomerun_device_set_tuner_channel(scan->hd, channel_str); 73 if (ret <= 0) { 74 return ret; 75 } 76 77 /* Wait for lock. */ 78 ret = hdhomerun_device_wait_for_lock(scan->hd, &result->status); 79 if (ret <= 0) { 80 return ret; 81 } 82 if (!result->status.lock_supported) { 83 return 1; 84 } 85 86 /* Wait for symbol quality = 100%. */ 87 uint64_t timeout = getcurrenttime() + 5000; 88 while (1) { 89 ret = hdhomerun_device_get_tuner_status(scan->hd, NULL, &result->status); 90 if (ret <= 0) { 91 return ret; 92 } 93 94 if (result->status.symbol_error_quality == 100) { 95 return 1; 96 } 97 98 if (getcurrenttime() >= timeout) { 99 return 1; 100 } 101 102 msleep(250); 103 } 104 } 105 106 static void channelscan_extract_name(struct hdhomerun_channelscan_program_t *program, const char *line) 107 { 108 /* Find start of name. */ 109 const char *start = strchr(line, ' '); 110 if (!start) { 111 return; 112 } 113 start++; 114 115 start = strchr(start, ' '); 116 if (!start) { 117 return; 118 } 119 start++; 120 121 /* Find end of name. */ 122 const char *end = strstr(start, " ("); 123 if (!end) { 124 end = strchr(line, 0); 125 } 126 127 if (end <= start) { 128 return; 129 } 130 131 /* Extract name. */ 132 size_t length = (size_t)(end - start); 133 if (length > sizeof(program->name) - 1) { 134 length = sizeof(program->name) - 1; 135 } 136 137 strncpy(program->name, start, length); 138 program->name[length] = 0; 139 } 140 141 static int channelscan_detect_programs(struct hdhomerun_channelscan_t *scan, struct hdhomerun_channelscan_result_t *result, bool_t *pchanged, bool_t *pincomplete) 142 { 143 *pchanged = FALSE; 144 *pincomplete = FALSE; 145 146 char *streaminfo; 147 int ret = hdhomerun_device_get_tuner_streaminfo(scan->hd, &streaminfo); 148 if (ret <= 0) { 149 return ret; 150 } 151 152 char *line = streaminfo; 153 int program_count = 0; 154 155 while (1) { 156 char *end = strchr(line, '\n'); 157 if (!end) { 158 break; 159 } 160 161 *end = 0; 162 163 unsigned long pat_crc; 164 if (sscanf(line, "crc=0x%lx", &pat_crc) == 1) { 165 result->pat_crc = pat_crc; 166 continue; 167 } 168 169 struct hdhomerun_channelscan_program_t program; 170 memset(&program, 0, sizeof(program)); 171 172 strncpy(program.program_str, line, sizeof(program.program_str)); 173 program.program_str[sizeof(program.program_str) - 1] = 0; 174 175 unsigned int program_number; 176 unsigned int virtual_major, virtual_minor; 177 if (sscanf(line, "%u: %u.%u", &program_number, &virtual_major, &virtual_minor) != 3) { 178 if (sscanf(line, "%u: %u", &program_number, &virtual_major) != 2) { 179 continue; 180 } 181 virtual_minor = 0; 182 } 183 184 program.program_number = program_number; 185 program.virtual_major = virtual_major; 186 program.virtual_minor = virtual_minor; 187 188 channelscan_extract_name(&program, line); 189 190 if (strstr(line, "(control)")) { 191 program.type = HDHOMERUN_CHANNELSCAN_PROGRAM_CONTROL; 192 } else if (strstr(line, "(encrypted)")) { 193 program.type = HDHOMERUN_CHANNELSCAN_PROGRAM_ENCRYPTED; 194 } else if (strstr(line, "(no data)")) { 195 program.type = HDHOMERUN_CHANNELSCAN_PROGRAM_NODATA; 196 *pincomplete = TRUE; 197 } else { 198 program.type = HDHOMERUN_CHANNELSCAN_PROGRAM_NORMAL; 199 if ((program.virtual_major == 0) || (program.name[0] == 0)) { 200 *pincomplete = TRUE; 201 } 202 } 203 204 if (memcmp(&result->programs[program_count], &program, sizeof(program)) != 0) { 205 memcpy(&result->programs[program_count], &program, sizeof(program)); 206 *pchanged = TRUE; 207 } 208 209 program_count++; 210 if (program_count >= HDHOMERUN_CHANNELSCAN_MAX_PROGRAM_COUNT) { 211 break; 212 } 213 214 line = end + 1; 215 } 216 217 if (program_count == 0) { 218 *pincomplete = TRUE; 219 } 220 if (result->program_count != program_count) { 221 result->program_count = program_count; 222 *pchanged = TRUE; 223 } 224 225 return 1; 226 } 227 228 int channelscan_advance(struct hdhomerun_channelscan_t *scan, struct hdhomerun_channelscan_result_t *result) 229 { 230 memset(result, 0, sizeof(struct hdhomerun_channelscan_result_t)); 231 232 struct hdhomerun_channel_entry_t *entry = scan->next_channel; 233 if (!entry) { 234 return 0; 235 } 236 237 /* Combine channels with same frequency. */ 238 result->frequency = hdhomerun_channel_entry_frequency(entry); 239 strncpy(result->channel_str, hdhomerun_channel_entry_name(entry), sizeof(result->channel_str) - 1); 240 result->channel_str[sizeof(result->channel_str) - 1] = 0; 241 242 while (1) { 243 entry = hdhomerun_channel_list_prev(scan->channel_list, entry); 244 if (!entry) { 245 scan->next_channel = NULL; 246 break; 247 } 248 249 if (hdhomerun_channel_entry_frequency(entry) != result->frequency) { 250 scan->next_channel = entry; 251 break; 252 } 253 254 char *ptr = strchr(result->channel_str, 0); 255 sprintf(ptr, ", %s", hdhomerun_channel_entry_name(entry)); 256 } 257 258 return 1; 259 } 260 261 int channelscan_detect(struct hdhomerun_channelscan_t *scan, struct hdhomerun_channelscan_result_t *result) 262 { 263 scan->scanned_channels++; 264 265 /* Find lock. */ 266 int ret = channelscan_find_lock(scan, result->frequency, result); 267 if (ret <= 0) { 268 return ret; 269 } 270 if (!result->status.lock_supported) { 271 return 1; 272 } 273 274 /* Detect programs. */ 275 result->program_count = 0; 276 277 uint64_t timeout = getcurrenttime() + 10000; 278 uint64_t complete_time = getcurrenttime() + 2000; 279 while (1) { 280 bool_t changed, incomplete; 281 ret = channelscan_detect_programs(scan, result, &changed, &incomplete); 282 if (ret <= 0) { 283 return ret; 284 } 285 286 if (changed) { 287 complete_time = getcurrenttime() + 2000; 288 } 289 290 if (!incomplete && (getcurrenttime() >= complete_time)) { 291 return 1; 292 } 293 294 if (getcurrenttime() >= timeout) { 295 return 1; 296 } 297 298 msleep(250); 299 } 300 } 301 302 uint8_t channelscan_get_progress(struct hdhomerun_channelscan_t *scan) 303 { 304 struct hdhomerun_channel_entry_t *entry = scan->next_channel; 305 if (!entry) { 306 return 100; 307 } 308 309 uint32_t channels_remaining = 1; 310 uint32_t frequency = hdhomerun_channel_entry_frequency(entry); 311 312 while (1) { 313 entry = hdhomerun_channel_list_prev(scan->channel_list, entry); 314 if (!entry) { 315 break; 316 } 317 318 if (hdhomerun_channel_entry_frequency(entry) != frequency) { 319 channels_remaining++; 320 frequency = hdhomerun_channel_entry_frequency(entry); 321 } 322 } 323 324 return scan->scanned_channels * 100 / (scan->scanned_channels + channels_remaining); 325 } -
libs/libmythtv/hdhomerun/hdhomerun_discover.c
1 1 /* 2 2 * hdhomerun_discover.c 3 3 * 4 * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.4 * Copyright © 2006-2007 Silicondust Engineering Ltd. <www.silicondust.com>. 5 5 * 6 * This library is free software; you can redistribute it and/or 6 * This library is free software; you can redistribute it and/or 7 7 * modify it under the terms of the GNU Lesser General Public 8 8 * License as published by the Free Software Foundation; either 9 * version 2.1of the License, or (at your option) any later version.9 * version 3 of the License, or (at your option) any later version. 10 10 * 11 11 * This library is distributed in the hope that it will be useful, 12 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of … … 14 14 * Lesser General Public License for more details. 15 15 * 16 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 * 19 * As a special exception to the GNU Lesser General Public License, 20 * you may link, statically or dynamically, an application with a 21 * publicly distributed version of the Library to produce an 22 * executable file containing portions of the Library, and 23 * distribute that executable file under terms of your choice, 24 * without any of the additional requirements listed in clause 4 of 25 * the GNU Lesser General Public License. 26 * 27 * By "a publicly distributed version of the Library", we mean 28 * either the unmodified Library as distributed by Silicondust, or a 29 * modified version of the Library that is distributed under the 30 * conditions defined in the GNU Lesser General Public License. 19 31 */ 20 32 21 #include "hdhomerun_os.h" 22 #include "hdhomerun_pkt.h" 23 #include "hdhomerun_discover.h" 33 #include "hdhomerun.h" 24 34 25 35 #if defined(__CYGWIN__) || defined(__WINDOWS__) 26 36 #include <windows.h> 27 #include <iptypes.h>28 37 #include <iphlpapi.h> 38 #define USE_IPHLPAPI 1 39 #else 40 #include <net/if.h> 41 #include <sys/ioctl.h> 42 #ifndef _SIZEOF_ADDR_IFREQ 43 #define _SIZEOF_ADDR_IFREQ(x) sizeof(x) 29 44 #endif 45 #endif 30 46 31 // for OSX 32 #include <unistd.h> // execl, pipe, sysconf 33 #include <sys/types.h> // waitpid 34 #include <sys/wait.h> // waitpid 47 #include <sys/param.h> // Defines BSD on FreeBSD and Mac OS X 48 #if defined(__linux__) || defined(__APPLE__) || defined(BSD) 49 # include <ifaddrs.h> 50 # define USE_IFADDRS 1 51 # include <sys/select.h> 52 #endif 35 53 54 #define HDHOMERUN_DISOCVER_MAX_SOCK_COUNT 16 55 36 56 struct hdhomerun_discover_sock_t { 37 57 int sock; 58 uint32_t local_ip; 59 uint32_t subnet_mask; 38 60 }; 39 61 40 static struct hdhomerun_discover_sock_t *hdhomerun_discover_create(void) 62 struct hdhomerun_discover_t { 63 struct hdhomerun_discover_sock_t socks[HDHOMERUN_DISOCVER_MAX_SOCK_COUNT]; 64 unsigned int sock_count; 65 struct hdhomerun_pkt_t tx_pkt; 66 struct hdhomerun_pkt_t rx_pkt; 67 }; 68 69 static bool_t hdhomerun_discover_sock_create(struct hdhomerun_discover_t *ds, uint32_t local_ip, uint32_t subnet_mask) 41 70 { 42 struct hdhomerun_discover_sock_t *ds = (struct hdhomerun_discover_sock_t *)malloc(sizeof(struct hdhomerun_discover_sock_t)); 43 if (!ds) { 44 return NULL; 71 if (ds->sock_count >= HDHOMERUN_DISOCVER_MAX_SOCK_COUNT) { 72 return FALSE; 45 73 } 46 74 47 75 /* Create socket. */ 48 ds->sock = (int)socket(AF_INET, SOCK_DGRAM, 0); 49 if (ds->sock == -1) { 50 free(ds); 51 return NULL; 76 int sock = (int)socket(AF_INET, SOCK_DGRAM, 0); 77 if (sock == -1) { 78 return FALSE; 52 79 } 53 80 54 81 /* Set timeouts. */ 55 setsocktimeout( ds->sock, SOL_SOCKET, SO_SNDTIMEO, 1000);56 setsocktimeout( ds->sock, SOL_SOCKET, SO_RCVTIMEO, 1000);82 setsocktimeout(sock, SOL_SOCKET, SO_SNDTIMEO, 1000); 83 setsocktimeout(sock, SOL_SOCKET, SO_RCVTIMEO, 1000); 57 84 58 85 /* Allow broadcast. */ 59 86 int sock_opt = 1; 60 setsockopt( ds->sock, SOL_SOCKET, SO_BROADCAST, (char *)&sock_opt, sizeof(sock_opt));87 setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&sock_opt, sizeof(sock_opt)); 61 88 62 89 /* Bind socket. */ 63 90 struct sockaddr_in sock_addr; 64 91 memset(&sock_addr, 0, sizeof(sock_addr)); 65 92 sock_addr.sin_family = AF_INET; 66 sock_addr.sin_addr.s_addr = htonl( INADDR_ANY);93 sock_addr.sin_addr.s_addr = htonl(local_ip); 67 94 sock_addr.sin_port = htons(0); 68 if (bind(ds->sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) { 69 close(ds->sock); 70 free(ds); 71 return NULL; 95 if (bind(sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) { 96 close(sock); 97 return FALSE; 72 98 } 73 99 74 /* Success. */ 75 return ds; 76 } 100 /* Write sock entry. */ 101 struct hdhomerun_discover_sock_t *dss = &ds->socks[ds->sock_count++]; 102 dss->sock = sock; 103 dss->local_ip = local_ip; 104 dss->subnet_mask = subnet_mask; 77 105 78 static void hdhomerun_discover_destroy(struct hdhomerun_discover_sock_t *ds) 79 { 80 close(ds->sock); 81 free(ds); 106 return TRUE; 82 107 } 83 108 84 static int hdhomerun_discover_send_packet(struct hdhomerun_discover_sock_t *ds, uint32_t ip_addr, uint32_t device_type, uint32_t device_id) 109 #if defined(USE_IPHLPAPI) 110 static void hdhomerun_discover_sock_detect(struct hdhomerun_discover_t *ds) 85 111 { 86 uint8_t buffer[1024];87 uint8_t *ptr = buffer;88 hdhomerun_write_discover_request(&ptr, device_type, device_id);89 90 struct sockaddr_in sock_addr;91 memset(&sock_addr, 0, sizeof(sock_addr));92 sock_addr.sin_family = AF_INET;93 sock_addr.sin_addr.s_addr = htonl(ip_addr);94 sock_addr.sin_port = htons(HDHOMERUN_DISCOVER_UDP_PORT);95 96 int length = (int)(ptr - buffer);97 if (sendto(ds->sock, (char *)buffer, (int)length, 0, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != length) {98 return -1;99 }100 101 return 0;102 }103 104 #if defined(__APPLE__)105 static int hdhomerun_discover_send_internal(struct hdhomerun_discover_sock_t *ds, unsigned long device_type, unsigned long device_id)106 {107 /* printf("Looking for 0x%lx with id 0x%lx\n", device_type, device_id); */108 int fds[2];109 if (pipe(fds) < 0)110 {111 printf("Pipe Failed\n");112 return -1;113 }114 115 pid_t child = fork();116 if (child < 0)117 {118 printf("Fork Failed\n");119 return -1;120 }121 else if (child == 0)122 {123 /* Child */124 int i = 0;125 126 /* Attach stdout to pipe */127 close(1);128 dup2(fds[1], 1);129 130 /* Close all open file descriptors except stdout/stderr */131 for (i = sysconf(_SC_OPEN_MAX) - 1; i > 2; i--)132 close(i);133 134 /* Run command */135 execl("/bin/sh", "sh", "-c", "ifconfig", NULL);136 137 /* Failed to exec */138 _exit(1); /* this exit is ok */139 }140 else141 {142 /* Parent */143 int send_count = 0;144 int status;145 FILE *fp;146 char line[1024];147 char adaptor[1024];148 149 close(fds[1]);150 151 if (waitpid(child, &status, 0) < 0)152 return -1;153 154 if (WEXITSTATUS(status))155 return -1;156 157 fp = fdopen(fds[0], "r");158 while (1)159 {160 char *ptr = NULL;161 int netmask, broadcast;162 int a,b,c,d;163 164 if (!fgets(line, sizeof(line) - 1, fp))165 {166 break;167 }168 169 line[1023] = 0;170 171 /* find ": flags" */172 ptr = strnstr(line, ": flags", 1024 - 1);173 if (ptr >= line)174 {175 /* grab adaptor before that */176 strncpy(adaptor, line, ptr-line);177 adaptor[ptr-line] = 0;178 }179 180 /* find "netmask " */181 ptr = strnstr(line, "netmask ", 1024 - 1);182 if (ptr <= line)183 continue;184 ptr += strlen("netmask ");185 sscanf(ptr, "%x", &netmask);186 187 /* find "broadcast " */188 ptr = strnstr(ptr, "broadcast ", 1024 - 1);189 if (ptr <= line)190 continue;191 ptr += strlen("broadcast ");192 sscanf(ptr, "%i.%i.%i.%i", &a, &b, &c, &d);193 broadcast = a<<24 | b<<16 | c<<8 | d;194 /*195 printf("Adaptor: '%s' 0x%08x %i.%i.%i.%i\n",196 adaptor, broadcast, a,b,c,d);197 */198 199 /* send discover packet this adaptor */200 if (hdhomerun_discover_send_packet(201 ds, broadcast, device_type, device_id) >= 0)202 {203 send_count++;204 }205 }206 207 fclose(fp); /* this closes fds[0] as well */208 209 /* printf("send_count: %i\n\n", send_count); */210 return (send_count == 0) ? -1 : 0;211 }212 }213 214 #elif defined(__CYGWIN__) || defined(__WINDOWS__)215 216 static int hdhomerun_discover_send_internal(struct hdhomerun_discover_sock_t *ds, uint32_t device_type, uint32_t device_id)217 {218 112 PIP_ADAPTER_INFO pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO)); 219 113 ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO); 220 114 … … 222 116 if (Ret != NO_ERROR) { 223 117 free(pAdapterInfo); 224 118 if (Ret != ERROR_BUFFER_OVERFLOW) { 225 return -1;119 return; 226 120 } 227 121 pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen); 228 122 Ret = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen); 229 123 if (Ret != NO_ERROR) { 230 124 free(pAdapterInfo); 231 return -1;125 return; 232 126 } 233 127 } 234 128 235 unsigned int send_count = 0;236 129 PIP_ADAPTER_INFO pAdapter = pAdapterInfo; 237 130 while (pAdapter) { 238 131 IP_ADDR_STRING *pIPAddr = &pAdapter->IpAddressList; 239 132 while (pIPAddr) { 240 uint32_t addr= ntohl(inet_addr(pIPAddr->IpAddress.String));133 uint32_t local_ip = ntohl(inet_addr(pIPAddr->IpAddress.String)); 241 134 uint32_t mask = ntohl(inet_addr(pIPAddr->IpMask.String)); 242 243 uint32_t broadcast = addr | ~mask;244 if ((broadcast == 0x00000000) || (broadcast == 0xFFFFFFFF)) {245 pIPAddr = pIPAddr->Next;246 continue;247 }248 135 249 if ( hdhomerun_discover_send_packet(ds, broadcast, device_type, device_id) <0) {136 if (local_ip == 0) { 250 137 pIPAddr = pIPAddr->Next; 251 138 continue; 252 139 } 253 140 254 send_count++; 255 141 hdhomerun_discover_sock_create(ds, local_ip, mask); 256 142 pIPAddr = pIPAddr->Next; 257 143 } 258 144 … … 260 146 } 261 147 262 148 free(pAdapterInfo); 263 264 if (send_count == 0) {265 return -1;266 }267 return 0;268 149 } 269 150 270 #el if defined(__linux__)151 #else 271 152 272 static int hdhomerun_discover_send_internal(struct hdhomerun_discover_sock_t *ds, uint32_t device_type, uint32_t device_id)153 static void hdhomerun_discover_sock_detect(struct hdhomerun_discover_t *ds) 273 154 { 274 FILE *fp = fopen("/proc/net/route", "r");275 if ( !fp) {276 return -1;155 int fd = socket(AF_INET, SOCK_DGRAM, 0); 156 if (fd == -1) { 157 return; 277 158 } 278 159 279 unsigned int send_count = 0; 280 while (1) { 281 char line[256]; 282 if (!fgets(line, sizeof(line), fp)) { 283 break; 284 } 285 line[255] = 0; 160 struct ifconf ifc; 161 uint8_t buf[8192]; 162 ifc.ifc_len = sizeof(buf); 163 ifc.ifc_buf = (char *)buf; 286 164 287 uint32_t dest; 288 uint32_t mask; 289 if (sscanf(line, "%*s %x %*x %*x %*d %*d %*d %x", &dest, &mask) != 2) { 165 memset(buf, 0, sizeof(buf)); 166 167 if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) { 168 close(fd); 169 return; 170 } 171 172 uint8_t *ptr = (uint8_t *)ifc.ifc_req; 173 uint8_t *end = (uint8_t *)&ifc.ifc_buf[ifc.ifc_len]; 174 175 while (ptr <= end) { 176 struct ifreq *ifr = (struct ifreq *)ptr; 177 ptr += _SIZEOF_ADDR_IFREQ(*ifr); 178 179 if (ioctl(fd, SIOCGIFADDR, ifr) != 0) { 290 180 continue; 291 181 } 292 dest = ntohl(dest); 293 mask = ntohl(mask); 294 295 uint32_t broadcast = dest | ~mask; 296 297 if ((broadcast == 0x00000000) || (broadcast == 0xFFFFFFFF)) { 182 struct sockaddr_in *addr_in = (struct sockaddr_in *)&(ifr->ifr_addr); 183 uint32_t local_ip = ntohl(addr_in->sin_addr.s_addr); 184 if (local_ip == 0) { 298 185 continue; 299 186 } 300 187 301 if ( hdhomerun_discover_send_packet(ds, broadcast, device_type, device_id) <0) {188 if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) { 302 189 continue; 303 190 } 191 struct sockaddr_in *mask_in = (struct sockaddr_in *)&(ifr->ifr_addr); 192 uint32_t mask = ntohl(mask_in->sin_addr.s_addr); 304 193 305 send_count++;194 hdhomerun_discover_sock_create(ds, local_ip, mask); 306 195 } 196 } 197 #endif 307 198 308 fclose(fp); 309 if (send_count == 0) { 310 return -1; 199 static struct hdhomerun_discover_t *hdhomerun_discover_create(void) 200 { 201 struct hdhomerun_discover_t *ds = (struct hdhomerun_discover_t *)calloc(1, sizeof(struct hdhomerun_discover_t)); 202 if (!ds) { 203 return NULL; 311 204 } 312 return 0; 205 206 /* Create a routable socket. */ 207 if (!hdhomerun_discover_sock_create(ds, 0, 0)) { 208 free(ds); 209 return NULL; 210 } 211 212 /* Detect & create local sockets. */ 213 hdhomerun_discover_sock_detect(ds); 214 215 /* Success. */ 216 return ds; 313 217 } 314 218 315 #else 219 static void hdhomerun_discover_destroy(struct hdhomerun_discover_t *ds) 220 { 221 unsigned int i; 222 for (i = 0; i < ds->sock_count; i++) { 223 struct hdhomerun_discover_sock_t *dss = &ds->socks[i]; 224 close(dss->sock); 225 } 316 226 317 static int hdhomerun_discover_send_internal(struct hdhomerun_discover_sock_t *ds, uint32_t device_type, uint32_t device_id) 227 free(ds); 228 } 229 230 static bool_t hdhomerun_discover_send_internal(struct hdhomerun_discover_t *ds, struct hdhomerun_discover_sock_t *dss, uint32_t target_ip, uint32_t device_type, uint32_t device_id) 318 231 { 319 return -1; 232 struct hdhomerun_pkt_t *tx_pkt = &ds->tx_pkt; 233 hdhomerun_pkt_reset(tx_pkt); 234 235 hdhomerun_pkt_write_u8(tx_pkt, HDHOMERUN_TAG_DEVICE_TYPE); 236 hdhomerun_pkt_write_var_length(tx_pkt, 4); 237 hdhomerun_pkt_write_u32(tx_pkt, device_type); 238 hdhomerun_pkt_write_u8(tx_pkt, HDHOMERUN_TAG_DEVICE_ID); 239 hdhomerun_pkt_write_var_length(tx_pkt, 4); 240 hdhomerun_pkt_write_u32(tx_pkt, device_id); 241 hdhomerun_pkt_seal_frame(tx_pkt, HDHOMERUN_TYPE_DISCOVER_REQ); 242 243 struct sockaddr_in sock_addr; 244 memset(&sock_addr, 0, sizeof(sock_addr)); 245 sock_addr.sin_family = AF_INET; 246 sock_addr.sin_addr.s_addr = htonl(target_ip); 247 sock_addr.sin_port = htons(HDHOMERUN_DISCOVER_UDP_PORT); 248 249 int length = (int)(tx_pkt->end - tx_pkt->start); 250 if (sendto(dss->sock, (char *)tx_pkt->start, length, 0, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != length) { 251 return FALSE; 252 } 253 254 return TRUE; 320 255 } 321 #endif322 256 323 static int hdhomerun_discover_send(struct hdhomerun_discover_sock_t *ds, uint32_t device_type, uint32_t device_id)257 static bool_t hdhomerun_discover_send_wildcard_ip(struct hdhomerun_discover_t *ds, uint32_t device_type, uint32_t device_id) 324 258 { 325 if (hdhomerun_discover_send_internal(ds, device_type, device_id) < 0) { 326 return hdhomerun_discover_send_packet(ds, 0xFFFFFFFF, device_type, device_id); 259 bool_t result = FALSE; 260 261 /* 262 * Send subnet broadcast using each local ip socket. 263 * This will work with multiple separate 169.254.x.x interfaces. 264 */ 265 unsigned int i; 266 for (i = 1; i < ds->sock_count; i++) { 267 struct hdhomerun_discover_sock_t *dss = &ds->socks[i]; 268 uint32_t target_ip = dss->local_ip | ~dss->subnet_mask; 269 result |= hdhomerun_discover_send_internal(ds, dss, target_ip, device_type, device_id); 327 270 } 328 return 0; 271 272 /* 273 * If no local ip sockets then fall back to sending a global broadcast letting the OS choose the interface. 274 */ 275 if (!result) { 276 struct hdhomerun_discover_sock_t *dss = &ds->socks[0]; 277 result = hdhomerun_discover_send_internal(ds, dss, 0xFFFFFFFF, device_type, device_id); 278 } 279 280 return result; 329 281 } 330 282 331 static int hdhomerun_discover_recv(struct hdhomerun_discover_sock_t *ds, struct hdhomerun_discover_device_t *result)283 static bool_t hdhomerun_discover_send_target_ip(struct hdhomerun_discover_t *ds, uint32_t target_ip, uint32_t device_type, uint32_t device_id) 332 284 { 333 struct timeval t; 334 t.tv_sec = 0; 335 t.tv_usec = 250000; 285 bool_t result = FALSE; 336 286 337 fd_set readfds; 338 FD_ZERO(&readfds); 339 FD_SET(ds->sock, &readfds); 287 /* 288 * Send targeted packet from any local ip that is in the same subnet. 289 * This will work with multiple separate 169.254.x.x interfaces. 290 */ 291 unsigned int i; 292 for (i = 1; i < ds->sock_count; i++) { 293 struct hdhomerun_discover_sock_t *dss = &ds->socks[i]; 294 if ((target_ip & dss->subnet_mask) != (dss->local_ip & dss->subnet_mask)) { 295 continue; 296 } 340 297 341 if (select(ds->sock+1, &readfds, NULL, NULL, &t) < 0) { 342 return -1; 298 result |= hdhomerun_discover_send_internal(ds, dss, target_ip, device_type, device_id); 343 299 } 344 if (!FD_ISSET(ds->sock, &readfds)) { 345 return 0; 300 301 /* 302 * If target IP does not match a local subnet then fall back to letting the OS choose the gateway interface. 303 */ 304 if (!result) { 305 struct hdhomerun_discover_sock_t *dss = &ds->socks[0]; 306 result = hdhomerun_discover_send_internal(ds, dss, target_ip, device_type, device_id); 346 307 } 347 308 348 uint8_t buffer[1024]; 309 return result; 310 } 311 312 static bool_t hdhomerun_discover_send(struct hdhomerun_discover_t *ds, uint32_t target_ip, uint32_t device_type, uint32_t device_id) 313 { 314 if (target_ip != 0) { 315 return hdhomerun_discover_send_target_ip(ds, target_ip, device_type, device_id); 316 } 317 318 return hdhomerun_discover_send_wildcard_ip(ds, device_type, device_id); 319 } 320 321 static int hdhomerun_discover_recv_internal(struct hdhomerun_discover_t *ds, struct hdhomerun_discover_sock_t *dss, struct hdhomerun_discover_device_t *result) 322 { 323 struct hdhomerun_pkt_t *rx_pkt = &ds->rx_pkt; 324 hdhomerun_pkt_reset(rx_pkt); 325 349 326 struct sockaddr_in sock_addr; 327 memset(&sock_addr, 0, sizeof(sock_addr)); 350 328 socklen_t sockaddr_size = sizeof(sock_addr); 351 int rx_length = recvfrom(ds->sock, (char *)buffer, sizeof(buffer), 0, (struct sockaddr *)&sock_addr, &sockaddr_size); 329 330 int rx_length = recvfrom(dss->sock, (char *)rx_pkt->end, (int)(rx_pkt->limit - rx_pkt->end), 0, (struct sockaddr *)&sock_addr, &sockaddr_size); 352 331 if (rx_length <= 0) { 353 332 /* Don't return error - windows machine on VPN can sometimes cause a sock error here but otherwise works. */ 354 333 return 0; 355 334 } 356 if (rx_length < HDHOMERUN_MIN_PEEK_LENGTH) { 357 return 0; 358 } 335 rx_pkt->end += rx_length; 359 336 360 size_t length = hdhomerun_peek_packet_length(buffer);361 if ( length > (size_t)rx_length) {337 uint16_t type; 338 if (hdhomerun_pkt_open_frame(rx_pkt, &type) <= 0) { 362 339 return 0; 363 340 } 364 365 uint8_t *ptr = buffer;366 uint8_t *end = buffer + length;367 int type = hdhomerun_process_packet(&ptr, &end);368 341 if (type != HDHOMERUN_TYPE_DISCOVER_RPY) { 369 342 return 0; 370 343 } … … 372 345 result->ip_addr = ntohl(sock_addr.sin_addr.s_addr); 373 346 result->device_type = 0; 374 347 result->device_id = 0; 348 375 349 while (1) { 376 350 uint8_t tag; 377 351 size_t len; 378 uint8_t * value;379 if ( hdhomerun_read_tlv(&ptr, end, &tag, &len, &value) < 0) {352 uint8_t *next = hdhomerun_pkt_read_tlv(rx_pkt, &tag, &len); 353 if (!next) { 380 354 break; 381 355 } 382 356 … … 385 359 if (len != 4) { 386 360 break; 387 361 } 388 result->device_type = hdhomerun_ read_u32(&value);362 result->device_type = hdhomerun_pkt_read_u32(rx_pkt); 389 363 break; 364 390 365 case HDHOMERUN_TAG_DEVICE_ID: 391 366 if (len != 4) { 392 367 break; 393 368 } 394 result->device_id = hdhomerun_ read_u32(&value);369 result->device_id = hdhomerun_pkt_read_u32(rx_pkt); 395 370 break; 371 396 372 default: 397 373 break; 398 374 } 375 376 rx_pkt->pos = next; 399 377 } 400 378 401 379 return 1; 402 380 } 403 381 404 static struct hdhomerun_discover_device_t *hdhomerun_discover_find_in_list(struct hdhomerun_discover_device_t result_list[], int count, uint32_t device_id)382 static int hdhomerun_discover_recv(struct hdhomerun_discover_t *ds, struct hdhomerun_discover_device_t *result) 405 383 { 384 struct timeval t; 385 t.tv_sec = 0; 386 t.tv_usec = 250000; 387 388 fd_set readfds; 389 FD_ZERO(&readfds); 390 int max_sock = -1; 391 392 unsigned int i; 393 for (i = 0; i < ds->sock_count; i++) { 394 struct hdhomerun_discover_sock_t *dss = &ds->socks[i]; 395 FD_SET(dss->sock, &readfds); 396 if (dss->sock > max_sock) { 397 max_sock = dss->sock; 398 } 399 } 400 401 if (select(max_sock+1, &readfds, NULL, NULL, &t) < 0) { 402 return -1; 403 } 404 405 for (i = 0; i < ds->sock_count; i++) { 406 struct hdhomerun_discover_sock_t *dss = &ds->socks[i]; 407 if (!FD_ISSET(dss->sock, &readfds)) { 408 continue; 409 } 410 411 if (hdhomerun_discover_recv_internal(ds, dss, result) <= 0) { 412 continue; 413 } 414 415 return 1; 416 } 417 418 return 0; 419 } 420 421 static struct hdhomerun_discover_device_t *hdhomerun_discover_find_in_list(struct hdhomerun_discover_device_t result_list[], int count, uint32_t ip_addr) 422 { 406 423 int index; 407 424 for (index = 0; index < count; index++) { 408 425 struct hdhomerun_discover_device_t *result = &result_list[index]; 409 if (result-> device_id == device_id) {426 if (result->ip_addr == ip_addr) { 410 427 return result; 411 428 } 412 429 } … … 414 431 return NULL; 415 432 } 416 433 417 static int hdhomerun_discover_find_devices_internal(struct hdhomerun_discover_ sock_t *ds, uint32_t device_type, uint32_t device_id, struct hdhomerun_discover_device_t result_list[], int max_count)434 static int hdhomerun_discover_find_devices_internal(struct hdhomerun_discover_t *ds, uint32_t target_ip, uint32_t device_type, uint32_t device_id, struct hdhomerun_discover_device_t result_list[], int max_count) 418 435 { 419 436 int count = 0; 420 421 437 int attempt; 422 438 for (attempt = 0; attempt < 4; attempt++) { 423 if ( hdhomerun_discover_send(ds, device_type, device_id) < 0) {439 if (!hdhomerun_discover_send(ds, target_ip, device_type, device_id)) { 424 440 return -1; 425 441 } 426 442 … … 433 449 return -1; 434 450 } 435 451 if (ret == 0) { 436 break;452 continue; 437 453 } 438 454 439 455 /* Filter. */ … … 449 465 } 450 466 451 467 /* Ensure not already in list. */ 452 if (hdhomerun_discover_find_in_list(result_list, count, result-> device_id)) {468 if (hdhomerun_discover_find_in_list(result_list, count, result->ip_addr)) { 453 469 continue; 454 470 } 455 471 … … 464 480 return count; 465 481 } 466 482 467 int hdhomerun_discover_find_device (uint32_t device_id, struct hdhomerun_discover_device_t *result)483 int hdhomerun_discover_find_devices_custom(uint32_t target_ip, uint32_t device_type, uint32_t device_id, struct hdhomerun_discover_device_t result_list[], int max_count) 468 484 { 469 struct hdhomerun_discover_ sock_t *ds = hdhomerun_discover_create();485 struct hdhomerun_discover_t *ds = hdhomerun_discover_create(); 470 486 if (!ds) { 471 487 return -1; 472 488 } 473 489 474 int ret = hdhomerun_discover_find_devices_internal(ds, HDHOMERUN_DEVICE_TYPE_WILDCARD, device_id, result, 1);490 int ret = hdhomerun_discover_find_devices_internal(ds, target_ip, device_type, device_id, result_list, max_count); 475 491 476 492 hdhomerun_discover_destroy(ds); 477 493 return ret; 478 494 } 479 495 480 int hdhomerun_discover_find_devices(uint32_t device_type, struct hdhomerun_discover_device_t result_list[], int max_count)481 {482 struct hdhomerun_discover_sock_t *ds = hdhomerun_discover_create();483 if (!ds) {484 return -1;485 }486 487 int ret = hdhomerun_discover_find_devices_internal(ds, device_type, HDHOMERUN_DEVICE_ID_WILDCARD, result_list, max_count);488 489 hdhomerun_discover_destroy(ds);490 return ret;491 }492 493 496 bool_t hdhomerun_discover_validate_device_id(uint32_t device_id) 494 497 { 495 498 static uint32_t lookup_table[16] = {0xA, 0x5, 0xF, 0x6, 0x7, 0xC, 0x1, 0xB, 0x9, 0x2, 0x8, 0xD, 0x4, 0x3, 0xE, 0x0}; -
libs/libmythtv/hdhomerun/hdhomerun_dhcp.c
1 /* 2 * hdhomerun_dhcp.c 3 * 4 * Copyright © 2006-2007 Silicondust Engineering Ltd. <www.silicondust.com>. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 3 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include "hdhomerun.h" 21 #include "hdhomerun_dhcp.h" 22 23 struct dhcp_hdr_t { 24 uint8_t bootp_message_type; 25 uint8_t hardware_type; 26 uint8_t hardware_address_length; 27 uint8_t hops; 28 uint32_t transaction_id; 29 uint16_t seconds_elapsed; 30 uint16_t bootp_flags; 31 uint32_t client_ip; 32 uint32_t your_ip; 33 uint32_t next_server_ip; 34 uint32_t relay_agent_ip; 35 uint8_t client_mac[16]; 36 uint8_t server_host_name[64]; 37 uint8_t boot_file_name[128]; 38 uint32_t magic_cookie; 39 }; 40 41 struct hdhomerun_dhcp_t { 42 int sock; 43 uint32_t local_address; 44 pthread_t thread; 45 volatile bool_t terminate; 46 }; 47 48 static THREAD_FUNC_PREFIX hdhomerun_dhcp_thread_execute(void *arg); 49 50 struct hdhomerun_dhcp_t *hdhomerun_dhcp_create(uint32_t bind_address) 51 { 52 if (bind_address != 0) { 53 if ((bind_address & 0xFFFF0000) != 0xA9FE0000) { 54 return NULL; 55 } 56 } 57 58 /* Create socket. */ 59 int sock = (int)socket(AF_INET, SOCK_DGRAM, 0); 60 if (sock == -1) { 61 return NULL; 62 } 63 64 /* Set timeout. */ 65 setsocktimeout(sock, SOL_SOCKET, SO_RCVTIMEO, 1000); 66 67 /* Allow broadcast. */ 68 int sock_opt = 1; 69 setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&sock_opt, sizeof(sock_opt)); 70 71 /* Allow reuse. */ 72 sock_opt = 1; 73 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&sock_opt, sizeof(sock_opt)); 74 75 /* Bind socket. */ 76 struct sockaddr_in sock_addr; 77 memset(&sock_addr, 0, sizeof(sock_addr)); 78 sock_addr.sin_family = AF_INET; 79 sock_addr.sin_addr.s_addr = htonl(bind_address); 80 sock_addr.sin_port = htons(67); 81 if (bind(sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) { 82 close(sock); 83 return NULL; 84 } 85 86 /* Allocate object. */ 87 struct hdhomerun_dhcp_t *dhcp = (struct hdhomerun_dhcp_t *)calloc(1, sizeof(struct hdhomerun_dhcp_t)); 88 if (!dhcp) { 89 close(sock); 90 return NULL; 91 } 92 93 dhcp->sock = sock; 94 95 if (bind_address != 0) { 96 dhcp->local_address = bind_address; 97 } else { 98 dhcp->local_address = 0xA9FEFFFF; 99 } 100 101 /* Spawn thread. */ 102 if (pthread_create(&dhcp->thread, NULL, &hdhomerun_dhcp_thread_execute, dhcp) != 0) { 103 close(sock); 104 free(dhcp); 105 return NULL; 106 } 107 108 /* Success. */ 109 return dhcp; 110 } 111 112 void hdhomerun_dhcp_destroy(struct hdhomerun_dhcp_t *dhcp) 113 { 114 dhcp->terminate = TRUE; 115 pthread_join(dhcp->thread, NULL); 116 117 close(dhcp->sock); 118 free(dhcp); 119 } 120 121 static void hdhomerun_dhcp_send(struct hdhomerun_dhcp_t *dhcp, uint8_t message_type, struct hdhomerun_pkt_t *pkt) 122 { 123 pkt->pos = pkt->start; 124 struct dhcp_hdr_t *hdr = (struct dhcp_hdr_t *)pkt->pos; 125 pkt->pos += sizeof(struct dhcp_hdr_t); 126 pkt->end = pkt->pos; 127 128 uint32_t remote_addr = 0xA9FE0000; 129 remote_addr |= (uint32_t)hdr->client_mac[4] << 8; 130 remote_addr |= (uint32_t)hdr->client_mac[5] << 0; 131 if ((remote_addr == 0xA9FE0000) || (remote_addr == 0xA9FEFFFF)) { 132 remote_addr = 0xA9FE8080; 133 } 134 135 hdr->bootp_message_type = 0x02; 136 hdr->your_ip = htonl(remote_addr); 137 hdr->next_server_ip = htonl(0x00000000); 138 139 hdhomerun_pkt_write_u8(pkt, 53); 140 hdhomerun_pkt_write_u8(pkt, 1); 141 hdhomerun_pkt_write_u8(pkt, message_type); 142 143 hdhomerun_pkt_write_u8(pkt, 54); 144 hdhomerun_pkt_write_u8(pkt, 4); 145 hdhomerun_pkt_write_u32(pkt, dhcp->local_address); 146 147 hdhomerun_pkt_write_u8(pkt, 51); 148 hdhomerun_pkt_write_u8(pkt, 4); 149 hdhomerun_pkt_write_u32(pkt, 7*24*60*60); 150 151 hdhomerun_pkt_write_u8(pkt, 1); 152 hdhomerun_pkt_write_u8(pkt, 4); 153 hdhomerun_pkt_write_u32(pkt, 0xFFFF0000); 154 155 hdhomerun_pkt_write_u8(pkt, 0xFF); 156 157 while (pkt->pos < pkt->start + 300) { 158 hdhomerun_pkt_write_u8(pkt, 0x00); 159 } 160 161 struct sockaddr_in sock_addr; 162 memset(&sock_addr, 0, sizeof(sock_addr)); 163 sock_addr.sin_family = AF_INET; 164 sock_addr.sin_addr.s_addr = htonl(0xFFFFFFFF); 165 sock_addr.sin_port = htons(68); 166 167 sendto(dhcp->sock, (char *)pkt->start, (int)(pkt->end - pkt->start), 0, (struct sockaddr *)&sock_addr, sizeof(sock_addr)); 168 } 169 170 static void hdhomerun_dhcp_recv(struct hdhomerun_dhcp_t *dhcp, struct hdhomerun_pkt_t *pkt) 171 { 172 pkt->pos = pkt->start; 173 struct dhcp_hdr_t *hdr = (struct dhcp_hdr_t *)pkt->pos; 174 pkt->pos += sizeof(struct dhcp_hdr_t); 175 if (pkt->pos > pkt->end) { 176 return; 177 } 178 179 if (ntohl(hdr->magic_cookie) != 0x63825363) { 180 return; 181 } 182 183 static uint8_t vendor[3] = {0x00, 0x18, 0xDD}; 184 if (memcmp(hdr->client_mac, vendor, 3) != 0) { 185 return; 186 } 187 188 if (pkt->pos + 3 > pkt->end) { 189 return; 190 } 191 if (hdhomerun_pkt_read_u8(pkt) != 53) { 192 return; 193 } 194 if (hdhomerun_pkt_read_u8(pkt) != 1) { 195 return; 196 } 197 uint8_t message_type_val = hdhomerun_pkt_read_u8(pkt); 198 199 switch (message_type_val) { 200 case 0x01: 201 hdhomerun_dhcp_send(dhcp, 0x02, pkt); 202 break; 203 case 0x03: 204 hdhomerun_dhcp_send(dhcp, 0x05, pkt); 205 break; 206 default: 207 return; 208 } 209 } 210 211 static THREAD_FUNC_PREFIX hdhomerun_dhcp_thread_execute(void *arg) 212 { 213 struct hdhomerun_dhcp_t *dhcp = (struct hdhomerun_dhcp_t *)arg; 214 struct hdhomerun_pkt_t pkt_inst; 215 216 while (1) { 217 if (dhcp->terminate) { 218 return NULL; 219 } 220 221 struct hdhomerun_pkt_t *pkt = &pkt_inst; 222 hdhomerun_pkt_reset(pkt); 223 224 int rx_length = recv(dhcp->sock, (char *)pkt->end, (int)(pkt->limit - pkt->end), 0); 225 if (rx_length <= 0) { 226 if (!sock_getlasterror_socktimeout) { 227 sleep(1); 228 } 229 continue; 230 } 231 pkt->end += rx_length; 232 233 hdhomerun_dhcp_recv(dhcp, pkt); 234 } 235 } -
libs/libmythtv/hdhomerun/hdhomerun_control.c
3 3 * 4 4 * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>. 5 5 * 6 * This library is free software; you can redistribute it and/or 6 * This library is free software; you can redistribute it and/or 7 7 * modify it under the terms of the GNU Lesser General Public 8 8 * License as published by the Free Software Foundation; either 9 * version 2.1of the License, or (at your option) any later version.9 * version 3 of the License, or (at your option) any later version. 10 10 * 11 11 * This library is distributed in the hope that it will be useful, 12 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of … … 14 14 * Lesser General Public License for more details. 15 15 * 16 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 * 19 * As a special exception to the GNU Lesser General Public License, 20 * you may link, statically or dynamically, an application with a 21 * publicly distributed version of the Library to produce an 22 * executable file containing portions of the Library, and 23 * distribute that executable file under terms of your choice, 24 * without any of the additional requirements listed in clause 4 of 25 * the GNU Lesser General Public License. 26 * 27 * By "a publicly distributed version of the Library", we mean 28 * either the unmodified Library as distributed by Silicondust, or a 29 * modified version of the Library that is distributed under the 30 * conditions defined in the GNU Lesser General Public License. 19 31 */ 20 32 21 #include "hdhomerun_os.h" 22 #include "hdhomerun_pkt.h" 23 #include "hdhomerun_discover.h" 24 #include "hdhomerun_control.h" 33 #include "hdhomerun.h" 25 34 35 #define HDHOMERUN_CONTROL_SEND_TIMEOUT 5000 36 #define HDHOMERUN_CONTROL_RECV_TIMEOUT 5000 37 #define HDHOMERUN_CONTROL_UPGRADE_TIMEOUT 20000 38 26 39 struct hdhomerun_control_sock_t { 27 uint32_t device_id; 28 uint32_t device_ip; 40 uint32_t desired_device_id; 41 uint32_t desired_device_ip; 42 uint32_t actual_device_id; 43 uint32_t actual_device_ip; 29 44 int sock; 30 uint8_t buffer[16384]; 45 struct hdhomerun_debug_t *dbg; 46 struct hdhomerun_pkt_t tx_pkt; 47 struct hdhomerun_pkt_t rx_pkt; 31 48 }; 32 49 33 st ruct hdhomerun_control_sock_t *hdhomerun_control_create(uint32_t device_id, uint32_t device_ip)50 static void hdhomerun_control_close_sock(struct hdhomerun_control_sock_t *cs) 34 51 { 35 struct hdhomerun_control_sock_t *cs = (struct hdhomerun_control_sock_t *)malloc(sizeof(struct hdhomerun_control_sock_t)); 52 if (cs->sock == -1) { 53 return; 54 } 55 56 close(cs->sock); 57 cs->sock = -1; 58 } 59 60 void hdhomerun_control_set_device(struct hdhomerun_control_sock_t *cs, uint32_t device_id, uint32_t device_ip) 61 { 62 hdhomerun_control_close_sock(cs); 63 64 cs->desired_device_id = device_id; 65 cs->desired_device_ip = device_ip; 66 cs->actual_device_id = 0; 67 cs->actual_device_ip = 0; 68 } 69 70 struct hdhomerun_control_sock_t *hdhomerun_control_create(uint32_t device_id, uint32_t device_ip, struct hdhomerun_debug_t *dbg) 71 { 72 struct hdhomerun_control_sock_t *cs = (struct hdhomerun_control_sock_t *)calloc(1, sizeof(struct hdhomerun_control_sock_t)); 36 73 if (!cs) { 74 hdhomerun_debug_printf(dbg, "hdhomerun_control_create: failed to allocate control object\n"); 37 75 return NULL; 38 76 } 39 40 cs->device_id = device_id; 41 cs->device_ip = device_ip; 77 78 cs->dbg = dbg; 42 79 cs->sock = -1; 80 hdhomerun_control_set_device(cs, device_id, device_ip); 43 81 44 82 return cs; 45 83 } 46 84 47 85 void hdhomerun_control_destroy(struct hdhomerun_control_sock_t *cs) 48 86 { 49 if (cs->sock != -1) { 50 close(cs->sock); 51 } 87 hdhomerun_control_close_sock(cs); 52 88 free(cs); 53 89 } 54 90 55 static void hdhomerun_control_close_sock(struct hdhomerun_control_sock_t *cs)56 {57 close(cs->sock);58 cs->sock = -1;59 }60 61 91 static bool_t hdhomerun_control_connect_sock(struct hdhomerun_control_sock_t *cs) 62 92 { 63 93 if (cs->sock != -1) { 64 94 return TRUE; 65 95 } 66 96 67 /* Find ip address. */ 68 uint32_t device_ip = cs->device_ip; 69 if (device_ip == 0) { 70 struct hdhomerun_discover_device_t result; 71 if (hdhomerun_discover_find_device(cs->device_id, &result) <= 0) { 72 return FALSE; 73 } 74 device_ip = result.ip_addr; 97 if ((cs->desired_device_id == 0) && (cs->desired_device_ip == 0)) { 98 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_connect_sock: no device specified\n"); 99 return FALSE; 75 100 } 76 101 102 /* Find device. */ 103 struct hdhomerun_discover_device_t result; 104 if (hdhomerun_discover_find_devices_custom(cs->desired_device_ip, HDHOMERUN_DEVICE_TYPE_WILDCARD, cs->desired_device_id, &result, 1) <= 0) { 105 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_connect_sock: device not found\n"); 106 return FALSE; 107 } 108 cs->actual_device_ip = result.ip_addr; 109 cs->actual_device_id = result.device_id; 110 77 111 /* Create socket. */ 78 112 cs->sock = (int)socket(AF_INET, SOCK_STREAM, 0); 79 113 if (cs->sock == -1) { 114 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_connect_sock: failed to create socket (%d)\n", sock_getlasterror); 80 115 return FALSE; 81 116 } 82 117 83 118 /* Set timeouts. */ 84 setsocktimeout(cs->sock, SOL_SOCKET, SO_SNDTIMEO, 1000);85 setsocktimeout(cs->sock, SOL_SOCKET, SO_RCVTIMEO, 1000);119 setsocktimeout(cs->sock, SOL_SOCKET, SO_SNDTIMEO, HDHOMERUN_CONTROL_SEND_TIMEOUT); 120 setsocktimeout(cs->sock, SOL_SOCKET, SO_RCVTIMEO, HDHOMERUN_CONTROL_RECV_TIMEOUT); 86 121 87 122 /* Initiate connection. */ 88 123 struct sockaddr_in sock_addr; 89 124 memset(&sock_addr, 0, sizeof(sock_addr)); 90 125 sock_addr.sin_family = AF_INET; 91 sock_addr.sin_addr.s_addr = htonl( device_ip);126 sock_addr.sin_addr.s_addr = htonl(cs->actual_device_ip); 92 127 sock_addr.sin_port = htons(HDHOMERUN_CONTROL_TCP_PORT); 93 128 if (connect(cs->sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) { 129 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_connect_sock: failed to connect (%d)\n", sock_getlasterror); 94 130 hdhomerun_control_close_sock(cs); 95 131 return FALSE; 96 132 } … … 99 135 return TRUE; 100 136 } 101 137 138 uint32_t hdhomerun_control_get_device_id(struct hdhomerun_control_sock_t *cs) 139 { 140 if (!hdhomerun_control_connect_sock(cs)) { 141 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_get_device_id: connect failed\n"); 142 return 0; 143 } 144 145 return cs->actual_device_id; 146 } 147 148 uint32_t hdhomerun_control_get_device_ip(struct hdhomerun_control_sock_t *cs) 149 { 150 if (!hdhomerun_control_connect_sock(cs)) { 151 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_get_device_ip: connect failed\n"); 152 return 0; 153 } 154 155 return cs->actual_device_ip; 156 } 157 158 uint32_t hdhomerun_control_get_device_id_requested(struct hdhomerun_control_sock_t *cs) 159 { 160 return cs->desired_device_id; 161 } 162 163 uint32_t hdhomerun_control_get_device_ip_requested(struct hdhomerun_control_sock_t *cs) 164 { 165 return cs->desired_device_ip; 166 } 167 102 168 uint32_t hdhomerun_control_get_local_addr(struct hdhomerun_control_sock_t *cs) 103 169 { 104 170 if (!hdhomerun_control_connect_sock(cs)) { 171 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_get_local_addr: connect failed\n"); 105 172 return 0; 106 173 } 107 174 108 175 struct sockaddr_in sock_addr; 109 176 socklen_t sockaddr_size = sizeof(sock_addr); 110 177 if (getsockname(cs->sock, (struct sockaddr*)&sock_addr, &sockaddr_size) != 0) { 178 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_get_local_addr: getsockname failed (%d)\n", sock_getlasterror); 111 179 return 0; 112 180 } 113 181 114 182 return ntohl(sock_addr.sin_addr.s_addr); 115 183 } 116 184 117 static int hdhomerun_control_send (struct hdhomerun_control_sock_t *cs, uint8_t *start, uint8_t *end)185 static int hdhomerun_control_send_sock(struct hdhomerun_control_sock_t *cs, struct hdhomerun_pkt_t *tx_pkt) 118 186 { 119 int length = (int)(end - start); 120 if (send(cs->sock, (char *)start, (int)length, 0) != length) { 187 int length = (int)(tx_pkt->end - tx_pkt->start); 188 if (send(cs->sock, (char *)tx_pkt->start, (int)length, 0) != length) { 189 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_send_sock: send failed (%d)\n", sock_getlasterror); 190 hdhomerun_control_close_sock(cs); 121 191 return -1; 122 192 } 123 193 124 return length;194 return 1; 125 195 } 126 196 127 static int hdhomerun_control_recv_sock(struct hdhomerun_control_sock_t *cs, uint8_t *buffer, uint8_t *limit)197 static int hdhomerun_control_recv_sock(struct hdhomerun_control_sock_t *cs, struct hdhomerun_pkt_t *rx_pkt, uint16_t *ptype, uint64_t recv_timeout) 128 198 { 129 struct timeval t; 130 t.tv_sec = 0; 131 t.tv_usec = 250000; 199 uint64_t stop_time = getcurrenttime() + recv_timeout; 200 hdhomerun_pkt_reset(rx_pkt); 132 201 133 fd_set readfds; 134 FD_ZERO(&readfds); 135 FD_SET(cs->sock, &readfds); 202 while (getcurrenttime() < stop_time) { 203 struct timeval t; 204 t.tv_sec = 0; 205 t.tv_usec = 250000; 206 207 fd_set readfds; 208 FD_ZERO(&readfds); 209 FD_SET(cs->sock, &readfds); 210 211 if (select(cs->sock+1, &readfds, NULL, NULL, &t) < 0) { 212 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_recv_sock: select failed (%d)\n", sock_getlasterror); 213 hdhomerun_control_close_sock(cs); 214 return -1; 215 } 216 217 if (!FD_ISSET(cs->sock, &readfds)) { 218 continue; 219 } 220 221 int rx_length = recv(cs->sock, (char *)rx_pkt->end, (int)(rx_pkt->limit - rx_pkt->end), 0); 222 if (rx_length <= 0) { 223 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_recv_sock: recv failed (%d)\n", sock_getlasterror); 224 hdhomerun_control_close_sock(cs); 225 return -1; 226 } 227 rx_pkt->end += rx_length; 136 228 137 if (select(cs->sock+1, &readfds, NULL, NULL, &t) < 0) { 138 return -1; 139 } 229 int ret = hdhomerun_pkt_open_frame(rx_pkt, ptype); 230 if (ret < 0) { 231 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_recv_sock: frame error\n"); 232 hdhomerun_control_close_sock(cs); 233 return -1; 234 } 235 if (ret == 0) { 236 continue; 237 } 140 238 141 if (!FD_ISSET(cs->sock, &readfds)) { 142 return 0; 239 return 1; 143 240 } 144 241 145 int length = recv(cs->sock, (char *)buffer, (int)(limit - buffer), 0); 146 if (length <= 0) { 147 return -1; 148 } 149 150 return length; 242 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_recv_sock: timeout\n"); 243 hdhomerun_control_close_sock(cs); 244 return -1; 151 245 } 152 246 153 static int hdhomerun_control_ recv(struct hdhomerun_control_sock_t *cs, uint8_t *buffer, uint8_t *limit)247 static int hdhomerun_control_send_recv_internal(struct hdhomerun_control_sock_t *cs, struct hdhomerun_pkt_t *tx_pkt, struct hdhomerun_pkt_t *rx_pkt, uint16_t type, uint64_t recv_timeout) 154 248 { 155 uint64_t timeout = getcurrenttime() + 1000; 156 uint8_t *ptr = buffer; 249 hdhomerun_pkt_seal_frame(tx_pkt, type); 157 250 158 while (getcurrenttime() < timeout) { 159 int length = hdhomerun_control_recv_sock(cs, ptr, limit); 160 if (length < 0) { 161 return -1; 251 int i; 252 for (i = 0; i < 2; i++) { 253 if (cs->sock == -1) { 254 if (!hdhomerun_control_connect_sock(cs)) { 255 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_send_recv: connect failed\n"); 256 return -1; 257 } 162 258 } 163 if (length == 0) { 259 260 if (hdhomerun_control_send_sock(cs, tx_pkt) < 0) { 164 261 continue; 165 262 } 166 ptr += length; 263 if (!rx_pkt) { 264 return 1; 265 } 167 266 168 if (buffer + HDHOMERUN_MIN_PEEK_LENGTH > limit) { 267 uint16_t rsp_type; 268 if (hdhomerun_control_recv_sock(cs, rx_pkt, &rsp_type, recv_timeout) < 0) { 169 269 continue; 170 270 } 171 172 length = (int)hdhomerun_peek_packet_length(buffer);173 if (buffer + length > limit) {271 if (rsp_type != type + 1) { 272 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_send_recv: unexpected frame type\n"); 273 hdhomerun_control_close_sock(cs); 174 274 continue; 175 275 } 176 276 177 return length;277 return 1; 178 278 } 179 279 280 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_send_recv: failed\n"); 180 281 return -1; 181 282 } 182 283 183 static int hdhomerun_control_get_set(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, char **pvalue, char **perror)284 int hdhomerun_control_send_recv(struct hdhomerun_control_sock_t *cs, struct hdhomerun_pkt_t *tx_pkt, struct hdhomerun_pkt_t *rx_pkt, uint16_t type) 184 285 { 185 /* Send request. */ 186 uint8_t *ptr = cs->buffer; 187 hdhomerun_write_get_set_request(&ptr, name, value); 188 if (hdhomerun_control_send(cs, cs->buffer, ptr) < 0) { 286 return hdhomerun_control_send_recv_internal(cs, tx_pkt, rx_pkt, type, HDHOMERUN_CONTROL_RECV_TIMEOUT); 287 } 288 289 static int hdhomerun_control_get_set(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, uint32_t lockkey, char **pvalue, char **perror) 290 { 291 struct hdhomerun_pkt_t *tx_pkt = &cs->tx_pkt; 292 struct hdhomerun_pkt_t *rx_pkt = &cs->rx_pkt; 293 294 /* Request. */ 295 hdhomerun_pkt_reset(tx_pkt); 296 297 int name_len = (int)strlen(name) + 1; 298 if (tx_pkt->end + 3 + name_len > tx_pkt->limit) { 299 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_get_set: request too long\n"); 189 300 return -1; 190 301 } 302 hdhomerun_pkt_write_u8(tx_pkt, HDHOMERUN_TAG_GETSET_NAME); 303 hdhomerun_pkt_write_var_length(tx_pkt, name_len); 304 hdhomerun_pkt_write_mem(tx_pkt, (void *)name, name_len); 191 305 192 /* Receive response. */ 193 int length = hdhomerun_control_recv(cs, cs->buffer, cs->buffer + sizeof(cs->buffer)); 194 if (length <= 0) { 195 return -1; 306 if (value) { 307 int value_len = (int)strlen(value) + 1; 308 if (tx_pkt->end + 3 + value_len > tx_pkt->limit) { 309 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_get_set: request too long\n"); 310 return -1; 311 } 312 hdhomerun_pkt_write_u8(tx_pkt, HDHOMERUN_TAG_GETSET_VALUE); 313 hdhomerun_pkt_write_var_length(tx_pkt, value_len); 314 hdhomerun_pkt_write_mem(tx_pkt, (void *)value, value_len); 196 315 } 197 316 198 /* Parse response. */ 199 ptr = cs->buffer; 200 uint8_t *end = ptr + length; 201 int type = hdhomerun_process_packet(&ptr, &end); 202 if (type < 0) { 203 return -1; 317 if (lockkey != 0) { 318 if (tx_pkt->end + 6 > tx_pkt->limit) { 319 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_get_set: request too long\n"); 320 return -1; 321 } 322 hdhomerun_pkt_write_u8(tx_pkt, HDHOMERUN_TAG_GETSET_LOCKKEY); 323 hdhomerun_pkt_write_var_length(tx_pkt, 4); 324 hdhomerun_pkt_write_u32(tx_pkt, lockkey); 204 325 } 205 if (type != HDHOMERUN_TYPE_GETSET_RPY) { 326 327 /* Send/Recv. */ 328 if (hdhomerun_control_send_recv_internal(cs, tx_pkt, rx_pkt, HDHOMERUN_TYPE_GETSET_REQ, HDHOMERUN_CONTROL_RECV_TIMEOUT) < 0) { 329 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_get_set: send/recv error\n"); 206 330 return -1; 207 331 } 208 332 209 while (ptr < end) { 333 /* Response. */ 334 while (1) { 210 335 uint8_t tag; 211 336 size_t len; 212 uint8_t * val;213 if ( hdhomerun_read_tlv(&ptr, end, &tag, &len, &val) < 0) {337 uint8_t *next = hdhomerun_pkt_read_tlv(rx_pkt, &tag, &len); 338 if (!next) { 214 339 break; 215 340 } 341 216 342 switch (tag) { 217 343 case HDHOMERUN_TAG_GETSET_VALUE: 218 344 if (pvalue) { 219 *pvalue = (char *) val;220 val[len] = 0;345 *pvalue = (char *)rx_pkt->pos; 346 rx_pkt->pos[len] = 0; 221 347 } 222 348 if (perror) { 223 349 *perror = NULL; … … 225 351 return 1; 226 352 227 353 case HDHOMERUN_TAG_ERROR_MESSAGE: 354 rx_pkt->pos[len] = 0; 355 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_get_set: %s\n", rx_pkt->pos); 356 228 357 if (pvalue) { 229 358 *pvalue = NULL; 230 359 } 231 360 if (perror) { 232 *perror = (char *)val; 233 val[len] = 0; 361 *perror = (char *)rx_pkt->pos; 234 362 } 363 235 364 return 0; 236 365 } 366 367 rx_pkt->pos = next; 237 368 } 238 369 370 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_get_set: missing response tags\n"); 239 371 return -1; 240 372 } 241 373 242 374 int hdhomerun_control_get(struct hdhomerun_control_sock_t *cs, const char *name, char **pvalue, char **perror) 243 375 { 244 if (!hdhomerun_control_connect_sock(cs)) { 245 return -1; 246 } 247 248 int ret = hdhomerun_control_get_set(cs, name, NULL, pvalue, perror); 249 if (ret < 0) { 250 hdhomerun_control_close_sock(cs); 251 return -1; 252 } 253 254 return ret; 376 return hdhomerun_control_get_set(cs, name, NULL, 0, pvalue, perror); 255 377 } 256 378 257 379 int hdhomerun_control_set(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, char **pvalue, char **perror) 258 380 { 259 if (!hdhomerun_control_connect_sock(cs)) { 260 return -1; 261 } 381 return hdhomerun_control_get_set(cs, name, value, 0, pvalue, perror); 382 } 262 383 263 int ret = hdhomerun_control_get_set(cs, name, value, pvalue, perror); 264 if (ret < 0) { 265 hdhomerun_control_close_sock(cs); 266 return -1; 267 } 268 269 return ret; 384 int hdhomerun_control_set_with_lockkey(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, uint32_t lockkey, char **pvalue, char **perror) 385 { 386 return hdhomerun_control_get_set(cs, name, value, lockkey, pvalue, perror); 270 387 } 271 388 272 389 int hdhomerun_control_upgrade(struct hdhomerun_control_sock_t *cs, FILE *upgrade_file) 273 390 { 274 if (!hdhomerun_control_connect_sock(cs)) { 275 return -1; 276 } 277 391 struct hdhomerun_pkt_t *tx_pkt = &cs->tx_pkt; 392 struct hdhomerun_pkt_t *rx_pkt = &cs->rx_pkt; 278 393 uint32_t sequence = 0; 279 uint8_t *ptr;280 394 395 /* Upload. */ 281 396 while (1) { 282 397 uint8_t data[256]; 283 398 size_t length = fread(data, 1, 256, upgrade_file); … … 285 400 break; 286 401 } 287 402 288 ptr = cs->buffer; 289 hdhomerun_write_upgrade_request(&ptr, sequence, data, length); 290 if (hdhomerun_control_send(cs, cs->buffer, ptr) < 0) { 291 hdhomerun_control_close_sock(cs); 403 hdhomerun_pkt_reset(tx_pkt); 404 hdhomerun_pkt_write_u32(tx_pkt, sequence); 405 hdhomerun_pkt_write_mem(tx_pkt, data, length); 406 407 if (hdhomerun_control_send_recv_internal(cs, tx_pkt, NULL, HDHOMERUN_TYPE_UPGRADE_REQ, 0) < 0) { 408 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_upgrade: send/recv failed\n"); 292 409 return -1; 293 410 } 294 411 … … 297 414 298 415 if (sequence == 0) { 299 416 /* No data in file. Error, but no need to close connection. */ 417 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_upgrade: zero length file\n"); 300 418 return 0; 301 419 } 302 420 303 ptr = cs->buffer; 304 hdhomerun_write_upgrade_request(&ptr, 0xFFFFFFFF, NULL, 0); 305 if (hdhomerun_control_send(cs, cs->buffer, ptr) < 0) { 306 hdhomerun_control_close_sock(cs); 421 /* Execute upgrade. */ 422 hdhomerun_pkt_reset(tx_pkt); 423 hdhomerun_pkt_write_u32(tx_pkt, 0xFFFFFFFF); 424 425 if (hdhomerun_control_send_recv_internal(cs, tx_pkt, rx_pkt, HDHOMERUN_TYPE_UPGRADE_REQ, HDHOMERUN_CONTROL_UPGRADE_TIMEOUT) < 0) { 426 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_upgrade: send/recv failed\n"); 307 427 return -1; 308 428 } 309 429 430 /* Check response. */ 431 while (1) { 432 uint8_t tag; 433 size_t len; 434 uint8_t *next = hdhomerun_pkt_read_tlv(rx_pkt, &tag, &len); 435 if (!next) { 436 break; 437 } 438 439 switch (tag) { 440 case HDHOMERUN_TAG_ERROR_MESSAGE: 441 rx_pkt->pos[len] = 0; 442 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_upgrade: %s\n", (char *)rx_pkt->pos); 443 return 0; 444 445 default: 446 break; 447 } 448 449 rx_pkt->pos = next; 450 } 451 310 452 return 1; 311 453 } -
libs/libmythtv/hdhomerun/hdhomerun_channelscan.h
1 /* 2 * hdhomerun_channelscan.h 3 * 4 * Copyright © 2007-2008 Silicondust Engineering Ltd. <www.silicondust.com>. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 3 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 * 19 * As a special exception to the GNU Lesser General Public License, 20 * you may link, statically or dynamically, an application with a 21 * publicly distributed version of the Library to produce an 22 * executable file containing portions of the Library, and 23 * distribute that executable file under terms of your choice, 24 * without any of the additional requirements listed in clause 4 of 25 * the GNU Lesser General Public License. 26 * 27 * By "a publicly distributed version of the Library", we mean 28 * either the unmodified Library as distributed by Silicondust, or a 29 * modified version of the Library that is distributed under the 30 * conditions defined in the GNU Lesser General Public License. 31 */ 32 33 #ifdef __cplusplus 34 extern "C" { 35 #endif 36 37 #define HDHOMERUN_CHANNELSCAN_PROGRAM_NORMAL 0 38 #define HDHOMERUN_CHANNELSCAN_PROGRAM_NODATA 1 39 #define HDHOMERUN_CHANNELSCAN_PROGRAM_CONTROL 2 40 #define HDHOMERUN_CHANNELSCAN_PROGRAM_ENCRYPTED 3 41 42 struct hdhomerun_channelscan_t; 43 44 extern LIBTYPE struct hdhomerun_channelscan_t *channelscan_create(struct hdhomerun_device_t *hd, const char *channelmap); 45 extern LIBTYPE void channelscan_destroy(struct hdhomerun_channelscan_t *scan); 46 47 extern LIBTYPE int channelscan_advance(struct hdhomerun_channelscan_t *scan, struct hdhomerun_channelscan_result_t *result); 48 extern LIBTYPE int channelscan_detect(struct hdhomerun_channelscan_t *scan, struct hdhomerun_channelscan_result_t *result); 49 extern LIBTYPE uint8_t channelscan_get_progress(struct hdhomerun_channelscan_t *scan); 50 51 #ifdef __cplusplus 52 } 53 #endif -
libs/libmythtv/hdhomerun/hdhomerun_discover.h
1 1 /* 2 2 * hdhomerun_discover.h 3 3 * 4 * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.4 * Copyright © 2006-2007 Silicondust Engineering Ltd. <www.silicondust.com>. 5 5 * 6 * This library is free software; you can redistribute it and/or 6 * This library is free software; you can redistribute it and/or 7 7 * modify it under the terms of the GNU Lesser General Public 8 8 * License as published by the Free Software Foundation; either 9 * version 2.1of the License, or (at your option) any later version.9 * version 3 of the License, or (at your option) any later version. 10 10 * 11 11 * This library is distributed in the hope that it will be useful, 12 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of … … 14 14 * Lesser General Public License for more details. 15 15 * 16 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 * 19 * As a special exception to the GNU Lesser General Public License, 20 * you may link, statically or dynamically, an application with a 21 * publicly distributed version of the Library to produce an 22 * executable file containing portions of the Library, and 23 * distribute that executable file under terms of your choice, 24 * without any of the additional requirements listed in clause 4 of 25 * the GNU Lesser General Public License. 26 * 27 * By "a publicly distributed version of the Library", we mean 28 * either the unmodified Library as distributed by Silicondust, or a 29 * modified version of the Library that is distributed under the 30 * conditions defined in the GNU Lesser General Public License. 19 31 */ 20 32 #ifdef __cplusplus 21 33 extern "C" { … … 28 40 }; 29 41 30 42 /* 31 * Find a device by device ID.43 * Find devices. 32 44 * 33 * The device information is stored in caller-supplied hdhomerun_discover_device_t var.34 * Multiple attempts are made to find the device.35 * Worst-case execution time is 1 second.36 *37 * Returns 1 on success.38 * Returns 0 if not found.39 * Retruns -1 on error.40 */41 extern int hdhomerun_discover_find_device(uint32_t device_id, struct hdhomerun_discover_device_t *result);42 43 /*44 * Find all devices of a given type.45 *46 45 * The device information is stored in caller-supplied array of hdhomerun_discover_device_t vars. 47 46 * Multiple attempts are made to find devices. 48 47 * Execution time is 1 second. 49 48 * 49 * Set target_ip to zero to auto-detect IP address. 50 * 50 51 * Returns the number of devices found. 51 52 * Retruns -1 on error. 52 53 */ 53 extern int hdhomerun_discover_find_devices(uint32_t device_type, struct hdhomerun_discover_device_t result_list[], int max_count);54 extern LIBTYPE int hdhomerun_discover_find_devices_custom(uint32_t target_ip, uint32_t device_type, uint32_t device_id, struct hdhomerun_discover_device_t result_list[], int max_count); 54 55 55 56 /* 56 57 * Verify that the device ID given is valid. … … 61 62 * Returns TRUE if valid. 62 63 * Returns FALSE if not valid. 63 64 */ 64 extern bool_t hdhomerun_discover_validate_device_id(uint32_t device_id);65 extern LIBTYPE bool_t hdhomerun_discover_validate_device_id(uint32_t device_id); 65 66 66 67 #ifdef __cplusplus 67 68 } -
libs/libmythtv/hdhomerun/Makefile
5 5 SRCS += hdhomerun_video.c 6 6 SRCS += hdhomerun_device.c 7 7 SRCS += hdhomerun_config.c 8 SRCS += hdhomerun_debug.c 9 SRCS += hdhomerun_channels.c 10 SRCS += hdhomerun_channelscan.c 8 11 9 12 CFLAGS += -Wall -O2 -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wpointer-arith 10 13 -
libs/libmythtv/hdhomerun/hdhomerun_dhcp.h
1 /* 2 * hdhomerun_dhcp.h 3 * 4 * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 3 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #ifdef __cplusplus 21 extern "C" { 22 #endif 23 24 struct hdhomerun_dhcp_t; 25 26 extern LIBTYPE struct hdhomerun_dhcp_t *hdhomerun_dhcp_create(uint32_t bind_address); 27 extern LIBTYPE void hdhomerun_dhcp_destroy(struct hdhomerun_dhcp_t *dhcp); 28 29 #ifdef __cplusplus 30 } 31 #endif -
libs/libmythtv/libmythtv.pro
459 459 DEFINES += USING_HDHOMERUN 460 460 461 461 # HDHomeRun library 462 HEADERS += hdhomerun/hdhomerun_pkt.h hdhomerun/hdhomerun_discover.h 463 HEADERS += hdhomerun/hdhomerun_video.h hdhomerun/hdhomerun_control.h 462 HEADERS += hdhomerun/hdhomerun.h 464 463 HEADERS += hdhomerun/hdhomerun_os.h 464 HEADERS += hdhomerun/hdhomerun_os_posix.h 465 HEADERS += hdhomerun/hdhomerun_os_windows.h 466 HEADERS += hdhomerun/hdhomerun_channelscan.h 467 HEADERS += hdhomerun/hdhomerun_channels.h 468 HEADERS += hdhomerun/hdhomerun_control.h 469 HEADERS += hdhomerun/hdhomerun_debug.h 470 HEADERS += hdhomerun/hdhomerun_pkt.h 471 HEADERS += hdhomerun/hdhomerun_device.h 472 HEADERS += hdhomerun/hdhomerun_types.h 473 HEADERS += hdhomerun/hdhomerun_discover.h 474 HEADERS += hdhomerun/hdhomerun_video.h 465 475 466 SOURCES += hdhomerun/hdhomerun_pkt.c hdhomerun/hdhomerun_discover.c 467 SOURCES += hdhomerun/hdhomerun_video.c hdhomerun/hdhomerun_control.c 476 SOURCES += hdhomerun/hdhomerun_pkt.c 477 SOURCES += hdhomerun/hdhomerun_debug.c 478 SOURCES += hdhomerun/hdhomerun_discover.c 479 SOURCES += hdhomerun/hdhomerun_channels.c 480 SOURCES += hdhomerun/hdhomerun_channelscan.c 481 SOURCES += hdhomerun/hdhomerun_control.c 482 SOURCES += hdhomerun/hdhomerun_video.c 483 SOURCES += hdhomerun/hdhomerun_device.c 468 484 } 469 485 470 486 # Support for PVR-150/250/350/500, etc. on Linux -
libs/libmythtv/hdhrsignalmonitor.cpp
139 139 { 140 140 dtvMonitorRunning = true; 141 141 142 struct hdhomerun_video_sock_t *_video_socket; 143 _video_socket = hdhomerun_video_create(0, VIDEO_DATA_BUFFER_SIZE_1S); 144 if (!_video_socket) 142 HDHRChannel *hdrc = dynamic_cast<HDHRChannel*>(channel); 143 struct hdhomerun_device_t *_hdhomerun_device = hdrc->GetHDHRDevice(); 144 145 if (!_hdhomerun_device) 145 146 { 146 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to get video socket");147 VERBOSE(VB_IMPORTANT, "Failed to get HDHomeRun device handle"); 147 148 return; 148 149 } 149 150 150 HDHRChannel *hdrc = dynamic_cast<HDHRChannel*>(channel); 151 uint localPort = hdhomerun_video_get_local_port(_video_socket); 152 if (!hdrc->DeviceSetTarget(localPort)) 151 if (!hdhomerun_device_stream_start(_hdhomerun_device)) 153 152 { 154 hdhomerun_video_destroy(_video_socket);155 153 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to set target"); 156 154 return; 157 155 } … … 166 164 167 165 size_t data_length; 168 166 unsigned char *data_buffer = 169 hdhomerun_ video_recv(_video_socket,167 hdhomerun_device_stream_recv(_hdhomerun_device, 170 168 VIDEO_DATA_BUFFER_SIZE_1S / 5, 171 169 &data_length); 172 170 … … 179 177 usleep(2500); 180 178 } 181 179 182 hdrc->DeviceClearTarget(); 183 hdhomerun_video_destroy(_video_socket); 180 hdhomerun_device_stream_stop(_hdhomerun_device); 184 181 185 182 VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- shutdown"); 186 183 … … 215 212 return; 216 213 } 217 214 218 QString msg = ((HDHRChannel*)channel)->TunerGet("status"); 219 //ss = signal strength, [0,100] 220 //snq = signal to noise quality [0,100] 221 //seq = signal error quality [0,100] 222 int loc_sig = msg.find("ss="), loc_snq = msg.find("snq="); 223 int loc_seq = msg.find("seq="), loc_end = msg.length(); 224 bool ok0, ok1, ok2; 225 uint sig = msg.mid(loc_sig + 3, loc_snq - loc_sig - 4).toUInt(&ok0); 226 uint snq = msg.mid(loc_snq + 4, loc_seq - loc_snq - 5).toUInt(&ok1); 227 uint seq = msg.mid(loc_seq + 4, loc_end - loc_seq - 4).toUInt(&ok2); 215 HDHRChannel *hdrc = dynamic_cast<HDHRChannel*>(channel); 216 struct hdhomerun_device_t *_hdhomerun_device = hdrc->GetHDHRDevice(); 217 struct hdhomerun_tuner_status_t status; 218 hdhomerun_device_get_tuner_status(_hdhomerun_device, NULL, &status); 219 220 uint sig = status.signal_strength; 221 uint snq = status.signal_to_noise_quality; 222 uint seq = status.symbol_error_quality; 223 228 224 (void) snq; // TODO should convert to S/N 229 225 (void) seq; // TODO should report this... 230 226 … … 236 232 bool isLocked = false; 237 233 { 238 234 QMutexLocker locker(&statusLock); 239 if (loc_sig > 0 && loc_snq > 0 && ok0) 240 signalStrength.SetValue(sig); 241 signalLock.SetValue(signalStrength.IsGood() ? 1 : 0); 235 signalStrength.SetValue(sig); 236 signalLock.SetValue(status.lock_supported); 242 237 isLocked = signalLock.IsGood(); 243 238 } 244 239 -
libs/libmythtv/hdhrrecorder.cpp
110 110 buffersize = max(49 * TSPacket::SIZE * 128, buffersize); 111 111 112 112 /* Create TS socket. */ 113 _video_socket = hdhomerun_video_create(0, buffersize );113 _video_socket = hdhomerun_video_create(0, buffersize, NULL); 114 114 if (!_video_socket) 115 115 { 116 116 VERBOSE(VB_IMPORTANT, LOC + "Open() failed to open socket"); -
libs/libmythtv/hdhrchannel.cpp
31 31 #define LOC_ERR QString("HDHRChan(%1), Error: ").arg(GetDevice()) 32 32 33 33 HDHRChannel::HDHRChannel(TVRec *parent, const QString &device, uint tuner) 34 : DTVChannel(parent), _ control_socket(NULL),34 : DTVChannel(parent), _hdhomerun_device(NULL), 35 35 _device_id(0), _device_ip(0), 36 36 _tuner(tuner), _lock(true) 37 37 { … … 66 66 if (IsOpen()) 67 67 return true; 68 68 69 if (!FindDevice())70 return false;71 72 69 if (!InitializeInputs()) 73 70 return false; 74 71 75 return (_device_ip != 0) &&Connect();72 return Connect(); 76 73 } 77 74 78 75 void HDHRChannel::Close(void) 79 76 { 80 if (_ control_socket)77 if (_hdhomerun_device) 81 78 { 82 hdhomerun_ control_destroy(_control_socket);83 _ control_socket= NULL;79 hdhomerun_device_destroy(_hdhomerun_device); 80 _hdhomerun_device = NULL; 84 81 } 85 82 } 86 83 87 84 bool HDHRChannel::EnterPowerSavingMode(void) 88 85 { 89 return QString::null != TunerSet("channel", "none", false);86 return hdhomerun_device_set_tuner_channel(_hdhomerun_device, "none") > 0; 90 87 } 91 88 92 bool HDHRChannel::FindDevice(void)93 {94 if (!_device_id)95 return _device_ip;96 97 _device_ip = 0;98 99 /* Discover. */100 struct hdhomerun_discover_device_t result;101 int ret = hdhomerun_discover_find_device(_device_id, &result);102 if (ret < 0)103 {104 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to send discovery request" + ENO);105 return false;106 }107 if (ret == 0)108 {109 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("device not found"));110 return false;111 }112 113 /* Found. */114 _device_ip = result.ip_addr;115 116 VERBOSE(VB_IMPORTANT, LOC +117 QString("device found at address %1.%2.%3.%4")118 .arg((_device_ip>>24) & 0xFF).arg((_device_ip>>16) & 0xFF)119 .arg((_device_ip>> 8) & 0xFF).arg((_device_ip>> 0) & 0xFF));120 121 return true;122 }123 124 89 bool HDHRChannel::Connect(void) 125 90 { 126 _control_socket = hdhomerun_control_create(_device_id, _device_ip); 127 if (!_control_socket) 128 { 129 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to create control socket"); 130 return false; 131 } 91 _hdhomerun_device = hdhomerun_device_create( 92 _device_id, _device_ip, _tuner, NULL); 132 93 133 if ( hdhomerun_control_get_local_addr(_control_socket) == 0)94 if (!_hdhomerun_device) 134 95 { 135 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to connect to device"); 96 VERBOSE(VB_IMPORTANT, 97 LOC_ERR + "Unable to create hdhomerun device object"); 136 98 return false; 137 99 } 138 100 139 VERBOSE(VB_CHANNEL, LOC + "Successfully connected to device");140 101 return true; 141 102 } 142 103 … … 144 105 { 145 106 QMutexLocker locker(&_lock); 146 107 147 if (!_ control_socket)108 if (!_hdhomerun_device) 148 109 { 149 110 VERBOSE(VB_IMPORTANT, LOC_ERR + "Get request failed (not connected)"); 150 111 return QString::null; … … 152 113 153 114 char *value = NULL; 154 115 char *error = NULL; 155 if (hdhomerun_ control_get(_control_socket, name, &value, &error) < 0)116 if (hdhomerun_device_get_var(_hdhomerun_device, name, &value, &error) < 0) 156 117 { 157 118 VERBOSE(VB_IMPORTANT, LOC_ERR + "Get request failed" + ENO); 158 119 return QString::null; … … 174 135 { 175 136 QMutexLocker locker(&_lock); 176 137 177 if (!_ control_socket)138 if (!_hdhomerun_device) 178 139 { 179 140 VERBOSE(VB_IMPORTANT, LOC_ERR + "Set request failed (not connected)"); 180 141 return QString::null; … … 182 143 183 144 char *value = NULL; 184 145 char *error = NULL; 185 if (hdhomerun_control_set(_control_socket, name, val, &value, &error) < 0) 146 if (hdhomerun_device_set_var( 147 _hdhomerun_device, name, val, &value, &error) < 0) 186 148 { 187 149 VERBOSE(VB_IMPORTANT, LOC_ERR + "Set request failed" + ENO); 188 150 … … 200 162 return QString(value); 201 163 } 202 164 165 struct hdhomerun_device_t *HDHRChannel::GetHDHRDevice(void) 166 { 167 return _hdhomerun_device; 168 } 169 203 170 QString HDHRChannel::TunerGet(const QString &name, bool report_error_return) 204 171 { 205 172 return DeviceGet(QString("/tuner%1/%2").arg(_tuner).arg(name), … … 220 187 return false; 221 188 } 222 189 223 unsigned long localIP = hdhomerun_control_get_local_addr(_control_socket); 190 unsigned long localIP = hdhomerun_device_get_local_machine_addr( 191 _hdhomerun_device); 224 192 if (localIP == 0) 225 193 { 226 194 return false; … … 231 199 .arg((localIP >> 8) & 0xFF).arg((localIP >> 0) & 0xFF) 232 200 .arg(localPort); 233 201 234 if ( !TunerSet("target", configValue))202 if (hdhomerun_device_set_tuner_target(_hdhomerun_device, configValue) <= 0) 235 203 { 236 204 return false; 237 205 } … … 239 207 return true; 240 208 } 241 209 242 bool HDHRChannel::DeviceClearTarget( )210 bool HDHRChannel::DeviceClearTarget(void) 243 211 { 244 return TunerSet("target", "0.0.0.0:0");212 return hdhomerun_device_set_tuner_target(_hdhomerun_device, "none") > 0; 245 213 } 246 214 247 215 bool HDHRChannel::SetChannelByString(const QString &channum) … … 347 315 if (mpeg_prog_num && (GetTuningMode() == "mpeg")) 348 316 { 349 317 QString pnum = QString::number(mpeg_prog_num); 350 _ignore_filters = QString::null != TunerSet("program", pnum, false); 318 _ignore_filters = (hdhomerun_device_set_tuner_program( 319 _hdhomerun_device, pnum) > 0); 351 320 } 352 321 353 322 return true; … … 404 373 405 374 VERBOSE(VB_CHANNEL, LOC + "Tune()ing to " + chan); 406 375 407 if ( TunerSet("channel", chan).length())376 if (hdhomerun_device_set_tuner_channel(_hdhomerun_device, chan) > 0) 408 377 { 409 378 SetSIStandard(si_std); 410 379 return true; -
libs/libmythtv/hdhrchannel.h
16 16 // HDHomeRun headers 17 17 #ifdef USING_HDHOMERUN 18 18 #include "hdhomerun/hdhomerun.h" 19 #undef max 20 #undef min 19 21 #else 20 22 struct hdhomerun_control_sock_t { int dummy; }; 21 23 #endif … … 39 41 bool SetChannelByString(const QString &chan); 40 42 41 43 // Gets 42 bool IsOpen(void) const { return (_ control_socket!= NULL); }44 bool IsOpen(void) const { return (_hdhomerun_device != NULL); } 43 45 QString GetDevice(void) const 44 46 { return QString("%1/%2").arg(_device_id, 8, 16).arg(_tuner); } 45 47 vector<uint> GetPIDs(void) const … … 57 59 bool Tune(const DTVMultiplex &tuning, QString inputname); 58 60 59 61 private: 60 bool FindDevice(void);61 62 bool Connect(void); 62 63 bool Tune(uint frequency, QString inputname, 63 64 QString modulation, QString si_std); 64 65 66 67 struct hdhomerun_device_t *GetHDHRDevice(void); 68 65 69 bool DeviceSetTarget(unsigned short localPort); 66 70 bool DeviceClearTarget(void); 67 71 … … 74 78 bool report_error_return = true); 75 79 76 80 private: 77 hdhr_socket_t *_control_socket;81 struct hdhomerun_device_t *_hdhomerun_device; 78 82 uint _device_id; 79 83 uint _device_ip; 80 84 uint _tuner;