1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "hdf_audio_input_event.h"
17 #include <fcntl.h>
18 #include <poll.h>
19 #include <pthread.h>
20 #include <unistd.h>
21 #include <linux/input.h>
22 #include "hdf_audio_pnp_server.h"
23 #include "osal_time.h"
24 #include "securec.h"
25 #include "audio_uhdf_log.h"
26
27 #define HDF_LOG_TAG HDF_AUDIO_HAL_HOST
28 #define INPUT_EVT_MAX_CNT 4
29 #define WAIT_THREAD_END_TIME_MS 1
30 static struct pollfd g_fdSets[INPUT_EVT_MAX_CNT];
31 static int32_t g_inputDevCnt = 0;
32 static bool g_bRunThread = false;
33
AudioAnalogHeadsetDeviceCheck(struct input_event evt)34 static int32_t AudioAnalogHeadsetDeviceCheck(struct input_event evt)
35 {
36 struct AudioEvent audioEvent;
37
38 AUDIO_FUNC_LOGI("enter.");
39 audioEvent.eventType = (evt.value == 0) ? AUDIO_DEVICE_REMOVE : AUDIO_DEVICE_ADD;
40 audioEvent.deviceType = AUDIO_DEVICE_UNKNOWN;
41 switch (evt.code) {
42 case SW_HEADPHONE_INSERT:
43 audioEvent.deviceType = AUDIO_HEADPHONE;
44 break;
45 case SW_MICROPHONE_INSERT:
46 audioEvent.deviceType = AUDIO_HEADSET;
47 break;
48 case SW_LINEOUT_INSERT:
49 audioEvent.deviceType = AUDIO_LINEOUT;
50 break;
51 default: // SW_JACK_PHYSICAL_INSERT = 0x7, SW_LINEIN_INSERT = 0xd and other.
52 AUDIO_FUNC_LOGE("n't surpport code =0x%{public}x\n", evt.code);
53 return HDF_FAILURE;
54 }
55 return AudioPnpUpdateInfoOnly(audioEvent);
56 }
57
AudioPnpInputCheck(struct input_event evt)58 static void AudioPnpInputCheck(struct input_event evt)
59 {
60 switch (evt.type) {
61 case EV_SYN:
62 break;
63 case EV_SW:
64 // The code possible is SW_HEADPHONE_INSERT=2,SW_MICROPHONE_INSERT=4,SW_LINEOUT_INSERT=6
65 // or SW_LINEIN_INSERT=13.
66 AUDIO_FUNC_LOGD("evt.type = EV_SW5, code =0x%{public}d, value = %{public}d\n", evt.code,
67 evt.value);
68 (void)AudioAnalogHeadsetDeviceCheck(evt);
69 break;
70 case EV_KEY:
71 // The key on the board or on the analog headset.
72 // The code possible is KEY_MEDIA=226,KEY_KP7=0x71(mute),KEY_KP8=0x72(volumn-),
73 // KEY_KP9=0x73(vol+) or KEY_KPMINUS=0x74(power).
74 if ((evt.code == KEY_MEDIA) || (evt.code == KEY_KP7) || (evt.code == KEY_KP8) || (evt.code == KEY_KP9)) {
75 AUDIO_FUNC_LOGD("evt.type = EV_KEY1, code = 0x%{public}x, value = %{public}d.", evt.code, evt.value);
76 }
77 break;
78 case EV_REL: // mouse move event.
79 case EV_MSC:
80 default:
81 break;
82 }
83 }
84
AudioPnpInputPollAndRead(void)85 static int32_t AudioPnpInputPollAndRead(void)
86 {
87 int32_t i;
88 int32_t ret;
89 int32_t n = g_inputDevCnt;
90 struct input_event evt;
91
92 ret = poll(g_fdSets, (nfds_t)n, -1);
93 if (ret < 0) {
94 AUDIO_FUNC_LOGE("[poll] failed, %{public}d", errno);
95 return HDF_FAILURE;
96 }
97
98 for (i = 0; i < n; i++) {
99 if ((uint32_t)g_fdSets[i].revents & POLLIN) {
100 if (read(g_fdSets[i].fd, (void *)&evt, sizeof(evt)) < 0) {
101 AUDIO_FUNC_LOGE("[read] failed, %{public}d", errno);
102 return HDF_FAILURE;
103 }
104 AudioPnpInputCheck(evt);
105 }
106 }
107
108 return HDF_SUCCESS;
109 }
110
AudioPnpInputOpen(void)111 static int32_t AudioPnpInputOpen(void)
112 {
113 int32_t i;
114 int32_t j;
115 char *devices[INPUT_EVT_MAX_CNT] = {
116 "/dev/input/event1",
117 "/dev/input/event2",
118 "/dev/input/event3",
119 "/dev/input/event4"
120 };
121
122 AUDIO_FUNC_LOGI("enter.");
123 j = 0;
124 for (i = 0; i < INPUT_EVT_MAX_CNT; i++) {
125 g_fdSets[j].fd = open(devices[i], O_RDONLY);
126 if (g_fdSets[j].fd < 0) {
127 AUDIO_FUNC_LOGW("[open] %{public}s failed!", devices[i]);
128 continue;
129 }
130 AUDIO_FUNC_LOGI("[open] %{public}s success!", devices[i]);
131 g_fdSets[j].events = POLLIN;
132 j++;
133 }
134 g_inputDevCnt = j;
135
136 return (j == 0) ? HDF_FAILURE : HDF_SUCCESS;
137 }
138
AudioPnpInputStart(void * useless)139 static void AudioPnpInputStart(void *useless)
140 {
141 int ret;
142 (void)useless;
143
144 AUDIO_FUNC_LOGI("audio input start.");
145 if (AudioPnpInputOpen() != HDF_SUCCESS) {
146 return;
147 }
148
149 do {
150 ret = AudioPnpInputPollAndRead();
151 if (ret != HDF_SUCCESS) {
152 AUDIO_FUNC_LOGE("[AudioPnpInputPollAndRead] failed!");
153 return;
154 }
155 } while (g_bRunThread);
156
157 return;
158 }
159
AudioHeadsetPnpInputStartThread(void)160 int32_t AudioHeadsetPnpInputStartThread(void)
161 {
162 const char *threadName = "pnp_headset";
163 AUDIO_FUNC_LOGI("create audio headset pnp uevent thread");
164 g_bRunThread = true;
165
166 FfrtTaskAttr attr;
167 FfrtAttrInitFunc()(&attr);
168 FfrtAttrSetQosFunc()(&attr, FFRT_QOS_DEFAULT);
169 FfrtAttrSetNameFunc()(&attr, threadName);
170 FfrtSubmitBaseFunc()(FfrtCreateFunctionWrapper(AudioPnpInputStart, NULL, NULL), NULL, NULL, &attr);
171
172 return HDF_SUCCESS;
173 }
174
AudioHeadsetPnpInputEndThread(void)175 void AudioHeadsetPnpInputEndThread(void)
176 {
177 AUDIO_FUNC_LOGI("audio headset pnp uevent thread exit");
178 g_bRunThread = false;
179 OsalMSleep(WAIT_THREAD_END_TIME_MS);
180 }
181