Ticket #6138: 132-hdhr.20081231.patch

File 132-hdhr.20081231.patch, 243.2 KB (added by anonymous, 17 years ago)

hdhomerun lib update

  • mythtv/libs/libmythtv/hdhomerun/README

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhomerun/README release.19703.0116b/mythtv/libs/libmythtv/hdhomerun/README
     
     1/*
     2 * README
     3 *
     4 * Copyright © 2005-2006 Silicondust Engineering Ltd. <www.silicondust.com>.
     5 *
     6 * This library is free software; you can redistribute it and/or
     7 * modify it under the terms of the GNU Lesser General Public
     8 * License as published by the Free Software Foundation; either
     9 * version 3 of the License, or (at your option) any later version.
     10 *
     11 * This library is distributed in the hope that it will be useful,
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14 * Lesser General Public License for more details.
     15 *
     16 * You should have received a copy of the GNU Lesser General Public
     17 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
     18 *
     19 * As a special exception to the GNU Lesser General Public License,
     20 * you may link, statically or dynamically, an application with a
     21 * publicly distributed version of the Library to produce an
     22 * executable file containing portions of the Library, and
     23 * distribute that executable file under terms of your choice,
     24 * without any of the additional requirements listed in clause 4 of
     25 * the GNU Lesser General Public License.
     26 *
     27 * By "a publicly distributed version of the Library", we mean
     28 * either the unmodified Library as distributed by Silicondust, or a
     29 * modified version of the Library that is distributed under the
     30 * conditions defined in the GNU Lesser General Public License.
     31 */
    132
    2 This directory contains Silicondust Engineering's hdhomerun
    3 library used for communicating with the HDHomeRun hardware.
     33Top level include file: hdhomerun.h
    434
    5 The files in this directory are released under the GNU LESSER GENERAL PUBLIC LICENSE
    6 For details see the lgpl.txt file which should be located in this directory.
    7 If you can not find it, it can also be seen at http://www.gnu.org/licenses/lgpl.txt
     35Top level API: hdhomerun_device. See hdhomerun_device.h for documentation.
     36
     37The hdhomerun_device API should be used rather than the low level control and video APIs required with previous versions.
     38
     39Additional libraries required:
     40- pthread
     41- iphlpapi (windows only)
  • mythtv/libs/libmythtv/hdhomerun/README.MythTV

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhomerun/README.MythTV release.19703.0116b/mythtv/libs/libmythtv/hdhomerun/README.MythTV
     
     1
     2This directory contains Silicondust Engineering's hdhomerun
     3library used for communicating with the HDHomeRun hardware.
     4
     5The files in this directory are released under the GNU LESSER GENERAL PUBLIC LICENSE
     6For details see the lgpl.txt file which should be located in this directory.
     7If you can not find it, it can also be seen at http://www.gnu.org/licenses/lgpl.txt
  • mythtv/libs/libmythtv/hdhomerun/hdhomerun.h

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhomerun/hdhomerun.h release.19703.0116b/mythtv/libs/libmythtv/hdhomerun/hdhomerun.h
     
    11/*
    2  * hdhomerun_device.h
     2 * hdhomerun.h
    33 *
    4  * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
     4 * Copyright © 2006-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
    55 *
    6  * This library is free software; you can redistribute it and/or
     6 * This library is free software; you can redistribute it and/or 
    77 * modify it under the terms of the GNU Lesser General Public
    88 * License as published by the Free Software Foundation; either
    9  * version 2.1 of the License, or (at your option) any later version.
     9 * version 3 of the License, or (at your option) any later version.
    1010 *
    1111 * This library is distributed in the hope that it will be useful,
    1212 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     
    1414 * Lesser General Public License for more details.
    1515 *
    1616 * You should have received a copy of the GNU Lesser General Public
    17  * License along with this library; if not, write to the Free Software
    18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     17 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
     18 *
     19 * As a special exception to the GNU Lesser General Public License,
     20 * you may link, statically or dynamically, an application with a
     21 * publicly distributed version of the Library to produce an
     22 * executable file containing portions of the Library, and
     23 * distribute that executable file under terms of your choice,
     24 * without any of the additional requirements listed in clause 4 of
     25 * the GNU Lesser General Public License.
     26 *
     27 * By "a publicly distributed version of the Library", we mean
     28 * either the unmodified Library as distributed by Silicondust, or a
     29 * modified version of the Library that is distributed under the
     30 * conditions defined in the GNU Lesser General Public License.
    1931 */
    2032
    2133#include "hdhomerun_os.h"
     34#include "hdhomerun_types.h"
    2235#include "hdhomerun_pkt.h"
     36#include "hdhomerun_debug.h"
    2337#include "hdhomerun_discover.h"
    2438#include "hdhomerun_control.h"
    2539#include "hdhomerun_video.h"
     40#include "hdhomerun_channels.h"
     41#include "hdhomerun_channelscan.h"
    2642#include "hdhomerun_device.h"
  • mythtv/libs/libmythtv/hdhomerun/hdhomerun_channels.c

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhomerun/hdhomerun_channels.c release.19703.0116b/mythtv/libs/libmythtv/hdhomerun/hdhomerun_channels.c
     
     1/*
     2 * hdhomerun_channels.c
     3 *
     4 * Copyright © 2007-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
     5 *
     6 * This library is free software; you can redistribute it and/or
     7 * modify it under the terms of the GNU Lesser General Public
     8 * License as published by the Free Software Foundation; either
     9 * version 3 of the License, or (at your option) any later version.
     10 *
     11 * This library is distributed in the hope that it will be useful,
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14 * Lesser General Public License for more details.
     15 *
     16 * You should have received a copy of the GNU Lesser General Public
     17 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
     18 *
     19 * As a special exception to the GNU Lesser General Public License,
     20 * you may link, statically or dynamically, an application with a
     21 * publicly distributed version of the Library to produce an
     22 * executable file containing portions of the Library, and
     23 * distribute that executable file under terms of your choice,
     24 * without any of the additional requirements listed in clause 4 of
     25 * the GNU Lesser General Public License.
     26 *
     27 * By "a publicly distributed version of the Library", we mean
     28 * either the unmodified Library as distributed by Silicondust, or a
     29 * modified version of the Library that is distributed under the
     30 * conditions defined in the GNU Lesser General Public License.
     31 */
     32
     33#include "hdhomerun.h"
     34
     35#define FREQUENCY_RESOLUTION 62500
     36
     37struct hdhomerun_channel_entry_t {
     38        struct hdhomerun_channel_entry_t *next;
     39        struct hdhomerun_channel_entry_t *prev;
     40        uint32_t frequency;
     41        uint8_t channel_number;
     42        char name[16];
     43};
     44
     45struct hdhomerun_channel_list_t {
     46        struct hdhomerun_channel_entry_t *head;
     47        struct hdhomerun_channel_entry_t *tail;
     48};
     49
     50struct hdhomerun_channelmap_range_t {
     51        uint8_t channel_range_start;
     52        uint8_t channel_range_end;
     53        uint32_t frequency;
     54        uint32_t spacing;
     55};
     56
     57struct hdhomerun_channelmap_record_t {
     58        const char *channelmap_prefix;
     59        const char *channelmap;
     60        const struct hdhomerun_channelmap_range_t *range_list;
     61        const char *channelmap_scan_group;
     62        const char *countrycodes;
     63};
     64
     65/* AU antenna channels. Channels {0, 1, 2, 6, 7, 8, 9, 9A} are numbered {2, 3, 4, 5, 6, 7, 8, 9} by the HDHomeRun. */
     66static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_au_bcast[] = {
     67        {  2,   2,  48500000, 7000000},
     68        {  3,   4,  59500000, 7000000},
     69        {  5,  12, 177500000, 7000000},
     70        { 28,  69, 529500000, 7000000},
     71        {  0,   0,         0,       0}
     72};
     73
     74/* AU cable channels. TBD. */
     75static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_au_cable[] = {
     76        {  0,   0,         0,       0}
     77};
     78
     79/* EU antenna channels. */
     80static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_eu_bcast[] = {
     81        {  2,   4,  50500000, 7000000},
     82        {  5,  12, 177500000, 7000000},
     83        { 21,  69, 474000000, 8000000},
     84        {  0,   0,         0,       0}
     85};
     86
     87/* EU cable channels. Channels do not have simple numbers - the HDHomeRun uses its own numbering scheme (subject to change). */
     88static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_eu_cable[] = {
     89        {  6,   7, 113000000, 8000000},
     90        {  9, 100, 138000000, 8000000},
     91        {  0,   0,         0,       0}
     92};
     93
     94/* US antenna channels. */
     95static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_us_bcast[] = {
     96        {  2,   4,  57000000, 6000000},
     97        {  5,   6,  79000000, 6000000},
     98        {  7,  13, 177000000, 6000000},
     99        { 14,  69, 473000000, 6000000},
     100        {  0,   0,         0,       0}
     101};
     102
     103/* US cable channels. */
     104static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_us_cable[] = {
     105        {  2,   4,  57000000, 6000000},
     106        {  5,   6,  79000000, 6000000},
     107        {  7,  13, 177000000, 6000000},
     108        { 14,  22, 123000000, 6000000},
     109        { 23,  94, 219000000, 6000000},
     110        { 95,  99,  93000000, 6000000},
     111        {100, 135, 651000000, 6000000},
     112        {  0,   0,         0,       0}
     113};
     114
     115/* US cable channels (HRC). */
     116static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_us_hrc[] = {
     117        {  2,   4,  55752700, 6000300},
     118        {  5,   6,  79753900, 6000300},
     119        {  7,  13, 175758700, 6000300},
     120        { 14,  22, 121756000, 6000300},
     121        { 23,  94, 217760800, 6000300},
     122        { 95,  99,  91754500, 6000300},
     123        {100, 135, 649782400, 6000300},
     124        {  0,   0,         0,       0}
     125};
     126
     127/* US cable channels (IRC). */
     128static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_us_irc[] = {
     129        {  2,   4,  57012500, 6000000},
     130        {  5,   6,  81012500, 6000000},
     131        {  7,  13, 177012500, 6000000},
     132        { 14,  22, 123012500, 6000000},
     133        { 23,  41, 219012500, 6000000},
     134        { 42,  42, 333025000, 6000000},
     135        { 43,  94, 339012500, 6000000},
     136        { 95,  97,  93012500, 6000000},
     137        { 98,  99, 111025000, 6000000},
     138        {100, 135, 651012500, 6000000},
     139        {  0,   0,         0,       0}
     140};
     141
     142static const struct hdhomerun_channelmap_record_t hdhomerun_channelmap_table[] = {
     143        {"au", "au-bcast", hdhomerun_channelmap_range_au_bcast, "au-bcast",               "AU"},
     144        {"au", "au-cable", hdhomerun_channelmap_range_au_cable, "au-cable",               "AU"},
     145        {"eu", "eu-bcast", hdhomerun_channelmap_range_eu_bcast, "eu-bcast",               "EU"},
     146        {"eu", "eu-cable", hdhomerun_channelmap_range_eu_cable, "eu-cable",               "EU"},
     147        {"tw", "tw-bcast", hdhomerun_channelmap_range_us_bcast, "tw-bcast",               "TW"},
     148        {"tw", "tw-cable", hdhomerun_channelmap_range_us_cable, "tw-cable",               "TW"},
     149        {"us", "us-bcast", hdhomerun_channelmap_range_us_bcast, "us-bcast",               "CA US"},
     150        {"us", "us-cable", hdhomerun_channelmap_range_us_cable, "us-cable us-hrc us-irc", "CA US"},
     151        {"us", "us-hrc",   hdhomerun_channelmap_range_us_hrc  , "us-cable us-hrc us-irc", "CA US"},
     152        {"us", "us-irc",   hdhomerun_channelmap_range_us_irc,   "us-cable us-hrc us-irc", "CA US"},
     153        {NULL, NULL,       NULL,                                NULL,                     NULL}
     154};
     155
     156const char *hdhomerun_channelmap_convert_countrycode_to_channelmap_prefix(const char *countrycode)
     157{
     158        const struct hdhomerun_channelmap_record_t *record = hdhomerun_channelmap_table;
     159        while (record->channelmap) {
     160                if (strstr(record->countrycodes, countrycode)) {
     161                        return record->channelmap_prefix;
     162                }
     163                record++;
     164        }
     165
     166        return "eu";
     167}
     168
     169const char *hdhomerun_channelmap_get_channelmap_scan_group(const char *channelmap)
     170{
     171        const struct hdhomerun_channelmap_record_t *record = hdhomerun_channelmap_table;
     172        while (record->channelmap) {
     173                if (strstr(channelmap, record->channelmap)) {
     174                        return record->channelmap_scan_group;
     175                }
     176                record++;
     177        }
     178
     179        return NULL;
     180}
     181
     182uint8_t hdhomerun_channel_entry_channel_number(struct hdhomerun_channel_entry_t *entry)
     183{
     184        return entry->channel_number;
     185}
     186
     187uint32_t hdhomerun_channel_entry_frequency(struct hdhomerun_channel_entry_t *entry)
     188{
     189        return entry->frequency;
     190}
     191
     192const char *hdhomerun_channel_entry_name(struct hdhomerun_channel_entry_t *entry)
     193{
     194        return entry->name;
     195}
     196
     197struct hdhomerun_channel_entry_t *hdhomerun_channel_list_first(struct hdhomerun_channel_list_t *channel_list)
     198{
     199        return channel_list->head;
     200}
     201
     202struct hdhomerun_channel_entry_t *hdhomerun_channel_list_last(struct hdhomerun_channel_list_t *channel_list)
     203{
     204        return channel_list->tail;
     205}
     206
     207struct hdhomerun_channel_entry_t *hdhomerun_channel_list_next(struct hdhomerun_channel_list_t *channel_list, struct hdhomerun_channel_entry_t *entry)
     208{
     209        return entry->next;
     210}
     211
     212struct hdhomerun_channel_entry_t *hdhomerun_channel_list_prev(struct hdhomerun_channel_list_t *channel_list, struct hdhomerun_channel_entry_t *entry)
     213{
     214        return entry->prev;
     215}
     216
     217uint32_t hdhomerun_channel_list_total_count(struct hdhomerun_channel_list_t *channel_list)
     218{
     219        uint32_t count = 0;
     220
     221        struct hdhomerun_channel_entry_t *entry = hdhomerun_channel_list_first(channel_list);
     222        while (entry) {
     223                count++;
     224                entry = hdhomerun_channel_list_next(channel_list, entry);
     225        }
     226
     227        return count;
     228}
     229
     230uint32_t hdhomerun_channel_list_frequency_count(struct hdhomerun_channel_list_t *channel_list)
     231{
     232        uint32_t count = 0;
     233        uint32_t last_frequency = 0;
     234
     235        struct hdhomerun_channel_entry_t *entry = hdhomerun_channel_list_first(channel_list);
     236        while (entry) {
     237                if (entry->frequency != last_frequency) {
     238                        last_frequency = entry->frequency;
     239                        count++;
     240                }
     241
     242                entry = hdhomerun_channel_list_next(channel_list, entry);
     243        }
     244
     245        return count;
     246}
     247
     248uint32_t hdhomerun_channel_frequency_truncate(uint32_t frequency)
     249{
     250        return (frequency / FREQUENCY_RESOLUTION) * FREQUENCY_RESOLUTION;
     251}
     252
     253uint32_t hdhomerun_channel_number_to_frequency(struct hdhomerun_channel_list_t *channel_list, uint8_t channel_number)
     254{
     255        struct hdhomerun_channel_entry_t *entry = hdhomerun_channel_list_first(channel_list);
     256        while (entry) {
     257                if (entry->channel_number == channel_number) {
     258                        return entry->frequency;
     259                }
     260
     261                entry = hdhomerun_channel_list_next(channel_list, entry);
     262        }
     263
     264        return 0;
     265}
     266
     267uint8_t hdhomerun_channel_frequency_to_number(struct hdhomerun_channel_list_t *channel_list, uint32_t frequency)
     268{
     269        frequency = hdhomerun_channel_frequency_truncate(frequency);
     270
     271        struct hdhomerun_channel_entry_t *entry = hdhomerun_channel_list_first(channel_list);
     272        while (entry) {
     273                if (entry->frequency == frequency) {
     274                        return entry->channel_number;
     275                }
     276                if (entry->frequency > frequency) {
     277                        return 0;
     278                }
     279
     280                entry = hdhomerun_channel_list_next(channel_list, entry);
     281        }
     282
     283        return 0;
     284}
     285
     286static void hdhomerun_channel_list_build_insert(struct hdhomerun_channel_list_t *channel_list, struct hdhomerun_channel_entry_t *entry)
     287{
     288        struct hdhomerun_channel_entry_t *prev = NULL;
     289        struct hdhomerun_channel_entry_t *next = channel_list->head;
     290
     291        while (next) {
     292                if (next->frequency > entry->frequency) {
     293                        break;
     294                }
     295
     296                prev = next;
     297                next = next->next;
     298        }
     299
     300        entry->prev = prev;
     301        entry->next = next;
     302
     303        if (prev) {
     304                prev->next = entry;
     305        } else {
     306                channel_list->head = entry;
     307        }
     308
     309        if (next) {
     310                next->prev = entry;
     311        } else {
     312                channel_list->tail = entry;
     313        }
     314}
     315
     316static void hdhomerun_channel_list_build_range(struct hdhomerun_channel_list_t *channel_list, const char *channelmap, const struct hdhomerun_channelmap_range_t *range)
     317{
     318        uint8_t channel_number;
     319        for (channel_number = range->channel_range_start; channel_number <= range->channel_range_end; channel_number++) {
     320                struct hdhomerun_channel_entry_t *entry = (struct hdhomerun_channel_entry_t *)calloc(1, sizeof(struct hdhomerun_channel_entry_t));
     321                if (!entry) {
     322                        return;
     323                }
     324
     325                entry->channel_number = channel_number;
     326                entry->frequency = range->frequency + ((uint32_t)(channel_number - range->channel_range_start) * range->spacing);
     327                entry->frequency = hdhomerun_channel_frequency_truncate(entry->frequency);
     328                sprintf(entry->name, "%s:%u", channelmap, entry->channel_number);
     329
     330                hdhomerun_channel_list_build_insert(channel_list, entry);
     331        }
     332}
     333
     334static void hdhomerun_channel_list_build_ranges(struct hdhomerun_channel_list_t *channel_list, const struct hdhomerun_channelmap_record_t *record)
     335{
     336        const struct hdhomerun_channelmap_range_t *range = record->range_list;
     337        while (range->frequency) {
     338                hdhomerun_channel_list_build_range(channel_list, record->channelmap, range);
     339                range++;
     340        }
     341}
     342
     343void hdhomerun_channel_list_destroy(struct hdhomerun_channel_list_t *channel_list)
     344{
     345        while (channel_list->head) {
     346                struct hdhomerun_channel_entry_t *entry = channel_list->head;
     347                channel_list->head = entry->next;
     348                free(entry);
     349        }
     350
     351        free(channel_list);
     352}
     353
     354struct hdhomerun_channel_list_t *hdhomerun_channel_list_create(const char *channelmap)
     355{
     356        struct hdhomerun_channel_list_t *channel_list = (struct hdhomerun_channel_list_t *)calloc(1, sizeof(struct hdhomerun_channel_list_t));
     357        if (!channel_list) {
     358                return NULL;
     359        }
     360
     361        const struct hdhomerun_channelmap_record_t *record = hdhomerun_channelmap_table;
     362        while (record->channelmap) {
     363                if (!strstr(channelmap, record->channelmap)) {
     364                        record++;
     365                        continue;
     366                }
     367
     368                hdhomerun_channel_list_build_ranges(channel_list, record);
     369                record++;
     370        }
     371
     372        if (!channel_list->head) {
     373                free(channel_list);
     374                return NULL;
     375        }
     376
     377        return channel_list;
     378}
  • mythtv/libs/libmythtv/hdhomerun/hdhomerun_channels.h

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhomerun/hdhomerun_channels.h release.19703.0116b/mythtv/libs/libmythtv/hdhomerun/hdhomerun_channels.h
     
     1/*
     2 * hdhomerun_channels.h
     3 *
     4 * Copyright © 2007-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
     5 *
     6 * This library is free software; you can redistribute it and/or
     7 * modify it under the terms of the GNU Lesser General Public
     8 * License as published by the Free Software Foundation; either
     9 * version 3 of the License, or (at your option) any later version.
     10 *
     11 * This library is distributed in the hope that it will be useful,
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14 * Lesser General Public License for more details.
     15 *
     16 * You should have received a copy of the GNU Lesser General Public
     17 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
     18 *
     19 * As a special exception to the GNU Lesser General Public License,
     20 * you may link, statically or dynamically, an application with a
     21 * publicly distributed version of the Library to produce an
     22 * executable file containing portions of the Library, and
     23 * distribute that executable file under terms of your choice,
     24 * without any of the additional requirements listed in clause 4 of
     25 * the GNU Lesser General Public License.
     26 *
     27 * By "a publicly distributed version of the Library", we mean
     28 * either the unmodified Library as distributed by Silicondust, or a
     29 * modified version of the Library that is distributed under the
     30 * conditions defined in the GNU Lesser General Public License.
     31 */
     32
     33#ifdef __cplusplus
     34extern "C" {
     35#endif
     36
     37struct hdhomerun_channel_entry_t;
     38struct hdhomerun_channel_list_t;
     39
     40extern LIBTYPE const char *hdhomerun_channelmap_convert_countrycode_to_channelmap_prefix(const char *countrycode);
     41extern LIBTYPE const char *hdhomerun_channelmap_get_channelmap_scan_group(const char *channelmap);
     42
     43extern LIBTYPE uint8_t hdhomerun_channel_entry_channel_number(struct hdhomerun_channel_entry_t *entry);
     44extern LIBTYPE uint32_t hdhomerun_channel_entry_frequency(struct hdhomerun_channel_entry_t *entry);
     45extern LIBTYPE const char *hdhomerun_channel_entry_name(struct hdhomerun_channel_entry_t *entry);
     46
     47extern LIBTYPE struct hdhomerun_channel_list_t *hdhomerun_channel_list_create(const char *channelmap);
     48extern LIBTYPE void hdhomerun_channel_list_destroy(struct hdhomerun_channel_list_t *channel_list);
     49
     50extern LIBTYPE struct hdhomerun_channel_entry_t *hdhomerun_channel_list_first(struct hdhomerun_channel_list_t *channel_list);
     51extern LIBTYPE struct hdhomerun_channel_entry_t *hdhomerun_channel_list_last(struct hdhomerun_channel_list_t *channel_list);
     52extern LIBTYPE struct hdhomerun_channel_entry_t *hdhomerun_channel_list_next(struct hdhomerun_channel_list_t *channel_list, struct hdhomerun_channel_entry_t *entry);
     53extern LIBTYPE struct hdhomerun_channel_entry_t *hdhomerun_channel_list_prev(struct hdhomerun_channel_list_t *channel_list, struct hdhomerun_channel_entry_t *entry);
     54extern LIBTYPE uint32_t hdhomerun_channel_list_total_count(struct hdhomerun_channel_list_t *channel_list);
     55extern LIBTYPE uint32_t hdhomerun_channel_list_frequency_count(struct hdhomerun_channel_list_t *channel_list);
     56
     57extern LIBTYPE uint32_t hdhomerun_channel_frequency_truncate(uint32_t frequency);
     58extern LIBTYPE uint32_t hdhomerun_channel_number_to_frequency(struct hdhomerun_channel_list_t *channel_list, uint8_t channel_number);
     59extern LIBTYPE uint8_t hdhomerun_channel_frequency_to_number(struct hdhomerun_channel_list_t *channel_list, uint32_t frequency);
     60
     61#ifdef __cplusplus
     62}
     63#endif
  • mythtv/libs/libmythtv/hdhomerun/hdhomerun_channelscan.c

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhomerun/hdhomerun_channelscan.c release.19703.0116b/mythtv/libs/libmythtv/hdhomerun/hdhomerun_channelscan.c
     
     1/*
     2 * hdhomerun_channelscan.c
     3 *
     4 * Copyright © 2007-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
     5 *
     6 * This library is free software; you can redistribute it and/or
     7 * modify it under the terms of the GNU Lesser General Public
     8 * License as published by the Free Software Foundation; either
     9 * version 3 of the License, or (at your option) any later version.
     10 *
     11 * This library is distributed in the hope that it will be useful,
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14 * Lesser General Public License for more details.
     15 *
     16 * You should have received a copy of the GNU Lesser General Public
     17 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
     18 *
     19 * As a special exception to the GNU Lesser General Public License,
     20 * you may link, statically or dynamically, an application with a
     21 * publicly distributed version of the Library to produce an
     22 * executable file containing portions of the Library, and
     23 * distribute that executable file under terms of your choice,
     24 * without any of the additional requirements listed in clause 4 of
     25 * the GNU Lesser General Public License.
     26 *
     27 * By "a publicly distributed version of the Library", we mean
     28 * either the unmodified Library as distributed by Silicondust, or a
     29 * modified version of the Library that is distributed under the
     30 * conditions defined in the GNU Lesser General Public License.
     31 */
     32
     33#include "hdhomerun.h"
     34
     35struct hdhomerun_channelscan_t {
     36        struct hdhomerun_device_t *hd;
     37        uint32_t scanned_channels;
     38        struct hdhomerun_channel_list_t *channel_list; 
     39        struct hdhomerun_channel_entry_t *next_channel;
     40};
     41
     42struct hdhomerun_channelscan_t *channelscan_create(struct hdhomerun_device_t *hd, const char *channelmap)
     43{
     44        struct hdhomerun_channelscan_t *scan = (struct hdhomerun_channelscan_t *)calloc(1, sizeof(struct hdhomerun_channelscan_t));
     45        if (!scan) {
     46                return NULL;
     47        }
     48
     49        scan->hd = hd;
     50
     51        scan->channel_list = hdhomerun_channel_list_create(channelmap);
     52        if (!scan->channel_list) {
     53                free(scan);
     54                return NULL;
     55        }
     56
     57        scan->next_channel = hdhomerun_channel_list_last(scan->channel_list);
     58        return scan;
     59}
     60
     61void channelscan_destroy(struct hdhomerun_channelscan_t *scan)
     62{
     63        free(scan);
     64}
     65
     66static int channelscan_execute_find_lock(struct hdhomerun_channelscan_t *scan, uint32_t frequency, struct hdhomerun_channelscan_result_t *result)
     67{
     68        /* Set channel. */
     69        char channel_str[64];
     70        sprintf(channel_str, "auto:%ld", (unsigned long)frequency);
     71
     72        int ret = hdhomerun_device_set_tuner_channel(scan->hd, channel_str);
     73        if (ret <= 0) {
     74                return ret;
     75        }
     76
     77        /* Wait for lock. */
     78        ret = hdhomerun_device_wait_for_lock(scan->hd, &result->status);
     79        if (ret <= 0) {
     80                return ret;
     81        }
     82        if (!result->status.lock_supported) {
     83                return 1;
     84        }
     85
     86        /* Wait for symbol quality = 100%. */
     87        int i;
     88        for (i = 0; i < 5 * 4; i++) {
     89                usleep(250000);
     90
     91                ret = hdhomerun_device_get_tuner_status(scan->hd, NULL, &result->status);
     92                if (ret <= 0) {
     93                        return ret;
     94                }
     95
     96                if (result->status.symbol_error_quality == 100) {
     97                        return 1;
     98                }
     99        }
     100
     101        /* Timeout. */
     102        return 1;
     103}
     104
     105static void channelscan_extract_name(struct hdhomerun_channelscan_program_t *program, const char *line)
     106{
     107        /* Find start of name. */
     108        const char *start = strchr(line, ' ');
     109        if (!start) {
     110                return;
     111        }
     112        start++;
     113
     114        start = strchr(start, ' ');
     115        if (!start) {
     116                return;
     117        }
     118        start++;
     119
     120        /* Find end of name. */
     121        const char *end = strstr(start, " (");
     122        if (!end) {
     123                end = strchr(line, 0);
     124        }
     125
     126        if (end <= start) {
     127                return;
     128        }
     129
     130        /* Extract name. */
     131        size_t length = (size_t)(end - start);
     132        if (length > sizeof(program->name) - 1) {
     133                length = sizeof(program->name) - 1;
     134        }
     135
     136        strncpy(program->name, start, length);
     137        program->name[length] = 0;
     138}
     139
     140static int channelscan_execute_detect_programs(struct hdhomerun_channelscan_t *scan, struct hdhomerun_channelscan_result_t *result, int *pchanged)
     141{
     142        *pchanged = FALSE;
     143
     144        char *streaminfo;
     145        int ret = hdhomerun_device_get_tuner_streaminfo(scan->hd, &streaminfo);
     146        if (ret <= 0) {
     147                return ret;
     148        }
     149
     150        char *line = streaminfo;
     151        int program_count = 0;
     152
     153        while (1) {
     154                char *end = strchr(line, '\n');
     155                if (!end) {
     156                        break;
     157                }
     158
     159                *end = 0;
     160
     161                struct hdhomerun_channelscan_program_t program;
     162                memset(&program, 0, sizeof(program));
     163
     164                strncpy(program.program_str, line, sizeof(program.program_str));
     165                program.program_str[sizeof(program.program_str) - 1] = 0;
     166
     167                unsigned int program_number;
     168                unsigned int virtual_major, virtual_minor;
     169                if (sscanf(line, "%u: %u.%u", &program_number, &virtual_major, &virtual_minor) != 3) {
     170                        continue;
     171                }
     172
     173                program.program_number = program_number;
     174                program.virtual_major = virtual_major;
     175                program.virtual_minor = virtual_minor;
     176
     177                channelscan_extract_name(&program, line);
     178
     179                program.type = HDHOMERUN_CHANNELSCAN_PROGRAM_NORMAL;
     180                if (strstr(line, "(no data)")) {
     181                        program.type = HDHOMERUN_CHANNELSCAN_PROGRAM_NODATA;
     182                }
     183                if (strstr(line, "(control)")) {
     184                        program.type = HDHOMERUN_CHANNELSCAN_PROGRAM_CONTROL;
     185                }
     186                if (strstr(line, "(encrypted)")) {
     187                        program.type = HDHOMERUN_CHANNELSCAN_PROGRAM_ENCRYPTED;
     188                }
     189
     190                if (memcmp(&result->programs[program_count], &program, sizeof(program)) != 0) {
     191                        memcpy(&result->programs[program_count], &program, sizeof(program));
     192                        *pchanged = TRUE;
     193                }
     194
     195                program_count++;
     196                if (program_count >= HDHOMERUN_CHANNELSCAN_MAX_PROGRAM_COUNT) {
     197                        break;
     198                }
     199
     200                line = end + 1;
     201        }
     202
     203        if (result->program_count != program_count) {
     204                result->program_count = program_count;
     205                *pchanged = TRUE;
     206        }
     207
     208        return 1;
     209}
     210
     211int channelscan_advance(struct hdhomerun_channelscan_t *scan, struct hdhomerun_channelscan_result_t *result)
     212{
     213        memset(result, 0, sizeof(struct hdhomerun_channelscan_result_t));
     214
     215        struct hdhomerun_channel_entry_t *entry = scan->next_channel;
     216        if (!entry) {
     217                return 0;
     218        }
     219
     220        /* Combine channels with same frequency. */
     221        result->frequency = hdhomerun_channel_entry_frequency(entry);
     222        strncpy(result->channel_str, hdhomerun_channel_entry_name(entry), sizeof(result->channel_str) - 1);
     223        result->channel_str[sizeof(result->channel_str) - 1] = 0;
     224
     225        while (1) {
     226                entry = hdhomerun_channel_list_prev(scan->channel_list, entry);
     227                if (!entry) {
     228                        scan->next_channel = NULL;
     229                        break;
     230                }
     231
     232                if (hdhomerun_channel_entry_frequency(entry) != result->frequency) {
     233                        scan->next_channel = entry;
     234                        break;
     235                }
     236
     237                char *ptr = strchr(result->channel_str, 0);
     238                sprintf(ptr, ", %s", hdhomerun_channel_entry_name(entry));
     239        }
     240
     241        return 1;
     242}
     243
     244int channelscan_detect(struct hdhomerun_channelscan_t *scan, struct hdhomerun_channelscan_result_t *result)
     245{
     246        scan->scanned_channels++;
     247
     248        /* Find lock. */
     249        int ret = channelscan_execute_find_lock(scan, result->frequency, result);
     250        if (ret <= 0) {
     251                return ret;
     252        }
     253        if (!result->status.lock_supported) {
     254                return 1;
     255        }
     256
     257        /* Detect programs. */
     258        result->program_count = 0;
     259
     260        int changed;
     261        ret = channelscan_execute_detect_programs(scan, result, &changed);
     262        if (ret <= 0) {
     263                return ret;
     264        }
     265
     266        int same_count = 0;
     267        int i;
     268        for (i = 0; i < 5 * 4; i++) {
     269                usleep(250000);
     270
     271                ret = channelscan_execute_detect_programs(scan, result, &changed);
     272                if (ret <= 0) {
     273                        return ret;
     274                }
     275
     276                if (changed) {
     277                        same_count = 0;
     278                        continue;
     279                }
     280
     281                same_count++;
     282                if (same_count >= 8) {
     283                        break;
     284                }
     285        }
     286
     287        /* Complete. */
     288        return 1;
     289}
     290
     291uint8_t channelscan_get_progress(struct hdhomerun_channelscan_t *scan)
     292{
     293        struct hdhomerun_channel_entry_t *entry = scan->next_channel;
     294        if (!entry) {
     295                return 100;
     296        }
     297
     298        uint32_t channels_remaining = 1;
     299        uint32_t frequency = hdhomerun_channel_entry_frequency(entry);
     300
     301        while (1) {
     302                entry = hdhomerun_channel_list_prev(scan->channel_list, entry);
     303                if (!entry) {
     304                        break;
     305                }
     306
     307                if (hdhomerun_channel_entry_frequency(entry) != frequency) {
     308                        channels_remaining++;
     309                        frequency = hdhomerun_channel_entry_frequency(entry);
     310                }
     311        }
     312
     313        return scan->scanned_channels * 100 / (scan->scanned_channels + channels_remaining);
     314}
  • mythtv/libs/libmythtv/hdhomerun/hdhomerun_channelscan.h

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhomerun/hdhomerun_channelscan.h release.19703.0116b/mythtv/libs/libmythtv/hdhomerun/hdhomerun_channelscan.h
     
     1/*
     2 * hdhomerun_channelscan.h
     3 *
     4 * Copyright © 2007-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
     5 *
     6 * This library is free software; you can redistribute it and/or
     7 * modify it under the terms of the GNU Lesser General Public
     8 * License as published by the Free Software Foundation; either
     9 * version 3 of the License, or (at your option) any later version.
     10 *
     11 * This library is distributed in the hope that it will be useful,
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14 * Lesser General Public License for more details.
     15 *
     16 * You should have received a copy of the GNU Lesser General Public
     17 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
     18 *
     19 * As a special exception to the GNU Lesser General Public License,
     20 * you may link, statically or dynamically, an application with a
     21 * publicly distributed version of the Library to produce an
     22 * executable file containing portions of the Library, and
     23 * distribute that executable file under terms of your choice,
     24 * without any of the additional requirements listed in clause 4 of
     25 * the GNU Lesser General Public License.
     26 *
     27 * By "a publicly distributed version of the Library", we mean
     28 * either the unmodified Library as distributed by Silicondust, or a
     29 * modified version of the Library that is distributed under the
     30 * conditions defined in the GNU Lesser General Public License.
     31 */
     32
     33#ifdef __cplusplus
     34extern "C" {
     35#endif
     36
     37#define HDHOMERUN_CHANNELSCAN_PROGRAM_NORMAL 0
     38#define HDHOMERUN_CHANNELSCAN_PROGRAM_NODATA 1
     39#define HDHOMERUN_CHANNELSCAN_PROGRAM_CONTROL 2
     40#define HDHOMERUN_CHANNELSCAN_PROGRAM_ENCRYPTED 3
     41
     42struct hdhomerun_channelscan_t;
     43
     44extern LIBTYPE struct hdhomerun_channelscan_t *channelscan_create(struct hdhomerun_device_t *hd, const char *channelmap);
     45extern LIBTYPE void channelscan_destroy(struct hdhomerun_channelscan_t *scan);
     46
     47extern LIBTYPE int channelscan_advance(struct hdhomerun_channelscan_t *scan, struct hdhomerun_channelscan_result_t *result);
     48extern LIBTYPE int channelscan_detect(struct hdhomerun_channelscan_t *scan, struct hdhomerun_channelscan_result_t *result);
     49extern LIBTYPE uint8_t channelscan_get_progress(struct hdhomerun_channelscan_t *scan);
     50
     51#ifdef __cplusplus
     52}
     53#endif
  • mythtv/libs/libmythtv/hdhomerun/hdhomerun_config.c

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhomerun/hdhomerun_config.c release.19703.0116b/mythtv/libs/libmythtv/hdhomerun/hdhomerun_config.c
     
    11/*
    22 * hdhomerun_config.c
    33 *
    4  * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
     4 * Copyright © 2006-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
    55 *
    6  * This library is free software; you can redistribute it and/or
     6 * This library is free software; you can redistribute it and/or 
    77 * modify it under the terms of the GNU Lesser General Public
    88 * License as published by the Free Software Foundation; either
    9  * version 2.1 of the License, or (at your option) any later version.
     9 * version 3 of the License, or (at your option) any later version.
    1010 *
    1111 * This library is distributed in the hope that it will be useful,
    1212 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     
    1414 * Lesser General Public License for more details.
    1515 *
    1616 * You should have received a copy of the GNU Lesser General Public
    17  * License along with this library; if not, write to the Free Software
    18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     17 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
     18 *
     19 * As a special exception to the GNU Lesser General Public License,
     20 * you may link, statically or dynamically, an application with a
     21 * publicly distributed version of the Library to produce an
     22 * executable file containing portions of the Library, and
     23 * distribute that executable file under terms of your choice,
     24 * without any of the additional requirements listed in clause 4 of
     25 * the GNU Lesser General Public License.
     26 *
     27 * By "a publicly distributed version of the Library", we mean
     28 * either the unmodified Library as distributed by Silicondust, or a
     29 * modified version of the Library that is distributed under the
     30 * conditions defined in the GNU Lesser General Public License.
    1931 */
    2032
    2133#include "hdhomerun.h"
    2234
     35/*
     36 * The console output format should be set to UTF-8, however in XP and Vista this breaks batch file processing.
     37 * Attempting to restore on exit fails to restore if the program is terminated by the user.
     38 * Solution - set the output format each printf.
     39 */
     40#if defined(__WINDOWS__)
     41#define printf console_printf
     42#define vprintf console_vprintf
     43#endif
     44
    2345static const char *appname;
    2446
    2547struct hdhomerun_device_t *hd;
     
    3153        printf("\t%s <id> get help\n", appname);
    3254        printf("\t%s <id> get <item>\n", appname);
    3355        printf("\t%s <id> set <item> <value>\n", appname);
    34         printf("\t%s <id> scan <tuner> <starting channel>\n", appname);
     56        printf("\t%s <id> scan <tuner> [<filename>]\n", appname);
     57        printf("\t%s <id> save <tuner> <filename>\n", appname);
    3558        printf("\t%s <id> upgrade <filename>\n", appname);
    3659        return -1;
    3760}
     
    6891        return FALSE;
    6992}
    7093
    71 static int discover_print(void)
     94static uint32_t parse_ip_addr(const char *str)
     95{
     96        unsigned long a[4];
     97        if (sscanf(str, "%lu.%lu.%lu.%lu", &a[0], &a[1], &a[2], &a[3]) != 4) {
     98                return 0;
     99        }
     100
     101        return (uint32_t)((a[0] << 24) | (a[1] << 16) | (a[2] << 8) | (a[3] << 0));
     102}
     103
     104static int discover_print(char *target_ip_str)
    72105{
     106        uint32_t target_ip = 0;
     107        if (target_ip_str) {
     108                target_ip = parse_ip_addr(target_ip_str);
     109                if (target_ip == 0) {
     110                        fprintf(stderr, "invalid ip address: %s\n", target_ip_str);
     111                        return -1;
     112                }
     113        }
     114
    73115        struct hdhomerun_discover_device_t result_list[64];
    74         int count = hdhomerun_discover_find_devices(HDHOMERUN_DEVICE_TYPE_TUNER, result_list, 64);
     116        int count = hdhomerun_discover_find_devices_custom(target_ip, HDHOMERUN_DEVICE_TYPE_TUNER, HDHOMERUN_DEVICE_ID_WILDCARD, result_list, 64);
    75117        if (count < 0) {
    76118                fprintf(stderr, "error sending discover request\n");
    77119                return -1;
     
    94136        return count;
    95137}
    96138
    97 static bool_t parse_device_id_str(const char *s, uint32_t *pdevice_id, uint32_t *pdevice_ip)
    98 {
    99         unsigned long a[4];
    100         if (sscanf(s, "%lu.%lu.%lu.%lu", &a[0], &a[1], &a[2], &a[3]) == 4) {
    101                 *pdevice_id = HDHOMERUN_DEVICE_ID_WILDCARD;
    102                 *pdevice_ip = (uint32_t)((a[0] << 24) | (a[1] << 16) | (a[2] << 8) | (a[3] << 0));
    103                 return TRUE;
    104         }
    105 
    106         unsigned long device_id_raw;
    107         if (sscanf(s, "%lx", &device_id_raw) != 1) {
    108                 fprintf(stderr, "invalid device id: %s\n", s);
    109                 return FALSE;
    110         }
    111 
    112         uint32_t device_id = (uint32_t)device_id_raw;
    113         if (!hdhomerun_discover_validate_device_id(device_id)) {
    114                 fprintf(stderr, "invalid device id: %s\n", s);
    115                 return FALSE;
    116         }
    117 
    118         *pdevice_id = device_id;
    119         *pdevice_ip = 0;
    120         return TRUE;
    121 }
    122 
    123139static int cmd_get(const char *item)
    124140{
    125141        char *ret_value;
     
    138154        return 1;
    139155}
    140156
    141 static int cmd_set(const char *item, const char *value)
     157static int cmd_set_internal(const char *item, const char *value)
    142158{
    143159        char *ret_error;
    144160        if (hdhomerun_device_set_var(hd, item, value, NULL, &ret_error) < 0) {
     
    154170        return 1;
    155171}
    156172
    157 static int cmd_streaminfo(const char *tuner_str)
     173static int cmd_set(const char *item, const char *value)
    158174{
    159         fprintf(stderr, "streaminfo: use \"get /tuner<n>/streaminfo\"\n");
    160         return -1;
     175        if (strcmp(value, "-") == 0) {
     176                char *buffer = NULL;
     177                size_t pos = 0;
     178
     179                while (1) {
     180                        buffer = (char *)realloc(buffer, pos + 1024);
     181                        if (!buffer) {
     182                                fprintf(stderr, "out of memory\n");
     183                                return -1;
     184                        }
     185
     186                        int size = fread(buffer + pos, 1, 1024, stdin);
     187                        pos += size;
     188
     189                        if (size < 1024) {
     190                                break;
     191                        }
     192                }
     193
     194                buffer[pos] = 0;
     195
     196                int ret = cmd_set_internal(item, buffer);
     197
     198                free(buffer);
     199                return ret;
     200        }
     201
     202        return cmd_set_internal(item, value);
    161203}
    162204
    163 static int cmd_scan(const char *tuner_str, const char *start_value)
     205static void cmd_scan_printf(FILE *fp, const char *fmt, ...)
    164206{
    165         unsigned int tuner;
    166         if (sscanf(tuner_str, "%u", &tuner) != 1) {
    167                 fprintf(stderr, "invalid tuner number\n");
    168                 return -1;
    169         }
     207        va_list ap;
     208        va_start(ap, fmt);
    170209
    171         hdhomerun_device_set_tuner(hd, tuner);
     210        if (fp) {
     211                va_list apc;
     212                va_copy(apc, ap);
    172213
    173         char channel_str[64];
    174         strncpy(channel_str, start_value, sizeof(channel_str));
    175         channel_str[sizeof(channel_str) - 8] = 0;
    176 
    177         char *channel_number_ptr = strrchr(channel_str, ':');
    178         if (!channel_number_ptr) {
    179                 channel_number_ptr = channel_str;
    180         } else {
    181                 channel_number_ptr++;
     214                vfprintf(fp, fmt, apc);
     215                fflush(fp);
     216
     217                va_end(apc);
    182218        }
    183219
    184         unsigned int channel_number = atol(channel_number_ptr);
    185         if (channel_number == 0) {
    186                 fprintf(stderr, "invalid starting channel\n");
     220        vprintf(fmt, ap);
     221        fflush(stdout);
     222
     223        va_end(ap);
     224}
     225
     226static int cmd_scan(const char *tuner_str, const char *filename)
     227{
     228        if (hdhomerun_device_set_tuner_from_str(hd, tuner_str) <= 0) {
     229                fprintf(stderr, "invalid tuner number\n");
    187230                return -1;
    188231        }
    189232
    190         /* Test starting channel. */
    191         int ret = hdhomerun_device_set_tuner_channel(hd, channel_str);
    192         if (ret < 0) {
    193                 fprintf(stderr, "communication error sending request to hdhomerun device\n");
     233        char *channelmap;
     234        if (hdhomerun_device_get_tuner_channelmap(hd, &channelmap) <= 0) {
     235                fprintf(stderr, "failed to query channelmap from device\n");
    194236                return -1;
    195237        }
    196         if (ret == 0) {
    197                 fprintf(stderr, "invalid starting channel\n");
     238
     239        const char *channelmap_scan_group = hdhomerun_channelmap_get_channelmap_scan_group(channelmap);
     240        if (!channelmap_scan_group) {
     241                fprintf(stderr, "unknown channelmap '%s'\n", channelmap);
    198242                return -1;
    199243        }
    200244
    201         while (1) {
    202                 /* Update channel value */
    203                 sprintf(channel_number_ptr, "%u", channel_number);
     245        if (hdhomerun_device_channelscan_init(hd, channelmap_scan_group) <= 0) {
     246                fprintf(stderr, "failed to initialize channel scan\n");
     247                return -1;
     248        }
    204249
    205                 /* Set channel. */
    206                 ret = hdhomerun_device_set_tuner_channel(hd, channel_str);
    207                 if (ret < 0) {
    208                         fprintf(stderr, "communication error sending request to hdhomerun device\n");
     250        FILE *fp = NULL;
     251        if (filename) {
     252                fp = fopen(filename, "w");
     253                if (!fp) {
     254                        fprintf(stderr, "unable to create file: %s\n", filename);
    209255                        return -1;
    210256                }
    211                 if (ret == 0) {
    212                         return 0;
     257        }
     258
     259        int ret;
     260        while (1) {
     261                struct hdhomerun_channelscan_result_t result;
     262                ret = hdhomerun_device_channelscan_advance(hd, &result);
     263                if (ret <= 0) {
     264                        break;
    213265                }
    214266
    215                 /* Wait 1.5s for lock (qam auto is the slowest to lock). */
    216                 usleep(HDHOMERUN_DEVICE_MAX_TUNE_TO_LOCK_TIME * 1000);
     267                cmd_scan_printf(fp, "SCANNING: %lu (%s)\n",
     268                        result.frequency, result.channel_str
     269                );
    217270
    218                 /* Get status to check for signal. Quality numbers will not be valid yet. */
    219                 struct hdhomerun_tuner_status_t status;
    220                 if (hdhomerun_device_get_tuner_status(hd, &status) < 0) {
    221                         fprintf(stderr, "communication error sending request to hdhomerun device\n");
    222                         return -1;
     271                ret = hdhomerun_device_channelscan_detect(hd, &result);
     272                if (ret <= 0) {
     273                        break;
    223274                }
    224275
    225                 /* If no signal then advance to next channel. */
    226                 if (status.signal_strength == 0) {
    227                         printf("%s: no signal\n", channel_str);
    228                         channel_number++;
    229                         continue;
     276                cmd_scan_printf(fp, "LOCK: %s (ss=%u snq=%u seq=%u)\n",
     277                        result.status.lock_str, result.status.signal_strength,
     278                        result.status.signal_to_noise_quality, result.status.symbol_error_quality
     279                );
     280
     281                int i;
     282                for (i = 0; i < result.program_count; i++) {
     283                        struct hdhomerun_channelscan_program_t *program = &result.programs[i];
     284                        cmd_scan_printf(fp, "PROGRAM %s\n", program->program_str);
    230285                }
     286        }
     287
     288        if (fp) {
     289                fclose(fp);
     290        }
     291        if (ret < 0) {
     292                fprintf(stderr, "communication error sending request to hdhomerun device\n");
     293        }
     294        return ret;
     295}
     296
     297static void cmd_save_abort(int junk)
     298{
     299        struct hdhomerun_video_stats_t stats;
     300        hdhomerun_device_get_video_stats(hd, &stats);
     301        hdhomerun_device_stream_stop(hd);
     302        hdhomerun_device_destroy(hd);
     303
     304        fprintf(stderr, "\n");
     305        fprintf(stderr, "-- Video statistics --\n");
     306        fprintf(stderr, "%u packets received, %u network errors, %u transport errors, %u sequence errors\n",
     307                (unsigned)stats.packet_count,
     308                (unsigned)stats.network_error_count,
     309                (unsigned)stats.transport_error_count,
     310                (unsigned)stats.sequence_error_count);
     311
     312        exit(0);
     313}
    231314
    232                 /* Wait for 2s. */
    233                 usleep(HDHOMERUN_DEVICE_MAX_LOCK_TO_DATA_TIME * 1000);
     315static int cmd_save(const char *tuner_str, const char *filename)
     316{
     317        if (hdhomerun_device_set_tuner_from_str(hd, tuner_str) <= 0) {
     318                fprintf(stderr, "invalid tuner number\n");
     319                return -1;
     320        }
    234321
    235                 /* Get status to check quality numbers. */
    236                 if (hdhomerun_device_get_tuner_status(hd, &status) < 0) {
    237                         fprintf(stderr, "communication error sending request to hdhomerun device\n");
     322        FILE *fp;
     323        if (strcmp(filename, "null") == 0) {
     324                fp = NULL;
     325        } else if (strcmp(filename, "-") == 0) {
     326                fp = stdout;
     327        } else {
     328                fp = fopen(filename, "wb");
     329                if (!fp) {
     330                        fprintf(stderr, "unable to create file %s\n", filename);
    238331                        return -1;
    239332                }
    240                 if (status.signal_strength == 0) {
    241                         printf("%s: no signal\n", channel_str);
    242                         channel_number++;
    243                         continue;
    244                 }
    245                 printf("%s: ss=%u snq=%u seq=%u\n", channel_str, status.signal_strength, status.signal_to_noise_quality, status.symbol_error_quality);
     333        }
     334
     335        int ret = hdhomerun_device_stream_start(hd);
     336        if (ret <= 0) {
     337                fprintf(stderr, "unable to start stream\n");
     338                return ret;
     339        }
     340
     341        signal(SIGINT, cmd_save_abort);
     342        signal(SIGPIPE, cmd_save_abort);
    246343
    247                 /* Detect sub channels. */
    248                 usleep(4 * 1000000);
    249                 char *streaminfo;
    250                 if (hdhomerun_device_get_tuner_streaminfo(hd, &streaminfo) <= 0) {
    251                         channel_number++;
     344        struct hdhomerun_video_stats_t stats_old, stats_cur;
     345        hdhomerun_device_get_video_stats(hd, &stats_old);
     346
     347        uint64_t next_progress = getcurrenttime() + 1000;
     348        while (1) {
     349                usleep(64000);
     350
     351                size_t actual_size;
     352                uint8_t *ptr = hdhomerun_device_stream_recv(hd, VIDEO_DATA_BUFFER_SIZE_1S, &actual_size);
     353                if (!ptr) {
    252354                        continue;
    253355                }
    254                 while (1) {
    255                         char *end = strchr(streaminfo, '\n');
    256                         if (!end) {
    257                                 break;
     356
     357                if (fp) {
     358                        if (fwrite(ptr, 1, actual_size, fp) != actual_size) {
     359                                fprintf(stderr, "error writing output\n");
     360                                return -1;
    258361                        }
     362                }
    259363
    260                         *end++ = 0;
    261                         printf("program %s\n", streaminfo);
     364                uint64_t current_time = getcurrenttime();
     365                if (current_time >= next_progress) {
     366                        next_progress = current_time + 1000;
     367
     368                        hdhomerun_device_get_video_stats(hd, &stats_cur);
     369
     370                        if (stats_cur.network_error_count > stats_old.network_error_count) {
     371                                fprintf(stderr, "n");
     372                        } else if (stats_cur.transport_error_count > stats_old.transport_error_count) {
     373                                fprintf(stderr, "t");
     374                        } else if (stats_cur.sequence_error_count > stats_old.sequence_error_count) {
     375                                fprintf(stderr, "s");
     376                        } else {
     377                                fprintf(stderr, ".");
     378                        }
    262379
    263                         streaminfo = end;
     380                        stats_old = stats_cur;
     381                        fflush(stderr);
    264382                }
    265 
    266                 /* Advance to next channel. */
    267                 channel_number++;
    268383        }
    269384}
    270385
     
    276391                return -1;
    277392        }
    278393
     394        printf("uploading firmware...\n");
    279395        if (hdhomerun_device_upgrade(hd, fp) <= 0) {
    280396                fprintf(stderr, "error sending upgrade file to hdhomerun device\n");
    281397                fclose(fp);
    282398                return -1;
    283399        }
     400        sleep(2);
     401
     402        printf("upgrading firmware...\n");
     403        sleep(8);
     404
     405        printf("rebooting...\n");
     406        int count = 0;
     407        char *version_str;
     408        while (1) {
     409                if (hdhomerun_device_get_version(hd, &version_str, NULL) >= 0) {
     410                        break;
     411                }
     412
     413                count++;
     414                if (count > 30) {
     415                        fprintf(stderr, "error finding device after firmware upgrade\n");
     416                        fclose(fp);
     417                        return -1;
     418                }
     419
     420                sleep(1);
     421        }
    284422
    285         printf("upgrade complete\n");
     423        printf("upgrade complete - now running firmware %s\n", version_str);
    286424        return 0;
    287425}
    288426
     
    308446                return cmd_set(argv[0], argv[1]);
    309447        }
    310448
    311         if (contains(cmd, "streaminfo")) {
     449        if (contains(cmd, "scan")) {
    312450                if (argc < 1) {
    313451                        return help();
    314452                }
    315                 return cmd_streaminfo(argv[0]);
     453                if (argc < 2) {
     454                        return cmd_scan(argv[0], NULL);
     455                } else {
     456                        return cmd_scan(argv[0], argv[1]);
     457                }
    316458        }
    317459
    318         if (contains(cmd, "scan")) {
     460        if (contains(cmd, "save")) {
    319461                if (argc < 2) {
    320462                        return help();
    321463                }
    322                 return cmd_scan(argv[0], argv[1]);
     464                return cmd_save(argv[0], argv[1]);
    323465        }
    324466
    325467        if (contains(cmd, "upgrade")) {
     
    335477static int main_internal(int argc, char *argv[])
    336478{
    337479#if defined(__WINDOWS__)
    338         //Start pthreads
    339         pthread_win32_process_attach_np();
    340 
    341         // Start WinSock
     480        /* Initialize network socket support. */
    342481        WORD wVersionRequested = MAKEWORD(2, 0);
    343482        WSADATA wsaData;
    344483        WSAStartup(wVersionRequested, &wsaData);
     
    357496                return help();
    358497        }
    359498        if (contains(id_str, "discover")) {
    360                 return discover_print();
    361         }
    362 
    363         /* Device ID. */
    364         uint32_t device_id, device_ip;
    365         if (!parse_device_id_str(id_str, &device_id, &device_ip)) {
    366                 return -1;
     499                if (argc < 1) {
     500                        return discover_print(NULL);
     501                } else {
     502                        return discover_print(argv[0]);
     503                }
    367504        }
    368505
    369506        /* Device object. */
    370         hd = hdhomerun_device_create(device_id, device_ip, 0);
     507        hd = hdhomerun_device_create_from_str(id_str);
    371508        if (!hd) {
    372                 fprintf(stderr, "unable to create device\n");
     509                fprintf(stderr, "invalid device id: %s\n", id_str);
    373510                return -1;
    374511        }
    375512
    376         /* Connect to device and check firmware version. */
    377         int ret = hdhomerun_device_firmware_version_check(hd, 0);
    378         if (ret < 0) {
     513        /* Device ID check. */
     514        uint32_t device_id_requested = hdhomerun_device_get_device_id_requested(hd);
     515        if (!hdhomerun_discover_validate_device_id(device_id_requested)) {
     516                fprintf(stderr, "invalid device id: %08lX\n", (unsigned long)device_id_requested);
     517        }
     518
     519        /* Connect to device and check model. */
     520        const char *model = hdhomerun_device_get_model_str(hd);
     521        if (!model) {
    379522                fprintf(stderr, "unable to connect to device\n");
    380523                hdhomerun_device_destroy(hd);
    381524                return -1;
    382525        }
    383         if (ret == 0) {
    384                 fprintf(stderr, "WARNING: firmware upgrade needed for all operations to function\n");
    385         }
    386526
    387527        /* Command. */
    388         ret = main_cmd(argc, argv);
     528        int ret = main_cmd(argc, argv);
    389529
    390530        /* Cleanup. */
    391531        hdhomerun_device_destroy(hd);
  • mythtv/libs/libmythtv/hdhomerun/hdhomerun_control.c

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhomerun/hdhomerun_control.c release.19703.0116b/mythtv/libs/libmythtv/hdhomerun/hdhomerun_control.c
     
    11/*
    22 * hdhomerun_control.c
    33 *
    4  * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
     4 * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
    55 *
    6  * This library is free software; you can redistribute it and/or
     6 * This library is free software; you can redistribute it and/or 
    77 * modify it under the terms of the GNU Lesser General Public
    88 * License as published by the Free Software Foundation; either
    9  * version 2.1 of the License, or (at your option) any later version.
     9 * version 3 of the License, or (at your option) any later version.
    1010 *
    1111 * This library is distributed in the hope that it will be useful,
    1212 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     
    1414 * Lesser General Public License for more details.
    1515 *
    1616 * You should have received a copy of the GNU Lesser General Public
    17  * License along with this library; if not, write to the Free Software
    18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     17 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
     18 *
     19 * As a special exception to the GNU Lesser General Public License,
     20 * you may link, statically or dynamically, an application with a
     21 * publicly distributed version of the Library to produce an
     22 * executable file containing portions of the Library, and
     23 * distribute that executable file under terms of your choice,
     24 * without any of the additional requirements listed in clause 4 of
     25 * the GNU Lesser General Public License.
     26 *
     27 * By "a publicly distributed version of the Library", we mean
     28 * either the unmodified Library as distributed by Silicondust, or a
     29 * modified version of the Library that is distributed under the
     30 * conditions defined in the GNU Lesser General Public License.
    1931 */
    2032
    21 #include "hdhomerun_os.h"
    22 #include "hdhomerun_pkt.h"
    23 #include "hdhomerun_discover.h"
    24 #include "hdhomerun_control.h"
     33#include "hdhomerun.h"
     34
     35#define HDHOMERUN_CONTROL_SEND_TIMEOUT 5000
     36#define HDHOMERUN_CONTROL_RECV_TIMEOUT 5000
     37#define HDHOMERUN_CONTROL_UPGRADE_TIMEOUT 20000
    2538
    2639struct hdhomerun_control_sock_t {
    27         uint32_t device_id;
    28         uint32_t device_ip;
     40        uint32_t desired_device_id;
     41        uint32_t desired_device_ip;
     42        uint32_t actual_device_id;
     43        uint32_t actual_device_ip;
    2944        int sock;
    30         uint8_t buffer[16384];
     45        struct hdhomerun_debug_t *dbg;
     46        struct hdhomerun_pkt_t tx_pkt;
     47        struct hdhomerun_pkt_t rx_pkt;
    3148};
    3249
     50static void hdhomerun_control_close_sock(struct hdhomerun_control_sock_t *cs)
     51{
     52        if (cs->sock == -1) {
     53                return;
     54        }
     55
     56        close(cs->sock);
     57        cs->sock = -1;
     58}
     59
     60void hdhomerun_control_set_device(struct hdhomerun_control_sock_t *cs, uint32_t device_id, uint32_t device_ip)
     61{
     62        hdhomerun_control_close_sock(cs);
     63
     64        cs->desired_device_id = device_id;
     65        cs->desired_device_ip = device_ip;
     66        cs->actual_device_id = 0;
     67        cs->actual_device_ip = 0;
     68}
     69
    3370struct hdhomerun_control_sock_t *hdhomerun_control_create(uint32_t device_id, uint32_t device_ip)
    3471{
    35         struct hdhomerun_control_sock_t *cs = (struct hdhomerun_control_sock_t *)malloc(sizeof(struct hdhomerun_control_sock_t));
     72        struct hdhomerun_control_sock_t *cs = (struct hdhomerun_control_sock_t *)calloc(1, sizeof(struct hdhomerun_control_sock_t));
    3673        if (!cs) {
    3774                return NULL;
    3875        }
    39        
    40         cs->device_id = device_id;
    41         cs->device_ip = device_ip;
     76
    4277        cs->sock = -1;
     78        hdhomerun_control_set_device(cs, device_id, device_ip);
    4379
    4480        return cs;
    4581}
    4682
    4783void hdhomerun_control_destroy(struct hdhomerun_control_sock_t *cs)
    4884{
    49         if (cs->sock != -1) {
    50                 close(cs->sock);
    51         }
     85        hdhomerun_control_close_sock(cs);
    5286        free(cs);
    5387}
    5488
    55 static void hdhomerun_control_close_sock(struct hdhomerun_control_sock_t *cs)
     89void hdhomerun_control_set_debug(struct hdhomerun_control_sock_t *cs, struct hdhomerun_debug_t *dbg)
    5690{
    57         close(cs->sock);
    58         cs->sock = -1;
     91        cs->dbg = dbg;
    5992}
    6093
    6194static bool_t hdhomerun_control_connect_sock(struct hdhomerun_control_sock_t *cs)
     
    6497                return TRUE;
    6598        }
    6699
    67         /* Find ip address. */
    68         uint32_t device_ip = cs->device_ip;
    69         if (device_ip == 0) {
    70                 struct hdhomerun_discover_device_t result;
    71                 if (hdhomerun_discover_find_device(cs->device_id, &result) <= 0) {
    72                         return FALSE;
    73                 }
    74                 device_ip = result.ip_addr;
     100        if ((cs->desired_device_id == 0) && (cs->desired_device_ip == 0)) {
     101                hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_connect_sock: no device specified\n");
     102                return FALSE;
     103        }
     104
     105        /* Find device. */
     106        struct hdhomerun_discover_device_t result;
     107        if (hdhomerun_discover_find_devices_custom(cs->desired_device_ip, HDHOMERUN_DEVICE_TYPE_WILDCARD, cs->desired_device_id, &result, 1) <= 0) {
     108                hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_connect_sock: device not found\n");
     109                return FALSE;
    75110        }
     111        cs->actual_device_ip = result.ip_addr;
     112        cs->actual_device_id = result.device_id;
    76113
    77114        /* Create socket. */
    78115        cs->sock = (int)socket(AF_INET, SOCK_STREAM, 0);
    79116        if (cs->sock == -1) {
     117                hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_connect_sock: failed to create socket (%d)\n", sock_getlasterror);
    80118                return FALSE;
    81119        }
    82120
    83121        /* Set timeouts. */
    84         setsocktimeout(cs->sock, SOL_SOCKET, SO_SNDTIMEO, 1000);
    85         setsocktimeout(cs->sock, SOL_SOCKET, SO_RCVTIMEO, 1000);
     122        setsocktimeout(cs->sock, SOL_SOCKET, SO_SNDTIMEO, HDHOMERUN_CONTROL_SEND_TIMEOUT);
     123        setsocktimeout(cs->sock, SOL_SOCKET, SO_RCVTIMEO, HDHOMERUN_CONTROL_RECV_TIMEOUT);
    86124
    87125        /* Initiate connection. */
    88126        struct sockaddr_in sock_addr;
    89127        memset(&sock_addr, 0, sizeof(sock_addr));
    90128        sock_addr.sin_family = AF_INET;
    91         sock_addr.sin_addr.s_addr = htonl(device_ip);
     129        sock_addr.sin_addr.s_addr = htonl(cs->actual_device_ip);
    92130        sock_addr.sin_port = htons(HDHOMERUN_CONTROL_TCP_PORT);
    93131        if (connect(cs->sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) {
     132                hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_connect_sock: failed to connect (%d)\n", sock_getlasterror);
    94133                hdhomerun_control_close_sock(cs);
    95134                return FALSE;
    96135        }
     
    99138        return TRUE;
    100139}
    101140
     141uint32_t hdhomerun_control_get_device_id(struct hdhomerun_control_sock_t *cs)
     142{
     143        if (!hdhomerun_control_connect_sock(cs)) {
     144                hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_get_device_id: connect failed\n");
     145                return 0;
     146        }
     147
     148        return cs->actual_device_id;
     149}
     150
     151uint32_t hdhomerun_control_get_device_ip(struct hdhomerun_control_sock_t *cs)
     152{
     153        if (!hdhomerun_control_connect_sock(cs)) {
     154                hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_get_device_ip: connect failed\n");
     155                return 0;
     156        }
     157
     158        return cs->actual_device_ip;
     159}
     160
     161uint32_t hdhomerun_control_get_device_id_requested(struct hdhomerun_control_sock_t *cs)
     162{
     163        return cs->desired_device_id;
     164}
     165
     166uint32_t hdhomerun_control_get_device_ip_requested(struct hdhomerun_control_sock_t *cs)
     167{
     168        return cs->desired_device_ip;
     169}
     170
    102171uint32_t hdhomerun_control_get_local_addr(struct hdhomerun_control_sock_t *cs)
    103172{
    104173        if (!hdhomerun_control_connect_sock(cs)) {
     174                hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_get_local_addr: connect failed\n");
    105175                return 0;
    106176        }
    107177
    108178        struct sockaddr_in sock_addr;
    109179        socklen_t sockaddr_size = sizeof(sock_addr);
    110180        if (getsockname(cs->sock, (struct sockaddr*)&sock_addr, &sockaddr_size) != 0) {
     181                hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_get_local_addr: getsockname failed (%d)\n", sock_getlasterror);
    111182                return 0;
    112183        }
    113184
    114185        return ntohl(sock_addr.sin_addr.s_addr);
    115186}
    116187
    117 static int hdhomerun_control_send(struct hdhomerun_control_sock_t *cs, uint8_t *start, uint8_t *end)
     188static int hdhomerun_control_send_sock(struct hdhomerun_control_sock_t *cs, struct hdhomerun_pkt_t *tx_pkt)
    118189{
    119         int length = (int)(end - start);
    120         if (send(cs->sock, (char *)start, (int)length, 0) != length) {
     190        int length = (int)(tx_pkt->end - tx_pkt->start);
     191        if (send(cs->sock, (char *)tx_pkt->start, (int)length, 0) != length) {
     192                hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_send_sock: send failed (%d)\n", sock_getlasterror);
     193                hdhomerun_control_close_sock(cs);
    121194                return -1;
    122195        }
    123196
    124         return length;
     197        return 1;
    125198}
    126199
    127 static int hdhomerun_control_recv_sock(struct hdhomerun_control_sock_t *cs, uint8_t *buffer, uint8_t *limit)
     200static int hdhomerun_control_recv_sock(struct hdhomerun_control_sock_t *cs, struct hdhomerun_pkt_t *rx_pkt, uint16_t *ptype, uint64_t recv_timeout)
    128201{
    129         struct timeval t;
    130         t.tv_sec = 0;
    131         t.tv_usec = 250000;
    132 
    133         fd_set readfds;
    134         FD_ZERO(&readfds);
    135         FD_SET(cs->sock, &readfds);
     202        uint64_t stop_time = getcurrenttime() + recv_timeout;
     203        hdhomerun_pkt_reset(rx_pkt);
    136204
    137         if (select(cs->sock+1, &readfds, NULL, NULL, &t) < 0) {
    138                 return -1;
    139         }
     205        while (getcurrenttime() < stop_time) {
     206                struct timeval t;
     207                t.tv_sec = 0;
     208                t.tv_usec = 250000;
     209       
     210                fd_set readfds;
     211                FD_ZERO(&readfds);
     212                FD_SET(cs->sock, &readfds);
     213       
     214                if (select(cs->sock+1, &readfds, NULL, NULL, &t) < 0) {
     215                        hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_recv_sock: select failed (%d)\n", sock_getlasterror);
     216                        hdhomerun_control_close_sock(cs);
     217                        return -1;
     218                }
     219       
     220                if (!FD_ISSET(cs->sock, &readfds)) {
     221                        continue;
     222                }
     223       
     224                int rx_length = recv(cs->sock, (char *)rx_pkt->end, (int)(rx_pkt->limit - rx_pkt->end), 0);
     225                if (rx_length <= 0) {
     226                        hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_recv_sock: recv failed (%d)\n", sock_getlasterror);
     227                        hdhomerun_control_close_sock(cs);
     228                        return -1;
     229                }
     230                rx_pkt->end += rx_length;
    140231
    141         if (!FD_ISSET(cs->sock, &readfds)) {
    142                 return 0;
    143         }
     232                int ret = hdhomerun_pkt_open_frame(rx_pkt, ptype);
     233                if (ret < 0) {
     234                        hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_recv_sock: frame error\n");
     235                        hdhomerun_control_close_sock(cs);
     236                        return -1;
     237                }
     238                if (ret == 0) {
     239                        continue;
     240                }
    144241
    145         int length = recv(cs->sock, (char *)buffer, (int)(limit - buffer), 0);
    146         if (length <= 0) {
    147                 return -1;
     242                return 1;
    148243        }
    149244
    150         return length;
     245        hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_recv_sock: timeout\n");
     246        hdhomerun_control_close_sock(cs);
     247        return -1;
    151248}
    152249
    153 static int hdhomerun_control_recv(struct hdhomerun_control_sock_t *cs, uint8_t *buffer, uint8_t *limit)
     250static 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)
    154251{
    155         uint64_t timeout = getcurrenttime() + 1000;
    156         uint8_t *ptr = buffer;
     252        hdhomerun_pkt_seal_frame(tx_pkt, type);
    157253
    158         while (getcurrenttime() < timeout) {
    159                 int length = hdhomerun_control_recv_sock(cs, ptr, limit);
    160                 if (length < 0) {
    161                         return -1;
     254        int i;
     255        for (i = 0; i < 2; i++) {
     256                if (cs->sock == -1) {
     257                        if (!hdhomerun_control_connect_sock(cs)) {
     258                                hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_send_recv: connect failed\n");
     259                                return -1;
     260                        }
    162261                }
    163                 if (length == 0) {
     262
     263                if (hdhomerun_control_send_sock(cs, tx_pkt) < 0) {
    164264                        continue;
    165265                }
    166                 ptr += length;
     266                if (!rx_pkt) {
     267                        return 1;
     268                }
    167269
    168                 if (buffer + HDHOMERUN_MIN_PEEK_LENGTH > limit) {
     270                uint16_t rsp_type;
     271                if (hdhomerun_control_recv_sock(cs, rx_pkt, &rsp_type, recv_timeout) < 0) {
    169272                        continue;
    170273                }
    171 
    172                 length = (int)hdhomerun_peek_packet_length(buffer);
    173                 if (buffer + length > limit) {
     274                if (rsp_type != type + 1) {
     275                        hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_send_recv: unexpected frame type\n");
     276                        hdhomerun_control_close_sock(cs);
    174277                        continue;
    175278                }
    176279
    177                 return length;
     280                return 1;
    178281        }
    179282
     283        hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_send_recv: failed\n");
    180284        return -1;
    181285}
    182286
    183 static int hdhomerun_control_get_set(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, char **pvalue, char **perror)
     287int hdhomerun_control_send_recv(struct hdhomerun_control_sock_t *cs, struct hdhomerun_pkt_t *tx_pkt, struct hdhomerun_pkt_t *rx_pkt, uint16_t type)
     288{
     289        return hdhomerun_control_send_recv_internal(cs, tx_pkt, rx_pkt, type, HDHOMERUN_CONTROL_RECV_TIMEOUT);
     290}
     291
     292static int hdhomerun_control_get_set(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, uint32_t lockkey, char **pvalue, char **perror)
    184293{
    185         /* Send request. */
    186         uint8_t *ptr = cs->buffer;
    187         hdhomerun_write_get_set_request(&ptr, name, value);
    188         if (hdhomerun_control_send(cs, cs->buffer, ptr) < 0) {
     294        struct hdhomerun_pkt_t *tx_pkt = &cs->tx_pkt;
     295        struct hdhomerun_pkt_t *rx_pkt = &cs->rx_pkt;
     296
     297        /* Request. */
     298        hdhomerun_pkt_reset(tx_pkt);
     299
     300        int name_len = (int)strlen(name) + 1;
     301        if (tx_pkt->end + 3 + name_len > tx_pkt->limit) {
    189302                return -1;
    190303        }
     304        hdhomerun_pkt_write_u8(tx_pkt, HDHOMERUN_TAG_GETSET_NAME);
     305        hdhomerun_pkt_write_var_length(tx_pkt, name_len);
     306        hdhomerun_pkt_write_mem(tx_pkt, (void *)name, name_len);
    191307
    192         /* Receive response. */
    193         int length = hdhomerun_control_recv(cs, cs->buffer, cs->buffer + sizeof(cs->buffer));
    194         if (length <= 0) {
    195                 return -1;
     308        if (value) {
     309                int value_len = (int)strlen(value) + 1;
     310                if (tx_pkt->end + 3 + value_len > tx_pkt->limit) {
     311                        return -1;
     312                }
     313                hdhomerun_pkt_write_u8(tx_pkt, HDHOMERUN_TAG_GETSET_VALUE);
     314                hdhomerun_pkt_write_var_length(tx_pkt, value_len);
     315                hdhomerun_pkt_write_mem(tx_pkt, (void *)value, value_len);
    196316        }
    197317
    198         /* Parse response. */
    199         ptr = cs->buffer;
    200         uint8_t *end = ptr + length;
    201         int type = hdhomerun_process_packet(&ptr, &end);
    202         if (type < 0) {
    203                 return -1;
     318        if (lockkey != 0) {
     319                if (tx_pkt->end + 6 > tx_pkt->limit) {
     320                        return -1;
     321                }
     322                hdhomerun_pkt_write_u8(tx_pkt, HDHOMERUN_TAG_GETSET_LOCKKEY);
     323                hdhomerun_pkt_write_var_length(tx_pkt, 4);
     324                hdhomerun_pkt_write_u32(tx_pkt, lockkey);
    204325        }
    205         if (type != HDHOMERUN_TYPE_GETSET_RPY) {
     326
     327        /* Send/Recv. */
     328        if (hdhomerun_control_send_recv_internal(cs, tx_pkt, rx_pkt, HDHOMERUN_TYPE_GETSET_REQ, HDHOMERUN_CONTROL_RECV_TIMEOUT) < 0) {
    206329                return -1;
    207330        }
    208331
    209         while (ptr < end) {
     332        /* Response. */
     333        while (1) {
    210334                uint8_t tag;
    211335                size_t len;
    212                 uint8_t *val;
    213                 if (hdhomerun_read_tlv(&ptr, end, &tag, &len, &val) < 0) {
     336                uint8_t *next = hdhomerun_pkt_read_tlv(rx_pkt, &tag, &len);
     337                if (!next) {
    214338                        break;
    215339                }
     340
    216341                switch (tag) {
    217342                case HDHOMERUN_TAG_GETSET_VALUE:
    218343                        if (pvalue) {
    219                                 *pvalue = (char *)val;
    220                                 val[len] = 0;
     344                                *pvalue = (char *)rx_pkt->pos;
     345                                rx_pkt->pos[len] = 0;
    221346                        }
    222347                        if (perror) {
    223348                                *perror = NULL;
     
    229354                                *pvalue = NULL;
    230355                        }
    231356                        if (perror) {
    232                                 *perror = (char *)val;
    233                                 val[len] = 0;
     357                                *perror = (char *)rx_pkt->pos;
     358                                rx_pkt->pos[len] = 0;
    234359                        }
    235360                        return 0;
    236361                }
     362
     363                rx_pkt->pos = next;
    237364        }
    238365
     366        hdhomerun_debug_printf(cs->dbg, "hdhomerun_control_get_set: missing response tags\n");
    239367        return -1;
    240368}
    241369
    242370int hdhomerun_control_get(struct hdhomerun_control_sock_t *cs, const char *name, char **pvalue, char **perror)
    243371{
    244         if (!hdhomerun_control_connect_sock(cs)) {
    245                 return -1;
    246         }
    247 
    248         int ret = hdhomerun_control_get_set(cs, name, NULL, pvalue, perror);
    249         if (ret < 0) {
    250                 hdhomerun_control_close_sock(cs);
    251                 return -1;
    252         }
    253 
    254         return ret;
     372        return hdhomerun_control_get_set(cs, name, NULL, 0, pvalue, perror);
    255373}
    256374
    257375int hdhomerun_control_set(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, char **pvalue, char **perror)
    258376{
    259         if (!hdhomerun_control_connect_sock(cs)) {
    260                 return -1;
    261         }
    262 
    263         int ret = hdhomerun_control_get_set(cs, name, value, pvalue, perror);
    264         if (ret < 0) {
    265                 hdhomerun_control_close_sock(cs);
    266                 return -1;
    267         }
     377        return hdhomerun_control_get_set(cs, name, value, 0, pvalue, perror);
     378}
    268379
    269         return ret;
     380int hdhomerun_control_set_with_lockkey(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, uint32_t lockkey, char **pvalue, char **perror)
     381{
     382        return hdhomerun_control_get_set(cs, name, value, lockkey, pvalue, perror);
    270383}
    271384
    272385int hdhomerun_control_upgrade(struct hdhomerun_control_sock_t *cs, FILE *upgrade_file)
    273386{
    274         if (!hdhomerun_control_connect_sock(cs)) {
    275                 return -1;
    276         }
    277 
     387        struct hdhomerun_pkt_t *tx_pkt = &cs->tx_pkt;
     388        struct hdhomerun_pkt_t *rx_pkt = &cs->rx_pkt;
    278389        uint32_t sequence = 0;
    279         uint8_t *ptr;
    280390
     391        /* Upload. */
    281392        while (1) {
    282393                uint8_t data[256];
    283394                size_t length = fread(data, 1, 256, upgrade_file);
     
    285396                        break;
    286397                }
    287398
    288                 ptr = cs->buffer;
    289                 hdhomerun_write_upgrade_request(&ptr, sequence, data, length);
    290                 if (hdhomerun_control_send(cs, cs->buffer, ptr) < 0) {
    291                         hdhomerun_control_close_sock(cs);
     399                hdhomerun_pkt_reset(tx_pkt);
     400                hdhomerun_pkt_write_u32(tx_pkt, sequence);
     401                hdhomerun_pkt_write_mem(tx_pkt, data, length);
     402
     403                if (hdhomerun_control_send_recv_internal(cs, tx_pkt, NULL, HDHOMERUN_TYPE_UPGRADE_REQ, 0) < 0) {
    292404                        return -1;
    293405                }
    294406
     
    300412                return 0;
    301413        }
    302414
    303         ptr = cs->buffer;
    304         hdhomerun_write_upgrade_request(&ptr, 0xFFFFFFFF, NULL, 0);
    305         if (hdhomerun_control_send(cs, cs->buffer, ptr) < 0) {
    306                 hdhomerun_control_close_sock(cs);
     415        /* Execute upgrade. */
     416        hdhomerun_pkt_reset(tx_pkt);
     417        hdhomerun_pkt_write_u32(tx_pkt, 0xFFFFFFFF);
     418
     419        if (hdhomerun_control_send_recv_internal(cs, tx_pkt, rx_pkt, HDHOMERUN_TYPE_UPGRADE_REQ, HDHOMERUN_CONTROL_UPGRADE_TIMEOUT) < 0) {
    307420                return -1;
    308421        }
    309422
     423        /* Check response. */
     424        while (1) {
     425                uint8_t tag;
     426                size_t len;
     427                uint8_t *next = hdhomerun_pkt_read_tlv(rx_pkt, &tag, &len);
     428                if (!next) {
     429                        break;
     430                }
     431
     432                switch (tag) {
     433                case HDHOMERUN_TAG_ERROR_MESSAGE:
     434                        return 0;
     435
     436                default:
     437                        break;
     438                }
     439
     440                rx_pkt->pos = next;
     441        }
     442
    310443        return 1;
    311444}
  • mythtv/libs/libmythtv/hdhomerun/hdhomerun_control.h

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhomerun/hdhomerun_control.h release.19703.0116b/mythtv/libs/libmythtv/hdhomerun/hdhomerun_control.h
     
    11/*
    22 * hdhomerun_control.h
    33 *
    4  * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
     4 * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
    55 *
    6  * This library is free software; you can redistribute it and/or
     6 * This library is free software; you can redistribute it and/or 
    77 * modify it under the terms of the GNU Lesser General Public
    88 * License as published by the Free Software Foundation; either
    9  * version 2.1 of the License, or (at your option) any later version.
     9 * version 3 of the License, or (at your option) any later version.
    1010 *
    1111 * This library is distributed in the hope that it will be useful,
    1212 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     
    1414 * Lesser General Public License for more details.
    1515 *
    1616 * You should have received a copy of the GNU Lesser General Public
    17  * License along with this library; if not, write to the Free Software
    18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     17 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
     18 *
     19 * As a special exception to the GNU Lesser General Public License,
     20 * you may link, statically or dynamically, an application with a
     21 * publicly distributed version of the Library to produce an
     22 * executable file containing portions of the Library, and
     23 * distribute that executable file under terms of your choice,
     24 * without any of the additional requirements listed in clause 4 of
     25 * the GNU Lesser General Public License.
     26 *
     27 * By "a publicly distributed version of the Library", we mean
     28 * either the unmodified Library as distributed by Silicondust, or a
     29 * modified version of the Library that is distributed under the
     30 * conditions defined in the GNU Lesser General Public License.
    1931 */
    2032#ifdef __cplusplus
    2133extern "C" {
     
    3648 *
    3749 * When no longer needed, the socket should be destroyed by calling hdhomerun_control_destroy.
    3850 */
    39 extern struct hdhomerun_control_sock_t *hdhomerun_control_create(uint32_t device_id, uint32_t device_ip);
    40 extern void hdhomerun_control_destroy(struct hdhomerun_control_sock_t *cs);
     51extern LIBTYPE struct hdhomerun_control_sock_t *hdhomerun_control_create(uint32_t device_id, uint32_t device_ip);
     52extern LIBTYPE void hdhomerun_control_destroy(struct hdhomerun_control_sock_t *cs);
     53
     54/*
     55 * Get the actual device id or ip of the device.
     56 *
     57 * Returns 0 if the device id cannot be determined.
     58 */
     59extern LIBTYPE uint32_t hdhomerun_control_get_device_id(struct hdhomerun_control_sock_t *cs);
     60extern LIBTYPE uint32_t hdhomerun_control_get_device_ip(struct hdhomerun_control_sock_t *cs);
     61extern LIBTYPE uint32_t hdhomerun_control_get_device_id_requested(struct hdhomerun_control_sock_t *cs);
     62extern LIBTYPE uint32_t hdhomerun_control_get_device_ip_requested(struct hdhomerun_control_sock_t *cs);
     63
     64extern LIBTYPE void hdhomerun_control_set_device(struct hdhomerun_control_sock_t *cs, uint32_t device_id, uint32_t device_ip);
    4165
    4266/*
    4367 * Get the local machine IP address used when communicating with the device.
     
    4670 *
    4771 * Returns 32-bit IP address with native endianness, or 0 on error.
    4872 */
    49 extern uint32_t hdhomerun_control_get_local_addr(struct hdhomerun_control_sock_t *cs);
     73extern LIBTYPE uint32_t hdhomerun_control_get_local_addr(struct hdhomerun_control_sock_t *cs);
     74
     75/*
     76 * Low-level communication.
     77 */
     78extern LIBTYPE int hdhomerun_control_send_recv(struct hdhomerun_control_sock_t *cs, struct hdhomerun_pkt_t *tx_pkt, struct hdhomerun_pkt_t *rx_pkt, uint16_t type);
    5079
    5180/*
    5281 * Get/set a control variable on the device.
     
    6594 * Returns 0 if the operation was rejected (pvalue NULL, perror set).
    6695 * Returns -1 if a communication error occurs.
    6796 */
    68 extern int hdhomerun_control_get(struct hdhomerun_control_sock_t *cs, const char *name, char **pvalue, char **perror);
    69 extern int hdhomerun_control_set(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, char **pvalue, char **perror);
     97extern LIBTYPE int hdhomerun_control_get(struct hdhomerun_control_sock_t *cs, const char *name, char **pvalue, char **perror);
     98extern LIBTYPE int hdhomerun_control_set(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, char **pvalue, char **perror);
     99extern LIBTYPE int hdhomerun_control_set_with_lockkey(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, uint32_t lockkey, char **pvalue, char **perror);
    70100
    71101/*
    72102 * Upload new firmware to the device.
     
    77107 * Returns 0 if the upload was rejected.
    78108 * Returns -1 if an error occurs.
    79109 */
    80 extern int hdhomerun_control_upgrade(struct hdhomerun_control_sock_t *cs, FILE *upgrade_file);
     110extern LIBTYPE int hdhomerun_control_upgrade(struct hdhomerun_control_sock_t *cs, FILE *upgrade_file);
     111
     112/*
     113 * Debug logging.
     114 */
     115extern LIBTYPE void hdhomerun_control_set_debug(struct hdhomerun_control_sock_t *cs, struct hdhomerun_debug_t *dbg);
    81116
    82117#ifdef __cplusplus
    83118}
  • mythtv/libs/libmythtv/hdhomerun/hdhomerun_debug.c

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhomerun/hdhomerun_debug.c release.19703.0116b/mythtv/libs/libmythtv/hdhomerun/hdhomerun_debug.c
     
     1/*
     2 * hdhomerun_debug.c
     3 *
     4 * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
     5 *
     6 * This library is free software; you can redistribute it and/or
     7 * modify it under the terms of the GNU Lesser General Public
     8 * License as published by the Free Software Foundation; either
     9 * version 3 of the License, or (at your option) any later version.
     10 *
     11 * This library is distributed in the hope that it will be useful,
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14 * Lesser General Public License for more details.
     15 *
     16 * You should have received a copy of the GNU Lesser General Public
     17 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
     18 *
     19 * As a special exception to the GNU Lesser General Public License,
     20 * you may link, statically or dynamically, an application with a
     21 * publicly distributed version of the Library to produce an
     22 * executable file containing portions of the Library, and
     23 * distribute that executable file under terms of your choice,
     24 * without any of the additional requirements listed in clause 4 of
     25 * the GNU Lesser General Public License.
     26 *
     27 * By "a publicly distributed version of the Library", we mean
     28 * either the unmodified Library as distributed by Silicondust, or a
     29 * modified version of the Library that is distributed under the
     30 * conditions defined in the GNU Lesser General Public License.
     31 */
     32
     33/*
     34 * The debug logging includes optional support for connecting to the
     35 * Silicondust support server. This option should not be used without
     36 * being explicitly enabled by the user. Debug information should be
     37 * limited to information useful to diagnosing a problem.
     38 *  - Silicondust.
     39 */
     40
     41#include "hdhomerun.h"
     42
     43#if !defined(HDHOMERUN_DEBUG_HOST)
     44#define HDHOMERUN_DEBUG_HOST "debug.silicondust.com"
     45#endif
     46#if !defined(HDHOMERUN_DEBUG_PORT)
     47#define HDHOMERUN_DEBUG_PORT "8002"
     48#endif
     49
     50struct hdhomerun_debug_message_t
     51{
     52        struct hdhomerun_debug_message_t *next;
     53        struct hdhomerun_debug_message_t *prev;
     54        char buffer[2048];
     55};
     56
     57struct hdhomerun_debug_t
     58{
     59        pthread_t thread;
     60        volatile bool_t enabled;
     61        volatile bool_t terminate;
     62        char *prefix;
     63
     64        pthread_mutex_t print_lock;
     65        pthread_mutex_t queue_lock;
     66        pthread_mutex_t send_lock;
     67
     68        struct hdhomerun_debug_message_t *queue_head;
     69        struct hdhomerun_debug_message_t *queue_tail;
     70        uint32_t queue_depth;
     71
     72        uint64_t connect_delay;
     73
     74        char *file_name;
     75        FILE *file_fp;
     76        int sock;
     77};
     78
     79static THREAD_FUNC_PREFIX hdhomerun_debug_thread_execute(void *arg);
     80
     81struct hdhomerun_debug_t *hdhomerun_debug_create(void)
     82{
     83        struct hdhomerun_debug_t *dbg = (struct hdhomerun_debug_t *)calloc(1, sizeof(struct hdhomerun_debug_t));
     84        if (!dbg) {
     85                return NULL;
     86        }
     87
     88        dbg->sock = -1;
     89
     90        pthread_mutex_init(&dbg->print_lock, NULL);
     91        pthread_mutex_init(&dbg->queue_lock, NULL);
     92        pthread_mutex_init(&dbg->send_lock, NULL);
     93
     94        if (pthread_create(&dbg->thread, NULL, &hdhomerun_debug_thread_execute, dbg) != 0) {
     95                free(dbg);
     96                return NULL;
     97        }
     98
     99        return dbg;
     100}
     101
     102/* Send lock held by caller */
     103static void hdhomerun_debug_close_file(struct hdhomerun_debug_t *dbg)
     104{
     105        if (!dbg->file_fp) {
     106                return;
     107        }
     108
     109        fclose(dbg->file_fp);
     110        dbg->file_fp = NULL;
     111}
     112
     113/* Send lock held by caller */
     114static void hdhomerun_debug_close_sock(struct hdhomerun_debug_t *dbg)
     115{
     116        if (dbg->sock == -1) {
     117                return;
     118        }
     119
     120        close(dbg->sock);
     121        dbg->sock = -1;
     122}
     123
     124void hdhomerun_debug_destroy(struct hdhomerun_debug_t *dbg)
     125{
     126        dbg->terminate = TRUE;
     127        pthread_join(dbg->thread, NULL);
     128
     129        hdhomerun_debug_close_file(dbg);
     130        hdhomerun_debug_close_sock(dbg);
     131
     132        if (dbg->prefix) {
     133                free(dbg->prefix);
     134        }
     135
     136        free(dbg);
     137}
     138
     139void hdhomerun_debug_set_prefix(struct hdhomerun_debug_t *dbg, const char *prefix)
     140{
     141        pthread_mutex_lock(&dbg->print_lock);
     142
     143        if (dbg->prefix) {
     144                free(dbg->prefix);
     145                dbg->prefix = NULL;
     146        }
     147
     148        if (prefix) {
     149                dbg->prefix = strdup(prefix);
     150        }
     151
     152        pthread_mutex_unlock(&dbg->print_lock);
     153}
     154
     155void hdhomerun_debug_set_filename(struct hdhomerun_debug_t *dbg, const char *filename)
     156{
     157        pthread_mutex_lock(&dbg->send_lock);
     158
     159        if (!filename && !dbg->file_name) {
     160                pthread_mutex_unlock(&dbg->send_lock);
     161                return;
     162        }
     163        if (filename && dbg->file_name) {
     164                if (strcmp(filename, dbg->file_name) == 0) {
     165                        pthread_mutex_unlock(&dbg->send_lock);
     166                        return;
     167                }
     168        }
     169
     170        hdhomerun_debug_close_file(dbg);
     171        hdhomerun_debug_close_sock(dbg);
     172
     173        if (dbg->file_name) {
     174                free(dbg->file_name);
     175                dbg->file_name = NULL;
     176        }
     177        if (filename) {
     178                dbg->file_name = strdup(filename);
     179        }
     180
     181        pthread_mutex_unlock(&dbg->send_lock);
     182}
     183
     184void hdhomerun_debug_enable(struct hdhomerun_debug_t *dbg)
     185{
     186        pthread_mutex_lock(&dbg->send_lock);
     187
     188        dbg->enabled = TRUE;
     189
     190        pthread_mutex_unlock(&dbg->send_lock);
     191}
     192
     193void hdhomerun_debug_disable(struct hdhomerun_debug_t *dbg)
     194{
     195        pthread_mutex_lock(&dbg->send_lock);
     196
     197        dbg->enabled = FALSE;
     198        hdhomerun_debug_close_file(dbg);
     199        hdhomerun_debug_close_sock(dbg);
     200
     201        pthread_mutex_unlock(&dbg->send_lock);
     202}
     203
     204bool_t hdhomerun_debug_enabled(struct hdhomerun_debug_t *dbg)
     205{
     206        if (!dbg) {
     207                return FALSE;
     208        }
     209
     210        return dbg->enabled;
     211}
     212
     213void hdhomerun_debug_flush(struct hdhomerun_debug_t *dbg, uint64_t timeout)
     214{
     215        timeout = getcurrenttime() + timeout;
     216
     217        while (getcurrenttime() < timeout) {
     218                pthread_mutex_lock(&dbg->queue_lock);
     219                struct hdhomerun_debug_message_t *message = dbg->queue_tail;
     220                pthread_mutex_unlock(&dbg->queue_lock);
     221
     222                if (!message) {
     223                        return;
     224                }
     225
     226                usleep(10*1000);
     227        }
     228}
     229
     230void hdhomerun_debug_printf(struct hdhomerun_debug_t *dbg, const char *fmt, ...)
     231{
     232        va_list args;
     233        va_start(args, fmt);
     234        hdhomerun_debug_vprintf(dbg, fmt, args);
     235        va_end(args);
     236}
     237
     238void hdhomerun_debug_vprintf(struct hdhomerun_debug_t *dbg, const char *fmt, va_list args)
     239{
     240        if (!dbg) {
     241                return;
     242        }
     243        if (!dbg->enabled) {
     244                return;
     245        }
     246
     247        struct hdhomerun_debug_message_t *message = (struct hdhomerun_debug_message_t *)malloc(sizeof(struct hdhomerun_debug_message_t));
     248        if (!message) {
     249                return;
     250        }
     251
     252        char *ptr = message->buffer;
     253        char *end = message->buffer + sizeof(message->buffer) - 2;
     254        *end = 0;
     255
     256        /*
     257         * Timestamp.
     258         */
     259        time_t current_time = time(NULL);
     260        ptr += strftime(ptr, end - ptr, "%Y%m%d-%H:%M:%S ", localtime(&current_time));
     261        if (ptr > end) {
     262                ptr = end;
     263        }
     264
     265        /*
     266         * Debug prefix.
     267         */
     268        pthread_mutex_lock(&dbg->print_lock);
     269
     270        if (dbg->prefix) {
     271                int len = snprintf(ptr, end - ptr, "%s ", dbg->prefix);
     272                len = (len <= 0) ? 0 : len;
     273                ptr += len;
     274                if (ptr > end) {
     275                        ptr = end;
     276                }
     277        }
     278
     279        pthread_mutex_unlock(&dbg->print_lock);
     280
     281        /*
     282         * Message text.
     283         */
     284        int len = vsnprintf(ptr, end - ptr, fmt, args);
     285        len = (len < 0) ? 0 : len; /* len does not include null */
     286        ptr += len;
     287        if (ptr > end) {
     288                ptr = end;
     289        }
     290
     291        /*
     292         * Force newline.
     293         */
     294        if ((ptr[-1] != '\n') && (ptr + 1 <= end)) {
     295                *ptr++ = '\n';
     296        }
     297
     298        /*
     299         * Force NULL.
     300         */
     301        if (ptr + 1 > end) {
     302                ptr = end - 1;
     303        }
     304        *ptr++ = 0;
     305
     306        /*
     307         * Enqueue.
     308         */
     309        pthread_mutex_lock(&dbg->queue_lock);
     310
     311        message->prev = NULL;
     312        message->next = dbg->queue_head;
     313        dbg->queue_head = message;
     314        if (message->next) {
     315                message->next->prev = message;
     316        } else {
     317                dbg->queue_tail = message;
     318        }
     319        dbg->queue_depth++;
     320
     321        pthread_mutex_unlock(&dbg->queue_lock);
     322}
     323
     324/* Send lock held by caller */
     325static bool_t hdhomerun_debug_output_message_file(struct hdhomerun_debug_t *dbg, struct hdhomerun_debug_message_t *message)
     326{
     327        if (!dbg->file_fp) {
     328                uint64_t current_time = getcurrenttime();
     329                if (current_time < dbg->connect_delay) {
     330                        return FALSE;
     331                }
     332                dbg->connect_delay = current_time + 60*1000;
     333
     334                dbg->file_fp = fopen(dbg->file_name, "a");
     335                if (!dbg->file_fp) {
     336                        return FALSE;
     337                }
     338        }
     339
     340        fprintf(dbg->file_fp, "%s", message->buffer);
     341        fflush(dbg->file_fp);
     342
     343        return TRUE;
     344}
     345
     346/* Send lock held by caller */
     347#if defined(__CYGWIN__)
     348static bool_t hdhomerun_debug_output_message_sock(struct hdhomerun_debug_t *dbg, struct hdhomerun_debug_message_t *message)
     349{
     350        return TRUE;
     351}
     352#else
     353static bool_t hdhomerun_debug_output_message_sock(struct hdhomerun_debug_t *dbg, struct hdhomerun_debug_message_t *message)
     354{
     355        if (dbg->sock == -1) {
     356                uint64_t current_time = getcurrenttime();
     357                if (current_time < dbg->connect_delay) {
     358                        return FALSE;
     359                }
     360                dbg->connect_delay = current_time + 60*1000;
     361
     362                dbg->sock = (int)socket(AF_INET, SOCK_STREAM, 0);
     363                if (dbg->sock == -1) {
     364                        return FALSE;
     365                }
     366
     367                struct addrinfo hints;
     368                memset(&hints, 0, sizeof(hints));
     369                hints.ai_family = AF_INET;
     370                hints.ai_socktype = SOCK_STREAM;
     371                hints.ai_protocol = IPPROTO_TCP;
     372
     373                struct addrinfo *sock_info;
     374                if (getaddrinfo(HDHOMERUN_DEBUG_HOST, HDHOMERUN_DEBUG_PORT, &hints, &sock_info) != 0) {
     375                        hdhomerun_debug_close_sock(dbg);
     376                        return FALSE;
     377                }
     378                if (connect(dbg->sock, sock_info->ai_addr, (int)sock_info->ai_addrlen) != 0) {
     379                        freeaddrinfo(sock_info);
     380                        hdhomerun_debug_close_sock(dbg);
     381                        return FALSE;
     382                }
     383                freeaddrinfo(sock_info);
     384        }
     385
     386        size_t length = strlen(message->buffer);
     387        if (send(dbg->sock, (char *)message->buffer, (int)length, 0) != length) {
     388                hdhomerun_debug_close_sock(dbg);
     389                return FALSE;
     390        }
     391
     392        return TRUE;
     393}
     394#endif
     395
     396static bool_t hdhomerun_debug_output_message(struct hdhomerun_debug_t *dbg, struct hdhomerun_debug_message_t *message)
     397{
     398        pthread_mutex_lock(&dbg->send_lock);
     399
     400        if (!dbg->enabled) {
     401                pthread_mutex_unlock(&dbg->send_lock);
     402                return TRUE;
     403        }
     404
     405        bool_t ret;
     406        if (dbg->file_name) {
     407                ret = hdhomerun_debug_output_message_file(dbg, message);
     408        } else {
     409                ret = hdhomerun_debug_output_message_sock(dbg, message);
     410        }
     411
     412        pthread_mutex_unlock(&dbg->send_lock);
     413        return ret;
     414}
     415
     416static void hdhomerun_debug_pop_and_free_message(struct hdhomerun_debug_t *dbg)
     417{
     418        pthread_mutex_lock(&dbg->queue_lock);
     419
     420        struct hdhomerun_debug_message_t *message = dbg->queue_tail;
     421        dbg->queue_tail = message->prev;
     422        if (message->prev) {
     423                message->prev->next = NULL;
     424        } else {
     425                dbg->queue_head = NULL;
     426        }
     427        dbg->queue_depth--;
     428
     429        pthread_mutex_unlock(&dbg->queue_lock);
     430
     431        free(message);
     432}
     433
     434static THREAD_FUNC_PREFIX hdhomerun_debug_thread_execute(void *arg)
     435{
     436        struct hdhomerun_debug_t *dbg = (struct hdhomerun_debug_t *)arg;
     437
     438        while (!dbg->terminate) {
     439
     440                pthread_mutex_lock(&dbg->queue_lock);
     441                struct hdhomerun_debug_message_t *message = dbg->queue_tail;
     442                uint32_t queue_depth = dbg->queue_depth;
     443                pthread_mutex_unlock(&dbg->queue_lock);
     444
     445                if (!message) {
     446                        sleep(1);
     447                        continue;
     448                }
     449
     450                if (queue_depth > 256) {
     451                        hdhomerun_debug_pop_and_free_message(dbg);
     452                        continue;
     453                }
     454
     455                if (!hdhomerun_debug_output_message(dbg, message)) {
     456                        sleep(1);
     457                        continue;
     458                }
     459
     460                hdhomerun_debug_pop_and_free_message(dbg);
     461        }
     462
     463        return 0;
     464}
  • mythtv/libs/libmythtv/hdhomerun/hdhomerun_debug.h

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhomerun/hdhomerun_debug.h release.19703.0116b/mythtv/libs/libmythtv/hdhomerun/hdhomerun_debug.h
     
     1/*
     2 * hdhomerun_debug.h
     3 *
     4 * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
     5 *
     6 * This library is free software; you can redistribute it and/or
     7 * modify it under the terms of the GNU Lesser General Public
     8 * License as published by the Free Software Foundation; either
     9 * version 3 of the License, or (at your option) any later version.
     10 *
     11 * This library is distributed in the hope that it will be useful,
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14 * Lesser General Public License for more details.
     15 *
     16 * You should have received a copy of the GNU Lesser General Public
     17 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
     18 *
     19 * As a special exception to the GNU Lesser General Public License,
     20 * you may link, statically or dynamically, an application with a
     21 * publicly distributed version of the Library to produce an
     22 * executable file containing portions of the Library, and
     23 * distribute that executable file under terms of your choice,
     24 * without any of the additional requirements listed in clause 4 of
     25 * the GNU Lesser General Public License.
     26 *
     27 * By "a publicly distributed version of the Library", we mean
     28 * either the unmodified Library as distributed by Silicondust, or a
     29 * modified version of the Library that is distributed under the
     30 * conditions defined in the GNU Lesser General Public License.
     31 */
     32
     33/*
     34 * The debug logging includes optional support for connecting to the
     35 * Silicondust support server. This option should not be used without
     36 * being explicitly enabled by the user. Debug information should be
     37 * limited to information useful to diagnosing a problem.
     38 *  - Silicondust.
     39 */
     40
     41#ifdef __cplusplus
     42extern "C" {
     43#endif
     44
     45struct hdhomerun_debug_t;
     46
     47extern LIBTYPE struct hdhomerun_debug_t *hdhomerun_debug_create(void);
     48extern LIBTYPE void hdhomerun_debug_destroy(struct hdhomerun_debug_t *dbg);
     49
     50extern LIBTYPE void hdhomerun_debug_set_prefix(struct hdhomerun_debug_t *dbg, const char *prefix);
     51extern LIBTYPE void hdhomerun_debug_set_filename(struct hdhomerun_debug_t *dbg, const char *filename);
     52extern LIBTYPE void hdhomerun_debug_enable(struct hdhomerun_debug_t *dbg);
     53extern LIBTYPE void hdhomerun_debug_disable(struct hdhomerun_debug_t *dbg);
     54extern LIBTYPE bool_t hdhomerun_debug_enabled(struct hdhomerun_debug_t *dbg);
     55
     56extern LIBTYPE void hdhomerun_debug_flush(struct hdhomerun_debug_t *dbg, uint64_t timeout);
     57
     58extern LIBTYPE void hdhomerun_debug_printf(struct hdhomerun_debug_t *dbg, const char *fmt, ...);
     59extern LIBTYPE void hdhomerun_debug_vprintf(struct hdhomerun_debug_t *dbg, const char *fmt, va_list args);
     60
     61#ifdef __cplusplus
     62}
     63#endif
  • mythtv/libs/libmythtv/hdhomerun/hdhomerun_device.c

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhomerun/hdhomerun_device.c release.19703.0116b/mythtv/libs/libmythtv/hdhomerun/hdhomerun_device.c
     
    11/*
    2  * hdhomerun_record.c
     2 * hdhomerun_device.c
    33 *
    4  * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
     4 * Copyright © 2006-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
    55 *
    6  * This library is free software; you can redistribute it and/or
     6 * This library is free software; you can redistribute it and/or 
    77 * modify it under the terms of the GNU Lesser General Public
    88 * License as published by the Free Software Foundation; either
    9  * version 2.1 of the License, or (at your option) any later version.
     9 * version 3 of the License, or (at your option) any later version.
    1010 *
    1111 * This library is distributed in the hope that it will be useful,
    1212 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     
    1414 * Lesser General Public License for more details.
    1515 *
    1616 * You should have received a copy of the GNU Lesser General Public
    17  * License along with this library; if not, write to the Free Software
    18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     17 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
     18 *
     19 * As a special exception to the GNU Lesser General Public License,
     20 * you may link, statically or dynamically, an application with a
     21 * publicly distributed version of the Library to produce an
     22 * executable file containing portions of the Library, and
     23 * distribute that executable file under terms of your choice,
     24 * without any of the additional requirements listed in clause 4 of
     25 * the GNU Lesser General Public License.
     26 *
     27 * By "a publicly distributed version of the Library", we mean
     28 * either the unmodified Library as distributed by Silicondust, or a
     29 * modified version of the Library that is distributed under the
     30 * conditions defined in the GNU Lesser General Public License.
    1931 */
    2032
    21 #include "hdhomerun_os.h"
    22 #include "hdhomerun_pkt.h"
    23 #include "hdhomerun_control.h"
    24 #include "hdhomerun_video.h"
    25 #include "hdhomerun_device.h"
     33#include "hdhomerun.h"
    2634
    2735struct hdhomerun_device_t {
    2836        struct hdhomerun_control_sock_t *cs;
    2937        struct hdhomerun_video_sock_t *vs;
     38        struct hdhomerun_debug_t *dbg;
     39        struct hdhomerun_channelscan_t *scan;
    3040        unsigned int tuner;
    31         char result_buffer[1024];
     41        uint32_t lockkey;
     42        char name[32];
     43        char model[32];
    3244};
    3345
     46static void hdhomerun_device_set_update(struct hdhomerun_device_t *hd)
     47{
     48        /* Clear cached information. */
     49        *hd->model = 0;
     50
     51        /* New name. */
     52        sprintf(hd->name, "%08lX-%u", (unsigned long)hdhomerun_control_get_device_id(hd->cs), hd->tuner);
     53}
     54
     55void hdhomerun_device_set_device(struct hdhomerun_device_t *hd, uint32_t device_id, uint32_t device_ip)
     56{
     57        hdhomerun_control_set_device(hd->cs, device_id, device_ip);
     58        hdhomerun_device_set_update(hd);
     59}
     60
     61void hdhomerun_device_set_tuner(struct hdhomerun_device_t *hd, unsigned int tuner)
     62{
     63        hd->tuner = tuner;
     64        hdhomerun_device_set_update(hd);
     65}
     66
    3467struct hdhomerun_device_t *hdhomerun_device_create(uint32_t device_id, uint32_t device_ip, unsigned int tuner)
    3568{
    3669        struct hdhomerun_device_t *hd = (struct hdhomerun_device_t *)calloc(1, sizeof(struct hdhomerun_device_t));
     
    3871                return NULL;
    3972        }
    4073
    41         hd->tuner = tuner;
    42 
    43         hd->cs = hdhomerun_control_create(device_id, device_ip);
     74        hd->cs = hdhomerun_control_create(0, 0);
    4475        if (!hd->cs) {
    4576                free(hd);
    4677                return NULL;
    4778        }
    4879
     80        hdhomerun_device_set_device(hd, device_id, device_ip);
     81        hdhomerun_device_set_tuner(hd, tuner);
     82
    4983        return hd;
    5084}
    5185
    5286void hdhomerun_device_destroy(struct hdhomerun_device_t *hd)
    5387{
     88        if (hd->scan) {
     89                channelscan_destroy(hd->scan);
     90        }
     91
    5492        if (hd->vs) {
    5593                hdhomerun_video_destroy(hd->vs);
    5694        }
     
    6098        free(hd);
    6199}
    62100
    63 void hdhomerun_device_set_tuner(struct hdhomerun_device_t *hd, unsigned int tuner)
     101static bool_t is_hex_char(char c)
    64102{
    65         hd->tuner = tuner;
     103        if ((c >= '0') && (c <= '9')) {
     104                return TRUE;
     105        }
     106        if ((c >= 'A') && (c <= 'F')) {
     107                return TRUE;
     108        }
     109        if ((c >= 'a') && (c <= 'f')) {
     110                return TRUE;
     111        }
     112        return FALSE;
     113}
     114
     115static struct hdhomerun_device_t *hdhomerun_device_create_from_str_device_id(const char *device_str)
     116{
     117        int i;
     118        const char *ptr = device_str;
     119        for (i = 0; i < 8; i++) {
     120                if (!is_hex_char(*ptr++)) {
     121                        return NULL;
     122                }
     123        }
     124
     125        if (*ptr == 0) {
     126                unsigned long device_id;
     127                if (sscanf(device_str, "%lx", &device_id) != 1) {
     128                        return NULL;
     129                }
     130                return hdhomerun_device_create((uint32_t)device_id, 0, 0);
     131        }
     132
     133        if (*ptr == '-') {
     134                unsigned long device_id;
     135                unsigned int tuner;
     136                if (sscanf(device_str, "%lx-%u", &device_id, &tuner) != 2) {
     137                        return NULL;
     138                }
     139                return hdhomerun_device_create((uint32_t)device_id, 0, tuner);
     140        }
     141
     142        return NULL;
     143}
     144
     145static struct hdhomerun_device_t *hdhomerun_device_create_from_str_ip(const char *device_str)
     146{
     147        unsigned long a[4];
     148        if (sscanf(device_str, "%lu.%lu.%lu.%lu", &a[0], &a[1], &a[2], &a[3]) != 4) {
     149                return NULL;
     150        }
     151
     152        unsigned long device_ip = (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | (a[3] << 0);
     153        return hdhomerun_device_create(HDHOMERUN_DEVICE_ID_WILDCARD, (uint32_t)device_ip, 0);
     154}
     155
     156static struct hdhomerun_device_t *hdhomerun_device_create_from_str_dns(const char *device_str)
     157{
     158#if defined(__CYGWIN__)
     159        return NULL;
     160#else
     161        struct addrinfo hints;
     162        memset(&hints, 0, sizeof(hints));
     163        hints.ai_family = AF_INET;
     164        hints.ai_socktype = SOCK_STREAM;
     165        hints.ai_protocol = IPPROTO_TCP;
     166
     167        struct addrinfo *sock_info;
     168        if (getaddrinfo(device_str, "65001", &hints, &sock_info) != 0) {
     169                return NULL;
     170        }
     171
     172        struct sockaddr_in *sock_addr = (struct sockaddr_in *)sock_info->ai_addr;
     173        uint32_t device_ip = ntohl(sock_addr->sin_addr.s_addr);
     174        freeaddrinfo(sock_info);
     175
     176        if (device_ip == 0) {
     177                return NULL;
     178        }
     179
     180        return hdhomerun_device_create(HDHOMERUN_DEVICE_ID_WILDCARD, (uint32_t)device_ip, 0);
     181#endif
     182}
     183
     184struct hdhomerun_device_t *hdhomerun_device_create_from_str(const char *device_str)
     185{
     186        struct hdhomerun_device_t *device = hdhomerun_device_create_from_str_device_id(device_str);
     187        if (device) {
     188                return device;
     189        }
     190
     191        device = hdhomerun_device_create_from_str_ip(device_str);
     192        if (device) {
     193                return device;
     194        }
     195
     196        device = hdhomerun_device_create_from_str_dns(device_str);
     197        if (device) {
     198                return device;
     199        }
     200
     201        return NULL;
     202}
     203
     204int hdhomerun_device_set_tuner_from_str(struct hdhomerun_device_t *hd, const char *tuner_str)
     205{
     206        unsigned int tuner;
     207        if (sscanf(tuner_str, "%u", &tuner) == 1) {
     208                hdhomerun_device_set_tuner(hd, tuner);
     209                return 1;
     210        }
     211        if (sscanf(tuner_str, "/tuner%u", &tuner) == 1) {
     212                hdhomerun_device_set_tuner(hd, tuner);
     213                return 1;
     214        }
     215
     216        return -1;
     217}
     218
     219void hdhomerun_device_set_debug(struct hdhomerun_device_t *hd, struct hdhomerun_debug_t *dbg)
     220{
     221        hd->dbg = dbg;
     222        hdhomerun_control_set_debug(hd->cs, dbg);
     223
     224        if (hd->vs) {
     225                hdhomerun_video_set_debug(hd->vs, dbg);
     226        }
     227}
     228
     229uint32_t hdhomerun_device_get_device_id(struct hdhomerun_device_t *hd)
     230{
     231        return hdhomerun_control_get_device_id(hd->cs);
     232}
     233
     234uint32_t hdhomerun_device_get_device_ip(struct hdhomerun_device_t *hd)
     235{
     236        return hdhomerun_control_get_device_ip(hd->cs);
     237}
     238
     239uint32_t hdhomerun_device_get_device_id_requested(struct hdhomerun_device_t *hd)
     240{
     241        return hdhomerun_control_get_device_id_requested(hd->cs);
     242}
     243
     244uint32_t hdhomerun_device_get_device_ip_requested(struct hdhomerun_device_t *hd)
     245{
     246        return hdhomerun_control_get_device_ip_requested(hd->cs);
     247}
     248
     249unsigned int hdhomerun_device_get_tuner(struct hdhomerun_device_t *hd)
     250{
     251        return hd->tuner;
    66252}
    67253
    68254struct hdhomerun_control_sock_t *hdhomerun_device_get_control_sock(struct hdhomerun_device_t *hd)
     
    72258
    73259struct hdhomerun_video_sock_t *hdhomerun_device_get_video_sock(struct hdhomerun_device_t *hd)
    74260{
     261        if (hd->vs) {
     262                return hd->vs;
     263        }
     264
     265        hd->vs = hdhomerun_video_create(0, VIDEO_DATA_BUFFER_SIZE_1S * 2);
    75266        if (!hd->vs) {
    76                 hd->vs = hdhomerun_video_create(0, VIDEO_DATA_BUFFER_SIZE_1S);
     267                return NULL;
    77268        }
     269
     270        hdhomerun_video_set_debug(hd->vs, hd->dbg);
    78271        return hd->vs;
    79272}
    80273
     
    96289        return (uint32_t)value;
    97290}
    98291
    99 int hdhomerun_device_get_tuner_status(struct hdhomerun_device_t *hd, struct hdhomerun_tuner_status_t *status)
     292static bool_t hdhomerun_device_get_tuner_status_lock_is_bcast(struct hdhomerun_tuner_status_t *status)
     293{
     294        if (strcmp(status->lock_str, "8vsb") == 0) {
     295                return TRUE;
     296        }
     297        if (strncmp(status->lock_str, "t8", 2) == 0) {
     298                return TRUE;
     299        }
     300        if (strncmp(status->lock_str, "t7", 2) == 0) {
     301                return TRUE;
     302        }
     303        if (strncmp(status->lock_str, "t6", 2) == 0) {
     304                return TRUE;
     305        }
     306
     307        return FALSE;
     308}
     309
     310uint32_t hdhomerun_device_get_tuner_status_ss_color(struct hdhomerun_tuner_status_t *status)
     311{
     312        unsigned int ss_yellow_min;
     313        unsigned int ss_green_min;
     314
     315        if (!status->lock_supported) {
     316                return HDHOMERUN_STATUS_COLOR_NEUTRAL;
     317        }
     318
     319        if (hdhomerun_device_get_tuner_status_lock_is_bcast(status)) {
     320                ss_yellow_min = 50;     /* -30dBmV */
     321                ss_green_min = 75;      /* -15dBmV */
     322        } else {
     323                ss_yellow_min = 80;     /* -12dBmV */
     324                ss_green_min = 90;      /* -6dBmV */
     325        }
     326
     327        if (status->signal_strength >= ss_green_min) {
     328                return HDHOMERUN_STATUS_COLOR_GREEN;
     329        }
     330        if (status->signal_strength >= ss_yellow_min) {
     331                return HDHOMERUN_STATUS_COLOR_YELLOW;
     332        }
     333
     334        return HDHOMERUN_STATUS_COLOR_RED;
     335}
     336
     337uint32_t hdhomerun_device_get_tuner_status_snq_color(struct hdhomerun_tuner_status_t *status)
     338{
     339        if (status->signal_to_noise_quality >= 70) {
     340                return HDHOMERUN_STATUS_COLOR_GREEN;
     341        }
     342        if (status->signal_to_noise_quality >= 50) {
     343                return HDHOMERUN_STATUS_COLOR_YELLOW;
     344        }
     345
     346        return HDHOMERUN_STATUS_COLOR_RED;
     347}
     348
     349uint32_t hdhomerun_device_get_tuner_status_seq_color(struct hdhomerun_tuner_status_t *status)
     350{
     351        if (status->symbol_error_quality >= 100) {
     352                return HDHOMERUN_STATUS_COLOR_GREEN;
     353        }
     354
     355        return HDHOMERUN_STATUS_COLOR_RED;
     356}
     357
     358int hdhomerun_device_get_tuner_status(struct hdhomerun_device_t *hd, char **pstatus_str, struct hdhomerun_tuner_status_t *status)
    100359{
    101360        memset(status, 0, sizeof(struct hdhomerun_tuner_status_t));
    102361
     
    109368                return ret;
    110369        }
    111370
     371        if (pstatus_str) {
     372                *pstatus_str = status_str;
     373        }
     374
    112375        char *channel = strstr(status_str, "ch=");
    113376        if (channel) {
    114                 sscanf(channel + 3, "%s", status->channel);
     377                sscanf(channel + 3, "%31s", status->channel);
     378        }
     379
     380        char *lock = strstr(status_str, "lock=");
     381        if (lock) {
     382                sscanf(lock + 5, "%31s", status->lock_str);
    115383        }
    116384
    117385        status->signal_strength = (unsigned int)hdhomerun_device_get_status_parse(status_str, "ss=");
     
    120388        status->raw_bits_per_second = hdhomerun_device_get_status_parse(status_str, "bps=");
    121389        status->packets_per_second = hdhomerun_device_get_status_parse(status_str, "pps=");
    122390
     391        status->signal_present = status->signal_strength >= 45;
     392
     393        if (strcmp(status->lock_str, "none") != 0) {
     394                if (status->lock_str[0] == '(') {
     395                        status->lock_unsupported = TRUE;
     396                } else {
     397                        status->lock_supported = TRUE;
     398                }
     399        }
     400
    123401        return 1;
    124402}
    125403
     
    151429        return hdhomerun_control_get(hd->cs, name, pfilter, NULL);
    152430}
    153431
    154 int hdhomerun_device_get_tuner_program(struct hdhomerun_device_t *hd, uint16_t *pprogram_number)
     432int hdhomerun_device_get_tuner_program(struct hdhomerun_device_t *hd, char **pprogram)
    155433{
    156434        char name[32];
    157435        sprintf(name, "/tuner%u/program", hd->tuner);
     436        return hdhomerun_control_get(hd->cs, name, pprogram, NULL);
     437}
    158438
    159         char *program_str;
    160         int ret = hdhomerun_control_get(hd->cs, name, &program_str, NULL);
     439int hdhomerun_device_get_tuner_target(struct hdhomerun_device_t *hd, char **ptarget)
     440{
     441        char name[32];
     442        sprintf(name, "/tuner%u/target", hd->tuner);
     443        return hdhomerun_control_get(hd->cs, name, ptarget, NULL);
     444}
     445
     446int hdhomerun_device_get_tuner_plotsample(struct hdhomerun_device_t *hd, struct hdhomerun_plotsample_t **psamples, size_t *pcount)
     447{
     448        char name[32];
     449        sprintf(name, "/tuner%u/plotsample", hd->tuner);
     450
     451        char *result;
     452        int ret = hdhomerun_control_get(hd->cs, name, &result, NULL);
    161453        if (ret <= 0) {
    162454                return ret;
    163455        }
    164456
    165         *pprogram_number = (uint16_t)atol(program_str);
     457        struct hdhomerun_plotsample_t *samples = (struct hdhomerun_plotsample_t *)result;
     458        *psamples = samples;
     459        size_t count = 0;
     460
     461        while (1) {
     462                char *ptr = strchr(result, ' ');
     463                if (!ptr) {
     464                        break;
     465                }
     466                *ptr++ = 0;
     467
     468                unsigned long raw;
     469                if (sscanf(result, "%lx", &raw) != 1) {
     470                        break;
     471                }
     472
     473                uint16_t real = (raw >> 12) & 0x0FFF;
     474                if (real & 0x0800) {
     475                        real |= 0xF000;
     476                }
     477
     478                uint16_t imag = (raw >> 0) & 0x0FFF;
     479                if (imag & 0x0800) {
     480                        imag |= 0xF000;
     481                }
     482
     483                samples->real = (int16_t)real;
     484                samples->imag = (int16_t)imag;
     485                samples++;
     486                count++;
     487
     488                result = ptr;
     489        }
     490
     491        *pcount = count;
    166492        return 1;
    167493}
    168494
    169 int hdhomerun_device_get_tuner_target(struct hdhomerun_device_t *hd, char **ptarget)
     495int hdhomerun_device_get_tuner_lockkey_owner(struct hdhomerun_device_t *hd, char **powner)
    170496{
    171497        char name[32];
    172         sprintf(name, "/tuner%u/target", hd->tuner);
    173         return hdhomerun_control_get(hd->cs, name, ptarget, NULL);
     498        sprintf(name, "/tuner%u/lockkey", hd->tuner);
     499        return hdhomerun_control_get(hd->cs, name, powner, NULL);
    174500}
    175501
    176502int hdhomerun_device_get_ir_target(struct hdhomerun_device_t *hd, char **ptarget)
     
    178504        return hdhomerun_control_get(hd->cs, "/ir/target", ptarget, NULL);
    179505}
    180506
     507int hdhomerun_device_get_lineup_location(struct hdhomerun_device_t *hd, char **plocation)
     508{
     509        return hdhomerun_control_get(hd->cs, "/lineup/location", plocation, NULL);
     510}
     511
    181512int hdhomerun_device_get_version(struct hdhomerun_device_t *hd, char **pversion_str, uint32_t *pversion_num)
    182513{
    183514        char *version_str;
     
    206537{
    207538        char name[32];
    208539        sprintf(name, "/tuner%u/channel", hd->tuner);
    209         return hdhomerun_control_set(hd->cs, name, channel, NULL, NULL);
     540        return hdhomerun_control_set_with_lockkey(hd->cs, name, channel, hd->lockkey, NULL, NULL);
    210541}
    211542
    212543int hdhomerun_device_set_tuner_channelmap(struct hdhomerun_device_t *hd, const char *channelmap)
    213544{
    214545        char name[32];
    215546        sprintf(name, "/tuner%u/channelmap", hd->tuner);
    216         return hdhomerun_control_set(hd->cs, name, channelmap, NULL, NULL);
     547        return hdhomerun_control_set_with_lockkey(hd->cs, name, channelmap, hd->lockkey, NULL, NULL);
    217548}
    218549
    219550int hdhomerun_device_set_tuner_filter(struct hdhomerun_device_t *hd, const char *filter)
    220551{
    221552        char name[32];
    222553        sprintf(name, "/tuner%u/filter", hd->tuner);
    223         return hdhomerun_control_set(hd->cs, name, filter, NULL, NULL);
     554        return hdhomerun_control_set_with_lockkey(hd->cs, name, filter, hd->lockkey, NULL, NULL);
     555}
     556
     557static int hdhomerun_device_set_tuner_filter_by_array_append(char **pptr, char *end, uint16_t range_begin, uint16_t range_end)
     558{
     559        char *ptr = *pptr;
     560
     561        size_t available = end - ptr;
     562        size_t required;
     563
     564        if (range_begin == range_end) {
     565                required = snprintf(ptr, available, "0x%04x ", range_begin) + 1;
     566        } else {
     567                required = snprintf(ptr, available, "0x%04x-0x%04x ", range_begin, range_end) + 1;
     568        }
     569
     570        if (required > available) {
     571                return FALSE;
     572        }
     573
     574        *pptr = strchr(ptr, 0);
     575        return TRUE;
    224576}
    225577
    226 int hdhomerun_device_set_tuner_program(struct hdhomerun_device_t *hd, uint16_t program_number)
     578int hdhomerun_device_set_tuner_filter_by_array(struct hdhomerun_device_t *hd, unsigned char filter_array[0x2000])
    227579{
    228         char name[32], value[32];
     580        char filter[1024];
     581        char *ptr = filter;
     582        char *end = filter + sizeof(filter);
     583
     584        uint16_t range_begin = 0xFFFF;
     585        uint16_t range_end = 0xFFFF;
     586
     587        uint16_t i;
     588        for (i = 0; i <= 0x1FFF; i++) {
     589                if (!filter_array[i]) {
     590                        if (range_begin == 0xFFFF) {
     591                                continue;
     592                        }
     593                        if (!hdhomerun_device_set_tuner_filter_by_array_append(&ptr, end, range_begin, range_end)) {
     594                                return 0;
     595                        }
     596                        range_begin = 0xFFFF;
     597                        range_end = 0xFFFF;
     598                        continue;
     599                }
     600
     601                if (range_begin == 0xFFFF) {
     602                        range_begin = i;
     603                        range_end = i;
     604                        continue;
     605                }
     606
     607                range_end = i;
     608        }
     609
     610        if (range_begin != 0xFFFF) {
     611                if (!hdhomerun_device_set_tuner_filter_by_array_append(&ptr, end, range_begin, range_end)) {
     612                        return 0;
     613                }
     614        }
     615
     616        /* Remove trailing space. */
     617        if (ptr > filter) {
     618                ptr--;
     619        }
     620        *ptr = 0;
     621
     622        return hdhomerun_device_set_tuner_filter(hd, filter);
     623}
     624
     625int hdhomerun_device_set_tuner_program(struct hdhomerun_device_t *hd, const char *program)
     626{
     627        char name[32];
    229628        sprintf(name, "/tuner%u/program", hd->tuner);
    230         sprintf(value, "%u", program_number);
    231         return hdhomerun_control_set(hd->cs, name, value, NULL, NULL);
     629        return hdhomerun_control_set_with_lockkey(hd->cs, name, program, hd->lockkey, NULL, NULL);
    232630}
    233631
    234632int hdhomerun_device_set_tuner_target(struct hdhomerun_device_t *hd, char *target)
    235633{
    236634        char name[32];
    237635        sprintf(name, "/tuner%u/target", hd->tuner);
    238         return hdhomerun_control_set(hd->cs, name, target, NULL, NULL);
     636        return hdhomerun_control_set_with_lockkey(hd->cs, name, target, hd->lockkey, NULL, NULL);
    239637}
    240638
    241 static int hdhomerun_device_set_tuner_target_to_local(struct hdhomerun_device_t *hd)
     639int hdhomerun_device_set_tuner_target_to_local_protocol(struct hdhomerun_device_t *hd, const char *protocol)
    242640{
     641        /* Create video socket. */
     642        hdhomerun_device_get_video_sock(hd);
     643        if (!hd->vs) {
     644                return -1;
     645        }
     646
     647        /* Set target. */
    243648        char target[64];
    244649        uint32_t local_ip = hdhomerun_control_get_local_addr(hd->cs);
    245650        uint16_t local_port = hdhomerun_video_get_local_port(hd->vs);
    246         sprintf(target, "%u.%u.%u.%u:%u",
     651        sprintf(target, "%s://%u.%u.%u.%u:%u",
     652                protocol,
    247653                (unsigned int)(local_ip >> 24) & 0xFF, (unsigned int)(local_ip >> 16) & 0xFF,
    248654                (unsigned int)(local_ip >> 8) & 0xFF, (unsigned int)(local_ip >> 0) & 0xFF,
    249655                (unsigned int)local_port
     
    252658        return hdhomerun_device_set_tuner_target(hd, target);
    253659}
    254660
     661int hdhomerun_device_set_tuner_target_to_local(struct hdhomerun_device_t *hd)
     662{
     663        return hdhomerun_device_set_tuner_target_to_local_protocol(hd, HDHOMERUN_TARGET_PROTOCOL_UDP);
     664}
     665
    255666int hdhomerun_device_set_ir_target(struct hdhomerun_device_t *hd, const char *target)
    256667{
    257668        return hdhomerun_control_set(hd->cs, "/ir/target", target, NULL, NULL);
    258669}
    259670
     671int hdhomerun_device_set_lineup_location(struct hdhomerun_device_t *hd, const char *location)
     672{
     673        return hdhomerun_control_set(hd->cs, "/lineup/location", location, NULL, NULL);
     674}
     675
    260676int hdhomerun_device_get_var(struct hdhomerun_device_t *hd, const char *name, char **pvalue, char **perror)
    261677{
    262678        return hdhomerun_control_get(hd->cs, name, pvalue, perror);
     
    267683        return hdhomerun_control_set(hd->cs, name, value, pvalue, perror);
    268684}
    269685
    270 int hdhomerun_device_stream_start(struct hdhomerun_device_t *hd)
     686int hdhomerun_device_tuner_lockkey_request(struct hdhomerun_device_t *hd)
    271687{
    272         /* Create video socket. */
    273         hdhomerun_device_get_video_sock(hd);
    274         if (!hd->vs) {
    275                 return -1;
     688        uint32_t new_lockkey = (uint32_t)getcurrenttime();
     689
     690        char name[32];
     691        sprintf(name, "/tuner%u/lockkey", hd->tuner);
     692
     693        char new_lockkey_str[64];
     694        sprintf(new_lockkey_str, "%u", (unsigned int)new_lockkey);
     695
     696        int ret = hdhomerun_control_set_with_lockkey(hd->cs, name, new_lockkey_str, hd->lockkey, NULL, NULL);
     697        if (ret <= 0) {
     698                hd->lockkey = 0;
     699                return ret;
    276700        }
    277701
     702        hd->lockkey = new_lockkey;
     703        return ret;
     704}
     705
     706int hdhomerun_device_tuner_lockkey_release(struct hdhomerun_device_t *hd)
     707{
     708        if (hd->lockkey == 0) {
     709                return 1;
     710        }
     711
     712        char name[32];
     713        sprintf(name, "/tuner%u/lockkey", hd->tuner);
     714        int ret = hdhomerun_control_set_with_lockkey(hd->cs, name, "none", hd->lockkey, NULL, NULL);
     715
     716        hd->lockkey = 0;
     717        return ret;
     718}
     719
     720int hdhomerun_device_wait_for_lock(struct hdhomerun_device_t *hd, struct hdhomerun_tuner_status_t *status)
     721{
     722        /* Wait for up to 2.5 seconds for lock. */
     723        int i;
     724        for (i = 0; i < 10; i++) {
     725                usleep(250000);
     726
     727                /* Get status to check for lock. Quality numbers will not be valid yet. */
     728                int ret = hdhomerun_device_get_tuner_status(hd, NULL, status);
     729                if (ret <= 0) {
     730                        return ret;
     731                }
     732
     733                if (!status->signal_present) {
     734                        return 1;
     735                }
     736                if (status->lock_supported || status->lock_unsupported) {
     737                        return 1;
     738                }
     739        }
     740
     741        return 1;
     742}
     743
     744int hdhomerun_device_stream_start(struct hdhomerun_device_t *hd)
     745{
    278746        /* Set target. */
    279         int ret = hdhomerun_device_set_tuner_target_to_local(hd);
     747        int ret = hdhomerun_device_stream_refresh_target(hd);
    280748        if (ret <= 0) {
    281749                return ret;
    282750        }
     
    289757        return 1;
    290758}
    291759
     760int hdhomerun_device_stream_refresh_target(struct hdhomerun_device_t *hd)
     761{
     762        return hdhomerun_device_set_tuner_target_to_local_protocol(hd, HDHOMERUN_TARGET_PROTOCOL_RTP);
     763}
     764
    292765uint8_t *hdhomerun_device_stream_recv(struct hdhomerun_device_t *hd, size_t max_size, size_t *pactual_size)
    293766{
     767        if (!hd->vs) {
     768                return NULL;
     769        }
    294770        return hdhomerun_video_recv(hd->vs, max_size, pactual_size);
    295771}
    296772
     773void hdhomerun_device_stream_flush(struct hdhomerun_device_t *hd)
     774{
     775        hdhomerun_video_flush(hd->vs);
     776}
     777
    297778void hdhomerun_device_stream_stop(struct hdhomerun_device_t *hd)
    298779{
    299780        hdhomerun_device_set_tuner_target(hd, "none");
    300781}
    301782
     783int hdhomerun_device_channelscan_init(struct hdhomerun_device_t *hd, const char *channelmap)
     784{
     785        if (hd->scan) {
     786                channelscan_destroy(hd->scan);
     787        }
     788
     789        hd->scan = channelscan_create(hd, channelmap);
     790        if (!hd->scan) {
     791                return -1;
     792        }
     793
     794        return 1;
     795}
     796
     797int hdhomerun_device_channelscan_advance(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result)
     798{
     799        if (!hd->scan) {
     800                return 0;
     801        }
     802
     803        int ret = channelscan_advance(hd->scan, result);
     804        if (ret <= 0) {
     805                channelscan_destroy(hd->scan);
     806                hd->scan = NULL;
     807        }
     808
     809        return ret;
     810}
     811
     812int hdhomerun_device_channelscan_detect(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result)
     813{
     814        if (!hd->scan) {
     815                return 0;
     816        }
     817
     818        int ret = channelscan_detect(hd->scan, result);
     819        if (ret <= 0) {
     820                channelscan_destroy(hd->scan);
     821                hd->scan = NULL;
     822        }
     823
     824        return ret;
     825}
     826
     827uint8_t hdhomerun_device_channelscan_get_progress(struct hdhomerun_device_t *hd)
     828{
     829        if (!hd->scan) {
     830                return 0;
     831        }
     832
     833        return channelscan_get_progress(hd->scan);
     834}
     835
    302836int hdhomerun_device_firmware_version_check(struct hdhomerun_device_t *hd, uint32_t features)
    303837{
    304838        uint32_t version;
     
    306840                return -1;
    307841        }
    308842
    309         if (version >= 20061213) {
    310                 return 1;
     843        if (version < 20070219) {
     844                return 0;
     845        }
     846
     847        return 1;
     848}
     849
     850const char *hdhomerun_device_get_model_str(struct hdhomerun_device_t *hd)
     851{
     852        if (*hd->model) {
     853                return hd->model;
     854        }
     855
     856        char *model_str;
     857        int ret = hdhomerun_control_get(hd->cs, "/sys/model", &model_str, NULL);
     858        if (ret < 0) {
     859                return NULL;
     860        }
     861        if (ret == 0) {
     862                model_str = "hdhomerun_atsc";
    311863        }
    312864
    313         return 0;
     865        strncpy(hd->model, model_str, sizeof(hd->model) - 1);
     866        hd->model[sizeof(hd->model) - 1] = 0;
     867
     868        return hd->model;
    314869}
    315870
    316871int hdhomerun_device_upgrade(struct hdhomerun_device_t *hd, FILE *upgrade_file)
    317872{
     873        hdhomerun_control_set(hd->cs, "/tuner0/lockkey", "force", NULL, NULL);
    318874        hdhomerun_control_set(hd->cs, "/tuner0/channel", "none", NULL, NULL);
     875
     876        hdhomerun_control_set(hd->cs, "/tuner1/lockkey", "force", NULL, NULL);
    319877        hdhomerun_control_set(hd->cs, "/tuner1/channel", "none", NULL, NULL);
     878
    320879        return hdhomerun_control_upgrade(hd->cs, upgrade_file);
    321880}
     881
     882void hdhomerun_device_debug_print_video_stats(struct hdhomerun_device_t *hd)
     883{
     884        if (!hdhomerun_debug_enabled(hd->dbg)) {
     885                return;
     886        }
     887
     888        char name[32];
     889        sprintf(name, "/tuner%u/debug", hd->tuner);
     890
     891        char *debug_str;
     892        char *error_str;
     893        int ret = hdhomerun_control_get(hd->cs, name, &debug_str, &error_str);
     894        if (ret < 0) {
     895                hdhomerun_debug_printf(hd->dbg, "video dev: communication error getting debug stats\n");
     896                return;
     897        }
     898
     899        if (error_str) {
     900                hdhomerun_debug_printf(hd->dbg, "video dev: %s\n", error_str);
     901        } else {
     902                hdhomerun_debug_printf(hd->dbg, "video dev: %s\n", debug_str);
     903        }
     904
     905        if (hd->vs) {
     906                hdhomerun_video_debug_print_stats(hd->vs);
     907        }
     908}
     909
     910void hdhomerun_device_get_video_stats(struct hdhomerun_device_t *hd, struct hdhomerun_video_stats_t *stats)
     911{
     912        hdhomerun_video_get_stats(hd->vs, stats);
     913}
  • mythtv/libs/libmythtv/hdhomerun/hdhomerun_device.h

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhomerun/hdhomerun_device.h release.19703.0116b/mythtv/libs/libmythtv/hdhomerun/hdhomerun_device.h
     
    11/*
    22 * hdhomerun_device.h
    33 *
    4  * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
     4 * Copyright © 2006-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
    55 *
    6  * This library is free software; you can redistribute it and/or
     6 * This library is free software; you can redistribute it and/or 
    77 * modify it under the terms of the GNU Lesser General Public
    88 * License as published by the Free Software Foundation; either
    9  * version 2.1 of the License, or (at your option) any later version.
     9 * version 3 of the License, or (at your option) any later version.
    1010 *
    1111 * This library is distributed in the hope that it will be useful,
    1212 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     
    1414 * Lesser General Public License for more details.
    1515 *
    1616 * You should have received a copy of the GNU Lesser General Public
    17  * License along with this library; if not, write to the Free Software
    18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     17 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
     18 *
     19 * As a special exception to the GNU Lesser General Public License,
     20 * you may link, statically or dynamically, an application with a
     21 * publicly distributed version of the Library to produce an
     22 * executable file containing portions of the Library, and
     23 * distribute that executable file under terms of your choice,
     24 * without any of the additional requirements listed in clause 4 of
     25 * the GNU Lesser General Public License.
     26 *
     27 * By "a publicly distributed version of the Library", we mean
     28 * either the unmodified Library as distributed by Silicondust, or a
     29 * modified version of the Library that is distributed under the
     30 * conditions defined in the GNU Lesser General Public License.
    1931 */
    2032
    2133#ifdef __cplusplus
     
    2638#define HDHOMERUN_DEVICE_MAX_LOCK_TO_DATA_TIME 2000
    2739#define HDHOMERUN_DEVICE_MAX_TUNE_TO_DATA_TIME (HDHOMERUN_DEVICE_MAX_TUNE_TO_LOCK_TIME + HDHOMERUN_DEVICE_MAX_LOCK_TO_DATA_TIME)
    2840
    29 struct hdhomerun_device_t;
     41#define HDHOMERUN_STATUS_COLOR_NEUTRAL  0xFFFFFFFF
     42#define HDHOMERUN_STATUS_COLOR_RED              0xFFFF0000
     43#define HDHOMERUN_STATUS_COLOR_YELLOW   0xFFFFFF00
     44#define HDHOMERUN_STATUS_COLOR_GREEN    0xFF00C000
    3045
    31 struct hdhomerun_tuner_status_t {
    32         char channel[32];
    33         unsigned int signal_strength;
    34         unsigned int signal_to_noise_quality;
    35         unsigned int symbol_error_quality;
    36         uint32_t raw_bits_per_second;
    37         uint32_t packets_per_second;
    38 };
     46#define HDHOMERUN_TARGET_PROTOCOL_UDP "udp"
     47#define HDHOMERUN_TARGET_PROTOCOL_RTP "rtp"
    3948
    4049/*
    4150 * Create a device object.
     
    5766 * Returns a pointer to the newly created device object.
    5867 *
    5968 * When no longer needed, the socket should be destroyed by calling hdhomerun_device_destroy.
     69 *
     70 * The hdhomerun_device_create_from_str function creates a device object from the given device_str.
     71 * The device_str parameter can be any of the following forms:
     72 *     <device id>
     73 *     <device id>-<tuner index>
     74 *     <ip address>
     75 * If the tuner index is not included in the device_str then it is set to zero.
     76 * Use hdhomerun_device_set_tuner or hdhomerun_device_set_tuner_from_str to set the tuner.
     77 *
     78 * The hdhomerun_device_set_tuner_from_str function sets the tuner from the given tuner_str.
     79 * The tuner_str parameter can be any of the following forms:
     80 *     <tuner index>
     81 *     /tuner<tuner index>
     82 */
     83extern LIBTYPE struct hdhomerun_device_t *hdhomerun_device_create(uint32_t device_id, uint32_t device_ip, unsigned int tuner);
     84extern LIBTYPE struct hdhomerun_device_t *hdhomerun_device_create_from_str(const char *device_str);
     85extern LIBTYPE void hdhomerun_device_destroy(struct hdhomerun_device_t *hd);
     86
     87/*
     88 * Get the device id, ip, or tuner of the device instance.
    6089 */
    61 extern struct hdhomerun_device_t *hdhomerun_device_create(uint32_t device_id, uint32_t device_ip, unsigned int tuner);
    62 extern void hdhomerun_device_destroy(struct hdhomerun_device_t *hd);
    63 extern void hdhomerun_device_set_tuner(struct hdhomerun_device_t *hd, unsigned int tuner);
     90extern LIBTYPE uint32_t hdhomerun_device_get_device_id(struct hdhomerun_device_t *hd);
     91extern LIBTYPE uint32_t hdhomerun_device_get_device_ip(struct hdhomerun_device_t *hd);
     92extern LIBTYPE uint32_t hdhomerun_device_get_device_id_requested(struct hdhomerun_device_t *hd);
     93extern LIBTYPE uint32_t hdhomerun_device_get_device_ip_requested(struct hdhomerun_device_t *hd);
     94extern LIBTYPE unsigned int hdhomerun_device_get_tuner(struct hdhomerun_device_t *hd);
     95
     96extern LIBTYPE void hdhomerun_device_set_device(struct hdhomerun_device_t *hd, uint32_t device_id, uint32_t device_ip);
     97extern LIBTYPE void hdhomerun_device_set_tuner(struct hdhomerun_device_t *hd, unsigned int tuner);
     98extern LIBTYPE int hdhomerun_device_set_tuner_from_str(struct hdhomerun_device_t *hd, const char *tuner_str);
    6499
    65100/*
    66101 * Get the local machine IP address used when communicating with the device.
     
    69104 *
    70105 * Returns 32-bit IP address with native endianness, or 0 on error.
    71106 */
    72 extern uint32_t hdhomerun_device_get_local_machine_addr(struct hdhomerun_device_t *hd);
     107extern LIBTYPE uint32_t hdhomerun_device_get_local_machine_addr(struct hdhomerun_device_t *hd);
    73108
    74109/*
    75110 * Get operations.
     
    82117 * Returns 0 if the operation was rejected.
    83118 * Returns -1 if a communication error occurred.
    84119 */
    85 extern int hdhomerun_device_get_tuner_status(struct hdhomerun_device_t *hd, struct hdhomerun_tuner_status_t *status);
    86 extern int hdhomerun_device_get_tuner_streaminfo(struct hdhomerun_device_t *hd, char **pstreaminfo);
    87 extern int hdhomerun_device_get_tuner_channel(struct hdhomerun_device_t *hd, char **pchannel);
    88 extern int hdhomerun_device_get_tuner_channelmap(struct hdhomerun_device_t *hd, char **pchannelmap);
    89 extern int hdhomerun_device_get_tuner_filter(struct hdhomerun_device_t *hd, char **pfilter);
    90 extern int hdhomerun_device_get_tuner_program(struct hdhomerun_device_t *hd, uint16_t *pprogram_number);
    91 extern int hdhomerun_device_get_tuner_target(struct hdhomerun_device_t *hd, char **ptarget);
    92 extern int hdhomerun_device_get_ir_target(struct hdhomerun_device_t *hd, char **ptarget);
    93 extern int hdhomerun_device_get_version(struct hdhomerun_device_t *hd, char **pversion_str, uint32_t *pversion_num);
     120extern LIBTYPE int hdhomerun_device_get_tuner_status(struct hdhomerun_device_t *hd, char **pstatus_str, struct hdhomerun_tuner_status_t *status);
     121extern LIBTYPE int hdhomerun_device_get_tuner_streaminfo(struct hdhomerun_device_t *hd, char **pstreaminfo);
     122extern LIBTYPE int hdhomerun_device_get_tuner_channel(struct hdhomerun_device_t *hd, char **pchannel);
     123extern LIBTYPE int hdhomerun_device_get_tuner_channelmap(struct hdhomerun_device_t *hd, char **pchannelmap);
     124extern LIBTYPE int hdhomerun_device_get_tuner_filter(struct hdhomerun_device_t *hd, char **pfilter);
     125extern LIBTYPE int hdhomerun_device_get_tuner_program(struct hdhomerun_device_t *hd, char **pprogram);
     126extern LIBTYPE int hdhomerun_device_get_tuner_target(struct hdhomerun_device_t *hd, char **ptarget);
     127extern LIBTYPE int hdhomerun_device_get_tuner_plotsample(struct hdhomerun_device_t *hd, struct hdhomerun_plotsample_t **psamples, size_t *pcount);
     128extern LIBTYPE int hdhomerun_device_get_tuner_lockkey_owner(struct hdhomerun_device_t *hd, char **powner);
     129extern LIBTYPE int hdhomerun_device_get_ir_target(struct hdhomerun_device_t *hd, char **ptarget);
     130extern LIBTYPE int hdhomerun_device_get_lineup_location(struct hdhomerun_device_t *hd, char **plocation);
     131extern LIBTYPE int hdhomerun_device_get_version(struct hdhomerun_device_t *hd, char **pversion_str, uint32_t *pversion_num);
     132
     133extern LIBTYPE uint32_t hdhomerun_device_get_tuner_status_ss_color(struct hdhomerun_tuner_status_t *status);
     134extern LIBTYPE uint32_t hdhomerun_device_get_tuner_status_snq_color(struct hdhomerun_tuner_status_t *status);
     135extern LIBTYPE uint32_t hdhomerun_device_get_tuner_status_seq_color(struct hdhomerun_tuner_status_t *status);
     136
     137extern LIBTYPE const char *hdhomerun_device_get_model_str(struct hdhomerun_device_t *hd);
    94138
    95139/*
    96140 * Set operations.
     
    101145 * Returns 0 if the operation was rejected.
    102146 * Returns -1 if a communication error occurred.
    103147 */
    104 extern int hdhomerun_device_set_tuner_channel(struct hdhomerun_device_t *hd, const char *channel);
    105 extern int hdhomerun_device_set_tuner_channelmap(struct hdhomerun_device_t *hd, const char *channelmap);
    106 extern int hdhomerun_device_set_tuner_filter(struct hdhomerun_device_t *hd, const char *filter);
    107 extern int hdhomerun_device_set_tuner_program(struct hdhomerun_device_t *hd, uint16_t program_number);
    108 extern int hdhomerun_device_set_tuner_target(struct hdhomerun_device_t *hd, char *target);
    109 extern int hdhomerun_device_set_ir_target(struct hdhomerun_device_t *hd, const char *target);
     148extern LIBTYPE int hdhomerun_device_set_tuner_channel(struct hdhomerun_device_t *hd, const char *channel);
     149extern LIBTYPE int hdhomerun_device_set_tuner_channelmap(struct hdhomerun_device_t *hd, const char *channelmap);
     150extern LIBTYPE int hdhomerun_device_set_tuner_filter(struct hdhomerun_device_t *hd, const char *filter);
     151extern LIBTYPE int hdhomerun_device_set_tuner_filter_by_array(struct hdhomerun_device_t *hd, unsigned char filter_array[0x2000]);
     152extern LIBTYPE int hdhomerun_device_set_tuner_program(struct hdhomerun_device_t *hd, const char *program);
     153extern LIBTYPE int hdhomerun_device_set_tuner_target(struct hdhomerun_device_t *hd, char *target);
     154extern LIBTYPE int hdhomerun_device_set_tuner_target_to_local_protocol(struct hdhomerun_device_t *hd, const char *protocol);
     155extern LIBTYPE int hdhomerun_device_set_tuner_target_to_local(struct hdhomerun_device_t *hd);
     156extern LIBTYPE int hdhomerun_device_set_ir_target(struct hdhomerun_device_t *hd, const char *target);
     157extern LIBTYPE int hdhomerun_device_set_lineup_location(struct hdhomerun_device_t *hd, const char *location);
    110158
    111159/*
    112160 * Get/set a named control variable on the device.
     
    125173 * Returns 0 if the operation was rejected (pvalue NULL, perror set).
    126174 * Returns -1 if a communication error occurs.
    127175 */
    128 extern int hdhomerun_device_get_var(struct hdhomerun_device_t *hd, const char *name, char **pvalue, char **perror);
    129 extern int hdhomerun_device_set_var(struct hdhomerun_device_t *hd, const char *name, const char *value, char **pvalue, char **perror);
     176extern LIBTYPE int hdhomerun_device_get_var(struct hdhomerun_device_t *hd, const char *name, char **pvalue, char **perror);
     177extern LIBTYPE int hdhomerun_device_set_var(struct hdhomerun_device_t *hd, const char *name, const char *value, char **pvalue, char **perror);
     178
     179/*
     180 * Tuner locking.
     181 *
     182 * The hdhomerun_device_tuner_lockkey_request function is used to obtain a lock
     183 * or to verify that the hdhomerun_device object still holds the lock.
     184 * Returns 1 if the lock request was successful and the lock was obtained.
     185 * Returns 0 if the lock request was rejected.
     186 * Returns -1 if a communication error occurs.
     187 *
     188 * The hdhomerun_device_tuner_lockkey_release function is used to release a
     189 * previously held lock. If locking is used then this function must be called
     190 * before destroying the hdhomerun_device object.
     191 */
     192extern LIBTYPE int hdhomerun_device_tuner_lockkey_request(struct hdhomerun_device_t *hd);
     193extern LIBTYPE int hdhomerun_device_tuner_lockkey_release(struct hdhomerun_device_t *hd);
     194
     195/*
     196 * Wait for tuner lock after channel change.
     197 *
     198 * The hdhomerun_device_wait_for_lock function is used to detect/wait for a lock vs no lock indication
     199 * after a channel change.
     200 *
     201 * It will return quickly if a lock is aquired.
     202 * It will return quickly if there is no signal detected.
     203 * Worst case it will time out after 1.5 seconds - the case where there is signal but no lock.
     204 */
     205extern LIBTYPE int hdhomerun_device_wait_for_lock(struct hdhomerun_device_t *hd, struct hdhomerun_tuner_status_t *status);
    130206
    131207/*
    132208 * Stream a filtered program or the unfiltered stream.
     
    144220 *
    145221 * The hdhomerun_device_stream_stop function tells the device to stop streaming data.
    146222 */
    147 extern int hdhomerun_device_stream_start(struct hdhomerun_device_t *hd);
    148 extern uint8_t *hdhomerun_device_stream_recv(struct hdhomerun_device_t *hd, size_t max_size, size_t *pactual_size);
    149 extern void hdhomerun_device_stream_stop(struct hdhomerun_device_t *hd);
     223extern LIBTYPE int hdhomerun_device_stream_start(struct hdhomerun_device_t *hd);
     224extern LIBTYPE int hdhomerun_device_stream_refresh_target(struct hdhomerun_device_t *hd);
     225extern LIBTYPE uint8_t *hdhomerun_device_stream_recv(struct hdhomerun_device_t *hd, size_t max_size, size_t *pactual_size);
     226extern LIBTYPE void hdhomerun_device_stream_flush(struct hdhomerun_device_t *hd);
     227extern LIBTYPE void hdhomerun_device_stream_stop(struct hdhomerun_device_t *hd);
     228
     229/*
     230 * Channel scan API.
     231 */
     232extern LIBTYPE int hdhomerun_device_channelscan_init(struct hdhomerun_device_t *hd, const char *channelmap);
     233extern LIBTYPE int hdhomerun_device_channelscan_advance(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result);
     234extern LIBTYPE int hdhomerun_device_channelscan_detect(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result);
     235extern LIBTYPE uint8_t hdhomerun_device_channelscan_get_progress(struct hdhomerun_device_t *hd);
    150236
    151237/*
    152238 * Check that the device is running the recommended firmware.
     
    157243 * Returns 0 if th firmware does not meet the minimum requriements for all operations.
    158244 * Returns -1 if an error occurs.
    159245 */
    160 extern int hdhomerun_device_firmware_version_check(struct hdhomerun_device_t *hd, uint32_t features);
     246extern LIBTYPE int hdhomerun_device_firmware_version_check(struct hdhomerun_device_t *hd, uint32_t features);
    161247
    162248/*
    163249 * Upload new firmware to the device.
     
    168254 * Returns 0 if the upload was rejected.
    169255 * Returns -1 if an error occurs.
    170256 */
    171 extern int hdhomerun_device_upgrade(struct hdhomerun_device_t *hd, FILE *upgrade_file);
     257extern LIBTYPE int hdhomerun_device_upgrade(struct hdhomerun_device_t *hd, FILE *upgrade_file);
    172258
    173259/*
    174260 * Low level accessor functions.
    175261 */
    176 extern struct hdhomerun_control_sock_t *hdhomerun_device_get_control_sock(struct hdhomerun_device_t *hd);
    177 extern struct hdhomerun_video_sock_t *hdhomerun_device_get_video_sock(struct hdhomerun_device_t *hd);
     262extern LIBTYPE struct hdhomerun_control_sock_t *hdhomerun_device_get_control_sock(struct hdhomerun_device_t *hd);
     263extern LIBTYPE struct hdhomerun_video_sock_t *hdhomerun_device_get_video_sock(struct hdhomerun_device_t *hd);
     264
     265/*
     266 * Debug print internal stats.
     267 */
     268extern LIBTYPE void hdhomerun_device_set_debug(struct hdhomerun_device_t *hd, struct hdhomerun_debug_t *dbg);
     269extern LIBTYPE void hdhomerun_device_debug_print_video_stats(struct hdhomerun_device_t *hd);
     270
     271extern LIBTYPE void hdhomerun_device_get_video_stats(struct hdhomerun_device_t *hd, struct hdhomerun_video_stats_t *stats);
    178272
    179273#ifdef __cplusplus
    180274}
  • mythtv/libs/libmythtv/hdhomerun/hdhomerun_dhcp.c

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhomerun/hdhomerun_dhcp.c release.19703.0116b/mythtv/libs/libmythtv/hdhomerun/hdhomerun_dhcp.c
     
     1/*
     2 * hdhomerun_dhcp.c
     3 *
     4 * Copyright © 2006-2007 Silicondust Engineering Ltd. <www.silicondust.com>.
     5 *
     6 * This library is free software; you can redistribute it and/or
     7 * modify it under the terms of the GNU Lesser General Public
     8 * License as published by the Free Software Foundation; either
     9 * version 3 of the License, or (at your option) any later version.
     10 *
     11 * This library is distributed in the hope that it will be useful,
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14 * Lesser General Public License for more details.
     15 *
     16 * You should have received a copy of the GNU Lesser General Public
     17 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
     18 *
     19 * As a special exception to the GNU Lesser General Public License,
     20 * you may link, statically or dynamically, an application with a
     21 * publicly distributed version of the Library to produce an
     22 * executable file containing portions of the Library, and
     23 * distribute that executable file under terms of your choice,
     24 * without any of the additional requirements listed in clause 4 of
     25 * the GNU Lesser General Public License.
     26 *
     27 * By "a publicly distributed version of the Library", we mean
     28 * either the unmodified Library as distributed by Silicondust, or a
     29 * modified version of the Library that is distributed under the
     30 * conditions defined in the GNU Lesser General Public License.
     31 */
     32
     33#include "hdhomerun.h"
     34#include "hdhomerun_dhcp.h"
     35
     36struct dhcp_hdr_t {
     37        uint8_t bootp_message_type;
     38        uint8_t hardware_type;
     39        uint8_t hardware_address_length;
     40        uint8_t hops;
     41        uint32_t transaction_id;
     42        uint16_t seconds_elapsed;
     43        uint16_t bootp_flags;
     44        uint32_t client_ip;
     45        uint32_t your_ip;
     46        uint32_t next_server_ip;
     47        uint32_t relay_agent_ip;
     48        uint8_t client_mac[16];
     49        uint8_t server_host_name[64];
     50        uint8_t boot_file_name[128];
     51        uint32_t magic_cookie;
     52};
     53
     54struct hdhomerun_dhcp_t {
     55        int sock;
     56        uint32_t local_address;
     57        pthread_t thread;
     58        volatile bool_t terminate;
     59};
     60
     61static THREAD_FUNC_PREFIX hdhomerun_dhcp_thread_execute(void *arg);
     62
     63struct hdhomerun_dhcp_t *hdhomerun_dhcp_create(uint32_t bind_address)
     64{
     65        if (bind_address != 0) {
     66                if ((bind_address & 0xFFFF0000) != 0xA9FE0000) {
     67                        return NULL;
     68                }
     69        }
     70
     71        /* Create socket. */
     72        int sock = (int)socket(AF_INET, SOCK_DGRAM, 0);
     73        if (sock == -1) {
     74                return NULL;
     75        }
     76
     77        /* Set timeout. */
     78        setsocktimeout(sock, SOL_SOCKET, SO_RCVTIMEO, 1000);
     79
     80        /* Allow broadcast. */
     81        int sock_opt = 1;
     82        setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&sock_opt, sizeof(sock_opt));
     83
     84        /* Allow reuse. */
     85        sock_opt = 1;
     86        setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&sock_opt, sizeof(sock_opt));
     87
     88        /* Bind socket. */
     89        struct sockaddr_in sock_addr;
     90        memset(&sock_addr, 0, sizeof(sock_addr));
     91        sock_addr.sin_family = AF_INET;
     92        sock_addr.sin_addr.s_addr = htonl(bind_address);
     93        sock_addr.sin_port = htons(67);
     94        if (bind(sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) {
     95                close(sock);
     96                return NULL;
     97        }
     98
     99        /* Allocate object. */
     100        struct hdhomerun_dhcp_t *dhcp = (struct hdhomerun_dhcp_t *)calloc(1, sizeof(struct hdhomerun_dhcp_t));
     101        if (!dhcp) {
     102                close(sock);
     103                return NULL;
     104        }
     105
     106        dhcp->sock = sock;
     107
     108        if (bind_address != 0) {
     109                dhcp->local_address = bind_address;
     110        } else {
     111                dhcp->local_address = 0xA9FEFFFF;
     112        }
     113
     114        /* Spawn thread. */
     115        if (pthread_create(&dhcp->thread, NULL, &hdhomerun_dhcp_thread_execute, dhcp) != 0) {
     116                close(sock);
     117                free(dhcp);
     118                return NULL;
     119        }
     120
     121        /* Success. */
     122        return dhcp;
     123}
     124
     125void hdhomerun_dhcp_destroy(struct hdhomerun_dhcp_t *dhcp)
     126{
     127        dhcp->terminate = TRUE;
     128        pthread_join(dhcp->thread, NULL);
     129
     130        close(dhcp->sock);
     131        free(dhcp);
     132}
     133
     134static void hdhomerun_dhcp_send(struct hdhomerun_dhcp_t *dhcp, uint8_t message_type, struct hdhomerun_pkt_t *pkt)
     135{
     136        pkt->pos = pkt->start;
     137        struct dhcp_hdr_t *hdr = (struct dhcp_hdr_t *)pkt->pos;
     138        pkt->pos += sizeof(struct dhcp_hdr_t);
     139        pkt->end = pkt->pos;
     140
     141        uint32_t remote_addr = 0xA9FE0000;
     142        remote_addr |= (uint32_t)hdr->client_mac[4] << 8;
     143        remote_addr |= (uint32_t)hdr->client_mac[5] << 0;
     144        if ((remote_addr == 0xA9FE0000) || (remote_addr == 0xA9FEFFFF)) {
     145                remote_addr = 0xA9FE8080;
     146        }
     147
     148        hdr->bootp_message_type = 0x02;
     149        hdr->your_ip = htonl(remote_addr);
     150        hdr->next_server_ip = htonl(0x00000000);
     151
     152        hdhomerun_pkt_write_u8(pkt, 53);
     153        hdhomerun_pkt_write_u8(pkt, 1);
     154        hdhomerun_pkt_write_u8(pkt, message_type);
     155
     156        hdhomerun_pkt_write_u8(pkt, 54);
     157        hdhomerun_pkt_write_u8(pkt, 4);
     158        hdhomerun_pkt_write_u32(pkt, dhcp->local_address);
     159
     160        hdhomerun_pkt_write_u8(pkt, 51);
     161        hdhomerun_pkt_write_u8(pkt, 4);
     162        hdhomerun_pkt_write_u32(pkt, 7*24*60*60);
     163
     164        hdhomerun_pkt_write_u8(pkt, 1);
     165        hdhomerun_pkt_write_u8(pkt, 4);
     166        hdhomerun_pkt_write_u32(pkt, 0xFFFF0000);
     167
     168        hdhomerun_pkt_write_u8(pkt, 0xFF);
     169
     170        while (pkt->pos < pkt->start + 300) {
     171                hdhomerun_pkt_write_u8(pkt, 0x00);
     172        }
     173
     174        struct sockaddr_in sock_addr;
     175        memset(&sock_addr, 0, sizeof(sock_addr));
     176        sock_addr.sin_family = AF_INET;
     177        sock_addr.sin_addr.s_addr = htonl(0xFFFFFFFF);
     178        sock_addr.sin_port = htons(68);
     179
     180        sendto(dhcp->sock, (char *)pkt->start, (int)(pkt->end - pkt->start), 0, (struct sockaddr *)&sock_addr, sizeof(sock_addr));
     181}
     182
     183static void hdhomerun_dhcp_recv(struct hdhomerun_dhcp_t *dhcp, struct hdhomerun_pkt_t *pkt)
     184{
     185        pkt->pos = pkt->start;
     186        struct dhcp_hdr_t *hdr = (struct dhcp_hdr_t *)pkt->pos;
     187        pkt->pos += sizeof(struct dhcp_hdr_t);
     188        if (pkt->pos > pkt->end) {
     189                return;
     190        }
     191
     192        if (ntohl(hdr->magic_cookie) != 0x63825363) {
     193                return;
     194        }
     195
     196        static uint8_t vendor[3] = {0x00, 0x18, 0xDD};
     197        if (memcmp(hdr->client_mac, vendor, 3) != 0) {
     198                return;
     199        }
     200
     201        if (pkt->pos + 3 > pkt->end) {
     202                return;
     203        }
     204        if (hdhomerun_pkt_read_u8(pkt) != 53) {
     205                return;
     206        }
     207        if (hdhomerun_pkt_read_u8(pkt) != 1) {
     208                return;
     209        }
     210        uint8_t message_type_val = hdhomerun_pkt_read_u8(pkt);
     211
     212        switch (message_type_val) {
     213        case 0x01:
     214                hdhomerun_dhcp_send(dhcp, 0x02, pkt);
     215                break;
     216        case 0x03:
     217                hdhomerun_dhcp_send(dhcp, 0x05, pkt);
     218                break;
     219        default:
     220                return;
     221        }
     222}
     223
     224static THREAD_FUNC_PREFIX hdhomerun_dhcp_thread_execute(void *arg)
     225{
     226        struct hdhomerun_dhcp_t *dhcp = (struct hdhomerun_dhcp_t *)arg;
     227        struct hdhomerun_pkt_t pkt_inst;
     228
     229        while (1) {
     230                if (dhcp->terminate) {
     231                        return NULL;
     232                }
     233
     234                struct hdhomerun_pkt_t *pkt = &pkt_inst;
     235                hdhomerun_pkt_reset(pkt);
     236
     237                int rx_length = recv(dhcp->sock, (char *)pkt->end, (int)(pkt->limit - pkt->end), 0);
     238                if (rx_length <= 0) {
     239                        if (!sock_getlasterror_socktimeout) {
     240                                sleep(1);
     241                        }
     242                        continue;
     243                }
     244                pkt->end += rx_length;
     245
     246                hdhomerun_dhcp_recv(dhcp, pkt);
     247        }
     248}
  • mythtv/libs/libmythtv/hdhomerun/hdhomerun_dhcp.h

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhomerun/hdhomerun_dhcp.h release.19703.0116b/mythtv/libs/libmythtv/hdhomerun/hdhomerun_dhcp.h
     
     1/*
     2 * hdhomerun_dhcp.h
     3 *
     4 * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
     5 *
     6 * This library is free software; you can redistribute it and/or
     7 * modify it under the terms of the GNU Lesser General Public
     8 * License as published by the Free Software Foundation; either
     9 * version 3 of the License, or (at your option) any later version.
     10 *
     11 * This library is distributed in the hope that it will be useful,
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14 * Lesser General Public License for more details.
     15 *
     16 * You should have received a copy of the GNU Lesser General Public
     17 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
     18 *
     19 * As a special exception to the GNU Lesser General Public License,
     20 * you may link, statically or dynamically, an application with a
     21 * publicly distributed version of the Library to produce an
     22 * executable file containing portions of the Library, and
     23 * distribute that executable file under terms of your choice,
     24 * without any of the additional requirements listed in clause 4 of
     25 * the GNU Lesser General Public License.
     26 *
     27 * By "a publicly distributed version of the Library", we mean
     28 * either the unmodified Library as distributed by Silicondust, or a
     29 * modified version of the Library that is distributed under the
     30 * conditions defined in the GNU Lesser General Public License.
     31 */
     32
     33#ifdef __cplusplus
     34extern "C" {
     35#endif
     36
     37struct hdhomerun_dhcp_t;
     38
     39extern LIBTYPE struct hdhomerun_dhcp_t *hdhomerun_dhcp_create(uint32_t bind_address);
     40extern LIBTYPE void hdhomerun_dhcp_destroy(struct hdhomerun_dhcp_t *dhcp);
     41
     42#ifdef __cplusplus
     43}
     44#endif
  • mythtv/libs/libmythtv/hdhomerun/hdhomerun_discover.c

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhomerun/hdhomerun_discover.c release.19703.0116b/mythtv/libs/libmythtv/hdhomerun/hdhomerun_discover.c
     
    11/*
    22 * hdhomerun_discover.c
    33 *
    4  * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
     4 * Copyright © 2006-2007 Silicondust Engineering Ltd. <www.silicondust.com>.
    55 *
    6  * This library is free software; you can redistribute it and/or
     6 * This library is free software; you can redistribute it and/or 
    77 * modify it under the terms of the GNU Lesser General Public
    88 * License as published by the Free Software Foundation; either
    9  * version 2.1 of the License, or (at your option) any later version.
     9 * version 3 of the License, or (at your option) any later version.
    1010 *
    1111 * This library is distributed in the hope that it will be useful,
    1212 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     
    1414 * Lesser General Public License for more details.
    1515 *
    1616 * You should have received a copy of the GNU Lesser General Public
    17  * License along with this library; if not, write to the Free Software
    18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     17 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
     18 *
     19 * As a special exception to the GNU Lesser General Public License,
     20 * you may link, statically or dynamically, an application with a
     21 * publicly distributed version of the Library to produce an
     22 * executable file containing portions of the Library, and
     23 * distribute that executable file under terms of your choice,
     24 * without any of the additional requirements listed in clause 4 of
     25 * the GNU Lesser General Public License.
     26 *
     27 * By "a publicly distributed version of the Library", we mean
     28 * either the unmodified Library as distributed by Silicondust, or a
     29 * modified version of the Library that is distributed under the
     30 * conditions defined in the GNU Lesser General Public License.
    1931 */
    2032
    21 #include "hdhomerun_os.h"
    22 #include "hdhomerun_pkt.h"
    23 #include "hdhomerun_discover.h"
     33#include "hdhomerun.h"
    2434
    2535#if defined(__CYGWIN__) || defined(__WINDOWS__)
    2636#include <windows.h>
    27 #include <iptypes.h>
    2837#include <iphlpapi.h>
     38#define USE_IPHLPAPI 1
     39#else
     40#include <net/if.h>
     41#include <sys/ioctl.h>
     42#ifndef _SIZEOF_ADDR_IFREQ
     43#define _SIZEOF_ADDR_IFREQ(x) sizeof(x)
     44#endif
    2945#endif
    3046
    31 // for OSX
    32 #include <unistd.h>    // execl, pipe, sysconf
    33 #include <sys/types.h> // waitpid
    34 #include <sys/wait.h>  // waitpid
     47#define HDHOMERUN_DISOCVER_MAX_SOCK_COUNT 16
    3548
    3649struct hdhomerun_discover_sock_t {
    3750        int sock;
     51        uint32_t local_ip;
     52        uint32_t subnet_mask;
    3853};
    3954
    40 static struct hdhomerun_discover_sock_t *hdhomerun_discover_create(void)
     55struct hdhomerun_discover_t {
     56        struct hdhomerun_discover_sock_t socks[HDHOMERUN_DISOCVER_MAX_SOCK_COUNT];
     57        unsigned int sock_count;
     58        struct hdhomerun_pkt_t tx_pkt;
     59        struct hdhomerun_pkt_t rx_pkt;
     60};
     61
     62static bool_t hdhomerun_discover_sock_create(struct hdhomerun_discover_t *ds, uint32_t local_ip, uint32_t subnet_mask)
    4163{
    42         struct hdhomerun_discover_sock_t *ds = (struct hdhomerun_discover_sock_t *)malloc(sizeof(struct hdhomerun_discover_sock_t));
    43         if (!ds) {
    44                 return NULL;
     64        if (ds->sock_count >= HDHOMERUN_DISOCVER_MAX_SOCK_COUNT) {
     65                return FALSE;
    4566        }
    46        
     67
    4768        /* Create socket. */
    48         ds->sock = (int)socket(AF_INET, SOCK_DGRAM, 0);
    49         if (ds->sock == -1) {
    50                 free(ds);
    51                 return NULL;
     69        int sock = (int)socket(AF_INET, SOCK_DGRAM, 0);
     70        if (sock == -1) {
     71                return FALSE;
    5272        }
    5373
    5474        /* Set timeouts. */
    55         setsocktimeout(ds->sock, SOL_SOCKET, SO_SNDTIMEO, 1000);
    56         setsocktimeout(ds->sock, SOL_SOCKET, SO_RCVTIMEO, 1000);
     75        setsocktimeout(sock, SOL_SOCKET, SO_SNDTIMEO, 1000);
     76        setsocktimeout(sock, SOL_SOCKET, SO_RCVTIMEO, 1000);
    5777
    5878        /* Allow broadcast. */
    5979        int sock_opt = 1;
    60         setsockopt(ds->sock, SOL_SOCKET, SO_BROADCAST, (char *)&sock_opt, sizeof(sock_opt));
     80        setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&sock_opt, sizeof(sock_opt));
    6181
    6282        /* Bind socket. */
    6383        struct sockaddr_in sock_addr;
    6484        memset(&sock_addr, 0, sizeof(sock_addr));
    6585        sock_addr.sin_family = AF_INET;
    66         sock_addr.sin_addr.s_addr = htonl(INADDR_ANY);
     86        sock_addr.sin_addr.s_addr = htonl(local_ip);
    6787        sock_addr.sin_port = htons(0);
    68         if (bind(ds->sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) {
    69                 close(ds->sock);
    70                 free(ds);
    71                 return NULL;
     88        if (bind(sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) {
     89                close(sock);
     90                return FALSE;
    7291        }
    7392
    74         /* Success. */
    75         return ds;
    76 }
     93        /* Write sock entry. */
     94        struct hdhomerun_discover_sock_t *dss = &ds->socks[ds->sock_count++];
     95        dss->sock = sock;
     96        dss->local_ip = local_ip;
     97        dss->subnet_mask = subnet_mask;
    7798
    78 static void hdhomerun_discover_destroy(struct hdhomerun_discover_sock_t *ds)
    79 {
    80         close(ds->sock);
    81         free(ds);
     99        return TRUE;
    82100}
    83101
    84 static int hdhomerun_discover_send_packet(struct hdhomerun_discover_sock_t *ds, uint32_t ip_addr, uint32_t device_type, uint32_t device_id)
    85 {
    86         uint8_t buffer[1024];
    87         uint8_t *ptr = buffer;
    88         hdhomerun_write_discover_request(&ptr, device_type, device_id);
    89 
    90         struct sockaddr_in sock_addr;
    91         memset(&sock_addr, 0, sizeof(sock_addr));
    92         sock_addr.sin_family = AF_INET;
    93         sock_addr.sin_addr.s_addr = htonl(ip_addr);
    94         sock_addr.sin_port = htons(HDHOMERUN_DISCOVER_UDP_PORT);
    95 
    96         int length = (int)(ptr - buffer);
    97         if (sendto(ds->sock, (char *)buffer, (int)length, 0, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != length) {
    98                 return -1;
    99         }
    100 
    101         return 0;
    102 }
    103 
    104 #if defined(__APPLE__)
    105 static int hdhomerun_discover_send_internal(struct hdhomerun_discover_sock_t *ds, unsigned long device_type, unsigned long device_id)
    106 {
    107     /* printf("Looking for 0x%lx with id 0x%lx\n", device_type, device_id); */
    108     int fds[2];
    109     if (pipe(fds) < 0)
    110     {
    111         printf("Pipe Failed\n");
    112         return -1;
    113     }
    114 
    115     pid_t child = fork();
    116     if (child < 0)
    117     {
    118         printf("Fork Failed\n");
    119         return -1;
    120     }
    121     else if (child == 0)
    122     {
    123         /* Child */
    124         int i = 0;
    125 
    126         /* Attach stdout to pipe */
    127         close(1);
    128         dup2(fds[1], 1);
    129 
    130         /* Close all open file descriptors except stdout/stderr */
    131         for (i = sysconf(_SC_OPEN_MAX) - 1; i > 2; i--)
    132             close(i);
    133 
    134         /* Run command */
    135         execl("/bin/sh", "sh", "-c", "ifconfig", NULL);
    136 
    137         /* Failed to exec */
    138         _exit(1); /* this exit is ok */
    139     }
    140     else
    141     {
    142         /* Parent */
    143         int send_count = 0;
    144         int status;
    145         FILE *fp;
    146         char line[1024];
    147         char adaptor[1024];
    148 
    149         close(fds[1]);
    150 
    151         if (waitpid(child, &status, 0) < 0)
    152             return -1;
    153 
    154         if (WEXITSTATUS(status))
    155             return -1;
    156 
    157         fp = fdopen(fds[0], "r");
    158         while (1)
    159         {
    160             char *ptr = NULL;
    161             int netmask, broadcast;
    162             int a,b,c,d;
    163 
    164             if (!fgets(line, sizeof(line) - 1, fp))
    165             {
    166                 break;
    167             }
    168 
    169             line[1023] = 0;
    170 
    171             /* find ": flags" */
    172             ptr = strnstr(line, ": flags", 1024 - 1);
    173             if (ptr >= line)
    174             {
    175                 /* grab adaptor before that */
    176                 strncpy(adaptor, line, ptr-line);
    177                 adaptor[ptr-line] = 0;
    178             }
    179 
    180             /* find "netmask " */
    181             ptr = strnstr(line, "netmask ", 1024 - 1);
    182             if (ptr <= line)
    183                 continue;
    184             ptr += strlen("netmask ");
    185             sscanf(ptr, "%x", &netmask);
    186 
    187             /* find "broadcast " */
    188             ptr = strnstr(ptr, "broadcast ", 1024 - 1);
    189             if (ptr <= line)
    190                 continue;
    191             ptr += strlen("broadcast ");
    192             sscanf(ptr, "%i.%i.%i.%i", &a, &b, &c, &d);
    193             broadcast = a<<24 | b<<16 | c<<8 | d;
    194             /*
    195             printf("Adaptor: '%s' 0x%08x %i.%i.%i.%i\n",
    196                    adaptor, broadcast, a,b,c,d);
    197             */
    198 
    199             /* send discover packet this adaptor */
    200             if (hdhomerun_discover_send_packet(
    201                     ds, broadcast, device_type, device_id) >= 0)
    202             {
    203                 send_count++;
    204             }
    205         }
    206 
    207         fclose(fp); /* this closes fds[0] as well */
    208 
    209         /* printf("send_count: %i\n\n", send_count); */
    210         return (send_count == 0) ? -1 : 0;
    211     }
    212 }
    213 
    214 #elif defined(__CYGWIN__) || defined(__WINDOWS__)
    215 
    216 static int hdhomerun_discover_send_internal(struct hdhomerun_discover_sock_t *ds, uint32_t device_type, uint32_t device_id)
     102#if defined(USE_IPHLPAPI)
     103static void hdhomerun_discover_sock_detect(struct hdhomerun_discover_t *ds)
    217104{
    218105        PIP_ADAPTER_INFO pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO));
    219106        ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
     
    222109        if (Ret != NO_ERROR) {
    223110                free(pAdapterInfo);
    224111                if (Ret != ERROR_BUFFER_OVERFLOW) {
    225                         return -1;
     112                        return;
    226113                }
    227114                pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen);
    228115                Ret = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen);
    229116                if (Ret != NO_ERROR) {
    230117                        free(pAdapterInfo);
    231                         return -1;
     118                        return;
    232119                }
    233120        }
    234121
    235         unsigned int send_count = 0;
    236122        PIP_ADAPTER_INFO pAdapter = pAdapterInfo;
    237123        while (pAdapter) {
    238124                IP_ADDR_STRING *pIPAddr = &pAdapter->IpAddressList;
    239125                while (pIPAddr) {
    240                         uint32_t addr = ntohl(inet_addr(pIPAddr->IpAddress.String));
     126                        uint32_t local_ip = ntohl(inet_addr(pIPAddr->IpAddress.String));
    241127                        uint32_t mask = ntohl(inet_addr(pIPAddr->IpMask.String));
    242                        
    243                         uint32_t broadcast = addr | ~mask;
    244                         if ((broadcast == 0x00000000) || (broadcast == 0xFFFFFFFF)) {
    245                                 pIPAddr = pIPAddr->Next;
    246                                 continue;
    247                         }
    248128
    249                         if (hdhomerun_discover_send_packet(ds, broadcast, device_type, device_id) < 0) {
     129                        if (local_ip == 0) {
    250130                                pIPAddr = pIPAddr->Next;
    251131                                continue;
    252132                        }
    253133
    254                         send_count++;
    255 
     134                        hdhomerun_discover_sock_create(ds, local_ip, mask);
    256135                        pIPAddr = pIPAddr->Next;
    257136                }
    258137
     
    260139        }
    261140
    262141        free(pAdapterInfo);
    263 
    264         if (send_count == 0) {
    265                 return -1;
    266         }
    267         return 0;
    268142}
    269143
    270 #elif defined(__linux__)
     144#else
    271145
    272 static int hdhomerun_discover_send_internal(struct hdhomerun_discover_sock_t *ds, uint32_t device_type, uint32_t device_id)
     146static void hdhomerun_discover_sock_detect(struct hdhomerun_discover_t *ds)
    273147{
    274         FILE *fp = fopen("/proc/net/route", "r");
    275         if (!fp) {
    276                 return -1;
     148        int fd = socket(AF_INET, SOCK_DGRAM, 0);
     149        if (fd == -1) {
     150                return;
    277151        }
    278152
    279         unsigned int send_count = 0;
    280         while (1) {
    281                 char line[256];
    282                 if (!fgets(line, sizeof(line), fp)) {
    283                         break;
    284                 }
    285                 line[255] = 0;
     153        struct ifconf ifc;
     154        uint8_t buf[8192];
     155        ifc.ifc_len = sizeof(buf);
     156        ifc.ifc_buf = (char *)buf;
     157
     158        memset(buf, 0, sizeof(buf));
    286159
    287                 uint32_t dest;
    288                 uint32_t mask;
    289                 if (sscanf(line, "%*s %x %*x %*x %*d %*d %*d %x", &dest, &mask) != 2) {
     160        if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) {
     161                close(fd);
     162                return;
     163        }
     164
     165        uint8_t *ptr = (uint8_t *)ifc.ifc_req;
     166        uint8_t *end = (uint8_t *)&ifc.ifc_buf[ifc.ifc_len];
     167
     168        while (ptr <= end) {
     169                struct ifreq *ifr = (struct ifreq *)ptr;
     170                ptr += _SIZEOF_ADDR_IFREQ(*ifr);
     171
     172                if (ioctl(fd, SIOCGIFADDR, ifr) != 0) {
    290173                        continue;
    291174                }
    292                 dest = ntohl(dest);
    293                 mask = ntohl(mask);
    294                
    295                 uint32_t broadcast = dest | ~mask;
    296 
    297                 if ((broadcast == 0x00000000) || (broadcast == 0xFFFFFFFF)) {
     175                struct sockaddr_in *addr_in = (struct sockaddr_in *)&(ifr->ifr_addr);
     176                uint32_t local_ip = ntohl(addr_in->sin_addr.s_addr);
     177                if (local_ip == 0) {
    298178                        continue;
    299179                }
    300180
    301                 if (hdhomerun_discover_send_packet(ds, broadcast, device_type, device_id) < 0) {
     181                if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) {
    302182                        continue;
    303183                }
     184                struct sockaddr_in *mask_in = (struct sockaddr_in *)&(ifr->ifr_addr);
     185                uint32_t mask = ntohl(mask_in->sin_addr.s_addr);
    304186
    305                 send_count++;
     187                hdhomerun_discover_sock_create(ds, local_ip, mask);
    306188        }
     189}
     190#endif
    307191
    308         fclose(fp);
    309         if (send_count == 0) {
    310                 return -1;
     192static struct hdhomerun_discover_t *hdhomerun_discover_create(void)
     193{
     194        struct hdhomerun_discover_t *ds = (struct hdhomerun_discover_t *)calloc(1, sizeof(struct hdhomerun_discover_t));
     195        if (!ds) {
     196                return NULL;
    311197        }
    312         return 0;
     198
     199        /* Create a routable socket. */
     200        if (!hdhomerun_discover_sock_create(ds, 0, 0)) {
     201                free(ds);
     202                return NULL;
     203        }
     204
     205        /* Detect & create local sockets. */
     206        hdhomerun_discover_sock_detect(ds);
     207
     208        /* Success. */
     209        return ds;
    313210}
    314211
    315 #else
     212static void hdhomerun_discover_destroy(struct hdhomerun_discover_t *ds)
     213{
     214        unsigned int i;
     215        for (i = 0; i < ds->sock_count; i++) {
     216                struct hdhomerun_discover_sock_t *dss = &ds->socks[i];
     217                close(dss->sock);
     218        }
    316219
    317 static int hdhomerun_discover_send_internal(struct hdhomerun_discover_sock_t *ds, uint32_t device_type, uint32_t device_id)
     220        free(ds);
     221}
     222
     223static 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)
    318224{
    319         return -1;
     225        struct hdhomerun_pkt_t *tx_pkt = &ds->tx_pkt;
     226        hdhomerun_pkt_reset(tx_pkt);
     227
     228        hdhomerun_pkt_write_u8(tx_pkt, HDHOMERUN_TAG_DEVICE_TYPE);
     229        hdhomerun_pkt_write_var_length(tx_pkt, 4);
     230        hdhomerun_pkt_write_u32(tx_pkt, device_type);
     231        hdhomerun_pkt_write_u8(tx_pkt, HDHOMERUN_TAG_DEVICE_ID);
     232        hdhomerun_pkt_write_var_length(tx_pkt, 4);
     233        hdhomerun_pkt_write_u32(tx_pkt, device_id);
     234        hdhomerun_pkt_seal_frame(tx_pkt, HDHOMERUN_TYPE_DISCOVER_REQ);
     235
     236        struct sockaddr_in sock_addr;
     237        memset(&sock_addr, 0, sizeof(sock_addr));
     238        sock_addr.sin_family = AF_INET;
     239        sock_addr.sin_addr.s_addr = htonl(target_ip);
     240        sock_addr.sin_port = htons(HDHOMERUN_DISCOVER_UDP_PORT);
     241
     242        int length = (int)(tx_pkt->end - tx_pkt->start);
     243        if (sendto(dss->sock, (char *)tx_pkt->start, length, 0, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != length) {
     244                return FALSE;
     245        }
     246
     247        return TRUE;
    320248}
    321 #endif
    322249
    323 static int hdhomerun_discover_send(struct hdhomerun_discover_sock_t *ds, uint32_t device_type, uint32_t device_id)
     250static bool_t hdhomerun_discover_send_wildcard_ip(struct hdhomerun_discover_t *ds, uint32_t device_type, uint32_t device_id)
    324251{
    325         if (hdhomerun_discover_send_internal(ds, device_type, device_id) < 0) {
    326                 return hdhomerun_discover_send_packet(ds, 0xFFFFFFFF, device_type, device_id);
     252        bool_t result = FALSE;
     253
     254        /*
     255         * Send subnet broadcast using each local ip socket.
     256         * This will work with multiple separate 169.254.x.x interfaces.
     257         */
     258        unsigned int i;
     259        for (i = 1; i < ds->sock_count; i++) {
     260                struct hdhomerun_discover_sock_t *dss = &ds->socks[i];
     261                uint32_t target_ip = dss->local_ip | ~dss->subnet_mask;
     262                result |= hdhomerun_discover_send_internal(ds, dss, target_ip, device_type, device_id);
    327263        }
    328         return 0;
     264
     265        /*
     266         * If no local ip sockets then fall back to sending a global broadcast letting the OS choose the interface.
     267         */
     268        if (!result) {
     269                struct hdhomerun_discover_sock_t *dss = &ds->socks[0];
     270                result = hdhomerun_discover_send_internal(ds, dss, 0xFFFFFFFF, device_type, device_id);
     271        }
     272
     273        return result;
    329274}
    330275
    331 static int hdhomerun_discover_recv(struct hdhomerun_discover_sock_t *ds, struct hdhomerun_discover_device_t *result)
     276static bool_t hdhomerun_discover_send_target_ip(struct hdhomerun_discover_t *ds, uint32_t target_ip, uint32_t device_type, uint32_t device_id)
    332277{
    333         struct timeval t;
    334         t.tv_sec = 0;
    335         t.tv_usec = 250000;
     278        bool_t result = FALSE;
    336279
    337         fd_set readfds;
    338         FD_ZERO(&readfds);
    339         FD_SET(ds->sock, &readfds);
     280        /*
     281         * Send targeted packet from any local ip that is in the same subnet.
     282         * This will work with multiple separate 169.254.x.x interfaces.
     283         */
     284        unsigned int i;
     285        for (i = 1; i < ds->sock_count; i++) {
     286                struct hdhomerun_discover_sock_t *dss = &ds->socks[i];
     287                if ((target_ip & dss->subnet_mask) != (dss->local_ip & dss->subnet_mask)) {
     288                        continue;
     289                }
    340290
    341         if (select(ds->sock+1, &readfds, NULL, NULL, &t) < 0) {
    342                 return -1;
     291                result |= hdhomerun_discover_send_internal(ds, dss, target_ip, device_type, device_id);
    343292        }
    344         if (!FD_ISSET(ds->sock, &readfds)) {
    345                 return 0;
     293
     294        /*
     295         * If target IP does not match a local subnet then fall back to letting the OS choose the gateway interface.
     296         */
     297        if (!result) {
     298                struct hdhomerun_discover_sock_t *dss = &ds->socks[0];
     299                result = hdhomerun_discover_send_internal(ds, dss, target_ip, device_type, device_id);
     300        }
     301
     302        return result;
     303}
     304
     305static bool_t hdhomerun_discover_send(struct hdhomerun_discover_t *ds, uint32_t target_ip, uint32_t device_type, uint32_t device_id)
     306{
     307        if (target_ip != 0) {
     308                return hdhomerun_discover_send_target_ip(ds, target_ip, device_type, device_id);
    346309        }
    347310
    348         uint8_t buffer[1024];
     311        return hdhomerun_discover_send_wildcard_ip(ds, device_type, device_id);
     312}
     313
     314static int hdhomerun_discover_recv_internal(struct hdhomerun_discover_t *ds, struct hdhomerun_discover_sock_t *dss, struct hdhomerun_discover_device_t *result)
     315{
     316        struct hdhomerun_pkt_t *rx_pkt = &ds->rx_pkt;
     317        hdhomerun_pkt_reset(rx_pkt);
     318
    349319        struct sockaddr_in sock_addr;
     320        memset(&sock_addr, 0, sizeof(sock_addr));
    350321        socklen_t sockaddr_size = sizeof(sock_addr);
    351         int rx_length = recvfrom(ds->sock, (char *)buffer, sizeof(buffer), 0, (struct sockaddr *)&sock_addr, &sockaddr_size);
     322
     323        int rx_length = recvfrom(dss->sock, (char *)rx_pkt->end, (int)(rx_pkt->limit - rx_pkt->end), 0, (struct sockaddr *)&sock_addr, &sockaddr_size);
    352324        if (rx_length <= 0) {
    353325                /* Don't return error - windows machine on VPN can sometimes cause a sock error here but otherwise works. */
    354326                return 0;
    355327        }
    356         if (rx_length < HDHOMERUN_MIN_PEEK_LENGTH) {
    357                 return 0;
    358         }
     328        rx_pkt->end += rx_length;
    359329
    360         size_t length = hdhomerun_peek_packet_length(buffer);
    361         if (length > (size_t)rx_length) {
     330        uint16_t type;
     331        if (hdhomerun_pkt_open_frame(rx_pkt, &type) <= 0) {
    362332                return 0;
    363333        }
    364 
    365         uint8_t *ptr = buffer;
    366         uint8_t *end = buffer + length;
    367         int type = hdhomerun_process_packet(&ptr, &end);
    368334        if (type != HDHOMERUN_TYPE_DISCOVER_RPY) {
    369335                return 0;
    370336        }
     
    372338        result->ip_addr = ntohl(sock_addr.sin_addr.s_addr);
    373339        result->device_type = 0;
    374340        result->device_id = 0;
     341
    375342        while (1) {
    376343                uint8_t tag;
    377344                size_t len;
    378                 uint8_t *value;
    379                 if (hdhomerun_read_tlv(&ptr, end, &tag, &len, &value) < 0) {
     345                uint8_t *next = hdhomerun_pkt_read_tlv(rx_pkt, &tag, &len);
     346                if (!next) {
    380347                        break;
    381348                }
    382349
     
    385352                        if (len != 4) {
    386353                                break;
    387354                        }
    388                         result->device_type = hdhomerun_read_u32(&value);
     355                        result->device_type = hdhomerun_pkt_read_u32(rx_pkt);
    389356                        break;
     357
    390358                case HDHOMERUN_TAG_DEVICE_ID:
    391359                        if (len != 4) {
    392360                                break;
    393361                        }
    394                         result->device_id = hdhomerun_read_u32(&value);
     362                        result->device_id = hdhomerun_pkt_read_u32(rx_pkt);
    395363                        break;
     364
    396365                default:
    397366                        break;
    398367                }
     368
     369                rx_pkt->pos = next;
    399370        }
    400371
    401372        return 1;
    402373}
    403374
    404 static struct hdhomerun_discover_device_t *hdhomerun_discover_find_in_list(struct hdhomerun_discover_device_t result_list[], int count, uint32_t device_id)
     375static int hdhomerun_discover_recv(struct hdhomerun_discover_t *ds, struct hdhomerun_discover_device_t *result)
     376{
     377        struct timeval t;
     378        t.tv_sec = 0;
     379        t.tv_usec = 250000;
     380
     381        fd_set readfds;
     382        FD_ZERO(&readfds);
     383        int max_sock = -1;
     384
     385        unsigned int i;
     386        for (i = 0; i < ds->sock_count; i++) {
     387                struct hdhomerun_discover_sock_t *dss = &ds->socks[i];
     388                FD_SET(dss->sock, &readfds);
     389                if (dss->sock > max_sock) {
     390                        max_sock = dss->sock;
     391                }
     392        }
     393
     394        if (select(max_sock+1, &readfds, NULL, NULL, &t) < 0) {
     395                return -1;
     396        }
     397
     398        for (i = 0; i < ds->sock_count; i++) {
     399                struct hdhomerun_discover_sock_t *dss = &ds->socks[i];
     400                if (!FD_ISSET(dss->sock, &readfds)) {
     401                        continue;
     402                }
     403
     404                if (hdhomerun_discover_recv_internal(ds, dss, result) <= 0) {
     405                        continue;
     406                }
     407
     408                return 1;
     409        }
     410
     411        return 0;
     412}
     413
     414static struct hdhomerun_discover_device_t *hdhomerun_discover_find_in_list(struct hdhomerun_discover_device_t result_list[], int count, uint32_t ip_addr)
    405415{
    406416        int index;
    407417        for (index = 0; index < count; index++) {
    408418                struct hdhomerun_discover_device_t *result = &result_list[index];
    409                 if (result->device_id == device_id) {
     419                if (result->ip_addr == ip_addr) {
    410420                        return result;
    411421                }
    412422        }
     
    414424        return NULL;
    415425}
    416426
    417 static int hdhomerun_discover_find_devices_internal(struct hdhomerun_discover_sock_t *ds, uint32_t device_type, uint32_t device_id, struct hdhomerun_discover_device_t result_list[], int max_count)
     427static 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)
    418428{
    419429        int count = 0;
    420 
    421430        int attempt;
    422431        for (attempt = 0; attempt < 4; attempt++) {
    423                 if (hdhomerun_discover_send(ds, device_type, device_id) < 0) {
     432                if (!hdhomerun_discover_send(ds, target_ip, device_type, device_id)) {
    424433                        return -1;
    425434                }
    426435
     
    433442                                return -1;
    434443                        }
    435444                        if (ret == 0) {
    436                                 break;
     445                                continue;
    437446                        }
    438447
    439448                        /* Filter. */
     
    449458                        }
    450459
    451460                        /* Ensure not already in list. */
    452                         if (hdhomerun_discover_find_in_list(result_list, count, result->device_id)) {
     461                        if (hdhomerun_discover_find_in_list(result_list, count, result->ip_addr)) {
    453462                                continue;
    454463                        }
    455464
     
    464473        return count;
    465474}
    466475
    467 int hdhomerun_discover_find_device(uint32_t device_id, struct hdhomerun_discover_device_t *result)
    468 {
    469         struct hdhomerun_discover_sock_t *ds = hdhomerun_discover_create();
    470         if (!ds) {
    471                 return -1;
    472         }
    473 
    474         int ret = hdhomerun_discover_find_devices_internal(ds, HDHOMERUN_DEVICE_TYPE_WILDCARD, device_id, result, 1);
    475 
    476         hdhomerun_discover_destroy(ds);
    477         return ret;
    478 }
    479 
    480 int hdhomerun_discover_find_devices(uint32_t device_type, struct hdhomerun_discover_device_t result_list[], int max_count)
     476int 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)
    481477{
    482         struct hdhomerun_discover_sock_t *ds = hdhomerun_discover_create();
     478        struct hdhomerun_discover_t *ds = hdhomerun_discover_create();
    483479        if (!ds) {
    484480                return -1;
    485481        }
    486482
    487         int ret = hdhomerun_discover_find_devices_internal(ds, device_type, HDHOMERUN_DEVICE_ID_WILDCARD, result_list, max_count);
     483        int ret = hdhomerun_discover_find_devices_internal(ds, target_ip, device_type, device_id, result_list, max_count);
    488484
    489485        hdhomerun_discover_destroy(ds);
    490486        return ret;
  • mythtv/libs/libmythtv/hdhomerun/hdhomerun_discover.h

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhomerun/hdhomerun_discover.h release.19703.0116b/mythtv/libs/libmythtv/hdhomerun/hdhomerun_discover.h
     
    11/*
    22 * hdhomerun_discover.h
    33 *
    4  * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
     4 * Copyright © 2006-2007 Silicondust Engineering Ltd. <www.silicondust.com>.
    55 *
    6  * This library is free software; you can redistribute it and/or
     6 * This library is free software; you can redistribute it and/or 
    77 * modify it under the terms of the GNU Lesser General Public
    88 * License as published by the Free Software Foundation; either
    9  * version 2.1 of the License, or (at your option) any later version.
     9 * version 3 of the License, or (at your option) any later version.
    1010 *
    1111 * This library is distributed in the hope that it will be useful,
    1212 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     
    1414 * Lesser General Public License for more details.
    1515 *
    1616 * You should have received a copy of the GNU Lesser General Public
    17  * License along with this library; if not, write to the Free Software
    18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     17 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
     18 *
     19 * As a special exception to the GNU Lesser General Public License,
     20 * you may link, statically or dynamically, an application with a
     21 * publicly distributed version of the Library to produce an
     22 * executable file containing portions of the Library, and
     23 * distribute that executable file under terms of your choice,
     24 * without any of the additional requirements listed in clause 4 of
     25 * the GNU Lesser General Public License.
     26 *
     27 * By "a publicly distributed version of the Library", we mean
     28 * either the unmodified Library as distributed by Silicondust, or a
     29 * modified version of the Library that is distributed under the
     30 * conditions defined in the GNU Lesser General Public License.
    1931 */
    2032#ifdef __cplusplus
    2133extern "C" {
     
    2840};
    2941
    3042/*
    31  * Find a device by device ID.
    32  *
    33  * The device information is stored in caller-supplied hdhomerun_discover_device_t var.
    34  * Multiple attempts are made to find the device.
    35  * Worst-case execution time is 1 second.
    36  *
    37  * Returns 1 on success.
    38  * Returns 0 if not found.
    39  * Retruns -1 on error.
    40  */
    41 extern int hdhomerun_discover_find_device(uint32_t device_id, struct hdhomerun_discover_device_t *result);
    42 
    43 /*
    44  * Find all devices of a given type.
     43 * Find devices.
    4544 *
    4645 * The device information is stored in caller-supplied array of hdhomerun_discover_device_t vars.
    4746 * Multiple attempts are made to find devices.
    4847 * Execution time is 1 second.
    4948 *
     49 * Set target_ip to zero to auto-detect IP address.
     50 *
    5051 * Returns the number of devices found.
    5152 * Retruns -1 on error.
    5253 */
    53 extern int hdhomerun_discover_find_devices(uint32_t device_type, struct hdhomerun_discover_device_t result_list[], int max_count);
     54extern 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);
    5455
    5556/*
    5657 * Verify that the device ID given is valid.
     
    6162 * Returns TRUE if valid.
    6263 * Returns FALSE if not valid.
    6364 */
    64 extern bool_t hdhomerun_discover_validate_device_id(uint32_t device_id);
     65extern LIBTYPE bool_t hdhomerun_discover_validate_device_id(uint32_t device_id);
    6566
    6667#ifdef __cplusplus
    6768}
  • mythtv/libs/libmythtv/hdhomerun/hdhomerun_os.h

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhomerun/hdhomerun_os.h release.19703.0116b/mythtv/libs/libmythtv/hdhomerun/hdhomerun_os.h
     
    11/*
    22 * hdhomerun_os.h
    33 *
    4  * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
     4 * Copyright © 2006-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
    55 *
    6  * This library is free software; you can redistribute it and/or
     6 * This library is free software; you can redistribute it and/or 
    77 * modify it under the terms of the GNU Lesser General Public
    88 * License as published by the Free Software Foundation; either
    9  * version 2.1 of the License, or (at your option) any later version.
     9 * version 3 of the License, or (at your option) any later version.
    1010 *
    1111 * This library is distributed in the hope that it will be useful,
    1212 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     
    1414 * Lesser General Public License for more details.
    1515 *
    1616 * You should have received a copy of the GNU Lesser General Public
    17  * License along with this library; if not, write to the Free Software
    18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     17 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
     18 *
     19 * As a special exception to the GNU Lesser General Public License,
     20 * you may link, statically or dynamically, an application with a
     21 * publicly distributed version of the Library to produce an
     22 * executable file containing portions of the Library, and
     23 * distribute that executable file under terms of your choice,
     24 * without any of the additional requirements listed in clause 4 of
     25 * the GNU Lesser General Public License.
     26 *
     27 * By "a publicly distributed version of the Library", we mean
     28 * either the unmodified Library as distributed by Silicondust, or a
     29 * modified version of the Library that is distributed under the
     30 * conditions defined in the GNU Lesser General Public License.
    1931 */
    2032
    21 #include <stdlib.h>
    22 #include <stdio.h>
    23 #include <string.h>
    24 
    25 #if defined(WIN32)
     33#if defined(_WIN32) || defined(_WIN64)
    2634#define __WINDOWS__
    2735#endif
    2836
    2937#if defined(__WINDOWS__)
    30 #include <windows.h>
    31 #include <sys/types.h>
    32 #include <sys/timeb.h>
     38#include "hdhomerun_os_windows.h"
    3339#else
    34 #include <unistd.h>
    35 #include <errno.h>
    36 #include <sys/types.h>
    37 #include <sys/socket.h>
    38 #include <netinet/in.h>
    39 #include <arpa/inet.h>
    40 #include <netdb.h>
    41 #include <sys/time.h>
    42 #include <sys/timeb.h>
    43 #include <fcntl.h>
     40#include "hdhomerun_os_posix.h"
    4441#endif
    4542
    46 #include <pthread.h>
    47 
    4843#if !defined(TRUE)
    4944#define TRUE 1
    5045#endif
     46
    5147#if !defined(FALSE)
    5248#define FALSE 0
    5349#endif
    54 
    55 #if defined(__WINDOWS__)
    56 
    57 typedef int bool_t;
    58 typedef unsigned __int8 uint8_t;
    59 typedef unsigned __int16 uint16_t;
    60 typedef unsigned __int32 uint32_t;
    61 typedef unsigned __int64 uint64_t;
    62 
    63 #define socklen_t int
    64 #define close closesocket
    65 #define sock_getlasterror WSAGetLastError()
    66 #define sock_getlasterror_socktimeout (WSAGetLastError() == WSAETIMEDOUT)
    67 #define atoll _atoi64
    68 #define strcasecmp _stricmp
    69 #define fseeko _fseeki64
    70 #define ftello _ftelli64
    71 #define usleep(us) Sleep((us)/1000)
    72 #define sleep(sec) Sleep((sec)*1000)
    73 
    74 static inline uint64_t getcurrenttime(void)
    75 {
    76         struct timeb tb;
    77         ftime(&tb);
    78         return ((uint64_t)tb.time * 1000) + tb.millitm;
    79 }
    80 
    81 static inline int setsocktimeout(int s, int level, int optname, uint64_t timeout)
    82 {
    83         int t = (int)timeout;
    84         return setsockopt(s, level, optname, (char *)&t, sizeof(t));
    85 }
    86 
    87 #else
    88 
    89 typedef int bool_t;
    90 
    91 #define sock_getlasterror errno
    92 #define sock_getlasterror_socktimeout (errno == EAGAIN)
    93 
    94 static inline uint64_t getcurrenttime(void)
    95 {
    96         struct timeval t;
    97         gettimeofday(&t, NULL);
    98         return ((uint64_t)t.tv_sec * 1000) + (t.tv_usec / 1000);
    99 }
    100 
    101 static inline int setsocktimeout(int s, int level, int optname, uint64_t timeout)
    102 {
    103         struct timeval t;
    104         t.tv_sec = timeout / 1000;
    105         t.tv_usec = (timeout % 1000) * 1000;
    106         return setsockopt(s, level, optname, (char *)&t, sizeof(t));
    107 }
    108 
    109 #endif
    110 
  • mythtv/libs/libmythtv/hdhomerun/hdhomerun_os_posix.h

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhomerun/hdhomerun_os_posix.h release.19703.0116b/mythtv/libs/libmythtv/hdhomerun/hdhomerun_os_posix.h
     
     1/*
     2 * hdhomerun_os_posix.h
     3 *
     4 * Copyright © 2006-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
     5 *
     6 * This library is free software; you can redistribute it and/or
     7 * modify it under the terms of the GNU Lesser General Public
     8 * License as published by the Free Software Foundation; either
     9 * version 3 of the License, or (at your option) any later version.
     10 *
     11 * This library is distributed in the hope that it will be useful,
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14 * Lesser General Public License for more details.
     15 *
     16 * You should have received a copy of the GNU Lesser General Public
     17 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
     18 *
     19 * As a special exception to the GNU Lesser General Public License,
     20 * you may link, statically or dynamically, an application with a
     21 * publicly distributed version of the Library to produce an
     22 * executable file containing portions of the Library, and
     23 * distribute that executable file under terms of your choice,
     24 * without any of the additional requirements listed in clause 4 of
     25 * the GNU Lesser General Public License.
     26 *
     27 * By "a publicly distributed version of the Library", we mean
     28 * either the unmodified Library as distributed by Silicondust, or a
     29 * modified version of the Library that is distributed under the
     30 * conditions defined in the GNU Lesser General Public License.
     31 */
     32
     33#define _FILE_OFFSET_BITS 64
     34#include <stdlib.h>
     35#include <stdio.h>
     36#include <stdarg.h>
     37#include <string.h>
     38#include <unistd.h>
     39#include <errno.h>
     40#include <fcntl.h>
     41#include <sys/types.h>
     42#include <sys/socket.h>
     43#include <sys/time.h>
     44#include <sys/timeb.h>
     45#include <sys/wait.h>
     46#include <sys/signal.h>
     47#include <netinet/in.h>
     48#include <arpa/inet.h>
     49#include <netdb.h>
     50#include <pthread.h>
     51
     52typedef int bool_t;
     53
     54#define LIBTYPE
     55#define sock_getlasterror errno
     56#define sock_getlasterror_socktimeout (errno == EAGAIN)
     57#define console_vprintf vprintf
     58#define console_printf printf
     59#define THREAD_FUNC_PREFIX void *
     60
     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}
     67
     68static inline int setsocktimeout(int s, int level, int optname, uint64_t timeout)
     69{
     70        struct timeval t;
     71        t.tv_sec = timeout / 1000;
     72        t.tv_usec = (timeout % 1000) * 1000;
     73        return setsockopt(s, level, optname, (char *)&t, sizeof(t));
     74}
  • mythtv/libs/libmythtv/hdhomerun/hdhomerun_os_windows.h

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhomerun/hdhomerun_os_windows.h release.19703.0116b/mythtv/libs/libmythtv/hdhomerun/hdhomerun_os_windows.h
     
     1/*
     2 * hdhomerun_os_windows.h
     3 *
     4 * Copyright © 2006-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
     5 *
     6 * This library is free software; you can redistribute it and/or
     7 * modify it under the terms of the GNU Lesser General Public
     8 * License as published by the Free Software Foundation; either
     9 * version 3 of the License, or (at your option) any later version.
     10 *
     11 * This library is distributed in the hope that it will be useful,
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14 * Lesser General Public License for more details.
     15 *
     16 * You should have received a copy of the GNU Lesser General Public
     17 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
     18 *
     19 * As a special exception to the GNU Lesser General Public License,
     20 * you may link, statically or dynamically, an application with a
     21 * publicly distributed version of the Library to produce an
     22 * executable file containing portions of the Library, and
     23 * distribute that executable file under terms of your choice,
     24 * without any of the additional requirements listed in clause 4 of
     25 * the GNU Lesser General Public License.
     26 *
     27 * By "a publicly distributed version of the Library", we mean
     28 * either the unmodified Library as distributed by Silicondust, or a
     29 * modified version of the Library that is distributed under the
     30 * conditions defined in the GNU Lesser General Public License.
     31 */
     32
     33#define _WINSOCKAPI_
     34#include <windows.h>
     35#include <winsock2.h>
     36#include <ws2tcpip.h>
     37#include <wspiapi.h>
     38#include <stdlib.h>
     39#include <stdio.h>
     40#include <stdarg.h>
     41#include <string.h>
     42#include <signal.h>
     43#include <time.h>
     44#include <sys/types.h>
     45#include <sys/timeb.h>
     46
     47#if defined(DLL_IMPORT)
     48#define LIBTYPE __declspec( dllexport )
     49#elif  defined(DLL_EXPORT)
     50#define LIBTYPE __declspec( dllimport )
     51#else
     52#define LIBTYPE
     53#endif
     54
     55typedef int bool_t;
     56typedef signed __int8 int8_t;
     57typedef signed __int16 int16_t;
     58typedef signed __int32 int32_t;
     59typedef signed __int64 int64_t;
     60typedef unsigned __int8 uint8_t;
     61typedef unsigned __int16 uint16_t;
     62typedef unsigned __int32 uint32_t;
     63typedef unsigned __int64 uint64_t;
     64typedef HANDLE pthread_t;
     65typedef HANDLE pthread_mutex_t;
     66
     67#define socklen_t int
     68#define close closesocket
     69#define sock_getlasterror WSAGetLastError()
     70#define sock_getlasterror_socktimeout (WSAGetLastError() == WSAETIMEDOUT)
     71#define va_copy(x, y) x = y
     72#define atoll _atoi64
     73#define strdup _strdup
     74#define strcasecmp _stricmp
     75#define snprintf _snprintf
     76#define fseeko _fseeki64
     77#define ftello _ftelli64
     78#define THREAD_FUNC_PREFIX DWORD WINAPI
     79#define SIGPIPE SIGABRT
     80
     81static inline int usleep(unsigned int us)
     82{
     83        Sleep((us)/1000);
     84        return 0;
     85}
     86
     87static inline int sleep(unsigned int sec)
     88{
     89        Sleep((sec)*1000);
     90        return 0;
     91}
     92
     93static inline uint64_t getcurrenttime(void)
     94{
     95        struct timeb tb;
     96        ftime(&tb);
     97        return ((uint64_t)tb.time * 1000) + tb.millitm;
     98}
     99
     100static inline int setsocktimeout(int s, int level, int optname, uint64_t timeout)
     101{
     102        int t = (int)timeout;
     103        return setsockopt(s, level, optname, (char *)&t, sizeof(t));
     104}
     105
     106static inline int pthread_create(pthread_t *tid, void *attr, LPTHREAD_START_ROUTINE start, void *arg)
     107{
     108        *tid = CreateThread(NULL, 0, start, arg, 0, NULL);
     109        if (!*tid) {
     110                return (int)GetLastError();
     111        }
     112        return 0;
     113}
     114
     115static inline int pthread_join(pthread_t tid, void **value_ptr)
     116{
     117        while (1) {
     118                DWORD ExitCode = 0;
     119                if (!GetExitCodeThread(tid, &ExitCode)) {
     120                        return (int)GetLastError();
     121                }
     122                if (ExitCode != STILL_ACTIVE) {
     123                        return 0;
     124                }
     125        }
     126}
     127
     128static inline void pthread_mutex_init(pthread_mutex_t *mutex, void *attr)
     129{
     130        *mutex = CreateMutex(NULL, FALSE, NULL);
     131}
     132
     133static inline void pthread_mutex_lock(pthread_mutex_t *mutex)
     134{
     135        WaitForSingleObject(*mutex, INFINITE);
     136}
     137
     138static inline void pthread_mutex_unlock(pthread_mutex_t *mutex)
     139{
     140        ReleaseMutex(*mutex);
     141}
     142
     143/*
     144 * The console output format should be set to UTF-8, however in XP and Vista this breaks batch file processing.
     145 * Attempting to restore on exit fails to restore if the program is terminated by the user.
     146 * Solution - set the output format each printf.
     147 */
     148static inline void console_vprintf(const char *fmt, va_list ap)
     149{
     150        UINT cp = GetConsoleOutputCP();
     151        SetConsoleOutputCP(CP_UTF8);
     152        vprintf(fmt, ap);
     153        SetConsoleOutputCP(cp);
     154}
     155
     156static inline void console_printf(const char *fmt, ...)
     157{
     158        va_list ap;
     159        va_start(ap, fmt);
     160        console_vprintf(fmt, ap);
     161        va_end(ap);
     162}
  • mythtv/libs/libmythtv/hdhomerun/hdhomerun_pkt.c

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhomerun/hdhomerun_pkt.c release.19703.0116b/mythtv/libs/libmythtv/hdhomerun/hdhomerun_pkt.c
     
    11/*
    22 * hdhomerun_pkt.c
    33 *
    4  * Copyright © 2005-2006 Silicondust Engineering Ltd. <www.silicondust.com>.
     4 * Copyright © 2005-2006 Silicondust Engineering Ltd. <www.silicondust.com>.
    55 *
    6  * This library is free software; you can redistribute it and/or
     6 * This library is free software; you can redistribute it and/or 
    77 * modify it under the terms of the GNU Lesser General Public
    88 * License as published by the Free Software Foundation; either
    9  * version 2.1 of the License, or (at your option) any later version.
     9 * version 3 of the License, or (at your option) any later version.
    1010 *
    1111 * This library is distributed in the hope that it will be useful,
    1212 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     
    1414 * Lesser General Public License for more details.
    1515 *
    1616 * You should have received a copy of the GNU Lesser General Public
    17  * License along with this library; if not, write to the Free Software
    18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     17 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
     18 *
     19 * As a special exception to the GNU Lesser General Public License,
     20 * you may link, statically or dynamically, an application with a
     21 * publicly distributed version of the Library to produce an
     22 * executable file containing portions of the Library, and
     23 * distribute that executable file under terms of your choice,
     24 * without any of the additional requirements listed in clause 4 of
     25 * the GNU Lesser General Public License.
     26 *
     27 * By "a publicly distributed version of the Library", we mean
     28 * either the unmodified Library as distributed by Silicondust, or a
     29 * modified version of the Library that is distributed under the
     30 * conditions defined in the GNU Lesser General Public License.
    1931 */
    2032
    21 #include "hdhomerun_os.h"
    22 #include "hdhomerun_pkt.h"
     33#include "hdhomerun.h"
    2334
    24 uint8_t hdhomerun_read_u8(uint8_t **pptr)
     35struct hdhomerun_pkt_t *hdhomerun_pkt_create(void)
    2536{
    26         uint8_t *ptr = *pptr;
    27         uint8_t v = *ptr++;
    28         *pptr = ptr;
     37        struct hdhomerun_pkt_t *pkt = (struct hdhomerun_pkt_t *)calloc(1, sizeof(struct hdhomerun_pkt_t));
     38        if (!pkt) {
     39                return NULL;
     40        }
     41
     42        hdhomerun_pkt_reset(pkt);
     43
     44        return pkt;
     45}
     46
     47void hdhomerun_pkt_destroy(struct hdhomerun_pkt_t *pkt)
     48{
     49        free(pkt);
     50}
     51
     52void hdhomerun_pkt_reset(struct hdhomerun_pkt_t *pkt)
     53{
     54        pkt->limit = pkt->buffer + sizeof(pkt->buffer) - 4;
     55        pkt->start = pkt->buffer + 1024;
     56        pkt->end = pkt->start;
     57        pkt->pos = pkt->start;
     58}
     59
     60static uint32_t hdhomerun_pkt_calc_crc(uint8_t *start, uint8_t *end)
     61{
     62        uint8_t *pos = start;
     63        uint32_t crc = 0xFFFFFFFF;
     64        while (pos < end) {
     65                uint8_t x = (uint8_t)(crc) ^ *pos++;
     66                crc >>= 8;
     67                if (x & 0x01) crc ^= 0x77073096;
     68                if (x & 0x02) crc ^= 0xEE0E612C;
     69                if (x & 0x04) crc ^= 0x076DC419;
     70                if (x & 0x08) crc ^= 0x0EDB8832;
     71                if (x & 0x10) crc ^= 0x1DB71064;
     72                if (x & 0x20) crc ^= 0x3B6E20C8;
     73                if (x & 0x40) crc ^= 0x76DC4190;
     74                if (x & 0x80) crc ^= 0xEDB88320;
     75        }
     76        return crc ^ 0xFFFFFFFF;
     77}
     78
     79uint8_t hdhomerun_pkt_read_u8(struct hdhomerun_pkt_t *pkt)
     80{
     81        uint8_t v = *pkt->pos++;
    2982        return v;
    3083}
    3184
    32 uint16_t hdhomerun_read_u16(uint8_t **pptr)
     85uint16_t hdhomerun_pkt_read_u16(struct hdhomerun_pkt_t *pkt)
    3386{
    34         uint8_t *ptr = *pptr;
    3587        uint16_t v;
    36         v =  (uint16_t)*ptr++ << 8;
    37         v |= (uint16_t)*ptr++ << 0;
    38         *pptr = ptr;
     88        v =  (uint16_t)*pkt->pos++ << 8;
     89        v |= (uint16_t)*pkt->pos++ << 0;
    3990        return v;
    4091}
    4192
    42 uint32_t hdhomerun_read_u32(uint8_t **pptr)
     93uint32_t hdhomerun_pkt_read_u32(struct hdhomerun_pkt_t *pkt)
    4394{
    44         uint8_t *ptr = *pptr;
    4595        uint32_t v;
    46         v =  (uint32_t)*ptr++ << 24;
    47         v |= (uint32_t)*ptr++ << 16;
    48         v |= (uint32_t)*ptr++ << 8;
    49         v |= (uint32_t)*ptr++ << 0;
    50         *pptr = ptr;
     96        v =  (uint32_t)*pkt->pos++ << 24;
     97        v |= (uint32_t)*pkt->pos++ << 16;
     98        v |= (uint32_t)*pkt->pos++ << 8;
     99        v |= (uint32_t)*pkt->pos++ << 0;
    51100        return v;
    52101}
    53102
    54 size_t hdhomerun_read_var_length(uint8_t **pptr, uint8_t *end)
     103size_t hdhomerun_pkt_read_var_length(struct hdhomerun_pkt_t *pkt)
    55104{
    56         uint8_t *ptr = *pptr;
    57105        size_t length;
    58106       
    59         if (ptr + 1 > end) {
    60                 return -1;
     107        if (pkt->pos + 1 > pkt->end) {
     108                return (size_t)-1;
    61109        }
    62110
    63         length = (size_t)*ptr++;
     111        length = (size_t)*pkt->pos++;
    64112        if (length & 0x0080) {
    65                 if (ptr + 1 > end) {
    66                         return -1;
     113                if (pkt->pos + 1 > pkt->end) {
     114                        return (size_t)-1;
    67115                }
    68116
    69117                length &= 0x007F;
    70                 length |= (size_t)*ptr++ << 7;
     118                length |= (size_t)*pkt->pos++ << 7;
    71119        }
    72120       
    73         *pptr = ptr;
    74121        return length;
    75122}
    76123
    77 int hdhomerun_read_tlv(uint8_t **pptr, uint8_t *end, uint8_t *ptag, size_t *plength, uint8_t **pvalue)
     124uint8_t *hdhomerun_pkt_read_tlv(struct hdhomerun_pkt_t *pkt, uint8_t *ptag, size_t *plength)
    78125{
    79         if (end - *pptr < 2) {
    80                 return -1;
     126        if (pkt->pos + 2 > pkt->end) {
     127                return NULL;
    81128        }
    82129       
    83         *ptag = hdhomerun_read_u8(pptr);
    84         *plength = hdhomerun_read_var_length(pptr, end);
    85         *pvalue = *pptr;
    86        
    87         if ((size_t)(end - *pptr) < *plength) {
    88                 return -1;
     130        *ptag = hdhomerun_pkt_read_u8(pkt);
     131        *plength = hdhomerun_pkt_read_var_length(pkt);
     132
     133        if (pkt->pos + *plength > pkt->end) {
     134                return NULL;
    89135        }
    90136       
    91         *pptr += *plength;
    92         return 0;
     137        return pkt->pos + *plength;
    93138}
    94139
    95 void hdhomerun_write_u8(uint8_t **pptr, uint8_t v)
     140void hdhomerun_pkt_write_u8(struct hdhomerun_pkt_t *pkt, uint8_t v)
    96141{
    97         uint8_t *ptr = *pptr;
    98         *ptr++ = v;
    99         *pptr = ptr;
    100 }
     142        *pkt->pos++ = v;
    101143
    102 void hdhomerun_write_u16(uint8_t **pptr, uint16_t v)
    103 {
    104         uint8_t *ptr = *pptr;
    105         *ptr++ = (uint8_t)(v >> 8);
    106         *ptr++ = (uint8_t)(v >> 0);
    107         *pptr = ptr;
     144        if (pkt->pos > pkt->end) {
     145                pkt->end = pkt->pos;
     146        }
    108147}
    109148
    110 void hdhomerun_write_u32(uint8_t **pptr, uint32_t v)
     149void hdhomerun_pkt_write_u16(struct hdhomerun_pkt_t *pkt, uint16_t v)
    111150{
    112         uint8_t *ptr = *pptr;
    113         *ptr++ = (uint8_t)(v >> 24);
    114         *ptr++ = (uint8_t)(v >> 16);
    115         *ptr++ = (uint8_t)(v >> 8);
    116         *ptr++ = (uint8_t)(v >> 0);
    117         *pptr = ptr;
    118 }
     151        *pkt->pos++ = (uint8_t)(v >> 8);
     152        *pkt->pos++ = (uint8_t)(v >> 0);
    119153
    120 void hdhomerun_write_var_length(uint8_t **pptr, size_t v)
    121 {
    122         uint8_t *ptr = *pptr;
    123         if (v <= 127) {
    124                 *ptr++ = (uint8_t)v;
    125         } else {
    126                 *ptr++ = (uint8_t)(v | 0x80);
    127                 *ptr++ = (uint8_t)(v >> 7);
     154        if (pkt->pos > pkt->end) {
     155                pkt->end = pkt->pos;
    128156        }
    129         *pptr = ptr;
    130157}
    131158
    132 static void hdhomerun_write_mem(uint8_t **pptr, void *mem, size_t length)
     159void hdhomerun_pkt_write_u32(struct hdhomerun_pkt_t *pkt, uint32_t v)
    133160{
    134         uint8_t *ptr = *pptr;
    135         memcpy(ptr, mem, length);
    136         ptr += length;
    137         *pptr = ptr;
    138 }
     161        *pkt->pos++ = (uint8_t)(v >> 24);
     162        *pkt->pos++ = (uint8_t)(v >> 16);
     163        *pkt->pos++ = (uint8_t)(v >> 8);
     164        *pkt->pos++ = (uint8_t)(v >> 0);
    139165
    140 static uint32_t hdhomerun_calc_crc(uint8_t *start, uint8_t *end)
    141 {
    142         uint8_t *ptr = start;
    143         uint32_t crc = 0xFFFFFFFF;
    144         while (ptr < end) {
    145                 uint8_t x = (uint8_t)(crc) ^ *ptr++;
    146                 crc >>= 8;
    147                 if (x & 0x01) crc ^= 0x77073096;
    148                 if (x & 0x02) crc ^= 0xEE0E612C;
    149                 if (x & 0x04) crc ^= 0x076DC419;
    150                 if (x & 0x08) crc ^= 0x0EDB8832;
    151                 if (x & 0x10) crc ^= 0x1DB71064;
    152                 if (x & 0x20) crc ^= 0x3B6E20C8;
    153                 if (x & 0x40) crc ^= 0x76DC4190;
    154                 if (x & 0x80) crc ^= 0xEDB88320;
     166        if (pkt->pos > pkt->end) {
     167                pkt->end = pkt->pos;
    155168        }
    156         return crc ^ 0xFFFFFFFF;
    157169}
    158170
    159 static int hdhomerun_check_crc(uint8_t *start, uint8_t *end)
     171void hdhomerun_pkt_write_var_length(struct hdhomerun_pkt_t *pkt, size_t v)
    160172{
    161         if (end - start < 8) {
    162                 return -1;
     173        if (v <= 127) {
     174                *pkt->pos++ = (uint8_t)v;
     175        } else {
     176                *pkt->pos++ = (uint8_t)(v | 0x80);
     177                *pkt->pos++ = (uint8_t)(v >> 7);
    163178        }
    164         uint8_t *ptr = end -= 4;
    165         uint32_t actual_crc = hdhomerun_calc_crc(start, ptr);
    166         uint32_t packet_crc;
    167         packet_crc =  (uint32_t)*ptr++ << 0;
    168         packet_crc |= (uint32_t)*ptr++ << 8;
    169         packet_crc |= (uint32_t)*ptr++ << 16;
    170         packet_crc |= (uint32_t)*ptr++ << 24;
    171         if (actual_crc != packet_crc) {
    172                 return -1;
     179
     180        if (pkt->pos > pkt->end) {
     181                pkt->end = pkt->pos;
    173182        }
    174         return 0;
    175183}
    176184
    177 static void hdhomerun_write_header_length(uint8_t *ptr, size_t length)
     185void hdhomerun_pkt_write_mem(struct hdhomerun_pkt_t *pkt, const void *mem, size_t length)
    178186{
    179         hdhomerun_write_u16(&ptr, (uint16_t)length);
    180 }
     187        memcpy(pkt->pos, mem, length);
     188        pkt->pos += length;
    181189
    182 void hdhomerun_write_crc(uint8_t **pptr, uint8_t *start)
    183 {
    184         uint8_t *ptr = *pptr;
    185         uint32_t crc = hdhomerun_calc_crc(start, ptr);
    186         *ptr++ = (uint8_t)(crc >> 0);
    187         *ptr++ = (uint8_t)(crc >> 8);
    188         *ptr++ = (uint8_t)(crc >> 16);
    189         *ptr++ = (uint8_t)(crc >> 24);
    190         *pptr = ptr;
     190        if (pkt->pos > pkt->end) {
     191                pkt->end = pkt->pos;
     192        }
    191193}
    192194
    193 void hdhomerun_write_discover_request(uint8_t **pptr, uint32_t device_type, uint32_t device_id)
     195int hdhomerun_pkt_open_frame(struct hdhomerun_pkt_t *pkt, uint16_t *ptype)
    194196{
    195         uint8_t *start = *pptr;
    196         hdhomerun_write_u16(pptr, HDHOMERUN_TYPE_DISCOVER_REQ);
    197         hdhomerun_write_u16(pptr, 0);
     197        pkt->pos = pkt->start;
    198198
    199         hdhomerun_write_u8(pptr, HDHOMERUN_TAG_DEVICE_TYPE);
    200         hdhomerun_write_var_length(pptr, 4);
    201         hdhomerun_write_u32(pptr, device_type);
    202         hdhomerun_write_u8(pptr, HDHOMERUN_TAG_DEVICE_ID);
    203         hdhomerun_write_var_length(pptr, 4);
    204         hdhomerun_write_u32(pptr, device_id);
     199        if (pkt->pos + 4 > pkt->end) {
     200                return 0;
     201        }
    205202
    206         hdhomerun_write_header_length(start + 2, (int)(*pptr - start - 4));
    207         hdhomerun_write_crc(pptr, start);
    208 }
     203        *ptype = hdhomerun_pkt_read_u16(pkt);
     204        size_t length = hdhomerun_pkt_read_u16(pkt);
     205        pkt->pos += length;
    209206
    210 void hdhomerun_write_get_set_request(uint8_t **pptr, const char *name, const char *value)
    211 {
    212         uint8_t *start = *pptr;
    213         hdhomerun_write_u16(pptr, HDHOMERUN_TYPE_GETSET_REQ);
    214         hdhomerun_write_u16(pptr, 0);
     207        if (pkt->pos + 4 > pkt->end) {
     208                pkt->pos = pkt->start;
     209                return 0;
     210        }
    215211
    216         int name_len = (int)strlen(name) + 1;
    217         hdhomerun_write_u8(pptr, HDHOMERUN_TAG_GETSET_NAME);
    218         hdhomerun_write_var_length(pptr, name_len);
    219         hdhomerun_write_mem(pptr, (void *)name, name_len);
     212        uint32_t calc_crc = hdhomerun_pkt_calc_crc(pkt->start, pkt->pos);
    220213
    221         if (value) {
    222                 int value_len = (int)strlen(value) + 1;
    223                 hdhomerun_write_u8(pptr, HDHOMERUN_TAG_GETSET_VALUE);
    224                 hdhomerun_write_var_length(pptr, value_len);
    225                 hdhomerun_write_mem(pptr, (void *)value, value_len);
     214        uint32_t packet_crc;
     215        packet_crc =  (uint32_t)*pkt->pos++ << 0;
     216        packet_crc |= (uint32_t)*pkt->pos++ << 8;
     217        packet_crc |= (uint32_t)*pkt->pos++ << 16;
     218        packet_crc |= (uint32_t)*pkt->pos++ << 24;
     219        if (calc_crc != packet_crc) {
     220                return -1;
    226221        }
    227222
    228         hdhomerun_write_header_length(start + 2, (int)(*pptr - start - 4));
    229         hdhomerun_write_crc(pptr, start);
     223        pkt->start += 4;
     224        pkt->end = pkt->start + length;
     225        pkt->pos = pkt->start;
     226        return 1;
    230227}
    231228
    232 void hdhomerun_write_upgrade_request(uint8_t **pptr, uint32_t sequence, void *data, size_t length)
     229void hdhomerun_pkt_seal_frame(struct hdhomerun_pkt_t *pkt, uint16_t frame_type)
    233230{
    234         uint8_t *start = *pptr;
    235         hdhomerun_write_u16(pptr, HDHOMERUN_TYPE_UPGRADE_REQ);
    236         hdhomerun_write_u16(pptr, 0);
     231        size_t length = pkt->end - pkt->start;
    237232
    238         hdhomerun_write_u32(pptr, sequence);
    239         if (length > 0) {
    240                 hdhomerun_write_mem(pptr, data, length);
    241         }
     233        pkt->start -= 4;
     234        pkt->pos = pkt->start;
     235        hdhomerun_pkt_write_u16(pkt, frame_type);
     236        hdhomerun_pkt_write_u16(pkt, (uint16_t)length);
    242237
    243         hdhomerun_write_header_length(start + 2, *pptr - start - 4);
    244         hdhomerun_write_crc(pptr, start);
    245 }
     238        uint32_t crc = hdhomerun_pkt_calc_crc(pkt->start, pkt->end);
     239        *pkt->end++ = (uint8_t)(crc >> 0);
     240        *pkt->end++ = (uint8_t)(crc >> 8);
     241        *pkt->end++ = (uint8_t)(crc >> 16);
     242        *pkt->end++ = (uint8_t)(crc >> 24);
    246243
    247 size_t hdhomerun_peek_packet_length(uint8_t *ptr)
    248 {
    249         ptr += 2;
    250         return (size_t)hdhomerun_read_u16(&ptr) + 8;
     244        pkt->pos = pkt->start;
    251245}
    252 
    253 int hdhomerun_process_packet(uint8_t **pptr, uint8_t **pend)
    254 {
    255         if (hdhomerun_check_crc(*pptr, *pend) < 0) {
    256                 return -1;
    257         }
    258         *pend -= 4;
    259        
    260         uint16_t type = hdhomerun_read_u16(pptr);
    261         uint16_t length = hdhomerun_read_u16(pptr);
    262         if ((*pend - *pptr) < length) {
    263                 return -1;
    264         }
    265         *pend = *pptr + length;
    266         return (int)type;
    267 }
    268 
  • mythtv/libs/libmythtv/hdhomerun/hdhomerun_pkt.h

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhomerun/hdhomerun_pkt.h release.19703.0116b/mythtv/libs/libmythtv/hdhomerun/hdhomerun_pkt.h
     
    11/*
    22 * hdhomerun_pkt.h
    33 *
    4  * Copyright © 2005-2006 Silicondust Engineering Ltd. <www.silicondust.com>.
     4 * Copyright © 2005-2006 Silicondust Engineering Ltd. <www.silicondust.com>.
    55 *
    6  * This library is free software; you can redistribute it and/or
     6 * This library is free software; you can redistribute it and/or 
    77 * modify it under the terms of the GNU Lesser General Public
    88 * License as published by the Free Software Foundation; either
    9  * version 2.1 of the License, or (at your option) any later version.
     9 * version 3 of the License, or (at your option) any later version.
    1010 *
    1111 * This library is distributed in the hope that it will be useful,
    1212 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     
    1414 * Lesser General Public License for more details.
    1515 *
    1616 * You should have received a copy of the GNU Lesser General Public
    17  * License along with this library; if not, write to the Free Software
    18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     17 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
     18 *
     19 * As a special exception to the GNU Lesser General Public License,
     20 * you may link, statically or dynamically, an application with a
     21 * publicly distributed version of the Library to produce an
     22 * executable file containing portions of the Library, and
     23 * distribute that executable file under terms of your choice,
     24 * without any of the additional requirements listed in clause 4 of
     25 * the GNU Lesser General Public License.
     26 *
     27 * By "a publicly distributed version of the Library", we mean
     28 * either the unmodified Library as distributed by Silicondust, or a
     29 * modified version of the Library that is distributed under the
     30 * conditions defined in the GNU Lesser General Public License.
    1931 */
    2032#ifdef __cplusplus
    2133extern "C" {
     
    110122#define HDHOMERUN_DISCOVER_UDP_PORT 65001
    111123#define HDHOMERUN_CONTROL_TCP_PORT 65001
    112124
     125#define HDHOMERUN_MAX_PACKET_SIZE 1460
     126#define HDHOMERUN_MAX_PAYLOAD_SIZE 1452
     127
    113128#define HDHOMERUN_TYPE_DISCOVER_REQ 0x0002
    114129#define HDHOMERUN_TYPE_DISCOVER_RPY 0x0003
    115130#define HDHOMERUN_TYPE_GETSET_REQ 0x0004
     
    121136#define HDHOMERUN_TAG_DEVICE_ID 0x02
    122137#define HDHOMERUN_TAG_GETSET_NAME 0x03
    123138#define HDHOMERUN_TAG_GETSET_VALUE 0x04
     139#define HDHOMERUN_TAG_GETSET_LOCKKEY 0x15
    124140#define HDHOMERUN_TAG_ERROR_MESSAGE 0x05
    125141
    126142#define HDHOMERUN_DEVICE_TYPE_WILDCARD 0xFFFFFFFF
     
    129145
    130146#define HDHOMERUN_MIN_PEEK_LENGTH 4
    131147
    132 extern uint8_t hdhomerun_read_u8(uint8_t **pptr);
    133 extern uint16_t hdhomerun_read_u16(uint8_t **pptr);
    134 extern uint32_t hdhomerun_read_u32(uint8_t **pptr);
    135 extern size_t hdhomerun_read_var_length(uint8_t **pptr, uint8_t *end);
    136 extern void hdhomerun_write_u8(uint8_t **pptr, uint8_t v);
    137 extern void hdhomerun_write_u16(uint8_t **pptr, uint16_t v);
    138 extern void hdhomerun_write_u32(uint8_t **pptr, uint32_t v);
    139 extern void hdhomerun_write_var_length(uint8_t **pptr, size_t v);
    140 extern void hdhomerun_write_crc(uint8_t **pptr, uint8_t *start);
    141 
    142 extern size_t hdhomerun_peek_packet_length(uint8_t *ptr);
    143 extern int hdhomerun_process_packet(uint8_t **pptr, uint8_t **pend);
    144 extern int hdhomerun_read_tlv(uint8_t **pptr, uint8_t *end, uint8_t *ptag, size_t *plength, uint8_t **pvalue);
    145 
    146 extern void hdhomerun_write_discover_request(uint8_t **pptr, uint32_t device_type, uint32_t device_id);
    147 extern void hdhomerun_write_get_set_request(uint8_t **pptr, const char *name, const char *value);
    148 extern void hdhomerun_write_upgrade_request(uint8_t **pptr, uint32_t sequence, void *data, size_t length);
     148struct hdhomerun_pkt_t {
     149        uint8_t *pos;
     150        uint8_t *start;
     151        uint8_t *end;
     152        uint8_t *limit;
     153        uint8_t buffer[3074];
     154};
     155
     156extern LIBTYPE struct hdhomerun_pkt_t *hdhomerun_pkt_create(void);
     157extern LIBTYPE void hdhomerun_pkt_destroy(struct hdhomerun_pkt_t *pkt);
     158extern LIBTYPE void hdhomerun_pkt_reset(struct hdhomerun_pkt_t *pkt);
     159
     160extern LIBTYPE uint8_t hdhomerun_pkt_read_u8(struct hdhomerun_pkt_t *pkt);
     161extern LIBTYPE uint16_t hdhomerun_pkt_read_u16(struct hdhomerun_pkt_t *pkt);
     162extern LIBTYPE uint32_t hdhomerun_pkt_read_u32(struct hdhomerun_pkt_t *pkt);
     163extern LIBTYPE size_t hdhomerun_pkt_read_var_length(struct hdhomerun_pkt_t *pkt);
     164extern LIBTYPE uint8_t *hdhomerun_pkt_read_tlv(struct hdhomerun_pkt_t *pkt, uint8_t *ptag, size_t *plength);
     165
     166extern LIBTYPE void hdhomerun_pkt_write_u8(struct hdhomerun_pkt_t *pkt, uint8_t v);
     167extern LIBTYPE void hdhomerun_pkt_write_u16(struct hdhomerun_pkt_t *pkt, uint16_t v);
     168extern LIBTYPE void hdhomerun_pkt_write_u32(struct hdhomerun_pkt_t *pkt, uint32_t v);
     169extern LIBTYPE void hdhomerun_pkt_write_var_length(struct hdhomerun_pkt_t *pkt, size_t v);
     170extern LIBTYPE void hdhomerun_pkt_write_mem(struct hdhomerun_pkt_t *pkt, const void *mem, size_t length);
     171
     172extern LIBTYPE bool_t hdhomerun_pkt_open_frame(struct hdhomerun_pkt_t *pkt, uint16_t *ptype);
     173extern LIBTYPE void hdhomerun_pkt_seal_frame(struct hdhomerun_pkt_t *pkt, uint16_t frame_type);
    149174
    150175#ifdef __cplusplus
    151176}
    152177#endif
    153 
  • mythtv/libs/libmythtv/hdhomerun/hdhomerun_types.h

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhomerun/hdhomerun_types.h release.19703.0116b/mythtv/libs/libmythtv/hdhomerun/hdhomerun_types.h
     
     1/*
     2 * hdhomerun_types.h
     3 *
     4 * Copyright © 2008 Silicondust Engineering Ltd. <www.silicondust.com>.
     5 *
     6 * This library is free software; you can redistribute it and/or
     7 * modify it under the terms of the GNU Lesser General Public
     8 * License as published by the Free Software Foundation; either
     9 * version 3 of the License, or (at your option) any later version.
     10 *
     11 * This library is distributed in the hope that it will be useful,
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14 * Lesser General Public License for more details.
     15 *
     16 * You should have received a copy of the GNU Lesser General Public
     17 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
     18 *
     19 * As a special exception to the GNU Lesser General Public License,
     20 * you may link, statically or dynamically, an application with a
     21 * publicly distributed version of the Library to produce an
     22 * executable file containing portions of the Library, and
     23 * distribute that executable file under terms of your choice,
     24 * without any of the additional requirements listed in clause 4 of
     25 * the GNU Lesser General Public License.
     26 *
     27 * By "a publicly distributed version of the Library", we mean
     28 * either the unmodified Library as distributed by Silicondust, or a
     29 * modified version of the Library that is distributed under the
     30 * conditions defined in the GNU Lesser General Public License.
     31 */
     32
     33struct hdhomerun_device_t;
     34
     35struct hdhomerun_tuner_status_t {
     36        char channel[32];
     37        char lock_str[32];
     38        bool_t signal_present;
     39        bool_t lock_supported;
     40        bool_t lock_unsupported;
     41        unsigned int signal_strength;
     42        unsigned int signal_to_noise_quality;
     43        unsigned int symbol_error_quality;
     44        uint32_t raw_bits_per_second;
     45        uint32_t packets_per_second;
     46};
     47
     48struct hdhomerun_channelscan_program_t {
     49        char program_str[64];
     50        uint16_t program_number;
     51        uint16_t virtual_major;
     52        uint16_t virtual_minor;
     53        uint16_t type;
     54        char name[32];
     55};
     56
     57#define HDHOMERUN_CHANNELSCAN_MAX_PROGRAM_COUNT 64
     58
     59struct hdhomerun_channelscan_result_t {
     60        char channel_str[64];
     61        uint32_t channelmap;
     62        uint32_t frequency;
     63        struct hdhomerun_tuner_status_t status;
     64        int program_count;
     65        struct hdhomerun_channelscan_program_t programs[HDHOMERUN_CHANNELSCAN_MAX_PROGRAM_COUNT];
     66};
     67
     68struct hdhomerun_plotsample_t {
     69        int16_t real;
     70        int16_t imag;
     71};
  • mythtv/libs/libmythtv/hdhomerun/hdhomerun_video.c

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhomerun/hdhomerun_video.c release.19703.0116b/mythtv/libs/libmythtv/hdhomerun/hdhomerun_video.c
     
    11/*
    22 * hdhomerun_video.c
    33 *
    4  * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
     4 * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
    55 *
    6  * This library is free software; you can redistribute it and/or
     6 * This library is free software; you can redistribute it and/or 
    77 * modify it under the terms of the GNU Lesser General Public
    88 * License as published by the Free Software Foundation; either
    9  * version 2.1 of the License, or (at your option) any later version.
     9 * version 3 of the License, or (at your option) any later version.
    1010 *
    1111 * This library is distributed in the hope that it will be useful,
    1212 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     
    1414 * Lesser General Public License for more details.
    1515 *
    1616 * You should have received a copy of the GNU Lesser General Public
    17  * License along with this library; if not, write to the Free Software
    18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     17 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
     18 *
     19 * As a special exception to the GNU Lesser General Public License,
     20 * you may link, statically or dynamically, an application with a
     21 * publicly distributed version of the Library to produce an
     22 * executable file containing portions of the Library, and
     23 * distribute that executable file under terms of your choice,
     24 * without any of the additional requirements listed in clause 4 of
     25 * the GNU Lesser General Public License.
     26 *
     27 * By "a publicly distributed version of the Library", we mean
     28 * either the unmodified Library as distributed by Silicondust, or a
     29 * modified version of the Library that is distributed under the
     30 * conditions defined in the GNU Lesser General Public License.
    1931 */
    2032
    21 #include "hdhomerun_os.h"
    22 #include "hdhomerun_pkt.h"
    23 #include "hdhomerun_video.h"
     33#include "hdhomerun.h"
    2434
    2535struct hdhomerun_video_sock_t {
     36        pthread_mutex_t lock;
    2637        uint8_t *buffer;
    2738        size_t buffer_size;
    2839        volatile size_t head;
    2940        volatile size_t tail;
    3041        size_t advance;
    31         volatile bool_t running;
    3242        volatile bool_t terminate;
    3343        pthread_t thread;
    3444        int sock;
     45        uint32_t rtp_sequence;
     46        struct hdhomerun_debug_t *dbg;
     47        volatile uint32_t packet_count;
     48        volatile uint32_t transport_error_count;
     49        volatile uint32_t network_error_count;
     50        volatile uint32_t sequence_error_count;
     51        volatile uint32_t overflow_error_count;
     52        volatile uint8_t sequence[0x2000];
    3553};
    3654
    37 static void *hdhomerun_video_thread(void *arg);
     55static THREAD_FUNC_PREFIX hdhomerun_video_thread_execute(void *arg);
    3856
    3957static bool_t hdhomerun_video_bind_sock_internal(struct hdhomerun_video_sock_t *vs, uint16_t listen_port)
    4058{
     
    8098                return NULL;
    8199        }
    82100
     101        pthread_mutex_init(&vs->lock, NULL);
     102
     103        /* Reset sequence tracking. */
     104        hdhomerun_video_flush(vs);
     105
    83106        /* Buffer size. */
    84107        vs->buffer_size = (buffer_size / VIDEO_DATA_PACKET_SIZE) * VIDEO_DATA_PACKET_SIZE;
    85108        if (vs->buffer_size == 0) {
     
    113136
    114137        /* Bind socket. */
    115138        if (!hdhomerun_video_bind_sock(vs, listen_port)) {
    116                 hdhomerun_video_destroy(vs);
     139                close(vs->sock);
     140                free(vs->buffer);
     141                free(vs);
    117142                return NULL;
    118143        }
    119144
    120145        /* Start thread. */
    121         if (pthread_create(&vs->thread, NULL, &hdhomerun_video_thread, vs) != 0) {
    122                 hdhomerun_video_destroy(vs);
     146        if (pthread_create(&vs->thread, NULL, &hdhomerun_video_thread_execute, vs) != 0) {
     147                close(vs->sock);
     148                free(vs->buffer);
     149                free(vs);
    123150                return NULL;
    124151        }
    125         vs->running = 1;
    126152
    127153        /* Success. */
    128154        return vs;
     
    130156
    131157void hdhomerun_video_destroy(struct hdhomerun_video_sock_t *vs)
    132158{
    133         if (vs->running) {
    134                 vs->terminate = 1;
    135                 pthread_join(vs->thread, NULL);
    136         }
     159        vs->terminate = TRUE;
     160        pthread_join(vs->thread, NULL);
     161
    137162        close(vs->sock);
    138163        free(vs->buffer);
     164
    139165        free(vs);
    140166}
    141167
     168void hdhomerun_video_set_debug(struct hdhomerun_video_sock_t *vs, struct hdhomerun_debug_t *dbg)
     169{
     170        vs->dbg = dbg;
     171}
     172
    142173uint16_t hdhomerun_video_get_local_port(struct hdhomerun_video_sock_t *vs)
    143174{
    144175        struct sockaddr_in sock_addr;
    145176        socklen_t sockaddr_size = sizeof(sock_addr);
    146177        if (getsockname(vs->sock, (struct sockaddr*)&sock_addr, &sockaddr_size) != 0) {
     178                hdhomerun_debug_printf(vs->dbg, "hdhomerun_video_get_local_port: getsockname failed (%d)\n", sock_getlasterror);
    147179                return 0;
    148180        }
    149181        return ntohs(sock_addr.sin_port);
    150182}
    151183
    152 int hdhomerun_video_get_sock(struct hdhomerun_video_sock_t *vs)
     184static void hdhomerun_video_stats_ts_pkt(struct hdhomerun_video_sock_t *vs, uint8_t *ptr)
    153185{
    154         return vs->sock;
     186        uint16_t packet_identifier = ((uint16_t)(ptr[1] & 0x1F) << 8) | (uint16_t)ptr[2];
     187        if (packet_identifier == 0x1FFF) {
     188                return;
     189        }
     190
     191        bool_t transport_error = ptr[1] >> 7;
     192        if (transport_error) {
     193                vs->transport_error_count++;
     194                vs->sequence[packet_identifier] = 0xFF;
     195                return;
     196        }
     197
     198        uint8_t continuity_counter = ptr[3] & 0x0F;
     199        uint8_t previous_sequence = vs->sequence[packet_identifier];
     200
     201        if (continuity_counter == ((previous_sequence + 1) & 0x0F)) {
     202                vs->sequence[packet_identifier] = continuity_counter;
     203                return;
     204        }
     205        if (previous_sequence == 0xFF) {
     206                vs->sequence[packet_identifier] = continuity_counter;
     207                return;
     208        }
     209        if (continuity_counter == previous_sequence) {
     210                return;
     211        }
     212
     213        vs->sequence_error_count++;
     214        vs->sequence[packet_identifier] = continuity_counter;
    155215}
    156216
    157 static void *hdhomerun_video_thread(void *arg)
     217static void hdhomerun_video_parse_rtp(struct hdhomerun_video_sock_t *vs, struct hdhomerun_pkt_t *pkt)
     218{
     219        pkt->pos += 2;
     220        uint32_t rtp_sequence = hdhomerun_pkt_read_u16(pkt);
     221        pkt->pos += 8;
     222
     223        if (rtp_sequence != ((vs->rtp_sequence + 1) & 0xFFFF)) {
     224                if (vs->rtp_sequence != 0xFFFFFFFF) {
     225                        vs->network_error_count++;
     226
     227                        /* restart pid sequence check */
     228                        memset((void *)vs->sequence, 0xFF, sizeof(vs->sequence));
     229                }
     230        }
     231
     232        vs->rtp_sequence = rtp_sequence;
     233}
     234
     235static THREAD_FUNC_PREFIX hdhomerun_video_thread_execute(void *arg)
    158236{
    159237        struct hdhomerun_video_sock_t *vs = (struct hdhomerun_video_sock_t *)arg;
     238        struct hdhomerun_pkt_t pkt_inst;
    160239
    161240        while (!vs->terminate) {
    162                 size_t head = vs->head;
     241                struct hdhomerun_pkt_t *pkt = &pkt_inst;
     242                hdhomerun_pkt_reset(pkt);
    163243
    164244                /* Receive. */
    165                 int length = recv(vs->sock, (char *)vs->buffer + head, VIDEO_DATA_PACKET_SIZE, 0);
     245                int length = recv(vs->sock, (char *)pkt->end, VIDEO_RTP_DATA_PACKET_SIZE, 0);
     246                pkt->end += length;
     247
     248                if (length == VIDEO_RTP_DATA_PACKET_SIZE) {
     249                        hdhomerun_video_parse_rtp(vs, pkt);
     250                        length = (int)(pkt->end - pkt->pos);
     251                }
     252
    166253                if (length != VIDEO_DATA_PACKET_SIZE) {
    167254                        if (length > 0) {
    168255                                /* Data received but not valid - ignore. */
     
    172259                                /* Wait for more data. */
    173260                                continue;
    174261                        }
    175                         vs->terminate = 1;
     262                        vs->terminate = TRUE;
    176263                        return NULL;
    177264                }
    178265
     266                pthread_mutex_lock(&vs->lock);
     267
     268                /* Store in ring buffer. */
     269                size_t head = vs->head;
     270                uint8_t *ptr = vs->buffer + head;
     271                memcpy(ptr, pkt->pos, length);
     272
     273                /* Stats. */
     274                vs->packet_count++;
     275                hdhomerun_video_stats_ts_pkt(vs, ptr + TS_PACKET_SIZE * 0);
     276                hdhomerun_video_stats_ts_pkt(vs, ptr + TS_PACKET_SIZE * 1);
     277                hdhomerun_video_stats_ts_pkt(vs, ptr + TS_PACKET_SIZE * 2);
     278                hdhomerun_video_stats_ts_pkt(vs, ptr + TS_PACKET_SIZE * 3);
     279                hdhomerun_video_stats_ts_pkt(vs, ptr + TS_PACKET_SIZE * 4);
     280                hdhomerun_video_stats_ts_pkt(vs, ptr + TS_PACKET_SIZE * 5);
     281                hdhomerun_video_stats_ts_pkt(vs, ptr + TS_PACKET_SIZE * 6);
     282
    179283                /* Calculate new head. */
    180284                head += length;
    181285                if (head >= vs->buffer_size) {
     
    184288
    185289                /* Check for buffer overflow. */
    186290                if (head == vs->tail) {
     291                        vs->overflow_error_count++;
     292                        pthread_mutex_unlock(&vs->lock);
    187293                        continue;
    188294                }
    189295
    190296                /* Atomic update. */
    191297                vs->head = head;
     298
     299                pthread_mutex_unlock(&vs->lock);
    192300        }
    193301
    194302        return NULL;
     
    196304
    197305uint8_t *hdhomerun_video_recv(struct hdhomerun_video_sock_t *vs, size_t max_size, size_t *pactual_size)
    198306{
     307        pthread_mutex_lock(&vs->lock);
     308
    199309        size_t head = vs->head;
    200310        size_t tail = vs->tail;
    201311
     
    212322        if (head == tail) {
    213323                vs->advance = 0;
    214324                *pactual_size = 0;
     325                pthread_mutex_unlock(&vs->lock);
    215326                return NULL;
    216327        }
    217328
     
    219330        if (size == 0) {
    220331                vs->advance = 0;
    221332                *pactual_size = 0;
     333                pthread_mutex_unlock(&vs->lock);
    222334                return NULL;
    223335        }
    224336
     
    233345        }
    234346        vs->advance = size;
    235347        *pactual_size = size;
    236         return vs->buffer + tail;
     348        uint8_t *result = vs->buffer + tail;
     349
     350        pthread_mutex_unlock(&vs->lock);
     351        return result;
    237352}
    238353
    239354void hdhomerun_video_flush(struct hdhomerun_video_sock_t *vs)
    240355{
    241         /* Atomic update of tail. */
     356        pthread_mutex_lock(&vs->lock);
     357
    242358        vs->tail = vs->head;
    243359        vs->advance = 0;
     360
     361        memset((void *)vs->sequence, 0xFF, sizeof(vs->sequence));
     362
     363        vs->rtp_sequence = 0xFFFFFFFF;
     364
     365        vs->packet_count = 0;
     366        vs->transport_error_count = 0;
     367        vs->network_error_count = 0;
     368        vs->sequence_error_count = 0;
     369        vs->overflow_error_count = 0;
     370
     371        pthread_mutex_unlock(&vs->lock);
    244372}
    245373
     374void hdhomerun_video_debug_print_stats(struct hdhomerun_video_sock_t *vs)
     375{
     376        struct hdhomerun_video_stats_t stats;
     377        hdhomerun_video_get_stats(vs, &stats);
     378
     379        hdhomerun_debug_printf(vs->dbg, "video sock: pkt=%ld net=%ld te=%ld miss=%ld drop=%ld\n",
     380                stats.packet_count, stats.network_error_count,
     381                stats.transport_error_count, stats.sequence_error_count,
     382                stats.overflow_error_count
     383        );
     384}
     385
     386void hdhomerun_video_get_stats(struct hdhomerun_video_sock_t *vs, struct hdhomerun_video_stats_t *stats)
     387{
     388        memset(stats, 0, sizeof(struct hdhomerun_video_stats_t));
     389
     390        pthread_mutex_lock(&vs->lock);
     391
     392        stats->packet_count = vs->packet_count;
     393        stats->network_error_count = vs->network_error_count;
     394        stats->transport_error_count = vs->transport_error_count;
     395        stats->sequence_error_count = vs->sequence_error_count;
     396        stats->overflow_error_count = vs->overflow_error_count;
     397
     398        pthread_mutex_unlock(&vs->lock);
     399}
  • mythtv/libs/libmythtv/hdhomerun/hdhomerun_video.h

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhomerun/hdhomerun_video.h release.19703.0116b/mythtv/libs/libmythtv/hdhomerun/hdhomerun_video.h
     
    11/*
    22 * hdhomerun_video.h
    33 *
    4  * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
     4 * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
    55 *
    6  * This library is free software; you can redistribute it and/or
     6 * This library is free software; you can redistribute it and/or 
    77 * modify it under the terms of the GNU Lesser General Public
    88 * License as published by the Free Software Foundation; either
    9  * version 2.1 of the License, or (at your option) any later version.
     9 * version 3 of the License, or (at your option) any later version.
    1010 *
    1111 * This library is distributed in the hope that it will be useful,
    1212 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     
    1414 * Lesser General Public License for more details.
    1515 *
    1616 * You should have received a copy of the GNU Lesser General Public
    17  * License along with this library; if not, write to the Free Software
    18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     17 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
     18 *
     19 * As a special exception to the GNU Lesser General Public License,
     20 * you may link, statically or dynamically, an application with a
     21 * publicly distributed version of the Library to produce an
     22 * executable file containing portions of the Library, and
     23 * distribute that executable file under terms of your choice,
     24 * without any of the additional requirements listed in clause 4 of
     25 * the GNU Lesser General Public License.
     26 *
     27 * By "a publicly distributed version of the Library", we mean
     28 * either the unmodified Library as distributed by Silicondust, or a
     29 * modified version of the Library that is distributed under the
     30 * conditions defined in the GNU Lesser General Public License.
    1931 */
    2032#ifdef __cplusplus
    2133extern "C" {
     
    2335
    2436struct hdhomerun_video_sock_t;
    2537
     38struct hdhomerun_video_stats_t {
     39        uint32_t packet_count;
     40        uint32_t network_error_count;
     41        uint32_t transport_error_count;
     42        uint32_t sequence_error_count;
     43        uint32_t overflow_error_count;
     44};
     45
    2646#define TS_PACKET_SIZE 188
    2747#define VIDEO_DATA_PACKET_SIZE (188 * 7)
    2848#define VIDEO_DATA_BUFFER_SIZE_1S (20000000 / 8)
    2949
     50#define VIDEO_RTP_DATA_PACKET_SIZE ((188 * 7) + 12)
     51
    3052/*
    3153 * Create a video/data socket.
    3254 *
     
    3759 *
    3860 * When no longer needed, the socket should be destroyed by calling hdhomerun_control_destroy.
    3961 */
    40 extern struct hdhomerun_video_sock_t *hdhomerun_video_create(uint16_t listen_port, size_t buffer_size);
    41 extern void hdhomerun_video_destroy(struct hdhomerun_video_sock_t *vs);
     62extern LIBTYPE struct hdhomerun_video_sock_t *hdhomerun_video_create(uint16_t listen_port, size_t buffer_size);
     63extern LIBTYPE void hdhomerun_video_destroy(struct hdhomerun_video_sock_t *vs);
    4264
    4365/*
    4466 * Get the port the socket is listening on.
    4567 *
    4668 * Returns 16-bit port with native endianness, or 0 on error.
    4769 */
    48 extern uint16_t hdhomerun_video_get_local_port(struct hdhomerun_video_sock_t *vs);
    49 
    50 /*
    51  * Get the low-level socket handle.
    52  */
    53 extern int hdhomerun_video_get_sock(struct hdhomerun_video_sock_t *vs);
     70extern LIBTYPE uint16_t hdhomerun_video_get_local_port(struct hdhomerun_video_sock_t *vs);
    5471
    5572/*
    5673 * Read data from buffer.
     
    6986 * The buffer is implemented as a ring buffer. It is possible for this function to return a small
    7087 * amount of data when more is available due to the wrap-around case.
    7188 */
    72 extern uint8_t *hdhomerun_video_recv(struct hdhomerun_video_sock_t *vs, size_t max_size, size_t *pactual_size);
     89extern LIBTYPE uint8_t *hdhomerun_video_recv(struct hdhomerun_video_sock_t *vs, size_t max_size, size_t *pactual_size);
    7390
    7491/*
    7592 * Flush the buffer.
    7693 */
    77 extern void hdhomerun_video_flush(struct hdhomerun_video_sock_t *vs);
     94extern LIBTYPE void hdhomerun_video_flush(struct hdhomerun_video_sock_t *vs);
     95
     96/*
     97 * Debug print internal stats.
     98 */
     99extern LIBTYPE void hdhomerun_video_set_debug(struct hdhomerun_video_sock_t *vs, struct hdhomerun_debug_t *dbg);
     100extern LIBTYPE void hdhomerun_video_debug_print_stats(struct hdhomerun_video_sock_t *vs);
     101
     102extern LIBTYPE void hdhomerun_video_get_stats(struct hdhomerun_video_sock_t *vs, struct hdhomerun_video_stats_t *stats);
    78103
    79104#ifdef __cplusplus
    80105}
  • mythtv/libs/libmythtv/hdhomerun/lgpl.txt

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhomerun/lgpl.txt release.19703.0116b/mythtv/libs/libmythtv/hdhomerun/lgpl.txt
     
    1                   GNU LESSER GENERAL PUBLIC LICENSE
    2                        Version 2.1, February 1999
     1                   GNU LESSER GENERAL PUBLIC LICENSE
     2                       Version 3, 29 June 2007
    33
    4  Copyright (C) 1991, 1999 Free Software Foundation, Inc.
    5  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     4 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
    65 Everyone is permitted to copy and distribute verbatim copies
    76 of this license document, but changing it is not allowed.
    87
    9 [This is the first released version of the Lesser GPL.  It also counts
    10  as the successor of the GNU Library Public License, version 2, hence
    11  the version number 2.1.]
    12 
    13                             Preamble
    14 
    15   The licenses for most software are designed to take away your
    16 freedom to share and change it.  By contrast, the GNU General Public
    17 Licenses are intended to guarantee your freedom to share and change
    18 free software--to make sure the software is free for all its users.
    19 
    20   This license, the Lesser General Public License, applies to some
    21 specially designated software packages--typically libraries--of the
    22 Free Software Foundation and other authors who decide to use it.  You
    23 can use it too, but we suggest you first think carefully about whether
    24 this license or the ordinary General Public License is the better
    25 strategy to use in any particular case, based on the explanations below.
    26 
    27   When we speak of free software, we are referring to freedom of use,
    28 not price.  Our General Public Licenses are designed to make sure that
    29 you have the freedom to distribute copies of free software (and charge
    30 for this service if you wish); that you receive source code or can get
    31 it if you want it; that you can change the software and use pieces of
    32 it in new free programs; and that you are informed that you can do
    33 these things.
    34 
    35   To protect your rights, we need to make restrictions that forbid
    36 distributors to deny you these rights or to ask you to surrender these
    37 rights.  These restrictions translate to certain responsibilities for
    38 you if you distribute copies of the library or if you modify it.
    39 
    40   For example, if you distribute copies of the library, whether gratis
    41 or for a fee, you must give the recipients all the rights that we gave
    42 you.  You must make sure that they, too, receive or can get the source
    43 code.  If you link other code with the library, you must provide
    44 complete object files to the recipients, so that they can relink them
    45 with the library after making changes to the library and recompiling
    46 it.  And you must show them these terms so they know their rights.
    47 
    48   We protect your rights with a two-step method: (1) we copyright the
    49 library, and (2) we offer you this license, which gives you legal
    50 permission to copy, distribute and/or modify the library.
    51 
    52   To protect each distributor, we want to make it very clear that
    53 there is no warranty for the free library.  Also, if the library is
    54 modified by someone else and passed on, the recipients should know
    55 that what they have is not the original version, so that the original
    56 author's reputation will not be affected by problems that might be
    57 introduced by others.
    58 
    598
    60   Finally, software patents pose a constant threat to the existence of
    61 any free program.  We wish to make sure that a company cannot
    62 effectively restrict the users of a free program by obtaining a
    63 restrictive license from a patent holder.  Therefore, we insist that
    64 any patent license obtained for a version of the library must be
    65 consistent with the full freedom of use specified in this license.
    66 
    67   Most GNU software, including some libraries, is covered by the
    68 ordinary GNU General Public License.  This license, the GNU Lesser
    69 General Public License, applies to certain designated libraries, and
    70 is quite different from the ordinary General Public License.  We use
    71 this license for certain libraries in order to permit linking those
    72 libraries into non-free programs.
    73 
    74   When a program is linked with a library, whether statically or using
    75 a shared library, the combination of the two is legally speaking a
    76 combined work, a derivative of the original library.  The ordinary
    77 General Public License therefore permits such linking only if the
    78 entire combination fits its criteria of freedom.  The Lesser General
    79 Public License permits more lax criteria for linking other code with
    80 the library.
    81 
    82   We call this license the "Lesser" General Public License because it
    83 does Less to protect the user's freedom than the ordinary General
    84 Public License.  It also provides other free software developers Less
    85 of an advantage over competing non-free programs.  These disadvantages
    86 are the reason we use the ordinary General Public License for many
    87 libraries.  However, the Lesser license provides advantages in certain
    88 special circumstances.
    89 
    90   For example, on rare occasions, there may be a special need to
    91 encourage the widest possible use of a certain library, so that it becomes
    92 a de-facto standard.  To achieve this, non-free programs must be
    93 allowed to use the library.  A more frequent case is that a free
    94 library does the same job as widely used non-free libraries.  In this
    95 case, there is little to gain by limiting the free library to free
    96 software only, so we use the Lesser General Public License.
    97 
    98   In other cases, permission to use a particular library in non-free
    99 programs enables a greater number of people to use a large body of
    100 free software.  For example, permission to use the GNU C Library in
    101 non-free programs enables many more people to use the whole GNU
    102 operating system, as well as its variant, the GNU/Linux operating
    103 system.
    104 
    105   Although the Lesser General Public License is Less protective of the
    106 users' freedom, it does ensure that the user of a program that is
    107 linked with the Library has the freedom and the wherewithal to run
    108 that program using a modified version of the Library.
    109 
    110   The precise terms and conditions for copying, distribution and
    111 modification follow.  Pay close attention to the difference between a
    112 "work based on the library" and a "work that uses the library".  The
    113 former contains code derived from the library, whereas the latter must
    114 be combined with the library in order to run.
    115 
    1169
    117                   GNU LESSER GENERAL PUBLIC LICENSE
    118    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
    119 
    120   0. This License Agreement applies to any software library or other
    121 program which contains a notice placed by the copyright holder or
    122 other authorized party saying it may be distributed under the terms of
    123 this Lesser General Public License (also called "this License").
    124 Each licensee is addressed as "you".
    125 
    126   A "library" means a collection of software functions and/or data
    127 prepared so as to be conveniently linked with application programs
    128 (which use some of those functions and data) to form executables.
    129 
    130   The "Library", below, refers to any such software library or work
    131 which has been distributed under these terms.  A "work based on the
    132 Library" means either the Library or any derivative work under
    133 copyright law: that is to say, a work containing the Library or a
    134 portion of it, either verbatim or with modifications and/or translated
    135 straightforwardly into another language.  (Hereinafter, translation is
    136 included without limitation in the term "modification".)
    137 
    138   "Source code" for a work means the preferred form of the work for
    139 making modifications to it.  For a library, complete source code means
    140 all the source code for all modules it contains, plus any associated
    141 interface definition files, plus the scripts used to control compilation
    142 and installation of the library.
    143 
    144   Activities other than copying, distribution and modification are not
    145 covered by this License; they are outside its scope.  The act of
    146 running a program using the Library is not restricted, and output from
    147 such a program is covered only if its contents constitute a work based
    148 on the Library (independent of the use of the Library in a tool for
    149 writing it).  Whether that is true depends on what the Library does
    150 and what the program that uses the Library does.
    151  
    152   1. You may copy and distribute verbatim copies of the Library's
    153 complete source code as you receive it, in any medium, provided that
    154 you conspicuously and appropriately publish on each copy an
    155 appropriate copyright notice and disclaimer of warranty; keep intact
    156 all the notices that refer to this License and to the absence of any
    157 warranty; and distribute a copy of this License along with the
    158 Library.
    159 
    160   You may charge a fee for the physical act of transferring a copy,
    161 and you may at your option offer warranty protection in exchange for a
    162 fee.
    163 
    16410
    165   2. You may modify your copy or copies of the Library or any portion
    166 of it, thus forming a work based on the Library, and copy and
    167 distribute such modifications or work under the terms of Section 1
    168 above, provided that you also meet all of these conditions:
    169 
    170     a) The modified work must itself be a software library.
    171 
    172     b) You must cause the files modified to carry prominent notices
    173     stating that you changed the files and the date of any change.
    174 
    175     c) You must cause the whole of the work to be licensed at no
    176     charge to all third parties under the terms of this License.
    177 
    178     d) If a facility in the modified Library refers to a function or a
    179     table of data to be supplied by an application program that uses
    180     the facility, other than as an argument passed when the facility
    181     is invoked, then you must make a good faith effort to ensure that,
    182     in the event an application does not supply such function or
    183     table, the facility still operates, and performs whatever part of
    184     its purpose remains meaningful.
    185 
    186     (For example, a function in a library to compute square roots has
    187     a purpose that is entirely well-defined independent of the
    188     application.  Therefore, Subsection 2d requires that any
    189     application-supplied function or table used by this function must
    190     be optional: if the application does not supply it, the square
    191     root function must still compute square roots.)
    192 
    193 These requirements apply to the modified work as a whole.  If
    194 identifiable sections of that work are not derived from the Library,
    195 and can be reasonably considered independent and separate works in
    196 themselves, then this License, and its terms, do not apply to those
    197 sections when you distribute them as separate works.  But when you
    198 distribute the same sections as part of a whole which is a work based
    199 on the Library, the distribution of the whole must be on the terms of
    200 this License, whose permissions for other licensees extend to the
    201 entire whole, and thus to each and every part regardless of who wrote
    202 it.
    203 
    204 Thus, it is not the intent of this section to claim rights or contest
    205 your rights to work written entirely by you; rather, the intent is to
    206 exercise the right to control the distribution of derivative or
    207 collective works based on the Library.
    208 
    209 In addition, mere aggregation of another work not based on the Library
    210 with the Library (or with a work based on the Library) on a volume of
    211 a storage or distribution medium does not bring the other work under
    212 the scope of this License.
    213 
    214   3. You may opt to apply the terms of the ordinary GNU General Public
    215 License instead of this License to a given copy of the Library.  To do
    216 this, you must alter all the notices that refer to this License, so
    217 that they refer to the ordinary GNU General Public License, version 2,
    218 instead of to this License.  (If a newer version than version 2 of the
    219 ordinary GNU General Public License has appeared, then you can specify
    220 that version instead if you wish.)  Do not make any other change in
    221 these notices.
    222 
    22311
    224   Once this change is made in a given copy, it is irreversible for
    225 that copy, so the ordinary GNU General Public License applies to all
    226 subsequent copies and derivative works made from that copy.
    227 
    228   This option is useful when you wish to copy part of the code of
    229 the Library into a program that is not a library.
    230 
    231   4. You may copy and distribute the Library (or a portion or
    232 derivative of it, under Section 2) in object code or executable form
    233 under the terms of Sections 1 and 2 above provided that you accompany
    234 it with the complete corresponding machine-readable source code, which
    235 must be distributed under the terms of Sections 1 and 2 above on a
    236 medium customarily used for software interchange.
    237 
    238   If distribution of object code is made by offering access to copy
    239 from a designated place, then offering equivalent access to copy the
    240 source code from the same place satisfies the requirement to
    241 distribute the source code, even though third parties are not
    242 compelled to copy the source along with the object code.
    243 
    244   5. A program that contains no derivative of any portion of the
    245 Library, but is designed to work with the Library by being compiled or
    246 linked with it, is called a "work that uses the Library".  Such a
    247 work, in isolation, is not a derivative work of the Library, and
    248 therefore falls outside the scope of this License.
    249 
    250   However, linking a "work that uses the Library" with the Library
    251 creates an executable that is a derivative of the Library (because it
    252 contains portions of the Library), rather than a "work that uses the
    253 library".  The executable is therefore covered by this License.
    254 Section 6 states terms for distribution of such executables.
    255 
    256   When a "work that uses the Library" uses material from a header file
    257 that is part of the Library, the object code for the work may be a
    258 derivative work of the Library even though the source code is not.
    259 Whether this is true is especially significant if the work can be
    260 linked without the Library, or if the work is itself a library.  The
    261 threshold for this to be true is not precisely defined by law.
    262 
    263   If such an object file uses only numerical parameters, data
    264 structure layouts and accessors, and small macros and small inline
    265 functions (ten lines or less in length), then the use of the object
    266 file is unrestricted, regardless of whether it is legally a derivative
    267 work.  (Executables containing this object code plus portions of the
    268 Library will still fall under Section 6.)
    269 
    270   Otherwise, if the work is a derivative of the Library, you may
    271 distribute the object code for the work under the terms of Section 6.
    272 Any executables containing that work also fall under Section 6,
    273 whether or not they are linked directly with the Library itself.
    274 
    27512
    276   6. As an exception to the Sections above, you may also combine or
    277 link a "work that uses the Library" with the Library to produce a
    278 work containing portions of the Library, and distribute that work
    279 under terms of your choice, provided that the terms permit
    280 modification of the work for the customer's own use and reverse
    281 engineering for debugging such modifications.
    282 
    283   You must give prominent notice with each copy of the work that the
    284 Library is used in it and that the Library and its use are covered by
    285 this License.  You must supply a copy of this License.  If the work
    286 during execution displays copyright notices, you must include the
    287 copyright notice for the Library among them, as well as a reference
    288 directing the user to the copy of this License.  Also, you must do one
    289 of these things:
    290 
    291     a) Accompany the work with the complete corresponding
    292     machine-readable source code for the Library including whatever
    293     changes were used in the work (which must be distributed under
    294     Sections 1 and 2 above); and, if the work is an executable linked
    295     with the Library, with the complete machine-readable "work that
    296     uses the Library", as object code and/or source code, so that the
    297     user can modify the Library and then relink to produce a modified
    298     executable containing the modified Library.  (It is understood
    299     that the user who changes the contents of definitions files in the
    300     Library will not necessarily be able to recompile the application
    301     to use the modified definitions.)
    302 
    303     b) Use a suitable shared library mechanism for linking with the
    304     Library.  A suitable mechanism is one that (1) uses at run time a
    305     copy of the library already present on the user's computer system,
    306     rather than copying library functions into the executable, and (2)
    307     will operate properly with a modified version of the library, if
    308     the user installs one, as long as the modified version is
    309     interface-compatible with the version that the work was made with.
    310 
    311     c) Accompany the work with a written offer, valid for at
    312     least three years, to give the same user the materials
    313     specified in Subsection 6a, above, for a charge no more
    314     than the cost of performing this distribution.
    315 
    316     d) If distribution of the work is made by offering access to copy
    317     from a designated place, offer equivalent access to copy the above
    318     specified materials from the same place.
    319 
    320     e) Verify that the user has already received a copy of these
    321     materials or that you have already sent this user a copy.
    322 
    323   For an executable, the required form of the "work that uses the
    324 Library" must include any data and utility programs needed for
    325 reproducing the executable from it.  However, as a special exception,
    326 the materials to be distributed need not include anything that is
    327 normally distributed (in either source or binary form) with the major
    328 components (compiler, kernel, and so on) of the operating system on
    329 which the executable runs, unless that component itself accompanies
    330 the executable.
    331 
    332   It may happen that this requirement contradicts the license
    333 restrictions of other proprietary libraries that do not normally
    334 accompany the operating system.  Such a contradiction means you cannot
    335 use both them and the Library together in an executable that you
    336 distribute.
    337 
    33813
    339   7. You may place library facilities that are a work based on the
    340 Library side-by-side in a single library together with other library
    341 facilities not covered by this License, and distribute such a combined
    342 library, provided that the separate distribution of the work based on
    343 the Library and of the other library facilities is otherwise
    344 permitted, and provided that you do these two things:
    345 
    346     a) Accompany the combined library with a copy of the same work
    347     based on the Library, uncombined with any other library
    348     facilities.  This must be distributed under the terms of the
    349     Sections above.
    350 
    351     b) Give prominent notice with the combined library of the fact
    352     that part of it is a work based on the Library, and explaining
    353     where to find the accompanying uncombined form of the same work.
    354 
    355   8. You may not copy, modify, sublicense, link with, or distribute
    356 the Library except as expressly provided under this License.  Any
    357 attempt otherwise to copy, modify, sublicense, link with, or
    358 distribute the Library is void, and will automatically terminate your
    359 rights under this License.  However, parties who have received copies,
    360 or rights, from you under this License will not have their licenses
    361 terminated so long as such parties remain in full compliance.
    362 
    363   9. You are not required to accept this License, since you have not
    364 signed it.  However, nothing else grants you permission to modify or
    365 distribute the Library or its derivative works.  These actions are
    366 prohibited by law if you do not accept this License.  Therefore, by
    367 modifying or distributing the Library (or any work based on the
    368 Library), you indicate your acceptance of this License to do so, and
    369 all its terms and conditions for copying, distributing or modifying
    370 the Library or works based on it.
    371 
    372   10. Each time you redistribute the Library (or any work based on the
    373 Library), the recipient automatically receives a license from the
    374 original licensor to copy, distribute, link with or modify the Library
    375 subject to these terms and conditions.  You may not impose any further
    376 restrictions on the recipients' exercise of the rights granted herein.
    377 You are not responsible for enforcing compliance by third parties with
    378 this License.
    379 
    38014
    381   11. If, as a consequence of a court judgment or allegation of patent
    382 infringement or for any other reason (not limited to patent issues),
    383 conditions are imposed on you (whether by court order, agreement or
    384 otherwise) that contradict the conditions of this License, they do not
    385 excuse you from the conditions of this License.  If you cannot
    386 distribute so as to satisfy simultaneously your obligations under this
    387 License and any other pertinent obligations, then as a consequence you
    388 may not distribute the Library at all.  For example, if a patent
    389 license would not permit royalty-free redistribution of the Library by
    390 all those who receive copies directly or indirectly through you, then
    391 the only way you could satisfy both it and this License would be to
    392 refrain entirely from distribution of the Library.
    393 
    394 If any portion of this section is held invalid or unenforceable under any
    395 particular circumstance, the balance of the section is intended to apply,
    396 and the section as a whole is intended to apply in other circumstances.
    397 
    398 It is not the purpose of this section to induce you to infringe any
    399 patents or other property right claims or to contest validity of any
    400 such claims; this section has the sole purpose of protecting the
    401 integrity of the free software distribution system which is
    402 implemented by public license practices.  Many people have made
    403 generous contributions to the wide range of software distributed
    404 through that system in reliance on consistent application of that
    405 system; it is up to the author/donor to decide if he or she is willing
    406 to distribute software through any other system and a licensee cannot
    407 impose that choice.
    408 
    409 This section is intended to make thoroughly clear what is believed to
    410 be a consequence of the rest of this License.
    411 
    412   12. If the distribution and/or use of the Library is restricted in
    413 certain countries either by patents or by copyrighted interfaces, the
    414 original copyright holder who places the Library under this License may add
    415 an explicit geographical distribution limitation excluding those countries,
    416 so that distribution is permitted only in or among countries not thus
    417 excluded.  In such case, this License incorporates the limitation as if
    418 written in the body of this License.
    419 
    420   13. The Free Software Foundation may publish revised and/or new
    421 versions of the Lesser General Public License from time to time.
    422 Such new versions will be similar in spirit to the present version,
    423 but may differ in detail to address new problems or concerns.
    424 
    425 Each version is given a distinguishing version number.  If the Library
    426 specifies a version number of this License which applies to it and
    427 "any later version", you have the option of following the terms and
    428 conditions either of that version or of any later version published by
    429 the Free Software Foundation.  If the Library does not specify a
    430 license version number, you may choose any version ever published by
    431 the Free Software Foundation.
    432 
    43315
    434   14. If you wish to incorporate parts of the Library into other free
    435 programs whose distribution conditions are incompatible with these,
    436 write to the author to ask for permission.  For software which is
    437 copyrighted by the Free Software Foundation, write to the Free
    438 Software Foundation; we sometimes make exceptions for this.  Our
    439 decision will be guided by the two goals of preserving the free status
    440 of all derivatives of our free software and of promoting the sharing
    441 and reuse of software generally.
    442 
    443                             NO WARRANTY
    444 
    445   15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
    446 WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
    447 EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
    448 OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
    449 KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
    450 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    451 PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
    452 LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
    453 THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
    454 
    455   16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
    456 WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
    457 AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
    458 FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
    459 CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
    460 LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
    461 RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
    462 FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
    463 SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
    464 DAMAGES.
    465 
    466                      END OF TERMS AND CONDITIONS
    467 
    46816
    469            How to Apply These Terms to Your New Libraries
    470 
    471   If you develop a new library, and you want it to be of the greatest
    472 possible use to the public, we recommend making it free software that
    473 everyone can redistribute and change.  You can do so by permitting
    474 redistribution under these terms (or, alternatively, under the terms of the
    475 ordinary General Public License).
    476 
    477   To apply these terms, attach the following notices to the library.  It is
    478 safest to attach them to the start of each source file to most effectively
    479 convey the exclusion of warranty; and each file should have at least the
    480 "copyright" line and a pointer to where the full notice is found.
    481 
    482     <one line to give the library's name and a brief idea of what it does.>
    483     Copyright (C) <year>  <name of author>
    484 
    485     This library is free software; you can redistribute it and/or
    486     modify it under the terms of the GNU Lesser General Public
    487     License as published by the Free Software Foundation; either
    488     version 2.1 of the License, or (at your option) any later version.
    489 
    490     This library is distributed in the hope that it will be useful,
    491     but WITHOUT ANY WARRANTY; without even the implied warranty of
    492     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    493     Lesser General Public License for more details.
    494 
    495     You should have received a copy of the GNU Lesser General Public
    496     License along with this library; if not, write to the Free Software
    497     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
    498 
    499 Also add information on how to contact you by electronic and paper mail.
    500 
    501 You should also get your employer (if you work as a programmer) or your
    502 school, if any, to sign a "copyright disclaimer" for the library, if
    503 necessary.  Here is a sample; alter the names:
    504 
    505   Yoyodyne, Inc., hereby disclaims all copyright interest in the
    506   library `Frob' (a library for tweaking knobs) written by James Random Hacker.
    507 
    508   <signature of Ty Coon>, 1 April 1990
    509   Ty Coon, President of Vice
    510 
    511 That's all there is to it!
    512 
    51317
     18  This version of the GNU Lesser General Public License incorporates
     19the terms and conditions of version 3 of the GNU General Public
     20License, supplemented by the additional permissions listed below.
     21
     22  0. Additional Definitions.
     23
     24  As used herein, "this License" refers to version 3 of the GNU Lesser
     25General Public License, and the "GNU GPL" refers to version 3 of the GNU
     26General Public License.
     27
     28  "The Library" refers to a covered work governed by this License,
     29other than an Application or a Combined Work as defined below.
     30
     31  An "Application" is any work that makes use of an interface provided
     32by the Library, but which is not otherwise based on the Library.
     33Defining a subclass of a class defined by the Library is deemed a mode
     34of using an interface provided by the Library.
     35
     36  A "Combined Work" is a work produced by combining or linking an
     37Application with the Library.  The particular version of the Library
     38with which the Combined Work was made is also called the "Linked
     39Version".
     40
     41  The "Minimal Corresponding Source" for a Combined Work means the
     42Corresponding Source for the Combined Work, excluding any source code
     43for portions of the Combined Work that, considered in isolation, are
     44based on the Application, and not on the Linked Version.
     45
     46  The "Corresponding Application Code" for a Combined Work means the
     47object code and/or source code for the Application, including any data
     48and utility programs needed for reproducing the Combined Work from the
     49Application, but excluding the System Libraries of the Combined Work.
     50
     51  1. Exception to Section 3 of the GNU GPL.
     52
     53  You may convey a covered work under sections 3 and 4 of this License
     54without being bound by section 3 of the GNU GPL.
     55
     56  2. Conveying Modified Versions.
     57
     58  If you modify a copy of the Library, and, in your modifications, a
     59facility refers to a function or data to be supplied by an Application
     60that uses the facility (other than as an argument passed when the
     61facility is invoked), then you may convey a copy of the modified
     62version:
     63
     64   a) under this License, provided that you make a good faith effort to
     65   ensure that, in the event an Application does not supply the
     66   function or data, the facility still operates, and performs
     67   whatever part of its purpose remains meaningful, or
     68
     69   b) under the GNU GPL, with none of the additional permissions of
     70   this License applicable to that copy.
     71
     72  3. Object Code Incorporating Material from Library Header Files.
     73
     74  The object code form of an Application may incorporate material from
     75a header file that is part of the Library.  You may convey such object
     76code under terms of your choice, provided that, if the incorporated
     77material is not limited to numerical parameters, data structure
     78layouts and accessors, or small macros, inline functions and templates
     79(ten or fewer lines in length), you do both of the following:
     80
     81   a) Give prominent notice with each copy of the object code that the
     82   Library is used in it and that the Library and its use are
     83   covered by this License.
     84
     85   b) Accompany the object code with a copy of the GNU GPL and this license
     86   document.
     87
     88  4. Combined Works.
     89
     90  You may convey a Combined Work under terms of your choice that,
     91taken together, effectively do not restrict modification of the
     92portions of the Library contained in the Combined Work and reverse
     93engineering for debugging such modifications, if you also do each of
     94the following:
     95
     96   a) Give prominent notice with each copy of the Combined Work that
     97   the Library is used in it and that the Library and its use are
     98   covered by this License.
     99
     100   b) Accompany the Combined Work with a copy of the GNU GPL and this license
     101   document.
     102
     103   c) For a Combined Work that displays copyright notices during
     104   execution, include the copyright notice for the Library among
     105   these notices, as well as a reference directing the user to the
     106   copies of the GNU GPL and this license document.
     107
     108   d) Do one of the following:
     109
     110       0) Convey the Minimal Corresponding Source under the terms of this
     111       License, and the Corresponding Application Code in a form
     112       suitable for, and under terms that permit, the user to
     113       recombine or relink the Application with a modified version of
     114       the Linked Version to produce a modified Combined Work, in the
     115       manner specified by section 6 of the GNU GPL for conveying
     116       Corresponding Source.
     117
     118       1) Use a suitable shared library mechanism for linking with the
     119       Library.  A suitable mechanism is one that (a) uses at run time
     120       a copy of the Library already present on the user's computer
     121       system, and (b) will operate properly with a modified version
     122       of the Library that is interface-compatible with the Linked
     123       Version.
     124
     125   e) Provide Installation Information, but only if you would otherwise
     126   be required to provide such information under section 6 of the
     127   GNU GPL, and only to the extent that such information is
     128   necessary to install and execute a modified version of the
     129   Combined Work produced by recombining or relinking the
     130   Application with a modified version of the Linked Version. (If
     131   you use option 4d0, the Installation Information must accompany
     132   the Minimal Corresponding Source and Corresponding Application
     133   Code. If you use option 4d1, you must provide the Installation
     134   Information in the manner specified by section 6 of the GNU GPL
     135   for conveying Corresponding Source.)
     136
     137  5. Combined Libraries.
     138
     139  You may place library facilities that are a work based on the
     140Library side by side in a single library together with other library
     141facilities that are not Applications and are not covered by this
     142License, and convey such a combined library under terms of your
     143choice, if you do both of the following:
     144
     145   a) Accompany the combined library with a copy of the same work based
     146   on the Library, uncombined with any other library facilities,
     147   conveyed under the terms of this License.
     148
     149   b) Give prominent notice with the combined library that part of it
     150   is a work based on the Library, and explaining where to find the
     151   accompanying uncombined form of the same work.
     152
     153  6. Revised Versions of the GNU Lesser General Public License.
     154
     155  The Free Software Foundation may publish revised and/or new versions
     156of the GNU Lesser General Public License from time to time. Such new
     157versions will be similar in spirit to the present version, but may
     158differ in detail to address new problems or concerns.
     159
     160  Each version is given a distinguishing version number. If the
     161Library as you received it specifies that a certain numbered version
     162of the GNU Lesser General Public License "or any later version"
     163applies to it, you have the option of following the terms and
     164conditions either of that published version or of any later version
     165published by the Free Software Foundation. If the Library as you
  • mythtv/libs/libmythtv/hdhrchannel.cpp

    +received it does not specify a version number of the GNU Lesser
    +General Public License, you may choose any version of the GNU Lesser
    +General Public License ever published by the Free Software Foundation.
    +
    +  If the Library as you received it specifies that a proxy can decide
    +whether future versions of the GNU Lesser General Public License shall
    +apply, that proxy's public statement of acceptance of any version is
    +permanent authorization for you to choose that version for the
    +Library.
    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/hdhrchannel.cpp release.19703.0116b/mythtv/libs/libmythtv/hdhrchannel.cpp
     
    4242    if (valid && hdhomerun_discover_validate_device_id(_device_id))
    4343        return;
    4444
     45    _device_id = HDHOMERUN_DEVICE_ID_WILDCARD;
    4546    /* Otherwise, is it a valid IP address? */
    4647    struct in_addr address;
    4748    if (inet_aton(device, &address))
     
    99100
    100101    /* Discover. */
    101102    struct hdhomerun_discover_device_t result;
    102     int ret = hdhomerun_discover_find_device(_device_id, &result);
     103    int ret = hdhomerun_discover_find_devices_custom(0, HDHOMERUN_DEVICE_TYPE_WILDCARD, _device_id, &result, 1);
    103104    if (ret < 0)
    104105    {
    105106        VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to send discovery request" + ENO);
  • mythtv/libs/libmythtv/libmythtv.pro

    diff -r -u -N -X diff.exclude -x release.19703.0116a -x release.19703.0116b release.19703.0116a/mythtv/libs/libmythtv/libmythtv.pro release.19703.0116b/mythtv/libs/libmythtv/libmythtv.pro
     
    461461        # HDHomeRun library
    462462        HEADERS += hdhomerun/hdhomerun_pkt.h   hdhomerun/hdhomerun_discover.h
    463463        HEADERS += hdhomerun/hdhomerun_video.h hdhomerun/hdhomerun_control.h
    464         HEADERS += hdhomerun/hdhomerun_os.h
     464        HEADERS += hdhomerun/hdhomerun_os.h    hdhomerun/hdhomerun.h
     465        HEADERS += hdhomerun/hdhomerun_dhcp.h  hdhomerun/hdhomerun_types.h
     466        HEADERS += hdhomerun/hdhomerun_channels.h
     467        HEADERS += hdhomerun/hdhomerun_channelscan.h
     468        HEADERS += hdhomerun/hdhomerun_debug.h
    465469
    466470        SOURCES += hdhomerun/hdhomerun_pkt.c   hdhomerun/hdhomerun_discover.c
    467471        SOURCES += hdhomerun/hdhomerun_video.c hdhomerun/hdhomerun_control.c
     472        SOURCES += hdhomerun/hdhomerun_debug.c hdhomerun/hdhomerun_channels.c
     473        SOURCES += hdhomerun/hdhomerun_dhcp.c  hdhomerun/hdhomerun_channelscan.c
     474        SOURCES += hdhomerun/hdhomerun_device.c
     475
    468476    }
    469477
    470478    # Support for PVR-150/250/350/500, etc. on Linux