1 /*
2  * Copyright Samsung Electronics Co.,LTD.
3  * Copyright (C) 2017 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 #include <cstring>
18 
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <fcntl.h>
22 #include <sys/ioctl.h>
23 
24 #include <log/log.h>
25 
26 #include "acrylic_internal.h"
27 #include "acrylic_device.h"
28 
AcrylicDevice(const char * devpath)29 AcrylicDevice::AcrylicDevice(const char *devpath)
30     : mDevPath(devpath), mDevFD(-1)
31 {
32 }
33 
~AcrylicDevice()34 AcrylicDevice::~AcrylicDevice()
35 {
36     if (mDevFD >= 0)
37         ::close(mDevFD);
38 }
39 
open()40 bool AcrylicDevice::open()
41 {
42     if (mDevFD >= 0)
43         return true;
44 
45     mDevFD = ::open(mDevPath.c_str(), O_RDWR);
46     if (mDevFD < 0) {
47         ALOGERR("Failed to open %s", mDevPath.c_str());
48         return false;
49     }
50 
51     ALOGD_TEST("Opened %s on fd %d", mDevPath.c_str(), mDevFD);
52 
53     return true;
54 }
55 
ioctl(int cmd,void * arg)56 int AcrylicDevice::ioctl(int cmd, void *arg)
57 {
58     if (!open())
59         return -1;
60 
61     return ::ioctl(mDevFD, cmd, arg);
62 }
63 
AcrylicRedundantDevice(const char * devpath)64 AcrylicRedundantDevice::AcrylicRedundantDevice(const char *devpath)
65     : mDevPath(devpath), mDevFd{-1, -1, -1}, mFdIdx(0)
66 {
67     mDevPath = devpath;
68 }
69 
~AcrylicRedundantDevice()70 AcrylicRedundantDevice::~AcrylicRedundantDevice()
71 {
72     for (int i = 0; i < MAX_DEVICE_FD; i++)
73         ::close(mDevFd[i]);
74 }
75 
open()76 bool AcrylicRedundantDevice::open()
77 {
78     if (mDevFd[0] >= 0)
79         return true;
80 
81     for (int i = 0; i < MAX_DEVICE_FD; i++) {
82         if (mDevFd[i] < 0) {
83             mDevFd[i] = ::open(mDevPath.c_str(), O_RDWR);
84             if (mDevFd[i] < 0) {
85                 ALOGERR("Failed to open %s for devfd[%d]", mDevPath.c_str(), i);
86                 while (i-- > 0) {
87                     ::close(mDevFd[i]);
88                     mDevFd[i] = -1;
89                 }
90                 return false;
91             }
92 
93             ALOGD_TEST("Opened %s on devfd[%d] %d", mDevPath.c_str(), i, mDevFd[i]);
94         }
95     }
96 
97     return true;
98 }
99 
ioctl_unique(int cmd,void * arg)100 int AcrylicRedundantDevice::ioctl_unique(int cmd, void *arg)
101 {
102     if (!open())
103         return -1;
104 
105     return ::ioctl(mDevFd[0], cmd, arg);
106 }
107 
ioctl_current(int cmd,void * arg)108 int AcrylicRedundantDevice::ioctl_current(int cmd, void *arg)
109 {
110     if (!open())
111         return -1;
112 
113     return ::ioctl(mDevFd[mFdIdx], cmd, arg);
114 }
115 
ioctl_broadcast(int cmd,void * arg)116 int AcrylicRedundantDevice::ioctl_broadcast(int cmd, void *arg) {
117     if (!open())
118         return -1;
119 
120     for (int i = 0; i < MAX_DEVICE_FD; i++) {
121         int ret = ::ioctl(mDevFd[i], cmd, arg);
122         if (ret < 0)
123             return ret;
124     }
125 
126     return 0;
127 }
128