Modifications to add HDHR prime, tuner as multicast source
Change-Id: Id83504747d3928d623546c0ba6e43c25b8813dae
diff --git a/libhdhomerun/hdhomerun_channels.c b/libhdhomerun/hdhomerun_channels.c
index c78ebce..4cfaf4a 100755
--- a/libhdhomerun/hdhomerun_channels.c
+++ b/libhdhomerun/hdhomerun_channels.c
@@ -79,16 +79,6 @@
{ 0, 0, 0, 0}
};
-/* KR cable channels. */
-static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_kr_cable[] = {
- { 2, 4, 57000000, 6000000},
- { 5, 6, 79000000, 6000000},
- { 7, 13, 177000000, 6000000},
- { 14, 22, 123000000, 6000000},
- { 23, 153, 219000000, 6000000},
- { 0, 0, 0, 0}
-};
-
/* US antenna channels. */
static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_us_bcast[] = {
{ 2, 4, 57000000, 6000000},
@@ -145,8 +135,6 @@
{"tw-bcast", hdhomerun_channelmap_range_us_bcast, "tw-bcast", "TW"},
{"tw-cable", hdhomerun_channelmap_range_us_cable, "tw-cable", "TW"},
- {"kr-bcast", hdhomerun_channelmap_range_us_bcast, "kr-bcast", "KR"},
- {"kr-cable", hdhomerun_channelmap_range_kr_cable, "kr-cable", "KR"},
{"us-bcast", hdhomerun_channelmap_range_us_bcast, "us-bcast", "CA US"},
{"us-cable", hdhomerun_channelmap_range_us_cable, "us-cable us-hrc us-irc", "CA PA US"},
{"us-hrc", hdhomerun_channelmap_range_us_hrc , "us-cable us-hrc us-irc", "CA PA US"},
diff --git a/libhdhomerun/hdhomerun_channelscan.c b/libhdhomerun/hdhomerun_channelscan.c
index 8c1f8db..ed1ec43 100755
--- a/libhdhomerun/hdhomerun_channelscan.c
+++ b/libhdhomerun/hdhomerun_channelscan.c
@@ -259,6 +259,29 @@
return 1;
}
+int channelscan_at(struct hdhomerun_channelscan_t *scan, int number, struct hdhomerun_channelscan_result_t *result)
+{
+ memset(result, 0, sizeof(struct hdhomerun_channelscan_result_t));
+ struct hdhomerun_channel_entry_t *entry = hdhomerun_channel_list_last( scan->channel_list );
+ while ( entry ) {
+ if ( hdhomerun_channel_entry_channel_number( entry ) == number )
+ break;
+ entry = hdhomerun_channel_list_prev(scan->channel_list, entry);
+ }
+ scan->next_channel = 0;
+
+
+ /* Combine channels with same frequency. */
+ result->frequency = hdhomerun_channel_entry_frequency(entry);
+ strncpy(result->channel_str, hdhomerun_channel_entry_name(entry), sizeof(result->channel_str) - 1);
+ result->channel_str[sizeof(result->channel_str) - 1] = 0;
+
+ char *ptr = strchr(result->channel_str, 0);
+ sprintf(ptr, ", %s", hdhomerun_channel_entry_name(entry));
+
+ return 1;
+}
+
int channelscan_detect(struct hdhomerun_channelscan_t *scan, struct hdhomerun_channelscan_result_t *result)
{
scan->scanned_channels++;
diff --git a/libhdhomerun/hdhomerun_channelscan.h b/libhdhomerun/hdhomerun_channelscan.h
index 8a1fac2..69db553 100755
--- a/libhdhomerun/hdhomerun_channelscan.h
+++ b/libhdhomerun/hdhomerun_channelscan.h
@@ -47,6 +47,7 @@
extern LIBTYPE int channelscan_advance(struct hdhomerun_channelscan_t *scan, struct hdhomerun_channelscan_result_t *result);
extern LIBTYPE int channelscan_detect(struct hdhomerun_channelscan_t *scan, struct hdhomerun_channelscan_result_t *result);
extern LIBTYPE uint8_t channelscan_get_progress(struct hdhomerun_channelscan_t *scan);
+extern LIBTYPE int channelscan_at(struct hdhomerun_channelscan_t *scan, int number, struct hdhomerun_channelscan_result_t *result); //ZQ
#ifdef __cplusplus
}
diff --git a/libhdhomerun/hdhomerun_device.c b/libhdhomerun/hdhomerun_device.c
index 059c043..7bbb75a 100755
--- a/libhdhomerun/hdhomerun_device.c
+++ b/libhdhomerun/hdhomerun_device.c
@@ -1296,6 +1296,22 @@
return ret;
}
+int hdhomerun_device_channelscan_at(struct hdhomerun_device_t *hd, int channel_num, struct hdhomerun_channelscan_result_t *result)
+{
+ if (!hd->scan) {
+ hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_channelscan_at: scan not initialized\n");
+ return 0;
+ }
+
+ int ret = channelscan_at(hd->scan, channel_num, result);
+ if (ret <= 0) { /* Free scan if normal finish or fatal error */
+ channelscan_destroy(hd->scan);
+ hd->scan = NULL;
+ }
+
+ return ret;
+}
+
int hdhomerun_device_channelscan_detect(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result)
{
if (!hd->scan) {
diff --git a/libhdhomerun/hdhomerun_device.h b/libhdhomerun/hdhomerun_device.h
index 51c2b86..0648caa 100755
--- a/libhdhomerun/hdhomerun_device.h
+++ b/libhdhomerun/hdhomerun_device.h
@@ -239,6 +239,7 @@
extern LIBTYPE int hdhomerun_device_channelscan_advance(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result);
extern LIBTYPE int hdhomerun_device_channelscan_detect(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result);
extern LIBTYPE uint8_t hdhomerun_device_channelscan_get_progress(struct hdhomerun_device_t *hd);
+extern LIBTYPE int hdhomerun_device_channelscan_at(struct hdhomerun_device_t *hd, int channel_num, struct hdhomerun_channelscan_result_t *result);
/*
* Upload new firmware to the device.
diff --git a/libhdhomerun/hdhomerun_sock_posix.c b/libhdhomerun/hdhomerun_sock_posix.c
index 52dccc0..5a8c376 100755
--- a/libhdhomerun/hdhomerun_sock_posix.c
+++ b/libhdhomerun/hdhomerun_sock_posix.c
@@ -50,19 +50,13 @@
#include <net/if.h>
#include <sys/ioctl.h>
-
#ifndef SIOCGIFCONF
#include <sys/sockio.h>
#endif
-
#ifndef _SIZEOF_ADDR_IFREQ
#define _SIZEOF_ADDR_IFREQ(x) sizeof(x)
#endif
-#ifndef MSG_NOSIGNAL
-#define MSG_NOSIGNAL 0
-#endif
-
int hdhomerun_local_ip_info(struct hdhomerun_local_ip_info_t ip_info_list[], int max_count)
{
int sock = socket(AF_INET, SOCK_DGRAM, 0);
@@ -374,20 +368,30 @@
sock_addr.sin_addr.s_addr = htonl(remote_addr);
sock_addr.sin_port = htons(remote_port);
- if (connect(sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) {
- if ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINPROGRESS)) {
- return FALSE;
- }
+ if (connect(sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) == 0) {
+ return TRUE;
}
uint64_t stop_time = getcurrenttime() + timeout;
+ /*
+ * getpeername() is used to detect if connect succeeded. Bug - cygwin
+ * will return getpeername success even if the connect process hasn't
+ * completed. This first call to select is used to work around the
+ * problem (at least for low numbered sockets where select is used).
+ */
+ if (!hdhomerun_sock_wait_for_write_event(sock, stop_time)) {
+ return FALSE;
+ }
+
while (1) {
- if (send(sock, NULL, 0, MSG_NOSIGNAL) == 0) {
+ struct sockaddr_in sock_addr;
+ socklen_t sockaddr_size = sizeof(sock_addr);
+ if (getpeername(sock, (struct sockaddr *)&sock_addr, &sockaddr_size) == 0) {
return TRUE;
}
- if ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINPROGRESS) && (errno != ENOTCONN)) {
+ if (errno != ENOTCONN) {
return FALSE;
}
@@ -403,24 +407,26 @@
const uint8_t *ptr = (const uint8_t *)data;
while (1) {
- int ret = send(sock, ptr, length, MSG_NOSIGNAL);
- if (ret <= 0) {
- if ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINPROGRESS)) {
- return FALSE;
- }
- if (!hdhomerun_sock_wait_for_write_event(sock, stop_time)) {
- return FALSE;
- }
- continue;
+ int ret = send(sock, ptr, length, 0);
+ if (ret >= (int)length) {
+ return TRUE;
}
- if (ret < (int)length) {
+ if (ret > 0) {
ptr += ret;
length -= ret;
- continue;
}
- return TRUE;
+ if (errno == EINPROGRESS) {
+ errno = EWOULDBLOCK;
+ }
+ if (errno != EWOULDBLOCK) {
+ return FALSE;
+ }
+
+ if (!hdhomerun_sock_wait_for_write_event(sock, stop_time)) {
+ return FALSE;
+ }
}
}
@@ -437,23 +443,25 @@
sock_addr.sin_port = htons(remote_port);
int ret = sendto(sock, ptr, length, 0, (struct sockaddr *)&sock_addr, sizeof(sock_addr));
- if (ret <= 0) {
- if ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINPROGRESS)) {
- return FALSE;
- }
- if (!hdhomerun_sock_wait_for_write_event(sock, stop_time)) {
- return FALSE;
- }
- continue;
+ if (ret >= (int)length) {
+ return TRUE;
}
- if (ret < (int)length) {
+ if (ret > 0) {
ptr += ret;
length -= ret;
- continue;
}
- return TRUE;
+ if (errno == EINPROGRESS) {
+ errno = EWOULDBLOCK;
+ }
+ if (errno != EWOULDBLOCK) {
+ return FALSE;
+ }
+
+ if (!hdhomerun_sock_wait_for_write_event(sock, stop_time)) {
+ return FALSE;
+ }
}
}
@@ -463,22 +471,21 @@
while (1) {
int ret = recv(sock, data, *length, 0);
- if (ret < 0) {
- if ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINPROGRESS)) {
- return FALSE;
- }
- if (!hdhomerun_sock_wait_for_read_event(sock, stop_time)) {
- return FALSE;
- }
- continue;
+ if (ret > 0) {
+ *length = ret;
+ return TRUE;
}
- if (ret == 0) {
+ if (errno == EINPROGRESS) {
+ errno = EWOULDBLOCK;
+ }
+ if (errno != EWOULDBLOCK) {
return FALSE;
}
- *length = ret;
- return TRUE;
+ if (!hdhomerun_sock_wait_for_read_event(sock, stop_time)) {
+ return FALSE;
+ }
}
}
@@ -492,23 +499,22 @@
socklen_t sockaddr_size = sizeof(sock_addr);
int ret = recvfrom(sock, data, *length, 0, (struct sockaddr *)&sock_addr, &sockaddr_size);
- if (ret < 0) {
- if ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINPROGRESS)) {
- return FALSE;
- }
- if (!hdhomerun_sock_wait_for_read_event(sock, stop_time)) {
- return FALSE;
- }
- continue;
+ if (ret > 0) {
+ *remote_addr = ntohl(sock_addr.sin_addr.s_addr);
+ *remote_port = ntohs(sock_addr.sin_port);
+ *length = ret;
+ return TRUE;
}
- if (ret == 0) {
+ if (errno == EINPROGRESS) {
+ errno = EWOULDBLOCK;
+ }
+ if (errno != EWOULDBLOCK) {
return FALSE;
}
- *remote_addr = ntohl(sock_addr.sin_addr.s_addr);
- *remote_port = ntohs(sock_addr.sin_port);
- *length = ret;
- return TRUE;
+ if (!hdhomerun_sock_wait_for_read_event(sock, stop_time)) {
+ return FALSE;
+ }
}
}
diff --git a/libhdhomerun/hdhomerun_sock_windows.c b/libhdhomerun/hdhomerun_sock_windows.c
index c599694..d03a059 100755
--- a/libhdhomerun/hdhomerun_sock_windows.c
+++ b/libhdhomerun/hdhomerun_sock_windows.c
@@ -269,6 +269,16 @@
bool_t hdhomerun_sock_connect(hdhomerun_sock_t sock, uint32_t remote_addr, uint16_t remote_port, uint64_t timeout)
{
+ WSAEVENT wsa_event = WSACreateEvent();
+ if (wsa_event == WSA_INVALID_EVENT) {
+ return FALSE;
+ }
+
+ if (WSAEventSelect(sock, wsa_event, FD_CONNECT) == SOCKET_ERROR) {
+ WSACloseEvent(wsa_event);
+ return FALSE;
+ }
+
/* Connect (non-blocking). */
struct sockaddr_in sock_addr;
memset(&sock_addr, 0, sizeof(sock_addr));
@@ -278,41 +288,22 @@
if (connect(sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) {
if (WSAGetLastError() != WSAEWOULDBLOCK) {
+ WSACloseEvent(wsa_event);
return FALSE;
}
}
/* Wait for connect to complete (both success and failure will signal). */
- WSAEVENT wsa_event = WSACreateEvent();
- if (wsa_event == WSA_INVALID_EVENT) {
- return FALSE;
- }
-
- if (WSAEventSelect(sock, wsa_event, FD_WRITE | FD_CLOSE) == SOCKET_ERROR) {
- WSACloseEvent(wsa_event);
- return FALSE;
- }
-
DWORD ret = WaitForSingleObjectEx(wsa_event, (DWORD)timeout, FALSE);
WSACloseEvent(wsa_event);
+
if (ret != WAIT_OBJECT_0) {
return FALSE;
}
/* Detect success/failure. */
- wsa_event = WSACreateEvent();
- if (wsa_event == WSA_INVALID_EVENT) {
- return FALSE;
- }
-
- if (WSAEventSelect(sock, wsa_event, FD_CLOSE) == SOCKET_ERROR) {
- WSACloseEvent(wsa_event);
- return FALSE;
- }
-
- ret = WaitForSingleObjectEx(wsa_event, 0, FALSE);
- WSACloseEvent(wsa_event);
- if (ret == WAIT_OBJECT_0) {
+ int sockaddr_size = sizeof(sock_addr);
+ if (getpeername(sock, (struct sockaddr *)&sock_addr, &sockaddr_size) != 0) {
return FALSE;
}
@@ -353,23 +344,22 @@
while (1) {
int ret = send(sock, (char *)ptr, (int)length, 0);
- if (ret <= 0) {
- if (WSAGetLastError() != WSAEWOULDBLOCK) {
- return FALSE;
- }
- if (!hdhomerun_sock_wait_for_event(sock, FD_WRITE | FD_CLOSE, stop_time)) {
- return FALSE;
- }
- continue;
+ if (ret >= (int)length) {
+ return TRUE;
}
- if (ret < (int)length) {
+ if (ret > 0) {
ptr += ret;
length -= ret;
- continue;
}
- return TRUE;
+ if (WSAGetLastError() != WSAEWOULDBLOCK) {
+ return FALSE;
+ }
+
+ if (!hdhomerun_sock_wait_for_event(sock, FD_WRITE | FD_CLOSE, stop_time)) {
+ return FALSE;
+ }
}
}
@@ -386,23 +376,22 @@
sock_addr.sin_port = htons(remote_port);
int ret = sendto(sock, (char *)ptr, (int)length, 0, (struct sockaddr *)&sock_addr, sizeof(sock_addr));
- if (ret <= 0) {
- if (WSAGetLastError() != WSAEWOULDBLOCK) {
- return FALSE;
- }
- if (!hdhomerun_sock_wait_for_event(sock, FD_WRITE | FD_CLOSE, stop_time)) {
- return FALSE;
- }
- continue;
+ if (ret >= (int)length) {
+ return TRUE;
}
- if (ret < (int)length) {
+ if (ret > 0) {
ptr += ret;
length -= ret;
- continue;
}
- return TRUE;
+ if (WSAGetLastError() != WSAEWOULDBLOCK) {
+ return FALSE;
+ }
+
+ if (!hdhomerun_sock_wait_for_event(sock, FD_WRITE | FD_CLOSE, stop_time)) {
+ return FALSE;
+ }
}
}
@@ -412,22 +401,18 @@
while (1) {
int ret = recv(sock, (char *)data, (int)(*length), 0);
- if (ret < 0) {
- if (WSAGetLastError() != WSAEWOULDBLOCK) {
- return FALSE;
- }
- if (!hdhomerun_sock_wait_for_event(sock, FD_READ | FD_CLOSE, stop_time)) {
- return FALSE;
- }
- continue;
+ if (ret > 0) {
+ *length = ret;
+ return TRUE;
}
- if (ret == 0) {
+ if (WSAGetLastError() != WSAEWOULDBLOCK) {
return FALSE;
}
- *length = ret;
- return TRUE;
+ if (!hdhomerun_sock_wait_for_event(sock, FD_READ | FD_CLOSE, stop_time)) {
+ return FALSE;
+ }
}
}
@@ -441,23 +426,19 @@
int sockaddr_size = sizeof(sock_addr);
int ret = recvfrom(sock, (char *)data, (int)(*length), 0, (struct sockaddr *)&sock_addr, &sockaddr_size);
- if (ret < 0) {
- if (WSAGetLastError() != WSAEWOULDBLOCK) {
- return FALSE;
- }
- if (!hdhomerun_sock_wait_for_event(sock, FD_READ | FD_CLOSE, stop_time)) {
- return FALSE;
- }
- continue;
+ if (ret > 0) {
+ *remote_addr = ntohl(sock_addr.sin_addr.s_addr);
+ *remote_port = ntohs(sock_addr.sin_port);
+ *length = ret;
+ return TRUE;
}
- if (ret == 0) {
+ if (WSAGetLastError() != WSAEWOULDBLOCK) {
return FALSE;
}
- *remote_addr = ntohl(sock_addr.sin_addr.s_addr);
- *remote_port = ntohs(sock_addr.sin_port);
- *length = ret;
- return TRUE;
+ if (!hdhomerun_sock_wait_for_event(sock, FD_READ | FD_CLOSE, stop_time)) {
+ return FALSE;
+ }
}
}