source: trunk/csctapi/ifd_mp35.c@ 4149

Last change on this file since 4149 was 4149, checked in by dingo35, 12 years ago

checked some routines on threadsafety

File size: 5.9 KB
Line 
1#include "../globals.h"
2#include "icc_async.h"
3#include "io_serial.h"
4#include <termios.h>
5
6#define ACK 0x06
7#define MP35_WRITE_DELAY 100
8#define MP35_READ_DELAY 200
9#define MP35_BREAK_LENGTH 1200
10
11typedef struct
12{
13 BYTE current_product;
14 ushort product_fw_version;
15} MP35_info;
16
17// Common command for AD-Teknik readers
18static const BYTE fw_version[] = {0x2a, 0x41};
19
20// Commands for AD-Teknik MP3.5 and MP3.6
21static const BYTE power_always_on[] = {0x2a, 0x8a};
22static const BYTE set_vpp[] = {0x2a, 0x42};
23static const BYTE set_data[] = {0x2a, 0x43};
24static const BYTE set_oscillator[] = {0x2a, 0x5e};
25static const BYTE terminate_com[] = {0x2a, 0x7b};
26static const BYTE transthrough_mode[] = {0x2a, 0x7c};
27static const BYTE phoenix_mode[] = {0x2a, 0x7d};
28static const BYTE smartmouse_mode[] = {0x2a, 0x7e};
29static const BYTE phoenix_6mhz_mode[] = {0x2a, 0x9a};
30static const BYTE smartmouse_6mhz_mode[] = {0x2a, 0x9b};
31static const BYTE fw_info[] = {0x2a, 0xa2};
32
33// Commands for AD-Teknik USB Phoenix
34static const BYTE set_mode_osc[] = {0x2a, 0x42};
35static const BYTE exit_program_mode[] = {0x2a, 0x43};
36
37static const struct product { BYTE code; const char* product_name; } product_codes[] = {
38 {0x10, "USB Phoenix"},
39 {0x40, "MP3.4"},
40 {0x41, "MP3.5"},
41 {0x42, "MP3.6 USB"}};
42
43static BYTE current_product;
44
45static int MP35_product_info(BYTE high, BYTE low, BYTE code, MP35_info* info)
46{
47 int i;
48
49 for(i = 0; i < (int)(sizeof(product_codes) / sizeof(struct product)); i++)
50 {
51 if(product_codes[i].code == code)
52 {
53 cs_log("MP35_Init: %s - FW:%02d.%02d", product_codes[i].product_name, high, low);
54 info->current_product = code;
55 info->product_fw_version = (high << 8) | low;
56 return OK;
57 }
58 }
59
60 return ERROR;
61}
62
63int MP35_Init(struct s_reader * reader)
64{
65 MP35_info reader_info;
66 BYTE rec_buf[32];
67 BYTE parameter;
68 int original_mhz;
69
70 cs_debug_mask (D_IFD, "IFD: Initializing MP35 reader %s", reader->label);
71
72 current_product = 0;
73 original_mhz = reader->mhz; // MP3.5 commands should be always be written using 9600 baud at 3.58MHz
74 reader->mhz = 357;
75
76 call(IO_Serial_SetParams(reader, 9600, 8, PARITY_NONE, 1, IO_SERIAL_HIGH, IO_SERIAL_HIGH));
77
78 IO_Serial_Sendbreak(reader, MP35_BREAK_LENGTH);
79 IO_Serial_DTR_Clr(reader);
80 IO_Serial_DTR_Set(reader);
81 cs_sleepms(200);
82 IO_Serial_Flush(reader);
83
84 memset(rec_buf, 0x00, sizeof(rec_buf));
85 call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2, fw_version));
86 call(IO_Serial_Read(reader, MP35_READ_DELAY, 4, rec_buf));
87 if(rec_buf[3] != ACK)
88 {
89 cs_debug_mask (D_IFD, "IFD: Failed MP35 command: fw_version");
90 return ERROR;
91 }
92
93 if(MP35_product_info(rec_buf[1], rec_buf[0], rec_buf[2], &reader_info) != OK)
94 {
95 cs_log("MP35_Init: unknown product code");
96 return ERROR;
97 }
98
99 if(reader_info.current_product == 0x10) // USB Phoenix
100 {
101 if(original_mhz == 357)
102 {
103 cs_log("MP35_Init: Using oscillator 1 (3.57MHz)");
104 parameter = 0x01;
105 }
106 else if(original_mhz == 368)
107 {
108 cs_log("MP35_Init: Using oscillator 2 (3.68MHz)");
109 parameter = 0x02;
110 }
111 else if(original_mhz == 600)
112 {
113 cs_log("MP35_Init: Using oscillator 3 (6.00MHz)");
114 parameter = 0x03;
115 }
116 else
117 {
118 cs_log("MP35_Init: MP35 support only mhz=357, mhz=368 or mhz=600");
119 cs_log("MP35_Init: Forced oscillator 1 (3.57MHz)");
120 parameter = 0x01;
121 original_mhz = 357;
122 }
123 memset(rec_buf, 0x00, sizeof(rec_buf));
124 call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2, set_mode_osc));
125 call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 1, &parameter));
126 call(IO_Serial_Read(reader, MP35_READ_DELAY, 1, rec_buf)); // Read ACK from previous command
127 if(rec_buf[0] != ACK)
128 {
129 cs_debug_mask (D_IFD, "IFD: Failed MP35 command: set_mode_osc");
130 return ERROR;
131 }
132 cs_log("MP35_Init: Leaving programming mode");
133 memset(rec_buf, 0x00, sizeof(rec_buf));
134 call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2, exit_program_mode));
135 call(IO_Serial_Read(reader, MP35_READ_DELAY, 1, rec_buf));
136 if(rec_buf[0] != ACK)
137 {
138 cs_debug_mask (D_IFD, "IFD: Failed MP35 command: exit_program_mode");
139 return ERROR;
140 }
141 }
142 else //MP3.5 or MP3.6
143 {
144 if(reader_info.product_fw_version >= 0x0500)
145 {
146 int info_len;
147 char info[sizeof(rec_buf) - 2];
148
149 memset(rec_buf, 0x00, sizeof(rec_buf));
150 call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2, fw_info));
151 call(IO_Serial_Read(reader, MP35_READ_DELAY, 1, rec_buf));
152 info_len = rec_buf[0];
153 call(IO_Serial_Read(reader, MP35_READ_DELAY, info_len + 1, rec_buf));
154 if(rec_buf[info_len] != ACK)
155 {
156 cs_debug_mask (D_IFD, "IFD: Failed MP35 command: fw_info");
157 return ERROR;
158 }
159 memcpy(info, rec_buf, info_len);
160 info[info_len] = '\0';
161 cs_log("MP35_Init: FW Info - %s", info);
162 }
163
164 memset(rec_buf, 0x00, sizeof(rec_buf));
165 if(original_mhz == 357)
166 {
167 cs_log("MP35_Init: Using oscillator 1 (3.57MHz)");
168 call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2, phoenix_mode));
169 }
170 else if(original_mhz == 600)
171 {
172 cs_log("MP35_Init: Using oscillator 2 (6.00MHz)");
173 call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2, phoenix_6mhz_mode));
174 }
175 else
176 {
177 cs_log("MP35_Init: MP35 support only mhz=357 or mhz=600");
178 cs_log("MP35_Init: Forced oscillator 1 (3.57MHz)");
179 call(IO_Serial_Write(reader, MP35_WRITE_DELAY, 2, phoenix_mode));
180 original_mhz = 357;
181 }
182 }
183
184 reader->mhz = original_mhz; // We might have switched oscillator here
185 current_product = reader_info.current_product;
186 IO_Serial_Flush(reader);
187
188 return OK;
189}
190
191int MP35_Close(struct s_reader * reader)
192{
193 cs_debug_mask (D_IFD, "IFD: Closing MP35 device %s", reader->device);
194
195 if(current_product != 0x10) // USB Phoenix
196 {
197 IO_Serial_Sendbreak(reader, MP35_BREAK_LENGTH);
198 IO_Serial_DTR_Clr(reader);
199 }
200
201 IO_Serial_Close(reader);
202
203 return OK;
204}
Note: See TracBrowser for help on using the repository browser.