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