Ticket #2807: mythtv_libhdhomerun_update_20061214.patch
| File mythtv_libhdhomerun_update_20061214.patch, 104.3 KB (added by , 19 years ago) |
|---|
-
libs/libmythtv/hdhomerun/hdhomerun.h
1 /* 2 * hdhomerun_device.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 2.1 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, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21 #include "hdhomerun_os.h" 22 #include "hdhomerun_pkt.h" 23 #include "hdhomerun_discover.h" 24 #include "hdhomerun_control.h" 25 #include "hdhomerun_video.h" 26 #include "hdhomerun_device.h" -
libs/libmythtv/hdhomerun/hdhomerun_control.h
23 23 24 24 struct hdhomerun_control_sock_t; 25 25 26 struct hdhomerun_control_data_t { 27 int type; 28 unsigned char buffer[1024]; 29 unsigned char *ptr; 30 unsigned char *end; 31 }; 32 33 extern struct hdhomerun_control_sock_t *hdhomerun_control_create(unsigned long ip_addr, unsigned long timeout); 26 /* 27 * Create a control socket. 28 * 29 * This function will not attempt to connect to the device. 30 * The connection will be established when first used. 31 * 32 * uint32_t device_id = 32-bit device id of device. Set to HDHOMERUN_DEVICE_ID_WILDCARD to match any device ID. 33 * uint32_t device_ip = IP address of device. Set to 0 to auto-detect. 34 * 35 * Returns a pointer to the newly created control socket. 36 * 37 * When no longer needed, the socket should be destroyed by calling hdhomerun_control_destroy. 38 */ 39 extern struct hdhomerun_control_sock_t *hdhomerun_control_create(uint32_t device_id, uint32_t device_ip); 34 40 extern void hdhomerun_control_destroy(struct hdhomerun_control_sock_t *cs); 35 extern unsigned long hdhomerun_control_get_local_addr(struct hdhomerun_control_sock_t *cs);36 41 37 extern int hdhomerun_control_send(struct hdhomerun_control_sock_t *cs, unsigned char *start, unsigned char *end); 38 extern int hdhomerun_control_send_get_request(struct hdhomerun_control_sock_t *cs, const char *name); 39 extern int hdhomerun_control_send_set_request(struct hdhomerun_control_sock_t *cs, const char *name, const char *value); 40 extern int hdhomerun_control_send_upgrade_request(struct hdhomerun_control_sock_t *cs, unsigned long sequence, void *data, int length); 42 /* 43 * Get the local machine IP address used when communicating with the device. 44 * 45 * This function is useful for determining the IP address to use with set target commands. 46 * 47 * Returns 32-bit IP address with native endianness, or 0 on error. 48 */ 49 extern uint32_t hdhomerun_control_get_local_addr(struct hdhomerun_control_sock_t *cs); 41 50 42 extern int hdhomerun_control_recv(struct hdhomerun_control_sock_t *cs, struct hdhomerun_control_data_t *result, unsigned long timeout); 51 /* 52 * Get/set a control variable on the device. 53 * 54 * const char *name: The name of var to get/set (c-string). The supported vars is device/firmware dependant. 55 * const char *value: The value to set (c-string). The format is device/firmware dependant. 43 56 57 * char **pvalue: If provided, the caller-supplied char pointer will be populated with a pointer to the value 58 * string returned by the device, or NULL if the device returned an error string. The string will remain 59 * valid until the next call to a control sock function. 60 * char **perror: If provided, the caller-supplied char pointer will be populated with a pointer to the error 61 * string returned by the device, or NULL if the device returned an value string. The string will remain 62 * valid until the next call to a control sock function. 63 * 64 * Returns 1 if the operation was successful (pvalue set, perror NULL). 65 * Returns 0 if the operation was rejected (pvalue NULL, perror set). 66 * Returns -1 if a communication error occurs. 67 */ 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); 70 71 /* 72 * Upload new firmware to the device. 73 * 74 * FILE *upgrade_file: File pointer to read from. The file must have been opened in binary mode for reading. 75 * 76 * Returns 1 if the upload succeeded. 77 * Returns 0 if the upload was rejected. 78 * Returns -1 if an error occurs. 79 */ 80 extern int hdhomerun_control_upgrade(struct hdhomerun_control_sock_t *cs, FILE *upgrade_file); 81 44 82 #ifdef __cplusplus 45 83 } 46 84 #endif -
libs/libmythtv/hdhomerun/hdhomerun_os.h
21 21 #include <stdlib.h> 22 22 #include <stdio.h> 23 23 #include <string.h> 24 25 #if defined(WIN32) 26 #define __WINDOWS__ 27 #endif 28 29 #if defined(__WINDOWS__) 30 #include <windows.h> 31 #include <sys/types.h> 32 #include <sys/timeb.h> 33 #else 24 34 #include <unistd.h> 25 35 #include <errno.h> 26 36 #include <sys/types.h> … … 29 39 #include <arpa/inet.h> 30 40 #include <netdb.h> 31 41 #include <sys/time.h> 42 #include <sys/timeb.h> 32 43 #include <fcntl.h> 44 #endif 33 45 46 #include <pthread.h> 47 34 48 #if !defined(TRUE) 35 49 #define TRUE 1 36 50 #endif 37 51 #if !defined(FALSE) 38 52 #define FALSE 0 39 53 #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 -
libs/libmythtv/hdhomerun/hdhomerun_pkt.c
18 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 19 */ 20 20 21 #include <string.h>21 #include "hdhomerun_os.h" 22 22 #include "hdhomerun_pkt.h" 23 23 24 u nsigned char hdhomerun_read_u8(unsigned char**pptr)24 uint8_t hdhomerun_read_u8(uint8_t **pptr) 25 25 { 26 u nsigned char*ptr = *pptr;27 u nsigned charv = *ptr++;26 uint8_t *ptr = *pptr; 27 uint8_t v = *ptr++; 28 28 *pptr = ptr; 29 29 return v; 30 30 } 31 31 32 u nsigned short hdhomerun_read_u16(unsigned char**pptr)32 uint16_t hdhomerun_read_u16(uint8_t **pptr) 33 33 { 34 u nsigned char*ptr = *pptr;35 u nsigned short v;36 v = (u nsigned short)*ptr++ << 8;37 v |= (u nsigned short)*ptr++ << 0;34 uint8_t *ptr = *pptr; 35 uint16_t v; 36 v = (uint16_t)*ptr++ << 8; 37 v |= (uint16_t)*ptr++ << 0; 38 38 *pptr = ptr; 39 39 return v; 40 40 } 41 41 42 u nsigned long hdhomerun_read_u32(unsigned char**pptr)42 uint32_t hdhomerun_read_u32(uint8_t **pptr) 43 43 { 44 u nsigned char*ptr = *pptr;45 u nsigned longv;46 v = (u nsigned long)*ptr++ << 24;47 v |= (u nsigned long)*ptr++ << 16;48 v |= (u nsigned long)*ptr++ << 8;49 v |= (u nsigned long)*ptr++ << 0;44 uint8_t *ptr = *pptr; 45 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 50 *pptr = ptr; 51 51 return v; 52 52 } 53 53 54 s tatic int hdhomerun_read_var_length(unsigned char **pptr, unsigned char*end)54 size_t hdhomerun_read_var_length(uint8_t **pptr, uint8_t *end) 55 55 { 56 u nsigned char*ptr = *pptr;57 unsigned int length;56 uint8_t *ptr = *pptr; 57 size_t length; 58 58 59 59 if (ptr + 1 > end) { 60 60 return -1; 61 61 } 62 62 63 length = ( unsigned int)*ptr++;63 length = (size_t)*ptr++; 64 64 if (length & 0x0080) { 65 65 if (ptr + 1 > end) { 66 66 return -1; 67 67 } 68 68 69 69 length &= 0x007F; 70 length |= ( unsigned int)*ptr++ << 7;70 length |= (size_t)*ptr++ << 7; 71 71 } 72 72 73 73 *pptr = ptr; 74 return (int)length;74 return length; 75 75 } 76 76 77 int hdhomerun_read_tlv(u nsigned char **pptr, unsigned char *end, unsigned char *ptag, int *plength, unsigned char**pvalue)77 int hdhomerun_read_tlv(uint8_t **pptr, uint8_t *end, uint8_t *ptag, size_t *plength, uint8_t **pvalue) 78 78 { 79 79 if (end - *pptr < 2) { 80 80 return -1; … … 84 84 *plength = hdhomerun_read_var_length(pptr, end); 85 85 *pvalue = *pptr; 86 86 87 if ( *plength < 0) {87 if ((size_t)(end - *pptr) < *plength) { 88 88 return -1; 89 89 } 90 if (end - *pptr < *plength) {91 return -1;92 }93 90 94 91 *pptr += *plength; 95 92 return 0; 96 93 } 97 94 98 void hdhomerun_write_u8(u nsigned char **pptr, unsigned charv)95 void hdhomerun_write_u8(uint8_t **pptr, uint8_t v) 99 96 { 100 u nsigned char*ptr = *pptr;97 uint8_t *ptr = *pptr; 101 98 *ptr++ = v; 102 99 *pptr = ptr; 103 100 } 104 101 105 void hdhomerun_write_u16(u nsigned char **pptr, unsigned short v)102 void hdhomerun_write_u16(uint8_t **pptr, uint16_t v) 106 103 { 107 u nsigned char*ptr = *pptr;108 *ptr++ = ( v >> 8) & 0xFF;109 *ptr++ = ( v >> 0) & 0xFF;104 uint8_t *ptr = *pptr; 105 *ptr++ = (uint8_t)(v >> 8); 106 *ptr++ = (uint8_t)(v >> 0); 110 107 *pptr = ptr; 111 108 } 112 109 113 void hdhomerun_write_u32(u nsigned char **pptr, unsigned longv)110 void hdhomerun_write_u32(uint8_t **pptr, uint32_t v) 114 111 { 115 u nsigned char*ptr = *pptr;116 *ptr++ = ( v >> 24) & 0xFF;117 *ptr++ = ( v >> 16) & 0xFF;118 *ptr++ = ( v >> 8) & 0xFF;119 *ptr++ = ( v >> 0) & 0xFF;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); 120 117 *pptr = ptr; 121 118 } 122 119 123 void hdhomerun_write_var_length(u nsigned char **pptr, int v)120 void hdhomerun_write_var_length(uint8_t **pptr, size_t v) 124 121 { 125 u nsigned char*ptr = *pptr;122 uint8_t *ptr = *pptr; 126 123 if (v <= 127) { 127 *ptr++ = v;124 *ptr++ = (uint8_t)v; 128 125 } else { 129 *ptr++ = v | 0x80;130 *ptr++ = v >> 7;126 *ptr++ = (uint8_t)(v | 0x80); 127 *ptr++ = (uint8_t)(v >> 7); 131 128 } 132 129 *pptr = ptr; 133 130 } 134 131 135 static void hdhomerun_write_mem(u nsigned char **pptr, void *mem, int length)132 static void hdhomerun_write_mem(uint8_t **pptr, void *mem, size_t length) 136 133 { 137 u nsigned char*ptr = *pptr;134 uint8_t *ptr = *pptr; 138 135 memcpy(ptr, mem, length); 139 136 ptr += length; 140 137 *pptr = ptr; 141 138 } 142 139 143 static u nsigned long hdhomerun_calc_crc(unsigned char *start, unsigned char*end)140 static uint32_t hdhomerun_calc_crc(uint8_t *start, uint8_t *end) 144 141 { 145 u nsigned char*ptr = start;146 u nsigned longcrc = 0xFFFFFFFF;142 uint8_t *ptr = start; 143 uint32_t crc = 0xFFFFFFFF; 147 144 while (ptr < end) { 148 unsigned char x = (crc & 0x000000FF) ^ *ptr++;149 crc >>= 8;145 uint8_t x = (uint8_t)(crc) ^ *ptr++; 146 crc >>= 8; 150 147 if (x & 0x01) crc ^= 0x77073096; 151 148 if (x & 0x02) crc ^= 0xEE0E612C; 152 149 if (x & 0x04) crc ^= 0x076DC419; … … 159 156 return crc ^ 0xFFFFFFFF; 160 157 } 161 158 162 static int hdhomerun_check_crc(u nsigned char *start, unsigned char*end)159 static int hdhomerun_check_crc(uint8_t *start, uint8_t *end) 163 160 { 164 161 if (end - start < 8) { 165 162 return -1; 166 163 } 167 u nsigned char*ptr = end -= 4;168 u nsigned longactual_crc = hdhomerun_calc_crc(start, ptr);169 u nsigned longpacket_crc;170 packet_crc = (u nsigned long)*ptr++ << 0;171 packet_crc |= (u nsigned long)*ptr++ << 8;172 packet_crc |= (u nsigned long)*ptr++ << 16;173 packet_crc |= (u nsigned long)*ptr++ << 24;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; 174 171 if (actual_crc != packet_crc) { 175 172 return -1; 176 173 } 177 174 return 0; 178 175 } 179 176 180 static void hdhomerun_write_header_length(u nsigned char *ptr, unsigned longlength)177 static void hdhomerun_write_header_length(uint8_t *ptr, size_t length) 181 178 { 182 hdhomerun_write_u16(&ptr, length);179 hdhomerun_write_u16(&ptr, (uint16_t)length); 183 180 } 184 181 185 void hdhomerun_write_crc(u nsigned char **pptr, unsigned char*start)182 void hdhomerun_write_crc(uint8_t **pptr, uint8_t *start) 186 183 { 187 u nsigned char*ptr = *pptr;188 u nsigned longcrc = hdhomerun_calc_crc(start, ptr);189 *ptr++ = ( crc >> 0) & 0xFF;190 *ptr++ = ( crc >> 8) & 0xFF;191 *ptr++ = ( crc >> 16) & 0xFF;192 *ptr++ = ( crc >> 24) & 0xFF;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); 193 190 *pptr = ptr; 194 191 } 195 192 196 void hdhomerun_write_discover_request(u nsigned char **pptr, unsigned long device_type, unsigned longdevice_id)193 void hdhomerun_write_discover_request(uint8_t **pptr, uint32_t device_type, uint32_t device_id) 197 194 { 198 u nsigned char*start = *pptr;195 uint8_t *start = *pptr; 199 196 hdhomerun_write_u16(pptr, HDHOMERUN_TYPE_DISCOVER_REQ); 200 197 hdhomerun_write_u16(pptr, 0); 201 198 … … 206 203 hdhomerun_write_var_length(pptr, 4); 207 204 hdhomerun_write_u32(pptr, device_id); 208 205 209 hdhomerun_write_header_length(start + 2, *pptr - start - 4);206 hdhomerun_write_header_length(start + 2, (int)(*pptr - start - 4)); 210 207 hdhomerun_write_crc(pptr, start); 211 208 } 212 209 213 void hdhomerun_write_get_ request(unsigned char **pptr, const char *name)210 void hdhomerun_write_get_set_request(uint8_t **pptr, const char *name, const char *value) 214 211 { 215 u nsigned char*start = *pptr;212 uint8_t *start = *pptr; 216 213 hdhomerun_write_u16(pptr, HDHOMERUN_TYPE_GETSET_REQ); 217 214 hdhomerun_write_u16(pptr, 0); 218 215 219 int name_len = strlen(name) + 1;216 int name_len = (int)strlen(name) + 1; 220 217 hdhomerun_write_u8(pptr, HDHOMERUN_TAG_GETSET_NAME); 221 218 hdhomerun_write_var_length(pptr, name_len); 222 219 hdhomerun_write_mem(pptr, (void *)name, name_len); 223 220 224 hdhomerun_write_header_length(start + 2, *pptr - start - 4); 225 hdhomerun_write_crc(pptr, start); 226 } 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); 226 } 227 227 228 void hdhomerun_write_set_request(unsigned char **pptr, const char *name, const char *value) 229 { 230 unsigned char *start = *pptr; 231 hdhomerun_write_u16(pptr, HDHOMERUN_TYPE_GETSET_REQ); 232 hdhomerun_write_u16(pptr, 0); 233 234 int name_len = strlen(name) + 1; 235 int value_len = strlen(value) + 1; 236 hdhomerun_write_u8(pptr, HDHOMERUN_TAG_GETSET_NAME); 237 hdhomerun_write_var_length(pptr, name_len); 238 hdhomerun_write_mem(pptr, (void *)name, name_len); 239 hdhomerun_write_u8(pptr, HDHOMERUN_TAG_GETSET_VALUE); 240 hdhomerun_write_var_length(pptr, value_len); 241 hdhomerun_write_mem(pptr, (void *)value, value_len); 242 243 hdhomerun_write_header_length(start + 2, *pptr - start - 4); 228 hdhomerun_write_header_length(start + 2, (int)(*pptr - start - 4)); 244 229 hdhomerun_write_crc(pptr, start); 245 230 } 246 231 247 void hdhomerun_write_upgrade_request(u nsigned char **pptr, unsigned long sequence, void *data, int length)232 void hdhomerun_write_upgrade_request(uint8_t **pptr, uint32_t sequence, void *data, size_t length) 248 233 { 249 u nsigned char*start = *pptr;234 uint8_t *start = *pptr; 250 235 hdhomerun_write_u16(pptr, HDHOMERUN_TYPE_UPGRADE_REQ); 251 236 hdhomerun_write_u16(pptr, 0); 252 237 … … 259 244 hdhomerun_write_crc(pptr, start); 260 245 } 261 246 262 int hdhomerun_peek_packet_length(unsigned char*ptr)247 size_t hdhomerun_peek_packet_length(uint8_t *ptr) 263 248 { 264 249 ptr += 2; 265 return hdhomerun_read_u16(&ptr) + 8;250 return (size_t)hdhomerun_read_u16(&ptr) + 8; 266 251 } 267 252 268 int hdhomerun_process_packet(u nsigned char **pptr, unsigned char**pend)253 int hdhomerun_process_packet(uint8_t **pptr, uint8_t **pend) 269 254 { 270 255 if (hdhomerun_check_crc(*pptr, *pend) < 0) { 271 256 return -1; 272 257 } 273 258 *pend -= 4; 274 259 275 u nsigned short type = hdhomerun_read_u16(pptr);276 u nsigned short length = hdhomerun_read_u16(pptr);260 uint16_t type = hdhomerun_read_u16(pptr); 261 uint16_t length = hdhomerun_read_u16(pptr); 277 262 if ((*pend - *pptr) < length) { 278 263 return -1; 279 264 } 280 265 *pend = *pptr + length; 281 266 return (int)type; 282 267 } 268 -
libs/libmythtv/hdhomerun/hdhomerun_device.c
1 /* 2 * hdhomerun_record.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 2.1 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, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 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" 26 27 struct hdhomerun_device_t { 28 struct hdhomerun_control_sock_t *cs; 29 struct hdhomerun_video_sock_t *vs; 30 unsigned int tuner; 31 char result_buffer[1024]; 32 }; 33 34 struct hdhomerun_device_t *hdhomerun_device_create(uint32_t device_id, uint32_t device_ip, unsigned int tuner) 35 { 36 struct hdhomerun_device_t *hd = (struct hdhomerun_device_t *)calloc(1, sizeof(struct hdhomerun_device_t)); 37 if (!hd) { 38 return NULL; 39 } 40 41 hd->tuner = tuner; 42 43 hd->cs = hdhomerun_control_create(device_id, device_ip); 44 if (!hd->cs) { 45 free(hd); 46 return NULL; 47 } 48 49 return hd; 50 } 51 52 void hdhomerun_device_destroy(struct hdhomerun_device_t *hd) 53 { 54 if (hd->vs) { 55 hdhomerun_video_destroy(hd->vs); 56 } 57 58 hdhomerun_control_destroy(hd->cs); 59 60 free(hd); 61 } 62 63 void hdhomerun_device_set_tuner(struct hdhomerun_device_t *hd, unsigned int tuner) 64 { 65 hd->tuner = tuner; 66 } 67 68 struct hdhomerun_control_sock_t *hdhomerun_device_get_control_sock(struct hdhomerun_device_t *hd) 69 { 70 return hd->cs; 71 } 72 73 struct hdhomerun_video_sock_t *hdhomerun_device_get_video_sock(struct hdhomerun_device_t *hd) 74 { 75 if (!hd->vs) { 76 hd->vs = hdhomerun_video_create(0, VIDEO_DATA_BUFFER_SIZE_1S); 77 } 78 return hd->vs; 79 } 80 81 uint32_t hdhomerun_device_get_local_machine_addr(struct hdhomerun_device_t *hd) 82 { 83 return hdhomerun_control_get_local_addr(hd->cs); 84 } 85 86 static uint32_t hdhomerun_device_get_status_parse(const char *status_str, const char *tag) 87 { 88 const char *ptr = strstr(status_str, tag); 89 if (!ptr) { 90 return 0; 91 } 92 93 unsigned long value = 0; 94 sscanf(ptr + strlen(tag), "%lu", &value); 95 96 return (uint32_t)value; 97 } 98 99 int hdhomerun_device_get_tuner_status(struct hdhomerun_device_t *hd, struct hdhomerun_tuner_status_t *status) 100 { 101 memset(status, 0, sizeof(struct hdhomerun_tuner_status_t)); 102 103 char name[32]; 104 sprintf(name, "/tuner%u/status", hd->tuner); 105 106 char *status_str; 107 int ret = hdhomerun_control_get(hd->cs, name, &status_str, NULL); 108 if (ret <= 0) { 109 return ret; 110 } 111 112 char *channel = strstr(status_str, "ch="); 113 if (channel) { 114 sscanf(channel + 3, "%s", status->channel); 115 } 116 117 status->signal_strength = (unsigned int)hdhomerun_device_get_status_parse(status_str, "ss="); 118 status->signal_to_noise_quality = (unsigned int)hdhomerun_device_get_status_parse(status_str, "snq="); 119 status->symbol_error_quality = (unsigned int)hdhomerun_device_get_status_parse(status_str, "seq="); 120 status->raw_bits_per_second = hdhomerun_device_get_status_parse(status_str, "bps="); 121 status->packets_per_second = hdhomerun_device_get_status_parse(status_str, "pps="); 122 123 return 1; 124 } 125 126 int hdhomerun_device_get_tuner_streaminfo(struct hdhomerun_device_t *hd, char **pstreaminfo) 127 { 128 char name[32]; 129 sprintf(name, "/tuner%u/streaminfo", hd->tuner); 130 return hdhomerun_control_get(hd->cs, name, pstreaminfo, NULL); 131 } 132 133 int hdhomerun_device_get_tuner_channel(struct hdhomerun_device_t *hd, char **pchannel) 134 { 135 char name[32]; 136 sprintf(name, "/tuner%u/channel", hd->tuner); 137 return hdhomerun_control_get(hd->cs, name, pchannel, NULL); 138 } 139 140 int hdhomerun_device_get_tuner_channelmap(struct hdhomerun_device_t *hd, char **pchannelmap) 141 { 142 char name[32]; 143 sprintf(name, "/tuner%u/channelmap", hd->tuner); 144 return hdhomerun_control_get(hd->cs, name, pchannelmap, NULL); 145 } 146 147 int hdhomerun_device_get_tuner_filter(struct hdhomerun_device_t *hd, char **pfilter) 148 { 149 char name[32]; 150 sprintf(name, "/tuner%u/filter", hd->tuner); 151 return hdhomerun_control_get(hd->cs, name, pfilter, NULL); 152 } 153 154 int hdhomerun_device_get_tuner_program(struct hdhomerun_device_t *hd, uint16_t *pprogram_number) 155 { 156 char name[32]; 157 sprintf(name, "/tuner%u/program", hd->tuner); 158 159 char *program_str; 160 int ret = hdhomerun_control_get(hd->cs, name, &program_str, NULL); 161 if (ret <= 0) { 162 return ret; 163 } 164 165 *pprogram_number = (uint16_t)atol(program_str); 166 return 1; 167 } 168 169 int hdhomerun_device_get_tuner_target(struct hdhomerun_device_t *hd, char **ptarget) 170 { 171 char name[32]; 172 sprintf(name, "/tuner%u/target", hd->tuner); 173 return hdhomerun_control_get(hd->cs, name, ptarget, NULL); 174 } 175 176 int hdhomerun_device_get_ir_target(struct hdhomerun_device_t *hd, char **ptarget) 177 { 178 return hdhomerun_control_get(hd->cs, "/ir/target", ptarget, NULL); 179 } 180 181 int hdhomerun_device_get_version(struct hdhomerun_device_t *hd, char **pversion_str, uint32_t *pversion_num) 182 { 183 char *version_str; 184 int ret = hdhomerun_control_get(hd->cs, "/sys/version", &version_str, NULL); 185 if (ret <= 0) { 186 return ret; 187 } 188 189 if (pversion_str) { 190 *pversion_str = version_str; 191 } 192 193 if (pversion_num) { 194 unsigned long version_num; 195 if (sscanf(version_str, "%lu", &version_num) != 1) { 196 *pversion_num = 0; 197 } else { 198 *pversion_num = (uint32_t)version_num; 199 } 200 } 201 202 return 1; 203 } 204 205 int hdhomerun_device_set_tuner_channel(struct hdhomerun_device_t *hd, const char *channel) 206 { 207 char name[32]; 208 sprintf(name, "/tuner%u/channel", hd->tuner); 209 return hdhomerun_control_set(hd->cs, name, channel, NULL, NULL); 210 } 211 212 int hdhomerun_device_set_tuner_channelmap(struct hdhomerun_device_t *hd, const char *channelmap) 213 { 214 char name[32]; 215 sprintf(name, "/tuner%u/channelmap", hd->tuner); 216 return hdhomerun_control_set(hd->cs, name, channelmap, NULL, NULL); 217 } 218 219 int hdhomerun_device_set_tuner_filter(struct hdhomerun_device_t *hd, const char *filter) 220 { 221 char name[32]; 222 sprintf(name, "/tuner%u/filter", hd->tuner); 223 return hdhomerun_control_set(hd->cs, name, filter, NULL, NULL); 224 } 225 226 int hdhomerun_device_set_tuner_program(struct hdhomerun_device_t *hd, uint16_t program_number) 227 { 228 char name[32], value[32]; 229 sprintf(name, "/tuner%u/program", hd->tuner); 230 sprintf(value, "%u", program_number); 231 return hdhomerun_control_set(hd->cs, name, value, NULL, NULL); 232 } 233 234 int hdhomerun_device_set_tuner_target(struct hdhomerun_device_t *hd, char *target) 235 { 236 char name[32]; 237 sprintf(name, "/tuner%u/target", hd->tuner); 238 return hdhomerun_control_set(hd->cs, name, target, NULL, NULL); 239 } 240 241 static int hdhomerun_device_set_tuner_target_to_local(struct hdhomerun_device_t *hd) 242 { 243 char target[64]; 244 uint32_t local_ip = hdhomerun_control_get_local_addr(hd->cs); 245 uint16_t local_port = hdhomerun_video_get_local_port(hd->vs); 246 sprintf(target, "%u.%u.%u.%u:%u", 247 (unsigned int)(local_ip >> 24) & 0xFF, (unsigned int)(local_ip >> 16) & 0xFF, 248 (unsigned int)(local_ip >> 8) & 0xFF, (unsigned int)(local_ip >> 0) & 0xFF, 249 (unsigned int)local_port 250 ); 251 252 return hdhomerun_device_set_tuner_target(hd, target); 253 } 254 255 int hdhomerun_device_set_ir_target(struct hdhomerun_device_t *hd, const char *target) 256 { 257 return hdhomerun_control_set(hd->cs, "/ir/target", target, NULL, NULL); 258 } 259 260 int hdhomerun_device_get_var(struct hdhomerun_device_t *hd, const char *name, char **pvalue, char **perror) 261 { 262 return hdhomerun_control_get(hd->cs, name, pvalue, perror); 263 } 264 265 int hdhomerun_device_set_var(struct hdhomerun_device_t *hd, const char *name, const char *value, char **pvalue, char **perror) 266 { 267 return hdhomerun_control_set(hd->cs, name, value, pvalue, perror); 268 } 269 270 int hdhomerun_device_stream_start(struct hdhomerun_device_t *hd) 271 { 272 /* Create video socket. */ 273 hdhomerun_device_get_video_sock(hd); 274 if (!hd->vs) { 275 return -1; 276 } 277 278 /* Set target. */ 279 int ret = hdhomerun_device_set_tuner_target_to_local(hd); 280 if (ret <= 0) { 281 return ret; 282 } 283 284 /* Flush video buffer. */ 285 usleep(64000); 286 hdhomerun_video_flush(hd->vs); 287 288 /* Success. */ 289 return 1; 290 } 291 292 uint8_t *hdhomerun_device_stream_recv(struct hdhomerun_device_t *hd, size_t max_size, size_t *pactual_size) 293 { 294 return hdhomerun_video_recv(hd->vs, max_size, pactual_size); 295 } 296 297 void hdhomerun_device_stream_stop(struct hdhomerun_device_t *hd) 298 { 299 hdhomerun_device_set_tuner_target(hd, "none"); 300 } 301 302 int hdhomerun_device_firmware_version_check(struct hdhomerun_device_t *hd, uint32_t features) 303 { 304 uint32_t version; 305 if (hdhomerun_device_get_version(hd, NULL, &version) <= 0) { 306 return -1; 307 } 308 309 if (version >= 20061213) { 310 return 1; 311 } 312 313 return 0; 314 } 315 316 int hdhomerun_device_upgrade(struct hdhomerun_device_t *hd, FILE *upgrade_file) 317 { 318 hdhomerun_control_set(hd->cs, "/tuner0/channel", "none", NULL, NULL); 319 hdhomerun_control_set(hd->cs, "/tuner1/channel", "none", NULL, NULL); 320 return hdhomerun_control_upgrade(hd->cs, upgrade_file); 321 } -
libs/libmythtv/hdhomerun/hdhomerun_pkt.h
21 21 extern "C" { 22 22 #endif 23 23 24 /* 25 * The discover protocol (UDP port 65001) and control protocol (TCP port 65001) 26 * both use the same packet based format: 27 * uint16_t Packet type 28 * uint16_t Payload length (bytes) 29 * uint8_t[] Payload data (0-n bytes). 30 * uint32_t CRC (Ethernet style 32-bit CRC) 31 * 32 * All variables are big-endian except for the crc which is little-endian. 33 * 34 * Valid values for the packet type are listed below as defines prefixed 35 * with "HDHOMERUN_TYPE_" 36 * 37 * Discovery: 38 * 39 * The payload for a discovery request or reply is a simple sequence of 40 * tag-length-value data: 41 * uint8_t Tag 42 * varlen Length 43 * uint8_t[] Value (0-n bytes) 44 * 45 * The length field can be one or two bytes long. 46 * For a length <= 127 bytes the length is expressed as a single byte. The 47 * most-significant-bit is clear indicating a single-byte length. 48 * For a length >= 128 bytes the length is expressed as a sequence of two bytes as follows: 49 * The first byte is contains the least-significant 7-bits of the length. The 50 * most-significant bit is then set (add 0x80) to indicate that it is a two byte length. 51 * The second byte contains the length shifted down 7 bits. 52 * 53 * A discovery request packet has a packet type of HDHOMERUN_TYPE_DISCOVER_REQ and should 54 * contain two tags: HDHOMERUN_TAG_DEVICE_TYPE and HDHOMERUN_TAG_DEVICE_ID. 55 * The HDHOMERUN_TAG_DEVICE_TYPE value should be set to HDHOMERUN_DEVICE_TYPE_TUNER. 56 * The HDHOMERUN_TAG_DEVICE_ID value should be set to HDHOMERUN_DEVICE_ID_WILDCARD to match 57 * all devices, or to the 32-bit device id number to match a single device. 58 * 59 * The discovery response packet has a packet type of HDHOMERUN_TYPE_DISCOVER_RPY and has the 60 * same format as the discovery request packet with the two tags: HDHOMERUN_TAG_DEVICE_TYPE and 61 * HDHOMERUN_TAG_DEVICE_ID. In the future additional tags may also be returned - unknown tags 62 * should be skipped and not treated as an error. 63 * 64 * Control get/set: 65 * 66 * The payload for a control get/set request is a simple sequence of tag-length-value data 67 * following the same format as for discover packets. 68 * 69 * A get request packet has a packet type of HDHOMERUN_TYPE_GETSET_REQ and should contain 70 * the tag: HDHOMERUN_TAG_GETSET_NAME. The HDHOMERUN_TAG_GETSET_NAME value should be a sequence 71 * of bytes forming a null-terminated string, including the NULL. The TLV length must include 72 * the NULL character so the length field should be set to strlen(str) + 1. 73 * 74 * A set request packet has a packet type of HDHOMERUN_TYPE_GETSET_REQ (same as a get request) 75 * and should contain two tags: HDHOMERUN_TAG_GETSET_NAME and HDHOMERUN_TAG_GETSET_VALUE. 76 * The HDHOMERUN_TAG_GETSET_NAME value should be a sequence of bytes forming a null-terminated 77 * string, including the NULL. 78 * The HDHOMERUN_TAG_GETSET_VALUE value should be a sequence of bytes forming a null-terminated 79 * string, including the NULL. 80 * 81 * The get and set reply packets have the packet type HDHOMERUN_TYPE_GETSET_RPY and have the same 82 * format as the set request packet with the two tags: HDHOMERUN_TAG_GETSET_NAME and 83 * HDHOMERUN_TAG_GETSET_VALUE. A set request is also implicit get request so the updated value is 84 * returned. 85 * 86 * If the device encounters an error handling the get or set request then the get/set reply packet 87 * will contain the tag HDHOMERUN_TAG_ERROR_MESSAGE. The format of the value is a sequence of 88 * bytes forming a null-terminated string, including the NULL. 89 * 90 * In the future additional tags may also be returned - unknown tags should be skipped and not 91 * treated as an error. 92 * 93 * Security note: The application should not rely on the NULL character being present. The 94 * application should write a NULL character based on the TLV length to protect the application 95 * from a potential attack. 96 * 97 * Firmware Upgrade: 98 * 99 * A firmware upgrade packet has a packet type of HDHOMERUN_TYPE_UPGRADE_REQ and has a fixed format: 100 * uint32_t Position in bytes from start of file. 101 * uint8_t[256] Firmware data (256 bytes) 102 * 103 * The data must be uploaded in 256 byte chunks and must be uploaded in order. 104 * The position number is in bytes so will increment by 256 each time. 105 * 106 * When all data is uploaded it should be signaled complete by sending another packet of type 107 * HDHOMERUN_TYPE_UPGRADE_REQ with payload of a single uint32_t with the value 0xFFFFFFFF. 108 */ 109 24 110 #define HDHOMERUN_DISCOVER_UDP_PORT 65001 25 111 #define HDHOMERUN_CONTROL_TCP_PORT 65001 26 112 … … 43 129 44 130 #define HDHOMERUN_MIN_PEEK_LENGTH 4 45 131 46 extern unsigned char hdhomerun_read_u8(unsigned char **pptr); 47 extern unsigned short hdhomerun_read_u16(unsigned char **pptr); 48 extern unsigned long hdhomerun_read_u32(unsigned char **pptr); 49 extern void hdhomerun_write_u8(unsigned char **pptr, unsigned char v); 50 extern void hdhomerun_write_u16(unsigned char **pptr, unsigned short v); 51 extern void hdhomerun_write_u32(unsigned char **pptr, unsigned long v); 52 extern void hdhomerun_write_crc(unsigned char **pptr, unsigned char *start); 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); 53 141 54 extern int hdhomerun_peek_packet_length(unsigned char*ptr);55 extern int hdhomerun_process_packet(u nsigned char **pptr, unsigned char**pend);56 extern int hdhomerun_read_tlv(u nsigned char **pptr, unsigned char *end, unsigned char *ptag, int *plength, unsigned char**pvalue);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); 57 145 58 extern void hdhomerun_write_discover_request(unsigned char **pptr, unsigned long device_type, unsigned long device_id); 59 extern void hdhomerun_write_get_request(unsigned char **pptr, const char *name); 60 extern void hdhomerun_write_set_request(unsigned char **pptr, const char *name, const char *value); 61 extern void hdhomerun_write_upgrade_request(unsigned char **pptr, unsigned long sequence, void *data, int length); 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); 62 149 63 150 #ifdef __cplusplus 64 151 } 65 152 #endif 153 -
libs/libmythtv/hdhomerun/hdhomerun_device.h
1 /* 2 * hdhomerun_device.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 2.1 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, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21 #ifdef __cplusplus 22 extern "C" { 23 #endif 24 25 #define HDHOMERUN_DEVICE_MAX_TUNE_TO_LOCK_TIME 1500 26 #define HDHOMERUN_DEVICE_MAX_LOCK_TO_DATA_TIME 2000 27 #define HDHOMERUN_DEVICE_MAX_TUNE_TO_DATA_TIME (HDHOMERUN_DEVICE_MAX_TUNE_TO_LOCK_TIME + HDHOMERUN_DEVICE_MAX_LOCK_TO_DATA_TIME) 28 29 struct hdhomerun_device_t; 30 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 }; 39 40 /* 41 * Create a device object. 42 * 43 * Typically a device object will be created for each tuner. 44 * It is valid to have multiple device objects communicating with a single HDHomeRun. 45 * 46 * For example, a threaded application that streams video from 4 tuners (2 HDHomeRun devices) and has 47 * GUI feedback to the user of the selected tuner might use 5 device objects: 4 for streaming video 48 * (one per thread) and one for the GUI display that can just between tuners. 49 * 50 * This function will not attempt to connect to the device. 51 * The connection will be established when first used. 52 * 53 * uint32_t device_id = 32-bit device id of device. Set to HDHOMERUN_DEVICE_ID_WILDCARD to match any device ID. 54 * uint32_t device_ip = IP address of device. Set to 0 to auto-detect. 55 * unsigned int tuner = tuner index (0 or 1). Can be changed later by calling hdhomerun_device_set_tuner. 56 * 57 * Returns a pointer to the newly created device object. 58 * 59 * When no longer needed, the socket should be destroyed by calling hdhomerun_device_destroy. 60 */ 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); 64 65 /* 66 * Get the local machine IP address used when communicating with the device. 67 * 68 * This function is useful for determining the IP address to use with set target commands. 69 * 70 * Returns 32-bit IP address with native endianness, or 0 on error. 71 */ 72 extern uint32_t hdhomerun_device_get_local_machine_addr(struct hdhomerun_device_t *hd); 73 74 /* 75 * Get operations. 76 * 77 * struct hdhomerun_tuner_status_t *status = Pointer to caller supplied status struct to be populated with result. 78 * const char **p<name> = Caller supplied char * to be updated to point to the result string. The string will remain 79 * valid until another call to a device function. 80 * 81 * Returns 1 if the operation was successful. 82 * Returns 0 if the operation was rejected. 83 * Returns -1 if a communication error occurred. 84 */ 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); 94 95 /* 96 * Set operations. 97 * 98 * const char *<name> = String to send to device. 99 * 100 * Returns 1 if the operation was successful. 101 * Returns 0 if the operation was rejected. 102 * Returns -1 if a communication error occurred. 103 */ 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); 110 111 /* 112 * Get/set a named control variable on the device. 113 * 114 * const char *name: The name of var to get/set (c-string). The supported vars is device/firmware dependant. 115 * const char *value: The value to set (c-string). The format is device/firmware dependant. 116 117 * char **pvalue: If provided, the caller-supplied char pointer will be populated with a pointer to the value 118 * string returned by the device, or NULL if the device returned an error string. The string will remain 119 * valid until the next call to a control sock function. 120 * char **perror: If provided, the caller-supplied char pointer will be populated with a pointer to the error 121 * string returned by the device, or NULL if the device returned an value string. The string will remain 122 * valid until the next call to a control sock function. 123 * 124 * Returns 1 if the operation was successful (pvalue set, perror NULL). 125 * Returns 0 if the operation was rejected (pvalue NULL, perror set). 126 * Returns -1 if a communication error occurs. 127 */ 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); 130 131 /* 132 * Stream a filtered program or the unfiltered stream. 133 * 134 * The hdhomerun_device_stream_start function initializes the process and tells the device to start streamin data. 135 * 136 * uint16_t program_number = The program number to filer, or 0 for unfiltered. 137 * 138 * Returns 1 if the oprtation started successfully. 139 * Returns 0 if the operation was rejected. 140 * Returns -1 if a communication error occurs. 141 * 142 * The hdhomerun_device_stream_recv function should be called periodically to receive the stream data. 143 * The buffer can losslessly store 1 second of data, however a more typical call rate would be every 64ms. 144 * 145 * The hdhomerun_device_stream_stop function tells the device to stop streaming data. 146 */ 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); 150 151 /* 152 * Check that the device is running the recommended firmware. 153 * 154 * uint32_t features: Reserved for future use. Set to zero. 155 * 156 * Returns 1 if the firmware meets the minimum requriements for all operations. 157 * Returns 0 if th firmware does not meet the minimum requriements for all operations. 158 * Returns -1 if an error occurs. 159 */ 160 extern int hdhomerun_device_firmware_version_check(struct hdhomerun_device_t *hd, uint32_t features); 161 162 /* 163 * Upload new firmware to the device. 164 * 165 * FILE *upgrade_file: File pointer to read from. The file must have been opened in binary mode for reading. 166 * 167 * Returns 1 if the upload succeeded. 168 * Returns 0 if the upload was rejected. 169 * Returns -1 if an error occurs. 170 */ 171 extern int hdhomerun_device_upgrade(struct hdhomerun_device_t *hd, FILE *upgrade_file); 172 173 /* 174 * Low level accessor functions. 175 */ 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); 178 179 #ifdef __cplusplus 180 } 181 #endif -
libs/libmythtv/hdhomerun/hdhomerun_config.c
18 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 19 */ 20 20 21 #include "hdhomerun_os.h" 22 #include "hdhomerun_pkt.h" 23 #include "hdhomerun_discover.h" 24 #include "hdhomerun_control.h" 21 #include "hdhomerun.h" 25 22 26 const char *appname;23 static const char *appname; 27 24 25 struct hdhomerun_device_t *hd; 26 28 27 static int help(void) 29 28 { 30 29 printf("Usage:\n"); 31 30 printf("\t%s discover\n", appname); 32 printf("\t%s <id |ip> get help\n", appname);33 printf("\t%s <id |ip> get <item>\n", appname);34 printf("\t%s <id |ip> set <item> <value>\n", appname);35 printf("\t%s <id |ip> scan <tuner> <starting channel>\n", appname);36 printf("\t%s <id |ip> upgrade <filename>\n", appname);37 return 1;31 printf("\t%s <id> get help\n", appname); 32 printf("\t%s <id> get <item>\n", appname); 33 printf("\t%s <id> set <item> <value>\n", appname); 34 printf("\t%s <id> scan <tuner> <starting channel>\n", appname); 35 printf("\t%s <id> upgrade <filename>\n", appname); 36 return -1; 38 37 } 39 38 40 39 static void extract_appname(const char *argv0) 41 40 { 42 c har *ptr = strrchr(argv0, '/');41 const char *ptr = strrchr(argv0, '/'); 43 42 if (ptr) { 44 43 argv0 = ptr + 1; 45 44 } … … 50 49 appname = argv0; 51 50 } 52 51 53 static int contains(const char *arg, const char *cmpstr)52 static bool_t contains(const char *arg, const char *cmpstr) 54 53 { 55 54 if (strcmp(arg, cmpstr) == 0) { 56 return 1;55 return TRUE; 57 56 } 58 57 59 58 if (*arg++ != '-') { 60 return 0;59 return FALSE; 61 60 } 62 61 if (*arg++ != '-') { 63 return 0;62 return FALSE; 64 63 } 65 64 if (strcmp(arg, cmpstr) == 0) { 66 return 1;65 return TRUE; 67 66 } 68 67 69 return 0;68 return FALSE; 70 69 } 71 70 72 static int discover_print_internal(struct hdhomerun_discover_sock_t *discover_sock)73 {74 if (hdhomerun_discover_send(discover_sock, HDHOMERUN_DEVICE_TYPE_TUNER, HDHOMERUN_DEVICE_ID_WILDCARD) < 0) {75 fprintf(stderr, "unable to send discover request\n");76 return 1;77 }78 79 while (1) {80 struct hdhomerun_discover_device_t result;81 int ret = hdhomerun_discover_recv(discover_sock, &result, 1000);82 if (ret < 0) {83 fprintf(stderr, "error listening for discover response\n");84 return 1;85 }86 if (ret == 0) {87 return 0;88 }89 90 printf("hdhomerun device %08lX found at %ld.%ld.%ld.%ld\n",91 result.device_id,92 (result.ip_addr >> 24) & 0x0FF, (result.ip_addr >> 16) & 0x0FF,93 (result.ip_addr >> 8) & 0x0FF, (result.ip_addr >> 0) & 0x0FF94 );95 }96 }97 98 71 static int discover_print(void) 99 72 { 100 struct hdhomerun_discover_sock_t *discover_sock = hdhomerun_discover_create(1000); 101 if (!discover_sock) { 102 fprintf(stderr, "unable to create discover socket\n"); 103 return 1; 73 struct hdhomerun_discover_device_t result_list[64]; 74 int count = hdhomerun_discover_find_devices(HDHOMERUN_DEVICE_TYPE_TUNER, result_list, 64); 75 if (count < 0) { 76 fprintf(stderr, "error sending discover request\n"); 77 return -1; 104 78 } 105 106 int ret = discover_print_internal(discover_sock); 107 108 hdhomerun_discover_destroy(discover_sock); 109 return ret; 110 } 111 112 static unsigned long get_ip_addr(struct hdhomerun_discover_sock_t *discover_sock, const char *id_str) 113 { 114 int a[4]; 115 if (sscanf(id_str, "%u.%u.%u.%u", &a[0], &a[1], &a[2], &a[3]) == 4) { 116 return (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | (a[3] << 0); 117 } 118 119 unsigned long id = (unsigned long)strtoll(id_str, NULL, 16); 120 if (!hdhomerun_discover_validate_device_id(id)) { 121 fprintf(stderr, "invalid device id: %s\n", id_str); 79 if (count == 0) { 80 printf("no devices found\n"); 122 81 return 0; 123 82 } 124 83 125 if (hdhomerun_discover_send(discover_sock, HDHOMERUN_DEVICE_TYPE_TUNER, id) < 0) { 126 fprintf(stderr, "unable to send discover request\n"); 127 return 0; 84 int index; 85 for (index = 0; index < count; index++) { 86 struct hdhomerun_discover_device_t *result = &result_list[index]; 87 printf("hdhomerun device %08lX found at %u.%u.%u.%u\n", 88 (unsigned long)result->device_id, 89 (unsigned int)(result->ip_addr >> 24) & 0x0FF, (unsigned int)(result->ip_addr >> 16) & 0x0FF, 90 (unsigned int)(result->ip_addr >> 8) & 0x0FF, (unsigned int)(result->ip_addr >> 0) & 0x0FF 91 ); 128 92 } 129 93 130 struct hdhomerun_discover_device_t result; 131 int ret = hdhomerun_discover_recv(discover_sock, &result, 1000); 132 if (ret < 0) { 133 fprintf(stderr, "error listening for discover response\n"); 134 return 0; 135 } 136 if (ret == 0) { 137 fprintf(stderr, "unable to find hdhomerun device %08lX\n", id); 138 return 0; 139 } 140 141 return result.ip_addr; 94 return count; 142 95 } 143 96 144 static struct hdhomerun_control_sock_t *create_control_sock(const char *id_str)97 static bool_t parse_device_id_str(const char *s, uint32_t *pdevice_id, uint32_t *pdevice_ip) 145 98 { 146 struct hdhomerun_discover_sock_t *discover_sock = hdhomerun_discover_create(1000); 147 if (!discover_sock) { 148 fprintf(stderr, "unable to create discover socket\n"); 149 return NULL; 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; 150 104 } 151 105 152 unsigned long ip_addr = get_ip_addr(discover_sock, id_str); 153 154 hdhomerun_discover_destroy(discover_sock); 155 if (ip_addr == 0) { 156 return NULL; 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; 157 110 } 158 111 159 struct hdhomerun_control_sock_t *control_sock = hdhomerun_control_create(ip_addr, 1000);160 if (! control_sock) {161 fprintf(stderr, " unable to connect to hdhomerun device\n");162 return NULL;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; 163 116 } 164 117 165 return control_sock; 118 *pdevice_id = device_id; 119 *pdevice_ip = 0; 120 return TRUE; 166 121 } 167 122 168 int cmd_get(struct hdhomerun_control_sock_t *control_sock,const char *item)123 static int cmd_get(const char *item) 169 124 { 170 if (hdhomerun_control_send_get_request(control_sock, item) < 0) { 125 char *ret_value; 126 char *ret_error; 127 if (hdhomerun_device_get_var(hd, item, &ret_value, &ret_error) < 0) { 171 128 fprintf(stderr, "communication error sending request to hdhomerun device\n"); 172 return 1;129 return -1; 173 130 } 174 131 175 struct hdhomerun_control_data_t result; 176 if (hdhomerun_control_recv(control_sock, &result, 1000) <= 0) { 177 fprintf(stderr, "communication error receiving response from hdhomerun device\n"); 178 return 1; 132 if (ret_error) { 133 printf("%s\n", ret_error); 134 return 0; 179 135 } 180 if (result.type != HDHOMERUN_TYPE_GETSET_RPY) {181 fprintf(stderr, "unexpected reply type from hdhomerun device\n");182 return 1;183 }184 136 185 while (result.ptr < result.end) { 186 unsigned char tag; 187 int length; 188 unsigned char *value; 189 if (hdhomerun_read_tlv(&result.ptr, result.end, &tag, &length, &value) < 0) { 190 break; 191 } 192 switch (tag) { 193 case HDHOMERUN_TAG_ERROR_MESSAGE: 194 case HDHOMERUN_TAG_GETSET_VALUE: 195 printf("%s\n", (char *)value); 196 break; 197 } 198 } 199 200 return 0; 137 printf("%s\n", ret_value); 138 return 1; 201 139 } 202 140 203 int cmd_set(struct hdhomerun_control_sock_t *control_sock,const char *item, const char *value)141 static int cmd_set(const char *item, const char *value) 204 142 { 205 if (hdhomerun_control_send_set_request(control_sock, item, value) < 0) { 143 char *ret_error; 144 if (hdhomerun_device_set_var(hd, item, value, NULL, &ret_error) < 0) { 206 145 fprintf(stderr, "communication error sending request to hdhomerun device\n"); 207 return 1;146 return -1; 208 147 } 209 148 210 struct hdhomerun_control_data_t result; 211 if (hdhomerun_control_recv(control_sock, &result, 1000) <= 0) { 212 fprintf(stderr, "communication error receiving response from hdhomerun device\n"); 213 return 1; 149 if (ret_error) { 150 printf("%s\n", ret_error); 151 return 0; 214 152 } 215 if (result.type != HDHOMERUN_TYPE_GETSET_RPY) {216 fprintf(stderr, "unexpected reply type from hdhomerun device\n");217 return 1;218 }219 153 220 while (result.ptr < result.end) { 221 unsigned char tag; 222 int length; 223 unsigned char *value; 224 if (hdhomerun_read_tlv(&result.ptr, result.end, &tag, &length, &value) < 0) { 225 break; 226 } 227 switch (tag) { 228 case HDHOMERUN_TAG_ERROR_MESSAGE: 229 printf("%s\n", (char *)value); 230 break; 231 } 232 } 233 234 return 0; 154 return 1; 235 155 } 236 156 237 int cmd_scan(struct hdhomerun_control_sock_t *control_sock, const char *tuner_str, const char *start_value)157 static int cmd_streaminfo(const char *tuner_str) 238 158 { 239 int tuner = atoi(tuner_str); 159 fprintf(stderr, "streaminfo: use \"get /tuner<n>/streaminfo\"\n"); 160 return -1; 161 } 240 162 241 /* Test starting channel. */ 242 char item[64]; 243 sprintf(item, "/tuner%d/channel", tuner);244 i nt ret = cmd_set(control_sock, item, start_value);245 if (ret != 0) {246 return ret;163 static int cmd_scan(const char *tuner_str, const char *start_value) 164 { 165 unsigned int tuner; 166 if (sscanf(tuner_str, "%u", &tuner) != 1) { 167 fprintf(stderr, "invalid tuner number\n"); 168 return -1; 247 169 } 248 170 249 char channel_value[64]; 250 strncpy(channel_value, start_value, sizeof(channel_value)); 251 channel_value[sizeof(channel_value) - 8] = 0; 171 hdhomerun_device_set_tuner(hd, tuner); 252 172 253 char *ptr = strrchr(channel_value, ':'); 254 if (!ptr) { 255 ptr = channel_value; 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; 256 180 } else { 257 ptr++;181 channel_number_ptr++; 258 182 } 259 183 260 int channel = atol(ptr);261 if (channel == 0) {184 unsigned int channel_number = atol(channel_number_ptr); 185 if (channel_number == 0) { 262 186 fprintf(stderr, "invalid starting channel\n"); 263 return 1;187 return -1; 264 188 } 265 189 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"); 194 return -1; 195 } 196 if (ret == 0) { 197 fprintf(stderr, "invalid starting channel\n"); 198 return -1; 199 } 200 266 201 while (1) { 267 202 /* Update channel value */ 268 sprintf( ptr, "%d", channel);203 sprintf(channel_number_ptr, "%u", channel_number); 269 204 270 205 /* Set channel. */ 271 sprintf(item, "/tuner%d/channel", tuner);272 if ( hdhomerun_control_send_set_request(control_sock, item, channel_value)< 0) {206 ret = hdhomerun_device_set_tuner_channel(hd, channel_str); 207 if (ret < 0) { 273 208 fprintf(stderr, "communication error sending request to hdhomerun device\n"); 274 return 1;209 return -1; 275 210 } 276 277 /* Verify set succeeded. */ 278 struct hdhomerun_control_data_t result; 279 if (hdhomerun_control_recv(control_sock, &result, 1000) <= 0) { 280 fprintf(stderr, "communication error receiving response from hdhomerun device\n"); 281 return 1; 211 if (ret == 0) { 212 return 0; 282 213 } 283 if (result.type != HDHOMERUN_TYPE_GETSET_RPY) {284 fprintf(stderr, "unexpected reply type from hdhomerun device\n");285 return 1;286 }287 while (result.ptr < result.end) {288 unsigned char tag;289 int length;290 unsigned char *value;291 if (hdhomerun_read_tlv(&result.ptr, result.end, &tag, &length, &value) < 0) {292 break;293 }294 if (tag == HDHOMERUN_TAG_ERROR_MESSAGE) {295 return 0;296 }297 }298 214 299 /* Wait for 1s. */300 sleep(1);215 /* Wait 1.5s for lock (qam auto is the slowest to lock). */ 216 usleep(HDHOMERUN_DEVICE_MAX_TUNE_TO_LOCK_TIME * 1000); 301 217 302 /* Get status . */303 s printf(item, "/tuner%d/status", tuner);304 if (hdhomerun_ control_send_get_request(control_sock, item) < 0) {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) { 305 221 fprintf(stderr, "communication error sending request to hdhomerun device\n"); 306 return 1;222 return -1; 307 223 } 308 224 309 /* Status result. */ 310 if (hdhomerun_control_recv(control_sock, &result, 1000) <= 0) { 311 fprintf(stderr, "communication error receiving response from hdhomerun device\n"); 312 return 1; 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; 313 230 } 314 if (result.type != HDHOMERUN_TYPE_GETSET_RPY) { 315 fprintf(stderr, "unexpected reply type from hdhomerun device\n"); 316 return 1; 231 232 /* Wait for 2s. */ 233 usleep(HDHOMERUN_DEVICE_MAX_LOCK_TO_DATA_TIME * 1000); 234 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"); 238 return -1; 317 239 } 318 char *status = NULL; 319 while (result.ptr < result.end) { 320 unsigned char tag; 321 int length; 322 unsigned char *value; 323 if (hdhomerun_read_tlv(&result.ptr, result.end, &tag, &length, &value) < 0) { 324 break; 325 } 326 if (tag == HDHOMERUN_TAG_ERROR_MESSAGE) { 327 return 0; 328 } 329 if (tag == HDHOMERUN_TAG_GETSET_VALUE) { 330 status = (char *)value; 331 } 240 if (status.signal_strength == 0) { 241 printf("%s: no signal\n", channel_str); 242 channel_number++; 243 continue; 332 244 } 333 if (!status) { 334 fprintf(stderr, "unexpected reply type from hdhomerun device\n"); 335 return 1; 336 } 245 printf("%s: ss=%u snq=%u seq=%u\n", channel_str, status.signal_strength, status.signal_to_noise_quality, status.symbol_error_quality); 337 246 338 /* If no signal then advance to next channel. */339 char *ss_str = strstr(status, "ss=");340 if (!ss_str) {341 printf("%s\n", status);342 channel ++;247 /* Detect sub channels. */ 248 usleep(4 * 1000000); 249 char *streaminfo; 250 if (hdhomerun_device_get_tuner_streaminfo(hd, &streaminfo) <= 0) { 251 channel_number++; 343 252 continue; 344 253 } 345 int ss = atoi(ss_str + strlen("ss=")); 346 if (ss == 0) { 347 printf("%s\n", status); 348 channel++; 349 continue; 350 } 254 while (1) { 255 char *end = strchr(streaminfo, '\n'); 256 if (!end) { 257 break; 258 } 351 259 352 /* Wait for 2s. */353 sleep(2);260 *end++ = 0; 261 printf("program %s\n", streaminfo); 354 262 355 /* Display channel status. */356 cmd_get(control_sock, item);263 streaminfo = end; 264 } 357 265 358 266 /* Advance to next channel. */ 359 channel ++;267 channel_number++; 360 268 } 361 269 } 362 270 363 int cmd_upgrade(struct hdhomerun_control_sock_t *control_sock,const char *filename)271 static int cmd_upgrade(const char *filename) 364 272 { 365 273 FILE *fp = fopen(filename, "rb"); 366 274 if (!fp) { 367 275 fprintf(stderr, "unable to open file %s\n", filename); 368 return 1;276 return -1; 369 277 } 370 278 371 unsigned long sequence = 0; 372 while (1) { 373 unsigned char data[256]; 374 int length = fread(data, 1, 256, fp); 375 if (length == 0) { 376 break; 377 } 378 379 int ret = hdhomerun_control_send_upgrade_request(control_sock, sequence, data, length); 380 if (ret < 0) { 381 fprintf(stderr, "communication error sending upgrade request to hdhomerun device\n"); 382 fclose(fp); 383 return 1; 384 } 385 386 sequence += length; 279 if (hdhomerun_device_upgrade(hd, fp) <= 0) { 280 fprintf(stderr, "error sending upgrade file to hdhomerun device\n"); 281 fclose(fp); 282 return -1; 387 283 } 388 284 389 fclose(fp);390 if (sequence == 0) {391 fprintf(stderr, "upgrade file does not contain data\n");392 return 1;393 }394 395 int ret = hdhomerun_control_send_upgrade_request(control_sock, 0xFFFFFFFF, NULL, 0);396 if (ret < 0) {397 fprintf(stderr, "communication error sending upgrade request to hdhomerun device\n");398 return 1;399 }400 401 285 printf("upgrade complete\n"); 402 286 return 0; 403 287 } 404 288 405 int main_cmd(struct hdhomerun_control_sock_t *control_sock,int argc, char *argv[])289 static int main_cmd(int argc, char *argv[]) 406 290 { 407 291 if (argc < 1) { 408 292 return help(); … … 414 298 if (argc < 1) { 415 299 return help(); 416 300 } 417 return cmd_get( control_sock,argv[0]);301 return cmd_get(argv[0]); 418 302 } 419 303 420 304 if (contains(cmd, "set")) { 421 305 if (argc < 2) { 422 306 return help(); 423 307 } 424 return cmd_set( control_sock,argv[0], argv[1]);308 return cmd_set(argv[0], argv[1]); 425 309 } 426 310 311 if (contains(cmd, "streaminfo")) { 312 if (argc < 1) { 313 return help(); 314 } 315 return cmd_streaminfo(argv[0]); 316 } 317 427 318 if (contains(cmd, "scan")) { 428 319 if (argc < 2) { 429 320 return help(); 430 321 } 431 return cmd_scan( control_sock,argv[0], argv[1]);322 return cmd_scan(argv[0], argv[1]); 432 323 } 433 324 434 325 if (contains(cmd, "upgrade")) { 435 326 if (argc < 1) { 436 327 return help(); 437 328 } 438 return cmd_upgrade( control_sock,argv[0]);329 return cmd_upgrade(argv[0]); 439 330 } 440 331 441 332 return help(); 442 333 } 443 334 444 int main(int argc, char *argv[])335 static int main_internal(int argc, char *argv[]) 445 336 { 446 extract_appname(argv[0]); 337 #if defined(__WINDOWS__) 338 //Start pthreads 339 pthread_win32_process_attach_np(); 447 340 341 // Start WinSock 342 WORD wVersionRequested = MAKEWORD(2, 0); 343 WSADATA wsaData; 344 WSAStartup(wVersionRequested, &wsaData); 345 #endif 346 347 extract_appname(argv[0]); 448 348 argv++; 449 349 argc--; 450 350 … … 460 360 return discover_print(); 461 361 } 462 362 463 struct hdhomerun_control_sock_t *control_sock = create_control_sock(id_str); 464 if (!control_sock) { 465 return 1; 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; 466 367 } 467 368 468 int ret = main_cmd(control_sock, argc, argv); 469 hdhomerun_control_destroy(control_sock); 369 /* Device object. */ 370 hd = hdhomerun_device_create(device_id, device_ip, 0); 371 if (!hd) { 372 fprintf(stderr, "unable to create device\n"); 373 return -1; 374 } 375 376 /* Connect to device and check firmware version. */ 377 int ret = hdhomerun_device_firmware_version_check(hd, 0); 378 if (ret < 0) { 379 fprintf(stderr, "unable to connect to device\n"); 380 hdhomerun_device_destroy(hd); 381 return -1; 382 } 383 if (ret == 0) { 384 fprintf(stderr, "WARNING: firmware upgrade needed for all operations to function\n"); 385 } 386 387 /* Command. */ 388 ret = main_cmd(argc, argv); 389 390 /* Cleanup. */ 391 hdhomerun_device_destroy(hd); 392 393 /* Complete. */ 470 394 return ret; 471 395 } 396 397 int main(int argc, char *argv[]) 398 { 399 int ret = main_internal(argc, argv); 400 if (ret <= 0) { 401 return 1; 402 } 403 return 0; 404 } -
libs/libmythtv/hdhomerun/hdhomerun_video.c
21 21 #include "hdhomerun_os.h" 22 22 #include "hdhomerun_pkt.h" 23 23 #include "hdhomerun_video.h" 24 #include <pthread.h>25 24 26 25 struct hdhomerun_video_sock_t { 27 u nsigned char*buffer;28 unsigned longbuffer_size;29 volatile unsigned longhead;30 volatile unsigned longtail;31 unsigned longadvance;32 volatile int running;33 volatile int terminate;26 uint8_t *buffer; 27 size_t buffer_size; 28 volatile size_t head; 29 volatile size_t tail; 30 size_t advance; 31 volatile bool_t running; 32 volatile bool_t terminate; 34 33 pthread_t thread; 35 34 int sock; 36 35 }; 37 36 38 37 static void *hdhomerun_video_thread(void *arg); 39 38 40 st ruct hdhomerun_video_sock_t *hdhomerun_video_create(unsigned long buffer_size, unsigned long timeout)39 static bool_t hdhomerun_video_bind_sock_internal(struct hdhomerun_video_sock_t *vs, uint16_t listen_port) 41 40 { 42 /* Buffer size. */ 43 buffer_size = (buffer_size / VIDEO_DATA_PACKET_SIZE) * VIDEO_DATA_PACKET_SIZE; 44 if (buffer_size == 0) { 45 return NULL; 41 struct sockaddr_in sock_addr; 42 memset(&sock_addr, 0, sizeof(sock_addr)); 43 sock_addr.sin_family = AF_INET; 44 sock_addr.sin_addr.s_addr = htonl(INADDR_ANY); 45 sock_addr.sin_port = htons(listen_port); 46 if (bind(vs->sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) { 47 return FALSE; 46 48 } 47 buffer_size += VIDEO_DATA_PACKET_SIZE; 49 return TRUE; 50 } 48 51 52 static bool_t hdhomerun_video_bind_sock(struct hdhomerun_video_sock_t *vs, uint16_t listen_port) 53 { 54 if (listen_port != 0) { 55 return hdhomerun_video_bind_sock_internal(vs, listen_port); 56 } 57 58 #if defined(__CYGWIN__) || defined(__WINDOWS__) 59 /* Windows firewall silently blocks a listening port if the port number is not explicitly given. */ 60 /* Workaround - pick a random port number. The port may already be in use to try multiple port numbers. */ 61 srand((int)getcurrenttime()); 62 int retry; 63 for (retry = 8; retry > 0; retry--) { 64 uint16_t listen_port = (uint16_t)((rand() % 32768) + 32768); 65 if (hdhomerun_video_bind_sock_internal(vs, listen_port)) { 66 return TRUE; 67 } 68 } 69 return FALSE; 70 #else 71 return hdhomerun_video_bind_sock_internal(vs, listen_port); 72 #endif 73 } 74 75 struct hdhomerun_video_sock_t *hdhomerun_video_create(uint16_t listen_port, size_t buffer_size) 76 { 49 77 /* Create object. */ 50 78 struct hdhomerun_video_sock_t *vs = (struct hdhomerun_video_sock_t *)calloc(1, sizeof(struct hdhomerun_video_sock_t)); 51 79 if (!vs) { 52 80 return NULL; 53 81 } 54 82 83 /* Buffer size. */ 84 vs->buffer_size = (buffer_size / VIDEO_DATA_PACKET_SIZE) * VIDEO_DATA_PACKET_SIZE; 85 if (vs->buffer_size == 0) { 86 free(vs); 87 return NULL; 88 } 89 vs->buffer_size += VIDEO_DATA_PACKET_SIZE; 90 55 91 /* Create buffer. */ 56 vs->buffer_size = buffer_size; 57 vs->buffer = (unsigned char *)malloc(buffer_size); 92 vs->buffer = (uint8_t *)malloc(vs->buffer_size); 58 93 if (!vs->buffer) { 59 94 free(vs); 60 95 return NULL; 61 96 } 62 97 63 98 /* Create socket. */ 64 vs->sock = socket(AF_INET, SOCK_DGRAM, 0);99 vs->sock = (int)socket(AF_INET, SOCK_DGRAM, 0); 65 100 if (vs->sock == -1) { 66 101 free(vs->buffer); 67 102 free(vs); 68 103 return NULL; 69 104 } 70 105 71 /* Set buffer size. */72 unsigned longrx_size = 1024 * 1024;73 setsockopt(vs->sock, SOL_SOCKET, SO_RCVBUF, &rx_size, sizeof(rx_size));106 /* Expand socket buffer size. */ 107 int rx_size = 1024 * 1024; 108 setsockopt(vs->sock, SOL_SOCKET, SO_RCVBUF, (char *)&rx_size, sizeof(rx_size)); 74 109 75 /* Set timeout. */ 76 struct timeval t; 77 t.tv_sec = timeout / 1000; 78 t.tv_usec = (timeout % 1000) * 1000; 79 setsockopt(vs->sock, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(t)); 110 /* Set timeouts. */ 111 setsocktimeout(vs->sock, SOL_SOCKET, SO_SNDTIMEO, 1000); 112 setsocktimeout(vs->sock, SOL_SOCKET, SO_RCVTIMEO, 1000); 80 113 81 114 /* Bind socket. */ 82 struct sockaddr_in sock_addr; 83 memset(&sock_addr, 0, sizeof(sock_addr)); 84 sock_addr.sin_family = AF_INET; 85 sock_addr.sin_addr.s_addr = htonl(INADDR_ANY); 86 sock_addr.sin_port = htons(0); 87 if (bind(vs->sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) { 115 if (!hdhomerun_video_bind_sock(vs, listen_port)) { 88 116 hdhomerun_video_destroy(vs); 89 117 return NULL; 90 118 } … … 111 139 free(vs); 112 140 } 113 141 114 u nsigned short hdhomerun_video_get_local_port(struct hdhomerun_video_sock_t *vs)142 uint16_t hdhomerun_video_get_local_port(struct hdhomerun_video_sock_t *vs) 115 143 { 116 144 struct sockaddr_in sock_addr; 117 145 socklen_t sockaddr_size = sizeof(sock_addr); … … 121 149 return ntohs(sock_addr.sin_port); 122 150 } 123 151 124 int hdhomerun_video_get_state(struct hdhomerun_video_sock_t *vs)125 {126 if (vs->terminate) {127 return 0;128 }129 return 1;130 }131 132 152 int hdhomerun_video_get_sock(struct hdhomerun_video_sock_t *vs) 133 153 { 134 154 return vs->sock; … … 139 159 struct hdhomerun_video_sock_t *vs = (struct hdhomerun_video_sock_t *)arg; 140 160 141 161 while (!vs->terminate) { 142 unsigned longhead = vs->head;162 size_t head = vs->head; 143 163 144 164 /* Receive. */ 145 int length = recv(vs->sock, vs->buffer + head, VIDEO_DATA_PACKET_SIZE, 0);165 int length = recv(vs->sock, (char *)vs->buffer + head, VIDEO_DATA_PACKET_SIZE, 0); 146 166 if (length != VIDEO_DATA_PACKET_SIZE) { 147 167 if (length > 0) { 148 168 /* Data received but not valid - ignore. */ 149 169 continue; 150 170 } 151 if ( errno == EAGAIN) {171 if (sock_getlasterror_socktimeout) { 152 172 /* Wait for more data. */ 153 173 continue; 154 174 } … … 174 194 return NULL; 175 195 } 176 196 177 static void hdhomerun_copy_and_advance_tail(struct hdhomerun_video_sock_t *vs, unsigned char *buffer, unsigned longsize)197 uint8_t *hdhomerun_video_recv(struct hdhomerun_video_sock_t *vs, size_t max_size, size_t *pactual_size) 178 198 { 179 unsigned long tail = vs->tail;180 memcpy(buffer, vs->buffer + tail, size);199 size_t head = vs->head; 200 size_t tail = vs->tail; 181 201 182 tail += size;183 if (tail >= vs->buffer_size) {184 tail -= vs->buffer_size;185 }186 187 /* Atomic update. */188 vs->tail = tail;189 }190 191 unsigned long hdhomerun_video_available_length(struct hdhomerun_video_sock_t *vs)192 {193 unsigned long head = vs->head;194 unsigned long tail = vs->tail;195 196 if (head >= tail) {197 return head - tail - vs->advance;198 } else {199 return head + vs->buffer_size - tail - vs->advance;200 }201 }202 203 unsigned long hdhomerun_video_recv_memcpy(struct hdhomerun_video_sock_t *vs, unsigned char *buffer, unsigned long size)204 {205 unsigned long head = vs->head;206 unsigned long tail = vs->tail;207 208 if (head == tail) {209 return 0;210 }211 212 size = (size / VIDEO_DATA_PACKET_SIZE) * VIDEO_DATA_PACKET_SIZE;213 214 /* Straight memcpy case. */215 if (head > tail) {216 unsigned long avail = head - tail;217 if (size > avail) {218 size = avail;219 }220 hdhomerun_copy_and_advance_tail(vs, buffer, size);221 return size;222 }223 224 /* Memcpy with wrap around check. */225 unsigned long avail = vs->buffer_size - tail;226 if (avail >= size) {227 hdhomerun_copy_and_advance_tail(vs, buffer, size);228 return size;229 }230 231 /* Memcpy with wrap around. */232 hdhomerun_copy_and_advance_tail(vs, buffer, avail);233 return avail + hdhomerun_video_recv_memcpy(vs, buffer + avail, size - avail);234 }235 236 unsigned char *hdhomerun_video_recv_inplace(struct hdhomerun_video_sock_t *vs, unsigned long max_size, unsigned long *pactual_size)237 {238 unsigned long head = vs->head;239 unsigned long tail = vs->tail;240 241 202 if (vs->advance > 0) { 242 203 tail += vs->advance; 243 204 if (tail >= vs->buffer_size) { … … 254 215 return NULL; 255 216 } 256 217 257 unsigned long size = (max_size / VIDEO_DATA_PACKET_SIZE) * VIDEO_DATA_PACKET_SIZE; 218 size_t size = (max_size / VIDEO_DATA_PACKET_SIZE) * VIDEO_DATA_PACKET_SIZE; 219 if (size == 0) { 220 vs->advance = 0; 221 *pactual_size = 0; 222 return NULL; 223 } 258 224 259 unsigned longavail;225 size_t avail; 260 226 if (head > tail) { 261 227 avail = head - tail; 262 228 } else { … … 274 240 { 275 241 /* Atomic update of tail. */ 276 242 vs->tail = vs->head; 243 vs->advance = 0; 277 244 } 245 -
libs/libmythtv/hdhomerun/hdhomerun_video.h
23 23 24 24 struct hdhomerun_video_sock_t; 25 25 26 #define TS_PACKET_SIZE 188 26 27 #define VIDEO_DATA_PACKET_SIZE (188 * 7) 27 28 #define VIDEO_DATA_BUFFER_SIZE_1S (20000000 / 8) 28 29 29 extern struct hdhomerun_video_sock_t *hdhomerun_video_create(unsigned long buffer_size, unsigned long timeout); 30 /* 31 * Create a video/data socket. 32 * 33 * uint16_t listen_port: Port number to listen on. Set to 0 to auto-select. 34 * size_t buffer_size: Size of receive buffer. For 1 second of buffer use VIDEO_DATA_BUFFER_SIZE_1S. 35 * 36 * Returns a pointer to the newly created control socket. 37 * 38 * When no longer needed, the socket should be destroyed by calling hdhomerun_control_destroy. 39 */ 40 extern struct hdhomerun_video_sock_t *hdhomerun_video_create(uint16_t listen_port, size_t buffer_size); 30 41 extern void hdhomerun_video_destroy(struct hdhomerun_video_sock_t *vs); 31 extern unsigned short hdhomerun_video_get_local_port(struct hdhomerun_video_sock_t *vs); 32 extern int hdhomerun_video_get_state(struct hdhomerun_video_sock_t *vs); 42 43 /* 44 * Get the port the socket is listening on. 45 * 46 * Returns 16-bit port with native endianness, or 0 on error. 47 */ 48 extern uint16_t hdhomerun_video_get_local_port(struct hdhomerun_video_sock_t *vs); 49 50 /* 51 * Get the low-level socket handle. 52 */ 33 53 extern int hdhomerun_video_get_sock(struct hdhomerun_video_sock_t *vs); 34 extern unsigned long hdhomerun_video_available_length(struct hdhomerun_video_sock_t *vs); 35 extern unsigned long hdhomerun_video_recv_memcpy(struct hdhomerun_video_sock_t *vs, unsigned char *buffer, unsigned long size); 36 extern unsigned char *hdhomerun_video_recv_inplace(struct hdhomerun_video_sock_t *vs, unsigned long max_size, unsigned long *pactual_size); 54 55 /* 56 * Read data from buffer. 57 * 58 * size_t max_size: The maximum amount of data to be returned. 59 * size_t *pactual_size: The caller-supplied pactual_size value will be updated to contain the amount 60 * of data available to the caller. 61 * 62 * Returns a pointer to the data, or NULL if no data is available. 63 * The data will remain valid until another call to hdhomerun_video_recv. 64 * 65 * The amount of data returned will always be a multiple of VIDEO_DATA_PACKET_SIZE (1316). 66 * Attempting to read a single TS frame (188 bytes) will not return data as it is less than 67 * the minimum size. 68 * 69 * The buffer is implemented as a ring buffer. It is possible for this function to return a small 70 * amount of data when more is available due to the wrap-around case. 71 */ 72 extern uint8_t *hdhomerun_video_recv(struct hdhomerun_video_sock_t *vs, size_t max_size, size_t *pactual_size); 73 74 /* 75 * Flush the buffer. 76 */ 37 77 extern void hdhomerun_video_flush(struct hdhomerun_video_sock_t *vs); 38 78 39 79 #ifdef __cplusplus -
libs/libmythtv/hdhomerun/hdhomerun_discover.c
22 22 #include "hdhomerun_pkt.h" 23 23 #include "hdhomerun_discover.h" 24 24 25 #if defined(__CYGWIN__) 25 #if defined(__CYGWIN__) || defined(__WINDOWS__) 26 26 #include <windows.h> 27 27 #include <iptypes.h> 28 28 #include <iphlpapi.h> … … 32 32 int sock; 33 33 }; 34 34 35 st ruct hdhomerun_discover_sock_t *hdhomerun_discover_create(unsigned long timeout)35 static struct hdhomerun_discover_sock_t *hdhomerun_discover_create(void) 36 36 { 37 37 struct hdhomerun_discover_sock_t *ds = (struct hdhomerun_discover_sock_t *)malloc(sizeof(struct hdhomerun_discover_sock_t)); 38 38 if (!ds) { … … 40 40 } 41 41 42 42 /* Create socket. */ 43 ds->sock = socket(AF_INET, SOCK_DGRAM, 0);43 ds->sock = (int)socket(AF_INET, SOCK_DGRAM, 0); 44 44 if (ds->sock == -1) { 45 45 free(ds); 46 46 return NULL; 47 47 } 48 48 49 /* Set timeout. */ 50 struct timeval t; 51 t.tv_sec = timeout / 1000; 52 t.tv_usec = (timeout % 1000) * 1000; 53 setsockopt(ds->sock, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(t)); 49 /* Set timeouts. */ 50 setsocktimeout(ds->sock, SOL_SOCKET, SO_SNDTIMEO, 1000); 51 setsocktimeout(ds->sock, SOL_SOCKET, SO_RCVTIMEO, 1000); 54 52 55 53 /* Allow broadcast. */ 56 54 int sock_opt = 1; … … 63 61 sock_addr.sin_addr.s_addr = htonl(INADDR_ANY); 64 62 sock_addr.sin_port = htons(0); 65 63 if (bind(ds->sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) { 66 hdhomerun_discover_destroy(ds); 64 close(ds->sock); 65 free(ds); 67 66 return NULL; 68 67 } 69 68 … … 71 70 return ds; 72 71 } 73 72 74 void hdhomerun_discover_destroy(struct hdhomerun_discover_sock_t *ds)73 static void hdhomerun_discover_destroy(struct hdhomerun_discover_sock_t *ds) 75 74 { 76 75 close(ds->sock); 77 76 free(ds); 78 77 } 79 78 80 static int hdhomerun_discover_send_packet(struct hdhomerun_discover_sock_t *ds, u nsigned long ip_addr, unsigned long device_type, unsigned longdevice_id)79 static int hdhomerun_discover_send_packet(struct hdhomerun_discover_sock_t *ds, uint32_t ip_addr, uint32_t device_type, uint32_t device_id) 81 80 { 82 u nsigned charbuffer[1024];83 u nsigned char*ptr = buffer;81 uint8_t buffer[1024]; 82 uint8_t *ptr = buffer; 84 83 hdhomerun_write_discover_request(&ptr, device_type, device_id); 85 84 86 85 struct sockaddr_in sock_addr; … … 89 88 sock_addr.sin_addr.s_addr = htonl(ip_addr); 90 89 sock_addr.sin_port = htons(HDHOMERUN_DISCOVER_UDP_PORT); 91 90 92 int length = ptr - buffer;93 if (sendto(ds->sock, (char *)buffer, length, 0, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != length) {91 int length = (int)(ptr - buffer); 92 if (sendto(ds->sock, (char *)buffer, (int)length, 0, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != length) { 94 93 return -1; 95 94 } 96 95 97 96 return 0; 98 97 } 99 98 100 #if defined(__CYGWIN__) 101 static int hdhomerun_discover_send_internal(struct hdhomerun_discover_sock_t *ds, u nsigned long device_type, unsigned longdevice_id)99 #if defined(__CYGWIN__) || defined(__WINDOWS__) 100 static int hdhomerun_discover_send_internal(struct hdhomerun_discover_sock_t *ds, uint32_t device_type, uint32_t device_id) 102 101 { 103 102 PIP_ADAPTER_INFO pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO)); 104 unsigned longulOutBufLen = sizeof(IP_ADAPTER_INFO);103 ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO); 105 104 106 105 DWORD Ret = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen); 107 106 if (Ret != NO_ERROR) { … … 117 116 } 118 117 } 119 118 120 int send_count = 0;119 unsigned int send_count = 0; 121 120 PIP_ADAPTER_INFO pAdapter = pAdapterInfo; 122 121 while (pAdapter) { 123 122 IP_ADDR_STRING *pIPAddr = &pAdapter->IpAddressList; 124 123 while (pIPAddr) { 125 u nsigned longaddr = ntohl(inet_addr(pIPAddr->IpAddress.String));126 u nsigned longmask = ntohl(inet_addr(pIPAddr->IpMask.String));124 uint32_t addr = ntohl(inet_addr(pIPAddr->IpAddress.String)); 125 uint32_t mask = ntohl(inet_addr(pIPAddr->IpMask.String)); 127 126 128 u nsigned longbroadcast = addr | ~mask;127 uint32_t broadcast = addr | ~mask; 129 128 if ((broadcast == 0x00000000) || (broadcast == 0xFFFFFFFF)) { 130 129 pIPAddr = pIPAddr->Next; 131 130 continue; 132 131 } 133 132 134 hdhomerun_discover_send_packet(ds, broadcast, device_type, device_id); 133 if (hdhomerun_discover_send_packet(ds, broadcast, device_type, device_id) < 0) { 134 pIPAddr = pIPAddr->Next; 135 continue; 136 } 137 135 138 send_count++; 136 139 137 140 pIPAddr = pIPAddr->Next; … … 150 153 #endif 151 154 152 155 #if defined(__linux__) 153 static int hdhomerun_discover_send_internal(struct hdhomerun_discover_sock_t *ds, u nsigned long device_type, unsigned longdevice_id)156 static int hdhomerun_discover_send_internal(struct hdhomerun_discover_sock_t *ds, uint32_t device_type, uint32_t device_id) 154 157 { 155 158 FILE *fp = fopen("/proc/net/route", "r"); 156 159 if (!fp) { 157 160 return -1; 158 161 } 159 162 160 int send_count = 0;163 unsigned int send_count = 0; 161 164 while (1) { 162 165 char line[256]; 163 166 if (!fgets(line, sizeof(line), fp)) { … … 165 168 } 166 169 line[255] = 0; 167 170 168 u nsigned longdest;169 u nsigned longmask;170 if (sscanf(line, "%*s % lx %*x %*x %*d %*d %*d %lx", &dest, &mask) != 2) {171 uint32_t dest; 172 uint32_t mask; 173 if (sscanf(line, "%*s %x %*x %*x %*d %*d %*d %x", &dest, &mask) != 2) { 171 174 continue; 172 175 } 173 176 dest = ntohl(dest); 174 177 mask = ntohl(mask); 175 178 176 u nsigned longbroadcast = dest | ~mask;179 uint32_t broadcast = dest | ~mask; 177 180 178 181 if ((broadcast == 0x00000000) || (broadcast == 0xFFFFFFFF)) { 179 182 continue; 180 183 } 181 184 182 hdhomerun_discover_send_packet(ds, broadcast, device_type, device_id); 185 if (hdhomerun_discover_send_packet(ds, broadcast, device_type, device_id) < 0) { 186 continue; 187 } 188 183 189 send_count++; 184 190 } 185 191 … … 191 197 } 192 198 #endif 193 199 194 #if !defined(__CYGWIN__) && !defined(__ linux__)195 static int hdhomerun_discover_send_internal(struct hdhomerun_discover_sock_t *ds, u nsigned long device_type, unsigned longdevice_id)200 #if !defined(__CYGWIN__) && !defined(__WINDOWS__) && !defined(__linux__) 201 static int hdhomerun_discover_send_internal(struct hdhomerun_discover_sock_t *ds, uint32_t device_type, uint32_t device_id) 196 202 { 197 203 return -1; 198 204 } 199 205 #endif 200 206 201 int hdhomerun_discover_send(struct hdhomerun_discover_sock_t *ds, unsigned long device_type, unsigned longdevice_id)207 static int hdhomerun_discover_send(struct hdhomerun_discover_sock_t *ds, uint32_t device_type, uint32_t device_id) 202 208 { 203 209 if (hdhomerun_discover_send_internal(ds, device_type, device_id) < 0) { 204 210 return hdhomerun_discover_send_packet(ds, 0xFFFFFFFF, device_type, device_id); … … 206 212 return 0; 207 213 } 208 214 209 int hdhomerun_discover_recv(struct hdhomerun_discover_sock_t *ds, struct hdhomerun_discover_device_t *result, unsigned long timeout)215 static int hdhomerun_discover_recv(struct hdhomerun_discover_sock_t *ds, struct hdhomerun_discover_device_t *result) 210 216 { 211 217 struct timeval t; 212 t.tv_sec = timeout / 1000;213 t.tv_usec = (timeout % 1000) * 1000;218 t.tv_sec = 0; 219 t.tv_usec = 250000; 214 220 215 221 fd_set readfds; 216 222 FD_ZERO(&readfds); … … 223 229 return 0; 224 230 } 225 231 226 u nsigned charbuffer[1024];232 uint8_t buffer[1024]; 227 233 struct sockaddr_in sock_addr; 228 234 socklen_t sockaddr_size = sizeof(sock_addr); 229 235 int rx_length = recvfrom(ds->sock, (char *)buffer, sizeof(buffer), 0, (struct sockaddr *)&sock_addr, &sockaddr_size); 230 236 if (rx_length <= 0) { 231 return -1; 237 /* Don't return error - windows machine on VPN can sometimes cause a sock error here but otherwise works. */ 238 return 0; 232 239 } 233 240 if (rx_length < HDHOMERUN_MIN_PEEK_LENGTH) { 234 241 return 0; 235 242 } 236 int length = hdhomerun_peek_packet_length(buffer); 237 if (rx_length < length) { 243 244 size_t length = hdhomerun_peek_packet_length(buffer); 245 if (length > (size_t)rx_length) { 238 246 return 0; 239 247 } 240 248 241 u nsigned char*ptr = buffer;242 u nsigned char*end = buffer + length;249 uint8_t *ptr = buffer; 250 uint8_t *end = buffer + length; 243 251 int type = hdhomerun_process_packet(&ptr, &end); 244 252 if (type != HDHOMERUN_TYPE_DISCOVER_RPY) { 245 253 return 0; … … 249 257 result->device_type = 0; 250 258 result->device_id = 0; 251 259 while (1) { 252 u nsigned chartag;253 int len;254 u nsigned char*value;260 uint8_t tag; 261 size_t len; 262 uint8_t *value; 255 263 if (hdhomerun_read_tlv(&ptr, end, &tag, &len, &value) < 0) { 256 264 break; 257 265 } … … 277 285 return 1; 278 286 } 279 287 280 int hdhomerun_discover_validate_device_id(unsigned longdevice_id)288 static struct hdhomerun_discover_device_t *hdhomerun_discover_find_in_list(struct hdhomerun_discover_device_t result_list[], int count, uint32_t device_id) 281 289 { 282 static unsigned long lookup_table[16] = {0xA, 0x5, 0xF, 0x6, 0x7, 0xC, 0x1, 0xB, 0x9, 0x2, 0x8, 0xD, 0x4, 0x3, 0xE, 0x0}; 290 int index; 291 for (index = 0; index < count; index++) { 292 struct hdhomerun_discover_device_t *result = &result_list[index]; 293 if (result->device_id == device_id) { 294 return result; 295 } 296 } 283 297 284 unsigned long checksum = 0; 298 return NULL; 299 } 285 300 301 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) 302 { 303 int count = 0; 304 305 int attempt; 306 for (attempt = 0; attempt < 4; attempt++) { 307 if (hdhomerun_discover_send(ds, device_type, device_id) < 0) { 308 return -1; 309 } 310 311 uint64_t timeout = getcurrenttime() + 250; 312 while (getcurrenttime() < timeout) { 313 struct hdhomerun_discover_device_t *result = &result_list[count]; 314 315 int ret = hdhomerun_discover_recv(ds, result); 316 if (ret < 0) { 317 return -1; 318 } 319 if (ret == 0) { 320 break; 321 } 322 323 /* Filter. */ 324 if (device_type != HDHOMERUN_DEVICE_TYPE_WILDCARD) { 325 if (device_type != result->device_type) { 326 continue; 327 } 328 } 329 if (device_id != HDHOMERUN_DEVICE_ID_WILDCARD) { 330 if (device_id != result->device_id) { 331 continue; 332 } 333 } 334 335 /* Ensure not already in list. */ 336 if (hdhomerun_discover_find_in_list(result_list, count, result->device_id)) { 337 continue; 338 } 339 340 /* Add to list. */ 341 count++; 342 if (count >= max_count) { 343 return count; 344 } 345 } 346 } 347 348 return count; 349 } 350 351 int hdhomerun_discover_find_device(uint32_t device_id, struct hdhomerun_discover_device_t *result) 352 { 353 struct hdhomerun_discover_sock_t *ds = hdhomerun_discover_create(); 354 if (!ds) { 355 return -1; 356 } 357 358 int ret = hdhomerun_discover_find_devices_internal(ds, HDHOMERUN_DEVICE_TYPE_WILDCARD, device_id, result, 1); 359 360 hdhomerun_discover_destroy(ds); 361 return ret; 362 } 363 364 int hdhomerun_discover_find_devices(uint32_t device_type, struct hdhomerun_discover_device_t result_list[], int max_count) 365 { 366 struct hdhomerun_discover_sock_t *ds = hdhomerun_discover_create(); 367 if (!ds) { 368 return -1; 369 } 370 371 int ret = hdhomerun_discover_find_devices_internal(ds, device_type, HDHOMERUN_DEVICE_ID_WILDCARD, result_list, max_count); 372 373 hdhomerun_discover_destroy(ds); 374 return ret; 375 } 376 377 bool_t hdhomerun_discover_validate_device_id(uint32_t device_id) 378 { 379 static uint32_t lookup_table[16] = {0xA, 0x5, 0xF, 0x6, 0x7, 0xC, 0x1, 0xB, 0x9, 0x2, 0x8, 0xD, 0x4, 0x3, 0xE, 0x0}; 380 381 uint32_t checksum = 0; 382 286 383 checksum ^= lookup_table[(device_id >> 28) & 0x0F]; 287 384 checksum ^= (device_id >> 24) & 0x0F; 288 385 checksum ^= lookup_table[(device_id >> 20) & 0x0F]; … … 294 391 295 392 return (checksum == 0); 296 393 } 394 -
libs/libmythtv/hdhomerun/hdhomerun_control.c
20 20 21 21 #include "hdhomerun_os.h" 22 22 #include "hdhomerun_pkt.h" 23 #include "hdhomerun_discover.h" 23 24 #include "hdhomerun_control.h" 24 25 25 26 struct hdhomerun_control_sock_t { 27 uint32_t device_id; 28 uint32_t device_ip; 26 29 int sock; 27 unsigned char rx_buffer[1024]; 28 unsigned char *rx_pos; 29 unsigned char *rx_end; 30 uint8_t buffer[16384]; 30 31 }; 31 32 32 struct hdhomerun_control_sock_t *hdhomerun_control_create(u nsigned long ip_addr, unsigned long timeout)33 struct hdhomerun_control_sock_t *hdhomerun_control_create(uint32_t device_id, uint32_t device_ip) 33 34 { 34 35 struct hdhomerun_control_sock_t *cs = (struct hdhomerun_control_sock_t *)malloc(sizeof(struct hdhomerun_control_sock_t)); 35 36 if (!cs) { 36 37 return NULL; 37 38 } 38 39 40 cs->device_id = device_id; 41 cs->device_ip = device_ip; 42 cs->sock = -1; 43 44 return cs; 45 } 46 47 void hdhomerun_control_destroy(struct hdhomerun_control_sock_t *cs) 48 { 49 if (cs->sock != -1) { 50 close(cs->sock); 51 } 52 free(cs); 53 } 54 55 static void hdhomerun_control_close_sock(struct hdhomerun_control_sock_t *cs) 56 { 57 close(cs->sock); 58 cs->sock = -1; 59 } 60 61 static bool_t hdhomerun_control_connect_sock(struct hdhomerun_control_sock_t *cs) 62 { 63 if (cs->sock != -1) { 64 return TRUE; 65 } 66 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; 75 } 76 39 77 /* Create socket. */ 40 cs->sock = socket(AF_INET, SOCK_STREAM, 0);78 cs->sock = (int)socket(AF_INET, SOCK_STREAM, 0); 41 79 if (cs->sock == -1) { 42 free(cs); 43 return NULL; 80 return FALSE; 44 81 } 45 82 46 /* Set timeout. */ 47 struct timeval t; 48 t.tv_sec = timeout / 1000; 49 t.tv_usec = (timeout % 1000) * 1000; 50 setsockopt(cs->sock, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(t)); 83 /* Set timeouts. */ 84 setsocktimeout(cs->sock, SOL_SOCKET, SO_SNDTIMEO, 1000); 85 setsocktimeout(cs->sock, SOL_SOCKET, SO_RCVTIMEO, 1000); 51 86 52 87 /* Initiate connection. */ 53 88 struct sockaddr_in sock_addr; 54 89 memset(&sock_addr, 0, sizeof(sock_addr)); 55 90 sock_addr.sin_family = AF_INET; 56 sock_addr.sin_addr.s_addr = htonl( ip_addr);91 sock_addr.sin_addr.s_addr = htonl(device_ip); 57 92 sock_addr.sin_port = htons(HDHOMERUN_CONTROL_TCP_PORT); 58 93 if (connect(cs->sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) { 59 hdhomerun_control_ destroy(cs);60 return NULL;94 hdhomerun_control_close_sock(cs); 95 return FALSE; 61 96 } 62 97 63 98 /* Success. */ 64 cs->rx_pos = cs->rx_buffer; 65 cs->rx_end = cs->rx_buffer + sizeof(cs->rx_buffer); 66 return cs; 99 return TRUE; 67 100 } 68 101 69 void hdhomerun_control_destroy(struct hdhomerun_control_sock_t *cs)102 uint32_t hdhomerun_control_get_local_addr(struct hdhomerun_control_sock_t *cs) 70 103 { 71 close(cs->sock);72 free(cs);73 }104 if (!hdhomerun_control_connect_sock(cs)) { 105 return 0; 106 } 74 107 75 unsigned long hdhomerun_control_get_local_addr(struct hdhomerun_control_sock_t *cs)76 {77 108 struct sockaddr_in sock_addr; 78 109 socklen_t sockaddr_size = sizeof(sock_addr); 79 110 if (getsockname(cs->sock, (struct sockaddr*)&sock_addr, &sockaddr_size) != 0) { 80 111 return 0; 81 112 } 113 82 114 return ntohl(sock_addr.sin_addr.s_addr); 83 115 } 84 116 85 int hdhomerun_control_send(struct hdhomerun_control_sock_t *cs, unsigned char *start, unsigned char*end)117 static int hdhomerun_control_send(struct hdhomerun_control_sock_t *cs, uint8_t *start, uint8_t *end) 86 118 { 87 int length = end - start;88 if (send(cs->sock, (char *)start, length, 0) != length) {119 int length = (int)(end - start); 120 if (send(cs->sock, (char *)start, (int)length, 0) != length) { 89 121 return -1; 90 122 } 91 return 0;92 }93 123 94 int hdhomerun_control_send_get_request(struct hdhomerun_control_sock_t *cs, const char *name) 95 { 96 unsigned char buffer[1024]; 97 unsigned char *ptr = buffer; 98 hdhomerun_write_get_request(&ptr, name); 99 return hdhomerun_control_send(cs, buffer, ptr); 124 return length; 100 125 } 101 126 102 int hdhomerun_control_send_set_request(struct hdhomerun_control_sock_t *cs, const char *name, const char *value)127 static int hdhomerun_control_recv_sock(struct hdhomerun_control_sock_t *cs, uint8_t *buffer, uint8_t *limit) 103 128 { 104 unsigned char buffer[1024]; 105 unsigned char *ptr = buffer; 106 hdhomerun_write_set_request(&ptr, name, value); 107 return hdhomerun_control_send(cs, buffer, ptr); 108 } 129 struct timeval t; 130 t.tv_sec = 0; 131 t.tv_usec = 250000; 109 132 110 int hdhomerun_control_send_upgrade_request(struct hdhomerun_control_sock_t *cs, unsigned long sequence, void *data, int length) 111 { 112 unsigned char buffer[1024 + 64]; 113 unsigned char *ptr = buffer; 133 fd_set readfds; 134 FD_ZERO(&readfds); 135 FD_SET(cs->sock, &readfds); 114 136 115 if ( length + 64 > (int)sizeof(buffer)) {137 if (select(cs->sock+1, &readfds, NULL, NULL, &t) < 0) { 116 138 return -1; 117 139 } 118 140 119 hdhomerun_write_upgrade_request(&ptr, sequence, data, length); 120 return hdhomerun_control_send(cs, buffer, ptr); 141 if (!FD_ISSET(cs->sock, &readfds)) { 142 return 0; 143 } 144 145 int length = recv(cs->sock, (char *)buffer, (int)(limit - buffer), 0); 146 if (length <= 0) { 147 return -1; 148 } 149 150 return length; 121 151 } 122 152 123 static int hdhomerun_control_recv _sock(struct hdhomerun_control_sock_t *cs, unsigned long timeout)153 static int hdhomerun_control_recv(struct hdhomerun_control_sock_t *cs, uint8_t *buffer, uint8_t *limit) 124 154 { 125 struct timeval t; 126 t.tv_sec = timeout / 1000; 127 t.tv_usec = (timeout % 1000) * 1000; 155 uint64_t timeout = getcurrenttime() + 1000; 156 uint8_t *ptr = buffer; 128 157 129 fd_set readfds; 130 FD_ZERO(&readfds); 131 FD_SET(cs->sock, &readfds); 158 while (getcurrenttime() < timeout) { 159 int length = hdhomerun_control_recv_sock(cs, ptr, limit); 160 if (length < 0) { 161 return -1; 162 } 163 if (length == 0) { 164 continue; 165 } 166 ptr += length; 132 167 133 if (select(cs->sock+1, &readfds, NULL, NULL, &t) < 0) { 168 if (buffer + HDHOMERUN_MIN_PEEK_LENGTH > limit) { 169 continue; 170 } 171 172 length = (int)hdhomerun_peek_packet_length(buffer); 173 if (buffer + length > limit) { 174 continue; 175 } 176 177 return length; 178 } 179 180 return -1; 181 } 182 183 static int hdhomerun_control_get_set(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, char **pvalue, char **perror) 184 { 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) { 134 189 return -1; 135 190 } 136 if (!FD_ISSET(cs->sock, &readfds)) { 137 return 0; 191 192 /* Receive response. */ 193 int length = hdhomerun_control_recv(cs, cs->buffer, cs->buffer + sizeof(cs->buffer)); 194 if (length <= 0) { 195 return -1; 138 196 } 139 197 140 int rx_length = recv(cs->sock, (char *)cs->rx_pos, cs->rx_end - cs->rx_pos, 0); 141 if (rx_length <= 0) { 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) { 142 203 return -1; 143 204 } 144 cs->rx_pos += rx_length; 145 return 1; 205 if (type != HDHOMERUN_TYPE_GETSET_RPY) { 206 return -1; 207 } 208 209 while (ptr < end) { 210 uint8_t tag; 211 size_t len; 212 uint8_t *val; 213 if (hdhomerun_read_tlv(&ptr, end, &tag, &len, &val) < 0) { 214 break; 215 } 216 switch (tag) { 217 case HDHOMERUN_TAG_GETSET_VALUE: 218 if (pvalue) { 219 *pvalue = (char *)val; 220 val[len] = 0; 221 } 222 if (perror) { 223 *perror = NULL; 224 } 225 return 1; 226 227 case HDHOMERUN_TAG_ERROR_MESSAGE: 228 if (pvalue) { 229 *pvalue = NULL; 230 } 231 if (perror) { 232 *perror = (char *)val; 233 val[len] = 0; 234 } 235 return 0; 236 } 237 } 238 239 return -1; 146 240 } 147 241 148 static int hdhomerun_control_recv_process(struct hdhomerun_control_sock_t *cs, struct hdhomerun_control_data_t *result)242 int hdhomerun_control_get(struct hdhomerun_control_sock_t *cs, const char *name, char **pvalue, char **perror) 149 243 { 150 int rx_length = cs->rx_pos - cs->rx_buffer; 151 if (rx_length < HDHOMERUN_MIN_PEEK_LENGTH) { 152 return 0; 244 if (!hdhomerun_control_connect_sock(cs)) { 245 return -1; 153 246 } 154 int length = hdhomerun_peek_packet_length(cs->rx_buffer); 155 if (rx_length < length) { 156 return 0; 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; 157 252 } 158 253 159 memcpy(result->buffer, cs->rx_buffer, length); 160 if (rx_length > length) { 161 memcpy(cs->rx_buffer, cs->rx_buffer + length, rx_length - length); 254 return ret; 255 } 256 257 int hdhomerun_control_set(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, char **pvalue, char **perror) 258 { 259 if (!hdhomerun_control_connect_sock(cs)) { 260 return -1; 162 261 } 163 cs->rx_pos = cs->rx_buffer + (rx_length - length);164 262 165 result->ptr = result->buffer; 166 result->end = result->buffer + length; 167 result->type = hdhomerun_process_packet(&result->ptr, &result->end); 168 if (result->type < 0) { 263 int ret = hdhomerun_control_get_set(cs, name, value, pvalue, perror); 264 if (ret < 0) { 265 hdhomerun_control_close_sock(cs); 169 266 return -1; 170 267 } 171 268 172 return 1;269 return ret; 173 270 } 174 271 175 int hdhomerun_control_ recv(struct hdhomerun_control_sock_t *cs, struct hdhomerun_control_data_t *result, unsigned long timeout)272 int hdhomerun_control_upgrade(struct hdhomerun_control_sock_t *cs, FILE *upgrade_file) 176 273 { 177 int ret = hdhomerun_control_recv_process(cs, result); 178 if (ret != 0) { 179 return ret; 274 if (!hdhomerun_control_connect_sock(cs)) { 275 return -1; 180 276 } 181 277 182 struct timeval t; 183 gettimeofday(&t, NULL); 184 unsigned long long stop_time = ((unsigned long long)t.tv_sec * 1000) + (t.tv_usec / 1000) + timeout; 278 uint32_t sequence = 0; 279 uint8_t *ptr; 185 280 186 281 while (1) { 187 ret = hdhomerun_control_recv_sock(cs, timeout); 188 if (ret < 0) { 189 return ret; 282 uint8_t data[256]; 283 size_t length = fread(data, 1, 256, upgrade_file); 284 if (length == 0) { 285 break; 190 286 } 191 if (ret == 1) { 192 ret = hdhomerun_control_recv_process(cs, result); 193 if (ret != 0) { 194 return ret; 195 } 287 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); 292 return -1; 196 293 } 197 294 198 gettimeofday(&t, NULL); 199 unsigned long long current_time = ((unsigned long long)t.tv_sec * 1000) + (t.tv_usec / 1000); 200 if (current_time >= stop_time) { 201 return 0; 202 } 295 sequence += (uint32_t)length; 203 296 } 297 298 if (sequence == 0) { 299 /* No data in file. Error, but no need to close connection. */ 300 return 0; 301 } 302 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); 307 return -1; 308 } 309 310 return 1; 204 311 } -
libs/libmythtv/hdhomerun/Makefile
2 2 SRCS += hdhomerun_pkt.c 3 3 SRCS += hdhomerun_discover.c 4 4 SRCS += hdhomerun_control.c 5 SRCS += hdhomerun_video.c 6 SRCS += hdhomerun_device.c 5 7 SRCS += hdhomerun_config.c 6 8 7 CFLAGS += -Wall -O2 9 CFLAGS += -Wall -O2 -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wpointer-arith 8 10 9 11 hdhomerun_config : $(SRCS) 10 gcc $(CFLAGS) $(SRCS) - o $@12 gcc $(CFLAGS) $(SRCS) -lpthread -o $@ 11 13 strip $@ 12 14 13 15 hdhomerun_config.exe : $(SRCS) 14 gcc $(CFLAGS) $(SRCS) -l iphlpapi -o $@16 gcc $(CFLAGS) $(SRCS) -lpthread -liphlpapi -o $@ 15 17 strip $@ 16 18 17 19 clean : -
libs/libmythtv/hdhomerun/hdhomerun_discover.h
21 21 extern "C" { 22 22 #endif 23 23 24 struct hdhomerun_discover_sock_t;25 26 24 struct hdhomerun_discover_device_t { 27 u nsigned longip_addr;28 u nsigned longdevice_type;29 u nsigned longdevice_id;25 uint32_t ip_addr; 26 uint32_t device_type; 27 uint32_t device_id; 30 28 }; 31 29 32 extern struct hdhomerun_discover_sock_t *hdhomerun_discover_create(unsigned long timeout); 33 extern void hdhomerun_discover_destroy(struct hdhomerun_discover_sock_t *ds); 34 extern int hdhomerun_discover_send(struct hdhomerun_discover_sock_t *ds, unsigned long device_type, unsigned long device_id); 35 extern int hdhomerun_discover_recv(struct hdhomerun_discover_sock_t *ds, struct hdhomerun_discover_device_t *result, unsigned long timeout); 30 /* 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); 36 42 37 extern int hdhomerun_discover_validate_device_id(unsigned long device_id); 43 /* 44 * Find all devices of a given type. 45 * 46 * The device information is stored in caller-supplied array of hdhomerun_discover_device_t vars. 47 * Multiple attempts are made to find devices. 48 * Execution time is 1 second. 49 * 50 * Returns the number of devices found. 51 * Retruns -1 on error. 52 */ 53 extern int hdhomerun_discover_find_devices(uint32_t device_type, struct hdhomerun_discover_device_t result_list[], int max_count); 38 54 55 /* 56 * Verify that the device ID given is valid. 57 * 58 * The device ID contains a self-check sequence that detects common user input errors including 59 * single-digit errors and two digit transposition errors. 60 * 61 * Returns TRUE if valid. 62 * Returns FALSE if not valid. 63 */ 64 extern bool_t hdhomerun_discover_validate_device_id(uint32_t device_id); 65 39 66 #ifdef __cplusplus 40 67 } 41 68 #endif -
libs/libmythtv/hdhrsignalmonitor.cpp
138 138 dtvMonitorRunning = true; 139 139 140 140 struct hdhomerun_video_sock_t *_video_socket; 141 _video_socket = hdhomerun_video_create( VIDEO_DATA_BUFFER_SIZE_1S, 50);141 _video_socket = hdhomerun_video_create(0, VIDEO_DATA_BUFFER_SIZE_1S); 142 142 if (!_video_socket) 143 143 { 144 144 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to get video socket"); … … 164 164 165 165 unsigned long data_length; 166 166 unsigned char *data_buffer = 167 hdhomerun_video_recv _inplace(_video_socket,167 hdhomerun_video_recv(_video_socket, 168 168 VIDEO_DATA_BUFFER_SIZE_1S / 5, 169 169 &data_length); 170 170 … … 174 174 continue; 175 175 } 176 176 177 if (!hdhomerun_video_get_state(_video_socket))178 {179 VERBOSE(VB_IMPORTANT, LOC_ERR + "Recv error" + ENO);180 break;181 }182 177 usleep(2500); 183 178 } 184 179 -
libs/libmythtv/hdhrrecorder.cpp
100 100 } 101 101 102 102 /* Create TS socket. */ 103 _video_socket = hdhomerun_video_create( VIDEO_DATA_BUFFER_SIZE_1S, 50);103 _video_socket = hdhomerun_video_create(0, VIDEO_DATA_BUFFER_SIZE_1S); 104 104 if (!_video_socket) 105 105 { 106 106 VERBOSE(VB_IMPORTANT, LOC + "Open() failed to open socket"); … … 357 357 358 358 unsigned long data_length; 359 359 unsigned char *data_buffer = 360 hdhomerun_video_recv _inplace(_video_socket,361 VIDEO_DATA_BUFFER_SIZE_1S / 5,362 &data_length);360 hdhomerun_video_recv(_video_socket, 361 VIDEO_DATA_BUFFER_SIZE_1S / 5, 362 &data_length); 363 363 if (!data_buffer) 364 364 { 365 if (hdhomerun_video_get_state(_video_socket) == 0)366 {367 VERBOSE(VB_IMPORTANT, LOC_ERR + "Recv error" + ENO);368 break;369 }370 365 usleep(5000); 371 366 continue; 372 367 } -
libs/libmythtv/hdhrchannel.cpp
90 90 91 91 _device_ip = 0; 92 92 93 /* Create socket. */ 94 struct hdhomerun_discover_sock_t *discoverSock = NULL; 95 discoverSock = hdhomerun_discover_create(500); 96 97 if (!discoverSock) 93 /* Discover. */ 94 struct hdhomerun_discover_device_t result; 95 int ret = hdhomerun_discover_find_device(_device_id, &result); 96 if (ret < 0) 98 97 { 99 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to create discovery socket");98 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to send discovery request" + ENO); 100 99 return false; 101 100 } 102 103 /* Discover. */ 104 for (int retry = 0; retry < 6; retry++) 101 if (ret == 0) 105 102 { 106 /* Send discovery request. */ 107 int ret = hdhomerun_discover_send(discoverSock, 108 HDHOMERUN_DEVICE_TYPE_TUNER, 109 _device_id); 110 if (ret < 0) 111 { 112 VERBOSE(VB_IMPORTANT, LOC_ERR + 113 "Unable to send discovery request" + ENO); 114 break; 115 } 116 117 /* Wait for response. */ 118 struct hdhomerun_discover_device_t device; 119 ret = hdhomerun_discover_recv(discoverSock, &device, 500); 120 if (ret < 0) 121 { 122 VERBOSE(VB_IMPORTANT, LOC_ERR + 123 "Unable to listen for discovery response" + ENO); 124 break; 125 } 126 if (ret == 0) 127 { 128 continue; 129 } 130 131 /* Found. */ 132 _device_ip = device.ip_addr; 133 134 VERBOSE(VB_IMPORTANT, LOC + 135 QString("device found at address %1.%2.%3.%4") 136 .arg((_device_ip>>24) & 0xFF).arg((_device_ip>>16) & 0xFF) 137 .arg((_device_ip>> 8) & 0xFF).arg((_device_ip>> 0) & 0xFF)); 138 139 hdhomerun_discover_destroy(discoverSock); 140 return true; 103 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("device not found")); 104 return false; 141 105 } 142 106 143 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("device not found"));144 hdhomerun_discover_destroy(discoverSock);107 /* Found. */ 108 _device_ip = result.ip_addr; 145 109 146 return false; 110 VERBOSE(VB_IMPORTANT, LOC + 111 QString("device found at address %1.%2.%3.%4") 112 .arg((_device_ip>>24) & 0xFF).arg((_device_ip>>16) & 0xFF) 113 .arg((_device_ip>> 8) & 0xFF).arg((_device_ip>> 0) & 0xFF)); 114 115 return true; 147 116 } 148 117 149 118 bool HDHRChannel::Connect(void) 150 119 { 151 _control_socket = hdhomerun_control_create(_device_i p, 2000);120 _control_socket = hdhomerun_control_create(_device_id, _device_ip); 152 121 if (!_control_socket) 153 122 { 123 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to create control socket"); 124 return false; 125 } 126 127 if (hdhomerun_control_get_local_addr(_control_socket) == 0) 128 { 154 129 VERBOSE(VB_IMPORTANT, LOC_ERR + "Unable to connect to device"); 155 130 return false; 156 131 } … … 162 137 QString HDHRChannel::DeviceGet(const QString &name) 163 138 { 164 139 QMutexLocker locker(&_lock); 165 //VERBOSE(VB_CHANNEL, LOC + QString("DeviceGet(%1)").arg(name));166 140 167 141 if (!_control_socket) 168 142 { … … 170 144 return QString::null; 171 145 } 172 146 173 /* Send request. */ 174 if (hdhomerun_control_send_get_request(_control_socket, name) < 0) 147 char *value = NULL; 148 char *error = NULL; 149 if (hdhomerun_control_get(_control_socket, name, &value, &error) < 0) 175 150 { 176 VERBOSE(VB_IMPORTANT, LOC_ERR + "Get request failed (send)" + ENO);151 VERBOSE(VB_IMPORTANT, LOC_ERR + "Get request failed" + ENO); 177 152 return QString::null; 178 153 } 179 154 180 /* Wait for response. */ 181 struct hdhomerun_control_data_t response; 182 if (hdhomerun_control_recv(_control_socket, &response, 2000) <= 0) 183 { 184 VERBOSE(VB_IMPORTANT, LOC_ERR + "Get request failed (timeout)"); 155 if (error) { 156 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("DeviceGet(%1): %2").arg(name).arg(error)); 185 157 return QString::null; 186 158 } 187 if (response.type != HDHOMERUN_TYPE_GETSET_RPY)188 {189 VERBOSE(VB_IMPORTANT, LOC_ERR +190 "Get request failed (unexpected response)");191 return QString::null;192 }193 159 194 QString ret = QString::null; 195 unsigned char *ptr = response.ptr, *data = NULL; 196 unsigned char tag; 197 int dlen; 198 while (hdhomerun_read_tlv(&ptr, response.end, &tag, &dlen, &data) >= 0) 199 { 200 char buf[1024+64]; 201 if (HDHOMERUN_TAG_GETSET_VALUE == tag) 202 { 203 memcpy(buf, (char*)data, dlen); 204 buf[dlen - 1] = 0x0; 205 ret = QString(buf); 206 } 207 else if (HDHOMERUN_TAG_ERROR_MESSAGE == tag) 208 { 209 memcpy(buf, (char*)data, dlen); 210 buf[dlen - 1] = 0x0; 211 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("DeviceGet(%1): %2") 212 .arg(name).arg(buf)); 213 } 214 } 215 216 //VERBOSE(VB_CHANNEL, LOC + QString("DeviceGet(%1) -> '%2' len(%3)") 217 // .arg(name).arg(ret).arg(len)); 218 219 return ret; 160 return QString(value); 220 161 } 221 162 222 163 QString HDHRChannel::DeviceSet(const QString &name, const QString &val) … … 229 170 return QString::null; 230 171 } 231 172 232 /* Send request. */ 233 if (hdhomerun_control_send_set_request(_control_socket, name, val) < 0) 173 char *value = NULL; 174 char *error = NULL; 175 if (hdhomerun_control_set(_control_socket, name, val, &value, &error) < 0) 234 176 { 235 VERBOSE(VB_IMPORTANT, LOC_ERR + "Set request failed (send)" + ENO);177 VERBOSE(VB_IMPORTANT, LOC_ERR + "Set request failed" + ENO); 236 178 return QString::null; 237 179 } 238 180 239 /* Wait for response. */ 240 struct hdhomerun_control_data_t response; 241 bzero(&response, sizeof(response)); 242 if (hdhomerun_control_recv(_control_socket, &response, 2000) <= 0) 243 { 244 VERBOSE(VB_IMPORTANT, LOC_ERR + "Set request failed (timeout)"); 181 if (error) { 182 VERBOSE(VB_IMPORTANT, LOC_ERR + QString("DeviceSet(%1 %2): %3").arg(name).arg(val).arg(error)); 245 183 return QString::null; 246 184 } 247 if (response.type != HDHOMERUN_TYPE_GETSET_RPY)248 {249 VERBOSE(VB_IMPORTANT, LOC_ERR +250 "Set request failed (unexpected response)");251 return QString::null;252 }253 185 254 QStringList list; 255 QString tmp = ""; 256 unsigned char *ptr = response.ptr; 257 for (;ptr < response.end; ptr++) 258 { 259 if (*ptr) 260 { 261 tmp += QChar(*((char*)ptr)); 262 continue; 263 } 264 list.push_back(tmp); 265 tmp = ""; 266 ptr++; 267 ptr++; 268 } 269 270 if (list.size() >= 2) 271 return list[1]; 272 return ""; 186 return QString(value); 273 187 } 274 188 275 189 QString HDHRChannel::TunerGet(const QString &name) -
libs/libmythtv/hdhrchannel.h
14 14 #include "dtvchannel.h" 15 15 16 16 // HDHomeRun headers 17 #include "hdhomerun/hdhomerun_pkt.h" 18 #include "hdhomerun/hdhomerun_discover.h" 19 #include "hdhomerun/hdhomerun_control.h" 20 #include "hdhomerun/hdhomerun_video.h" 17 #include "hdhomerun/hdhomerun.h" 21 18 22 19 typedef struct hdhomerun_control_sock_t hdhr_socket_t; 23 20
