<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>http://wiki.samygo.tv/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Hedak</id>
	<title>SamyGO - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.samygo.tv/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Hedak"/>
	<link rel="alternate" type="text/html" href="http://wiki.samygo.tv/index.php?title=Special:Contributions/Hedak"/>
	<updated>2026-04-27T00:59:39Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.31.1</generator>
	<entry>
		<id>http://wiki.samygo.tv/index.php?title=UnBricking_TV_by_EEPROM_Reset&amp;diff=3911</id>
		<title>UnBricking TV by EEPROM Reset</title>
		<link rel="alternate" type="text/html" href="http://wiki.samygo.tv/index.php?title=UnBricking_TV_by_EEPROM_Reset&amp;diff=3911"/>
		<updated>2014-03-09T13:22:40Z</updated>

		<summary type="html">&lt;p&gt;Hedak: Added EEPROM specification 'SoC'&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Here we will show you how to reset your TV by resetting the SoC EEPROM. This can be very useful in case you have bricked your TV by messing with some of its internal settings, which can easily happen if you mess around in the Service Menu. It is highly recommended to take photos of each screen in the service menu, showing your original firmware settings, before changing anything!&lt;br /&gt;
&lt;br /&gt;
=Blind Factory Reset=&lt;br /&gt;
Before trying to EEPROM reset, please try a factory reset, that might revive your TV also.&lt;br /&gt;
&lt;br /&gt;
Press &amp;quot;EXIT&amp;quot; button for 12 seconds (15 is better since you cannot see TV), than press &amp;quot;Left&amp;quot; and &amp;quot;Enter&amp;quot;&lt;br /&gt;
&lt;br /&gt;
[http://www.samsung.com/us/support/supportOwnersHowToGuidePopup.do?howto_guide_seq=5306&amp;amp;prd_ia_cd=N0000058&amp;amp;map_seq=31175 Samsung Documentation]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''This wiki entry will not help resolve a TV bricked by firmware flashing.''' &lt;br /&gt;
&lt;br /&gt;
One example (from the original post of this wiki): &lt;br /&gt;
 ''This is Erdem. As I bricked my D series device by miss service menu setting, I search for solutions to recover it. &lt;br /&gt;
 After with help  of Juzis we unbricked device with the same way of C series TVs... Here I wanted to try to let &lt;br /&gt;
 you know how the process is working. Firstly, this hack doesn't work if you bricked you device by &lt;br /&gt;
 firmware flashing... This hacks just removes service menu settings and let you give another chance &lt;br /&gt;
 to fix settings... Also you needed to find correct values for your TV after resetting NVRAM like &lt;br /&gt;
 Model / Type / Tuner / Font Color and others. It's better to have screen shots of your service menu. &lt;br /&gt;
 You can also ask help from our forums.''&lt;br /&gt;
&lt;br /&gt;
=EEPROM=&lt;br /&gt;
EEPROM is a short of ''electrically erasable programmable read only memory'', which is actually a chip. There are several EEPROM chips used in Samsung TVs. All service menu settings are kept in the so called SoC EEPROM. You can delete and reprogram this chips millions time. So they are fast and reliable...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Reseting NVRAM (EEPROM)=&lt;br /&gt;
&lt;br /&gt;
For resetting TV, settings, you needed to remove SoC EEPROM device from TV. But it's not required. In electronic world, if you disable communication of the chip, it counts as removed. So we just needed to kill communication of SoC EEPROM. EEPROMs on Samsung TV's communicating via common i2c protocol. That protocol carries data via SDA line and send clocks via SCL line. In our situation, both blocking SCL or SDA will works. But I decide SDA.&lt;br /&gt;
&lt;br /&gt;
To do this, all you have to do that feeding (connecting) GND (ground) or VCC (3.3v) to SDA line with little wire... That's all. Since this lines are HIGH (v3.3) in IDLE, its better to hold it via VCC. You can also hold this lines via GND too. But don't try to connect both GND and VCC. It will be short circuit and probably will damage your board.&lt;br /&gt;
&lt;br /&gt;
Join VCC and SDA, power on TV and hold about for 20 seconds with the TV powered. It just try to read (wrong) settings from EEPROM, since it cannot read anything (refer to the warning message bellow), just start with defaults. That is what we want. Than releasing SDA line and shutting TV off will update the settings on EEPROM with null values, that TV could boot with it. After all, you can enter service menu and change the required changes.&lt;br /&gt;
&lt;br /&gt;
[[File:UE40D5000 RESET MESSAGE.JPG|center|300px| UE40D5000 Reset message]]&lt;br /&gt;
&lt;br /&gt;
=Where do I find the SoC EEPROM chip?=&lt;br /&gt;
:Its located near CPU (SoC) at C and D series. On top, it writes some numbers and letters starting with 24256 or 24512... Here I place some screen shots from D series bellow. In my TV, 24512 EEPROM chip used. You can get the [http://pdf1.alldatasheet.com/datasheet-pdf/view/22813/STMICROELECTRONICS/M24512-RBN6.html 24512 Chip Datasheet here]. In picture, white triangle shows the first pin.&lt;br /&gt;
==B Series SoC EEPROM Location==&lt;br /&gt;
===LExxB550===&lt;br /&gt;
You have to search for eeprom on '''back side''' of mainboard. IC3001&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
[[Image:LExxB55x_mainboard_front.JPG|270px|B550 mainboarboard front side]]&lt;br /&gt;
[[Image:LE46B550A5W full.jpg|270px|B550 mainboarboard back side]]&lt;br /&gt;
[[Image:LExxB550_eeprom.png|270px|B550 eeprom reset. Red line!]]&lt;br /&gt;
===LExxB6000===&lt;br /&gt;
[[Image:Samsung_UExxB6000_mainboard.jpg|250px|B6000 mainboarboard]]&lt;br /&gt;
[[Image:Samsung_UE32_B6000_eeprom_reset.jpg|270px|eeprom location, reset procedure]]&lt;br /&gt;
&lt;br /&gt;
==C Series SoC EEPROM Location==&lt;br /&gt;
===LExxC550/530===&lt;br /&gt;
[[Image:C550_full.jpg|270px|C550/530 Board]]&lt;br /&gt;
[[Image:C550_reset.jpg|200px|C550/530 reset. Red line!]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===LAxxC650===&lt;br /&gt;
[[Image:LA40C650full.jpg|150px|LA40C650 Board]]&lt;br /&gt;
[[Image:LA40C650_eeprom_is_C.jpg|225px|LA40C650 eeprom`s place]]&lt;br /&gt;
[[Image:LA40C650_eeprom_reset.jpg|202px|LA40C650 reset]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===UAxxC6200===&lt;br /&gt;
[[Image:UA40C6200_full.jpg|150px|UA40C6200 Board]]&lt;br /&gt;
[[Image:UA40C6200_1.jpg|285px|UA40C6200 reset]]&lt;br /&gt;
===UExxC7700===&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:DSC 0272 resized marked.jpg|UE46C7700 Board (back side of mainboard)&lt;br /&gt;
Image:DSC 0273 resized.jpg|UE46C7700 eeprom &lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===OTHER===&lt;br /&gt;
please fill up missing models. Thanks!&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==D Series SoC EEPROM Location==&lt;br /&gt;
===D5000===&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:UE40D5000 Board.JPG|UE40D5000 Board&lt;br /&gt;
Image:UE40D5000 EEPROM.JPG|UE40D5000 EEPROM Chip and UnBrick way&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===D4003/5003===&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:UE40D5003_Board.jpg|UE40D5003 Board&lt;br /&gt;
Image:UE40D5003_EEprom_reset.jpg|UE40D5003 EEPROM Chip and UnBrick way&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===D550===&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:le32d550_mainboard.jpg|LExxD550 Board&lt;br /&gt;
Image:le32d550_eeprom.jpg|LExxD550 EEPROM Chip and UnBrick way&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===D60xx/61xx/62xx/63xx/64xx/65xx/66xx/67xx/68xx===&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:UA40D6000_Board_EEPROM.jpg|UA40D6000 Board&lt;br /&gt;
Image:EEPROM_Reset.jpg|UA40D6000 EEPROM Chip and UnBrick way&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==BD (BlueRay DVD Player) SoC EEPROM Location==&lt;br /&gt;
===BD-D8X00===&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:Bd-d8900_Board.png|BD-D8900 Board&lt;br /&gt;
Image:Bd-d8900_Eprom.png|BD-D8900 EEPROM Chip and UnBrick way&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===BD-E8X00===&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:Bd-e8300_Board.png|BD-D8900 Board&lt;br /&gt;
Image:Bd-e8300_Eprom.png|BD-D8900 EEPROM Chip and UnBrick way&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==ES-series SoC EEPROM Location==&lt;br /&gt;
This may also be compatible with the &amp;quot;E&amp;quot;-series...&lt;br /&gt;
Do check forums for latest info.&lt;br /&gt;
&lt;br /&gt;
===UNxxES7500===&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:UNxxES7500_Eeprom_location.jpg|UNxxES7500 Board&lt;br /&gt;
Image:UNxxES7500_Eeprom.jpg|UNxxES7500 Reset EEPROM&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==F series SoC EEPROM location==&lt;br /&gt;
&lt;br /&gt;
===UExxF8000===&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Image:UExxF8000.jpg|UExxF8000&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;/div&gt;</summary>
		<author><name>Hedak</name></author>
		
	</entry>
	<entry>
		<id>http://wiki.samygo.tv/index.php?title=Ethernet_multi-function_Interface&amp;diff=3910</id>
		<title>Ethernet multi-function Interface</title>
		<link rel="alternate" type="text/html" href="http://wiki.samygo.tv/index.php?title=Ethernet_multi-function_Interface&amp;diff=3910"/>
		<updated>2014-03-07T20:08:03Z</updated>

		<summary type="html">&lt;p&gt;Hedak: /* Teensy(++ 2.0) sketch for accessing I2C interface */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Using an Arduino Ethernet board, you can send IR codes to your TV or BD&lt;br /&gt;
&lt;br /&gt;
With the same board, you can also interface to the Serial Console, and read your device config eeprom.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== What you can do ==&lt;br /&gt;
* Send IR codes to your TV, PVR or BD, with an URL in your browser&lt;br /&gt;
* Use telnet to have the Serial Console on your PC or smartphone&lt;br /&gt;
* Read your SoC config eeprom&lt;br /&gt;
* Read/write micom config eeprom&lt;br /&gt;
* See Arduino as a Samsung device in the Samsung Remote App (can be used to power on the device !)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Arduino interface.jpg|335px]]             [[File:EthernetInterface-SamsungRemote.png|335px]]&lt;br /&gt;
&lt;br /&gt;
== Bill of materials ==&lt;br /&gt;
* Arduino Ethernet board (see [http://arduino.cc/en/Main/ArduinoBoardEthernet Arduino])&lt;br /&gt;
Alternatively, an Arduino Uno with an Ethernet shield could also be used&lt;br /&gt;
* IR led (SFH4510 for example) or RED Led (Clear Type RED LED's are emitting more than enough light at IR spectrum)&lt;br /&gt;
* 220 ohms resistor to limit current in the IR led&lt;br /&gt;
* If you plan to use the telnet interface to the Serial Console, make sure you have a 100 ohms resistor on both RX and TX signals (Arduino TX/RX are 5v !)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== How to use it ==&lt;br /&gt;
* Upload the following '''[[#Arduino_sketch | sketch]]''' into your Arduino&lt;br /&gt;
* Connect the IR or RED led with its resistor on pin 8 on the Arduino&lt;br /&gt;
* Connect power and network&lt;br /&gt;
* Find the IP address of the board on your DHCP (or use the static IP embedded in the sketch if you don't have DHCP)&lt;br /&gt;
* Use your browser to send an URL to the board (see format below)&lt;br /&gt;
* If you want to use telnet to connect to the Serial Console :&lt;br /&gt;
 * Connect your Serial Console signals TX&amp;amp;RX to the Arduino board pins 0&amp;amp;1  ({{red|with 100 ohms resistors}})&lt;br /&gt;
 * Use Putty with options 'Local Echo' and 'Local line editing' forced to OFF&lt;br /&gt;
* If you want to read your config eeprom :&lt;br /&gt;
 * Connect the eeprom SDA&amp;amp;SCK signals to the Arduino board pins A4/A5 ({{red|with 100 ohms resistors}})&lt;br /&gt;
 * Connect the eeprom GND to 0v&lt;br /&gt;
* If you want to use the Samsung Remote feature :&lt;br /&gt;
 * Compile with SAMSUNGREMOTE defined&lt;br /&gt;
 * The program only handles BD_KEY_POWER; if you want aditional keys, it's easy to add them&lt;br /&gt;
&lt;br /&gt;
== URL format to send IR codes ==&lt;br /&gt;
The format is http://IP/ir.htm?data=XX&amp;amp;type=Y&amp;amp;device=ZZZZ&lt;br /&gt;
where&lt;br /&gt;
* IP is the Arduino board IP address&lt;br /&gt;
* XX is the IR code to send&lt;br /&gt;
* Y is 0 for TV/PVR frame format and 1 for BD frame format&lt;br /&gt;
* ZZZZ is the device code (0707 for TV, 0505 for PVR, 301A for BD)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The IR codes are listed at [[Key codes]]&lt;br /&gt;
* For TV/PVR, use the 'code' column&lt;br /&gt;
* For BD, use the 'BD-IR code' column&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To get the Service Menu on your TV, use the 2 following URLs :&lt;br /&gt;
* http://IP/ir.htm?data=1F&amp;amp;type=0&amp;amp;device=0707&lt;br /&gt;
* http://IP/ir.htm?data=3B&amp;amp;type=0&amp;amp;device=0707&lt;br /&gt;
Please note that you cannot send KEY_FACTORY to a BD, as the corresponding code is not know yet&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To have a kind of Wake Up on LAN on your BD player, use&lt;br /&gt;
* http://IP/ir.htm?data=91&amp;amp;type=1&amp;amp;device=301A&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To switch to channel 1 :&lt;br /&gt;
* On a TV : http://IP/ir.htm?data=65&amp;amp;type=0&amp;amp;device=0707&lt;br /&gt;
* On a BD : http://IP/ir.htm?data=81&amp;amp;type=0&amp;amp;device=301A&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== URL format to read config Eeprom ==&lt;br /&gt;
The format is http://IP/read?format=F&amp;amp;device=D&amp;amp;addr=A&amp;amp;size=S&amp;amp;width=W&lt;br /&gt;
&lt;br /&gt;
* IP is the Arduino board IP address&lt;br /&gt;
* F is 0 to get the result in html, 1 to download a binary file&lt;br /&gt;
* D is the Eeprom device identification (80 by default)&lt;br /&gt;
* A is the starting address for reading (0 by default)&lt;br /&gt;
* S is the number of bytes to read (default=256)&lt;br /&gt;
* W is the address bus width (8 bits for Micom eeprom, 16 bits for SoC eeprom); default is 16&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
BD-E8300 is equiped with a 24512 eeprom (64 kbytes)&lt;br /&gt;
&lt;br /&gt;
To download its whole config :&lt;br /&gt;
* http://IP/read?format=1&amp;amp;size=65536&lt;br /&gt;
or :&lt;br /&gt;
* http://IP/read?format=1&amp;amp;device=80&amp;amp;size=65536&amp;amp;addr=0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Eeprom connection :&lt;br /&gt;
&lt;br /&gt;
[[File:Arduino_I2C_Eeprom.jpg|335px]]&lt;br /&gt;
&lt;br /&gt;
== URL format to write config Eeprom ==&lt;br /&gt;
The format is http://IP/write?device=D&amp;amp;addr=A&amp;amp;data=X&amp;amp;width=W&lt;br /&gt;
&lt;br /&gt;
* IP is the Arduino board IP address&lt;br /&gt;
* D is the Eeprom device identification (80 by default)&lt;br /&gt;
* A is the starting address for writing (0 by default)&lt;br /&gt;
* X is the data byte to write&lt;br /&gt;
* W is the address bus width (8 bits for Micom eeprom, 16 bits for SoC eeprom); default is 16&lt;br /&gt;
&lt;br /&gt;
On this version, it is only possible to write one byte at once...&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
http://IP/write?addr=e0&amp;amp;data=55&amp;amp;width=16 will write 0x55 at address 0xe0&lt;br /&gt;
&lt;br /&gt;
== IR frames format == &lt;br /&gt;
BD players use a modified IR frame format that TV and PVR.&lt;br /&gt;
The reason is that samsung increased the data field length from 8 to 12 bits&lt;br /&gt;
The general format is now :&lt;br /&gt;
* Start bit&lt;br /&gt;
* Device ID (16 bits - 0707 for TV, 301A for BD)&lt;br /&gt;
* For BD only : Stop bit and data MSB on 4 bits&lt;br /&gt;
* Data LSB&lt;br /&gt;
* Data LSB 1's complement&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A frame for BD :&lt;br /&gt;
&lt;br /&gt;
[[File:BD_IR_Frame_Format.png‎]]&lt;br /&gt;
&lt;br /&gt;
== Arduino sketch ==&lt;br /&gt;
&lt;br /&gt;
This sketch has been compiled with Arduino 1.0.3 ([http://arduino.cc/en/Main/Software Download here])&lt;br /&gt;
&lt;br /&gt;
  // ---------------------------------------------------------------------&lt;br /&gt;
  // Samsung multi-functions ethernet interface &lt;br /&gt;
  //   - Send IR frame with http get requests&lt;br /&gt;
  //   - Debug console on telnet&lt;br /&gt;
  //   - Read &amp;amp; Write I2C config eeprom&lt;br /&gt;
  //&lt;br /&gt;
  // 29-06-2012 / v1.1 / oga83&lt;br /&gt;
  // 11-09-2012 / v1.1 / oga83&lt;br /&gt;
  //    Added optionnal 'crc' url parameter for testing IR (allow to force CRC)&lt;br /&gt;
  //    Added I2C interface to read/write config eeprom&lt;br /&gt;
  // 09-01-2013 / v1.1.1 / oga83&lt;br /&gt;
  //    Fixed compilation issue with Arduino 1.0.3 and typo in wiki&lt;br /&gt;
  // 11-01-2013 / v1.1.2 / oga83&lt;br /&gt;
  //    Modified ReadEeprom and WriteEeprom for 1-byte address eeproms&lt;br /&gt;
  // 11-01-2013 / v1.2 / oga83&lt;br /&gt;
  //    Added Samsung Remote protocol (Arduino seen as a samsung device)&lt;br /&gt;
  //----------------------------------------------------------------------&lt;br /&gt;
  &lt;br /&gt;
  #include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
  #include &amp;lt;Ethernet.h&amp;gt;&lt;br /&gt;
  #include &amp;lt;EthernetUdp.h&amp;gt;&lt;br /&gt;
  #include &amp;lt;Wire.h&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  #define IRPIN      8    // IR led is connected on pin 8&lt;br /&gt;
  #define LEDPIN     9    // Onboard led - blink at 2 Hz&lt;br /&gt;
                          // Debug console TX signal connected on 0&lt;br /&gt;
                          // Debug console RX signal connected on 1&lt;br /&gt;
                          // I2C Eeprom : SDA connected on A4&lt;br /&gt;
                          // I2C Eeprom : SCK connected on A5&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
  byte mac[] = { 0x90, 0xA2, 0xda, 0x00, 0xe6, 0x5e }; // Arduino Ethernet board MAC address&lt;br /&gt;
  &lt;br /&gt;
  IPAddress ip(192,168,1,178);     // Default static IP if no DHCP &lt;br /&gt;
  EthernetServer HttpServer(80);   // HTTP is used to send IR commands&lt;br /&gt;
  EthernetServer TelnetServer(23); // Telnet is used for Serial Console&lt;br /&gt;
  &lt;br /&gt;
  #define SAMSUNGREMOTE            // if defined, Arduino will be seen as a Samsung device&lt;br /&gt;
  #ifdef SAMSUNGREMOTE&lt;br /&gt;
  EthernetServer SamsungRemote(55000); // Emulates a Samsung device&lt;br /&gt;
  EthernetUDP SamsungSSDP;  // Handles Samsung device discovery&lt;br /&gt;
  #endif&lt;br /&gt;
  &lt;br /&gt;
  // ---------------------------------------------------------------------&lt;br /&gt;
  // Utilities&lt;br /&gt;
  // ---------------------------------------------------------------------&lt;br /&gt;
  &lt;br /&gt;
  // Convert a hex string to unsigned int&lt;br /&gt;
  unsigned int HexToULong(char *s)&lt;br /&gt;
  {&lt;br /&gt;
    unsigned long u=0;&lt;br /&gt;
    while (*s)&lt;br /&gt;
    {&lt;br /&gt;
      char c=*s++;&lt;br /&gt;
      // Convert to uppercase&lt;br /&gt;
      if (c&amp;gt;='a') c&amp;amp;=0xdf;&lt;br /&gt;
      // Exit if not hex digit&lt;br /&gt;
      if ((c&amp;lt;'0' || c&amp;gt;'9') &amp;amp;&amp;amp; (c&amp;lt;'A' || c&amp;gt;'F')) break;&lt;br /&gt;
      // Convert digit&lt;br /&gt;
      u&amp;lt;&amp;lt;=4;&lt;br /&gt;
      u|=c-((c&amp;gt;'9') ? 'A'-0xa:'0');&lt;br /&gt;
    }&lt;br /&gt;
    return u;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  #ifdef SAMSUNGREMOTE&lt;br /&gt;
  // Base64 conversion&lt;br /&gt;
  const char *sBase64TranslateTable = &amp;quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+%&amp;quot;;&lt;br /&gt;
  void AsciiToBase64(char *Ascii, char *Buffer, int BufferSize)&lt;br /&gt;
  {&lt;br /&gt;
    int Length=0;&lt;br /&gt;
    while (*Ascii)&lt;br /&gt;
    {&lt;br /&gt;
      unsigned long s32bits=0;&lt;br /&gt;
      int i, j;&lt;br /&gt;
      // Read 3 ASCII bytes&lt;br /&gt;
      for (i = 2; i &amp;gt;= 0; i--)&lt;br /&gt;
      {&lt;br /&gt;
        if (*Ascii==0) break;&lt;br /&gt;
        s32bits |= ((unsigned long)*Ascii++)&amp;lt;&amp;lt;(8*i);&lt;br /&gt;
      }&lt;br /&gt;
      // Convert them to four 6-bit items &lt;br /&gt;
      for (j=3; j&amp;gt;=i+1; j--)&lt;br /&gt;
      {&lt;br /&gt;
        // Check for buffer overflow&lt;br /&gt;
        if (++Length&amp;gt;=BufferSize) { *Buffer=0; return; }&lt;br /&gt;
        // Convert 6-bit item&lt;br /&gt;
        int c = ((s32bits &amp;gt;&amp;gt; (6 * j)) &amp;amp; 0x3f);&lt;br /&gt;
        *Buffer++ = sBase64TranslateTable[c];&lt;br /&gt;
      }&lt;br /&gt;
      // Complete last bytes&lt;br /&gt;
      for (/*void*/; j&amp;gt;=0 &amp;amp;&amp;amp; ++Length&amp;lt;BufferSize; j--) *Buffer++='=';&lt;br /&gt;
    }&lt;br /&gt;
    *Buffer=0; // Trailing 0 is not needed for this project, but simplify testing&lt;br /&gt;
  }&lt;br /&gt;
  void Base64ToAscii(char *Base64, char *Buffer, int BufferSize)&lt;br /&gt;
  {&lt;br /&gt;
    int Length=0;&lt;br /&gt;
    while (*Base64 &amp;amp;&amp;amp; *Base64!='=')&lt;br /&gt;
    {&lt;br /&gt;
      unsigned long s24bits = 0;&lt;br /&gt;
      // Read four 6-bit items&lt;br /&gt;
      for (int i=3; i&amp;gt;=0; i--)&lt;br /&gt;
      {&lt;br /&gt;
        if (*Base64==0 || *Base64=='=') break;&lt;br /&gt;
        char *p=strchr(sBase64TranslateTable, *Base64++);&lt;br /&gt;
        if (p) s24bits |= ((unsigned long)(p-sBase64TranslateTable))&amp;lt;&amp;lt;(6*i);&lt;br /&gt;
      }&lt;br /&gt;
      // Convert them to three 8-bit items &lt;br /&gt;
      for (int i=2; i&amp;gt;=0; i--) &lt;br /&gt;
      {&lt;br /&gt;
        // Check for buffer overflow&lt;br /&gt;
        if (++Length&amp;gt;=BufferSize) break;&lt;br /&gt;
        // Save byte&lt;br /&gt;
        *Buffer++ = (char)((s24bits&amp;gt;&amp;gt;(8*i))&amp;amp;0xff);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    *Buffer=0;&lt;br /&gt;
  }&lt;br /&gt;
  unsigned DecodeSamsungProtocolString(char *s, char *Buffer, int BufferSize, boolean bBase64)&lt;br /&gt;
  {&lt;br /&gt;
    // Get length of string in message&lt;br /&gt;
    unsigned Length=s[0] | (((unsigned)s[1])&amp;lt;&amp;lt;8);&lt;br /&gt;
    // Get the string&lt;br /&gt;
    if (bBase64)&lt;br /&gt;
    {&lt;br /&gt;
      // Force trailing 0 into Base64 string &lt;br /&gt;
      // (dirty but will work in this project, as the Base64 string is in a frame buffer...)&lt;br /&gt;
      char c=s[Length+2]; s[Length+2]=0;&lt;br /&gt;
      Base64ToAscii(s+2, Buffer, BufferSize);&lt;br /&gt;
      // Restore corrupted char&lt;br /&gt;
      s[Length+2]=c;&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
      // Check for buffer overflow&lt;br /&gt;
      unsigned MaxLength=(Length&amp;gt;BufferSize-1) ? BufferSize-1:Length;&lt;br /&gt;
      // Just copy string&lt;br /&gt;
      strncpy(Buffer, s+2, MaxLength);&lt;br /&gt;
      Buffer[MaxLength]=0;&lt;br /&gt;
    }&lt;br /&gt;
    // Returns length of initial buffer &lt;br /&gt;
    return Length+2;&lt;br /&gt;
  }&lt;br /&gt;
  unsigned EncodeSamsungProtocolString(char *s, char *Buffer, int BufferSize, boolean bBase64)&lt;br /&gt;
  {&lt;br /&gt;
    unsigned Length;&lt;br /&gt;
    if (bBase64) &lt;br /&gt;
    {&lt;br /&gt;
      // Encode string in Base64&lt;br /&gt;
      AsciiToBase64(s, Buffer+2, BufferSize-2); &lt;br /&gt;
      Length=strlen(Buffer+2);&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
      // Leave string in Ascii - No trailing 0&lt;br /&gt;
      Length=strlen(s);&lt;br /&gt;
      if (Length&amp;gt;BufferSize-2) Length=BufferSize-2;&lt;br /&gt;
      strncpy(Buffer+2, s, Length);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Add size of string in message&lt;br /&gt;
    Buffer[0]=Length; Buffer[1]=Length&amp;gt;&amp;gt;8;&lt;br /&gt;
    return Length+2; &lt;br /&gt;
  }&lt;br /&gt;
  #endif&lt;br /&gt;
  &lt;br /&gt;
  // ---------------------------------------------------------------------&lt;br /&gt;
  // Samsung IR class&lt;br /&gt;
  // ---------------------------------------------------------------------&lt;br /&gt;
  &lt;br /&gt;
  class Samsung&lt;br /&gt;
  {&lt;br /&gt;
    private:&lt;br /&gt;
    // Send a 36kHz-modulated pulse&lt;br /&gt;
    static void Pulse(void)&lt;br /&gt;
    {&lt;br /&gt;
      byte i;&lt;br /&gt;
      for (i=0; i&amp;lt;21; i++)&lt;br /&gt;
      {&lt;br /&gt;
        digitalWrite(IRPIN, HIGH);&lt;br /&gt;
        delayMicroseconds(10); // Value adjusted with oscilloscope&lt;br /&gt;
        digitalWrite(IRPIN, LOW);&lt;br /&gt;
        delayMicroseconds(10); // Value adjusted with oscilloscope&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    // Send a bit&lt;br /&gt;
    static void SendIRBit(byte b)&lt;br /&gt;
    {&lt;br /&gt;
      Pulse(); &lt;br /&gt;
      if (b) &lt;br /&gt;
        delayMicroseconds(1390);&lt;br /&gt;
      else&lt;br /&gt;
        delayMicroseconds(430);&lt;br /&gt;
    }&lt;br /&gt;
    // Send 4 bits&lt;br /&gt;
    static void SendIRNibble(byte b)&lt;br /&gt;
    {&lt;br /&gt;
      byte i;&lt;br /&gt;
      for (i=0; i&amp;lt;4; i++)&lt;br /&gt;
        SendIRBit((b&amp;gt;&amp;gt;i)&amp;amp;1);&lt;br /&gt;
    }&lt;br /&gt;
    // Send a byte&lt;br /&gt;
    static void SendIRByte(byte b)&lt;br /&gt;
    {&lt;br /&gt;
      byte i;&lt;br /&gt;
      for (i=0; i&amp;lt;8; i++)&lt;br /&gt;
        SendIRBit((b&amp;gt;&amp;gt;i)&amp;amp;1);&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    public:&lt;br /&gt;
    // Send an IR command&lt;br /&gt;
    // Type is 0 for TV, 1 for BD&lt;br /&gt;
    // Device is 0x0707 for TV, 0x301A for BD&lt;br /&gt;
    // Crc should be ~Command, except for tests&lt;br /&gt;
    static void SendCommand(char Type, unsigned int Device, unsigned int Command, unsigned char Crc)&lt;br /&gt;
    {&lt;br /&gt;
      byte i;&lt;br /&gt;
     &lt;br /&gt;
      // Disable interrupts&lt;br /&gt;
      cli();&lt;br /&gt;
    &lt;br /&gt;
      // Start bit&lt;br /&gt;
      for (i=0; i&amp;lt;8; i++)	Pulse();&lt;br /&gt;
      delayMicroseconds(4500);&lt;br /&gt;
  &lt;br /&gt;
      // Send Device Id&lt;br /&gt;
      SendIRByte(Device&amp;gt;&amp;gt;8);&lt;br /&gt;
      SendIRByte(Device&amp;amp;0xff);&lt;br /&gt;
  &lt;br /&gt;
      // BD Player&lt;br /&gt;
      if (Type==1)&lt;br /&gt;
      {&lt;br /&gt;
        // Stop bit&lt;br /&gt;
        Pulse();&lt;br /&gt;
        delayMicroseconds(4500);&lt;br /&gt;
        // Send Data&lt;br /&gt;
        SendIRNibble(Command&amp;gt;&amp;gt;8);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      SendIRByte(Command);&lt;br /&gt;
      SendIRByte(Crc);&lt;br /&gt;
  &lt;br /&gt;
      // Stop bit&lt;br /&gt;
      Pulse();&lt;br /&gt;
      delayMicroseconds(4500);&lt;br /&gt;
    &lt;br /&gt;
      // Re-enable interrupts&lt;br /&gt;
      sei();&lt;br /&gt;
    }&lt;br /&gt;
    // Read Eeprom&lt;br /&gt;
    static void ReadEeprom(byte device, long addr, byte *data, int count)&lt;br /&gt;
    {&lt;br /&gt;
      if (addr!=0xffffffff)&lt;br /&gt;
      {&lt;br /&gt;
        Wire.beginTransmission(device);&lt;br /&gt;
        if (bEeprom2ByteAddress) Wire.write(addr&amp;gt;&amp;gt;8);&lt;br /&gt;
        Wire.write(addr);&lt;br /&gt;
        Wire.endTransmission();&lt;br /&gt;
      }&lt;br /&gt;
      Wire.requestFrom((int)device, count);&lt;br /&gt;
      for (int i=0; i&amp;lt;count; i++)&lt;br /&gt;
      {&lt;br /&gt;
        if (!Wire.available()) break;&lt;br /&gt;
        data[i]=Wire.read();&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    // Write Eeprom&lt;br /&gt;
    static void WriteEeprom(byte device, long addr, byte *data, int count)&lt;br /&gt;
    {&lt;br /&gt;
      Wire.beginTransmission(device);&lt;br /&gt;
      if (bEeprom2ByteAddress) Wire.write(addr&amp;gt;&amp;gt;8);&lt;br /&gt;
      Wire.write(addr);&lt;br /&gt;
      for (int i=0; i&amp;lt;count; i++) Wire.write(data[i]);&lt;br /&gt;
      Wire.endTransmission();&lt;br /&gt;
    }&lt;br /&gt;
    static boolean bEeprom2ByteAddress;&lt;br /&gt;
  };&lt;br /&gt;
  boolean Samsung::bEeprom2ByteAddress=true;&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
  // ---------------------------------------------------------------------&lt;br /&gt;
  // Initialization&lt;br /&gt;
  // ---------------------------------------------------------------------&lt;br /&gt;
  &lt;br /&gt;
  void setup()&lt;br /&gt;
  {&lt;br /&gt;
    // Led&lt;br /&gt;
    pinMode(LEDPIN, OUTPUT);&lt;br /&gt;
    digitalWrite(LEDPIN, HIGH);&lt;br /&gt;
  &lt;br /&gt;
    // IR Led&lt;br /&gt;
    pinMode(IRPIN, OUTPUT);&lt;br /&gt;
    digitalWrite(IRPIN, HIGH);&lt;br /&gt;
  &lt;br /&gt;
    // I2C&lt;br /&gt;
    Wire.begin();&lt;br /&gt;
  &lt;br /&gt;
    // Serial Console&lt;br /&gt;
    Serial.begin(115200);&lt;br /&gt;
  &lt;br /&gt;
    // Initialize Ethernet. Try DHCP, otherwise static IP&lt;br /&gt;
    if (Ethernet.begin(mac)==0)&lt;br /&gt;
      Ethernet.begin(mac, ip);&lt;br /&gt;
    // Initialize HTTP server&lt;br /&gt;
    HttpServer.begin();&lt;br /&gt;
    // Initialize Telnet server&lt;br /&gt;
    TelnetServer.begin();&lt;br /&gt;
    #ifdef SAMSUNGREMOTE&lt;br /&gt;
    // Initialize Samsung Remote server&lt;br /&gt;
    SamsungRemote.begin();&lt;br /&gt;
    // Initialize SSDP&lt;br /&gt;
    SamsungSSDP.begin(1900);&lt;br /&gt;
    #endif&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
  // ---------------------------------------------------------------------&lt;br /&gt;
  // Main Program&lt;br /&gt;
  // ---------------------------------------------------------------------&lt;br /&gt;
  &lt;br /&gt;
  char HttpFrame[256];           // General buffer for Http and Samsung protocol frames&lt;br /&gt;
  char TelnetFrame[256];         // General buffer for Telnet frames&lt;br /&gt;
  char Buffer[32];               // General buffer&lt;br /&gt;
  boolean iStateLed=false;       // Used for led blinking&lt;br /&gt;
  unsigned long timeLastLedMs=0; // Used for blinking delay&lt;br /&gt;
  &lt;br /&gt;
  void loop()&lt;br /&gt;
  {&lt;br /&gt;
    // -------------------------------------------------&lt;br /&gt;
    // LED blinks at 2Hz&lt;br /&gt;
    // -------------------------------------------------&lt;br /&gt;
    if (millis()&amp;gt;timeLastLedMs+250)&lt;br /&gt;
    {&lt;br /&gt;
      timeLastLedMs=millis();&lt;br /&gt;
      digitalWrite(LEDPIN, (iStateLed) ? HIGH:LOW);&lt;br /&gt;
      iStateLed=!iStateLed;&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // -------------------------------------------------&lt;br /&gt;
    // Handle HTTP requests&lt;br /&gt;
    // Example : &lt;br /&gt;
    //   To send KEY_1 on BD :&lt;br /&gt;
    //   http://IP/ir.htm?data=81&amp;amp;type=1&amp;amp;device=301a&lt;br /&gt;
    // -------------------------------------------------&lt;br /&gt;
    EthernetClient client = HttpServer.available();&lt;br /&gt;
    if (client) &lt;br /&gt;
    {&lt;br /&gt;
      char *ptr=HttpFrame;&lt;br /&gt;
      int n=0;&lt;br /&gt;
      while (client.connected() &amp;amp;&amp;amp; client.available())&lt;br /&gt;
      {&lt;br /&gt;
        if (n++&amp;lt;sizeof(HttpFrame))&lt;br /&gt;
          *ptr++=client.read();&lt;br /&gt;
        else&lt;br /&gt;
          client.flush(); &lt;br /&gt;
      }&lt;br /&gt;
      *ptr=0;&lt;br /&gt;
      if (n&amp;gt;0)&lt;br /&gt;
      {&lt;br /&gt;
        const __FlashStringHelper *HtmlHeader=F(&amp;quot;HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
        // -------------------------------------------------&lt;br /&gt;
        // Send Samsung IR command&lt;br /&gt;
        // -------------------------------------------------&lt;br /&gt;
        ptr=strstr(HttpFrame, &amp;quot;/ir.htm?&amp;quot;);&lt;br /&gt;
        if (ptr)&lt;br /&gt;
        {&lt;br /&gt;
          byte Type=0, Crc;&lt;br /&gt;
          unsigned int Device=0x0707, Data=0;&lt;br /&gt;
  &lt;br /&gt;
          ptr=strstr(HttpFrame, &amp;quot;data=&amp;quot;);&lt;br /&gt;
          if (ptr) Data=HexToULong(ptr+5);&lt;br /&gt;
          ptr=strstr(HttpFrame, &amp;quot;type=&amp;quot;);&lt;br /&gt;
          if (ptr) Type=HexToULong(ptr+5);&lt;br /&gt;
          ptr=strstr(HttpFrame, &amp;quot;device=&amp;quot;);&lt;br /&gt;
          if (ptr) Device=HexToULong(ptr+7);&lt;br /&gt;
          &lt;br /&gt;
          // Next parameter is optional and can be used for tests&lt;br /&gt;
          Crc=~Data;&lt;br /&gt;
          ptr=strstr(HttpFrame, &amp;quot;crc=&amp;quot;);&lt;br /&gt;
          if (ptr) Crc=HexToULong(ptr+4);&lt;br /&gt;
  &lt;br /&gt;
          Samsung::SendCommand(Type, Device, Data, Crc);&lt;br /&gt;
          client.println(HtmlHeader);&lt;br /&gt;
          client.println(&amp;quot;OK !&amp;quot;);&lt;br /&gt;
          client.stop();&lt;br /&gt;
          return;&lt;br /&gt;
        }&lt;br /&gt;
  &lt;br /&gt;
        // -------------------------------------------------&lt;br /&gt;
        // Read Eeprom&lt;br /&gt;
        // -------------------------------------------------&lt;br /&gt;
        ptr=strstr(HttpFrame, &amp;quot;/read&amp;quot;);&lt;br /&gt;
        if (ptr)&lt;br /&gt;
        {&lt;br /&gt;
          byte Device=80, Format=0x50; // hedak: changed eeprom device id to 80 to comply with description above&lt;br /&gt;
          unsigned long Size=0x100, Addr=0;&lt;br /&gt;
  &lt;br /&gt;
          ptr=strstr(HttpFrame, &amp;quot;addr=&amp;quot;);&lt;br /&gt;
          if (ptr) Addr=HexToULong(ptr+5);&lt;br /&gt;
          ptr=strstr(HttpFrame, &amp;quot;size=&amp;quot;);&lt;br /&gt;
          if (ptr) Size=atol(ptr+5);&lt;br /&gt;
          ptr=strstr(HttpFrame, &amp;quot;device=&amp;quot;);&lt;br /&gt;
          if (ptr) Device=atoi(ptr+7);&lt;br /&gt;
          ptr=strstr(HttpFrame, &amp;quot;format=&amp;quot;);&lt;br /&gt;
          if (ptr) Format=atoi(ptr+7);&lt;br /&gt;
          ptr=strstr(HttpFrame, &amp;quot;width=8&amp;quot;);&lt;br /&gt;
          Samsung::bEeprom2ByteAddress=(ptr==0);&lt;br /&gt;
  &lt;br /&gt;
          if (Format==0) &lt;br /&gt;
          {&lt;br /&gt;
            client.println(&amp;quot;HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n&amp;quot;);&lt;br /&gt;
          }&lt;br /&gt;
          else&lt;br /&gt;
            client.println(&amp;quot;HTTP/1.1 200 OK\r\nContent-Type: binary/octet-stream\r\n&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
          byte bSequential=0;    &lt;br /&gt;
          for (long i=Addr; i&amp;lt;Addr+Size; i+=32)&lt;br /&gt;
          {&lt;br /&gt;
            unsigned char Data[32]; &lt;br /&gt;
            for (int i=0; i&amp;lt;32; i++) Data[i]=0xff;&lt;br /&gt;
            Samsung::ReadEeprom(Device, (bSequential) ? -1:i, Data, 32);&lt;br /&gt;
            bSequential=1;&lt;br /&gt;
  &lt;br /&gt;
            if (Format==0)&lt;br /&gt;
            {          &lt;br /&gt;
              sprintf(Buffer, &amp;quot;%04lx: &amp;quot;, i); client.print(Buffer);&lt;br /&gt;
              for (int j=0; j&amp;lt;32; j++)&lt;br /&gt;
                { sprintf(Buffer, &amp;quot;%02X &amp;quot;, Data[j]); client.print(Buffer); }&lt;br /&gt;
              for (int j=0; j&amp;lt;32; j++)&lt;br /&gt;
                { client.write((Data[j]&amp;lt;=0x20 || Data[j]&amp;gt;0x7f) ? '.':Data[j]); }&lt;br /&gt;
              client.println(&amp;quot;&amp;quot;);&lt;br /&gt;
              client.flush();&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
              for (int j=0; j&amp;lt;32; j++)&lt;br /&gt;
                client.write(Data[j]);&lt;br /&gt;
            }&lt;br /&gt;
          }&lt;br /&gt;
  &lt;br /&gt;
          client.stop();&lt;br /&gt;
          return;&lt;br /&gt;
        }&lt;br /&gt;
  &lt;br /&gt;
        // -------------------------------------------------&lt;br /&gt;
        // Write Eeprom&lt;br /&gt;
        // -------------------------------------------------&lt;br /&gt;
        ptr=strstr(HttpFrame, &amp;quot;/write&amp;quot;);&lt;br /&gt;
        char *ptrAddr=strstr(HttpFrame, &amp;quot;addr=&amp;quot;);&lt;br /&gt;
        char *ptrData=strstr(HttpFrame, &amp;quot;data=&amp;quot;);&lt;br /&gt;
        if (ptr &amp;amp;&amp;amp; ptrAddr &amp;amp;&amp;amp; ptrData)&lt;br /&gt;
        {&lt;br /&gt;
          byte Device=80, Data; // hedak: changed eeprom device id to 80 to comply with description above&lt;br /&gt;
          unsigned long Addr;&lt;br /&gt;
          &lt;br /&gt;
          Addr=HexToULong(ptrAddr+5);&lt;br /&gt;
          Data=HexToULong(ptrData+5);&lt;br /&gt;
          ptr=strstr(HttpFrame, &amp;quot;device=&amp;quot;);&lt;br /&gt;
          if (ptr) Device=atoi(ptr+7);&lt;br /&gt;
          ptr=strstr(HttpFrame, &amp;quot;width=8&amp;quot;);&lt;br /&gt;
          Samsung::bEeprom2ByteAddress=(ptr==0);&lt;br /&gt;
  &lt;br /&gt;
          Samsung::WriteEeprom(Device, Addr, &amp;amp;Data, 1);&lt;br /&gt;
          client.println(&amp;quot;HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n&amp;quot;);&lt;br /&gt;
          Data=~Data;&lt;br /&gt;
          Samsung::ReadEeprom(Device, Addr, &amp;amp;Data, 1);    &lt;br /&gt;
          sprintf(Buffer, &amp;quot;%02X &amp;quot;, Data); &lt;br /&gt;
          client.print(Buffer);&lt;br /&gt;
  &lt;br /&gt;
          client.stop();&lt;br /&gt;
          return;&lt;br /&gt;
        }&lt;br /&gt;
  &lt;br /&gt;
        #ifdef SAMSUNGREMOTE&lt;br /&gt;
        // -------------------------------------------------&lt;br /&gt;
        // Device info - used for Samsung Remote Protocol&lt;br /&gt;
        // -------------------------------------------------&lt;br /&gt;
        ptr=strstr(HttpFrame, &amp;quot;/smp_2_&amp;quot;);&lt;br /&gt;
        if (ptr)&lt;br /&gt;
        {&lt;br /&gt;
          client.println(F(&amp;quot;HTTP/1.1 200 OK\r\nContent-Type: text/xml\r\n&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;&amp;lt;?xml version=\&amp;quot;1.0\&amp;quot;?&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;&amp;lt;root xmlns='urn:schemas-upnp-org:device-1-0' xmlns:sec='http://www.sec.co.kr/dlna' xmlns:dlna='urn:schemas-dlna-org:device-1-0'&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot; &amp;lt;specVersion&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;major&amp;gt;1&amp;lt;/major&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;minor&amp;gt;0&amp;lt;/minor&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot; &amp;lt;/specVersion&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot; &amp;lt;device&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;deviceType&amp;gt;urn:samsung.com:device:RemoteControlReceiver:1&amp;lt;/deviceType&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;friendlyName&amp;gt;SamyGO&amp;lt;/friendlyName&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;manufacturer&amp;gt;Samsung Electronics&amp;lt;/manufacturer&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;manufacturerURL&amp;gt;http://www.samsung.com/sec&amp;lt;/manufacturerURL&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;modelDescription&amp;gt;Samsung BD RCR&amp;lt;/modelDescription&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;modelName&amp;gt;BD-E8500&amp;lt;/modelName&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;modelNumber&amp;gt;1.0&amp;lt;/modelNumber&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;modelURL&amp;gt;http://www.samsung.com/sec&amp;lt;/modelURL&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;serialNumber&amp;gt;12345678RCR&amp;lt;/serialNumber&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;UDN&amp;gt;uuid:11111111-2222-3333-4444-555555555555&amp;lt;/UDN&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;sec:deviceID&amp;gt;ABCDEFGHIJKLM&amp;lt;/sec:deviceID&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;sec:ProductCap&amp;gt;Resolution:1280X720,ImageZoom,ImageRotate,Y2012&amp;lt;/sec:ProductCap&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;serviceList&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;   &amp;lt;service&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;    &amp;lt;serviceType&amp;gt;urn:samsung.com:service:TestRCRService:1&amp;lt;/serviceType&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;    &amp;lt;serviceId&amp;gt;urn:samsung.com:serviceId:TestRCRService&amp;lt;/serviceId&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;    &amp;lt;controlURL&amp;gt;/smp_4_&amp;lt;/controlURL&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;    &amp;lt;eventSubURL&amp;gt;/smp_5_&amp;lt;/eventSubURL&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;    &amp;lt;SCPDURL&amp;gt;/smp_3_&amp;lt;/SCPDURL&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;   &amp;lt;/service&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;/serviceList&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot; &amp;lt;/device&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;&amp;lt;/root&amp;gt;&amp;quot;));&lt;br /&gt;
          client.stop();&lt;br /&gt;
          return;&lt;br /&gt;
        }&lt;br /&gt;
        #endif&lt;br /&gt;
  &lt;br /&gt;
        // send an error !&lt;br /&gt;
        client.println(HtmlHeader);&lt;br /&gt;
        client.println(F(&amp;quot;Error !&amp;quot;));&lt;br /&gt;
        delay(1);&lt;br /&gt;
      }&lt;br /&gt;
      client.stop();&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    #ifdef SAMSUNGREMOTE&lt;br /&gt;
    // -------------------------------------------------&lt;br /&gt;
    // Samsung Remote Protocol&lt;br /&gt;
    // -------------------------------------------------&lt;br /&gt;
    client = SamsungRemote.available();&lt;br /&gt;
    if (client) &lt;br /&gt;
    {&lt;br /&gt;
      //Serial.println(&amp;quot;Incoming frame...&amp;quot;);&lt;br /&gt;
      &lt;br /&gt;
      // Read incoming frame&lt;br /&gt;
      char *ptr=HttpFrame;&lt;br /&gt;
      int n=0;&lt;br /&gt;
      while (client.connected() &amp;amp;&amp;amp; client.available())&lt;br /&gt;
        if (n++&amp;lt;sizeof(HttpFrame)) *ptr++=client.read();&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
      ptr=HttpFrame+1;&lt;br /&gt;
      // Decode App Name&lt;br /&gt;
      ptr+=DecodeSamsungProtocolString(ptr, Buffer, sizeof(Buffer), false);&lt;br /&gt;
      //Serial.print(&amp;quot;Name=&amp;quot;); Serial.println(Buffer);&lt;br /&gt;
  &lt;br /&gt;
      // Ignore message length&lt;br /&gt;
      ptr+=2;&lt;br /&gt;
  &lt;br /&gt;
      // Decode command&lt;br /&gt;
      unsigned Cmd=*ptr++; Cmd|=(*ptr++)&amp;lt;&amp;lt;8;&lt;br /&gt;
      //Serial.print(&amp;quot;Cmd=&amp;quot;); Serial.println(Cmd);&lt;br /&gt;
  &lt;br /&gt;
      // Connection frame ?&lt;br /&gt;
      if (Cmd==0x64)&lt;br /&gt;
      {&lt;br /&gt;
        // Decode remote IP&lt;br /&gt;
        ptr+=DecodeSamsungProtocolString(ptr, Buffer, sizeof(Buffer), true);&lt;br /&gt;
        //Serial.print(&amp;quot;IP=&amp;quot;); Serial.println(Buffer);&lt;br /&gt;
  &lt;br /&gt;
        // Decode remote MAC address&lt;br /&gt;
        ptr+=DecodeSamsungProtocolString(ptr, Buffer, sizeof(Buffer), true);&lt;br /&gt;
        //Serial.print(&amp;quot;MAC=&amp;quot;); Serial.println(Buffer);&lt;br /&gt;
  &lt;br /&gt;
        // Decode machine name&lt;br /&gt;
        ptr+=DecodeSamsungProtocolString(ptr, Buffer, sizeof(Buffer), true);&lt;br /&gt;
        //Serial.print(&amp;quot;Machine=&amp;quot;); Serial.println(Buffer);&lt;br /&gt;
        delay(5);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      // Key frame ?&lt;br /&gt;
      else if (Cmd==0x00)&lt;br /&gt;
      {&lt;br /&gt;
        ptr++; // Skip first byte&lt;br /&gt;
        ptr+=DecodeSamsungProtocolString(ptr, Buffer, sizeof(Buffer), true);&lt;br /&gt;
        //Serial.print(&amp;quot;KeyName=&amp;quot;); Serial.print(Buffer); Serial.println(&amp;quot;----&amp;quot;);&lt;br /&gt;
        if (!strcmp(Buffer, &amp;quot;BD_KEY_POWER&amp;quot;))&lt;br /&gt;
        {&lt;br /&gt;
          // Power key for BD&lt;br /&gt;
          Samsung::SendCommand(1, 0x301a, 0x91, ~0x91);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      // Answer&lt;br /&gt;
      HttpFrame[0]=0;&lt;br /&gt;
      int len=1;&lt;br /&gt;
      len+=EncodeSamsungProtocolString(&amp;quot;iapp.samsung&amp;quot;, HttpFrame+1, sizeof(HttpFrame), false);&lt;br /&gt;
      if (Cmd==0x64)&lt;br /&gt;
      {&lt;br /&gt;
        byte answer[]={0x04,0x00,0x64,0x00,0x01,0x00};&lt;br /&gt;
        memcpy(HttpFrame+len, answer, sizeof(answer));&lt;br /&gt;
        len+=sizeof(answer);&lt;br /&gt;
      }&lt;br /&gt;
      else&lt;br /&gt;
      {&lt;br /&gt;
        byte answer[]={0x04,0x00,0x00,0x00,0x00,0x00};&lt;br /&gt;
        memcpy(HttpFrame+len, answer, sizeof(answer));&lt;br /&gt;
        len+=sizeof(answer);&lt;br /&gt;
      }&lt;br /&gt;
      client.write((byte *)HttpFrame, len);&lt;br /&gt;
      delay(5);&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // SSDP discovery protocol&lt;br /&gt;
    int PacketSize=SamsungSSDP.parsePacket();&lt;br /&gt;
    if (PacketSize)&lt;br /&gt;
    {&lt;br /&gt;
      // Read incoming frame&lt;br /&gt;
      char *ptr=HttpFrame;&lt;br /&gt;
      int n=0;&lt;br /&gt;
      while (SamsungSSDP.available())&lt;br /&gt;
        if (n++&amp;lt;sizeof(HttpFrame)) *ptr++=SamsungSSDP.read();&lt;br /&gt;
  &lt;br /&gt;
      // Discovery request ?&lt;br /&gt;
      if (strstr(HttpFrame, &amp;quot;M-SEARCH *&amp;quot;) &amp;amp;&amp;amp; strstr(HttpFrame, &amp;quot;urn:samsung.com:device:RemoteControlReceiver:1&amp;quot;))&lt;br /&gt;
      {&lt;br /&gt;
        //Serial.print(&amp;quot;SSDP Discovery from : IP=&amp;quot;); Serial.print(SamsungSSDP.remoteIP()); Serial.print(&amp;quot;:&amp;quot;); Serial.println(SamsungSSDP.remotePort());&lt;br /&gt;
        SamsungSSDP.beginPacket(SamsungSSDP.remoteIP(), SamsungSSDP.remotePort());&lt;br /&gt;
        SamsungSSDP.println(F(&amp;quot;HTTP/1.1 200 OK&amp;quot;));&lt;br /&gt;
        SamsungSSDP.println(F(&amp;quot;CACHE-CONTROL: max-age= 1800&amp;quot;));&lt;br /&gt;
        SamsungSSDP.println(F(&amp;quot;Date: Sat, 01 Jan 2012 00:00:00 GMT&amp;quot;));&lt;br /&gt;
        SamsungSSDP.println(F(&amp;quot;EXT: &amp;quot;));&lt;br /&gt;
        SamsungSSDP.print(F(&amp;quot;LOCATION: http://&amp;quot;)); SamsungSSDP.print(Ethernet.localIP()); SamsungSSDP.println(F(&amp;quot;:80/smp_2_&amp;quot;));&lt;br /&gt;
        SamsungSSDP.println(F(&amp;quot;SERVER: SHP, UPnP/1.0, Samsung UPnP SDK/1.0&amp;quot;));&lt;br /&gt;
        SamsungSSDP.println(F(&amp;quot;ST: urn:samsung.com:device:RemoteControlReceiver:1&amp;quot;));&lt;br /&gt;
        SamsungSSDP.println(F(&amp;quot;USN: uuid:11111111-2222-3333-4444-555555555555::urn:samsung.com:device:RemoteControlReceiver:1&amp;quot;));&lt;br /&gt;
        SamsungSSDP.println(F(&amp;quot;Content-Length: 0&amp;quot;));&lt;br /&gt;
        SamsungSSDP.endPacket();&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    #endif&lt;br /&gt;
  &lt;br /&gt;
    // -------------------------------------------------&lt;br /&gt;
    // Telnet Serial Console Interface&lt;br /&gt;
    // Configure Putty with :&lt;br /&gt;
    //   - &amp;quot;Local Echo : Force off&amp;quot;&lt;br /&gt;
    //   - &amp;quot;Local line editing : Force off&amp;quot;&lt;br /&gt;
    // -------------------------------------------------&lt;br /&gt;
    client = TelnetServer.available();&lt;br /&gt;
    if (client) &lt;br /&gt;
    {&lt;br /&gt;
      char *ptr=TelnetFrame;&lt;br /&gt;
      int n=0;&lt;br /&gt;
      while (client.connected() &amp;amp;&amp;amp; client.available())&lt;br /&gt;
        if (n++&amp;lt;sizeof(TelnetFrame)) *ptr++=client.read();&lt;br /&gt;
      *ptr=0;&lt;br /&gt;
      &lt;br /&gt;
      // Sends telnet buffer to Serial Console&lt;br /&gt;
      if (n&amp;gt;0) Serial.write(TelnetFrame);&lt;br /&gt;
    }&lt;br /&gt;
    // Anything received from Serial Console ?&lt;br /&gt;
    char *ptr=TelnetFrame;&lt;br /&gt;
    int n=0;&lt;br /&gt;
    while (Serial.available())&lt;br /&gt;
      if (n++&amp;lt;sizeof(TelnetFrame)) *ptr++=Serial.read();&lt;br /&gt;
    *ptr=0;&lt;br /&gt;
      // Send it to telnet&lt;br /&gt;
    if (n&amp;gt;0) TelnetServer.write(TelnetFrame);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  // ---------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
== Teensy(++ 2.0) sketch for accessing I2C interface ==&lt;br /&gt;
&lt;br /&gt;
This sketch has been compiled with Arduino 1.0.5.&lt;br /&gt;
It's a limited version compared to the arduino sketch above. Only the I2C interface to read/write tv's eeprom is implemented and instead of the ethernet interface there's a usb interface (Hint: sketch becomes active only if DTR on pc side is set). Usage of the I2C feature is the same anyway.&lt;br /&gt;
&lt;br /&gt;
 // ---------------------------------------------------------------------&lt;br /&gt;
 // Samsung I2C interface based on oga83's 'Samsung multi-functions ethernet interface' v1.2&lt;br /&gt;
 //   - Read &amp;amp; Write I2C config eeprom&lt;br /&gt;
 //&lt;br /&gt;
 // 07-03-2014 / v1.1 / hedak&lt;br /&gt;
 //----------------------------------------------------------------------&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;Wire.h&amp;gt;&lt;br /&gt;
 #include &amp;quot;utility\twi.h&amp;quot; //hedak: for outputting I2C frequency&lt;br /&gt;
 &lt;br /&gt;
 #define CPU_PRESCALE(n)	(CLKPR = 0x80, CLKPR = (n))&lt;br /&gt;
 &lt;br /&gt;
 #define LEDPIN     CORE_LED0_PIN    // Onboard led - blink at 2 Hz&lt;br /&gt;
                         // I2C Eeprom : SDA connected on D1&lt;br /&gt;
                         // I2C Eeprom : SCL connected on D0&lt;br /&gt;
 &lt;br /&gt;
 // ---------------------------------------------------------------------&lt;br /&gt;
 // Utilities&lt;br /&gt;
 // ---------------------------------------------------------------------&lt;br /&gt;
 &lt;br /&gt;
 // Convert a hex string to unsigned int&lt;br /&gt;
 unsigned long HexToULong(char *s)&lt;br /&gt;
 {&lt;br /&gt;
   unsigned long u=0;&lt;br /&gt;
   while (*s)&lt;br /&gt;
   {&lt;br /&gt;
     char c=*s++;&lt;br /&gt;
     // Convert to uppercase&lt;br /&gt;
     if (c&amp;gt;='a') c&amp;amp;=0xdf;&lt;br /&gt;
     // Exit if not hex digit&lt;br /&gt;
     if ((c&amp;lt;'0' || c&amp;gt;'9') &amp;amp;&amp;amp; (c&amp;lt;'A' || c&amp;gt;'F')) break;&lt;br /&gt;
     // Convert digit&lt;br /&gt;
     u&amp;lt;&amp;lt;=4;&lt;br /&gt;
     u|=c-((c&amp;gt;'9') ? 'A'-0xa:'0');&lt;br /&gt;
   }&lt;br /&gt;
   return u;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 // ---------------------------------------------------------------------&lt;br /&gt;
 // Samsung class&lt;br /&gt;
 // ---------------------------------------------------------------------&lt;br /&gt;
 &lt;br /&gt;
 class Samsung&lt;br /&gt;
 {&lt;br /&gt;
   public:&lt;br /&gt;
   // Read Eeprom&lt;br /&gt;
   static void ReadEeprom(byte device, long addr, byte *data, int count)&lt;br /&gt;
   {&lt;br /&gt;
     if (addr!=0xffffffff)&lt;br /&gt;
     {&lt;br /&gt;
       Wire.beginTransmission(device);&lt;br /&gt;
       if (bEeprom2ByteAddress) Wire.write(addr&amp;gt;&amp;gt;8);&lt;br /&gt;
       Wire.write(addr);&lt;br /&gt;
       Wire.endTransmission();&lt;br /&gt;
     }&lt;br /&gt;
     Wire.requestFrom((int)device, count);&lt;br /&gt;
     for (int i=0; i&amp;lt;count; i++)&lt;br /&gt;
     {&lt;br /&gt;
       if (!Wire.available()) break;&lt;br /&gt;
       data[i]=Wire.read();&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   // Write Eeprom&lt;br /&gt;
   static void WriteEeprom(byte device, long addr, byte *data, int count)&lt;br /&gt;
   {&lt;br /&gt;
     Wire.beginTransmission(device);&lt;br /&gt;
     if (bEeprom2ByteAddress) Wire.write(addr&amp;gt;&amp;gt;8);&lt;br /&gt;
     Wire.write(addr);&lt;br /&gt;
     for (int i=0; i&amp;lt;count; i++) Wire.write(data[i]);&lt;br /&gt;
     Wire.endTransmission();&lt;br /&gt;
   }&lt;br /&gt;
   static boolean bEeprom2ByteAddress;&lt;br /&gt;
 };&lt;br /&gt;
 boolean Samsung::bEeprom2ByteAddress=true; &lt;br /&gt;
 &lt;br /&gt;
 // ---------------------------------------------------------------------&lt;br /&gt;
 // Main Program&lt;br /&gt;
 // ---------------------------------------------------------------------&lt;br /&gt;
 &lt;br /&gt;
 char HttpFrame[256];           // General buffer for Http and Samsung protocol frames&lt;br /&gt;
 char Buffer[32];               // General buffer&lt;br /&gt;
 boolean iStateLed=false;       // Used for led blinking&lt;br /&gt;
 unsigned long timeLastLedMs=0; // Used for blinking delay&lt;br /&gt;
 &lt;br /&gt;
 void loop()&lt;br /&gt;
 {&lt;br /&gt;
   // -------------------------------------------------&lt;br /&gt;
   // LED blinks at 2Hz&lt;br /&gt;
   // -------------------------------------------------&lt;br /&gt;
   if (millis()&amp;gt;timeLastLedMs+250)&lt;br /&gt;
   {&lt;br /&gt;
     timeLastLedMs=millis();&lt;br /&gt;
     digitalWrite(LEDPIN, (iStateLed) ? HIGH:LOW);&lt;br /&gt;
     iStateLed=!iStateLed;&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   // -------------------------------------------------&lt;br /&gt;
   // Handle HTTP requests&lt;br /&gt;
   // Example : &lt;br /&gt;
   //   To read a whole EEPROM dump :&lt;br /&gt;
   //   http://IP/read?format=1&amp;amp;device=80&amp;amp;size=256&lt;br /&gt;
   // -------------------------------------------------&lt;br /&gt;
     char *ptr=HttpFrame;&lt;br /&gt;
     int n=0;&lt;br /&gt;
     while (Serial.available())&lt;br /&gt;
     {&lt;br /&gt;
       if (n++&amp;lt;sizeof(HttpFrame))&lt;br /&gt;
         *ptr++=Serial.read();&lt;br /&gt;
       else&lt;br /&gt;
         Serial.flush(); &lt;br /&gt;
     }&lt;br /&gt;
     *ptr=0;&lt;br /&gt;
     Serial.write(HttpFrame);&lt;br /&gt;
     if (n&amp;gt;0)&lt;br /&gt;
     {&lt;br /&gt;
       // -------------------------------------------------&lt;br /&gt;
       // Read Eeprom&lt;br /&gt;
       // -------------------------------------------------&lt;br /&gt;
       ptr=strstr(HttpFrame, &amp;quot;/read&amp;quot;);&lt;br /&gt;
       if (ptr)&lt;br /&gt;
       {&lt;br /&gt;
         byte Device=80, Format=0x50; // hedak: fixed wrong default value for 'Device'&lt;br /&gt;
         unsigned long Size=0x100, Addr=0;&lt;br /&gt;
 &lt;br /&gt;
         ptr=strstr(HttpFrame, &amp;quot;addr=&amp;quot;);&lt;br /&gt;
         if (ptr) Addr=HexToULong(ptr+5);&lt;br /&gt;
         ptr=strstr(HttpFrame, &amp;quot;size=&amp;quot;);&lt;br /&gt;
         if (ptr) Size=atol(ptr+5);&lt;br /&gt;
         ptr=strstr(HttpFrame, &amp;quot;device=&amp;quot;);&lt;br /&gt;
         if (ptr) Device=atoi(ptr+7);&lt;br /&gt;
         ptr=strstr(HttpFrame, &amp;quot;format=&amp;quot;);&lt;br /&gt;
         if (ptr) Format=atoi(ptr+7);&lt;br /&gt;
         ptr=strstr(HttpFrame, &amp;quot;width=8&amp;quot;);&lt;br /&gt;
         Samsung::bEeprom2ByteAddress=(ptr==0);&lt;br /&gt;
 &lt;br /&gt;
         sprintf(Buffer, &amp;quot;Start reading @ address: %lX\r\n&amp;quot;, Addr);&lt;br /&gt;
         Serial.write(Buffer);&lt;br /&gt;
         &lt;br /&gt;
         if (Format==0) &lt;br /&gt;
         {&lt;br /&gt;
           Serial.write(&amp;quot;HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
         else&lt;br /&gt;
           Serial.write(&amp;quot;HTTP/1.1 200 OK\r\nContent-Type: binary/octet-stream\r\n&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
         byte bSequential=0;    &lt;br /&gt;
         for (long i=Addr; i&amp;lt;Addr+Size; i+=32)&lt;br /&gt;
         {&lt;br /&gt;
           unsigned char Data[32]; &lt;br /&gt;
           for (int i=0; i&amp;lt;32; i++) Data[i]=0xff;&lt;br /&gt;
           Samsung::ReadEeprom(Device, (bSequential) ? -1:i, Data, 32);&lt;br /&gt;
           bSequential=1;&lt;br /&gt;
 &lt;br /&gt;
           if (Format==0)&lt;br /&gt;
           {          &lt;br /&gt;
             sprintf(Buffer, &amp;quot;%04lx: &amp;quot;, i); Serial.write(Buffer);&lt;br /&gt;
             for (int j=0; j&amp;lt;32; j++)&lt;br /&gt;
               { sprintf(Buffer, &amp;quot;%02X &amp;quot;, Data[j]); Serial.write(Buffer); }&lt;br /&gt;
             for (int j=0; j&amp;lt;32; j++)&lt;br /&gt;
               { Serial.write((Data[j]&amp;lt;=0x20 || Data[j]&amp;gt;0x7f) ? '.':Data[j]); }&lt;br /&gt;
             Serial.write(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
             Serial.flush();&lt;br /&gt;
           }&lt;br /&gt;
           else&lt;br /&gt;
           {&lt;br /&gt;
             for (int j=0; j&amp;lt;32; j++)&lt;br /&gt;
               Serial.write(Data[j]);&lt;br /&gt;
           }&lt;br /&gt;
         }&lt;br /&gt;
         return;&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       // -------------------------------------------------&lt;br /&gt;
       // Write Eeprom&lt;br /&gt;
       // -------------------------------------------------&lt;br /&gt;
       ptr=strstr(HttpFrame, &amp;quot;/write&amp;quot;);&lt;br /&gt;
       Serial.write(&amp;quot;Remove the following 'return;' line to activate write feature!\r\n&amp;quot;);&lt;br /&gt;
       return;&lt;br /&gt;
       char *ptrAddr=strstr(HttpFrame, &amp;quot;addr=&amp;quot;);&lt;br /&gt;
       char *ptrData=strstr(HttpFrame, &amp;quot;data=&amp;quot;);&lt;br /&gt;
       if (ptr &amp;amp;&amp;amp; ptrAddr &amp;amp;&amp;amp; ptrData)&lt;br /&gt;
       {&lt;br /&gt;
         byte Device=0, Data;&lt;br /&gt;
         unsigned long Addr;&lt;br /&gt;
         &lt;br /&gt;
         Addr=HexToULong(ptrAddr+5);&lt;br /&gt;
         Data=HexToULong(ptrData+5);&lt;br /&gt;
         ptr=strstr(HttpFrame, &amp;quot;device=&amp;quot;);&lt;br /&gt;
         if (ptr) Device=atoi(ptr+7);&lt;br /&gt;
         ptr=strstr(HttpFrame, &amp;quot;width=8&amp;quot;);&lt;br /&gt;
         Samsung::bEeprom2ByteAddress=(ptr==0);&lt;br /&gt;
 &lt;br /&gt;
         Samsung::WriteEeprom(Device, Addr, &amp;amp;Data, 1);&lt;br /&gt;
         Serial.write(&amp;quot;HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n&amp;quot;);&lt;br /&gt;
         Data=~Data;&lt;br /&gt;
         Samsung::ReadEeprom(Device, Addr, &amp;amp;Data, 1);    &lt;br /&gt;
         sprintf(Buffer, &amp;quot;%02X &amp;quot;, Data); &lt;br /&gt;
         Serial.write(Buffer);&lt;br /&gt;
         return;&lt;br /&gt;
       }&lt;br /&gt;
       // send an error !&lt;br /&gt;
       Serial.write(&amp;quot;HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n&amp;quot;);&lt;br /&gt;
       Serial.write(&amp;quot;Error !\r\n&amp;quot;);&lt;br /&gt;
       delay(1);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // ---------------------------------------------------------------------&lt;br /&gt;
 // Initialization&lt;br /&gt;
 // ---------------------------------------------------------------------&lt;br /&gt;
 &lt;br /&gt;
 void setup()&lt;br /&gt;
 {&lt;br /&gt;
 #if (F_CPU == 8000000)&lt;br /&gt;
    // set for 8 MHz clock because of operating at 3.3 volts&lt;br /&gt;
    CPU_PRESCALE(0x01);&lt;br /&gt;
 #else&lt;br /&gt;
    // set for external 16 MHz clock&lt;br /&gt;
    CPU_PRESCALE(0x00);&lt;br /&gt;
 #endif&lt;br /&gt;
   // Led&lt;br /&gt;
   pinMode(LEDPIN, OUTPUT);&lt;br /&gt;
   digitalWrite(LEDPIN, HIGH);&lt;br /&gt;
 &lt;br /&gt;
   // I2C&lt;br /&gt;
   Wire.begin();&lt;br /&gt;
 &lt;br /&gt;
   // Serial Console&lt;br /&gt;
   Serial.begin(115200);&lt;br /&gt;
   &lt;br /&gt;
   // wait for the user to run their terminal emulator program&lt;br /&gt;
   // which sets DTR to indicate it is ready to receive.&lt;br /&gt;
   while (!Serial.dtr()) /* wait */ ;&lt;br /&gt;
   sprintf(Buffer, &amp;quot;TWI_FREQ: %ld&amp;quot;, TWI_FREQ);&lt;br /&gt;
   Serial.write(Buffer);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // ---------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
Any discussion on related [http://forum.samygo.tv/viewtopic.php?f=51&amp;amp;t=5307#p38502 forum topic].&lt;br /&gt;
Thread using teensy sketch is [http://forum.samygo.tv/viewtopic.php?f=15&amp;amp;t=7117#p53751 here].&lt;/div&gt;</summary>
		<author><name>Hedak</name></author>
		
	</entry>
	<entry>
		<id>http://wiki.samygo.tv/index.php?title=Ethernet_multi-function_Interface&amp;diff=3909</id>
		<title>Ethernet multi-function Interface</title>
		<link rel="alternate" type="text/html" href="http://wiki.samygo.tv/index.php?title=Ethernet_multi-function_Interface&amp;diff=3909"/>
		<updated>2014-03-07T20:03:20Z</updated>

		<summary type="html">&lt;p&gt;Hedak: Added teensy sketch and made arduino sketch eeprom device id compliant to description&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Using an Arduino Ethernet board, you can send IR codes to your TV or BD&lt;br /&gt;
&lt;br /&gt;
With the same board, you can also interface to the Serial Console, and read your device config eeprom.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== What you can do ==&lt;br /&gt;
* Send IR codes to your TV, PVR or BD, with an URL in your browser&lt;br /&gt;
* Use telnet to have the Serial Console on your PC or smartphone&lt;br /&gt;
* Read your SoC config eeprom&lt;br /&gt;
* Read/write micom config eeprom&lt;br /&gt;
* See Arduino as a Samsung device in the Samsung Remote App (can be used to power on the device !)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Arduino interface.jpg|335px]]             [[File:EthernetInterface-SamsungRemote.png|335px]]&lt;br /&gt;
&lt;br /&gt;
== Bill of materials ==&lt;br /&gt;
* Arduino Ethernet board (see [http://arduino.cc/en/Main/ArduinoBoardEthernet Arduino])&lt;br /&gt;
Alternatively, an Arduino Uno with an Ethernet shield could also be used&lt;br /&gt;
* IR led (SFH4510 for example) or RED Led (Clear Type RED LED's are emitting more than enough light at IR spectrum)&lt;br /&gt;
* 220 ohms resistor to limit current in the IR led&lt;br /&gt;
* If you plan to use the telnet interface to the Serial Console, make sure you have a 100 ohms resistor on both RX and TX signals (Arduino TX/RX are 5v !)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== How to use it ==&lt;br /&gt;
* Upload the following '''[[#Arduino_sketch | sketch]]''' into your Arduino&lt;br /&gt;
* Connect the IR or RED led with its resistor on pin 8 on the Arduino&lt;br /&gt;
* Connect power and network&lt;br /&gt;
* Find the IP address of the board on your DHCP (or use the static IP embedded in the sketch if you don't have DHCP)&lt;br /&gt;
* Use your browser to send an URL to the board (see format below)&lt;br /&gt;
* If you want to use telnet to connect to the Serial Console :&lt;br /&gt;
 * Connect your Serial Console signals TX&amp;amp;RX to the Arduino board pins 0&amp;amp;1  ({{red|with 100 ohms resistors}})&lt;br /&gt;
 * Use Putty with options 'Local Echo' and 'Local line editing' forced to OFF&lt;br /&gt;
* If you want to read your config eeprom :&lt;br /&gt;
 * Connect the eeprom SDA&amp;amp;SCK signals to the Arduino board pins A4/A5 ({{red|with 100 ohms resistors}})&lt;br /&gt;
 * Connect the eeprom GND to 0v&lt;br /&gt;
* If you want to use the Samsung Remote feature :&lt;br /&gt;
 * Compile with SAMSUNGREMOTE defined&lt;br /&gt;
 * The program only handles BD_KEY_POWER; if you want aditional keys, it's easy to add them&lt;br /&gt;
&lt;br /&gt;
== URL format to send IR codes ==&lt;br /&gt;
The format is http://IP/ir.htm?data=XX&amp;amp;type=Y&amp;amp;device=ZZZZ&lt;br /&gt;
where&lt;br /&gt;
* IP is the Arduino board IP address&lt;br /&gt;
* XX is the IR code to send&lt;br /&gt;
* Y is 0 for TV/PVR frame format and 1 for BD frame format&lt;br /&gt;
* ZZZZ is the device code (0707 for TV, 0505 for PVR, 301A for BD)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The IR codes are listed at [[Key codes]]&lt;br /&gt;
* For TV/PVR, use the 'code' column&lt;br /&gt;
* For BD, use the 'BD-IR code' column&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To get the Service Menu on your TV, use the 2 following URLs :&lt;br /&gt;
* http://IP/ir.htm?data=1F&amp;amp;type=0&amp;amp;device=0707&lt;br /&gt;
* http://IP/ir.htm?data=3B&amp;amp;type=0&amp;amp;device=0707&lt;br /&gt;
Please note that you cannot send KEY_FACTORY to a BD, as the corresponding code is not know yet&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To have a kind of Wake Up on LAN on your BD player, use&lt;br /&gt;
* http://IP/ir.htm?data=91&amp;amp;type=1&amp;amp;device=301A&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To switch to channel 1 :&lt;br /&gt;
* On a TV : http://IP/ir.htm?data=65&amp;amp;type=0&amp;amp;device=0707&lt;br /&gt;
* On a BD : http://IP/ir.htm?data=81&amp;amp;type=0&amp;amp;device=301A&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== URL format to read config Eeprom ==&lt;br /&gt;
The format is http://IP/read?format=F&amp;amp;device=D&amp;amp;addr=A&amp;amp;size=S&amp;amp;width=W&lt;br /&gt;
&lt;br /&gt;
* IP is the Arduino board IP address&lt;br /&gt;
* F is 0 to get the result in html, 1 to download a binary file&lt;br /&gt;
* D is the Eeprom device identification (80 by default)&lt;br /&gt;
* A is the starting address for reading (0 by default)&lt;br /&gt;
* S is the number of bytes to read (default=256)&lt;br /&gt;
* W is the address bus width (8 bits for Micom eeprom, 16 bits for SoC eeprom); default is 16&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
BD-E8300 is equiped with a 24512 eeprom (64 kbytes)&lt;br /&gt;
&lt;br /&gt;
To download its whole config :&lt;br /&gt;
* http://IP/read?format=1&amp;amp;size=65536&lt;br /&gt;
or :&lt;br /&gt;
* http://IP/read?format=1&amp;amp;device=80&amp;amp;size=65536&amp;amp;addr=0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Eeprom connection :&lt;br /&gt;
&lt;br /&gt;
[[File:Arduino_I2C_Eeprom.jpg|335px]]&lt;br /&gt;
&lt;br /&gt;
== URL format to write config Eeprom ==&lt;br /&gt;
The format is http://IP/write?device=D&amp;amp;addr=A&amp;amp;data=X&amp;amp;width=W&lt;br /&gt;
&lt;br /&gt;
* IP is the Arduino board IP address&lt;br /&gt;
* D is the Eeprom device identification (80 by default)&lt;br /&gt;
* A is the starting address for writing (0 by default)&lt;br /&gt;
* X is the data byte to write&lt;br /&gt;
* W is the address bus width (8 bits for Micom eeprom, 16 bits for SoC eeprom); default is 16&lt;br /&gt;
&lt;br /&gt;
On this version, it is only possible to write one byte at once...&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
http://IP/write?addr=e0&amp;amp;data=55&amp;amp;width=16 will write 0x55 at address 0xe0&lt;br /&gt;
&lt;br /&gt;
== IR frames format == &lt;br /&gt;
BD players use a modified IR frame format that TV and PVR.&lt;br /&gt;
The reason is that samsung increased the data field length from 8 to 12 bits&lt;br /&gt;
The general format is now :&lt;br /&gt;
* Start bit&lt;br /&gt;
* Device ID (16 bits - 0707 for TV, 301A for BD)&lt;br /&gt;
* For BD only : Stop bit and data MSB on 4 bits&lt;br /&gt;
* Data LSB&lt;br /&gt;
* Data LSB 1's complement&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A frame for BD :&lt;br /&gt;
&lt;br /&gt;
[[File:BD_IR_Frame_Format.png‎]]&lt;br /&gt;
&lt;br /&gt;
== Arduino sketch ==&lt;br /&gt;
&lt;br /&gt;
This sketch has been compiled with Arduino 1.0.3 ([http://arduino.cc/en/Main/Software Download here])&lt;br /&gt;
&lt;br /&gt;
  // ---------------------------------------------------------------------&lt;br /&gt;
  // Samsung multi-functions ethernet interface &lt;br /&gt;
  //   - Send IR frame with http get requests&lt;br /&gt;
  //   - Debug console on telnet&lt;br /&gt;
  //   - Read &amp;amp; Write I2C config eeprom&lt;br /&gt;
  //&lt;br /&gt;
  // 29-06-2012 / v1.1 / oga83&lt;br /&gt;
  // 11-09-2012 / v1.1 / oga83&lt;br /&gt;
  //    Added optionnal 'crc' url parameter for testing IR (allow to force CRC)&lt;br /&gt;
  //    Added I2C interface to read/write config eeprom&lt;br /&gt;
  // 09-01-2013 / v1.1.1 / oga83&lt;br /&gt;
  //    Fixed compilation issue with Arduino 1.0.3 and typo in wiki&lt;br /&gt;
  // 11-01-2013 / v1.1.2 / oga83&lt;br /&gt;
  //    Modified ReadEeprom and WriteEeprom for 1-byte address eeproms&lt;br /&gt;
  // 11-01-2013 / v1.2 / oga83&lt;br /&gt;
  //    Added Samsung Remote protocol (Arduino seen as a samsung device)&lt;br /&gt;
  //----------------------------------------------------------------------&lt;br /&gt;
  &lt;br /&gt;
  #include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
  #include &amp;lt;Ethernet.h&amp;gt;&lt;br /&gt;
  #include &amp;lt;EthernetUdp.h&amp;gt;&lt;br /&gt;
  #include &amp;lt;Wire.h&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
  #define IRPIN      8    // IR led is connected on pin 8&lt;br /&gt;
  #define LEDPIN     9    // Onboard led - blink at 2 Hz&lt;br /&gt;
                          // Debug console TX signal connected on 0&lt;br /&gt;
                          // Debug console RX signal connected on 1&lt;br /&gt;
                          // I2C Eeprom : SDA connected on A4&lt;br /&gt;
                          // I2C Eeprom : SCK connected on A5&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
  byte mac[] = { 0x90, 0xA2, 0xda, 0x00, 0xe6, 0x5e }; // Arduino Ethernet board MAC address&lt;br /&gt;
  &lt;br /&gt;
  IPAddress ip(192,168,1,178);     // Default static IP if no DHCP &lt;br /&gt;
  EthernetServer HttpServer(80);   // HTTP is used to send IR commands&lt;br /&gt;
  EthernetServer TelnetServer(23); // Telnet is used for Serial Console&lt;br /&gt;
  &lt;br /&gt;
  #define SAMSUNGREMOTE            // if defined, Arduino will be seen as a Samsung device&lt;br /&gt;
  #ifdef SAMSUNGREMOTE&lt;br /&gt;
  EthernetServer SamsungRemote(55000); // Emulates a Samsung device&lt;br /&gt;
  EthernetUDP SamsungSSDP;  // Handles Samsung device discovery&lt;br /&gt;
  #endif&lt;br /&gt;
  &lt;br /&gt;
  // ---------------------------------------------------------------------&lt;br /&gt;
  // Utilities&lt;br /&gt;
  // ---------------------------------------------------------------------&lt;br /&gt;
  &lt;br /&gt;
  // Convert a hex string to unsigned int&lt;br /&gt;
  unsigned int HexToULong(char *s)&lt;br /&gt;
  {&lt;br /&gt;
    unsigned long u=0;&lt;br /&gt;
    while (*s)&lt;br /&gt;
    {&lt;br /&gt;
      char c=*s++;&lt;br /&gt;
      // Convert to uppercase&lt;br /&gt;
      if (c&amp;gt;='a') c&amp;amp;=0xdf;&lt;br /&gt;
      // Exit if not hex digit&lt;br /&gt;
      if ((c&amp;lt;'0' || c&amp;gt;'9') &amp;amp;&amp;amp; (c&amp;lt;'A' || c&amp;gt;'F')) break;&lt;br /&gt;
      // Convert digit&lt;br /&gt;
      u&amp;lt;&amp;lt;=4;&lt;br /&gt;
      u|=c-((c&amp;gt;'9') ? 'A'-0xa:'0');&lt;br /&gt;
    }&lt;br /&gt;
    return u;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  #ifdef SAMSUNGREMOTE&lt;br /&gt;
  // Base64 conversion&lt;br /&gt;
  const char *sBase64TranslateTable = &amp;quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+%&amp;quot;;&lt;br /&gt;
  void AsciiToBase64(char *Ascii, char *Buffer, int BufferSize)&lt;br /&gt;
  {&lt;br /&gt;
    int Length=0;&lt;br /&gt;
    while (*Ascii)&lt;br /&gt;
    {&lt;br /&gt;
      unsigned long s32bits=0;&lt;br /&gt;
      int i, j;&lt;br /&gt;
      // Read 3 ASCII bytes&lt;br /&gt;
      for (i = 2; i &amp;gt;= 0; i--)&lt;br /&gt;
      {&lt;br /&gt;
        if (*Ascii==0) break;&lt;br /&gt;
        s32bits |= ((unsigned long)*Ascii++)&amp;lt;&amp;lt;(8*i);&lt;br /&gt;
      }&lt;br /&gt;
      // Convert them to four 6-bit items &lt;br /&gt;
      for (j=3; j&amp;gt;=i+1; j--)&lt;br /&gt;
      {&lt;br /&gt;
        // Check for buffer overflow&lt;br /&gt;
        if (++Length&amp;gt;=BufferSize) { *Buffer=0; return; }&lt;br /&gt;
        // Convert 6-bit item&lt;br /&gt;
        int c = ((s32bits &amp;gt;&amp;gt; (6 * j)) &amp;amp; 0x3f);&lt;br /&gt;
        *Buffer++ = sBase64TranslateTable[c];&lt;br /&gt;
      }&lt;br /&gt;
      // Complete last bytes&lt;br /&gt;
      for (/*void*/; j&amp;gt;=0 &amp;amp;&amp;amp; ++Length&amp;lt;BufferSize; j--) *Buffer++='=';&lt;br /&gt;
    }&lt;br /&gt;
    *Buffer=0; // Trailing 0 is not needed for this project, but simplify testing&lt;br /&gt;
  }&lt;br /&gt;
  void Base64ToAscii(char *Base64, char *Buffer, int BufferSize)&lt;br /&gt;
  {&lt;br /&gt;
    int Length=0;&lt;br /&gt;
    while (*Base64 &amp;amp;&amp;amp; *Base64!='=')&lt;br /&gt;
    {&lt;br /&gt;
      unsigned long s24bits = 0;&lt;br /&gt;
      // Read four 6-bit items&lt;br /&gt;
      for (int i=3; i&amp;gt;=0; i--)&lt;br /&gt;
      {&lt;br /&gt;
        if (*Base64==0 || *Base64=='=') break;&lt;br /&gt;
        char *p=strchr(sBase64TranslateTable, *Base64++);&lt;br /&gt;
        if (p) s24bits |= ((unsigned long)(p-sBase64TranslateTable))&amp;lt;&amp;lt;(6*i);&lt;br /&gt;
      }&lt;br /&gt;
      // Convert them to three 8-bit items &lt;br /&gt;
      for (int i=2; i&amp;gt;=0; i--) &lt;br /&gt;
      {&lt;br /&gt;
        // Check for buffer overflow&lt;br /&gt;
        if (++Length&amp;gt;=BufferSize) break;&lt;br /&gt;
        // Save byte&lt;br /&gt;
        *Buffer++ = (char)((s24bits&amp;gt;&amp;gt;(8*i))&amp;amp;0xff);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    *Buffer=0;&lt;br /&gt;
  }&lt;br /&gt;
  unsigned DecodeSamsungProtocolString(char *s, char *Buffer, int BufferSize, boolean bBase64)&lt;br /&gt;
  {&lt;br /&gt;
    // Get length of string in message&lt;br /&gt;
    unsigned Length=s[0] | (((unsigned)s[1])&amp;lt;&amp;lt;8);&lt;br /&gt;
    // Get the string&lt;br /&gt;
    if (bBase64)&lt;br /&gt;
    {&lt;br /&gt;
      // Force trailing 0 into Base64 string &lt;br /&gt;
      // (dirty but will work in this project, as the Base64 string is in a frame buffer...)&lt;br /&gt;
      char c=s[Length+2]; s[Length+2]=0;&lt;br /&gt;
      Base64ToAscii(s+2, Buffer, BufferSize);&lt;br /&gt;
      // Restore corrupted char&lt;br /&gt;
      s[Length+2]=c;&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
      // Check for buffer overflow&lt;br /&gt;
      unsigned MaxLength=(Length&amp;gt;BufferSize-1) ? BufferSize-1:Length;&lt;br /&gt;
      // Just copy string&lt;br /&gt;
      strncpy(Buffer, s+2, MaxLength);&lt;br /&gt;
      Buffer[MaxLength]=0;&lt;br /&gt;
    }&lt;br /&gt;
    // Returns length of initial buffer &lt;br /&gt;
    return Length+2;&lt;br /&gt;
  }&lt;br /&gt;
  unsigned EncodeSamsungProtocolString(char *s, char *Buffer, int BufferSize, boolean bBase64)&lt;br /&gt;
  {&lt;br /&gt;
    unsigned Length;&lt;br /&gt;
    if (bBase64) &lt;br /&gt;
    {&lt;br /&gt;
      // Encode string in Base64&lt;br /&gt;
      AsciiToBase64(s, Buffer+2, BufferSize-2); &lt;br /&gt;
      Length=strlen(Buffer+2);&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
      // Leave string in Ascii - No trailing 0&lt;br /&gt;
      Length=strlen(s);&lt;br /&gt;
      if (Length&amp;gt;BufferSize-2) Length=BufferSize-2;&lt;br /&gt;
      strncpy(Buffer+2, s, Length);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Add size of string in message&lt;br /&gt;
    Buffer[0]=Length; Buffer[1]=Length&amp;gt;&amp;gt;8;&lt;br /&gt;
    return Length+2; &lt;br /&gt;
  }&lt;br /&gt;
  #endif&lt;br /&gt;
  &lt;br /&gt;
  // ---------------------------------------------------------------------&lt;br /&gt;
  // Samsung IR class&lt;br /&gt;
  // ---------------------------------------------------------------------&lt;br /&gt;
  &lt;br /&gt;
  class Samsung&lt;br /&gt;
  {&lt;br /&gt;
    private:&lt;br /&gt;
    // Send a 36kHz-modulated pulse&lt;br /&gt;
    static void Pulse(void)&lt;br /&gt;
    {&lt;br /&gt;
      byte i;&lt;br /&gt;
      for (i=0; i&amp;lt;21; i++)&lt;br /&gt;
      {&lt;br /&gt;
        digitalWrite(IRPIN, HIGH);&lt;br /&gt;
        delayMicroseconds(10); // Value adjusted with oscilloscope&lt;br /&gt;
        digitalWrite(IRPIN, LOW);&lt;br /&gt;
        delayMicroseconds(10); // Value adjusted with oscilloscope&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    // Send a bit&lt;br /&gt;
    static void SendIRBit(byte b)&lt;br /&gt;
    {&lt;br /&gt;
      Pulse(); &lt;br /&gt;
      if (b) &lt;br /&gt;
        delayMicroseconds(1390);&lt;br /&gt;
      else&lt;br /&gt;
        delayMicroseconds(430);&lt;br /&gt;
    }&lt;br /&gt;
    // Send 4 bits&lt;br /&gt;
    static void SendIRNibble(byte b)&lt;br /&gt;
    {&lt;br /&gt;
      byte i;&lt;br /&gt;
      for (i=0; i&amp;lt;4; i++)&lt;br /&gt;
        SendIRBit((b&amp;gt;&amp;gt;i)&amp;amp;1);&lt;br /&gt;
    }&lt;br /&gt;
    // Send a byte&lt;br /&gt;
    static void SendIRByte(byte b)&lt;br /&gt;
    {&lt;br /&gt;
      byte i;&lt;br /&gt;
      for (i=0; i&amp;lt;8; i++)&lt;br /&gt;
        SendIRBit((b&amp;gt;&amp;gt;i)&amp;amp;1);&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    public:&lt;br /&gt;
    // Send an IR command&lt;br /&gt;
    // Type is 0 for TV, 1 for BD&lt;br /&gt;
    // Device is 0x0707 for TV, 0x301A for BD&lt;br /&gt;
    // Crc should be ~Command, except for tests&lt;br /&gt;
    static void SendCommand(char Type, unsigned int Device, unsigned int Command, unsigned char Crc)&lt;br /&gt;
    {&lt;br /&gt;
      byte i;&lt;br /&gt;
     &lt;br /&gt;
      // Disable interrupts&lt;br /&gt;
      cli();&lt;br /&gt;
    &lt;br /&gt;
      // Start bit&lt;br /&gt;
      for (i=0; i&amp;lt;8; i++)	Pulse();&lt;br /&gt;
      delayMicroseconds(4500);&lt;br /&gt;
  &lt;br /&gt;
      // Send Device Id&lt;br /&gt;
      SendIRByte(Device&amp;gt;&amp;gt;8);&lt;br /&gt;
      SendIRByte(Device&amp;amp;0xff);&lt;br /&gt;
  &lt;br /&gt;
      // BD Player&lt;br /&gt;
      if (Type==1)&lt;br /&gt;
      {&lt;br /&gt;
        // Stop bit&lt;br /&gt;
        Pulse();&lt;br /&gt;
        delayMicroseconds(4500);&lt;br /&gt;
        // Send Data&lt;br /&gt;
        SendIRNibble(Command&amp;gt;&amp;gt;8);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      SendIRByte(Command);&lt;br /&gt;
      SendIRByte(Crc);&lt;br /&gt;
  &lt;br /&gt;
      // Stop bit&lt;br /&gt;
      Pulse();&lt;br /&gt;
      delayMicroseconds(4500);&lt;br /&gt;
    &lt;br /&gt;
      // Re-enable interrupts&lt;br /&gt;
      sei();&lt;br /&gt;
    }&lt;br /&gt;
    // Read Eeprom&lt;br /&gt;
    static void ReadEeprom(byte device, long addr, byte *data, int count)&lt;br /&gt;
    {&lt;br /&gt;
      if (addr!=0xffffffff)&lt;br /&gt;
      {&lt;br /&gt;
        Wire.beginTransmission(device);&lt;br /&gt;
        if (bEeprom2ByteAddress) Wire.write(addr&amp;gt;&amp;gt;8);&lt;br /&gt;
        Wire.write(addr);&lt;br /&gt;
        Wire.endTransmission();&lt;br /&gt;
      }&lt;br /&gt;
      Wire.requestFrom((int)device, count);&lt;br /&gt;
      for (int i=0; i&amp;lt;count; i++)&lt;br /&gt;
      {&lt;br /&gt;
        if (!Wire.available()) break;&lt;br /&gt;
        data[i]=Wire.read();&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    // Write Eeprom&lt;br /&gt;
    static void WriteEeprom(byte device, long addr, byte *data, int count)&lt;br /&gt;
    {&lt;br /&gt;
      Wire.beginTransmission(device);&lt;br /&gt;
      if (bEeprom2ByteAddress) Wire.write(addr&amp;gt;&amp;gt;8);&lt;br /&gt;
      Wire.write(addr);&lt;br /&gt;
      for (int i=0; i&amp;lt;count; i++) Wire.write(data[i]);&lt;br /&gt;
      Wire.endTransmission();&lt;br /&gt;
    }&lt;br /&gt;
    static boolean bEeprom2ByteAddress;&lt;br /&gt;
  };&lt;br /&gt;
  boolean Samsung::bEeprom2ByteAddress=true;&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
  // ---------------------------------------------------------------------&lt;br /&gt;
  // Initialization&lt;br /&gt;
  // ---------------------------------------------------------------------&lt;br /&gt;
  &lt;br /&gt;
  void setup()&lt;br /&gt;
  {&lt;br /&gt;
    // Led&lt;br /&gt;
    pinMode(LEDPIN, OUTPUT);&lt;br /&gt;
    digitalWrite(LEDPIN, HIGH);&lt;br /&gt;
  &lt;br /&gt;
    // IR Led&lt;br /&gt;
    pinMode(IRPIN, OUTPUT);&lt;br /&gt;
    digitalWrite(IRPIN, HIGH);&lt;br /&gt;
  &lt;br /&gt;
    // I2C&lt;br /&gt;
    Wire.begin();&lt;br /&gt;
  &lt;br /&gt;
    // Serial Console&lt;br /&gt;
    Serial.begin(115200);&lt;br /&gt;
  &lt;br /&gt;
    // Initialize Ethernet. Try DHCP, otherwise static IP&lt;br /&gt;
    if (Ethernet.begin(mac)==0)&lt;br /&gt;
      Ethernet.begin(mac, ip);&lt;br /&gt;
    // Initialize HTTP server&lt;br /&gt;
    HttpServer.begin();&lt;br /&gt;
    // Initialize Telnet server&lt;br /&gt;
    TelnetServer.begin();&lt;br /&gt;
    #ifdef SAMSUNGREMOTE&lt;br /&gt;
    // Initialize Samsung Remote server&lt;br /&gt;
    SamsungRemote.begin();&lt;br /&gt;
    // Initialize SSDP&lt;br /&gt;
    SamsungSSDP.begin(1900);&lt;br /&gt;
    #endif&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
  // ---------------------------------------------------------------------&lt;br /&gt;
  // Main Program&lt;br /&gt;
  // ---------------------------------------------------------------------&lt;br /&gt;
  &lt;br /&gt;
  char HttpFrame[256];           // General buffer for Http and Samsung protocol frames&lt;br /&gt;
  char TelnetFrame[256];         // General buffer for Telnet frames&lt;br /&gt;
  char Buffer[32];               // General buffer&lt;br /&gt;
  boolean iStateLed=false;       // Used for led blinking&lt;br /&gt;
  unsigned long timeLastLedMs=0; // Used for blinking delay&lt;br /&gt;
  &lt;br /&gt;
  void loop()&lt;br /&gt;
  {&lt;br /&gt;
    // -------------------------------------------------&lt;br /&gt;
    // LED blinks at 2Hz&lt;br /&gt;
    // -------------------------------------------------&lt;br /&gt;
    if (millis()&amp;gt;timeLastLedMs+250)&lt;br /&gt;
    {&lt;br /&gt;
      timeLastLedMs=millis();&lt;br /&gt;
      digitalWrite(LEDPIN, (iStateLed) ? HIGH:LOW);&lt;br /&gt;
      iStateLed=!iStateLed;&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // -------------------------------------------------&lt;br /&gt;
    // Handle HTTP requests&lt;br /&gt;
    // Example : &lt;br /&gt;
    //   To send KEY_1 on BD :&lt;br /&gt;
    //   http://IP/ir.htm?data=81&amp;amp;type=1&amp;amp;device=301a&lt;br /&gt;
    // -------------------------------------------------&lt;br /&gt;
    EthernetClient client = HttpServer.available();&lt;br /&gt;
    if (client) &lt;br /&gt;
    {&lt;br /&gt;
      char *ptr=HttpFrame;&lt;br /&gt;
      int n=0;&lt;br /&gt;
      while (client.connected() &amp;amp;&amp;amp; client.available())&lt;br /&gt;
      {&lt;br /&gt;
        if (n++&amp;lt;sizeof(HttpFrame))&lt;br /&gt;
          *ptr++=client.read();&lt;br /&gt;
        else&lt;br /&gt;
          client.flush(); &lt;br /&gt;
      }&lt;br /&gt;
      *ptr=0;&lt;br /&gt;
      if (n&amp;gt;0)&lt;br /&gt;
      {&lt;br /&gt;
        const __FlashStringHelper *HtmlHeader=F(&amp;quot;HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
        // -------------------------------------------------&lt;br /&gt;
        // Send Samsung IR command&lt;br /&gt;
        // -------------------------------------------------&lt;br /&gt;
        ptr=strstr(HttpFrame, &amp;quot;/ir.htm?&amp;quot;);&lt;br /&gt;
        if (ptr)&lt;br /&gt;
        {&lt;br /&gt;
          byte Type=0, Crc;&lt;br /&gt;
          unsigned int Device=0x0707, Data=0;&lt;br /&gt;
  &lt;br /&gt;
          ptr=strstr(HttpFrame, &amp;quot;data=&amp;quot;);&lt;br /&gt;
          if (ptr) Data=HexToULong(ptr+5);&lt;br /&gt;
          ptr=strstr(HttpFrame, &amp;quot;type=&amp;quot;);&lt;br /&gt;
          if (ptr) Type=HexToULong(ptr+5);&lt;br /&gt;
          ptr=strstr(HttpFrame, &amp;quot;device=&amp;quot;);&lt;br /&gt;
          if (ptr) Device=HexToULong(ptr+7);&lt;br /&gt;
          &lt;br /&gt;
          // Next parameter is optional and can be used for tests&lt;br /&gt;
          Crc=~Data;&lt;br /&gt;
          ptr=strstr(HttpFrame, &amp;quot;crc=&amp;quot;);&lt;br /&gt;
          if (ptr) Crc=HexToULong(ptr+4);&lt;br /&gt;
  &lt;br /&gt;
          Samsung::SendCommand(Type, Device, Data, Crc);&lt;br /&gt;
          client.println(HtmlHeader);&lt;br /&gt;
          client.println(&amp;quot;OK !&amp;quot;);&lt;br /&gt;
          client.stop();&lt;br /&gt;
          return;&lt;br /&gt;
        }&lt;br /&gt;
  &lt;br /&gt;
        // -------------------------------------------------&lt;br /&gt;
        // Read Eeprom&lt;br /&gt;
        // -------------------------------------------------&lt;br /&gt;
        ptr=strstr(HttpFrame, &amp;quot;/read&amp;quot;);&lt;br /&gt;
        if (ptr)&lt;br /&gt;
        {&lt;br /&gt;
          byte Device=80, Format=0x50; // hedak: changed eeprom device id to 80 to comply with description above&lt;br /&gt;
          unsigned long Size=0x100, Addr=0;&lt;br /&gt;
  &lt;br /&gt;
          ptr=strstr(HttpFrame, &amp;quot;addr=&amp;quot;);&lt;br /&gt;
          if (ptr) Addr=HexToULong(ptr+5);&lt;br /&gt;
          ptr=strstr(HttpFrame, &amp;quot;size=&amp;quot;);&lt;br /&gt;
          if (ptr) Size=atol(ptr+5);&lt;br /&gt;
          ptr=strstr(HttpFrame, &amp;quot;device=&amp;quot;);&lt;br /&gt;
          if (ptr) Device=atoi(ptr+7);&lt;br /&gt;
          ptr=strstr(HttpFrame, &amp;quot;format=&amp;quot;);&lt;br /&gt;
          if (ptr) Format=atoi(ptr+7);&lt;br /&gt;
          ptr=strstr(HttpFrame, &amp;quot;width=8&amp;quot;);&lt;br /&gt;
          Samsung::bEeprom2ByteAddress=(ptr==0);&lt;br /&gt;
  &lt;br /&gt;
          if (Format==0) &lt;br /&gt;
          {&lt;br /&gt;
            client.println(&amp;quot;HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n&amp;quot;);&lt;br /&gt;
          }&lt;br /&gt;
          else&lt;br /&gt;
            client.println(&amp;quot;HTTP/1.1 200 OK\r\nContent-Type: binary/octet-stream\r\n&amp;quot;);&lt;br /&gt;
  &lt;br /&gt;
          byte bSequential=0;    &lt;br /&gt;
          for (long i=Addr; i&amp;lt;Addr+Size; i+=32)&lt;br /&gt;
          {&lt;br /&gt;
            unsigned char Data[32]; &lt;br /&gt;
            for (int i=0; i&amp;lt;32; i++) Data[i]=0xff;&lt;br /&gt;
            Samsung::ReadEeprom(Device, (bSequential) ? -1:i, Data, 32);&lt;br /&gt;
            bSequential=1;&lt;br /&gt;
  &lt;br /&gt;
            if (Format==0)&lt;br /&gt;
            {          &lt;br /&gt;
              sprintf(Buffer, &amp;quot;%04lx: &amp;quot;, i); client.print(Buffer);&lt;br /&gt;
              for (int j=0; j&amp;lt;32; j++)&lt;br /&gt;
                { sprintf(Buffer, &amp;quot;%02X &amp;quot;, Data[j]); client.print(Buffer); }&lt;br /&gt;
              for (int j=0; j&amp;lt;32; j++)&lt;br /&gt;
                { client.write((Data[j]&amp;lt;=0x20 || Data[j]&amp;gt;0x7f) ? '.':Data[j]); }&lt;br /&gt;
              client.println(&amp;quot;&amp;quot;);&lt;br /&gt;
              client.flush();&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
              for (int j=0; j&amp;lt;32; j++)&lt;br /&gt;
                client.write(Data[j]);&lt;br /&gt;
            }&lt;br /&gt;
          }&lt;br /&gt;
  &lt;br /&gt;
          client.stop();&lt;br /&gt;
          return;&lt;br /&gt;
        }&lt;br /&gt;
  &lt;br /&gt;
        // -------------------------------------------------&lt;br /&gt;
        // Write Eeprom&lt;br /&gt;
        // -------------------------------------------------&lt;br /&gt;
        ptr=strstr(HttpFrame, &amp;quot;/write&amp;quot;);&lt;br /&gt;
        char *ptrAddr=strstr(HttpFrame, &amp;quot;addr=&amp;quot;);&lt;br /&gt;
        char *ptrData=strstr(HttpFrame, &amp;quot;data=&amp;quot;);&lt;br /&gt;
        if (ptr &amp;amp;&amp;amp; ptrAddr &amp;amp;&amp;amp; ptrData)&lt;br /&gt;
        {&lt;br /&gt;
          byte Device=80, Data; // hedak: changed eeprom device id to 80 to comply with description above&lt;br /&gt;
          unsigned long Addr;&lt;br /&gt;
          &lt;br /&gt;
          Addr=HexToULong(ptrAddr+5);&lt;br /&gt;
          Data=HexToULong(ptrData+5);&lt;br /&gt;
          ptr=strstr(HttpFrame, &amp;quot;device=&amp;quot;);&lt;br /&gt;
          if (ptr) Device=atoi(ptr+7);&lt;br /&gt;
          ptr=strstr(HttpFrame, &amp;quot;width=8&amp;quot;);&lt;br /&gt;
          Samsung::bEeprom2ByteAddress=(ptr==0);&lt;br /&gt;
  &lt;br /&gt;
          Samsung::WriteEeprom(Device, Addr, &amp;amp;Data, 1);&lt;br /&gt;
          client.println(&amp;quot;HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n&amp;quot;);&lt;br /&gt;
          Data=~Data;&lt;br /&gt;
          Samsung::ReadEeprom(Device, Addr, &amp;amp;Data, 1);    &lt;br /&gt;
          sprintf(Buffer, &amp;quot;%02X &amp;quot;, Data); &lt;br /&gt;
          client.print(Buffer);&lt;br /&gt;
  &lt;br /&gt;
          client.stop();&lt;br /&gt;
          return;&lt;br /&gt;
        }&lt;br /&gt;
  &lt;br /&gt;
        #ifdef SAMSUNGREMOTE&lt;br /&gt;
        // -------------------------------------------------&lt;br /&gt;
        // Device info - used for Samsung Remote Protocol&lt;br /&gt;
        // -------------------------------------------------&lt;br /&gt;
        ptr=strstr(HttpFrame, &amp;quot;/smp_2_&amp;quot;);&lt;br /&gt;
        if (ptr)&lt;br /&gt;
        {&lt;br /&gt;
          client.println(F(&amp;quot;HTTP/1.1 200 OK\r\nContent-Type: text/xml\r\n&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;&amp;lt;?xml version=\&amp;quot;1.0\&amp;quot;?&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;&amp;lt;root xmlns='urn:schemas-upnp-org:device-1-0' xmlns:sec='http://www.sec.co.kr/dlna' xmlns:dlna='urn:schemas-dlna-org:device-1-0'&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot; &amp;lt;specVersion&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;major&amp;gt;1&amp;lt;/major&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;minor&amp;gt;0&amp;lt;/minor&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot; &amp;lt;/specVersion&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot; &amp;lt;device&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;deviceType&amp;gt;urn:samsung.com:device:RemoteControlReceiver:1&amp;lt;/deviceType&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;friendlyName&amp;gt;SamyGO&amp;lt;/friendlyName&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;manufacturer&amp;gt;Samsung Electronics&amp;lt;/manufacturer&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;manufacturerURL&amp;gt;http://www.samsung.com/sec&amp;lt;/manufacturerURL&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;modelDescription&amp;gt;Samsung BD RCR&amp;lt;/modelDescription&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;modelName&amp;gt;BD-E8500&amp;lt;/modelName&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;modelNumber&amp;gt;1.0&amp;lt;/modelNumber&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;modelURL&amp;gt;http://www.samsung.com/sec&amp;lt;/modelURL&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;serialNumber&amp;gt;12345678RCR&amp;lt;/serialNumber&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;UDN&amp;gt;uuid:11111111-2222-3333-4444-555555555555&amp;lt;/UDN&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;sec:deviceID&amp;gt;ABCDEFGHIJKLM&amp;lt;/sec:deviceID&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;sec:ProductCap&amp;gt;Resolution:1280X720,ImageZoom,ImageRotate,Y2012&amp;lt;/sec:ProductCap&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;serviceList&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;   &amp;lt;service&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;    &amp;lt;serviceType&amp;gt;urn:samsung.com:service:TestRCRService:1&amp;lt;/serviceType&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;    &amp;lt;serviceId&amp;gt;urn:samsung.com:serviceId:TestRCRService&amp;lt;/serviceId&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;    &amp;lt;controlURL&amp;gt;/smp_4_&amp;lt;/controlURL&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;    &amp;lt;eventSubURL&amp;gt;/smp_5_&amp;lt;/eventSubURL&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;    &amp;lt;SCPDURL&amp;gt;/smp_3_&amp;lt;/SCPDURL&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;   &amp;lt;/service&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;  &amp;lt;/serviceList&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot; &amp;lt;/device&amp;gt;&amp;quot;));&lt;br /&gt;
          client.println(F(&amp;quot;&amp;lt;/root&amp;gt;&amp;quot;));&lt;br /&gt;
          client.stop();&lt;br /&gt;
          return;&lt;br /&gt;
        }&lt;br /&gt;
        #endif&lt;br /&gt;
  &lt;br /&gt;
        // send an error !&lt;br /&gt;
        client.println(HtmlHeader);&lt;br /&gt;
        client.println(F(&amp;quot;Error !&amp;quot;));&lt;br /&gt;
        delay(1);&lt;br /&gt;
      }&lt;br /&gt;
      client.stop();&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    #ifdef SAMSUNGREMOTE&lt;br /&gt;
    // -------------------------------------------------&lt;br /&gt;
    // Samsung Remote Protocol&lt;br /&gt;
    // -------------------------------------------------&lt;br /&gt;
    client = SamsungRemote.available();&lt;br /&gt;
    if (client) &lt;br /&gt;
    {&lt;br /&gt;
      //Serial.println(&amp;quot;Incoming frame...&amp;quot;);&lt;br /&gt;
      &lt;br /&gt;
      // Read incoming frame&lt;br /&gt;
      char *ptr=HttpFrame;&lt;br /&gt;
      int n=0;&lt;br /&gt;
      while (client.connected() &amp;amp;&amp;amp; client.available())&lt;br /&gt;
        if (n++&amp;lt;sizeof(HttpFrame)) *ptr++=client.read();&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
      ptr=HttpFrame+1;&lt;br /&gt;
      // Decode App Name&lt;br /&gt;
      ptr+=DecodeSamsungProtocolString(ptr, Buffer, sizeof(Buffer), false);&lt;br /&gt;
      //Serial.print(&amp;quot;Name=&amp;quot;); Serial.println(Buffer);&lt;br /&gt;
  &lt;br /&gt;
      // Ignore message length&lt;br /&gt;
      ptr+=2;&lt;br /&gt;
  &lt;br /&gt;
      // Decode command&lt;br /&gt;
      unsigned Cmd=*ptr++; Cmd|=(*ptr++)&amp;lt;&amp;lt;8;&lt;br /&gt;
      //Serial.print(&amp;quot;Cmd=&amp;quot;); Serial.println(Cmd);&lt;br /&gt;
  &lt;br /&gt;
      // Connection frame ?&lt;br /&gt;
      if (Cmd==0x64)&lt;br /&gt;
      {&lt;br /&gt;
        // Decode remote IP&lt;br /&gt;
        ptr+=DecodeSamsungProtocolString(ptr, Buffer, sizeof(Buffer), true);&lt;br /&gt;
        //Serial.print(&amp;quot;IP=&amp;quot;); Serial.println(Buffer);&lt;br /&gt;
  &lt;br /&gt;
        // Decode remote MAC address&lt;br /&gt;
        ptr+=DecodeSamsungProtocolString(ptr, Buffer, sizeof(Buffer), true);&lt;br /&gt;
        //Serial.print(&amp;quot;MAC=&amp;quot;); Serial.println(Buffer);&lt;br /&gt;
  &lt;br /&gt;
        // Decode machine name&lt;br /&gt;
        ptr+=DecodeSamsungProtocolString(ptr, Buffer, sizeof(Buffer), true);&lt;br /&gt;
        //Serial.print(&amp;quot;Machine=&amp;quot;); Serial.println(Buffer);&lt;br /&gt;
        delay(5);&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      // Key frame ?&lt;br /&gt;
      else if (Cmd==0x00)&lt;br /&gt;
      {&lt;br /&gt;
        ptr++; // Skip first byte&lt;br /&gt;
        ptr+=DecodeSamsungProtocolString(ptr, Buffer, sizeof(Buffer), true);&lt;br /&gt;
        //Serial.print(&amp;quot;KeyName=&amp;quot;); Serial.print(Buffer); Serial.println(&amp;quot;----&amp;quot;);&lt;br /&gt;
        if (!strcmp(Buffer, &amp;quot;BD_KEY_POWER&amp;quot;))&lt;br /&gt;
        {&lt;br /&gt;
          // Power key for BD&lt;br /&gt;
          Samsung::SendCommand(1, 0x301a, 0x91, ~0x91);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
  &lt;br /&gt;
      // Answer&lt;br /&gt;
      HttpFrame[0]=0;&lt;br /&gt;
      int len=1;&lt;br /&gt;
      len+=EncodeSamsungProtocolString(&amp;quot;iapp.samsung&amp;quot;, HttpFrame+1, sizeof(HttpFrame), false);&lt;br /&gt;
      if (Cmd==0x64)&lt;br /&gt;
      {&lt;br /&gt;
        byte answer[]={0x04,0x00,0x64,0x00,0x01,0x00};&lt;br /&gt;
        memcpy(HttpFrame+len, answer, sizeof(answer));&lt;br /&gt;
        len+=sizeof(answer);&lt;br /&gt;
      }&lt;br /&gt;
      else&lt;br /&gt;
      {&lt;br /&gt;
        byte answer[]={0x04,0x00,0x00,0x00,0x00,0x00};&lt;br /&gt;
        memcpy(HttpFrame+len, answer, sizeof(answer));&lt;br /&gt;
        len+=sizeof(answer);&lt;br /&gt;
      }&lt;br /&gt;
      client.write((byte *)HttpFrame, len);&lt;br /&gt;
      delay(5);&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    // SSDP discovery protocol&lt;br /&gt;
    int PacketSize=SamsungSSDP.parsePacket();&lt;br /&gt;
    if (PacketSize)&lt;br /&gt;
    {&lt;br /&gt;
      // Read incoming frame&lt;br /&gt;
      char *ptr=HttpFrame;&lt;br /&gt;
      int n=0;&lt;br /&gt;
      while (SamsungSSDP.available())&lt;br /&gt;
        if (n++&amp;lt;sizeof(HttpFrame)) *ptr++=SamsungSSDP.read();&lt;br /&gt;
  &lt;br /&gt;
      // Discovery request ?&lt;br /&gt;
      if (strstr(HttpFrame, &amp;quot;M-SEARCH *&amp;quot;) &amp;amp;&amp;amp; strstr(HttpFrame, &amp;quot;urn:samsung.com:device:RemoteControlReceiver:1&amp;quot;))&lt;br /&gt;
      {&lt;br /&gt;
        //Serial.print(&amp;quot;SSDP Discovery from : IP=&amp;quot;); Serial.print(SamsungSSDP.remoteIP()); Serial.print(&amp;quot;:&amp;quot;); Serial.println(SamsungSSDP.remotePort());&lt;br /&gt;
        SamsungSSDP.beginPacket(SamsungSSDP.remoteIP(), SamsungSSDP.remotePort());&lt;br /&gt;
        SamsungSSDP.println(F(&amp;quot;HTTP/1.1 200 OK&amp;quot;));&lt;br /&gt;
        SamsungSSDP.println(F(&amp;quot;CACHE-CONTROL: max-age= 1800&amp;quot;));&lt;br /&gt;
        SamsungSSDP.println(F(&amp;quot;Date: Sat, 01 Jan 2012 00:00:00 GMT&amp;quot;));&lt;br /&gt;
        SamsungSSDP.println(F(&amp;quot;EXT: &amp;quot;));&lt;br /&gt;
        SamsungSSDP.print(F(&amp;quot;LOCATION: http://&amp;quot;)); SamsungSSDP.print(Ethernet.localIP()); SamsungSSDP.println(F(&amp;quot;:80/smp_2_&amp;quot;));&lt;br /&gt;
        SamsungSSDP.println(F(&amp;quot;SERVER: SHP, UPnP/1.0, Samsung UPnP SDK/1.0&amp;quot;));&lt;br /&gt;
        SamsungSSDP.println(F(&amp;quot;ST: urn:samsung.com:device:RemoteControlReceiver:1&amp;quot;));&lt;br /&gt;
        SamsungSSDP.println(F(&amp;quot;USN: uuid:11111111-2222-3333-4444-555555555555::urn:samsung.com:device:RemoteControlReceiver:1&amp;quot;));&lt;br /&gt;
        SamsungSSDP.println(F(&amp;quot;Content-Length: 0&amp;quot;));&lt;br /&gt;
        SamsungSSDP.endPacket();&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    #endif&lt;br /&gt;
  &lt;br /&gt;
    // -------------------------------------------------&lt;br /&gt;
    // Telnet Serial Console Interface&lt;br /&gt;
    // Configure Putty with :&lt;br /&gt;
    //   - &amp;quot;Local Echo : Force off&amp;quot;&lt;br /&gt;
    //   - &amp;quot;Local line editing : Force off&amp;quot;&lt;br /&gt;
    // -------------------------------------------------&lt;br /&gt;
    client = TelnetServer.available();&lt;br /&gt;
    if (client) &lt;br /&gt;
    {&lt;br /&gt;
      char *ptr=TelnetFrame;&lt;br /&gt;
      int n=0;&lt;br /&gt;
      while (client.connected() &amp;amp;&amp;amp; client.available())&lt;br /&gt;
        if (n++&amp;lt;sizeof(TelnetFrame)) *ptr++=client.read();&lt;br /&gt;
      *ptr=0;&lt;br /&gt;
      &lt;br /&gt;
      // Sends telnet buffer to Serial Console&lt;br /&gt;
      if (n&amp;gt;0) Serial.write(TelnetFrame);&lt;br /&gt;
    }&lt;br /&gt;
    // Anything received from Serial Console ?&lt;br /&gt;
    char *ptr=TelnetFrame;&lt;br /&gt;
    int n=0;&lt;br /&gt;
    while (Serial.available())&lt;br /&gt;
      if (n++&amp;lt;sizeof(TelnetFrame)) *ptr++=Serial.read();&lt;br /&gt;
    *ptr=0;&lt;br /&gt;
      // Send it to telnet&lt;br /&gt;
    if (n&amp;gt;0) TelnetServer.write(TelnetFrame);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  // ---------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
== Teensy(++ 2.0) sketch for accessing I2C interface ==&lt;br /&gt;
&lt;br /&gt;
This sketch has been compiled with Arduino 1.0.5.&lt;br /&gt;
It's a limited version compared to the arduino sketch above. Only the I2C interface to read/write tv's eeprom is implemented and instead of the ethernet interface there's a usb interface (Hint: sketch becomes active only if DTR on pc side is set). Usage of the I2C feature is the same anyway.&lt;br /&gt;
&lt;br /&gt;
 // ---------------------------------------------------------------------&lt;br /&gt;
 // Samsung I2C interface based on oga83's 'Samsung multi-functions ethernet interface' v1.2&lt;br /&gt;
 //   - Read &amp;amp; Write I2C config eeprom&lt;br /&gt;
 //&lt;br /&gt;
 // 07-03-2014 / v1.1 / hedak&lt;br /&gt;
 //----------------------------------------------------------------------&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;Wire.h&amp;gt;&lt;br /&gt;
 #include &amp;quot;utility\twi.h&amp;quot; //hedak: for outputting I2C frequency&lt;br /&gt;
 &lt;br /&gt;
 #define CPU_PRESCALE(n)	(CLKPR = 0x80, CLKPR = (n))&lt;br /&gt;
&lt;br /&gt;
 #define LEDPIN     CORE_LED0_PIN    // Onboard led - blink at 2 Hz&lt;br /&gt;
                         // I2C Eeprom : SDA connected on D1&lt;br /&gt;
                         // I2C Eeprom : SCL connected on D0&lt;br /&gt;
 &lt;br /&gt;
 // ---------------------------------------------------------------------&lt;br /&gt;
 // Utilities&lt;br /&gt;
 // ---------------------------------------------------------------------&lt;br /&gt;
 &lt;br /&gt;
 // Convert a hex string to unsigned int&lt;br /&gt;
 unsigned long HexToULong(char *s)&lt;br /&gt;
 {&lt;br /&gt;
   unsigned long u=0;&lt;br /&gt;
   while (*s)&lt;br /&gt;
   {&lt;br /&gt;
     char c=*s++;&lt;br /&gt;
     // Convert to uppercase&lt;br /&gt;
     if (c&amp;gt;='a') c&amp;amp;=0xdf;&lt;br /&gt;
     // Exit if not hex digit&lt;br /&gt;
     if ((c&amp;lt;'0' || c&amp;gt;'9') &amp;amp;&amp;amp; (c&amp;lt;'A' || c&amp;gt;'F')) break;&lt;br /&gt;
     // Convert digit&lt;br /&gt;
     u&amp;lt;&amp;lt;=4;&lt;br /&gt;
     u|=c-((c&amp;gt;'9') ? 'A'-0xa:'0');&lt;br /&gt;
   }&lt;br /&gt;
   return u;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 // ---------------------------------------------------------------------&lt;br /&gt;
 // Samsung class&lt;br /&gt;
 // ---------------------------------------------------------------------&lt;br /&gt;
 &lt;br /&gt;
 class Samsung&lt;br /&gt;
 {&lt;br /&gt;
   public:&lt;br /&gt;
   // Read Eeprom&lt;br /&gt;
   static void ReadEeprom(byte device, long addr, byte *data, int count)&lt;br /&gt;
   {&lt;br /&gt;
     if (addr!=0xffffffff)&lt;br /&gt;
     {&lt;br /&gt;
       Wire.beginTransmission(device);&lt;br /&gt;
       if (bEeprom2ByteAddress) Wire.write(addr&amp;gt;&amp;gt;8);&lt;br /&gt;
       Wire.write(addr);&lt;br /&gt;
       Wire.endTransmission();&lt;br /&gt;
     }&lt;br /&gt;
     Wire.requestFrom((int)device, count);&lt;br /&gt;
     for (int i=0; i&amp;lt;count; i++)&lt;br /&gt;
     {&lt;br /&gt;
       if (!Wire.available()) break;&lt;br /&gt;
       data[i]=Wire.read();&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   // Write Eeprom&lt;br /&gt;
   static void WriteEeprom(byte device, long addr, byte *data, int count)&lt;br /&gt;
   {&lt;br /&gt;
     Wire.beginTransmission(device);&lt;br /&gt;
     if (bEeprom2ByteAddress) Wire.write(addr&amp;gt;&amp;gt;8);&lt;br /&gt;
     Wire.write(addr);&lt;br /&gt;
     for (int i=0; i&amp;lt;count; i++) Wire.write(data[i]);&lt;br /&gt;
     Wire.endTransmission();&lt;br /&gt;
   }&lt;br /&gt;
   static boolean bEeprom2ByteAddress;&lt;br /&gt;
 };&lt;br /&gt;
 boolean Samsung::bEeprom2ByteAddress=true; &lt;br /&gt;
 &lt;br /&gt;
 // ---------------------------------------------------------------------&lt;br /&gt;
 // Main Program&lt;br /&gt;
 // ---------------------------------------------------------------------&lt;br /&gt;
 &lt;br /&gt;
 char HttpFrame[256];           // General buffer for Http and Samsung protocol frames&lt;br /&gt;
 char Buffer[32];               // General buffer&lt;br /&gt;
 boolean iStateLed=false;       // Used for led blinking&lt;br /&gt;
 unsigned long timeLastLedMs=0; // Used for blinking delay&lt;br /&gt;
 &lt;br /&gt;
 void loop()&lt;br /&gt;
 {&lt;br /&gt;
   // -------------------------------------------------&lt;br /&gt;
   // LED blinks at 2Hz&lt;br /&gt;
   // -------------------------------------------------&lt;br /&gt;
   if (millis()&amp;gt;timeLastLedMs+250)&lt;br /&gt;
   {&lt;br /&gt;
     timeLastLedMs=millis();&lt;br /&gt;
     digitalWrite(LEDPIN, (iStateLed) ? HIGH:LOW);&lt;br /&gt;
     iStateLed=!iStateLed;&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   // -------------------------------------------------&lt;br /&gt;
   // Handle HTTP requests&lt;br /&gt;
   // Example : &lt;br /&gt;
   //   To read a whole EEPROM dump :&lt;br /&gt;
   //   http://IP/read?format=1&amp;amp;device=80&amp;amp;size=65536&lt;br /&gt;
   // -------------------------------------------------&lt;br /&gt;
     char *ptr=HttpFrame;&lt;br /&gt;
     int n=0;&lt;br /&gt;
     while (Serial.available())&lt;br /&gt;
     {&lt;br /&gt;
       if (n++&amp;lt;sizeof(HttpFrame))&lt;br /&gt;
         *ptr++=Serial.read();&lt;br /&gt;
       else&lt;br /&gt;
         Serial.flush(); &lt;br /&gt;
     }&lt;br /&gt;
     *ptr=0;&lt;br /&gt;
     Serial.write(HttpFrame);&lt;br /&gt;
     if (n&amp;gt;0)&lt;br /&gt;
     {&lt;br /&gt;
       // -------------------------------------------------&lt;br /&gt;
       // Read Eeprom&lt;br /&gt;
       // -------------------------------------------------&lt;br /&gt;
       ptr=strstr(HttpFrame, &amp;quot;/read&amp;quot;);&lt;br /&gt;
       if (ptr)&lt;br /&gt;
       {&lt;br /&gt;
         byte Device=80, Format=0x50; // hedak: fixed wrong default value for 'Device'&lt;br /&gt;
         unsigned long Size=0x100, Addr=0;&lt;br /&gt;
 &lt;br /&gt;
         ptr=strstr(HttpFrame, &amp;quot;addr=&amp;quot;);&lt;br /&gt;
         if (ptr) Addr=HexToULong(ptr+5);&lt;br /&gt;
         ptr=strstr(HttpFrame, &amp;quot;size=&amp;quot;);&lt;br /&gt;
         if (ptr) Size=atol(ptr+5);&lt;br /&gt;
         ptr=strstr(HttpFrame, &amp;quot;device=&amp;quot;);&lt;br /&gt;
         if (ptr) Device=atoi(ptr+7);&lt;br /&gt;
         ptr=strstr(HttpFrame, &amp;quot;format=&amp;quot;);&lt;br /&gt;
         if (ptr) Format=atoi(ptr+7);&lt;br /&gt;
         ptr=strstr(HttpFrame, &amp;quot;width=8&amp;quot;);&lt;br /&gt;
         Samsung::bEeprom2ByteAddress=(ptr==0);&lt;br /&gt;
 &lt;br /&gt;
         sprintf(Buffer, &amp;quot;Start reading @ address: %lX\r\n&amp;quot;, Addr);&lt;br /&gt;
         Serial.write(Buffer);&lt;br /&gt;
         &lt;br /&gt;
         if (Format==0) &lt;br /&gt;
         {&lt;br /&gt;
           Serial.write(&amp;quot;HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n&amp;quot;);&lt;br /&gt;
         }&lt;br /&gt;
         else&lt;br /&gt;
           Serial.write(&amp;quot;HTTP/1.1 200 OK\r\nContent-Type: binary/octet-stream\r\n&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
         byte bSequential=0;    &lt;br /&gt;
         for (long i=Addr; i&amp;lt;Addr+Size; i+=32)&lt;br /&gt;
         {&lt;br /&gt;
           unsigned char Data[32]; &lt;br /&gt;
           for (int i=0; i&amp;lt;32; i++) Data[i]=0xff;&lt;br /&gt;
           Samsung::ReadEeprom(Device, (bSequential) ? -1:i, Data, 32);&lt;br /&gt;
           bSequential=1;&lt;br /&gt;
 &lt;br /&gt;
           if (Format==0)&lt;br /&gt;
           {          &lt;br /&gt;
             sprintf(Buffer, &amp;quot;%04lx: &amp;quot;, i); Serial.write(Buffer);&lt;br /&gt;
             for (int j=0; j&amp;lt;32; j++)&lt;br /&gt;
               { sprintf(Buffer, &amp;quot;%02X &amp;quot;, Data[j]); Serial.write(Buffer); }&lt;br /&gt;
             for (int j=0; j&amp;lt;32; j++)&lt;br /&gt;
               { Serial.write((Data[j]&amp;lt;=0x20 || Data[j]&amp;gt;0x7f) ? '.':Data[j]); }&lt;br /&gt;
             Serial.write(&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
             Serial.flush();&lt;br /&gt;
           }&lt;br /&gt;
           else&lt;br /&gt;
           {&lt;br /&gt;
             for (int j=0; j&amp;lt;32; j++)&lt;br /&gt;
               Serial.write(Data[j]);&lt;br /&gt;
           }&lt;br /&gt;
         }&lt;br /&gt;
         return;&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       // -------------------------------------------------&lt;br /&gt;
       // Write Eeprom&lt;br /&gt;
       // -------------------------------------------------&lt;br /&gt;
       ptr=strstr(HttpFrame, &amp;quot;/write&amp;quot;);&lt;br /&gt;
       Serial.write(&amp;quot;Remove the following 'return;' line to activate write feature!\r\n&amp;quot;);&lt;br /&gt;
       return;&lt;br /&gt;
       char *ptrAddr=strstr(HttpFrame, &amp;quot;addr=&amp;quot;);&lt;br /&gt;
       char *ptrData=strstr(HttpFrame, &amp;quot;data=&amp;quot;);&lt;br /&gt;
       if (ptr &amp;amp;&amp;amp; ptrAddr &amp;amp;&amp;amp; ptrData)&lt;br /&gt;
       {&lt;br /&gt;
         byte Device=0, Data;&lt;br /&gt;
         unsigned long Addr;&lt;br /&gt;
         &lt;br /&gt;
         Addr=HexToULong(ptrAddr+5);&lt;br /&gt;
         Data=HexToULong(ptrData+5);&lt;br /&gt;
         ptr=strstr(HttpFrame, &amp;quot;device=&amp;quot;);&lt;br /&gt;
         if (ptr) Device=atoi(ptr+7);&lt;br /&gt;
         ptr=strstr(HttpFrame, &amp;quot;width=8&amp;quot;);&lt;br /&gt;
         Samsung::bEeprom2ByteAddress=(ptr==0);&lt;br /&gt;
 &lt;br /&gt;
         Samsung::WriteEeprom(Device, Addr, &amp;amp;Data, 1);&lt;br /&gt;
         Serial.write(&amp;quot;HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n&amp;quot;);&lt;br /&gt;
         Data=~Data;&lt;br /&gt;
         Samsung::ReadEeprom(Device, Addr, &amp;amp;Data, 1);    &lt;br /&gt;
         sprintf(Buffer, &amp;quot;%02X &amp;quot;, Data); &lt;br /&gt;
         Serial.write(Buffer);&lt;br /&gt;
         return;&lt;br /&gt;
       }&lt;br /&gt;
       // send an error !&lt;br /&gt;
       Serial.write(&amp;quot;HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n&amp;quot;);&lt;br /&gt;
       Serial.write(&amp;quot;Error !\r\n&amp;quot;);&lt;br /&gt;
       delay(1);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // ---------------------------------------------------------------------&lt;br /&gt;
 // Initialization&lt;br /&gt;
 // ---------------------------------------------------------------------&lt;br /&gt;
 &lt;br /&gt;
 void setup()&lt;br /&gt;
 {&lt;br /&gt;
 #if (F_CPU == 8000000)&lt;br /&gt;
    // set for 8 MHz clock because of operating at 3.3 volts&lt;br /&gt;
    CPU_PRESCALE(0x01);&lt;br /&gt;
 #else&lt;br /&gt;
    // set for external 16 MHz clock&lt;br /&gt;
    CPU_PRESCALE(0x00);&lt;br /&gt;
 #endif&lt;br /&gt;
   // Led&lt;br /&gt;
   pinMode(LEDPIN, OUTPUT);&lt;br /&gt;
   digitalWrite(LEDPIN, HIGH);&lt;br /&gt;
 &lt;br /&gt;
   // I2C&lt;br /&gt;
   Wire.begin();&lt;br /&gt;
 &lt;br /&gt;
   // Serial Console&lt;br /&gt;
   Serial.begin(115200);&lt;br /&gt;
   &lt;br /&gt;
   // wait for the user to run their terminal emulator program&lt;br /&gt;
   // which sets DTR to indicate it is ready to receive.&lt;br /&gt;
   while (!Serial.dtr()) /* wait */ ;&lt;br /&gt;
   sprintf(Buffer, &amp;quot;TWI_FREQ: %ld&amp;quot;, TWI_FREQ);&lt;br /&gt;
   Serial.write(Buffer);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // ---------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
Any discussion on related [http://forum.samygo.tv/viewtopic.php?f=51&amp;amp;t=5307#p38502 forum topic].&lt;br /&gt;
Thread using teensy sketch is [http://forum.samygo.tv/viewtopic.php?f=15&amp;amp;t=7117#p53751 here].&lt;/div&gt;</summary>
		<author><name>Hedak</name></author>
		
	</entry>
	<entry>
		<id>http://wiki.samygo.tv/index.php?title=BEFORE_YOU_START:_Safety_measures_for_C_series_TVs&amp;diff=3908</id>
		<title>BEFORE YOU START: Safety measures for C series TVs</title>
		<link rel="alternate" type="text/html" href="http://wiki.samygo.tv/index.php?title=BEFORE_YOU_START:_Safety_measures_for_C_series_TVs&amp;diff=3908"/>
		<updated>2014-03-05T21:59:34Z</updated>

		<summary type="html">&lt;p&gt;Hedak: Added hint to disable watchdog&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* In service menu, '''enable Debug mode''' for the RS232 port AND '''disable watchdog'''.&lt;br /&gt;
:: With TV switched off, press the following sequence on the remote: '''[INFO] [MENU] [MUTE] [POWER]'''&lt;br /&gt;
:: Enter the '''Control''' menu (then enter '''Sub Option''') and set the value of the '''RS232 mode''' to '''Debug'''. Also set '''Watchdog''' to '''OFF'''.&lt;br /&gt;
:: Once you're back to the main Service menu, you will have to power off the TV for normal operation.&lt;br /&gt;
:: Notice that your TV will reset RS232 mode back to UART when you install another firmware (no matter if it's older or newer).&lt;br /&gt;
* Have a working '''[[Ex-Link Cable for C-Series]]''' at hand.&lt;br /&gt;
:: If you don't feel capable of soldering such a cable, you can find and buy a cheap (under '''$5''') '''[http://shop.ebay.com/i.html?_trkparms=65%253A12%257C66%253A2%257C39%253A1%257C72%253A4030&amp;amp;rt=nc&amp;amp;_nkw=usb+ttl&amp;amp;_sticky=1&amp;amp;_trksid=p3286.c0.m14&amp;amp;_sop=15&amp;amp;_sc=1 USB to TTL adapter]''' at eBay.&lt;/div&gt;</summary>
		<author><name>Hedak</name></author>
		
	</entry>
	<entry>
		<id>http://wiki.samygo.tv/index.php?title=How_to_downgrade_T-VALDEUC_firmware&amp;diff=3907</id>
		<title>How to downgrade T-VALDEUC firmware</title>
		<link rel="alternate" type="text/html" href="http://wiki.samygo.tv/index.php?title=How_to_downgrade_T-VALDEUC_firmware&amp;diff=3907"/>
		<updated>2014-03-05T20:47:19Z</updated>

		<summary type="html">&lt;p&gt;Hedak: Added warning for not working zero fw from version 3018&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Using &amp;quot;the zero&amp;quot; firmware (not rooted TV)=&lt;br /&gt;
'''without SSH/Telnet or script execution'''&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''WARNING: This doesn't seem to work for firmware version &amp;gt;=3018 anymore (at least for c series, see here: [http://forum.samygo.tv/viewtopic.php?f=10&amp;amp;t=6318#p44767])'''&lt;br /&gt;
&lt;br /&gt;
If you do not have SSH/Telnet access to your TV, it is still possible to downgrade your firmware. For example, if you have 3011 firmware and would like to use SamyGo, you'd need 3005 or 3009 firmware.&lt;br /&gt;
To do this, follow these steps:&lt;br /&gt;
&lt;br /&gt;
* Download the following file:&lt;br /&gt;
:[http://linksave.in/7663217674f4fbe74196ff rapidshare.com] or [http://uploaded.to/file/muz58fle uploaded.to]&lt;br /&gt;
* Extract the file to an USB pendrive (formatted in a file system your TV can read (e.g. FAT32, ext3, NTFS)&lt;br /&gt;
* Plug the pendrive into your TV&lt;br /&gt;
* There should pop up a message asking you if you want to use the pendrive for &amp;quot;Media Player&amp;quot; or &amp;quot;Software Update&amp;quot;. Choose &amp;quot;Software Update&amp;quot;.&lt;br /&gt;
:Should this message not pop up, go to the TV's menu and select &amp;quot;Software Update&amp;quot; from there&lt;br /&gt;
* Follow the procedures for a normal software update from USB. Once the TV is finished, it should restart. Usually, there should come a message up saying &amp;quot;Not for Sale&amp;quot;.&lt;br /&gt;
* Once your TV is started, you can download any T-VALDEUC firmware on your TV (preferebly from USB), there won't be any version checks.&lt;br /&gt;
:Do not use firmware 0000 for &amp;quot;regular&amp;quot; use of your TV since most functions propably won't work (correctly).&lt;br /&gt;
&lt;br /&gt;
=Using shell(rooted TV only)=&lt;br /&gt;
How to downgrade if you already have SSH/Telnet access and your run.sh is being executed:&amp;lt;br&amp;gt;&lt;br /&gt;
'''1.''' fill up run.sh with this code:&lt;br /&gt;
    #!/bin/sh&lt;br /&gt;
    if [ -f /mtd_rwarea/Version.0 ] ; then&lt;br /&gt;
    echo SWU_T-VALDEUC_001000_I04_ES000DS000KS000RS000_100205 &amp;gt; /mtd_rwarea/Version.0&lt;br /&gt;
    else&lt;br /&gt;
    echo SWU_T-VALDEUC_001000_I04_ES000DS000KS000RS000_100205 &amp;gt; /mtd_rwarea/Version.1&lt;br /&gt;
    fi&lt;br /&gt;
    sync &lt;br /&gt;
&lt;br /&gt;
'''2.''' Do not reboot TV, attach USB with firmware version you want to install (T-VALDEUC....)&amp;lt;br&amp;gt;&lt;br /&gt;
'''3.''' Go to &amp;quot;Help -&amp;gt; Software Upgrade -&amp;gt; USB&amp;quot; and TV should accept firmware to downgrade&lt;br /&gt;
&lt;br /&gt;
* '''Attention - code above only for T-VALDEUC'''&lt;br /&gt;
&lt;br /&gt;
* When editing scripts, '''always make sure line breaks are done with unix style &amp;quot;LF&amp;quot;, NOT Windows' &amp;quot;CRLF&amp;quot;'''!&lt;br /&gt;
&lt;br /&gt;
=Firmwares=&lt;br /&gt;
[[Old_&amp;amp;_Good_Firmwares]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
=References=&lt;br /&gt;
[http://forum.samygo.tv/viewtopic.php?p=12695#p12695 topic]:&lt;/div&gt;</summary>
		<author><name>Hedak</name></author>
		
	</entry>
	<entry>
		<id>http://wiki.samygo.tv/index.php?title=Hash_partition_structure&amp;diff=3906</id>
		<title>Hash partition structure</title>
		<link rel="alternate" type="text/html" href="http://wiki.samygo.tv/index.php?title=Hash_partition_structure&amp;diff=3906"/>
		<updated>2014-03-04T21:49:31Z</updated>

		<summary type="html">&lt;p&gt;Hedak: Added c series hash data infos, moved b series references to b series section and added empty f series section&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Article describes structure and partition numbers for most known Samsung TV models.&lt;br /&gt;
=B series CI+ TV`s=&lt;br /&gt;
Almost all read only partitions on B series are observed by secure boot and modifying them may convert TV in to the brick.&amp;lt;br&amp;gt;&lt;br /&gt;
What ''for the hell'' are hashes and how do we calculate them? Read here: '''[[Hashes]].&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
*Hashes for the u-boot (/dev/bml0/2), fnw (dev/bml0/4) and kernel (dev/bml0/5) are stored in /dev/bml0/3 and begin at offset 0x1000.&lt;br /&gt;
*Hashes of firmware files (exe.img and appdata.img) are stored at other place on TV. begin at offset 0x0.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Hashes on /dev/bml0/3  ==&lt;br /&gt;
We have the following structure within this file (at offset 0x1000)&lt;br /&gt;
* '''Image''' [16 bytes hash] [4 bytes length]&lt;br /&gt;
* '''u-boot''' [16 bytes hash] [4 bytes length]&lt;br /&gt;
* '''fnw''' [16 bytes hash] [4 bytes length]&lt;br /&gt;
* '''authuld''' [16 bytes hash] [4 bytes length]&lt;br /&gt;
* '''rootfs''' [16 bytes hash] [4 bytes length]&lt;br /&gt;
* '''boot''' [16 bytes hash] [4 bytes length]&lt;br /&gt;
&lt;br /&gt;
For example, bml0/3 of T-CHLCIPDEUC 2006.0. The hash for kernel (Image) starts at offset 0x1000 and it's length starts at offset 0x1010:&lt;br /&gt;
 # hexdump -C ./bml0_3_dump&lt;br /&gt;
 00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|&lt;br /&gt;
 *&lt;br /&gt;
 00001000  '''26 7a 0e f7 6f f0 e4 9f  79 1b c5 74 54 10 2e d9'''  |&amp;amp;z..o...y..tT...|&lt;br /&gt;
 00001010  '''{{green|e0 3c 2f 00}}  {{gray|72 ab f2 09  a8 ea d4 bc e5 4b 24 a8'''}}  |.&amp;lt;/.r........K$.|&lt;br /&gt;
 00001020  '''{{gray|7b 1d f6 bb}}  {{green|dc 21 04 00}}  {{blue|62 41 92 96 d0 4c 2f b1}}'''  |{....!..bA...L/.|&lt;br /&gt;
 00001030  '''{{blue|17 00 81 0f b5 78 47 ca}}  {{green|b4 ba 02 00}} 3d 8a 03 f3'''  |.....xG.....=...|&lt;br /&gt;
 00001040  '''1c f0 b8 15 30 a1 4b f7  42 d8 4d fa {{green|b8 95 00 00}}'''  |....0.K.B.M.....|&lt;br /&gt;
 00001050  '''{{gray|c0 d5 c5 4b bf 04 e5 28  ef 3b c8 4a 5b 75 aa 07}}'''  |...K...(.;.J[u..|&lt;br /&gt;
 00001060  '''{{green|00 10 33 00}} {{blue|b0 5a b0 71  00 32 84 11 e2 f7 fe 45}}'''  |..3..Z.q.2.....E|&lt;br /&gt;
 00001070  '''{{blue|a4 83 fe 5e}} {{green|00 e0 0d 00}}'''  79 f0 81 7f 56 65 61 93  |...^....y...Vea.|&lt;br /&gt;
 00001080  00 10 31 00 81 6a a0 6c  0a 06 a3 94 23 f4 06 2e  |..1..j.l....#...|&lt;br /&gt;
 00001090  b8 f0 68 3e 00 b0 0d 00  92 4c 61 38 a1 1a f0 0b  |..h&amp;gt;.....La8....|&lt;br /&gt;
 &amp;lt;...&amp;gt;&lt;br /&gt;
 00020000  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|&lt;br /&gt;
 *&lt;br /&gt;
 00080000&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Where: hash of kernel comes first and it is: &lt;br /&gt;
 26 7a 0e f7 6f f0 e4 9f  79 1b c5 74 54 10 2e d9&lt;br /&gt;
Image lengh (hexadecimal)is: {{green|e0 3c 2f 00}}, which has to be read {{red|backwards}}. So the real length is:&lt;br /&gt;
 00 2f 3c e0 (hex) = 3095776 (decimal)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Calculation made with dumps of LE40B650T2P-2006.0 let you understand better structure of bml0/3:&lt;br /&gt;
 ./chkhash -k 7CED26D8CA2FA0F80BC637E2FF07EC46 -L 0x1000 8 bml0_3_dump *&lt;br /&gt;
 hash[ 0] = 267a0ef76ff0e49f791bc57454102ed9   length =  3095776  :  bml05.dmp&lt;br /&gt;
 hash[ 1] = 72abf209a8ead4bce54b24a87b1df6bb   length =   270812  :  bml02.dmp&lt;br /&gt;
 hash[ 2] = 62419296d04c2fb11700810fb57847ca   length =   178868  :  bml04.dmp&lt;br /&gt;
 hash[ 3] = 3d8a03f31cf0b81530a14bf742d84dfa   length =    38328  :  authuld&lt;br /&gt;
 hash[ 4] = c0d5c54bbf04e528ef3bc84a5b75aa07   length =  3346432  :  bml06.dmp&lt;br /&gt;
 hash[ 5] = b05ab07100328411e2f7fe45a483fe5e   length =   909312  :  bml07.dmp&lt;br /&gt;
Now you will know, that after you modify any of those partitions, you have also modify hex signature (hash) as well. MANDATORY at same TV session. Don`t reboot you you haven`t restored hash partition with updated hashes.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== exe.img and appdata.img ==&lt;br /&gt;
The hashes for mtd_exe and mtd_appdata are in /dev/bml0/18 and /dev/bml0/19 for a 1Gb flash type TV models (it differs for other flash sizes).&lt;br /&gt;
&lt;br /&gt;
Structureis similar to bml0/3, just hashes are at the beginning of file:&amp;lt;br&amp;gt;&lt;br /&gt;
*'''mtd_exe''' [16 bytes hash ] [4 bytes lengh], the next [16 bytes ] [4 bytes] are for '''mtd_appdata'''&amp;lt;br&amp;gt;&lt;br /&gt;
For example T-CHLCIPDEUC-2006.0:&lt;br /&gt;
 00000000  '''43 72 15 c3 a6 ff 21 14  ac ac 65 9f cd 5a 25 eb'''  |Cr....!...e..Z%.|&lt;br /&gt;
 00000010  {{green|00 f0 40 03}} 07 7c b3 32  41 ec cd b1 dd f0 40 fd  |..@..|.2A.....@.|&lt;br /&gt;
 00000020  f4 21 82 9d 00 d0 ca 01  00 00 00 00 00 00 00 00  |.!..............|&lt;br /&gt;
 00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|&lt;br /&gt;
&lt;br /&gt;
Hash of exe.img:&lt;br /&gt;
 43 72 15 c3 a6 ff 21 14  ac ac 65 9f cd 5a 25 eb&lt;br /&gt;
Lengh of it: {{green|00 f0 40 03}}, but {{red|backwards}} it is:&lt;br /&gt;
 03 40 f0 00 = 54587392 bytes (decimal)&lt;br /&gt;
This is exact size in bytes of decrypted exe.img! :)&lt;br /&gt;
 ./chkhash -k 7CED26D8CA2FA0F80BC637E2FF07EC46 -L 0x0 3 bml19.dmp *&lt;br /&gt;
 hash[ 0] = d960b582b2ad80eb3203c6bc23735bca   length = 54587392  :  exe.img&lt;br /&gt;
 hash[ 1] = 077cb33241eccdb1ddf040fdf421829d   length = 30068736  :  appdata.img&lt;br /&gt;
&lt;br /&gt;
== Authuld ==&lt;br /&gt;
After boot of kernel and mounting of rootfs, /bin/authuld is called and it is checking hashes '''of active''' partitions and authuld itself.&amp;lt;br&amp;gt; It is important to understand that this check takes some time (this is the delay experienced until authuld reboots the system if it detects modifications, should be approx 1 minute). If it matches, nothing happens (besides an authuld completed successfully message), if it doesn't match, the kernel tells Micom to reboot the system (Micom cmd 143).&lt;br /&gt;
&lt;br /&gt;
On B series (differs from C/D/E series) here are one set of partitions which is always checked (hashes stored on /dev/bml0/'''{{red|3}}''' AND two sets of firmware files (checked only active). Example LExxB650T2P:&lt;br /&gt;
 1nd. /dev/bml0/8 and /dev/bml0/10&lt;br /&gt;
 2nd. /dev/bml0/9 and /dev/bml0/11&lt;br /&gt;
After authuld finishes checking of partitions whose hashes are stored on /dev/bml0/3, it starts to check firmware active partitions, depends from what boot flag is present on /mtd_rwarea:&lt;br /&gt;
 PartitionSwitch_0_0 - 1st set of partitions is booting and hashes are checked on '''1st strmackeypartition'''&lt;br /&gt;
 PartitionSwitch_1_0 - 2nd set of partitions is booting and hashes are checked on '''2nd strmackeypartition'''&lt;br /&gt;
&lt;br /&gt;
At boot time neither hashes of alternative (inactive) partitions, nor its strmackeypartition are checked.&lt;br /&gt;
&lt;br /&gt;
== Known numbers of strmackeypartitions ==&lt;br /&gt;
1Gb flash size B series models (like B650...)&lt;br /&gt;
 /dev/bml0/18 is the '''1st strmackeypartition'''&lt;br /&gt;
 /dev/bml0/19 is the '''2nd strmackeypartition'''&lt;br /&gt;
2Gb flash size B series models (like B7000/8000...)&lt;br /&gt;
 /dev/bml0/16 is the '''1st strmackeypartition''' &lt;br /&gt;
 /dev/bml0/17 is the '''2nd strmackeypartition'''&lt;br /&gt;
128Mb flash size models (like B550...)&lt;br /&gt;
 /dev/bml0/13 is the '''1st strmackeypartition''' &lt;br /&gt;
 /dev/bml0/14 is the '''2nd strmackeypartition'''&lt;br /&gt;
==Key partition ==&lt;br /&gt;
We until today don`t know what is stored on that partition and what is used this info for.&amp;lt;br&amp;gt;&lt;br /&gt;
For above mentioned models it`s number is:&lt;br /&gt;
 1Gb flash - /dev/bml0/20&lt;br /&gt;
 2Gb flash - /dev/bml0/18&lt;br /&gt;
 128Mb flash /dev/bml0/15&lt;br /&gt;
Example of hex data on that partition (1Gb flash, T-CHLCIPDEUC 2006.0)&lt;br /&gt;
 hexdump -C ./bml20.dmp&lt;br /&gt;
 00000000  27 07 79 19 2d 65 f1 22  86 29 40 6c 90 0d af 55  |'.y.-e.&amp;quot;.)@l...U|&lt;br /&gt;
 00000010  17 c7 99 2a 27 07 79 19  ff ff ff ff ff ff ff ff  |...*'.y.........|&lt;br /&gt;
 00000020  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|&lt;br /&gt;
 *&lt;br /&gt;
 00100000&lt;br /&gt;
If anyone has some ideas, what is needed for, please share with us [http://forum.samygo.tv/viewtopic.php?f=2&amp;amp;t=655 on forum]. Thanks!&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
#[http://forum.samygo.tv/viewtopic.php?f=2&amp;amp;t=655&amp;amp;start=30#p9491 research of cyberdemon79]&lt;br /&gt;
&lt;br /&gt;
=C series TV`s=&lt;br /&gt;
Almost all read only partitions on C series are observed by secure boot and modifying them may convert TV in to the brick.&amp;lt;br&amp;gt;&lt;br /&gt;
What ''for the hell'' are hashes and how do we calculate them? Read here: '''[[Hashes]].&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For knowing what it's talked about here is the whole partition list of a UE46C7700 T-VALDEUC 3011.0:&lt;br /&gt;
 # cat /mtd_exe/partition.txt&lt;br /&gt;
 partitionID flash_device_name flash_device_size flash_image_name flash_device_type flash_upgrade_type	flash_partition_map flash_mount_path default_block_size flash_format_option flash_mount_option&lt;br /&gt;
 0  /dev/bml0/1  262144    onboot.bin    DEVICE OTHER BOOTLOADER0 NONE         	262144	NONE	NONE&lt;br /&gt;
 1  /dev/bml0/2  262144    u-boot.bin    BML    OTHER BOOTLOADER1 NONE         	262144	NONE	NONE&lt;br /&gt;
 2  /dev/bml0/3  262144    uboot_env.bin BML    OTHER BOOTLOADER2 NONE         	262144	NONE	NONE&lt;br /&gt;
 3  /dev/bml0/4  262144    fnw.bin       BML    OTHER BOOTLOADER3 NONE         	262144	NONE	NONE&lt;br /&gt;
 4  /dev/bml0/5  4194304   Image         BML    USER  KERNEL0     NONE         	262144	NONE	NONE&lt;br /&gt;
 5  /dev/bml0/6  3670016   rootfs.img    BML    USER  RFS0        NONE         	262144	NONE	NONE&lt;br /&gt;
 6  /dev/bml0/7  4194304   Image         BML    USER  KERNEL1     NONE         	262144	NONE	NONE&lt;br /&gt;
 7  /dev/bml0/8  3670016   rootfs.img    BML    USER  RFS1        NONE         	262144	NONE	NONE&lt;br /&gt;
 8  /dev/bml0/9  262144    NONE          BML    OTHER SECUREMAC0  NONE         	262144	NONE	NONE&lt;br /&gt;
 9  /dev/bml0/10 262144    NONE          BML    OTHER SECUREMAC1  NONE         	262144	NONE	NONE&lt;br /&gt;
 10 /dev/bml0/11 262144    key.bin       BML    OTHER SECUREMAC2  NONE         	262144	NONE	NONE&lt;br /&gt;
 11 /dev/bml0/12 262144    NONE          BML    OTHER NONE        NONE         	262144	NONE	NONE&lt;br /&gt;
 12 /dev/stl0/13 11272192  NONE          STL    OTHER NONE        /mtd_contents	4096	ERASE:,STL:-r_7,FAT:-S_1024_-s_1 -t_rfs_-o_codepage=utf8&lt;br /&gt;
 13 /dev/stl0/14 26214400  NONE          STL    OTHER NONE        /mtd_rwarea	4096	ERASE:,STL:-r_7,FAT:-S_1024_-s_1 -t_rfs_-o_codepage=utf8&lt;br /&gt;
 14 /dev/stl0/15 93323264  exe.img       STL    USER  EXE0        /mtd_exe	4096	ERASE:,STL:-r_2	NONE&lt;br /&gt;
 15 /dev/stl0/16 58195968  appdata.img   STL    USER  APP_DATA0   /mtd_appdata	4096	ERASE:,STL:-r_2	NONE&lt;br /&gt;
 16 /dev/stl0/17 93323264  exe.img       STL    USER  EXE1        /mtd_exe	4096	ERASE:,STL:-r_2	NONE&lt;br /&gt;
 17 /dev/stl0/18 58195968  appdata.img   STL    USER  APP_DATA1   /mtd_appdata	4096	ERASE:,STL:-r_2	NONE&lt;br /&gt;
 18 /dev/stl0/19 52953088  rocommon.img  STL    OTHER CONTENT0    /mtd_rocommon	4096	ERASE:,STL:-r_2	NONE&lt;br /&gt;
 19 /dev/stl0/20 104857600 NONE          STL    OTHER NONE        /mtd_swu	4096	ERASE:,STL:-r_16,FAT:-S_4096_-s_4 -t_rfs&lt;br /&gt;
 20 /dev/stl0/21 411566080 NONE          STL    OTHER NONE        /mtd_rwcommon	4096	FAT:-S_4096_-s_1 -t_rfs_-o_codepage=utf8&lt;br /&gt;
&lt;br /&gt;
Just for completeness: SECUREMAC2 (/dev/bml0/11) is the strmackeypartition here.&lt;br /&gt;
&lt;br /&gt;
==Typical hash data structure==&lt;br /&gt;
For all hashes the structure is as follows:&amp;lt;br&amp;gt;&lt;br /&gt;
[16 bytes hash][4 bytes length]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
16 bytes hash is calculated using chkhash.&amp;lt;br&amp;gt;&lt;br /&gt;
4 bytes length is the byte count the hash is/was calculated over. It is stored backwards (see B series for details).&lt;br /&gt;
&lt;br /&gt;
==Partition hash data==&lt;br /&gt;
The hashes of the images exe.img, appdata.img, Image (kernel) and rootfs.img are stored in that order sequentially within a separate partition, sometimes called cmac (hash) partition. These four images are stored in separate partitions. As all four partitions exist twice (one for active set, one for inactive set) there also exist two cmac partitions: SECUREMAC0 and SECUREMAC1&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
During boot process the hashes of inactive partition are not checked.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The relation is as follows:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
SECUREMAC0 (/dev/bml0/9): EXE0 (/dev/stl0/15), APP_DATA0 (/dev/stl0/16), KERNEL0 (/dev/bml0/5) and RFS0 (/dev/bml0/6)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
SECUREMAC1 (/dev/bml0/10): EXE1 (/dev/stl0/17), APP_DATA1 (/dev/stl0/18), KERNEL1 (/dev/bml0/7) and RFS1 (/dev/bml0/8)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
For example cmac partition for 2nd partition set (/dev/bml0/10) of T-VALDEUC 3011.0 looks like this:&lt;br /&gt;
 Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F&lt;br /&gt;
 &lt;br /&gt;
 00000000  48 F5 8B FA 80 50 D8 8E A1 75 79 57 DC F7 EB C5  Hõ‹ú€PØŽ¡uyWÜ÷ëÅ&lt;br /&gt;
 00000010  00 70 55 05 58 03 6F E3 6C 3F E1 58 56 13 A9 45  .pU.X.oãl?áXV.©E&lt;br /&gt;
 00000020  51 AE 92 00 00 40 7D 02 7E E4 E5 37 96 1A A0 DE  Q®’..@}.~äå7–. Þ&lt;br /&gt;
 00000030  C4 95 3B AE D4 AD CE 99 90 A4 38 00 9B 86 63 05  Ä•;®Ô.Î™.¤8.›†c.&lt;br /&gt;
 00000040  0A 8F FA 3B 66 07 BA 93 1D BF BE 2B 14 F0 37 00  ..ú;f.º“.¿¾+.ð7.&lt;br /&gt;
 00000050  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................&lt;br /&gt;
&lt;br /&gt;
Where&lt;br /&gt;
 48 F5 8B FA 80 50 D8 8E A1 75 79 57 DC F7 EB C5&lt;br /&gt;
is the hash of exe.img (stored in /dev/stl0/17), the image byte size is 0x05557000 (00 70 55 05 read backwards)&lt;br /&gt;
&lt;br /&gt;
 58 03 6F E3 6C 3F E1 58 56 13 A9 4 51 AE 92 00&lt;br /&gt;
is the hash of appdata.img (stored in /dev/stl0/18), the image byte size is 0x027D4000 (00 40 7D 02 read backwards)&lt;br /&gt;
&lt;br /&gt;
 7E E4 E5 37 96 1A A0 DE C4 95 3B AE D4 AD CE 99&lt;br /&gt;
is the hash of Image (kernel) (stored in /dev/bml0/7), the image byte size is 0x0038A490 (90 A4 38 00 read backwards)&lt;br /&gt;
&lt;br /&gt;
 9B 86 63 05 0A 8F FA 3B 66 07 BA 93 1D BF BE 2B&lt;br /&gt;
is the hash of rootfs.img (stored in /dev/bml0/8), the image byte size is 0x0037F014 (14 F0 37 00 read backwards)&lt;br /&gt;
&lt;br /&gt;
==authuld hash data==&lt;br /&gt;
The binary authuld is stored within read-only rootfs partition (is NOT image!). Although rootfs's hash is already checked authuld's hash is checked separately! authuld's hash is stored 0x1000 (4096 dez) byte in front of the end of partition (is NOT image!) rootfs.&lt;br /&gt;
&lt;br /&gt;
For example rootfs partition for 2nd partition set (/dev/bml0/8) of T-VALDEUC 3011.0 looks like this:&lt;br /&gt;
 Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F&lt;br /&gt;
 &lt;br /&gt;
 0037EFF0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................&lt;br /&gt;
 0037F000  05 C7 9B 14 D3 DF 2B A0 88 C3 EB CB 4C A9 3E B5  .Ç›.Óß+ ˆÃëËL©&amp;gt;µ&lt;br /&gt;
 0037F010  68 98 00 00 FF FF FF FF FF FF FF FF FF FF FF FF  h˜..ÿÿÿÿÿÿÿÿÿÿÿÿ&lt;br /&gt;
 0037F020  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ&lt;br /&gt;
&lt;br /&gt;
Notice: Referring to the partition list written above the partition size of rootfs is 3670016 byte (0x380000). So the hash data for authuld is located at offset 0x37F000 (0x380000 - 0x1000).&lt;br /&gt;
&lt;br /&gt;
Where&lt;br /&gt;
 05 C7 9B 14 D3 DF 2B A0 88 C3 EB CB 4C A9 3E B5&lt;br /&gt;
is the hash of binary authuld, the binary byte size is 0x00009868 (68 98 00 00 read backwards)&lt;br /&gt;
&lt;br /&gt;
After boot of kernel and mounting of rootfs, /bin/authuld is called and it is checking hashes of active partitions and authuld itself.&lt;br /&gt;
It is important to understand that this check takes some time (this is the delay experienced until authuld reboots the system if it detects modifications, should be approx 1 minute). If it matches, nothing happens (besides an authuld completed successfully message), if it doesn't match, the system reboots.&lt;br /&gt;
&lt;br /&gt;
==Bootlader hashes==&lt;br /&gt;
Not available as far as i could figure out. (maybe because its not used (anymore))&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
#[http://forum.samygo.tv/viewtopic.php?f=10&amp;amp;t=7396&amp;amp;p=56294 Modifying /mtd_exe of active partition]&lt;br /&gt;
#[http://wiki.samygo.tv/index.php5/Remove_shell_input_filtration#Patch_kernel_image Patch kernel image]&lt;br /&gt;
#[http://forum.samygo.tv/viewtopic.php?f=10&amp;amp;t=7247&amp;amp;p=54937 Modifying rootfs image]&lt;br /&gt;
&lt;br /&gt;
=D series TV`s=&lt;br /&gt;
ToDo&lt;br /&gt;
&lt;br /&gt;
=E series TV`s=&lt;br /&gt;
ToDo&lt;br /&gt;
&lt;br /&gt;
=F series TV`s=&lt;br /&gt;
ToDo&lt;br /&gt;
&lt;br /&gt;
=BluRay players=&lt;br /&gt;
ToDo&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Work in progress, to be updated.&lt;/div&gt;</summary>
		<author><name>Hedak</name></author>
		
	</entry>
	<entry>
		<id>http://wiki.samygo.tv/index.php?title=Hashes&amp;diff=3905</id>
		<title>Hashes</title>
		<link rel="alternate" type="text/html" href="http://wiki.samygo.tv/index.php?title=Hashes&amp;diff=3905"/>
		<updated>2014-02-26T21:35:08Z</updated>

		<summary type="html">&lt;p&gt;Hedak: Added some 0.02 feature descriptions and download links&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;WORK IN PROGRESS, NOT FINISHED YET! {{red|Ned to remake and update}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=getmkey utility=&lt;br /&gt;
&lt;br /&gt;
To calculate hashes you will need a 128-bit key which can be obtained from the TV or blu-ray player using getmkey utility. Check file getmkey/Makefile to get the idea how to build getmkey program, upload it to the TV or player and run it. If you do not wish to install a toolchain for cross-compilation, you may try prebuilt binaries: getmkey or getmkey_static.&lt;br /&gt;
&lt;br /&gt;
If you have root access to the TV or player, run getmkey. You should get the output which looks like this:&lt;br /&gt;
&lt;br /&gt;
 opening /dev/mem ok!&lt;br /&gt;
 No key was supplied from a command line.&lt;br /&gt;
 Using mackey from /dev/tfsr11&lt;br /&gt;
 Input key = 86d446c947765600a4a83098e6ee7ae2&lt;br /&gt;
 After waiting 1 loops&lt;br /&gt;
 mkey='2b7e151628aed2a6abf7158809cf4f3c'  	# for BD-C6900 player&lt;br /&gt;
 #mkey='7ced26d8ca2fa0f80bc637e2ff07ec46'  	# B series&lt;br /&gt;
 #mkey='6f6bc7e1fc7f86bf9c150a82f343e2e0'  	# for T-VALDEUC-1014.3 TV&lt;br /&gt;
 &lt;br /&gt;
 ./chkhash -k 7ced26d8ca2fa0f80bc637e2ff07ec46 -h 3665940 rootfs.img&lt;br /&gt;
Last line of the output contains an mkey which will be used in chkhash program:&lt;br /&gt;
&lt;br /&gt;
=Printing hashes=&lt;br /&gt;
&lt;br /&gt;
 ./chkhash -p offset n file              : prints &amp;lt;n&amp;gt; hashes at &amp;lt;offset&amp;gt; in &amp;lt;file&amp;gt;&lt;br /&gt;
                                          offset less than zero means offset from the end of the file.&lt;br /&gt;
&lt;br /&gt;
Example: print hashes in dumps from /dev/tbml9 and /dev/tbml10. Here and below we assume that dumps from firmware partitions /dev/tbmlX are stored in files tbmlX.bin, and dumps from /dev/stl0/X are stored in files stl0-X.bin.&lt;br /&gt;
&lt;br /&gt;
 ./chkhash -p 0 6 tbml9.bin&lt;br /&gt;
 hash[ 0] = cb82e0476eecfe10b7415c099c34a53f   length = 39735296&lt;br /&gt;
 hash[ 1] = efb116822ffe713571b988f4bd71fb14   length = 36028416&lt;br /&gt;
 hash[ 2] = 66d50c94a62cb51cf51482e77c74e267   length =  3104328&lt;br /&gt;
 hash[ 3] = 1b8f9aa5846d4d8624482c183cb9c147   length =  4190228&lt;br /&gt;
 hash[ 4] = 7bca4cf5f259475adac2c57965d7d6f1   length =   123510&lt;br /&gt;
 Only 5 hashes were detected&lt;br /&gt;
 &lt;br /&gt;
 ./chkhash -p 0 6 tbml10.bin&lt;br /&gt;
 hash[ 0] = 25a3d13599932da3d255a749f1fe7581   length = 41050112&lt;br /&gt;
 hash[ 1] = 2c23831d821407d180607890c07d4d22   length = 37797888&lt;br /&gt;
 hash[ 2] = 60a8d999f3b6da20c58a3eb2056d43d6   length =  3104328&lt;br /&gt;
 hash[ 3] = b0dac74b78a6814149187cf4d660f1f5   length =  4190228&lt;br /&gt;
 hash[ 4] = 7bca4cf5f259475adac2c57965d7d6f1   length =   123510&lt;br /&gt;
 Only 5 hashes were detected&lt;br /&gt;
&lt;br /&gt;
Or print hash for /bin/authuld file (this hash is stored at the offset 4096 bytes from the end of RootFS image in /dev/tbml6 or /dev/tbml8):&lt;br /&gt;
&lt;br /&gt;
 ./chkhash -p -4096 1 tbml6.bin&lt;br /&gt;
 hash[ 0] = 7fe99ddcf4c6c67f68374dbc60879f64   length =    36308&lt;br /&gt;
 &lt;br /&gt;
 ./chkhash -p -4096 1 tbml8.bin&lt;br /&gt;
 hash[ 0] = 941137492edd0c83b489c665d6335295   length =    36308&lt;br /&gt;
&lt;br /&gt;
=Calculating hashes=&lt;br /&gt;
&lt;br /&gt;
 ./chkhash -k mkey -h length file        : calculates and prints hash from the first &amp;lt;length&amp;gt; bytes of the file.&lt;br /&gt;
                                          if length is 0, the hash is calculated for full file length.&lt;br /&gt;
&lt;br /&gt;
Example: if you have a copy of an authuld in current directory, run&lt;br /&gt;
&lt;br /&gt;
 ./chkhash -k 2b7e151628aed2a6abf7158809cf4f3c -h 0 authuld&lt;br /&gt;
 Hash: 941137492edd0c83b489c665d6335295, length = 36308&lt;br /&gt;
&lt;br /&gt;
Or you can calculate, for example a hash for bootloader (in /dev/tbml1):&lt;br /&gt;
&lt;br /&gt;
 ./chkhash -k 2b7e151628aed2a6abf7158809cf4f3c -h 123510 tbml1.bin&lt;br /&gt;
 Hash: 7bca4cf5f259475adac2c57965d7d6f1, length = 123510&lt;br /&gt;
&lt;br /&gt;
=Calculating and comparing hashes=&lt;br /&gt;
&lt;br /&gt;
 ./chkhash -k mkey -m length file hash   : calculates hash from the first &amp;lt;length&amp;gt; bytes of the file and compares with &amp;lt;hash&amp;gt;&lt;br /&gt;
                                          prints no result, useful in scripts only: return 0 if hashes are equal&lt;br /&gt;
                                          if length is 0, the hash is calculated for full file length.&lt;br /&gt;
&lt;br /&gt;
=Looking for dumps whose hashes are stored in a hash block file (CMAC):=&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 ./chkhash -k mkey -L offset n hashfile file1 file2 ... fileN&lt;br /&gt;
                                         : checks if &amp;lt;n&amp;gt; hashes stored at &amp;lt;offset&amp;gt; in a &amp;lt;hashfile&amp;gt; match&lt;br /&gt;
                                         : with hashes for &amp;lt;file1&amp;gt; &amp;lt;file2&amp;gt; ... &amp;lt;fileN&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Example: tbml10.bin (dump from /dev/tbml10), as shown above, contains a set of hashes for some files. Let's find these files (search will take some time because of calculation of hashes for many files):&lt;br /&gt;
&lt;br /&gt;
 ./chkhash -k 2b7e151628aed2a6abf7158809cf4f3c -L 0 5 tbml10.bin tbml*.bin stl0-*.bin&lt;br /&gt;
 hash[ 0] = 25a3d13599932da3d255a749f1fe7581   length = 41050112  :  stl0-16.bin&lt;br /&gt;
 hash[ 1] = 2c23831d821407d180607890c07d4d22   length = 37797888  :  stl0-17.bin&lt;br /&gt;
 hash[ 2] = 60a8d999f3b6da20c58a3eb2056d43d6   length =  3104328  :  tbml7.bin&lt;br /&gt;
 hash[ 3] = b0dac74b78a6814149187cf4d660f1f5   length =  4190228  :  tbml8.bin&lt;br /&gt;
 hash[ 4] = 7bca4cf5f259475adac2c57965d7d6f1   length =   123510  :  tbml1.bin&lt;br /&gt;
&lt;br /&gt;
Here these files contain:&lt;br /&gt;
&lt;br /&gt;
 stl0-16.bin	: mtd_exe&lt;br /&gt;
 stl0-17.bin	: mtd_appdata&lt;br /&gt;
 tbml7.bin	: kernel&lt;br /&gt;
 tbml8.bin	: rootfs&lt;br /&gt;
 tbml1.bin	: bootloader&lt;br /&gt;
&lt;br /&gt;
=Calculation of hash block (CMAC) for firmware modification=&lt;br /&gt;
&lt;br /&gt;
 ./chkhash -k mkey -H outfile file1 file2 ... fileN&lt;br /&gt;
                                         : creates hash block (cmac) for given input files&lt;br /&gt;
&lt;br /&gt;
Hashes are written in the same order as supplied files. This can be used for building a hash block (CMAC) if you modify some firmware partitions.&lt;br /&gt;
&lt;br /&gt;
=Save given key to binary file=&lt;br /&gt;
&lt;br /&gt;
 ./chkhash -S key file : saves given hex &amp;lt;key&amp;gt; (16 byte) to binary &amp;lt;file&amp;gt;&lt;br /&gt;
                         &amp;lt;file&amp;gt; is created if not existent and overwritten if already existent&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 ./chkhash -S 6f6bc7e1fc7f86bf9c150a82f343e2e0 /mtd_rwcommon/test.bin&lt;br /&gt;
will create the file /mtd_rwcommon/test.bin with content (hex view):&lt;br /&gt;
00000000  6F 6B C7 E1 FC 7F 86 BF 9C 15 0A 82 F3 43 E2 E0  okÇáü.†¿œ..‚óCâà&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Write calculated hash to file=&lt;br /&gt;
&lt;br /&gt;
 ./chkhash -k mkey -w offset k hashfile file : writes calculated hash for &amp;lt;file&amp;gt; (full length) at hash position &amp;lt;k&amp;gt; in a hash &lt;br /&gt;
                                               block located at &amp;lt;offset&amp;gt; in &amp;lt;hashfile&amp;gt;&lt;br /&gt;
                                               offset less than zero means offset from the end of the hashfile&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 ./chkhash -k 6f6bc7e1fc7f86bf9c150a82f343e2e0 -w 0 0 /mtd_rwcommon/bml10.dmp /mtd_rwcommon/mtd_exe_part.dmp&lt;br /&gt;
will write the calculated hash of /mtd_rwcommon/mtd_exe_part.dmp ('_part' indicates that the dump is cut to the length read in /dev/bml0/10, for example using 'dd' to dump the first xx blocks only) in /mtd_rwcommon/bml10.dmp with no offset (0) and update the hash at index 0 (i.e. the hash of /mtd_exe)&lt;br /&gt;
&lt;br /&gt;
= mknewfs.sh =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This an example script to create a modified version of rootfs, mtd_exe or mtd_appdata. Please check it carefully before using. I did not test it for flashing my own firmware, so be careful. Read comments explaining the whole process and, anyway, you must accept any risk of possible bricking your TV or player.&lt;br /&gt;
&lt;br /&gt;
= Other remarks = &lt;br /&gt;
&lt;br /&gt;
Note that you will also need to know how to switch partitions for booting. Flashing of active (mounted) partition is dangerous, so you can only flash inactive (currently unused and unmounted) partition. So, first you will need to find which partition is active now. Run the following command in your device:&lt;br /&gt;
&lt;br /&gt;
 # df&lt;br /&gt;
 Filesystem           1k-blocks      Used Available Use% Mounted on&lt;br /&gt;
 /dev/tbml8                2880      2880         0 100% /&lt;br /&gt;
 none                     10240        20     10220   0% /dtv&lt;br /&gt;
 none                     60204         0     60204   0% /core&lt;br /&gt;
 /dev/stl0/17             36928     36928         0 100% /mtd_appdata&lt;br /&gt;
 /dev/stl0/16             40128     40128         0 100% /mtd_exe&lt;br /&gt;
&lt;br /&gt;
This is for BD-C6900 player. Other devices may have other filesystem structure, so procedure described here may be different. Here we can see that active devices are /dev/tbml8 /dev/stl0/17 /dev/stl0/16 which belong to second partiton and their CMAC data (hashes) are stored in /dev/tbml10. Therefore we can flash first partition: /dev/tbml6 /dev/stl0/15 /dev/stl0/14 and write their hashes to /dev/tbml9.&lt;br /&gt;
&lt;br /&gt;
If we assume that dumps from firmware /dev/tbmlX are stored in files tbmlX.bin, and dumps from /dev/stl0/X are stored in files stl0-X.bin, first of all we need to copy currently active files to prepare them for first (now inactive) partition:&lt;br /&gt;
&lt;br /&gt;
 cp tbml8.bin tbml6.bin      # rootfs&lt;br /&gt;
 cp stl0-17.bin stl0-15.bin  # mtd_appdata&lt;br /&gt;
 cp stl0-16.bin stl0-14.bin  # mtd_exe&lt;br /&gt;
 cp tbml7.bin tbml5.bin      # kernel&lt;br /&gt;
&lt;br /&gt;
Also, we need to copy hashes:&lt;br /&gt;
&lt;br /&gt;
 cp tbml10.bin tbml9.bin&lt;br /&gt;
&lt;br /&gt;
Now we can start to modify the firmware: run&lt;br /&gt;
&lt;br /&gt;
 mknewfs.sh tbml6.bin tbml9.bin&lt;br /&gt;
&lt;br /&gt;
for the first time to unsquash the rootfs. Then go to the tbml6.bin.rootdir and do necessary changes. Create new rootfs by running the same script again. You will get two files: tbml6.bin.new and tbml9.bin.new which contain new rootfs and new CMAC ready for flashing to /dev/tbml6 and /dev/tbml9. You may also modify mtd_exe by running&lt;br /&gt;
&lt;br /&gt;
 mknewfs.sh stl0-14.bin tbml9.bin&lt;br /&gt;
&lt;br /&gt;
two times: first, to unsquash filesystem, and second time after your modifications to build new mtd_exe.&lt;br /&gt;
&lt;br /&gt;
After flashing modified filesystems, kernel and hash block (CMAC), you will need to switch partitions to boot into your modified filesystems. That's it!&lt;br /&gt;
&lt;br /&gt;
How to flash firmware partitions and switch them: this probably can be found elsewhere...&lt;br /&gt;
&lt;br /&gt;
Note that I did not try that. So, consider this just as some theoretical analysis. Study it, check for possible errors, and use it on your own risk.&lt;br /&gt;
----&lt;br /&gt;
'''Download chkhash sources and precompiled getmkey [http://download.samygo.tv/Others/chkhash-0.02.zip chkhash-0.2.zip]'''&lt;br /&gt;
&lt;br /&gt;
'''Download precompiled chkhash for arm [https://forum.samygo.tv/download/file.php?id=3748]'''&lt;br /&gt;
&lt;br /&gt;
'''Download precompiled chkhash for win32 [https://forum.samygo.tv/download/file.php?id=3766]'''&lt;br /&gt;
&lt;br /&gt;
=References =&lt;br /&gt;
Discussion on the SamyGO forum (can`t decide which subforum it belongs to...)&lt;/div&gt;</summary>
		<author><name>Hedak</name></author>
		
	</entry>
</feed>