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