blob: b9729b908938a8cb6d480e7ccb006ccc97000f59 [file] [log] [blame]
Kiran Gundaa7032222021-03-24 15:50:49 +05301/*
2 * Copyright (c) 2021, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#define LOG_TAG "vendor.qti.vibrator.offload"
31
32#include <stdio.h>
33#include <stdint.h>
34#include <string.h>
35#include <thread>
36#include <linux/input.h>
Kiran Gunda5fba8112021-09-15 18:36:27 +053037#include <linux/slatecom_interface.h>
Kiran Gundaa7032222021-03-24 15:50:49 +053038#include <log/log.h>
39#include <fcntl.h>
40#include <cutils/log.h>
41#include <cutils/uevent.h>
42#include <sys/poll.h>
43#include <sys/ioctl.h>
44
45#include "include/Vibrator.h"
46#include "VibratorPatterns.h"
47
Kiran Gundaa7032222021-03-24 15:50:49 +053048namespace aidl {
49namespace android {
50namespace hardware {
51namespace vibrator {
52
53#define UEVENT_MSG_LEN 1024
54#define SLATE_EVENT "SLATE_EVENT="
55#define SLATE_EVENT_STRING_LEN 12 //length of SLATE_EVENT
Kiran Gundaa7032222021-03-24 15:50:49 +053056
57PatternOffload::PatternOffload()
58{
59 std::thread t(&PatternOffload::SSREventListener, this);
60 t.detach();
61}
62
63void PatternOffload::SSREventListener(void)
64{
65 int device_fd, n, ssr_event = 0;
66 char msg[UEVENT_MSG_LEN + 2];
67 char *msg_ptr = msg;
68
69 /* Offload during the bootup */
70 SendPatterns();
71
72 device_fd = uevent_open_socket(64*1024, true);
73 if(device_fd < 0)
74 {
75 ALOGE("open socket failed: %d", device_fd);
76 return;
77 }
78
79 while ((n = uevent_kernel_multicast_recv(device_fd, msg, UEVENT_MSG_LEN)) > 0) {
80 if (n <= 0 || n >= UEVENT_MSG_LEN) {
81 ALOGE("Message length %d is not correct\n", n);
82 continue;
83 }
84 msg[n] = '\0';
85 msg[n+1] = '\0';
86 if (strstr(msg, "slate_com_dev")) {
87 while(*msg_ptr) {
88 if(!strncmp(msg_ptr, SLATE_EVENT, SLATE_EVENT_STRING_LEN)) {
89 msg_ptr += SLATE_EVENT_STRING_LEN;
90 ssr_event = (atoi(msg_ptr));
91 switch(ssr_event) {
92 case SLATE_AFTER_POWER_UP:
93 ALOGD("SLATE is powered up");
94 SendPatterns();
95 break;
96 }
97 }
98 while(*msg_ptr++);
99 }
100 }
101 }
102}
103
104/** Offload patterns
105 * The sequence of steps in offloading patterns.
106 * 1. Open the Glink channel to offload the patterns
107 * 2. Send the configuration/meta data to co-proc
108 * 3. Wait for the response from the co-proc
109 * 4. Send the pattern data to co-proc
110 * 5. Wait for the response
111 * 6. Exit
112 */
113void PatternOffload::SendPatterns()
114{
115 uint8_t *data;
116 uint32_t len;
117 int32_t rc;
118
119 rc = initChannel();
120 if (rc < 0)
121 return;
122
123 rc = get_pattern_config(&data, &len);
124 if (rc < 0 || !data)
125 return;
126
127 /* Send config data */
128 rc = sendData(data, len);
129 if (rc < 0)
130 return;
131
132 rc = get_pattern_data(&data, &len);
133 if (rc < 0 || !data)
134 return;
135
136 /* Send pattern data */
137 rc = sendData(data, len);
138 if (rc < 0)
139 return;
140
141 free_pattern_mem(data);
142
143 ALOGI("Patterns offloaded successfully\n");
144}
145
146int PatternOffload::sendData(uint8_t *data, int len)
147{
148 int rc, status = 0;
149
150 if (!data || !len)
151 return -EINVAL;
152
153 rc = GlinkCh.GlinkWrite(data, len);
154 if (rc < 0)
155 return rc;
156
157 rc = GlinkCh.GlinkPoll();
158 if (rc < 0)
159 return rc;
160
161 rc = GlinkCh.GlinkRead((uint8_t *)&status, 4);
162 if (rc < 0)
163 return rc;
164
165 if (status != OFFLOAD_SUCCESS)
166 return -EIO;
167
168 return 0;
169}
170
171
172int PatternOffload::initChannel()
173{
174 std::string chname = "/dev/glinkpkt_slate_haptics_offload";
175 int rc;
176
177 rc = GlinkCh.GlinkOpen(chname);
178 if (rc < 0)
179 {
Kiran Gunda2feeb5e2021-08-25 13:06:07 +0530180 ALOGE("Failed to open Glink channel name %s\n", chname.c_str());
Kiran Gundaa7032222021-03-24 15:50:49 +0530181 return rc;
182 }
183
184 return 0;
185}
186
187#define GLINK_MAX_CONN_RETRIES 60
188int OffloadGlinkConnection::GlinkOpen(std::string& dev)
189{
190 int tries = GLINK_MAX_CONN_RETRIES;
191 dev_name = dev;
192
193 do {
194 fd = ::open(dev_name.c_str(), O_RDWR);
195 tries--;
196 if (fd < 0)
197 {
198 ALOGE("%s: %s: open error(%s)", __func__, dev.c_str(), strerror(errno));
199 sleep(1);
200 }
201 } while(-ETIMEDOUT == errno && tries > 0 );
202
203 return fd;
204}
205
206int OffloadGlinkConnection::GlinkClose()
207{
208 if (fd >= 0)
209 {
210 ::close(fd);
211 fd = -1;
212 }
213 return 0;
214}
215
216int OffloadGlinkConnection::GlinkPoll()
217{
218 ssize_t rc = 0;
219 struct pollfd poll_fd;
220
221 // wait for Rx data available in fd, for 2 seconds timeout
222 poll_fd.fd = fd;
223 poll_fd.events = POLLIN;
224
225 rc = ::poll(&poll_fd, 1, 2000);
226
227 if(rc > 0)
228 {
229 if (poll_fd.revents & POLLIN)
230 return 0;
231 } else if (rc == 0) {
232 ALOGE("Glink poll timeout");
233 } else {
234 ALOGE("Glink poll error: %s\n", strerror(errno));
235 }
236
237 return -1;
238}
239
240int OffloadGlinkConnection::GlinkRead(uint8_t *data, size_t size)
241{
242 int rc = 0;
243 size_t bytes_read = 0;
244
245 if (fd < 0)
246 return -1;
247
248 if (0 != GlinkPoll())
249 return -1;
250
251 while (bytes_read < size)
252 {
253 rc = ::read(fd, data+bytes_read, size-bytes_read);
254 if (rc < 0) {
255 if (errno != EAGAIN) {
256 ALOGE("%s: Read error: %s, rc %d", __func__,
257 strerror(errno), rc);
258 goto read_error;
259 }
260 } else if (rc == 0) {
261 ALOGE("%s: Zero length packet received or hardware connection went off",
262 __func__);
263 }
264 bytes_read += rc;
265 }
266 return 0;
267
268read_error:
269 return -1;
270}
271
272int OffloadGlinkConnection::GlinkWrite(uint8_t *buf, size_t buflen)
273{
274 size_t bytes_written_out = 0;
275 int rc = 0;
276
277 if (fd < 0)
278 return -1;
279
280 if (!buflen) {
281 ALOGE("%s: Invalid buffer len", __func__);
282 return 0;
283 }
284
285 while (bytes_written_out < buflen) {
286 rc = ::write (fd, buf+bytes_written_out, buflen-bytes_written_out);
287 if (rc < 0) {
288 ALOGE("%s: Write returned failure %d", __func__, rc);
289 return errno;
290 }
291 bytes_written_out += rc;
292 }
293 rc = 0;
294
295 return rc;
296}
297
298} // namespace vibrator
299} // namespace hardware
300} // namespace android
301} // namespace aidl