Ticket #7970: hdhr.patch

File hdhr.patch, 80.2 KB (added by Nigel, 14 years ago)

Changes after [23439]

  • libs/libmythhdhomerun/hdhomerun.h

     
    33/*
    44 * hdhomerun.h
    55 *
    6  * Copyright © 2006-2008 Silicondust USA Inc. <www.silicondust.com>.
     6 * Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>.
    77 *
    88 * This library is free software; you can redistribute it and/or
    99 * modify it under the terms of the GNU Lesser General Public
     
    3535#include "hdhomerun_os.h"
    3636#include "hdhomerun_types.h"
    3737#include "hdhomerun_pkt.h"
     38#include "hdhomerun_sock.h"
    3839#include "hdhomerun_debug.h"
    3940#include "hdhomerun_discover.h"
    4041#include "hdhomerun_control.h"
  • libs/libmythhdhomerun/hdhomerun_debug.c

     
    11/*
    22 * hdhomerun_debug.c
    33 *
    4  * Copyright © 2006 Silicondust USA Inc. <www.silicondust.com>.
     4 * Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>.
    55 *
    66 * This library is free software; you can redistribute it and/or
    77 * modify it under the terms of the GNU Lesser General Public
     
    4444#define HDHOMERUN_DEBUG_HOST "debug.silicondust.com"
    4545#endif
    4646#if !defined(HDHOMERUN_DEBUG_PORT)
    47 #define HDHOMERUN_DEBUG_PORT "8002"
     47#define HDHOMERUN_DEBUG_PORT 8002
    4848#endif
    4949
     50#define HDHOMERUN_DEBUG_CONNECT_RETRY_TIME 30000
     51#define HDHOMERUN_DEBUG_CONNECT_TIMEOUT 10000
     52#define HDHOMERUN_DEBUG_SEND_TIMEOUT 10000
     53
    5054struct hdhomerun_debug_message_t
    5155{
    5256        struct hdhomerun_debug_message_t *next;
     
    7377
    7478        char *file_name;
    7579        FILE *file_fp;
    76         int sock;
     80        hdhomerun_sock_t sock;
    7781};
    7882
    7983static THREAD_FUNC_PREFIX hdhomerun_debug_thread_execute(void *arg);
     
    8589                return NULL;
    8690        }
    8791
    88         dbg->sock = -1;
     92        dbg->sock = HDHOMERUN_SOCK_INVALID;
    8993
    9094        pthread_mutex_init(&dbg->print_lock, NULL);
    9195        pthread_mutex_init(&dbg->queue_lock, NULL);
     
    117121        if (dbg->file_fp) {
    118122                fclose(dbg->file_fp);
    119123        }
    120         if (dbg->sock != -1) {
    121                 close(dbg->sock);
     124        if (dbg->sock != HDHOMERUN_SOCK_INVALID) {
     125                hdhomerun_sock_destroy(dbg->sock);
    122126        }
    123127
    124128        free(dbg);
     
    132136                dbg->file_fp = NULL;
    133137        }
    134138
    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;
    138142        }
    139143}
    140144
     
    251255                        return;
    252256                }
    253257
    254                 msleep(10);
     258                msleep_approx(10);
    255259        }
    256260}
    257261
     
    372376}
    373377
    374378/* Send lock held by caller */
    375 #if defined(__CYGWIN__)
    376379static bool_t hdhomerun_debug_output_message_sock(struct hdhomerun_debug_t *dbg, struct hdhomerun_debug_message_t *message)
    377380{
    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) {
    384382                uint64_t current_time = getcurrenttime();
    385383                if (current_time < dbg->connect_delay) {
    386384                        return FALSE;
    387385                }
    388                 dbg->connect_delay = current_time + 30*1000;
     386                dbg->connect_delay = current_time + HDHOMERUN_DEBUG_CONNECT_RETRY_TIME;
    389387
    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) {
    392390                        return FALSE;
    393391                }
    394392
    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) {
    403395                        hdhomerun_debug_close_internal(dbg);
    404396                        return FALSE;
    405397                }
    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)) {
    408400                        hdhomerun_debug_close_internal(dbg);
    409401                        return FALSE;
    410402                }
    411                 freeaddrinfo(sock_info);
    412403        }
    413404
    414405        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)) {
    416407                hdhomerun_debug_close_internal(dbg);
    417408                return FALSE;
    418409        }
    419410
    420411        return TRUE;
    421412}
    422 #endif
    423413
    424414static bool_t hdhomerun_debug_output_message(struct hdhomerun_debug_t *dbg, struct hdhomerun_debug_message_t *message)
    425415{
     
    466456                pthread_mutex_unlock(&dbg->queue_lock);
    467457
    468458                if (!message) {
    469                         msleep(250);
     459                        msleep_approx(250);
    470460                        continue;
    471461                }
    472462
     
    476466                }
    477467
    478468                if (!hdhomerun_debug_output_message(dbg, message)) {
    479                         msleep(250);
     469                        msleep_approx(250);
    480470                        continue;
    481471                }
    482472
  • libs/libmythhdhomerun/libmythhdhomerun.pro

     
    1010
    1111QMAKE_CLEAN += $(TARGET) $(TARGETA) $(TARGETD) $(TARGET0) $(TARGET1) $(TARGET2)
    1212
    13 HEADERS += hdhomerun.h  hdhomerun_os.h  hdhomerun_types.h
     13HEADERS += hdhomerun.h  hdhomerun_os.h  hdhomerun_sock.h  hdhomerun_types.h
    1414
    1515HEADERS += 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
     16HEADERS += hdhomerun_debug.h     hdhomerun_device.h
    1817HEADERS += hdhomerun_device_selector.h
     18HEADERS += hdhomerun_discover.h  hdhomerun_os_posix.h
     19HEADERS += hdhomerun_pkt.h       hdhomerun_video.h
    1920
     21SOURCES += hdhomerun_config.c
     22
    2023SOURCES += 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
     24SOURCES += hdhomerun_debug.c     hdhomerun_device.c
    2325SOURCES += hdhomerun_device_selector.c
     26SOURCES += hdhomerun_discover.c  hdhomerun_os_posix.c
     27SOURCES += hdhomerun_pkt.c       hdhomerun_video.c
    2428
     29
     30unix:SOURCES += hdhomerun_sock_posix.c
     31
    2532mingw {
    2633    HEADERS += hdhomerun_os_windows.h
     34    SOURCES += hdhomerun_os_windows.c
     35    SOURCES += hdhomerun_sock_windows.c
    2736    LIBS += -lws2_32 -liphlpapi -lpthread
    2837}
    2938
  • libs/libmythhdhomerun/hdhomerun_config.c

     
    286286                }
    287287
    288288                cmd_scan_printf(fp, "SCANNING: %lu (%s)\n",
    289                         result.frequency, result.channel_str
     289                        (unsigned long)result.frequency, result.channel_str
    290290                );
    291291
    292292                ret = hdhomerun_device_channelscan_detect(hd, &result);
     
    364364                size_t actual_size;
    365365                uint8_t *ptr = hdhomerun_device_stream_recv(hd, VIDEO_DATA_BUFFER_SIZE_1S, &actual_size);
    366366                if (!ptr) {
    367                         msleep(64);
     367                        msleep_approx(64);
    368368                        continue;
    369369                }
    370370
     
    381381                                next_progress = loop_start_time + 1000;
    382382                        }
    383383
     384                        /* Windows - indicate activity to suppress auto sleep mode. */
     385                        #if defined(__WINDOWS__)
     386                        SetThreadExecutionState(ES_SYSTEM_REQUIRED);
     387                        #endif
     388
     389                        /* Video stats. */
    384390                        hdhomerun_device_get_video_stats(hd, &stats_cur);
    385391
    386392                        if (stats_cur.overflow_error_count > stats_old.overflow_error_count) {
     
    404410                        continue;
    405411                }
    406412
    407                 msleep(delay);
     413                msleep_approx(delay);
    408414        }
    409415
    410416        if (fp) {
     
    440446                fclose(fp);
    441447                return -1;
    442448        }
    443         sleep(2);
     449        msleep_minimum(2000);
    444450
    445451        printf("upgrading firmware...\n");
    446         sleep(8);
     452        msleep_minimum(8000);
    447453
    448454        printf("rebooting...\n");
    449455        int count = 0;
     
    460466                        return -1;
    461467                }
    462468
    463                 sleep(1);
     469                msleep_minimum(1000);
    464470        }
    465471
    466472        printf("upgrade complete - now running firmware %s\n", version_str);
  • libs/libmythhdhomerun/hdhomerun_video.c

     
    3434
    3535struct hdhomerun_video_sock_t {
    3636        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;
    3744        uint8_t *buffer;
    3845        size_t buffer_size;
    39         volatile size_t head;
    40         volatile size_t tail;
    4146        size_t advance;
     47
     48        pthread_t thread;
    4249        volatile bool_t terminate;
    43         pthread_t thread;
    44         int sock;
    45         uint32_t rtp_sequence;
    46         struct hdhomerun_debug_t *dbg;
     50
    4751        volatile uint32_t packet_count;
    4852        volatile uint32_t transport_error_count;
    4953        volatile uint32_t network_error_count;
    5054        volatile uint32_t sequence_error_count;
    5155        volatile uint32_t overflow_error_count;
     56
     57        volatile uint32_t rtp_sequence;
    5258        volatile uint8_t sequence[0x2000];
    5359};
    5460
     
    6470        }
    6571
    6672        vs->dbg = dbg;
    67         vs->sock = -1;
     73        vs->sock = HDHOMERUN_SOCK_INVALID;
    6874        pthread_mutex_init(&vs->lock, NULL);
    6975
    7076        /* Reset sequence tracking. */
     
    8692        }
    8793       
    8894        /* 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) {
    9197                hdhomerun_debug_printf(dbg, "hdhomerun_video_create: failed to allocate socket\n");
    9298                goto error;
    9399        }
     
    96102        int rx_size = 1024 * 1024;
    97103        setsockopt(vs->sock, SOL_SOCKET, SO_RCVBUF, (char *)&rx_size, sizeof(rx_size));
    98104
    99         /* Set timeouts. */
    100         setsocktimeout(vs->sock, SOL_SOCKET, SO_SNDTIMEO, 1000);
    101         setsocktimeout(vs->sock, SOL_SOCKET, SO_RCVTIMEO, 1000);
    102 
    103105        /* 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)) {
    110107                hdhomerun_debug_printf(dbg, "hdhomerun_video_create: failed to bind socket (port %u)\n", listen_port);
    111108                goto error;
    112109        }
     
    121118        return vs;
    122119
    123120error:
    124         if (vs->sock != -1) {
    125                 close(vs->sock);
     121        if (vs->sock != HDHOMERUN_SOCK_INVALID) {
     122                hdhomerun_sock_destroy(vs->sock);
    126123        }
    127124        if (vs->buffer) {
    128125                free(vs->buffer);
     
    136133        vs->terminate = TRUE;
    137134        pthread_join(vs->thread, NULL);
    138135
    139         close(vs->sock);
     136        hdhomerun_sock_destroy(vs->sock);
    140137        free(vs->buffer);
    141138
    142139        free(vs);
     
    144141
    145142uint16_t hdhomerun_video_get_local_port(struct hdhomerun_video_sock_t *vs)
    146143{
    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());
    151147                return 0;
    152148        }
    153149
    154         return ntohs(sock_addr.sin_port);
     150        return port;
    155151}
    156152
     153int 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
     173int 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
    157192static void hdhomerun_video_stats_ts_pkt(struct hdhomerun_video_sock_t *vs, uint8_t *ptr)
    158193{
    159194        uint16_t packet_identifier = ((uint16_t)(ptr[1] & 0x1F) << 8) | (uint16_t)ptr[2];
     
    168203                return;
    169204        }
    170205
    171         uint8_t continuity_counter = ptr[3] & 0x0F;
     206        uint8_t sequence = ptr[3] & 0x0F;
     207
    172208        uint8_t previous_sequence = vs->sequence[packet_identifier];
     209        vs->sequence[packet_identifier] = sequence;
    173210
    174         if (continuity_counter == ((previous_sequence + 1) & 0x0F)) {
    175                 vs->sequence[packet_identifier] = continuity_counter;
     211        if (previous_sequence == 0xFF) {
    176212                return;
    177213        }
    178         if (previous_sequence == 0xFF) {
    179                 vs->sequence[packet_identifier] = continuity_counter;
     214        if (sequence == ((previous_sequence + 1) & 0x0F)) {
    180215                return;
    181216        }
    182         if (continuity_counter == previous_sequence) {
     217        if (sequence == previous_sequence) {
    183218                return;
    184219        }
    185220
    186221        vs->sequence_error_count++;
    187         vs->sequence[packet_identifier] = continuity_counter;
    188222}
    189223
    190224static void hdhomerun_video_parse_rtp(struct hdhomerun_video_sock_t *vs, struct hdhomerun_pkt_t *pkt)
     
    193227        uint32_t rtp_sequence = hdhomerun_pkt_read_u16(pkt);
    194228        pkt->pos += 8;
    195229
    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;
    199232
    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;
    206236        }
    207237
    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        }
    209251}
    210252
    211253static THREAD_FUNC_PREFIX hdhomerun_video_thread_execute(void *arg)
     
    218260                hdhomerun_pkt_reset(pkt);
    219261
    220262                /* 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
    222268                pkt->end += length;
    223269
    224270                if (length == VIDEO_RTP_DATA_PACKET_SIZE) {
     
    227273                }
    228274
    229275                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;
    240278                }
    241279
    242280                pthread_mutex_lock(&vs->lock);
     
    269307                        continue;
    270308                }
    271309
    272                 /* Atomic update. */
    273310                vs->head = head;
    274311
    275312                pthread_mutex_unlock(&vs->lock);
     
    291328                        tail -= vs->buffer_size;
    292329                }
    293330       
    294                 /* Atomic update. */
    295331                vs->tail = tail;
    296332        }
    297333
     
    334370        vs->tail = vs->head;
    335371        vs->advance = 0;
    336372
    337         /* can't use memset bcs sequence is volatile */
     373        vs->rtp_sequence = 0xFFFFFFFF;
    338374        int i;
    339         for (i = 0; i < sizeof(vs->sequence) / sizeof(uint8_t) ; i++)
     375        for (i = 0; i < 0x2000; i++) {
    340376                vs->sequence[i] = 0xFF;
     377        }
    341378
    342         vs->rtp_sequence = 0xFFFFFFFF;
    343 
    344379        vs->packet_count = 0;
    345380        vs->transport_error_count = 0;
    346381        vs->network_error_count = 0;
     
    355390        struct hdhomerun_video_stats_t stats;
    356391        hdhomerun_video_get_stats(vs, &stats);
    357392
    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
     393        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
    362397        );
    363398}
    364399
  • libs/libmythhdhomerun/hdhomerun_os_posix.h

     
    11/*
    22 * hdhomerun_os_posix.h
    33 *
    4  * Copyright © 2006-2008 Silicondust USA Inc. <www.silicondust.com>.
     4 * Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>.
    55 *
    66 * This library is free software; you can redistribute it and/or
    77 * modify it under the terms of the GNU Lesser General Public
     
    5252typedef int bool_t;
    5353
    5454#define LIBTYPE
    55 #define sock_getlasterror errno
    56 #define sock_getlasterror_socktimeout (errno == EAGAIN)
    5755#define console_vprintf vprintf
    5856#define console_printf printf
    5957#define THREAD_FUNC_PREFIX void *
    6058
    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
     60extern "C" {
     61#endif
    6762
    68 static inline int msleep(unsigned int ms)
    69 {
    70         uint64_t stop_time = getcurrenttime() + ms;
     63extern LIBTYPE uint64_t getcurrenttime(void);
     64extern LIBTYPE void msleep_approx(uint64_t ms);
     65extern LIBTYPE void msleep_minimum(uint64_t ms);
    7166
    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
    8768}
    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

     
    7171extern LIBTYPE uint16_t hdhomerun_video_get_local_port(struct hdhomerun_video_sock_t *vs);
    7272
    7373/*
     74 * Join/leave multicast group.
     75 */
     76extern LIBTYPE int hdhomerun_video_join_multicast_group(struct hdhomerun_video_sock_t *vs, uint32_t multicast_ip, uint32_t local_ip);
     77extern LIBTYPE int hdhomerun_video_leave_multicast_group(struct hdhomerun_video_sock_t *vs);
     78
     79/*
    7480 * Read data from buffer.
    7581 *
    7682 * size_t max_size: The maximum amount of data to be returned.
  • libs/libmythhdhomerun/hdhomerun_channelscan.c

     
    11/*
    22 * hdhomerun_channelscan.c
    33 *
    4  * Copyright © 2007-2008 Silicondust USA Inc. <www.silicondust.com>.
     4 * Copyright © 2007-2010 Silicondust USA Inc. <www.silicondust.com>.
    55 *
    66 * This library is free software; you can redistribute it and/or
    77 * modify it under the terms of the GNU Lesser General Public
     
    9999                        return 1;
    100100                }
    101101
    102                 msleep(250);
     102                msleep_approx(250);
    103103        }
    104104}
    105105
     
    303303                        break;
    304304                }
    305305
    306                 msleep(250);
     306                msleep_approx(250);
    307307        }
    308308
    309309        /* Lock => skip overlapping channels. */
  • libs/libmythhdhomerun/hdhomerun_discover.c

     
    11/*
    22 * hdhomerun_discover.c
    33 *
    4  * Copyright © 2006-2007 Silicondust USA Inc. <www.silicondust.com>.
     4 * Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>.
    55 *
    66 * This library is free software; you can redistribute it and/or
    77 * modify it under the terms of the GNU Lesser General Public
     
    4444#endif
    4545#endif
    4646
    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
    53 
    5447#define HDHOMERUN_DISOCVER_MAX_SOCK_COUNT 16
    5548
    5649struct hdhomerun_discover_sock_t {
    57         int sock;
     50        hdhomerun_sock_t sock;
     51        bool_t detected;
    5852        uint32_t local_ip;
    5953        uint32_t subnet_mask;
    6054};
     
    6660        struct hdhomerun_pkt_t rx_pkt;
    6761};
    6862
    69 static bool_t hdhomerun_discover_sock_create(struct hdhomerun_discover_t *ds, uint32_t local_ip, uint32_t subnet_mask)
     63static bool_t hdhomerun_discover_sock_add(struct hdhomerun_discover_t *ds, uint32_t local_ip, uint32_t subnet_mask)
    7064{
     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
    7175        if (ds->sock_count >= HDHOMERUN_DISOCVER_MAX_SOCK_COUNT) {
    7276                return FALSE;
    7377        }
    7478
    7579        /* 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) {
    7882                return FALSE;
    7983        }
    8084
    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 
    8985        /* 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);
    9788                return FALSE;
    9889        }
    9990
    10091        /* Write sock entry. */
    10192        struct hdhomerun_discover_sock_t *dss = &ds->socks[ds->sock_count++];
    10293        dss->sock = sock;
     94        dss->detected = TRUE;
    10395        dss->local_ip = local_ip;
    10496        dss->subnet_mask = subnet_mask;
    10597
    10698        return TRUE;
    10799}
    108100
     101struct 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
     118void 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
    109129#if defined(USE_IPHLPAPI)
    110 static void hdhomerun_discover_sock_detect(struct hdhomerun_discover_t *ds)
     130static void hdhomerun_discover_sock_detect_internal(struct hdhomerun_discover_t *ds)
    111131{
    112132        PIP_ADAPTER_INFO pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO));
    113133        ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
     
    138158                                continue;
    139159                        }
    140160
    141                         hdhomerun_discover_sock_create(ds, local_ip, mask);
     161                        hdhomerun_discover_sock_add(ds, local_ip, mask);
    142162                        pIPAddr = pIPAddr->Next;
    143163                }
    144164
     
    150170
    151171#else
    152172
    153 static void hdhomerun_discover_sock_detect(struct hdhomerun_discover_t *ds)
     173static void hdhomerun_discover_sock_detect_internal(struct hdhomerun_discover_t *ds)
    154174{
    155         int fd = socket(AF_INET, SOCK_DGRAM, 0);
    156         if (fd == -1) {
    157                 return;
    158         }
     175        int sock = ds->socks[0].sock;
    159176
    160177        struct ifconf ifc;
    161178        uint8_t buf[8192];
     
    164181
    165182        memset(buf, 0, sizeof(buf));
    166183
    167         if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) {
    168                 close(fd);
     184        if (ioctl(sock, SIOCGIFCONF, &ifc) != 0) {
    169185                return;
    170186        }
    171187
     
    176192                struct ifreq *ifr = (struct ifreq *)ptr;
    177193                ptr += _SIZEOF_ADDR_IFREQ(*ifr);
    178194
    179                 if (ioctl(fd, SIOCGIFADDR, ifr) != 0) {
     195                if (ioctl(sock, SIOCGIFADDR, ifr) != 0) {
    180196                        continue;
    181197                }
    182198                struct sockaddr_in *addr_in = (struct sockaddr_in *)&(ifr->ifr_addr);
     
    185201                        continue;
    186202                }
    187203
    188                 if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) {
     204                if (ioctl(sock, SIOCGIFNETMASK, ifr) != 0) {
    189205                        continue;
    190206                }
    191207                struct sockaddr_in *mask_in = (struct sockaddr_in *)&(ifr->ifr_addr);
    192208                uint32_t mask = ntohl(mask_in->sin_addr.s_addr);
    193209
    194                 hdhomerun_discover_sock_create(ds, local_ip, mask);
     210                hdhomerun_discover_sock_add(ds, local_ip, mask);
    195211        }
    196 
    197         close(fd);
    198212}
    199213#endif
    200214
    201 static struct hdhomerun_discover_t *hdhomerun_discover_create(void)
     215static void hdhomerun_discover_sock_detect(struct hdhomerun_discover_t *ds)
    202216{
    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;
    206221        }
    207222
    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);
    213224
    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++;
    227240        }
    228241
    229         free(ds);
     242        ds->sock_count = count;
    230243}
    231244
    232245static 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)
     
    242255        hdhomerun_pkt_write_u32(tx_pkt, device_id);
    243256        hdhomerun_pkt_seal_frame(tx_pkt, HDHOMERUN_TYPE_DISCOVER_REQ);
    244257
    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);
    257259}
    258260
    259261static bool_t hdhomerun_discover_send_wildcard_ip(struct hdhomerun_discover_t *ds, uint32_t device_type, uint32_t device_id)
     
    313315
    314316static bool_t hdhomerun_discover_send(struct hdhomerun_discover_t *ds, uint32_t target_ip, uint32_t device_type, uint32_t device_id)
    315317{
    316         if (target_ip != 0) {
     318        if (target_ip == 0) {
     319                return hdhomerun_discover_send_wildcard_ip(ds, device_type, device_id);
     320        } else {
    317321                return hdhomerun_discover_send_target_ip(ds, target_ip, device_type, device_id);
    318322        }
    319 
    320         return hdhomerun_discover_send_wildcard_ip(ds, device_type, device_id);
    321323}
    322324
    323 static int hdhomerun_discover_recv_internal(struct hdhomerun_discover_t *ds, struct hdhomerun_discover_sock_t *dss, struct hdhomerun_discover_device_t *result)
     325static bool_t hdhomerun_discover_recv_internal(struct hdhomerun_discover_t *ds, struct hdhomerun_discover_sock_t *dss, struct hdhomerun_discover_device_t *result)
    324326{
    325327        struct hdhomerun_pkt_t *rx_pkt = &ds->rx_pkt;
    326328        hdhomerun_pkt_reset(rx_pkt);
    327329
    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;
    336335        }
    337         rx_pkt->end += rx_length;
    338336
     337        rx_pkt->end += length;
     338
    339339        uint16_t type;
    340340        if (hdhomerun_pkt_open_frame(rx_pkt, &type) <= 0) {
    341                 return 0;
     341                return FALSE;
    342342        }
    343343        if (type != HDHOMERUN_TYPE_DISCOVER_RPY) {
    344                 return 0;
     344                return FALSE;
    345345        }
    346346
    347         result->ip_addr = ntohl(sock_addr.sin_addr.s_addr);
     347        result->ip_addr = remote_addr;
    348348        result->device_type = 0;
    349349        result->device_id = 0;
    350350
     
    378378                rx_pkt->pos = next;
    379379        }
    380380
    381         return 1;
     381        return TRUE;
    382382}
    383383
    384 static int hdhomerun_discover_recv(struct hdhomerun_discover_t *ds, struct hdhomerun_discover_device_t *result)
     384static bool_t hdhomerun_discover_recv(struct hdhomerun_discover_t *ds, struct hdhomerun_discover_device_t *result)
    385385{
    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 
    394386        unsigned int i;
    395387        for (i = 0; i < ds->sock_count; i++) {
    396388                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         }
    402389
    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;
    411392                }
    412 
    413                 if (hdhomerun_discover_recv_internal(ds, dss, result) <= 0) {
    414                         continue;
    415                 }
    416 
    417                 return 1;
    418393        }
    419394
    420         return 0;
     395        return FALSE;
    421396}
    422397
    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)
     398static 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)
    424399{
    425400        int index;
    426401        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;
    430405                }
    431406        }
    432407
    433408        return NULL;
    434409}
    435410
    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)
     411int 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)
    437412{
     413        hdhomerun_discover_sock_detect(ds);
     414
    438415        int count = 0;
    439416        int attempt;
    440417        for (attempt = 0; attempt < 2; attempt++) {
     
    443420                }
    444421
    445422                uint64_t timeout = getcurrenttime() + 200;
    446                 while (getcurrenttime() < timeout) {
     423                while (1) {
    447424                        struct hdhomerun_discover_device_t *result = &result_list[count];
    448425
    449                         int 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);
    454431                                continue;
    455432                        }
    456433
     
    467444                        }
    468445
    469446                        /* 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)) {
    471448                                continue;
    472449                        }
    473450
     
    484461
    485462int 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)
    486463{
     464        if (hdhomerun_discover_is_ip_multicast(target_ip)) {
     465                return 0;
     466        }
     467
    487468        struct hdhomerun_discover_t *ds = hdhomerun_discover_create();
    488469        if (!ds) {
    489470                return -1;
    490471        }
    491472
    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);
    493474
    494475        hdhomerun_discover_destroy(ds);
    495476        return ret;
     
    513494        return (checksum == 0);
    514495}
    515496
     497bool_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

     
    4444 *
    4545 * The device information is stored in caller-supplied array of hdhomerun_discover_device_t vars.
    4646 * 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.
    4848 *
    4949 * 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.
    5052 *
    5153 * Returns the number of devices found.
    5254 * Retruns -1 on error.
     
    5456extern 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);
    5557
    5658/*
     59 * Optional: persistent discover instance available for discover polling use.
     60 */
     61extern LIBTYPE struct hdhomerun_discover_t *hdhomerun_discover_create(void);
     62extern LIBTYPE void hdhomerun_discover_destroy(struct hdhomerun_discover_t *ds);
     63extern 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/*
    5766 * Verify that the device ID given is valid.
    5867 *
    5968 * The device ID contains a self-check sequence that detects common user input errors including
     
    6473 */
    6574extern LIBTYPE bool_t hdhomerun_discover_validate_device_id(uint32_t device_id);
    6675
     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 */
     82extern LIBTYPE bool_t hdhomerun_discover_is_ip_multicast(uint32_t ip_addr);
     83
    6784#ifdef __cplusplus
    6885}
    6986#endif
  • libs/libmythhdhomerun/Makefile.bin

     
    1 LIBSRCS += hdhomerun_pkt.c
    2 LIBSRCS += hdhomerun_debug.c
    3 LIBSRCS += hdhomerun_discover.c
     1
    42LIBSRCS += hdhomerun_channels.c
    53LIBSRCS += hdhomerun_channelscan.c
    64LIBSRCS += hdhomerun_control.c
    7 LIBSRCS += hdhomerun_video.c
     5LIBSRCS += hdhomerun_debug.c
    86LIBSRCS += hdhomerun_device.c
    97LIBSRCS += hdhomerun_device_selector.c
     8LIBSRCS += hdhomerun_discover.c
     9LIBSRCS += hdhomerun_os_posix.c
     10LIBSRCS += hdhomerun_pkt.c
     11LIBSRCS += hdhomerun_sock_posix.c
     12LIBSRCS += hdhomerun_video.c
    1013
    1114CC    := $(CROSS_COMPILE)gcc
    1215STRIP := $(CROSS_COMPILE)strip
     
    2023  LIBEXT := .dll
    2124  LDFLAGS += -liphlpapi
    2225else
     26  OS := $(shell uname -s)
    2327  LIBEXT := .so
    24   ifneq ($(findstring solaris,$(shell echo $$OSTYPE)),)
     28  ifeq ($(OS),Linux)
     29    LDFLAGS += -lrt
     30  endif
     31  ifeq ($(OS),SunOS)
    2532    LDFLAGS += -lns -lsocket
    2633  endif
    27   ifneq ($(findstring darwin,$(shell echo $$OSTYPE)),)
     34  ifeq ($(OS),Darwin)
    2835    CFLAGS += -arch i386 -arch ppc
    2936    LIBEXT := .dylib
    3037    SHARED := -dynamiclib -install_name libhdhomerun$(LIBEXT)
  • libs/libmythhdhomerun/hdhomerun_device_selector.c

     
    11/*
    22 * hdhomerun_device_selector.c
    33 *
    4  * Copyright © 2009 Silicondust USA Inc. <www.silicondust.com>.
     4 * Copyright © 2009-2010 Silicondust USA Inc. <www.silicondust.com>.
    55 *
    66 * This library is free software; you can redistribute it and/or
    77 * modify it under the terms of the GNU Lesser General Public
     
    6868        free(hds);
    6969}
    7070
     71LIBTYPE int hdhomerun_device_selector_get_device_count(struct hdhomerun_device_selector_t *hds)
     72{
     73        return (int)hds->hd_count;
     74}
     75
    7176void hdhomerun_device_selector_add_device(struct hdhomerun_device_selector_t *hds, struct hdhomerun_device_t *hd)
    7277{
    7378        size_t index;
     
    129134        return NULL;
    130135}
    131136
    132 void hdhomerun_device_selector_load_from_file(struct hdhomerun_device_selector_t *hds, char *filename)
     137int hdhomerun_device_selector_load_from_file(struct hdhomerun_device_selector_t *hds, char *filename)
    133138{
    134139        FILE *fp = fopen(filename, "r");
    135140        if (!fp) {
    136                 return;
     141                return 0;
    137142        }
    138143
    139144        while(1) {
     
    151156        }
    152157
    153158        fclose(fp);
     159        return (int)hds->hd_count;
    154160}
    155161
    156162#if defined(__WINDOWS__)
    157 void hdhomerun_device_selector_load_from_windows_registry(struct hdhomerun_device_selector_t *hds, wchar_t *wsource)
     163int hdhomerun_device_selector_load_from_windows_registry(struct hdhomerun_device_selector_t *hds, wchar_t *wsource)
    158164{
    159165        HKEY tuners_key;
    160166        LONG ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Silicondust\\HDHomeRun\\Tuners", 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &tuners_key);
    161167        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;
    164170        }
    165171
    166172        DWORD index = 0;
     
    177183                HKEY device_key;
    178184                ret = RegOpenKeyEx(tuners_key, wdevice_name, 0, KEY_QUERY_VALUE, &device_key);
    179185                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);
    181187                        continue;
    182188                }
    183189
     
    207213        }
    208214
    209215        RegCloseKey(tuners_key);
     216        return (int)hds->hd_count;
    210217}
    211218#endif
    212219
     
    268275        /*
    269276         * Test local port.
    270277         */
    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) {
    273280                hdhomerun_debug_printf(hds->dbg, "hdhomerun_device_selector_choose_test: device %s in use, failed to create test sock\n", name);
    274281                return FALSE;
    275282        }
    276283
    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);
    284286
    285         if (ret != 0) {
     287        if (inuse) {
    286288                hdhomerun_debug_printf(hds->dbg, "hdhomerun_device_selector_choose_test: device %s in use by local machine\n", name);
    287289                return FALSE;
    288290        }
  • libs/libmythhdhomerun/hdhomerun_device.c

     
    3737        struct hdhomerun_video_sock_t *vs;
    3838        struct hdhomerun_debug_t *dbg;
    3939        struct hdhomerun_channelscan_t *scan;
     40        uint32_t multicast_ip;
     41        uint16_t multicast_port;
    4042        uint32_t device_id;
    4143        unsigned int tuner;
    4244        uint32_t lockkey;
     
    4446        char model[32];
    4547};
    4648
    47 static void hdhomerun_device_set_update(struct hdhomerun_device_t *hd)
     49static int hdhomerun_device_set_device_normal(struct hdhomerun_device_t *hd, uint32_t device_id, uint32_t device_ip)
    4850{
    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        }
    5158
    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 {
    5859        hdhomerun_control_set_device(hd->cs, device_id, device_ip);
    5960
    6061        if ((device_id == 0) || (device_id == HDHOMERUN_DEVICE_ID_WILDCARD)) {
    6162                device_id = hdhomerun_control_get_device_id(hd->cs);
    6263        }
    6364
     65        hd->multicast_ip = 0;
     66        hd->multicast_port = 0;
    6467        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;
    6675}
    6776
    68 void hdhomerun_device_set_tuner(struct hdhomerun_device_t *hd, unsigned int tuner)
     77static int hdhomerun_device_set_device_multicast(struct hdhomerun_device_t *hd, uint32_t multicast_ip)
    6978{
     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
     97int 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
     111int 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
    70122        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;
    72126}
    73127
    74128struct hdhomerun_device_t *hdhomerun_device_create(uint32_t device_id, uint32_t device_ip, unsigned int tuner, struct hdhomerun_debug_t *dbg)
    75129{
    76130        struct hdhomerun_device_t *hd = (struct hdhomerun_device_t *)calloc(1, sizeof(struct hdhomerun_device_t));
    77131        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");
    79133                return NULL;
    80134        }
    81135
    82136        hd->dbg = dbg;
    83137
    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) {
    87143                free(hd);
    88144                return NULL;
    89145        }
     146        if (hdhomerun_device_set_tuner(hd, tuner) <= 0) {
     147                free(hd);
     148                return NULL;
     149        }
    90150
    91         hdhomerun_device_set_device(hd, device_id, device_ip);
    92         hdhomerun_device_set_tuner(hd, tuner);
    93 
    94151        return hd;
    95152}
    96153
     
    104161                hdhomerun_video_destroy(hd->vs);
    105162        }
    106163
    107         hdhomerun_control_destroy(hd->cs);
     164        if (hd->cs) {
     165                hdhomerun_control_destroy(hd->cs);
     166        }
    108167
    109168        free(hd);
    110169}
     
    156215static struct hdhomerun_device_t *hdhomerun_device_create_from_str_ip(const char *device_str, struct hdhomerun_debug_t *dbg)
    157216{
    158217        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) {
    163220                if (sscanf(device_str, "%lu.%lu.%lu.%lu", &a[0], &a[1], &a[2], &a[3]) != 4) {
    164221                        return NULL;
    165222                }
    166223        }
    167224
    168225        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;
    170236}
    171237
    172238static struct hdhomerun_device_t *hdhomerun_device_create_from_str_dns(const char *device_str, struct hdhomerun_debug_t *dbg)
     
    239305
    240306uint32_t hdhomerun_device_get_device_id(struct hdhomerun_device_t *hd)
    241307{
    242         return hdhomerun_control_get_device_id(hd->cs);
     308        return hd->device_id;
    243309}
    244310
    245311uint32_t hdhomerun_device_get_device_ip(struct hdhomerun_device_t *hd)
    246312{
    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;
    248321}
    249322
    250323uint32_t hdhomerun_device_get_device_id_requested(struct hdhomerun_device_t *hd)
    251324{
    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;
    253333}
    254334
    255335uint32_t hdhomerun_device_get_device_ip_requested(struct hdhomerun_device_t *hd)
    256336{
    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;
    258345}
    259346
    260347unsigned int hdhomerun_device_get_tuner(struct hdhomerun_device_t *hd)
     
    273360                return hd->vs;
    274361        }
    275362
    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);
    277364        if (!hd->vs) {
    278365                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_video_sock: failed to create video object\n");
    279366                return NULL;
     
    284371
    285372uint32_t hdhomerun_device_get_local_machine_addr(struct hdhomerun_device_t *hd)
    286373{
    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;
    288379}
    289380
    290381static uint32_t hdhomerun_device_get_status_parse(const char *status_str, const char *tag)
     
    368459
    369460int hdhomerun_device_get_tuner_status(struct hdhomerun_device_t *hd, char **pstatus_str, struct hdhomerun_tuner_status_t *status)
    370461{
     462        if (!hd->cs) {
     463                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_status: device not set\n");
     464                return -1;
     465        }
     466
    371467        memset(status, 0, sizeof(struct hdhomerun_tuner_status_t));
    372468
    373469        char name[32];
     
    414510
    415511int hdhomerun_device_get_tuner_streaminfo(struct hdhomerun_device_t *hd, char **pstreaminfo)
    416512{
     513        if (!hd->cs) {
     514                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_streaminfo: device not set\n");
     515                return -1;
     516        }
     517
    417518        char name[32];
    418519        sprintf(name, "/tuner%u/streaminfo", hd->tuner);
    419520        return hdhomerun_control_get(hd->cs, name, pstreaminfo, NULL);
     
    421522
    422523int hdhomerun_device_get_tuner_channel(struct hdhomerun_device_t *hd, char **pchannel)
    423524{
     525        if (!hd->cs) {
     526                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_channel: device not set\n");
     527                return -1;
     528        }
     529
    424530        char name[32];
    425531        sprintf(name, "/tuner%u/channel", hd->tuner);
    426532        return hdhomerun_control_get(hd->cs, name, pchannel, NULL);
     
    428534
    429535int hdhomerun_device_get_tuner_channelmap(struct hdhomerun_device_t *hd, char **pchannelmap)
    430536{
     537        if (!hd->cs) {
     538                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_channelmap: device not set\n");
     539                return -1;
     540        }
     541
    431542        char name[32];
    432543        sprintf(name, "/tuner%u/channelmap", hd->tuner);
    433544        return hdhomerun_control_get(hd->cs, name, pchannelmap, NULL);
     
    435546
    436547int hdhomerun_device_get_tuner_filter(struct hdhomerun_device_t *hd, char **pfilter)
    437548{
     549        if (!hd->cs) {
     550                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_filter: device not set\n");
     551                return -1;
     552        }
     553
    438554        char name[32];
    439555        sprintf(name, "/tuner%u/filter", hd->tuner);
    440556        return hdhomerun_control_get(hd->cs, name, pfilter, NULL);
     
    442558
    443559int hdhomerun_device_get_tuner_program(struct hdhomerun_device_t *hd, char **pprogram)
    444560{
     561        if (!hd->cs) {
     562                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_program: device not set\n");
     563                return -1;
     564        }
     565
    445566        char name[32];
    446567        sprintf(name, "/tuner%u/program", hd->tuner);
    447568        return hdhomerun_control_get(hd->cs, name, pprogram, NULL);
     
    449570
    450571int hdhomerun_device_get_tuner_target(struct hdhomerun_device_t *hd, char **ptarget)
    451572{
     573        if (!hd->cs) {
     574                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_target: device not set\n");
     575                return -1;
     576        }
     577
    452578        char name[32];
    453579        sprintf(name, "/tuner%u/target", hd->tuner);
    454580        return hdhomerun_control_get(hd->cs, name, ptarget, NULL);
     
    456582
    457583int hdhomerun_device_get_tuner_plotsample(struct hdhomerun_device_t *hd, struct hdhomerun_plotsample_t **psamples, size_t *pcount)
    458584{
     585        if (!hd->cs) {
     586                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_plotsample: device not set\n");
     587                return -1;
     588        }
     589
    459590        char name[32];
    460591        sprintf(name, "/tuner%u/plotsample", hd->tuner);
    461592
     
    505636
    506637int hdhomerun_device_get_tuner_lockkey_owner(struct hdhomerun_device_t *hd, char **powner)
    507638{
     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
    508644        char name[32];
    509645        sprintf(name, "/tuner%u/lockkey", hd->tuner);
    510646        return hdhomerun_control_get(hd->cs, name, powner, NULL);
     
    512648
    513649int hdhomerun_device_get_ir_target(struct hdhomerun_device_t *hd, char **ptarget)
    514650{
     651        if (!hd->cs) {
     652                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_ir_target: device not set\n");
     653                return -1;
     654        }
     655
    515656        return hdhomerun_control_get(hd->cs, "/ir/target", ptarget, NULL);
    516657}
    517658
    518659int hdhomerun_device_get_lineup_location(struct hdhomerun_device_t *hd, char **plocation)
    519660{
     661        if (!hd->cs) {
     662                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_lineup_location: device not set\n");
     663                return -1;
     664        }
     665
    520666        return hdhomerun_control_get(hd->cs, "/lineup/location", plocation, NULL);
    521667}
    522668
    523669int hdhomerun_device_get_version(struct hdhomerun_device_t *hd, char **pversion_str, uint32_t *pversion_num)
    524670{
     671        if (!hd->cs) {
     672                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_version: device not set\n");
     673                return -1;
     674        }
     675
    525676        char *version_str;
    526677        int ret = hdhomerun_control_get(hd->cs, "/sys/version", &version_str, NULL);
    527678        if (ret <= 0) {
     
    546697
    547698int hdhomerun_device_set_tuner_channel(struct hdhomerun_device_t *hd, const char *channel)
    548699{
     700        if (!hd->cs) {
     701                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_channel: device not set\n");
     702                return -1;
     703        }
     704
    549705        char name[32];
    550706        sprintf(name, "/tuner%u/channel", hd->tuner);
    551707        return hdhomerun_control_set_with_lockkey(hd->cs, name, channel, hd->lockkey, NULL, NULL);
     
    553709
    554710int hdhomerun_device_set_tuner_channelmap(struct hdhomerun_device_t *hd, const char *channelmap)
    555711{
     712        if (!hd->cs) {
     713                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_channelmap: device not set\n");
     714                return -1;
     715        }
     716
    556717        char name[32];
    557718        sprintf(name, "/tuner%u/channelmap", hd->tuner);
    558719        return hdhomerun_control_set_with_lockkey(hd->cs, name, channelmap, hd->lockkey, NULL, NULL);
     
    560721
    561722int hdhomerun_device_set_tuner_filter(struct hdhomerun_device_t *hd, const char *filter)
    562723{
     724        if (!hd->cs) {
     725                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_filter: device not set\n");
     726                return -1;
     727        }
     728
    563729        char name[32];
    564730        sprintf(name, "/tuner%u/filter", hd->tuner);
    565731        return hdhomerun_control_set_with_lockkey(hd->cs, name, filter, hd->lockkey, NULL, NULL);
     
    635801
    636802int hdhomerun_device_set_tuner_program(struct hdhomerun_device_t *hd, const char *program)
    637803{
     804        if (!hd->cs) {
     805                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_program: device not set\n");
     806                return -1;
     807        }
     808
    638809        char name[32];
    639810        sprintf(name, "/tuner%u/program", hd->tuner);
    640811        return hdhomerun_control_set_with_lockkey(hd->cs, name, program, hd->lockkey, NULL, NULL);
     
    642813
    643814int hdhomerun_device_set_tuner_target(struct hdhomerun_device_t *hd, const char *target)
    644815{
     816        if (!hd->cs) {
     817                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_target: device not set\n");
     818                return -1;
     819        }
     820
    645821        char name[32];
    646822        sprintf(name, "/tuner%u/target", hd->tuner);
    647823        return hdhomerun_control_set_with_lockkey(hd->cs, name, target, hd->lockkey, NULL, NULL);
    648824}
    649825
    650 int hdhomerun_device_set_tuner_target_to_local_protocol(struct hdhomerun_device_t *hd, const char *protocol)
     826static int hdhomerun_device_set_tuner_target_to_local(struct hdhomerun_device_t *hd, const char *protocol)
    651827{
    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        }
    654832        if (!hd->vs) {
     833                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_target_to_local: video not initialized\n");
    655834                return -1;
    656835        }
    657836
     
    669848        return hdhomerun_device_set_tuner_target(hd, target);
    670849}
    671850
    672 int hdhomerun_device_set_tuner_target_to_local(struct hdhomerun_device_t *hd)
     851int hdhomerun_device_set_ir_target(struct hdhomerun_device_t *hd, const char *target)
    673852{
    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        }
    676857
    677 int hdhomerun_device_set_ir_target(struct hdhomerun_device_t *hd, const char *target)
    678 {
    679858        return hdhomerun_control_set(hd->cs, "/ir/target", target, NULL, NULL);
    680859}
    681860
    682861int hdhomerun_device_set_lineup_location(struct hdhomerun_device_t *hd, const char *location)
    683862{
     863        if (!hd->cs) {
     864                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_lineup_location: device not set\n");
     865                return -1;
     866        }
     867
    684868        return hdhomerun_control_set(hd->cs, "/lineup/location", location, NULL, NULL);
    685869}
    686870
     871int 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
    687881int hdhomerun_device_get_var(struct hdhomerun_device_t *hd, const char *name, char **pvalue, char **perror)
    688882{
     883        if (!hd->cs) {
     884                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_var: device not set\n");
     885                return -1;
     886        }
     887
    689888        return hdhomerun_control_get(hd->cs, name, pvalue, perror);
    690889}
    691890
    692891int hdhomerun_device_set_var(struct hdhomerun_device_t *hd, const char *name, const char *value, char **pvalue, char **perror)
    693892{
     893        if (!hd->cs) {
     894                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_var: device not set\n");
     895                return -1;
     896        }
     897
    694898        return hdhomerun_control_set_with_lockkey(hd->cs, name, value, hd->lockkey, pvalue, perror);
    695899}
    696900
    697901int hdhomerun_device_tuner_lockkey_request(struct hdhomerun_device_t *hd, char **perror)
    698902{
     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
    699911        uint32_t new_lockkey = (uint32_t)getcurrenttime();
    700912
    701913        char name[32];
     
    716928
    717929int hdhomerun_device_tuner_lockkey_release(struct hdhomerun_device_t *hd)
    718930{
     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
    719939        if (hd->lockkey == 0) {
    720940                return 1;
    721941        }
     
    730950
    731951int hdhomerun_device_tuner_lockkey_force(struct hdhomerun_device_t *hd)
    732952{
     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
    733961        char name[32];
    734962        sprintf(name, "/tuner%u/lockkey", hd->tuner);
    735963        int ret = hdhomerun_control_set(hd->cs, name, "force", NULL, NULL);
     
    740968
    741969void hdhomerun_device_tuner_lockkey_use_value(struct hdhomerun_device_t *hd, uint32_t lockkey)
    742970{
     971        if (hd->multicast_ip != 0) {
     972                return;
     973        }
     974
    743975        hd->lockkey = lockkey;
    744976}
    745977
    746978int hdhomerun_device_wait_for_lock(struct hdhomerun_device_t *hd, struct hdhomerun_tuner_status_t *status)
    747979{
    748980        /* Delay for SS reading to be valid (signal present). */
    749         msleep(250);
     981        msleep_minimum(250);
    750982
    751983        /* Wait for up to 2.5 seconds for lock. */
    752984        uint64_t timeout = getcurrenttime() + 2500;
     
    7681000                        return 1;
    7691001                }
    7701002
    771                 msleep(250);
     1003                msleep_approx(250);
    7721004        }
    7731005}
    7741006
    7751007int hdhomerun_device_stream_start(struct hdhomerun_device_t *hd)
    7761008{
     1009        hdhomerun_device_get_video_sock(hd);
     1010        if (!hd->vs) {
     1011                return -1;
     1012        }
     1013
    7771014        /* 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                }
    7811028        }
    7821029
    7831030        /* Flush video buffer. */
    784         msleep(64);
     1031        msleep_minimum(64);
    7851032        hdhomerun_video_flush(hd->vs);
    7861033
    7871034        /* Success. */
    7881035        return 1;
    7891036}
    7901037
    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 
    8001038uint8_t *hdhomerun_device_stream_recv(struct hdhomerun_device_t *hd, size_t max_size, size_t *pactual_size)
    8011039{
    8021040        if (!hd->vs) {
     1041                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_stream_recv: video not initialized\n");
    8031042                return NULL;
    8041043        }
     1044
    8051045        return hdhomerun_video_recv(hd->vs, max_size, pactual_size);
    8061046}
    8071047
    8081048void hdhomerun_device_stream_flush(struct hdhomerun_device_t *hd)
    8091049{
     1050        if (!hd->vs) {
     1051                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_stream_flush: video not initialized\n");
     1052                return;
     1053        }
     1054
    8101055        hdhomerun_video_flush(hd->vs);
    8111056}
    8121057
    8131058void hdhomerun_device_stream_stop(struct hdhomerun_device_t *hd)
    8141059{
    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        }
    8161070}
    8171071
    8181072int hdhomerun_device_channelscan_init(struct hdhomerun_device_t *hd, const char *channelmap)
     
    8231077
    8241078        hd->scan = channelscan_create(hd, channelmap);
    8251079        if (!hd->scan) {
     1080                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_channelscan_init: failed to create scan object\n");
    8261081                return -1;
    8271082        }
    8281083
     
    8321087int hdhomerun_device_channelscan_advance(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result)
    8331088{
    8341089        if (!hd->scan) {
     1090                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_channelscan_advance: scan not initialized\n");
    8351091                return 0;
    8361092        }
    8371093
     
    8471103int hdhomerun_device_channelscan_detect(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result)
    8481104{
    8491105        if (!hd->scan) {
     1106                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_channelscan_detect: scan not initialized\n");
    8501107                return 0;
    8511108        }
    8521109
     
    8621119uint8_t hdhomerun_device_channelscan_get_progress(struct hdhomerun_device_t *hd)
    8631120{
    8641121        if (!hd->scan) {
     1122                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_channelscan_get_progress: scan not initialized\n");
    8651123                return 0;
    8661124        }
    8671125
    8681126        return channelscan_get_progress(hd->scan);
    8691127}
    8701128
    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 
    8851129const char *hdhomerun_device_get_model_str(struct hdhomerun_device_t *hd)
    8861130{
    8871131        if (*hd->model) {
    8881132                return hd->model;
    8891133        }
    8901134
     1135        if (!hd->cs) {
     1136                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_model_str: device not set\n");
     1137                return NULL;
     1138        }
     1139
    8911140        char *model_str;
    8921141        int ret = hdhomerun_control_get(hd->cs, "/sys/model", &model_str, NULL);
    8931142        if (ret < 0) {
    8941143                return NULL;
    8951144        }
    8961145        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";
    8991147        }
    900         else
    901         {
    902                 strncpy(hd->model, model_str, sizeof(hd->model) - 1);
    903                 hd->model[sizeof(hd->model) - 1] = 0;
    904         }
    9051148
     1149        strncpy(hd->model, model_str, sizeof(hd->model) - 1);
     1150        hd->model[sizeof(hd->model) - 1] = 0;
     1151
    9061152        return hd->model;
    9071153}
    9081154
    9091155int hdhomerun_device_upgrade(struct hdhomerun_device_t *hd, FILE *upgrade_file)
    9101156{
     1157        if (!hd->cs) {
     1158                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_upgrade: device not set\n");
     1159                return -1;
     1160        }
     1161
    9111162        hdhomerun_control_set(hd->cs, "/tuner0/lockkey", "force", NULL, NULL);
    9121163        hdhomerun_control_set(hd->cs, "/tuner0/channel", "none", NULL, NULL);
    9131164
     
    9231174                return;
    9241175        }
    9251176
    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);
    9281180
    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                }
    9361188
    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                }
    9411194        }
    9421195
    9431196        if (hd->vs) {
     
    9471200
    9481201void hdhomerun_device_get_video_stats(struct hdhomerun_device_t *hd, struct hdhomerun_video_stats_t *stats)
    9491202{
     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
    9501209        hdhomerun_video_get_stats(hd->vs, stats);
    9511210}
  • libs/libmythhdhomerun/hdhomerun_os_windows.h

     
    11/*
    22 * hdhomerun_os_windows.h
    33 *
    4  * Copyright © 2006-2008 Silicondust USA Inc. <www.silicondust.com>.
     4 * Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>.
    55 *
    66 * This library is free software; you can redistribute it and/or
    77 * modify it under the terms of the GNU Lesser General Public
     
    3131 */
    3232
    3333#define _WINSOCKAPI_
    34 // MinGW lacks wspiapi, so remove dependency by setting minimum WINVER to WinXP
    35 #define WINVER 0x0501
    3634#include <windows.h>
    3735#include <winsock2.h>
    3836#include <ws2tcpip.h>
    39 //#include <wspiapi.h>
     37#include <wspiapi.h>
    4038#include <stdlib.h>
    4139#include <stdio.h>
    4240#include <stdarg.h>
     
    5553#endif
    5654
    5755typedef int bool_t;
    58 /* Use MinGW includes instead
    5956typedef signed __int8 int8_t;
    6057typedef signed __int16 int16_t;
    6158typedef signed __int32 int32_t;
     
    6663typedef unsigned __int64 uint64_t;
    6764typedef HANDLE pthread_t;
    6865typedef HANDLE pthread_mutex_t;
    69 */
    70 #include <stdint.h>
    71 #include <pthread.h>
    7266
    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
    8068#define atoll _atoi64
    8169#define strdup _strdup
    8270#define strcasecmp _stricmp
     
    8573#define ftello _ftelli64
    8674#define THREAD_FUNC_PREFIX DWORD WINAPI
    8775#define SIGPIPE SIGABRT
     76
     77#ifdef __cplusplus
     78extern "C" {
    8879#endif
    8980
    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 }
     81extern LIBTYPE uint64_t getcurrenttime(void);
     82extern LIBTYPE void msleep_approx(uint64_t ms);
     83extern LIBTYPE void msleep_minimum(uint64_t ms);
    9684
    97 static inline int msleep(unsigned int ms)
    98 {
    99         uint64_t stop_time = getcurrenttime() + ms;
     85extern LIBTYPE int pthread_create(pthread_t *tid, void *attr, LPTHREAD_START_ROUTINE start, void *arg);
     86extern LIBTYPE int pthread_join(pthread_t tid, void **value_ptr);
     87extern LIBTYPE void pthread_mutex_init(pthread_mutex_t *mutex, void *attr);
     88extern LIBTYPE void pthread_mutex_lock(pthread_mutex_t *mutex);
     89extern LIBTYPE void pthread_mutex_unlock(pthread_mutex_t *mutex);
    10090
    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 conflict
    113 /*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 instead
    127 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 
    16591/*
    16692 * The console output format should be set to UTF-8, however in XP and Vista this breaks batch file processing.
    16793 * Attempting to restore on exit fails to restore if the program is terminated by the user.
    16894 * Solution - set the output format each printf.
    16995 */
    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 }
     96extern LIBTYPE void console_vprintf(const char *fmt, va_list ap);
     97extern LIBTYPE void console_printf(const char *fmt, ...);
    17798
    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
    184100}
     101#endif
  • libs/libmythhdhomerun/hdhomerun_device.h

     
    9090extern LIBTYPE uint32_t hdhomerun_device_get_device_ip_requested(struct hdhomerun_device_t *hd);
    9191extern LIBTYPE unsigned int hdhomerun_device_get_tuner(struct hdhomerun_device_t *hd);
    9292
    93 extern LIBTYPE void hdhomerun_device_set_device(struct hdhomerun_device_t *hd, uint32_t device_id, uint32_t device_ip);
    94 extern LIBTYPE void hdhomerun_device_set_tuner(struct hdhomerun_device_t *hd, unsigned int tuner);
     93extern LIBTYPE int hdhomerun_device_set_device(struct hdhomerun_device_t *hd, uint32_t device_id, uint32_t device_ip);
     94extern LIBTYPE int hdhomerun_device_set_tuner(struct hdhomerun_device_t *hd, unsigned int tuner);
    9595extern LIBTYPE int hdhomerun_device_set_tuner_from_str(struct hdhomerun_device_t *hd, const char *tuner_str);
    9696
    9797/*
     
    148148extern LIBTYPE int hdhomerun_device_set_tuner_filter_by_array(struct hdhomerun_device_t *hd, unsigned char filter_array[0x2000]);
    149149extern LIBTYPE int hdhomerun_device_set_tuner_program(struct hdhomerun_device_t *hd, const char *program);
    150150extern 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);
    153151extern LIBTYPE int hdhomerun_device_set_ir_target(struct hdhomerun_device_t *hd, const char *target);
    154152extern LIBTYPE int hdhomerun_device_set_lineup_location(struct hdhomerun_device_t *hd, const char *location);
     153extern LIBTYPE int hdhomerun_device_set_sys_dvbc_modulation(struct hdhomerun_device_t *hd, const char *modulation_list);
    155154
    156155/*
    157156 * Get/set a named control variable on the device.
     
    224223 * The hdhomerun_device_stream_stop function tells the device to stop streaming data.
    225224 */
    226225extern 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);
    228226extern LIBTYPE uint8_t *hdhomerun_device_stream_recv(struct hdhomerun_device_t *hd, size_t max_size, size_t *pactual_size);
    229227extern LIBTYPE void hdhomerun_device_stream_flush(struct hdhomerun_device_t *hd);
    230228extern LIBTYPE void hdhomerun_device_stream_stop(struct hdhomerun_device_t *hd);
     
    238236extern LIBTYPE uint8_t hdhomerun_device_channelscan_get_progress(struct hdhomerun_device_t *hd);
    239237
    240238/*
    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 /*
    252239 * Upload new firmware to the device.
    253240 *
    254241 * 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

     
    4343extern LIBTYPE void hdhomerun_device_selector_destroy(struct hdhomerun_device_selector_t *hds, bool_t destroy_devices);
    4444
    4545/*
     46 * Get the number of devices in the list.
     47 */
     48extern LIBTYPE int hdhomerun_device_selector_get_device_count(struct hdhomerun_device_selector_t *hds);
     49
     50/*
    4651 * Populate device selector with devices from given source.
     52 * Returns the number of devices populated.
    4753 */
    48 extern LIBTYPE void hdhomerun_device_selector_load_from_file(struct hdhomerun_device_selector_t *hds, char *filename);
     54extern LIBTYPE int hdhomerun_device_selector_load_from_file(struct hdhomerun_device_selector_t *hds, char *filename);
    4955#if defined(__WINDOWS__)
    50 extern LIBTYPE void hdhomerun_device_selector_load_from_windows_registry(struct hdhomerun_device_selector_t *hds, wchar_t *wsource);
     56extern LIBTYPE int hdhomerun_device_selector_load_from_windows_registry(struct hdhomerun_device_selector_t *hds, wchar_t *wsource);
    5157#endif
    5258
    5359/*
  • libs/libmythhdhomerun/hdhomerun_control.c

     
    11/*
    22 * hdhomerun_control.c
    33 *
    4  * Copyright © 2006 Silicondust USA Inc. <www.silicondust.com>.
     4 * Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>.
    55 *
    66 * This library is free software; you can redistribute it and/or
    77 * modify it under the terms of the GNU Lesser General Public
     
    3232
    3333#include "hdhomerun.h"
    3434
    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
    3738#define HDHOMERUN_CONTROL_UPGRADE_TIMEOUT 20000
    3839
    3940struct hdhomerun_control_sock_t {
     
    4950
    5051static void hdhomerun_control_close_sock(struct hdhomerun_control_sock_t *cs)
    5152{
    52         if (cs->sock == -1) {
     53        if (cs->sock == HDHOMERUN_SOCK_INVALID) {
    5354                return;
    5455        }
    5556
    56         close(cs->sock);
    57         cs->sock = -1;
     57        hdhomerun_sock_destroy(cs->sock);
     58        cs->sock = HDHOMERUN_SOCK_INVALID;
    5859}
    5960
    6061void hdhomerun_control_set_device(struct hdhomerun_control_sock_t *cs, uint32_t device_id, uint32_t device_ip)
     
    7677        }
    7778
    7879        cs->dbg = dbg;
    79         cs->sock = -1;
     80        cs->sock = HDHOMERUN_SOCK_INVALID;
    8081        hdhomerun_control_set_device(cs, device_id, device_ip);
    8182
    8283        return cs;
     
    9091
    9192static bool_t hdhomerun_control_connect_sock(struct hdhomerun_control_sock_t *cs)
    9293{
    93         if (cs->sock != -1) {
     94        if (cs->sock != HDHOMERUN_SOCK_INVALID) {
    9495                return TRUE;
    9596        }
    9697
     
    9899                hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_connect_sock: no device specified\n");
    99100                return FALSE;
    100101        }
     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        }
    101106
    102107        /* Find device. */
    103108        struct hdhomerun_discover_device_t result;
     
    109114        cs->actual_device_id = result.device_id;
    110115
    111116        /* 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());
    115120                return FALSE;
    116121        }
    117122
    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 
    122123        /* 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());
    130126                hdhomerun_control_close_sock(cs);
    131127                return FALSE;
    132128        }
     
    172168                return 0;
    173169        }
    174170
    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());
    179174                return 0;
    180175        }
    181176
    182         return ntohl(sock_addr.sin_addr.s_addr);
     177        return addr;
    183178}
    184179
    185 static int hdhomerun_control_send_sock(struct hdhomerun_control_sock_t *cs, struct hdhomerun_pkt_t *tx_pkt)
     180static bool_t hdhomerun_control_send_sock(struct hdhomerun_control_sock_t *cs, struct hdhomerun_pkt_t *tx_pkt)
    186181{
    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());
    190184                hdhomerun_control_close_sock(cs);
    191                 return -1;
     185                return FALSE;
    192186        }
    193187
    194         return 1;
     188        return TRUE;
    195189}
    196190
    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)
     191static 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)
    198192{
    199193        uint64_t stop_time = getcurrenttime() + recv_timeout;
    200194        hdhomerun_pkt_reset(rx_pkt);
    201195
    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");
    213200                        hdhomerun_control_close_sock(cs);
    214                         return -1;
     201                        return FALSE;
    215202                }
    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());
    224207                        hdhomerun_control_close_sock(cs);
    225                         return -1;
     208                        return FALSE;
    226209                }
    227                 rx_pkt->end += rx_length;
    228210
     211                rx_pkt->end += length;
     212
    229213                int ret = hdhomerun_pkt_open_frame(rx_pkt, ptype);
    230214                if (ret < 0) {
    231215                        hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_recv_sock: frame error\n");
    232216                        hdhomerun_control_close_sock(cs);
    233                         return -1;
     217                        return FALSE;
    234218                }
    235                 if (ret == 0) {
    236                         continue;
     219                if (ret > 0) {
     220                        return TRUE;
    237221                }
    238 
    239                 return 1;
    240222        }
    241 
    242         hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_recv_sock: timeout\n");
    243         hdhomerun_control_close_sock(cs);
    244         return -1;
    245223}
    246224
    247225static 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)
     
    250228
    251229        int i;
    252230        for (i = 0; i < 2; i++) {
    253                 if (cs->sock == -1) {
     231                if (cs->sock == HDHOMERUN_SOCK_INVALID) {
    254232                        if (!hdhomerun_control_connect_sock(cs)) {
    255233                                hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_send_recv: connect failed\n");
    256234                                return -1;
    257235                        }
    258236                }
    259237
    260                 if (hdhomerun_control_send_sock(cs, tx_pkt) < 0) {
     238                if (!hdhomerun_control_send_sock(cs, tx_pkt)) {
    261239                        continue;
    262240                }
    263241                if (!rx_pkt) {
     
    265243                }
    266244
    267245                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)) {
    269247                        continue;
    270248                }
    271249                if (rsp_type != type + 1) {
     
    301279        }
    302280        hdhomerun_pkt_write_u8(tx_pkt, HDHOMERUN_TAG_GETSET_NAME);
    303281        hdhomerun_pkt_write_var_length(tx_pkt, name_len);
    304         hdhomerun_pkt_write_mem(tx_pkt, (const void *)name, name_len);
     282        hdhomerun_pkt_write_mem(tx_pkt, (void *)name, name_len);
    305283
    306284        if (value) {
    307285                int value_len = (int)strlen(value) + 1;
     
    311289                }
    312290                hdhomerun_pkt_write_u8(tx_pkt, HDHOMERUN_TAG_GETSET_VALUE);
    313291                hdhomerun_pkt_write_var_length(tx_pkt, value_len);
    314                 hdhomerun_pkt_write_mem(tx_pkt, (const void *)value, value_len);
     292                hdhomerun_pkt_write_mem(tx_pkt, (void *)value, value_len);
    315293        }
    316294
    317295        if (lockkey != 0) {