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