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