Ticket #4752: r5000_r16_trunk19162.patch
| File r5000_r16_trunk19162.patch, 179.4 KB (added by anonymous, 3 years ago) |
|---|
-
configure
old new 179 179 echo " --disable-ivtv disable ivtv support (PVR-x50) req. v4l support" 180 180 echo " --disable-hdpvr disable HD-PVR support" 181 181 echo " --disable-dvb disable DVB support" 182 echo " --disable-r5000 disable support for R5000 USB STBs" 182 183 echo " --dvb-path=HDRLOC location of directory containing" 183 184 echo " 'linux/dvb/frontend.h', not the" 184 185 echo " directory with frontend.h [$dvb_path]" … … 1018 1019 hdpvr 1019 1020 iptv 1020 1021 ivtv 1022 r5000 1021 1023 joystick_menu 1022 1024 libfftw3 1023 1025 lirc … … 1203 1205 dbox2_deps="backend" 1204 1206 dvb_deps="backend" 1205 1207 firewire_deps="backend" 1208 r5000_deps="backend" 1206 1209 iptv_deps="backend" 1207 1210 ivtv_deps="backend v4l" 1208 1211 hdpvr_deps="backend v4l" … … 1320 1323 enable hdpvr 1321 1324 enable iptv 1322 1325 enable ivtv 1326 enable r5000 1323 1327 enable lamemp3 1324 1328 enable lirc 1325 1329 enable mheg … … 2966 2970 enabled libfftw3 && check_lib2 fftw3.h fftw_init_threads -lfftw3_threads -lfftw3 || 2967 2971 disable libfftw3 2968 2972 2973 enabled r5000 && has_library libusb && check_header usb.h || disable r5000 2974 2969 2975 enabled x11 && has_library libX11 || disable x11 2970 2976 enabled xrandr && check_header X11/extensions/Xrandr.h || disable xrandr 2971 2977 enabled xv && has_library libXv || disable xv … … 3289 3295 # echo "DBox2 support ${dbox2-no}" 3290 3296 echo "HDHomeRun support ${hdhomerun-no}" 3291 3297 echo "IPTV support ${iptv-no}" 3298 echo "R5000 support ${r5000-no}" 3292 3299 fi 3293 3300 3294 3301 if enabled frontend; then -
libs/libmythtv/cardutil.h
old new 54 54 HDHOMERUN = 10, 55 55 FREEBOX = 11, 56 56 HDPVR = 12, 57 R5000 = 13, 57 58 }; 58 59 59 60 static enum CARD_TYPES toCardType(const QString &name) … … 84 85 return FREEBOX; 85 86 if ("HDPVR" == name) 86 87 return HDPVR; 88 if ("R5000" == name) 89 return R5000; 87 90 return ERROR_UNKNOWN; 88 91 } 89 92 … … 92 95 return 93 96 (rawtype != "DVB") && 94 97 (rawtype != "FIREWIRE") && (rawtype != "DBOX2") && 95 (rawtype != "HDHOMERUN") && (rawtype != "FREEBOX"); 98 (rawtype != "HDHOMERUN") && (rawtype != "FREEBOX") && 99 (rawtype != "R5000") ; 96 100 } 97 101 98 102 static bool IsUnscanable(const QString &rawtype) 99 103 { 100 104 return 101 105 (rawtype == "FIREWIRE") || (rawtype == "DBOX2") || 102 (rawtype == "HDPVR") ;106 (rawtype == "HDPVR") || (rawtype == "R5000"); 103 107 } 104 108 105 109 static bool IsEITCapable(const QString &rawtype) -
libs/libmythtv/libmythtv.pro
old new 516 516 DEFINES += USING_DVB 517 517 } 518 518 519 #Support for R5000 usb device 520 using_r5000 { 521 HEADERS += r5000channel.h r5000recorder.h 522 HEADERS += r5000signalmonitor.h r5000device.h 523 HEADERS += r5000/r5000.h r5000/libusb_augment.h 524 HEADERS += r5000/r5000_internal.h r5000/r5000init.h 525 526 SOURCES += r5000channel.cpp r5000recorder.cpp 527 SOURCES += r5000signalmonitor.cpp r5000device.cpp 528 SOURCES += r5000/r5000.c r5000/libusb_augment.c 529 SOURCES += r5000/r5k_vip.c r5000/r5k_directv.c 530 SOURCES += r5000/r5k_sat.c r5000/r5k_misc.c 531 532 LIBS += -lusb 533 DEFINES += USING_R5000 534 } 535 519 536 DEFINES += USING_BACKEND 520 537 } 521 538 -
libs/libmythtv/signalmonitor.h
old new 288 288 (cardtype.toUpper() == "HDTV") || 289 289 (cardtype.toUpper() == "HDHOMERUN") || 290 290 (cardtype.toUpper() == "FIREWIRE") || 291 (cardtype.toUpper() == "FREEBOX")); 291 (cardtype.toUpper() == "FREEBOX") || 292 (cardtype.toUpper() == "R5000")); 292 293 } 293 294 294 295 inline bool SignalMonitor::IsSupported(const QString &cardtype) -
libs/libmythtv/signalmonitor.cpp
old new 42 42 # include "firewirechannel.h" 43 43 #endif 44 44 45 #ifdef USING_R5000 46 # include "r5000signalmonitor.h" 47 # include "r5000channel.h" 48 #endif 49 45 50 #undef DBG_SM 46 51 #define DBG_SM(FUNC, MSG) VERBOSE(VB_CHANNEL, \ 47 52 "SM("<<channel->GetDevice()<<")::"<<FUNC<<": "<<MSG); … … 129 134 signalMonitor = new FirewireSignalMonitor(db_cardnum, fc); 130 135 } 131 136 #endif 137 #ifdef USING_R5000 138 if (cardtype.toUpper() == "R5000") 139 { 140 R5000Channel *fc = dynamic_cast<R5000Channel*>(channel); 141 if (fc) 142 signalMonitor = new R5000SignalMonitor(db_cardnum, fc); 143 } 144 #endif 132 145 133 146 if (!signalMonitor) 134 147 { -
libs/libmythtv/cardutil.cpp
old new 1613 1613 if (("FIREWIRE" == cardtype) || 1614 1614 ("FREEBOX" == cardtype) || 1615 1615 ("DBOX2" == cardtype) || 1616 ("HDHOMERUN" == cardtype)) 1616 ("HDHOMERUN" == cardtype) || 1617 ("R5000" == cardtype)) 1617 1618 { 1618 1619 ret += "MPEG2TS"; 1619 1620 } … … 1783 1784 if (("FIREWIRE" == cardtype) || 1784 1785 ("FREEBOX" == cardtype) || 1785 1786 ("DBOX2" == cardtype) || 1786 ("HDHOMERUN" == cardtype)) 1787 ("HDHOMERUN" == cardtype) || 1788 ("R5000" == cardtype)) 1787 1789 { 1788 1790 inputs += "MPEG2TS"; 1789 1791 } -
libs/libmythtv/videosource.cpp
old new 35 35 #include "frequencies.h" 36 36 #include "diseqcsettings.h" 37 37 #include "firewiredevice.h" 38 #include "r5000device.h" 38 39 #include "libmythdb/compat.h" 39 40 #include "libmythdb/mythdb.h" 40 41 #include "libmythdb/mythdirs.h" … … 1424 1425 } 1425 1426 }; 1426 1427 1428 class R5000Serial : public ComboBoxSetting, public CaptureCardDBStorage 1429 { 1430 public: 1431 R5000Serial(const CaptureCard &parent) : 1432 ComboBoxSetting(this), 1433 CaptureCardDBStorage(this, parent, "videodevice") 1434 { 1435 setLabel(QObject::tr("Serial #")); 1436 #ifdef USING_R5000 1437 QStringList serials = R5000Device::GetSTBList(); 1438 for (uint i = 0; i < serials.size(); i++) 1439 { 1440 addSelection(serials[i]); 1441 } 1442 #endif // USING_FIREWIRE 1443 } 1444 }; 1445 1446 class R5000Model : public ComboBoxSetting, public CaptureCardDBStorage 1447 { 1448 public: 1449 R5000Model(const CaptureCard &parent) : 1450 ComboBoxSetting(this), 1451 CaptureCardDBStorage(this, parent, "firewire_model") 1452 { 1453 setLabel(QObject::tr("R5000 STB type")); 1454 addSelection("VIP211"); 1455 addSelection("VIP411"); 1456 addSelection("VIP622"); 1457 addSelection("VIP722"); 1458 addSelection("BEV9242"); 1459 addSelection("DIRECTV"); 1460 addSelection("STARCHOICE/DSR"); 1461 addSelection("HDD-200"); 1462 QString help = QObject::tr( 1463 "Choose the type of R5000 enabled STB you are using."); 1464 setHelpText(help); 1465 } 1466 }; 1467 class R5000ConfigurationGroup : public VerticalConfigurationGroup 1468 { 1469 public: 1470 R5000ConfigurationGroup(CaptureCard& a_parent): 1471 VerticalConfigurationGroup(false, true, false, false), 1472 parent(a_parent) 1473 { 1474 setUseLabel(false); 1475 addChild(new R5000Serial(parent)); 1476 addChild(new R5000Model(parent)); 1477 addChild(new SingleCardInput(parent)); 1478 }; 1479 1480 private: 1481 CaptureCard &parent; 1482 }; 1483 1427 1484 class IPTVHost : public LineEditSetting, public CaptureCardDBStorage 1428 1485 { 1429 1486 public: … … 1654 1711 #ifdef USING_IPTV 1655 1712 addTarget("FREEBOX", new IPTVConfigurationGroup(parent)); 1656 1713 #endif // USING_IPTV 1714 1715 #ifdef USING_R5000 1716 addTarget("R5000", new R5000ConfigurationGroup(parent)); 1717 #endif // USING_R5000 1657 1718 } 1658 1719 1659 1720 void CaptureCardGroup::triggerChanged(const QString& value) … … 1854 1915 #ifdef USING_IPTV 1855 1916 setting->addSelection(QObject::tr("Network Recorder"), "FREEBOX"); 1856 1917 #endif // USING_IPTV 1918 1919 #ifdef USING_R5000 1920 setting->addSelection(QObject::tr("R5000 Capable STB"), "R5000"); 1921 #endif // USING_R5000 1857 1922 } 1858 1923 1859 1924 class CardID : public SelectLabelSetting, public CardInputDBStorage -
libs/libmythtv/tv_rec.cpp
old new 49 49 #include "hdhrchannel.h" 50 50 #include "iptvchannel.h" 51 51 #include "firewirechannel.h" 52 #include "r5000channel.h" 52 53 53 54 #include "recorderbase.h" 54 55 #include "NuppelVideoRecorder.h" … … 58 59 #include "hdhrrecorder.h" 59 60 #include "iptvrecorder.h" 60 61 #include "firewirerecorder.h" 62 #include "r5000recorder.h" 61 63 62 64 #ifdef USING_V4L 63 65 #include "v4lchannel.h" … … 198 200 init_run = true; 199 201 #endif 200 202 } 203 else if (genOpt.cardtype == "R5000") 204 { 205 #ifdef USING_R5000 206 channel = new R5000Channel(this, genOpt.videodev, fwOpt.model); 207 if (!channel->Open()) 208 return false; 209 InitChannel(genOpt.defaultinput, startchannel); 210 init_run = true; 211 #endif 212 } 201 213 else // "V4L" or "MPEG", ie, analog TV 202 214 { 203 215 #ifdef USING_V4L … … 1016 1028 recorder->SetOption("mrl", genOpt.videodev); 1017 1029 #endif // USING_IPTV 1018 1030 } 1031 else if (genOpt.cardtype == "R5000") 1032 { 1033 #ifdef USING_R5000 1034 recorder = new R5000Recorder(this, GetR5000Channel()); 1035 #endif // USING_R5000 1036 } 1019 1037 else 1020 1038 { 1021 1039 #ifdef USING_V4L … … 1233 1251 #endif // USING_FIREWIRE 1234 1252 } 1235 1253 1254 R5000Channel *TVRec::GetR5000Channel(void) 1255 { 1256 #ifdef USING_R5000 1257 return dynamic_cast<R5000Channel*>(channel); 1258 #else 1259 return NULL; 1260 #endif // USING_R5000 1261 } 1262 1236 1263 V4LChannel *TVRec::GetV4LChannel(void) 1237 1264 { 1238 1265 #ifdef USING_V4L -
libs/libmythtv/transporteditor.cpp
old new 734 734 left->addChild(new Modulation(id, nType)); 735 735 } 736 736 else if ((CardUtil::FIREWIRE == nType) || 737 (CardUtil::FREEBOX == nType)) 737 (CardUtil::FREEBOX == nType) || 738 (CardUtil::R5000 == nType)) 738 739 { 739 740 left->addChild(new DTVStandard(id, true, true)); 740 741 } -
libs/libmythtv/tv_rec.h
old new 42 42 class FirewireChannel; 43 43 class V4LChannel; 44 44 class HDHRChannel; 45 class R5000Channel; 45 46 46 47 class MPEGStreamData; 47 48 class ProgramMapTable; … … 285 286 HDHRChannel *GetHDHRChannel(void); 286 287 DVBChannel *GetDVBChannel(void); 287 288 FirewireChannel *GetFirewireChannel(void); 289 R5000Channel *GetR5000Channel(void); 288 290 V4LChannel *GetV4LChannel(void); 289 291 290 292 bool SetupSignalMonitor(bool enable_table_monitoring, bool notify); -
new file libs/libmythtv/r5000channel.cpp
- + 1 /** 2 * R5000Channel 3 * Copyright (c) 2005 by Jim Westfall, Dave Abrahams 4 * Copyright (c) 2006 by Daniel Kristjansson 5 * Distributed as part of MythTV under GPL v2 and later. 6 */ 7 8 #include "mythcontext.h" 9 #include "tv_rec.h" 10 #include "r5000channel.h" 11 12 #define LOC QString("R5kChan(%1): ").arg(GetDevice()) 13 #define LOC_WARN QString("R5kChan(%1), Warning: ").arg(GetDevice()) 14 #define LOC_ERR QString("R5kChan(%1), Error: ").arg(GetDevice()) 15 16 R5000Channel::R5000Channel(TVRec *parent, const QString &_videodevice,const QString &_r5ktype) : 17 DTVChannel(parent), 18 videodevice(_videodevice), 19 device(NULL), 20 current_channel(""), 21 current_mpeg_prog(0), 22 isopen(false) 23 { 24 int type = R5000Device::GetDeviceType(_r5ktype); 25 device = new R5000Device(type, videodevice); 26 27 InitializeInputs(); 28 } 29 30 bool R5000Channel::SetChannelByString(const QString &channum) 31 { 32 QString loc = LOC + QString("SetChannelByString(%1)").arg(channum); 33 bool ok = false; 34 VERBOSE(VB_CHANNEL, loc); 35 36 InputMap::const_iterator it = inputs.find(currentInputID); 37 if (it == inputs.end()) 38 return false; 39 40 QString tvformat, modulation, freqtable, freqid, dtv_si_std; 41 int finetune; 42 uint64_t frequency; 43 int mpeg_prog_num; 44 uint atsc_major, atsc_minor, mplexid, tsid, netid; 45 if (!ChannelUtil::GetChannelData( 46 (*it)->sourceid, channum, 47 tvformat, modulation, freqtable, freqid, 48 finetune, frequency, 49 dtv_si_std, mpeg_prog_num, atsc_major, atsc_minor, tsid, netid, 50 mplexid, commfree)) 51 { 52 VERBOSE(VB_IMPORTANT, loc + " " + QString( 53 "Requested channel '%1' is on input '%2' " 54 "which is in a busy input group") 55 .arg(channum).arg(currentInputID)); 56 57 return false; 58 } 59 uint mplexid_restriction; 60 if (!IsInputAvailable(currentInputID, mplexid_restriction)) 61 { 62 VERBOSE(VB_IMPORTANT, loc + " " + QString( 63 "Requested channel '%1' is on input '%2' " 64 "which is in a busy input group") 65 .arg(channum).arg(currentInputID)); 66 67 return false; 68 } 69 70 if (!(*it)->externalChanger.isEmpty()) 71 { 72 ok = ChangeExternalChannel(freqid); 73 // -1 resets any state without executing a channel change 74 device->SetChannel(fw_opts.model, 0, mpeg_prog_num); 75 SetSIStandard("mpeg"); 76 SetDTVInfo(0,0,0,0,1); 77 } 78 else 79 { 80 ok = isopen && SetChannelByNumber(freqid, mpeg_prog_num); 81 } 82 83 if (ok) 84 { 85 // Set the current channum to the new channel's channum 86 QString tmp = channum; 87 tmp.detach(); 88 curchannelname = tmp; 89 tmp.detach(); 90 (*it)->startChanNum = tmp; 91 } 92 93 VERBOSE(VB_CHANNEL, loc + " " + ((ok) ? "success" : "failure")); 94 95 return ok; 96 } 97 98 bool R5000Channel::Open(void) 99 { 100 VERBOSE(VB_CHANNEL, LOC + "Open()"); 101 102 if (inputs.find(currentInputID) == inputs.end()) 103 return false; 104 105 if (!device) 106 return false; 107 108 if (isopen) 109 return true; 110 111 if (!device->OpenPort()) 112 return false; 113 114 isopen = true; 115 116 return true; 117 } 118 119 void R5000Channel::Close(void) 120 { 121 VERBOSE(VB_CHANNEL, LOC + "Close()"); 122 if (isopen) 123 { 124 device->ClosePort(); 125 isopen = false; 126 } 127 } 128 129 QString R5000Channel::GetDevice(void) const 130 { 131 return videodevice; 132 } 133 134 bool R5000Channel::SetPowerState(bool on) 135 { 136 if (!isopen) 137 { 138 VERBOSE(VB_IMPORTANT, LOC_ERR + 139 "SetPowerState() called on closed R5000Channel."); 140 141 return false; 142 } 143 144 return device->SetPowerState(on); 145 } 146 147 R5000Device::PowerState R5000Channel::GetPowerState(void) const 148 { 149 if (!isopen) 150 { 151 VERBOSE(VB_IMPORTANT, LOC_ERR + 152 "GetPowerState() called on closed R5000Channel."); 153 154 return R5000Device::kAVCPowerQueryFailed; 155 } 156 157 return device->GetPowerState(); 158 } 159 160 bool R5000Channel::Retune(void) 161 { 162 VERBOSE(VB_CHANNEL, LOC + "Retune()"); 163 164 if (R5000Device::kAVCPowerOff == GetPowerState()) 165 { 166 VERBOSE(VB_IMPORTANT, LOC_ERR + 167 "STB is turned off, must be on to retune."); 168 169 return false; 170 } 171 172 if (current_channel.length()) 173 return SetChannelByNumber(current_channel, current_mpeg_prog); 174 175 return false; 176 } 177 178 bool R5000Channel::SetChannelByNumber(const QString &channel, int mpeg_prog) 179 { 180 VERBOSE(VB_CHANNEL, QString("SetChannelByNumber(%1)").arg(channel)); 181 current_channel = channel; 182 current_mpeg_prog = mpeg_prog; 183 184 if (R5000Device::kAVCPowerOff == GetPowerState()) 185 { 186 VERBOSE(VB_IMPORTANT, LOC_WARN + 187 "STB is turned off, must be on to set channel."); 188 189 SetSIStandard("mpeg"); 190 SetDTVInfo(0,0,0,0,1); 191 192 return true; // signal monitor will call retune later... 193 } 194 195 if (!device->SetChannel(fw_opts.model, channel, mpeg_prog)) 196 return false; 197 198 SetSIStandard("mpeg"); 199 SetDTVInfo(0,0,0,0,1); 200 201 return true; 202 } -
new file libs/libmythtv/r5000device.cpp
- + 1 /** 2 * R5000Device 3 * Copyright (c) 2008 by Alan Nisota 4 * Copyright (c) 2005 by Jim Westfall 5 * Distributed as part of MythTV under GPL v2 and later. 6 */ 7 8 // MythTV headers 9 #include "r5000device.h" 10 #include "mythcontext.h" 11 #include "pespacket.h" 12 13 #define LOC QString("R5kDev: ") 14 #define LOC_WARN QString("R5kDev, Warning: ") 15 #define LOC_ERR QString("R5kDev, Error: ") 16 17 static int r5k_init = 0; 18 QMap<uint64_t,QString> R5000Device::s_id_to_model; 19 QMutex R5000Device::s_static_lock; 20 21 unsigned int r5000_device_tspacket_handler(unsigned char *tspacket, int len, void *callback_data) 22 { 23 R5000Device *fw = (R5000Device*) callback_data; 24 if (! fw) 25 return 0; 26 if (len > 0) 27 fw->BroadcastToListeners(tspacket, len); 28 return 1; 29 } 30 31 void r5000_msg(char * msg) 32 { 33 VERBOSE(VB_IMPORTANT, "R5kLib: "<<msg); 34 } 35 36 class R5kPriv 37 { 38 public: 39 R5kPriv() : 40 reset_timer_on(false), 41 run_port_handler(false), is_port_handler_running(false), 42 channel(-1), 43 is_streaming(false) 44 { 45 } 46 47 bool reset_timer_on; 48 MythTimer reset_timer; 49 50 bool run_port_handler; 51 bool is_port_handler_running; 52 QMutex start_stop_port_handler_lock; 53 54 int channel; 55 56 bool is_streaming; 57 58 QDateTime stop_streaming_timer; 59 pthread_t port_handler_thread; 60 61 static QMutex s_lock; 62 }; 63 QMutex R5kPriv::s_lock; 64 65 //callback functions 66 void *r5000_device_port_handler_thunk(void *param); 67 68 R5000Device::R5000Device(int type, QString serial) : 69 m_type(type), 70 m_serial(serial), 71 m_last_channel(""), m_last_crc(0), 72 m_buffer_cleared(true), m_open_port_cnt(0), 73 m_lock(), m_priv(new R5kPriv()) 74 { 75 QMutexLocker locker(&s_static_lock); 76 usbdev = NULL; 77 if (! r5k_init) 78 r5k_init = r5000_init(r5000_msg); 79 } 80 81 R5000Device::~R5000Device() 82 { 83 if (usbdev) 84 { 85 VERBOSE(VB_IMPORTANT, LOC_ERR + "ctor called with open port"); 86 while (usbdev) 87 ClosePort(); 88 } 89 90 if (m_priv) 91 { 92 delete m_priv; 93 m_priv = NULL; 94 } 95 } 96 97 void R5000Device::AddListener(TSDataListener *listener) 98 { 99 if (listener) 100 { 101 vector<TSDataListener*>::iterator it = 102 find(m_listeners.begin(), m_listeners.end(), listener); 103 104 if (it == m_listeners.end()) 105 m_listeners.push_back(listener); 106 } 107 108 VERBOSE(VB_RECORD, LOC + "AddListener() "<<m_listeners.size()); 109 if (!m_listeners.empty()) 110 { 111 StartStreaming(); 112 } 113 } 114 115 void R5000Device::RemoveListener(TSDataListener *listener) 116 { 117 vector<TSDataListener*>::iterator it = m_listeners.end(); 118 119 do 120 { 121 it = find(m_listeners.begin(), m_listeners.end(), listener); 122 if (it != m_listeners.end()) 123 m_listeners.erase(it); 124 } 125 while (it != m_listeners.end()); 126 127 VERBOSE(VB_RECORD, LOC + "RemoveListener() "<<m_listeners.size()); 128 if (m_listeners.empty()) 129 { 130 StopStreaming(); 131 } 132 } 133 134 bool R5000Device::StartStreaming(void) 135 { 136 if (m_priv->is_streaming) 137 return m_priv->is_streaming; 138 139 if (! usbdev) 140 { 141 VERBOSE(VB_IMPORTANT, LOC_ERR + "Device not open"); 142 return false; 143 } 144 if (r5000_start_stream(usbdev)) 145 { 146 m_priv->is_streaming = true; 147 } 148 else 149 { 150 VERBOSE(VB_IMPORTANT, LOC_ERR + "Starting A/V streaming "); 151 } 152 153 VERBOSE(VB_RECORD, LOC + "Starting A/V streaming -- done"); 154 155 return m_priv->is_streaming; 156 } 157 158 bool R5000Device::StopStreaming(void) 159 { 160 if (m_priv->is_streaming) 161 { 162 VERBOSE(VB_RECORD, LOC + "Stopping A/V streaming -- really"); 163 164 m_priv->is_streaming = false; 165 166 r5000_stop_stream(usbdev); 167 } 168 169 VERBOSE(VB_RECORD, LOC + "Stopped A/V streaming"); 170 171 return true; 172 } 173 174 bool R5000Device::SetPowerState(bool on) 175 { 176 QMutexLocker locker(&m_lock); 177 QString cmdStr = (on) ? "on" : "off"; 178 VERBOSE(VB_RECORD, LOC + QString("Powering %1").arg(cmdStr)); 179 r5000_power_on_off(usbdev, on); 180 return true; 181 } 182 183 R5000Device::PowerState R5000Device::GetPowerState(void) 184 { 185 QMutexLocker locker(&m_lock); 186 int on_off; 187 188 VERBOSE(VB_CHANNEL, LOC + "Requesting STB Power State"); 189 on_off = r5000_get_power_state(usbdev); 190 VERBOSE(VB_CHANNEL, LOC + (on_off ? "On" : "Off")); 191 return on_off ? kAVCPowerOn : kAVCPowerOff; 192 } 193 194 bool R5000Device::SetChannel(const QString &panel_model, 195 const QString &channel, uint mpeg_prog) 196 { 197 VERBOSE(VB_CHANNEL, QString("SetChannel(model %1, chan %2 mpeg_prog %3)") 198 .arg(panel_model).arg(channel).arg(mpeg_prog)); 199 200 QMutexLocker locker(&m_lock); 201 VERBOSE(VB_CHANNEL, "SetChannel() -- locked"); 202 if (! r5000_change_channel(usbdev, channel.toAscii(), mpeg_prog)) 203 VERBOSE(VB_IMPORTANT, LOC + "Failed to set channel"); 204 return true; 205 } 206 207 void R5000Device::BroadcastToListeners( 208 const unsigned char *data, uint dataSize) 209 { 210 if ((dataSize >= TSPacket::SIZE) && (data[0] == SYNC_BYTE) && 211 ((data[1] & 0x1f) == 0) && (data[2] == 0)) 212 { 213 ProcessPATPacket(*((const TSPacket*)data)); 214 } 215 216 vector<TSDataListener*>::iterator it = m_listeners.begin(); 217 for (; it != m_listeners.end(); ++it) 218 (*it)->AddData(data, dataSize); 219 } 220 221 void R5000Device::SetLastChannel(const QString &channel) 222 { 223 m_buffer_cleared = (channel == m_last_channel); 224 m_last_channel = channel; 225 226 VERBOSE(VB_IMPORTANT, QString("SetLastChannel(%1): cleared: %2") 227 .arg(channel).arg(m_buffer_cleared ? "yes" : "no")); 228 } 229 230 void R5000Device::ProcessPATPacket(const TSPacket &tspacket) 231 { 232 if (!tspacket.TransportError() && !tspacket.ScramplingControl() && 233 tspacket.HasPayload() && tspacket.PayloadStart() && !tspacket.PID()) 234 { 235 PESPacket pes = PESPacket::View(tspacket); 236 uint crc = pes.CalcCRC(); 237 m_buffer_cleared |= (crc != m_last_crc); 238 m_last_crc = crc; 239 #if 0 240 VERBOSE(VB_RECORD, LOC + 241 QString("ProcessPATPacket: CRC 0x%1 cleared: %2") 242 .arg(crc,0,16).arg(m_buffer_cleared ? "yes" : "no")); 243 #endif 244 } 245 else 246 { 247 VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't handle large PAT's"); 248 } 249 } 250 251 QString R5000Device::GetModelName(uint vendor_id, uint model_id) 252 { 253 QMutexLocker locker(&s_static_lock); 254 /* 255 if (s_id_to_model.empty()) 256 fw_init(s_id_to_model); 257 258 QString ret = s_id_to_model[(((uint64_t) vendor_id) << 32) | model_id]; 259 260 if (ret.isEmpty()) 261 return "GENERIC"; 262 */ 263 return "R5000"; 264 } 265 266 bool R5000Device::IsSTBSupported(const QString &panel_model) 267 { 268 return true; 269 } 270 271 bool R5000Device::OpenPort(void) 272 { 273 VERBOSE(VB_RECORD, LOC + "Starting Port Handler Thread"); 274 QMutexLocker mlocker(&m_lock); 275 VERBOSE(VB_RECORD, LOC + "Starting Port Handler Thread -- locked"); 276 if (usbdev) 277 { 278 m_open_port_cnt++; 279 return true; 280 } 281 282 if (m_serial.length()) 283 { 284 VERBOSE(VB_RECORD, LOC + QString("Opening R5000 device type %1 with serial#: "+ m_serial).arg(m_type)); 285 usbdev = r5000_open((r5ktype_t)m_type, r5000_device_tspacket_handler, this, m_serial.toAscii()); 286 } 287 else 288 { 289 VERBOSE(VB_RECORD, LOC + "Opening R5000 device with unknown serial#"); 290 usbdev = r5000_open((r5ktype_t)m_type, r5000_device_tspacket_handler, this, NULL); 291 } 292 if (! usbdev) 293 { 294 VERBOSE(VB_IMPORTANT, LOC + "Failed to open R5000 device"); 295 return false; 296 } 297 298 VERBOSE(VB_RECORD, LOC + "Starting port handler thread"); 299 m_priv->run_port_handler = true; 300 pthread_create(&m_priv->port_handler_thread, NULL, 301 r5000_device_port_handler_thunk, this); 302 303 VERBOSE(VB_RECORD, LOC + "Waiting for port handler thread to start"); 304 while (!m_priv->is_port_handler_running) 305 { 306 m_lock.unlock(); 307 usleep(5000); 308 m_lock.lock(); 309 } 310 311 VERBOSE(VB_RECORD, LOC + "Port handler thread started"); 312 313 m_open_port_cnt++; 314 315 return true; 316 } 317 318 bool R5000Device::ClosePort(void) 319 { 320 VERBOSE(VB_RECORD, LOC + "Stopping Port Handler Thread"); 321 QMutexLocker locker(&m_priv->start_stop_port_handler_lock); 322 VERBOSE(VB_RECORD, LOC + "Stopping Port Handler Thread -- locked"); 323 324 QMutexLocker mlocker(&m_lock); 325 326 VERBOSE(VB_RECORD, LOC + "ClosePort()"); 327 328 if (m_open_port_cnt < 1) 329 return false; 330 331 m_open_port_cnt--; 332 333 if (m_open_port_cnt != 0) 334 return true; 335 336 if (!usbdev) 337 return false; 338 339 VERBOSE(VB_RECORD, LOC + "Waiting for port handler thread to stop"); 340 m_priv->run_port_handler = false; 341 while (m_priv->is_port_handler_running) 342 { 343 m_lock.unlock(); 344 usleep(5000); 345 m_lock.lock(); 346 } 347 VERBOSE(VB_RECORD, LOC + "Joining port handler thread"); 348 pthread_join(m_priv->port_handler_thread, NULL); 349 350 r5000_close(usbdev); 351 usbdev = NULL; 352 353 return true; 354 } 355 356 void *r5000_device_port_handler_thunk(void *param) 357 { 358 R5000Device *mon = (R5000Device*) param; 359 mon->RunPortHandler(); 360 return NULL; 361 } 362 363 void R5000Device::RunPortHandler(void) 364 { 365 VERBOSE(VB_RECORD, LOC + "RunPortHandler -- start"); 366 m_lock.lock(); 367 VERBOSE(VB_RECORD, LOC + "RunPortHandler -- got first lock"); 368 m_priv->is_port_handler_running = true; 369 m_lock.unlock(); 370 371 while (m_priv->run_port_handler) 372 { 373 if (m_priv->is_streaming) 374 { 375 // This will timeout after 10ms regardless of data availability 376 r5000_loop_iterate(usbdev, 10); 377 } 378 else 379 { 380 usleep(10000); 381 } 382 } 383 384 m_lock.lock(); 385 m_priv->is_port_handler_running = false; 386 m_lock.unlock(); 387 VERBOSE(VB_RECORD, LOC + "RunPortHandler -- end"); 388 } 389 390 QStringList R5000Device::GetSTBList(void) 391 { 392 QStringList STBList; 393 int i; 394 r5kenum_t r5k_stbs; 395 if (! r5k_init) 396 { 397 r5k_init = r5000_init(r5000_msg); 398 if (! r5k_init) 399 return STBList; 400 } 401 if (! r5000_find_stbs(&r5k_stbs)) 402 VERBOSE(VB_IMPORTANT, LOC + "Locating R5000 devices failed." 403 " This may be a permission problem"); 404 405 for (i = 0; i < r5k_stbs.count; i++) 406 STBList.append((char *)r5k_stbs.serial[i]); 407 return STBList; 408 } 409 410 int R5000Device::GetDeviceType(const QString &r5ktype) 411 { 412 QString type = r5ktype.toUpper(); 413 if (type == "DIRECTV") 414 { 415 return R5K_STB_DIRECTV; 416 } 417 else if ("VIP211/VIP622/DISH411" == type || 418 "VIP211/VIP422" == type || 419 "VIP211" == type || 420 "VIP411" == type) 421 { 422 return R5K_STB_VIP211; 423 } 424 else if ("STARCHOICE/DSR" == type) 425 { 426 return R5K_STB_DSR; 427 } 428 else if ("HDD-200" == type) 429 { 430 return R5K_STB_HDD; 431 } 432 else if ("VIP622" == type || 433 "VIP722" == type || 434 "BEV9242" == type) 435 { 436 return R5K_STB_VIP622; 437 } 438 else 439 { 440 return R5K_STB_VIP211; 441 } 442 } -
new file libs/libmythtv/r5000recorder.cpp
- + 1 /** 2 * R5000Recorder 3 * Copyright (c) 2005 by Jim Westfall and Dave Abrahams 4 * Distributed as part of MythTV under GPL v2 and later. 5 */ 6 7 // MythTV includes 8 #include "r5000recorder.h" 9 #include "r5000channel.h" 10 #include "mythcontext.h" 11 #include "mpegtables.h" 12 #include "mpegstreamdata.h" 13 #include "tv_rec.h" 14 15 #define LOC QString("R5000RecBase(%1): ").arg(channel->GetDevice()) 16 #define LOC_ERR QString("R5000RecBase(%1), Error: ").arg(channel->GetDevice()) 17 18 R5000Recorder::R5000Recorder(TVRec *rec, R5000Channel *chan) : 19 DTVRecorder(rec), _mpeg_stream_data(NULL), 20 channel(chan), isopen(false) 21 { 22 _wait_for_keyframe_option = false; 23 } 24 25 R5000Recorder::~R5000Recorder() 26 { 27 SetStreamData(NULL); 28 Close(); 29 } 30 31 bool R5000Recorder::Open(void) 32 { 33 if (!isopen) 34 isopen = channel->GetR5000Device()->OpenPort(); 35 36 return isopen; 37 } 38 39 void R5000Recorder::Close(void) 40 { 41 if (isopen) 42 { 43 channel->GetR5000Device()->ClosePort(); 44 isopen = false; 45 } 46 } 47 48 void R5000Recorder::StartStreaming(void) 49 { 50 channel->GetR5000Device()->AddListener(this); 51 } 52 53 void R5000Recorder::StopStreaming(void) 54 { 55 channel->GetR5000Device()->RemoveListener(this); 56 } 57 58 void R5000Recorder::StartRecording(void) 59 { 60 VERBOSE(VB_RECORD, LOC + "StartRecording"); 61 62 if (!Open()) 63 { 64 _error = true; 65 return; 66 } 67 68 _request_recording = true; 69 _recording = true; 70 71 StartStreaming(); 72 73 while (_request_recording) 74 { 75 if (!PauseAndWait()) 76 usleep(50 * 1000); 77 } 78 79 StopStreaming(); 80 FinishRecording(); 81 82 _recording = false; 83 } 84 85 void R5000Recorder::AddData(const unsigned char *data, uint len) 86 { 87 uint bufsz = buffer.size(); 88 if ((SYNC_BYTE == data[0]) && (TSPacket::SIZE == len) && 89 (TSPacket::SIZE > bufsz)) 90 { 91 if (bufsz) 92 buffer.clear(); 93 94 ProcessTSPacket(*(reinterpret_cast<const TSPacket*>(data))); 95 return; 96 } 97 98 buffer.insert(buffer.end(), data, data + len); 99 bufsz += len; 100 101 int sync_at = -1; 102 for (uint i = 0; (i < bufsz) && (sync_at < 0); i++) 103 { 104 if (buffer[i] == SYNC_BYTE) 105 sync_at = i; 106 } 107 108 if (sync_at < 0) 109 return; 110 111 if (bufsz < 30 * TSPacket::SIZE) 112 return; // build up a little buffer 113 114 while (sync_at + TSPacket::SIZE < bufsz) 115 { 116 ProcessTSPacket(*(reinterpret_cast<const TSPacket*>( 117 &buffer[0] + sync_at))); 118 119 sync_at += TSPacket::SIZE; 120 } 121 122 buffer.erase(buffer.begin(), buffer.begin() + sync_at); 123 124 return; 125 } 126 127 void R5000Recorder::ProcessTSPacket(const TSPacket &tspacket) 128 { 129 if (tspacket.TransportError()) 130 return; 131 132 if (tspacket.ScramplingControl()) 133 return; 134 135 if (tspacket.HasAdaptationField()) 136 GetStreamData()->HandleAdaptationFieldControl(&tspacket); 137 138 if (tspacket.HasPayload()) 139 { 140 const unsigned int lpid = tspacket.PID(); 141 // Pass or reject packets based on PID, and parse info from them 142 if (lpid == GetStreamData()->VideoPIDSingleProgram()) 143 { 144 _buffer_packets = !FindMPEG2Keyframes(&tspacket); 145 BufferedWrite(tspacket); 146 } 147 else if (GetStreamData()->IsAudioPID(lpid)) 148 { 149 _buffer_packets = !FindAudioKeyframes(&tspacket); 150 BufferedWrite(tspacket); 151 } 152 else if (GetStreamData()->IsListeningPID(lpid)) 153 GetStreamData()->HandleTSTables(&tspacket); 154 else if (GetStreamData()->IsWritingPID(lpid)) 155 BufferedWrite(tspacket); 156 } 157 } 158 159 void R5000Recorder::SetOptionsFromProfile(RecordingProfile *profile, 160 const QString &videodev, 161 const QString &audiodev, 162 const QString &vbidev) 163 { 164 (void)videodev; 165 (void)audiodev; 166 (void)vbidev; 167 (void)profile; 168 } 169 170 // documented in recorderbase.cpp 171 bool R5000Recorder::PauseAndWait(int timeout) 172 { 173 if (request_pause) 174 { 175 VERBOSE(VB_RECORD, LOC + "PauseAndWait("<<timeout<<") -- pause"); 176 if (!paused) 177 { 178 StopStreaming(); 179 paused = true; 180 pauseWait.wakeAll(); 181 if (tvrec) 182 tvrec->RecorderPaused(); 183 } 184 QMutex unpause_lock; 185 unpause_lock.lock(); 186 unpauseWait.wait(&unpause_lock, timeout); 187 } 188 if (!request_pause && paused) 189 { 190 VERBOSE(VB_RECORD, LOC + "PauseAndWait("<<timeout<<") -- unpause"); 191 StartStreaming(); 192 paused = false; 193 } 194 return paused; 195 } 196 197 void R5000Recorder::SetStreamData(MPEGStreamData *data) 198 { 199 VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- begin"); 200 if (data == _mpeg_stream_data) 201 { 202 VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 0"); 203 return; 204 } 205 206 MPEGStreamData *old_data = _mpeg_stream_data; 207 _mpeg_stream_data = data; 208 if (old_data) 209 delete old_data; 210 211 if (data) 212 { 213 data->AddMPEGSPListener(this); 214 215 if (data->DesiredProgram() >= 0) 216 data->SetDesiredProgram(data->DesiredProgram()); 217 } 218 VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 1"); 219 } 220 221 void R5000Recorder::HandleSingleProgramPAT(ProgramAssociationTable *pat) 222 { 223 if (!pat) 224 { 225 VERBOSE(VB_RECORD, LOC + "HandleSingleProgramPAT(NULL)"); 226 return; 227 } 228 int next = (pat->tsheader()->ContinuityCounter()+1)&0xf; 229 pat->tsheader()->SetContinuityCounter(next); 230 BufferedWrite(*(reinterpret_cast<const TSPacket*>(pat->tsheader()))); 231 } 232 233 void R5000Recorder::HandleSingleProgramPMT(ProgramMapTable *pmt) 234 { 235 if (!pmt) 236 { 237 VERBOSE(VB_RECORD, LOC + "HandleSingleProgramPMT(NULL)"); 238 return; 239 } 240 int next = (pmt->tsheader()->ContinuityCounter()+1)&0xf; 241 pmt->tsheader()->SetContinuityCounter(next); 242 BufferedWrite(*(reinterpret_cast<const TSPacket*>(pmt->tsheader()))); 243 } -
new file libs/libmythtv/r5000signalmonitor.cpp
- + 1 // -*- Mode: c++ -*- 2 // Copyright (c) 2006, Daniel Thor Kristjansson 3 4 #include <pthread.h> 5 #include <fcntl.h> 6 #include <unistd.h> 7 #include <sys/select.h> 8 9 #include "mythcontext.h" 10 #include "mythdbcon.h" 11 #include "atscstreamdata.h" 12 #include "mpegtables.h" 13 #include "atsctables.h" 14 #include "r5000channel.h" 15 #include "r5000signalmonitor.h" 16 17 #define LOC QString("R5kSM(%1): ").arg(channel->GetDevice()) 18 #define LOC_WARN QString("R5kSM(%1), Warning: ").arg(channel->GetDevice()) 19 #define LOC_ERR QString("R5kSM(%1), Error: ").arg(channel->GetDevice()) 20 21 const uint R5000SignalMonitor::kPowerTimeout = 3000; /* ms */ 22 const uint R5000SignalMonitor::kBufferTimeout = 5000; /* ms */ 23 24 QMap<void*,uint> R5000SignalMonitor::pat_keys; 25 QMutex R5000SignalMonitor::pat_keys_lock; 26 27 /** \fn R5000SignalMonitor::R5000SignalMonitor(int,R5000Channel*,uint,const char*) 28 * \brief Initializes signal lock and signal values. 29 * 30 * Start() must be called to actually begin continuous 31 * signal monitoring. The timeout is set to 3 seconds, 32 * and the signal threshold is initialized to 0%. 33 * 34 * \param db_cardnum Recorder number to monitor, 35 * if this is less than 0, SIGNAL events will not be 36 * sent to the frontend even if SetNotifyFrontend(true) 37 * is called. 38 * \param _channel R5000Channel for card 39 * \param _flags Flags to start with 40 * \param _name Name for Qt signal debugging 41 */ 42 R5000SignalMonitor::R5000SignalMonitor( 43 int db_cardnum, 44 R5000Channel *_channel, 45 uint64_t _flags, const char *_name) : 46 DTVSignalMonitor(db_cardnum, _channel, _flags), 47 dtvMonitorRunning(false), 48 stb_needs_retune(true), 49 stb_needs_to_wait_for_pat(false), 50 stb_needs_to_wait_for_power(false) 51 { 52 VERBOSE(VB_CHANNEL, LOC + "ctor"); 53 54 signalStrength.SetThreshold(65); 55 56 AddFlags(kSigMon_WaitForSig); 57 58 stb_needs_retune = 59 (R5000Device::kAVCPowerOff == _channel->GetPowerState()); 60 } 61 62 /** \fn R5000SignalMonitor::~R5000SignalMonitor() 63 * \brief Stops signal monitoring and table monitoring threads. 64 */ 65 R5000SignalMonitor::~R5000SignalMonitor() 66 { 67 VERBOSE(VB_CHANNEL, LOC + "dtor"); 68 Stop(); 69 } 70 71 /** \fn R5000SignalMonitor::Stop(void) 72 * \brief Stop signal monitoring and table monitoring threads. 73 */ 74 void R5000SignalMonitor::Stop(void) 75 { 76 VERBOSE(VB_CHANNEL, LOC + "Stop() -- begin"); 77 SignalMonitor::Stop(); 78 if (dtvMonitorRunning) 79 { 80 dtvMonitorRunning = false; 81 pthread_join(table_monitor_thread, NULL); 82 } 83 VERBOSE(VB_CHANNEL, LOC + "Stop() -- end"); 84 } 85 86 void R5000SignalMonitor::HandlePAT(const ProgramAssociationTable *pat) 87 { 88 AddFlags(kDTVSigMon_PATSeen); 89 90 R5000Channel *fwchan = dynamic_cast<R5000Channel*>(channel); 91 bool crc_bogus = !fwchan->GetR5000Device()->IsSTBBufferCleared(); 92 if (crc_bogus && stb_needs_to_wait_for_pat && 93 (stb_wait_for_pat_timer.elapsed() < (int)kBufferTimeout)) 94 { 95 VERBOSE(VB_CHANNEL, LOC + "HandlePAT() ignoring PAT"); 96 uint tsid = pat->TransportStreamID(); 97 GetStreamData()->SetVersionPAT(tsid, -1,0); 98 return; 99 } 100 101 if (crc_bogus && stb_needs_to_wait_for_pat) 102 { 103 VERBOSE(VB_IMPORTANT, LOC_WARN + "Wait for valid PAT timed out"); 104 stb_needs_to_wait_for_pat = false; 105 } 106 107 DTVSignalMonitor::HandlePAT(pat); 108 } 109 110 void R5000SignalMonitor::HandlePMT(uint pnum, const ProgramMapTable *pmt) 111 { 112 VERBOSE(VB_CHANNEL, LOC + "HandlePMT()"); 113 114 AddFlags(kDTVSigMon_PMTSeen); 115 116 if (!HasFlags(kDTVSigMon_PATMatch)) 117 { 118 GetStreamData()->SetVersionPMT(pnum, -1,0); 119 VERBOSE(VB_CHANNEL, LOC + "HandlePMT() ignoring PMT"); 120 return; 121 } 122 123 DTVSignalMonitor::HandlePMT(pnum, pmt); 124 } 125 126 void *R5000SignalMonitor::TableMonitorThread(void *param) 127 { 128 R5000SignalMonitor *mon = (R5000SignalMonitor*) param; 129 mon->RunTableMonitor(); 130 return NULL; 131 } 132 133 void R5000SignalMonitor::RunTableMonitor(void) 134 { 135 stb_needs_to_wait_for_pat = true; 136 stb_wait_for_pat_timer.start(); 137 dtvMonitorRunning = true; 138 139 VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- begin"); 140 141 R5000Channel *lchan = dynamic_cast<R5000Channel*>(channel); 142 if (!lchan) 143 { 144 VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- err end"); 145 dtvMonitorRunning = false; 146 return; 147 } 148 149 R5000Device *dev = lchan->GetR5000Device(); 150 151 dev->OpenPort(); 152 dev->AddListener(this); 153 154 while (dtvMonitorRunning && GetStreamData()) 155 usleep(100000); 156 157 VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- shutdown "); 158 159 dev->RemoveListener(this); 160 dev->ClosePort(); 161 162 dtvMonitorRunning = false; 163 164 VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- end"); 165 } 166 167 void R5000SignalMonitor::AddData(const unsigned char *data, uint len) 168 { 169 if (!dtvMonitorRunning) 170 return; 171 172 if (GetStreamData()) 173 GetStreamData()->ProcessData((unsigned char *)data, len); 174 } 175 176 /** \fn R5000SignalMonitor::UpdateValues(void) 177 * \brief Fills in frontend stats and emits status Qt signals. 178 * 179 * This function uses five ioctl's FE_READ_SNR, FE_READ_SIGNAL_STRENGTH 180 * FE_READ_BER, FE_READ_UNCORRECTED_BLOCKS, and FE_READ_STATUS to obtain 181 * statistics from the frontend. 182 * 183 * This is automatically called by MonitorLoop(), after Start() 184 * has been used to start the signal monitoring thread. 185 */ 186 void R5000SignalMonitor::UpdateValues(void) 187 { 188 if (!running || exit) 189 return; 190 191 if (dtvMonitorRunning) 192 { 193 EmitStatus(); 194 if (IsAllGood()) 195 SendMessageAllGood(); 196 // TODO dtv signals... 197 198 update_done = true; 199 return; 200 } 201 202 if (stb_needs_to_wait_for_power && 203 (stb_wait_for_power_timer.elapsed() < (int)kPowerTimeout)) 204 { 205 return; 206 } 207 stb_needs_to_wait_for_power = false; 208 209 R5000Channel *fwchan = dynamic_cast<R5000Channel*>(channel); 210 211 if (HasFlags(kFWSigMon_WaitForPower) && !HasFlags(kFWSigMon_PowerMatch)) 212 { 213 bool retried = false; 214 while (true) 215 { 216 R5000Device::PowerState power = fwchan->GetPowerState(); 217 if (R5000Device::kAVCPowerOn == power) 218 { 219 AddFlags(kFWSigMon_PowerSeen | kFWSigMon_PowerMatch); 220 } 221 else if (R5000Device::kAVCPowerOff == power) 222 { 223 AddFlags(kFWSigMon_PowerSeen); 224 fwchan->SetPowerState(true); 225 stb_wait_for_power_timer.start(); 226 stb_needs_to_wait_for_power = true; 227 } 228 else 229 { 230 bool qfailed = (R5000Device::kAVCPowerQueryFailed == power); 231 if (qfailed && !retried) 232 { 233 retried = true; 234 continue; 235 } 236 237 VERBOSE(VB_RECORD, "Can't determine if STB is power on, " 238 "assuming it is..."); 239 AddFlags(kFWSigMon_PowerSeen | kFWSigMon_PowerMatch); 240 } 241 break; 242 } 243 } 244 245 bool isLocked = !HasFlags(kFWSigMon_WaitForPower) || 246 HasFlags(kFWSigMon_WaitForPower | kFWSigMon_PowerMatch); 247 248 if (isLocked && stb_needs_retune) 249 { 250 fwchan->Retune(); 251 isLocked = stb_needs_retune = false; 252 } 253 254 // Set SignalMonitorValues from info from card. 255 { 256 QMutexLocker locker(&statusLock); 257 signalStrength.SetValue(isLocked ? 100 : 0); 258 signalLock.SetValue(isLocked ? 1 : 0); 259 } 260 261 EmitStatus(); 262 if (IsAllGood()) 263 SendMessageAllGood(); 264 265 // Start table monitoring if we are waiting on any table 266 // and we have a lock. 267 if (isLocked && GetStreamData() && 268 HasAnyFlag(kDTVSigMon_WaitForPAT | kDTVSigMon_WaitForPMT | 269 kDTVSigMon_WaitForMGT | kDTVSigMon_WaitForVCT | 270 kDTVSigMon_WaitForNIT | kDTVSigMon_WaitForSDT)) 271 { 272 pthread_create(&table_monitor_thread, NULL, 273 TableMonitorThread, this); 274 275 VERBOSE(VB_CHANNEL, LOC + "UpdateValues() -- " 276 "Waiting for table monitor to start"); 277 278 while (!dtvMonitorRunning) 279 usleep(50); 280 281 VERBOSE(VB_CHANNEL, LOC + "UpdateValues() -- " 282 "Table monitor started"); 283 } 284 285 update_done = true; 286 } -
new file libs/libmythtv/r5000channel.h
- + 1 /** 2 * R5000Channel 3 * Copyright (c) 2008 by Alan Nisota 4 * Copyright (c) 2005 by Jim Westfall and Dave Abrahams 5 * Distributed as part of MythTV under GPL v2 and later. 6 */ 7 8 #ifndef _R5000CHANNEL_H_ 9 #define _R5000CHANNEL_H_ 10 11 #include "tv_rec.h" 12 #include "dtvchannel.h" 13 #include "r5000device.h" 14 15 class R5000Channel : public DTVChannel 16 { 17 public: 18 R5000Channel(TVRec *parent, const QString &videodevice, 19 const QString &_r5ktype); 20 ~R5000Channel() { Close(); } 21 22 // Commands 23 virtual bool Open(void); 24 virtual void Close(void); 25 26 virtual bool TuneMultiplex(uint /*mplexid*/, QString /*inputname*/) 27 { return false; } 28 virtual bool Tune(const DTVMultiplex &/*tuning*/, QString /*inputname*/) 29 { return false; } 30 virtual bool Retune(void); 31 32 // Sets 33 virtual bool SetChannelByString(const QString &chan); 34 virtual bool SetChannelByNumber(const QString &channel, int mpeg_prog); 35 virtual bool SetPowerState(bool on); 36 37 // Gets 38 virtual bool IsOpen(void) const { return isopen; } 39 virtual R5000Device::PowerState GetPowerState(void) const; 40 virtual QString GetDevice(void) const; 41 virtual R5000Device *GetR5000Device(void) { return device; } 42 43 protected: 44 QString videodevice; 45 FireWireDBOptions fw_opts; 46 R5000Device *device; 47 QString current_channel; 48 uint current_mpeg_prog; 49 bool isopen; 50 }; 51 52 #endif // _FIREWIRECHANNEL_H_ -
new file libs/libmythtv/r5000device.h
- + 1 /** 2 * R5000Device 3 * Copyright (c) 2005 by Jim Westfall 4 * Distributed as part of MythTV under GPL v2 and later. 5 */ 6 7 #ifndef _R5000_DEVICE_H_ 8 #define _R5000_DEVICE_H_ 9 10 // C++ headers 11 #include <vector> 12 using namespace std; 13 14 // Qt headers 15 #include <qstring.h> 16 #include <qmutex.h> 17 18 // MythTV headers 19 #include "streamlisteners.h" 20 21 extern "C" { 22 #include "r5000/r5000.h" 23 } 24 25 class TSPacket; 26 class R5kPriv; 27 class R5000Device 28 { 29 public: 30 31 // Public enums 32 typedef enum 33 { 34 kAVCPowerOn, 35 kAVCPowerOff, 36 kAVCPowerUnknown, 37 kAVCPowerQueryFailed, 38 } PowerState; 39 40 41 // AVC param 0 42 typedef enum 43 { 44 kAVCPowerStateOn = 0x70, 45 kAVCPowerStateOff = 0x60, 46 kAVCPowerStateQuery = 0x7f, 47 } IEEE1394UnitPowerParam0; 48 49 R5000Device(int type, QString serial); 50 ~R5000Device(); 51 52 bool OpenPort(void); 53 bool ClosePort(void); 54 void RunPortHandler(void); 55 56 // Commands 57 virtual bool ResetBus(void) { return false; } 58 59 virtual void AddListener(TSDataListener*); 60 virtual void RemoveListener(TSDataListener*); 61 62 // Sets 63 virtual bool SetPowerState(bool on); 64 virtual bool SetChannel(const QString &panel_model, 65 const QString &channel, uint mpeg_prog); 66 67 // Gets 68 bool IsSTBBufferCleared(void) const { return m_buffer_cleared; } 69 70 // non-const Gets 71 virtual PowerState GetPowerState(void); 72 73 // Statics 74 static bool IsSTBSupported(const QString &model); 75 static QString GetModelName(uint vendorid, uint modelid); 76 static QStringList GetSTBList(void); 77 static int GetDeviceType(const QString &r5ktype); 78 void BroadcastToListeners( 79 const unsigned char *data, uint dataSize); 80 81 protected: 82 83 bool GetSubunitInfo(uint8_t table[32]); 84 85 void SetLastChannel(const QString &channel); 86 void ProcessPATPacket(const TSPacket&); 87 bool StartStreaming(void); 88 bool StopStreaming(void); 89 90 int m_type; 91 QString m_serial; 92 uint m_subunitid; 93 uint m_speed; 94 QString m_last_channel; 95 uint m_last_crc; 96 bool m_buffer_cleared; 97 98 uint m_open_port_cnt; 99 vector<TSDataListener*> m_listeners; 100 mutable QMutex m_lock; 101 102 /// Vendor ID + Model ID to R5000Device STB model string 103 static QMap<uint64_t,QString> s_id_to_model; 104 static QMutex s_static_lock; 105 private: 106 r5kdev_t *usbdev; 107 R5kPriv *m_priv; 108 }; 109 110 #endif // _FIREWIRE_DEVICE_H_ -
new file libs/libmythtv/r5000recorder.h
- + 1 /** 2 * R5000Recorder 3 * Copyright (c) 2005 by Jim Westfall 4 * Distributed as part of MythTV under GPL v2 and later. 5 */ 6 7 #ifndef _R5000RECORDER_H_ 8 #define _R5000RECORDER_H_ 9 10 // MythTV headers 11 #include "dtvrecorder.h" 12 #include "tspacket.h" 13 #include "streamlisteners.h" 14 15 class TVRec; 16 class R5000Channel; 17 18 /** \class R5000Recorder 19 * \brief This is a specialization of DTVRecorder used to 20 * handle DVB and ATSC streams from a firewire input. 21 * 22 * \sa DTVRecorder 23 */ 24 class R5000Recorder : public DTVRecorder, 25 public MPEGSingleProgramStreamListener, 26 public TSDataListener 27 { 28 friend class MPEGStreamData; 29 friend class TSPacketProcessor; 30 31 public: 32 R5000Recorder(TVRec *rec, R5000Channel *chan); 33 virtual ~R5000Recorder(); 34 35 // Commands 36 bool Open(void); 37 void Close(void); 38 39 void StartStreaming(void); 40 void StopStreaming(void); 41 42 void StartRecording(void); 43 bool PauseAndWait(int timeout = 100); 44 45 void AddData(const unsigned char *data, uint dataSize); 46 void ProcessTSPacket(const TSPacket &tspacket); 47 48 // Sets 49 void SetOptionsFromProfile(RecordingProfile *profile, 50 const QString &videodev, 51 const QString &audiodev, 52 const QString &vbidev); 53 void SetStreamData(MPEGStreamData*); 54 55 // Gets 56 MPEGStreamData *GetStreamData(void) { return _mpeg_stream_data; } 57 58 // MPEG Single Program 59 void HandleSingleProgramPAT(ProgramAssociationTable*); 60 void HandleSingleProgramPMT(ProgramMapTable*); 61 62 protected: 63 R5000Recorder(TVRec *rec); 64 65 private: 66 MPEGStreamData *_mpeg_stream_data; 67 R5000Channel *channel; 68 bool isopen; 69 vector<unsigned char> buffer; 70 }; 71 72 #endif // _R5000RECORDER_H_ -
new file libs/libmythtv/r5000signalmonitor.h
- + 1 // -*- Mode: c++ -*- 2 3 #ifndef _R5000SIGNALMONITOR_H_ 4 #define _R5000SIGNALMONITOR_H_ 5 6 #include <qmap.h> 7 #include <qmutex.h> 8 #include <qdatetime.h> 9 10 #include "dtvsignalmonitor.h" 11 #include "r5000device.h" 12 #include "util.h" 13 14 class R5000Channel; 15 16 class R5000SignalMonitor : public DTVSignalMonitor, public TSDataListener 17 { 18 public: 19 R5000SignalMonitor(int db_cardnum, R5000Channel *_channel, 20 uint64_t _flags = kFWSigMon_WaitForPower, 21 const char *_name = "R5000SignalMonitor"); 22 23 virtual void HandlePAT(const ProgramAssociationTable*); 24 virtual void HandlePMT(uint, const ProgramMapTable*); 25 26 void Stop(void); 27 28 protected: 29 R5000SignalMonitor(void); 30 R5000SignalMonitor(const R5000SignalMonitor&); 31 virtual ~R5000SignalMonitor(); 32 33 virtual void UpdateValues(void); 34 35 static void *TableMonitorThread(void *param); 36 void RunTableMonitor(void); 37 38 bool SupportsTSMonitoring(void); 39 40 void AddData(const unsigned char *data, uint dataSize); 41 42 public: 43 static const uint kPowerTimeout; 44 static const uint kBufferTimeout; 45 46 protected: 47 bool dtvMonitorRunning; 48 pthread_t table_monitor_thread; 49 bool stb_needs_retune; 50 bool stb_needs_to_wait_for_pat; 51 bool stb_needs_to_wait_for_power; 52 MythTimer stb_wait_for_pat_timer; 53 MythTimer stb_wait_for_power_timer; 54 55 vector<unsigned char> buffer; 56 57 static QMap<void*,uint> pat_keys; 58 static QMutex pat_keys_lock; 59 }; 60 61 #endif // _R5000SIGNALMONITOR_H_ -
new file libs/libmythtv/r5000/libusb_augment.c
- + 1 /* Copyright 2008 Alan Nisota <alannisota@gmail.com> 2 * 2005-10-19/lindi: downloaded from http://www.gaesi.org/~nmct/cvista/cvista/ 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 // libusb_augment.c 19 // $Revision$ 20 // $Date$ 21 22 // Hopefully, the functions in this file will become part of libusb. 23 24 #include <stdio.h> 25 #include <sys/ioctl.h> 26 #include <errno.h> 27 #include <sys/time.h> 28 #include <sys/poll.h> 29 #include <usb.h> 30 #include <linux/usbdevice_fs.h> 31 #include <string.h> 32 #include <signal.h> 33 #define LIBUSB_AUGMENT 34 #include "libusb_augment.h" 35 36 // Taken from libusb file usbi.h because usb.h 37 // hides the definition of usb_dev_handle. 38 extern int usb_debug; 39 40 struct usb_dev_handle { 41 int fd; 42 43 struct usb_bus *bus; 44 struct usb_device *device; 45 46 int config; 47 int interface; 48 int altsetting; 49 50 /* Added by RMT so implementations can store other per-open-device data */ 51 void *impl_info; 52 }; 53 54 // Taken from libusb file error.h to supply error handling macro definition. 55 typedef enum { 56 USB_ERROR_TYPE_NONE = 0, 57 USB_ERROR_TYPE_STRING, 58 USB_ERROR_TYPE_ERRNO, 59 } usb_error_type_t; 60 61 extern char usb_error_str[1024]; 62 extern usb_error_type_t usb_error_type; 63 64 #define USB_ERROR_STR(format, args...) \ 65 do { \ 66 usb_error_type = USB_ERROR_TYPE_STRING; \ 67 snprintf(usb_error_str, sizeof(usb_error_str) - 1, format, ## args); \ 68 if (usb_debug >= 2) \ 69 fprintf(stderr, "USB error: %s\n", usb_error_str); \ 70 } while (0) 71 72 static int urb_signr = 0; 73 void (*urb_completion_callback)(struct usbdevfs_urb *) = NULL; 74 #define USB_ASYNC_COMPLETION_SIGNAL (SIGRTMIN + 5) 75 76 void urb_completion_handler(int signum, siginfo_t *info, void *context) 77 { 78 struct usbdevfs_urb *urb = (struct usbdevfs_urb *)info->si_addr; 79 struct usbdevfs_urb *context1; 80 usb_dev_handle *dev = (usb_dev_handle *)urb->usercontext; 81 int ret; 82 if (info->si_code != SI_ASYNCIO || 83 info->si_signo != USB_ASYNC_COMPLETION_SIGNAL) { 84 return; 85 } 86 if(info->si_errno != 0) { 87 USB_ERROR_STR("Async URB Completion failed: %s", strerror(info->si_errno)); 88 return; 89 } 90 ret = ioctl(dev->fd, USBDEVFS_REAPURB, &context1); 91 if(ret < 0) { 92 USB_ERROR_STR("Failed to read URB: %s", strerror(-ret)); 93 return; 94 } 95 if(context1 != urb) { 96 USB_ERROR_STR("Reaped unexpected urb"); 97 return; 98 } 99 if(urb_completion_callback) 100 urb_completion_callback(urb); 101 } 102 103 int usbdevfs_urb_signal_completion(void (*cb)( struct usbdevfs_urb *)) 104 { 105 urb_completion_callback = cb; 106 urb_signr = USB_ASYNC_COMPLETION_SIGNAL; 107 struct sigaction usb_linux_sa; 108 usb_linux_sa.sa_sigaction = urb_completion_handler; 109 sigfillset(&usb_linux_sa.sa_mask); 110 usb_linux_sa.sa_flags = SA_SIGINFO; 111 usb_linux_sa.sa_flags |= SA_ONSTACK; 112 sigaction(USB_ASYNC_COMPLETION_SIGNAL, &usb_linux_sa, NULL); 113 return 0; 114 } 115 116 struct usbdevfs_urb *usb_bulk_setup( 117 struct usbdevfs_urb *iso_urb, // URB pointer-pointer. 118 unsigned char ep, // Device endpoint. 119 char *bytes, // Data buffer pointer. 120 int size) { // Size of the buffer. 121 struct usbdevfs_urb *local_urb; 122 123 // No more than 16384 bytes can be transferred at a time. 124 if (size > 16384) { 125 USB_ERROR_STR("error on transfer size: %s", strerror(EINVAL)); 126 return NULL; 127 } 128 local_urb = iso_urb; 129 if (!local_urb) { 130 local_urb = (struct usbdevfs_urb *) calloc(1, sizeof(struct usbdevfs_urb)); 131 if (!local_urb) { 132 USB_ERROR_STR("error on packet size: %s", strerror(EINVAL)); 133 return NULL; 134 } 135 } 136 local_urb->type = USBDEVFS_URB_TYPE_BULK; 137 local_urb->endpoint = ep; 138 local_urb->status = 0; 139 local_urb->flags = 0; 140 local_urb->buffer = bytes; 141 local_urb->buffer_length = size; 142 local_urb->actual_length = 0; 143 local_urb->start_frame = 0; 144 local_urb->number_of_packets = 0; 145 local_urb->error_count = 0; 146 local_urb->signr = urb_signr; 147 local_urb->usercontext = (void *) 0; 148 return local_urb; 149 } 150 // Reading and writing are the same except for the endpoint 151 struct usbdevfs_urb *usb_isochronous_setup( 152 struct usbdevfs_urb *iso_urb, // URB pointer-pointer. 153 unsigned char ep, // Device endpoint. 154 int pktsize, // Endpoint packet size. 155 char *bytes, // Data buffer pointer. 156 int size) { // Size of the buffer. 157 struct usbdevfs_urb *local_urb; 158 // int ret 159 // was unused /lindi 160 int pktcount, fullpkts, partpktsize, packets, urb_size; 161 162 // No more than 32768 bytes can be transferred at a time. 163 if (size > 32768) { 164 USB_ERROR_STR("error on transfer size: %s", strerror(EINVAL)); 165 return NULL; 166 } 167 168 // Determine the number of packets that need to be created based upon the 169 // amount of data to be transferred, and the maximum packet size of the 170 // endpoint. 171 172 // Find integral number of full packets. 173 //fprintf(stderr, "buf size: %d\n", size); 174 //fprintf(stderr, "iso size: %d\n", pktsize); 175 fullpkts = size / pktsize; 176 //fprintf(stderr, "Number of full packets: %d\n", fullpkts); 177 // Find length of partial packet. 178 partpktsize = size % pktsize; 179 //fprintf(stderr, "Size of partial packet: %d\n", partpktsize); 180 // Find total number of packets to be transfered. 181 packets = fullpkts + ((partpktsize > 0) ? 1 : 0); 182 //fprintf(stderr, "Total number of packets: %d\n", packets); 183 // Limit the number of packets transfered according to 184 // the Linux usbdevfs maximum read/write buffer size. 185 if ((packets < 1) || (packets > 128)) { 186 USB_ERROR_STR("error on packet size: %s", strerror(EINVAL)); 187 return NULL; 188 } 189 190 // If necessary, allocate the urb and packet 191 // descriptor structures from the heap. 192 local_urb = iso_urb; 193 if (!local_urb) { 194 urb_size = sizeof(struct usbdevfs_urb) + 195 packets * sizeof(struct usb_iso_packet_desc); 196 local_urb = (struct usbdevfs_urb *) calloc(1, urb_size); 197 if (!local_urb) { 198 USB_ERROR_STR("error on packet size: %s", strerror(EINVAL)); 199 return NULL; 200 } 201 } 202 203 // Set up each packet for the data to be transferred. 204 for (pktcount = 0; pktcount < fullpkts; pktcount++) { 205 local_urb->iso_frame_desc[pktcount].length = pktsize; 206 local_urb->iso_frame_desc[pktcount].actual_length = 0; 207 local_urb->iso_frame_desc[pktcount].status = 0; 208 } 209 210 // Set up the last packet for the partial data to be transferred. 211 if (partpktsize > 0) { 212 local_urb->iso_frame_desc[pktcount].length = partpktsize; 213 local_urb->iso_frame_desc[pktcount].actual_length = 0; 214 local_urb->iso_frame_desc[pktcount++].status = 0; 215 } 216 217 // Set up the URB structure. 218 local_urb->type = USBDEVFS_URB_TYPE_ISO; 219 //fprintf(stderr, "type: %d\n", local_urb->type); 220 local_urb->endpoint = ep; 221 //fprintf(stderr, "endpoint: 0x%x\n", local_urb->endpoint); 222 local_urb->status = 0; 223 local_urb->flags = USBDEVFS_URB_ISO_ASAP; // Additional flags here? 224 //fprintf(stderr, "flags: %d\n", local_urb->flags); 225 local_urb->buffer = bytes; 226 //fprintf(stderr, "buffer: 0x%x\n", local_urb->buffer); 227 local_urb->buffer_length = size; 228 //fprintf(stderr, "buffer_length: %d\n", local_urb->buffer_length); 229 local_urb->actual_length = 0; 230 local_urb->start_frame = 0; 231 //fprintf(stderr, "start_frame: %d\n", local_urb->start_frame); 232 local_urb->number_of_packets = pktcount; 233 //fprintf(stderr, "number_of_packets: %d\n", local_urb->number_of_packets); 234 local_urb->error_count = 0; 235 local_urb->signr = 0; 236 //fprintf(stderr, "signr: %d\n", local_urb->signr); 237 local_urb->usercontext = (void *) 0; 238 return local_urb; 239 } 240 241 242 int usb_urb_submit(usb_dev_handle *dev, // Open usb device handle. 243 struct usbdevfs_urb *iso_urb, // Pointer to URB. 244 struct timeval *tv_submit) { // Time structure pointer. 245 int ret; 246 247 iso_urb->usercontext = dev; 248 // Get actual time, of the URB submission. 249 if(tv_submit) 250 gettimeofday(tv_submit, NULL); 251 // Submit the URB through an IOCTL call. 252 ret = ioctl(dev->fd, USBDEVFS_SUBMITURB, iso_urb); 253 //fprintf(stderr, "start_frame now: %d\n", iso_urb->start_frame); 254 //fprintf(stderr, "submit ioctl return value: %d\n", ret); 255 if (ret < 0) { 256 //fprintf(stderr, "error submitting URB: %s\n", strerror(errno)); 257 USB_ERROR_STR("error submitting URB: %s", strerror(errno)); 258 return -errno; 259 } 260 return ret; 261 } 262 263 264 int usb_urb_reap(usb_dev_handle *dev, // Open usb device handle. 265 struct usbdevfs_urb *iso_urb, // Pointer to URB. 266 int timeout) { // Attempt timeout (usec). 267 void *context = NULL; 268 int ret; 269 struct pollfd ufd[1]; 270 271 // Get actual time, and add the timeout value. The result is the absolute 272 // time where we have to quit waiting for an isochronous message. 273 ufd[0].fd = dev->fd; 274 ufd[0].events = POLLIN | POLLOUT; 275 ufd[0].revents = 0; 276 ret = poll(ufd, 1, timeout); 277 if(ret <= 0) 278 return -ETIMEDOUT; 279 280 //fprintf(stderr, "preparing to reap\n"); 281 ret = ioctl(dev->fd, USBDEVFS_REAPURB, &context); 282 283 /* 284 * If there was an error, that wasn"t EAGAIN (no completion), then 285 * something happened during the reaping and we should return that 286 * error now 287 */ 288 //fprintf(stderr, "reap ioctl return value: %d\n", ret); 289 if (ret < 0) { 290 USB_ERROR_STR("error reaping interrupt URB: %s", 291 strerror(errno)); 292 return -errno; 293 } 294 295 //fprintf(stderr, "actual_length: %d\n", iso_urb->actual_length); 296 //fprintf(stderr, "URB status: %d\n", iso_urb->status); 297 //fprintf(stderr, "error count: %d\n", iso_urb->error_count); 298 299 //fprintf(stderr, "waiting done\n"); 300 if(context != NULL && iso_urb != context) { 301 fprintf(stderr, "Expected urb: %p but got %p\n", iso_urb, context); 302 return -1; 303 } 304 //fprintf(stderr, "Total bytes: %d\n", bytesdone); 305 return iso_urb->actual_length; 306 } 307 308 int usb_urb_cancel(usb_dev_handle *dev, struct usbdevfs_urb *iso_urb) 309 { 310 return ioctl(dev->fd, USBDEVFS_DISCARDURB, iso_urb); 311 } -
new file libs/libmythtv/r5000/libusb_augment.h
- + 1 /* Copyright 2008 Alan Nisota <alannisota@gmail.com> 2 * 2005-10-19/lindi: downloaded from http://www.gaesi.org/~nmct/cvista/cvista/ 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #ifdef LIBUSB_AUGMENT 19 // Taken from libusb file linux.h to provide the URB structure definitions. 20 struct usb_iso_packet_desc { 21 unsigned int length; 22 unsigned int actual_length; 23 unsigned int status; 24 }; 25 #endif 26 27 int usbdevfs_urb_signal_completion(void (*cb)( struct usbdevfs_urb *)); 28 struct usbdevfs_urb *usb_bulk_setup(struct usbdevfs_urb *iso_urb, unsigned char ep, 29 char *bytes, int size); 30 struct usbdevfs_urb *usb_isochronous_setup(struct usbdevfs_urb *iso_urb, 31 unsigned char ep, int pktsize, char *bytes, int size); 32 int usb_urb_submit(usb_dev_handle *dev, struct usbdevfs_urb *iso_urb, 33 struct timeval *tv_rsubmit); 34 int usb_urb_reap(usb_dev_handle *dev, struct usbdevfs_urb *iso_urb, 35 int timeout_usec); 36 int usb_urb_cancel(usb_dev_handle *dev, struct usbdevfs_urb *iso_urb); -
new file libs/libmythtv/r5000/r5000.c
- + 1 /* Copyright 2008 Alan Nisota <alannisota@gmail.com> 2 * 3 * This library is free software; you can redistribute it and/or 4 * modify it under the terms of the GNU Lesser General Public 5 * License as published by the Free Software Foundation; either 6 * version 2.1 of the License, or (at your option) any later version. 7 * 8 * This library is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * Lesser General Public License for more details. 12 * 13 * You should have received a copy of the GNU Lesser General Public 14 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 17 #include <stdio.h> 18 #include <sys/types.h> 19 #include <sys/stat.h> 20 #include <fcntl.h> 21 #include <string.h> 22 #include <errno.h> 23 #include <stdarg.h> 24 25 #ifdef R5K_DEBUG 26 char strmfile[256] = "/tmp/strm"; 27 int fd = -1; 28 #endif 29 30 #ifdef R5K_RAWUSB 31 int usbfd = -1; 32 #endif 33 #include "r5000_internal.h" 34 #include "r5000init.h" 35 36 #define R5K_WARM_VID 0x0547 37 #define R5K_WARM_PID 0x1002 38 39 #define MAX_URBS_IN_FLIGHT 128 40 41 #ifndef USE_ISOCHRONOUS 42 //BULK 43 #define R5K_URB_BUFFER_SIZE (1 << 14) 44 #else 45 //ISOCHRONOUS 46 #define LIBUSB_AUGMENT 47 #define R5K_URB_BUFFER_SIZE (1 << 15) 48 #endif 49 #include "libusb_augment.h" 50 51 static int r5000_usb_init = 0; 52 static struct { 53 unsigned char serial[R5K_MAX_DEVS][8]; 54 struct usb_device *dev[R5K_MAX_DEVS]; 55 int count; 56 } r5000_dev_map; 57 58 static void (*msgcb)(char *msg); 59 60 enum { 61 R5K_PMT_START = 0x01, 62 R5K_PMT_READY = 0x02 63 }; 64 65 void r5000_print(const char *fmt, ...) 66 { 67 va_list args; 68 char logmsg[1024]; 69 va_start(args,fmt); 70 vsnprintf(logmsg,sizeof(logmsg),fmt,args); 71 va_end(args); 72 if(msgcb) { 73 //msgcb routine must ensure thread safeness 74 msgcb(logmsg); 75 } else { 76 fprintf(stderr, logmsg); 77 } 78 } 79 80 int r5000_create_urbs(r5kdev_t *r5kdev) 81 { 82 int i, urbsize; 83 #ifndef USE_ISOCHRONOUS 84 urbsize = sizeof(struct usbdevfs_urb); 85 #else 86 urbsize = sizeof(struct usbdevfs_urb) + sizeof(struct usb_iso_packet_desc) * R5K_URB_BUFFER_SIZE / 1024; 87 #endif 88 89 r5kdev->buffer = malloc(R5K_URB_BUFFER_SIZE * MAX_URBS_IN_FLIGHT); 90 r5kdev->urbs = (struct usbdevfs_urb **)malloc(sizeof(struct usbdevfs_urb *) * MAX_URBS_IN_FLIGHT); 91 r5kdev->urbblk = (void *)malloc(urbsize * MAX_URBS_IN_FLIGHT); 92 for(i = 0; i < MAX_URBS_IN_FLIGHT; i++) { 93 r5kdev->urbs[i] = (struct usbdevfs_urb *)((unsigned long)r5kdev->urbblk + (urbsize * i)); 94 #ifndef USE_ISOCHRONOUS 95 usb_bulk_setup(r5kdev->urbs[i], 0x82, r5kdev->buffer + (R5K_URB_BUFFER_SIZE*i), R5K_URB_BUFFER_SIZE); 96 #else 97 usb_isochronous_setup(r5kdev->urbs[i], 0x82, 1024, r5kdev->buffer + (R5K_URB_BUFFER_SIZE*i), R5K_URB_BUFFER_SIZE); 98 #endif 99 } 100 r5kdev->nexturb = 0; 101 return 1; 102 } 103 104 int r5000_free_urbs(r5kdev_t *r5kdev) 105 { 106 free(r5kdev->urbblk); 107 free(r5kdev->urbs); 108 free(r5kdev->buffer); 109 return 0; 110 } 111 112 usb_dev_handle *r5000_locate_device( 113 unsigned short vendor_id, unsigned short product_id, int skip) 114 { 115 struct usb_bus *bus; 116 struct usb_device *dev; 117 usb_dev_handle *device_handle = 0; 118 usb_find_busses(); 119 usb_find_devices(); 120 121 for (bus = usb_get_busses(); bus && !device_handle; bus = bus->next) 122 { 123 for (dev = bus->devices; dev && !device_handle; dev = dev->next) 124 { 125 if (dev->descriptor.idVendor == vendor_id && 126 dev->descriptor.idProduct == product_id) 127 { 128 device_handle = usb_open(dev); 129 if(device_handle && skip) { 130 usb_close(device_handle); 131 device_handle = NULL; 132 skip--; 133 } 134 } 135 } 136 } 137 138 if (device_handle) { 139 int open_status = usb_set_configuration(device_handle,1); 140 141 open_status = usb_claim_interface(device_handle,0); 142 143 open_status = usb_set_altinterface(device_handle,0); 144 } 145 return (device_handle); 146 } 147 148 int r5000_dev_init(r5kdev_t *r5kdev) { 149 int i, bytes; 150 unsigned char *ptr, *serial = r5kdev->serial; 151 unsigned char datain[0x80]; 152 bytes = usb_bulk_read(r5kdev->handle, 129, datain, sizeof(datain), 5000); 153 for(i = 0; i < R5K_INIT_SERIAL; i++) { 154 //PRINTHEX("Write:\n", r5kinit[i].data, r5kinit[i].wlen); 155 if(r5kinit[i].wsleep) usleep(r5kinit[i].wsleep); 156 usb_bulk_write(r5kdev->handle, 1, r5kinit[i].data, r5kinit[i].wlen, 5000); 157 if(r5kinit[i].rsleep) usleep(r5kinit[i].rsleep); 158 bytes = usb_bulk_read(r5kdev->handle, 129, datain, sizeof(datain), 5000); 159 //PRINTHEX("Read:\n", datain, bytes); 160 if(r5kinit[i].rlen > 0 && bytes != r5kinit[i].rlen) { 161 r5000_print("R5000 initialization failed at stage %d:\n\tExpected %d bytes, but got %d bytes\n", i, r5kinit[i].rlen, bytes); 162 return 0; 163 } 164 } 165 166 //last read is serial # 167 if (datain[0] != 0x08) { 168 r5000_print("R5000 initialization failed reading serial #\n"); 169 return 0; 170 } 171 for(ptr = datain + 6; ptr < datain + 13; ptr++) { 172 *serial++ = ( *ptr >= '0' && *ptr <= 'z' ) ? *ptr : '*'; 173 } 174 *serial = 0; 175 176 //complete initialization now 177 for(; i < R5K_INIT_MAX; i++) { 178 //PRINTHEX("Write:\n", r5kinit[i].data, r5kinit[i].wlen); 179 if(r5kinit[i].wsleep) usleep(r5kinit[i].wsleep); 180 usb_bulk_write(r5kdev->handle, 1, r5kinit[i].data, r5kinit[i].wlen, 5000); 181 if(r5kinit[i].rsleep) usleep(r5kinit[i].rsleep); 182 bytes = usb_bulk_read(r5kdev->handle, 129, datain, sizeof(datain), 5000); 183 //PRINTHEX("Read:\n", datain, bytes); 184 if(r5kinit[i].rlen > 0 && bytes != r5kinit[i].rlen) { 185 r5000_print("R5000 initialization failed at stage %d:\n\tExpected %d bytes, but got %d bytes\n", i, r5kinit[i].rlen, bytes); 186 return 0; 187 } 188 } 189 return 1; 190 } 191 192 int r5000_start_stream(r5kdev_t *r5kdev) 193 { 194 unsigned char data[0x80]; 195 int bytes; 196 int i; 197 struct usb_dev_handle *handle = (struct usb_dev_handle *)r5kdev->handle; 198 199 if(! r5kdev->urbs) 200 r5000_create_urbs(r5kdev); 201 202 data[0] = 0x30; 203 usb_bulk_write(handle, 1, data, 1, 5000); 204 bytes = usb_bulk_read(handle, 129, data, 2, 5000); 205 206 //0x50 sets byte mode. Use '0x60' to set word mode 207 data[0] = r5kdev->read_words ? 0x60: 0x50; 208 usb_bulk_write(handle, 1, data, 1, 5000); 209 210 for(i=0; i < MAX_URBS_IN_FLIGHT; i++) { 211 usb_urb_submit(handle, r5kdev->urbs[i], NULL); 212 } 213 r5kdev->nexturb = 0; 214 r5kdev->streaming = 1; 215 if(r5kdev->start_stream) 216 r5kdev->start_stream(r5kdev); 217 return 1; 218 } 219 220 int r5000_stop_stream(r5kdev_t *r5kdev) 221 { 222 struct usb_dev_handle *handle = (struct usb_dev_handle *)r5kdev->handle; 223 struct usbdevfs_urb **urbs = r5kdev->urbs; 224 int i; 225 226 if(r5kdev->streaming) { 227 for(i=0; i < MAX_URBS_IN_FLIGHT; i++) 228 usb_urb_cancel(handle, urbs[i]); 229 r5kdev->streaming = 0; 230 } 231 return 1; 232 } 233 234 /* r5000_init must be called from a thread-safe context */ 235 int r5000_init(void (*_msgcb)(char *str)) 236 { 237 int bus_count, dev_count; 238 r5kdev_t r5kd; 239 int count = 0; 240 241 msgcb = _msgcb; 242 243 if(r5000_usb_init) 244 return 1; 245 usb_init(); 246 bus_count = usb_find_busses(); 247 dev_count = usb_find_devices(); 248 if(bus_count == 0 || dev_count ==0) { 249 r5000_print("R5000 failed to locate any USB devices. Are you sure you have permissions set properly?\n"); 250 return 0; 251 } 252 while(r5000_dev_map.count < R5K_MAX_DEVS) { 253 r5kd.handle = r5000_locate_device(R5K_WARM_VID, R5K_WARM_PID, count); 254 if(! r5kd.handle) 255 break; 256 if (r5000_dev_init(&r5kd)) { 257 memcpy(r5000_dev_map.serial[r5000_dev_map.count], r5kd.serial, 8); 258 r5000_dev_map.dev[r5000_dev_map.count] = usb_device(r5kd.handle); 259 r5000_dev_map.count++; 260 } 261 count++; 262 usb_close(r5kd.handle); 263 } 264 if(! r5000_dev_map.count) { 265 r5000_print("R5000 failed to locate any R5000 devices. Are you sure you have permissions set properly?\n"); 266 return 0; 267 } 268 r5000_usb_init = 1; 269 return 1; 270 } 271 272 r5kdev_t *r5000_open(r5ktype_t type, 273 unsigned int (*cb)(unsigned char *buffer, int len, void *callback_data), 274 void *cb_data, 275 const char *serial) 276 { 277 r5kdev_t *r5kdev, r5kd; 278 int count = 0; 279 memset(&r5kd, 0, sizeof(r5kdev_t)); 280 281 if(! r5000_usb_init) { 282 r5000_print("R5000 was not initialized before r5000_open(). Please call r5000_init() first\n"); 283 return NULL; 284 } 285 for(count = 0; count < r5000_dev_map.count; count++) { 286 if(! serial || memcmp(r5000_dev_map.serial[count], serial, 8) == 0) { 287 r5kd.handle = usb_open(r5000_dev_map.dev[count]); 288 if(! r5kd.handle) 289 return NULL; 290 usb_set_configuration(r5kd.handle,1); 291 usb_claim_interface(r5kd.handle,0); 292 usb_set_altinterface(r5kd.handle,0); 293 if(! r5000_dev_init(&r5kd)) { 294 usb_close(r5kd.handle); 295 return NULL; 296 } 297 break; 298 } 299 } 300 if(count == r5000_dev_map.count) { 301 //We can't get here unless a serial was specified 302 r5000_print("Could not locate R5000 device with serial '%s'\n", serial); 303 return NULL; 304 } 305 #ifdef R5K_DEBUG 306 fd = open(strmfile, O_RDONLY); 307 #endif 308 #ifdef R5K_RAWUSB 309 usbfd = open("raw.av", O_WRONLY | O_CREAT | O_TRUNC, 0666); 310 #endif 311 r5kdev = (r5kdev_t *)malloc(sizeof(r5kdev_t)); 312 *r5kdev = r5kd; 313 r5kdev->urbs = NULL; 314 r5kdev->cb = cb; 315 r5kdev->cb_data = cb_data; 316 r5kdev->stb_type = type; 317 switch(type) { 318 case R5K_STB_VIP211: 319 case R5K_STB_VIP622: 320 vip_init(r5kdev); 321 break; 322 case R5K_STB_DIRECTV: 323 directv_init(r5kdev); 324 break; 325 case R5K_STB_DSR: 326 case R5K_STB_HDD: 327 sat_init(r5kdev); 328 break; 329 default: 330 r5000_print("Unknown STB type %d specified.\n", type); 331 r5kdev->stb_type = R5K_STB_VIP211; 332 vip_init(r5kdev); 333 break; 334 } 335 return r5kdev; 336 } 337 338 int r5000_close(r5kdev_t *r5kdev) 339 { 340 if(! r5kdev) 341 return 1; 342 if(r5kdev->urbs) { 343 if(r5kdev->streaming) 344 r5000_stop_stream(r5kdev); 345 r5000_free_urbs(r5kdev); 346 } 347 usb_close(r5kdev->handle); 348 #ifdef R5K_RAWUSB 349 if(usbfd >= 0) close(usbfd); 350 #endif 351 switch(r5kdev->stb_type) { 352 case R5K_STB_VIP211: 353 case R5K_STB_VIP622: 354 vip_free(r5kdev); 355 break; 356 case R5K_STB_DIRECTV: 357 directv_free(r5kdev); 358 break; 359 case R5K_STB_DSR: 360 case R5K_STB_HDD: 361 sat_free(r5kdev); 362 break; 363 } 364 free(r5kdev); 365 return 1; 366 } 367 368 int r5000_loop_iterate(r5kdev_t *r5kdev, int timeout_usec) 369 { 370 struct usb_dev_handle *handle = (struct usb_dev_handle *)r5kdev->handle; 371 struct usbdevfs_urb **urbs = r5kdev->urbs; 372 int len; 373 unsigned char *buf; 374 if(! r5kdev->streaming) 375 return -1; 376 len = usb_urb_reap(handle, urbs[r5kdev->nexturb], timeout_usec); 377 if(len <= 0) { 378 if(len != -ETIMEDOUT) 379 r5000_print("(%d) Reap failed at %08x: %s\n", r5kdev->nexturb, r5kdev->bytes_read, strerror(errno)); 380 return len; 381 } 382 buf = r5kdev->buffer + (R5K_URB_BUFFER_SIZE*r5kdev->nexturb); 383 #ifdef R5K_RAWUSB 384 if(usbfd >= 0) write(usbfd, buf, len); 385 #endif 386 #ifdef R5K_DEBUG 387 if(fd >= 0) 388 len = read(fd, buf, len); 389 if(len == 0) 390 r5000_print("hit end of debug file\n"); 391 #endif 392 r5kdev->process_block(r5kdev, buf, len); 393 r5kdev->bytes_read += len; 394 usb_urb_submit(handle, urbs[r5kdev->nexturb], NULL); 395 r5kdev->nexturb = (r5kdev->nexturb + 1) % MAX_URBS_IN_FLIGHT; 396 return 0; 397 } 398 399 //use this to read a status frame. It doesn't do anything special 400 //but makes it obvious what data is expected 401 int r5000_read_status(r5kdev_t *r5kdev, unsigned char *buf) 402 { 403 return usb_bulk_read(r5kdev->handle, 129, buf, 128, 5000); 404 } 405 406 int r5000_get_power_state(r5kdev_t *r5kdev) 407 { 408 unsigned char data1[1] = { 0x30 }; 409 unsigned char data2[0x80]; 410 int count = 10; 411 while(count--) { 412 r5000_read_status(r5kdev, data2); 413 usb_bulk_write(r5kdev->handle, 1, data1, 1, 5000); 414 usleep(100000); 415 if(usb_bulk_read(r5kdev->handle, 1, data2, 2, 5000) == 2 && 416 data2[0] == 0x0a && (data2[1] & 0x4e) == 0x4c) { 417 // The following boxes are known to be power active low: 418 // 4DTV 922, Dish 622/722, Bell 9242, D* 419 if(r5kdev->power_active_low) 420 return (!(data2[1] == 0x4d)); 421 else 422 return (!!(data2[1] == 0x4d)); 423 } 424 usleep(100000); 425 } 426 r5000_print("R5000 failed to read power state. Assuming ON state\n"); 427 return 1; 428 } 429 430 int r5000_send_pwr_cmd(r5kdev_t *r5kdev, unsigned char *data) 431 { 432 unsigned char data1[1] = { 0x30 }; 433 unsigned char data3[0x80]; 434 int len; 435 usb_bulk_write(r5kdev->handle, 1, data1, 1, 5000); 436 usleep(100000); 437 usb_bulk_write(r5kdev->handle, 1, data, r5kdev->button->len, 5000); 438 usleep(100000); 439 len = usb_bulk_read(r5kdev->handle, 1, data3, 2, 5000); 440 usleep(100000); 441 return len; 442 } 443 444 int r5000_wait_pwr(r5kdev_t *r5kdev, int on_off) 445 { 446 int new_state, count = 20; 447 while(count-- && (new_state = r5000_get_power_state(r5kdev)) != on_off) 448 usleep(100000); 449 //r5000_print("End state: %s\n", !on_off ? "On" : "Off"); 450 return new_state; 451 } 452 453 int r5000_toggle_on_off(r5kdev_t *r5kdev) 454 { 455 unsigned on_off; 456 on_off = r5000_get_power_state(r5kdev); 457 if(! r5kdev->button) { 458 r5000_print("No button IR commands defined for this device!\n"); 459 return on_off; 460 } 461 //r5000_print("Start state: %s\n", on_off ? "On" : "Off"); 462 r5000_send_pwr_cmd(r5kdev, r5kdev->button->power); 463 on_off = r5000_wait_pwr(r5kdev, ! on_off); 464 //r5000_print("End state: %s\n", on_off ? "On" : "Off"); 465 return on_off; 466 } 467 468 int r5000_power_on_off(r5kdev_t *r5kdev, int turn_on) 469 { 470 unsigned char *pwr_command; 471 int on_off = r5000_get_power_state(r5kdev); 472 if(on_off == turn_on) { 473 return on_off; 474 } 475 if(! r5kdev->button) { 476 r5000_print("No button IR commands defined for this device!\n"); 477 return on_off; 478 } 479 if(r5kdev->discrete_power) { 480 //r5000_print("Using discrete power commands\n"); 481 if(turn_on) { 482 pwr_command = r5kdev->button->power_on; 483 } else { 484 pwr_command = r5kdev->button->power_off; 485 } 486 } else { 487 pwr_command = r5kdev->button->power; 488 } 489 r5000_send_pwr_cmd(r5kdev, pwr_command); 490 return r5000_wait_pwr(r5kdev, turn_on); 491 } 492 493 int r5000_change_channel(r5kdev_t *r5kdev, const char *chan, int mpeg_prog) 494 { 495 unsigned char data2[0x80]; 496 unsigned char *ptr = NULL; 497 const char *p; 498 if(! r5kdev) 499 return 0; 500 if (chan) { 501 if(! r5kdev->button) { 502 r5000_print("No button IR commands defined for this device!\n"); 503 } else { 504 r5000_read_status(r5kdev, data2); 505 usb_bulk_write(r5kdev->handle, 1, r5kdev->button->clear, r5kdev->button->len, 5000); 506 usleep(r5kdev->button->delay); 507 for(p = chan; *p; p++) { 508 switch(*p) { 509 case '0' : ptr = r5kdev->button->b0; break; 510 case '1' : ptr = r5kdev->button->b1; break; 511 case '2' : ptr = r5kdev->button->b2; break; 512 case '3' : ptr = r5kdev->button->b3; break; 513 case '4' : ptr = r5kdev->button->b4; break; 514 case '5' : ptr = r5kdev->button->b5; break; 515 case '6' : ptr = r5kdev->button->b6; break; 516 case '7' : ptr = r5kdev->button->b7; break; 517 case '8' : ptr = r5kdev->button->b8; break; 518 case '9' : ptr = r5kdev->button->b9; break; 519 } 520 if(ptr) { 521 usb_bulk_write(r5kdev->handle, 1, ptr, r5kdev->button->len, 5000); 522 usleep(r5kdev->button->delay); 523 } 524 } 525 usb_bulk_write(r5kdev->handle, 1, r5kdev->button->enter, r5kdev->button->len, 5000); 526 } 527 } 528 r5kdev->channel = mpeg_prog; 529 if(r5kdev->change_channel) 530 r5kdev->change_channel(r5kdev); 531 return 1; 532 } 533 534 int r5000_find_stbs(r5kenum_t *devs) 535 { 536 devs->count = 0; 537 if(! r5000_usb_init) { 538 r5000_print("R5000 was not initialized before r5000_find_stbs(). Please call r5000_init() first\n"); 539 return 0; 540 } 541 devs->count = r5000_dev_map.count; 542 memcpy(devs->serial, r5000_dev_map.serial, 8 * r5000_dev_map.count); 543 return 1; 544 } -
new file libs/libmythtv/r5000/r5000.h
- + 1 /* Copyright 2008 Alan Nisota <alannisota@gmail.com> 2 * 3 * This library is free software; you can redistribute it and/or 4 * modify it under the terms of the GNU Lesser General Public 5 * License as published by the Free Software Foundation; either 6 * version 2.1 of the License, or (at your option) any later version. 7 * 8 * This library is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * Lesser General Public License for more details. 12 * 13 * You should have received a copy of the GNU Lesser General Public 14 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 17 #ifndef R5000_H 18 #define R5000_H 19 20 #ifndef r5kdev_t 21 #define r5kdev_t void 22 #endif 23 24 #define R5K_MAX_DEVS 10 25 typedef struct { 26 unsigned char serial[R5K_MAX_DEVS][8]; 27 int count; 28 } r5kenum_t; 29 30 typedef enum { 31 R5K_STB_VIP211 = 0, 32 R5K_STB_DIRECTV, 33 R5K_STB_HDD, 34 R5K_STB_DSR, 35 R5K_STB_VIP622, 36 R5K_STB_MAX, 37 } r5ktype_t; 38 39 extern int r5000_init(void (*_msgcb)(char *str)); 40 extern r5kdev_t *r5000_open(r5ktype_t type, unsigned int (*cb)(unsigned char *buffer, int len, void *callback_data), void *cb_data, const char *serial); 41 extern int r5000_close(r5kdev_t *r5kdev); 42 extern int r5000_start_stream(r5kdev_t *r5kdev); 43 extern int r5000_stop_stream(r5kdev_t *r5kdev); 44 extern int r5000_loop_iterate(r5kdev_t *r5kdev, int timeout_usec); 45 extern int r5000_get_power_state(r5kdev_t *r5kdev); 46 extern int r5000_toggle_on_off(r5kdev_t *r5kdev); 47 extern int r5000_power_on_off(r5kdev_t *r5kdev, int turn_on); 48 extern int r5000_change_channel(r5kdev_t *r5kdev, const char *chan, int mpeg_prog); 49 extern int r5000_find_stbs(r5kenum_t *devs); 50 #endif //R5000_H -
new file libs/libmythtv/r5000/r5000_internal.h
- + 1 /* Copyright 2008 Alan Nisota <alannisota@gmail.com> 2 * 3 * This library is free software; you can redistribute it and/or 4 * modify it under the terms of the GNU Lesser General Public 5 * License as published by the Free Software Foundation; either 6 * version 2.1 of the License, or (at your option) any later version. 7 * 8 * This library is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * Lesser General Public License for more details. 12 * 13 * You should have received a copy of the GNU Lesser General Public 14 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 17 #ifndef R5000_INT_H 18 #define R5000_INT_H 19 20 #include <usb.h> 21 #include <linux/usbdevice_fs.h> 22 23 #define PRINTHEX(str, data, len) if(1) do { \ 24 int _i; \ 25 fprintf(stderr, str); \ 26 for(_i = 0; _i < (len); _i++) { \ 27 fprintf(stderr, "%02x ", (data)[_i]); \ 28 if((_i % 16) == 15) fprintf(stderr, "\n"); \ 29 } \ 30 if(_i % 16) fprintf(stderr, "\n"); \ 31 } while(0) 32 33 #define R5K_MAX_BUTTON_SIZE 0x80 34 #define R5K_MAX_PIDS 10 35 #define IS_VIDEO(x) ((x) == 0x02 || (x) == 0x1b || (x) == 0x80) 36 37 struct r5k_descriptor { 38 unsigned char d[10]; 39 }; 40 41 struct r5k_epid { 42 int pid; 43 unsigned char id; 44 struct r5k_descriptor desc; 45 }; 46 47 struct r5000_buttons { 48 int len; 49 int delay; 50 unsigned char b0[R5K_MAX_BUTTON_SIZE]; 51 unsigned char b1[R5K_MAX_BUTTON_SIZE]; 52 unsigned char b2[R5K_MAX_BUTTON_SIZE]; 53 unsigned char b3[R5K_MAX_BUTTON_SIZE]; 54 unsigned char b4[R5K_MAX_BUTTON_SIZE]; 55 unsigned char b5[R5K_MAX_BUTTON_SIZE]; 56 unsigned char b6[R5K_MAX_BUTTON_SIZE]; 57 unsigned char b7[R5K_MAX_BUTTON_SIZE]; 58 unsigned char b8[R5K_MAX_BUTTON_SIZE]; 59 unsigned char b9[R5K_MAX_BUTTON_SIZE]; 60 unsigned char clear[R5K_MAX_BUTTON_SIZE]; 61 unsigned char enter[R5K_MAX_BUTTON_SIZE]; 62 unsigned char power[R5K_MAX_BUTTON_SIZE]; 63 unsigned char power_on[R5K_MAX_BUTTON_SIZE]; 64 unsigned char power_off[R5K_MAX_BUTTON_SIZE]; 65 }; 66 67 struct r5kdev { 68 usb_dev_handle *handle; 69 unsigned char serial[8]; 70 void *urbblk; 71 struct usbdevfs_urb **urbs; 72 unsigned char *buffer; 73 int stb_type; 74 int read_words; 75 void (*process_block)(struct r5kdev *r5kdev, unsigned char *buf, int len); 76 void (*start_stream)(struct r5kdev *r5kdev); 77 void (*change_channel)(struct r5kdev *r5kdev); 78 void *stbdata; 79 unsigned int (*cb)(unsigned char *buffer, int len, void *callback_data); 80 void *cb_data; 81 int nexturb; 82 int streaming; 83 int bytes_read; 84 struct r5000_buttons *button; 85 int power_active_low; 86 int discrete_power; 87 int channel; 88 unsigned char pmt_pkt[188]; 89 unsigned char num_pmt_entries; 90 unsigned char pmt_state; 91 unsigned char pmt_next_cc; 92 unsigned char pmt_version; 93 struct r5k_epid pmt[R5K_MAX_PIDS]; 94 } r5kdev_t; 95 #define r5kdev_t struct r5kdev 96 97 #include "r5000.h" 98 99 extern void r5000_print(const char *fmt, ...); 100 extern unsigned char r5000_pat_pkt[188]; 101 extern struct r5k_descriptor r5000_pmt_audio_desc; 102 extern struct r5k_descriptor r5000_pmt_video_desc; 103 extern void r5000_reset_pmt(r5kdev_t *r5kdev); 104 extern void r5000_send_pmt(r5kdev_t *r5kdev); 105 106 //Support for all DirecTV boxes 107 extern void directv_init(r5kdev_t *r5kdev); 108 extern void directv_free(r5kdev_t *r5kdev); 109 110 //Support for ViP series Dish Network boxes 111 extern void vip_init(r5kdev_t *r5kdev); 112 extern void vip_free(r5kdev_t *r5kdev); 113 114 //Support for HDD and DSR series satellite/cable boxes 115 extern void sat_init(r5kdev_t *r5kdev); 116 extern void sat_free(r5kdev_t *r5kdev); 117 118 #endif -
new file libs/libmythtv/r5000/r5k_vip.c
- + 1 /* Copyright 2008 Alan Nisota <alannisota@gmail.com> 2 * 3 * This library is free software; you can redistribute it and/or 4 * modify it under the terms of the GNU Lesser General Public 5 * License as published by the Free Software Foundation; either 6 * version 2.1 of the License, or (at your option) any later version. 7 * 8 * This library is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * Lesser General Public License for more details. 12 * 13 * You should have received a copy of the GNU Lesser General Public 14 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 17 //Support for Dish Network ViP211/ViP422 boxes 18 #include <stdio.h> 19 #include <string.h> 20 #include "r5000_internal.h" 21 #include "r5k_vip_buttons.h" 22 struct r5000_vip { 23 unsigned char leftover[188]; 24 int offset; 25 int pos; 26 }; 27 #define CHECK_CONTINUITY 1 28 #ifdef CHECK_CONTINUITY 29 static unsigned char continuity[0x2000]; 30 #endif 31 void vip_add_pmt(r5kdev_t *r5kdev, int pid, int table_id) 32 { 33 int i; 34 struct r5000_vip *vip = (struct r5000_vip *)r5kdev->stbdata; 35 36 int is_video = IS_VIDEO(table_id); 37 38 for(i = 0; i < r5kdev->num_pmt_entries; i++) { 39 if(r5kdev->pmt[i].pid == pid) { 40 if(r5kdev->pmt[i].id == table_id) 41 return; 42 //different table_id for existing pid. Reset 43 r5000_reset_pmt(r5kdev); 44 break; 45 } 46 if(is_video) { 47 if(IS_VIDEO(r5kdev->pmt[i].id)) { 48 //a video entry already exists. Reset 49 r5000_reset_pmt(r5kdev); 50 break; 51 } 52 } 53 } 54 //Didn't find this PID, add it 55 if(i == R5K_MAX_PIDS) 56 return; 57 r5000_print("Adding %04x: %02x @ %08x\n", pid, table_id, r5kdev->bytes_read + vip->pos); 58 r5kdev->pmt[r5kdev->num_pmt_entries].pid = pid; 59 r5kdev->pmt[r5kdev->num_pmt_entries].id = table_id; 60 r5kdev->pmt[r5kdev->num_pmt_entries].desc = is_video ? r5000_pmt_video_desc : r5000_pmt_audio_desc; 61 r5kdev->num_pmt_entries++; 62 r5kdev->pmt_state |= is_video ? 0x01 : 0x02; 63 } 64 65 void vip_force_pmt(r5kdev_t *r5kdev, unsigned char *buf) 66 { 67 int stream_id, pid, afc, af_size = 0; 68 69 pid = ((buf[1] << 8) | buf[2]) & 0x1fff; 70 if(pid == 0x1fff) 71 return; 72 #ifdef CHECK_CONTINUITY 73 if(pid >= 0x1000) { 74 struct r5000_vip *vip = (struct r5000_vip *)r5kdev->stbdata; 75 unsigned char cont = buf[3] & 0x0f; 76 if(continuity[pid] != cont && (buf[3] & 0x30) != 0x20) { 77 r5000_print("Continuity (0x%04x) %d != %d @%08x\n", 78 pid, cont, continuity[pid], r5kdev->bytes_read + vip->pos); 79 } 80 continuity[pid] = (cont + 1) & 0x0f; 81 } 82 #endif 83 if(pid == 0) { 84 r5kdev->cb(r5000_pat_pkt, 188, r5kdev->cb_data); 85 if(r5kdev->pmt_state == 0x03) 86 r5000_send_pmt(r5kdev); 87 } else { 88 if(pid != 0x21) 89 r5kdev->cb(buf, 188, r5kdev->cb_data); 90 //Only interested in PES packets starting in this TS packet 91 if (!(buf[1] & 0x40)) 92 return; 93 afc = (buf[3]>>4) & 0x03; 94 if(afc == 0x2) 95 return; 96 if(afc == 0x3) 97 af_size = buf[4]+1; 98 if(buf[4+af_size] != 0x00 || buf[5+af_size] != 0x00 || buf[6+af_size] != 0x01) 99 return; 100 //We have a PES packet 101 stream_id = buf[7+af_size]; 102 if((stream_id & 0xf0) == 0xe0) { 103 //Video stream (we need the adaptation field) 104 if(afc != 0x03) 105 return; 106 if(0) { 107 PRINTHEX("data", buf, af_size+8); 108 } 109 if(buf[5] & 0x02) { 110 // Has private data, this is MPEG4 111 vip_add_pmt(r5kdev, pid, 0x1b); 112 } else if(buf[5] & 0x10) { 113 // Has PCR and no private data, this is MPEG2 114 vip_add_pmt(r5kdev, pid, 0x02); 115 } 116 } else if((stream_id & 0xf0) == 0xc0) { 117 //Audio stream 118 vip_add_pmt(r5kdev, pid, 0x04); 119 } else if(stream_id == 0xbd) { 120 //Audio stream 121 vip_add_pmt(r5kdev, pid, 0x81); 122 } 123 } 124 } 125 126 static void vip_process_block(r5kdev_t *r5kdev, unsigned char *buf, int len) 127 { 128 struct r5000_vip *vip = (struct r5000_vip *)r5kdev->stbdata; 129 130 int sync = 1; 131 if(! r5kdev->streaming) 132 return; 133 if(len <= 0) 134 return; 135 136 vip->pos = vip->offset; 137 while(vip->pos < len) { 138 if(buf[vip->pos] != 0x47 || (vip->pos <len-1 && buf[vip->pos+1] == 0xff)) 139 goto nosync; 140 // If we get here, buf[vip->pos] == 0x47 141 if(vip->offset) { 142 //previous data exists and is part of a good packet 143 memcpy(vip->leftover+188-vip->offset, buf, vip->offset); 144 vip_force_pmt(r5kdev, vip->leftover); 145 vip->offset = 0; 146 } 147 if(vip->pos+188 <= len) { 148 //at least one full packet is available 149 if(vip->pos+188 < len && buf[vip->pos+188] != 0x47) 150 goto nosync; 151 } else { 152 //Out of data, but the partial packet may be ok. 153 memcpy(vip->leftover, buf+vip->pos, len-vip->pos); 154 vip->offset = 188-(len-vip->pos); 155 break; 156 } 157 //If we get here, we have a good packet 158 vip_force_pmt(r5kdev, buf+vip->pos); 159 if(! sync) 160 r5000_print("(%d) Found sync @ %08x\n", r5kdev->nexturb, r5kdev->bytes_read+vip->pos); 161 sync = 1; 162 vip->pos+=188; 163 continue; 164 nosync: 165 vip->offset=0; 166 if(sync) 167 r5000_print("(%d)Lost sync @ %08x\n", r5kdev->nexturb, r5kdev->bytes_read+vip->pos); 168 sync = 0; 169 vip->pos++; 170 } 171 } 172 173 static void vip_start_stream(r5kdev_t *r5kdev) 174 { 175 struct r5000_vip *vip = (struct r5000_vip *)r5kdev->stbdata; 176 vip->offset = 0; 177 } 178 179 static void vip_change_channel(r5kdev_t *r5kdev) 180 { 181 r5000_reset_pmt(r5kdev); 182 } 183 184 void vip_init(r5kdev_t *r5kdev) 185 { 186 struct r5000_vip *vip = (struct r5000_vip *)malloc(sizeof(struct r5000_vip)); 187 r5kdev->stbdata = vip; 188 r5kdev->process_block = vip_process_block; 189 r5kdev->start_stream = vip_start_stream; 190 r5kdev->button = &vip_button_cmd; 191 r5kdev->change_channel = &vip_change_channel; 192 r5kdev->discrete_power = 1; 193 if(r5kdev->stb_type == R5K_STB_VIP622) 194 r5kdev->power_active_low = 1; 195 } 196 197 void vip_free(r5kdev_t *r5kdev) 198 { 199 free(r5kdev->stbdata); 200 } 201 -
new file libs/libmythtv/r5000/r5k_directv.c
- + 1 /* Copyright 2008 Alan Nisota <alannisota@gmail.com> 2 * 3 * This library is free software; you can redistribute it and/or 4 * modify it under the terms of the GNU Lesser General Public 5 * License as published by the Free Software Foundation; either 6 * version 2.1 of the License, or (at your option) any later version. 7 * 8 * This library is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * Lesser General Public License for more details. 12 * 13 * You should have received a copy of the GNU Lesser General Public 14 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 17 //Support for DirecTV boxes 18 #include <netinet/in.h> 19 #include <string.h> 20 21 #include "r5000_internal.h" 22 23 #define DTV_VPID 0x1322 24 #define DTV_APID 0x1333 25 #define DTV_PAT_PMT_COUNT 5000 26 27 struct r5000_dtv { 28 unsigned char vbuf[188*2+4]; 29 unsigned char abuf[188*2+6]; 30 unsigned char *video; 31 unsigned char *audio; 32 unsigned int vpos; 33 unsigned int apos; 34 unsigned int vstart; 35 unsigned int astart; 36 unsigned int video_cc; 37 unsigned int audio_cc; 38 unsigned int vstate; 39 unsigned int pic_pos; 40 int alen; 41 unsigned int pat_pmt_count; 42 }; 43 44 struct r5000_buttons directv_button_cmd = 45 { 46 0x49, //len 47 400000, //delay 48 //button 0: 49 { 50 0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 51 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 52 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 53 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 54 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 55 }, 56 //button 1: 57 { 58 0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 59 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 60 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 61 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 62 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 63 }, 64 //button 2: 65 { 66 0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 67 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 68 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 69 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 70 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 71 }, 72 //button 3: 73 { 74 0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 75 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 76 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 77 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 78 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 79 }, 80 //button 4: 81 { 82 0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 83 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 84 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 85 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 86 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 87 }, 88 //button 5: 89 { 90 0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 91 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 92 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 93 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 94 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 95 }, 96 //button 6: 97 { 98 0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 99 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 100 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 101 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 102 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 103 }, 104 //button 7: 105 { 106 0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 107 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 108 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 109 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 110 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 111 }, 112 //button 8: 113 { 114 0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 115 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 116 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 117 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 118 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 119 }, 120 //button 9: 121 { 122 0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 123 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 124 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 125 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 126 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 127 }, 128 //Clear: 129 { 130 0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 131 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 132 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 133 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 134 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 135 }, 136 //Enter: 137 { 138 0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 139 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 140 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 141 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 142 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 143 }, 144 //Power 145 { 146 0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 147 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 148 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 149 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 150 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 151 } 152 }; 153 154 static int directv_make_empty_pes(unsigned char *ptr, unsigned char type) 155 { 156 ptr[0] = 0x00; 157 ptr[1] = 0x00; 158 ptr[2] = 0x01; 159 ptr[3] = type; 160 ptr[4] = 0x00; 161 ptr[5] = 0x00; 162 ptr[6] = 0x80; 163 ptr[7] = 0x00; //2 MSB represent PTS/DTS flag 164 ptr[8] = 0x0a; 165 ptr[9] = 0xff; 166 ptr[10] = 0xff; 167 ptr[11] = 0xff; 168 ptr[12] = 0xff; 169 ptr[13] = 0xff; 170 ptr[14] = 0xff; 171 ptr[15] = 0xff; 172 ptr[16] = 0xff; 173 ptr[17] = 0xff; 174 ptr[18] = 0xff; 175 return 19; 176 } 177 178 static void directv_make_pespts(unsigned char *outptr, unsigned int pts) 179 { 180 pts = htonl(pts); 181 unsigned char *inpts = (unsigned char *)&pts; 182 outptr[0] = 0x01 | 183 ((inpts[0] & 0xC0) >>5); 184 outptr[1] = ((inpts[0] & 0x3F) << 2) | 185 ((inpts[1] & 0xC0) >> 6); 186 outptr[2] = 0x01 | ((inpts[1] & 0x3F) << 2) | 187 ((inpts[2] & 0x80) >> 6); 188 outptr[3] = ((inpts[2] & 0x7F) << 1) | 189 ((inpts[3] & 0x80) >> 7); 190 outptr[4] = 0x01 | ((inpts[3] & 0x7F) << 1); 191 } 192 193 static void directv_update_video_pes(unsigned char *ptr, int pos) 194 { 195 //pos points at the 1st char after a pic start code 196 int picture_coding_type; 197 int hdr_len; 198 unsigned int pts1, dts1; 199 unsigned char *buf = ptr + pos; 200 picture_coding_type = (buf[1] >> 3) & 0x07; 201 hdr_len = (picture_coding_type > 1) ? 5 : 4; 202 if(buf[hdr_len + 3] == 0xb5) 203 hdr_len += 9; 204 if(buf[hdr_len + 3] == 0xb2) { 205 pts1 = ((buf[hdr_len+6] & 0x03) << 30) + 206 ((buf[hdr_len+7] & 0x7f) << 23) + 207 ((buf[hdr_len+8]) << 15) + 208 ((buf[hdr_len+9] & 0x7f) << 8) + 209 buf[hdr_len+10]; 210 dts1 = ((buf[hdr_len+13] & 0x03) << 30) + 211 ((buf[hdr_len+14] & 0x7f) << 23) + 212 ((buf[hdr_len+15]) << 15) + 213 ((buf[hdr_len+16] & 0x7f) << 8) + 214 buf[hdr_len+17]; 215 //NOTE: This is wrong. DSS timestamps only have a resolution of 2^32/300 216 //r5000_print("pts: %08x/%f dts: %08x/%f\n", pts1, pts1 / 27000000.0, dts1, dts1 / 27000000.0); 217 ptr[7] |= 0xc0; 218 directv_make_pespts(ptr+9, pts1/300); 219 ptr[9] |= 0x30; 220 directv_make_pespts(ptr+14, dts1/300); 221 ptr[14] |= 0x10; 222 } 223 } 224 225 static void directv_fix_audio_pts(unsigned char *ptr) 226 { 227 unsigned int pts = ((ptr[0] & 0x06) << 29) + 228 (ptr[1] << 22) + 229 ((ptr[2] & 0xfe) << 14) + 230 (ptr[3] << 7) + 231 (ptr[4] >> 1); 232 directv_make_pespts(ptr, pts/300); 233 ptr[0] |= 0x20; 234 } 235 236 237 static void directv_write_ts(r5kdev_t *r5kdev, unsigned char *ptr, int len, int pid, int start, int *cc) 238 { 239 int stuff = 184 - len; 240 //Note: we know that there are 188 bytes allocated before 'ptr' 241 // that we can use for the header 242 if(stuff > 0) { 243 int stuff1 = stuff; 244 while(stuff1 > 2) { 245 *--ptr = 0xff; 246 stuff1--; 247 } 248 if(stuff1 == 2) { 249 *--ptr = 0x00; 250 } 251 *--ptr = stuff - 1; 252 *--ptr = 0x30 | *cc; 253 } else { 254 *--ptr = 0x10 | *cc; 255 } 256 *--ptr = pid & 0xff; 257 *--ptr = (start << 6) | (pid >> 8); 258 *--ptr = 0x47; 259 r5kdev->cb(ptr, 188, r5kdev->cb_data); 260 *cc = (*cc+1) & 0x0f; 261 } 262 263 static void directv_process_block(r5kdev_t *r5kdev, unsigned char *buf, int len) 264 { 265 int i; 266 struct r5000_dtv *dtv = (struct r5000_dtv *)r5kdev->stbdata; 267 for(i = 0; i < len; i+=2) { 268 unsigned char data = buf[i]; 269 unsigned char type = buf[i+1]; 270 if(0xff == type) { 271 //video 272 dtv->video[dtv->vpos++] = data; 273 if(dtv->vpos > 4 && dtv->video[dtv->vpos-2] == 0x01 && 274 dtv->video[dtv->vpos-3] == 0x00 && dtv->video[dtv->vpos-4] == 0x00) { 275 if (data == 0xe0) { 276 //HD video header (PES) 277 directv_write_ts(r5kdev, dtv->video, dtv->vpos - 4, DTV_VPID, dtv->vstart, &dtv->video_cc); 278 dtv->pat_pmt_count++; 279 dtv->video[0] = 0x00; 280 dtv->video[1] = 0x00; 281 dtv->video[2] = 0x01; 282 dtv->video[3] = 0xe0; 283 dtv->vpos = 4; 284 dtv->vstart = 1; 285 dtv->vstate = data; 286 } else if (data == 0xb3 || data == 0x00) { 287 if (dtv->vstate == 0xff) { 288 dtv->vstate = data; 289 directv_write_ts(r5kdev, dtv->video, dtv->vpos - 4, DTV_VPID, dtv->vstart, &dtv->video_cc); 290 dtv->pat_pmt_count++; 291 //Create a PES header, but no PTS/DTS info yet so just use stuffing bytes 292 dtv->vpos = directv_make_empty_pes(dtv->video, 0xe0); 293 dtv->video[dtv->vpos++] = 0x00; 294 dtv->video[dtv->vpos++] = 0x00; 295 dtv->video[dtv->vpos++] = 0x01; 296 dtv->video[dtv->vpos++] = data; 297 dtv->vstart = 1; 298 dtv->pic_pos = dtv->vpos; 299 } 300 } 301 } 302 if(dtv->vpos == 188) { 303 if (dtv->vstate == 0x00) 304 //We found pic frame without a PES header (SD) 305 directv_update_video_pes(dtv->video, dtv->pic_pos); 306 directv_write_ts(r5kdev, dtv->video, 184, DTV_VPID, dtv->vstart, &dtv->video_cc); 307 dtv->pat_pmt_count++; 308 dtv->video[0] = dtv->video[184]; 309 dtv->video[1] = dtv->video[185]; 310 dtv->video[2] = dtv->video[186]; 311 dtv->video[3] = dtv->video[187]; 312 dtv->vpos = 4; 313 dtv->vstart = 0; 314 dtv->vstate = 0xff; 315 } 316 } else if(0xfe == type) { 317 //audio 318 dtv->audio[dtv->apos++] = data; 319 dtv->alen--; 320 if(dtv->alen <= 0 && dtv->apos > 6 && dtv->audio[dtv->apos-3] == 0xbd && dtv->audio[dtv->apos-4] == 0x01 && 321 dtv->audio[dtv->apos-5] == 0x00 && dtv->audio[dtv->apos-6] == 0x00) { 322 dtv->alen = (dtv->audio[dtv->apos-2] << 8) + data; 323 directv_write_ts(r5kdev, dtv->audio, dtv->apos - 6, DTV_APID, dtv->astart, &dtv->audio_cc); 324 dtv->pat_pmt_count++; 325 dtv->audio[0] = 0x00; 326 dtv->audio[1] = 0x00; 327 dtv->audio[2] = 0x01; 328 dtv->audio[3] = 0xbd; 329 dtv->audio[4] = dtv->audio[dtv->apos-2]; 330 dtv->audio[5] = data; 331 dtv->apos = 6; 332 dtv->astart = 1; 333 r5kdev->pmt[1].id = 0x81; //AC3 334 } else if(dtv->alen <= 0 && dtv->apos > 6 && dtv->audio[dtv->apos-3] == 0xc0 && dtv->audio[dtv->apos-4] == 0x01 && 335 dtv->audio[dtv->apos-5] == 0x00 && dtv->audio[dtv->apos-6] == 0x00) { 336 dtv->alen = (dtv->audio[dtv->apos-2] << 8) + data; 337 directv_write_ts(r5kdev, dtv->audio, dtv->apos - 6, DTV_APID, dtv->astart, &dtv->audio_cc); 338 dtv->pat_pmt_count++; 339 dtv->audio[0] = 0x00; 340 dtv->audio[1] = 0x00; 341 dtv->audio[2] = 0x01; 342 dtv->audio[3] = 0xc0; 343 dtv->audio[4] = (dtv->alen + 3) >> 8; 344 dtv->audio[5] = (dtv->alen + 3) & 0xff; 345 dtv->audio[6] = 0x80; 346 dtv->audio[7] = 0x80; 347 dtv->audio[8] = 0x05; 348 dtv->apos = 9; 349 dtv->astart = 1; 350 r5kdev->pmt[1].id = 0x04; //MP2 351 } else if(dtv->apos == 190) { 352 if(dtv->astart && dtv->audio[3] == 0xc0) 353 directv_fix_audio_pts(dtv->audio+9); 354 directv_write_ts(r5kdev, dtv->audio, 184, DTV_APID, dtv->astart, &dtv->audio_cc); 355 dtv->pat_pmt_count++; 356 dtv->audio[0] = dtv->audio[184]; 357 dtv->audio[1] = dtv->audio[185]; 358 dtv->audio[2] = dtv->audio[186]; 359 dtv->audio[3] = dtv->audio[187]; 360 dtv->audio[4] = dtv->audio[188]; 361 dtv->audio[5] = dtv->audio[189]; 362 dtv->apos = 6; 363 dtv->astart = 0; 364 } 365 } 366 } 367 if(r5kdev->pmt[1].id && dtv->pat_pmt_count > DTV_PAT_PMT_COUNT) { 368 r5kdev->cb(r5000_pat_pkt, 188, r5kdev->cb_data); 369 r5000_send_pmt(r5kdev); 370 dtv->pat_pmt_count = 0; 371 } 372 } 373 374 static void directv_start_stream(r5kdev_t *r5kdev) 375 { 376 struct r5000_dtv *dtv = (struct r5000_dtv *)r5kdev->stbdata; 377 dtv->vstart = 0; 378 dtv->astart = 0; 379 dtv->vpos = 0; 380 dtv->apos = 0; 381 dtv->video_cc = 0; 382 dtv->audio_cc = 0; 383 dtv->vstate = 0; 384 dtv->pat_pmt_count = DTV_PAT_PMT_COUNT; 385 } 386 void directv_init(r5kdev_t *r5kdev) 387 { 388 struct r5000_dtv *dtv = (struct r5000_dtv *)calloc(1, sizeof(struct r5000_dtv)); 389 dtv->video = dtv->vbuf + 188; 390 dtv->audio = dtv->abuf + 188; 391 dtv->pat_pmt_count = DTV_PAT_PMT_COUNT; 392 dtv->vstate = 0xff; 393 r5kdev->stbdata = dtv; 394 r5kdev->pmt[0].id = 0x02; //MPEG2 395 r5kdev->pmt[0].pid = DTV_VPID; 396 r5kdev->pmt[0].desc = r5000_pmt_video_desc; 397 r5kdev->pmt[1].id = 0x00; 398 r5kdev->pmt[1].pid = DTV_APID; 399 r5kdev->pmt[1].desc = r5000_pmt_audio_desc; 400 r5kdev->num_pmt_entries = 2; 401 r5kdev->process_block = directv_process_block; 402 r5kdev->start_stream = directv_start_stream; 403 r5kdev->button = &directv_button_cmd; 404 r5kdev->power_active_low = 1; 405 r5kdev->read_words = 1; 406 } 407 408 void directv_free(r5kdev_t *r5kdev) 409 { 410 free(r5kdev->stbdata); 411 } -
new file libs/libmythtv/r5000/r5k_misc.c
- + 1 /* Copyright 2008 Alan Nisota <alannisota@gmail.com> 2 * 3 * This library is free software; you can redistribute it and/or 4 * modify it under the terms of the GNU Lesser General Public 5 * License as published by the Free Software Foundation; either 6 * version 2.1 of the License, or (at your option) any later version. 7 * 8 * This library is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * Lesser General Public License for more details. 12 * 13 * You should have received a copy of the GNU Lesser General Public 14 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 17 #include <stdio.h> 18 #include <string.h> 19 #include "r5000_internal.h" 20 21 unsigned char r5000_pat_pkt[188] = { 22 0x47, 0x40, 0x00, 0x13, 0x00, 0x00, 0xb0, 0x0d, 0x00, 0x06, 0xc5, 0x00, 0x00, 0x00, 0x01, 0xe0, 23 0x21, 0x19, 0x3a, 0x82, 0xc4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 24 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 25 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 26 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 27 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 28 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 29 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 30 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 31 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 32 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 33 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 34 35 36 struct r5k_descriptor r5000_pmt_audio_desc = {{0x06, 0x0a, 0x04, 0x65, 0x6e, 0x67, 0x00}}; 37 struct r5k_descriptor r5000_pmt_video_desc = {{0x00}}; 38 39 //taken and adapted from libdtv, (c) Rolf Hakenes 40 // CRC32 lookup table for polynomial 0x04c11db7 41 static unsigned int crc_table[256] = { 42 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 43 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 44 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, 45 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, 46 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 47 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 48 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, 49 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, 50 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 51 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 52 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, 53 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, 54 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 55 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 56 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 57 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, 58 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 59 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 60 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 61 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 62 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 63 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 64 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, 65 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, 66 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 67 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 68 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, 69 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, 70 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 71 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 72 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, 73 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, 74 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 75 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 76 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 77 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, 78 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 79 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 80 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 81 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 82 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 83 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 84 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4}; 85 86 static void r5000_calc_crc(unsigned char *out, const unsigned char *d, int len) 87 { 88 register int i; 89 unsigned int crc = 0xFFFFFFFF; 90 const unsigned char *u=(unsigned char*)d; // Saves '& 0xff' 91 92 for (i=0; i<len; i++) 93 crc = (crc << 8) ^ crc_table[((crc >> 24) ^ *u++)]; 94 95 *out++ = (crc >> 24) & 0xff; 96 *out++ = (crc >> 16) & 0xff; 97 *out++ = (crc >> 8) & 0xff; 98 *out++ = (crc >> 0) & 0xff; 99 } 100 101 static void r5000_build_pmt(r5kdev_t *r5kdev) 102 { 103 int i; 104 unsigned char *ptr; 105 unsigned char ts[188] = { 106 0x47, 0x40, 0x21, 0x10, 107 0x00, 0x02, 108 0xb0, 0x00, //length 109 0x00, 0x01, 110 0xc1, //version<<1 (5 bits) | current_next 111 0x00, 0x00, //section/last_section 112 0xf0, 0x00, //PCR_PID 113 0xf0, 0x00}; //Program Info Length 114 115 ts[3] = 0x10 | r5kdev->pmt_next_cc; 116 117 //Change the PMT version every time we rebuild the PMT 118 ts[10] |= r5kdev->pmt_version << 1; 119 r5kdev->pmt_version = (r5kdev->pmt_version + 1) % 32; 120 121 r5000_print("Building PMT\n"); 122 ptr = ts + 17; 123 for(i = 0; i < r5kdev->num_pmt_entries; i++) { 124 *ptr++ = r5kdev->pmt[i].id; 125 *ptr++ = 0xe0 | (r5kdev->pmt[i].pid>>8); 126 *ptr++ = r5kdev->pmt[i].pid & 0xff; 127 *ptr++ = 0xf0; 128 memcpy(ptr, r5kdev->pmt[i].desc.d, r5kdev->pmt[i].desc.d[0]+1); 129 ptr += r5kdev->pmt[i].desc.d[0]+1; 130 if(IS_VIDEO(r5kdev->pmt[i].id)) { 131 ts[13] = 0xe0 | (r5kdev->pmt[i].pid >> 8); 132 ts[14] = r5kdev->pmt[i].pid & 0xff; 133 } 134 } 135 ts[7] = (ptr - ts) - 8/*header*/ + 4/*CRC*/; 136 r5000_calc_crc(ptr, ts + 5, (ptr - ts) - 5); 137 memset(ptr+4, 0xff, 188 - (ptr + 4 - ts)); 138 memcpy(r5kdev->pmt_pkt, ts, 188); 139 //PRINTHEX("PMT", r5kdev->pmt_pkt, 188); 140 } 141 142 void r5000_reset_pmt(r5kdev_t *r5kdev) 143 { 144 r5kdev->num_pmt_entries = 0; 145 r5kdev->pmt_state = 0; 146 r5kdev->pmt_pkt[0] = 0; 147 } 148 149 void r5000_send_pmt(r5kdev_t *r5kdev) 150 { 151 if(r5kdev->pmt_pkt[0] != 0x47) { 152 r5000_build_pmt(r5kdev); 153 } 154 r5kdev->pmt_pkt[3] = 0x10 | r5kdev->pmt_next_cc; 155 r5kdev->pmt_next_cc = (r5kdev->pmt_next_cc + 1) & 0x0f; 156 r5kdev->cb(r5kdev->pmt_pkt, 188, r5kdev->cb_data); 157 } -
new file libs/libmythtv/r5000/r5k_sat.c
- + 1 /* Copyright 2008 Alan Nisota <alannisota@gmail.com> 2 * 3 * This library is free software; you can redistribute it and/or 4 * modify it under the terms of the GNU Lesser General Public 5 * License as published by the Free Software Foundation; either 6 * version 2.1 of the License, or (at your option) any later version. 7 * 8 * This library is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * Lesser General Public License for more details. 12 * 13 * You should have received a copy of the GNU Lesser General Public 14 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 17 //Support for Dish Network ViP211/ViP422 boxes 18 #include <stdio.h> 19 #include <string.h> 20 #include "r5000_internal.h" 21 22 #define DTV_PAT_PMT_COUNT 5000 23 #define MAX_PKT_SIZE 272 24 #define MAX_PAT_SECTIONS 1 25 #define MAX_SIDS 200 26 #define MAX_EPIDS 5 27 28 struct pat { 29 int version; 30 unsigned char last_section; 31 unsigned char section_seen[MAX_PAT_SECTIONS]; 32 unsigned int crc[MAX_PAT_SECTIONS]; 33 unsigned int pmts[MAX_SIDS]; 34 int pmt_count; 35 }; 36 37 struct sids { 38 unsigned short sid; 39 unsigned int crc; 40 unsigned char seen_name; 41 struct r5k_epid epid[MAX_EPIDS]; 42 unsigned char epid_count; 43 }; 44 45 struct r5000_sat { 46 unsigned char buf[MAX_PKT_SIZE]; 47 unsigned int pos; 48 int offset; 49 unsigned char sync; 50 unsigned char bytesize; 51 unsigned char sync_byte; 52 unsigned int has_sync_byte; 53 unsigned int pat_pmt_count; 54 unsigned int packet_size; 55 unsigned int allowed_packet_size[8]; 56 57 unsigned int current_sid; 58 struct pat pats; 59 struct sids *sids; 60 }; 61 62 static int sat_read_pat_pkt(unsigned char *pes, struct pat *pat, unsigned int size) { 63 unsigned int sec, end, crc, current_next; 64 int version; 65 unsigned char *ptr, last_sec; 66 67 if (pes[0] != 0x00) { 68 r5000_print("read_pat: expected PAT table 0x00 but got 0x%02x\n", pes[0]); 69 return -1; 70 } 71 end = (((pes[1] & 0x03) << 8 | pes[2]) + 3 - 4); 72 if(end > size-4) { 73 r5000_print("read_pat: invalid PAT table size (%d > %d)\n", end, size-4); 74 return -1; 75 } 76 crc = (pes[end]<<24) | (pes[end+1]<<16) | (pes[end+2]<<8) | pes[end+3]; 77 version = (pes[5] >> 1) & 0x1f; 78 current_next = pes[5] & 0x01; 79 sec = pes[6]; 80 last_sec = pes[7]; 81 if(! current_next) 82 //ignore inactive PAT 83 return 0; 84 if(last_sec >= MAX_PAT_SECTIONS) { 85 r5000_print("read_pat: illegal section count %d > %d\n", 86 last_sec, MAX_PAT_SECTIONS); 87 return -1; 88 } 89 if (pat->version != version || last_sec != pat->last_section || 90 pat->crc[sec] != crc) { 91 pat->version = version; 92 pat->last_section = last_sec; 93 pat->pmt_count = 0; 94 memset(pat->section_seen, 0, sizeof(pat->section_seen)); 95 } 96 if(pat->section_seen[sec]) 97 return 0; 98 pat->crc[sec] = crc; 99 pat->section_seen[sec] = 1; 100 for(ptr = pes + 8; ptr < pes + end; ptr += 4) { 101 int sid, pid; 102 sid = (ptr[0] << 8) | ptr[1]; 103 pid = ((ptr[2] & 0x1F) << 8) | ptr[3]; 104 r5000_print("found PID: %04x for sid: %d\n", pid, sid); 105 if(sid != 0) { 106 pat->pmts[pat->pmt_count++] = (sid << 16) | pid; 107 } 108 } 109 return 1; 110 } 111 112 static struct sids *sat_read_pmt_pkt(unsigned char *buf, struct sids *sids, 113 unsigned int size) { 114 // 115 // NOTE we aren't using last_sec here yet! 116 // 117 118 struct sids *sidptr = sids; 119 unsigned int count, skip, pos, crc, current_next; 120 int sid, sec, last_sec, pcrpid, epid, type; 121 if (buf[0] != 0x02) { 122 r5000_print("read_pmt expected table 0x02 but got 0x%02x\n", buf[0]); 123 return NULL; 124 } 125 count = (((buf[1] & 0x03) << 8) | buf[2]) + 3 - 4; 126 sid = (buf[3] << 8) | buf[4]; 127 current_next = buf[5] & 0x01; 128 crc = (buf[count]<<24) | (buf[count+1]<<16) | (buf[count+2]<<8) | buf[count+3]; 129 sec = buf[6]; 130 last_sec = buf[7]; 131 pcrpid = ((buf[8] & 0x1F) << 8) | buf[9]; 132 skip = ((buf[10] & 0x03) << 8) | buf[11]; 133 if(skip > count - 12 || count > size) { 134 r5000_print("skip: %d > count: %d - 12 || count > size: %d\n", 135 skip, count, size); 136 return NULL; 137 } 138 if(! current_next) { 139 r5000_print("read_pmt ignoring future PMT\n"); 140 return NULL; 141 } 142 while(sidptr->sid != 0) { 143 if(sidptr->sid == sid) 144 break; 145 sidptr++; 146 } 147 if(sidptr->sid == 0) { 148 // We weren't expecting this sid 149 r5000_print("read_pmt found unexpected sid: %d\n", sidptr->sid); 150 return sidptr; 151 } 152 if(sidptr->crc == crc) { 153 //sid is unchanged 154 //r5000_print("read_pmt found identical crc (%08x) for %d\n", crc, sidptr->sid); 155 return NULL; 156 } 157 memset(sidptr, 0, sizeof(struct sids)); 158 159 r5000_print("read_pmt: sid: %d pcrpid: %d skip: %d count: %d\n", sid, pcrpid, skip, count); 160 sidptr->sid = sid; 161 sidptr->crc = crc; 162 sidptr->epid_count = 0; 163 for(pos = 12 + skip; pos < count;) { 164 struct r5k_epid *pidptr = &sidptr->epid[sidptr->epid_count]; 165 type = buf[pos]; 166 epid = ((buf[pos+1] & 0x1F) << 8) | buf[pos+2]; 167 skip = ((buf[pos+3] & 0x03) << 8) | buf[pos+4]; 168 pidptr->pid = epid; 169 pidptr->id = type == 0x80 ? 0x02 : type; 170 memcpy(pidptr->desc.d, buf + pos + 4, skip + 1); 171 sidptr->epid_count++; 172 r5000_print("read_pmt: epid %04x (type %02x, skip=%d) mapped to sid %d\n", epid, type, skip, sid); 173 pos += 5 + skip; 174 } 175 return sidptr; 176 } 177 178 void sat_find_chname(unsigned char *buf, struct sids *sids, unsigned int size) { 179 struct sids *sidptr = sids; 180 unsigned int count; 181 int sid; 182 char str[20], *strptr = str; 183 while(size) { 184 count = (((buf[1] & 0x03) << 8) | buf[2]) + 3; 185 if(buf[0] == 0x41) { 186 buf += count; 187 size -= count; 188 continue; 189 } 190 if(buf[0] == 0xc1) { 191 unsigned char *ptr = buf+16; 192 sid = (buf[7]<<8) | buf[8]; 193 while(sidptr->sid != 0) { 194 if(sidptr->sid == sid) 195 break; 196 sidptr++; 197 } 198 if(sidptr->sid == 0) { 199 // We weren't expecting this sid 200 return; 201 } 202 if(sidptr->seen_name) 203 return; 204 sidptr->seen_name = 1; 205 while(*ptr >= 0x20 && *ptr < 0x7b && strptr-str < sizeof(str)-1) { 206 *strptr++ = *ptr++; 207 } 208 *strptr = 0; 209 r5000_print("sid: %d is channel %s\n", sid, str); 210 return; 211 } 212 return; 213 } 214 } 215 216 int sat_add_pmt(r5kdev_t *r5kdev, struct r5k_epid *epid) 217 { 218 int i; 219 int is_video = IS_VIDEO(epid->id); 220 221 for(i = 0; i < r5kdev->num_pmt_entries; i++) { 222 if(r5kdev->pmt[i].pid == epid->pid) { 223 if(r5kdev->pmt[i].id == epid->id) 224 return 0; 225 //different table_id for existing pid. Reset 226 r5000_reset_pmt(r5kdev); 227 break; 228 } 229 if(is_video) { 230 if(IS_VIDEO(r5kdev->pmt[i].id)) { 231 //a video entry already exists. Reset 232 r5000_reset_pmt(r5kdev); 233 break; 234 } 235 } 236 } 237 //Didn't find this PID, add it 238 if(i == R5K_MAX_PIDS) 239 return 0; 240 r5000_print("Adding %04x: %02x (desc_len=%d) @ %08x\n", epid->pid, epid->id, epid->desc.d[0], r5kdev->bytes_read); 241 r5kdev->pmt[r5kdev->num_pmt_entries++] = *epid; 242 r5kdev->pmt_state |= is_video ? 0x01 : 0x02; 243 return 1; 244 } 245 246 void sat_process_ts(r5kdev_t *r5kdev, unsigned char *buf) 247 { 248 struct r5000_sat *sat = (struct r5000_sat *)r5kdev->stbdata; 249 int pid; 250 int i, j, k; 251 pid = ((buf[1] << 8) | buf[2]) & 0x1fff; 252 if(pid == 0x1fff) 253 return; 254 if(pid == 0 && (buf[1] & 0x40)) { 255 //Always read PAT in case we changed transponders 256 if(sat_read_pat_pkt(buf+buf[4]+5, &sat->pats, 188-buf[4]-5) > 0) { 257 r5000_print("Found new PAT\n"); 258 if(sat->pats.pmt_count) { 259 sat->sids = realloc(sat->sids, sizeof(struct sids)*(sat->pats.pmt_count+1)); 260 memset(sat->sids, 0, sizeof(struct sids)*(sat->pats.pmt_count+1)); 261 //Pre load sids so we don't overrun if the PMT changes before the PAT 262 for(i = 0; i < sat->pats.pmt_count; i++) { 263 sat->sids[i].sid = sat->pats.pmts[i]>>16; 264 } 265 sat->sids[i].sid = 0; 266 r5000_reset_pmt(r5kdev); 267 } 268 } else if(r5kdev->pmt_state == 0x03) { 269 r5kdev->cb(r5000_pat_pkt, 188, r5kdev->cb_data); 270 r5000_send_pmt(r5kdev); 271 sat->pat_pmt_count = 0; 272 } 273 return; 274 } 275 //Always reread PMT in case the pids have changed 276 for(i = 0; i < sat->pats.pmt_count; i++) { 277 if(pid == (unsigned short)(sat->pats.pmts[i])) { 278 #if 0 279 { 280 char s[80]; 281 FILE *fh; 282 sprintf(s, "0x%04x.ts", pid); 283 fh= fopen(s, "a"); 284 fwrite(buf, 188, 1, fh); 285 fclose(fh); 286 } 287 #endif 288 //r5000_print("PID: %04x - %04x (%d) %02x %02x %02x %02x %02x\n", pid, (unsigned short)(sat->pats.pmts[i]), i, buf[1], buf[2], buf[3], buf[4], buf[5]); 289 if(buf[1] & 0x40 && buf[4]+5 < 188) { 290 if(buf[buf[4]+5] == 0x02) { 291 struct sids *sidptr; 292 if((sidptr = sat_read_pmt_pkt(buf+buf[4]+5, sat->sids, 188-buf[4]-5))) { 293 if(sidptr->sid == 0) { 294 //Unexpected sid, reset PAT; 295 memset(&sat->pats, 0, sizeof(struct pat)); 296 } else if(sat->current_sid == sidptr->sid) { 297 r5000_reset_pmt(r5kdev); 298 sat->current_sid = 0; 299 } 300 } 301 //} else if(buf[buf[4]+5] == 0xc1 || buf[buf[4]+5] == 0x41) { 302 // sat_find_chname(buf+buf[4]+5, sat->sids, 188-buf[4]-5); 303 } 304 } 305 return; 306 } 307 if(! sat->current_sid) { 308 for(j = 0; j < sat->sids[i].epid_count; j++) { 309 if(pid == sat->sids[i].epid[j].pid && 310 IS_VIDEO(sat->sids[i].epid[j].id) && 311 (!r5kdev->channel || r5kdev->channel == sat->sids[i].sid)) { 312 //Found unencrypted video. Choose this one 313 // Assume this is MPEG2. Don't know what MPEG4 looks like yet 314 sat->current_sid = sat->sids[i].sid; 315 r5000_print("Found decrypted sid %d\n", sat->current_sid); 316 if (sat_add_pmt(r5kdev, &sat->sids[i].epid[j])) { 317 //This is a new Video PID 318 for(k = 0; k < sat->sids[i].epid_count; k++) { 319 if(sat->sids[i].epid[k].id == 0x81 || 320 sat->sids[i].epid[k].id == 0xbd) { 321 sat_add_pmt(r5kdev, &sat->sids[i].epid[k]); 322 } 323 } 324 r5kdev->cb(r5000_pat_pkt, 188, r5kdev->cb_data); 325 r5000_send_pmt(r5kdev); 326 sat->pat_pmt_count = 0; 327 } 328 r5kdev->cb(sat->buf, 188, r5kdev->cb_data); 329 return; 330 } 331 } 332 } 333 } 334 for(i = 0; i < r5kdev->num_pmt_entries; i++) { 335 if(pid == r5kdev->pmt[i].pid) { 336 r5kdev->cb(sat->buf, 188, r5kdev->cb_data); 337 sat->pat_pmt_count++; 338 return; 339 } 340 } 341 #if 0 342 //r5000_print("Ignoring PID: %04x\n", pid); 343 { 344 char s[80]; 345 FILE *fh; 346 sprintf(s, "0x%04x.ts", pid); 347 fh= fopen(s, "a"); 348 fwrite(buf, 188, 1, fh); 349 fclose(fh); 350 } 351 #endif 352 } 353 354 static void sat_process_block(r5kdev_t *r5kdev, unsigned char *buf, int len) 355 { 356 struct r5000_sat *sat = (struct r5000_sat *)r5kdev->stbdata; 357 358 int pos; 359 if(! r5kdev->streaming) 360 return; 361 if(len <= 0) 362 return; 363 364 for(pos = sat->offset; pos < len; pos += sat->bytesize) { 365 if(! sat->sync) { 366 if(buf[pos] == 0x47) { 367 int i; 368 if (pos + (sat->allowed_packet_size[0]<<1) < len) { 369 if((buf[pos+1] & 0xfc) == 0xfc && (buf[pos+3] & 0xfc) == 0xfc && 370 (buf[pos+5] & 0xfc) == 0xfc && (buf[pos+7] & 0xfc) == 0xfc) { 371 sat->bytesize = 2; 372 } 373 for(i=0; sat->allowed_packet_size[i] != 0; i++) { 374 if(buf[pos+(sat->allowed_packet_size[i] * sat->bytesize)] == 0x47) { 375 r5000_print("(%d) Found %d byte sync at %08x: bytesize = %d\n", 376 r5kdev->nexturb, sat->allowed_packet_size[i], 377 r5kdev->bytes_read+pos, sat->bytesize); 378 sat->packet_size = sat->allowed_packet_size[i]; 379 sat->sync = 1; 380 sat->buf[0] = 0x47; 381 sat->pos = 1; 382 break; 383 } 384 } 385 } 386 } 387 continue; 388 } 389 if (sat->pos == 0 && buf[pos] != 0x47) { 390 sat->sync = 0; 391 sat->bytesize = 1; 392 r5000_print("(%d)Lost sync at %08x\n", r5kdev->nexturb, 393 r5kdev->bytes_read+pos); 394 continue; 395 } 396 if(sat->pos == 3 && (buf[pos] & 0xc0) != 0x00) { 397 // Encrypted channel, skip this packet 398 sat->pos = 0; 399 pos += sat->bytesize * (sat->packet_size - 4); //Loop adds additional 2 400 continue; 401 } 402 sat->buf[sat->pos++] = buf[pos]; 403 if (sat->pos == sat->packet_size) { 404 sat_process_ts(r5kdev, sat->buf); 405 //if packet size > 188, assume remaining bytes are parity and ignore 406 sat->pos = 0; 407 } 408 } 409 sat->offset = pos - len; 410 if(r5kdev->pmt_state == 0x03 && sat->pat_pmt_count > DTV_PAT_PMT_COUNT) { 411 r5kdev->cb(r5000_pat_pkt, 188, r5kdev->cb_data); 412 r5000_send_pmt(r5kdev); 413 sat->pat_pmt_count = 0; 414 } 415 } 416 417 static void sat_start_stream(r5kdev_t *r5kdev) 418 { 419 struct r5000_sat *sat = (struct r5000_sat *)r5kdev->stbdata; 420 sat->offset = 0; 421 sat->sync = 0; 422 sat->pos = 0; 423 sat->bytesize = 1; 424 425 //Clear any defined PAT or PMT data 426 if(sat->sids) { 427 free(sat->sids); 428 sat->sids = 0; 429 } 430 memset(&sat->pats, 0, sizeof(struct pat)); 431 sat->pat_pmt_count = DTV_PAT_PMT_COUNT; 432 } 433 434 static void sat_change_channel(r5kdev_t *r5kdev) 435 { 436 r5000_reset_pmt(r5kdev); 437 } 438 439 void sat_init(r5kdev_t *r5kdev) 440 { 441 struct r5000_sat *sat = 442 (struct r5000_sat *)calloc(1, sizeof(struct r5000_sat)); 443 r5kdev->stbdata = sat; 444 sat->pat_pmt_count = DTV_PAT_PMT_COUNT; 445 if(r5kdev->stb_type == R5K_STB_HDD) { 446 sat->sync_byte = 0xff; 447 sat->has_sync_byte = 1; 448 sat->allowed_packet_size[0] = 272; 449 sat->allowed_packet_size[1] = 233; 450 sat->allowed_packet_size[2] = 204; 451 sat->allowed_packet_size[3] = 188; 452 sat->allowed_packet_size[4] = 0; 453 } else { 454 sat->allowed_packet_size[0] = 188; 455 sat->allowed_packet_size[1] = 0; 456 } 457 r5kdev->process_block = sat_process_block; 458 r5kdev->start_stream = sat_start_stream; 459 r5kdev->change_channel = &sat_change_channel; 460 } 461 462 void sat_free(r5kdev_t *r5kdev) 463 { 464 struct r5000_sat *sat = (struct r5000_sat *)r5kdev->stbdata; 465 if(sat->sids) 466 free(sat->sids); 467 free(r5kdev->stbdata); 468 } 469 -
new file libs/libmythtv/r5000/r5000init.h
- + 1 /* Copyright 2008 Alan Nisota <alannisota@gmail.com> 2 * 3 * This library is free software; you can redistribute it and/or 4 * modify it under the terms of the GNU Lesser General Public 5 * License as published by the Free Software Foundation; either 6 * version 2.1 of the License, or (at your option) any later version. 7 * 8 * This library is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * Lesser General Public License for more details. 12 * 13 * You should have received a copy of the GNU Lesser General Public 14 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 17 #ifndef R5000_INIT_H 18 #define R5000_INIT_H 19 20 #define R5K_INIT_MAX 9 21 #define R5K_INIT_SERIAL 8 22 #define R5K_DEFAULT_SLEEP 100000 23 struct { 24 int rsleep; 25 int rlen; 26 int wsleep; 27 int wlen; 28 unsigned char data[0x40]; 29 } r5kinit[R5K_INIT_MAX] = { 30 // 0 31 {R5K_DEFAULT_SLEEP, -1, 0, 64, 32 {0x30}}, 33 // 1 34 {R5K_DEFAULT_SLEEP, 1, 0, 64, 35 {0x08, 0x00, 0x20, 0x00, 0x00, 0x3a, 0xd4, 0x29, 0x7c, 0x56, 0x31, 0x44, 0x86, 0x6d, 0x0d, 0x0d, 36 0x1b, 0x0a, 0xad, 0x0f, 0xd0, 0x2e, 0x94, 0x3f, 0xd4, 0x08, 0xa2, 0x4b, 0x68, 0x14, 0x1f, 0x13, 37 0x04, 0x62, 0x1b, 0x14, 0xb9, 0x69, 0xcc, 0x25, 0x91, 0x06, 0xc9, 0x26, 0xf9, 0x41, 0x64, 0x46, 38 0x7d, 0x17, 0x61, 0x09, 0x5c, 0x5b, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, 39 // 2 40 {R5K_DEFAULT_SLEEP, 1, 0, 64, 41 {0x08, 0x00, 0x5a, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 42 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 43 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 44 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, 45 // 3 46 {R5K_DEFAULT_SLEEP, 1, 0, 64, 47 {0x08, 0x00, 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 48 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 49 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 50 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, 51 // 4 52 {R5K_DEFAULT_SLEEP, 1, R5K_DEFAULT_SLEEP, 64, 53 {0x08, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 54 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 55 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 56 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, 57 // 5 58 {R5K_DEFAULT_SLEEP, 26, 0, 6, 59 {0x08, 0x01, 0x00, 0x00, 0x01, 0x14}}, 60 // 6 61 {R5K_DEFAULT_SLEEP, 1, 0, 64, 62 {0x08, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 64 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, 66 // 7 67 {R5K_DEFAULT_SLEEP, 22, 0, 64, 68 {0x08, 0x01, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 69 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, 72 // 8 73 {R5K_DEFAULT_SLEEP, 4, 0, 1, 74 {0x20}} 75 }; 76 77 #endif -
new file contrib/r5000/ehci-2.6.25.patch
- + 1 --- a/drivers/usb/host/ehci-q.c 2007-06-11 11:37:06.000000000 -0700 2 +++ b/drivers/usb/host/ehci-q.c 2008-02-05 19:46:08.000000000 -0800 3 @@ -751,7 +751,7 @@ 4 info2 |= (EHCI_TUNE_MULT_HS << 30); 5 } else if (type == PIPE_BULK) { 6 info1 |= (EHCI_TUNE_RL_HS << 28); 7 - info1 |= 512 << 16; /* usb2 fixed maxpacket */ 8 + info1 |= ((maxp == 1024) ? 1024 : 512) << 16; /* usb2 fixed maxpacket */ 9 info2 |= (EHCI_TUNE_MULT_HS << 30); 10 } else { /* PIPE_INTERRUPT */ 11 info1 |= max_packet (maxp) << 16; -
new file contrib/r5000/r5000.hex
- + 1 :10000000020BBEAAAAAAAAAAAAAAAA020EFBAAAA76 2 :10001000AAAAAA020E76AAAAAAAAAA0208B8AAAAF4 3 :10002000AAAAAAAAAAAAAAAAAAAAAA020B31AAAAF0 4 :10003000AAAAAA020FDEAAAAAAAAAAAAAAAAAAAA2F 5 :10004000AAAAAA020800AAAAAAAAAA02069DAAAA5D 6 :10005000AAAAAA020800AAAAAAAAAAAAAAAAAAAAF4 7 :10006000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF0 8 :10007000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE0 9 :1000800090E6B9E0700302015B14700302020424DD 10 :10009000FE700302029924FB7003020155147003E1 11 :1000A00002014F147003020143147003020149243A 12 :1000B000056003020305120FE6400302031190E6F8 13 :1000C000BBE024FE602C14604724FD6016146031F0 14 :1000D00024067065E52490E6B3F0E52590E6B4F0DB 15 :1000E000020311E52C90E6B3F0E52D90E6B4F002A2 16 :1000F0000311E52690E6B3F0E52790E6B4F002039D 17 :1001000011E52890E6B3F0E52990E6B4F00203117A 18 :1001100090E6BAE0FF120ECFAA06A9077B01EA49D2 19 :10012000600DEE90E6B3F0EF90E6B4F002031190AC 20 :10013000E6A0E04401F002031190E6A0E04401F0E3 21 :10014000020311120FA7020311120FD6020311129C 22 :100150000FCE020311120F95020311120FE8400394 23 :1001600002031190E6B8E0247F602B14603C240267 24 :1001700060030201FAA200E433FF25E0FFA204E4D9 25 :10018000334F90E740F0E4A3F090E68AF090E68BDE 26 :100190007402F0020311E490E740F0A3F090E68AC5 27 :1001A000F090E68B7402F002031190E6BCE0547EFE 28 :1001B000FF7E00E0D3948040067C007D0180047CBB 29 :1001C000007D00EC4EFEED4F24C4F582740F3EF529 30 :1001D00083E493FF3395E0FEEF24A1FFEE34E68F36 31 :1001E00082F583E0540190E740F0E4A3F090E68AC2 32 :1001F000F090E68B7402F002031190E6A0E0440157 33 :10020000F0020311120FEA400302031190E6B8E076 34 :1002100024FE601D2402600302031190E6BAE0B4DC 35 :100220000105C20002031190E6A0E04401F00203C0 36 :100230001190E6BAE0705990E6BCE0547EFF7E0073 37 :10024000E0D3948040067C007D0180047C007D002A 38 :10025000EC4EFEED4F24C4F582740F3EF583E4931B 39 :10026000FF3395E0FEEF24A1FFEE34E68F82F583A5 40 :10027000E054FEF090E6BCE05480FF131313541FCB 41 :10028000FFE0540F2F90E683F0E04420F0020311CA 42 :1002900090E6A0E04401F08078120FEC507390E6F5 43 :1002A000B8E024FE60202402706790E6BAE0B40152 44 :1002B00004D200805C90E6BAE06402605490E6A04C 45 :1002C000E04401F0804B90E6BCE0547EFF7E00E00D 46 :1002D000D3948040067C007D0180047C007D00EC8E 47 :1002E0004EFEED4F24C4F582740F3EF583E493FF78 48 :1002F0003395E0FEEF24A1FFEE34E68F82F583E034 49 :100300004401F0800C120FEE500790E6A0E044018B 50 :10031000F090E6A0E04480F022E4F517F516F5151C 51 :10032000F514C205C200C204C201120A9D7E0A7FF2 52 :10033000008E248F25752C0A752D1275220A7523BF 53 :100340001C752A0A752B43752F0A753071EE54E01F 54 :10035000700302045D7518007519808E1A8F1BC317 55 :10036000749B9FFF740A9ECF2402CF3400FEE48F5B 56 :10037000138E12F511F510F50FF50EF50DF50CAF06 57 :1003800013AE12AD11AC10AB0FAA0EA90DA80CC381 58 :10039000120E105026E519250FF582E518350EF5D9 59 :1003A0008374CDF0E50F2401F50FE4350EF50EE46E 60 :1003B000350DF50DE4350CF50C80C4E4F50FF50EA4 61 :1003C000F50DF50CAF13AE12AD11AC10AB0FAA0EBC 62 :1003D000A90DA80CC3120E105031AE0EAF0FE51BC5 63 :1003E0002FF582E51A3EF583E0FDE5192FF582E54C 64 :1003F000183EF583EDF0EF2401F50FE43EF50EE431 65 :10040000350DF50DE4350CF50C80B98518248519EA 66 :100410002574002480FF740A34FFFEC3E52D9FF588 67 :100420002DE52C9EF52CC3E5279FF527E5269EF5A7 68 :1004300026C3E5299FF529E5289EF528C3E5239FD6 69 :10044000F523E5229EF522C3E52B9FF52BE52A9E99 70 :10045000F52AC3E5309FF530E52F9EF52FD2E8430E 71 :10046000D82090E668E04409F0E04402F090E65EAF 72 :10047000E0440CF043E80443E80290E6507404F0D2 73 :10048000000000E4F5B290E67AF043B288F58043CC 74 :10049000A82E438804438910758B6F758DFE90E6F6 75 :1004A0008F04F075AF07759DE1E4F59E90E65CE082 76 :1004B000443DF0D2AF90E680E020E105D207120E75 77 :1004C0004790E680E04408F00000000000000000D3 78 :1004D00000E054F7F0538EF8C20530010512008099 79 :1004E000C201300529120FE25024C2051207DB2099 80 :1004F000001690E682E030E704E020E1EF90E6822B 81 :10050000E030E604E020E0E4120EA3120FE4120F44 82 :10051000F080C7C0E0C0F0C083C082C0D075D000FA 83 :10052000C000C001C002C003C004C005C006C007AF 84 :10053000759AE7759B80759DE130060302061A7572 85 :100540000A00750B0090E67BE0FF7432250BF8A6DD 86 :1005500007050BE50B7002050AE59B2480C3940692 87 :1005600040E3E532120E2105F900058908059F10C8 88 :1005700005DF2005B93005D240061250060A600595 89 :10058000DACC05CCFF0000061A159B5391EF90E6DC 90 :100590005F7408F090E68DE4F0120D670206827435 91 :1005A000FD259BF59B5391EF90E65F7408F090E674 92 :1005B0008DE4F0120D6702068290E7C0740AF0A382 93 :1005C000E580F090E68F7402F00206745380F70223 94 :1005D000067490E68F7401F08040753900803B907E 95 :1005E000E7C074DDF0A37431F0A3742EF0A3743669 96 :1005F000F090E68F7404F0807B53A8F785368A75F7 97 :10060000CDFE75CC6F759E00801090E618740DF0CD 98 :10061000806290E618740CF0805A90E67BE090E6D9 99 :100620007CF0E59B2480FF90E68DE0FEEFC39E40CA 100 :10063000E9E53324FEFFE59EC39F5006E4F0D206B1 101 :100640008032C206759DE1759E00438902758E0059 102 :10065000858A8C75C800E5367006E53542808005D0 103 :10066000E535F4528043800890E67CE0F538438815 104 :100670001043C8045391EF90E65F7408F090E68D44 105 :10068000E4F0D007D006D005D004D003D002D001CA 106 :10069000D000D0D0D082D083D0F0D0E032C0E0C043 107 :1006A00083C082C0D075D000C000C004C005C006A1 108 :1006B000C0075391DF90E678E05404FF7E003002DB 109 :1006C0000BE0F430E1067C007D0180047C007D00BD 110 :1006D000EC4EFEED4F4E6008E4FF12096F0207C8B2 111 :1006E000E53224F860030207C8E53314604904606A 112 :1006F000030207C8E59B2480FFBF050B059B90E61E 113 :1007000079E534F00207C8E5372406FFE433FEAD8F 114 :100710009BED2480FDE434FFFCC3ED9FEE6480F884 115 :10072000EC648098500B90E67BE090E679F002074D 116 :10073000C81209660207C8E536701CE59B2480C311 117 :100740009406500B059B90E679E534F00207C875D6 118 :100750003601120D67807130020F90E679E075085E 119 :1007600000F509C202059B805FE5372406FFE433EC 120 :10077000FEAD9BED2480FDE434FFFCC3ED9FEE64F1 121 :1007800080F8EC648098503DE5372405FFE59B2414 122 :1007900080B5071490E678E04440F090E679E09068 123 :1007A000E67BF07F0112096FE5372404FFE59B2407 124 :1007B00080B5070790E678E04420F090E679E09075 125 :1007C000E67BF08003120966D007D006D005D0047E 126 :1007D000D000D0D0D082D083D0E03290E682E04406 127 :1007E000C0F090E681F04387010000000000227411 128 :1007F00000F58690FDA57C05A3E582458370F9226E 129 :10080000020F3900020F7F00020F6900020F510032 130 :10081000020DA200020DD900020FF100020FF2003A 131 :10082000020FF300020FF400020C4A00020513004D 132 :10083000020FF500020FF600020FF700020FF8009A 133 :10084000020FF900020FF200020FFA00020FFB0084 134 :10085000020FFC00020FFD00020FFE00020FFF005E 135 :1008600002100000020FF200020FF200020FF2006D 136 :100870000210010002100200021003000210040026 137 :10088000020F1C00021005000210060002100700F3 138 :10089000021008000210090002100A0002100B00EA 139 :1008A00002100C0002100D0002100E0002100F00CA 140 :1008B0000210100002101100C0E0C083C082C0D03E 141 :1008C0005388BF758B6F758DFEE59EC3947A507209 142 :1008D000300313E58020E10E43800890E67CE53884 143 :1008E000F0753800C203200313E58030E10E538019 144 :1008F000F790E67CE538F0753800D203E538F470FF 145 :100900003AE59EC3947A503390E67CE538F075382A 146 :1009100000E4F00521E52194004020E59E94185064 147 :100920001A759E00752100753800B2035388BF7593 148 :100930003D0090E65EE04404F080224388400538A4 149 :10094000801B53A8F75388F75388BF753800C2033C 150 :10095000752100753D0290E65EE04404F0D0D0D0F1 151 :1009600082D083D0E03290E678E04440F07F01EF1F 152 :1009700014603E0460030209FF90E7C074FFF0A317 153 :10098000E59BF090E678E090E7C2F090E678E0F43E 154 :1009900030E604E04440F0E490E679F00000000026 155 :1009A000000090E678E090E7C3F090E68F7405F0E1 156 :1009B00022E533700D90E7C07410F090E68F74015B 157 :1009C000F022759B80759DE7759EC090E67BE09058 158 :1009D000E67CF0E5372406FFE433FEAD9BED248092 159 :1009E000FDE434FFFCC3ED9FEE6480F8EC64809876 160 :1009F00040D9E537240690E68FF05380F7D20222E3 161 :100A00001201000200000040470502100000010230 162 :100A100000010A0600020000004001000902270050 163 :100A2000010100A0320904000003FF0000000705D7 164 :100A30000102400000070581024000000705820214 165 :100A400000040009022E00010100A0320904000088 166 :100A500004FF000000070502024000000705040231 167 :100A6000400000070586024000000705880240009C 168 :100A7000000403090410034E00650078007400634D 169 :100A8000006F006D001603480044002D0055005310 170 :100A90000042002000440056005200000090E60B87 171 :100AA0007403F000000090E6047480F0000000740D 172 :100AB00002F000000014F0000000E4F000000090DC 173 :100AC000E6007412F090E6017443F090E61074A012 174 :100AD000F090E68D7401F090E61174A0F090E618A5 175 :100AE000740DF090E6137420F090E614F090E61583 176 :100AF000F090E61274E8F0E490E602F00000009056 177 :100B0000E603F090E670F090E609F000000090E651 178 :100B1000207404F0000000E490E621F00000009052 179 :100B2000E630749AF0000000E490E631F000000036 180 :100B300022C0E0C083C082C0D053C8FBE538D39444 181 :100B400000400D75CDFE75CC6F153843C80480622A 182 :100B5000E59EC39533502790E67CE0F538E5883074 183 :100B6000E40AE535F452805388EF8007E53542808A 184 :100B700043881075CDFE75CC6F43C8048034759ED4 185 :100B800000E537B47719753700759DE1059E753816 186 :100B90000075CDFE75CC6F43881043C80480135395 187 :100BA00088EF53C8FB90E68DE4F0E535F4528043BE 188 :100BB000A80853C87FD0D0D082D083D0E032787FCD 189 :100BC000E4F6D8FD75813D020C05020319E493A3F8 190 :100BD000F8E493A34003F68001F208DFF48029E4EF 191 :100BE00093A3F85407240CC8C333C4540F4420C83B 192 :100BF000834004F456800146F6DFE4800B010204D2 193 :100C00000810204080900FB9E47E019360BCA3FFE0 194 :100C1000543F30E509541FFEE493A360010ECF5406 195 :100C2000C025E060A840B8E493A3FAE493A3F8E4F5 196 :100C300093A3C8C582C8CAC583CAF0A3C8C582C861 197 :100C4000CAC583CADFE9DEE780BEC0E0C0F0C0836A 198 :100C5000C082C0D075D000C000C001C002C003C0B7 199 :100C600004C005C006C00790E65F7404F05391EF1E 200 :100C7000300605120CBF802CE53D7005F59E43A89B 201 :100C800008438008E53D6401601AE53DB4020512A1 202 :100C90000CBF801090E7C074CCF0A3E539F090E66B 203 :100CA0008F7440F0D007D006D005D004D003D00216 204 :100CB000D001D000D0D0D082D083D0F0D0E0327537 205 :100CC0009AE720062AE490E7C0F0A3E59EF0A3741B 206 :100CD000A0F0A37402F0A37497F0E4A3F0759BC690 207 :100CE000F59E90E7C1E0D3943A400CD20680087597 208 :100CF0009BC0C206759E3A90E7C1E0FF90E67CE09B 209 :100D000090E67BF0AE9BEEC3748094815006E59E26 210 :100D1000C39F40E890E68F7440F05380F7E4F53DC0 211 :100D2000228E1C8F1D90E600E054187012E51D24E1 212 :100D300001FFE4351CC313F51CEF13F51D8015905E 213 :100D4000E600E05418FFBF100BE51D25E0F51DE59A 214 :100D50001C33F51CE51D151DAE1C7002151C4E60E4 215 :100D6000051207EF80EE2290E678E0F430E62DE001 216 :100D70004480F0E53224F0601C24087024E533B48C 217 :100D8000010CE536B4010790E67974A1F02290E6F3 218 :100D90007974A0F02290E679E534F022E4FF12099C 219 :100DA0006F22C0E0C083C08290E680E030E70E850D 220 :100DB0002226852327852A28852B29800C852A260B 221 :100DC000852B278522288523295391EF90E65D7492 222 :100DD00010F0D082D083D0E032C0E0C083C08290D7 223 :100DE000E680E030E70E852226852327852A2885A0 224 :100DF0002B29800C852A26852B27852228852329C7 225 :100E00005391EF90E65D7420F0D082D083D0E03231 226 :100E1000EB9FF5F0EA9E42F0E99D42F0E89C45F038 227 :100E200022D083D082F8E4937012740193700DA3E2 228 :100E3000A393F8740193F5828883E4737402936832 229 :100E400060EFA3A3A380DF30070990E680E0440AA7 230 :100E5000F0800790E680E04408F07FDC7E05120D0C 231 :100E60002190E65D74FFF090E65FF05391EF90E61D 232 :100E700080E054F7F022C0E0C083C082C0D0E59E7D 233 :100E8000C3947A501543884043800890E68FE4F07D 234 :100E900090E65EE054FBF0753D01D0D0D082D08367 235 :100EA000D0E03290E682E030E004E020E60B90E60D 236 :100EB00082E030E119E030E71590E680E04401F08F 237 :100EC0007F147E00120D2190E680E054FEF022A9EE 238 :100ED00007AE2FAF308F828E83A3E064037017AD0F 239 :100EE0000119ED7001228F828E83E07C002FFDECD2 240 :100EF0003EFEAF0580DF7E007F0022C0E0C0D0E56F 241 :100F000036D394004011E58055356007E535F4523D 242 :100F1000808004E5354280D0D0D0E032C0E0C0838C 243 :100F2000C0825380F77539015391BF90E651E05468 244 :100F3000FEF0D082D083D0E032C0E0C083C082D245 245 :100F4000015391EF90E65D7401F0D082D083D0E040 246 :100F500032C0E0C083C082D2055391EF90E65D7449 247 :100F600008F0D082D083D0E032C0E0C083C082538A 248 :100F700091EF90E65D7404F0D082D083D0E032C06F 249 :100F8000E0C083C0825391EF90E65D7402F0D0829E 250 :100F9000D083D0E03290E740E53CF0E490E68AF080 251 :100FA00090E68B04F0D32290E740E531F0E490E640 252 :100FB0008AF090E68B04F0D322C182013D00C10685 253 :100FC000013900000001020203030404050590E654 254 :100FD000BAE0F53CD32290E6BAE0F531D32253D8FB 255 :100FE000EF32D322D322D322D322D322D322D3222D 256 :100FF00022323232323232323232323232323232E1 257 :1010000032323232323232323232323232323232C0 258 :101010003232AAAAAAAAAAAAAAAAAAAAAAAAAAAA20 259 :10102000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA20 260 :10103000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA10 261 :10104000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA00 262 :10105000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF0 263 :10106000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE0 264 :10107000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD0 265 :10108000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC0 266 :10109000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0 267 :1010A000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0 268 :1010B000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA90 269 :1010C000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA80 270 :1010D000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA70 271 :1010E000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA60 272 :1010F000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA50 273 :10110000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3F 274 :10111000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2F 275 :10112000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1F 276 :10113000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0F 277 :10114000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFF 278 :10115000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEF 279 :10116000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADF 280 :10117000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACF 281 :10118000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABF 282 :10119000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF 283 :1011A000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9F 284 :1011B000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8F 285 :1011C000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7F 286 :1011D000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6F 287 :1011E000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5F 288 :1011F000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4F 289 :10120000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3E 290 :10121000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2E 291 :10122000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1E 292 :10123000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0E 293 :10124000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFE 294 :10125000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEE 295 :10126000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADE 296 :10127000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACE 297 :10128000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABE 298 :10129000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE 299 :1012A000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9E 300 :1012B000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8E 301 :1012C000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7E 302 :1012D000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6E 303 :1012E000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5E 304 :1012F000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4E 305 :10130000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3D 306 :10131000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2D 307 :10132000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1D 308 :10133000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0D 309 :10134000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFD 310 :10135000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAED 311 :10136000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADD 312 :10137000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACD 313 :10138000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABD 314 :10139000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD 315 :1013A000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9D 316 :1013B000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8D 317 :1013C000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7D 318 :1013D000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6D 319 :1013E000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5D 320 :1013F000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4D 321 :10140000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3C 322 :10141000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2C 323 :10142000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1C 324 :10143000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0C 325 :10144000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFC 326 :10145000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEC 327 :10146000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADC 328 :10147000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACC 329 :10148000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABC 330 :10149000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC 331 :1014A000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9C 332 :1014B000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8C 333 :1014C000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7C 334 :1014D000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6C 335 :1014E000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5C 336 :1014F000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4C 337 :10150000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3B 338 :10151000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2B 339 :10152000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1B 340 :10153000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0B 341 :10154000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFB 342 :10155000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEB 343 :10156000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADB 344 :10157000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACB 345 :10158000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABB 346 :10159000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB 347 :1015A000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9B 348 :1015B000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8B 349 :1015C000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7B 350 :1015D000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6B 351 :1015E000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5B 352 :1015F000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4B 353 :10160000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3A 354 :10161000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2A 355 :10162000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1A 356 :10163000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0A 357 :10164000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFA 358 :10165000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEA 359 :10166000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADA 360 :10167000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACA 361 :10168000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA 362 :10169000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 363 :1016A000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9A 364 :1016B000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8A 365 :1016C000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7A 366 :1016D000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6A 367 :1016E000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5A 368 :1016F000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4A 369 :10170000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA39 370 :10171000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA29 371 :10172000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA19 372 :10173000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA09 373 :10174000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF9 374 :10175000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE9 375 :10176000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD9 376 :10177000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC9 377 :10178000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB9 378 :10179000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9 379 :1017A000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA99 380 :1017B000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA89 381 :1017C000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA79 382 :1017D000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA69 383 :1017E000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA59 384 :1017F000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA49 385 :10180000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA38 386 :10181000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA28 387 :10182000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA18 388 :10183000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA08 389 :10184000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF8 390 :10185000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE8 391 :10186000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8 392 :10187000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8 393 :10188000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8 394 :10189000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8 395 :1018A000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA98 396 :1018B000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA88 397 :1018C000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA78 398 :1018D000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA68 399 :1018E000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA58 400 :1018F000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA48 401 :10190000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA37 402 :10191000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA27 403 :10192000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA17 404 :10193000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA07 405 :10194000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF7 406 :10195000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE7 407 :10196000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD7 408 :10197000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7 409 :10198000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB7 410 :10199000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7 411 :1019A000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA97 412 :1019B000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA87 413 :1019C000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA77 414 :1019D000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA67 415 :1019E000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA57 416 :1019F000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA47 417 :101A0000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA36 418 :101A1000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA26 419 :101A2000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA16 420 :101A3000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA06 421 :101A4000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF6 422 :101A5000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE6 423 :101A6000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD6 424 :101A7000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6 425 :101A8000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB6 426 :101A9000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6 427 :101AA000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA96 428 :101AB000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA86 429 :101AC000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA76 430 :101AD000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA66 431 :101AE000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA56 432 :101AF000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA46 433 :101B0000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA35 434 :101B1000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA25 435 :101B2000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA15 436 :101B3000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA05 437 :101B4000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF5 438 :101B5000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE5 439 :101B6000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD5 440 :101B7000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC5 441 :101B8000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB5 442 :101B9000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5 443 :101BA000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA95 444 :101BB000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA85 445 :101BC000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA75 446 :101BD000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA65 447 :101BE000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA55 448 :101BF000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA45 449 :101C0000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA34 450 :101C1000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA24 451 :101C2000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA14 452 :101C3000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA04 453 :101C4000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF4 454 :101C5000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE4 455 :101C6000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4 456 :101C7000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC4 457 :101C8000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB4 458 :101C9000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4 459 :101CA000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA94 460 :101CB000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA84 461 :101CC000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA74 462 :101CD000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA64 463 :101CE000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA54 464 :101CF000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA44 465 :101D0000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA33 466 :101D1000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA23 467 :101D2000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA13 468 :101D3000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA03 469 :101D4000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF3 470 :101D5000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE3 471 :101D6000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD3 472 :101D7000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC3 473 :101D8000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB3 474 :101D9000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3 475 :101DA000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA93 476 :101DB000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA83 477 :101DC000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA73 478 :101DD000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA63 479 :101DE000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA53 480 :101DF000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA43 481 :101E0000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA32 482 :101E1000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA22 483 :101E2000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA12 484 :101E3000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA02 485 :101E4000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF2 486 :101E5000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE2 487 :101E6000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2 488 :101E7000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC2 489 :101E8000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB2 490 :101E9000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2 491 :101EA000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA92 492 :101EB000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA82 493 :101EC000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA72 494 :101ED000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA62 495 :101EE000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA52 496 :101EF000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA42 497 :101F0000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA31 498 :101F1000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA21 499 :101F2000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA11 500 :101F3000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA01 501 :101F4000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF1 502 :101F5000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE1 503 :101F6000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD1 504 :101F7000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC1 505 :101F8000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1 506 :101F9000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1 507 :101FA000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA91 508 :101FB000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA81 509 :101FC000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA71 510 :101FD000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA61 511 :101FE000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA51 512 :101FF000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA41 -
new file contrib/r5000/r5ktest.c
- + 1 /* Copyright 2007 Alan Nisota <alannisota@gmail.com> 2 * 3 * This program is free software; you can redistribute it and/or 4 * modify it under the terms of the GNU General Public License as 5 * published by the Free Software Foundation; either version 2 of 6 * the License, or (at your option) any later version. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 17 #include <stdlib.h> 18 #include <stdio.h> 19 #include <sys/types.h> 20 #include <sys/stat.h> 21 #include <fcntl.h> 22 #include <string.h> 23 #include <getopt.h> 24 #include "r5000/r5000.h" 25 26 enum { 27 TOGGLE_POWER, 28 CHANGE_CHANNEL, 29 READ_STREAM, 30 MULTI_READ, 31 MULTI_OPEN, 32 OPEN_CLOSE, 33 SCAN_DEVICES, 34 TURN_ON, 35 TURN_OFF, 36 CHECK_POWER, 37 MAX_CMD, 38 }; 39 char cmd_names[][20] = { 40 {"TOGGLE_POWER"}, 41 {"CHANGE_CHANNEL"}, 42 {"READ_STREAM"}, 43 {"MULTI_READ"}, 44 {"MULTI_OPEN"}, 45 {"OPEN_CLOSE"}, 46 {"SCAN_DEVICES"}, 47 {"TURN_ON"}, 48 {"TURN_OFF"}, 49 {"CHECK_POWER"}, 50 }; 51 52 char stb_names[][20] = { 53 {"vip211"}, 54 {"directv"}, 55 {"hdd"}, 56 {"dsr"}, 57 {"vip622"}, 58 {0}, 59 }; 60 61 extern char strmfile[255]; 62 void help(char *cmdline) { 63 int i; 64 printf("%s <-t type> <--m command> [--c channel] [--s serial] [-h]\n", cmdline); 65 printf("\t-t/--type type : set STB type to type. 'type' can be either\n"); 66 printf("\t a numerical value or string. Valid types are:\n"); 67 for(i = 0; stb_names[i][0] != 0; i++) { 68 printf("\t\t%d: %s\n", i, stb_names[i]); 69 } 70 printf("\t-m/--cmd command : set command to execute. 'command' can be either\n"); 71 printf("\t a numerical value or string. Valid commands are:\n"); 72 for(i = 0; i < MAX_CMD; i++) { 73 printf("\t\t%d: %s\n", i, cmd_names[i]); 74 } 75 printf("\t-c/--channel : set channel to read (this does NOT tune\n"); 76 printf("\t-s/--serial serial : set serial number\n"); 77 printf("\t-h/--help : show this help message\n"); 78 exit(0); 79 } 80 81 void printstr(char *str) 82 { 83 fprintf(stderr, "%s", str); 84 } 85 86 static unsigned char buffer[1000189]; 87 static unsigned char *ptr = buffer; 88 unsigned int r5000_device_tspacket_handler(unsigned char *tspacket, int len, void *callback_data) 89 { 90 int fd = *(int *) callback_data; 91 if (len <= 0) 92 return 0; 93 if(memcpy(ptr, tspacket, len)); 94 ptr+=len; 95 if(ptr-buffer > 1000000) { 96 write(fd, buffer, ptr-buffer); 97 ptr = buffer; 98 } 99 return 1; 100 } 101 102 int main(int argc, char *argv[]) 103 { 104 r5kdev_t *usbdev = NULL; 105 int glblfd, i, j; 106 unsigned char buf[0x80]; 107 int stb = -1; 108 int cmd = -1; 109 const char *channel = NULL; 110 const char *serial = NULL; 111 int runtime = 10; 112 struct option long_options[] = { 113 {"type", required_argument, NULL, 't'}, 114 {"cmd", required_argument, NULL, 'm'}, 115 {"channel", required_argument, NULL, 'c'}, 116 {"serial", required_argument, NULL, 's'}, 117 {"time", required_argument, NULL, 'i'}, 118 {"dbgfile", required_argument, NULL, 'D'}, 119 {"help", no_argument , NULL, 'h'}, 120 {0, 0, 0, 0} 121 }; 122 while (1) { 123 char c; 124 c = getopt_long (argc, argv, 125 "t:m:c:s:hD:i:", 126 long_options, NULL); 127 if(c == EOF) 128 break; 129 switch(c) { 130 case 't': 131 { 132 char *ptr; 133 int i; 134 stb = strtol(optarg, &ptr, 10); 135 if(ptr == optarg) { 136 stb = -1; 137 for(i = 0; stb_names[i][0] != 0; i++) { 138 if(strncasecmp(optarg, stb_names[i], strlen(stb_names[i])) == 0) { 139 stb = i; 140 break; 141 } 142 } 143 if(stb == -1) { 144 fprintf(stderr, "Unknown STB type: %s\n", optarg); 145 exit(-1); 146 } 147 } else if(stb < 0 || stb >= R5K_STB_MAX) { 148 fprintf(stderr, "Illegal STB type: %d\n", stb); 149 exit(-1); 150 } 151 break; 152 } 153 case 'm': 154 { 155 char *ptr; 156 int i; 157 cmd = strtol(optarg, &ptr, 10); 158 if(ptr == optarg) { 159 cmd = -1; 160 for(i = 0; i < MAX_CMD; i++) { 161 if(strncasecmp(optarg, cmd_names[i], strlen(cmd_names[i])) == 0) { 162 cmd = i; 163 break; 164 } 165 } 166 if(cmd == -1) { 167 fprintf(stderr, "Unknown command: %d\n", optarg); 168 exit(-1); 169 } 170 } else if(cmd < 0 || cmd >= MAX_CMD) { 171 fprintf(stderr, "Illegal command: %d\n", cmd); 172 exit(-1); 173 } 174 break; 175 } 176 case 'c': 177 { 178 int ok = 1; 179 char *p; 180 if(! strlen(optarg)) { 181 fprintf(stderr, "Couldn't parse channel '%s'\n", channel); 182 ok = 0; 183 } 184 for(p = optarg; *p; p++) { 185 if(*p < '0' || *p > '9') { 186 fprintf(stderr, "Couldn't parse channel '%s'\n", channel); 187 ok = 0; 188 break; 189 } 190 } 191 if(ok) 192 channel = optarg; 193 break; 194 } 195 case 'i': 196 { 197 char *ptr; 198 runtime = strtol(optarg, &ptr, 0); 199 if(optarg == ptr) { 200 fprintf(stderr, "Couldn't parse time '%s'\n", optarg); 201 } 202 break; 203 } 204 case 's': 205 serial = optarg; 206 break; 207 case 'h': 208 help(argv[0]); 209 break; 210 case 'D': 211 #ifdef R5K_DEBUG 212 strncpy(strmfile, optarg, 255); 213 #else 214 fprintf(stderr, "--dbgfile only supported in debug mode.\nMake sure you know what you are doing!\n"); 215 exit(-1); 216 #endif 217 } 218 } 219 if(cmd == -1 || stb == -1) { 220 fprintf(stderr, "Must specify --cmd and --stb\n"); 221 exit(-1); 222 } 223 r5000_init(printstr); 224 if(cmd == SCAN_DEVICES) { 225 r5kenum_t devs; 226 printf("Scanning for R5000 devices\n"); 227 if(! r5000_find_stbs(&devs)) { 228 printf("Failed to initialize r5000 devices\n"); 229 } 230 for(i=0; i < devs.count; i++) { 231 printf("Found: %s\n", devs.serial[i]); 232 } 233 goto end; 234 } 235 usbdev = r5000_open(stb, r5000_device_tspacket_handler, &glblfd, serial); 236 if(! usbdev) { 237 fprintf(stderr, "R5000 device could not be found/opened\n"); 238 exit(-1); 239 } 240 glblfd=open("raw.ts", O_WRONLY | O_TRUNC | O_CREAT, 0666); 241 if(cmd == TOGGLE_POWER) { 242 int new_state; 243 printf("Toggling On/Off\n"); 244 new_state = r5000_toggle_on_off(usbdev); 245 printf("Turned power %s\n", new_state ? "On" : "Off"); 246 } 247 if(cmd == TURN_ON) { 248 int new_state; 249 printf("Turning STB On\n"); 250 new_state = r5000_power_on_off(usbdev, 1); 251 printf("Turned power %s\n", new_state ? "On" : "Off"); 252 } 253 if(cmd == TURN_OFF) { 254 int new_state; 255 printf("Turning STB Off\n"); 256 new_state = r5000_power_on_off(usbdev, 0); 257 printf("Turned power %s\n", new_state ? "On" : "Off"); 258 } 259 if(cmd == CHECK_POWER) { 260 int new_state; 261 new_state = r5000_get_power_state(usbdev); 262 printf("Power is currently %s\n", new_state ? "On" : "Off"); 263 } 264 if(cmd == CHANGE_CHANNEL) { 265 if(! channel) { 266 printf("Must specify a channel when using '-m CHANGE_CHANNEL'\n"); 267 exit(-1); 268 } 269 printf("Setting channel %s\n", channel); 270 r5000_change_channel(usbdev, channel, 0); 271 } 272 if(cmd == OPEN_CLOSE) { 273 int on_off; 274 printf("Doing open/close\n"); 275 on_off = r5000_get_power_state(usbdev); 276 printf("State1: %d\n", on_off); 277 r5000_close(usbdev); 278 printf("Closed\n"); 279 sleep(1); 280 usbdev = r5000_open(stb, r5000_device_tspacket_handler, &glblfd, serial); 281 printf("ReOpened\n"); 282 on_off = r5000_get_power_state(usbdev); 283 printf("State2: %d\n", on_off); 284 } 285 if(cmd == READ_STREAM || cmd == MULTI_READ) { 286 if(channel) { 287 uint c; 288 char *ptr; 289 printf("Setting channel %d\n"); 290 c = strtol(channel, &ptr, 0); 291 r5000_change_channel(usbdev, NULL, c); 292 } 293 printf("Reading stream\n"); 294 r5000_start_stream(usbdev); 295 time_t t = time(NULL); 296 while (time(NULL) - t < runtime) 297 { 298 // This will timeout after 1ms regardless of data availability 299 //usleep(10000); 300 r5000_loop_iterate(usbdev, 10); 301 } 302 r5000_stop_stream(usbdev); 303 } 304 if(cmd == MULTI_READ) { 305 printf("Reading stream again\n"); 306 close(glblfd); 307 glblfd=open("raw_1.ts", O_WRONLY | O_TRUNC | O_CREAT, 0666); 308 sleep(1); 309 r5000_start_stream(usbdev); 310 time_t t = time(NULL); 311 while (time(NULL) - t < 10) 312 { 313 // This will timeout after 1ms regardless of data availability 314 //usleep(10000); 315 r5000_loop_iterate(usbdev, 10); 316 } 317 r5000_stop_stream(usbdev); 318 } 319 if(cmd == MULTI_OPEN) { 320 printf("Doing multi-open\n"); 321 while(usbdev) { 322 time_t t; 323 r5000_start_stream(usbdev); 324 t = time(NULL); 325 while (time(NULL) - t < 2) 326 { 327 // This will timeout after 1ms regardless of data availability 328 //usleep(10000); 329 r5000_loop_iterate(usbdev, 10); 330 } 331 r5000_stop_stream(usbdev); 332 r5000_close(usbdev); 333 printf("Closed\n"); 334 sleep(1); 335 usbdev = r5000_open(stb, r5000_device_tspacket_handler, &glblfd, serial); 336 printf("ReOpened %s\n", serial); 337 } 338 r5000_start_stream(usbdev); 339 time_t t = time(NULL); 340 while (time(NULL) - t < 10) 341 { 342 // This will timeout after 1ms regardless of data availability 343 //usleep(10000); 344 r5000_loop_iterate(usbdev, 10); 345 } 346 r5000_stop_stream(usbdev); 347 } 348 end: 349 r5000_close(usbdev); 350 if(ptr != buffer) 351 write(glblfd, buffer, ptr-buffer); 352 close(glblfd); 353 } -
new file libs/libmythtv/r5000/r5k_vip_buttons.h
- + 1 struct r5000_buttons vip_button_cmd = 2 { 3 0x40, //len 4 400000, //delay 5 //button 0: 6 { 7 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 8 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 9 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 10 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 11 }, 12 //button 1: 13 { 14 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 15 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 16 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 17 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 18 }, 19 //button 2: 20 { 21 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 22 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 23 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 24 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 25 }, 26 //button 3: 27 { 28 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 29 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 30 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 31 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 32 }, 33 //button 4: 34 { 35 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 36 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 37 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 38 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 39 }, 40 //button 5: 41 { 42 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 43 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 44 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 45 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 46 }, 47 //button 6: 48 { 49 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 50 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 51 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 52 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 53 }, 54 //button 7: 55 { 56 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 57 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 58 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 59 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 60 }, 61 //button 8: 62 { 63 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 64 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 65 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 66 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 67 }, 68 //button 9: 69 { 70 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 71 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 72 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 73 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 74 }, 75 //Clear: 76 { 77 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 78 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 79 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 80 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 81 }, 82 //Enter: 83 { 84 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 85 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 86 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 87 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 88 }, 89 //Power 90 { 91 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 92 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 93 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 94 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 95 }, 96 //Power-On 97 { 98 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 99 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 100 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 101 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 102 }, 103 //Power-Off 104 { 105 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 106 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 107 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 108 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 109 }, 110 }; -
new file contrib/r5000/README
- + 1 ehci-2.6.25.patch: 2 This patch is needed for all kernels earlier than 2.6.26. It adds support 3 for 1024 byte frames which the R5000 needs. As of 2.6.26 the patch is already 4 in the kernel. 5 6 r5ktest: 7 Compile r5ktest via: 8 gcc -g -o r5ktest -I../../libs/libmythtv r5ktest.c ../../libs/libmythtv/r5000/*.c -lusb 9 10 ############################################################################### 11 ############################################################################### 12 In order to use the R5000 in linux, you must 1st load the firmware into the 13 device. 14 Make sure you have the following installed: 15 lsusb (in Debian/Ubuntu this is in the usbutils package) 16 fxload 17 1) Locate the device using lsusb: 18 lsusb 19 ... 20 Bus 001 Device 026: ID 04b4:8613 Cypress Semiconductor Corp. CY7C68013 EZ-USB FX2 USB 2.0 Development Kit 21 2)Install the firmware (this often needs to be done via sudo/root) 22 (depending on where usbfs is mounted): 23 fxload -t fx2 -D /dev/bus/usb/001/026 -I r5000.hex -m 0666 24 or 25 fxload -t fx2 -D /proc/bus/usb/001/026 -I r5000.hex -m 0666 26 (note that 001 is the Bus and 026 is the Device from lsusb) 27 28 3) Ensure that the firmware loaded: 29 lsusb 30 ... 31 Bus 001 Device 028: ID 0547:1002 Anchor Chips, Inc. 32 (Note that is has a completely different name now) 33 34 4)ensure that the usbtest module did not load: 35 lsmod | grep usbtest 36 If you see the usbtest module you'll need to blacklist it and/or rmmod it 37 ############################################################################### 38 ############################################################################### 39 40 Before trying to use the R5000 in mythtv, make sure it is working in r5ktest 41 ./r5ktest -t 0 -m 6 42 Scanning for R5000 devices 43 Found: xxxxxxx 44 45 If you see something like: 46 R5000 initialization failed at stage 1: 47 Expected 1 bytes, but got -1 bytes 48 R5000 failed to locate any R5000 devices. Are you sure you have 49 permissions set properly? 50 Then you likely do not have permissions to access the usb device. Try running 51 as root. 52 53 next do: 54 ./r5ktest --help 55 and choose the correct type for your STB: 56 vip211 : VIP211 and VIP411 57 vip622 : VIP622, VIP722, BEV9242 58 hdd: 59 dsr: 60 directv: 61 62 Now try a few commands to make sure they work properly: 63 ./r5ktest --type vip211 --cmd TURN_ON 64 ./r5ktest --type vip211 --cmd TURN_OFF 65 ./r5ktest --type vip211 --cmd CHANGE_CHANNEL -c <channel number> 66 ./r5ktest --type vip211 --cmd OPEN_CLOSE 67 68 ############################################################################### 69 ############################################################################### 70 71 Configure mythtv: 72 Go into myth-setup and select the R5000 device, and the relevant STB. 73 Configure a Video Source 74 Configure an Input 75 To enter channels, the easiest way is to set up scehdules-direct with the provider/channels you receieve then import them from the Card-Input menu 76 If you choose to enter them yourself, make sure to set the frequency to whatever needs to be punched into the remote to select the channel 77 78 Some notes: 79 Only ViP style STBs (Dish Network and BEV) and DirectTV STBs have channel-change capabilities. Others need an external program 80 81 At least on the ViP211, it is necessary to disable the auto-power-off on the STB, as the box will power off but the LED will remain on, and the R5000 module won't be able to detect teh power state properly. I'm not sure whether this applies to other boxes or not. 82
