blob: a523285adb31cc1fed819e68d99dda9f3c098b34
1 | #include "CSerialPort.h" |
2 | #include <pthread.h> |
3 | #include "CTvLog.h" |
4 | #include <stdio.h> |
5 | #include <unistd.h> |
6 | #include <stdlib.h> |
7 | #include <sys/types.h> |
8 | #include <sys/stat.h> |
9 | #include <fcntl.h> |
10 | #include <string.h> |
11 | #include <termios.h> |
12 | #include <errno.h> |
13 | |
14 | #include "../tvconfig/tvconfig.h" |
15 | |
16 | CSerialPort::CSerialPort() |
17 | { |
18 | mDevId = -1; |
19 | } |
20 | |
21 | //close it |
22 | CSerialPort::~CSerialPort() |
23 | { |
24 | } |
25 | |
26 | int CSerialPort::OpenDevice(int serial_dev_id) |
27 | { |
28 | int tmp_ret = 0; |
29 | const char *dev_file_name = NULL; |
30 | |
31 | if (getFd() < 0) { |
32 | if (serial_dev_id == SERIAL_A) { |
33 | dev_file_name = DEV_PATH_S0; |
34 | } else if (serial_dev_id == SERIAL_B) { |
35 | dev_file_name = DEV_PATH_S1; |
36 | } else if (serial_dev_id == SERIAL_C) { |
37 | dev_file_name = DEV_PATH_S2; |
38 | } |
39 | |
40 | if (dev_file_name != NULL) { |
41 | mDevId = serial_dev_id; |
42 | tmp_ret = openFile(dev_file_name); |
43 | } |
44 | } |
45 | |
46 | return tmp_ret; |
47 | } |
48 | |
49 | int CSerialPort::CloseDevice() |
50 | { |
51 | mDevId = -1; |
52 | closeFile(); |
53 | |
54 | return 0; |
55 | } |
56 | |
57 | void CSerialPort::set_speed (int fd, int speed) |
58 | { |
59 | int i; |
60 | int status; |
61 | struct termios Opt; |
62 | tcgetattr (fd, &Opt); |
63 | for (i = 0; i < (int)(sizeof (speed_arr) / sizeof (int)); i++) { |
64 | if (speed == name_arr[i]) { |
65 | tcflush (fd, TCIOFLUSH); |
66 | cfsetispeed (&Opt, speed_arr[i]); |
67 | cfsetospeed (&Opt, speed_arr[i]); |
68 | status = tcsetattr (fd, TCSANOW, &Opt); |
69 | if (status != 0) { |
70 | perror ("tcsetattr fd1"); |
71 | return; |
72 | } |
73 | tcflush (fd, TCIOFLUSH); |
74 | } |
75 | } |
76 | } |
77 | |
78 | int CSerialPort::set_Parity (int fd, int databits, int stopbits, int parity) |
79 | { |
80 | struct termios options; |
81 | if (tcgetattr (fd, &options) != 0) { |
82 | perror ("SetupSerial 1"); |
83 | return (0); |
84 | } |
85 | options.c_cflag &= ~CSIZE; |
86 | switch (databits) { |
87 | case 7: |
88 | options.c_cflag |= CS7; |
89 | break; |
90 | case 8: |
91 | options.c_cflag |= CS8; |
92 | break; |
93 | default: |
94 | fprintf (stderr, "Unsupported data size\n"); |
95 | return (0); |
96 | } |
97 | switch (parity) { |
98 | case 'n': |
99 | case 'N': |
100 | options.c_cflag &= ~PARENB; /* Clear parity enable */ |
101 | options.c_iflag &= ~INPCK; /* Enable parity checking */ |
102 | break; |
103 | case 'o': |
104 | case 'O': |
105 | options.c_cflag |= (PARODD | PARENB); |
106 | options.c_iflag |= INPCK; /* Disnable parity checking */ |
107 | break; |
108 | case 'e': |
109 | case 'E': |
110 | options.c_cflag |= PARENB; /* Enable parity */ |
111 | options.c_cflag &= ~PARODD; |
112 | options.c_iflag |= INPCK; /* Disnable parity checking */ |
113 | break; |
114 | case 'S': |
115 | case 's': /*as no parity */ |
116 | options.c_cflag &= ~PARENB; |
117 | options.c_cflag &= ~CSTOPB; |
118 | break; |
119 | default: |
120 | fprintf (stderr, "Unsupported parity\n"); |
121 | return (0); |
122 | } |
123 | |
124 | switch (stopbits) { |
125 | case 1: |
126 | options.c_cflag &= ~CSTOPB; |
127 | break; |
128 | case 2: |
129 | options.c_cflag |= CSTOPB; |
130 | break; |
131 | default: |
132 | fprintf (stderr, "Unsupported stop bits\n"); |
133 | return (0); |
134 | } |
135 | /* Set input parity option */ |
136 | if (parity != 'n') |
137 | options.c_iflag |= INPCK; |
138 | tcflush (fd, TCIFLUSH); |
139 | options.c_cc[VTIME] = 150; |
140 | options.c_cc[VMIN] = 0; /* Update the options and do it NOW */ |
141 | //qd to set raw mode, which is copied from web |
142 | options.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP |
143 | | INLCR | IGNCR | ICRNL | IXON); |
144 | options.c_oflag &= ~OPOST; |
145 | options.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); |
146 | options.c_cflag &= ~(CSIZE | PARENB); |
147 | options.c_cflag |= CS8; |
148 | |
149 | if (tcsetattr (fd, TCSANOW, &options) != 0) { |
150 | perror ("SetupSerial 3"); |
151 | return (0); |
152 | } |
153 | return (1); |
154 | } |
155 | |
156 | int CSerialPort::setup_serial() |
157 | { |
158 | set_speed(mFd, 115200); |
159 | set_Parity(mFd, 8, 1, 'N'); |
160 | return 0; |
161 | } |
162 | |
163 | int CSerialPort::set_opt(int speed, int db, int sb, char pb, int overtime, bool raw_mode) |
164 | { |
165 | int i = 0; |
166 | struct termios old_cfg, new_cfg; |
167 | if (mFd <= 0) { |
168 | LOGE("not open dev, when set opt"); |
169 | return -1; |
170 | } |
171 | //first get it |
172 | if (tcgetattr(mFd, &old_cfg) != 0) { |
173 | LOGE("get serial attr error mFd = %d(%s)!\n", mFd, strerror(errno)); |
174 | return -1; |
175 | } |
176 | |
177 | //set speed |
178 | for (i = 0; i < (int)(sizeof(speed_arr) / sizeof(int)); i++) { |
179 | if (speed == name_arr[i]) { |
180 | cfsetispeed(&new_cfg, speed_arr[i]); |
181 | cfsetospeed(&new_cfg, speed_arr[i]); |
182 | break; |
183 | } |
184 | } |
185 | |
186 | setdatabits(&new_cfg, db); |
187 | setstopbits(&new_cfg, sb); |
188 | setparity(&new_cfg, pb); |
189 | |
190 | |
191 | if (overtime >= 0) { |
192 | new_cfg.c_cc[VTIME] = overtime / 100; /* 设置超时 seconds*/ |
193 | new_cfg.c_cc[VMIN] = 0; /* Update the options and do it NOW */ |
194 | } |
195 | |
196 | if (raw_mode) { |
197 | cfmakeraw(&new_cfg); |
198 | } |
199 | |
200 | //clear |
201 | tcflush(mFd, TCIOFLUSH); |
202 | if (tcsetattr(mFd, TCSANOW, &new_cfg) < 0) { |
203 | LOGE("%s, set serial attr error(%s)!\n", "TV", strerror(errno)); |
204 | return -1; |
205 | } |
206 | //clear,let be avail |
207 | tcflush(mFd, TCIOFLUSH); |
208 | |
209 | return 0; |
210 | } |
211 | |
212 | int CSerialPort::writeFile(const unsigned char *pData, unsigned int uLen) |
213 | { |
214 | unsigned int len; |
215 | len = write(mFd, pData, uLen); |
216 | if (len == uLen) { |
217 | return len; |
218 | } else { |
219 | tcflush(mFd, TCOFLUSH); |
220 | LOGE("write data failed and tcflush hComm\n"); |
221 | return -1; |
222 | } |
223 | } |
224 | |
225 | static int com_read_data(int hComm, unsigned char *pData, unsigned int uLen) |
226 | { |
227 | char inbuff[uLen]; |
228 | char buff[uLen]; |
229 | char tempbuff[uLen]; |
230 | int i = 0, j = 0; |
231 | |
232 | memset(inbuff, '\0', uLen); |
233 | memset(buff, '\0', uLen); |
234 | memset(tempbuff, '\0', uLen); |
235 | |
236 | if (hComm < 0) { |
237 | return -1; |
238 | } |
239 | |
240 | char *p = inbuff; |
241 | |
242 | fd_set readset; |
243 | struct timeval tv; |
244 | int MaxFd = 0; |
245 | |
246 | unsigned int c = 0; |
247 | int z, k; |
248 | |
249 | do { |
250 | FD_ZERO(&readset); |
251 | FD_SET(hComm, &readset); |
252 | MaxFd = hComm + 1; |
253 | tv.tv_sec = 0; |
254 | tv.tv_usec = 100000; |
255 | do { |
256 | z = select(MaxFd, &readset, 0, 0, &tv); |
257 | } while (z == -1 && errno == EINTR); |
258 | |
259 | if (z == -1) { |
260 | hComm = -1; |
261 | break; |
262 | } |
263 | |
264 | if (z == 0) { |
265 | hComm = -1; |
266 | break; |
267 | } |
268 | |
269 | if (FD_ISSET(hComm, &readset)) { |
270 | z = read(hComm, buff, uLen - c); |
271 | #if 0 |
272 | for (k = 0; k < z; k++) { |
273 | LOGD("%s, inbuff[%d]:%02X", "TV", k, buff[k]); |
274 | } |
275 | #endif |
276 | c += z; |
277 | |
278 | if (z > 0) { |
279 | if (z < (signed int) uLen) { |
280 | buff[z + 1] = '\0'; |
281 | memcpy(p, buff, z); |
282 | p += z; |
283 | } else { |
284 | memcpy(inbuff, buff, z); |
285 | } |
286 | |
287 | memset(buff, '\0', uLen); |
288 | } else { |
289 | hComm = -1; |
290 | } |
291 | |
292 | if (c >= uLen) { |
293 | hComm = -1; |
294 | break; |
295 | } |
296 | } |
297 | } while (hComm >= 0); |
298 | |
299 | memcpy(pData, inbuff, c); |
300 | p = NULL; |
301 | return c; |
302 | } |
303 | |
304 | int CSerialPort::readFile(unsigned char *pBuf, unsigned int uLen) |
305 | { |
306 | //using non-block mode |
307 | return com_read_data(mFd, pBuf, uLen); |
308 | } |
309 | |
310 | int CSerialPort::setdatabits(struct termios *s, int db) |
311 | { |
312 | if (db == 5) { |
313 | s->c_cflag = (s->c_cflag & ~CSIZE) | (CS5 & CSIZE); |
314 | } else if (db == 6) { |
315 | s->c_cflag = (s->c_cflag & ~CSIZE) | (CS6 & CSIZE); |
316 | } else if (db == 7) { |
317 | s->c_cflag = (s->c_cflag & ~CSIZE) | (CS7 & CSIZE); |
318 | } else if (db == 8) { |
319 | s->c_cflag = (s->c_cflag & ~CSIZE) | (CS8 & CSIZE); |
320 | } else { |
321 | LOGE("Unsupported data size!\n"); |
322 | } |
323 | return 0; |
324 | } |
325 | |
326 | int CSerialPort::setstopbits(struct termios *s, int sb) |
327 | { |
328 | if (sb == 1) { |
329 | s->c_cflag &= ~CSTOPB; |
330 | } else if (sb == 2) { |
331 | s->c_cflag |= CSTOPB; |
332 | } else { |
333 | LOGE("Unsupported stop bits!\n"); |
334 | } |
335 | return 0; |
336 | } |
337 | |
338 | int CSerialPort::setparity(struct termios *s, char pb) |
339 | { |
340 | if (pb == 'n' || pb == 'N') { |
341 | s->c_cflag &= ~PARENB; /* Clear parity enable */ |
342 | s->c_cflag &= ~INPCK; /* Enable parity checking */ |
343 | } else if (pb == 'o' || pb == 'O') { |
344 | s->c_cflag |= (PARODD | PARENB); |
345 | s->c_cflag |= INPCK; /* Disable parity checking */ |
346 | } else if (pb == 'e' || pb == 'E') { |
347 | s->c_cflag |= PARENB; /* Enable parity */ |
348 | s->c_cflag &= ~PARODD; |
349 | s->c_iflag |= INPCK; /* Disable parity checking */ |
350 | } else if (pb == 's' || pb == 'S') { |
351 | s->c_cflag &= ~PARENB; |
352 | s->c_cflag &= ~CSTOPB; |
353 | s->c_cflag |= INPCK; /* Disable parity checking */ |
354 | } else { |
355 | LOGE("Unsupported parity!\n"); |
356 | } |
357 | return 0; |
358 | } |
359 |