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 <stdlib.h>
21 #include <ctype.h>
22 #include <errno.h>
23 #include <string.h>
24 #include <sys/ioctl.h>
25 #include <unistd.h>
26
27 #include <log/log.h>
28 #include <linux/mfd/adnc/iaxxx-tunnel-intf.h>
29 #include <linux/mfd/adnc/iaxxx-system-identifiers.h>
30 #include "tunnel.h"
31
32 #define TUNNELING_DEVICE "/dev/tunnel0"
33 #define FUNCTION_ENTRY_LOG ALOGV("Entering %s", __func__);
34 #define FUNCTION_EXIT_LOG ALOGV("Exiting %s", __func__);
35
36 struct ia_tunneling_hal {
37 int tunnel_dev;
38 };
39
ia_start_tunneling(int buffering_size __unused)40 struct ia_tunneling_hal* ia_start_tunneling(int buffering_size __unused)
41 {
42 struct ia_tunneling_hal *thdl;
43
44 FUNCTION_ENTRY_LOG;
45
46 thdl = (struct ia_tunneling_hal *)malloc(sizeof(struct ia_tunneling_hal));
47 if (thdl == NULL) {
48 ALOGE("%s: ERROR Failed to allocate memory of ia_tunneling_hal",
49 __func__);
50 return NULL;
51 }
52
53 thdl->tunnel_dev = open(TUNNELING_DEVICE, O_RDONLY);
54 if (-1 == thdl->tunnel_dev) {
55 ALOGE("%s: ERROR Failed to open the tunneling device - %s",
56 __func__, strerror(errno));
57 free(thdl);
58 return NULL;
59 }
60
61 return thdl;
62 }
63
ia_stop_tunneling(struct ia_tunneling_hal * thdl)64 int ia_stop_tunneling(struct ia_tunneling_hal *thdl)
65 {
66 FUNCTION_ENTRY_LOG;
67
68 if (thdl) {
69 close(thdl->tunnel_dev);
70 thdl->tunnel_dev = 0;
71 free(thdl);
72 }
73
74 return 0;
75 }
76
ia_enable_tunneling_source(struct ia_tunneling_hal * thdl,unsigned int src_id,unsigned int tnl_mode,unsigned int tnl_encode)77 int ia_enable_tunneling_source(struct ia_tunneling_hal *thdl,
78 unsigned int src_id,
79 unsigned int tnl_mode,
80 unsigned int tnl_encode)
81 {
82 FUNCTION_ENTRY_LOG;
83 struct tunlMsg tm;
84 int err = 0;
85
86 if (thdl == NULL) {
87 ALOGE("%s: ERROR Tunneling hdl is NULL", __func__);
88 err = -EIO;
89 goto exit;
90 }
91
92 tm.tunlSrc = src_id;
93 tm.tunlMode = tnl_mode;
94 tm.tunlEncode = tnl_encode;
95 err = ioctl(thdl->tunnel_dev, TUNNEL_SETUP, &tm);
96 if (err == -1) {
97 ALOGE("%s: ERROR Tunnel setup failed %s", __func__, strerror(errno));
98 }
99
100 exit:
101 return err;
102 }
103
ia_disable_tunneling_source(struct ia_tunneling_hal * thdl,unsigned int src_id,unsigned int tunl_mode,unsigned int tunl_encode)104 int ia_disable_tunneling_source(struct ia_tunneling_hal *thdl,
105 unsigned int src_id,
106 unsigned int tunl_mode,
107 unsigned int tunl_encode)
108 {
109 FUNCTION_ENTRY_LOG;
110 struct tunlMsg tm;
111 int err = 0;
112
113 if (thdl == NULL) {
114 ALOGE("%s: ERROR Tunneling hdl is NULL", __func__);
115 err = -EIO;
116 goto exit;
117 }
118
119 tm.tunlSrc = src_id;
120 tm.tunlMode = tunl_mode;
121 tm.tunlEncode = tunl_encode;
122 err = ioctl(thdl->tunnel_dev, TUNNEL_TERMINATE, &tm);
123 if (err == -1) {
124 ALOGE("%s: ERROR Tunnel terminate failed %s",
125 __func__, strerror(errno));
126 }
127
128 exit:
129 return err;
130 }
131
ia_read_tunnel_data(struct ia_tunneling_hal * thdl,void * buf,int buf_sz)132 int ia_read_tunnel_data(struct ia_tunneling_hal *thdl,
133 void *buf,
134 int buf_sz)
135 {
136 int read_bytes;
137
138 if ((buf == NULL) || (buf_sz <= 0)) {
139 ALOGE("%s: ERROR Invalid buffer or buffer size", __func__);
140 return -EINVAL;
141 }
142
143 if (thdl == NULL) {
144 ALOGE("%s: ERROR Tunneling hdl is NULL", __func__);
145 return -EIO;
146 }
147
148 read_bytes = read(thdl->tunnel_dev, buf, buf_sz);
149 if (read_bytes == 0) {
150 ALOGE("%s: Warning zero bytes read from tunneling device, "
151 "trying again..", __func__);
152 }
153
154 return read_bytes;
155 }
156
ia_set_tunnel_out_buf_threshold(struct ia_tunneling_hal * thdl,uint32_t threshold)157 int ia_set_tunnel_out_buf_threshold(struct ia_tunneling_hal *thdl,
158 uint32_t threshold)
159 {
160 int err;
161
162 FUNCTION_ENTRY_LOG;
163
164 if (thdl == NULL) {
165 ALOGE("%s: ERROR Tunneling hdl is NULL", __func__);
166 err = -EIO;
167 goto exit;
168 }
169
170 err = ioctl(thdl->tunnel_dev, TUNNEL_SET_EVENT_THRESHOLD,
171 threshold);
172 if (err == -1) {
173 ALOGE("%s: ERROR Tunnel terminate failed %s",
174 __func__, strerror(errno));
175 }
176
177 exit:
178 return err;
179 }
180