• 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 
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