1 /*
2  * Copyright (C) 2018 Knowles Electronics
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "ia_tunneling_hal"
18 #define LOG_NDEBUG 0
19 
20 #include <fcntl.h>
21 #include <stdlib.h>
22 #include <ctype.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <sys/ioctl.h>
26 #include <unistd.h>
27 
28 #include <log/log.h>
29 #include <linux/mfd/adnc/iaxxx-tunnel-intf.h>
30 #include <linux/mfd/adnc/iaxxx-system-identifiers.h>
31 #include "tunnel.h"
32 
33 #define TUNNELING_DEVICE "/dev/tunnel0"
34 #define FUNCTION_ENTRY_LOG ALOGV("Entering %s", __func__);
35 #define FUNCTION_EXIT_LOG ALOGV("Exiting %s", __func__);
36 
37 struct ia_tunneling_hal {
38     int tunnel_dev;
39 };
40 
ia_start_tunneling(int buffering_size __unused)41 struct ia_tunneling_hal* ia_start_tunneling(int buffering_size __unused)
42 {
43     struct ia_tunneling_hal *thdl;
44 
45     FUNCTION_ENTRY_LOG;
46 
47     thdl = (struct ia_tunneling_hal *)malloc(sizeof(struct ia_tunneling_hal));
48     if (thdl == NULL) {
49         ALOGE("%s: ERROR Failed to allocate memory of ia_tunneling_hal",
50             __func__);
51         return NULL;
52     }
53 
54     thdl->tunnel_dev = open(TUNNELING_DEVICE, O_RDONLY);
55     if (-1 == thdl->tunnel_dev) {
56         ALOGE("%s: ERROR Failed to open the tunneling device - %s",
57             __func__, strerror(errno));
58         free(thdl);
59         return NULL;
60     }
61 
62     return thdl;
63 }
64 
ia_stop_tunneling(struct ia_tunneling_hal * thdl)65 int ia_stop_tunneling(struct ia_tunneling_hal *thdl)
66 {
67     FUNCTION_ENTRY_LOG;
68 
69     if (thdl) {
70         close(thdl->tunnel_dev);
71         thdl->tunnel_dev = 0;
72         free(thdl);
73     }
74 
75     return 0;
76 }
77 
ia_enable_tunneling_source(struct ia_tunneling_hal * thdl,unsigned int src_id,unsigned int tnl_mode,unsigned int tnl_encode)78 int ia_enable_tunneling_source(struct ia_tunneling_hal *thdl,
79                             unsigned int src_id,
80                             unsigned int tnl_mode,
81                             unsigned int tnl_encode)
82 {
83     FUNCTION_ENTRY_LOG;
84     struct tunlMsg tm;
85     int err = 0;
86 
87     if (thdl == NULL) {
88         ALOGE("%s: ERROR Tunneling hdl is NULL", __func__);
89         err = -EIO;
90         goto exit;
91     }
92 
93     tm.tunlSrc = src_id;
94     tm.tunlMode = tnl_mode;
95     tm.tunlEncode = tnl_encode;
96     err = ioctl(thdl->tunnel_dev, TUNNEL_SETUP, &tm);
97     if (err == -1) {
98         ALOGE("%s: ERROR Tunnel setup failed %s", __func__, strerror(errno));
99     }
100 
101 exit:
102     return err;
103 }
104 
ia_disable_tunneling_source(struct ia_tunneling_hal * thdl,unsigned int src_id,unsigned int tunl_mode,unsigned int tunl_encode)105 int ia_disable_tunneling_source(struct ia_tunneling_hal *thdl,
106                                 unsigned int src_id,
107                                 unsigned int tunl_mode,
108                                 unsigned int tunl_encode)
109 {
110     FUNCTION_ENTRY_LOG;
111     struct tunlMsg tm;
112     int err = 0;
113 
114     if (thdl == NULL) {
115         ALOGE("%s: ERROR Tunneling hdl is NULL", __func__);
116         err = -EIO;
117         goto exit;
118     }
119 
120     tm.tunlSrc = src_id;
121     tm.tunlMode = tunl_mode;
122     tm.tunlEncode = tunl_encode;
123     err = ioctl(thdl->tunnel_dev, TUNNEL_TERMINATE, &tm);
124     if (err == -1) {
125         ALOGE("%s: ERROR Tunnel terminate failed %s",
126             __func__, strerror(errno));
127     }
128 
129 exit:
130     return err;
131 }
132 
ia_read_tunnel_data(struct ia_tunneling_hal * thdl,void * buf,int buf_sz)133 int ia_read_tunnel_data(struct ia_tunneling_hal *thdl,
134                         void *buf,
135                         int buf_sz)
136 {
137     int read_bytes;
138 
139     if ((buf == NULL) || (buf_sz <= 0)) {
140         ALOGE("%s: ERROR Invalid buffer or buffer size", __func__);
141         return -EINVAL;
142     }
143 
144     if (thdl == NULL) {
145         ALOGE("%s: ERROR Tunneling hdl is NULL", __func__);
146         return -EIO;
147     }
148 
149     read_bytes = read(thdl->tunnel_dev, buf, buf_sz);
150     if (read_bytes == 0) {
151         ALOGE("%s: Warning zero bytes read from tunneling device, "
152             "trying again..", __func__);
153     }
154 
155     return read_bytes;
156 }
157 
ia_set_tunnel_out_buf_threshold(struct ia_tunneling_hal * thdl,uint32_t threshold)158 int ia_set_tunnel_out_buf_threshold(struct ia_tunneling_hal *thdl,
159                                     uint32_t threshold)
160 {
161     int err;
162 
163     FUNCTION_ENTRY_LOG;
164 
165     if (thdl == NULL) {
166         ALOGE("%s: ERROR Tunneling hdl is NULL", __func__);
167         err = -EIO;
168         goto exit;
169     }
170 
171     err = ioctl(thdl->tunnel_dev, TUNNEL_SET_EVENT_THRESHOLD,
172                 threshold);
173     if (err == -1) {
174         ALOGE("%s: ERROR Tunnel terminate failed %s",
175             __func__, strerror(errno));
176     }
177 
178 exit:
179     return err;
180 }
181