Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | // SPDX-License-Identifier: GPL-2.0 /* * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III * flexcop-eeprom.c - eeprom access methods (currently only MAC address reading) * see flexcop.c for copyright information */ #include "flexcop.h" #if 0 /*EEPROM (Skystar2 has one "24LC08B" chip on board) */ static int eeprom_write(struct adapter *adapter, u16 addr, u8 *buf, u16 len) { return flex_i2c_write(adapter, 0x20000000, 0x50, addr, buf, len); } static int eeprom_lrc_write(struct adapter *adapter, u32 addr, u32 len, u8 *wbuf, u8 *rbuf, int retries) { int i; for (i = 0; i < retries; i++) { if (eeprom_write(adapter, addr, wbuf, len) == len) { if (eeprom_lrc_read(adapter, addr, len, rbuf, retries) == 1) return 1; } } return 0; } /* These functions could be used to unlock SkyStar2 cards. */ static int eeprom_writeKey(struct adapter *adapter, u8 *key, u32 len) { u8 rbuf[20]; u8 wbuf[20]; if (len != 16) return 0; memcpy(wbuf, key, len); wbuf[16] = 0; wbuf[17] = 0; wbuf[18] = 0; wbuf[19] = calc_lrc(wbuf, 19); return eeprom_lrc_write(adapter, 0x3e4, 20, wbuf, rbuf, 4); } static int eeprom_readKey(struct adapter *adapter, u8 *key, u32 len) { u8 buf[20]; if (len != 16) return 0; if (eeprom_lrc_read(adapter, 0x3e4, 20, buf, 4) == 0) return 0; memcpy(key, buf, len); return 1; } static char eeprom_set_mac_addr(struct adapter *adapter, char type, u8 *mac) { u8 tmp[8]; if (type != 0) { tmp[0] = mac[0]; tmp[1] = mac[1]; tmp[2] = mac[2]; tmp[3] = mac[5]; tmp[4] = mac[6]; tmp[5] = mac[7]; } else { tmp[0] = mac[0]; tmp[1] = mac[1]; tmp[2] = mac[2]; tmp[3] = mac[3]; tmp[4] = mac[4]; tmp[5] = mac[5]; } tmp[6] = 0; tmp[7] = calc_lrc(tmp, 7); if (eeprom_write(adapter, 0x3f8, tmp, 8) == 8) return 1; return 0; } static int flexcop_eeprom_read(struct flexcop_device *fc, u16 addr, u8 *buf, u16 len) { return fc->i2c_request(fc,FC_READ,FC_I2C_PORT_EEPROM,0x50,addr,buf,len); } #endif static u8 calc_lrc(u8 *buf, int len) { int i; u8 sum = 0; for (i = 0; i < len; i++) sum = sum ^ buf[i]; return sum; } static int flexcop_eeprom_request(struct flexcop_device *fc, flexcop_access_op_t op, u16 addr, u8 *buf, u16 len, int retries) { int i,ret = 0; u8 chipaddr = 0x50 | ((addr >> 8) & 3); for (i = 0; i < retries; i++) { ret = fc->i2c_request(&fc->fc_i2c_adap[1], op, chipaddr, addr & 0xff, buf, len); if (ret == 0) break; } return ret; } static int flexcop_eeprom_lrc_read(struct flexcop_device *fc, u16 addr, u8 *buf, u16 len, int retries) { int ret = flexcop_eeprom_request(fc, FC_READ, addr, buf, len, retries); if (ret == 0) if (calc_lrc(buf, len - 1) != buf[len - 1]) ret = -EINVAL; return ret; } /* JJ's comment about extended == 1: it is not presently used anywhere but was * added to the low-level functions for possible support of EUI64 */ int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended) { u8 buf[8]; int ret = 0; if ((ret = flexcop_eeprom_lrc_read(fc,0x3f8,buf,8,4)) == 0) { if (extended != 0) { err("TODO: extended (EUI64) MAC addresses aren't completely supported yet"); ret = -EINVAL; } else memcpy(fc->dvb_adapter.proposed_mac,buf,6); } return ret; } EXPORT_SYMBOL(flexcop_eeprom_check_mac_addr); |