- fix for Browser localStorage (thanks to ohmza)
[oscam.git] / csctapi / ifd_mp35.c
blob80590b1a5435d6e1527c72938dbef44e98f73a8a
1 #include "../globals.h"
3 #ifdef CARDREADER_MP35
4 #include "../oscam-time.h"
5 #include "atr.h"
6 #include "ifd_phoenix.h"
7 #include "io_serial.h"
9 #define OK 0
10 #define ERROR 1
12 #define ACK 0x06
13 #define MP35_WRITE_DELAY 100000
14 #define MP35_READ_DELAY 200000
15 #define MP35_BREAK_LENGTH 1200000
17 typedef struct
19 unsigned char current_product;
20 uint16_t product_fw_version;
21 } MP35_info;
23 // Common command for AD-Teknik readers
24 static const unsigned char fw_version[] = {0x2a, 0x41};
26 // Commands for AD-Teknik MP3.5 and MP3.6
27 //static const unsigned char power_always_on[] = {0x2a, 0x8a};
28 //static const unsigned char set_vpp[] = {0x2a, 0x42};
29 //static const unsigned char set_data[] = {0x2a, 0x43};
30 //static const unsigned char set_oscillator[] = {0x2a, 0x5e};
31 //static const unsigned char terminate_com[] = {0x2a, 0x7b};
32 //static const unsigned char transthrough_mode[] = {0x2a, 0x7c};
33 static const unsigned char phoenix_mode[] = {0x2a, 0x7d};
34 //static const unsigned char smartmouse_mode[] = {0x2a, 0x7e};
35 static const unsigned char phoenix_6mhz_mode[] = {0x2a, 0x9a};
36 //static const unsigned char smartmouse_6mhz_mode[] = {0x2a, 0x9b};
37 static const unsigned char fw_info[] = {0x2a, 0xa2};
39 // Commands for AD-Teknik USB Phoenix
40 static const unsigned char set_mode_osc[] = {0x2a, 0x42};
41 static const unsigned char exit_program_mode[] = {0x2a, 0x43};
43 static const struct product
45 unsigned char code;
46 const char *product_name;
47 } product_codes[] =
49 {0x10, "USB Phoenix"},
50 {0x40, "MP3.4"},
51 {0x41, "MP3.5"},
52 {0x42, "MP3.6 USB"}
55 static int32_t mp35_product_info(struct s_reader *reader, unsigned char high, unsigned char low, unsigned char code, MP35_info *info)
57 int32_t i;
59 for(i = 0; i < (int)(sizeof(product_codes) / sizeof(struct product)); i++)
61 if(product_codes[i].code == code)
63 rdr_log(reader, "%s: %s - FW:%02d.%02d", __func__, product_codes[i].product_name, high, low);
64 info->current_product = code;
65 info->product_fw_version = (high << 8) | low;
66 return OK;
70 return ERROR;
73 static int32_t mp35_reader_init(struct s_reader *reader)
75 MP35_info reader_info;
76 unsigned char rec_buf[32];
77 unsigned char parameter;
78 int32_t original_mhz;
79 int32_t original_cardmhz;
81 rdr_log(reader, "%s: started", __func__);
83 original_mhz = reader->mhz;
84 original_cardmhz = reader->cardmhz;
86 // MP3.5 commands should be always be written using 9600 baud at 3.57MHz
87 reader->mhz = 357;
88 reader->cardmhz = 357;
90 int32_t dtr = IO_SERIAL_HIGH;
91 int32_t cts = IO_SERIAL_HIGH;
93 call(IO_Serial_SetParams(reader, 9600, 8, PARITY_NONE, 1, &dtr, &cts));
95 IO_Serial_Sendbreak(reader, MP35_BREAK_LENGTH);
96 IO_Serial_DTR_Clr(reader);
97 IO_Serial_DTR_Set(reader);
98 cs_sleepms(200);
99 IO_Serial_RTS_Set(reader);
100 IO_Serial_Flush(reader);
102 memset(rec_buf, 0x00, sizeof(rec_buf));
103 call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 1000000, 2, fw_version));
104 call(IO_Serial_Read(reader, MP35_READ_DELAY, 1000000, 4, rec_buf));
105 if(rec_buf[3] != ACK)
107 rdr_log_dbg(reader, D_IFD, "Failed MP35 command: fw_version");
108 return ERROR;
111 if(mp35_product_info(reader, rec_buf[1], rec_buf[0], rec_buf[2], &reader_info) != OK)
113 rdr_log(reader, "%s: unknown product code", __func__);
114 return ERROR;
117 if(reader_info.current_product == 0x10) // USB Phoenix
119 if(original_mhz == 357)
121 rdr_log(reader, "%s: Using oscillator 1 (3.57MHz)", __func__);
122 parameter = 0x01;
124 else if(original_mhz == 368)
126 rdr_log(reader, "%s: Using oscillator 2 (3.68MHz)", __func__);
127 parameter = 0x02;
129 else if(original_mhz == 600)
131 rdr_log(reader, "%s: Using oscillator 3 (6.00MHz)", __func__);
132 parameter = 0x03;
134 else
136 rdr_log(reader, "%s: MP35 support only mhz=357, mhz=368 or mhz=600", __func__);
137 rdr_log(reader, "%s: Forced oscillator 1 (3.57MHz)", __func__);
138 parameter = 0x01;
139 original_mhz = 357;
141 memset(rec_buf, 0x00, sizeof(rec_buf));
142 call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 1000000, 2, set_mode_osc));
143 call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 1000000, 1, &parameter));
144 call(IO_Serial_Read(reader, MP35_READ_DELAY, 1000000, 1, rec_buf)); // Read ACK from previous command
145 if(rec_buf[0] != ACK)
147 rdr_log_dbg(reader, D_IFD, "Failed MP35 command: set_mode_osc");
148 return ERROR;
150 rdr_log_dbg(reader, D_IFD, "%s: Leaving programming mode", __func__);
151 memset(rec_buf, 0x00, sizeof(rec_buf));
152 call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 1000000, 2, exit_program_mode));
153 call(IO_Serial_Read(reader, MP35_READ_DELAY, 1000000, 1, rec_buf));
154 if(rec_buf[0] != ACK)
156 rdr_log_dbg(reader, D_IFD, "Failed MP35 command: exit_program_mode");
157 return ERROR;
160 else //MP3.5 or MP3.6
162 if(reader_info.product_fw_version >= 0x0500)
164 int32_t info_len;
165 char info[sizeof(rec_buf) - 2];
167 memset(rec_buf, 0x00, sizeof(rec_buf));
168 call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 1000000, 2, fw_info));
169 call(IO_Serial_Read(reader, MP35_READ_DELAY, 1000000, 1, rec_buf));
170 info_len = rec_buf[0];
171 call(IO_Serial_Read(reader, MP35_READ_DELAY, 1000000, info_len + 1, rec_buf));
172 if(rec_buf[info_len] != ACK)
174 rdr_log_dbg(reader, D_IFD, "Failed MP35 command: fw_info");
175 return ERROR;
177 memcpy(info, rec_buf, info_len);
178 info[info_len] = '\0';
179 rdr_log(reader, "%s: FW Info - %s", __func__, info);
182 memset(rec_buf, 0x00, sizeof(rec_buf));
183 if(original_mhz == 357)
185 rdr_log(reader, "%s: Using oscillator 1 (3.57MHz)", __func__);
186 call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 1000000, 2, phoenix_mode));
188 else if(original_mhz == 600)
190 rdr_log(reader, "%s: Using oscillator 2 (6.00MHz)", __func__);
191 call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 1000000, 2, phoenix_6mhz_mode));
193 else
195 rdr_log(reader, "%s: MP35 support only mhz=357 or mhz=600", __func__);
196 rdr_log(reader, "%s: Forced oscillator 1 (3.57MHz)", __func__);
197 call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 1000000, 2, phoenix_mode));
198 original_mhz = 357;
200 tcdrain(reader->handle);
203 // We might have switched oscillator here
204 reader->mhz = original_mhz;
205 reader->cardmhz = original_cardmhz;
207 /* Default serial port settings */
208 if(reader->atr[0] == 0)
210 IO_Serial_Flush(reader);
211 call(IO_Serial_SetParams(reader, DEFAULT_BAUDRATE, 8, PARITY_EVEN, 2, NULL, NULL));
214 return OK;
217 static int32_t mp35_close(struct s_reader *reader)
219 rdr_log_dbg(reader, D_IFD, "Closing MP35 device %s", reader->device);
221 IO_Serial_DTR_Clr(reader);
222 IO_Serial_Close(reader);
224 return OK;
227 static int32_t mp35_init(struct s_reader *reader)
229 reader->handle = open(reader->device, O_RDWR | O_NOCTTY | O_NONBLOCK);
230 if(reader->handle < 0)
232 rdr_log(reader, "ERROR: Opening device %s (errno=%d %s)",
233 reader->device, errno, strerror(errno));
234 return ERROR;
236 if(IO_Serial_SetParams(reader, DEFAULT_BAUDRATE, 8, PARITY_EVEN, 2, NULL, NULL))
237 { return ERROR; }
239 if(mp35_reader_init(reader))
241 rdr_log(reader, "ERROR: mp35_reader_init returned error");
242 mp35_close(reader);
243 return ERROR;
245 return OK;
248 const struct s_cardreader cardreader_mp35 =
250 .desc = "mp35",
251 .typ = R_MOUSE,
252 .flush = 1,
253 .need_inverse = 1,
254 .read_written = 1,
255 .reader_init = mp35_init,
256 .get_status = IO_Serial_GetStatus,
257 .activate = Phoenix_Reset,
258 .transmit = IO_Serial_Transmit,
259 .receive = IO_Serial_Receive,
260 .close = mp35_close,
261 .set_parity = IO_Serial_SetParity,
262 .set_baudrate = IO_Serial_SetBaudrate,
265 #endif