Ticket #7970: hdhr.patch
File hdhr.patch, 80.2 KB (added by , 14 years ago) |
---|
-
libs/libmythhdhomerun/hdhomerun.h
3 3 /* 4 4 * hdhomerun.h 5 5 * 6 * Copyright © 2006-20 08Silicondust USA Inc. <www.silicondust.com>.6 * Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>. 7 7 * 8 8 * This library is free software; you can redistribute it and/or 9 9 * modify it under the terms of the GNU Lesser General Public … … 35 35 #include "hdhomerun_os.h" 36 36 #include "hdhomerun_types.h" 37 37 #include "hdhomerun_pkt.h" 38 #include "hdhomerun_sock.h" 38 39 #include "hdhomerun_debug.h" 39 40 #include "hdhomerun_discover.h" 40 41 #include "hdhomerun_control.h" -
libs/libmythhdhomerun/hdhomerun_debug.c
1 1 /* 2 2 * hdhomerun_debug.c 3 3 * 4 * Copyright © 2006 Silicondust USA Inc. <www.silicondust.com>.4 * Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>. 5 5 * 6 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 … … 44 44 #define HDHOMERUN_DEBUG_HOST "debug.silicondust.com" 45 45 #endif 46 46 #if !defined(HDHOMERUN_DEBUG_PORT) 47 #define HDHOMERUN_DEBUG_PORT "8002"47 #define HDHOMERUN_DEBUG_PORT 8002 48 48 #endif 49 49 50 #define HDHOMERUN_DEBUG_CONNECT_RETRY_TIME 30000 51 #define HDHOMERUN_DEBUG_CONNECT_TIMEOUT 10000 52 #define HDHOMERUN_DEBUG_SEND_TIMEOUT 10000 53 50 54 struct hdhomerun_debug_message_t 51 55 { 52 56 struct hdhomerun_debug_message_t *next; … … 73 77 74 78 char *file_name; 75 79 FILE *file_fp; 76 int sock;80 hdhomerun_sock_t sock; 77 81 }; 78 82 79 83 static THREAD_FUNC_PREFIX hdhomerun_debug_thread_execute(void *arg); … … 85 89 return NULL; 86 90 } 87 91 88 dbg->sock = -1;92 dbg->sock = HDHOMERUN_SOCK_INVALID; 89 93 90 94 pthread_mutex_init(&dbg->print_lock, NULL); 91 95 pthread_mutex_init(&dbg->queue_lock, NULL); … … 117 121 if (dbg->file_fp) { 118 122 fclose(dbg->file_fp); 119 123 } 120 if (dbg->sock != -1) {121 close(dbg->sock);124 if (dbg->sock != HDHOMERUN_SOCK_INVALID) { 125 hdhomerun_sock_destroy(dbg->sock); 122 126 } 123 127 124 128 free(dbg); … … 132 136 dbg->file_fp = NULL; 133 137 } 134 138 135 if (dbg->sock != -1) {136 close(dbg->sock);137 dbg->sock = -1;139 if (dbg->sock != HDHOMERUN_SOCK_INVALID) { 140 hdhomerun_sock_destroy(dbg->sock); 141 dbg->sock = HDHOMERUN_SOCK_INVALID; 138 142 } 139 143 } 140 144 … … 251 255 return; 252 256 } 253 257 254 msleep (10);258 msleep_approx(10); 255 259 } 256 260 } 257 261 … … 372 376 } 373 377 374 378 /* Send lock held by caller */ 375 #if defined(__CYGWIN__)376 379 static bool_t hdhomerun_debug_output_message_sock(struct hdhomerun_debug_t *dbg, struct hdhomerun_debug_message_t *message) 377 380 { 378 return TRUE; 379 } 380 #else 381 static bool_t hdhomerun_debug_output_message_sock(struct hdhomerun_debug_t *dbg, struct hdhomerun_debug_message_t *message) 382 { 383 if (dbg->sock == -1) { 381 if (dbg->sock == HDHOMERUN_SOCK_INVALID) { 384 382 uint64_t current_time = getcurrenttime(); 385 383 if (current_time < dbg->connect_delay) { 386 384 return FALSE; 387 385 } 388 dbg->connect_delay = current_time + 30*1000;386 dbg->connect_delay = current_time + HDHOMERUN_DEBUG_CONNECT_RETRY_TIME; 389 387 390 dbg->sock = (int)socket(AF_INET, SOCK_STREAM, 0);391 if (dbg->sock == -1) {388 dbg->sock = hdhomerun_sock_create_tcp(); 389 if (dbg->sock == HDHOMERUN_SOCK_INVALID) { 392 390 return FALSE; 393 391 } 394 392 395 struct addrinfo hints; 396 memset(&hints, 0, sizeof(hints)); 397 hints.ai_family = AF_INET; 398 hints.ai_socktype = SOCK_STREAM; 399 hints.ai_protocol = IPPROTO_TCP; 400 401 struct addrinfo *sock_info; 402 if (getaddrinfo(HDHOMERUN_DEBUG_HOST, HDHOMERUN_DEBUG_PORT, &hints, &sock_info) != 0) { 393 uint32_t remote_addr = hdhomerun_sock_getaddrinfo_addr(dbg->sock, HDHOMERUN_DEBUG_HOST); 394 if (remote_addr == 0) { 403 395 hdhomerun_debug_close_internal(dbg); 404 396 return FALSE; 405 397 } 406 if (connect(dbg->sock, sock_info->ai_addr, (int)sock_info->ai_addrlen) != 0) { 407 freeaddrinfo(sock_info);398 399 if (!hdhomerun_sock_connect(dbg->sock, remote_addr, HDHOMERUN_DEBUG_PORT, HDHOMERUN_DEBUG_CONNECT_TIMEOUT)) { 408 400 hdhomerun_debug_close_internal(dbg); 409 401 return FALSE; 410 402 } 411 freeaddrinfo(sock_info);412 403 } 413 404 414 405 size_t length = strlen(message->buffer); 415 if ( send(dbg->sock, (char *)message->buffer, (int)length, 0) != length) {406 if (!hdhomerun_sock_send(dbg->sock, message->buffer, length, HDHOMERUN_DEBUG_SEND_TIMEOUT)) { 416 407 hdhomerun_debug_close_internal(dbg); 417 408 return FALSE; 418 409 } 419 410 420 411 return TRUE; 421 412 } 422 #endif423 413 424 414 static bool_t hdhomerun_debug_output_message(struct hdhomerun_debug_t *dbg, struct hdhomerun_debug_message_t *message) 425 415 { … … 466 456 pthread_mutex_unlock(&dbg->queue_lock); 467 457 468 458 if (!message) { 469 msleep (250);459 msleep_approx(250); 470 460 continue; 471 461 } 472 462 … … 476 466 } 477 467 478 468 if (!hdhomerun_debug_output_message(dbg, message)) { 479 msleep (250);469 msleep_approx(250); 480 470 continue; 481 471 } 482 472 -
libs/libmythhdhomerun/libmythhdhomerun.pro
10 10 11 11 QMAKE_CLEAN += $(TARGET) $(TARGETA) $(TARGETD) $(TARGET0) $(TARGET1) $(TARGET2) 12 12 13 HEADERS += hdhomerun.h hdhomerun_os.h hdhomerun_ types.h13 HEADERS += hdhomerun.h hdhomerun_os.h hdhomerun_sock.h hdhomerun_types.h 14 14 15 15 HEADERS += hdhomerun_channels.h hdhomerun_channelscan.h hdhomerun_control.h 16 HEADERS += hdhomerun_debug.h hdhomerun_device.h hdhomerun_dhcp.h 17 HEADERS += hdhomerun_discover.h hdhomerun_pkt.h hdhomerun_video.h 16 HEADERS += hdhomerun_debug.h hdhomerun_device.h 18 17 HEADERS += hdhomerun_device_selector.h 18 HEADERS += hdhomerun_discover.h hdhomerun_os_posix.h 19 HEADERS += hdhomerun_pkt.h hdhomerun_video.h 19 20 21 SOURCES += hdhomerun_config.c 22 20 23 SOURCES += hdhomerun_channels.c hdhomerun_channelscan.c hdhomerun_control.c 21 SOURCES += hdhomerun_debug.c hdhomerun_device.c hdhomerun_dhcp.c 22 SOURCES += hdhomerun_discover.c hdhomerun_pkt.c hdhomerun_video.c 24 SOURCES += hdhomerun_debug.c hdhomerun_device.c 23 25 SOURCES += hdhomerun_device_selector.c 26 SOURCES += hdhomerun_discover.c hdhomerun_os_posix.c 27 SOURCES += hdhomerun_pkt.c hdhomerun_video.c 24 28 29 30 unix:SOURCES += hdhomerun_sock_posix.c 31 25 32 mingw { 26 33 HEADERS += hdhomerun_os_windows.h 34 SOURCES += hdhomerun_os_windows.c 35 SOURCES += hdhomerun_sock_windows.c 27 36 LIBS += -lws2_32 -liphlpapi -lpthread 28 37 } 29 38 -
libs/libmythhdhomerun/hdhomerun_config.c
286 286 } 287 287 288 288 cmd_scan_printf(fp, "SCANNING: %lu (%s)\n", 289 result.frequency, result.channel_str289 (unsigned long)result.frequency, result.channel_str 290 290 ); 291 291 292 292 ret = hdhomerun_device_channelscan_detect(hd, &result); … … 364 364 size_t actual_size; 365 365 uint8_t *ptr = hdhomerun_device_stream_recv(hd, VIDEO_DATA_BUFFER_SIZE_1S, &actual_size); 366 366 if (!ptr) { 367 msleep (64);367 msleep_approx(64); 368 368 continue; 369 369 } 370 370 … … 381 381 next_progress = loop_start_time + 1000; 382 382 } 383 383 384 /* Windows - indicate activity to suppress auto sleep mode. */ 385 #if defined(__WINDOWS__) 386 SetThreadExecutionState(ES_SYSTEM_REQUIRED); 387 #endif 388 389 /* Video stats. */ 384 390 hdhomerun_device_get_video_stats(hd, &stats_cur); 385 391 386 392 if (stats_cur.overflow_error_count > stats_old.overflow_error_count) { … … 404 410 continue; 405 411 } 406 412 407 msleep (delay);413 msleep_approx(delay); 408 414 } 409 415 410 416 if (fp) { … … 440 446 fclose(fp); 441 447 return -1; 442 448 } 443 sleep(2);449 msleep_minimum(2000); 444 450 445 451 printf("upgrading firmware...\n"); 446 sleep(8);452 msleep_minimum(8000); 447 453 448 454 printf("rebooting...\n"); 449 455 int count = 0; … … 460 466 return -1; 461 467 } 462 468 463 sleep(1);469 msleep_minimum(1000); 464 470 } 465 471 466 472 printf("upgrade complete - now running firmware %s\n", version_str); -
libs/libmythhdhomerun/hdhomerun_video.c
34 34 35 35 struct hdhomerun_video_sock_t { 36 36 pthread_mutex_t lock; 37 struct hdhomerun_debug_t *dbg; 38 39 int sock; 40 uint32_t multicast_ip; 41 42 volatile size_t head; 43 volatile size_t tail; 37 44 uint8_t *buffer; 38 45 size_t buffer_size; 39 volatile size_t head;40 volatile size_t tail;41 46 size_t advance; 47 48 pthread_t thread; 42 49 volatile bool_t terminate; 43 pthread_t thread; 44 int sock; 45 uint32_t rtp_sequence; 46 struct hdhomerun_debug_t *dbg; 50 47 51 volatile uint32_t packet_count; 48 52 volatile uint32_t transport_error_count; 49 53 volatile uint32_t network_error_count; 50 54 volatile uint32_t sequence_error_count; 51 55 volatile uint32_t overflow_error_count; 56 57 volatile uint32_t rtp_sequence; 52 58 volatile uint8_t sequence[0x2000]; 53 59 }; 54 60 … … 64 70 } 65 71 66 72 vs->dbg = dbg; 67 vs->sock = -1;73 vs->sock = HDHOMERUN_SOCK_INVALID; 68 74 pthread_mutex_init(&vs->lock, NULL); 69 75 70 76 /* Reset sequence tracking. */ … … 86 92 } 87 93 88 94 /* Create socket. */ 89 vs->sock = (int)socket(AF_INET, SOCK_DGRAM, 0);90 if (vs->sock == -1) {95 vs->sock = hdhomerun_sock_create_udp(); 96 if (vs->sock == HDHOMERUN_SOCK_INVALID) { 91 97 hdhomerun_debug_printf(dbg, "hdhomerun_video_create: failed to allocate socket\n"); 92 98 goto error; 93 99 } … … 96 102 int rx_size = 1024 * 1024; 97 103 setsockopt(vs->sock, SOL_SOCKET, SO_RCVBUF, (char *)&rx_size, sizeof(rx_size)); 98 104 99 /* Set timeouts. */100 setsocktimeout(vs->sock, SOL_SOCKET, SO_SNDTIMEO, 1000);101 setsocktimeout(vs->sock, SOL_SOCKET, SO_RCVTIMEO, 1000);102 103 105 /* Bind socket. */ 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) { 106 if (!hdhomerun_sock_bind(vs->sock, INADDR_ANY, listen_port)) { 110 107 hdhomerun_debug_printf(dbg, "hdhomerun_video_create: failed to bind socket (port %u)\n", listen_port); 111 108 goto error; 112 109 } … … 121 118 return vs; 122 119 123 120 error: 124 if (vs->sock != -1) {125 close(vs->sock);121 if (vs->sock != HDHOMERUN_SOCK_INVALID) { 122 hdhomerun_sock_destroy(vs->sock); 126 123 } 127 124 if (vs->buffer) { 128 125 free(vs->buffer); … … 136 133 vs->terminate = TRUE; 137 134 pthread_join(vs->thread, NULL); 138 135 139 close(vs->sock);136 hdhomerun_sock_destroy(vs->sock); 140 137 free(vs->buffer); 141 138 142 139 free(vs); … … 144 141 145 142 uint16_t hdhomerun_video_get_local_port(struct hdhomerun_video_sock_t *vs) 146 143 { 147 struct sockaddr_in sock_addr; 148 socklen_t sockaddr_size = sizeof(sock_addr); 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); 144 uint16_t port = hdhomerun_sock_getsockname_port(vs->sock); 145 if (port == 0) { 146 hdhomerun_debug_printf(vs->dbg, "hdhomerun_video_get_local_port: getsockname failed (%d)\n", hdhomerun_sock_getlasterror()); 151 147 return 0; 152 148 } 153 149 154 return ntohs(sock_addr.sin_port);150 return port; 155 151 } 156 152 153 int hdhomerun_video_join_multicast_group(struct hdhomerun_video_sock_t *vs, uint32_t multicast_ip, uint32_t local_ip) 154 { 155 if (vs->multicast_ip != 0) { 156 hdhomerun_video_leave_multicast_group(vs); 157 } 158 159 struct ip_mreq imr; 160 memset(&imr, 0, sizeof(imr)); 161 imr.imr_multiaddr.s_addr = htonl(multicast_ip); 162 imr.imr_interface.s_addr = htonl(local_ip); 163 164 if (setsockopt(vs->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char *)&imr, sizeof(imr)) != 0) { 165 hdhomerun_debug_printf(vs->dbg, "hdhomerun_video_join_multicast_group: setsockopt failed (%d)\n", hdhomerun_sock_getlasterror()); 166 return -1; 167 } 168 169 vs->multicast_ip = multicast_ip; 170 return 1; 171 } 172 173 int hdhomerun_video_leave_multicast_group(struct hdhomerun_video_sock_t *vs) 174 { 175 if (vs->multicast_ip == 0) { 176 return 1; 177 } 178 179 struct ip_mreq imr; 180 memset(&imr, 0, sizeof(imr)); 181 imr.imr_multiaddr.s_addr = htonl(vs->multicast_ip); 182 imr.imr_interface.s_addr = htonl(INADDR_ANY); 183 184 if (setsockopt(vs->sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, (const char *)&imr, sizeof(imr)) != 0) { 185 hdhomerun_debug_printf(vs->dbg, "hdhomerun_video_leave_multicast_group: setsockopt failed (%d)\n", hdhomerun_sock_getlasterror()); 186 } 187 188 vs->multicast_ip = 0; 189 return 1; 190 } 191 157 192 static void hdhomerun_video_stats_ts_pkt(struct hdhomerun_video_sock_t *vs, uint8_t *ptr) 158 193 { 159 194 uint16_t packet_identifier = ((uint16_t)(ptr[1] & 0x1F) << 8) | (uint16_t)ptr[2]; … … 168 203 return; 169 204 } 170 205 171 uint8_t continuity_counter = ptr[3] & 0x0F; 206 uint8_t sequence = ptr[3] & 0x0F; 207 172 208 uint8_t previous_sequence = vs->sequence[packet_identifier]; 209 vs->sequence[packet_identifier] = sequence; 173 210 174 if (continuity_counter == ((previous_sequence + 1) & 0x0F)) { 175 vs->sequence[packet_identifier] = continuity_counter; 211 if (previous_sequence == 0xFF) { 176 212 return; 177 213 } 178 if (previous_sequence == 0xFF) { 179 vs->sequence[packet_identifier] = continuity_counter; 214 if (sequence == ((previous_sequence + 1) & 0x0F)) { 180 215 return; 181 216 } 182 if ( continuity_counter== previous_sequence) {217 if (sequence == previous_sequence) { 183 218 return; 184 219 } 185 220 186 221 vs->sequence_error_count++; 187 vs->sequence[packet_identifier] = continuity_counter;188 222 } 189 223 190 224 static void hdhomerun_video_parse_rtp(struct hdhomerun_video_sock_t *vs, struct hdhomerun_pkt_t *pkt) … … 193 227 uint32_t rtp_sequence = hdhomerun_pkt_read_u16(pkt); 194 228 pkt->pos += 8; 195 229 196 if (rtp_sequence != ((vs->rtp_sequence + 1) & 0xFFFF)) { 197 if (vs->rtp_sequence != 0xFFFFFFFF) { 198 vs->network_error_count++; 230 uint32_t previous_rtp_sequence = vs->rtp_sequence; 231 vs->rtp_sequence = rtp_sequence; 199 232 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 } 233 /* Initial case - first packet received. */ 234 if (previous_rtp_sequence == 0xFFFFFFFF) { 235 return; 206 236 } 207 237 208 vs->rtp_sequence = rtp_sequence; 238 /* Normal case - next sequence number. */ 239 if (rtp_sequence == ((previous_rtp_sequence + 1) & 0xFFFF)) { 240 return; 241 } 242 243 /* Error case - sequence missed. */ 244 vs->network_error_count++; 245 246 /* Restart pid sequence check after packet loss. */ 247 int i; 248 for (i = 0; i < 0x2000; i++) { 249 vs->sequence[i] = 0xFF; 250 } 209 251 } 210 252 211 253 static THREAD_FUNC_PREFIX hdhomerun_video_thread_execute(void *arg) … … 218 260 hdhomerun_pkt_reset(pkt); 219 261 220 262 /* Receive. */ 221 int length = recv(vs->sock, (char *)pkt->end, VIDEO_RTP_DATA_PACKET_SIZE, 0); 263 size_t length = VIDEO_RTP_DATA_PACKET_SIZE; 264 if (!hdhomerun_sock_recv(vs->sock, pkt->end, &length, 25)) { 265 continue; 266 } 267 222 268 pkt->end += length; 223 269 224 270 if (length == VIDEO_RTP_DATA_PACKET_SIZE) { … … 227 273 } 228 274 229 275 if (length != VIDEO_DATA_PACKET_SIZE) { 230 if (length > 0) { 231 /* Data received but not valid - ignore. */ 232 continue; 233 } 234 if (sock_getlasterror_socktimeout) { 235 /* Wait for more data. */ 236 continue; 237 } 238 vs->terminate = TRUE; 239 return NULL; 276 /* Data received but not valid - ignore. */ 277 continue; 240 278 } 241 279 242 280 pthread_mutex_lock(&vs->lock); … … 269 307 continue; 270 308 } 271 309 272 /* Atomic update. */273 310 vs->head = head; 274 311 275 312 pthread_mutex_unlock(&vs->lock); … … 291 328 tail -= vs->buffer_size; 292 329 } 293 330 294 /* Atomic update. */295 331 vs->tail = tail; 296 332 } 297 333 … … 334 370 vs->tail = vs->head; 335 371 vs->advance = 0; 336 372 337 /* can't use memset bcs sequence is volatile */373 vs->rtp_sequence = 0xFFFFFFFF; 338 374 int i; 339 for (i = 0; i < sizeof(vs->sequence) / sizeof(uint8_t) ; i++)375 for (i = 0; i < 0x2000; i++) { 340 376 vs->sequence[i] = 0xFF; 377 } 341 378 342 vs->rtp_sequence = 0xFFFFFFFF;343 344 379 vs->packet_count = 0; 345 380 vs->transport_error_count = 0; 346 381 vs->network_error_count = 0; … … 355 390 struct hdhomerun_video_stats_t stats; 356 391 hdhomerun_video_get_stats(vs, &stats); 357 392 358 hdhomerun_debug_printf(vs->dbg, "video sock: pkt=%l d 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_count393 hdhomerun_debug_printf(vs->dbg, "video sock: pkt=%lu net=%lu te=%lu miss=%lu drop=%lu\n", 394 (unsigned long)stats.packet_count, (unsigned long)stats.network_error_count, 395 (unsigned long)stats.transport_error_count, (unsigned long)stats.sequence_error_count, 396 (unsigned long)stats.overflow_error_count 362 397 ); 363 398 } 364 399 -
libs/libmythhdhomerun/hdhomerun_os_posix.h
1 1 /* 2 2 * hdhomerun_os_posix.h 3 3 * 4 * Copyright © 2006-20 08Silicondust USA Inc. <www.silicondust.com>.4 * Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>. 5 5 * 6 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 … … 52 52 typedef int bool_t; 53 53 54 54 #define LIBTYPE 55 #define sock_getlasterror errno56 #define sock_getlasterror_socktimeout (errno == EAGAIN)57 55 #define console_vprintf vprintf 58 56 #define console_printf printf 59 57 #define THREAD_FUNC_PREFIX void * 60 58 61 static inline uint64_t getcurrenttime(void) 62 { 63 struct timeval t; 64 gettimeofday(&t, NULL); 65 return ((uint64_t)t.tv_sec * 1000) + (t.tv_usec / 1000); 66 } 59 #ifdef __cplusplus 60 extern "C" { 61 #endif 67 62 68 static inline int msleep(unsigned int ms) 69 { 70 uint64_t stop_time = getcurrenttime() + ms;63 extern LIBTYPE uint64_t getcurrenttime(void); 64 extern LIBTYPE void msleep_approx(uint64_t ms); 65 extern LIBTYPE void msleep_minimum(uint64_t ms); 71 66 72 while (1) { 73 uint64_t current_time = getcurrenttime(); 74 if (current_time >= stop_time) { 75 return 0; 76 } 77 78 uint64_t delay_s = (stop_time - current_time) / 1000; 79 if (delay_s > 0) { 80 sleep((unsigned int)delay_s); 81 continue; 82 } 83 84 uint64_t delay_us = (stop_time - current_time) * 1000; 85 usleep((unsigned int)delay_us); 86 } 67 #ifdef __cplusplus 87 68 } 88 89 static inline int setsocktimeout(int s, int level, int optname, uint64_t timeout) 90 { 91 struct timeval t; 92 t.tv_sec = timeout / 1000; 93 t.tv_usec = (timeout % 1000) * 1000; 94 return setsockopt(s, level, optname, (char *)&t, sizeof(t)); 95 } 69 #endif -
libs/libmythhdhomerun/hdhomerun_video.h
71 71 extern LIBTYPE uint16_t hdhomerun_video_get_local_port(struct hdhomerun_video_sock_t *vs); 72 72 73 73 /* 74 * Join/leave multicast group. 75 */ 76 extern LIBTYPE int hdhomerun_video_join_multicast_group(struct hdhomerun_video_sock_t *vs, uint32_t multicast_ip, uint32_t local_ip); 77 extern LIBTYPE int hdhomerun_video_leave_multicast_group(struct hdhomerun_video_sock_t *vs); 78 79 /* 74 80 * Read data from buffer. 75 81 * 76 82 * size_t max_size: The maximum amount of data to be returned. -
libs/libmythhdhomerun/hdhomerun_channelscan.c
1 1 /* 2 2 * hdhomerun_channelscan.c 3 3 * 4 * Copyright © 2007-20 08Silicondust USA Inc. <www.silicondust.com>.4 * Copyright © 2007-2010 Silicondust USA Inc. <www.silicondust.com>. 5 5 * 6 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 … … 99 99 return 1; 100 100 } 101 101 102 msleep (250);102 msleep_approx(250); 103 103 } 104 104 } 105 105 … … 303 303 break; 304 304 } 305 305 306 msleep (250);306 msleep_approx(250); 307 307 } 308 308 309 309 /* Lock => skip overlapping channels. */ -
libs/libmythhdhomerun/hdhomerun_discover.c
1 1 /* 2 2 * hdhomerun_discover.c 3 3 * 4 * Copyright © 2006-20 07Silicondust USA Inc. <www.silicondust.com>.4 * Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>. 5 5 * 6 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 … … 44 44 #endif 45 45 #endif 46 46 47 #include <sys/param.h> // Defines BSD on FreeBSD and Mac OS X48 #if defined(__linux__) || defined(__APPLE__) || defined(BSD)49 # include <ifaddrs.h>50 # define USE_IFADDRS 151 # include <sys/select.h>52 #endif53 54 47 #define HDHOMERUN_DISOCVER_MAX_SOCK_COUNT 16 55 48 56 49 struct hdhomerun_discover_sock_t { 57 int sock; 50 hdhomerun_sock_t sock; 51 bool_t detected; 58 52 uint32_t local_ip; 59 53 uint32_t subnet_mask; 60 54 }; … … 66 60 struct hdhomerun_pkt_t rx_pkt; 67 61 }; 68 62 69 static bool_t hdhomerun_discover_sock_ create(struct hdhomerun_discover_t *ds, uint32_t local_ip, uint32_t subnet_mask)63 static bool_t hdhomerun_discover_sock_add(struct hdhomerun_discover_t *ds, uint32_t local_ip, uint32_t subnet_mask) 70 64 { 65 unsigned int i; 66 for (i = 1; i < ds->sock_count; i++) { 67 struct hdhomerun_discover_sock_t *dss = &ds->socks[i]; 68 69 if ((dss->local_ip == local_ip) && (dss->subnet_mask == subnet_mask)) { 70 dss->detected = TRUE; 71 return TRUE; 72 } 73 } 74 71 75 if (ds->sock_count >= HDHOMERUN_DISOCVER_MAX_SOCK_COUNT) { 72 76 return FALSE; 73 77 } 74 78 75 79 /* Create socket. */ 76 int sock = (int)socket(AF_INET, SOCK_DGRAM, 0);77 if (sock == -1) {80 hdhomerun_sock_t sock = hdhomerun_sock_create_udp(); 81 if (sock == HDHOMERUN_SOCK_INVALID) { 78 82 return FALSE; 79 83 } 80 84 81 /* Set timeouts. */82 setsocktimeout(sock, SOL_SOCKET, SO_SNDTIMEO, 1000);83 setsocktimeout(sock, SOL_SOCKET, SO_RCVTIMEO, 1000);84 85 /* Allow broadcast. */86 int sock_opt = 1;87 setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&sock_opt, sizeof(sock_opt));88 89 85 /* Bind socket. */ 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(local_ip); 94 sock_addr.sin_port = htons(0); 95 if (bind(sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) { 96 close(sock); 86 if (!hdhomerun_sock_bind(sock, local_ip, 0)) { 87 hdhomerun_sock_destroy(sock); 97 88 return FALSE; 98 89 } 99 90 100 91 /* Write sock entry. */ 101 92 struct hdhomerun_discover_sock_t *dss = &ds->socks[ds->sock_count++]; 102 93 dss->sock = sock; 94 dss->detected = TRUE; 103 95 dss->local_ip = local_ip; 104 96 dss->subnet_mask = subnet_mask; 105 97 106 98 return TRUE; 107 99 } 108 100 101 struct hdhomerun_discover_t *hdhomerun_discover_create(void) 102 { 103 struct hdhomerun_discover_t *ds = (struct hdhomerun_discover_t *)calloc(1, sizeof(struct hdhomerun_discover_t)); 104 if (!ds) { 105 return NULL; 106 } 107 108 /* Create a routable socket (always first entry). */ 109 if (!hdhomerun_discover_sock_add(ds, 0, 0)) { 110 free(ds); 111 return NULL; 112 } 113 114 /* Success. */ 115 return ds; 116 } 117 118 void hdhomerun_discover_destroy(struct hdhomerun_discover_t *ds) 119 { 120 unsigned int i; 121 for (i = 0; i < ds->sock_count; i++) { 122 struct hdhomerun_discover_sock_t *dss = &ds->socks[i]; 123 hdhomerun_sock_destroy(dss->sock); 124 } 125 126 free(ds); 127 } 128 109 129 #if defined(USE_IPHLPAPI) 110 static void hdhomerun_discover_sock_detect (struct hdhomerun_discover_t *ds)130 static void hdhomerun_discover_sock_detect_internal(struct hdhomerun_discover_t *ds) 111 131 { 112 132 PIP_ADAPTER_INFO pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO)); 113 133 ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO); … … 138 158 continue; 139 159 } 140 160 141 hdhomerun_discover_sock_ create(ds, local_ip, mask);161 hdhomerun_discover_sock_add(ds, local_ip, mask); 142 162 pIPAddr = pIPAddr->Next; 143 163 } 144 164 … … 150 170 151 171 #else 152 172 153 static void hdhomerun_discover_sock_detect (struct hdhomerun_discover_t *ds)173 static void hdhomerun_discover_sock_detect_internal(struct hdhomerun_discover_t *ds) 154 174 { 155 int fd = socket(AF_INET, SOCK_DGRAM, 0); 156 if (fd == -1) { 157 return; 158 } 175 int sock = ds->socks[0].sock; 159 176 160 177 struct ifconf ifc; 161 178 uint8_t buf[8192]; … … 164 181 165 182 memset(buf, 0, sizeof(buf)); 166 183 167 if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) { 168 close(fd); 184 if (ioctl(sock, SIOCGIFCONF, &ifc) != 0) { 169 185 return; 170 186 } 171 187 … … 176 192 struct ifreq *ifr = (struct ifreq *)ptr; 177 193 ptr += _SIZEOF_ADDR_IFREQ(*ifr); 178 194 179 if (ioctl( fd, SIOCGIFADDR, ifr) != 0) {195 if (ioctl(sock, SIOCGIFADDR, ifr) != 0) { 180 196 continue; 181 197 } 182 198 struct sockaddr_in *addr_in = (struct sockaddr_in *)&(ifr->ifr_addr); … … 185 201 continue; 186 202 } 187 203 188 if (ioctl( fd, SIOCGIFNETMASK, ifr) != 0) {204 if (ioctl(sock, SIOCGIFNETMASK, ifr) != 0) { 189 205 continue; 190 206 } 191 207 struct sockaddr_in *mask_in = (struct sockaddr_in *)&(ifr->ifr_addr); 192 208 uint32_t mask = ntohl(mask_in->sin_addr.s_addr); 193 209 194 hdhomerun_discover_sock_ create(ds, local_ip, mask);210 hdhomerun_discover_sock_add(ds, local_ip, mask); 195 211 } 196 197 close(fd);198 212 } 199 213 #endif 200 214 201 static struct hdhomerun_discover_t *hdhomerun_discover_create(void)215 static void hdhomerun_discover_sock_detect(struct hdhomerun_discover_t *ds) 202 216 { 203 struct hdhomerun_discover_t *ds = (struct hdhomerun_discover_t *)calloc(1, sizeof(struct hdhomerun_discover_t)); 204 if (!ds) { 205 return NULL; 217 unsigned int i; 218 for (i = 1; i < ds->sock_count; i++) { 219 struct hdhomerun_discover_sock_t *dss = &ds->socks[i]; 220 dss->detected = FALSE; 206 221 } 207 222 208 /* Create a routable socket. */ 209 if (!hdhomerun_discover_sock_create(ds, 0, 0)) { 210 free(ds); 211 return NULL; 212 } 223 hdhomerun_discover_sock_detect_internal(ds); 213 224 214 /* Detect & create local sockets. */ 215 hdhomerun_discover_sock_detect(ds); 216 217 /* Success. */ 218 return ds; 219 } 220 221 static void hdhomerun_discover_destroy(struct hdhomerun_discover_t *ds) 222 { 223 unsigned int i; 224 for (i = 0; i < ds->sock_count; i++) { 225 struct hdhomerun_discover_sock_t *dss = &ds->socks[i]; 226 close(dss->sock); 225 struct hdhomerun_discover_sock_t *src = &ds->socks[1]; 226 struct hdhomerun_discover_sock_t *dst = &ds->socks[1]; 227 unsigned int count = 1; 228 for (i = 1; i < ds->sock_count; i++) { 229 if (!src->detected) { 230 hdhomerun_sock_destroy(src->sock); 231 src++; 232 continue; 233 } 234 if (dst != src) { 235 *dst = *src; 236 } 237 src++; 238 dst++; 239 count++; 227 240 } 228 241 229 free(ds);242 ds->sock_count = count; 230 243 } 231 244 232 245 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) … … 242 255 hdhomerun_pkt_write_u32(tx_pkt, device_id); 243 256 hdhomerun_pkt_seal_frame(tx_pkt, HDHOMERUN_TYPE_DISCOVER_REQ); 244 257 245 struct sockaddr_in sock_addr; 246 memset(&sock_addr, 0, sizeof(sock_addr)); 247 sock_addr.sin_family = AF_INET; 248 sock_addr.sin_addr.s_addr = htonl(target_ip); 249 sock_addr.sin_port = htons(HDHOMERUN_DISCOVER_UDP_PORT); 250 251 int length = (int)(tx_pkt->end - tx_pkt->start); 252 if (sendto(dss->sock, (char *)tx_pkt->start, length, 0, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != length) { 253 return FALSE; 254 } 255 256 return TRUE; 258 return hdhomerun_sock_sendto(dss->sock, target_ip, HDHOMERUN_DISCOVER_UDP_PORT, tx_pkt->start, tx_pkt->end - tx_pkt->start, 0); 257 259 } 258 260 259 261 static bool_t hdhomerun_discover_send_wildcard_ip(struct hdhomerun_discover_t *ds, uint32_t device_type, uint32_t device_id) … … 313 315 314 316 static bool_t hdhomerun_discover_send(struct hdhomerun_discover_t *ds, uint32_t target_ip, uint32_t device_type, uint32_t device_id) 315 317 { 316 if (target_ip != 0) { 318 if (target_ip == 0) { 319 return hdhomerun_discover_send_wildcard_ip(ds, device_type, device_id); 320 } else { 317 321 return hdhomerun_discover_send_target_ip(ds, target_ip, device_type, device_id); 318 322 } 319 320 return hdhomerun_discover_send_wildcard_ip(ds, device_type, device_id);321 323 } 322 324 323 static int hdhomerun_discover_recv_internal(struct hdhomerun_discover_t *ds, struct hdhomerun_discover_sock_t *dss, struct hdhomerun_discover_device_t *result)325 static bool_t hdhomerun_discover_recv_internal(struct hdhomerun_discover_t *ds, struct hdhomerun_discover_sock_t *dss, struct hdhomerun_discover_device_t *result) 324 326 { 325 327 struct hdhomerun_pkt_t *rx_pkt = &ds->rx_pkt; 326 328 hdhomerun_pkt_reset(rx_pkt); 327 329 328 struct sockaddr_in sock_addr; 329 memset(&sock_addr, 0, sizeof(sock_addr)); 330 socklen_t sockaddr_size = sizeof(sock_addr); 331 332 int rx_length = recvfrom(dss->sock, (char *)rx_pkt->end, (int)(rx_pkt->limit - rx_pkt->end), 0, (struct sockaddr *)&sock_addr, &sockaddr_size); 333 if (rx_length <= 0) { 334 /* Don't return error - windows machine on VPN can sometimes cause a sock error here but otherwise works. */ 335 return 0; 330 uint32_t remote_addr; 331 uint16_t remote_port; 332 size_t length = rx_pkt->limit - rx_pkt->end; 333 if (!hdhomerun_sock_recvfrom(dss->sock, &remote_addr, &remote_port, rx_pkt->end, &length, 0)) { 334 return FALSE; 336 335 } 337 rx_pkt->end += rx_length;338 336 337 rx_pkt->end += length; 338 339 339 uint16_t type; 340 340 if (hdhomerun_pkt_open_frame(rx_pkt, &type) <= 0) { 341 return 0;341 return FALSE; 342 342 } 343 343 if (type != HDHOMERUN_TYPE_DISCOVER_RPY) { 344 return 0;344 return FALSE; 345 345 } 346 346 347 result->ip_addr = ntohl(sock_addr.sin_addr.s_addr);347 result->ip_addr = remote_addr; 348 348 result->device_type = 0; 349 349 result->device_id = 0; 350 350 … … 378 378 rx_pkt->pos = next; 379 379 } 380 380 381 return 1;381 return TRUE; 382 382 } 383 383 384 static int hdhomerun_discover_recv(struct hdhomerun_discover_t *ds, struct hdhomerun_discover_device_t *result)384 static bool_t hdhomerun_discover_recv(struct hdhomerun_discover_t *ds, struct hdhomerun_discover_device_t *result) 385 385 { 386 struct timeval t;387 t.tv_sec = 0;388 t.tv_usec = 250000;389 390 fd_set readfds;391 FD_ZERO(&readfds);392 int max_sock = -1;393 394 386 unsigned int i; 395 387 for (i = 0; i < ds->sock_count; i++) { 396 388 struct hdhomerun_discover_sock_t *dss = &ds->socks[i]; 397 FD_SET(dss->sock, &readfds);398 if (dss->sock > max_sock) {399 max_sock = dss->sock;400 }401 }402 389 403 if (select(max_sock+1, &readfds, NULL, NULL, &t) < 0) { 404 return -1; 405 } 406 407 for (i = 0; i < ds->sock_count; i++) { 408 struct hdhomerun_discover_sock_t *dss = &ds->socks[i]; 409 if (!FD_ISSET(dss->sock, &readfds)) { 410 continue; 390 if (hdhomerun_discover_recv_internal(ds, dss, result)) { 391 return TRUE; 411 392 } 412 413 if (hdhomerun_discover_recv_internal(ds, dss, result) <= 0) {414 continue;415 }416 417 return 1;418 393 } 419 394 420 return 0;395 return FALSE; 421 396 } 422 397 423 static struct hdhomerun_discover_device_t *hdhomerun_discover_find_in_list(struct hdhomerun_discover_device_t result_list[], int count, uint32_t ip_addr)398 static struct hdhomerun_discover_device_t *hdhomerun_discover_find_in_list(struct hdhomerun_discover_device_t result_list[], int count, struct hdhomerun_discover_device_t *lookup) 424 399 { 425 400 int index; 426 401 for (index = 0; index < count; index++) { 427 struct hdhomerun_discover_device_t * result= &result_list[index];428 if ( result->ip_addr == ip_addr) {429 return result;402 struct hdhomerun_discover_device_t *entry = &result_list[index]; 403 if (memcmp(lookup, entry, sizeof(struct hdhomerun_discover_device_t)) == 0) { 404 return entry; 430 405 } 431 406 } 432 407 433 408 return NULL; 434 409 } 435 410 436 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)411 int hdhomerun_discover_find_devices(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) 437 412 { 413 hdhomerun_discover_sock_detect(ds); 414 438 415 int count = 0; 439 416 int attempt; 440 417 for (attempt = 0; attempt < 2; attempt++) { … … 443 420 } 444 421 445 422 uint64_t timeout = getcurrenttime() + 200; 446 while ( getcurrenttime() < timeout) {423 while (1) { 447 424 struct hdhomerun_discover_device_t *result = &result_list[count]; 448 425 449 i nt ret = hdhomerun_discover_recv(ds, result);450 if (ret < 0) {451 return -1;452 }453 if (ret == 0) {426 if (!hdhomerun_discover_recv(ds, result)) { 427 if (getcurrenttime() >= timeout) { 428 break; 429 } 430 msleep_approx(10); 454 431 continue; 455 432 } 456 433 … … 467 444 } 468 445 469 446 /* Ensure not already in list. */ 470 if (hdhomerun_discover_find_in_list(result_list, count, result ->ip_addr)) {447 if (hdhomerun_discover_find_in_list(result_list, count, result)) { 471 448 continue; 472 449 } 473 450 … … 484 461 485 462 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) 486 463 { 464 if (hdhomerun_discover_is_ip_multicast(target_ip)) { 465 return 0; 466 } 467 487 468 struct hdhomerun_discover_t *ds = hdhomerun_discover_create(); 488 469 if (!ds) { 489 470 return -1; 490 471 } 491 472 492 int ret = hdhomerun_discover_find_devices _internal(ds, target_ip, device_type, device_id, result_list, max_count);473 int ret = hdhomerun_discover_find_devices(ds, target_ip, device_type, device_id, result_list, max_count); 493 474 494 475 hdhomerun_discover_destroy(ds); 495 476 return ret; … … 513 494 return (checksum == 0); 514 495 } 515 496 497 bool_t hdhomerun_discover_is_ip_multicast(uint32_t ip_addr) 498 { 499 return (ip_addr >= 0xE0000000) && (ip_addr < 0xF0000000); 500 } -
libs/libmythhdhomerun/hdhomerun_discover.h
44 44 * 45 45 * The device information is stored in caller-supplied array of hdhomerun_discover_device_t vars. 46 46 * Multiple attempts are made to find devices. 47 * Execution time is 1 second.47 * Execution time is typically 400ms if max_count is not reached. 48 48 * 49 49 * Set target_ip to zero to auto-detect IP address. 50 * Set device_type to HDHOMERUN_DEVICE_TYPE_TUNER to detect HDHomeRun tuner devices. 51 * Set device_id to HDHOMERUN_DEVICE_ID_WILDCARD to detect all device ids. 50 52 * 51 53 * Returns the number of devices found. 52 54 * Retruns -1 on error. … … 54 56 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); 55 57 56 58 /* 59 * Optional: persistent discover instance available for discover polling use. 60 */ 61 extern LIBTYPE struct hdhomerun_discover_t *hdhomerun_discover_create(void); 62 extern LIBTYPE void hdhomerun_discover_destroy(struct hdhomerun_discover_t *ds); 63 extern LIBTYPE int hdhomerun_discover_find_devices(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); 64 65 /* 57 66 * Verify that the device ID given is valid. 58 67 * 59 68 * The device ID contains a self-check sequence that detects common user input errors including … … 64 73 */ 65 74 extern LIBTYPE bool_t hdhomerun_discover_validate_device_id(uint32_t device_id); 66 75 76 /* 77 * Detect if an IP address is multicast. 78 * 79 * Returns TRUE if multicast. 80 * Returns FALSE if zero, unicast, expermental, or broadcast. 81 */ 82 extern LIBTYPE bool_t hdhomerun_discover_is_ip_multicast(uint32_t ip_addr); 83 67 84 #ifdef __cplusplus 68 85 } 69 86 #endif -
libs/libmythhdhomerun/Makefile.bin
1 LIBSRCS += hdhomerun_pkt.c 2 LIBSRCS += hdhomerun_debug.c 3 LIBSRCS += hdhomerun_discover.c 1 4 2 LIBSRCS += hdhomerun_channels.c 5 3 LIBSRCS += hdhomerun_channelscan.c 6 4 LIBSRCS += hdhomerun_control.c 7 LIBSRCS += hdhomerun_ video.c5 LIBSRCS += hdhomerun_debug.c 8 6 LIBSRCS += hdhomerun_device.c 9 7 LIBSRCS += hdhomerun_device_selector.c 8 LIBSRCS += hdhomerun_discover.c 9 LIBSRCS += hdhomerun_os_posix.c 10 LIBSRCS += hdhomerun_pkt.c 11 LIBSRCS += hdhomerun_sock_posix.c 12 LIBSRCS += hdhomerun_video.c 10 13 11 14 CC := $(CROSS_COMPILE)gcc 12 15 STRIP := $(CROSS_COMPILE)strip … … 20 23 LIBEXT := .dll 21 24 LDFLAGS += -liphlpapi 22 25 else 26 OS := $(shell uname -s) 23 27 LIBEXT := .so 24 ifneq ($(findstring solaris,$(shell echo $$OSTYPE)),) 28 ifeq ($(OS),Linux) 29 LDFLAGS += -lrt 30 endif 31 ifeq ($(OS),SunOS) 25 32 LDFLAGS += -lns -lsocket 26 33 endif 27 if neq ($(findstring darwin,$(shell echo $$OSTYPE)),)34 ifeq ($(OS),Darwin) 28 35 CFLAGS += -arch i386 -arch ppc 29 36 LIBEXT := .dylib 30 37 SHARED := -dynamiclib -install_name libhdhomerun$(LIBEXT) -
libs/libmythhdhomerun/hdhomerun_device_selector.c
1 1 /* 2 2 * hdhomerun_device_selector.c 3 3 * 4 * Copyright © 2009 Silicondust USA Inc. <www.silicondust.com>.4 * Copyright © 2009-2010 Silicondust USA Inc. <www.silicondust.com>. 5 5 * 6 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 … … 68 68 free(hds); 69 69 } 70 70 71 LIBTYPE int hdhomerun_device_selector_get_device_count(struct hdhomerun_device_selector_t *hds) 72 { 73 return (int)hds->hd_count; 74 } 75 71 76 void hdhomerun_device_selector_add_device(struct hdhomerun_device_selector_t *hds, struct hdhomerun_device_t *hd) 72 77 { 73 78 size_t index; … … 129 134 return NULL; 130 135 } 131 136 132 voidhdhomerun_device_selector_load_from_file(struct hdhomerun_device_selector_t *hds, char *filename)137 int hdhomerun_device_selector_load_from_file(struct hdhomerun_device_selector_t *hds, char *filename) 133 138 { 134 139 FILE *fp = fopen(filename, "r"); 135 140 if (!fp) { 136 return ;141 return 0; 137 142 } 138 143 139 144 while(1) { … … 151 156 } 152 157 153 158 fclose(fp); 159 return (int)hds->hd_count; 154 160 } 155 161 156 162 #if defined(__WINDOWS__) 157 voidhdhomerun_device_selector_load_from_windows_registry(struct hdhomerun_device_selector_t *hds, wchar_t *wsource)163 int hdhomerun_device_selector_load_from_windows_registry(struct hdhomerun_device_selector_t *hds, wchar_t *wsource) 158 164 { 159 165 HKEY tuners_key; 160 166 LONG ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Silicondust\\HDHomeRun\\Tuners", 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &tuners_key); 161 167 if (ret != ERROR_SUCCESS) { 162 hdhomerun_debug_printf(hds->dbg, "hdhomerun_device_selector_load_from_windows_registry: failed to open tuners registry key (%ld)\n", ret);163 return ;168 hdhomerun_debug_printf(hds->dbg, "hdhomerun_device_selector_load_from_windows_registry: failed to open tuners registry key (%ld)\n", (long)ret); 169 return 0; 164 170 } 165 171 166 172 DWORD index = 0; … … 177 183 HKEY device_key; 178 184 ret = RegOpenKeyEx(tuners_key, wdevice_name, 0, KEY_QUERY_VALUE, &device_key); 179 185 if (ret != ERROR_SUCCESS) { 180 hdhomerun_debug_printf(hds->dbg, "hdhomerun_device_selector_load_from_windows_registry: failed to open registry key for %S (%ld)\n", wdevice_name, ret);186 hdhomerun_debug_printf(hds->dbg, "hdhomerun_device_selector_load_from_windows_registry: failed to open registry key for %S (%ld)\n", wdevice_name, (long)ret); 181 187 continue; 182 188 } 183 189 … … 207 213 } 208 214 209 215 RegCloseKey(tuners_key); 216 return (int)hds->hd_count; 210 217 } 211 218 #endif 212 219 … … 268 275 /* 269 276 * Test local port. 270 277 */ 271 int test_sock = (int)socket(AF_INET, SOCK_DGRAM, 0);272 if (test_sock == -1) {278 hdhomerun_sock_t test_sock = hdhomerun_sock_create_udp(); 279 if (test_sock == HDHOMERUN_SOCK_INVALID) { 273 280 hdhomerun_debug_printf(hds->dbg, "hdhomerun_device_selector_choose_test: device %s in use, failed to create test sock\n", name); 274 281 return FALSE; 275 282 } 276 283 277 struct sockaddr_in sock_addr; 278 memset(&sock_addr, 0, sizeof(sock_addr)); 279 sock_addr.sin_family = AF_INET; 280 sock_addr.sin_addr.s_addr = htonl(INADDR_ANY); 281 sock_addr.sin_port = htons((uint16_t)target_port); 282 ret = bind(test_sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)); 283 close(test_sock); 284 bool_t inuse = (hdhomerun_sock_bind(test_sock, INADDR_ANY, (uint16_t)target_port) == FALSE); 285 hdhomerun_sock_destroy(test_sock); 284 286 285 if ( ret != 0) {287 if (inuse) { 286 288 hdhomerun_debug_printf(hds->dbg, "hdhomerun_device_selector_choose_test: device %s in use by local machine\n", name); 287 289 return FALSE; 288 290 } -
libs/libmythhdhomerun/hdhomerun_device.c
37 37 struct hdhomerun_video_sock_t *vs; 38 38 struct hdhomerun_debug_t *dbg; 39 39 struct hdhomerun_channelscan_t *scan; 40 uint32_t multicast_ip; 41 uint16_t multicast_port; 40 42 uint32_t device_id; 41 43 unsigned int tuner; 42 44 uint32_t lockkey; … … 44 46 char model[32]; 45 47 }; 46 48 47 static void hdhomerun_device_set_update(struct hdhomerun_device_t *hd)49 static int hdhomerun_device_set_device_normal(struct hdhomerun_device_t *hd, uint32_t device_id, uint32_t device_ip) 48 50 { 49 /* Clear cached information. */ 50 *hd->model = 0; 51 if (!hd->cs) { 52 hd->cs = hdhomerun_control_create(0, 0, hd->dbg); 53 if (!hd->cs) { 54 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_device: failed to create control object\n"); 55 return -1; 56 } 57 } 51 58 52 /* New name. */53 sprintf(hd->name, "%08lX-%u", (unsigned long)hd->device_id, hd->tuner);54 }55 56 void hdhomerun_device_set_device(struct hdhomerun_device_t *hd, uint32_t device_id, uint32_t device_ip)57 {58 59 hdhomerun_control_set_device(hd->cs, device_id, device_ip); 59 60 60 61 if ((device_id == 0) || (device_id == HDHOMERUN_DEVICE_ID_WILDCARD)) { 61 62 device_id = hdhomerun_control_get_device_id(hd->cs); 62 63 } 63 64 65 hd->multicast_ip = 0; 66 hd->multicast_port = 0; 64 67 hd->device_id = device_id; 65 hdhomerun_device_set_update(hd); 68 hd->tuner = 0; 69 hd->lockkey = 0; 70 71 sprintf(hd->name, "%08lX-%u", (unsigned long)hd->device_id, hd->tuner); 72 hd->model[0] = 0; /* clear cached model string */ 73 74 return 1; 66 75 } 67 76 68 void hdhomerun_device_set_tuner(struct hdhomerun_device_t *hd, unsigned int tuner)77 static int hdhomerun_device_set_device_multicast(struct hdhomerun_device_t *hd, uint32_t multicast_ip) 69 78 { 79 if (hd->cs) { 80 hdhomerun_control_destroy(hd->cs); 81 hd->cs = NULL; 82 } 83 84 hd->multicast_ip = multicast_ip; 85 hd->multicast_port = 0; 86 hd->device_id = 0; 87 hd->tuner = 0; 88 hd->lockkey = 0; 89 90 unsigned long ip = multicast_ip; 91 sprintf(hd->name, "%lu.%lu.%lu.%lu", (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, (ip >> 0) & 0xFF); 92 sprintf(hd->model, "multicast"); 93 94 return 1; 95 } 96 97 int hdhomerun_device_set_device(struct hdhomerun_device_t *hd, uint32_t device_id, uint32_t device_ip) 98 { 99 if ((device_id == 0) && (device_ip == 0)) { 100 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_device: device not specified\n"); 101 return -1; 102 } 103 104 if (hdhomerun_discover_is_ip_multicast(device_ip)) { 105 return hdhomerun_device_set_device_multicast(hd, device_ip); 106 } 107 108 return hdhomerun_device_set_device_normal(hd, device_id, device_ip); 109 } 110 111 int hdhomerun_device_set_tuner(struct hdhomerun_device_t *hd, unsigned int tuner) 112 { 113 if (hd->multicast_ip != 0) { 114 if (tuner != 0) { 115 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner: tuner cannot be specified in multicast mode\n"); 116 return -1; 117 } 118 119 return 1; 120 } 121 70 122 hd->tuner = tuner; 71 hdhomerun_device_set_update(hd); 123 sprintf(hd->name, "%08lX-%u", (unsigned long)hd->device_id, hd->tuner); 124 125 return 1; 72 126 } 73 127 74 128 struct hdhomerun_device_t *hdhomerun_device_create(uint32_t device_id, uint32_t device_ip, unsigned int tuner, struct hdhomerun_debug_t *dbg) 75 129 { 76 130 struct hdhomerun_device_t *hd = (struct hdhomerun_device_t *)calloc(1, sizeof(struct hdhomerun_device_t)); 77 131 if (!hd) { 78 hdhomerun_debug_printf( dbg, "hdhomerun_device_create: failed to allocate device object\n");132 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_create: failed to allocate device object\n"); 79 133 return NULL; 80 134 } 81 135 82 136 hd->dbg = dbg; 83 137 84 hd->cs = hdhomerun_control_create(0, 0, hd->dbg); 85 if (!hd->cs) { 86 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_create: failed to create control object\n"); 138 if ((device_id == 0) && (device_ip == 0) && (tuner == 0)) { 139 return hd; 140 } 141 142 if (hdhomerun_device_set_device(hd, device_id, device_ip) <= 0) { 87 143 free(hd); 88 144 return NULL; 89 145 } 146 if (hdhomerun_device_set_tuner(hd, tuner) <= 0) { 147 free(hd); 148 return NULL; 149 } 90 150 91 hdhomerun_device_set_device(hd, device_id, device_ip);92 hdhomerun_device_set_tuner(hd, tuner);93 94 151 return hd; 95 152 } 96 153 … … 104 161 hdhomerun_video_destroy(hd->vs); 105 162 } 106 163 107 hdhomerun_control_destroy(hd->cs); 164 if (hd->cs) { 165 hdhomerun_control_destroy(hd->cs); 166 } 108 167 109 168 free(hd); 110 169 } … … 156 215 static struct hdhomerun_device_t *hdhomerun_device_create_from_str_ip(const char *device_str, struct hdhomerun_debug_t *dbg) 157 216 { 158 217 unsigned long a[4]; 159 unsigned int tuner; 160 161 if (sscanf(device_str, "%lu.%lu.%lu.%lu-%u", &a[0], &a[1], &a[2], &a[3], &tuner) != 5) { 162 tuner = 0; 218 unsigned int port = 0; 219 if (sscanf(device_str, "%lu.%lu.%lu.%lu:%u", &a[0], &a[1], &a[2], &a[3], &port) != 5) { 163 220 if (sscanf(device_str, "%lu.%lu.%lu.%lu", &a[0], &a[1], &a[2], &a[3]) != 4) { 164 221 return NULL; 165 222 } 166 223 } 167 224 168 225 unsigned long device_ip = (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | (a[3] << 0); 169 return hdhomerun_device_create(HDHOMERUN_DEVICE_ID_WILDCARD, (uint32_t)device_ip, tuner, dbg); 226 struct hdhomerun_device_t *hd = hdhomerun_device_create(HDHOMERUN_DEVICE_ID_WILDCARD, (uint32_t)device_ip, 0, dbg); 227 if (!hd) { 228 return NULL; 229 } 230 231 if (hd->multicast_ip != 0) { 232 hd->multicast_port = port; 233 } 234 235 return hd; 170 236 } 171 237 172 238 static struct hdhomerun_device_t *hdhomerun_device_create_from_str_dns(const char *device_str, struct hdhomerun_debug_t *dbg) … … 239 305 240 306 uint32_t hdhomerun_device_get_device_id(struct hdhomerun_device_t *hd) 241 307 { 242 return hd homerun_control_get_device_id(hd->cs);308 return hd->device_id; 243 309 } 244 310 245 311 uint32_t hdhomerun_device_get_device_ip(struct hdhomerun_device_t *hd) 246 312 { 247 return hdhomerun_control_get_device_ip(hd->cs); 313 if (hd->multicast_ip != 0) { 314 return hd->multicast_ip; 315 } 316 if (hd->cs) { 317 return hdhomerun_control_get_device_ip(hd->cs); 318 } 319 320 return 0; 248 321 } 249 322 250 323 uint32_t hdhomerun_device_get_device_id_requested(struct hdhomerun_device_t *hd) 251 324 { 252 return hdhomerun_control_get_device_id_requested(hd->cs); 325 if (hd->multicast_ip != 0) { 326 return 0; 327 } 328 if (hd->cs) { 329 return hdhomerun_control_get_device_id_requested(hd->cs); 330 } 331 332 return 0; 253 333 } 254 334 255 335 uint32_t hdhomerun_device_get_device_ip_requested(struct hdhomerun_device_t *hd) 256 336 { 257 return hdhomerun_control_get_device_ip_requested(hd->cs); 337 if (hd->multicast_ip != 0) { 338 return hd->multicast_ip; 339 } 340 if (hd->cs) { 341 return hdhomerun_control_get_device_ip_requested(hd->cs); 342 } 343 344 return 0; 258 345 } 259 346 260 347 unsigned int hdhomerun_device_get_tuner(struct hdhomerun_device_t *hd) … … 273 360 return hd->vs; 274 361 } 275 362 276 hd->vs = hdhomerun_video_create( 0, VIDEO_DATA_BUFFER_SIZE_1S * 2, hd->dbg);363 hd->vs = hdhomerun_video_create(hd->multicast_port, VIDEO_DATA_BUFFER_SIZE_1S * 2, hd->dbg); 277 364 if (!hd->vs) { 278 365 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_video_sock: failed to create video object\n"); 279 366 return NULL; … … 284 371 285 372 uint32_t hdhomerun_device_get_local_machine_addr(struct hdhomerun_device_t *hd) 286 373 { 287 return hdhomerun_control_get_local_addr(hd->cs); 374 if (hd->cs) { 375 return hdhomerun_control_get_local_addr(hd->cs); 376 } 377 378 return 0; 288 379 } 289 380 290 381 static uint32_t hdhomerun_device_get_status_parse(const char *status_str, const char *tag) … … 368 459 369 460 int hdhomerun_device_get_tuner_status(struct hdhomerun_device_t *hd, char **pstatus_str, struct hdhomerun_tuner_status_t *status) 370 461 { 462 if (!hd->cs) { 463 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_status: device not set\n"); 464 return -1; 465 } 466 371 467 memset(status, 0, sizeof(struct hdhomerun_tuner_status_t)); 372 468 373 469 char name[32]; … … 414 510 415 511 int hdhomerun_device_get_tuner_streaminfo(struct hdhomerun_device_t *hd, char **pstreaminfo) 416 512 { 513 if (!hd->cs) { 514 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_streaminfo: device not set\n"); 515 return -1; 516 } 517 417 518 char name[32]; 418 519 sprintf(name, "/tuner%u/streaminfo", hd->tuner); 419 520 return hdhomerun_control_get(hd->cs, name, pstreaminfo, NULL); … … 421 522 422 523 int hdhomerun_device_get_tuner_channel(struct hdhomerun_device_t *hd, char **pchannel) 423 524 { 525 if (!hd->cs) { 526 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_channel: device not set\n"); 527 return -1; 528 } 529 424 530 char name[32]; 425 531 sprintf(name, "/tuner%u/channel", hd->tuner); 426 532 return hdhomerun_control_get(hd->cs, name, pchannel, NULL); … … 428 534 429 535 int hdhomerun_device_get_tuner_channelmap(struct hdhomerun_device_t *hd, char **pchannelmap) 430 536 { 537 if (!hd->cs) { 538 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_channelmap: device not set\n"); 539 return -1; 540 } 541 431 542 char name[32]; 432 543 sprintf(name, "/tuner%u/channelmap", hd->tuner); 433 544 return hdhomerun_control_get(hd->cs, name, pchannelmap, NULL); … … 435 546 436 547 int hdhomerun_device_get_tuner_filter(struct hdhomerun_device_t *hd, char **pfilter) 437 548 { 549 if (!hd->cs) { 550 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_filter: device not set\n"); 551 return -1; 552 } 553 438 554 char name[32]; 439 555 sprintf(name, "/tuner%u/filter", hd->tuner); 440 556 return hdhomerun_control_get(hd->cs, name, pfilter, NULL); … … 442 558 443 559 int hdhomerun_device_get_tuner_program(struct hdhomerun_device_t *hd, char **pprogram) 444 560 { 561 if (!hd->cs) { 562 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_program: device not set\n"); 563 return -1; 564 } 565 445 566 char name[32]; 446 567 sprintf(name, "/tuner%u/program", hd->tuner); 447 568 return hdhomerun_control_get(hd->cs, name, pprogram, NULL); … … 449 570 450 571 int hdhomerun_device_get_tuner_target(struct hdhomerun_device_t *hd, char **ptarget) 451 572 { 573 if (!hd->cs) { 574 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_target: device not set\n"); 575 return -1; 576 } 577 452 578 char name[32]; 453 579 sprintf(name, "/tuner%u/target", hd->tuner); 454 580 return hdhomerun_control_get(hd->cs, name, ptarget, NULL); … … 456 582 457 583 int hdhomerun_device_get_tuner_plotsample(struct hdhomerun_device_t *hd, struct hdhomerun_plotsample_t **psamples, size_t *pcount) 458 584 { 585 if (!hd->cs) { 586 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_plotsample: device not set\n"); 587 return -1; 588 } 589 459 590 char name[32]; 460 591 sprintf(name, "/tuner%u/plotsample", hd->tuner); 461 592 … … 505 636 506 637 int hdhomerun_device_get_tuner_lockkey_owner(struct hdhomerun_device_t *hd, char **powner) 507 638 { 639 if (!hd->cs) { 640 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_lockkey_owner: device not set\n"); 641 return -1; 642 } 643 508 644 char name[32]; 509 645 sprintf(name, "/tuner%u/lockkey", hd->tuner); 510 646 return hdhomerun_control_get(hd->cs, name, powner, NULL); … … 512 648 513 649 int hdhomerun_device_get_ir_target(struct hdhomerun_device_t *hd, char **ptarget) 514 650 { 651 if (!hd->cs) { 652 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_ir_target: device not set\n"); 653 return -1; 654 } 655 515 656 return hdhomerun_control_get(hd->cs, "/ir/target", ptarget, NULL); 516 657 } 517 658 518 659 int hdhomerun_device_get_lineup_location(struct hdhomerun_device_t *hd, char **plocation) 519 660 { 661 if (!hd->cs) { 662 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_lineup_location: device not set\n"); 663 return -1; 664 } 665 520 666 return hdhomerun_control_get(hd->cs, "/lineup/location", plocation, NULL); 521 667 } 522 668 523 669 int hdhomerun_device_get_version(struct hdhomerun_device_t *hd, char **pversion_str, uint32_t *pversion_num) 524 670 { 671 if (!hd->cs) { 672 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_version: device not set\n"); 673 return -1; 674 } 675 525 676 char *version_str; 526 677 int ret = hdhomerun_control_get(hd->cs, "/sys/version", &version_str, NULL); 527 678 if (ret <= 0) { … … 546 697 547 698 int hdhomerun_device_set_tuner_channel(struct hdhomerun_device_t *hd, const char *channel) 548 699 { 700 if (!hd->cs) { 701 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_channel: device not set\n"); 702 return -1; 703 } 704 549 705 char name[32]; 550 706 sprintf(name, "/tuner%u/channel", hd->tuner); 551 707 return hdhomerun_control_set_with_lockkey(hd->cs, name, channel, hd->lockkey, NULL, NULL); … … 553 709 554 710 int hdhomerun_device_set_tuner_channelmap(struct hdhomerun_device_t *hd, const char *channelmap) 555 711 { 712 if (!hd->cs) { 713 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_channelmap: device not set\n"); 714 return -1; 715 } 716 556 717 char name[32]; 557 718 sprintf(name, "/tuner%u/channelmap", hd->tuner); 558 719 return hdhomerun_control_set_with_lockkey(hd->cs, name, channelmap, hd->lockkey, NULL, NULL); … … 560 721 561 722 int hdhomerun_device_set_tuner_filter(struct hdhomerun_device_t *hd, const char *filter) 562 723 { 724 if (!hd->cs) { 725 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_filter: device not set\n"); 726 return -1; 727 } 728 563 729 char name[32]; 564 730 sprintf(name, "/tuner%u/filter", hd->tuner); 565 731 return hdhomerun_control_set_with_lockkey(hd->cs, name, filter, hd->lockkey, NULL, NULL); … … 635 801 636 802 int hdhomerun_device_set_tuner_program(struct hdhomerun_device_t *hd, const char *program) 637 803 { 804 if (!hd->cs) { 805 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_program: device not set\n"); 806 return -1; 807 } 808 638 809 char name[32]; 639 810 sprintf(name, "/tuner%u/program", hd->tuner); 640 811 return hdhomerun_control_set_with_lockkey(hd->cs, name, program, hd->lockkey, NULL, NULL); … … 642 813 643 814 int hdhomerun_device_set_tuner_target(struct hdhomerun_device_t *hd, const char *target) 644 815 { 816 if (!hd->cs) { 817 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_target: device not set\n"); 818 return -1; 819 } 820 645 821 char name[32]; 646 822 sprintf(name, "/tuner%u/target", hd->tuner); 647 823 return hdhomerun_control_set_with_lockkey(hd->cs, name, target, hd->lockkey, NULL, NULL); 648 824 } 649 825 650 int hdhomerun_device_set_tuner_target_to_local_protocol(struct hdhomerun_device_t *hd, const char *protocol)826 static int hdhomerun_device_set_tuner_target_to_local(struct hdhomerun_device_t *hd, const char *protocol) 651 827 { 652 /* Create video socket. */ 653 hdhomerun_device_get_video_sock(hd); 828 if (!hd->cs) { 829 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_target_to_local: device not set\n"); 830 return -1; 831 } 654 832 if (!hd->vs) { 833 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_target_to_local: video not initialized\n"); 655 834 return -1; 656 835 } 657 836 … … 669 848 return hdhomerun_device_set_tuner_target(hd, target); 670 849 } 671 850 672 int hdhomerun_device_set_ tuner_target_to_local(struct hdhomerun_device_t *hd)851 int hdhomerun_device_set_ir_target(struct hdhomerun_device_t *hd, const char *target) 673 852 { 674 return hdhomerun_device_set_tuner_target_to_local_protocol(hd, HDHOMERUN_TARGET_PROTOCOL_UDP); 675 } 853 if (!hd->cs) { 854 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_ir_target: device not set\n"); 855 return -1; 856 } 676 857 677 int hdhomerun_device_set_ir_target(struct hdhomerun_device_t *hd, const char *target)678 {679 858 return hdhomerun_control_set(hd->cs, "/ir/target", target, NULL, NULL); 680 859 } 681 860 682 861 int hdhomerun_device_set_lineup_location(struct hdhomerun_device_t *hd, const char *location) 683 862 { 863 if (!hd->cs) { 864 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_lineup_location: device not set\n"); 865 return -1; 866 } 867 684 868 return hdhomerun_control_set(hd->cs, "/lineup/location", location, NULL, NULL); 685 869 } 686 870 871 int hdhomerun_device_set_sys_dvbc_modulation(struct hdhomerun_device_t *hd, const char *modulation_list) 872 { 873 if (!hd->cs) { 874 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_sys_dvbc_modulation: device not set\n"); 875 return -1; 876 } 877 878 return hdhomerun_control_set(hd->cs, "/sys/dvbc_modulation", modulation_list, NULL, NULL); 879 } 880 687 881 int hdhomerun_device_get_var(struct hdhomerun_device_t *hd, const char *name, char **pvalue, char **perror) 688 882 { 883 if (!hd->cs) { 884 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_var: device not set\n"); 885 return -1; 886 } 887 689 888 return hdhomerun_control_get(hd->cs, name, pvalue, perror); 690 889 } 691 890 692 891 int hdhomerun_device_set_var(struct hdhomerun_device_t *hd, const char *name, const char *value, char **pvalue, char **perror) 693 892 { 893 if (!hd->cs) { 894 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_var: device not set\n"); 895 return -1; 896 } 897 694 898 return hdhomerun_control_set_with_lockkey(hd->cs, name, value, hd->lockkey, pvalue, perror); 695 899 } 696 900 697 901 int hdhomerun_device_tuner_lockkey_request(struct hdhomerun_device_t *hd, char **perror) 698 902 { 903 if (hd->multicast_ip != 0) { 904 return 1; 905 } 906 if (!hd->cs) { 907 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_tuner_lockkey_request: device not set\n"); 908 return -1; 909 } 910 699 911 uint32_t new_lockkey = (uint32_t)getcurrenttime(); 700 912 701 913 char name[32]; … … 716 928 717 929 int hdhomerun_device_tuner_lockkey_release(struct hdhomerun_device_t *hd) 718 930 { 931 if (hd->multicast_ip != 0) { 932 return 1; 933 } 934 if (!hd->cs) { 935 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_tuner_lockkey_release: device not set\n"); 936 return -1; 937 } 938 719 939 if (hd->lockkey == 0) { 720 940 return 1; 721 941 } … … 730 950 731 951 int hdhomerun_device_tuner_lockkey_force(struct hdhomerun_device_t *hd) 732 952 { 953 if (hd->multicast_ip != 0) { 954 return 1; 955 } 956 if (!hd->cs) { 957 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_tuner_lockkey_force: device not set\n"); 958 return -1; 959 } 960 733 961 char name[32]; 734 962 sprintf(name, "/tuner%u/lockkey", hd->tuner); 735 963 int ret = hdhomerun_control_set(hd->cs, name, "force", NULL, NULL); … … 740 968 741 969 void hdhomerun_device_tuner_lockkey_use_value(struct hdhomerun_device_t *hd, uint32_t lockkey) 742 970 { 971 if (hd->multicast_ip != 0) { 972 return; 973 } 974 743 975 hd->lockkey = lockkey; 744 976 } 745 977 746 978 int hdhomerun_device_wait_for_lock(struct hdhomerun_device_t *hd, struct hdhomerun_tuner_status_t *status) 747 979 { 748 980 /* Delay for SS reading to be valid (signal present). */ 749 msleep (250);981 msleep_minimum(250); 750 982 751 983 /* Wait for up to 2.5 seconds for lock. */ 752 984 uint64_t timeout = getcurrenttime() + 2500; … … 768 1000 return 1; 769 1001 } 770 1002 771 msleep (250);1003 msleep_approx(250); 772 1004 } 773 1005 } 774 1006 775 1007 int hdhomerun_device_stream_start(struct hdhomerun_device_t *hd) 776 1008 { 1009 hdhomerun_device_get_video_sock(hd); 1010 if (!hd->vs) { 1011 return -1; 1012 } 1013 777 1014 /* Set target. */ 778 int ret = hdhomerun_device_stream_refresh_target(hd); 779 if (ret <= 0) { 780 return ret; 1015 if (hd->multicast_ip != 0) { 1016 int ret = hdhomerun_video_join_multicast_group(hd->vs, hd->multicast_ip, 0); 1017 if (ret <= 0) { 1018 return ret; 1019 } 1020 } else { 1021 int ret = hdhomerun_device_set_tuner_target_to_local(hd, HDHOMERUN_TARGET_PROTOCOL_RTP); 1022 if (ret == 0) { 1023 ret = hdhomerun_device_set_tuner_target_to_local(hd, HDHOMERUN_TARGET_PROTOCOL_UDP); 1024 } 1025 if (ret <= 0) { 1026 return ret; 1027 } 781 1028 } 782 1029 783 1030 /* Flush video buffer. */ 784 msleep (64);1031 msleep_minimum(64); 785 1032 hdhomerun_video_flush(hd->vs); 786 1033 787 1034 /* Success. */ 788 1035 return 1; 789 1036 } 790 1037 791 int hdhomerun_device_stream_refresh_target(struct hdhomerun_device_t *hd)792 {793 int ret = hdhomerun_device_set_tuner_target_to_local_protocol(hd, HDHOMERUN_TARGET_PROTOCOL_RTP);794 if (ret == 0) {795 ret = hdhomerun_device_set_tuner_target_to_local_protocol(hd, HDHOMERUN_TARGET_PROTOCOL_UDP);796 }797 return ret;798 }799 800 1038 uint8_t *hdhomerun_device_stream_recv(struct hdhomerun_device_t *hd, size_t max_size, size_t *pactual_size) 801 1039 { 802 1040 if (!hd->vs) { 1041 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_stream_recv: video not initialized\n"); 803 1042 return NULL; 804 1043 } 1044 805 1045 return hdhomerun_video_recv(hd->vs, max_size, pactual_size); 806 1046 } 807 1047 808 1048 void hdhomerun_device_stream_flush(struct hdhomerun_device_t *hd) 809 1049 { 1050 if (!hd->vs) { 1051 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_stream_flush: video not initialized\n"); 1052 return; 1053 } 1054 810 1055 hdhomerun_video_flush(hd->vs); 811 1056 } 812 1057 813 1058 void hdhomerun_device_stream_stop(struct hdhomerun_device_t *hd) 814 1059 { 815 hdhomerun_device_set_tuner_target(hd, "none"); 1060 if (!hd->vs) { 1061 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_stream_stop: video not initialized\n"); 1062 return; 1063 } 1064 1065 if (hd->multicast_ip != 0) { 1066 hdhomerun_video_leave_multicast_group(hd->vs); 1067 } else { 1068 hdhomerun_device_set_tuner_target(hd, "none"); 1069 } 816 1070 } 817 1071 818 1072 int hdhomerun_device_channelscan_init(struct hdhomerun_device_t *hd, const char *channelmap) … … 823 1077 824 1078 hd->scan = channelscan_create(hd, channelmap); 825 1079 if (!hd->scan) { 1080 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_channelscan_init: failed to create scan object\n"); 826 1081 return -1; 827 1082 } 828 1083 … … 832 1087 int hdhomerun_device_channelscan_advance(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result) 833 1088 { 834 1089 if (!hd->scan) { 1090 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_channelscan_advance: scan not initialized\n"); 835 1091 return 0; 836 1092 } 837 1093 … … 847 1103 int hdhomerun_device_channelscan_detect(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result) 848 1104 { 849 1105 if (!hd->scan) { 1106 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_channelscan_detect: scan not initialized\n"); 850 1107 return 0; 851 1108 } 852 1109 … … 862 1119 uint8_t hdhomerun_device_channelscan_get_progress(struct hdhomerun_device_t *hd) 863 1120 { 864 1121 if (!hd->scan) { 1122 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_channelscan_get_progress: scan not initialized\n"); 865 1123 return 0; 866 1124 } 867 1125 868 1126 return channelscan_get_progress(hd->scan); 869 1127 } 870 1128 871 int hdhomerun_device_firmware_version_check(struct hdhomerun_device_t *hd, uint32_t features)872 {873 uint32_t version;874 if (hdhomerun_device_get_version(hd, NULL, &version) <= 0) {875 return -1;876 }877 878 if (version < 20070219) {879 return 0;880 }881 882 return 1;883 }884 885 1129 const char *hdhomerun_device_get_model_str(struct hdhomerun_device_t *hd) 886 1130 { 887 1131 if (*hd->model) { 888 1132 return hd->model; 889 1133 } 890 1134 1135 if (!hd->cs) { 1136 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_model_str: device not set\n"); 1137 return NULL; 1138 } 1139 891 1140 char *model_str; 892 1141 int ret = hdhomerun_control_get(hd->cs, "/sys/model", &model_str, NULL); 893 1142 if (ret < 0) { 894 1143 return NULL; 895 1144 } 896 1145 if (ret == 0) { 897 strncpy(hd->model, "hdhomerun_atsc", sizeof(hd->model) - 1); 898 hd->model[sizeof(hd->model) - 1] = 0; 1146 model_str = "hdhomerun_atsc"; 899 1147 } 900 else901 {902 strncpy(hd->model, model_str, sizeof(hd->model) - 1);903 hd->model[sizeof(hd->model) - 1] = 0;904 }905 1148 1149 strncpy(hd->model, model_str, sizeof(hd->model) - 1); 1150 hd->model[sizeof(hd->model) - 1] = 0; 1151 906 1152 return hd->model; 907 1153 } 908 1154 909 1155 int hdhomerun_device_upgrade(struct hdhomerun_device_t *hd, FILE *upgrade_file) 910 1156 { 1157 if (!hd->cs) { 1158 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_upgrade: device not set\n"); 1159 return -1; 1160 } 1161 911 1162 hdhomerun_control_set(hd->cs, "/tuner0/lockkey", "force", NULL, NULL); 912 1163 hdhomerun_control_set(hd->cs, "/tuner0/channel", "none", NULL, NULL); 913 1164 … … 923 1174 return; 924 1175 } 925 1176 926 char name[32]; 927 sprintf(name, "/tuner%u/debug", hd->tuner); 1177 if (hd->cs) { 1178 char name[32]; 1179 sprintf(name, "/tuner%u/debug", hd->tuner); 928 1180 929 char *debug_str;930 char *error_str;931 int ret = hdhomerun_control_get(hd->cs, name, &debug_str, &error_str);932 if (ret < 0) {933 hdhomerun_debug_printf(hd->dbg, "video dev: communication error getting debug stats\n");934 return;935 }1181 char *debug_str; 1182 char *error_str; 1183 int ret = hdhomerun_control_get(hd->cs, name, &debug_str, &error_str); 1184 if (ret < 0) { 1185 hdhomerun_debug_printf(hd->dbg, "video dev: communication error getting debug stats\n"); 1186 return; 1187 } 936 1188 937 if (error_str) { 938 hdhomerun_debug_printf(hd->dbg, "video dev: %s\n", error_str); 939 } else { 940 hdhomerun_debug_printf(hd->dbg, "video dev: %s\n", debug_str); 1189 if (error_str) { 1190 hdhomerun_debug_printf(hd->dbg, "video dev: %s\n", error_str); 1191 } else { 1192 hdhomerun_debug_printf(hd->dbg, "video dev: %s\n", debug_str); 1193 } 941 1194 } 942 1195 943 1196 if (hd->vs) { … … 947 1200 948 1201 void hdhomerun_device_get_video_stats(struct hdhomerun_device_t *hd, struct hdhomerun_video_stats_t *stats) 949 1202 { 1203 if (!hd->vs) { 1204 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_stream_flush: video not initialized\n"); 1205 memset(stats, 0, sizeof(struct hdhomerun_video_stats_t)); 1206 return; 1207 } 1208 950 1209 hdhomerun_video_get_stats(hd->vs, stats); 951 1210 } -
libs/libmythhdhomerun/hdhomerun_os_windows.h
1 1 /* 2 2 * hdhomerun_os_windows.h 3 3 * 4 * Copyright © 2006-20 08Silicondust USA Inc. <www.silicondust.com>.4 * Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>. 5 5 * 6 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 … … 31 31 */ 32 32 33 33 #define _WINSOCKAPI_ 34 // MinGW lacks wspiapi, so remove dependency by setting minimum WINVER to WinXP35 #define WINVER 0x050136 34 #include <windows.h> 37 35 #include <winsock2.h> 38 36 #include <ws2tcpip.h> 39 //#include <wspiapi.h>37 #include <wspiapi.h> 40 38 #include <stdlib.h> 41 39 #include <stdio.h> 42 40 #include <stdarg.h> … … 55 53 #endif 56 54 57 55 typedef int bool_t; 58 /* Use MinGW includes instead59 56 typedef signed __int8 int8_t; 60 57 typedef signed __int16 int16_t; 61 58 typedef signed __int32 int32_t; … … 66 63 typedef unsigned __int64 uint64_t; 67 64 typedef HANDLE pthread_t; 68 65 typedef HANDLE pthread_mutex_t; 69 */70 #include <stdint.h>71 #include <pthread.h>72 66 73 // Avoid #define conflicts by limiting scope to non-c++ 74 #ifndef __cplusplus 75 #define socklen_t int 76 #define close closesocket 77 #define sock_getlasterror WSAGetLastError() 78 #define sock_getlasterror_socktimeout (WSAGetLastError() == WSAETIMEDOUT) 79 //#define va_copy(x, y) x = y 67 #define va_copy(x, y) x = y 80 68 #define atoll _atoi64 81 69 #define strdup _strdup 82 70 #define strcasecmp _stricmp … … 85 73 #define ftello _ftelli64 86 74 #define THREAD_FUNC_PREFIX DWORD WINAPI 87 75 #define SIGPIPE SIGABRT 76 77 #ifdef __cplusplus 78 extern "C" { 88 79 #endif 89 80 90 static inline uint64_t getcurrenttime(void) 91 { 92 struct timeb tb; 93 ftime(&tb); 94 return ((uint64_t)tb.time * 1000) + tb.millitm; 95 } 81 extern LIBTYPE uint64_t getcurrenttime(void); 82 extern LIBTYPE void msleep_approx(uint64_t ms); 83 extern LIBTYPE void msleep_minimum(uint64_t ms); 96 84 97 static inline int msleep(unsigned int ms) 98 { 99 uint64_t stop_time = getcurrenttime() + ms; 85 extern LIBTYPE int pthread_create(pthread_t *tid, void *attr, LPTHREAD_START_ROUTINE start, void *arg); 86 extern LIBTYPE int pthread_join(pthread_t tid, void **value_ptr); 87 extern LIBTYPE void pthread_mutex_init(pthread_mutex_t *mutex, void *attr); 88 extern LIBTYPE void pthread_mutex_lock(pthread_mutex_t *mutex); 89 extern LIBTYPE void pthread_mutex_unlock(pthread_mutex_t *mutex); 100 90 101 while (1) {102 uint64_t current_time = getcurrenttime();103 if (current_time >= stop_time) {104 return 0;105 }106 107 uint64_t delay_ms = stop_time - current_time;108 Sleep((DWORD)delay_ms);109 }110 }111 112 // Avoid a define conflict113 /*static inline int sleep(unsigned int sec)114 {115 msleep(sec * 1000);116 return 0;117 }118 */119 120 static inline int setsocktimeout(int s, int level, int optname, uint64_t timeout)121 {122 int t = (int)timeout;123 return setsockopt(s, level, optname, (char *)&t, sizeof(t));124 }125 126 /* MythTV uses pthreads lib instead127 static inline int pthread_create(pthread_t *tid, void *attr, LPTHREAD_START_ROUTINE start, void *arg)128 {129 *tid = CreateThread(NULL, 0, start, arg, 0, NULL);130 if (!*tid) {131 return (int)GetLastError();132 }133 return 0;134 }135 136 static inline int pthread_join(pthread_t tid, void **value_ptr)137 {138 while (1) {139 DWORD ExitCode = 0;140 if (!GetExitCodeThread(tid, &ExitCode)) {141 return (int)GetLastError();142 }143 if (ExitCode != STILL_ACTIVE) {144 return 0;145 }146 }147 }148 149 static inline void pthread_mutex_init(pthread_mutex_t *mutex, void *attr)150 {151 *mutex = CreateMutex(NULL, FALSE, NULL);152 }153 154 static inline void pthread_mutex_lock(pthread_mutex_t *mutex)155 {156 WaitForSingleObject(*mutex, INFINITE);157 }158 159 static inline void pthread_mutex_unlock(pthread_mutex_t *mutex)160 {161 ReleaseMutex(*mutex);162 }163 */164 165 91 /* 166 92 * The console output format should be set to UTF-8, however in XP and Vista this breaks batch file processing. 167 93 * Attempting to restore on exit fails to restore if the program is terminated by the user. 168 94 * Solution - set the output format each printf. 169 95 */ 170 static inline void console_vprintf(const char *fmt, va_list ap) 171 { 172 UINT cp = GetConsoleOutputCP(); 173 SetConsoleOutputCP(CP_UTF8); 174 vprintf(fmt, ap); 175 SetConsoleOutputCP(cp); 176 } 96 extern LIBTYPE void console_vprintf(const char *fmt, va_list ap); 97 extern LIBTYPE void console_printf(const char *fmt, ...); 177 98 178 static inline void console_printf(const char *fmt, ...) 179 { 180 va_list ap; 181 va_start(ap, fmt); 182 console_vprintf(fmt, ap); 183 va_end(ap); 99 #ifdef __cplusplus 184 100 } 101 #endif -
libs/libmythhdhomerun/hdhomerun_device.h
90 90 extern LIBTYPE uint32_t hdhomerun_device_get_device_ip_requested(struct hdhomerun_device_t *hd); 91 91 extern LIBTYPE unsigned int hdhomerun_device_get_tuner(struct hdhomerun_device_t *hd); 92 92 93 extern LIBTYPE voidhdhomerun_device_set_device(struct hdhomerun_device_t *hd, uint32_t device_id, uint32_t device_ip);94 extern LIBTYPE voidhdhomerun_device_set_tuner(struct hdhomerun_device_t *hd, unsigned int tuner);93 extern LIBTYPE int hdhomerun_device_set_device(struct hdhomerun_device_t *hd, uint32_t device_id, uint32_t device_ip); 94 extern LIBTYPE int hdhomerun_device_set_tuner(struct hdhomerun_device_t *hd, unsigned int tuner); 95 95 extern LIBTYPE int hdhomerun_device_set_tuner_from_str(struct hdhomerun_device_t *hd, const char *tuner_str); 96 96 97 97 /* … … 148 148 extern LIBTYPE int hdhomerun_device_set_tuner_filter_by_array(struct hdhomerun_device_t *hd, unsigned char filter_array[0x2000]); 149 149 extern LIBTYPE int hdhomerun_device_set_tuner_program(struct hdhomerun_device_t *hd, const char *program); 150 150 extern LIBTYPE int hdhomerun_device_set_tuner_target(struct hdhomerun_device_t *hd, const char *target); 151 extern LIBTYPE int hdhomerun_device_set_tuner_target_to_local_protocol(struct hdhomerun_device_t *hd, const char *protocol);152 extern LIBTYPE int hdhomerun_device_set_tuner_target_to_local(struct hdhomerun_device_t *hd);153 151 extern LIBTYPE int hdhomerun_device_set_ir_target(struct hdhomerun_device_t *hd, const char *target); 154 152 extern LIBTYPE int hdhomerun_device_set_lineup_location(struct hdhomerun_device_t *hd, const char *location); 153 extern LIBTYPE int hdhomerun_device_set_sys_dvbc_modulation(struct hdhomerun_device_t *hd, const char *modulation_list); 155 154 156 155 /* 157 156 * Get/set a named control variable on the device. … … 224 223 * The hdhomerun_device_stream_stop function tells the device to stop streaming data. 225 224 */ 226 225 extern LIBTYPE int hdhomerun_device_stream_start(struct hdhomerun_device_t *hd); 227 extern LIBTYPE int hdhomerun_device_stream_refresh_target(struct hdhomerun_device_t *hd);228 226 extern LIBTYPE uint8_t *hdhomerun_device_stream_recv(struct hdhomerun_device_t *hd, size_t max_size, size_t *pactual_size); 229 227 extern LIBTYPE void hdhomerun_device_stream_flush(struct hdhomerun_device_t *hd); 230 228 extern LIBTYPE void hdhomerun_device_stream_stop(struct hdhomerun_device_t *hd); … … 238 236 extern LIBTYPE uint8_t hdhomerun_device_channelscan_get_progress(struct hdhomerun_device_t *hd); 239 237 240 238 /* 241 * Check that the device is running the recommended firmware.242 *243 * uint32_t features: Reserved for future use. Set to zero.244 *245 * Returns 1 if the firmware meets the minimum requriements for all operations.246 * Returns 0 if th firmware does not meet the minimum requriements for all operations.247 * Returns -1 if an error occurs.248 */249 extern LIBTYPE int hdhomerun_device_firmware_version_check(struct hdhomerun_device_t *hd, uint32_t features);250 251 /*252 239 * Upload new firmware to the device. 253 240 * 254 241 * FILE *upgrade_file: File pointer to read from. The file must have been opened in binary mode for reading. -
libs/libmythhdhomerun/hdhomerun_device_selector.h
43 43 extern LIBTYPE void hdhomerun_device_selector_destroy(struct hdhomerun_device_selector_t *hds, bool_t destroy_devices); 44 44 45 45 /* 46 * Get the number of devices in the list. 47 */ 48 extern LIBTYPE int hdhomerun_device_selector_get_device_count(struct hdhomerun_device_selector_t *hds); 49 50 /* 46 51 * Populate device selector with devices from given source. 52 * Returns the number of devices populated. 47 53 */ 48 extern LIBTYPE voidhdhomerun_device_selector_load_from_file(struct hdhomerun_device_selector_t *hds, char *filename);54 extern LIBTYPE int hdhomerun_device_selector_load_from_file(struct hdhomerun_device_selector_t *hds, char *filename); 49 55 #if defined(__WINDOWS__) 50 extern LIBTYPE voidhdhomerun_device_selector_load_from_windows_registry(struct hdhomerun_device_selector_t *hds, wchar_t *wsource);56 extern LIBTYPE int hdhomerun_device_selector_load_from_windows_registry(struct hdhomerun_device_selector_t *hds, wchar_t *wsource); 51 57 #endif 52 58 53 59 /* -
libs/libmythhdhomerun/hdhomerun_control.c
1 1 /* 2 2 * hdhomerun_control.c 3 3 * 4 * Copyright © 2006 Silicondust USA Inc. <www.silicondust.com>.4 * Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>. 5 5 * 6 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 … … 32 32 33 33 #include "hdhomerun.h" 34 34 35 #define HDHOMERUN_CONTROL_SEND_TIMEOUT 5000 36 #define HDHOMERUN_CONTROL_RECV_TIMEOUT 5000 35 #define HDHOMERUN_CONTROL_CONNECT_TIMEOUT 2500 36 #define HDHOMERUN_CONTROL_SEND_TIMEOUT 2500 37 #define HDHOMERUN_CONTROL_RECV_TIMEOUT 2500 37 38 #define HDHOMERUN_CONTROL_UPGRADE_TIMEOUT 20000 38 39 39 40 struct hdhomerun_control_sock_t { … … 49 50 50 51 static void hdhomerun_control_close_sock(struct hdhomerun_control_sock_t *cs) 51 52 { 52 if (cs->sock == -1) {53 if (cs->sock == HDHOMERUN_SOCK_INVALID) { 53 54 return; 54 55 } 55 56 56 close(cs->sock);57 cs->sock = -1;57 hdhomerun_sock_destroy(cs->sock); 58 cs->sock = HDHOMERUN_SOCK_INVALID; 58 59 } 59 60 60 61 void hdhomerun_control_set_device(struct hdhomerun_control_sock_t *cs, uint32_t device_id, uint32_t device_ip) … … 76 77 } 77 78 78 79 cs->dbg = dbg; 79 cs->sock = -1;80 cs->sock = HDHOMERUN_SOCK_INVALID; 80 81 hdhomerun_control_set_device(cs, device_id, device_ip); 81 82 82 83 return cs; … … 90 91 91 92 static bool_t hdhomerun_control_connect_sock(struct hdhomerun_control_sock_t *cs) 92 93 { 93 if (cs->sock != -1) {94 if (cs->sock != HDHOMERUN_SOCK_INVALID) { 94 95 return TRUE; 95 96 } 96 97 … … 98 99 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_connect_sock: no device specified\n"); 99 100 return FALSE; 100 101 } 102 if (hdhomerun_discover_is_ip_multicast(cs->desired_device_ip)) { 103 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_connect_sock: cannot use multicast ip address for device operations\n"); 104 return FALSE; 105 } 101 106 102 107 /* Find device. */ 103 108 struct hdhomerun_discover_device_t result; … … 109 114 cs->actual_device_id = result.device_id; 110 115 111 116 /* Create socket. */ 112 cs->sock = (int)socket(AF_INET, SOCK_STREAM, 0);113 if (cs->sock == -1) {114 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_connect_sock: failed to create socket (%d)\n", sock_getlasterror);117 cs->sock = hdhomerun_sock_create_tcp(); 118 if (cs->sock == HDHOMERUN_SOCK_INVALID) { 119 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_connect_sock: failed to create socket (%d)\n", hdhomerun_sock_getlasterror()); 115 120 return FALSE; 116 121 } 117 122 118 /* Set timeouts. */119 setsocktimeout(cs->sock, SOL_SOCKET, SO_SNDTIMEO, HDHOMERUN_CONTROL_SEND_TIMEOUT);120 setsocktimeout(cs->sock, SOL_SOCKET, SO_RCVTIMEO, HDHOMERUN_CONTROL_RECV_TIMEOUT);121 122 123 /* Initiate connection. */ 123 struct sockaddr_in sock_addr; 124 memset(&sock_addr, 0, sizeof(sock_addr)); 125 sock_addr.sin_family = AF_INET; 126 sock_addr.sin_addr.s_addr = htonl(cs->actual_device_ip); 127 sock_addr.sin_port = htons(HDHOMERUN_CONTROL_TCP_PORT); 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); 124 if (!hdhomerun_sock_connect(cs->sock, cs->actual_device_ip, HDHOMERUN_CONTROL_TCP_PORT, HDHOMERUN_CONTROL_CONNECT_TIMEOUT)) { 125 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_connect_sock: failed to connect (%d)\n", hdhomerun_sock_getlasterror()); 130 126 hdhomerun_control_close_sock(cs); 131 127 return FALSE; 132 128 } … … 172 168 return 0; 173 169 } 174 170 175 struct sockaddr_in sock_addr; 176 socklen_t sockaddr_size = sizeof(sock_addr); 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); 171 uint32_t addr = hdhomerun_sock_getsockname_addr(cs->sock); 172 if (addr == 0) { 173 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_get_local_addr: getsockname failed (%d)\n", hdhomerun_sock_getlasterror()); 179 174 return 0; 180 175 } 181 176 182 return ntohl(sock_addr.sin_addr.s_addr);177 return addr; 183 178 } 184 179 185 static int hdhomerun_control_send_sock(struct hdhomerun_control_sock_t *cs, struct hdhomerun_pkt_t *tx_pkt)180 static bool_t hdhomerun_control_send_sock(struct hdhomerun_control_sock_t *cs, struct hdhomerun_pkt_t *tx_pkt) 186 181 { 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); 182 if (!hdhomerun_sock_send(cs->sock, tx_pkt->start, tx_pkt->end - tx_pkt->start, HDHOMERUN_CONTROL_SEND_TIMEOUT)) { 183 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_send_sock: send failed (%d)\n", hdhomerun_sock_getlasterror()); 190 184 hdhomerun_control_close_sock(cs); 191 return -1;185 return FALSE; 192 186 } 193 187 194 return 1;188 return TRUE; 195 189 } 196 190 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)191 static bool_t hdhomerun_control_recv_sock(struct hdhomerun_control_sock_t *cs, struct hdhomerun_pkt_t *rx_pkt, uint16_t *ptype, uint64_t recv_timeout) 198 192 { 199 193 uint64_t stop_time = getcurrenttime() + recv_timeout; 200 194 hdhomerun_pkt_reset(rx_pkt); 201 195 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); 196 while (1) { 197 uint64_t current_time = getcurrenttime(); 198 if (current_time >= stop_time) { 199 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_recv_sock: timeout\n"); 213 200 hdhomerun_control_close_sock(cs); 214 return -1;201 return FALSE; 215 202 } 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); 203 204 size_t length = rx_pkt->limit - rx_pkt->end; 205 if (!hdhomerun_sock_recv(cs->sock, rx_pkt->end, &length, stop_time - current_time)) { 206 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_recv_sock: recv failed (%d)\n", hdhomerun_sock_getlasterror()); 224 207 hdhomerun_control_close_sock(cs); 225 return -1;208 return FALSE; 226 209 } 227 rx_pkt->end += rx_length;228 210 211 rx_pkt->end += length; 212 229 213 int ret = hdhomerun_pkt_open_frame(rx_pkt, ptype); 230 214 if (ret < 0) { 231 215 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_recv_sock: frame error\n"); 232 216 hdhomerun_control_close_sock(cs); 233 return -1;217 return FALSE; 234 218 } 235 if (ret ==0) {236 continue;219 if (ret > 0) { 220 return TRUE; 237 221 } 238 239 return 1;240 222 } 241 242 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_recv_sock: timeout\n");243 hdhomerun_control_close_sock(cs);244 return -1;245 223 } 246 224 247 225 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) … … 250 228 251 229 int i; 252 230 for (i = 0; i < 2; i++) { 253 if (cs->sock == -1) {231 if (cs->sock == HDHOMERUN_SOCK_INVALID) { 254 232 if (!hdhomerun_control_connect_sock(cs)) { 255 233 hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_send_recv: connect failed\n"); 256 234 return -1; 257 235 } 258 236 } 259 237 260 if ( hdhomerun_control_send_sock(cs, tx_pkt) < 0) {238 if (!hdhomerun_control_send_sock(cs, tx_pkt)) { 261 239 continue; 262 240 } 263 241 if (!rx_pkt) { … … 265 243 } 266 244 267 245 uint16_t rsp_type; 268 if ( hdhomerun_control_recv_sock(cs, rx_pkt, &rsp_type, recv_timeout) < 0) {246 if (!hdhomerun_control_recv_sock(cs, rx_pkt, &rsp_type, recv_timeout)) { 269 247 continue; 270 248 } 271 249 if (rsp_type != type + 1) { … … 301 279 } 302 280 hdhomerun_pkt_write_u8(tx_pkt, HDHOMERUN_TAG_GETSET_NAME); 303 281 hdhomerun_pkt_write_var_length(tx_pkt, name_len); 304 hdhomerun_pkt_write_mem(tx_pkt, ( constvoid *)name, name_len);282 hdhomerun_pkt_write_mem(tx_pkt, (void *)name, name_len); 305 283 306 284 if (value) { 307 285 int value_len = (int)strlen(value) + 1; … … 311 289 } 312 290 hdhomerun_pkt_write_u8(tx_pkt, HDHOMERUN_TAG_GETSET_VALUE); 313 291 hdhomerun_pkt_write_var_length(tx_pkt, value_len); 314 hdhomerun_pkt_write_mem(tx_pkt, ( constvoid *)value, value_len);292 hdhomerun_pkt_write_mem(tx_pkt, (void *)value, value_len); 315 293 } 316 294 317 295 if (lockkey != 0) {