4 * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Junhwan An <jh48.an@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
30 #include <sys/ioctl.h>
33 #include "legacy/TelUtility.h"
35 #include "vdpram_dump.h"
39 # define TIOCMODG TIOCMGET
42 # define TIOCMODG MCGETA
49 # define TIOCMODS TIOCMSET
52 # define TIOCMODS MCSETA
57 typedef struct _tty_old_setting_t {
59 struct termios termiosVal;
60 struct _tty_old_setting_t *next;
61 struct _tty_old_setting_t *prev;
64 #define VDPRAM_OPEN_PATH "/dev/vdpram0"
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)
72 static tty_old_setting_t *ttyold_head = NULL;
74 /* static functions */
75 static void __insert_tty_oldsetting(tty_old_setting_t *me)
77 dbg("Function Enterence.");
83 ttyold_head->prev = me;
85 me->next = ttyold_head;
90 static tty_old_setting_t *__search_tty_oldsetting(int fd)
92 tty_old_setting_t *tty = NULL;
94 dbg("Function Enterence.");
96 if (ttyold_head == NULL)
103 dbg("oldsetting for inputted fd is found");
106 if (tty->next == NULL) {
107 dbg("No oldsetting is found");
118 static void __remove_tty_oldsetting(tty_old_setting_t *me)
120 dbg("Function Enterence.");
126 me->prev->next = me->next;
128 ttyold_head = me->next;
131 me->next->prev = me->prev;
135 * Set hardware flow control.
137 static void __tty_sethwf(int fd, int on)
141 dbg("Function Enterence.");
143 if (tcgetattr(fd, &tty))
144 err("__tty_sethwf: tcgetattr:");
147 tty.c_cflag |= CRTSCTS;
149 tty.c_cflag &= ~CRTSCTS;
151 if (tcsetattr(fd, TCSANOW, &tty))
152 err("__tty_sethwf: tcsetattr:");
156 * Set RTS line. Sometimes dropped. Linux specific?
158 static int __tty_setrts(int fd)
162 dbg("Function Enterence.");
164 if (-1 == ioctl(fd, TIOCMODG, &mcs))
165 err("icotl: TIOCMODG");
169 if (-1 == ioctl(fd, TIOCMODS, &mcs))
170 err("icotl: TIOCMODS");
176 * Set baudrate, parity and number of bits.
178 static int __tty_setparms(int fd,
179 const char *baudr, const char *par,
180 const char *bits, const char *stop,
186 int stop_bit = stop[0];
189 tty_old_setting_t *old_setting = NULL;
191 dbg("Function Enterence.");
193 old_setting = calloc(sizeof(tty_old_setting_t), 1);
194 if (old_setting == NULL)
195 return TAPI_API_SYSTEM_OUT_OF_MEM;
197 old_setting->fd = fd;
199 if (tcgetattr(fd, &tty) < 0) {
201 return TAPI_API_TRANSPORT_LAYER_FAILURE;
204 if (tcgetattr(fd, &old_setting->termiosVal) < 0) {
206 return TAPI_API_TRANSPORT_LAYER_FAILURE;
209 __insert_tty_oldsetting(old_setting);
213 /* We generate mark and space parity ourself. */
214 if (bit == '7' && (par[0] == 'M' || par[0] == 'S'))
217 /* Check if 'baudr' is really a number */
218 if ((newbaud = (atol(baudr) / 100)) == 0 && baudr[0] != '0')
267 err("invaid baud rate");
272 cfsetospeed(&tty, (speed_t) spd);
273 cfsetispeed(&tty, (speed_t) spd);
278 tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS5;
282 tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS6;
286 tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS7;
291 tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;
297 tty.c_cflag &= ~CSTOPB;
302 tty.c_cflag |= CSTOPB;
306 /* Set into raw, no echo mode */
307 tty.c_iflag = IGNBRK;
310 tty.c_cflag |= CLOCAL | CREAD;
315 tty.c_iflag |= IXON | IXOFF;
317 tty.c_iflag &= ~(IXON | IXOFF | IXANY);
319 tty.c_cflag &= ~(PARENB | PARODD);
322 tty.c_cflag |= PARENB;
323 else if (par[0] == 'O')
324 tty.c_cflag |= (PARENB | PARODD);
326 if (tcsetattr(fd, TCSANOW, &tty) < 0) {
328 return TAPI_API_TRANSPORT_LAYER_FAILURE;
332 __tty_sethwf(fd, hwf);
334 return TAPI_API_SUCCESS;
337 static int __tty_close(int fd)
339 tty_old_setting_t *old_setting = NULL;
341 dbg("Function Enterence.");
343 old_setting = __search_tty_oldsetting(fd);
344 if (old_setting == NULL)
345 return TAPI_API_SUCCESS;
347 if (tcsetattr(fd, TCSAFLUSH, &old_setting->termiosVal) < 0) {
349 return TAPI_API_TRANSPORT_LAYER_FAILURE;
352 __remove_tty_oldsetting(old_setting);
358 return TAPI_API_SUCCESS;
362 * Restore the old settings before close.
364 int vdpram_close(int fd)
366 int ret = TAPI_API_SUCCESS;
368 dbg("Function Enterence.");
370 ret = __tty_close(fd);
376 * Open the vdpram fd.
378 int vdpram_open(void)
383 unsigned int cmd = 0;
385 fd = open(VDPRAM_OPEN_PATH, O_RDWR);
388 err("#### Failed to open vdpram file: error no hex %x", errno);
391 dbg("#### Success to open vdpram file. fd:%d, path:%s", fd, VDPRAM_OPEN_PATH);
395 if (__tty_setparms(fd, "115200", "N", "8", "1", 0, 0) != TAPI_API_SUCCESS) {
399 dbg("#### Success set tty vdpram params. fd:%d", fd);
402 /*TODO: No need to check Status. Delete*/
403 cmd = HN_DPRAM_PHONE_GETSTATUS;
405 if (ioctl(fd, cmd, &val) < 0) {
406 err("#### ioctl failed fd:%d, cmd:%lu, val:%d", fd, cmd, val);
410 dbg("#### ioctl Success fd:%d, cmd:%lu, val:%d", fd, cmd, val);
418 * power on the phone.
420 int vdpram_poweron(int fd)
424 if (ioctl(fd, HN_DPRAM_PHONE_ON, NULL) < 0) {
425 err("Phone Power On failed (fd:%d)", fd);
428 dbg("Phone Power On success (fd:%d)", fd);
435 * Power Off the Phone.
437 int vdpram_poweroff(int fd)
441 if (ioctl(fd, HN_DPRAM_PHONE_OFF, NULL) < 0) {
442 err("Phone Power Off failed.");
445 dbg("Phone Power Off success.");
453 * Read data from vdpram.
455 int vdpram_tty_read(int nFd, void *buf, size_t nbytes)
459 if ((actual = read(nFd, buf, nbytes)) < 0)
460 dbg("[TRANSPORT DPRAM]read failed.");
462 vdpram_hex_dump(IPC_RX, actual, buf);
467 static void __selectsleep(int sec, int msec)
473 select(0, NULL, NULL, NULL, &tv);
477 * Write data to vdpram.
479 int vdpram_tty_write(int nFd, void *buf, size_t nbytes)
486 vdpram_hex_dump(IPC_TX, nbytes, buf);
487 ret = write(nFd, (unsigned char *)buf, nbytes - actual);
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);
501 if (actual != nbytes)
502 err("write failed.ret[%d]", ret);
504 err("errno [%d]", errno);
511 } while (actual < nbytes);