Code sync from tizen_2.4
[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                 } else {
106                         if (tty->next == NULL) {
107                                 dbg("No oldsetting is found");
108                                 tty = NULL;
109                                 break;
110                         }
111                         tty = tty->next;
112                 }
113         } while (1);
114
115         return tty;
116 }
117
118 static void __remove_tty_oldsetting(tty_old_setting_t *me)
119 {
120         dbg("Function Enterence.");
121
122         if (me == NULL)
123                 return;
124
125         if (me->prev)
126                 me->prev->next = me->next;
127         else
128                 ttyold_head = me->next;
129
130         if (me->next)
131                 me->next->prev = me->prev;
132 }
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         if (old_setting == NULL)
195                 return TAPI_API_SYSTEM_OUT_OF_MEM;
196
197         old_setting->fd = fd;
198
199         if (tcgetattr(fd, &tty) < 0) {
200                 free(old_setting);
201                 return TAPI_API_TRANSPORT_LAYER_FAILURE;
202         }
203
204         if (tcgetattr(fd, &old_setting->termiosVal) < 0) {
205                 free(old_setting);
206                 return TAPI_API_TRANSPORT_LAYER_FAILURE;
207         }
208
209         __insert_tty_oldsetting(old_setting);
210
211         fflush(stdout);
212
213         /* We generate mark and space parity ourself. */
214         if (bit == '7' && (par[0] == 'M' || par[0] == 'S'))
215                 bit = '8';
216
217         /* Check if 'baudr' is really a number */
218         if ((newbaud = (atol(baudr) / 100)) == 0 && baudr[0] != '0')
219                 newbaud = -1;
220
221         switch (newbaud) {
222         case 0:
223                 spd = 0;
224         break;
225
226         case 3:
227                 spd = B300;
228         break;
229
230         case 6:
231                 spd = B600;
232         break;
233
234         case 12:
235                 spd = B1200;
236         break;
237
238         case 24:
239                 spd = B2400;
240         break;
241
242         case 48:
243                 spd = B4800;
244         break;
245
246         case 96:
247                 spd = B9600;
248         break;
249
250         case 192:
251                 spd = B19200;
252         break;
253
254         case 384:
255                 spd = B38400;
256         break;
257
258         case 576:
259                 spd = B57600;
260         break;
261
262         case 1152:
263                 spd = B115200;
264         break;
265
266         default:
267                 err("invaid baud rate");
268         break;
269         }
270
271         if (spd != -1) {
272                 cfsetospeed(&tty, (speed_t) spd);
273                 cfsetispeed(&tty, (speed_t) spd);
274         }
275
276         switch (bit) {
277         case '5':
278                 tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS5;
279         break;
280
281         case '6':
282                 tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS6;
283         break;
284
285         case '7':
286                 tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS7;
287         break;
288
289         case '8':
290         default:
291                 tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;
292         break;
293         }
294
295         switch (stop_bit) {
296         case '1':
297                 tty.c_cflag &= ~CSTOPB;
298         break;
299
300         case '2':
301         default:
302                 tty.c_cflag |= CSTOPB;
303         break;
304         }
305
306         /* Set into raw, no echo mode */
307         tty.c_iflag = IGNBRK;
308         tty.c_lflag = 0;
309         tty.c_oflag = 0;
310         tty.c_cflag |= CLOCAL | CREAD;
311         tty.c_cc[VMIN] = 1;
312         tty.c_cc[VTIME] = 1;
313
314         if (swf)
315                 tty.c_iflag |= IXON | IXOFF;
316         else
317                 tty.c_iflag &= ~(IXON | IXOFF | IXANY);
318
319         tty.c_cflag &= ~(PARENB | PARODD);
320
321         if (par[0] == 'E')
322                 tty.c_cflag |= PARENB;
323         else if (par[0] == 'O')
324                 tty.c_cflag |= (PARENB | PARODD);
325
326         if (tcsetattr(fd, TCSANOW, &tty) < 0) {
327                 free(old_setting);
328                 return TAPI_API_TRANSPORT_LAYER_FAILURE;
329         }
330
331         __tty_setrts(fd);
332         __tty_sethwf(fd, hwf);
333
334         return TAPI_API_SUCCESS;
335 }
336
337 static int __tty_close(int fd)
338 {
339         tty_old_setting_t *old_setting = NULL;
340
341         dbg("Function Enterence.");
342
343         old_setting = __search_tty_oldsetting(fd);
344         if (old_setting == NULL)
345                 return TAPI_API_SUCCESS;
346
347         if (tcsetattr(fd, TCSAFLUSH, &old_setting->termiosVal) < 0) {
348                 err("close failed");
349                 return TAPI_API_TRANSPORT_LAYER_FAILURE;
350         }
351
352         __remove_tty_oldsetting(old_setting);
353
354         free(old_setting);
355
356         close(fd);
357
358         return TAPI_API_SUCCESS;
359 }
360
361 /*
362  * Restore the old settings before close.
363  */
364 int vdpram_close(int fd)
365 {
366         int ret = TAPI_API_SUCCESS;
367
368         dbg("Function Enterence.");
369
370         ret = __tty_close(fd);
371
372         return ret;
373 }
374
375 /*
376  * Open the vdpram fd.
377  */
378 int vdpram_open(void)
379 {
380         int rv = -1;
381         int fd = -1;
382         int val = 0;
383         unsigned int cmd = 0;
384
385         fd = open(VDPRAM_OPEN_PATH, O_RDWR);
386
387         if (fd < 0) {
388                 err("#### Failed to open vdpram file: error no hex %x", errno);
389                 return rv;
390         } else {
391                 dbg("#### Success to open vdpram file. fd:%d, path:%s", fd, VDPRAM_OPEN_PATH);
392         }
393
394
395         if (__tty_setparms(fd, "115200", "N", "8", "1", 0, 0) != TAPI_API_SUCCESS) {
396                 vdpram_close(fd);
397                 return rv;
398         } else {
399                 dbg("#### Success set tty vdpram params. fd:%d", fd);
400         }
401
402         /*TODO: No need to check Status. Delete*/
403         cmd = HN_DPRAM_PHONE_GETSTATUS;
404
405         if (ioctl(fd, cmd, &val) < 0) {
406                 err("#### ioctl failed fd:%d, cmd:%lu, val:%d", fd, cmd, val);
407                 vdpram_close(fd);
408                 return rv;
409         } else {
410                 dbg("#### ioctl Success fd:%d, cmd:%lu, val:%d", fd, cmd, val);
411         }
412
413         return fd;
414
415 }
416
417 /*
418  * power on the phone.
419  */
420 int vdpram_poweron(int fd)
421 {
422         int rv = -1;
423
424         if (ioctl(fd, HN_DPRAM_PHONE_ON, NULL) < 0) {
425                 err("Phone Power On failed (fd:%d)", fd);
426                 rv = 0;
427         } else {
428                 dbg("Phone Power On success (fd:%d)", fd);
429                 rv = 1;
430         }
431         return rv;
432 }
433
434  /*
435   * Power Off the Phone.
436   */
437 int vdpram_poweroff(int fd)
438 {
439         int rv;
440
441         if (ioctl(fd, HN_DPRAM_PHONE_OFF, NULL) < 0) {
442                 err("Phone Power Off failed.");
443                 rv = -1;
444         } else {
445                 dbg("Phone Power Off success.");
446                 rv = 1;
447         }
448
449         return rv;
450 }
451
452 /*
453  * Read data from vdpram.
454  */
455 int vdpram_tty_read(int nFd, void *buf, size_t nbytes)
456 {
457         int     actual = 0;
458
459         if ((actual = read(nFd, buf, nbytes)) < 0)
460                 dbg("[TRANSPORT DPRAM]read failed.");
461
462         vdpram_hex_dump(IPC_RX, actual, buf);
463
464         return actual;
465 }
466
467 static void __selectsleep(int sec, int msec)
468 {
469         struct timeval tv;
470
471         tv.tv_sec = sec;
472         tv.tv_usec = msec;
473         select(0, NULL, NULL, NULL, &tv);
474 }
475
476 /*
477  * Write data to vdpram.
478  */
479 int vdpram_tty_write(int nFd, void *buf, size_t nbytes)
480 {
481         int ret;
482         size_t actual = 0;
483         int     retry = 0;
484
485         do {
486                 vdpram_hex_dump(IPC_TX, nbytes, buf);
487                 ret = write(nFd, (unsigned char *)buf, nbytes - actual);
488
489                 if ((ret < 0 && errno == EAGAIN) || (ret < 0 && errno == EBUSY)) {
490                         err("write failed. retry.. ret[%d] with errno[%d] ", ret, errno);
491                         __selectsleep(0, 50);
492
493                         if (retry == 10)
494                                 return 0;
495
496                         retry = retry + 1;
497                         continue;
498                 }
499
500                 if (ret < 0) {
501                     if (actual != nbytes)
502                                 err("write failed.ret[%d]", ret);
503
504                         err("errno [%d]", errno);
505                         return actual;
506                 }
507
508                 actual += ret;
509                 buf += ret;
510
511         } while (actual < nbytes);
512
513         return actual;
514 }
515 /*      EOF     */