Ticket #4752: r5000_r19_trunk19501.patch
| File r5000_r19_trunk19501.patch, 197.2 KB (added by anonymous, 3 years ago) |
|---|
-
configure
old new 179 179 echo " --disable-ivtv disable ivtv support (PVR-x50) req. v4l support" 180 180 echo " --disable-hdpvr disable HD-PVR support" 181 181 echo " --disable-dvb disable DVB support" 182 echo " --disable-r5000 disable support for R5000 USB STBs" 182 183 echo " --dvb-path=HDRLOC location of directory containing" 183 184 echo " 'linux/dvb/frontend.h', not the" 184 185 echo " directory with frontend.h [$dvb_path]" … … 1020 1021 hdpvr 1021 1022 iptv 1022 1023 ivtv 1024 r5000 1023 1025 joystick_menu 1024 1026 libfftw3 1025 1027 lirc … … 1211 1213 dbox2_deps="backend" 1212 1214 dvb_deps="backend" 1213 1215 firewire_deps="backend" 1216 r5000_deps="backend" 1214 1217 iptv_deps="backend" 1215 1218 ivtv_deps="backend v4l" 1216 1219 hdpvr_deps="backend v4l" … … 1329 1332 enable hdpvr 1330 1333 enable iptv 1331 1334 enable ivtv 1335 enable r5000 1332 1336 enable lamemp3 1333 1337 enable lirc 1334 1338 enable mheg … … 2976 2980 enabled libfftw3 && check_lib2 fftw3.h fftw_init_threads -lfftw3_threads -lfftw3 || 2977 2981 disable libfftw3 2978 2982 2983 enabled r5000 && has_library libusb && check_header usb.h || disable r5000 2984 2979 2985 enabled x11 && has_library libX11 || disable x11 2980 2986 enabled xrandr && check_header X11/extensions/Xrandr.h || disable xrandr 2981 2987 enabled xv && has_library libXv || disable xv … … 3301 3307 # echo "DBox2 support ${dbox2-no}" 3302 3308 echo "HDHomeRun support ${hdhomerun-no}" 3303 3309 echo "IPTV support ${iptv-no}" 3310 echo "R5000 support ${r5000-no}" 3304 3311 fi 3305 3312 3306 3313 if enabled frontend; then -
libs/libmythtv/cardutil.h
old new 54 54 HDHOMERUN = 10, 55 55 FREEBOX = 11, 56 56 HDPVR = 12, 57 R5000 = 13, 57 58 }; 58 59 59 60 static enum CARD_TYPES toCardType(const QString &name) … … 84 85 return FREEBOX; 85 86 if ("HDPVR" == name) 86 87 return HDPVR; 88 if ("R5000" == name) 89 return R5000; 87 90 return ERROR_UNKNOWN; 88 91 } 89 92 … … 92 95 return 93 96 (rawtype != "DVB") && 94 97 (rawtype != "FIREWIRE") && (rawtype != "DBOX2") && 95 (rawtype != "HDHOMERUN") && (rawtype != "FREEBOX"); 98 (rawtype != "HDHOMERUN") && (rawtype != "FREEBOX") && 99 (rawtype != "R5000") ; 96 100 } 97 101 98 102 static bool IsUnscanable(const QString &rawtype) 99 103 { 100 104 return 101 105 (rawtype == "FIREWIRE") || (rawtype == "DBOX2") || 102 (rawtype == "HDPVR") ;106 (rawtype == "HDPVR") || (rawtype == "R5000"); 103 107 } 104 108 105 109 static bool IsEITCapable(const QString &rawtype) -
libs/libmythtv/libmythtv.pro
old new 540 540 DEFINES += USING_DVB 541 541 } 542 542 543 #Support for R5000 usb device 544 using_r5000 { 545 HEADERS += r5000channel.h r5000recorder.h 546 HEADERS += r5000signalmonitor.h r5000device.h 547 HEADERS += r5000/r5000.h r5000/libusb_augment.h 548 HEADERS += r5000/r5000_internal.h r5000/r5000init.h 549 550 SOURCES += r5000channel.cpp r5000recorder.cpp 551 SOURCES += r5000signalmonitor.cpp r5000device.cpp 552 SOURCES += r5000/r5000.c r5000/libusb_augment.c 553 SOURCES += r5000/r5k_vip.c r5000/r5k_pes.c 554 SOURCES += r5000/r5k_sat.c r5000/r5k_misc.c 555 SOURCES += r5000/r5k_vip_buttons.c r5000/r5k_directv_buttons.c 556 SOURCES += r5000/r5k_dish6000_buttons.c 557 558 LIBS += -lusb 559 DEFINES += USING_R5000 560 } 561 543 562 DEFINES += USING_BACKEND 544 563 } 545 564 -
libs/libmythtv/signalmonitor.h
old new 288 288 (cardtype.toUpper() == "HDTV") || 289 289 (cardtype.toUpper() == "HDHOMERUN") || 290 290 (cardtype.toUpper() == "FIREWIRE") || 291 (cardtype.toUpper() == "FREEBOX")); 291 (cardtype.toUpper() == "FREEBOX") || 292 (cardtype.toUpper() == "R5000")); 292 293 } 293 294 294 295 inline bool SignalMonitor::IsSupported(const QString &cardtype) -
libs/libmythtv/signalmonitor.cpp
old new 42 42 # include "firewirechannel.h" 43 43 #endif 44 44 45 #ifdef USING_R5000 46 # include "r5000signalmonitor.h" 47 # include "r5000channel.h" 48 #endif 49 45 50 #undef DBG_SM 46 51 #define DBG_SM(FUNC, MSG) VERBOSE(VB_CHANNEL, \ 47 52 "SM("<<channel->GetDevice()<<")::"<<FUNC<<": "<<MSG); … … 129 134 signalMonitor = new FirewireSignalMonitor(db_cardnum, fc); 130 135 } 131 136 #endif 137 #ifdef USING_R5000 138 if (cardtype.toUpper() == "R5000") 139 { 140 R5000Channel *fc = dynamic_cast<R5000Channel*>(channel); 141 if (fc) 142 signalMonitor = new R5000SignalMonitor(db_cardnum, fc); 143 } 144 #endif 132 145 133 146 if (!signalMonitor) 134 147 { -
libs/libmythtv/cardutil.cpp
old new 1613 1613 if (("FIREWIRE" == cardtype) || 1614 1614 ("FREEBOX" == cardtype) || 1615 1615 ("DBOX2" == cardtype) || 1616 ("HDHOMERUN" == cardtype)) 1616 ("HDHOMERUN" == cardtype) || 1617 ("R5000" == cardtype)) 1617 1618 { 1618 1619 ret += "MPEG2TS"; 1619 1620 } … … 1783 1784 if (("FIREWIRE" == cardtype) || 1784 1785 ("FREEBOX" == cardtype) || 1785 1786 ("DBOX2" == cardtype) || 1786 ("HDHOMERUN" == cardtype)) 1787 ("HDHOMERUN" == cardtype) || 1788 ("R5000" == cardtype)) 1787 1789 { 1788 1790 inputs += "MPEG2TS"; 1789 1791 } -
libs/libmythtv/videosource.cpp
old new 35 35 #include "frequencies.h" 36 36 #include "diseqcsettings.h" 37 37 #include "firewiredevice.h" 38 #include "r5000device.h" 38 39 #include "libmythdb/compat.h" 39 40 #include "libmythdb/mythdb.h" 40 41 #include "libmythdb/mythdirs.h" … … 1424 1425 } 1425 1426 }; 1426 1427 1428 class R5000SendPowerBeforeChannel : public CheckBoxSetting, public CaptureCardDBStorage 1429 { 1430 public: 1431 R5000SendPowerBeforeChannel(const CaptureCard &parent) : 1432 CheckBoxSetting(this), 1433 CaptureCardDBStorage(this, parent, "dvb_on_demand") 1434 { 1435 setValue(false); 1436 setLabel(QObject::tr("Turn on before Channel Change")); 1437 setHelpText(QObject::tr( 1438 "On some STBs klike the ViP211, the power on/off " 1439 "detection isn't reliable if you let the box go into " 1440 "standby. This forces a 'power-on' command before " 1441 "changing channels. This will very likely do the " 1442 "wrong thing for non ViP boxes.")); 1443 1444 }; 1445 }; 1446 1447 class R5000Serial : public ComboBoxSetting, public CaptureCardDBStorage 1448 { 1449 public: 1450 R5000Serial(const CaptureCard &parent) : 1451 ComboBoxSetting(this), 1452 CaptureCardDBStorage(this, parent, "videodevice") 1453 { 1454 setLabel(QObject::tr("Serial #")); 1455 #ifdef USING_R5000 1456 QStringList serials = R5000Device::GetSTBList(); 1457 for (int i = 0; i < serials.size(); i++) 1458 { 1459 addSelection(serials[i]); 1460 } 1461 #endif // USING_FIREWIRE 1462 } 1463 }; 1464 1465 class R5000Model : public ComboBoxSetting, public CaptureCardDBStorage 1466 { 1467 public: 1468 R5000Model(const CaptureCard &parent) : 1469 ComboBoxSetting(this), 1470 CaptureCardDBStorage(this, parent, "firewire_model") 1471 { 1472 setLabel(QObject::tr("R5000 STB type")); 1473 addSelection("VIP211"); 1474 addSelection("VIP411"); 1475 addSelection("VIP622"); 1476 addSelection("VIP722"); 1477 addSelection("BEV9242"); 1478 addSelection("DISH6000"); 1479 addSelection("DIRECTV"); 1480 addSelection("STARCHOICE/DSR"); 1481 addSelection("HDD-200"); 1482 QString help = QObject::tr( 1483 "Choose the type of R5000 enabled STB you are using."); 1484 setHelpText(help); 1485 } 1486 }; 1487 class R5000ConfigurationGroup : public VerticalConfigurationGroup 1488 { 1489 public: 1490 R5000ConfigurationGroup(CaptureCard& a_parent): 1491 VerticalConfigurationGroup(false, true, false, false), 1492 parent(a_parent) 1493 { 1494 setUseLabel(false); 1495 addChild(new R5000SendPowerBeforeChannel(parent)); 1496 addChild(new R5000Serial(parent)); 1497 addChild(new R5000Model(parent)); 1498 addChild(new SingleCardInput(parent)); 1499 }; 1500 1501 private: 1502 CaptureCard &parent; 1503 }; 1504 1427 1505 class IPTVHost : public LineEditSetting, public CaptureCardDBStorage 1428 1506 { 1429 1507 public: … … 1654 1732 #ifdef USING_IPTV 1655 1733 addTarget("FREEBOX", new IPTVConfigurationGroup(parent)); 1656 1734 #endif // USING_IPTV 1735 1736 #ifdef USING_R5000 1737 addTarget("R5000", new R5000ConfigurationGroup(parent)); 1738 #endif // USING_R5000 1657 1739 } 1658 1740 1659 1741 void CaptureCardGroup::triggerChanged(const QString& value) … … 1854 1936 #ifdef USING_IPTV 1855 1937 setting->addSelection(QObject::tr("Network Recorder"), "FREEBOX"); 1856 1938 #endif // USING_IPTV 1939 1940 #ifdef USING_R5000 1941 setting->addSelection(QObject::tr("R5000 Capable STB"), "R5000"); 1942 #endif // USING_R5000 1857 1943 } 1858 1944 1859 1945 class CardID : public SelectLabelSetting, public CardInputDBStorage -
libs/libmythtv/tv_rec.cpp
old new 49 49 #include "hdhrchannel.h" 50 50 #include "iptvchannel.h" 51 51 #include "firewirechannel.h" 52 #include "r5000channel.h" 52 53 53 54 #include "recorderbase.h" 54 55 #include "NuppelVideoRecorder.h" … … 58 59 #include "hdhrrecorder.h" 59 60 #include "iptvrecorder.h" 60 61 #include "firewirerecorder.h" 62 #include "r5000recorder.h" 61 63 62 64 #ifdef USING_V4L 63 65 #include "v4lchannel.h" … … 202 204 init_run = true; 203 205 #endif 204 206 } 207 else if (genOpt.cardtype == "R5000") 208 { 209 #ifdef USING_R5000 210 channel = new R5000Channel(this, genOpt.videodev, fwOpt.model, dvbOpt.dvb_on_demand); 211 if (!channel->Open()) 212 return false; 213 InitChannel(genOpt.defaultinput, startchannel); 214 init_run = true; 215 #endif 216 } 205 217 else // "V4L" or "MPEG", ie, analog TV 206 218 { 207 219 #ifdef USING_V4L … … 1021 1033 recorder->SetOption("mrl", genOpt.videodev); 1022 1034 #endif // USING_IPTV 1023 1035 } 1036 else if (genOpt.cardtype == "R5000") 1037 { 1038 #ifdef USING_R5000 1039 recorder = new R5000Recorder(this, GetR5000Channel()); 1040 #endif // USING_R5000 1041 } 1024 1042 else 1025 1043 { 1026 1044 #ifdef USING_V4L … … 1238 1256 #endif // USING_FIREWIRE 1239 1257 } 1240 1258 1259 R5000Channel *TVRec::GetR5000Channel(void) 1260 { 1261 #ifdef USING_R5000 1262 return dynamic_cast<R5000Channel*>(channel); 1263 #else 1264 return NULL; 1265 #endif // USING_R5000 1266 } 1267 1241 1268 V4LChannel *TVRec::GetV4LChannel(void) 1242 1269 { 1243 1270 #ifdef USING_V4L -
libs/libmythtv/transporteditor.cpp
old new 734 734 left->addChild(new Modulation(id, nType)); 735 735 } 736 736 else if ((CardUtil::FIREWIRE == nType) || 737 (CardUtil::FREEBOX == nType)) 737 (CardUtil::FREEBOX == nType) || 738 (CardUtil::R5000 == nType)) 738 739 { 739 740 left->addChild(new DTVStandard(id, true, true)); 740 741 } -
libs/libmythtv/tv_rec.h
old new 42 42 class FirewireChannel; 43 43 class V4LChannel; 44 44 class HDHRChannel; 45 class R5000Channel; 45 46 46 47 class MPEGStreamData; 47 48 class ProgramMapTable; … … 288 289 HDHRChannel *GetHDHRChannel(void); 289 290 DVBChannel *GetDVBChannel(void); 290 291 FirewireChannel *GetFirewireChannel(void); 292 R5000Channel *GetR5000Channel(void); 291 293 V4LChannel *GetV4LChannel(void); 292 294 293 295 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, bool pocc) : 17 DTVChannel(parent), 18 videodevice(_videodevice), 19 power_on_channel_change(pocc), 20 device(NULL), 21 current_channel(""), 22 current_mpeg_prog(0), 23 isopen(false) 24 { 25 int type = R5000Device::GetDeviceType(_r5ktype); 26 device = new R5000Device(type, videodevice); 27 28 InitializeInputs(); 29 } 30 31 bool R5000Channel::SetChannelByString(const QString &channum) 32 { 33 QString loc = LOC + QString("SetChannelByString(%1)").arg(channum); 34 bool ok = false; 35 VERBOSE(VB_CHANNEL, loc); 36 37 InputMap::const_iterator it = inputs.find(currentInputID); 38 if (it == inputs.end()) 39 return false; 40 41 QString tvformat, modulation, freqtable, freqid, dtv_si_std; 42 int finetune; 43 uint64_t frequency; 44 int mpeg_prog_num; 45 uint atsc_major, atsc_minor, mplexid, tsid, netid; 46 if (!ChannelUtil::GetChannelData( 47 (*it)->sourceid, channum, 48 tvformat, modulation, freqtable, freqid, 49 finetune, frequency, 50 dtv_si_std, mpeg_prog_num, atsc_major, atsc_minor, tsid, netid, 51 mplexid, commfree)) 52 { 53 VERBOSE(VB_IMPORTANT, loc + " " + QString( 54 "Requested channel '%1' is on input '%2' " 55 "which is in a busy input group") 56 .arg(channum).arg(currentInputID)); 57 58 return false; 59 } 60 uint mplexid_restriction; 61 if (!IsInputAvailable(currentInputID, mplexid_restriction)) 62 { 63 VERBOSE(VB_IMPORTANT, loc + " " + QString( 64 "Requested channel '%1' is on input '%2' " 65 "which is in a busy input group") 66 .arg(channum).arg(currentInputID)); 67 68 return false; 69 } 70 71 if (!(*it)->externalChanger.isEmpty()) 72 { 73 ok = ChangeExternalChannel(freqid); 74 // -1 resets any state without executing a channel change 75 device->SetChannel(fw_opts.model, 0, mpeg_prog_num); 76 SetSIStandard("mpeg"); 77 SetDTVInfo(0,0,0,0,1); 78 } 79 else 80 { 81 ok = isopen && SetChannelByNumber(freqid, mpeg_prog_num); 82 } 83 84 if (ok) 85 { 86 // Set the current channum to the new channel's channum 87 QString tmp = channum; 88 tmp.detach(); 89 curchannelname = tmp; 90 tmp.detach(); 91 (*it)->startChanNum = tmp; 92 } 93 94 VERBOSE(VB_CHANNEL, loc + " " + ((ok) ? "success" : "failure")); 95 96 return ok; 97 } 98 99 bool R5000Channel::Open(void) 100 { 101 VERBOSE(VB_CHANNEL, LOC + "Open()"); 102 103 if (inputs.find(currentInputID) == inputs.end()) 104 return false; 105 106 if (!device) 107 return false; 108 109 if (isopen) 110 return true; 111 112 if (!device->OpenPort()) 113 return false; 114 115 isopen = true; 116 117 return true; 118 } 119 120 void R5000Channel::Close(void) 121 { 122 VERBOSE(VB_CHANNEL, LOC + "Close()"); 123 if (isopen) 124 { 125 device->ClosePort(); 126 isopen = false; 127 } 128 } 129 130 QString R5000Channel::GetDevice(void) const 131 { 132 return videodevice; 133 } 134 135 bool R5000Channel::SetPowerState(bool on) 136 { 137 if (!isopen) 138 { 139 VERBOSE(VB_IMPORTANT, LOC_ERR + 140 "SetPowerState() called on closed R5000Channel."); 141 142 return false; 143 } 144 145 return device->SetPowerState(on); 146 } 147 148 R5000Device::PowerState R5000Channel::GetPowerState(void) const 149 { 150 if (!isopen) 151 { 152 VERBOSE(VB_IMPORTANT, LOC_ERR + 153 "GetPowerState() called on closed R5000Channel."); 154 155 return R5000Device::kAVCPowerQueryFailed; 156 } 157 158 return device->GetPowerState(); 159 } 160 161 bool R5000Channel::Retune(void) 162 { 163 VERBOSE(VB_CHANNEL, LOC + "Retune()"); 164 165 if (! power_on_channel_change && R5000Device::kAVCPowerOff == GetPowerState()) 166 { 167 VERBOSE(VB_IMPORTANT, LOC_ERR + 168 "STB is turned off, must be on to retune."); 169 170 return false; 171 } 172 173 if (current_channel.length()) 174 return SetChannelByNumber(current_channel, current_mpeg_prog); 175 176 return false; 177 } 178 179 bool R5000Channel::SetChannelByNumber(const QString &channel, int mpeg_prog) 180 { 181 VERBOSE(VB_CHANNEL, QString("SetChannelByNumber(%1)").arg(channel)); 182 current_channel = channel; 183 current_mpeg_prog = mpeg_prog; 184 185 if (R5000Device::kAVCPowerOff == GetPowerState()) 186 { 187 VERBOSE(VB_IMPORTANT, LOC_WARN + 188 "STB is turned off, must be on to set channel."); 189 190 SetSIStandard("mpeg"); 191 SetDTVInfo(0,0,0,0,1); 192 193 return true; // signal monitor will call retune later... 194 } 195 196 QString tmpchan = (power_on_channel_change ? "P" : "") + channel; 197 if (! device->SetChannel(fw_opts.model, tmpchan, mpeg_prog)) 198 return false; 199 200 SetSIStandard("mpeg"); 201 SetDTVInfo(0,0,0,0,1); 202 203 return true; 204 } -
new file libs/libmythtv/r5000device.cpp
- + 1 /** 2 * R5000Device 3 * Copyright (c) 2008 by Alan Nisota 4 * Copyright (c) 2005 by Jim Westfall 5 * Distributed as part of MythTV under GPL v2 and later. 6 */ 7 8 // MythTV headers 9 #include "r5000device.h" 10 #include "mythcontext.h" 11 #include "pespacket.h" 12 13 #define LOC QString("R5kDev: ") 14 #define LOC_WARN QString("R5kDev, Warning: ") 15 #define LOC_ERR QString("R5kDev, Error: ") 16 17 static int r5k_init = 0; 18 QMap<uint64_t,QString> R5000Device::s_id_to_model; 19 QMutex R5000Device::s_static_lock; 20 21 unsigned int r5000_device_tspacket_handler(unsigned char *tspacket, int len, void *callback_data) 22 { 23 R5000Device *fw = (R5000Device*) callback_data; 24 if (! fw) 25 return 0; 26 if (len > 0) 27 fw->BroadcastToListeners(tspacket, len); 28 return 1; 29 } 30 31 void r5000_msg(char * msg) 32 { 33 VERBOSE(VB_IMPORTANT, "R5kLib: "<<msg); 34 } 35 36 class R5kPriv 37 { 38 public: 39 R5kPriv() : 40 reset_timer_on(false), 41 run_port_handler(false), is_port_handler_running(false), 42 channel(-1), 43 is_streaming(false) 44 { 45 } 46 47 bool reset_timer_on; 48 MythTimer reset_timer; 49 50 bool run_port_handler; 51 bool is_port_handler_running; 52 QMutex start_stop_port_handler_lock; 53 54 int channel; 55 56 bool is_streaming; 57 58 QDateTime stop_streaming_timer; 59 pthread_t port_handler_thread; 60 61 static QMutex s_lock; 62 }; 63 QMutex R5kPriv::s_lock; 64 65 //callback functions 66 void *r5000_device_port_handler_thunk(void *param); 67 68 R5000Device::R5000Device(int type, QString serial) : 69 m_type(type), 70 m_serial(serial), 71 m_last_channel(""), m_last_crc(0), 72 m_buffer_cleared(true), m_open_port_cnt(0), 73 m_lock(), m_priv(new R5kPriv()) 74 { 75 QMutexLocker locker(&s_static_lock); 76 usbdev = NULL; 77 if (! r5k_init) 78 r5k_init = r5000_init(r5000_msg); 79 } 80 81 R5000Device::~R5000Device() 82 { 83 if (usbdev) 84 { 85 VERBOSE(VB_IMPORTANT, LOC_ERR + "ctor called with open port"); 86 while (usbdev) 87 ClosePort(); 88 } 89 90 if (m_priv) 91 { 92 delete m_priv; 93 m_priv = NULL; 94 } 95 } 96 97 void R5000Device::AddListener(TSDataListener *listener) 98 { 99 if (listener) 100 { 101 vector<TSDataListener*>::iterator it = 102 find(m_listeners.begin(), m_listeners.end(), listener); 103 104 if (it == m_listeners.end()) 105 m_listeners.push_back(listener); 106 } 107 108 VERBOSE(VB_RECORD, LOC + "AddListener() "<<m_listeners.size()); 109 if (!m_listeners.empty()) 110 { 111 StartStreaming(); 112 } 113 } 114 115 void R5000Device::RemoveListener(TSDataListener *listener) 116 { 117 vector<TSDataListener*>::iterator it = m_listeners.end(); 118 119 do 120 { 121 it = find(m_listeners.begin(), m_listeners.end(), listener); 122 if (it != m_listeners.end()) 123 m_listeners.erase(it); 124 } 125 while (it != m_listeners.end()); 126 127 VERBOSE(VB_RECORD, LOC + "RemoveListener() "<<m_listeners.size()); 128 if (m_listeners.empty()) 129 { 130 StopStreaming(); 131 } 132 } 133 134 bool R5000Device::StartStreaming(void) 135 { 136 if (m_priv->is_streaming) 137 return m_priv->is_streaming; 138 139 if (! usbdev) 140 { 141 VERBOSE(VB_IMPORTANT, LOC_ERR + "Device not open"); 142 return false; 143 } 144 if (r5000_start_stream(usbdev)) 145 { 146 m_priv->is_streaming = true; 147 } 148 else 149 { 150 VERBOSE(VB_IMPORTANT, LOC_ERR + "Starting A/V streaming "); 151 } 152 153 VERBOSE(VB_RECORD, LOC + "Starting A/V streaming -- done"); 154 155 return m_priv->is_streaming; 156 } 157 158 bool R5000Device::StopStreaming(void) 159 { 160 if (m_priv->is_streaming) 161 { 162 VERBOSE(VB_RECORD, LOC + "Stopping A/V streaming -- really"); 163 164 m_priv->is_streaming = false; 165 166 r5000_stop_stream(usbdev); 167 } 168 169 VERBOSE(VB_RECORD, LOC + "Stopped A/V streaming"); 170 171 return true; 172 } 173 174 bool R5000Device::SetPowerState(bool on) 175 { 176 QMutexLocker locker(&m_lock); 177 QString cmdStr = (on) ? "on" : "off"; 178 VERBOSE(VB_RECORD, LOC + QString("Powering %1").arg(cmdStr)); 179 r5000_power_on_off(usbdev, on); 180 return true; 181 } 182 183 R5000Device::PowerState R5000Device::GetPowerState(void) 184 { 185 QMutexLocker locker(&m_lock); 186 int on_off; 187 188 VERBOSE(VB_CHANNEL, LOC + "Requesting STB Power State"); 189 on_off = r5000_get_power_state(usbdev); 190 VERBOSE(VB_CHANNEL, LOC + (on_off ? "On" : "Off")); 191 return on_off ? kAVCPowerOn : kAVCPowerOff; 192 } 193 194 bool R5000Device::SetChannel(const QString &panel_model, 195 const QString &channel, uint mpeg_prog) 196 { 197 VERBOSE(VB_CHANNEL, QString("SetChannel(model %1, chan %2 mpeg_prog %3)") 198 .arg(panel_model).arg(channel).arg(mpeg_prog)); 199 200 QMutexLocker locker(&m_lock); 201 VERBOSE(VB_CHANNEL, "SetChannel() -- locked"); 202 if (! r5000_change_channel(usbdev, channel.toAscii(), mpeg_prog)) 203 VERBOSE(VB_IMPORTANT, LOC + "Failed to set channel"); 204 return true; 205 } 206 207 void R5000Device::BroadcastToListeners( 208 const unsigned char *data, uint dataSize) 209 { 210 if ((dataSize >= TSPacket::SIZE) && (data[0] == SYNC_BYTE) && 211 ((data[1] & 0x1f) == 0) && (data[2] == 0)) 212 { 213 ProcessPATPacket(*((const TSPacket*)data)); 214 } 215 216 vector<TSDataListener*>::iterator it = m_listeners.begin(); 217 for (; it != m_listeners.end(); ++it) 218 (*it)->AddData(data, dataSize); 219 } 220 221 void R5000Device::SetLastChannel(const QString &channel) 222 { 223 m_buffer_cleared = (channel == m_last_channel); 224 m_last_channel = channel; 225 226 VERBOSE(VB_IMPORTANT, QString("SetLastChannel(%1): cleared: %2") 227 .arg(channel).arg(m_buffer_cleared ? "yes" : "no")); 228 } 229 230 void R5000Device::ProcessPATPacket(const TSPacket &tspacket) 231 { 232 if (!tspacket.TransportError() && !tspacket.ScramplingControl() && 233 tspacket.HasPayload() && tspacket.PayloadStart() && !tspacket.PID()) 234 { 235 PESPacket pes = PESPacket::View(tspacket); 236 uint crc = pes.CalcCRC(); 237 m_buffer_cleared |= (crc != m_last_crc); 238 m_last_crc = crc; 239 #if 0 240 VERBOSE(VB_RECORD, LOC + 241 QString("ProcessPATPacket: CRC 0x%1 cleared: %2") 242 .arg(crc,0,16).arg(m_buffer_cleared ? "yes" : "no")); 243 #endif 244 } 245 else 246 { 247 VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't handle large PAT's"); 248 } 249 } 250 251 QString R5000Device::GetModelName(uint vendor_id, uint model_id) 252 { 253 QMutexLocker locker(&s_static_lock); 254 /* 255 if (s_id_to_model.empty()) 256 fw_init(s_id_to_model); 257 258 QString ret = s_id_to_model[(((uint64_t) vendor_id) << 32) | model_id]; 259 260 if (ret.isEmpty()) 261 return "GENERIC"; 262 */ 263 return "R5000"; 264 } 265 266 bool R5000Device::IsSTBSupported(const QString &panel_model) 267 { 268 return true; 269 } 270 271 bool R5000Device::OpenPort(void) 272 { 273 VERBOSE(VB_RECORD, LOC + "Starting Port Handler Thread"); 274 QMutexLocker mlocker(&m_lock); 275 VERBOSE(VB_RECORD, LOC + "Starting Port Handler Thread -- locked"); 276 if (usbdev) 277 { 278 m_open_port_cnt++; 279 return true; 280 } 281 282 if (m_serial.length()) 283 { 284 VERBOSE(VB_RECORD, LOC + QString("Opening R5000 device type %1 with serial#: "+ m_serial).arg(m_type)); 285 usbdev = r5000_open((r5ktype_t)m_type, r5000_device_tspacket_handler, this, m_serial.toAscii()); 286 } 287 else 288 { 289 VERBOSE(VB_RECORD, LOC + "Opening R5000 device with unknown serial#"); 290 usbdev = r5000_open((r5ktype_t)m_type, r5000_device_tspacket_handler, this, NULL); 291 } 292 if (! usbdev) 293 { 294 VERBOSE(VB_IMPORTANT, LOC + "Failed to open R5000 device"); 295 return false; 296 } 297 298 VERBOSE(VB_RECORD, LOC + "Starting port handler thread"); 299 m_priv->run_port_handler = true; 300 pthread_create(&m_priv->port_handler_thread, NULL, 301 r5000_device_port_handler_thunk, this); 302 303 VERBOSE(VB_RECORD, LOC + "Waiting for port handler thread to start"); 304 while (!m_priv->is_port_handler_running) 305 { 306 m_lock.unlock(); 307 usleep(5000); 308 m_lock.lock(); 309 } 310 311 VERBOSE(VB_RECORD, LOC + "Port handler thread started"); 312 313 m_open_port_cnt++; 314 315 return true; 316 } 317 318 bool R5000Device::ClosePort(void) 319 { 320 VERBOSE(VB_RECORD, LOC + "Stopping Port Handler Thread"); 321 QMutexLocker locker(&m_priv->start_stop_port_handler_lock); 322 VERBOSE(VB_RECORD, LOC + "Stopping Port Handler Thread -- locked"); 323 324 QMutexLocker mlocker(&m_lock); 325 326 VERBOSE(VB_RECORD, LOC + "ClosePort()"); 327 328 if (m_open_port_cnt < 1) 329 return false; 330 331 m_open_port_cnt--; 332 333 if (m_open_port_cnt != 0) 334 return true; 335 336 if (!usbdev) 337 return false; 338 339 VERBOSE(VB_RECORD, LOC + "Waiting for port handler thread to stop"); 340 m_priv->run_port_handler = false; 341 while (m_priv->is_port_handler_running) 342 { 343 m_lock.unlock(); 344 usleep(5000); 345 m_lock.lock(); 346 } 347 VERBOSE(VB_RECORD, LOC + "Joining port handler thread"); 348 pthread_join(m_priv->port_handler_thread, NULL); 349 350 r5000_close(usbdev); 351 usbdev = NULL; 352 353 return true; 354 } 355 356 void *r5000_device_port_handler_thunk(void *param) 357 { 358 R5000Device *mon = (R5000Device*) param; 359 mon->RunPortHandler(); 360 return NULL; 361 } 362 363 void R5000Device::RunPortHandler(void) 364 { 365 VERBOSE(VB_RECORD, LOC + "RunPortHandler -- start"); 366 m_lock.lock(); 367 VERBOSE(VB_RECORD, LOC + "RunPortHandler -- got first lock"); 368 m_priv->is_port_handler_running = true; 369 m_lock.unlock(); 370 371 while (m_priv->run_port_handler) 372 { 373 if (m_priv->is_streaming) 374 { 375 // This will timeout after 10ms regardless of data availability 376 r5000_loop_iterate(usbdev, 10); 377 } 378 else 379 { 380 usleep(10000); 381 } 382 } 383 384 m_lock.lock(); 385 m_priv->is_port_handler_running = false; 386 m_lock.unlock(); 387 VERBOSE(VB_RECORD, LOC + "RunPortHandler -- end"); 388 } 389 390 QStringList R5000Device::GetSTBList(void) 391 { 392 QStringList STBList; 393 int i; 394 r5kenum_t r5k_stbs; 395 if (! r5k_init) 396 { 397 r5k_init = r5000_init(r5000_msg); 398 if (! r5k_init) 399 return STBList; 400 } 401 if (! r5000_find_stbs(&r5k_stbs)) 402 VERBOSE(VB_IMPORTANT, LOC + "Locating R5000 devices failed." 403 " This may be a permission problem"); 404 405 for (i = 0; i < r5k_stbs.count; i++) 406 STBList.append((char *)r5k_stbs.serial[i]); 407 return STBList; 408 } 409 410 int R5000Device::GetDeviceType(const QString &r5ktype) 411 { 412 QString type = r5ktype.toUpper(); 413 if (type == "DIRECTV") 414 { 415 return R5K_STB_DIRECTV; 416 } 417 else if ("VIP211/VIP622/DISH411" == type || 418 "VIP211/VIP422" == type || 419 "VIP211" == type || 420 "VIP411" == type) 421 { 422 return R5K_STB_VIP211; 423 } 424 else if ("STARCHOICE/DSR" == type) 425 { 426 return R5K_STB_DSR; 427 } 428 else if ("HDD-200" == type) 429 { 430 return R5K_STB_HDD; 431 } 432 else if ("VIP622" == type || 433 "VIP722" == type || 434 "BEV9242" == type) 435 { 436 return R5K_STB_VIP622; 437 } 438 else if ("DISH6000" == type) 439 { 440 return R5K_STB_DISH6000; 441 } 442 else 443 { 444 return R5K_STB_VIP211; 445 } 446 } -
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 ProgramMapTable *pmt = GetStreamData()->PMTSingleProgram(); 145 uint video_stream_type = pmt->StreamType(pmt->FindPID(lpid)); 146 147 if (video_stream_type == StreamID::H264Video) 148 _buffer_packets = !FindH264Keyframes(&tspacket); 149 else if (StreamID::IsVideo(video_stream_type)) 150 _buffer_packets = !FindMPEG2Keyframes(&tspacket); 151 152 if ((video_stream_type != StreamID::H264Video) || _seen_sps) 153 BufferedWrite(tspacket); 154 } 155 else if (GetStreamData()->IsAudioPID(lpid)) 156 { 157 _buffer_packets = !FindAudioKeyframes(&tspacket); 158 BufferedWrite(tspacket); 159 } 160 else if (GetStreamData()->IsListeningPID(lpid)) 161 GetStreamData()->HandleTSTables(&tspacket); 162 else if (GetStreamData()->IsWritingPID(lpid)) 163 BufferedWrite(tspacket); 164 } 165 } 166 167 void R5000Recorder::SetOptionsFromProfile(RecordingProfile *profile, 168 const QString &videodev, 169 const QString &audiodev, 170 const QString &vbidev) 171 { 172 (void)videodev; 173 (void)audiodev; 174 (void)vbidev; 175 (void)profile; 176 } 177 178 // documented in recorderbase.cpp 179 bool R5000Recorder::PauseAndWait(int timeout) 180 { 181 if (request_pause) 182 { 183 VERBOSE(VB_RECORD, LOC + "PauseAndWait("<<timeout<<") -- pause"); 184 if (!paused) 185 { 186 StopStreaming(); 187 paused = true; 188 pauseWait.wakeAll(); 189 if (tvrec) 190 tvrec->RecorderPaused(); 191 } 192 QMutex unpause_lock; 193 unpause_lock.lock(); 194 unpauseWait.wait(&unpause_lock, timeout); 195 } 196 if (!request_pause && paused) 197 { 198 VERBOSE(VB_RECORD, LOC + "PauseAndWait("<<timeout<<") -- unpause"); 199 StartStreaming(); 200 paused = false; 201 } 202 return paused; 203 } 204 205 void R5000Recorder::SetStreamData(MPEGStreamData *data) 206 { 207 VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- begin"); 208 if (data == _mpeg_stream_data) 209 { 210 VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 0"); 211 return; 212 } 213 214 MPEGStreamData *old_data = _mpeg_stream_data; 215 _mpeg_stream_data = data; 216 if (old_data) 217 delete old_data; 218 219 if (data) 220 { 221 data->AddMPEGSPListener(this); 222 223 if (data->DesiredProgram() >= 0) 224 data->SetDesiredProgram(data->DesiredProgram()); 225 } 226 VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 1"); 227 } 228 229 void R5000Recorder::HandleSingleProgramPAT(ProgramAssociationTable *pat) 230 { 231 if (!pat) 232 { 233 VERBOSE(VB_RECORD, LOC + "HandleSingleProgramPAT(NULL)"); 234 return; 235 } 236 int next = (pat->tsheader()->ContinuityCounter()+1)&0xf; 237 pat->tsheader()->SetContinuityCounter(next); 238 BufferedWrite(*(reinterpret_cast<const TSPacket*>(pat->tsheader()))); 239 } 240 241 void R5000Recorder::HandleSingleProgramPMT(ProgramMapTable *pmt) 242 { 243 if (!pmt) 244 { 245 VERBOSE(VB_RECORD, LOC + "HandleSingleProgramPMT(NULL)"); 246 return; 247 } 248 int next = (pmt->tsheader()->ContinuityCounter()+1)&0xf; 249 pmt->tsheader()->SetContinuityCounter(next); 250 BufferedWrite(*(reinterpret_cast<const TSPacket*>(pmt->tsheader()))); 251 } -
new file libs/libmythtv/r5000signalmonitor.cpp
- + 1 // -*- Mode: c++ -*- 2 // Copyright (c) 2006, Daniel Thor Kristjansson 3 4 #include <pthread.h> 5 #include <fcntl.h> 6 #include <unistd.h> 7 #include <sys/select.h> 8 9 #include "mythcontext.h" 10 #include "mythdbcon.h" 11 #include "atscstreamdata.h" 12 #include "mpegtables.h" 13 #include "atsctables.h" 14 #include "r5000channel.h" 15 #include "r5000signalmonitor.h" 16 17 #define LOC QString("R5kSM(%1): ").arg(channel->GetDevice()) 18 #define LOC_WARN QString("R5kSM(%1), Warning: ").arg(channel->GetDevice()) 19 #define LOC_ERR QString("R5kSM(%1), Error: ").arg(channel->GetDevice()) 20 21 const uint R5000SignalMonitor::kPowerTimeout = 3000; /* ms */ 22 const uint R5000SignalMonitor::kBufferTimeout = 5000; /* ms */ 23 24 QMap<void*,uint> R5000SignalMonitor::pat_keys; 25 QMutex R5000SignalMonitor::pat_keys_lock; 26 27 /** \fn R5000SignalMonitor::R5000SignalMonitor(int,R5000Channel*,uint,const char*) 28 * \brief Initializes signal lock and signal values. 29 * 30 * Start() must be called to actually begin continuous 31 * signal monitoring. The timeout is set to 3 seconds, 32 * and the signal threshold is initialized to 0%. 33 * 34 * \param db_cardnum Recorder number to monitor, 35 * if this is less than 0, SIGNAL events will not be 36 * sent to the frontend even if SetNotifyFrontend(true) 37 * is called. 38 * \param _channel R5000Channel for card 39 * \param _flags Flags to start with 40 * \param _name Name for Qt signal debugging 41 */ 42 R5000SignalMonitor::R5000SignalMonitor( 43 int db_cardnum, 44 R5000Channel *_channel, 45 uint64_t _flags, const char *_name) : 46 DTVSignalMonitor(db_cardnum, _channel, _flags), 47 dtvMonitorRunning(false), 48 stb_needs_retune(true), 49 stb_needs_to_wait_for_pat(false), 50 stb_needs_to_wait_for_power(false) 51 { 52 VERBOSE(VB_CHANNEL, LOC + "ctor"); 53 54 signalStrength.SetThreshold(65); 55 56 AddFlags(kSigMon_WaitForSig); 57 58 stb_needs_retune = 59 (R5000Device::kAVCPowerOff == _channel->GetPowerState()); 60 } 61 62 /** \fn R5000SignalMonitor::~R5000SignalMonitor() 63 * \brief Stops signal monitoring and table monitoring threads. 64 */ 65 R5000SignalMonitor::~R5000SignalMonitor() 66 { 67 VERBOSE(VB_CHANNEL, LOC + "dtor"); 68 Stop(); 69 } 70 71 /** \fn R5000SignalMonitor::Stop(void) 72 * \brief Stop signal monitoring and table monitoring threads. 73 */ 74 void R5000SignalMonitor::Stop(void) 75 { 76 VERBOSE(VB_CHANNEL, LOC + "Stop() -- begin"); 77 SignalMonitor::Stop(); 78 if (dtvMonitorRunning) 79 { 80 dtvMonitorRunning = false; 81 pthread_join(table_monitor_thread, NULL); 82 } 83 VERBOSE(VB_CHANNEL, LOC + "Stop() -- end"); 84 } 85 86 void R5000SignalMonitor::HandlePAT(const ProgramAssociationTable *pat) 87 { 88 AddFlags(kDTVSigMon_PATSeen); 89 90 R5000Channel *fwchan = dynamic_cast<R5000Channel*>(channel); 91 bool crc_bogus = !fwchan->GetR5000Device()->IsSTBBufferCleared(); 92 if (crc_bogus && stb_needs_to_wait_for_pat && 93 (stb_wait_for_pat_timer.elapsed() < (int)kBufferTimeout)) 94 { 95 VERBOSE(VB_CHANNEL, LOC + "HandlePAT() ignoring PAT"); 96 uint tsid = pat->TransportStreamID(); 97 GetStreamData()->SetVersionPAT(tsid, -1,0); 98 return; 99 } 100 101 if (crc_bogus && stb_needs_to_wait_for_pat) 102 { 103 VERBOSE(VB_IMPORTANT, LOC_WARN + "Wait for valid PAT timed out"); 104 stb_needs_to_wait_for_pat = false; 105 } 106 107 DTVSignalMonitor::HandlePAT(pat); 108 } 109 110 void R5000SignalMonitor::HandlePMT(uint pnum, const ProgramMapTable *pmt) 111 { 112 VERBOSE(VB_CHANNEL, LOC + "HandlePMT()"); 113 114 AddFlags(kDTVSigMon_PMTSeen); 115 116 if (!HasFlags(kDTVSigMon_PATMatch)) 117 { 118 GetStreamData()->SetVersionPMT(pnum, -1,0); 119 VERBOSE(VB_CHANNEL, LOC + "HandlePMT() ignoring PMT"); 120 return; 121 } 122 123 DTVSignalMonitor::HandlePMT(pnum, pmt); 124 } 125 126 void *R5000SignalMonitor::TableMonitorThread(void *param) 127 { 128 R5000SignalMonitor *mon = (R5000SignalMonitor*) param; 129 mon->RunTableMonitor(); 130 return NULL; 131 } 132 133 void R5000SignalMonitor::RunTableMonitor(void) 134 { 135 stb_needs_to_wait_for_pat = true; 136 stb_wait_for_pat_timer.start(); 137 dtvMonitorRunning = true; 138 139 VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- begin"); 140 141 R5000Channel *lchan = dynamic_cast<R5000Channel*>(channel); 142 if (!lchan) 143 { 144 VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- err end"); 145 dtvMonitorRunning = false; 146 return; 147 } 148 149 R5000Device *dev = lchan->GetR5000Device(); 150 151 dev->OpenPort(); 152 dev->AddListener(this); 153 154 while (dtvMonitorRunning && GetStreamData()) 155 usleep(100000); 156 157 VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- shutdown "); 158 159 dev->RemoveListener(this); 160 dev->ClosePort(); 161 162 dtvMonitorRunning = false; 163 164 VERBOSE(VB_CHANNEL, LOC + "RunTableMonitor(): -- end"); 165 } 166 167 void R5000SignalMonitor::AddData(const unsigned char *data, uint len) 168 { 169 if (!dtvMonitorRunning) 170 return; 171 172 if (GetStreamData()) 173 GetStreamData()->ProcessData((unsigned char *)data, len); 174 } 175 176 /** \fn R5000SignalMonitor::UpdateValues(void) 177 * \brief Fills in frontend stats and emits status Qt signals. 178 * 179 * This function uses five ioctl's FE_READ_SNR, FE_READ_SIGNAL_STRENGTH 180 * FE_READ_BER, FE_READ_UNCORRECTED_BLOCKS, and FE_READ_STATUS to obtain 181 * statistics from the frontend. 182 * 183 * This is automatically called by MonitorLoop(), after Start() 184 * has been used to start the signal monitoring thread. 185 */ 186 void R5000SignalMonitor::UpdateValues(void) 187 { 188 if (!running || exit) 189 return; 190 191 if (dtvMonitorRunning) 192 { 193 EmitStatus(); 194 if (IsAllGood()) 195 SendMessageAllGood(); 196 // TODO dtv signals... 197 198 update_done = true; 199 return; 200 } 201 202 if (stb_needs_to_wait_for_power && 203 (stb_wait_for_power_timer.elapsed() < (int)kPowerTimeout)) 204 { 205 return; 206 } 207 stb_needs_to_wait_for_power = false; 208 209 R5000Channel *fwchan = dynamic_cast<R5000Channel*>(channel); 210 211 if (HasFlags(kFWSigMon_WaitForPower) && !HasFlags(kFWSigMon_PowerMatch)) 212 { 213 bool retried = false; 214 while (true) 215 { 216 R5000Device::PowerState power = fwchan->GetPowerState(); 217 if (R5000Device::kAVCPowerOn == power) 218 { 219 AddFlags(kFWSigMon_PowerSeen | kFWSigMon_PowerMatch); 220 } 221 else if (R5000Device::kAVCPowerOff == power) 222 { 223 AddFlags(kFWSigMon_PowerSeen); 224 fwchan->SetPowerState(true); 225 stb_wait_for_power_timer.start(); 226 stb_needs_to_wait_for_power = true; 227 } 228 else 229 { 230 bool qfailed = (R5000Device::kAVCPowerQueryFailed == power); 231 if (qfailed && !retried) 232 { 233 retried = true; 234 continue; 235 } 236 237 VERBOSE(VB_RECORD, "Can't determine if STB is power on, " 238 "assuming it is..."); 239 AddFlags(kFWSigMon_PowerSeen | kFWSigMon_PowerMatch); 240 } 241 break; 242 } 243 } 244 245 bool isLocked = !HasFlags(kFWSigMon_WaitForPower) || 246 HasFlags(kFWSigMon_WaitForPower | kFWSigMon_PowerMatch); 247 248 if (isLocked && stb_needs_retune) 249 { 250 fwchan->Retune(); 251 isLocked = stb_needs_retune = false; 252 } 253 254 // Set SignalMonitorValues from info from card. 255 { 256 QMutexLocker locker(&statusLock); 257 signalStrength.SetValue(isLocked ? 100 : 0); 258 signalLock.SetValue(isLocked ? 1 : 0); 259 } 260 261 EmitStatus(); 262 if (IsAllGood()) 263 SendMessageAllGood(); 264 265 // Start table monitoring if we are waiting on any table 266 // and we have a lock. 267 if (isLocked && GetStreamData() && 268 HasAnyFlag(kDTVSigMon_WaitForPAT | kDTVSigMon_WaitForPMT | 269 kDTVSigMon_WaitForMGT | kDTVSigMon_WaitForVCT | 270 kDTVSigMon_WaitForNIT | kDTVSigMon_WaitForSDT)) 271 { 272 pthread_create(&table_monitor_thread, NULL, 273 TableMonitorThread, this); 274 275 VERBOSE(VB_CHANNEL, LOC + "UpdateValues() -- " 276 "Waiting for table monitor to start"); 277 278 while (!dtvMonitorRunning) 279 usleep(50); 280 281 VERBOSE(VB_CHANNEL, LOC + "UpdateValues() -- " 282 "Table monitor started"); 283 } 284 285 update_done = true; 286 } -
new file libs/libmythtv/r5000channel.h
- + 1 /** 2 * R5000Channel 3 * Copyright (c) 2008 by Alan Nisota 4 * Copyright (c) 2005 by Jim Westfall and Dave Abrahams 5 * Distributed as part of MythTV under GPL v2 and later. 6 */ 7 8 #ifndef _R5000CHANNEL_H_ 9 #define _R5000CHANNEL_H_ 10 11 #include "tv_rec.h" 12 #include "dtvchannel.h" 13 #include "r5000device.h" 14 15 class R5000Channel : public DTVChannel 16 { 17 public: 18 R5000Channel(TVRec *parent, const QString &videodevice, 19 const QString &_r5ktype, bool pocc); 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 bool power_on_channel_change; 47 R5000Device *device; 48 QString current_channel; 49 uint current_mpeg_prog; 50 bool isopen; 51 }; 52 53 #endif // _FIREWIRECHANNEL_H_ -
new file libs/libmythtv/r5000device.h
- + 1 /** 2 * R5000Device 3 * Copyright (c) 2005 by Jim Westfall 4 * Distributed as part of MythTV under GPL v2 and later. 5 */ 6 7 #ifndef _R5000_DEVICE_H_ 8 #define _R5000_DEVICE_H_ 9 10 // C++ headers 11 #include <vector> 12 using namespace std; 13 14 // Qt headers 15 #include <qstring.h> 16 #include <qmutex.h> 17 18 // MythTV headers 19 #include "streamlisteners.h" 20 21 extern "C" { 22 #include "r5000/r5000.h" 23 } 24 25 class TSPacket; 26 class R5kPriv; 27 class R5000Device 28 { 29 public: 30 31 // Public enums 32 typedef enum 33 { 34 kAVCPowerOn, 35 kAVCPowerOff, 36 kAVCPowerUnknown, 37 kAVCPowerQueryFailed, 38 } PowerState; 39 40 41 // AVC param 0 42 typedef enum 43 { 44 kAVCPowerStateOn = 0x70, 45 kAVCPowerStateOff = 0x60, 46 kAVCPowerStateQuery = 0x7f, 47 } IEEE1394UnitPowerParam0; 48 49 R5000Device(int type, QString serial); 50 ~R5000Device(); 51 52 bool OpenPort(void); 53 bool ClosePort(void); 54 void RunPortHandler(void); 55 56 // Commands 57 virtual bool ResetBus(void) { return false; } 58 59 virtual void AddListener(TSDataListener*); 60 virtual void RemoveListener(TSDataListener*); 61 62 // Sets 63 virtual bool SetPowerState(bool on); 64 virtual bool SetChannel(const QString &panel_model, 65 const QString &channel, uint mpeg_prog); 66 67 // Gets 68 bool IsSTBBufferCleared(void) const { return m_buffer_cleared; } 69 70 // non-const Gets 71 virtual PowerState GetPowerState(void); 72 73 // Statics 74 static bool IsSTBSupported(const QString &model); 75 static QString GetModelName(uint vendorid, uint modelid); 76 static QStringList GetSTBList(void); 77 static int GetDeviceType(const QString &r5ktype); 78 void BroadcastToListeners( 79 const unsigned char *data, uint dataSize); 80 81 protected: 82 83 bool GetSubunitInfo(uint8_t table[32]); 84 85 void SetLastChannel(const QString &channel); 86 void ProcessPATPacket(const TSPacket&); 87 bool StartStreaming(void); 88 bool StopStreaming(void); 89 90 int m_type; 91 QString m_serial; 92 uint m_subunitid; 93 uint m_speed; 94 QString m_last_channel; 95 uint m_last_crc; 96 bool m_buffer_cleared; 97 98 uint m_open_port_cnt; 99 vector<TSDataListener*> m_listeners; 100 mutable QMutex m_lock; 101 102 /// Vendor ID + Model ID to R5000Device STB model string 103 static QMap<uint64_t,QString> s_id_to_model; 104 static QMutex s_static_lock; 105 private: 106 r5kdev_t *usbdev; 107 R5kPriv *m_priv; 108 }; 109 110 #endif // _FIREWIRE_DEVICE_H_ -
new file libs/libmythtv/r5000recorder.h
- + 1 /** 2 * R5000Recorder 3 * Copyright (c) 2005 by Jim Westfall 4 * Distributed as part of MythTV under GPL v2 and later. 5 */ 6 7 #ifndef _R5000RECORDER_H_ 8 #define _R5000RECORDER_H_ 9 10 // MythTV headers 11 #include "dtvrecorder.h" 12 #include "tspacket.h" 13 #include "streamlisteners.h" 14 15 class TVRec; 16 class R5000Channel; 17 18 /** \class R5000Recorder 19 * \brief This is a specialization of DTVRecorder used to 20 * handle DVB and ATSC streams from a firewire input. 21 * 22 * \sa DTVRecorder 23 */ 24 class R5000Recorder : public DTVRecorder, 25 public MPEGSingleProgramStreamListener, 26 public TSDataListener 27 { 28 friend class MPEGStreamData; 29 friend class TSPacketProcessor; 30 31 public: 32 R5000Recorder(TVRec *rec, R5000Channel *chan); 33 virtual ~R5000Recorder(); 34 35 // Commands 36 bool Open(void); 37 void Close(void); 38 39 void StartStreaming(void); 40 void StopStreaming(void); 41 42 void StartRecording(void); 43 bool PauseAndWait(int timeout = 100); 44 45 void AddData(const unsigned char *data, uint dataSize); 46 void ProcessTSPacket(const TSPacket &tspacket); 47 48 // Sets 49 void SetOptionsFromProfile(RecordingProfile *profile, 50 const QString &videodev, 51 const QString &audiodev, 52 const QString &vbidev); 53 void SetStreamData(MPEGStreamData*); 54 55 // Gets 56 MPEGStreamData *GetStreamData(void) { return _mpeg_stream_data; } 57 58 // MPEG Single Program 59 void HandleSingleProgramPAT(ProgramAssociationTable*); 60 void HandleSingleProgramPMT(ProgramMapTable*); 61 62 protected: 63 R5000Recorder(TVRec *rec); 64 65 private: 66 MPEGStreamData *_mpeg_stream_data; 67 R5000Channel *channel; 68 bool isopen; 69 vector<unsigned char> buffer; 70 }; 71 72 #endif // _R5000RECORDER_H_ -
new file libs/libmythtv/r5000signalmonitor.h
- + 1 // -*- Mode: c++ -*- 2 3 #ifndef _R5000SIGNALMONITOR_H_ 4 #define _R5000SIGNALMONITOR_H_ 5 6 #include <qmap.h> 7 #include <qmutex.h> 8 #include <qdatetime.h> 9 10 #include "dtvsignalmonitor.h" 11 #include "r5000device.h" 12 #include "util.h" 13 14 class R5000Channel; 15 16 class R5000SignalMonitor : public DTVSignalMonitor, public TSDataListener 17 { 18 public: 19 R5000SignalMonitor(int db_cardnum, R5000Channel *_channel, 20 uint64_t _flags = kFWSigMon_WaitForPower, 21 const char *_name = "R5000SignalMonitor"); 22 23 virtual void HandlePAT(const ProgramAssociationTable*); 24 virtual void HandlePMT(uint, const ProgramMapTable*); 25 26 void Stop(void); 27 28 protected: 29 R5000SignalMonitor(void); 30 R5000SignalMonitor(const R5000SignalMonitor&); 31 virtual ~R5000SignalMonitor(); 32 33 virtual void UpdateValues(void); 34 35 static void *TableMonitorThread(void *param); 36 void RunTableMonitor(void); 37 38 bool SupportsTSMonitoring(void); 39 40 void AddData(const unsigned char *data, uint dataSize); 41 42 public: 43 static const uint kPowerTimeout; 44 static const uint kBufferTimeout; 45 46 protected: 47 bool dtvMonitorRunning; 48 pthread_t table_monitor_thread; 49 bool stb_needs_retune; 50 bool stb_needs_to_wait_for_pat; 51 bool stb_needs_to_wait_for_power; 52 MythTimer stb_wait_for_pat_timer; 53 MythTimer stb_wait_for_power_timer; 54 55 vector<unsigned char> buffer; 56 57 static QMap<void*,uint> pat_keys; 58 static QMutex pat_keys_lock; 59 }; 60 61 #endif // _R5000SIGNALMONITOR_H_ -
new file libs/libmythtv/r5000/libusb_augment.c
- + 1 /* Copyright 2008 Alan Nisota <alannisota@gmail.com> 2 * 2005-10-19/lindi: downloaded from http://www.gaesi.org/~nmct/cvista/cvista/ 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 // libusb_augment.c 19 // $Revision$ 20 // $Date$ 21 22 // Hopefully, the functions in this file will become part of libusb. 23 24 #include <stdio.h> 25 #include <sys/ioctl.h> 26 #include <errno.h> 27 #include <sys/time.h> 28 #include <sys/poll.h> 29 #include <usb.h> 30 #include <linux/usbdevice_fs.h> 31 #include <string.h> 32 #include <signal.h> 33 #define LIBUSB_AUGMENT 34 #include "libusb_augment.h" 35 36 // Taken from libusb file usbi.h because usb.h 37 // hides the definition of usb_dev_handle. 38 extern int usb_debug; 39 40 struct usb_dev_handle { 41 int fd; 42 43 struct usb_bus *bus; 44 struct usb_device *device; 45 46 int config; 47 int interface; 48 int altsetting; 49 50 /* Added by RMT so implementations can store other per-open-device data */ 51 void *impl_info; 52 }; 53 54 // Taken from libusb file error.h to supply error handling macro definition. 55 typedef enum { 56 USB_ERROR_TYPE_NONE = 0, 57 USB_ERROR_TYPE_STRING, 58 USB_ERROR_TYPE_ERRNO, 59 } usb_error_type_t; 60 61 extern char usb_error_str[1024]; 62 extern usb_error_type_t usb_error_type; 63 64 #define USB_ERROR_STR(format, args...) \ 65 do { \ 66 usb_error_type = USB_ERROR_TYPE_STRING; \ 67 snprintf(usb_error_str, sizeof(usb_error_str) - 1, format, ## args); \ 68 if (usb_debug >= 2) \ 69 fprintf(stderr, "USB error: %s\n", usb_error_str); \ 70 } while (0) 71 72 static int urb_signr = 0; 73 void (*urb_completion_callback)(struct usbdevfs_urb *) = NULL; 74 #define USB_ASYNC_COMPLETION_SIGNAL (SIGRTMIN + 5) 75 76 void urb_completion_handler(int signum, siginfo_t *info, void *context) 77 { 78 struct usbdevfs_urb *urb = (struct usbdevfs_urb *)info->si_addr; 79 struct usbdevfs_urb *context1; 80 usb_dev_handle *dev = (usb_dev_handle *)urb->usercontext; 81 int ret; 82 if (info->si_code != SI_ASYNCIO || 83 info->si_signo != USB_ASYNC_COMPLETION_SIGNAL) { 84 return; 85 } 86 if(info->si_errno != 0) { 87 USB_ERROR_STR("Async URB Completion failed: %s", strerror(info->si_errno)); 88 return; 89 } 90 ret = ioctl(dev->fd, USBDEVFS_REAPURB, &context1); 91 if(ret < 0) { 92 USB_ERROR_STR("Failed to read URB: %s", strerror(-ret)); 93 return; 94 } 95 if(context1 != urb) { 96 USB_ERROR_STR("Reaped unexpected urb"); 97 return; 98 } 99 if(urb_completion_callback) 100 urb_completion_callback(urb); 101 } 102 103 int usbdevfs_urb_signal_completion(void (*cb)( struct usbdevfs_urb *)) 104 { 105 urb_completion_callback = cb; 106 urb_signr = USB_ASYNC_COMPLETION_SIGNAL; 107 struct sigaction usb_linux_sa; 108 usb_linux_sa.sa_sigaction = urb_completion_handler; 109 sigfillset(&usb_linux_sa.sa_mask); 110 usb_linux_sa.sa_flags = SA_SIGINFO; 111 usb_linux_sa.sa_flags |= SA_ONSTACK; 112 sigaction(USB_ASYNC_COMPLETION_SIGNAL, &usb_linux_sa, NULL); 113 return 0; 114 } 115 116 struct usbdevfs_urb *usb_bulk_setup( 117 struct usbdevfs_urb *iso_urb, // URB pointer-pointer. 118 unsigned char ep, // Device endpoint. 119 char *bytes, // Data buffer pointer. 120 int size) { // Size of the buffer. 121 struct usbdevfs_urb *local_urb; 122 123 // No more than 16384 bytes can be transferred at a time. 124 if (size > 16384) { 125 USB_ERROR_STR("error on transfer size: %s", strerror(EINVAL)); 126 return NULL; 127 } 128 local_urb = iso_urb; 129 if (!local_urb) { 130 local_urb = (struct usbdevfs_urb *) calloc(1, sizeof(struct usbdevfs_urb)); 131 if (!local_urb) { 132 USB_ERROR_STR("error on packet size: %s", strerror(EINVAL)); 133 return NULL; 134 } 135 } 136 local_urb->type = USBDEVFS_URB_TYPE_BULK; 137 local_urb->endpoint = ep; 138 local_urb->status = 0; 139 local_urb->flags = 0; 140 local_urb->buffer = bytes; 141 local_urb->buffer_length = size; 142 local_urb->actual_length = 0; 143 local_urb->start_frame = 0; 144 local_urb->number_of_packets = 0; 145 local_urb->error_count = 0; 146 local_urb->signr = urb_signr; 147 local_urb->usercontext = (void *) 0; 148 return local_urb; 149 } 150 // Reading and writing are the same except for the endpoint 151 struct usbdevfs_urb *usb_isochronous_setup( 152 struct usbdevfs_urb *iso_urb, // URB pointer-pointer. 153 unsigned char ep, // Device endpoint. 154 int pktsize, // Endpoint packet size. 155 char *bytes, // Data buffer pointer. 156 int size) { // Size of the buffer. 157 struct usbdevfs_urb *local_urb; 158 // int ret 159 // was unused /lindi 160 int pktcount, fullpkts, partpktsize, packets, urb_size; 161 162 // No more than 32768 bytes can be transferred at a time. 163 if (size > 32768) { 164 USB_ERROR_STR("error on transfer size: %s", strerror(EINVAL)); 165 return NULL; 166 } 167 168 // Determine the number of packets that need to be created based upon the 169 // amount of data to be transferred, and the maximum packet size of the 170 // endpoint. 171 172 // Find integral number of full packets. 173 //fprintf(stderr, "buf size: %d\n", size); 174 //fprintf(stderr, "iso size: %d\n", pktsize); 175 fullpkts = size / pktsize; 176 //fprintf(stderr, "Number of full packets: %d\n", fullpkts); 177 // Find length of partial packet. 178 partpktsize = size % pktsize; 179 //fprintf(stderr, "Size of partial packet: %d\n", partpktsize); 180 // Find total number of packets to be transfered. 181 packets = fullpkts + ((partpktsize > 0) ? 1 : 0); 182 //fprintf(stderr, "Total number of packets: %d\n", packets); 183 // Limit the number of packets transfered according to 184 // the Linux usbdevfs maximum read/write buffer size. 185 if ((packets < 1) || (packets > 128)) { 186 USB_ERROR_STR("error on packet size: %s", strerror(EINVAL)); 187 return NULL; 188 } 189 190 // If necessary, allocate the urb and packet 191 // descriptor structures from the heap. 192 local_urb = iso_urb; 193 if (!local_urb) { 194 urb_size = sizeof(struct usbdevfs_urb) + 195 packets * sizeof(struct usb_iso_packet_desc); 196 local_urb = (struct usbdevfs_urb *) calloc(1, urb_size); 197 if (!local_urb) { 198 USB_ERROR_STR("error on packet size: %s", strerror(EINVAL)); 199 return NULL; 200 } 201 } 202 203 // Set up each packet for the data to be transferred. 204 for (pktcount = 0; pktcount < fullpkts; pktcount++) { 205 local_urb->iso_frame_desc[pktcount].length = pktsize; 206 local_urb->iso_frame_desc[pktcount].actual_length = 0; 207 local_urb->iso_frame_desc[pktcount].status = 0; 208 } 209 210 // Set up the last packet for the partial data to be transferred. 211 if (partpktsize > 0) { 212 local_urb->iso_frame_desc[pktcount].length = partpktsize; 213 local_urb->iso_frame_desc[pktcount].actual_length = 0; 214 local_urb->iso_frame_desc[pktcount++].status = 0; 215 } 216 217 // Set up the URB structure. 218 local_urb->type = USBDEVFS_URB_TYPE_ISO; 219 //fprintf(stderr, "type: %d\n", local_urb->type); 220 local_urb->endpoint = ep; 221 //fprintf(stderr, "endpoint: 0x%x\n", local_urb->endpoint); 222 local_urb->status = 0; 223 local_urb->flags = USBDEVFS_URB_ISO_ASAP; // Additional flags here? 224 //fprintf(stderr, "flags: %d\n", local_urb->flags); 225 local_urb->buffer = bytes; 226 //fprintf(stderr, "buffer: 0x%x\n", local_urb->buffer); 227 local_urb->buffer_length = size; 228 //fprintf(stderr, "buffer_length: %d\n", local_urb->buffer_length); 229 local_urb->actual_length = 0; 230 local_urb->start_frame = 0; 231 //fprintf(stderr, "start_frame: %d\n", local_urb->start_frame); 232 local_urb->number_of_packets = pktcount; 233 //fprintf(stderr, "number_of_packets: %d\n", local_urb->number_of_packets); 234 local_urb->error_count = 0; 235 local_urb->signr = 0; 236 //fprintf(stderr, "signr: %d\n", local_urb->signr); 237 local_urb->usercontext = (void *) 0; 238 return local_urb; 239 } 240 241 242 int usb_urb_submit(usb_dev_handle *dev, // Open usb device handle. 243 struct usbdevfs_urb *iso_urb, // Pointer to URB. 244 struct timeval *tv_submit) { // Time structure pointer. 245 int ret; 246 247 iso_urb->usercontext = dev; 248 // Get actual time, of the URB submission. 249 if(tv_submit) 250 gettimeofday(tv_submit, NULL); 251 // Submit the URB through an IOCTL call. 252 ret = ioctl(dev->fd, USBDEVFS_SUBMITURB, iso_urb); 253 //fprintf(stderr, "start_frame now: %d\n", iso_urb->start_frame); 254 //fprintf(stderr, "submit ioctl return value: %d\n", ret); 255 if (ret < 0) { 256 //fprintf(stderr, "error submitting URB: %s\n", strerror(errno)); 257 USB_ERROR_STR("error submitting URB: %s", strerror(errno)); 258 return -errno; 259 } 260 return ret; 261 } 262 263 264 int usb_urb_reap(usb_dev_handle *dev, // Open usb device handle. 265 struct usbdevfs_urb *iso_urb, // Pointer to URB. 266 int timeout) { // Attempt timeout (usec). 267 void *context = NULL; 268 int ret; 269 struct pollfd ufd[1]; 270 271 // Get actual time, and add the timeout value. The result is the absolute 272 // time where we have to quit waiting for an isochronous message. 273 ufd[0].fd = dev->fd; 274 ufd[0].events = POLLIN | POLLOUT; 275 ufd[0].revents = 0; 276 ret = poll(ufd, 1, timeout); 277 if(ret <= 0) 278 return -ETIMEDOUT; 279 280 //fprintf(stderr, "preparing to reap\n"); 281 ret = ioctl(dev->fd, USBDEVFS_REAPURB, &context); 282 283 /* 284 * If there was an error, that wasn"t EAGAIN (no completion), then 285 * something happened during the reaping and we should return that 286 * error now 287 */ 288 //fprintf(stderr, "reap ioctl return value: %d\n", ret); 289 if (ret < 0) { 290 USB_ERROR_STR("error reaping interrupt URB: %s", 291 strerror(errno)); 292 return -errno; 293 } 294 295 //fprintf(stderr, "actual_length: %d\n", iso_urb->actual_length); 296 //fprintf(stderr, "URB status: %d\n", iso_urb->status); 297 //fprintf(stderr, "error count: %d\n", iso_urb->error_count); 298 299 //fprintf(stderr, "waiting done\n"); 300 if(context != NULL && iso_urb != context) { 301 fprintf(stderr, "Expected urb: %p but got %p\n", iso_urb, context); 302 return -1; 303 } 304 //fprintf(stderr, "Total bytes: %d\n", bytesdone); 305 return iso_urb->actual_length; 306 } 307 308 int usb_urb_cancel(usb_dev_handle *dev, struct usbdevfs_urb *iso_urb) 309 { 310 return ioctl(dev->fd, USBDEVFS_DISCARDURB, iso_urb); 311 } -
new file libs/libmythtv/r5000/libusb_augment.h
- + 1 /* Copyright 2008 Alan Nisota <alannisota@gmail.com> 2 * 2005-10-19/lindi: downloaded from http://www.gaesi.org/~nmct/cvista/cvista/ 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #ifdef LIBUSB_AUGMENT 19 // Taken from libusb file linux.h to provide the URB structure definitions. 20 struct usb_iso_packet_desc { 21 unsigned int length; 22 unsigned int actual_length; 23 unsigned int status; 24 }; 25 #endif 26 27 int usbdevfs_urb_signal_completion(void (*cb)( struct usbdevfs_urb *)); 28 struct usbdevfs_urb *usb_bulk_setup(struct usbdevfs_urb *iso_urb, unsigned char ep, 29 char *bytes, int size); 30 struct usbdevfs_urb *usb_isochronous_setup(struct usbdevfs_urb *iso_urb, 31 unsigned char ep, int pktsize, char *bytes, int size); 32 int usb_urb_submit(usb_dev_handle *dev, struct usbdevfs_urb *iso_urb, 33 struct timeval *tv_rsubmit); 34 int usb_urb_reap(usb_dev_handle *dev, struct usbdevfs_urb *iso_urb, 35 int timeout_usec); 36 int usb_urb_cancel(usb_dev_handle *dev, struct usbdevfs_urb *iso_urb); -
new file libs/libmythtv/r5000/r5000.c
- + 1 /* Copyright 2008 Alan Nisota <alannisota@gmail.com> 2 * 3 * This library is free software; you can redistribute it and/or 4 * modify it under the terms of the GNU Lesser General Public 5 * License as published by the Free Software Foundation; either 6 * version 2.1 of the License, or (at your option) any later version. 7 * 8 * This library is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * Lesser General Public License for more details. 12 * 13 * You should have received a copy of the GNU Lesser General Public 14 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 17 #include <stdio.h> 18 #include <sys/types.h> 19 #include <sys/stat.h> 20 #include <fcntl.h> 21 #include <string.h> 22 #include <errno.h> 23 #include <stdarg.h> 24 25 #ifdef R5K_DEBUG 26 char strmfile[256] = "/tmp/strm"; 27 int fd = -1; 28 #endif 29 30 #ifdef R5K_RAWUSB 31 int usbfd = -1; 32 #endif 33 #include "r5000_internal.h" 34 #include "r5000init.h" 35 36 #define R5K_WARM_VID 0x0547 37 #define R5K_WARM_PID 0x1002 38 39 #define MAX_URBS_IN_FLIGHT 128 40 41 #ifndef USE_ISOCHRONOUS 42 //BULK 43 #define R5K_URB_BUFFER_SIZE (1 << 14) 44 #else 45 //ISOCHRONOUS 46 #define LIBUSB_AUGMENT 47 #define R5K_URB_BUFFER_SIZE (1 << 15) 48 #endif 49 #include "libusb_augment.h" 50 51 static int r5000_usb_init = 0; 52 static struct { 53 unsigned char serial[R5K_MAX_DEVS][8]; 54 struct usb_device *dev[R5K_MAX_DEVS]; 55 int count; 56 } r5000_dev_map; 57 58 static void (*msgcb)(char *msg); 59 60 enum { 61 R5K_PMT_START = 0x01, 62 R5K_PMT_READY = 0x02 63 }; 64 65 void r5000_print(const char *fmt, ...) 66 { 67 va_list args; 68 char logmsg[1024]; 69 va_start(args,fmt); 70 vsnprintf(logmsg,sizeof(logmsg),fmt,args); 71 va_end(args); 72 if(msgcb) { 73 //msgcb routine must ensure thread safeness 74 msgcb(logmsg); 75 } else { 76 fprintf(stderr, logmsg); 77 } 78 } 79 80 int r5000_create_urbs(r5kdev_t *r5kdev) 81 { 82 int i, urbsize; 83 #ifndef USE_ISOCHRONOUS 84 urbsize = sizeof(struct usbdevfs_urb); 85 #else 86 urbsize = sizeof(struct usbdevfs_urb) + sizeof(struct usb_iso_packet_desc) * R5K_URB_BUFFER_SIZE / 1024; 87 #endif 88 89 r5kdev->buffer = malloc(R5K_URB_BUFFER_SIZE * MAX_URBS_IN_FLIGHT); 90 r5kdev->urbs = (struct usbdevfs_urb **)malloc(sizeof(struct usbdevfs_urb *) * MAX_URBS_IN_FLIGHT); 91 r5kdev->urbblk = (void *)malloc(urbsize * MAX_URBS_IN_FLIGHT); 92 for(i = 0; i < MAX_URBS_IN_FLIGHT; i++) { 93 r5kdev->urbs[i] = (struct usbdevfs_urb *)((unsigned long)r5kdev->urbblk + (urbsize * i)); 94 #ifndef USE_ISOCHRONOUS 95 usb_bulk_setup(r5kdev->urbs[i], 0x82, r5kdev->buffer + (R5K_URB_BUFFER_SIZE*i), R5K_URB_BUFFER_SIZE); 96 #else 97 usb_isochronous_setup(r5kdev->urbs[i], 0x82, 1024, r5kdev->buffer + (R5K_URB_BUFFER_SIZE*i), R5K_URB_BUFFER_SIZE); 98 #endif 99 } 100 r5kdev->nexturb = 0; 101 return 1; 102 } 103 104 int r5000_free_urbs(r5kdev_t *r5kdev) 105 { 106 free(r5kdev->urbblk); 107 free(r5kdev->urbs); 108 free(r5kdev->buffer); 109 return 0; 110 } 111 112 usb_dev_handle *r5000_locate_device( 113 unsigned short vendor_id, unsigned short product_id, int skip) 114 { 115 struct usb_bus *bus; 116 struct usb_device *dev; 117 usb_dev_handle *device_handle = 0; 118 usb_find_busses(); 119 usb_find_devices(); 120 121 for (bus = usb_get_busses(); bus && !device_handle; bus = bus->next) 122 { 123 for (dev = bus->devices; dev && !device_handle; dev = dev->next) 124 { 125 if (dev->descriptor.idVendor == vendor_id && 126 dev->descriptor.idProduct == product_id) 127 { 128 device_handle = usb_open(dev); 129 if(device_handle && skip) { 130 usb_close(device_handle); 131 device_handle = NULL; 132 skip--; 133 } 134 } 135 } 136 } 137 138 if (device_handle) { 139 int open_status = usb_set_configuration(device_handle,1); 140 141 open_status = usb_claim_interface(device_handle,0); 142 143 open_status = usb_set_altinterface(device_handle,0); 144 } 145 return (device_handle); 146 } 147 148 int r5000_dev_init(r5kdev_t *r5kdev) { 149 int i, bytes; 150 unsigned char *ptr, *serial = r5kdev->serial; 151 unsigned char datain[0x80]; 152 bytes = usb_bulk_read(r5kdev->handle, 129, datain, sizeof(datain), 5000); 153 for(i = 0; i < R5K_INIT_SERIAL; i++) { 154 //PRINTHEX("Write:\n", r5kinit[i].data, r5kinit[i].wlen); 155 if(r5kinit[i].wsleep) usleep(r5kinit[i].wsleep); 156 usb_bulk_write(r5kdev->handle, 1, r5kinit[i].data, r5kinit[i].wlen, 5000); 157 if(r5kinit[i].rsleep) usleep(r5kinit[i].rsleep); 158 bytes = usb_bulk_read(r5kdev->handle, 129, datain, sizeof(datain), 5000); 159 //PRINTHEX("Read:\n", datain, bytes); 160 if(r5kinit[i].rlen > 0 && bytes != r5kinit[i].rlen) { 161 r5000_print("R5000 initialization failed at stage %d:\n\tExpected %d bytes, but got %d bytes\n", i, r5kinit[i].rlen, bytes); 162 return 0; 163 } 164 } 165 166 //last read is serial # 167 if (datain[0] != 0x08) { 168 r5000_print("R5000 initialization failed reading serial #\n"); 169 return 0; 170 } 171 for(ptr = datain + 6; ptr < datain + 13; ptr++) { 172 *serial++ = ( *ptr >= '0' && *ptr <= 'z' ) ? *ptr : '*'; 173 } 174 *serial = 0; 175 176 //complete initialization now 177 for(; i < R5K_INIT_MAX; i++) { 178 //PRINTHEX("Write:\n", r5kinit[i].data, r5kinit[i].wlen); 179 if(r5kinit[i].wsleep) usleep(r5kinit[i].wsleep); 180 usb_bulk_write(r5kdev->handle, 1, r5kinit[i].data, r5kinit[i].wlen, 5000); 181 if(r5kinit[i].rsleep) usleep(r5kinit[i].rsleep); 182 bytes = usb_bulk_read(r5kdev->handle, 129, datain, sizeof(datain), 5000); 183 //PRINTHEX("Read:\n", datain, bytes); 184 if(r5kinit[i].rlen > 0 && bytes != r5kinit[i].rlen) { 185 r5000_print("R5000 initialization failed at stage %d:\n\tExpected %d bytes, but got %d bytes\n", i, r5kinit[i].rlen, bytes); 186 return 0; 187 } 188 } 189 return 1; 190 } 191 192 int r5000_start_stream(r5kdev_t *r5kdev) 193 { 194 unsigned char data[0x80]; 195 int bytes; 196 int i; 197 struct usb_dev_handle *handle = (struct usb_dev_handle *)r5kdev->handle; 198 199 if(! r5kdev->urbs) 200 r5000_create_urbs(r5kdev); 201 202 data[0] = 0x30; 203 usb_bulk_write(handle, 1, data, 1, 5000); 204 bytes = usb_bulk_read(handle, 129, data, 2, 5000); 205 206 //0x50 sets byte mode. Use '0x60' to set word mode 207 data[0] = r5kdev->read_words ? 0x60: 0x50; 208 usb_bulk_write(handle, 1, data, 1, 5000); 209 210 for(i=0; i < MAX_URBS_IN_FLIGHT; i++) { 211 usb_urb_submit(handle, r5kdev->urbs[i], NULL); 212 } 213 r5kdev->nexturb = 0; 214 r5kdev->streaming = 1; 215 if(r5kdev->start_stream) 216 r5kdev->start_stream(r5kdev); 217 return 1; 218 } 219 220 int r5000_stop_stream(r5kdev_t *r5kdev) 221 { 222 struct usb_dev_handle *handle = (struct usb_dev_handle *)r5kdev->handle; 223 struct usbdevfs_urb **urbs = r5kdev->urbs; 224 int i; 225 226 if(r5kdev->streaming) { 227 for(i=0; i < MAX_URBS_IN_FLIGHT; i++) 228 usb_urb_cancel(handle, urbs[i]); 229 r5kdev->streaming = 0; 230 } 231 return 1; 232 } 233 234 /* r5000_init must be called from a thread-safe context */ 235 int r5000_init(void (*_msgcb)(char *str)) 236 { 237 int bus_count, dev_count; 238 r5kdev_t r5kd; 239 int count = 0; 240 241 msgcb = _msgcb; 242 243 if(r5000_usb_init) 244 return 1; 245 usb_init(); 246 bus_count = usb_find_busses(); 247 dev_count = usb_find_devices(); 248 if(bus_count == 0 || dev_count ==0) { 249 r5000_print("R5000 failed to locate any USB devices. Are you sure you have permissions set properly?\n"); 250 return 0; 251 } 252 while(r5000_dev_map.count < R5K_MAX_DEVS) { 253 r5kd.handle = r5000_locate_device(R5K_WARM_VID, R5K_WARM_PID, count); 254 if(! r5kd.handle) 255 break; 256 if (r5000_dev_init(&r5kd)) { 257 memcpy(r5000_dev_map.serial[r5000_dev_map.count], r5kd.serial, 8); 258 r5000_dev_map.dev[r5000_dev_map.count] = usb_device(r5kd.handle); 259 r5000_dev_map.count++; 260 } 261 count++; 262 usb_close(r5kd.handle); 263 } 264 if(! r5000_dev_map.count) { 265 r5000_print("R5000 failed to locate any R5000 devices. Are you sure you have permissions set properly?\n"); 266 return 0; 267 } 268 r5000_usb_init = 1; 269 return 1; 270 } 271 272 r5kdev_t *r5000_open(r5ktype_t type, 273 unsigned int (*cb)(unsigned char *buffer, int len, void *callback_data), 274 void *cb_data, 275 const char *serial) 276 { 277 r5kdev_t *r5kdev, r5kd; 278 int count = 0; 279 memset(&r5kd, 0, sizeof(r5kdev_t)); 280 281 if(! r5000_usb_init) { 282 r5000_print("R5000 was not initialized before r5000_open(). Please call r5000_init() first\n"); 283 return NULL; 284 } 285 for(count = 0; count < r5000_dev_map.count; count++) { 286 if(! serial || memcmp(r5000_dev_map.serial[count], serial, 8) == 0) { 287 r5kd.handle = usb_open(r5000_dev_map.dev[count]); 288 if(! r5kd.handle) 289 return NULL; 290 usb_set_configuration(r5kd.handle,1); 291 usb_claim_interface(r5kd.handle,0); 292 usb_set_altinterface(r5kd.handle,0); 293 if(! r5000_dev_init(&r5kd)) { 294 usb_close(r5kd.handle); 295 return NULL; 296 } 297 break; 298 } 299 } 300 if(count == r5000_dev_map.count) { 301 //We can't get here unless a serial was specified 302 r5000_print("Could not locate R5000 device with serial '%s'\n", serial); 303 return NULL; 304 } 305 #ifdef R5K_DEBUG 306 printf("Reading stream file: %s\n", strmfile); 307 fd = open(strmfile, O_RDONLY); 308 #endif 309 #ifdef R5K_RAWUSB 310 usbfd = open("raw.av", O_WRONLY | O_CREAT | O_TRUNC, 0666); 311 #endif 312 r5kdev = (r5kdev_t *)malloc(sizeof(r5kdev_t)); 313 *r5kdev = r5kd; 314 r5kdev->urbs = NULL; 315 r5kdev->cb = cb; 316 r5kdev->cb_data = cb_data; 317 r5kdev->stb_type = type; 318 switch(type) { 319 case R5K_STB_VIP211: 320 case R5K_STB_VIP622: 321 vip_init(r5kdev); 322 break; 323 case R5K_STB_DIRECTV: 324 case R5K_STB_DISH6000: 325 pes_init(r5kdev); 326 break; 327 case R5K_STB_DSR: 328 case R5K_STB_HDD: 329 sat_init(r5kdev); 330 break; 331 default: 332 r5000_print("Unknown STB type %d specified.\n", type); 333 r5kdev->stb_type = R5K_STB_VIP211; 334 vip_init(r5kdev); 335 break; 336 } 337 return r5kdev; 338 } 339 340 int r5000_close(r5kdev_t *r5kdev) 341 { 342 if(! r5kdev) 343 return 1; 344 if(r5kdev->urbs) { 345 if(r5kdev->streaming) 346 r5000_stop_stream(r5kdev); 347 r5000_free_urbs(r5kdev); 348 } 349 usb_close(r5kdev->handle); 350 #ifdef R5K_RAWUSB 351 if(usbfd >= 0) close(usbfd); 352 #endif 353 switch(r5kdev->stb_type) { 354 case R5K_STB_VIP211: 355 case R5K_STB_VIP622: 356 vip_free(r5kdev); 357 break; 358 case R5K_STB_DIRECTV: 359 case R5K_STB_DISH6000: 360 pes_free(r5kdev); 361 break; 362 case R5K_STB_DSR: 363 case R5K_STB_HDD: 364 sat_free(r5kdev); 365 break; 366 } 367 free(r5kdev); 368 return 1; 369 } 370 371 int r5000_loop_iterate(r5kdev_t *r5kdev, int timeout_usec) 372 { 373 struct usb_dev_handle *handle = (struct usb_dev_handle *)r5kdev->handle; 374 struct usbdevfs_urb **urbs = r5kdev->urbs; 375 int len; 376 unsigned char *buf; 377 if(! r5kdev->streaming) 378 return -1; 379 len = usb_urb_reap(handle, urbs[r5kdev->nexturb], timeout_usec); 380 if(len <= 0) { 381 if(len != -ETIMEDOUT) 382 r5000_print("(%d) Reap failed at %08x: %s\n", r5kdev->nexturb, r5kdev->bytes_read, strerror(errno)); 383 return len; 384 } 385 buf = r5kdev->buffer + (R5K_URB_BUFFER_SIZE*r5kdev->nexturb); 386 #ifdef R5K_RAWUSB 387 if(usbfd >= 0) write(usbfd, buf, len); 388 #endif 389 #ifdef R5K_DEBUG 390 if(fd >= 0) { 391 int newlen = read(fd, buf, len); 392 if(newlen < len) { 393 r5000_print("hit end of debug file\n"); 394 lseek(fd, 0, SEEK_SET); 395 read(fd, buf + newlen, len - newlen); 396 } 397 } 398 #endif 399 r5kdev->process_block(r5kdev, buf, len); 400 r5kdev->bytes_read += len; 401 usb_urb_submit(handle, urbs[r5kdev->nexturb], NULL); 402 r5kdev->nexturb = (r5kdev->nexturb + 1) % MAX_URBS_IN_FLIGHT; 403 return 0; 404 } 405 406 //use this to read a status frame. It doesn't do anything special 407 //but makes it obvious what data is expected 408 int r5000_read_status(r5kdev_t *r5kdev, unsigned char *buf) 409 { 410 return usb_bulk_read(r5kdev->handle, 129, buf, 128, 5000); 411 } 412 413 int r5000_get_power_state(r5kdev_t *r5kdev) 414 { 415 unsigned char data1[1] = { 0x30 }; 416 unsigned char data2[0x80]; 417 int count = 10; 418 while(count--) { 419 r5000_read_status(r5kdev, data2); 420 usb_bulk_write(r5kdev->handle, 1, data1, 1, 5000); 421 usleep(100000); 422 if(usb_bulk_read(r5kdev->handle, 1, data2, 2, 5000) == 2 && 423 data2[0] == 0x0a && (data2[1] & 0x4e) == 0x4c) { 424 // The following boxes are known to be power active low: 425 // 4DTV 922, Dish 622/722, Bell 9242, D* 426 if(r5kdev->power_active_low) 427 return (!(data2[1] == 0x4d)); 428 else 429 return (!!(data2[1] == 0x4d)); 430 } 431 usleep(100000); 432 } 433 r5000_print("R5000 failed to read power state. Assuming ON state\n"); 434 return 1; 435 } 436 437 int r5000_send_pwr_cmd(r5kdev_t *r5kdev, unsigned char *data) 438 { 439 unsigned char data1[1] = { 0x30 }; 440 unsigned char data3[0x80]; 441 int len; 442 usb_bulk_write(r5kdev->handle, 1, data1, 1, 5000); 443 usleep(100000); 444 usb_bulk_write(r5kdev->handle, 1, data, r5kdev->button->len, 5000); 445 usleep(100000); 446 len = usb_bulk_read(r5kdev->handle, 1, data3, 2, 5000); 447 usleep(100000); 448 return len; 449 } 450 451 int r5000_wait_pwr(r5kdev_t *r5kdev, int on_off) 452 { 453 int new_state, count = 20; 454 while(count-- && (new_state = r5000_get_power_state(r5kdev)) != on_off) 455 usleep(100000); 456 //r5000_print("End state: %s\n", !on_off ? "On" : "Off"); 457 return new_state; 458 } 459 460 int r5000_toggle_on_off(r5kdev_t *r5kdev) 461 { 462 unsigned on_off; 463 on_off = r5000_get_power_state(r5kdev); 464 if(! r5kdev->button) { 465 r5000_print("No button IR commands defined for this device!\n"); 466 return on_off; 467 } 468 //r5000_print("Start state: %s\n", on_off ? "On" : "Off"); 469 r5000_send_pwr_cmd(r5kdev, r5kdev->button->power); 470 on_off = r5000_wait_pwr(r5kdev, ! on_off); 471 //r5000_print("End state: %s\n", on_off ? "On" : "Off"); 472 return on_off; 473 } 474 475 int r5000_power_on_off(r5kdev_t *r5kdev, int turn_on) 476 { 477 unsigned char *pwr_command; 478 int on_off = r5000_get_power_state(r5kdev); 479 if(on_off == turn_on) { 480 return on_off; 481 } 482 if(! r5kdev->button) { 483 r5000_print("No button IR commands defined for this device!\n"); 484 return on_off; 485 } 486 if(r5kdev->discrete_power) { 487 //r5000_print("Using discrete power commands\n"); 488 if(turn_on) { 489 pwr_command = r5kdev->button->power_on; 490 } else { 491 pwr_command = r5kdev->button->power_off; 492 } 493 } else { 494 pwr_command = r5kdev->button->power; 495 } 496 r5000_send_pwr_cmd(r5kdev, pwr_command); 497 return r5000_wait_pwr(r5kdev, turn_on); 498 } 499 500 int r5000_change_channel(r5kdev_t *r5kdev, const char *chan, int mpeg_prog) 501 { 502 unsigned char data2[0x80]; 503 unsigned char *ptr = NULL; 504 const char *p; 505 if(! r5kdev) 506 return 0; 507 if (chan) { 508 if(! r5kdev->button) { 509 r5000_print("No button IR commands defined for this device!\n"); 510 } else { 511 r5000_read_status(r5kdev, data2); 512 usb_bulk_write(r5kdev->handle, 1, r5kdev->button->clear, r5kdev->button->len, 5000); 513 usleep(r5kdev->button->delay); 514 for(p = chan; *p; p++) { 515 ptr = NULL; 516 switch(*p) { 517 case '0' : ptr = r5kdev->button->b0; break; 518 case '1' : ptr = r5kdev->button->b1; break; 519 case '2' : ptr = r5kdev->button->b2; break; 520 case '3' : ptr = r5kdev->button->b3; break; 521 case '4' : ptr = r5kdev->button->b4; break; 522 case '5' : ptr = r5kdev->button->b5; break; 523 case '6' : ptr = r5kdev->button->b6; break; 524 case '7' : ptr = r5kdev->button->b7; break; 525 case '8' : ptr = r5kdev->button->b8; break; 526 case '9' : ptr = r5kdev->button->b9; break; 527 case 'P' : r5000_power_on_off(r5kdev, 2); break; 528 } 529 if(ptr) { 530 usb_bulk_write(r5kdev->handle, 1, ptr, r5kdev->button->len, 5000); 531 } 532 usleep(r5kdev->button->delay); 533 } 534 usb_bulk_write(r5kdev->handle, 1, r5kdev->button->enter, r5kdev->button->len, 5000); 535 } 536 } 537 r5kdev->channel = mpeg_prog; 538 if(r5kdev->change_channel) 539 r5kdev->change_channel(r5kdev); 540 return 1; 541 } 542 543 int r5000_find_stbs(r5kenum_t *devs) 544 { 545 devs->count = 0; 546 if(! r5000_usb_init) { 547 r5000_print("R5000 was not initialized before r5000_find_stbs(). Please call r5000_init() first\n"); 548 return 0; 549 } 550 devs->count = r5000_dev_map.count; 551 memcpy(devs->serial, r5000_dev_map.serial, 8 * r5000_dev_map.count); 552 return 1; 553 } -
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_DISH6000, 37 R5K_STB_MAX, 38 } r5ktype_t; 39 40 extern int r5000_init(void (*_msgcb)(char *str)); 41 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); 42 extern int r5000_close(r5kdev_t *r5kdev); 43 extern int r5000_start_stream(r5kdev_t *r5kdev); 44 extern int r5000_stop_stream(r5kdev_t *r5kdev); 45 extern int r5000_loop_iterate(r5kdev_t *r5kdev, int timeout_usec); 46 extern int r5000_get_power_state(r5kdev_t *r5kdev); 47 extern int r5000_toggle_on_off(r5kdev_t *r5kdev); 48 extern int r5000_power_on_off(r5kdev_t *r5kdev, int turn_on); 49 extern int r5000_change_channel(r5kdev_t *r5kdev, const char *chan, int mpeg_prog); 50 extern int r5000_find_stbs(r5kenum_t *devs); 51 #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 DirecTV and Dish/BEV 6000 boxes 107 extern void pes_init(r5kdev_t *r5kdev); 108 extern void pes_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 //Buttons 119 extern struct r5000_buttons vip_button_cmd; 120 extern struct r5000_buttons directv_button_cmd; 121 extern struct r5000_buttons dish6000_button_cmd; 122 #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 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_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 {"dish6000"}, 59 {0}, 60 }; 61 62 extern char strmfile[255]; 63 void help(char *cmdline) { 64 int i; 65 printf("%s <-t type> <--m command> [--c channel] [--s serial] [-h]\n", cmdline); 66 printf("\t-t/--type type : set STB type to type. 'type' can be either\n"); 67 printf("\t a numerical value or string. Valid types are:\n"); 68 for(i = 0; stb_names[i][0] != 0; i++) { 69 printf("\t\t%d: %s\n", i, stb_names[i]); 70 } 71 printf("\t-m/--cmd command : set command to execute. 'command' can be either\n"); 72 printf("\t a numerical value or string. Valid commands are:\n"); 73 for(i = 0; i < MAX_CMD; i++) { 74 printf("\t\t%d: %s\n", i, cmd_names[i]); 75 } 76 printf("\t-c/--channel : set channel to read (this does NOT tune\n"); 77 printf("\t-s/--serial serial : set serial number\n"); 78 printf("\t-h/--help : show this help message\n"); 79 exit(0); 80 } 81 82 void printstr(char *str) 83 { 84 fprintf(stderr, "%s", str); 85 } 86 87 static unsigned char buffer[1000189]; 88 static unsigned char *ptr = buffer; 89 unsigned int r5000_device_tspacket_handler(unsigned char *tspacket, int len, void *callback_data) 90 { 91 int fd = *(int *) callback_data; 92 if (len <= 0) 93 return 0; 94 if(memcpy(ptr, tspacket, len)); 95 ptr+=len; 96 if(ptr-buffer > 1000000) { 97 write(fd, buffer, ptr-buffer); 98 ptr = buffer; 99 } 100 return 1; 101 } 102 103 int main(int argc, char *argv[]) 104 { 105 r5kdev_t *usbdev = NULL; 106 int glblfd, i, j; 107 unsigned char buf[0x80]; 108 int stb = -1; 109 int cmd = -1; 110 const char *channel = NULL; 111 const char *serial = NULL; 112 int runtime = 10; 113 struct option long_options[] = { 114 {"type", required_argument, NULL, 't'}, 115 {"cmd", required_argument, NULL, 'm'}, 116 {"channel", required_argument, NULL, 'c'}, 117 {"serial", required_argument, NULL, 's'}, 118 {"time", required_argument, NULL, 'i'}, 119 {"dbgfile", required_argument, NULL, 'D'}, 120 {"help", no_argument , NULL, 'h'}, 121 {0, 0, 0, 0} 122 }; 123 while (1) { 124 char c; 125 c = getopt_long (argc, argv, 126 "t:m:c:s:hD:i:", 127 long_options, NULL); 128 if(c == EOF) 129 break; 130 switch(c) { 131 case 't': 132 { 133 char *ptr; 134 int i; 135 stb = strtol(optarg, &ptr, 10); 136 if(ptr == optarg) { 137 stb = -1; 138 for(i = 0; stb_names[i][0] != 0; i++) { 139 if(strncasecmp(optarg, stb_names[i], strlen(stb_names[i])) == 0) { 140 stb = i; 141 break; 142 } 143 } 144 if(stb == -1) { 145 fprintf(stderr, "Unknown STB type: %s\n", optarg); 146 exit(-1); 147 } 148 } else if(stb < 0 || stb >= R5K_STB_MAX) { 149 fprintf(stderr, "Illegal STB type: %d\n", stb); 150 exit(-1); 151 } 152 break; 153 } 154 case 'm': 155 { 156 char *ptr; 157 int i; 158 cmd = strtol(optarg, &ptr, 10); 159 if(ptr == optarg) { 160 cmd = -1; 161 for(i = 0; i < MAX_CMD; i++) { 162 if(strncasecmp(optarg, cmd_names[i], strlen(cmd_names[i])) == 0) { 163 cmd = i; 164 break; 165 } 166 } 167 if(cmd == -1) { 168 fprintf(stderr, "Unknown command: %d\n", optarg); 169 exit(-1); 170 } 171 } else if(cmd < 0 || cmd >= MAX_CMD) { 172 fprintf(stderr, "Illegal command: %d\n", cmd); 173 exit(-1); 174 } 175 break; 176 } 177 case 'c': 178 { 179 int ok = 1; 180 char *p; 181 if(! strlen(optarg)) { 182 fprintf(stderr, "Couldn't parse channel '%s'\n", optarg); 183 ok = 0; 184 } 185 for(p = optarg; *p; p++) { 186 if(*p != 'P' && *p != ',' && (*p < '0' || *p > '9')) { 187 fprintf(stderr, "Couldn't parse channel '%s'\n", optarg); 188 ok = 0; 189 break; 190 } 191 } 192 if(ok) 193 channel = optarg; 194 break; 195 } 196 case 'i': 197 { 198 char *ptr; 199 runtime = strtol(optarg, &ptr, 0); 200 if(optarg == ptr) { 201 fprintf(stderr, "Couldn't parse time '%s'\n", optarg); 202 } 203 break; 204 } 205 case 's': 206 serial = optarg; 207 break; 208 case 'h': 209 help(argv[0]); 210 break; 211 case 'D': 212 #ifdef R5K_DEBUG 213 strncpy(strmfile, optarg, 255); 214 #else 215 fprintf(stderr, "--dbgfile only supported in debug mode.\nMake sure you know what you are doing!\n"); 216 exit(-1); 217 #endif 218 } 219 } 220 if(cmd == -1 || stb == -1) { 221 fprintf(stderr, "Must specify --cmd and --stb\n"); 222 exit(-1); 223 } 224 r5000_init(printstr); 225 if(cmd == SCAN_DEVICES) { 226 r5kenum_t devs; 227 printf("Scanning for R5000 devices\n"); 228 if(! r5000_find_stbs(&devs)) { 229 printf("Failed to initialize r5000 devices\n"); 230 } 231 for(i=0; i < devs.count; i++) { 232 printf("Found: %s\n", devs.serial[i]); 233 } 234 goto end; 235 } 236 usbdev = r5000_open(stb, r5000_device_tspacket_handler, &glblfd, serial); 237 if(! usbdev) { 238 fprintf(stderr, "R5000 device could not be found/opened\n"); 239 exit(-1); 240 } 241 glblfd=open("raw.ts", O_WRONLY | O_TRUNC | O_CREAT, 0666); 242 if(cmd == TOGGLE_POWER) { 243 int new_state; 244 printf("Toggling On/Off\n"); 245 new_state = r5000_toggle_on_off(usbdev); 246 printf("Turned power %s\n", new_state ? "On" : "Off"); 247 } 248 if(cmd == TURN_ON) { 249 int new_state; 250 printf("Turning STB On\n"); 251 new_state = r5000_power_on_off(usbdev, 1); 252 printf("Turned power %s\n", new_state ? "On" : "Off"); 253 } 254 if(cmd == TURN_OFF) { 255 int new_state; 256 printf("Turning STB Off\n"); 257 new_state = r5000_power_on_off(usbdev, 0); 258 printf("Turned power %s\n", new_state ? "On" : "Off"); 259 } 260 if(cmd == CHECK_POWER) { 261 int new_state; 262 new_state = r5000_get_power_state(usbdev); 263 printf("Power is currently %s\n", new_state ? "On" : "Off"); 264 } 265 if(cmd == CHANGE_CHANNEL) { 266 if(! channel) { 267 printf("Must specify a channel when using '-m CHANGE_CHANNEL'\n"); 268 exit(-1); 269 } 270 printf("Setting channel %s\n", channel); 271 r5000_change_channel(usbdev, channel, 0); 272 } 273 if(cmd == OPEN_CLOSE) { 274 int on_off; 275 printf("Doing open/close\n"); 276 on_off = r5000_get_power_state(usbdev); 277 printf("State1: %d\n", on_off); 278 r5000_close(usbdev); 279 printf("Closed\n"); 280 sleep(1); 281 usbdev = r5000_open(stb, r5000_device_tspacket_handler, &glblfd, serial); 282 printf("ReOpened\n"); 283 on_off = r5000_get_power_state(usbdev); 284 printf("State2: %d\n", on_off); 285 } 286 if(cmd == READ_STREAM || cmd == MULTI_READ) { 287 if(channel) { 288 uint c; 289 char *ptr; 290 printf("Setting channel %d\n"); 291 c = strtol(channel, &ptr, 0); 292 r5000_change_channel(usbdev, NULL, c); 293 } 294 printf("Reading stream\n"); 295 r5000_start_stream(usbdev); 296 time_t t = time(NULL); 297 while (time(NULL) - t < runtime) 298 { 299 // This will timeout after 1ms regardless of data availability 300 //usleep(10000); 301 r5000_loop_iterate(usbdev, 10); 302 } 303 r5000_stop_stream(usbdev); 304 } 305 if(cmd == MULTI_READ) { 306 printf("Reading stream again\n"); 307 close(glblfd); 308 glblfd=open("raw_1.ts", O_WRONLY | O_TRUNC | O_CREAT, 0666); 309 sleep(1); 310 r5000_start_stream(usbdev); 311 time_t t = time(NULL); 312 while (time(NULL) - t < 10) 313 { 314 // This will timeout after 1ms regardless of data availability 315 //usleep(10000); 316 r5000_loop_iterate(usbdev, 10); 317 } 318 r5000_stop_stream(usbdev); 319 } 320 if(cmd == MULTI_OPEN) { 321 printf("Doing multi-open\n"); 322 while(usbdev) { 323 time_t t; 324 r5000_start_stream(usbdev); 325 t = time(NULL); 326 while (time(NULL) - t < 2) 327 { 328 // This will timeout after 1ms regardless of data availability 329 //usleep(10000); 330 r5000_loop_iterate(usbdev, 10); 331 } 332 r5000_stop_stream(usbdev); 333 r5000_close(usbdev); 334 printf("Closed\n"); 335 sleep(1); 336 usbdev = r5000_open(stb, r5000_device_tspacket_handler, &glblfd, serial); 337 printf("ReOpened %s\n", serial); 338 } 339 r5000_start_stream(usbdev); 340 time_t t = time(NULL); 341 while (time(NULL) - t < 10) 342 { 343 // This will timeout after 1ms regardless of data availability 344 //usleep(10000); 345 r5000_loop_iterate(usbdev, 10); 346 } 347 r5000_stop_stream(usbdev); 348 } 349 end: 350 r5000_close(usbdev); 351 if(ptr != buffer) 352 write(glblfd, buffer, ptr-buffer); 353 close(glblfd); 354 } -
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 The easiest way to do this is with udev: 15 1) sudo cp 85-r5000.rules /etc/udev/rules.d 16 2) sudo cp r5000.hex /lib/firmware/r5000.hex 17 3) Now plug in the R5000 STB 18 4) lsusb | grep Anchor 19 Bus 004 Device 013: ID 0547:1002 Anchor Chips, Inc. 20 5)ensure that the usbtest module did not load: 21 lsmod | grep usbtest 22 If you see the usbtest module you'll need to blacklist it and/or rmmod it 23 24 -------------------------------------------------------------- 25 If this fails at any step along the way, try the manual method: 26 -------------------------------------------------------------- 27 28 Make sure you have the following installed: 29 lsusb (in Debian/Ubuntu this is in the usbutils package) 30 fxload 31 1) Locate the device using lsusb: 32 lsusb 33 ... 34 Bus 001 Device 026: ID 04b4:8613 Cypress Semiconductor Corp. CY7C68013 EZ-USB FX2 USB 2.0 Development Kit 35 2)Install the firmware (this often needs to be done via sudo/root) 36 (depending on where usbfs is mounted): 37 fxload -t fx2 -D /dev/bus/usb/001/026 -I r5000.hex -m 0666 38 or 39 fxload -t fx2 -D /proc/bus/usb/001/026 -I r5000.hex -m 0666 40 (note that 001 is the Bus and 026 is the Device from lsusb) 41 42 3) Ensure that the firmware loaded: 43 lsusb 44 ... 45 Bus 001 Device 028: ID 0547:1002 Anchor Chips, Inc. 46 (Note that is has a completely different name now) 47 48 4)ensure that the usbtest module did not load: 49 lsmod | grep usbtest 50 If you see the usbtest module you'll need to blacklist it and/or rmmod it 51 ############################################################################### 52 ############################################################################### 53 54 Before trying to use the R5000 in mythtv, make sure it is working in r5ktest 55 ./r5ktest -t 0 -m 6 56 Scanning for R5000 devices 57 Found: xxxxxxx 58 59 If you see something like: 60 R5000 initialization failed at stage 1: 61 Expected 1 bytes, but got -1 bytes 62 R5000 failed to locate any R5000 devices. Are you sure you have 63 permissions set properly? 64 Then you likely do not have permissions to access the usb device. Try running 65 as root. 66 67 next do: 68 ./r5ktest --help 69 and choose the correct type for your STB: 70 vip211 : VIP211 and VIP411 71 vip622 : VIP622, VIP722, BEV9242 72 hdd: 73 dsr: 74 directv: 75 76 Now try a few commands to make sure they work properly: 77 ./r5ktest --type vip211 --cmd TURN_ON 78 ./r5ktest --type vip211 --cmd TURN_OFF 79 ./r5ktest --type vip211 --cmd CHANGE_CHANNEL -c <channel number> 80 ./r5ktest --type vip211 --cmd OPEN_CLOSE 81 82 ############################################################################### 83 ############################################################################### 84 85 Configure mythtv: 86 Go into myth-setup and select the R5000 device, and the relevant STB. 87 Configure a Video Source 88 Configure an Input 89 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 90 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 91 92 Some notes: 93 Only ViP style STBs (Dish Network and BEV) and DirectTV STBs have channel-change capabilities. Others need an external program 94 95 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. 96 -
new file contrib/r5000/85-r5000.rules
- + 1 SUBSYSTEM=="usb", ACTION=="add", ENV{PRODUCT}=="4b4/8613/*", RUN+="/sbin/fxload -D %N -I /lib/firmware/r5000.hex -t fx2 -m 0666" 2 SUBSYSTEM=="usb", ENV{PRODUCT}=="547/1002/*", MODE="666" 3 -
new file libs/libmythtv/r5000/r5k_directv_buttons.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 DirectTV remotes 18 19 #include "r5000_internal.h" 20 21 struct r5000_buttons directv_button_cmd = 22 { 23 0x49, //len 24 400000, //delay 25 //button 0: 26 { 27 0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 28 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 29 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 30 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 31 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 32 }, 33 //button 1: 34 { 35 0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 36 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 37 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 38 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 39 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 40 }, 41 //button 2: 42 { 43 0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 44 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 45 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 46 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 47 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 48 }, 49 //button 3: 50 { 51 0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 52 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 53 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 54 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 55 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 56 }, 57 //button 4: 58 { 59 0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 60 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 61 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 62 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 63 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 64 }, 65 //button 5: 66 { 67 0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 68 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 69 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 70 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 71 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 72 }, 73 //button 6: 74 { 75 0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 76 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 77 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 78 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 79 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 80 }, 81 //button 7: 82 { 83 0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 84 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 85 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 86 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 87 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 88 }, 89 //button 8: 90 { 91 0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 92 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 93 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 94 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 95 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 96 }, 97 //button 9: 98 { 99 0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 100 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 101 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 102 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 103 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 104 }, 105 //Clear: 106 { 107 0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 108 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 109 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 110 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 111 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 112 }, 113 //Enter: 114 { 115 0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 116 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 117 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 118 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 119 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 120 }, 121 //Power 122 { 123 0x00, 0x43, 0x0a, 0x80, 0xca, 0x00, 0x5a, 0x2d, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 124 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 125 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 126 0x05, 0x0f, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0f, 0x05, 0x05, 0x05, 0x0f, 127 0x05, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x0f, 0x05, 128 }, 129 }; -
new file libs/libmythtv/r5000/r5k_pes.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 //The following are used to convert DirectTV into TS format 45 static int directv_make_empty_pes(unsigned char *ptr, unsigned char type) 46 { 47 ptr[0] = 0x00; 48 ptr[1] = 0x00; 49 ptr[2] = 0x01; 50 ptr[3] = type; 51 ptr[4] = 0x00; 52 ptr[5] = 0x00; 53 ptr[6] = 0x80; 54 ptr[7] = 0x00; //2 MSB represent PTS/DTS flag 55 ptr[8] = 0x0a; 56 ptr[9] = 0xff; 57 ptr[10] = 0xff; 58 ptr[11] = 0xff; 59 ptr[12] = 0xff; 60 ptr[13] = 0xff; 61 ptr[14] = 0xff; 62 ptr[15] = 0xff; 63 ptr[16] = 0xff; 64 ptr[17] = 0xff; 65 ptr[18] = 0xff; 66 return 19; 67 } 68 69 static void directv_make_pespts(unsigned char *outptr, unsigned int pts) 70 { 71 pts = htonl(pts); 72 unsigned char *inpts = (unsigned char *)&pts; 73 outptr[0] = 0x01 | 74 ((inpts[0] & 0xC0) >>5); 75 outptr[1] = ((inpts[0] & 0x3F) << 2) | 76 ((inpts[1] & 0xC0) >> 6); 77 outptr[2] = 0x01 | ((inpts[1] & 0x3F) << 2) | 78 ((inpts[2] & 0x80) >> 6); 79 outptr[3] = ((inpts[2] & 0x7F) << 1) | 80 ((inpts[3] & 0x80) >> 7); 81 outptr[4] = 0x01 | ((inpts[3] & 0x7F) << 1); 82 } 83 84 static void directv_update_video_pes(unsigned char *ptr, int pos) 85 { 86 //pos points at the 1st char after a pic start code 87 int picture_coding_type; 88 int hdr_len; 89 unsigned int pts1, dts1; 90 unsigned char *buf = ptr + pos; 91 picture_coding_type = (buf[1] >> 3) & 0x07; 92 hdr_len = (picture_coding_type > 1) ? 5 : 4; 93 if(buf[hdr_len + 3] == 0xb5) 94 hdr_len += 9; 95 if(buf[hdr_len + 3] == 0xb2) { 96 pts1 = ((buf[hdr_len+6] & 0x03) << 30) + 97 ((buf[hdr_len+7] & 0x7f) << 23) + 98 ((buf[hdr_len+8]) << 15) + 99 ((buf[hdr_len+9] & 0x7f) << 8) + 100 buf[hdr_len+10]; 101 dts1 = ((buf[hdr_len+13] & 0x03) << 30) + 102 ((buf[hdr_len+14] & 0x7f) << 23) + 103 ((buf[hdr_len+15]) << 15) + 104 ((buf[hdr_len+16] & 0x7f) << 8) + 105 buf[hdr_len+17]; 106 //NOTE: This is wrong. DSS timestamps only have a resolution of 2^32/300 107 //r5000_print("pts: %08x/%f dts: %08x/%f\n", pts1, pts1 / 27000000.0, dts1, dts1 / 27000000.0); 108 ptr[7] |= 0xc0; 109 directv_make_pespts(ptr+9, pts1/300); 110 ptr[9] |= 0x30; 111 directv_make_pespts(ptr+14, dts1/300); 112 ptr[14] |= 0x10; 113 } 114 } 115 116 static void directv_fix_audio_pts(unsigned char *ptr) 117 { 118 unsigned int pts = ((ptr[0] & 0x06) << 29) + 119 (ptr[1] << 22) + 120 ((ptr[2] & 0xfe) << 14) + 121 (ptr[3] << 7) + 122 (ptr[4] >> 1); 123 directv_make_pespts(ptr, pts/300); 124 ptr[0] |= 0x20; 125 } 126 127 128 static void pes_write_ts(r5kdev_t *r5kdev, unsigned char *ptr, int len, int pid, int start, int *cc) 129 { 130 int stuff = 184 - len; 131 //Note: we know that there are 188 bytes allocated before 'ptr' 132 // that we can use for the header 133 if(stuff > 0) { 134 int stuff1 = stuff; 135 while(stuff1 > 2) { 136 *--ptr = 0xff; 137 stuff1--; 138 } 139 if(stuff1 == 2) { 140 *--ptr = 0x00; 141 } 142 *--ptr = stuff - 1; 143 *--ptr = 0x30 | *cc; 144 } else { 145 *--ptr = 0x10 | *cc; 146 } 147 *--ptr = pid & 0xff; 148 *--ptr = (start << 6) | (pid >> 8); 149 *--ptr = 0x47; 150 r5kdev->cb(ptr, 188, r5kdev->cb_data); 151 *cc = (*cc+1) & 0x0f; 152 } 153 154 static void pes_process_block(r5kdev_t *r5kdev, unsigned char *buf, int len) 155 { 156 int i; 157 struct r5000_dtv *dtv = (struct r5000_dtv *)r5kdev->stbdata; 158 for(i = 0; i < len; i+=2) { 159 unsigned char data = buf[i]; 160 unsigned char type = buf[i+1]; 161 if(0xff == type) { 162 //video 163 dtv->video[dtv->vpos++] = data; 164 if(dtv->vpos > 4 && dtv->video[dtv->vpos-2] == 0x01 && 165 dtv->video[dtv->vpos-3] == 0x00 && dtv->video[dtv->vpos-4] == 0x00) { 166 if (data == 0xe0) { 167 //HD video header (PES) 168 pes_write_ts(r5kdev, dtv->video, dtv->vpos - 4, DTV_VPID, dtv->vstart, &dtv->video_cc); 169 dtv->pat_pmt_count++; 170 dtv->video[0] = 0x00; 171 dtv->video[1] = 0x00; 172 dtv->video[2] = 0x01; 173 dtv->video[3] = 0xe0; 174 dtv->vpos = 4; 175 dtv->vstart = 1; 176 dtv->vstate = data; 177 } else if (r5kdev->stb_type == R5K_STB_DIRECTV && 178 (data == 0xb3 || data == 0x00)) { 179 if (dtv->vstate == 0xff) { 180 dtv->vstate = data; 181 pes_write_ts(r5kdev, dtv->video, dtv->vpos - 4, DTV_VPID, dtv->vstart, &dtv->video_cc); 182 dtv->pat_pmt_count++; 183 //Create a PES header, but no PTS/DTS info yet so just use stuffing bytes 184 dtv->vpos = directv_make_empty_pes(dtv->video, 0xe0); 185 dtv->video[dtv->vpos++] = 0x00; 186 dtv->video[dtv->vpos++] = 0x00; 187 dtv->video[dtv->vpos++] = 0x01; 188 dtv->video[dtv->vpos++] = data; 189 dtv->vstart = 1; 190 dtv->pic_pos = dtv->vpos; 191 } 192 } 193 } 194 if(dtv->vpos == 188) { 195 if (dtv->vstate == 0x00) 196 //We found pic frame without a PES header (SD) 197 directv_update_video_pes(dtv->video, dtv->pic_pos); 198 pes_write_ts(r5kdev, dtv->video, 184, DTV_VPID, dtv->vstart, &dtv->video_cc); 199 dtv->pat_pmt_count++; 200 dtv->video[0] = dtv->video[184]; 201 dtv->video[1] = dtv->video[185]; 202 dtv->video[2] = dtv->video[186]; 203 dtv->video[3] = dtv->video[187]; 204 dtv->vpos = 4; 205 dtv->vstart = 0; 206 dtv->vstate = 0xff; 207 } 208 } else if(0xfe == type) { 209 //audio 210 dtv->audio[dtv->apos++] = data; 211 dtv->alen--; 212 if(dtv->alen <= 0 && dtv->apos > 6 && dtv->audio[dtv->apos-3] == 0xbd && dtv->audio[dtv->apos-4] == 0x01 && 213 dtv->audio[dtv->apos-5] == 0x00 && dtv->audio[dtv->apos-6] == 0x00) { 214 dtv->alen = (dtv->audio[dtv->apos-2] << 8) + data; 215 pes_write_ts(r5kdev, dtv->audio, dtv->apos - 6, DTV_APID, dtv->astart, &dtv->audio_cc); 216 dtv->pat_pmt_count++; 217 dtv->audio[0] = 0x00; 218 dtv->audio[1] = 0x00; 219 dtv->audio[2] = 0x01; 220 dtv->audio[3] = 0xbd; 221 dtv->audio[4] = dtv->audio[dtv->apos-2]; 222 dtv->audio[5] = data; 223 dtv->apos = 6; 224 dtv->astart = 1; 225 r5kdev->pmt[1].id = 0x81; //AC3 226 } else if(dtv->alen <= 0 && dtv->apos > 6 && dtv->audio[dtv->apos-3] == 0xc0 && dtv->audio[dtv->apos-4] == 0x01 && 227 dtv->audio[dtv->apos-5] == 0x00 && dtv->audio[dtv->apos-6] == 0x00) { 228 dtv->alen = (dtv->audio[dtv->apos-2] << 8) + data; 229 pes_write_ts(r5kdev, dtv->audio, dtv->apos - 6, DTV_APID, dtv->astart, &dtv->audio_cc); 230 dtv->pat_pmt_count++; 231 dtv->audio[0] = 0x00; 232 dtv->audio[1] = 0x00; 233 dtv->audio[2] = 0x01; 234 dtv->audio[3] = 0xc0; 235 if (r5kdev->stb_type == R5K_STB_DIRECTV) { 236 dtv->audio[4] = (dtv->alen + 3) >> 8; 237 dtv->audio[5] = (dtv->alen + 3) & 0xff; 238 dtv->audio[6] = 0x80; 239 dtv->audio[7] = 0x80; 240 dtv->audio[8] = 0x05; 241 dtv->apos = 9; 242 } else { 243 dtv->audio[4] = dtv->audio[dtv->apos-2]; 244 dtv->audio[5] = data; 245 dtv->apos = 6; 246 } 247 dtv->astart = 1; 248 r5kdev->pmt[1].id = 0x04; //MP2 249 } else if(dtv->apos == 190) { 250 if(dtv->astart && dtv->audio[3] == 0xc0 && r5kdev->stb_type == R5K_STB_DIRECTV) 251 directv_fix_audio_pts(dtv->audio+9); 252 pes_write_ts(r5kdev, dtv->audio, 184, DTV_APID, dtv->astart, &dtv->audio_cc); 253 dtv->pat_pmt_count++; 254 dtv->audio[0] = dtv->audio[184]; 255 dtv->audio[1] = dtv->audio[185]; 256 dtv->audio[2] = dtv->audio[186]; 257 dtv->audio[3] = dtv->audio[187]; 258 dtv->audio[4] = dtv->audio[188]; 259 dtv->audio[5] = dtv->audio[189]; 260 dtv->apos = 6; 261 dtv->astart = 0; 262 } 263 } 264 } 265 if(r5kdev->pmt[1].id && dtv->pat_pmt_count > DTV_PAT_PMT_COUNT) { 266 r5kdev->cb(r5000_pat_pkt, 188, r5kdev->cb_data); 267 r5000_send_pmt(r5kdev); 268 dtv->pat_pmt_count = 0; 269 } 270 } 271 272 static void pes_start_stream(r5kdev_t *r5kdev) 273 { 274 struct r5000_dtv *dtv = (struct r5000_dtv *)r5kdev->stbdata; 275 dtv->vstart = 0; 276 dtv->astart = 0; 277 dtv->vpos = 0; 278 dtv->apos = 0; 279 dtv->video_cc = 0; 280 dtv->audio_cc = 0; 281 dtv->vstate = 0xff; 282 dtv->pat_pmt_count = DTV_PAT_PMT_COUNT; 283 } 284 285 void pes_init(r5kdev_t *r5kdev) 286 { 287 struct r5000_dtv *dtv = (struct r5000_dtv *)calloc(1, sizeof(struct r5000_dtv)); 288 dtv->video = dtv->vbuf + 188; 289 dtv->audio = dtv->abuf + 188; 290 dtv->pat_pmt_count = DTV_PAT_PMT_COUNT; 291 dtv->vstate = 0xff; 292 r5kdev->stbdata = dtv; 293 r5kdev->pmt[0].id = 0x02; //MPEG2 294 r5kdev->pmt[0].pid = DTV_VPID; 295 r5kdev->pmt[0].desc = r5000_pmt_video_desc; 296 r5kdev->pmt[1].id = 0x00; 297 r5kdev->pmt[1].pid = DTV_APID; 298 r5kdev->pmt[1].desc = r5000_pmt_audio_desc; 299 r5kdev->num_pmt_entries = 2; 300 r5kdev->process_block = pes_process_block; 301 r5kdev->start_stream = pes_start_stream; 302 if(r5kdev->stb_type == R5K_STB_DIRECTV) { 303 r5kdev->button = &directv_button_cmd; 304 r5kdev->power_active_low = 1; 305 } else { 306 r5kdev->button = &dish6000_button_cmd; 307 r5kdev->power_active_low = 0; 308 r5kdev->discrete_power = 1; 309 } 310 r5kdev->read_words = 1; 311 } 312 313 void pes_free(r5kdev_t *r5kdev) 314 { 315 free(r5kdev->stbdata); 316 } -
new file libs/libmythtv/r5000/r5k_vip_buttons.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 remotes 18 19 #include "r5000_internal.h" 20 21 struct r5000_buttons vip_button_cmd = 22 { 23 0x40, //len 24 400000, //delay 25 //button 0: 26 { 27 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 28 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 29 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 30 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 31 }, 32 //button 1: 33 { 34 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 35 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 36 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 37 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 38 }, 39 //button 2: 40 { 41 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 42 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 43 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 44 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 45 }, 46 //button 3: 47 { 48 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 49 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 50 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 51 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 52 }, 53 //button 4: 54 { 55 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 56 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 57 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 58 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 59 }, 60 //button 5: 61 { 62 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 63 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 64 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 65 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 66 }, 67 //button 6: 68 { 69 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 70 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 71 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 72 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 73 }, 74 //button 7: 75 { 76 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 77 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 78 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 79 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 80 }, 81 //button 8: 82 { 83 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 84 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 85 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 86 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 87 }, 88 //button 9: 89 { 90 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 91 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 92 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 93 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 94 }, 95 //Clear: 96 { 97 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 98 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 99 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 100 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 101 }, 102 //Enter: 103 { 104 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 105 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 106 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 107 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 108 }, 109 //Power 110 { 111 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 112 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 113 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 114 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 115 }, 116 //Power-On 117 { 118 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 119 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 120 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 121 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 122 }, 123 //Power-Off 124 { 125 0x00, 0x23, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 126 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 127 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 128 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 129 }, 130 }; -
new file libs/libmythtv/r5000/r5k_dish6000_buttons.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/BEV 6000 remotes 18 19 #include "r5000_internal.h" 20 21 struct r5000_buttons dish6000_button_cmd = 22 { 23 0x79, //len 24 800000, //delay 25 //button 0: 26 { 27 0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 28 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 29 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 30 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 31 0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 32 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 33 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 34 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 35 }, 36 //button 1: 37 { 38 0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 39 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 40 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 41 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 42 0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 43 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 44 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 45 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 46 }, 47 //button 2: 48 { 49 0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 50 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 51 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 52 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 53 0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 54 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 55 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 56 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 57 }, 58 //button 3: 59 { 60 0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 61 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 62 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 63 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 64 0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 65 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 66 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 67 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 68 }, 69 //button 4: 70 { 71 0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 72 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 73 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 74 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 75 0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 76 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 77 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 78 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 79 }, 80 //button 5: 81 { 82 0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 83 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 84 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 85 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 86 0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 87 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 88 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 89 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 90 }, 91 //button 6: 92 { 93 0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 94 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 95 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 96 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 97 0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 98 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 99 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 100 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 101 }, 102 //button 7: 103 { 104 0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 105 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 106 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 107 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 108 0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 109 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 110 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 111 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 112 }, 113 //button 8: 114 { 115 0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 116 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 117 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 118 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 119 0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 120 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 121 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 122 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 123 }, 124 //button 9: 125 { 126 0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 127 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 128 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 129 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 130 0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x0e, 131 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 132 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 133 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 134 }, 135 //Clear: 136 { 137 0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 138 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 139 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 140 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 141 0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 142 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 143 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 144 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 145 }, 146 //Enter: 147 { 148 0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 149 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 150 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 151 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 152 0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 153 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 154 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 155 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 156 }, 157 //Power 158 { 159 0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 160 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 161 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 162 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 163 0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 164 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 165 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 166 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 167 }, 168 //Power-On 169 { 170 0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 171 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 172 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 173 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 174 0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 175 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 176 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 177 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 178 }, 179 //Power-Off 180 { 181 0x00, 0x67, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 182 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 183 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 184 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 185 0x00, 0x39, 0x0a, 0x80, 0x00, 0x77, 0x04, 0x3a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x0e, 186 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 187 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x1a, 0x04, 0x3a, 0x04, 0x0e, 0x04, 0x1a, 0x04, 0x1a, 188 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x0e, 0x04, 0x1a, 0x04, 189 }, 190 };
