Change dev node name to /dev/vdpram0 from /dev/dpram/0
[platform/core/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 <glib.h>
33
34 #include <log.h>\r
35 #include "legacy/TelUtility.h"\r
36 #include "vdpram.h"\r
37 #include "vdpram_dump.h"\r
38 \r
39 #ifndef TIOCMODG\r
40 #  ifdef TIOCMGET\r
41 #    define TIOCMODG TIOCMGET\r
42 #  else\r
43 #    ifdef MCGETA\r
44 #      define TIOCMODG MCGETA\r
45 #    endif\r
46 #  endif\r
47 #endif\r
48 \r
49 #ifndef TIOCMODS\r
50 #  ifdef TIOCMSET\r
51 #    define TIOCMODS TIOCMSET\r
52 #  else\r
53 #    ifdef MCSETA\r
54 #      define TIOCMODS MCSETA\r
55 #    endif\r
56 #  endif\r
57 #endif\r
58 \r
59 /* Retry parameters */
60 #define SLEEP_TIME_IN_SEC               0
61 #define SLEEP_TIME_IN_MSEC              50
62
63 #define MAX_RETRY_COUNT                 10
64
65 typedef struct _tty_old_setting_t {
66         int             fd;\r
67         struct  termios  termiosVal;\r
68         struct  _tty_old_setting_t *next;\r
69         struct  _tty_old_setting_t *prev;\r
70 } tty_old_setting_t;\r
71 \r
72 #define VDPRAM_OPEN_PATH                "/dev/vdpram0"\r
73 \r
74 /* DPRAM ioctls for DPRAM tty devices */\r
75 #define IOC_MZ_MAGIC            ('h')\r
76 #define HN_DPRAM_PHONE_ON                       _IO (IOC_MZ_MAGIC, 0xd0)\r
77 #define HN_DPRAM_PHONE_OFF                      _IO (IOC_MZ_MAGIC, 0xd1)\r
78 #define HN_DPRAM_PHONE_GETSTATUS        _IOR(IOC_MZ_MAGIC, 0xd2, unsigned int)\r
79 \r
80 static tty_old_setting_t *ttyold_head = NULL;\r
81 \r
82 /*
83  *      Insert TTY old settings.
84  */
85 static void __insert_tty_oldsetting(tty_old_setting_t *me)\r
86 {\r
87         dbg("Function Entrance");
88 \r
89         if (me == NULL)\r
90                 return;\r
91 \r
92         if (ttyold_head)\r
93                 ttyold_head->prev = me;
94 \r
95         me->next = ttyold_head;\r
96         me->prev = 0;\r
97         ttyold_head = me;\r
98 }\r
99 \r
100 /*
101  *      Search TTY old settings.
102  */
103 static tty_old_setting_t *__search_tty_oldsetting(int fd)\r
104 {\r
105         tty_old_setting_t *tty = NULL;\r
106 \r
107         dbg("Function Entrance");
108 \r
109         if (ttyold_head == NULL)\r
110                 return NULL;\r
111 \r
112         tty = ttyold_head;\r
113 \r
114         do {
115                 if (tty->fd == fd) {\r
116                         dbg("oldsetting for inputted fd [%d] is found", fd);
117                         break;\r
118                 } else {
119                         if (tty->next == NULL) {\r
120                                 err("No oldsetting found!!!");
121                                 tty = NULL;\r
122                                 break;\r
123                         }\r
124                         tty = tty->next;\r
125                 }\r
126         } while (1);
127 \r
128         return tty;\r
129 }\r
130 \r
131 /*
132  *      Remove TTY old settings.
133  */
134 static void __remove_tty_oldsetting(tty_old_setting_t *me)\r
135 {\r
136         dbg( "Function Enterence.");\r
137 \r
138         if (me == NULL)\r
139                 return;\r
140 \r
141         if (me->prev)\r
142                 me->prev->next = me->next;
143         else\r
144                 ttyold_head = me->next;
145 \r
146         if (me->next)\r
147                 me->next->prev = me->prev;
148 }\r
149 \r
150 /*
151  *      Set hardware flow control.
152  */
153 static void __tty_sethwf(int fd, int on)\r
154 {\r
155         struct termios tty;\r
156 \r
157         dbg("Function Entrance");
158 \r
159         if (tcgetattr(fd, &tty))\r
160                 err("__tty_sethwf: tcgetattr:");\r
161 \r
162         if (on)\r
163                 tty.c_cflag |= CRTSCTS;
164         else\r
165                 tty.c_cflag &= ~CRTSCTS;
166 \r
167         if (tcsetattr(fd, TCSANOW, &tty))\r
168                 err("__tty_sethwf: tcsetattr:");\r
169 }\r
170 \r
171 /*\r
172  *      Set RTS line. Sometimes dropped. Linux specific?
173  */
174 static int __tty_setrts(int fd)\r
175 {\r
176         int mcs;\r
177 \r
178         dbg("Function Entrance");
179 \r
180         if (-1 ==  ioctl(fd, TIOCMODG, &mcs))\r
181                 err("icotl: TIOCMODG");\r
182 \r
183         mcs |= TIOCM_RTS;\r
184 \r
185         if (-1 == ioctl(fd, TIOCMODS, &mcs))\r
186                 err("icotl: TIOCMODS");\r
187 \r
188         return 0;\r
189 }\r
190 \r
191 /*\r
192  *      Set baudrate, parity and number of bits.
193  */\r
194 static int __tty_setparms(int fd, char* baudr, char* par, char* bits, char* stop, int hwf, int swf)\r
195 {\r
196         int spd = -1;\r
197         int newbaud;\r
198         int bit = bits[0];\r
199         int stop_bit = stop[0];\r
200 \r
201         struct termios tty;\r
202         tty_old_setting_t *old_setting = NULL;\r
203 \r
204         dbg("Function Entrance");
205 \r
206         old_setting = g_try_new0(tty_old_setting_t, 1);
207 \r
208         if (old_setting == NULL)\r
209                 return TAPI_API_SYSTEM_OUT_OF_MEM;\r
210 \r
211         old_setting->fd = fd;\r
212 \r
213         if (tcgetattr(fd, &tty) < 0) {\r
214                 g_free(old_setting);
215                 return TAPI_API_TRANSPORT_LAYER_FAILURE;\r
216         }\r
217 \r
218         if (tcgetattr(fd, &old_setting->termiosVal) < 0) {\r
219                 g_free(old_setting);
220                 return TAPI_API_TRANSPORT_LAYER_FAILURE;\r
221         }\r
222 \r
223         __insert_tty_oldsetting(old_setting);\r
224 \r
225         fflush(stdout);\r
226 \r
227         /* We generate mark and space parity ourself. */\r
228         if (bit == '7' && (par[0] == 'M' || par[0] == 'S'))\r
229                 bit = '8';\r
230 \r
231         /* Check if 'baudr' is really a number */\r
232         if ((newbaud = (atol(baudr) / 100)) == 0 && baudr[0] != '0')\r
233                 newbaud = -1;\r
234 \r
235         switch(newbaud) {
236                 case 0:\r
237                         spd = 0;\r
238                 break;
239 \r
240                 case 3:\r
241                         spd = B300;\r
242                 break;
243 \r
244                 case 6:\r
245                         spd = B600;\r
246                 break;
247 \r
248                 case 12:\r
249                         spd = B1200;\r
250                 break;
251 \r
252                 case 24:\r
253                         spd = B2400;\r
254                 break;
255 \r
256                 case 48:\r
257                         spd = B4800;\r
258                 break;
259 \r
260                 case 96:\r
261                         spd = B9600;\r
262                 break;
263 \r
264                 case 192:\r
265                         spd = B19200;\r
266                 break;
267 \r
268                 case 384:\r
269                         spd = B38400;\r
270                 break;
271 \r
272                 case 576:\r
273                         spd = B57600;\r
274                 break;
275 \r
276                 case 1152:\r
277                         spd = B115200;\r
278                 break;
279 \r
280                 default:\r
281                         err("invaid baud rate");\r
282                 break;
283         }\r
284 \r
285         if (spd != -1) {\r
286                 cfsetospeed(&tty, (speed_t) spd);
287                 cfsetispeed(&tty, (speed_t) spd);
288         }\r
289 \r
290         switch(bit) {
291                 case '5':
292                         tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS5;
293                 break;
294 \r
295                 case '6':
296                         tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS6;
297                 break;
298 \r
299                 case '7':
300                         tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS7;
301                 break;
302 \r
303                 case '8':
304                 default:
305                         tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;
306                 break;
307         }\r
308 \r
309         switch(stop_bit) {
310                 case '1':
311                         tty.c_cflag &= ~CSTOPB;
312                 break;
313 \r
314                 case '2':
315                 default:
316                         tty.c_cflag |= CSTOPB;
317                 break;
318         }\r
319 \r
320         /* Set into raw, no echo mode */\r
321         tty.c_iflag = IGNBRK;\r
322         tty.c_lflag = 0;\r
323         tty.c_oflag = 0;\r
324         tty.c_cflag |= CLOCAL | CREAD;\r
325         tty.c_cc[VMIN] = 1;\r
326         tty.c_cc[VTIME] = 1;\r
327 \r
328         if (swf)\r
329                 tty.c_iflag |= IXON | IXOFF;
330         else\r
331                 tty.c_iflag &= ~(IXON | IXOFF | IXANY);
332 \r
333         tty.c_cflag &= ~(PARENB | PARODD);\r
334 \r
335         if (par[0] == 'E')\r
336                 tty.c_cflag |= PARENB;
337         else if (par[0] == 'O')\r
338                 tty.c_cflag |= (PARENB | PARODD);
339 \r
340         if (tcsetattr(fd, TCSANOW, &tty) < 0) {\r
341                 g_free(old_setting);
342                 return TAPI_API_TRANSPORT_LAYER_FAILURE;
343         }\r
344 \r
345         __tty_setrts(fd);\r
346         __tty_sethwf(fd, hwf);\r
347 \r
348         return TAPI_API_SUCCESS;\r
349 }\r
350 \r
351 /*
352  *      Close TTY Device.
353  */
354 static int __tty_close(int fd)\r
355 {\r
356         tty_old_setting_t *old_setting = NULL;\r
357 \r
358         dbg("Function Entrance");
359 \r
360         /* Get previous settings */
361         old_setting = __search_tty_oldsetting(fd);\r
362         if (old_setting == NULL) {
363                 dbg("[VDPRAM] No previous settings found!!!");
364                 return TAPI_API_SUCCESS;\r
365         }
366 \r
367         if (tcsetattr(fd, TCSAFLUSH, &old_setting->termiosVal) < 0)     {\r
368                 err("[VDPRAM] Close failed");
369                 return TAPI_API_TRANSPORT_LAYER_FAILURE;\r
370         }\r
371 \r
372         /* Remove the previous setting configured */
373         __remove_tty_oldsetting(old_setting);\r
374 \r
375         /* Free memory */
376         g_free(old_setting);
377 \r
378         /* Close fd */
379         close(fd);\r
380 \r
381         return TAPI_API_SUCCESS;\r
382 }\r
383 \r
384 /*\r
385  *      Wait on select.
386  */
387 static void __sleep(int sec, int msec)
388 {
389     struct timeval tv;
390
391     tv.tv_sec = sec;
392     tv.tv_usec = msec;
393
394     select(0, NULL, NULL, NULL, &tv);
395 }
396
397 /*
398  * Close the VDPRAM device
399  */
400 int vdpram_close(int fd)\r
401 {\r
402         int ret = TAPI_API_SUCCESS;\r
403 \r
404         dbg("Function Entrance");
405 \r
406         /* Close VDPRAM Device */
407         ret = __tty_close(fd);\r
408 \r
409         return ret;\r
410 }\r
411 \r
412 /*\r
413  * Open the VDPRAM device
414  */
415 int vdpram_open (void)\r
416 {\r
417         int rv = -1;\r
418         int fd = -1;\r
419         int val = 0;\r
420         unsigned int cmd =0;\r
421 \r
422         dbg("Function Enterence.");
423
424         /* Open DPRAM device */
425         fd = open(VDPRAM_OPEN_PATH, O_RDWR);\r
426         if (fd < 0) {\r
427                 err("[VDPRAM] Open VDPRAM file - [FAIL] Error: [%s]", strerror(errno));
428                 return rv;\r
429         } else {
430                 dbg("[VDPRAM] Open VDPRAM file - [SUCCESS] fd: [%d] path: [%s]",
431                                                                                 fd, VDPRAM_OPEN_PATH);
432         }\r
433 \r
434         /* Set device parameters */
435         if (__tty_setparms(fd, "115200", "N", "8", "1", 0, 0) != TAPI_API_SUCCESS) {
436                 err("[VDPRAM] Set TTY device parameters - [FAIL]");
437 \r
438                 /* Close VDPRAM Device */
439                 vdpram_close(fd);\r
440                 return rv;\r
441         }\r
442         else {
443                 dbg("[VDPRAM] Set TTY device parameters - [SUCCESS]");
444         }
445 \r
446         /* TODO: No need to check Status. Delete */
447         cmd = HN_DPRAM_PHONE_GETSTATUS;\r
448         if (ioctl(fd, cmd, &val) < 0) {
449                 err("[VDPRAM] Get Phone status - [FAIL] fd: [d] cmd: [%d] val: [%d]",
450                                                                                         fd, cmd, val);
451 \r
452                 /* Close Device */
453                 vdpram_close(fd);\r
454
455                 return rv;\r
456         } else {
457                 dbg("[VDPRAM] Get Phone status - [SUCCESS]");
458         }\r
459 \r
460         return fd;\r
461 }\r
462 \r
463 /*\r
464  *      Power ON the Phone.
465  */
466 gboolean vdpram_poweron(int fd)
467 {\r
468         if (ioctl(fd, HN_DPRAM_PHONE_ON, NULL) < 0) {\r
469                 err("[VDPRAM] Phone Power ON [FAIL] - fd: [%d] Error: [%s]", fd, strerror(errno));
470                 return FALSE;
471         }\r
472         else {\r
473                 dbg("[VDPRAM] Phone Power ON [SUCCESS] - fd: [%d]", fd);
474                 return TRUE;
475         }\r
476 }\r
477 \r
478 /*
479  *      Power OFF the Phone.
480  */\r
481 gboolean vdpram_poweroff(int fd)
482 {\r
483         if (ioctl(fd, HN_DPRAM_PHONE_OFF, NULL) < 0) {\r
484                 err("[VDPRAM] Phone Power OFF [FAIL] - fd: [%d] Error: [%s]", fd, strerror(errno));
485                 return FALSE;
486         }\r
487         else {\r
488                 dbg("[VDPRAM] Phone Power OFF [SUCCESS] - fd: [%d]", fd);
489                 return TRUE;
490         }\r
491 }\r
492 \r
493 /*\r
494  *      Read data from VDPRAM.
495  */
496 int vdpram_tty_read(int nFd, void* buf, size_t nbytes)\r
497 {\r
498         int     actual = 0;\r
499 \r
500         if ((actual = read(nFd, buf, nbytes)) < 0) {\r
501                 err("[VDPRAM] Read [FAIL] - fd: [%d] Error: [%s]", nFd, strerror(errno));
502         }\r
503
504         /* Dumping Read data */
505         vdpram_hex_dump(RX, actual, buf);
506 \r
507         return actual;\r
508 }\r
509 \r
510 /*\r
511  *      Write data to VDPRAM.
512  */
513 int vdpram_tty_write(int nFd, void* buf, size_t nbytes)\r
514 {\r
515         int ret;\r
516         size_t actual = 0;\r
517         int     retry = 0;\r
518 \r
519         do {\r
520                 vdpram_hex_dump(TX, nbytes, buf);
521
522                 /* Write to Device */
523                 ret = write(nFd, (unsigned char* )buf, nbytes - actual);\r
524                 if (ret < 0) {
525                         err("[VDPRAM] Write [FAIL] - fd: [%d] Error: [%s]",
526                                                                                                 nFd, strerror(errno));
527 \r
528                         if ((errno == EAGAIN) || (errno == EBUSY)) {
529                                 /* Sleep for 50 msecs */
530                                 __sleep(SLEEP_TIME_IN_SEC, SLEEP_TIME_IN_MSEC);
531 \r
532                                 if (retry == MAX_RETRY_COUNT) {
533                                         err("[VDPRAM] Maximum retries completed!!!");
534                                         return 0;
535                                 }
536 \r
537                                 retry = retry + 1;
538                                 continue;
539                         }
540 \r
541                         if (actual != nbytes)
542                                 err("[VDPRAM] Write [FAIL] - fd: [%d]", nFd);
543 \r
544                         err("[VDPRAM] Write [FAIL] - Error: [%s]", strerror(errno));
545                         return actual;\r
546                 }\r
547 \r
548                 actual  += ret;\r
549                 buf     += ret;\r
550                 dbg("[VDPRAM] Write Actual bytes: [%d] Written bytes: [%d]", actual, ret);
551         } while(actual < nbytes);\r
552 \r
553         return actual;\r
554 }\r