Friday 16 May 2014

Raspberry Pi and Programming EEPROMs on SFP/SFP+ modules

Connecting to the I2C pins on an SFP can be difficult, the easiest way I have found is to use old Cisco TwinGig module to house the SFP or SFP+. These can be purchased at a very reasonable price from ebay if you don't have one lying around.

The pins we are interested in on the SFP/SFP+ are:
Pin1: All VeeT or VeeR pins are ground, you only need to connect to one as they are connected internally in the SFP.
Pin 15 and Pin 16 both require +3.3V.
Pin 4: MOD-Def(2) - data line of i2c serial interface
Pin 5: MOD-Def(1) - clock line of i2c serial interface
Pin 6: MOD-Def(0) is connected to ground internally on any of the SFPs I have played with. So no need to connect.

The easiest place I found to make a solder was on the ends of resistors R57 (SDA) and R54(SCL) on the back of the PCB. For the 3.3V and 0V I used the large PCB edge card connectors.

On the Raspberry Pi you just need to connect the 4 wires to the GPIO pins:
GPIO Pin 1: 3.3V
GPIO Pin 6: 0V

Here is what the final version should look like:

How to test that everything is working:
1) Install i2c-tools. ie apt-get install i2c-tools
2) Make sure the module is being loaded and not blacklisted.
pi@raspberrypi ~ $ cat /etc/modprobe.d/raspi-blacklist.conf
# blacklist spi and i2c by default (many users don't need them)
blacklist spi-bcm2708
#blacklist i2c-bcm2708

3) Test your wiring. Make sure you can see the SFP address (0x50) on the I2C bus. If you cannot see the address something is wrong with your wiring.

pi@raspberrypi ~ $ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: 50 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --                      
pi@raspberrypi ~ $

If you also see address 0x51, your SFP supports DOM(Digital Optical Monitoring).

4) Read the EEPROM details from address 0x50 using i2cdump.

pi@raspberrypi ~ $ i2cdump -y 1 0x50
No size specified (using byte-data access)
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 03 04 07 00 00 00 01 00 00 00 00 01 0d 00 00 00    ???...?....??...
10: 37 1b 00 00 52 61 73 70 62 65 72 72 79 20 50 69    7?..Raspberry Pi
20: 20 20 20 20 00 00 30 d3 51 46 42 52 2d 35 37 36        ..0?QFBR-576
30: 36 4c 50 20 20 20 20 20 20 20 20 20 03 52 00 c6    6LP         ?R.?
40: 00 1a 00 00 31 32 33 34 35 36 37 38 39 4a 4b 20    .?..123456789JK
50: 20 20 20 20 30 35 30 33 31 30 20 20 00 00 00 95        050310  ...?
60: 00 00 02 ab 89 12 ea 3e 00 04 1c 5f 6a 0a de 10    ..?????>.??_j???
70: 74 11 3b 00 00 00 00 00 00 00 00 00 ef 19 f8 08    t?;.........????
80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
90: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff    ................
pi@raspberrypi ~ $

To understand the details of the EEPROM refer to the latest SFP MSA.
Note the addresses in the SFP MSA are in decimal while the addresses above in the dump are in hex.

5) How to read/write to the EEPROM on your SFP or SFP+

The easiest way I have come across for the Pi is using a library called wiringPi by Gordon Henderson. Check out for details.

To read all the bytes on the EEPROM and store them in an array called A50.

