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