1 /*
2 * Copyright (c) 2022-2023 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_pnp_uevent.h"
17 #include <ctype.h>
18 #include <dirent.h>
19 #include <errno.h>
20 #include <fcntl.h>
21
22 #include <linux/netlink.h>
23
24 #include <poll.h>
25 #include <pthread.h>
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <sys/socket.h>
29 #include <sys/types.h>
30 #include <unistd.h>
31
32 #include "audio_uhdf_log.h"
33 #include "hdf_audio_pnp_server.h"
34 #include "hdf_base.h"
35 #include "hdf_device_object.h"
36 #include "osal_time.h"
37 #include "securec.h"
38
39 #define HDF_LOG_TAG HDF_AUDIO_HOST
40
41 #define UEVENT_ACTION "ACTION="
42 #define UEVENT_NAME "NAME="
43 #define UEVENT_STATE "STATE="
44 #define UEVENT_DEV_NAME "DEVNAME="
45 #define UEVENT_DEVTYPE "DEVTYPE="
46 #define UEVENT_SUBSYSTEM "SUBSYSTEM="
47 #define UEVENT_SWITCH_NAME "SWITCH_NAME="
48 #define UEVENT_SWITCH_STATE "SWITCH_STATE="
49 #define UEVENT_ID_MODEL "ID_MODEL="
50 #define UEVENT_HDI_NAME "HID_NAME="
51 #define UEVENT_ACTION_ADD "add"
52 #define UEVENT_ACTION_REMOVE "remove"
53 #define UEVENT_ACTION_CHANGE "change"
54 #define UEVENT_TYPE_EXTCON "extcon3"
55 #define UEVENT_NAME_HEADSET "headset"
56 #define UEVENT_STATE_ANALOG_HS0 "MICROPHONE=0"
57 #define UEVENT_STATE_ANALOG_HS1 "MICROPHONE=1"
58 #define UEVENT_SUBSYSTEM_SWITCH "switch"
59 #define UEVENT_SWITCH_NAME_H2W "h2w"
60 #define UEVENT_USB_AUDIO "USB Audio"
61 #define UEVENT_USB_HEADSET "HEADSET"
62 #define UEVENT_SUBSYSTEM_USB "usb"
63 #define UEVENT_SUBSYSTEM_USB_DEVICE "usb_device"
64
65 #define UEVENT_SOCKET_BUFF_SIZE (64 * 1024)
66 #define UEVENT_SOCKET_GROUPS 0xffffffff
67 #define UEVENT_MSG_LEN 2048
68 #define AUDIO_EVENT_INFO_LEN_MAX 256
69 #define UEVENT_POLL_WAIT_TIME 100
70 #define AUDIO_UEVENT_USB_DEVICE_COUNT 10
71
72 #define USB_DEV_NAME_LEN_MAX 64
73 #define USB_DES_LEN_MAX 4096
74 #define DEV_BUS_USB_DIR "/dev/bus/usb"
75 #define BUS_USB_DIR "bus/usb"
76 #define USB_IF_DESC_LEN 9
77 #define USB_IF_CLASS_OFFSET 5
78 #define USB_IF_SUBCLASS_OFFSET 6
79 #define USB_AUDIO_DESC_TYPE 0x4
80 #define USB_AUDIO_CLASS 1
81 #define USB_AUDIO_SUBCLASS_CTRL 1
82 #define AUDIO_DEVICE_ONLINE 1
83 #define AUDIO_DEVICE_WAIT_ONLINE 20
84 #define AUDIO_DEVICE_WAIT_TRY_TIME 10
85 #define AUDIO_DEVICE_WAIT_USB_ONLINE 1300
86
87 struct UsbDevice {
88 int8_t devName[USB_DEV_NAME_LEN_MAX];
89 uint8_t desc[USB_DES_LEN_MAX];
90 size_t descLen;
91 };
92
93 struct AudioPnpUevent {
94 const char *action;
95 const char *name;
96 const char *state;
97 const char *devType;
98 const char *subSystem;
99 const char *switchName;
100 const char *switchState;
101 const char *hidName;
102 const char *devName;
103 };
104
105 struct AudioEvent g_audioPnpDeviceState = {
106 .eventType = AUDIO_EVENT_UNKNOWN,
107 .deviceType = AUDIO_DEVICE_UNKNOWN,
108 };
109
IsUpdatePnpDeviceState(struct AudioEvent * pnpDeviceEvent)110 static bool IsUpdatePnpDeviceState(struct AudioEvent *pnpDeviceEvent)
111 {
112 if (pnpDeviceEvent->eventType == g_audioPnpDeviceState.eventType &&
113 pnpDeviceEvent->deviceType == g_audioPnpDeviceState.deviceType) {
114 return false;
115 }
116 return true;
117 }
118
UpdatePnpDeviceState(struct AudioEvent * pnpDeviceEvent)119 static void UpdatePnpDeviceState(struct AudioEvent *pnpDeviceEvent)
120 {
121 g_audioPnpDeviceState.eventType = pnpDeviceEvent->eventType;
122 g_audioPnpDeviceState.deviceType = pnpDeviceEvent->deviceType;
123 }
124
CheckUsbDesc(struct UsbDevice * usbDevice)125 static int32_t CheckUsbDesc(struct UsbDevice *usbDevice)
126 {
127 if (usbDevice->descLen > USB_DES_LEN_MAX) {
128 AUDIO_FUNC_LOGE("usbDevice->descLen is more than USB_DES_LEN_MAX");
129 return HDF_ERR_INVALID_PARAM;
130 }
131 for (size_t len = 0; len < usbDevice->descLen;) {
132 size_t descLen = usbDevice->desc[len];
133 if (descLen == 0) {
134 AUDIO_FUNC_LOGE("descLen is 0");
135 return HDF_ERR_INVALID_PARAM;
136 }
137
138 if (descLen < USB_IF_DESC_LEN) {
139 len += descLen;
140 continue;
141 }
142
143 int32_t descType = usbDevice->desc[len + 1];
144 if (descType != USB_AUDIO_DESC_TYPE) {
145 len += descLen;
146 continue;
147 }
148
149 /* According to the 1.0 and 2.0 usb standard protocols, the audio field corresponding to the interface
150 * description type is: offset=1 interface descriptor type is 4; offset=5 interface class,audio is 1; offset=6
151 * interface subclass,audio control is 1 */
152 int32_t usbClass = usbDevice->desc[len + USB_IF_CLASS_OFFSET];
153 int32_t subClass = usbDevice->desc[len + USB_IF_SUBCLASS_OFFSET];
154 if (usbClass == USB_AUDIO_CLASS && subClass == USB_AUDIO_SUBCLASS_CTRL) {
155 AUDIO_FUNC_LOGI(
156 "descType %{public}d, usbClass %{public}d, subClass %{public}d", descType, usbClass, subClass);
157 return AUDIO_DEVICE_ONLINE;
158 }
159 len += descLen;
160 }
161 return HDF_SUCCESS;
162 }
163
ReadAndScanUsbDev(const char * devPath)164 static int32_t ReadAndScanUsbDev(const char *devPath)
165 {
166 FILE *fp = NULL;
167 struct UsbDevice usbDevice;
168 size_t len;
169 errno_t error;
170 uint32_t tryTime = 0;
171 char realpathRes[PATH_MAX + 1] = {'\0'};
172
173 if (devPath == NULL) {
174 AUDIO_FUNC_LOGE("audio devPath null");
175 return HDF_FAILURE;
176 }
177
178 while (tryTime < AUDIO_DEVICE_WAIT_TRY_TIME) {
179 if (realpath(devPath, realpathRes) != NULL) {
180 break;
181 }
182
183 tryTime++;
184 AUDIO_FUNC_LOGW("audio try[%{public}d] realpath fail[%{public}d]", tryTime, errno);
185 OsalMSleep(AUDIO_DEVICE_WAIT_ONLINE);
186 }
187
188 fp = fopen(realpathRes, "r");
189 if (fp == NULL) {
190 AUDIO_FUNC_LOGE("audio realpath open fail[%{public}d]", errno);
191 return HDF_FAILURE;
192 }
193
194 len = fread(usbDevice.desc, 1, sizeof(usbDevice.desc) - 1, fp);
195 if (len == 0) {
196 AUDIO_FUNC_LOGE("audio realpath read fail");
197 (void)fclose(fp);
198 return HDF_FAILURE;
199 }
200 (void)fclose(fp);
201
202 error = strncpy_s((char *)usbDevice.devName, sizeof(usbDevice.devName), realpathRes, sizeof(usbDevice.devName) - 1);
203 if (error != EOK) {
204 AUDIO_FUNC_LOGE("audio realpath strncpy fail");
205 return HDF_FAILURE;
206 }
207
208 usbDevice.descLen = len;
209 return CheckUsbDesc(&usbDevice);
210 }
211
212 #define SWITCH_STATE_PATH "/sys/class/switch/h2w/state"
213 #define STATE_PATH_ITEM_SIZE 1
214
DetectAnalogHeadsetState(struct AudioEvent * audioEvent)215 static int32_t DetectAnalogHeadsetState(struct AudioEvent *audioEvent)
216 {
217 int8_t state = 0;
218 FILE *fp = fopen(SWITCH_STATE_PATH, "r");
219 if (fp == NULL) {
220 AUDIO_FUNC_LOGE("audio open switch state node fail, %{public}d", errno);
221 return HDF_ERR_INVALID_PARAM;
222 }
223
224 size_t ret = fread(&state, STATE_PATH_ITEM_SIZE, STATE_PATH_ITEM_SIZE, fp);
225 if (ret == 0) {
226 (void)fclose(fp);
227 AUDIO_FUNC_LOGE("audio read switch state node fail, %{public}d", errno);
228 return HDF_FAILURE;
229 }
230
231 AUDIO_FUNC_LOGI("audio switch state = %{public}c", state);
232 if (state == '0') {
233 audioEvent->eventType = AUDIO_DEVICE_REMOVE;
234 audioEvent->deviceType = AUDIO_HEADSET;
235 } else {
236 audioEvent->eventType = AUDIO_DEVICE_ADD;
237 audioEvent->deviceType = AUDIO_HEADSET;
238 }
239
240 (void)fclose(fp);
241 return HDF_SUCCESS;
242 }
243
244 struct AudioDevBusUsbDevice {
245 bool isUsed;
246 int8_t devName[USB_DEV_NAME_LEN_MAX];
247 };
248
249 struct AudioDevBusUsbDevice g_audioUsbDeviceList[AUDIO_UEVENT_USB_DEVICE_COUNT] = {0};
250
FindAudioUsbDevice(const char * devName)251 static bool FindAudioUsbDevice(const char *devName)
252 {
253 if (strlen(devName) > USB_DEV_NAME_LEN_MAX - 1) {
254 AUDIO_FUNC_LOGE("find usb audio device name exceed max len");
255 return false;
256 }
257
258 for (uint32_t i = 0; i < AUDIO_UEVENT_USB_DEVICE_COUNT; i++) {
259 if (g_audioUsbDeviceList[i].isUsed &&
260 (strncmp((char *)g_audioUsbDeviceList[i].devName, devName, strlen(devName)) == EOK)) {
261 return true;
262 }
263 }
264 return false;
265 }
AddAudioUsbDevice(const char * devName)266 static bool AddAudioUsbDevice(const char *devName)
267 {
268 if (strlen(devName) > USB_DEV_NAME_LEN_MAX - 1) {
269 AUDIO_FUNC_LOGE("add usb audio device name exceed max len");
270 return false;
271 }
272
273 if (FindAudioUsbDevice(devName)) {
274 AUDIO_FUNC_LOGI("find usb audio device name[%{public}s]", devName);
275 return true;
276 }
277
278 for (uint32_t i = 0; i < AUDIO_UEVENT_USB_DEVICE_COUNT; i++) {
279 if (g_audioUsbDeviceList[i].isUsed) {
280 continue;
281 }
282 if (strncpy_s((char *)g_audioUsbDeviceList[i].devName, USB_DEV_NAME_LEN_MAX, devName, strlen(devName)) != EOK) {
283 AUDIO_FUNC_LOGE("add usb audio device name fail");
284 return false;
285 }
286 g_audioUsbDeviceList[i].isUsed = true;
287 return true;
288 }
289 AUDIO_FUNC_LOGE("add usb audio device name fail");
290 return false;
291 }
292
DeleteAudioUsbDevice(const char * devName)293 static bool DeleteAudioUsbDevice(const char *devName)
294 {
295 if (strlen(devName) > USB_DEV_NAME_LEN_MAX - 1) {
296 AUDIO_FUNC_LOGE("delete usb audio device name exceed max len");
297 return false;
298 }
299
300 for (uint32_t i = 0; i < AUDIO_UEVENT_USB_DEVICE_COUNT; i++) {
301 if (g_audioUsbDeviceList[i].isUsed &&
302 strncmp((char *)g_audioUsbDeviceList[i].devName, devName, strlen(devName)) == EOK) {
303 g_audioUsbDeviceList[i].isUsed = false;
304 AUDIO_FUNC_LOGI("delete usb audio device name[%{public}s]", devName);
305 return true;
306 }
307 }
308
309 return false;
310 }
311
CheckAudioUsbDevice(const char * devName)312 static bool CheckAudioUsbDevice(const char *devName)
313 {
314 int32_t state = 0;
315 int32_t len;
316 char subDir[USB_DEV_NAME_LEN_MAX] = {0};
317
318 if (*devName == '\0') {
319 return false;
320 }
321 len = snprintf_s(subDir, USB_DEV_NAME_LEN_MAX, USB_DEV_NAME_LEN_MAX - 1, "/dev/" "%s", devName);
322 if (len < 0) {
323 AUDIO_FUNC_LOGE("audio snprintf dev dir fail");
324 return false;
325 }
326
327 AUDIO_FUNC_LOGI("usb device name[%{public}s]", devName);
328 state = ReadAndScanUsbDev(subDir);
329 if ((state == AUDIO_DEVICE_ONLINE) && AddAudioUsbDevice(devName)) {
330 return true;
331 }
332 return false;
333 }
334
IsBadName(const char * name)335 static inline bool IsBadName(const char *name)
336 {
337 if (*name == '\0') {
338 AUDIO_FUNC_LOGE("name is null");
339 return true;
340 }
341
342 while (*name != '\0') {
343 if (isdigit(*name++) == 0) {
344 return true;
345 }
346 }
347
348 return false;
349 }
350
ScanUsbBusSubDir(const char * subDir)351 static int32_t ScanUsbBusSubDir(const char *subDir)
352 {
353 int32_t len;
354 DIR *devDir = NULL;
355 struct dirent *dirEnt = NULL;
356
357 char devName[USB_DEV_NAME_LEN_MAX] = {0};
358
359 devDir = opendir(subDir);
360 if (devDir == NULL) {
361 AUDIO_FUNC_LOGE("open usb sub dir failed");
362 return HDF_ERR_INVALID_PARAM;
363 }
364
365 int32_t state = HDF_SUCCESS;
366 while (((dirEnt = readdir(devDir)) != NULL) && (state == HDF_SUCCESS)) {
367 if (IsBadName(dirEnt->d_name)) {
368 continue;
369 }
370
371 len = snprintf_s(devName, USB_DEV_NAME_LEN_MAX, USB_DEV_NAME_LEN_MAX - 1, "%s/%s", subDir, dirEnt->d_name);
372 if (len < 0) {
373 AUDIO_FUNC_LOGE("audio snprintf dev dir fail");
374 state = HDF_FAILURE;
375 break;
376 }
377
378 AUDIO_FUNC_LOGD("audio usb dir[%{public}s]", devName);
379 state = ReadAndScanUsbDev(devName);
380 if (state == AUDIO_DEVICE_ONLINE) {
381 char *subDevName = devName + strlen("/dev/");
382 AUDIO_FUNC_LOGI("audio sub dev dir=[%{public}s]", subDevName);
383 if (AddAudioUsbDevice(subDevName)) {
384 AUDIO_FUNC_LOGI("audio add usb audio device success");
385 break;
386 }
387 }
388 }
389
390 closedir(devDir);
391 return state;
392 }
393
DetectUsbHeadsetState(struct AudioEvent * audioEvent)394 static int32_t DetectUsbHeadsetState(struct AudioEvent *audioEvent)
395 {
396 int32_t len;
397 DIR *busDir = NULL;
398 struct dirent *dirEnt = NULL;
399
400 char subDir[USB_DEV_NAME_LEN_MAX] = {0};
401
402 busDir = opendir(DEV_BUS_USB_DIR);
403 if (busDir == NULL) {
404 AUDIO_FUNC_LOGE("open usb dir failed");
405 return HDF_ERR_INVALID_PARAM;
406 }
407
408 int32_t state = HDF_SUCCESS;
409 while (((dirEnt = readdir(busDir)) != NULL) && (state == HDF_SUCCESS)) {
410 if (IsBadName(dirEnt->d_name)) {
411 continue;
412 }
413
414 len = snprintf_s(subDir, USB_DEV_NAME_LEN_MAX, USB_DEV_NAME_LEN_MAX - 1, DEV_BUS_USB_DIR "/%s", dirEnt->d_name);
415 if (len < 0) {
416 AUDIO_FUNC_LOGE("audio snprintf dev dir fail");
417 break;
418 }
419
420 state = ScanUsbBusSubDir(subDir);
421 if (state == AUDIO_DEVICE_ONLINE) {
422 audioEvent->eventType = AUDIO_DEVICE_ADD;
423 audioEvent->deviceType = AUDIO_USB_HEADSET;
424 closedir(busDir);
425 return HDF_SUCCESS;
426 }
427 }
428
429 closedir(busDir);
430 return HDF_FAILURE;
431 }
432
AudioUsbHeadsetDetectDevice(struct AudioPnpUevent * audioPnpUevent)433 static int32_t AudioUsbHeadsetDetectDevice(struct AudioPnpUevent *audioPnpUevent)
434 {
435 struct AudioEvent audioEvent = {0};
436
437 if (audioPnpUevent == NULL) {
438 AUDIO_FUNC_LOGE("audioPnpUevent is null");
439 return HDF_ERR_INVALID_PARAM;
440 }
441
442 if (audioPnpUevent->action == NULL || audioPnpUevent->devName == NULL || audioPnpUevent->subSystem == NULL ||
443 audioPnpUevent->devType == NULL) {
444 AUDIO_FUNC_LOGE("audioPnpUevent element is null");
445 return HDF_ERR_INVALID_PARAM;
446 }
447
448 if ((strcmp(audioPnpUevent->subSystem, UEVENT_SUBSYSTEM_USB) != 0) ||
449 (strcmp(audioPnpUevent->devType, UEVENT_SUBSYSTEM_USB_DEVICE) != 0) ||
450 (strstr(audioPnpUevent->devName, BUS_USB_DIR) == NULL)) {
451 return HDF_ERR_INVALID_PARAM;
452 }
453
454 if (strcmp(audioPnpUevent->action, UEVENT_ACTION_ADD) == 0) {
455 if (!CheckAudioUsbDevice(audioPnpUevent->devName)) {
456 AUDIO_FUNC_LOGW("check audio usb device not exist, not add");
457 return HDF_ERR_INVALID_PARAM;
458 }
459 audioEvent.eventType = AUDIO_DEVICE_ADD;
460 } else if (strcmp(audioPnpUevent->action, UEVENT_ACTION_REMOVE) == 0) {
461 if (!DeleteAudioUsbDevice(audioPnpUevent->devName)) {
462 AUDIO_FUNC_LOGW("check audio usb device[%{public}s] not exist, not delete", audioPnpUevent->devName);
463 return HDF_ERR_INVALID_PARAM;
464 }
465 audioEvent.eventType = AUDIO_DEVICE_REMOVE;
466 } else {
467 return HDF_FAILURE;
468 }
469
470 audioEvent.deviceType = AUDIO_USB_HEADSET;
471 AUDIO_FUNC_LOGI("audio usb headset [%{public}s]", audioEvent.eventType == AUDIO_DEVICE_ADD ? "add" : "removed");
472
473 if (!IsUpdatePnpDeviceState(&audioEvent)) {
474 AUDIO_FUNC_LOGI("audio usb device[%{public}u] state[%{public}u] not need flush !", audioEvent.deviceType,
475 audioEvent.eventType);
476 return HDF_SUCCESS;
477 }
478 UpdatePnpDeviceState(&audioEvent);
479
480 return AudioPnpUpdateInfoOnly(audioEvent);
481 }
482
AudioAnalogHeadsetDetectDevice(struct AudioPnpUevent * audioPnpUevent)483 static int32_t AudioAnalogHeadsetDetectDevice(struct AudioPnpUevent *audioPnpUevent)
484 {
485 struct AudioEvent audioEvent;
486 if (audioPnpUevent == NULL) {
487 AUDIO_FUNC_LOGE("audioPnpUevent is null!");
488 return HDF_ERR_INVALID_PARAM;
489 }
490
491 if (strncmp(audioPnpUevent->subSystem, UEVENT_SUBSYSTEM_SWITCH, strlen(UEVENT_SUBSYSTEM_SWITCH)) == 0) {
492 static uint32_t h2wTypeLast = AUDIO_HEADSET;
493 if (strncmp(audioPnpUevent->switchName, UEVENT_SWITCH_NAME_H2W, strlen(UEVENT_SWITCH_NAME_H2W)) != 0) {
494 AUDIO_FUNC_LOGE("the switch name of 'h2w' not found!");
495 return HDF_FAILURE;
496 }
497 if (audioPnpUevent->switchState[0] == '0') {
498 audioEvent.eventType = AUDIO_DEVICE_REMOVE;
499 audioEvent.deviceType = h2wTypeLast;
500 } else if ((audioPnpUevent->switchState[0] == '1') || (audioPnpUevent->switchState[0] == '2')) {
501 audioEvent.eventType = AUDIO_DEVICE_ADD;
502 audioEvent.deviceType = AUDIO_HEADSET;
503 } else if (audioPnpUevent->switchState[0] == '4'){
504 audioEvent.eventType = AUDIO_DEVICE_ADD;
505 audioEvent.deviceType = AUDIO_ADAPTER_DEVICE;
506 } else {
507 audioEvent.eventType = AUDIO_DEVICE_ADD;
508 audioEvent.deviceType = AUDIO_DEVICE_UNKNOWN;
509 }
510 h2wTypeLast = audioEvent.deviceType;
511 } else {
512 if (strncmp(audioPnpUevent->action, UEVENT_ACTION_CHANGE, strlen(UEVENT_ACTION_CHANGE)) != 0) {
513 return HDF_FAILURE;
514 }
515 if (strstr(audioPnpUevent->name, UEVENT_NAME_HEADSET) == NULL) {
516 return HDF_FAILURE;
517 }
518 if (strncmp(audioPnpUevent->devType, UEVENT_TYPE_EXTCON, strlen(UEVENT_TYPE_EXTCON)) != 0) {
519 return HDF_FAILURE;
520 }
521 if (strstr(audioPnpUevent->state, UEVENT_STATE_ANALOG_HS0) != NULL) {
522 audioEvent.eventType = AUDIO_DEVICE_REMOVE;
523 } else if (strstr(audioPnpUevent->state, UEVENT_STATE_ANALOG_HS1) != NULL) {
524 audioEvent.eventType = AUDIO_DEVICE_ADD;
525 } else {
526 return HDF_FAILURE;
527 }
528 audioEvent.deviceType = AUDIO_HEADSET;
529 }
530
531 AUDIO_FUNC_LOGI("audio analog [%{public}s][%{public}s]",
532 audioEvent.deviceType == AUDIO_HEADSET ? "headset" : "headphone",
533 audioEvent.eventType == AUDIO_DEVICE_ADD ? "add" : "removed");
534
535 if (!IsUpdatePnpDeviceState(&audioEvent)) {
536 AUDIO_FUNC_LOGI("audio analog device[%{public}u] state[%{public}u] not need flush !", audioEvent.deviceType,
537 audioEvent.eventType);
538 return HDF_SUCCESS;
539 }
540 UpdatePnpDeviceState(&audioEvent);
541 return AudioPnpUpdateInfoOnly(audioEvent);
542 }
543
AudioPnpUeventParse(const char * msg,const ssize_t strLength)544 static bool AudioPnpUeventParse(const char *msg, const ssize_t strLength)
545 {
546 struct AudioPnpUevent audioPnpUevent = {"", "", "", "", "", "", "", "", ""};
547
548 if (strncmp(msg, "libudev", strlen("libudev")) == 0) {
549 return false;
550 }
551
552 if (strLength > UEVENT_MSG_LEN + 1) {
553 AUDIO_FUNC_LOGE("strLength > UEVENT_MSG_LEN + 1");
554 return false;
555 }
556 for (const char *msgTmp = msg; msgTmp < (msg + strLength);) {
557 if (*msgTmp == '\0') {
558 msgTmp++;
559 continue;
560 }
561
562 if (strncmp(msgTmp, UEVENT_ACTION, strlen(UEVENT_ACTION)) == 0) {
563 msgTmp += strlen(UEVENT_ACTION);
564 audioPnpUevent.action = msgTmp;
565 } else if (strncmp(msgTmp, UEVENT_DEV_NAME, strlen(UEVENT_DEV_NAME)) == 0) {
566 msgTmp += strlen(UEVENT_DEV_NAME);
567 audioPnpUevent.devName = msgTmp;
568 } else if (strncmp(msgTmp, UEVENT_NAME, strlen(UEVENT_NAME)) == 0) {
569 msgTmp += strlen(UEVENT_NAME);
570 audioPnpUevent.name = msgTmp;
571 } else if (strncmp(msgTmp, UEVENT_STATE, strlen(UEVENT_STATE)) == 0) {
572 msgTmp += strlen(UEVENT_STATE);
573 audioPnpUevent.state = msgTmp;
574 } else if (strncmp(msgTmp, UEVENT_DEVTYPE, strlen(UEVENT_DEVTYPE)) == 0) {
575 msgTmp += strlen(UEVENT_DEVTYPE);
576 audioPnpUevent.devType = msgTmp;
577 } else if (strncmp(msgTmp, UEVENT_SUBSYSTEM, strlen(UEVENT_SUBSYSTEM)) == 0) {
578 msgTmp += strlen(UEVENT_SUBSYSTEM);
579 audioPnpUevent.subSystem = msgTmp;
580 } else if (strncmp(msgTmp, UEVENT_SWITCH_NAME, strlen(UEVENT_SWITCH_NAME)) == 0) {
581 msgTmp += strlen(UEVENT_SWITCH_NAME);
582 audioPnpUevent.switchName = msgTmp;
583 } else if (strncmp(msgTmp, UEVENT_SWITCH_STATE, strlen(UEVENT_SWITCH_STATE)) == 0) {
584 msgTmp += strlen(UEVENT_SWITCH_STATE);
585 audioPnpUevent.switchState = msgTmp;
586 } else if (strncmp(msgTmp, UEVENT_HDI_NAME, strlen(UEVENT_HDI_NAME)) == 0) {
587 msgTmp += strlen(UEVENT_HDI_NAME);
588 audioPnpUevent.hidName = msgTmp;
589 }
590 msgTmp += strlen(msgTmp) + 1;
591 }
592
593 if (AudioAnalogHeadsetDetectDevice(&audioPnpUevent) == HDF_SUCCESS) {
594 return true;
595 }
596 if (AudioUsbHeadsetDetectDevice(&audioPnpUevent) == HDF_SUCCESS) {
597 return true;
598 }
599
600 return false;
601 }
602
AudioPnpUeventOpen(int * fd)603 static int AudioPnpUeventOpen(int *fd)
604 {
605 int socketFd = -1;
606 int buffSize = UEVENT_SOCKET_BUFF_SIZE;
607 const int32_t on = 1; // turn on passcred
608 struct sockaddr_nl addr;
609
610 if (memset_s(&addr, sizeof(addr), 0, sizeof(addr)) != EOK) {
611 AUDIO_FUNC_LOGE("addr memset_s failed!");
612 return HDF_FAILURE;
613 }
614 addr.nl_family = AF_NETLINK;
615 addr.nl_pid = (sa_family_t)getpid();
616 addr.nl_groups = UEVENT_SOCKET_GROUPS;
617
618 socketFd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
619 if (socketFd < 0) {
620 AUDIO_FUNC_LOGE("socket failed, %{public}d", errno);
621 return HDF_FAILURE;
622 }
623
624 if (setsockopt(socketFd, SOL_SOCKET, SO_RCVBUF, &buffSize, sizeof(buffSize)) != 0) {
625 AUDIO_FUNC_LOGE("setsockopt SO_RCVBUF failed, %{public}d", errno);
626 close(socketFd);
627 return HDF_FAILURE;
628 }
629
630 if (setsockopt(socketFd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) != 0) {
631 AUDIO_FUNC_LOGE("setsockopt SO_PASSCRED failed, %{public}d", errno);
632 close(socketFd);
633 return HDF_FAILURE;
634 }
635
636 if (bind(socketFd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
637 AUDIO_FUNC_LOGE("bind socket failed, %{public}d", errno);
638 close(socketFd);
639 return HDF_FAILURE;
640 }
641
642 *fd = socketFd;
643
644 return HDF_SUCCESS;
645 }
646
AudioPnpReadUeventMsg(int sockFd,char * buffer,size_t length)647 static ssize_t AudioPnpReadUeventMsg(int sockFd, char *buffer, size_t length)
648 {
649 char credMsg[CMSG_SPACE(sizeof(struct ucred))] = {0};
650 struct iovec iov;
651 struct sockaddr_nl addr;
652 struct msghdr msghdr = {0};
653
654 (void)memset_s(&addr, sizeof(addr), 0, sizeof(addr));
655
656 iov.iov_base = buffer;
657 iov.iov_len = length;
658
659 msghdr.msg_name = &addr;
660 msghdr.msg_namelen = sizeof(addr);
661 msghdr.msg_iov = &iov;
662 msghdr.msg_iovlen = 1;
663 msghdr.msg_control = credMsg;
664 msghdr.msg_controllen = sizeof(credMsg);
665
666 ssize_t len = recvmsg(sockFd, &msghdr, 0);
667 if (len <= 0) {
668 return HDF_FAILURE;
669 }
670
671 struct cmsghdr *hdr = CMSG_FIRSTHDR(&msghdr);
672 if (hdr == NULL || hdr->cmsg_type != SCM_CREDENTIALS) {
673 AUDIO_FUNC_LOGW("Unexpected control message, ignored");
674 *buffer = '\0';
675 return HDF_FAILURE;
676 }
677
678 return len;
679 }
680
DetectAudioDevice(struct HdfDeviceObject * device)681 void DetectAudioDevice(struct HdfDeviceObject *device)
682 {
683 int32_t ret;
684 struct AudioEvent audioEvent = {0};
685 char pnpInfo[AUDIO_EVENT_INFO_LEN_MAX] = {0};
686
687 OsalMSleep(AUDIO_DEVICE_WAIT_USB_ONLINE); // Wait until the usb node is successfully created
688 ret = DetectAnalogHeadsetState(&audioEvent);
689 if ((ret == HDF_SUCCESS) && (audioEvent.eventType == AUDIO_DEVICE_ADD)) {
690 AUDIO_FUNC_LOGI("audio detect analog headset");
691 goto FINISH;
692 }
693
694 audioEvent.eventType = AUDIO_EVENT_UNKNOWN;
695 audioEvent.deviceType = AUDIO_DEVICE_UNKNOWN;
696 ret = DetectUsbHeadsetState(&audioEvent);
697 if ((ret == HDF_SUCCESS) && (audioEvent.eventType == AUDIO_DEVICE_ADD)) {
698 AUDIO_FUNC_LOGI("audio detect usb headset");
699 goto FINISH;
700 }
701
702 return;
703
704 FINISH:
705 if (!IsUpdatePnpDeviceState(&audioEvent)) {
706 AUDIO_FUNC_LOGI("audio first pnp device[%{public}u] state[%{public}u] not need flush !", audioEvent.deviceType,
707 audioEvent.eventType);
708 return;
709 }
710 ret = snprintf_s(pnpInfo, AUDIO_EVENT_INFO_LEN_MAX, AUDIO_EVENT_INFO_LEN_MAX - 1, "EVENT_TYPE=%u;DEVICE_TYPE=%u",
711 audioEvent.eventType, audioEvent.deviceType);
712 if (ret < 0) {
713 AUDIO_FUNC_LOGE("snprintf_s fail!");
714 return;
715 }
716
717 UpdatePnpDeviceState(&audioEvent);
718 if (HdfDeviceObjectSetServInfo(device, pnpInfo) != HDF_SUCCESS) {
719 AUDIO_FUNC_LOGE("set audio event status info failed!");
720 }
721 }
722
723 static bool g_pnpThreadRunning = false;
AudioPnpUeventStart(void * useless)724 static void *AudioPnpUeventStart(void *useless)
725 {
726 (void)useless;
727 ssize_t rcvLen;
728 int socketFd = -1;
729 struct pollfd fd;
730 char msg[UEVENT_MSG_LEN + 1] = {0};
731
732 AUDIO_FUNC_LOGI("audio uevent start");
733 if (AudioPnpUeventOpen(&socketFd) != HDF_SUCCESS) {
734 AUDIO_FUNC_LOGE("open audio pnp socket failed!");
735 return NULL;
736 }
737
738 fd.fd = socketFd;
739 fd.events = POLLIN | POLLERR;
740 fd.revents = 0;
741
742 while (g_pnpThreadRunning) {
743 if (poll(&fd, 1, -1) <= 0) {
744 AUDIO_FUNC_LOGE("audio event poll fail %{public}d", errno);
745 OsalMSleep(UEVENT_POLL_WAIT_TIME);
746 continue;
747 }
748
749 if (((uint32_t)fd.revents & POLLIN) == POLLIN) {
750 (void)memset_s(&msg, sizeof(msg), 0, sizeof(msg));
751 rcvLen = AudioPnpReadUeventMsg(socketFd, msg, UEVENT_MSG_LEN);
752 if (rcvLen <= 0) {
753 continue;
754 }
755
756 if (!AudioPnpUeventParse(msg, rcvLen)) {
757 continue;
758 }
759 } else if (((uint32_t)fd.revents & POLLERR) == POLLERR) {
760 AUDIO_FUNC_LOGE("audio event poll error");
761 }
762 }
763
764 close(socketFd);
765 return NULL;
766 }
767
AudioUsbPnpUeventStartThread(void)768 int32_t AudioUsbPnpUeventStartThread(void)
769 {
770 pthread_t thread;
771 pthread_attr_t tidsAttr;
772 const char *threadName = "pnp_usb";
773 g_pnpThreadRunning = true;
774
775 AUDIO_FUNC_LOGI("create audio usb uevent thread");
776 pthread_attr_init(&tidsAttr);
777 pthread_attr_setdetachstate(&tidsAttr, PTHREAD_CREATE_DETACHED);
778 if (pthread_create(&thread, &tidsAttr, AudioPnpUeventStart, NULL) != 0) {
779 AUDIO_FUNC_LOGE("create audio pnp uevent thread failed");
780 return HDF_FAILURE;
781 }
782
783 if (pthread_setname_np(thread, threadName) != 0) {
784 AUDIO_FUNC_LOGE("setname failed");
785 return HDF_FAILURE;
786 }
787
788 return HDF_SUCCESS;
789 }
790
AudioUsbPnpUeventStopThread(void)791 void AudioUsbPnpUeventStopThread(void)
792 {
793 AUDIO_FUNC_LOGI("audio pnp uevent thread exit");
794 g_pnpThreadRunning = false;
795 }
796