8 #include <winsock2.h>
\r
11 #include "Raym/Log.h"
\r
12 #include "ry0/device/PT1/PT1Tuner.h"
\r
13 #include "ry0/device/PT1/PT1Core.h"
\r
22 static HMODULE module_ = NULL; // for scan
\r
24 PT1Tuner::PT1Tuner(PT1Core *core, uint32_t tuner, HMODULE multi2_dll)
\r
26 DebugLog2("PT1Tuner::PT1Tuner()\n");
\r
28 InitializeCriticalSection(&_cs);
\r
30 EnterCriticalSection(&_cs);
\r
35 memset(_name, sizeof(_name), 0x00);
\r
44 while (multi2_dll != NULL)
\r
46 // create "B25" & initialize
\r
47 ARIB_STD_B25 *(*func_b25)();
\r
48 func_b25 = reinterpret_cast<ARIB_STD_B25 *(*)()>(::GetProcAddress(multi2_dll, "create_arib_std_b25"));
\r
49 if (func_b25 == NULL)
\r
51 DebugLog0("b25 func address get ng.");
\r
57 DebugLog0("b25 create ng.");
\r
61 int ret = _b25->set_multi2_round(_b25, 4);
\r
64 _b25->release(_b25);
\r
66 DebugLog0("b25 set multi2 round ng. %d", ret);
\r
70 ret = _b25->set_strip(_b25, 0);
\r
73 _b25->release(_b25);
\r
75 DebugLog0("b25 set strip ng. %d", ret);
\r
79 ret = _b25->set_emm_proc(_b25, 0);
\r
82 _b25->release(_b25);
\r
84 DebugLog0("b25 set emm proc ng. %d", ret);
\r
88 // create "B-CAS" & initialize
\r
89 B_CAS_CARD *(*func_bcas)();
\r
90 func_bcas = reinterpret_cast<B_CAS_CARD *(*)()>(::GetProcAddress(multi2_dll, "create_b_cas_card"));
\r
91 if (func_bcas == NULL)
\r
94 DebugLog0("bcas func address get ng.");
\r
97 _bcas = func_bcas();
\r
100 _b25->release(_b25);
\r
102 DebugLog0("bcas create ng.");
\r
106 ret = _bcas->init(_bcas);
\r
109 _b25->release(_b25);
\r
111 _bcas->release(_bcas);
\r
113 DebugLog0("bcas init ng. %d", ret);
\r
116 ret = _b25->set_b_cas_card(_b25, _bcas);
\r
119 _b25->release(_b25);
\r
121 _bcas->release(_bcas);
\r
123 DebugLog0("b25 set bcas card ng. %d", ret);
\r
127 DebugLog2("b25 & bcas initialize success.");
\r
131 // WSADATA wsaData;
\r
132 // WSAStartup(MAKEWORD(2,0), &wsaData);
\r
135 if ((_udp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET)
\r
137 DebugLog0("fatal error occured: socket(): 0x%08x", WSAGetLastError());
\r
140 struct sockaddr_in own_addr;
\r
141 own_addr.sin_family = AF_INET;
\r
142 own_addr.sin_port = 0;
\r
143 own_addr.sin_addr.s_addr = INADDR_ANY;
\r
144 if (bind(_udp, (struct sockaddr *)&own_addr, sizeof(own_addr)) == SOCKET_ERROR)
\r
146 DebugLog0("fatal error occured: bind()\n");
\r
149 _dst_addr.sin_family = AF_UNSPEC;
\r
151 LeaveCriticalSection(&_cs);
\r
154 PT1Tuner::~PT1Tuner()
\r
156 EnterCriticalSection(&_cs);
\r
159 _bcas->release(_bcas);
\r
164 _b25->release(_b25);
\r
171 if (_dst_addr.sin_family == AF_INET)
\r
173 _dst_addr.sin_family = AF_UNSPEC;
\r
177 LeaveCriticalSection(&_cs);
\r
179 _core->release(this);
\r
183 DeleteCriticalSection(&_cs);
\r
185 DebugLog2("PT1Tuner::~PT1Tuner()\n");
\r
188 void PT1Tuner::setListener(Listener *listener)
\r
190 EnterCriticalSection(&_cs);
\r
191 _listener = listener;
\r
192 LeaveCriticalSection(&_cs);
\r
195 const char *PT1Tuner::name()
\r
197 DebugLog2("PT1Tuner::name()\n");
\r
199 if (strlen(_name) == 0)
\r
201 sprintf_s(_name, sizeof(_name), "%s-%02d", _core->name(), _tuner);
\r
207 Tuner::Type PT1Tuner::type()
\r
209 DebugLog2("PT1Tuner::type()\n");
\r
223 Tuner::LnbPower PT1Tuner::lnbPower()
\r
225 DebugLog2("PT1Tuner::lnbPower()\n");
\r
227 return LNB_POWER_OFF;
\r
230 bool PT1Tuner::getCnAgc(uint32_t *cn100, uint32_t *agc, uint32_t *maxAgc)
\r
232 DebugLog2("PT1Tuner::getCnAgc()\n");
\r
233 bool result = false;
\r
234 if ((cn100 != NULL) && (agc != NULL) && (maxAgc != NULL))
\r
236 result = _core->getCnAgc(_tuner, (EARTH::uint *)cn100, (EARTH::uint *)agc, (EARTH::uint *)maxAgc);
\r
241 int PT1Tuner::channel()
\r
244 EnterCriticalSection(&_cs);
\r
246 LeaveCriticalSection(&_cs);
\r
250 bool PT1Tuner::setChannel(int channel)
\r
252 bool result = false;
\r
253 EnterCriticalSection(&_cs);
\r
254 if (_channel != channel)
\r
258 result = _core->setChannel(_tuner, channel);
\r
261 _channel = channel;
\r
273 LeaveCriticalSection(&_cs);
\r
277 bool PT1Tuner::startRecording(int fd)
\r
279 bool result = false;
\r
280 EnterCriticalSection(&_cs);
\r
281 if ((!_recording) && (!_locked) && (fd >= 0))
\r
288 LeaveCriticalSection(&_cs);
\r
292 int PT1Tuner::stopRecording()
\r
295 EnterCriticalSection(&_cs);
\r
298 _recording = false;
\r
299 if (_dst_addr.sin_family != AF_INET)
\r
306 LeaveCriticalSection(&_cs);
\r
310 bool PT1Tuner::isRecording()
\r
312 bool result = false;
\r
313 EnterCriticalSection(&_cs);
\r
314 result = _recording;
\r
315 LeaveCriticalSection(&_cs);
\r
319 bool PT1Tuner::lock()
\r
321 bool result = false;
\r
322 EnterCriticalSection(&_cs);
\r
328 LeaveCriticalSection(&_cs);
\r
332 void PT1Tuner::unlock()
\r
334 EnterCriticalSection(&_cs);
\r
342 LeaveCriticalSection(&_cs);
\r
345 bool PT1Tuner::isLocked()
\r
347 bool result = false;
\r
348 EnterCriticalSection(&_cs);
\r
350 LeaveCriticalSection(&_cs);
\r
354 bool PT1Tuner::startStreaming(struct sockaddr_in *addr)
\r
356 bool result = false;
\r
357 EnterCriticalSection(&_cs);
\r
358 if (_dst_addr.sin_family == AF_UNSPEC)
\r
360 if (addr->sin_family == AF_INET)
\r
367 LeaveCriticalSection(&_cs);
\r
371 void PT1Tuner::stopStreaming()
\r
373 EnterCriticalSection(&_cs);
\r
374 if (_dst_addr.sin_family == AF_INET)
\r
376 _dst_addr.sin_family = AF_UNSPEC;
\r
382 LeaveCriticalSection(&_cs);
\r
385 bool PT1Tuner::isStreaming()
\r
387 bool result = false;
\r
388 EnterCriticalSection(&_cs);
\r
389 result = (_dst_addr.sin_family == AF_INET);
\r
390 LeaveCriticalSection(&_cs);
\r
395 void PT1Tuner::addPacket(uint32_t packet)
\r
397 // DebugLog3("%s\n", __FUNCTION__);
\r
400 uint32_t packetCounter = BIT_SHIFT_MASK(packet, 26, 3);
\r
401 uint32_t packetStart = BIT_SHIFT_MASK(packet, 25, 1);
\r
402 uint32_t packetData = BIT_SHIFT_MASK(packet, 0, 24);
\r
405 uint32_t count = BIT_SHIFT_MASK(_count, 0, 3);
\r
408 if (packetCounter != count)
\r
410 // DebugLog3("counter value is invalid.\n");
\r
413 // check packet start offset flag
\r
416 if (BIT_SHIFT_MASK(packetData, 15, 1))
\r
418 // DebugLog3("There is an error that could not be corrected by Reed-Solomon decoding\n");
\r
423 if (BIT_SHIFT_MASK(packetData, 16, 8) != 0x47)
\r
425 // DebugLog3("The first byte of the packet does not have an 0x47.\n");
\r
429 if (_packetOffset != 0)
\r
431 // DebugLog3("The previous packet was not completed.\n");
\r
438 for (i = 0; i < 3; ++i)
\r
440 if (_packetOffset < PT1Core::PACKET_SIZE)
\r
442 _buffer[PT1Core::PACKET_SIZE * _packetCount + _packetOffset] = BIT_SHIFT_MASK(packetData, 8*(2-i), 8);
\r
446 if (PT1Core::PACKET_SIZE <= _packetOffset)
\r
448 // One packet is complete
\r
451 if (PT1Core::PAGE_SIZE * PT1Core::PAGE_COUNT / PT1Core::PACKET_SIZE <= ++_packetCount)
\r
455 uint8_t *ptr = _buffer;
\r
456 int32_t size = (PT1Core::PAGE_SIZE * PT1Core::PAGE_COUNT);
\r
458 EnterCriticalSection(&_cs);
\r
463 ARIB_STD_B25_BUFFER sBuffer, dBuffer;
\r
464 sBuffer.data = _buffer;
\r
465 sBuffer.size = (PT1Core::PAGE_SIZE * PT1Core::PAGE_COUNT);
\r
466 dBuffer.data = NULL;
\r
469 int ret = _b25->put(_b25, &sBuffer);
\r
472 ret = _b25->get(_b25, &dBuffer);
\r
475 ptr = dBuffer.data;
\r
476 size = dBuffer.size;
\r
480 DebugLog3("_b25->get() NG. %d\n", ret);
\r
486 DebugLog3("_b25->put() NG. %d\n", ret);
\r
494 _write(_recfd, ptr, size);
\r
498 if (_dst_addr.sin_family == AF_INET)
\r
501 int32_t offset = 0;
\r
502 int32_t unit = 188 * 4;
\r
503 // int32_t unit = 188 * 8;
\r
504 int32_t remain = size;
\r
511 int len = sendto(_udp, (const char *)&ptr[offset], unit, 0, (struct sockaddr *)&_dst_addr, sizeof(struct sockaddr_in));
\r
520 strerror_s(tmp, sizeof(tmp), errno);
\r
521 DebugLog3("len = %d, %s", len, tmp);
\r
526 sendto(_udp, (const char *)ptr, size, 0, (struct sockaddr *)&_dst_addr, sizeof(struct sockaddr_in));
\r
531 if (_listener != NULL)
\r
533 _listener->put(ptr, size);
\r
536 LeaveCriticalSection(&_cs);
\r
542 int PT1Tuner::scan(Tuner *tuners[], HMODULE multi2_dll)
\r
544 DebugLog2("%s()\n", __FUNCTION__);
\r
546 if (module_ == NULL)
\r
548 module_ = ::LoadLibrary(L"SDK_EARTHSOFT_PT1_PT2.dll");
\r
549 if (module_ == NULL)
\r
551 DebugLog0("Can't load library: ");
\r
556 EARTH::PT::Bus::NewBusFunction function = reinterpret_cast<EARTH::PT::Bus::NewBusFunction>(::GetProcAddress(module_, "_"));
\r
557 if (function == NULL)
\r
559 DebugLog0("internal error.");
\r
563 EARTH::PT::Bus *bus = NULL;
\r
564 EARTH::status status = function(&bus);
\r
565 if (status != EARTH::PT::STATUS_OK)
\r
567 DebugLog3("error: NewBusFunction() 0x%08x", status);
\r
571 EARTH::uint version;
\r
572 bus->GetVersion(&version);
\r
573 if ((version >> 8) != 2)
\r
575 DebugLog3("no support version");
\r
579 EARTH::PT::Bus::DeviceInfo deviceInfo[ry0::device::MAX_DEVICES];
\r
580 EARTH::uint deviceInfoCount = sizeof(deviceInfo)/sizeof(*deviceInfo);
\r
581 bus->Scan(deviceInfo, &deviceInfoCount, 3);
\r
583 DebugLog2("deviceInfoCount = %d", deviceInfoCount);
\r
585 int tunerCount = 0;
\r
587 for (EARTH::uint i = 0; i < deviceInfoCount; ++i)
\r
589 const EARTH::PT::Bus::DeviceInfo *info = &deviceInfo[i];
\r
590 if (info->BadBitCount == 0)
\r
594 PT1Core *core = new PT1Core(bus, info, &tuners[tunerCount], multi2_dll);
\r
595 tunerCount += PT1Core::MAX_TUNERS;
\r
599 DebugLog0("throw %d", e);
\r
601 catch (const std::bad_alloc& e)
\r
603 DebugLog0("throw bad_alloc %s", e);
\r