upload tizen1.0 source
[framework/telephony/tel-plugin-vmodem.git] / src / vdpram.c
1 /*\r
2  * tel-plugin-vmodem\r
3  *\r
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.\r
5  *\r
6  * Contact: Junhwan An <jh48.an@samsung.com>\r
7  *\r
8  * Licensed under the Apache License, Version 2.0 (the "License");\r
9  * you may not use this file except in compliance with the License.\r
10  * You may obtain a copy of the License at\r
11  *\r
12  * http://www.apache.org/licenses/LICENSE-2.0\r
13  *\r
14  * Unless required by applicable law or agreed to in writing, software\r
15  * distributed under the License is distributed on an "AS IS" BASIS,\r
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
17  * See the License for the specific language governing permissions and\r
18  * limitations under the License.\r
19  */\r
20 \r
21 #include <string.h>\r
22 #include <stdlib.h>\r
23 #include <stdio.h>\r
24 #include <termios.h>\r
25 #include <errno.h>\r
26 #include <sys/time.h>\r
27 #include <sys/mman.h>\r
28 #include <unistd.h>\r
29 #include <fcntl.h>\r
30 #include <sys/ioctl.h>\r
31 \r
32 #include <log.h>\r
33 #include "legacy/TelUtility.h"\r
34 #include "vdpram.h"\r
35 #include "vdpram_dump.h"\r
36 \r
37 #ifndef TIOCMODG\r
38 #  ifdef TIOCMGET\r
39 #    define TIOCMODG TIOCMGET\r
40 #  else\r
41 #    ifdef MCGETA\r
42 #      define TIOCMODG MCGETA\r
43 #    endif\r
44 #  endif\r
45 #endif\r
46 \r
47 #ifndef TIOCMODS\r
48 #  ifdef TIOCMSET\r
49 #    define TIOCMODS TIOCMSET\r
50 #  else\r
51 #    ifdef MCSETA\r
52 #      define TIOCMODS MCSETA\r
53 #    endif\r
54 #  endif\r
55 #endif\r
56 \r
57 typedef struct _tty_old_setting_t{\r
58         int             fd;\r
59         struct  termios  termiosVal;\r
60         struct  _tty_old_setting_t *next;\r
61         struct  _tty_old_setting_t *prev;\r
62 } tty_old_setting_t;\r
63 \r
64 #define VDPRAM_OPEN_PATH                "/dev/dpram/0"\r
65 \r
66 /* DPRAM ioctls for DPRAM tty devices */\r
67 #define IOC_MZ_MAGIC            ('h')\r
68 #define HN_DPRAM_PHONE_ON                       _IO (IOC_MZ_MAGIC, 0xd0)\r
69 #define HN_DPRAM_PHONE_OFF                      _IO (IOC_MZ_MAGIC, 0xd1)\r
70 #define HN_DPRAM_PHONE_GETSTATUS        _IOR(IOC_MZ_MAGIC, 0xd2, unsigned int)\r
71 \r
72 static tty_old_setting_t *ttyold_head = NULL;\r
73 \r
74 /* static functions */\r
75 static void __insert_tty_oldsetting(tty_old_setting_t *me)\r
76 {\r
77         dbg("Function Enterence.");\r
78 \r
79         if (me == NULL)\r
80                 return;\r
81 \r
82         if (ttyold_head)\r
83             ttyold_head->prev = me;\r
84 \r
85         me->next = ttyold_head;\r
86         me->prev = 0;\r
87         ttyold_head = me;\r
88 }\r
89 \r
90 static tty_old_setting_t *__search_tty_oldsetting(int fd)\r
91 {\r
92         tty_old_setting_t *tty = NULL;\r
93 \r
94         dbg("Function Enterence.");\r
95 \r
96         if (ttyold_head == NULL)\r
97                 return NULL;\r
98 \r
99         tty = ttyold_head;\r
100 \r
101         do{\r
102                 if (tty->fd == fd) {\r
103                         dbg("oldsetting for inputted fd is found");\r
104                         break;\r
105                 }\r
106                 else {\r
107                         if (tty->next == NULL) {\r
108                                 dbg("No oldsetting is found");\r
109                                 tty = NULL;\r
110                                 break;\r
111                         }\r
112                         tty = tty->next;\r
113                 }\r
114         }while(1);\r
115 \r
116         return tty;\r
117 }\r
118 \r
119 static void __remove_tty_oldsetting(tty_old_setting_t *me)\r
120 {\r
121         dbg( "Function Enterence.");\r
122 \r
123         if (me == NULL)\r
124                 return;\r
125 \r
126         if (me->prev)\r
127             me->prev->next = me->next;\r
128         else\r
129             ttyold_head = me->next;\r
130 \r
131         if (me->next)\r
132             me->next->prev = me->prev;\r
133 }\r
134 \r
135 /* Set hardware flow control.\r
136 */\r
137 static void __tty_sethwf(int fd, int on)\r
138 {\r
139         struct termios tty;\r
140 \r
141         dbg("Function Enterence.");\r
142 \r
143         if (tcgetattr(fd, &tty))\r
144                 err("__tty_sethwf: tcgetattr:");\r
145 \r
146         if (on)\r
147             tty.c_cflag |= CRTSCTS;\r
148         else\r
149             tty.c_cflag &= ~CRTSCTS;\r
150 \r
151         if (tcsetattr(fd, TCSANOW, &tty))\r
152                 err("__tty_sethwf: tcsetattr:");\r
153 }\r
154 \r
155 /*\r
156 * Set RTS line. Sometimes dropped. Linux specific?\r
157 */\r
158 static int __tty_setrts(int fd)\r
159 {\r
160         int mcs;\r
161 \r
162         dbg("Function Enterence.");\r
163 \r
164         if (-1 ==  ioctl(fd, TIOCMODG, &mcs))\r
165                 err("icotl: TIOCMODG");\r
166 \r
167         mcs |= TIOCM_RTS;\r
168 \r
169         if (-1 == ioctl(fd, TIOCMODS, &mcs))\r
170                 err("icotl: TIOCMODS");\r
171 \r
172         return 0;\r
173 }\r
174 \r
175 /*\r
176  * Set baudrate, parity and number of bits.\r
177  */\r
178 static int __tty_setparms(int fd, char* baudr, char* par, char* bits, char* stop, int hwf, int swf)\r
179 {\r
180         int spd = -1;\r
181         int newbaud;\r
182         int bit = bits[0];\r
183         int stop_bit = stop[0];\r
184 \r
185         struct termios tty;\r
186         tty_old_setting_t *old_setting = NULL;\r
187 \r
188         dbg("Function Enterence.");\r
189 \r
190         old_setting = calloc(sizeof(tty_old_setting_t), 1);\r
191 \r
192         if (old_setting == NULL)\r
193                 return TAPI_API_SYSTEM_OUT_OF_MEM;\r
194 \r
195         old_setting->fd = fd;\r
196 \r
197         if (tcgetattr(fd, &tty) < 0) {\r
198                 free(old_setting);\r
199                 return TAPI_API_TRANSPORT_LAYER_FAILURE;\r
200         }\r
201 \r
202         if (tcgetattr(fd, &old_setting->termiosVal) < 0) {\r
203                 free(old_setting);\r
204                 return TAPI_API_TRANSPORT_LAYER_FAILURE;\r
205         }\r
206 \r
207         __insert_tty_oldsetting(old_setting);\r
208 \r
209         fflush(stdout);\r
210 \r
211         /* We generate mark and space parity ourself. */\r
212         if (bit == '7' && (par[0] == 'M' || par[0] == 'S'))\r
213                 bit = '8';\r
214 \r
215         /* Check if 'baudr' is really a number */\r
216         if ((newbaud = (atol(baudr) / 100)) == 0 && baudr[0] != '0')\r
217                 newbaud = -1;\r
218 \r
219         switch(newbaud)\r
220         {\r
221                 case 0:\r
222                         spd = 0;\r
223                         break;\r
224 \r
225                 case 3:\r
226                         spd = B300;\r
227                         break;\r
228 \r
229                 case 6:\r
230                         spd = B600;\r
231                         break;\r
232 \r
233                 case 12:\r
234                         spd = B1200;\r
235                         break;\r
236 \r
237                 case 24:\r
238                         spd = B2400;\r
239                         break;\r
240 \r
241                 case 48:\r
242                         spd = B4800;\r
243                         break;\r
244 \r
245                 case 96:\r
246                         spd = B9600;\r
247                         break;\r
248 \r
249                 case 192:\r
250                         spd = B19200;\r
251                         break;\r
252 \r
253                 case 384:\r
254                         spd = B38400;\r
255                         break;\r
256 \r
257                 case 576:\r
258                         spd = B57600;\r
259                         break;\r
260 \r
261                 case 1152:\r
262                         spd = B115200;\r
263                         break;\r
264 \r
265                 default:\r
266                         err("invaid baud rate");\r
267                         break;\r
268         }\r
269 \r
270         if (spd != -1) {\r
271             cfsetospeed(&tty, (speed_t) spd);\r
272             cfsetispeed(&tty, (speed_t) spd);\r
273         }\r
274 \r
275         switch(bit)\r
276         {\r
277             case '5':\r
278                 tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS5;\r
279                 break;\r
280 \r
281             case '6':\r
282                 tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS6;\r
283                 break;\r
284 \r
285             case '7':\r
286                 tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS7;\r
287                 break;\r
288 \r
289             case '8':\r
290             default:\r
291                 tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;\r
292                 break;\r
293         }\r
294 \r
295         switch(stop_bit)\r
296         {\r
297             case '1':\r
298                 tty.c_cflag &= ~CSTOPB;\r
299                 break;\r
300 \r
301             case '2':\r
302             default:\r
303                 tty.c_cflag |= CSTOPB;\r
304                 break;\r
305         }\r
306 \r
307         /* Set into raw, no echo mode */\r
308         tty.c_iflag = IGNBRK;\r
309         tty.c_lflag = 0;\r
310         tty.c_oflag = 0;\r
311         tty.c_cflag |= CLOCAL | CREAD;\r
312         tty.c_cc[VMIN] = 1;\r
313         tty.c_cc[VTIME] = 1;\r
314 \r
315         if (swf)\r
316             tty.c_iflag |= IXON | IXOFF;\r
317         else\r
318             tty.c_iflag &= ~(IXON | IXOFF | IXANY);\r
319 \r
320         tty.c_cflag &= ~(PARENB | PARODD);\r
321 \r
322         if (par[0] == 'E')\r
323             tty.c_cflag |= PARENB;\r
324         else if (par[0] == 'O')\r
325             tty.c_cflag |= (PARENB | PARODD);\r
326 \r
327         if (tcsetattr(fd, TCSANOW, &tty) < 0) {\r
328                 free(old_setting);\r
329             return TAPI_API_TRANSPORT_LAYER_FAILURE;\r
330         }\r
331 \r
332         __tty_setrts(fd);\r
333         __tty_sethwf(fd, hwf);\r
334 \r
335         return TAPI_API_SUCCESS;\r
336 \r
337 }\r
338 \r
339 static int __tty_close(int fd)\r
340 {\r
341         tty_old_setting_t *old_setting = NULL;\r
342 \r
343         dbg("Function Enterence.");\r
344 \r
345         old_setting = __search_tty_oldsetting(fd);\r
346         if (old_setting == NULL)\r
347                 return TAPI_API_SUCCESS;\r
348 \r
349         if (tcsetattr(fd, TCSAFLUSH, &old_setting->termiosVal) < 0)     {\r
350                 err("close failed");\r
351                 return TAPI_API_TRANSPORT_LAYER_FAILURE;\r
352         }\r
353 \r
354         __remove_tty_oldsetting(old_setting);\r
355 \r
356         free(old_setting);\r
357 \r
358         close(fd);\r
359 \r
360         return TAPI_API_SUCCESS;\r
361 }\r
362 \r
363 /*\r
364 * restore the old settings before close.\r
365 */\r
366 int vdpram_close(int fd)\r
367 {\r
368         int ret = TAPI_API_SUCCESS;\r
369 \r
370         dbg("Function Enterence.");\r
371 \r
372         ret = __tty_close(fd);\r
373 \r
374         return ret;\r
375 }\r
376 \r
377 /*\r
378 *       Open the vdpram fd.\r
379 */\r
380 int vdpram_open (void)\r
381 {\r
382         int rv = -1;\r
383         int fd = -1;\r
384         int val = 0;\r
385         unsigned int cmd =0;\r
386 \r
387         fd = open(VDPRAM_OPEN_PATH, O_RDWR);\r
388 \r
389         if (fd < 0) {\r
390                 err("#### Failed to open vdpram file: error no hex %x", errno);\r
391                 return rv;\r
392         }\r
393         else\r
394                 dbg("#### Success to open vdpram file. fd:%d, path:%s", fd, VDPRAM_OPEN_PATH);\r
395 \r
396 \r
397         if (__tty_setparms(fd, "115200", "N", "8", "1", 0, 0) != TAPI_API_SUCCESS) {\r
398                 vdpram_close(fd);\r
399                 return rv;\r
400         }\r
401         else\r
402                 dbg("#### Success set tty vdpram params. fd:%d", fd);\r
403 \r
404         /*TODO: No need to check Status. Delete*/\r
405         cmd = HN_DPRAM_PHONE_GETSTATUS;\r
406 \r
407         if (ioctl(fd, cmd, &val) < 0) {\r
408                 err("#### ioctl failed fd:%d, cmd:%lu, val:%d", fd,cmd,val);\r
409                 vdpram_close(fd);\r
410                 return rv;\r
411         }\r
412         else\r
413                 dbg("#### ioctl Success fd:%d, cmd:%lu, val:%d", fd,cmd,val);\r
414 \r
415         return fd;\r
416 \r
417 }\r
418 \r
419 /*\r
420 *       power on the phone.\r
421 */\r
422 int vdpram_poweron(int fd)\r
423 {\r
424         int rv = -1;\r
425 \r
426         if (ioctl(fd, HN_DPRAM_PHONE_ON, NULL) < 0) {\r
427                 err("Phone Power On failed (fd:%d)", fd);\r
428                 rv = 0;\r
429         }\r
430         else {\r
431                 dbg("Phone Power On success (fd:%d)", fd);\r
432                 rv = 1;\r
433         }\r
434         return rv;\r
435 }\r
436 \r
437  /*\r
438  *      Power Off the Phone.\r
439  */\r
440 int vdpram_poweroff(int fd)\r
441 {\r
442         int rv;\r
443 \r
444         if (ioctl(fd, HN_DPRAM_PHONE_OFF, NULL) < 0) {\r
445                 err("Phone Power Off failed.");\r
446                 rv = -1;\r
447         }\r
448         else {\r
449                 dbg("Phone Power Off success.");\r
450                 rv = 1;\r
451         }\r
452 \r
453         return rv;\r
454 }\r
455 \r
456 /*\r
457 *       Read data from vdpram.\r
458 */\r
459 \r
460 int vdpram_tty_read(int nFd, void* buf, size_t nbytes)\r
461 {\r
462         int     actual = 0;\r
463 \r
464         if ((actual = read(nFd, buf, nbytes)) < 0) {\r
465                 dbg("[TRANSPORT DPRAM]read failed.");\r
466         }\r
467         vdpram_hex_dump(IPC_RX, actual, buf);\r
468 \r
469         return actual;\r
470 }\r
471 \r
472 static void __selectsleep(int sec,int msec)\r
473 {\r
474     struct timeval tv;\r
475     tv.tv_sec=sec;\r
476     tv.tv_usec=msec;\r
477     select(0,NULL,NULL,NULL,&tv);\r
478     return;\r
479 }\r
480 \r
481 /*\r
482 *       Write data to vdpram.\r
483 */\r
484 int vdpram_tty_write(int nFd, void* buf, size_t nbytes)\r
485 {\r
486         int ret;\r
487         size_t actual = 0;\r
488         int     retry = 0;\r
489 \r
490         do {\r
491                 vdpram_hex_dump(IPC_TX, nbytes, buf);\r
492                 ret = write(nFd, (unsigned char* )buf, nbytes - actual);\r
493 \r
494                 if ((ret < 0 && errno == EAGAIN) || (ret < 0 && errno == EBUSY)) {\r
495                         err("write failed. retry.. ret[%d] with errno[%d] ",ret, errno);\r
496                         __selectsleep(0,50);\r
497 \r
498                         if (retry == 10)\r
499                                 return 0;\r
500 \r
501                         retry = retry + 1;\r
502                     continue;\r
503                 }\r
504 \r
505                 if (ret < 0) {\r
506                     if (actual != nbytes)\r
507                                 err("write failed.ret[%d]",ret);\r
508 \r
509                         err("errno [%d]",errno);\r
510                         return actual;\r
511                 }\r
512 \r
513                 actual  += ret;\r
514                 buf     += ret;\r
515 \r
516         } while(actual < nbytes);\r
517 \r
518         return actual;\r
519 }\r
520 /*      EOF     */\r