int xio;
int fd1;
unsigned char A50[128];
printf ("Read SFP EEPROM\n");

        xio = wiringPiI2CSetup (0x50);
        if (xio < 0){
                fprintf (stderr, "xio: Unable to initialise I2C: %s\n", strerror (errno));
                return 1;
        /*Read in the first 128 bytes 0 to 127*/
        for(i=0; i <128; i++){
                fd1 = wiringPiI2CReadReg8 (xio,i);
                A50[i] = fd1;

//print vendor id bytes 20 to 35
        memcpy(&vendor, &A50[20],16);
        vendor[16] = '\0';
        printf("\nVendor = %s",vendor);

You can write a byte or an array containing your bytes using a loop for  wiringPiI2CWriteReg8.
unsigned char mybytes[] = {0xff};
   wiringPiI2CWriteReg8(xio, counter, mybytes[0]);

To check to see if your checksum agrees with the value on the EEPROM.
        sum = 0;
        for (counter = 0; counter <0x3f; counter++)
        sum = (A50[counter] + sum);
        sum = sum & 0xff;
        cc_base = A50[0x3f]; //sum stored in address 63.
        printf("value of cc_base = %x and sum= %x\n",cc_base,sum);
        printf ("\n");

To read the transceiver wavelength:
int wave; //3 bytes. 60 high order, 61 low order. 62 is the mantissa             
        wave = ((int) A50[60]<<8) | ((int) A50[61]);
        printf("\nWavelength = %d.%d",wave,A50[62]);

The dump of the EEPROM from the SFP above has a vendor id of Raspberry Pi. It's easy enough to read in and print out more values.
Transceiver is 1000Base SX
Wavelength = 850.0
Vendor = Raspberry Pi  
Serial = 123456789JK
cc_base = c6 and cc_ext = 95

The SFP EEPROM above is Cisco compliant without using service unsupported. To make an SFP Cisco compliant you need to make the two checksums valid(cc_base and cc_ext), you also need to compute the vendor specific bytes 60 to 0x7f. 
Details can be found here:

My code can be found here:


  1. sw1#show idprom int gig0/2

    General SFP Information


    Identifier : 0x03

    Connector : 0x07

    Transceiver : 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00

    Encoding : 0x01

    BR_Nominal : 0x0D

    Vendor Name : Raspberry Pi

    Vendor Part Number : QFBR-5766LP

    Vendor Revision : 0x20 0x20 0x20 0x20

    Vendor Serial Number : 123456789JK


    sw1#show int gig0/2 status

    Port Name Status Vlan Duplex Speed Type

    Gi0/2 Raspberry connected 1 full 1000 1000BaseSX SFP


    sw1#show int gig0/2

    GigabitEthernet0/2 is up, line protocol is up (connected)

    Hardware is Gigabit Ethernet, address is 001a.a292.5c82 (bia 001a.a292.5c82)

    Description: Raspberry

    MTU 9000 bytes, BW 1000000 Kbit/sec, DLY 10 usec,

    reliability 255/255, txload 1/255, rxload 1/255

    Encapsulation ARPA, loopback not set

    Keepalive set (10 sec)

    Full-duplex, 1000Mb/s, link type is auto, media type is 1000BaseSX SFP

    1. I've located your post while looking for a project that will allow me to have my raspberry pi tune my SFP and SFP+ optics. I'm not sure if what you have here will help me with that or not. It seems so.

    2. I have no experience of tuning SFPs but it looks reasonably straight forward. SFF-8690 provides details of how to set the Tx wavelength for tunable SFP+. You should be able to write your own code to do it. Let me know how you get on or if you need some help.

  2. My code can be found here:

  3. Can you share the manufacturer ID and vendor key bytes you used to make a SFP Cisco compliant? I've tried the ones I found on the russian forum you linked to, but I can't get a 3750 to accept the SFP!

  4. See the dump from the SFP above. You can see the man_id is 0x02. See if you can recreate the above values.
    I have tested the above in a 3750 with IOS15.2 and it works without service unsupported transceiver.

  5. Would this work with Twingig+Infineon SFP? Can't seem to find SFP in the /dev tree. Running Pi2-B+ with Minibian OS.

    1. Switched to Raspbian Wheezy (3.18) then followed the instructions at to setup i2c. i2cdetect responds correctly and can see /dev/i2c-1 now - thanks

  6. It is also possible to use molex sfp and xfp hosts directly rather than using the twingig, but you need to be comfortable soldering very small components. You need a very fine solder and solder iron. Here is an xfp host I have used.

  7. Compiled the sfppi-vendor/sfpii-generic scripts and is working ok.
    For the vendor bytes update, I have not been able to update the vendor id. I think I set the vendor related vars correctly. What is the significance of of vendor_key1 in vendor_fy routine?

  8. A great article.

    I assume that the algorithm you used to generate the values from 0x60 to 0x7f was the one outlined at: (post 63)

    As my Russian skills amount to zero and I suspect I am loosing a bit in the google translation, perhaps you could elaborate on the method you used to generate those Cisco specific bytes?

  9. Gandalf, yes that is all the vendor_fy routine does. Many vendors use the same or similar concepts.

  10. This comment has been removed by the author.

  11. Hi Eoin,

    Thank you for this great article. As Gandalf, my russian skills are a bit limited :-)
    Do you know if HP uses the same kind of algorithm for the Procurve series ?

  12. Interesting article. Can you email me so we can talk? I might have a project we would like your help on. mark AT pcwmemory DOT com

  13. Interesting article. Can you email me so we can talk? I might have a project we would like your help on. mark AT pcwmemory DOT com

  14. I did a PCB with this info and a molex connector, seems to work awesome with my Raspberry Pi 2 (Raspbian Jessie kernel 4.1). I got stuck at one point building the "sfpp-vendor", but solved it by installing "libssl-dev" (it said it didn't found openssl/evp.h).

    But, looking at the script I'm a bit confused about the vendor key and manufacter id. We have a bunch of OEM SFP which are programed for different vendors (Cisco, HP, etc), and my goal is to be able to reprogram some of them instead of buy more of them. But because we have almost one for each brand, is it a way to easy copy info from one of each like a template and then program another one (change from HP to Cisco for example)? Might be a stupid question, it isn't obvious for me how. Thanks in advance and good work!

  15. I got caught in finding out what makes a HP Procurve switch accept or reject a SFP. I have two "alien" SFP that ARE accepted, and a bunch that are not. First I thought that the OID or the Name was the reason, but studying the result of the "physhow 26" I saw that SFP's were accepted with make OEM and make Finisar. Comparing the dumps the crucial factor seems to be "Unallocated bits 18 are set", reported in conjunction with RATE_SELECT, TX_ENABLE and TX_FAULT.
    The problem I have with this is the bit number, since the option field is only two bytes, I only expected B0 - B15.
    Do you have any idea where "bit 18" is located?

  16. i'm trying to figure out how to even upload to the SPF, i have vendor and generic compiled, i can see them on the i2c, but from my understanding we need a vendor key? if you can throw me in the right direction that would be awesome!

    1. nvm, pulled some off of nag that worked :)

    2. Could you please share detailed information? :)

    3. the forum has pre compiled ones. if you download them and force the firmware reprogram it will work.

      i dont know how to change the mac however.

  17. How do you actually write to SFP? I have almost a 100 SFP's that need programming from one vendor to other and cannot move from a spot... Anybody to help?

  18. Hi,
    Have you stopped your work on this project ?
    I also need to rewrite to sfp :)
    (Read from one sfp and write to many)

  19. Hi Eoin,
    I know this is an older post, but I'm interested in talking to you privately- I have a few simple questions about this and I think you might be interested in a project I'm getting started with. Please drop me an email at

  20. Hi Eoin,
    Quick question if I may, were you able to locate Cisco vendor keys through, I have had a trawl myself but have been unable to find any. I'm not asking for keys here, but it would be useful to know whether such keys are available in the nag forums, it may save me from making a futile search.
    Also, many thanks for this article, good work :)

  21. This comment has been removed by a blog administrator.

  22. Does anyone know how and what to modify to get an SFP to work in my procurve switch?

    I looked at the russian forum mentioned and can't find a way...


  24. Are you still online Eoin - would be interested in chatting to you about a commercial project. Thanks. Jamie

  25. Was the one capable to write something into EEPROMM in SFP+ using CISCO's TWIG as I haven't succeeded ..?

  26. Hello Eion, where can I contact you? , I am working on my final degree project for the university on a fiber optic monitor equipment, I am trying to implement your demonstration and I want to see if I can get other data such as the measurement of the path of the optical fiber, among other things such as if it were an OTDR but with the sfp using a raspberry pi.

  27. For anyone else, the other SFP cage shares the VCC & ground, so no need to reconnect (you can easily confirm this by measuring the same large gold fingers on the edges). SDA/SDC are on R2 and R46. Solder your wiring behind the resistor like the other one.