Ticket #4752: r5000_r16.patch
| File r5000_r16.patch, 179.8 KB (added by anonymous, 3 years ago) |
|---|
-
configure
old new 158 158 echo " --disable-v4l disable Video4Linux support" 159 159 echo " --disable-ivtv disable ivtv support (PVR-x50) req. v4l support" 160 160 echo " --disable-dvb disable DVB support" 161 echo " --disable-r5000 disable support for R5000 USB STBs" 161 162 echo " --dvb-path=HDRLOC location of directory containing" 162 163 echo " 'linux/dvb/frontend.h', not the" 163 164 echo " directory with frontend.h [$dvb_path]" … … 891 892 hdhomerun 892 893 iptv 893 894 ivtv 895 r5000 894 896 joystick_menu 895 897 libfftw3 896 898 lirc … … 1046 1048 dbox2_deps="backend" 1047 1049 dvb_deps="backend" 1048 1050 firewire_deps="backend" 1051 r5000_deps="backend" 1049 1052 iptv_deps="backend" 1050 1053 ivtv_deps="backend v4l" 1051 1054 hdhomerun_deps="backend" … … 1179 1182 hdhomerun="yes" 1180 1183 iptv="yes" 1181 1184 ivtv="yes" 1185 r5000="yes" 1182 1186 joystick_menu="default" 1183 1187 lamemp3="yes" 1184 1188 lirc="yes" … … 2717 2721 enabled libfftw3 && has_library libfftw3_threads && has_header fftw3.h || 2718 2722 disable libfftw3 2719 2723 2724 enabled r5000 && has_library libusb && check_header usb.h || disable r5000 2725 2720 2726 enabled x11 && has_library libX11 || disable x11 2721 2727 enabled xrandr && has_header X11/extensions/Xrandr.h || disable xrandr 2722 2728 enabled xv && has_library libXv || disable xv … … 2998 3004 echo "DBox2 support ${dbox2-no}" 2999 3005 echo "HDHomeRun support ${hdhomerun-no}" 3000 3006 echo "IPTV support ${iptv-no}" 3007 echo "R5000 support ${r5000-no}" 3001 3008 fi 3002 3009 3003 3010 if enabled frontend; then -
libs/libmythtv/cardutil.h
old new 53 53 FIREWIRE, 54 54 HDHOMERUN, 55 55 FREEBOX, 56 R5000, 56 57 }; 57 58 58 59 static enum CARD_TYPES toCardType(const QString &name) … … 81 82 return HDHOMERUN; 82 83 if ("FREEBOX" == name) 83 84 return FREEBOX; 85 if ("R5000" == name) 86 return R5000; 84 87 return ERROR_UNKNOWN; 85 88 } 86 89 … … 89 92 return 90 93 (rawtype != "DVB") && 91 94 (rawtype != "FIREWIRE") && (rawtype != "DBOX2") && 92 (rawtype != "HDHOMERUN") && (rawtype != "FREEBOX"); 95 (rawtype != "HDHOMERUN") && (rawtype != "FREEBOX") && 96 (rawtype != "R5000"); 93 97 } 94 98 95 99 static bool IsUnscanable(const QString &rawtype) 96 100 { 97 101 return 98 (rawtype == "FIREWIRE") || (rawtype == "DBOX2"); 102 (rawtype == "FIREWIRE") || (rawtype == "DBOX2") || 103 (rawtype == "R5000"); 99 104 } 100 105 101 106 static bool IsEITCapable(const QString &rawtype) -
libs/libmythtv/libmythtv.pro
old new 496 496 DEFINES += USING_DVB 497 497 } 498 498 499 #Support for R5000 usb device 500 using_r5000 { 501 HEADERS += r5000channel.h r5000recorder.h 502 HEADERS += r5000signalmonitor.h r5000device.h 503 HEADERS += r5000/r5000.h r5000/libusb_augment.h 504 HEADERS += r5000/r5000_internal.h r5000/r5000init.h 505 506 SOURCES += r5000channel.cpp r5000recorder.cpp 507 SOURCES += r5000signalmonitor.cpp r5000device.cpp 508 SOURCES += r5000/r5000.c r5000/libusb_augment.c 509 SOURCES += r5000/r5k_vip.c r5000/r5k_directv.c 510 SOURCES += r5000/r5k_sat.c r5000/r5k_misc.c 511 512 LIBS += -lusb 513 DEFINES += USING_R5000 514 } 515 499 516 DEFINES += USING_BACKEND 500 517 } 501 518 -
libs/libmythtv/signalmonitor.h
old new 297 297 (cardtype.upper() == "HDTV") || 298 298 (cardtype.upper() == "HDHOMERUN") || 299 299 (cardtype.upper() == "FIREWIRE") || 300 (cardtype.upper() == "FREEBOX")); 300 (cardtype.upper() == "FREEBOX") || 301 (cardtype.upper() == "R5000")); 301 302 } 302 303 303 304 inline bool SignalMonitor::IsSupported(const QString &cardtype) -
libs/libmythtv/signalmonitor.cpp
old new 41 41 # include "firewirechannel.h" 42 42 #endif 43 43 44 #ifdef USING_R5000 45 # include "r5000signalmonitor.h" 46 # include "r5000channel.h" 47 #endif 48 44 49 #undef DBG_SM 45 50 #define DBG_SM(FUNC, MSG) VERBOSE(VB_CHANNEL, \ 46 51 "SM("<<channel->GetDevice()<<")::"<<FUNC<<": "<<MSG); … … 127 132 signalMonitor = new FirewireSignalMonitor(db_cardnum, fc); 128 133 } 129 134 #endif 135 #ifdef USING_R5000 136 if (cardtype.upper() == "R5000") 137 { 138 R5000Channel *fc = dynamic_cast<R5000Channel*>(channel); 139 if (fc) 140 signalMonitor = new R5000SignalMonitor(db_cardnum, fc); 141 } 142 #endif 130 143 131 144 if (!signalMonitor) 132 145 { -
libs/libmythtv/cardutil.cpp
old new 1457 1457 if (("FIREWIRE" == cardtype) || 1458 1458 ("FREEBOX" == cardtype) || 1459 1459 ("DBOX2" == cardtype) || 1460 ("HDHOMERUN" == cardtype)) 1460 ("HDHOMERUN" == cardtype) || 1461 ("R5000" == cardtype)) 1461 1462 { 1462 1463 ret += "MPEG2TS"; 1463 1464 } … … 1582 1583 if (("FIREWIRE" == cardtype) || 1583 1584 ("FREEBOX" == cardtype) || 1584 1585 ("DBOX2" == cardtype) || 1585 ("HDHOMERUN" == cardtype)) 1586 ("HDHOMERUN" == cardtype) || 1587 ("R5000" == cardtype)) 1586 1588 { 1587 1589 inputs += "MPEG2TS"; 1588 1590 } -
libs/libmythtv/videosource.cpp
old new 36 36 #include "frequencies.h" 37 37 #include "diseqcsettings.h" 38 38 #include "firewiredevice.h" 39 #include "r5000device.h" 39 40 #include "compat.h" 40 41 41 42 … … 1299 1300 } 1300 1301 }; 1301 1302 1303 class R5000Serial : public ComboBoxSetting, public CaptureCardDBStorage 1304 { 1305 public: 1306 R5000Serial(const CaptureCard &parent) : 1307 ComboBoxSetting(this), 1308 CaptureCardDBStorage(this, parent, "videodevice") 1309 { 1310 setLabel(QObject::tr("Serial #")); 1311 #ifdef USING_R5000 1312 QStringList serials = R5000Device::GetSTBList(); 1313 for (uint i = 0; i < serials.size(); i++) 1314 { 1315 addSelection(serials[i]); 1316 } 1317 #endif // USING_FIREWIRE 1318 } 1319 }; 1320 1321 class R5000Model : public ComboBoxSetting, public CaptureCardDBStorage 1322 { 1323 public: 1324 R5000Model(const CaptureCard &parent) : 1325 ComboBoxSetting(this), 1326 CaptureCardDBStorage(this, parent, "firewire_model") 1327 { 1328 setLabel(QObject::tr("R5000 STB type")); 1329 addSelection("VIP211"); 1330 addSelection("VIP411"); 1331 addSelection("VIP622"); 1332 addSelection("VIP722"); 1333 addSelection("BEV9242"); 1334 addSelection("DIRECTV"); 1335 addSelection("STARCHOICE/DSR"); 1336 addSelection("HDD-200"); 1337 QString help = QObject::tr( 1338 "Choose the type of R5000 enabled STB you are using."); 1339 setHelpText(help); 1340 } 1341 }; 1342 class R5000ConfigurationGroup : public VerticalConfigurationGroup 1343 { 1344 public: 1345 R5000ConfigurationGroup(CaptureCard& a_parent): 1346 VerticalConfigurationGroup(false, true, false, false), 1347 parent(a_parent) 1348 { 1349 setUseLabel(false); 1350 addChild(new R5000Serial(parent)); 1351 addChild(new R5000Model(parent)); 1352 addChild(new SingleCardInput(parent)); 1353 }; 1354 1355 private: 1356 CaptureCard &parent; 1357 }; 1358 1302 1359 class IPTVHost : public LineEditSetting, public CaptureCardDBStorage 1303 1360 { 1304 1361 public: … … 1483 1540 #ifdef USING_IPTV 1484 1541 addTarget("FREEBOX", new IPTVConfigurationGroup(parent)); 1485 1542 #endif // USING_IPTV 1543 1544 #ifdef USING_R5000 1545 addTarget("R5000", new R5000ConfigurationGroup(parent)); 1546 #endif // USING_R5000 1486 1547 } 1487 1548 1488 1549 void CaptureCardGroup::triggerChanged(const QString& value) … … 1670 1731 #ifdef USING_IPTV 1671 1732 setting->addSelection(QObject::tr("Network Recorder"), "FREEBOX"); 1672 1733 #endif // USING_IPTV 1734 1735 #ifdef USING_R5000 1736 setting->addSelection(QObject::tr("R5000 Capable STB"), "R5000"); 1737 #endif // USING_R5000 1673 1738 } 1674 1739 1675 1740 class CardID : public SelectLabelSetting, public CardInputDBStorage -
libs/libmythtv/tv_rec.cpp
old new 50 50 #include "hdhrchannel.h" 51 51 #include "iptvchannel.h" 52 52 #include "firewirechannel.h" 53 #include "r5000channel.h" 53 54 54 55 #include "recorderbase.h" 55 56 #include "NuppelVideoRecorder.h" … … 59 60 #include "hdhrrecorder.h" 60 61 #include "iptvrecorder.h" 61 62 #include "firewirerecorder.h" 63 #include "r5000recorder.h" 62 64 63 65 #ifdef USING_V4L 64 66 #include "channel.h" … … 199 201 init_run = true; 200 202 #endif 201 203 } 204 else if (genOpt.cardtype == "R5000") 205 { 206 #ifdef USING_R5000 207 channel = new R5000Channel(this, genOpt.videodev, fwOpt.model); 208 if (!channel->Open()) 209 return false; 210 InitChannel(genOpt.defaultinput, startchannel); 211 init_run = true; 212 #endif 213 } 202 214 else // "V4L" or "MPEG", ie, analog TV 203 215 { 204 216 #ifdef USING_V4L … … 1017 1029 recorder->SetOption("mrl", genOpt.videodev); 1018 1030 #endif // USING_IPTV 1019 1031 } 1032 else if (genOpt.cardtype == "R5000") 1033 { 1034 #ifdef USING_R5000 1035 recorder = new R5000Recorder(this, GetR5000Channel()); 1036 #endif // USING_R5000 1037 } 1020 1038 else 1021 1039 { 1022 1040 #ifdef USING_V4L … … 1230 1248 #endif // USING_FIREWIRE 1231 1249 } 1232 1250 1251 R5000Channel *TVRec::GetR5000Channel(void) 1252 { 1253 #ifdef USING_R5000 1254 return dynamic_cast<R5000Channel*>(channel); 1255 #else 1256 return NULL; 1257 #endif // USING_R5000 1258 } 1259 1233 1260 Channel *TVRec::GetV4LChannel(void) 1234 1261 { 1235 1262 #ifdef USING_V4L -
libs/libmythtv/transporteditor.cpp
old new 735 735 left->addChild(new Modulation(id, nType)); 736 736 } 737 737 else if ((CardUtil::FIREWIRE == nType) || 738 (CardUtil::FREEBOX == nType)) 738 (CardUtil::FREEBOX == nType) || 739 (CardUtil::R5000 == nType)) 739 740 { 740 741 left->addChild(new DTVStandard(id, true, true)); 741 742 } -
libs/libmythtv/tv_rec.h
old new 39 39 class FirewireChannel; 40 40 class Channel; 41 41 class HDHRChannel; 42 class R5000Channel; 42 43 43 44 class MPEGStreamData; 44 45 class ProgramMapTable; … … 281 282 HDHRChannel *GetHDHRChannel(void); 282 283 DVBChannel *GetDVBChannel(void); 283 284 FirewireChannel *GetFirewireChannel(void); 285 R5000Channel *GetR5000Channel(void); 284 286 Channel *GetV4LChannel(void); 285 287 286 288 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 curchannelname = QDeepCopy<QString>(channum); 87 (*it)->startChanNum = QDeepCopy<QString>(channum); 88 } 89 90 VERBOSE(VB_CHANNEL, loc + " " + ((ok) ? "success" : "failure")); 91 92 return ok; 93 } 94 95 bool R5000Channel::Open(void) 96 { 97 VERBOSE(VB_CHANNEL, LOC + "Open()"); 98 99 if (inputs.find(currentInputID) == inputs.end()) 100 return false; 101 102 if (!device) 103 return false; 104 105 if (isopen) 106 return true; 107 108 if (!device->OpenPort()) 109 return false; 110 111 isopen = true; 112 113 return true; 114 } 115 116 void R5000Channel::Close(void) 117 { 118 VERBOSE(VB_CHANNEL, LOC + "Close()"); 119 if (isopen) 120 { 121 device->ClosePort(); 122 isopen = false; 123 } 124 } 125 126 QString R5000Channel::GetDevice(void) const 127 { 128 return videodevice; 129 } 130 131 bool R5000Channel::SetPowerState(bool on) 132 { 133 if (!isopen) 134 { 135 VERBOSE(VB_IMPORTANT, LOC_ERR + 136 "SetPowerState() called on closed R5000Channel."); 137 138 return false; 139 } 140 141 return device->SetPowerState(on); 142 } 143 144 R5000Device::PowerState R5000Channel::GetPowerState(void) const 145 { 146 if (!isopen) 147 { 148 VERBOSE(VB_IMPORTANT, LOC_ERR + 149 "GetPowerState() called on closed R5000Channel."); 150 151 return R5000Device::kAVCPowerQueryFailed; 152 } 153 154 return device->GetPowerState(); 155 } 156 157 bool R5000Channel::Retune(void) 158 { 159 VERBOSE(VB_CHANNEL, LOC + "Retune()"); 160 161 if (R5000Device::kAVCPowerOff == GetPowerState()) 162 { 163 VERBOSE(VB_IMPORTANT, LOC_ERR + 164 "STB is turned off, must be on to retune."); 165 166 return false; 167 } 168 169 if (current_channel) 170 return SetChannelByNumber(current_channel, current_mpeg_prog); 171 172 return false; 173 } 174 175 bool R5000Channel::SetChannelByNumber(const QString &channel, int mpeg_prog) 176 { 177 VERBOSE(VB_CHANNEL, QString("SetChannelByNumber(%1)").arg(channel)); 178 current_channel = channel; 179 current_mpeg_prog = mpeg_prog; 180 181 if (R5000Device::kAVCPowerOff == GetPowerState()) 182 { 183 VERBOSE(VB_IMPORTANT, LOC_WARN + 184 "STB is turned off, must be on to set channel."); 185 186 SetSIStandard("mpeg"); 187 SetDTVInfo(0,0,0,0,1); 188 189 return true; // signal monitor will call retune later... 190 } 191 192 if (!device->SetChannel(fw_opts.model, channel, mpeg_prog)) 193 return false; 194 195 SetSIStandard("mpeg"); 196 SetDTVInfo(0,0,0,0,1); 197 198 return true; 199 } -
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 // Qt headers 9 #include <qdeepcopy.h> 10 11 // MythTV headers 12 #include "r5000device.h" 13 #include "mythcontext.h" 14 #include "pespacket.h" 15 16 #define LOC QString("R5kDev: ") 17 #define LOC_WARN QString("R5kDev, Warning: ") 18 #define LOC_ERR QString("R5kDev, Error: ") 19 20 static int r5k_init = 0; 21 QMap<uint64_t,QString> R5000Device::s_id_to_model; 22 QMutex R5000Device::s_static_lock; 23 24 unsigned int r5000_device_tspacket_handler(unsigned char *tspacket, int len, void *callback_data) 25 { 26 R5000Device *fw = (R5000Device*) callback_data; 27 if (! fw) 28 return 0; 29 if (len > 0) 30 fw->BroadcastToListeners(tspacket, len); 31 return 1; 32 } 33 34 void r5000_msg(char * msg) 35 { 36 VERBOSE(VB_IMPORTANT, "R5kLib: "<<msg); 37 } 38 39 class R5kPriv 40 { 41 public: 42 R5kPriv() : 43 reset_timer_on(false), 44 run_port_handler(false), is_port_handler_running(false), 45 channel(-1), 46 is_streaming(false) 47 { 48 } 49 50 bool reset_timer_on; 51 MythTimer reset_timer; 52 53 bool run_port_handler; 54 bool is_port_handler_running; 55 QMutex start_stop_port_handler_lock; 56 57 int channel; 58 59 bool is_streaming; 60 61 QDateTime stop_streaming_timer; 62 pthread_t port_handler_thread; 63 64 static QMutex s_lock; 65 }; 66 QMutex R5kPriv::s_lock; 67 68 //callback functions 69 void *r5000_device_port_handler_thunk(void *param); 70 71 R5000Device::R5000Device(int type, QString serial) : 72 m_type(type), 73 m_serial(serial), 74 m_last_channel(""), m_last_crc(0), 75 m_buffer_cleared(true), m_open_port_cnt(0), 76 m_lock(false), m_priv(new R5kPriv()) 77 { 78 QMutexLocker locker(&s_static_lock); 79 usbdev = NULL; 80 if(! r5k_init) 81 r5k_init = r5000_init(r5000_msg); 82 } 83 84 R5000Device::~R5000Device() 85 { 86 if (usbdev) 87 { 88 VERBOSE(VB_IMPORTANT, LOC_ERR + "ctor called with open port"); 89 while(usbdev) 90 ClosePort(); 91 } 92 93 if (m_priv) 94 { 95 delete m_priv; 96 m_priv = NULL; 97 } 98 } 99 100 void R5000Device::AddListener(TSDataListener *listener) 101 { 102 if (listener) 103 { 104 vector<TSDataListener*>::iterator it = 105 find(m_listeners.begin(), m_listeners.end(), listener); 106 107 if (it == m_listeners.end()) 108 m_listeners.push_back(listener); 109 } 110 111 VERBOSE(VB_RECORD, LOC + "AddListener() "<<m_listeners.size()); 112 if (!m_listeners.empty()) 113 { 114 StartStreaming(); 115 } 116 } 117 118 void R5000Device::RemoveListener(TSDataListener *listener) 119 { 120 vector<TSDataListener*>::iterator it = m_listeners.end(); 121 122 do 123 { 124 it = find(m_listeners.begin(), m_listeners.end(), listener); 125 if (it != m_listeners.end()) 126 m_listeners.erase(it); 127 } 128 while (it != m_listeners.end()); 129 130 VERBOSE(VB_RECORD, LOC + "RemoveListener() "<<m_listeners.size()); 131 if (m_listeners.empty()) 132 { 133 StopStreaming(); 134 } 135 } 136 137 bool R5000Device::StartStreaming(void) 138 { 139 if (m_priv->is_streaming) 140 return m_priv->is_streaming; 141 142 if (! usbdev) 143 { 144 VERBOSE(VB_IMPORTANT, LOC_ERR + "Device not open"); 145 return false; 146 } 147 if (r5000_start_stream(usbdev)) 148 { 149 m_priv->is_streaming = true; 150 } 151 else 152 { 153 VERBOSE(VB_IMPORTANT, LOC_ERR + "Starting A/V streaming "); 154 } 155 156 VERBOSE(VB_RECORD, LOC + "Starting A/V streaming -- done"); 157 158 return m_priv->is_streaming; 159 } 160 161 bool R5000Device::StopStreaming(void) 162 { 163 if (m_priv->is_streaming) 164 { 165 VERBOSE(VB_RECORD, LOC + "Stopping A/V streaming -- really"); 166 167 m_priv->is_streaming = false; 168 169 r5000_stop_stream(usbdev); 170 } 171 172 VERBOSE(VB_RECORD, LOC + "Stopped A/V streaming"); 173 174 return true; 175 } 176 177 bool R5000Device::SetPowerState(bool on) 178 { 179 QMutexLocker locker(&m_lock); 180 QString cmdStr = (on) ? "on" : "off"; 181 VERBOSE(VB_RECORD, LOC + QString("Powering %1").arg(cmdStr)); 182 r5000_power_on_off(usbdev, on); 183 return true; 184 } 185 186 R5000Device::PowerState R5000Device::GetPowerState(void) 187 { 188 QMutexLocker locker(&m_lock); 189 int on_off; 190 191 VERBOSE(VB_CHANNEL, LOC + "Requesting STB Power State"); 192 on_off = r5000_get_power_state(usbdev); 193 VERBOSE(VB_CHANNEL, LOC + (on_off ? "On" : "Off")); 194 return on_off ? kAVCPowerOn : kAVCPowerOff; 195 } 196 197 bool R5000Device::SetChannel(const QString &panel_model, 198 const QString &channel, uint mpeg_prog) 199 { 200 VERBOSE(VB_CHANNEL, QString("SetChannel(model %1, chan %2 mpeg_prog %3)") 201 .arg(panel_model).arg(channel).arg(mpeg_prog)); 202 203 QMutexLocker locker(&m_lock); 204 VERBOSE(VB_CHANNEL, "SetChannel() -- locked"); 205 if(! r5000_change_channel(usbdev, channel.ascii(), mpeg_prog)) 206 VERBOSE(VB_IMPORTANT, LOC + "Failed to set channel"); 207 return true; 208 } 209 210 void R5000Device::BroadcastToListeners( 211 const unsigned char *data, uint dataSize) 212 { 213 if ((dataSize >= TSPacket::SIZE) && (data[0] == SYNC_BYTE) && 214 ((data[1] & 0x1f) == 0) && (data[2] == 0)) 215 { 216 ProcessPATPacket(*((const TSPacket*)data)); 217 } 218 219 vector<TSDataListener*>::iterator it = m_listeners.begin(); 220 for (; it != m_listeners.end(); ++it) 221 (*it)->AddData(data, dataSize); 222 } 223 224 void R5000Device::SetLastChannel(const QString &channel) 225 { 226 m_buffer_cleared = (channel == m_last_channel); 227 m_last_channel = channel; 228 229 VERBOSE(VB_IMPORTANT, QString("SetLastChannel(%1): cleared: %2") 230 .arg(channel).arg(m_buffer_cleared ? "yes" : "no")); 231 } 232 233 void R5000Device::ProcessPATPacket(const TSPacket &tspacket) 234 { 235 if (!tspacket.TransportError() && !tspacket.ScramplingControl() && 236 tspacket.HasPayload() && tspacket.PayloadStart() && !tspacket.PID()) 237 { 238 PESPacket pes = PESPacket::View(tspacket); 239 uint crc = pes.CalcCRC(); 240 m_buffer_cleared |= (crc != m_last_crc); 241 m_last_crc = crc; 242 #if 0 243 VERBOSE(VB_RECORD, LOC + 244 QString("ProcessPATPacket: CRC 0x%1 cleared: %2") 245 .arg(crc,0,16).arg(m_buffer_cleared ? "yes" : "no")); 246 #endif 247 } 248 else 249 { 250 VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't handle large PAT's"); 251 } 252 } 253 254 QString R5000Device::GetModelName(uint vendor_id, uint model_id) 255 { 256 QMutexLocker locker(&s_static_lock); 257 /* 258 if (s_id_to_model.empty()) 259 fw_init(s_id_to_model); 260 261 QString ret = s_id_to_model[(((uint64_t) vendor_id) << 32) | model_id]; 262 263 if (ret.isEmpty()) 264 return "GENERIC"; 265 */ 266 return "R5000"; 267 } 268 269 bool R5000Device::IsSTBSupported(const QString &panel_model) 270 { 271 return true; 272 } 273 274 bool R5000Device::OpenPort(void) 275 { 276 VERBOSE(VB_RECORD, LOC + "Starting Port Handler Thread"); 277 QMutexLocker mlocker(&m_lock); 278 VERBOSE(VB_RECORD, LOC + "Starting Port Handler Thread -- locked"); 279 if(usbdev) { 280 m_open_port_cnt++; 281 return true; 282 } 283 284 if(m_serial) { 285 VERBOSE(VB_RECORD, LOC + QString("Opening R5000 device type %1 with serial#: "+ m_serial).arg(m_type)); 286 usbdev = r5000_open((r5ktype_t)m_type, r5000_device_tspacket_handler, this, m_serial.ascii()); 287 } else { 288 VERBOSE(VB_RECORD, LOC + "Opening R5000 device with unknown serial#"); 289 usbdev = r5000_open((r5ktype_t)m_type, r5000_device_tspacket_handler, this, NULL); 290 } 291 if(! usbdev) { 292 VERBOSE(VB_IMPORTANT, LOC + "Failed to open R5000 device"); 293 return false; 294 } 295 296 VERBOSE(VB_RECORD, LOC + "Starting port handler thread"); 297 m_priv->run_port_handler = true; 298 pthread_create(&m_priv->port_handler_thread, NULL, 299 r5000_device_port_handler_thunk, this); 300 301 VERBOSE(VB_RECORD, LOC + "Waiting for port handler thread to start"); 302 while (!m_priv->is_port_handler_running) 303 { 304 m_lock.unlock(); 305 usleep(5000); 306 m_lock.lock(); 307 } 308 309 VERBOSE(VB_RECORD, LOC + "Port handler thread started"); 310 311 m_open_port_cnt++; 312 313 return true; 314 } 315 316 bool R5000Device::ClosePort(void) 317 { 318 VERBOSE(VB_RECORD, LOC + "Stopping Port Handler Thread"); 319 QMutexLocker locker(&m_priv->start_stop_port_handler_lock); 320 VERBOSE(VB_RECORD, LOC + "Stopping Port Handler Thread -- locked"); 321 322 QMutexLocker mlocker(&m_lock); 323 324 VERBOSE(VB_RECORD, LOC + "ClosePort()"); 325 326 if (m_open_port_cnt < 1) 327 return false; 328 329 m_open_port_cnt--; 330 331 if (m_open_port_cnt != 0) 332 return true; 333 334 if (!usbdev) 335 return false; 336 337 VERBOSE(VB_RECORD, LOC + "Waiting for port handler thread to stop"); 338 m_priv->run_port_handler = false; 339 while (m_priv->is_port_handler_running) 340 { 341 m_lock.unlock(); 342 usleep(5000); 343 m_lock.lock(); 344 } 345 VERBOSE(VB_RECORD, LOC + "Joining port handler thread"); 346 pthread_join(m_priv->port_handler_thread, NULL); 347 348 r5000_close(usbdev); 349 usbdev = NULL; 350 351 return true; 352 } 353 354 void *r5000_device_port_handler_thunk(void *param) 355 { 356 R5000Device *mon = (R5000Device*) param; 357 mon->RunPortHandler(); 358 return NULL; 359 } 360 361 void R5000Device::RunPortHandler(void) 362 { 363 VERBOSE(VB_RECORD, LOC + "RunPortHandler -- start"); 364 m_lock.lock(); 365 VERBOSE(VB_RECORD, LOC + "RunPortHandler -- got first lock"); 366 m_priv->is_port_handler_running = true; 367 m_lock.unlock(); 368 369 while (m_priv->run_port_handler) 370 { 371 if (m_priv->is_streaming) { 372 // This will timeout after 10ms regardless of data availability 373 r5000_loop_iterate(usbdev, 10); 374 } else { 375 usleep(10000); 376 } 377 } 378 379 m_lock.lock(); 380 m_priv->is_port_handler_running = false; 381 m_lock.unlock(); 382 VERBOSE(VB_RECORD, LOC + "RunPortHandler -- end"); 383 } 384 385 QStringList R5000Device::GetSTBList(void) 386 { 387 QStringList STBList; 388 int i; 389 r5kenum_t r5k_stbs; 390 if(! r5k_init) { 391 r5k_init = r5000_init(r5000_msg); 392 if(! r5k_init) 393 return STBList; 394 } 395 if (! r5000_find_stbs(&r5k_stbs)) 396 VERBOSE(VB_IMPORTANT, LOC + "Locating R5000 devices failed." 397 " This may be a permission problem"); 398 399 for (i = 0; i < r5k_stbs.count; i++) 400 STBList.append((char *)r5k_stbs.serial[i]); 401 return STBList; 402 } 403 404 int R5000Device::GetDeviceType(const QString &r5ktype) 405 { 406 QString type = r5ktype.upper(); 407 if(type == "DIRECTV") { 408 return R5K_STB_DIRECTV; 409 } else if(type == "VIP211/VIP622/DISH411" || 410 type == "VIP211/VIP422" || 411 type == "VIP211" || 412 type == "VIP411") { 413 return R5K_STB_VIP211; 414 } else if(type == "STARCHOICE/DSR") { 415 return R5K_STB_DSR; 416 } else if(type == "HDD-200") { 417 return R5K_STB_HDD; 418 } else if(type == "VIP622" || 419 type == "VIP722" || 420 type == "BEV9242") { 421 return R5K_STB_VIP622; 422 } else { 423 return R5K_STB_VIP211; 424 } 425 } -
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 unpauseWait.wait(timeout); 185 } 186 if (!request_pause && paused) 187 { 188 VERBOSE(VB_RECORD, LOC + "PauseAndWait("<<timeout<<") -- unpause"); 189 StartStreaming(); 190 paused = false; 191 } 192 return paused; 193 } 194 195 void R5000Recorder::SetStreamData(MPEGStreamData *data) 196 { 197 VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- begin"); 198 if (data == _mpeg_stream_data) 199 { 200 VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 0"); 201 return; 202 } 203 204 MPEGStreamData *old_data = _mpeg_stream_data; 205 _mpeg_stream_data = data; 206 if (old_data) 207 delete old_data; 208 209 if (data) 210 { 211 data->AddMPEGSPListener(this); 212 213 if (data->DesiredProgram() >= 0) 214 data->SetDesiredProgram(data->DesiredProgram()); 215 } 216 VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 1"); 217 } 218 219 void R5000Recorder::HandleSingleProgramPAT(ProgramAssociationTable *pat) 220 { 221 if (!pat) { 222 VERBOSE(VB_RECORD, LOC + "HandleSingleProgramPAT(NULL)"); 223 return; 224 } 225 int next = (pat->tsheader()->ContinuityCounter()+1)&0xf; 226 pat->tsheader()->SetContinuityCounter(next); 227 BufferedWrite(*(reinterpret_cast<const TSPacket*>(pat->tsheader()))); 228 } 229 230 void R5000Recorder::HandleSingleProgramPMT(ProgramMapTable *pmt) 231 { 232 if (!pmt) { 233 VERBOSE(VB_RECORD, LOC + "HandleSingleProgramPMT(NULL)"); 234 return; 235 } 236 int next = (pmt->tsheader()->ContinuityCounter()+1)&0xf; 237 pmt->tsheader()->SetContinuityCounter(next); 238 BufferedWrite(*(reinterpret_cast<const TSPacket*>(pmt->tsheader()))); 239 } -
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, _name), 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(kDTVSigMon_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 void R5000SignalMonitor::deleteLater(void) 72 { 73 disconnect(); // disconnect signals we may be sending... 74 Stop(); 75 DTVSignalMonitor::deleteLater(); 76 } 77 78 /** \fn R5000SignalMonitor::Stop(void) 79 * \brief Stop signal monitoring and table monitoring threads. 80 */ 81 void R5000SignalMonitor::Stop(void) 82 { 83 VERBOSE(VB_CHANNEL, LOC + "Stop() -- begin"); 84 SignalMonitor::Stop(); 85 if (dtvMonitorRunning) 86 { 87 dtvMonitorRunning = false; 88 pthread_join(table_monitor_thread, NULL); 89 } 90 VERBOSE(VB_CHANNEL, LOC + "Stop() -- end"); 91 } 92 93 void R5000SignalMonitor::HandlePAT(const ProgramAssociationTable *pat) 94 { 95 AddFlags(kDTVSigMon_PATSeen); 96 97 R5000Channel *fwchan = dynamic_cast<R5000Channel*>(channel); 98 bool crc_bogus = !fwchan->GetR5000Device()->IsSTBBufferCleared(); 99 if (crc_bogus && stb_needs_to_wait_for_pat && 100 (stb_wait_for_pat_timer.elapsed() < (int)kBufferTimeout)) 101 { 102 VERBOSE(VB_CHANNEL, LOC + "HandlePAT() ignoring PAT"); 103 uint tsid = pat->TransportStreamID(); 104 GetStreamData()->SetVersionPAT(tsid, -1,0); 105 return; 106 } 107 108 if (crc_bogus && stb_needs_to_wait_for_pat) 109 { 110 VERBOSE(VB_IMPORTANT, LOC_WARN + "Wait for valid PAT timed out"); 111 stb_needs_to_wait_for_pat = false; 112 } 113 114 DTVSignalMonitor::HandlePAT(pat); 115 } 116 117 void R5000SignalMonitor::HandlePMT(uint pnum, const ProgramMapTable *pmt) 118 { 119 VERBOSE(VB_CHANNEL, LOC + "HandlePMT()"); 120 121 AddFlags(kDTVSigMon_PMTSeen); 122 123 if (!HasFlags(kDTVSigMon_PATMatch)) 124 { 125 GetStreamData()->SetVersionPMT(pnum, -1,0); 126 VERBOSE(VB_CHANNEL, LOC + "HandlePMT() ignoring PMT"); 127 return; 128 } 129 130 DTVSignalMonitor::HandlePMT(pnum, pmt); 131 } 132 133 void *R5000SignalMonitor::TableMonitorThread(void *param) 134 { 135 R5000SignalMonitor *mon = (R5000SignalMonitor*) param; 136 mon->RunTableMonitor(); 137 return NULL; 138 } 139 140 void R5000SignalMonitor::RunTableMonitor(void) 141 { 142 stb_needs_to_wait_for_pat = true; 143 stb_wait_for_pat_timer.start(); 144 dtvMonitorRunning = true; 145 146 VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- begin"); 147 148 R5000Channel *lchan = dynamic_cast<R5000Channel*>(channel); 149 if (!lchan) 150 { 151 VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- err end"); 152 dtvMonitorRunning = false; 153 return; 154 } 155 156 R5000Device *dev = lchan->GetR5000Device(); 157 158 dev->OpenPort(); 159 dev->AddListener(this); 160 161 while (dtvMonitorRunning && GetStreamData()) 162 usleep(100000); 163 164 VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- shutdown "); 165 166 dev->RemoveListener(this); 167 dev->ClosePort(); 168 169 dtvMonitorRunning = false; 170 171 VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- end"); 172 } 173 174 void R5000SignalMonitor::AddData(const unsigned char *data, uint len) 175 { 176 if (!dtvMonitorRunning) 177 return; 178 179 if (GetStreamData()) 180 GetStreamData()->ProcessData((unsigned char *)data, len); 181 } 182 183 /** \fn R5000SignalMonitor::UpdateValues(void) 184 * \brief Fills in frontend stats and emits status Qt signals. 185 * 186 * This function uses five ioctl's FE_READ_SNR, FE_READ_SIGNAL_STRENGTH 187 * FE_READ_BER, FE_READ_UNCORRECTED_BLOCKS, and FE_READ_STATUS to obtain 188 * statistics from the frontend. 189 * 190 * This is automatically called by MonitorLoop(), after Start() 191 * has been used to start the signal monitoring thread. 192 */ 193 void R5000SignalMonitor::UpdateValues(void) 194 { 195 if (!running || exit) 196 return; 197 198 if (dtvMonitorRunning) 199 { 200 EmitR5000Signals(); 201 if (IsAllGood()) 202 emit AllGood(); 203 // TODO dtv signals... 204 205 update_done = true; 206 return; 207 } 208 209 if (stb_needs_to_wait_for_power && 210 (stb_wait_for_power_timer.elapsed() < (int)kPowerTimeout)) 211 { 212 return; 213 } 214 stb_needs_to_wait_for_power = false; 215 216 R5000Channel *fwchan = dynamic_cast<R5000Channel*>(channel); 217 218 if (HasFlags(kFWSigMon_WaitForPower) && !HasFlags(kFWSigMon_PowerMatch)) 219 { 220 bool retried = false; 221 while (true) 222 { 223 R5000Device::PowerState power = fwchan->GetPowerState(); 224 if (R5000Device::kAVCPowerOn == power) 225 { 226 AddFlags(kFWSigMon_PowerSeen | kFWSigMon_PowerMatch); 227 } 228 else if (R5000Device::kAVCPowerOff == power) 229 { 230 AddFlags(kFWSigMon_PowerSeen); 231 fwchan->SetPowerState(true); 232 stb_wait_for_power_timer.start(); 233 stb_needs_to_wait_for_power = true; 234 } 235 else 236 { 237 bool qfailed = (R5000Device::kAVCPowerQueryFailed == power); 238 if (qfailed && !retried) 239 { 240 retried = true; 241 continue; 242 } 243 244 VERBOSE(VB_RECORD, "Can't determine if STB is power on, " 245 "assuming it is..."); 246 AddFlags(kFWSigMon_PowerSeen | kFWSigMon_PowerMatch); 247 } 248 break; 249 } 250 } 251 252 bool isLocked = !HasFlags(kFWSigMon_WaitForPower) || 253 HasFlags(kFWSigMon_WaitForPower | kFWSigMon_PowerMatch); 254 255 if (isLocked && stb_needs_retune) 256 { 257 fwchan->Retune(); 258 isLocked = stb_needs_retune = false; 259 } 260 261 // Set SignalMonitorValues from info from card. 262 { 263 QMutexLocker locker(&statusLock); 264 signalStrength.SetValue(isLocked ? 100 : 0); 265 signalLock.SetValue(isLocked ? 1 : 0); 266 } 267 268 EmitR5000Signals(); 269 if (IsAllGood()) 270 emit AllGood(); 271 272 // Start table monitoring if we are waiting on any table 273 // and we have a lock. 274 if (isLocked && GetStreamData() && 275 HasAnyFlag(kDTVSigMon_WaitForPAT | kDTVSigMon_WaitForPMT | 276 kDTVSigMon_WaitForMGT | kDTVSigMon_WaitForVCT | 277 kDTVSigMon_WaitForNIT | kDTVSigMon_WaitForSDT)) 278 { 279 pthread_create(&table_monitor_thread, NULL, 280 TableMonitorThread, this); 281 282 VERBOSE(VB_CHANNEL, LOC + "UpdateValues() -- " 283 "Waiting for table monitor to start"); 284 285 while (!dtvMonitorRunning) 286 usleep(50); 287 288 VERBOSE(VB_CHANNEL, LOC + "UpdateValues() -- " 289 "Table monitor started"); 290 } 291 292 update_done = true; 293 } 294 295 #define EMIT(SIGNAL_FUNC, SIGNAL_VAL) \ 296 do { statusLock.lock(); \ 297 SignalMonitorValue val = SIGNAL_VAL; \ 298 statusLock.unlock(); \ 299 emit SIGNAL_FUNC(val); } while (false) 300 301 /** \fn R5000SignalMonitor::EmitR5000Signals(void) 302 * \brief Emits signals for lock, signal strength, etc. 303 */ 304 void R5000SignalMonitor::EmitR5000Signals(void) 305 { 306 // Emit signals.. 307 EMIT(StatusSignalLock, signalLock); 308 if (HasFlags(kDTVSigMon_WaitForSig)) 309 EMIT(StatusSignalStrength, signalStrength); 310 } 311 312 #undef EMIT -
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 "firewiredevice.h" 12 #include "util.h" 13 14 class R5000Channel; 15 16 class R5000SignalMonitor : public DTVSignalMonitor, public TSDataListener 17 { 18 Q_OBJECT 19 20 public: 21 R5000SignalMonitor(int db_cardnum, R5000Channel *_channel, 22 uint64_t _flags = kFWSigMon_WaitForPower, 23 const char *_name = "R5000SignalMonitor"); 24 25 virtual void HandlePAT(const ProgramAssociationTable*); 26 virtual void HandlePMT(uint, const ProgramMapTable*); 27 28 void Stop(void); 29 30 public slots: 31 void deleteLater(void); 32 33 protected: 34 R5000SignalMonitor(void); 35 R5000SignalMonitor(const R5000SignalMonitor&); 36 virtual ~R5000SignalMonitor(); 37 38 virtual void UpdateValues(void); 39 void EmitR5000Signals(void); 40 41 static void *TableMonitorThread(void *param); 42 void RunTableMonitor(void); 43 44 bool SupportsTSMonitoring(void); 45 46 void AddData(const unsigned char *data, uint dataSize); 47 48 public: 49 static const uint kPowerTimeout; 50 static const uint kBufferTimeout; 51 52 protected: 53 bool dtvMonitorRunning; 54 pthread_t table_monitor_thread; 55 bool stb_needs_retune; 56 bool stb_needs_to_wait_for_pat; 57 bool stb_needs_to_wait_for_power; 58 MythTimer stb_wait_for_pat_timer; 59 MythTimer stb_wait_for_power_timer; 60 61 vector<unsigned char> buffer; 62 63 static QMap<void*,uint> pat_keys; 64 static QMutex pat_keys_lock; 65 }; 66 67 #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
