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