// // Copyright 2019 Ettus Research, a National Instruments Brand // // SPDX-License-Identifier: GPL-3.0-or-later // #include "common_helpers.h" #include "common_const.h" #include "common_descriptors.h" #define UNREAD 0xFFFF /* Check the rev, magic value, and eeprom compatibility field to determine if our eeprom map is up-to-date with what is written on the device */ int eeprom_is_readable(eeprom_read_t read_fn) { /* Only check this once, then store that info */ static int is_readable = UNREAD; if (is_readable != UNREAD) { return is_readable; } int rev = get_rev(read_fn); if (rev == EEPROM_REV_UNRECOGNIZED) { is_readable = 0; return is_readable; } /* If rev is 0, there's no further checks available */ if (rev == 0) { is_readable = 1; return is_readable; } /* For rev 1, check the EEPROM magic value and compat number */ if (rev == 1) { { uint8_t buffer[EEPROM_MAGIC_LENGTH]; read_fn(EEPROM_REV1_MAGIC_ADDR, buffer, EEPROM_MAGIC_LENGTH); if ((buffer[1] << 8 | buffer[0]) != EEPROM_EXPECTED_MAGIC) { is_readable = 0; return is_readable; } } { uint8_t buffer[EEPROM_COMPAT_LENGTH]; read_fn(EEPROM_REV1_COMPAT_ADDR, buffer, EEPROM_COMPAT_LENGTH); if ((buffer[1] << 8 | buffer[0]) > EEPROM_EXPECTED_COMPAT) { is_readable = 0; return is_readable; } } is_readable = 1; return is_readable; } /* some other unrecognized rev */ is_readable = 0; return is_readable; } /* Read the EEPROM layout revision number from EEPROM using the function specified */ int get_rev(eeprom_read_t read_fn) { /* Only check the rev once, then store that info */ static int rev = UNREAD; if (rev != UNREAD) { return rev; } uint8_t buffer[EEPROM_SIGNATURE_LENGTH]; read_fn(EEPROM_SIGNATURE_ADDR, buffer, EEPROM_SIGNATURE_LENGTH); const uint32_t signature = buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0]; if (signature == EEPROM_REV0_SIGNATURE) { rev = 0; } else if (signature == EEPROM_REV1_OR_GREATER_SIGNATURE) { rev = 1; } else { rev = EEPROM_REV_UNRECOGNIZED; } return rev; } /* Read the vendor ID from EEPROM using the function specified*/ uint16_t get_vid(eeprom_read_t read_fn) { static uint16_t vid = UNREAD; if (vid != UNREAD) { return vid; } if (!eeprom_is_readable(read_fn)) { vid = VID_CYPRESS; return vid; } // eeprom_is_readable guarantees rev is valid int rev = get_rev(read_fn); const uint16_t addr = (rev == 0) ? EEPROM_REV0_VID_ADDR : EEPROM_REV1_VID_ADDR; uint8_t buffer[EEPROM_VID_LENGTH]; read_fn(addr, buffer, EEPROM_VID_LENGTH); vid = buffer[1] << 8 | buffer[0]; return vid; } /* Read the product ID from EEPROM using the function specified*/ uint16_t get_pid(eeprom_read_t read_fn) { static uint16_t pid = UNREAD; if (pid != UNREAD) { return pid; } if (!eeprom_is_readable(read_fn)) { pid = PID_CYPRESS_DEFAULT; return pid; } // eeprom_is_readable guarantees rev is valid int rev = get_rev(read_fn); const uint16_t addr = (rev == 0) ? EEPROM_REV0_PID_ADDR : EEPROM_REV1_PID_ADDR; uint8_t buffer[EEPROM_PID_LENGTH]; read_fn(addr, buffer, EEPROM_PID_LENGTH); pid = buffer[1] << 8 | buffer[0]; return pid; } /* Read the vendor ID from EEPROM using the function specified */ const uint8_t* get_serial_string_descriptor(eeprom_read_t read_fn) { static uint8_t* serial_string_descriptor = 0; if (serial_string_descriptor) { return serial_string_descriptor; } /* All code paths will eventually return this value, but some will modify it beforehand */ serial_string_descriptor = common_dev_serial_desc; if (!eeprom_is_readable(read_fn)) { return serial_string_descriptor; } // eeprom_is_readable guarantees rev is valid int rev = get_rev(read_fn); const uint16_t addr = (rev == 0) ? EEPROM_REV0_SERIAL_ADDR : EEPROM_REV1_SERIAL_ADDR; uint8_t buffer[EEPROM_SERIAL_LENGTH]; read_fn(addr, buffer, EEPROM_SERIAL_LENGTH); int i; for (i = 0; i < EEPROM_SERIAL_LENGTH; ++i) { common_dev_serial_desc[2 + i * 2] = buffer[i]; } return serial_string_descriptor; } /* Return the string descriptor based on the VID given */ const uint8_t* get_manufacturer_string_descriptor(uint16_t vid) { if (vid == VID_ETTUS_RESEARCH) { return common_ettus_manufacturer_desc; } else if (vid == VID_NATIONAL_INSTRUMENTS) { return common_ni_manufacturer_desc; } else { return common_unknown_desc; } } /* Return the string descriptor based on the PID given */ const uint8_t* get_product_string_descriptor(uint16_t pid) { if (pid == PID_ETTUS_B200_B210) { return common_b200_product_desc; } else if (pid == PID_NI_USRP_2900) { return common_niusrp_2900_product_desc; } else if (pid == PID_NI_USRP_2901) { return common_niusrp_2901_product_desc; } else { return common_unknown_desc; } }