Ticket #8313: hdhrrevert.diff

File hdhrrevert.diff, 111.1 KB (added by robertm, 10 years ago)

Revert HDHomeRun library updates.

  • mythtv/libs/libmythhdhomerun/hdhomerun.h

     
    33/*
    44 * hdhomerun.h
    55 *
    6  * Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>.
     6 * Copyright © 2006-2008 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"
    3938#include "hdhomerun_debug.h"
    4039#include "hdhomerun_discover.h"
    4140#include "hdhomerun_control.h"
  • mythtv/libs/libmythhdhomerun/hdhomerun_debug.c

     
    11/*
    22 * hdhomerun_debug.c
    33 *
    4  * Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>.
     4 * Copyright © 2006 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 
    5450struct hdhomerun_debug_message_t
    5551{
    5652        struct hdhomerun_debug_message_t *next;
     
    7773
    7874        char *file_name;
    7975        FILE *file_fp;
    80         hdhomerun_sock_t sock;
     76        int sock;
    8177};
    8278
    8379static THREAD_FUNC_PREFIX hdhomerun_debug_thread_execute(void *arg);
     
    8985                return NULL;
    9086        }
    9187
    92         dbg->sock = HDHOMERUN_SOCK_INVALID;
     88        dbg->sock = -1;
    9389
    9490        pthread_mutex_init(&dbg->print_lock, NULL);
    9591        pthread_mutex_init(&dbg->queue_lock, NULL);
     
    121117        if (dbg->file_fp) {
    122118                fclose(dbg->file_fp);
    123119        }
    124         if (dbg->sock != HDHOMERUN_SOCK_INVALID) {
    125                 hdhomerun_sock_destroy(dbg->sock);
     120        if (dbg->sock != -1) {
     121                close(dbg->sock);
    126122        }
    127123
    128124        free(dbg);
     
    136132                dbg->file_fp = NULL;
    137133        }
    138134
    139         if (dbg->sock != HDHOMERUN_SOCK_INVALID) {
    140                 hdhomerun_sock_destroy(dbg->sock);
    141                 dbg->sock = HDHOMERUN_SOCK_INVALID;
     135        if (dbg->sock != -1) {
     136                close(dbg->sock);
     137                dbg->sock = -1;
    142138        }
    143139}
    144140
     
    255251                        return;
    256252                }
    257253
    258                 msleep_approx(10);
     254                msleep(10);
    259255        }
    260256}
    261257
     
    376372}
    377373
    378374/* Send lock held by caller */
     375#if defined(__CYGWIN__)
    379376static bool_t hdhomerun_debug_output_message_sock(struct hdhomerun_debug_t *dbg, struct hdhomerun_debug_message_t *message)
    380377{
    381         if (dbg->sock == HDHOMERUN_SOCK_INVALID) {
     378        return TRUE;
     379}
     380#else
     381static bool_t hdhomerun_debug_output_message_sock(struct hdhomerun_debug_t *dbg, struct hdhomerun_debug_message_t *message)
     382{
     383        if (dbg->sock == -1) {
    382384                uint64_t current_time = getcurrenttime();
    383385                if (current_time < dbg->connect_delay) {
    384386                        return FALSE;
    385387                }
    386                 dbg->connect_delay = current_time + HDHOMERUN_DEBUG_CONNECT_RETRY_TIME;
     388                dbg->connect_delay = current_time + 30*1000;
    387389
    388                 dbg->sock = hdhomerun_sock_create_tcp();
    389                 if (dbg->sock == HDHOMERUN_SOCK_INVALID) {
     390                dbg->sock = (int)socket(AF_INET, SOCK_STREAM, 0);
     391                if (dbg->sock == -1) {
    390392                        return FALSE;
    391393                }
    392394
    393                 uint32_t remote_addr = hdhomerun_sock_getaddrinfo_addr(dbg->sock, HDHOMERUN_DEBUG_HOST);
    394                 if (remote_addr == 0) {
     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) {
    395403                        hdhomerun_debug_close_internal(dbg);
    396404                        return FALSE;
    397405                }
    398 
    399                 if (!hdhomerun_sock_connect(dbg->sock, remote_addr, HDHOMERUN_DEBUG_PORT, HDHOMERUN_DEBUG_CONNECT_TIMEOUT)) {
     406                if (connect(dbg->sock, sock_info->ai_addr, (int)sock_info->ai_addrlen) != 0) {
     407                        freeaddrinfo(sock_info);
    400408                        hdhomerun_debug_close_internal(dbg);
    401409                        return FALSE;
    402410                }
     411                freeaddrinfo(sock_info);
    403412        }
    404413
    405414        size_t length = strlen(message->buffer);
    406         if (!hdhomerun_sock_send(dbg->sock, message->buffer, length, HDHOMERUN_DEBUG_SEND_TIMEOUT)) {
     415        if (send(dbg->sock, (char *)message->buffer, (int)length, 0) != length) {
    407416                hdhomerun_debug_close_internal(dbg);
    408417                return FALSE;
    409418        }
    410419
    411420        return TRUE;
    412421}
     422#endif
    413423
    414424static bool_t hdhomerun_debug_output_message(struct hdhomerun_debug_t *dbg, struct hdhomerun_debug_message_t *message)
    415425{
     
    456466                pthread_mutex_unlock(&dbg->queue_lock);
    457467
    458468                if (!message) {
    459                         msleep_approx(250);
     469                        msleep(250);
    460470                        continue;
    461471                }
    462472
     
    466476                }
    467477
    468478                if (!hdhomerun_debug_output_message(dbg, message)) {
    469                         msleep_approx(250);
     479                        msleep(250);
    470480                        continue;
    471481                }
    472482
  • mythtv/libs/libmythhdhomerun/libmythhdhomerun.pro

     
    1010
    1111QMAKE_CLEAN += $(TARGET) $(TARGETA) $(TARGETD) $(TARGET0) $(TARGET1) $(TARGET2)
    1212
    13 HEADERS += hdhomerun.h  hdhomerun_os.h  hdhomerun_sock.h  hdhomerun_types.h
     13HEADERS += hdhomerun.h  hdhomerun_os.h  hdhomerun_types.h
    1414
    1515HEADERS += hdhomerun_channels.h  hdhomerun_channelscan.h  hdhomerun_control.h
    16 HEADERS += hdhomerun_debug.h     hdhomerun_device.h
     16HEADERS += hdhomerun_debug.h     hdhomerun_device.h       hdhomerun_dhcp.h
     17HEADERS += hdhomerun_discover.h  hdhomerun_pkt.h          hdhomerun_video.h
    1718HEADERS += hdhomerun_device_selector.h
    18 HEADERS += hdhomerun_discover.h  hdhomerun_os_posix.h
    19 HEADERS += hdhomerun_pkt.h       hdhomerun_video.h
    2019
    21 SOURCES += hdhomerun_config.c
    22 
    2320SOURCES += hdhomerun_channels.c  hdhomerun_channelscan.c  hdhomerun_control.c
    24 SOURCES += hdhomerun_debug.c     hdhomerun_device.c
     21SOURCES += hdhomerun_debug.c     hdhomerun_device.c       hdhomerun_dhcp.c
     22SOURCES += hdhomerun_discover.c  hdhomerun_pkt.c          hdhomerun_video.c
    2523SOURCES += hdhomerun_device_selector.c
    26 SOURCES += hdhomerun_discover.c  hdhomerun_os_posix.c
    27 SOURCES += hdhomerun_pkt.c       hdhomerun_video.c
    2824
    29 
    30 unix:SOURCES += hdhomerun_sock_posix.c
    31 
    3225mingw {
    3326    HEADERS += hdhomerun_os_windows.h
    34     SOURCES += hdhomerun_os_windows.c
    35     SOURCES -= hdhomerun_os_posix.c
    36     SOURCES += hdhomerun_sock_windows.c
    3727    LIBS += -lws2_32 -liphlpapi -lpthread
    3828}
    3929
    40 LIBS += $$EXTRALIBS
    41 
    4230include ( ../libs-targetfix.pro )
  • mythtv/libs/libmythhdhomerun/hdhomerun_os_posix.c

     
    1 /*
    2  * hdhomerun_os_posix.c
    3  *
    4  * Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>.
    5  *
    6  * This library is free software; you can redistribute it and/or
    7  * modify it under the terms of the GNU Lesser General Public
    8  * License as published by the Free Software Foundation; either
    9  * version 3 of the License, or (at your option) any later version.
    10  *
    11  * This library is distributed in the hope that it will be useful,
    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    14  * Lesser General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU Lesser General Public
    17  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
    18  *
    19  * As a special exception to the GNU Lesser General Public License,
    20  * you may link, statically or dynamically, an application with a
    21  * publicly distributed version of the Library to produce an
    22  * executable file containing portions of the Library, and
    23  * distribute that executable file under terms of your choice,
    24  * without any of the additional requirements listed in clause 4 of
    25  * the GNU Lesser General Public License.
    26  *
    27  * By "a publicly distributed version of the Library", we mean
    28  * either the unmodified Library as distributed by Silicondust, or a
    29  * modified version of the Library that is distributed under the
    30  * conditions defined in the GNU Lesser General Public License.
    31  */
    32 
    33 #include "hdhomerun_os.h"
    34 
    35 uint64_t getcurrenttime(void)
    36 {
    37         static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
    38         static uint64_t result = 0;
    39         static uint64_t previous_time = 0;
    40 
    41         pthread_mutex_lock(&lock);
    42 
    43 #if defined(CLOCK_MONOTONIC)
    44         struct timespec tp;
    45         clock_gettime(CLOCK_MONOTONIC, &tp);
    46         uint64_t current_time = ((uint64_t)tp.tv_sec * 1000) + (tp.tv_nsec / 1000000);
    47 #else
    48         struct timeval t;
    49         gettimeofday(&t, NULL);
    50         uint64_t current_time = ((uint64_t)t.tv_sec * 1000) + (t.tv_usec / 1000);
    51 #endif
    52 
    53         if (current_time > previous_time) {
    54                 result += current_time - previous_time;
    55         }
    56 
    57         previous_time = current_time;
    58 
    59         pthread_mutex_unlock(&lock);
    60         return result;
    61 }
    62 
    63 void msleep_approx(uint64_t ms)
    64 {
    65         unsigned int delay_s = ms / 1000;
    66         if (delay_s > 0) {
    67                 sleep(delay_s);
    68                 ms -= delay_s * 1000;
    69         }
    70 
    71         unsigned int delay_us = ms * 1000;
    72         if (delay_us > 0) {
    73                 usleep(delay_us);
    74         }
    75 }
    76 
    77 void msleep_minimum(uint64_t ms)
    78 {
    79         uint64_t stop_time = getcurrenttime() + ms;
    80 
    81         while (1) {
    82                 uint64_t current_time = getcurrenttime();
    83                 if (current_time >= stop_time) {
    84                         return;
    85                 }
    86 
    87                 msleep_approx(stop_time - current_time);
    88         }
    89 }
  • mythtv/libs/libmythhdhomerun/hdhomerun_sock.h

     
    1 /*
    2  * hdhomerun_sock.h
    3  *
    4  * Copyright © 2010 Silicondust USA Inc. <www.silicondust.com>.
    5  *
    6  * This library is free software; you can redistribute it and/or
    7  * modify it under the terms of the GNU Lesser General Public
    8  * License as published by the Free Software Foundation; either
    9  * version 3 of the License, or (at your option) any later version.
    10  *
    11  * This library is distributed in the hope that it will be useful,
    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    14  * Lesser General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU Lesser General Public
    17  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
    18  *
    19  * As a special exception to the GNU Lesser General Public License,
    20  * you may link, statically or dynamically, an application with a
    21  * publicly distributed version of the Library to produce an
    22  * executable file containing portions of the Library, and
    23  * distribute that executable file under terms of your choice,
    24  * without any of the additional requirements listed in clause 4 of
    25  * the GNU Lesser General Public License.
    26  *
    27  * By "a publicly distributed version of the Library", we mean
    28  * either the unmodified Library as distributed by Silicondust, or a
    29  * modified version of the Library that is distributed under the
    30  * conditions defined in the GNU Lesser General Public License.
    31  */
    32 #ifdef __cplusplus
    33 extern "C" {
    34 #endif
    35 
    36 #define HDHOMERUN_SOCK_INVALID -1
    37 
    38 typedef int hdhomerun_sock_t;
    39 
    40 extern LIBTYPE hdhomerun_sock_t hdhomerun_sock_create_udp(void);
    41 extern LIBTYPE hdhomerun_sock_t hdhomerun_sock_create_tcp(void);
    42 extern LIBTYPE void hdhomerun_sock_destroy(hdhomerun_sock_t sock);
    43 
    44 extern LIBTYPE int hdhomerun_sock_getlasterror(void);
    45 extern LIBTYPE uint32_t hdhomerun_sock_getsockname_addr(hdhomerun_sock_t sock);
    46 extern LIBTYPE uint16_t hdhomerun_sock_getsockname_port(hdhomerun_sock_t sock);
    47 extern LIBTYPE uint32_t hdhomerun_sock_getpeername_addr(hdhomerun_sock_t sock);
    48 extern LIBTYPE uint32_t hdhomerun_sock_getaddrinfo_addr(hdhomerun_sock_t sock, const char *name);
    49 
    50 extern LIBTYPE bool_t hdhomerun_sock_bind(hdhomerun_sock_t sock, uint32_t local_addr, uint16_t local_port);
    51 extern LIBTYPE bool_t hdhomerun_sock_connect(hdhomerun_sock_t sock, uint32_t remote_addr, uint16_t remote_port, uint64_t timeout);
    52 
    53 extern LIBTYPE bool_t hdhomerun_sock_send(hdhomerun_sock_t sock, const void *data, size_t length, uint64_t timeout);
    54 extern LIBTYPE bool_t hdhomerun_sock_sendto(hdhomerun_sock_t sock, uint32_t remote_addr, uint16_t remote_port, const void *data, size_t length, uint64_t timeout);
    55 
    56 extern LIBTYPE bool_t hdhomerun_sock_recv(hdhomerun_sock_t sock, void *data, size_t *length, uint64_t timeout);
    57 extern LIBTYPE bool_t hdhomerun_sock_recvfrom(hdhomerun_sock_t sock, uint32_t *remote_addr, uint16_t *remote_port, void *data, size_t *length, uint64_t timeout);
    58 
    59 
    60 #ifdef __cplusplus
    61 }
    62 #endif
  • mythtv/libs/libmythhdhomerun/hdhomerun_config.c

     
    286286                }
    287287
    288288                cmd_scan_printf(fp, "SCANNING: %lu (%s)\n",
    289                         (unsigned long)result.frequency, result.channel_str
     289                        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_approx(64);
     367                        msleep(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. */
    390384                        hdhomerun_device_get_video_stats(hd, &stats_cur);
    391385
    392386                        if (stats_cur.overflow_error_count > stats_old.overflow_error_count) {
     
    410404                        continue;
    411405                }
    412406
    413                 msleep_approx(delay);
     407                msleep(delay);
    414408        }
    415409
    416410        if (fp) {
     
    446440                fclose(fp);
    447441                return -1;
    448442        }
    449         msleep_minimum(2000);
     443        sleep(2);
    450444
    451445        printf("upgrading firmware...\n");
    452         msleep_minimum(8000);
     446        sleep(8);
    453447
    454448        printf("rebooting...\n");
    455449        int count = 0;
     
    466460                        return -1;
    467461                }
    468462
    469                 msleep_minimum(1000);
     463                sleep(1);
    470464        }
    471465
    472466        printf("upgrade complete - now running firmware %s\n", version_str);
  • mythtv/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;
    4437        uint8_t *buffer;
    4538        size_t buffer_size;
     39        volatile size_t head;
     40        volatile size_t tail;
    4641        size_t advance;
    47 
    48         pthread_t thread;
    4942        volatile bool_t terminate;
    50 
     43        pthread_t thread;
     44        int sock;
     45        uint32_t rtp_sequence;
     46        struct hdhomerun_debug_t *dbg;
    5147        volatile uint32_t packet_count;
    5248        volatile uint32_t transport_error_count;
    5349        volatile uint32_t network_error_count;
    5450        volatile uint32_t sequence_error_count;
    5551        volatile uint32_t overflow_error_count;
    56 
    57         volatile uint32_t rtp_sequence;
    5852        volatile uint8_t sequence[0x2000];
    5953};
    6054
     
    7064        }
    7165
    7266        vs->dbg = dbg;
    73         vs->sock = HDHOMERUN_SOCK_INVALID;
     67        vs->sock = -1;
    7468        pthread_mutex_init(&vs->lock, NULL);
    7569
    7670        /* Reset sequence tracking. */
     
    9286        }
    9387       
    9488        /* Create socket. */
    95         vs->sock = hdhomerun_sock_create_udp();
    96         if (vs->sock == HDHOMERUN_SOCK_INVALID) {
     89        vs->sock = (int)socket(AF_INET, SOCK_DGRAM, 0);
     90        if (vs->sock == -1) {
    9791                hdhomerun_debug_printf(dbg, "hdhomerun_video_create: failed to allocate socket\n");
    9892                goto error;
    9993        }
     
    10296        int rx_size = 1024 * 1024;
    10397        setsockopt(vs->sock, SOL_SOCKET, SO_RCVBUF, (char *)&rx_size, sizeof(rx_size));
    10498
     99        /* Set timeouts. */
     100        setsocktimeout(vs->sock, SOL_SOCKET, SO_SNDTIMEO, 1000);
     101        setsocktimeout(vs->sock, SOL_SOCKET, SO_RCVTIMEO, 1000);
     102
    105103        /* Bind socket. */
    106         if (!hdhomerun_sock_bind(vs->sock, INADDR_ANY, listen_port)) {
     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) {
    107110                hdhomerun_debug_printf(dbg, "hdhomerun_video_create: failed to bind socket (port %u)\n", listen_port);
    108111                goto error;
    109112        }
     
    118121        return vs;
    119122
    120123error:
    121         if (vs->sock != HDHOMERUN_SOCK_INVALID) {
    122                 hdhomerun_sock_destroy(vs->sock);
     124        if (vs->sock != -1) {
     125                close(vs->sock);
    123126        }
    124127        if (vs->buffer) {
    125128                free(vs->buffer);
     
    133136        vs->terminate = TRUE;
    134137        pthread_join(vs->thread, NULL);
    135138
    136         hdhomerun_sock_destroy(vs->sock);
     139        close(vs->sock);
    137140        free(vs->buffer);
    138141
    139142        free(vs);
     
    141144
    142145uint16_t hdhomerun_video_get_local_port(struct hdhomerun_video_sock_t *vs)
    143146{
    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());
     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);
    147151                return 0;
    148152        }
    149153
    150         return port;
     154        return ntohs(sock_addr.sin_port);
    151155}
    152156
    153 int hdhomerun_video_join_multicast_group(struct hdhomerun_video_sock_t *vs, uint32_t multicast_ip, uint32_t local_ip)
    154 {
    155         if (vs->multicast_ip != 0) {
    156                 hdhomerun_video_leave_multicast_group(vs);
    157         }
    158 
    159         struct ip_mreq imr;
    160         memset(&imr, 0, sizeof(imr));
    161         imr.imr_multiaddr.s_addr  = htonl(multicast_ip);
    162         imr.imr_interface.s_addr  = htonl(local_ip);
    163 
    164         if (setsockopt(vs->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char *)&imr, sizeof(imr)) != 0) {
    165                 hdhomerun_debug_printf(vs->dbg, "hdhomerun_video_join_multicast_group: setsockopt failed (%d)\n", hdhomerun_sock_getlasterror());
    166                 return -1;
    167         }
    168 
    169         vs->multicast_ip = multicast_ip;
    170         return 1;
    171 }
    172 
    173 int hdhomerun_video_leave_multicast_group(struct hdhomerun_video_sock_t *vs)
    174 {
    175         if (vs->multicast_ip == 0) {
    176                 return 1;
    177         }
    178 
    179         struct ip_mreq imr;
    180         memset(&imr, 0, sizeof(imr));
    181         imr.imr_multiaddr.s_addr  = htonl(vs->multicast_ip);
    182         imr.imr_interface.s_addr  = htonl(INADDR_ANY);
    183 
    184         if (setsockopt(vs->sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, (const char *)&imr, sizeof(imr)) != 0) {
    185                 hdhomerun_debug_printf(vs->dbg, "hdhomerun_video_leave_multicast_group: setsockopt failed (%d)\n", hdhomerun_sock_getlasterror());
    186         }
    187 
    188         vs->multicast_ip = 0;
    189         return 1;
    190 }
    191 
    192157static void hdhomerun_video_stats_ts_pkt(struct hdhomerun_video_sock_t *vs, uint8_t *ptr)
    193158{
    194159        uint16_t packet_identifier = ((uint16_t)(ptr[1] & 0x1F) << 8) | (uint16_t)ptr[2];
     
    203168                return;
    204169        }
    205170
    206         uint8_t sequence = ptr[3] & 0x0F;
    207 
     171        uint8_t continuity_counter = ptr[3] & 0x0F;
    208172        uint8_t previous_sequence = vs->sequence[packet_identifier];
    209         vs->sequence[packet_identifier] = sequence;
    210173
    211         if (previous_sequence == 0xFF) {
     174        if (continuity_counter == ((previous_sequence + 1) & 0x0F)) {
     175                vs->sequence[packet_identifier] = continuity_counter;
    212176                return;
    213177        }
    214         if (sequence == ((previous_sequence + 1) & 0x0F)) {
     178        if (previous_sequence == 0xFF) {
     179                vs->sequence[packet_identifier] = continuity_counter;
    215180                return;
    216181        }
    217         if (sequence == previous_sequence) {
     182        if (continuity_counter == previous_sequence) {
    218183                return;
    219184        }
    220185
    221186        vs->sequence_error_count++;
     187        vs->sequence[packet_identifier] = continuity_counter;
    222188}
    223189
    224190static void hdhomerun_video_parse_rtp(struct hdhomerun_video_sock_t *vs, struct hdhomerun_pkt_t *pkt)
     
    227193        uint32_t rtp_sequence = hdhomerun_pkt_read_u16(pkt);
    228194        pkt->pos += 8;
    229195
    230         uint32_t previous_rtp_sequence = vs->rtp_sequence;
    231         vs->rtp_sequence = rtp_sequence;
     196        if (rtp_sequence != ((vs->rtp_sequence + 1) & 0xFFFF)) {
     197                if (vs->rtp_sequence != 0xFFFFFFFF) {
     198                        vs->network_error_count++;
    232199
    233         /* Initial case - first packet received. */
    234         if (previous_rtp_sequence == 0xFFFFFFFF) {
    235                 return;
     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                }
    236206        }
    237207
    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         }
     208        vs->rtp_sequence = rtp_sequence;
    251209}
    252210
    253211static THREAD_FUNC_PREFIX hdhomerun_video_thread_execute(void *arg)
     
    260218                hdhomerun_pkt_reset(pkt);
    261219
    262220                /* Receive. */
    263                 size_t length = VIDEO_RTP_DATA_PACKET_SIZE;
    264                 if (!hdhomerun_sock_recv(vs->sock, pkt->end, &length, 25)) {
    265                         continue;
    266                 }
    267 
     221                int length = recv(vs->sock, (char *)pkt->end, VIDEO_RTP_DATA_PACKET_SIZE, 0);
    268222                pkt->end += length;
    269223
    270224                if (length == VIDEO_RTP_DATA_PACKET_SIZE) {
     
    273227                }
    274228
    275229                if (length != VIDEO_DATA_PACKET_SIZE) {
    276                         /* Data received but not valid - ignore. */
    277                         continue;
     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;
    278240                }
    279241
    280242                pthread_mutex_lock(&vs->lock);
     
    307269                        continue;
    308270                }
    309271
     272                /* Atomic update. */
    310273                vs->head = head;
    311274
    312275                pthread_mutex_unlock(&vs->lock);
     
    328291                        tail -= vs->buffer_size;
    329292                }
    330293       
     294                /* Atomic update. */
    331295                vs->tail = tail;
    332296        }
    333297
     
    370334        vs->tail = vs->head;
    371335        vs->advance = 0;
    372336
    373         vs->rtp_sequence = 0xFFFFFFFF;
     337        /* can't use memset bcs sequence is volatile */
    374338        int i;
    375         for (i = 0; i < 0x2000; i++) {
     339        for (i = 0; i < sizeof(vs->sequence) / sizeof(uint8_t) ; i++)
    376340                vs->sequence[i] = 0xFF;
    377         }
    378341
     342        vs->rtp_sequence = 0xFFFFFFFF;
     343
    379344        vs->packet_count = 0;
    380345        vs->transport_error_count = 0;
    381346        vs->network_error_count = 0;
     
    390355        struct hdhomerun_video_stats_t stats;
    391356        hdhomerun_video_get_stats(vs, &stats);
    392357
    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
     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
    397362        );
    398363}
    399364
  • mythtv/libs/libmythhdhomerun/hdhomerun_os_posix.h

     
    11/*
    22 * hdhomerun_os_posix.h
    33 *
    4  * Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>.
     4 * Copyright © 2006-2008 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)
    5557#define console_vprintf vprintf
    5658#define console_printf printf
    5759#define THREAD_FUNC_PREFIX void *
    5860
    59 #ifdef __cplusplus
    60 extern "C" {
    61 #endif
     61static 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}
    6267
    63 extern LIBTYPE uint64_t getcurrenttime(void);
    64 extern LIBTYPE void msleep_approx(uint64_t ms);
    65 extern LIBTYPE void msleep_minimum(uint64_t ms);
     68static inline int msleep(unsigned int ms)
     69{
     70        uint64_t stop_time = getcurrenttime() + ms;
    6671
    67 #ifdef __cplusplus
     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        }
    6887}
    69 #endif
     88
     89static 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}
  • mythtv/libs/libmythhdhomerun/hdhomerun_sock_windows.c

     
    1 /*
    2  * hdhomerun_sock_windows.c
    3  *
    4  * Copyright © 2010 Silicondust USA Inc. <www.silicondust.com>.
    5  *
    6  * This library is free software; you can redistribute it and/or
    7  * modify it under the terms of the GNU Lesser General Public
    8  * License as published by the Free Software Foundation; either
    9  * version 3 of the License, or (at your option) any later version.
    10  *
    11  * This library is distributed in the hope that it will be useful,
    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    14  * Lesser General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU Lesser General Public
    17  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
    18  *
    19  * As a special exception to the GNU Lesser General Public License,
    20  * you may link, statically or dynamically, an application with a
    21  * publicly distributed version of the Library to produce an
    22  * executable file containing portions of the Library, and
    23  * distribute that executable file under terms of your choice,
    24  * without any of the additional requirements listed in clause 4 of
    25  * the GNU Lesser General Public License.
    26  *
    27  * By "a publicly distributed version of the Library", we mean
    28  * either the unmodified Library as distributed by Silicondust, or a
    29  * modified version of the Library that is distributed under the
    30  * conditions defined in the GNU Lesser General Public License.
    31  */
    32 
    33 /*
    34  * Implementation notes:
    35  *
    36  * API specifies timeout for each operation (or zero for non-blocking).
    37  *
    38  * It is not possible to rely on the OS socket timeout as this will fail to
    39  * detect the command-response situation where data is sent successfully and
    40  * the other end chooses not to send a response (other than the TCP ack).
    41  *
    42  * Windows supports select() however native WSA events are used to:
    43  * - avoid problems with socket numbers above 1024.
    44  * - wait without allowing other events handlers to run (important for use
    45  *   with win7 WMC).
    46  */
    47 
    48 #include "hdhomerun.h"
    49 
    50 hdhomerun_sock_t hdhomerun_sock_create_udp(void)
    51 {
    52         /* Create socket. */
    53         hdhomerun_sock_t sock = (hdhomerun_sock_t)socket(AF_INET, SOCK_DGRAM, 0);
    54         if (sock == -1) {
    55                 return HDHOMERUN_SOCK_INVALID;
    56         }
    57 
    58         /* Set non-blocking */
    59         unsigned long mode = 1;
    60         if (ioctlsocket(sock, FIONBIO, &mode) != 0) {
    61                 closesocket(sock);
    62                 return HDHOMERUN_SOCK_INVALID;
    63         }
    64 
    65         /* Allow broadcast. */
    66         int sock_opt = 1;
    67         setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&sock_opt, sizeof(sock_opt));
    68 
    69         /* Success. */
    70         return sock;
    71 }
    72 
    73 hdhomerun_sock_t hdhomerun_sock_create_tcp(void)
    74 {
    75         /* Create socket. */
    76         hdhomerun_sock_t sock = (hdhomerun_sock_t)socket(AF_INET, SOCK_STREAM, 0);
    77         if (sock == -1) {
    78                 return HDHOMERUN_SOCK_INVALID;
    79         }
    80 
    81         /* Set non-blocking */
    82         unsigned long mode = 1;
    83         if (ioctlsocket(sock, FIONBIO, &mode) != 0) {
    84                 closesocket(sock);
    85                 return HDHOMERUN_SOCK_INVALID;
    86         }
    87 
    88         /* Success. */
    89         return sock;
    90 }
    91 
    92 void hdhomerun_sock_destroy(hdhomerun_sock_t sock)
    93 {
    94         closesocket(sock);
    95 }
    96 
    97 int hdhomerun_sock_getlasterror(void)
    98 {
    99         return WSAGetLastError();
    100 }
    101 
    102 uint32_t hdhomerun_sock_getsockname_addr(hdhomerun_sock_t sock)
    103 {
    104         struct sockaddr_in sock_addr;
    105         int sockaddr_size = sizeof(sock_addr);
    106 
    107         if (getsockname(sock, (struct sockaddr *)&sock_addr, &sockaddr_size) != 0) {
    108                 return 0;
    109         }
    110 
    111         return ntohl(sock_addr.sin_addr.s_addr);
    112 }
    113 
    114 uint16_t hdhomerun_sock_getsockname_port(hdhomerun_sock_t sock)
    115 {
    116         struct sockaddr_in sock_addr;
    117         int sockaddr_size = sizeof(sock_addr);
    118 
    119         if (getsockname(sock, (struct sockaddr *)&sock_addr, &sockaddr_size) != 0) {
    120                 return 0;
    121         }
    122 
    123         return ntohs(sock_addr.sin_port);
    124 }
    125 
    126 uint32_t hdhomerun_sock_getpeername_addr(hdhomerun_sock_t sock)
    127 {
    128         struct sockaddr_in sock_addr;
    129         int sockaddr_size = sizeof(sock_addr);
    130 
    131         if (getpeername(sock, (struct sockaddr *)&sock_addr, &sockaddr_size) != 0) {
    132                 return 0;
    133         }
    134 
    135         return ntohl(sock_addr.sin_addr.s_addr);
    136 }
    137 
    138 uint32_t hdhomerun_sock_getaddrinfo_addr(hdhomerun_sock_t sock, const char *name)
    139 {
    140         struct addrinfo hints;
    141         memset(&hints, 0, sizeof(hints));
    142         hints.ai_family = AF_INET;
    143         hints.ai_socktype = SOCK_STREAM;
    144         hints.ai_protocol = IPPROTO_TCP;
    145 
    146         struct addrinfo *sock_info;
    147         if (getaddrinfo(name, "", &hints, &sock_info) != 0) {
    148                 return 0;
    149         }
    150 
    151         struct sockaddr_in *sock_addr = (struct sockaddr_in *)sock_info->ai_addr;
    152         uint32_t addr = ntohl(sock_addr->sin_addr.s_addr);
    153 
    154         freeaddrinfo(sock_info);
    155         return addr;
    156 }
    157 
    158 bool_t hdhomerun_sock_bind(hdhomerun_sock_t sock, uint32_t local_addr, uint16_t local_port)
    159 {
    160         struct sockaddr_in sock_addr;
    161         memset(&sock_addr, 0, sizeof(sock_addr));
    162         sock_addr.sin_family = AF_INET;
    163         sock_addr.sin_addr.s_addr = htonl(local_addr);
    164         sock_addr.sin_port = htons(local_port);
    165 
    166         if (bind(sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) {
    167                 return FALSE;
    168         }
    169 
    170         return TRUE;
    171 }
    172 
    173 bool_t hdhomerun_sock_connect(hdhomerun_sock_t sock, uint32_t remote_addr, uint16_t remote_port, uint64_t timeout)
    174 {
    175         WSAEVENT wsa_event = WSACreateEvent();
    176         if (wsa_event == WSA_INVALID_EVENT) {
    177                 return FALSE;
    178         }
    179 
    180         if (WSAEventSelect(sock, wsa_event, FD_CONNECT) == SOCKET_ERROR) {
    181                 WSACloseEvent(wsa_event);
    182                 return FALSE;
    183         }
    184 
    185         /* Connect (non-blocking). */
    186         struct sockaddr_in sock_addr;
    187         memset(&sock_addr, 0, sizeof(sock_addr));
    188         sock_addr.sin_family = AF_INET;
    189         sock_addr.sin_addr.s_addr = htonl(remote_addr);
    190         sock_addr.sin_port = htons(remote_port);
    191 
    192         if (connect(sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) {
    193                 if (WSAGetLastError() != WSAEWOULDBLOCK) {
    194                         WSACloseEvent(wsa_event);
    195                         return FALSE;
    196                 }
    197         }
    198 
    199         /* Wait for connect to complete (both success and failure will signal). */
    200         DWORD ret = WaitForSingleObjectEx(wsa_event, (DWORD)timeout, FALSE);
    201         WSACloseEvent(wsa_event);
    202 
    203         if (ret != WAIT_OBJECT_0) {
    204                 return FALSE;
    205         }
    206 
    207         /* Detect success/failure. */
    208         int sockaddr_size = sizeof(sock_addr);
    209         if (getpeername(sock, (struct sockaddr *)&sock_addr, &sockaddr_size) != 0) {
    210                 return FALSE;
    211         }
    212 
    213         return TRUE;
    214 }
    215 
    216 static bool_t hdhomerun_sock_wait_for_event(hdhomerun_sock_t sock, long event_type, uint64_t stop_time)
    217 {
    218         uint64_t current_time = getcurrenttime();
    219         if (current_time >= stop_time) {
    220                 return FALSE;
    221         }
    222 
    223         WSAEVENT wsa_event = WSACreateEvent();
    224         if (wsa_event == WSA_INVALID_EVENT) {
    225                 return FALSE;
    226         }
    227 
    228         if (WSAEventSelect(sock, wsa_event, event_type) == SOCKET_ERROR) {
    229                 WSACloseEvent(wsa_event);
    230                 return FALSE;
    231         }
    232 
    233         DWORD ret = WaitForSingleObjectEx(wsa_event, (DWORD)(stop_time - current_time), FALSE);
    234         WSACloseEvent(wsa_event);
    235 
    236         if (ret != WAIT_OBJECT_0) {
    237                 return FALSE;
    238         }
    239 
    240         return TRUE;
    241 }
    242 
    243 bool_t hdhomerun_sock_send(hdhomerun_sock_t sock, const void *data, size_t length, uint64_t timeout)
    244 {
    245         uint64_t stop_time = getcurrenttime() + timeout;
    246         const uint8_t *ptr = (uint8_t *)data;
    247 
    248         while (1) {
    249                 int ret = send(sock, (char *)ptr, (int)length, 0);
    250                 if (ret >= (int)length) {
    251                         return TRUE;
    252                 }
    253 
    254                 if (ret > 0) {
    255                         ptr += ret;
    256                         length -= ret;
    257                 }
    258 
    259                 if (WSAGetLastError() != WSAEWOULDBLOCK) {
    260                         return FALSE;
    261                 }
    262 
    263                 if (!hdhomerun_sock_wait_for_event(sock, FD_WRITE | FD_CLOSE, stop_time)) {
    264                         return FALSE;
    265                 }
    266         }
    267 }
    268 
    269 bool_t hdhomerun_sock_sendto(hdhomerun_sock_t sock, uint32_t remote_addr, uint16_t remote_port, const void *data, size_t length, uint64_t timeout)
    270 {
    271         uint64_t stop_time = getcurrenttime() + timeout;
    272         const uint8_t *ptr = (uint8_t *)data;
    273 
    274         while (1) {
    275                 struct sockaddr_in sock_addr;
    276                 memset(&sock_addr, 0, sizeof(sock_addr));
    277                 sock_addr.sin_family = AF_INET;
    278                 sock_addr.sin_addr.s_addr = htonl(remote_addr);
    279                 sock_addr.sin_port = htons(remote_port);
    280 
    281                 int ret = sendto(sock, (char *)ptr, (int)length, 0, (struct sockaddr *)&sock_addr, sizeof(sock_addr));
    282                 if (ret >= (int)length) {
    283                         return TRUE;
    284                 }
    285 
    286                 if (ret > 0) {
    287                         ptr += ret;
    288                         length -= ret;
    289                 }
    290 
    291                 if (WSAGetLastError() != WSAEWOULDBLOCK) {
    292                         return FALSE;
    293                 }
    294 
    295                 if (!hdhomerun_sock_wait_for_event(sock, FD_WRITE | FD_CLOSE, stop_time)) {
    296                         return FALSE;
    297                 }
    298         }
    299 }
    300 
    301 bool_t hdhomerun_sock_recv(hdhomerun_sock_t sock, void *data, size_t *length, uint64_t timeout)
    302 {
    303         uint64_t stop_time = getcurrenttime() + timeout;
    304 
    305         while (1) {
    306                 int ret = recv(sock, (char *)data, (int)(*length), 0);
    307                 if (ret > 0) {
    308                         *length = ret;
    309                         return TRUE;
    310                 }
    311 
    312                 if (WSAGetLastError() != WSAEWOULDBLOCK) {
    313                         return FALSE;
    314                 }
    315 
    316                 if (!hdhomerun_sock_wait_for_event(sock, FD_READ | FD_CLOSE, stop_time)) {
    317                         return FALSE;
    318                 }
    319         }
    320 }
    321 
    322 bool_t hdhomerun_sock_recvfrom(hdhomerun_sock_t sock, uint32_t *remote_addr, uint16_t *remote_port, void *data, size_t *length, uint64_t timeout)
    323 {
    324         uint64_t stop_time = getcurrenttime() + timeout;
    325 
    326         while (1) {
    327                 struct sockaddr_in sock_addr;
    328                 memset(&sock_addr, 0, sizeof(sock_addr));
    329                 int sockaddr_size = sizeof(sock_addr);
    330 
    331                 int ret = recvfrom(sock, (char *)data, (int)(*length), 0, (struct sockaddr *)&sock_addr, &sockaddr_size);
    332                 if (ret > 0) {
    333                         *remote_addr = ntohl(sock_addr.sin_addr.s_addr);
    334                         *remote_port = ntohs(sock_addr.sin_port);
    335                         *length = ret;
    336                         return TRUE;
    337                 }
    338 
    339                 if (WSAGetLastError() != WSAEWOULDBLOCK) {
    340                         return FALSE;
    341                 }
    342 
    343                 if (!hdhomerun_sock_wait_for_event(sock, FD_READ | FD_CLOSE, stop_time)) {
    344                         return FALSE;
    345                 }
    346         }
    347 }
  • mythtv/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  */
    76 extern LIBTYPE int hdhomerun_video_join_multicast_group(struct hdhomerun_video_sock_t *vs, uint32_t multicast_ip, uint32_t local_ip);
    77 extern LIBTYPE int hdhomerun_video_leave_multicast_group(struct hdhomerun_video_sock_t *vs);
    78 
    79 /*
    8074 * Read data from buffer.
    8175 *
    8276 * size_t max_size: The maximum amount of data to be returned.
  • mythtv/libs/libmythhdhomerun/hdhomerun_channelscan.c

     
    11/*
    22 * hdhomerun_channelscan.c
    33 *
    4  * Copyright © 2007-2010 Silicondust USA Inc. <www.silicondust.com>.
     4 * Copyright © 2007-2008 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_approx(250);
     102                msleep(250);
    103103        }
    104104}
    105105
     
    303303                        break;
    304304                }
    305305
    306                 msleep_approx(250);
     306                msleep(250);
    307307        }
    308308
    309309        /* Lock => skip overlapping channels. */
  • mythtv/libs/libmythhdhomerun/hdhomerun_discover.c

     
    11/*
    22 * hdhomerun_discover.c
    33 *
    4  * Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>.
     4 * Copyright © 2006-2007 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
    4754#define HDHOMERUN_DISOCVER_MAX_SOCK_COUNT 16
    4855
    4956struct hdhomerun_discover_sock_t {
    50         hdhomerun_sock_t sock;
    51         bool_t detected;
     57        int sock;
    5258        uint32_t local_ip;
    5359        uint32_t subnet_mask;
    5460};
     
    6066        struct hdhomerun_pkt_t rx_pkt;
    6167};
    6268
    63 static bool_t hdhomerun_discover_sock_add(struct hdhomerun_discover_t *ds, uint32_t local_ip, uint32_t subnet_mask)
     69static bool_t hdhomerun_discover_sock_create(struct hdhomerun_discover_t *ds, uint32_t local_ip, uint32_t subnet_mask)
    6470{
    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 
    7571        if (ds->sock_count >= HDHOMERUN_DISOCVER_MAX_SOCK_COUNT) {
    7672                return FALSE;
    7773        }
    7874
    7975        /* Create socket. */
    80         hdhomerun_sock_t sock = hdhomerun_sock_create_udp();
    81         if (sock == HDHOMERUN_SOCK_INVALID) {
     76        int sock = (int)socket(AF_INET, SOCK_DGRAM, 0);
     77        if (sock == -1) {
    8278                return FALSE;
    8379        }
    8480
     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
    8589        /* Bind socket. */
    86         if (!hdhomerun_sock_bind(sock, local_ip, 0)) {
    87                 hdhomerun_sock_destroy(sock);
     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);
    8897                return FALSE;
    8998        }
    9099
    91100        /* Write sock entry. */
    92101        struct hdhomerun_discover_sock_t *dss = &ds->socks[ds->sock_count++];
    93102        dss->sock = sock;
    94         dss->detected = TRUE;
    95103        dss->local_ip = local_ip;
    96104        dss->subnet_mask = subnet_mask;
    97105
    98106        return TRUE;
    99107}
    100108
    101 struct hdhomerun_discover_t *hdhomerun_discover_create(void)
    102 {
    103         struct hdhomerun_discover_t *ds = (struct hdhomerun_discover_t *)calloc(1, sizeof(struct hdhomerun_discover_t));
    104         if (!ds) {
    105                 return NULL;
    106         }
    107 
    108         /* Create a routable socket (always first entry). */
    109         if (!hdhomerun_discover_sock_add(ds, 0, 0)) {
    110                 free(ds);
    111                 return NULL;
    112         }
    113 
    114         /* Success. */
    115         return ds;
    116 }
    117 
    118 void hdhomerun_discover_destroy(struct hdhomerun_discover_t *ds)
    119 {
    120         unsigned int i;
    121         for (i = 0; i < ds->sock_count; i++) {
    122                 struct hdhomerun_discover_sock_t *dss = &ds->socks[i];
    123                 hdhomerun_sock_destroy(dss->sock);
    124         }
    125 
    126         free(ds);
    127 }
    128 
    129109#if defined(USE_IPHLPAPI)
    130 static void hdhomerun_discover_sock_detect_internal(struct hdhomerun_discover_t *ds)
     110static void hdhomerun_discover_sock_detect(struct hdhomerun_discover_t *ds)
    131111{
    132112        PIP_ADAPTER_INFO pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO));
    133113        ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
     
    158138                                continue;
    159139                        }
    160140
    161                         hdhomerun_discover_sock_add(ds, local_ip, mask);
     141                        hdhomerun_discover_sock_create(ds, local_ip, mask);
    162142                        pIPAddr = pIPAddr->Next;
    163143                }
    164144
     
    170150
    171151#else
    172152
    173 static void hdhomerun_discover_sock_detect_internal(struct hdhomerun_discover_t *ds)
     153static void hdhomerun_discover_sock_detect(struct hdhomerun_discover_t *ds)
    174154{
    175         int sock = ds->socks[0].sock;
     155        int fd = socket(AF_INET, SOCK_DGRAM, 0);
     156        if (fd == -1) {
     157                return;
     158        }
    176159
    177160        struct ifconf ifc;
    178161        uint8_t buf[8192];
     
    181164
    182165        memset(buf, 0, sizeof(buf));
    183166
    184         if (ioctl(sock, SIOCGIFCONF, &ifc) != 0) {
     167        if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) {
     168                close(fd);
    185169                return;
    186170        }
    187171
     
    192176                struct ifreq *ifr = (struct ifreq *)ptr;
    193177                ptr += _SIZEOF_ADDR_IFREQ(*ifr);
    194178
    195                 if (ioctl(sock, SIOCGIFADDR, ifr) != 0) {
     179                if (ioctl(fd, SIOCGIFADDR, ifr) != 0) {
    196180                        continue;
    197181                }
    198182                struct sockaddr_in *addr_in = (struct sockaddr_in *)&(ifr->ifr_addr);
     
    201185                        continue;
    202186                }
    203187
    204                 if (ioctl(sock, SIOCGIFNETMASK, ifr) != 0) {
     188                if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) {
    205189                        continue;
    206190                }
    207191                struct sockaddr_in *mask_in = (struct sockaddr_in *)&(ifr->ifr_addr);
    208192                uint32_t mask = ntohl(mask_in->sin_addr.s_addr);
    209193
    210                 hdhomerun_discover_sock_add(ds, local_ip, mask);
     194                hdhomerun_discover_sock_create(ds, local_ip, mask);
    211195        }
     196
     197        close(fd);
    212198}
    213199#endif
    214200
    215 static void hdhomerun_discover_sock_detect(struct hdhomerun_discover_t *ds)
     201static struct hdhomerun_discover_t *hdhomerun_discover_create(void)
    216202{
    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;
     203        struct hdhomerun_discover_t *ds = (struct hdhomerun_discover_t *)calloc(1, sizeof(struct hdhomerun_discover_t));
     204        if (!ds) {
     205                return NULL;
    221206        }
    222207
    223         hdhomerun_discover_sock_detect_internal(ds);
     208        /* Create a routable socket. */
     209        if (!hdhomerun_discover_sock_create(ds, 0, 0)) {
     210                free(ds);
     211                return NULL;
     212        }
    224213
    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++;
     214        /* Detect & create local sockets. */
     215        hdhomerun_discover_sock_detect(ds);
     216
     217        /* Success. */
     218        return ds;
     219}
     220
     221static 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);
    240227        }
    241228
    242         ds->sock_count = count;
     229        free(ds);
    243230}
    244231
    245232static 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)
     
    255242        hdhomerun_pkt_write_u32(tx_pkt, device_id);
    256243        hdhomerun_pkt_seal_frame(tx_pkt, HDHOMERUN_TYPE_DISCOVER_REQ);
    257244
    258         return hdhomerun_sock_sendto(dss->sock, target_ip, HDHOMERUN_DISCOVER_UDP_PORT, tx_pkt->start, tx_pkt->end - tx_pkt->start, 0);
     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;
    259257}
    260258
    261259static bool_t hdhomerun_discover_send_wildcard_ip(struct hdhomerun_discover_t *ds, uint32_t device_type, uint32_t device_id)
     
    315313
    316314static bool_t hdhomerun_discover_send(struct hdhomerun_discover_t *ds, uint32_t target_ip, uint32_t device_type, uint32_t device_id)
    317315{
    318         if (target_ip == 0) {
    319                 return hdhomerun_discover_send_wildcard_ip(ds, device_type, device_id);
    320         } else {
     316        if (target_ip != 0) {
    321317                return hdhomerun_discover_send_target_ip(ds, target_ip, device_type, device_id);
    322318        }
     319
     320        return hdhomerun_discover_send_wildcard_ip(ds, device_type, device_id);
    323321}
    324322
    325 static bool_t hdhomerun_discover_recv_internal(struct hdhomerun_discover_t *ds, struct hdhomerun_discover_sock_t *dss, struct hdhomerun_discover_device_t *result)
     323static int hdhomerun_discover_recv_internal(struct hdhomerun_discover_t *ds, struct hdhomerun_discover_sock_t *dss, struct hdhomerun_discover_device_t *result)
    326324{
    327325        struct hdhomerun_pkt_t *rx_pkt = &ds->rx_pkt;
    328326        hdhomerun_pkt_reset(rx_pkt);
    329327
    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;
     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;
    335336        }
     337        rx_pkt->end += rx_length;
    336338
    337         rx_pkt->end += length;
    338 
    339339        uint16_t type;
    340340        if (hdhomerun_pkt_open_frame(rx_pkt, &type) <= 0) {
    341                 return FALSE;
     341                return 0;
    342342        }
    343343        if (type != HDHOMERUN_TYPE_DISCOVER_RPY) {
    344                 return FALSE;
     344                return 0;
    345345        }
    346346
    347         result->ip_addr = remote_addr;
     347        result->ip_addr = ntohl(sock_addr.sin_addr.s_addr);
    348348        result->device_type = 0;
    349349        result->device_id = 0;
    350350
     
    378378                rx_pkt->pos = next;
    379379        }
    380380
    381         return TRUE;
     381        return 1;
    382382}
    383383
    384 static bool_t hdhomerun_discover_recv(struct hdhomerun_discover_t *ds, struct hdhomerun_discover_device_t *result)
     384static int 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
    386394        unsigned int i;
    387395        for (i = 0; i < ds->sock_count; i++) {
    388396                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        }
    389402
    390                 if (hdhomerun_discover_recv_internal(ds, dss, result)) {
    391                         return TRUE;
     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;
    392411                }
     412
     413                if (hdhomerun_discover_recv_internal(ds, dss, result) <= 0) {
     414                        continue;
     415                }
     416
     417                return 1;
    393418        }
    394419
    395         return FALSE;
     420        return 0;
    396421}
    397422
    398 static struct hdhomerun_discover_device_t *hdhomerun_discover_find_in_list(struct hdhomerun_discover_device_t result_list[], int count, struct hdhomerun_discover_device_t *lookup)
     423static struct hdhomerun_discover_device_t *hdhomerun_discover_find_in_list(struct hdhomerun_discover_device_t result_list[], int count, uint32_t ip_addr)
    399424{
    400425        int index;
    401426        for (index = 0; index < count; index++) {
    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;
     427                struct hdhomerun_discover_device_t *result = &result_list[index];
     428                if (result->ip_addr == ip_addr) {
     429                        return result;
    405430                }
    406431        }
    407432
    408433        return NULL;
    409434}
    410435
    411 int hdhomerun_discover_find_devices(struct hdhomerun_discover_t *ds, uint32_t target_ip, uint32_t device_type, uint32_t device_id, struct hdhomerun_discover_device_t result_list[], int max_count)
     436static 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)
    412437{
    413         hdhomerun_discover_sock_detect(ds);
    414 
    415438        int count = 0;
    416439        int attempt;
    417440        for (attempt = 0; attempt < 2; attempt++) {
     
    420443                }
    421444
    422445                uint64_t timeout = getcurrenttime() + 200;
    423                 while (1) {
     446                while (getcurrenttime() < timeout) {
    424447                        struct hdhomerun_discover_device_t *result = &result_list[count];
    425448
    426                         if (!hdhomerun_discover_recv(ds, result)) {
    427                                 if (getcurrenttime() >= timeout) {
    428                                         break;
    429                                 }
    430                                 msleep_approx(10);
     449                        int ret = hdhomerun_discover_recv(ds, result);
     450                        if (ret < 0) {
     451                                return -1;
     452                        }
     453                        if (ret == 0) {
    431454                                continue;
    432455                        }
    433456
     
    444467                        }
    445468
    446469                        /* Ensure not already in list. */
    447                         if (hdhomerun_discover_find_in_list(result_list, count, result)) {
     470                        if (hdhomerun_discover_find_in_list(result_list, count, result->ip_addr)) {
    448471                                continue;
    449472                        }
    450473
     
    461484
    462485int 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)
    463486{
    464         if (hdhomerun_discover_is_ip_multicast(target_ip)) {
    465                 return 0;
    466         }
    467 
    468487        struct hdhomerun_discover_t *ds = hdhomerun_discover_create();
    469488        if (!ds) {
    470489                return -1;
    471490        }
    472491
    473         int ret = hdhomerun_discover_find_devices(ds, target_ip, device_type, device_id, result_list, max_count);
     492        int ret = hdhomerun_discover_find_devices_internal(ds, target_ip, device_type, device_id, result_list, max_count);
    474493
    475494        hdhomerun_discover_destroy(ds);
    476495        return ret;
     
    494513        return (checksum == 0);
    495514}
    496515
    497 bool_t hdhomerun_discover_is_ip_multicast(uint32_t ip_addr)
    498 {
    499         return (ip_addr >= 0xE0000000) && (ip_addr < 0xF0000000);
    500 }
  • mythtv/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 typically 400ms if max_count is not reached.
     47 * Execution time is 1 second.
    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.
    5250 *
    5351 * Returns the number of devices found.
    5452 * Retruns -1 on error.
     
    5654extern 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);
    5755
    5856/*
    59  * Optional: persistent discover instance available for discover polling use.
    60  */
    61 extern LIBTYPE struct hdhomerun_discover_t *hdhomerun_discover_create(void);
    62 extern LIBTYPE void hdhomerun_discover_destroy(struct hdhomerun_discover_t *ds);
    63 extern LIBTYPE int hdhomerun_discover_find_devices(struct hdhomerun_discover_t *ds, uint32_t target_ip, uint32_t device_type, uint32_t device_id, struct hdhomerun_discover_device_t result_list[], int max_count);
    64 
    65 /*
    6657 * Verify that the device ID given is valid.
    6758 *
    6859 * The device ID contains a self-check sequence that detects common user input errors including
     
    7364 */
    7465extern LIBTYPE bool_t hdhomerun_discover_validate_device_id(uint32_t device_id);
    7566
    76 /*
    77  * Detect if an IP address is multicast.
    78  *
    79  * Returns TRUE if multicast.
    80  * Returns FALSE if zero, unicast, expermental, or broadcast.
    81  */
    82 extern LIBTYPE bool_t hdhomerun_discover_is_ip_multicast(uint32_t ip_addr);
    83 
    8467#ifdef __cplusplus
    8568}
    8669#endif
  • mythtv/libs/libmythhdhomerun/Makefile.bin

     
    1 
     1LIBSRCS += hdhomerun_pkt.c
     2LIBSRCS += hdhomerun_debug.c
     3LIBSRCS += hdhomerun_discover.c
    24LIBSRCS += hdhomerun_channels.c
    35LIBSRCS += hdhomerun_channelscan.c
    46LIBSRCS += hdhomerun_control.c
    5 LIBSRCS += hdhomerun_debug.c
     7LIBSRCS += hdhomerun_video.c
    68LIBSRCS += hdhomerun_device.c
    79LIBSRCS += hdhomerun_device_selector.c
    8 LIBSRCS += hdhomerun_discover.c
    9 LIBSRCS += hdhomerun_os_posix.c
    10 LIBSRCS += hdhomerun_pkt.c
    11 LIBSRCS += hdhomerun_sock_posix.c
    12 LIBSRCS += hdhomerun_video.c
    1310
    1411CC    := $(CROSS_COMPILE)gcc
    1512STRIP := $(CROSS_COMPILE)strip
     
    2320  LIBEXT := .dll
    2421  LDFLAGS += -liphlpapi
    2522else
    26   OS := $(shell uname -s)
    2723  LIBEXT := .so
    28   ifeq ($(OS),Linux)
    29     LDFLAGS += -lrt
    30   endif
    31   ifeq ($(OS),SunOS)
     24  ifneq ($(findstring solaris,$(shell echo $$OSTYPE)),)
    3225    LDFLAGS += -lns -lsocket
    3326  endif
    34   ifeq ($(OS),Darwin)
     27  ifneq ($(findstring darwin,$(shell echo $$OSTYPE)),)
    3528    CFLAGS += -arch i386 -arch ppc
    3629    LIBEXT := .dylib
    3730    SHARED := -dynamiclib -install_name libhdhomerun$(LIBEXT)
  • mythtv/libs/libmythhdhomerun/hdhomerun_os_windows.c

     
    1 /*
    2  * hdhomerun_os_windows.c
    3  *
    4  * Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>.
    5  *
    6  * This library is free software; you can redistribute it and/or
    7  * modify it under the terms of the GNU Lesser General Public
    8  * License as published by the Free Software Foundation; either
    9  * version 3 of the License, or (at your option) any later version.
    10  *
    11  * This library is distributed in the hope that it will be useful,
    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    14  * Lesser General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU Lesser General Public
    17  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
    18  *
    19  * As a special exception to the GNU Lesser General Public License,
    20  * you may link, statically or dynamically, an application with a
    21  * publicly distributed version of the Library to produce an
    22  * executable file containing portions of the Library, and
    23  * distribute that executable file under terms of your choice,
    24  * without any of the additional requirements listed in clause 4 of
    25  * the GNU Lesser General Public License.
    26  *
    27  * By "a publicly distributed version of the Library", we mean
    28  * either the unmodified Library as distributed by Silicondust, or a
    29  * modified version of the Library that is distributed under the
    30  * conditions defined in the GNU Lesser General Public License.
    31  */
    32 
    33 #include "hdhomerun_os.h"
    34 
    35 uint64_t getcurrenttime(void)
    36 {
    37         static pthread_mutex_t lock = INVALID_HANDLE_VALUE;
    38         static uint64_t result = 0;
    39         static uint32_t previous_time = 0;
    40 
    41         /* Initialization is not thread safe. */
    42         if (lock == INVALID_HANDLE_VALUE) {
    43                 pthread_mutex_init(&lock, NULL);
    44         }
    45 
    46         pthread_mutex_lock(&lock);
    47 
    48         uint32_t current_time = GetTickCount();
    49 
    50         if (current_time > previous_time) {
    51                 result += current_time - previous_time;
    52         }
    53 
    54         previous_time = current_time;
    55 
    56         pthread_mutex_unlock(&lock);
    57         return result;
    58 }
    59 
    60 void msleep_approx(uint64_t ms)
    61 {
    62         Sleep((DWORD)ms);
    63 }
    64 
    65 void msleep_minimum(uint64_t ms)
    66 {
    67         uint64_t stop_time = getcurrenttime() + ms;
    68 
    69         while (1) {
    70                 uint64_t current_time = getcurrenttime();
    71                 if (current_time >= stop_time) {
    72                         return;
    73                 }
    74 
    75                 msleep_approx(stop_time - current_time);
    76         }
    77 }
    78 
    79 #if !defined(PTHREAD_H)
    80 int pthread_create(pthread_t *tid, void *attr, LPTHREAD_START_ROUTINE start, void *arg)
    81 {
    82         *tid = CreateThread(NULL, 0, start, arg, 0, NULL);
    83         if (!*tid) {
    84                 return (int)GetLastError();
    85         }
    86         return 0;
    87 }
    88 
    89 int pthread_join(pthread_t tid, void **value_ptr)
    90 {
    91         while (1) {
    92                 DWORD ExitCode = 0;
    93                 if (!GetExitCodeThread(tid, &ExitCode)) {
    94                         return (int)GetLastError();
    95                 }
    96                 if (ExitCode != STILL_ACTIVE) {
    97                         return 0;
    98                 }
    99         }
    100 }
    101 
    102 void pthread_mutex_init(pthread_mutex_t *mutex, void *attr)
    103 {
    104         *mutex = CreateMutex(NULL, FALSE, NULL);
    105 }
    106 
    107 void pthread_mutex_lock(pthread_mutex_t *mutex)
    108 {
    109         WaitForSingleObject(*mutex, INFINITE);
    110 }
    111 
    112 void pthread_mutex_unlock(pthread_mutex_t *mutex)
    113 {
    114         ReleaseMutex(*mutex);
    115 }
    116 #endif
    117 
    118 /*
    119  * The console output format should be set to UTF-8, however in XP and Vista this breaks batch file processing.
    120  * Attempting to restore on exit fails to restore if the program is terminated by the user.
    121  * Solution - set the output format each printf.
    122  */
    123 void console_vprintf(const char *fmt, va_list ap)
    124 {
    125         UINT cp = GetConsoleOutputCP();
    126         SetConsoleOutputCP(CP_UTF8);
    127         vprintf(fmt, ap);
    128         SetConsoleOutputCP(cp);
    129 }
    130 
    131 void console_printf(const char *fmt, ...)
    132 {
    133         va_list ap;
    134         va_start(ap, fmt);
    135         console_vprintf(fmt, ap);
    136         va_end(ap);
    137 }
  • mythtv/libs/libmythhdhomerun/hdhomerun_device_selector.c

     
    11/*
    22 * hdhomerun_device_selector.c
    33 *
    4  * Copyright © 2009-2010 Silicondust USA Inc. <www.silicondust.com>.
     4 * Copyright © 2009 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
    71 LIBTYPE int hdhomerun_device_selector_get_device_count(struct hdhomerun_device_selector_t *hds)
    72 {
    73         return (int)hds->hd_count;
    74 }
    75 
    7671void hdhomerun_device_selector_add_device(struct hdhomerun_device_selector_t *hds, struct hdhomerun_device_t *hd)
    7772{
    7873        size_t index;
     
    134129        return NULL;
    135130}
    136131
    137 int hdhomerun_device_selector_load_from_file(struct hdhomerun_device_selector_t *hds, char *filename)
     132void hdhomerun_device_selector_load_from_file(struct hdhomerun_device_selector_t *hds, char *filename)
    138133{
    139134        FILE *fp = fopen(filename, "r");
    140135        if (!fp) {
    141                 return 0;
     136                return;
    142137        }
    143138
    144139        while(1) {
     
    156151        }
    157152
    158153        fclose(fp);
    159         return (int)hds->hd_count;
    160154}
    161155
    162156#if defined(__WINDOWS__)
    163 int hdhomerun_device_selector_load_from_windows_registry(struct hdhomerun_device_selector_t *hds, wchar_t *wsource)
     157void hdhomerun_device_selector_load_from_windows_registry(struct hdhomerun_device_selector_t *hds, wchar_t *wsource)
    164158{
    165159        HKEY tuners_key;
    166160        LONG ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Silicondust\\HDHomeRun\\Tuners", 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &tuners_key);
    167161        if (ret != ERROR_SUCCESS) {
    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;
     162                hdhomerun_debug_printf(hds->dbg, "hdhomerun_device_selector_load_from_windows_registry: failed to open tuners registry key (%ld)\n", ret);
     163                return;
    170164        }
    171165
    172166        DWORD index = 0;
     
    183177                HKEY device_key;
    184178                ret = RegOpenKeyEx(tuners_key, wdevice_name, 0, KEY_QUERY_VALUE, &device_key);
    185179                if (ret != ERROR_SUCCESS) {
    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);
     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);
    187181                        continue;
    188182                }
    189183
     
    213207        }
    214208
    215209        RegCloseKey(tuners_key);
    216         return (int)hds->hd_count;
    217210}
    218211#endif
    219212
     
    275268        /*
    276269         * Test local port.
    277270         */
    278         hdhomerun_sock_t test_sock = hdhomerun_sock_create_udp();
    279         if (test_sock == HDHOMERUN_SOCK_INVALID) {
     271        int test_sock = (int)socket(AF_INET, SOCK_DGRAM, 0);
     272        if (test_sock == -1) {
    280273                hdhomerun_debug_printf(hds->dbg, "hdhomerun_device_selector_choose_test: device %s in use, failed to create test sock\n", name);
    281274                return FALSE;
    282275        }
    283276
    284         bool_t inuse = (hdhomerun_sock_bind(test_sock, INADDR_ANY, (uint16_t)target_port) == FALSE);
    285         hdhomerun_sock_destroy(test_sock);
     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);
    286284
    287         if (inuse) {
     285        if (ret != 0) {
    288286                hdhomerun_debug_printf(hds->dbg, "hdhomerun_device_selector_choose_test: device %s in use by local machine\n", name);
    289287                return FALSE;
    290288        }
  • mythtv/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;
    4240        uint32_t device_id;
    4341        unsigned int tuner;
    4442        uint32_t lockkey;
     
    4644        char model[32];
    4745};
    4846
    49 static int hdhomerun_device_set_device_normal(struct hdhomerun_device_t *hd, uint32_t device_id, uint32_t device_ip)
     47static void hdhomerun_device_set_update(struct hdhomerun_device_t *hd)
    5048{
    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         }
     49        /* Clear cached information. */
     50        *hd->model = 0;
    5851
     52        /* New name. */
     53        sprintf(hd->name, "%08lX-%u", (unsigned long)hd->device_id, hd->tuner);
     54}
     55
     56void hdhomerun_device_set_device(struct hdhomerun_device_t *hd, uint32_t device_id, uint32_t device_ip)
     57{
    5958        hdhomerun_control_set_device(hd->cs, device_id, device_ip);
    6059
    6160        if ((device_id == 0) || (device_id == HDHOMERUN_DEVICE_ID_WILDCARD)) {
    6261                device_id = hdhomerun_control_get_device_id(hd->cs);
    6362        }
    6463
    65         hd->multicast_ip = 0;
    66         hd->multicast_port = 0;
    6764        hd->device_id = device_id;
    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;
     65        hdhomerun_device_set_update(hd);
    7566}
    7667
    77 static int hdhomerun_device_set_device_multicast(struct hdhomerun_device_t *hd, uint32_t multicast_ip)
     68void hdhomerun_device_set_tuner(struct hdhomerun_device_t *hd, unsigned int tuner)
    7869{
    79         if (hd->cs) {
    80                 hdhomerun_control_destroy(hd->cs);
    81                 hd->cs = NULL;
    82         }
    83 
    84         hd->multicast_ip = multicast_ip;
    85         hd->multicast_port = 0;
    86         hd->device_id = 0;
    87         hd->tuner = 0;
    88         hd->lockkey = 0;
    89 
    90         unsigned long ip = multicast_ip;
    91         sprintf(hd->name, "%lu.%lu.%lu.%lu", (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, (ip >> 0) & 0xFF);
    92         sprintf(hd->model, "multicast");
    93 
    94         return 1;
    95 }
    96 
    97 int hdhomerun_device_set_device(struct hdhomerun_device_t *hd, uint32_t device_id, uint32_t device_ip)
    98 {
    99         if ((device_id == 0) && (device_ip == 0)) {
    100                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_device: device not specified\n");
    101                 return -1;
    102         }
    103 
    104         if (hdhomerun_discover_is_ip_multicast(device_ip)) {
    105                 return hdhomerun_device_set_device_multicast(hd, device_ip);
    106         }
    107 
    108         return hdhomerun_device_set_device_normal(hd, device_id, device_ip);
    109 }
    110 
    111 int hdhomerun_device_set_tuner(struct hdhomerun_device_t *hd, unsigned int tuner)
    112 {
    113         if (hd->multicast_ip != 0) {
    114                 if (tuner != 0) {
    115                         hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner: tuner cannot be specified in multicast mode\n");
    116                         return -1;
    117                 }
    118 
    119                 return 1;
    120         }
    121 
    12270        hd->tuner = tuner;
    123         sprintf(hd->name, "%08lX-%u", (unsigned long)hd->device_id, hd->tuner);
    124 
    125         return 1;
     71        hdhomerun_device_set_update(hd);
    12672}
    12773
    12874struct hdhomerun_device_t *hdhomerun_device_create(uint32_t device_id, uint32_t device_ip, unsigned int tuner, struct hdhomerun_debug_t *dbg)
    12975{
    13076        struct hdhomerun_device_t *hd = (struct hdhomerun_device_t *)calloc(1, sizeof(struct hdhomerun_device_t));
    13177        if (!hd) {
    132                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_create: failed to allocate device object\n");
     78                hdhomerun_debug_printf(dbg, "hdhomerun_device_create: failed to allocate device object\n");
    13379                return NULL;
    13480        }
    13581
    13682        hd->dbg = dbg;
    13783
    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) {
     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");
    14387                free(hd);
    14488                return NULL;
    14589        }
    146         if (hdhomerun_device_set_tuner(hd, tuner) <= 0) {
    147                 free(hd);
    148                 return NULL;
    149         }
    15090
     91        hdhomerun_device_set_device(hd, device_id, device_ip);
     92        hdhomerun_device_set_tuner(hd, tuner);
     93
    15194        return hd;
    15295}
    15396
     
    161104                hdhomerun_video_destroy(hd->vs);
    162105        }
    163106
    164         if (hd->cs) {
    165                 hdhomerun_control_destroy(hd->cs);
    166         }
     107        hdhomerun_control_destroy(hd->cs);
    167108
    168109        free(hd);
    169110}
     
    215156static struct hdhomerun_device_t *hdhomerun_device_create_from_str_ip(const char *device_str, struct hdhomerun_debug_t *dbg)
    216157{
    217158        unsigned long a[4];
    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) {
     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;
    220163                if (sscanf(device_str, "%lu.%lu.%lu.%lu", &a[0], &a[1], &a[2], &a[3]) != 4) {
    221164                        return NULL;
    222165                }
    223166        }
    224167
    225168        unsigned long device_ip = (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | (a[3] << 0);
    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;
     169        return hdhomerun_device_create(HDHOMERUN_DEVICE_ID_WILDCARD, (uint32_t)device_ip, tuner, dbg);
    236170}
    237171
    238172static struct hdhomerun_device_t *hdhomerun_device_create_from_str_dns(const char *device_str, struct hdhomerun_debug_t *dbg)
     
    305239
    306240uint32_t hdhomerun_device_get_device_id(struct hdhomerun_device_t *hd)
    307241{
    308         return hd->device_id;
     242        return hdhomerun_control_get_device_id(hd->cs);
    309243}
    310244
    311245uint32_t hdhomerun_device_get_device_ip(struct hdhomerun_device_t *hd)
    312246{
    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;
     247        return hdhomerun_control_get_device_ip(hd->cs);
    321248}
    322249
    323250uint32_t hdhomerun_device_get_device_id_requested(struct hdhomerun_device_t *hd)
    324251{
    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;
     252        return hdhomerun_control_get_device_id_requested(hd->cs);
    333253}
    334254
    335255uint32_t hdhomerun_device_get_device_ip_requested(struct hdhomerun_device_t *hd)
    336256{
    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;
     257        return hdhomerun_control_get_device_ip_requested(hd->cs);
    345258}
    346259
    347260unsigned int hdhomerun_device_get_tuner(struct hdhomerun_device_t *hd)
     
    360273                return hd->vs;
    361274        }
    362275
    363         hd->vs = hdhomerun_video_create(hd->multicast_port, VIDEO_DATA_BUFFER_SIZE_1S * 2, hd->dbg);
     276        hd->vs = hdhomerun_video_create(0, VIDEO_DATA_BUFFER_SIZE_1S * 2, hd->dbg);
    364277        if (!hd->vs) {
    365278                hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_video_sock: failed to create video object\n");
    366279                return NULL;
     
    371284
    372285uint32_t hdhomerun_device_get_local_machine_addr(struct hdhomerun_device_t *hd)
    373286{
    374         if (hd->cs) {
    375                 return hdhomerun_control_get_local_addr(hd->cs);
    376         }
    377 
    378         return 0;
     287        return hdhomerun_control_get_local_addr(hd->cs);
    379288}
    380289
    381290static uint32_t hdhomerun_device_get_status_parse(const char *status_str, const char *tag)
     
    459368
    460369int hdhomerun_device_get_tuner_status(struct hdhomerun_device_t *hd, char **pstatus_str, struct hdhomerun_tuner_status_t *status)
    461370{
    462         if (!hd->cs) {
    463                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_status: device not set\n");
    464                 return -1;
    465         }
    466 
    467371        memset(status, 0, sizeof(struct hdhomerun_tuner_status_t));
    468372
    469373        char name[32];
     
    510414
    511415int hdhomerun_device_get_tuner_streaminfo(struct hdhomerun_device_t *hd, char **pstreaminfo)
    512416{
    513         if (!hd->cs) {
    514                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_streaminfo: device not set\n");
    515                 return -1;
    516         }
    517 
    518417        char name[32];
    519418        sprintf(name, "/tuner%u/streaminfo", hd->tuner);
    520419        return hdhomerun_control_get(hd->cs, name, pstreaminfo, NULL);
     
    522421
    523422int hdhomerun_device_get_tuner_channel(struct hdhomerun_device_t *hd, char **pchannel)
    524423{
    525         if (!hd->cs) {
    526                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_channel: device not set\n");
    527                 return -1;
    528         }
    529 
    530424        char name[32];
    531425        sprintf(name, "/tuner%u/channel", hd->tuner);
    532426        return hdhomerun_control_get(hd->cs, name, pchannel, NULL);
     
    534428
    535429int hdhomerun_device_get_tuner_channelmap(struct hdhomerun_device_t *hd, char **pchannelmap)
    536430{
    537         if (!hd->cs) {
    538                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_channelmap: device not set\n");
    539                 return -1;
    540         }
    541 
    542431        char name[32];
    543432        sprintf(name, "/tuner%u/channelmap", hd->tuner);
    544433        return hdhomerun_control_get(hd->cs, name, pchannelmap, NULL);
     
    546435
    547436int hdhomerun_device_get_tuner_filter(struct hdhomerun_device_t *hd, char **pfilter)
    548437{
    549         if (!hd->cs) {
    550                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_filter: device not set\n");
    551                 return -1;
    552         }
    553 
    554438        char name[32];
    555439        sprintf(name, "/tuner%u/filter", hd->tuner);
    556440        return hdhomerun_control_get(hd->cs, name, pfilter, NULL);
     
    558442
    559443int hdhomerun_device_get_tuner_program(struct hdhomerun_device_t *hd, char **pprogram)
    560444{
    561         if (!hd->cs) {
    562                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_program: device not set\n");
    563                 return -1;
    564         }
    565 
    566445        char name[32];
    567446        sprintf(name, "/tuner%u/program", hd->tuner);
    568447        return hdhomerun_control_get(hd->cs, name, pprogram, NULL);
     
    570449
    571450int hdhomerun_device_get_tuner_target(struct hdhomerun_device_t *hd, char **ptarget)
    572451{
    573         if (!hd->cs) {
    574                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_target: device not set\n");
    575                 return -1;
    576         }
    577 
    578452        char name[32];
    579453        sprintf(name, "/tuner%u/target", hd->tuner);
    580454        return hdhomerun_control_get(hd->cs, name, ptarget, NULL);
     
    582456
    583457int hdhomerun_device_get_tuner_plotsample(struct hdhomerun_device_t *hd, struct hdhomerun_plotsample_t **psamples, size_t *pcount)
    584458{
    585         if (!hd->cs) {
    586                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_tuner_plotsample: device not set\n");
    587                 return -1;
    588         }
    589 
    590459        char name[32];
    591460        sprintf(name, "/tuner%u/plotsample", hd->tuner);
    592461
     
    636505
    637506int hdhomerun_device_get_tuner_lockkey_owner(struct hdhomerun_device_t *hd, char **powner)
    638507{
    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 
    644508        char name[32];
    645509        sprintf(name, "/tuner%u/lockkey", hd->tuner);
    646510        return hdhomerun_control_get(hd->cs, name, powner, NULL);
     
    648512
    649513int hdhomerun_device_get_ir_target(struct hdhomerun_device_t *hd, char **ptarget)
    650514{
    651         if (!hd->cs) {
    652                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_ir_target: device not set\n");
    653                 return -1;
    654         }
    655 
    656515        return hdhomerun_control_get(hd->cs, "/ir/target", ptarget, NULL);
    657516}
    658517
    659518int hdhomerun_device_get_lineup_location(struct hdhomerun_device_t *hd, char **plocation)
    660519{
    661         if (!hd->cs) {
    662                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_lineup_location: device not set\n");
    663                 return -1;
    664         }
    665 
    666520        return hdhomerun_control_get(hd->cs, "/lineup/location", plocation, NULL);
    667521}
    668522
    669523int hdhomerun_device_get_version(struct hdhomerun_device_t *hd, char **pversion_str, uint32_t *pversion_num)
    670524{
    671         if (!hd->cs) {
    672                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_version: device not set\n");
    673                 return -1;
    674         }
    675 
    676525        char *version_str;
    677526        int ret = hdhomerun_control_get(hd->cs, "/sys/version", &version_str, NULL);
    678527        if (ret <= 0) {
     
    697546
    698547int hdhomerun_device_set_tuner_channel(struct hdhomerun_device_t *hd, const char *channel)
    699548{
    700         if (!hd->cs) {
    701                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_channel: device not set\n");
    702                 return -1;
    703         }
    704 
    705549        char name[32];
    706550        sprintf(name, "/tuner%u/channel", hd->tuner);
    707551        return hdhomerun_control_set_with_lockkey(hd->cs, name, channel, hd->lockkey, NULL, NULL);
     
    709553
    710554int hdhomerun_device_set_tuner_channelmap(struct hdhomerun_device_t *hd, const char *channelmap)
    711555{
    712         if (!hd->cs) {
    713                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_channelmap: device not set\n");
    714                 return -1;
    715         }
    716 
    717556        char name[32];
    718557        sprintf(name, "/tuner%u/channelmap", hd->tuner);
    719558        return hdhomerun_control_set_with_lockkey(hd->cs, name, channelmap, hd->lockkey, NULL, NULL);
     
    721560
    722561int hdhomerun_device_set_tuner_filter(struct hdhomerun_device_t *hd, const char *filter)
    723562{
    724         if (!hd->cs) {
    725                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_filter: device not set\n");
    726                 return -1;
    727         }
    728 
    729563        char name[32];
    730564        sprintf(name, "/tuner%u/filter", hd->tuner);
    731565        return hdhomerun_control_set_with_lockkey(hd->cs, name, filter, hd->lockkey, NULL, NULL);
     
    801635
    802636int hdhomerun_device_set_tuner_program(struct hdhomerun_device_t *hd, const char *program)
    803637{
    804         if (!hd->cs) {
    805                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_program: device not set\n");
    806                 return -1;
    807         }
    808 
    809638        char name[32];
    810639        sprintf(name, "/tuner%u/program", hd->tuner);
    811640        return hdhomerun_control_set_with_lockkey(hd->cs, name, program, hd->lockkey, NULL, NULL);
     
    813642
    814643int hdhomerun_device_set_tuner_target(struct hdhomerun_device_t *hd, const char *target)
    815644{
    816         if (!hd->cs) {
    817                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_target: device not set\n");
    818                 return -1;
    819         }
    820 
    821645        char name[32];
    822646        sprintf(name, "/tuner%u/target", hd->tuner);
    823647        return hdhomerun_control_set_with_lockkey(hd->cs, name, target, hd->lockkey, NULL, NULL);
    824648}
    825649
    826 static int hdhomerun_device_set_tuner_target_to_local(struct hdhomerun_device_t *hd, const char *protocol)
     650int hdhomerun_device_set_tuner_target_to_local_protocol(struct hdhomerun_device_t *hd, const char *protocol)
    827651{
    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         }
     652        /* Create video socket. */
     653        hdhomerun_device_get_video_sock(hd);
    832654        if (!hd->vs) {
    833                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_tuner_target_to_local: video not initialized\n");
    834655                return -1;
    835656        }
    836657
     
    848669        return hdhomerun_device_set_tuner_target(hd, target);
    849670}
    850671
    851 int hdhomerun_device_set_ir_target(struct hdhomerun_device_t *hd, const char *target)
     672int hdhomerun_device_set_tuner_target_to_local(struct hdhomerun_device_t *hd)
    852673{
    853         if (!hd->cs) {
    854                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_ir_target: device not set\n");
    855                 return -1;
    856         }
     674        return hdhomerun_device_set_tuner_target_to_local_protocol(hd, HDHOMERUN_TARGET_PROTOCOL_UDP);
     675}
    857676
     677int hdhomerun_device_set_ir_target(struct hdhomerun_device_t *hd, const char *target)
     678{
    858679        return hdhomerun_control_set(hd->cs, "/ir/target", target, NULL, NULL);
    859680}
    860681
    861682int hdhomerun_device_set_lineup_location(struct hdhomerun_device_t *hd, const char *location)
    862683{
    863         if (!hd->cs) {
    864                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_lineup_location: device not set\n");
    865                 return -1;
    866         }
    867 
    868684        return hdhomerun_control_set(hd->cs, "/lineup/location", location, NULL, NULL);
    869685}
    870686
    871 int hdhomerun_device_set_sys_dvbc_modulation(struct hdhomerun_device_t *hd, const char *modulation_list)
    872 {
    873         if (!hd->cs) {
    874                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_sys_dvbc_modulation: device not set\n");
    875                 return -1;
    876         }
    877 
    878         return hdhomerun_control_set(hd->cs, "/sys/dvbc_modulation", modulation_list, NULL, NULL);
    879 }
    880 
    881687int hdhomerun_device_get_var(struct hdhomerun_device_t *hd, const char *name, char **pvalue, char **perror)
    882688{
    883         if (!hd->cs) {
    884                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_var: device not set\n");
    885                 return -1;
    886         }
    887 
    888689        return hdhomerun_control_get(hd->cs, name, pvalue, perror);
    889690}
    890691
    891692int hdhomerun_device_set_var(struct hdhomerun_device_t *hd, const char *name, const char *value, char **pvalue, char **perror)
    892693{
    893         if (!hd->cs) {
    894                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_set_var: device not set\n");
    895                 return -1;
    896         }
    897 
    898694        return hdhomerun_control_set_with_lockkey(hd->cs, name, value, hd->lockkey, pvalue, perror);
    899695}
    900696
    901697int hdhomerun_device_tuner_lockkey_request(struct hdhomerun_device_t *hd, char **perror)
    902698{
    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 
    911699        uint32_t new_lockkey = (uint32_t)getcurrenttime();
    912700
    913701        char name[32];
     
    928716
    929717int hdhomerun_device_tuner_lockkey_release(struct hdhomerun_device_t *hd)
    930718{
    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 
    939719        if (hd->lockkey == 0) {
    940720                return 1;
    941721        }
     
    950730
    951731int hdhomerun_device_tuner_lockkey_force(struct hdhomerun_device_t *hd)
    952732{
    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 
    961733        char name[32];
    962734        sprintf(name, "/tuner%u/lockkey", hd->tuner);
    963735        int ret = hdhomerun_control_set(hd->cs, name, "force", NULL, NULL);
     
    968740
    969741void hdhomerun_device_tuner_lockkey_use_value(struct hdhomerun_device_t *hd, uint32_t lockkey)
    970742{
    971         if (hd->multicast_ip != 0) {
    972                 return;
    973         }
    974 
    975743        hd->lockkey = lockkey;
    976744}
    977745
    978746int hdhomerun_device_wait_for_lock(struct hdhomerun_device_t *hd, struct hdhomerun_tuner_status_t *status)
    979747{
    980748        /* Delay for SS reading to be valid (signal present). */
    981         msleep_minimum(250);
     749        msleep(250);
    982750
    983751        /* Wait for up to 2.5 seconds for lock. */
    984752        uint64_t timeout = getcurrenttime() + 2500;
     
    1000768                        return 1;
    1001769                }
    1002770
    1003                 msleep_approx(250);
     771                msleep(250);
    1004772        }
    1005773}
    1006774
    1007775int hdhomerun_device_stream_start(struct hdhomerun_device_t *hd)
    1008776{
    1009         hdhomerun_device_get_video_sock(hd);
    1010         if (!hd->vs) {
    1011                 return -1;
    1012         }
    1013 
    1014777        /* Set target. */
    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                 }
     778        int ret = hdhomerun_device_stream_refresh_target(hd);
     779        if (ret <= 0) {
     780                return ret;
    1028781        }
    1029782
    1030783        /* Flush video buffer. */
    1031         msleep_minimum(64);
     784        msleep(64);
    1032785        hdhomerun_video_flush(hd->vs);
    1033786
    1034787        /* Success. */
    1035788        return 1;
    1036789}
    1037790
     791int 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
    1038800uint8_t *hdhomerun_device_stream_recv(struct hdhomerun_device_t *hd, size_t max_size, size_t *pactual_size)
    1039801{
    1040802        if (!hd->vs) {
    1041                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_stream_recv: video not initialized\n");
    1042803                return NULL;
    1043804        }
    1044 
    1045805        return hdhomerun_video_recv(hd->vs, max_size, pactual_size);
    1046806}
    1047807
    1048808void hdhomerun_device_stream_flush(struct hdhomerun_device_t *hd)
    1049809{
    1050         if (!hd->vs) {
    1051                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_stream_flush: video not initialized\n");
    1052                 return;
    1053         }
    1054 
    1055810        hdhomerun_video_flush(hd->vs);
    1056811}
    1057812
    1058813void hdhomerun_device_stream_stop(struct hdhomerun_device_t *hd)
    1059814{
    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         }
     815        hdhomerun_device_set_tuner_target(hd, "none");
    1070816}
    1071817
    1072818int hdhomerun_device_channelscan_init(struct hdhomerun_device_t *hd, const char *channelmap)
     
    1077823
    1078824        hd->scan = channelscan_create(hd, channelmap);
    1079825        if (!hd->scan) {
    1080                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_channelscan_init: failed to create scan object\n");
    1081826                return -1;
    1082827        }
    1083828
     
    1087832int hdhomerun_device_channelscan_advance(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result)
    1088833{
    1089834        if (!hd->scan) {
    1090                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_channelscan_advance: scan not initialized\n");
    1091835                return 0;
    1092836        }
    1093837
     
    1103847int hdhomerun_device_channelscan_detect(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result)
    1104848{
    1105849        if (!hd->scan) {
    1106                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_channelscan_detect: scan not initialized\n");
    1107850                return 0;
    1108851        }
    1109852
     
    1119862uint8_t hdhomerun_device_channelscan_get_progress(struct hdhomerun_device_t *hd)
    1120863{
    1121864        if (!hd->scan) {
    1122                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_channelscan_get_progress: scan not initialized\n");
    1123865                return 0;
    1124866        }
    1125867
    1126868        return channelscan_get_progress(hd->scan);
    1127869}
    1128870
     871int 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
    1129885const char *hdhomerun_device_get_model_str(struct hdhomerun_device_t *hd)
    1130886{
    1131887        if (*hd->model) {
    1132888                return hd->model;
    1133889        }
    1134890
    1135         if (!hd->cs) {
    1136                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_model_str: device not set\n");
    1137                 return NULL;
    1138         }
    1139 
    1140891        char *model_str;
    1141892        int ret = hdhomerun_control_get(hd->cs, "/sys/model", &model_str, NULL);
    1142893        if (ret < 0) {
    1143894                return NULL;
    1144895        }
    1145896        if (ret == 0) {
    1146                 model_str = "hdhomerun_atsc";
     897                strncpy(hd->model, "hdhomerun_atsc", sizeof(hd->model) - 1);
     898                hd->model[sizeof(hd->model) - 1] = 0;
    1147899        }
     900        else
     901        {
     902                strncpy(hd->model, model_str, sizeof(hd->model) - 1);
     903                hd->model[sizeof(hd->model) - 1] = 0;
     904        }
    1148905
    1149         strncpy(hd->model, model_str, sizeof(hd->model) - 1);
    1150         hd->model[sizeof(hd->model) - 1] = 0;
    1151 
    1152906        return hd->model;
    1153907}
    1154908
    1155909int hdhomerun_device_upgrade(struct hdhomerun_device_t *hd, FILE *upgrade_file)
    1156910{
    1157         if (!hd->cs) {
    1158                 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_upgrade: device not set\n");
    1159                 return -1;
    1160         }
    1161 
    1162911        hdhomerun_control_set(hd->cs, "/tuner0/lockkey", "force", NULL, NULL);
    1163912        hdhomerun_control_set(hd->cs, "/tuner0/channel", "none", NULL, NULL);
    1164913
     
    1174923                return;
    1175924        }
    1176925
    1177         if (hd->cs) {
    1178                 char name[32];
    1179                 sprintf(name, "/tuner%u/debug", hd->tuner);
     926        char name[32];
     927        sprintf(name, "/tuner%u/debug", hd->tuner);
    1180928
    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                 }
     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        }
    1188936
    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                 }
     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);
    1194941        }
    1195942
    1196943        if (hd->vs) {
     
    1200947
    1201948void hdhomerun_device_get_video_stats(struct hdhomerun_device_t *hd, struct hdhomerun_video_stats_t *stats)
    1202949{
    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 
    1209950        hdhomerun_video_get_stats(hd->vs, stats);
    1210951}
  • mythtv/libs/libmythhdhomerun/hdhomerun_os_windows.h

     
    11/*
    22 * hdhomerun_os_windows.h
    33 *
    4  * Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>.
     4 * Copyright © 2006-2008 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 #if defined(USING_MINGW)
    35 /* MinGW lacks wspiapi.h; set minimum WINVER to WinXP to remove dependency */
     34// MinGW lacks wspiapi, so remove dependency by setting minimum WINVER to WinXP
    3635#define WINVER 0x0501
    37 #endif
    3836#include <windows.h>
    3937#include <winsock2.h>
    4038#include <ws2tcpip.h>
    41 #if !defined(USING_MINGW)
    42 #include <wspiapi.h>
    43 #endif
     39//#include <wspiapi.h>
    4440#include <stdlib.h>
    4541#include <stdio.h>
    4642#include <stdarg.h>
     
    5955#endif
    6056
    6157typedef int bool_t;
    62 #if defined(USING_MINGW)
    63 #include <stdint.h>
    64 #include <pthread.h>
    65 #else
     58/* Use MinGW includes instead
    6659typedef signed __int8 int8_t;
    6760typedef signed __int16 int16_t;
    6861typedef signed __int32 int32_t;
     
    7366typedef unsigned __int64 uint64_t;
    7467typedef HANDLE pthread_t;
    7568typedef HANDLE pthread_mutex_t;
    76 #endif
     69*/
     70#include <stdint.h>
     71#include <pthread.h>
    7772
    78 #define va_copy(x, y) x = y
     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
    7980#define atoll _atoi64
    8081#define strdup _strdup
    8182#define strcasecmp _stricmp
     
    8485#define ftello _ftelli64
    8586#define THREAD_FUNC_PREFIX DWORD WINAPI
    8687#define SIGPIPE SIGABRT
    87 
    88 #ifdef __cplusplus
    89 extern "C" {
    9088#endif
    9189
    92 extern LIBTYPE uint64_t getcurrenttime(void);
    93 extern LIBTYPE void msleep_approx(uint64_t ms);
    94 extern LIBTYPE void msleep_minimum(uint64_t ms);
     90static inline uint64_t getcurrenttime(void)
     91{
     92        struct timeb tb;
     93        ftime(&tb);
     94        return ((uint64_t)tb.time * 1000) + tb.millitm;
     95}
    9596
    96 #if !defined(PTHREAD_H)
    97 extern LIBTYPE int pthread_create(pthread_t *tid, void *attr, LPTHREAD_START_ROUTINE start, void *arg);
    98 extern LIBTYPE int pthread_join(pthread_t tid, void **value_ptr);
    99 extern LIBTYPE void pthread_mutex_init(pthread_mutex_t *mutex, void *attr);
    100 extern LIBTYPE void pthread_mutex_lock(pthread_mutex_t *mutex);
    101 extern LIBTYPE void pthread_mutex_unlock(pthread_mutex_t *mutex);
    102 #endif
     97static inline int msleep(unsigned int ms)
     98{
     99        uint64_t stop_time = getcurrenttime() + ms;
    103100
     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
     120static 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
     127static 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
     136static 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
     149static inline void pthread_mutex_init(pthread_mutex_t *mutex, void *attr)
     150{
     151        *mutex = CreateMutex(NULL, FALSE, NULL);
     152}
     153
     154static inline void pthread_mutex_lock(pthread_mutex_t *mutex)
     155{
     156        WaitForSingleObject(*mutex, INFINITE);
     157}
     158
     159static inline void pthread_mutex_unlock(pthread_mutex_t *mutex)
     160{
     161        ReleaseMutex(*mutex);
     162}
     163*/
     164
    104165/*
    105166 * The console output format should be set to UTF-8, however in XP and Vista this breaks batch file processing.
    106167 * Attempting to restore on exit fails to restore if the program is terminated by the user.
    107168 * Solution - set the output format each printf.
    108169 */
    109 extern LIBTYPE void console_vprintf(const char *fmt, va_list ap);
    110 extern LIBTYPE void console_printf(const char *fmt, ...);
     170static 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}
    111177
    112 #ifdef __cplusplus
     178static 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);
    113184}
    114 #endif
  • mythtv/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  */
    48 extern LIBTYPE int hdhomerun_device_selector_get_device_count(struct hdhomerun_device_selector_t *hds);
    49 
    50 /*
    5146 * Populate device selector with devices from given source.
    52  * Returns the number of devices populated.
    5347 */
    54 extern LIBTYPE int hdhomerun_device_selector_load_from_file(struct hdhomerun_device_selector_t *hds, char *filename);
     48extern LIBTYPE void hdhomerun_device_selector_load_from_file(struct hdhomerun_device_selector_t *hds, char *filename);
    5549#if defined(__WINDOWS__)
    56 extern LIBTYPE int hdhomerun_device_selector_load_from_windows_registry(struct hdhomerun_device_selector_t *hds, wchar_t *wsource);
     50extern LIBTYPE void hdhomerun_device_selector_load_from_windows_registry(struct hdhomerun_device_selector_t *hds, wchar_t *wsource);
    5751#endif
    5852
    5953/*
  • mythtv/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 int hdhomerun_device_set_device(struct hdhomerun_device_t *hd, uint32_t device_id, uint32_t device_ip);
    94 extern LIBTYPE int hdhomerun_device_set_tuner(struct hdhomerun_device_t *hd, unsigned int tuner);
     93extern LIBTYPE void hdhomerun_device_set_device(struct hdhomerun_device_t *hd, uint32_t device_id, uint32_t device_ip);
     94extern LIBTYPE void 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);
     151extern LIBTYPE int hdhomerun_device_set_tuner_target_to_local_protocol(struct hdhomerun_device_t *hd, const char *protocol);
     152extern LIBTYPE int hdhomerun_device_set_tuner_target_to_local(struct hdhomerun_device_t *hd);
    151153extern LIBTYPE int hdhomerun_device_set_ir_target(struct hdhomerun_device_t *hd, const char *target);
    152154extern LIBTYPE int hdhomerun_device_set_lineup_location(struct hdhomerun_device_t *hd, const char *location);
    153 extern LIBTYPE int hdhomerun_device_set_sys_dvbc_modulation(struct hdhomerun_device_t *hd, const char *modulation_list);
    154155
    155156/*
    156157 * Get/set a named control variable on the device.
     
    223224 * The hdhomerun_device_stream_stop function tells the device to stop streaming data.
    224225 */
    225226extern LIBTYPE int hdhomerun_device_stream_start(struct hdhomerun_device_t *hd);
     227extern LIBTYPE int hdhomerun_device_stream_refresh_target(struct hdhomerun_device_t *hd);
    226228extern LIBTYPE uint8_t *hdhomerun_device_stream_recv(struct hdhomerun_device_t *hd, size_t max_size, size_t *pactual_size);
    227229extern LIBTYPE void hdhomerun_device_stream_flush(struct hdhomerun_device_t *hd);
    228230extern LIBTYPE void hdhomerun_device_stream_stop(struct hdhomerun_device_t *hd);
     
    236238extern LIBTYPE uint8_t hdhomerun_device_channelscan_get_progress(struct hdhomerun_device_t *hd);
    237239
    238240/*
     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 */
     249extern LIBTYPE int hdhomerun_device_firmware_version_check(struct hdhomerun_device_t *hd, uint32_t features);
     250
     251/*
    239252 * Upload new firmware to the device.
    240253 *
    241254 * FILE *upgrade_file: File pointer to read from. The file must have been opened in binary mode for reading.
  • mythtv/libs/libmythhdhomerun/hdhomerun_control.c

     
    11/*
    22 * hdhomerun_control.c
    33 *
    4  * Copyright © 2006-2010 Silicondust USA Inc. <www.silicondust.com>.
     4 * Copyright © 2006 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_CONNECT_TIMEOUT 2500
    36 #define HDHOMERUN_CONTROL_SEND_TIMEOUT 2500
    37 #define HDHOMERUN_CONTROL_RECV_TIMEOUT 2500
     35#define HDHOMERUN_CONTROL_SEND_TIMEOUT 5000
     36#define HDHOMERUN_CONTROL_RECV_TIMEOUT 5000
    3837#define HDHOMERUN_CONTROL_UPGRADE_TIMEOUT 20000
    3938
    4039struct hdhomerun_control_sock_t {
     
    5049
    5150static void hdhomerun_control_close_sock(struct hdhomerun_control_sock_t *cs)
    5251{
    53         if (cs->sock == HDHOMERUN_SOCK_INVALID) {
     52        if (cs->sock == -1) {
    5453                return;
    5554        }
    5655
    57         hdhomerun_sock_destroy(cs->sock);
    58         cs->sock = HDHOMERUN_SOCK_INVALID;
     56        close(cs->sock);
     57        cs->sock = -1;
    5958}
    6059
    6160void hdhomerun_control_set_device(struct hdhomerun_control_sock_t *cs, uint32_t device_id, uint32_t device_ip)
     
    7776        }
    7877
    7978        cs->dbg = dbg;
    80         cs->sock = HDHOMERUN_SOCK_INVALID;
     79        cs->sock = -1;
    8180        hdhomerun_control_set_device(cs, device_id, device_ip);
    8281
    8382        return cs;
     
    9190
    9291static bool_t hdhomerun_control_connect_sock(struct hdhomerun_control_sock_t *cs)
    9392{
    94         if (cs->sock != HDHOMERUN_SOCK_INVALID) {
     93        if (cs->sock != -1) {
    9594                return TRUE;
    9695        }
    9796
     
    9998                hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_connect_sock: no device specified\n");
    10099                return FALSE;
    101100        }
    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         }
    106101
    107102        /* Find device. */
    108103        struct hdhomerun_discover_device_t result;
     
    114109        cs->actual_device_id = result.device_id;
    115110
    116111        /* Create socket. */
    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());
     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);
    120115                return FALSE;
    121116        }
    122117
     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
    123122        /* Initiate connection. */
    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());
     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);
    126130                hdhomerun_control_close_sock(cs);
    127131                return FALSE;
    128132        }
     
    168172                return 0;
    169173        }
    170174
    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());
     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);
    174179                return 0;
    175180        }
    176181
    177         return addr;
     182        return ntohl(sock_addr.sin_addr.s_addr);
    178183}
    179184
    180 static bool_t hdhomerun_control_send_sock(struct hdhomerun_control_sock_t *cs, struct hdhomerun_pkt_t *tx_pkt)
     185static int hdhomerun_control_send_sock(struct hdhomerun_control_sock_t *cs, struct hdhomerun_pkt_t *tx_pkt)
    181186{
    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());
     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);
    184190                hdhomerun_control_close_sock(cs);
    185                 return FALSE;
     191                return -1;
    186192        }
    187193
    188         return TRUE;
     194        return 1;
    189195}
    190196
    191 static bool_t hdhomerun_control_recv_sock(struct hdhomerun_control_sock_t *cs, struct hdhomerun_pkt_t *rx_pkt, uint16_t *ptype, uint64_t recv_timeout)
     197static int hdhomerun_control_recv_sock(struct hdhomerun_control_sock_t *cs, struct hdhomerun_pkt_t *rx_pkt, uint16_t *ptype, uint64_t recv_timeout)
    192198{
    193199        uint64_t stop_time = getcurrenttime() + recv_timeout;
    194200        hdhomerun_pkt_reset(rx_pkt);
    195201
    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");
     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);
    200213                        hdhomerun_control_close_sock(cs);
    201                         return FALSE;
     214                        return -1;
    202215                }
    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());
     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);
    207224                        hdhomerun_control_close_sock(cs);
    208                         return FALSE;
     225                        return -1;
    209226                }
     227                rx_pkt->end += rx_length;
    210228
    211                 rx_pkt->end += length;
    212 
    213229                int ret = hdhomerun_pkt_open_frame(rx_pkt, ptype);
    214230                if (ret < 0) {
    215231                        hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_recv_sock: frame error\n");
    216232                        hdhomerun_control_close_sock(cs);
    217                         return FALSE;
     233                        return -1;
    218234                }
    219                 if (ret > 0) {
    220                         return TRUE;
     235                if (ret == 0) {
     236                        continue;
    221237                }
     238
     239                return 1;
    222240        }
     241
     242        hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_recv_sock: timeout\n");
     243        hdhomerun_control_close_sock(cs);
     244        return -1;
    223245}
    224246
    225247static 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)
     
    228250
    229251        int i;
    230252        for (i = 0; i < 2; i++) {
    231                 if (cs->sock == HDHOMERUN_SOCK_INVALID) {
     253                if (cs->sock == -1) {
    232254                        if (!hdhomerun_control_connect_sock(cs)) {
    233255                                hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_send_recv: connect failed\n");
    234256                                return -1;
    235257                        }
    236258                }
    237259
    238                 if (!hdhomerun_control_send_sock(cs, tx_pkt)) {
     260                if (hdhomerun_control_send_sock(cs, tx_pkt) < 0) {
    239261                        continue;
    240262                }
    241263                if (!rx_pkt) {
     
    243265                }
    244266
    245267                uint16_t rsp_type;
    246                 if (!hdhomerun_control_recv_sock(cs, rx_pkt, &rsp_type, recv_timeout)) {
     268                if (hdhomerun_control_recv_sock(cs, rx_pkt, &rsp_type, recv_timeout) < 0) {
    247269                        continue;
    248270                }
    249271                if (rsp_type != type + 1) {
     
    279301        }
    280302        hdhomerun_pkt_write_u8(tx_pkt, HDHOMERUN_TAG_GETSET_NAME);
    281303        hdhomerun_pkt_write_var_length(tx_pkt, name_len);
    282         hdhomerun_pkt_write_mem(tx_pkt, (void *)name, name_len);
     304        hdhomerun_pkt_write_mem(tx_pkt, (const void *)name, name_len);
    283305
    284306        if (value) {
    285307                int value_len = (int)strlen(value) + 1;
     
    289311                }
    290312                hdhomerun_pkt_write_u8(tx_pkt, HDHOMERUN_TAG_GETSET_VALUE);
    291313                hdhomerun_pkt_write_var_length(tx_pkt, value_len);
    292                 hdhomerun_pkt_write_mem(tx_pkt, (void *)value, value_len);
     314                hdhomerun_pkt_write_mem(tx_pkt, (const void *)value, value_len);
    293315        }
    294316
    295317        if (lockkey != 0) {
  • mythtv/libs/libmythhdhomerun/hdhomerun_sock_posix.c

     
    1 /*
    2  * hdhomerun_sock_posix.c
    3  *
    4  * Copyright © 2010 Silicondust USA Inc. <www.silicondust.com>.
    5  *
    6  * This library is free software; you can redistribute it and/or
    7  * modify it under the terms of the GNU Lesser General Public
    8  * License as published by the Free Software Foundation; either
    9  * version 3 of the License, or (at your option) any later version.
    10  *
    11  * This library is distributed in the hope that it will be useful,
    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    14  * Lesser General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU Lesser General Public
    17  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
    18  *
    19  * As a special exception to the GNU Lesser General Public License,
    20  * you may link, statically or dynamically, an application with a
    21  * publicly distributed version of the Library to produce an
    22  * executable file containing portions of the Library, and
    23  * distribute that executable file under terms of your choice,
    24  * without any of the additional requirements listed in clause 4 of
    25  * the GNU Lesser General Public License.
    26  *
    27  * By "a publicly distributed version of the Library", we mean
    28  * either the unmodified Library as distributed by Silicondust, or a
    29  * modified version of the Library that is distributed under the
    30  * conditions defined in the GNU Lesser General Public License.
    31  */
    32 
    33 /*
    34  * Implementation notes:
    35  *
    36  * API specifies timeout for each operation (or zero for non-blocking).
    37  *
    38  * It is not possible to rely on the OS socket timeout as this will fail to
    39  * detect the command-response situation where data is sent successfully and
    40  * the other end chooses not to send a response (other than the TCP ack).
    41  *
    42  * The select() cannot be used with high socket numbers (typically max 1024)
    43  * so the code works as follows:
    44  * - Use non-blocking sockets to allow operation without select.
    45  * - Use select where safe (low socket numbers).
    46  * - Poll with short sleep when select cannot be used safely.
    47  */
    48 
    49 #include "hdhomerun.h"
    50 
    51 hdhomerun_sock_t hdhomerun_sock_create_udp(void)
    52 {
    53         /* Create socket. */
    54         hdhomerun_sock_t sock = (hdhomerun_sock_t)socket(AF_INET, SOCK_DGRAM, 0);
    55         if (sock == -1) {
    56                 return HDHOMERUN_SOCK_INVALID;
    57         }
    58 
    59         /* Set non-blocking */
    60         if (fcntl(sock, F_SETFL, O_NONBLOCK) != 0) {
    61                 close(sock);
    62                 return HDHOMERUN_SOCK_INVALID;
    63         }
    64 
    65         /* Allow broadcast. */
    66         int sock_opt = 1;
    67         setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&sock_opt, sizeof(sock_opt));
    68 
    69         /* Success. */
    70         return sock;
    71 }
    72 
    73 hdhomerun_sock_t hdhomerun_sock_create_tcp(void)
    74 {
    75         /* Create socket. */
    76         hdhomerun_sock_t sock = (hdhomerun_sock_t)socket(AF_INET, SOCK_STREAM, 0);
    77         if (sock == -1) {
    78                 return HDHOMERUN_SOCK_INVALID;
    79         }
    80 
    81         /* Set non-blocking */
    82         if (fcntl(sock, F_SETFL, O_NONBLOCK) != 0) {
    83                 close(sock);
    84                 return HDHOMERUN_SOCK_INVALID;
    85         }
    86 
    87         /* Success. */
    88         return sock;
    89 }
    90 
    91 void hdhomerun_sock_destroy(hdhomerun_sock_t sock)
    92 {
    93         close(sock);
    94 }
    95 
    96 int hdhomerun_sock_getlasterror(void)
    97 {
    98         return errno;
    99 }
    100 
    101 uint32_t hdhomerun_sock_getsockname_addr(hdhomerun_sock_t sock)
    102 {
    103         struct sockaddr_in sock_addr;
    104         socklen_t sockaddr_size = sizeof(sock_addr);
    105 
    106         if (getsockname(sock, (struct sockaddr *)&sock_addr, &sockaddr_size) != 0) {
    107                 return 0;
    108         }
    109 
    110         return ntohl(sock_addr.sin_addr.s_addr);
    111 }
    112 
    113 uint16_t hdhomerun_sock_getsockname_port(hdhomerun_sock_t sock)
    114 {
    115         struct sockaddr_in sock_addr;
    116         socklen_t sockaddr_size = sizeof(sock_addr);
    117 
    118         if (getsockname(sock, (struct sockaddr *)&sock_addr, &sockaddr_size) != 0) {
    119                 return 0;
    120         }
    121 
    122         return ntohs(sock_addr.sin_port);
    123 }
    124 
    125 uint32_t hdhomerun_sock_getpeername_addr(hdhomerun_sock_t sock)
    126 {
    127         struct sockaddr_in sock_addr;
    128         socklen_t sockaddr_size = sizeof(sock_addr);
    129 
    130         if (getpeername(sock, (struct sockaddr *)&sock_addr, &sockaddr_size) != 0) {
    131                 return 0;
    132         }
    133 
    134         return ntohl(sock_addr.sin_addr.s_addr);
    135 }
    136 
    137 #if defined(__CYGWIN__)
    138 uint32_t hdhomerun_sock_getaddrinfo_addr(hdhomerun_sock_t sock, const char *name)
    139 {
    140         return 0;
    141 }
    142 #else
    143 uint32_t hdhomerun_sock_getaddrinfo_addr(hdhomerun_sock_t sock, const char *name)
    144 {
    145         struct addrinfo hints;
    146         memset(&hints, 0, sizeof(hints));
    147         hints.ai_family = AF_INET;
    148         hints.ai_socktype = SOCK_STREAM;
    149         hints.ai_protocol = IPPROTO_TCP;
    150 
    151         struct addrinfo *sock_info;
    152         if (getaddrinfo(name, "", &hints, &sock_info) != 0) {
    153                 return 0;
    154         }
    155 
    156         struct sockaddr_in *sock_addr = (struct sockaddr_in *)sock_info->ai_addr;
    157         uint32_t addr = ntohl(sock_addr->sin_addr.s_addr);
    158 
    159         freeaddrinfo(sock_info);
    160         return addr;
    161 }
    162 #endif
    163 
    164 bool_t hdhomerun_sock_bind(hdhomerun_sock_t sock, uint32_t local_addr, uint16_t local_port)
    165 {
    166         struct sockaddr_in sock_addr;
    167         memset(&sock_addr, 0, sizeof(sock_addr));
    168         sock_addr.sin_family = AF_INET;
    169         sock_addr.sin_addr.s_addr = htonl(local_addr);
    170         sock_addr.sin_port = htons(local_port);
    171 
    172         if (bind(sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) {
    173                 return FALSE;
    174         }
    175 
    176         return TRUE;
    177 }
    178 
    179 static bool_t hdhomerun_sock_wait_for_read_event(hdhomerun_sock_t sock, uint64_t stop_time)
    180 {
    181         uint64_t current_time = getcurrenttime();
    182         if (current_time >= stop_time) {
    183                 return FALSE;
    184         }
    185 
    186         if (sock < FD_SETSIZE) {
    187                 uint64_t timeout = stop_time - current_time;
    188                 struct timeval t;
    189                 t.tv_sec = timeout / 1000;
    190                 t.tv_usec = (timeout % 1000) * 1000;
    191 
    192                 fd_set readfds;
    193                 FD_ZERO(&readfds);
    194                 FD_SET(sock, &readfds);
    195 
    196                 fd_set errorfds;
    197                 FD_ZERO(&errorfds);
    198                 FD_SET(sock, &errorfds);
    199 
    200                 if (select(sock + 1, &readfds, NULL, &errorfds, &t) <= 0) {
    201                         return FALSE;
    202                 }
    203                 if (!FD_ISSET(sock, &readfds)) {
    204                         return FALSE;
    205                 }
    206         } else {
    207                 uint64_t delay = stop_time - current_time;
    208                 if (delay > 5) {
    209                         delay = 5;
    210                 }
    211 
    212                 msleep_approx(delay);
    213         }
    214 
    215         return TRUE;
    216 }
    217 
    218 static bool_t hdhomerun_sock_wait_for_write_event(hdhomerun_sock_t sock, uint64_t stop_time)
    219 {
    220         uint64_t current_time = getcurrenttime();
    221         if (current_time >= stop_time) {
    222                 return FALSE;
    223         }
    224 
    225         if (sock < FD_SETSIZE) {
    226                 uint64_t timeout = stop_time - current_time;
    227                 struct timeval t;
    228                 t.tv_sec = timeout / 1000;
    229                 t.tv_usec = (timeout % 1000) * 1000;
    230 
    231                 fd_set writefds;
    232                 FD_ZERO(&writefds);
    233                 FD_SET(sock, &writefds);
    234 
    235                 fd_set errorfds;
    236                 FD_ZERO(&errorfds);
    237                 FD_SET(sock, &errorfds);
    238 
    239                 if (select(sock + 1, NULL, &writefds, &errorfds, &t) <= 0) {
    240                         return FALSE;
    241                 }
    242                 if (!FD_ISSET(sock, &writefds)) {
    243                         return FALSE;
    244                 }
    245         } else {
    246                 uint64_t delay = stop_time - current_time;
    247                 if (delay > 5) {
    248                         delay = 5;
    249                 }
    250 
    251                 msleep_approx(delay);
    252         }
    253 
    254         return TRUE;
    255 }
    256 
    257 bool_t hdhomerun_sock_connect(hdhomerun_sock_t sock, uint32_t remote_addr, uint16_t remote_port, uint64_t timeout)
    258 {
    259         struct sockaddr_in sock_addr;
    260         memset(&sock_addr, 0, sizeof(sock_addr));
    261         sock_addr.sin_family = AF_INET;
    262         sock_addr.sin_addr.s_addr = htonl(remote_addr);
    263         sock_addr.sin_port = htons(remote_port);
    264 
    265         if (connect(sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) == 0) {
    266                 return TRUE;
    267         }
    268 
    269         uint64_t stop_time = getcurrenttime() + timeout;
    270 
    271         /*
    272          * getpeername() is used to detect if connect succeeded. Bug - cygwin
    273          * will return getpeername success even if the connect process hasn't
    274          * completed. This first call to select is used to work around the
    275          * problem (at least for low numbered sockets where select is used).
    276          */
    277         if (!hdhomerun_sock_wait_for_write_event(sock, stop_time)) {
    278                 return FALSE;
    279         }
    280 
    281         while (1) {
    282                 struct sockaddr_in sock_addr;
    283                 socklen_t sockaddr_size = sizeof(sock_addr);
    284                 if (getpeername(sock, (struct sockaddr *)&sock_addr, &sockaddr_size) == 0) {
    285                         return TRUE;
    286                 }
    287 
    288                 if (errno != ENOTCONN) {
    289                         return FALSE;
    290                 }
    291 
    292                 if (!hdhomerun_sock_wait_for_write_event(sock, stop_time)) {
    293                         return FALSE;
    294                 }
    295         }
    296 }
    297 
    298 bool_t hdhomerun_sock_send(hdhomerun_sock_t sock, const void *data, size_t length, uint64_t timeout)
    299 {
    300         uint64_t stop_time = getcurrenttime() + timeout;
    301         const uint8_t *ptr = (uint8_t *)data;
    302 
    303         while (1) {
    304                 int ret = send(sock, ptr, length, 0);
    305                 if (ret >= (int)length) {
    306                         return TRUE;
    307                 }
    308 
    309                 if (ret > 0) {
    310                         ptr += ret;
    311                         length -= ret;
    312                 }
    313 
    314                 if (errno != EWOULDBLOCK) {
    315                         return FALSE;
    316                 }
    317 
    318                 if (!hdhomerun_sock_wait_for_write_event(sock, stop_time)) {
    319                         return FALSE;
    320                 }
    321         }
    322 }
    323 
    324 bool_t hdhomerun_sock_sendto(hdhomerun_sock_t sock, uint32_t remote_addr, uint16_t remote_port, const void *data, size_t length, uint64_t timeout)
    325 {
    326         uint64_t stop_time = getcurrenttime() + timeout;
    327         const uint8_t *ptr = (uint8_t *)data;
    328 
    329         while (1) {
    330                 struct sockaddr_in sock_addr;
    331                 memset(&sock_addr, 0, sizeof(sock_addr));
    332                 sock_addr.sin_family = AF_INET;
    333                 sock_addr.sin_addr.s_addr = htonl(remote_addr);
    334                 sock_addr.sin_port = htons(remote_port);
    335 
    336                 int ret = sendto(sock, ptr, length, 0, (struct sockaddr *)&sock_addr, sizeof(sock_addr));
    337                 if (ret >= (int)length) {
    338                         return TRUE;
    339                 }
    340 
    341                 if (ret > 0) {
    342                         ptr += ret;
    343                         length -= ret;
    344                 }
    345 
    346                 if (errno != EWOULDBLOCK) {
    347                         return FALSE;
    348                 }
    349 
    350                 if (!hdhomerun_sock_wait_for_write_event(sock, stop_time)) {
    351                         return FALSE;
    352                 }
    353         }
    354 }
    355 
    356 bool_t hdhomerun_sock_recv(hdhomerun_sock_t sock, void *data, size_t *length, uint64_t timeout)
    357 {
    358         uint64_t stop_time = getcurrenttime() + timeout;
    359 
    360         while (1) {
    361                 int ret = recv(sock, data, *length, 0);
    362                 if (ret > 0) {
    363                         *length = ret;
    364                         return TRUE;
    365                 }
    366 
    367                 if (errno != EWOULDBLOCK) {
    368                         return FALSE;
    369                 }
    370 
    371                 if (!hdhomerun_sock_wait_for_read_event(sock, stop_time)) {
    372                         return FALSE;
    373                 }
    374         }
    375 }
    376 
    377 bool_t hdhomerun_sock_recvfrom(hdhomerun_sock_t sock, uint32_t *remote_addr, uint16_t *remote_port, void *data, size_t *length, uint64_t timeout)
    378 {
    379         uint64_t stop_time = getcurrenttime() + timeout;
    380 
    381         while (1) {
    382                 struct sockaddr_in sock_addr;
    383                 memset(&sock_addr, 0, sizeof(sock_addr));
    384                 socklen_t sockaddr_size = sizeof(sock_addr);
    385 
    386                 int ret = recvfrom(sock, data, *length, 0, (struct sockaddr *)&sock_addr, &sockaddr_size);
    387                 if (ret > 0) {
    388                         *remote_addr = ntohl(sock_addr.sin_addr.s_addr);
    389                         *remote_port = ntohs(sock_addr.sin_port);
    390                         *length = ret;
    391                         return TRUE;
    392                 }
    393 
    394                 if (errno != EWOULDBLOCK) {
    395                         return FALSE;
    396                 }
    397 
    398                 if (!hdhomerun_sock_wait_for_read_event(sock, stop_time)) {
    399                         return FALSE;
    400                 }
    401         }
    402 }