Ticket #6138: 132-hdhr.20081231.patch

File 132-hdhr.20081231.patch, 243.2 KB (added by anonymous, 12 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;