diff --git a/agent/device/device.cc b/agent/device/device.cc
new file mode 100644
index 0000000..c6f4cbf
--- /dev/null
+++ b/agent/device/device.cc
@@ -0,0 +1,369 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "device.h"
+#include "vendor.h"
+#include "core_utils.h"
+
+using namespace std;
+
+// PonTrxBase class member function definitions
+// Note: 'cout' logger has been used in this file instead of OPENOLT_LOG
+// because the logger task may not be initialized in the openolt core module
+// before PonTrx module is initialized in the main handler. In that case,
+// any OPENOLT_LOG logger (which internally uses BCM_LOG) will not be logged.
+
+PonTrxBase::PonTrxBase(string eeprom_file_name,
+                       int port_addr,
+                       string eeprom_file_path_name,
+                       string sfp_presence_command) :
+        _eeprom_file_name{eeprom_file_name},
+        _port_addr{port_addr},
+        _eeprom_file_path_format{eeprom_file_path_name},
+        _sfp_presence_command{sfp_presence_command}
+{
+}
+
+PonTrxBase::~PonTrxBase() {
+    for (auto it : _t_data) {
+        delete it;
+    }
+}
+
+// returns the _sfp_presence_data
+const set<int> PonTrxBase::get_sfp_presence_data() {
+    return _sfp_presence_data;
+}
+
+// reads, updates and returns the _sfp_presence_data
+const set<int> PonTrxBase::read_sfp_presence_data() {
+    set<int> sp;
+    // command to read the sfp presence array
+    // The sample output of the command looks like below
+    // root@localhost:~# onlpdump -p
+    // Presence: 0 1 16
+    const string& command = _sfp_presence_command;
+    int status_code = system((command + " > temp.txt").c_str());
+    if (status_code != 0) {
+        perror("error getting sfp presence array from ONL\n");
+        // return the current _sfp_presence_data
+        return _sfp_presence_data;
+    }
+    ifstream ifs("temp.txt");
+    string res = {istreambuf_iterator<char>(ifs), istreambuf_iterator<char>()};
+    ifs.close(); // must close the inout stream so the file can be cleaned up
+    // If there is issue reading the sfp presence array, print error and return existing data
+    if (remove("temp.txt") != 0) {
+        perror("Error deleting temporary file");
+        // return the current sfp presence array
+        return _sfp_presence_data;
+    }
+
+    // parse the output of sfp presence command and read which PON Trx are connected/disconnected now
+    stringstream ss(res);
+    string s;
+    while (getline(ss, s, ' ')) {
+        try {
+            int i = stoi(s);
+            // Set the Trx port index corresponding the PON port to true if it appears on the sfp presence command output
+            if (i < TOTAL_PON_TRX_PORTS) {
+                sp.insert(i);
+            }
+
+        } catch(invalid_argument) {
+            // do nothing
+        } catch(out_of_range) {
+            // do nothing
+        }
+    }
+
+    // If the current _sfp_presence_data is not same the newly read data,
+    // update local copy and also raise an event.
+    if (sp != _sfp_presence_data) {
+        cout << "sfp presence data has been updated\n";
+
+        set<int> sfp_ports_up, sfp_ports_down;
+
+        set_difference(sp.begin(), sp.end(), _sfp_presence_data.begin(), _sfp_presence_data.end(), inserter(sfp_ports_up, sfp_ports_up.begin()));
+        // New SFPs are detected
+        if (sfp_ports_up.size() > 0) {
+            cout << "following pon sfp ports are up: ";
+            for (auto up_it : sfp_ports_up) {
+                cout << up_it << " ";
+            }
+            cout << "\n";
+        }
+        set_difference(_sfp_presence_data.begin(), _sfp_presence_data.end(), sp.begin(), sp.end(), inserter(sfp_ports_down, sfp_ports_down.begin()));
+        // Some SFPs are down
+        if (sfp_ports_down.size() > 0) {
+            cout << "following pon sfp ports are down: \n";
+            for (auto down_it : sfp_ports_down) {
+                cout << down_it << " ";
+            }
+            cout << "\n";
+        }
+
+        // FIXME: raise an event for all the PON Trx ports that have been updated
+        _sfp_presence_data = sp;
+    }
+
+    return _sfp_presence_data;
+}
+
+// reads the EEPROM data. The sfp_index is the bus index corresponding to the PON Trx
+// returns true if success
+bool PonTrxBase::read_eeprom_data_for_sfp(int sfp_index) {
+    ifstream is;
+    int len;
+    array<char, EEPROM_READ_PATH_SIZE> path{};
+    array<unsigned char, EEPROM_DATA_READ_SIZE> data{};
+
+    if (sfp_index >= TOTAL_PON_TRX_PORTS) {
+        perror("invalid pon trx index\n");
+        return false;
+    }
+
+    if (_eeprom_read_path.count(sfp_index) == 0) {
+        _eeprom_read_path[sfp_index] = path;
+        char file_name[PON_TRX_BUS_FORMAT_SIZE];
+        char *tmp_place_holder = new char[PON_TRX_BUS_FORMAT_SIZE];
+        // 4 is max length of _port_addr
+        if ((_eeprom_file_path_format.length() + _eeprom_file_name.length() + 4) > PON_TRX_BUS_FORMAT_SIZE) {
+            cerr << "resultant eeprom file length too long\n";
+            delete []tmp_place_holder;
+            return false;
+        }
+        strcpy(tmp_place_holder, _eeprom_file_path_format.c_str());
+        sprintf(file_name, tmp_place_holder, bus_index[sfp_index], _port_addr, _eeprom_file_name.c_str());
+        memcpy(&_eeprom_read_path[sfp_index][0], file_name, PON_TRX_BUS_FORMAT_SIZE);
+        delete []tmp_place_holder;
+    }
+    cout << "eeprom file to read is: " << _eeprom_read_path[sfp_index].data() << "for sfp " << sfp_index << endl;
+    FILE* fp = fopen(_eeprom_read_path[sfp_index].data(), "rb");
+    if (!fp) {
+        perror("failed to open file");
+        _eeprom_read_path.erase(sfp_index);
+        return false;
+    }
+    _eeprom_data[sfp_index] = data;
+    int val, cnt = 0;
+
+    // Populate EEPROM data
+    while ((val = fgetc(fp)) != EOF && cnt < EEPROM_DATA_READ_SIZE) {
+        _eeprom_data[sfp_index][cnt] = (unsigned char)val;
+        cnt++;
+    }
+    fclose(fp);
+    if (cnt != EEPROM_DATA_READ_SIZE) {
+        cerr << "invalid length of data read:" << cnt << endl;
+        _eeprom_read_path.erase(sfp_index);
+        _eeprom_data.erase(sfp_index);
+        return false;
+    }
+
+    return true;
+}
+
+// decodes the EEPROM data. The sfp_index is the bus index corresponding to the PON Trx
+// returns true if success
+bool PonTrxBase::decode_eeprom_data(int sfp_index) {
+    /*
+    try {
+    */
+
+    trx_data tmp, *store=NULL;
+    tmp.sfp_index = sfp_index;
+
+    // decode vendor name
+    array<unsigned char, EEPROM_VENDOR_NAME_LENGTH> vn{};
+    copy(&_eeprom_data[sfp_index][EEPROM_VENDOR_NAME_START_IDX],
+         &_eeprom_data[sfp_index][EEPROM_VENDOR_NAME_START_IDX] + EEPROM_VENDOR_NAME_LENGTH,
+         &vn[0]);
+    pair<string, bool> res_str = hex_to_ascii_string(vn.data(), vn.max_size());
+    if (!res_str.second) {
+        perror("error decoding vendor name\n");
+        return false;
+    }
+    tmp.vendor_name = res_str.first;
+    cout << "[" << sfp_index << "]" << " vendor name: " << tmp.vendor_name << endl;
+
+
+    // decode vendor oui
+    array<unsigned char, EEPROM_VENDOR_OUI_LENGTH> oui{};
+    copy(&_eeprom_data[sfp_index][EEPROM_VENDOR_OUI_START_IDX],
+         &_eeprom_data[sfp_index][EEPROM_VENDOR_OUI_START_IDX] + EEPROM_VENDOR_OUI_LENGTH,
+         &oui[0]);
+    res_str = hex_to_ascii_string(oui.data(), oui.max_size());
+    if (!res_str.second) {
+        perror("error decoding vendor oui\n");
+        return false;
+    }
+    if (res_str.first.length() == 3) { // vendor_oui length is 3
+        memcpy(tmp.vendor_oui, res_str.first.c_str(), 3);
+    }
+    cout << "[" << sfp_index << "]" << " vendor oui: " << res_str.first << endl;
+
+    // decode vendor part number
+    array<unsigned char, EEPROM_VENDOR_PART_NUMBER_LENGTH> pn{};
+    copy(&_eeprom_data[sfp_index][EEPROM_VENDOR_PART_NUMBER_START_IDX],
+         &_eeprom_data[sfp_index][EEPROM_VENDOR_PART_NUMBER_START_IDX] + EEPROM_VENDOR_PART_NUMBER_LENGTH,
+         &pn[0]);
+    res_str = hex_to_ascii_string(pn.data(), pn.max_size());
+    if (!res_str.second) {
+        perror("error decoding vendor part number\n");
+        return false;
+    }
+    tmp.vendor_part_no = res_str.first;
+    cout << "[" << sfp_index << "]" << " vendor pn: " << tmp.vendor_part_no << endl;
+
+    // decode vendor revision
+    array<unsigned char, EEPROM_VENDOR_REVISION_LENGTH> rev{};
+    copy(&_eeprom_data[sfp_index][EEPROM_VENDOR_REVISION_START_IDX],
+         &_eeprom_data[sfp_index][EEPROM_VENDOR_REVISION_START_IDX] + EEPROM_VENDOR_REVISION_LENGTH,
+         &rev[0]);
+    res_str = hex_to_ascii_string(rev.data(), rev.max_size());
+    if (!res_str.second) {
+        perror("error decoding vendor revision\n");
+        return false;
+    }
+    tmp.vendor_rev = res_str.first;
+    cout << "[" << sfp_index << "]" << " vendor rev: " << tmp.vendor_rev << endl;
+
+    // decode pon wavelength(s)
+    array<unsigned char, EEPROM_DOWNSTREAM_WAVELENGTH_LENGTH> wv{};
+    copy(&_eeprom_data[sfp_index][EEPROM_DOWNSTREAM_WAVELENGTH_START_IDX],
+         &_eeprom_data[sfp_index][EEPROM_DOWNSTREAM_WAVELENGTH_START_IDX] + EEPROM_DOWNSTREAM_WAVELENGTH_LENGTH,
+         &wv[0]);
+    pair<uint32_t, bool> res_uint = hex_to_uinteger(wv.data(), wv.max_size());
+    if (!res_uint.second) {
+        perror("error decoding primary downstream wavelength\n");
+        return false;
+    }
+    tmp.p_data[0].valid = true;
+    tmp.p_data[0].wavelength = res_uint.first * EEPROM_WAVELENGTH_RESOLUTION;
+    tmp.p_data[0].pon_type = get_pon_type_from_wavelength(tmp.p_data[0].wavelength);
+    cout << "[" << sfp_index << "]" << " pon wavelength: " << tmp.p_data[0].wavelength << endl;
+    // TODO: also fill the field pon_type
+
+    // TODO: Let's ignore secondary wavelength decode for now as we do not know how the secondary wavelength is represent on the Combo PON
+    tmp.p_data[1].valid = false;
+
+    store = new(nothrow) trx_data;
+    if (store == NULL) {
+        perror("could not allocate memory for trx_data");
+        return false;
+    }
+
+    // Copy data
+    store->sfp_index = sfp_index;
+    store->vendor_name = tmp.vendor_name;
+    memcpy(store->vendor_oui, tmp.vendor_oui, 3);
+    store->vendor_part_no = tmp.vendor_part_no;
+    store->vendor_rev = tmp.vendor_rev;
+    store->trx_type = tmp.trx_type;
+    for (int i = 0; i < MAX_PONS_PER_TRX; i++) {
+        store->p_data[i].valid = tmp.p_data[i].valid;
+        store->p_data[i].wavelength = tmp.p_data[i].wavelength;
+        store->p_data[i].pon_type = tmp.p_data[i].pon_type;
+    }
+
+    _t_data.insert(store);
+    /*
+    } catch(...) { // FIXME: Put specific exceptions here
+        perror("caught exception\n");
+        return false;
+    }
+    */
+    return true;
+}
+
+bcmolt_pon_type PonTrxBase::get_pon_type_from_wavelength(int wavelength) {
+    bcmolt_pon_type pon_type = BCMOLT_PON_TYPE_UNKNOWN;
+    switch (wavelength) {
+        case GPON_DOWNSTREAM_WAVELENGTH_NM:
+            pon_type = BCMOLT_PON_TYPE_GPON;
+        case XGSPON_DOWNSTREAM_WAVELENGTH_NM:
+            pon_type = BCMOLT_PON_TYPE_XGPON;
+        // Add more in the future as needed.
+    }
+    return pon_type;
+}
+
+bcmolt_pon_type PonTrxBase::get_sfp_mode(int sfp_index) {
+    bcmolt_pon_type pon0_type = BCMOLT_PON_TYPE_UNKNOWN;
+    bcmolt_pon_type pon1_type = BCMOLT_PON_TYPE_UNKNOWN;
+    trx_data *td = NULL;
+    set<trx_data*>::iterator it;
+    // Iterate the trx data set and break if we find a trx data with mathcing sfp index
+    for (it = _t_data.begin(); it != _t_data.end(); it++) {
+        if ((*it)->sfp_index == sfp_index) {
+            td = *it;
+            break;
+        }
+    }
+    if (it == _t_data.end()) {
+        perror("end of iterator, pon type not detected");
+        return pon0_type;
+    }
+    if (td == NULL) {
+        cerr << "trx data is null\n";
+        return pon0_type;
+    }
+
+    // Find the PON type/mode
+    if (td->p_data[0].valid) {
+        pon0_type = td->p_data[0].pon_type;
+        if (pon0_type == BCMOLT_PON_TYPE_UNKNOWN) {
+            return pon0_type;
+        }
+        if (td->p_data[1].valid) {
+            pon1_type = td->p_data[1].pon_type;
+            if (pon1_type == BCMOLT_PON_TYPE_UNKNOWN) {
+                return pon1_type;
+            }
+
+            if  (pon0_type == pon1_type) {
+                return pon0_type;
+            } else {
+                return BCMOLT_PON_TYPE_XGPON_GPON_WDMA; // Combo SFP!
+            }
+        }
+        return pon0_type;
+    }
+
+    return pon0_type;
+}
+
+// Returns the MAC System Mode based on the set of SFP IDs provided.
+// The derived class will most likely need to override this method to provide a
+// different implementation for that particular OLT platform.
+pair<bcmolt_system_mode, bool> PonTrxBase::get_mac_system_mode(int olt_mac_id, set<int> sfp_ids) {
+    bool ret = true;
+    bcmolt_system_mode sm = BCMOLT_SYSTEM_MODE_GPON__16_X;
+
+    return {sm, ret};
+}
+
+// Get trx data for sfp
+trx_data* PonTrxBase::get_trx_data(int sfp_index) {
+    for (auto it : _t_data) {
+        if (it->sfp_index == sfp_index) {
+            cout << "[" << sfp_index << "]" << " found trx data\n";
+            return (it);
+        }
+    }
+    return NULL;
+}
