1 /*
2 * Copyright (c) 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 #ifndef LOG_TAG
16 #define LOG_TAG "AudioSocketThread"
17 #endif
18
19 #include "audio_socket_thread.h"
20 #include <cctype>
21 #include <cstdlib>
22 #include <dirent.h>
23 #include <linux/netlink.h>
24 #include <sys/socket.h>
25 #include <unistd.h>
26 #include <string>
27 #include "osal_time.h"
28 #include "audio_utils.h"
29 #include "audio_errors.h"
30 #include "securec.h"
31 #include "audio_policy_log.h"
32 #include "audio_pnp_server.h"
33
34 namespace OHOS {
35 namespace AudioStandard {
36 using namespace std;
37 AudioEvent AudioSocketThread::audioSocketEvent_ = {
38 .eventType = AUDIO_EVENT_UNKNOWN,
39 .deviceType = AUDIO_DEVICE_UNKNOWN,
40 };
41
42 AudioDevBusUsbDevice g_audioUsbDeviceList[AUDIO_UEVENT_USB_DEVICE_COUNT] = {};
43
IsUpdatePnpDeviceState(AudioEvent * pnpDeviceEvent)44 bool AudioSocketThread::IsUpdatePnpDeviceState(AudioEvent *pnpDeviceEvent)
45 {
46 if (pnpDeviceEvent->eventType == audioSocketEvent_.eventType &&
47 pnpDeviceEvent->deviceType == audioSocketEvent_.deviceType &&
48 pnpDeviceEvent->name == audioSocketEvent_.name &&
49 pnpDeviceEvent->address == audioSocketEvent_.address) {
50 return false;
51 }
52 return true;
53 }
54
UpdatePnpDeviceState(AudioEvent * pnpDeviceEvent)55 void AudioSocketThread::UpdatePnpDeviceState(AudioEvent *pnpDeviceEvent)
56 {
57 audioSocketEvent_.eventType = pnpDeviceEvent->eventType;
58 audioSocketEvent_.deviceType = pnpDeviceEvent->deviceType;
59 audioSocketEvent_.name = pnpDeviceEvent->name;
60 audioSocketEvent_.address = pnpDeviceEvent->address;
61 }
62
AudioPnpUeventOpen(int * fd)63 int AudioSocketThread::AudioPnpUeventOpen(int *fd)
64 {
65 int socketFd = -1;
66 int buffSize = UEVENT_SOCKET_BUFF_SIZE;
67 const int32_t on = 1; // turn on passcred
68 sockaddr_nl addr;
69
70 if (memset_s(&addr, sizeof(addr), 0, sizeof(addr)) != EOK) {
71 AUDIO_ERR_LOG("addr memset_s failed!");
72 return ERROR;
73 }
74 addr.nl_family = AF_NETLINK;
75 addr.nl_pid = ((uint32_t)gettid() << MOVE_NUM) | (uint32_t)getpid();
76 addr.nl_groups = UEVENT_SOCKET_GROUPS;
77
78 socketFd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
79 if (socketFd < 0) {
80 AUDIO_ERR_LOG("socket failed, %{public}d", errno);
81 return ERROR;
82 }
83
84 if (setsockopt(socketFd, SOL_SOCKET, SO_RCVBUF, &buffSize, sizeof(buffSize)) != 0) {
85 AUDIO_ERR_LOG("setsockopt SO_RCVBUF failed, %{public}d", errno);
86 CloseFd(socketFd);
87 return ERROR;
88 }
89
90 if (setsockopt(socketFd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) != 0) {
91 AUDIO_ERR_LOG("setsockopt SO_PASSCRED failed, %{public}d", errno);
92 CloseFd(socketFd);
93 return ERROR;
94 }
95
96 if (::bind(socketFd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
97 AUDIO_ERR_LOG("bind socket failed, %{public}d", errno);
98 CloseFd(socketFd);
99 return ERROR;
100 }
101
102 *fd = socketFd;
103 return SUCCESS;
104 }
105
AudioPnpReadUeventMsg(int sockFd,char * buffer,size_t length)106 ssize_t AudioSocketThread::AudioPnpReadUeventMsg(int sockFd, char *buffer, size_t length)
107 {
108 char credMsg[CMSG_SPACE(sizeof(struct ucred))] = {0};
109 iovec iov;
110 sockaddr_nl addr;
111 msghdr msghdr = {0};
112
113 memset_s(&addr, sizeof(addr), 0, sizeof(addr));
114
115 iov.iov_base = buffer;
116 iov.iov_len = length;
117
118 msghdr.msg_name = &addr;
119 msghdr.msg_namelen = sizeof(addr);
120 msghdr.msg_iov = &iov;
121 msghdr.msg_iovlen = 1;
122 msghdr.msg_control = credMsg;
123 msghdr.msg_controllen = sizeof(credMsg);
124
125 ssize_t len = recvmsg(sockFd, &msghdr, 0);
126 if (len <= 0) {
127 return ERROR;
128 }
129 cmsghdr *hdr = CMSG_FIRSTHDR(&msghdr);
130 if (hdr == NULL || hdr->cmsg_type != SCM_CREDENTIALS) {
131 AUDIO_ERR_LOG("Unexpected control message, ignored");
132 *buffer = '\0';
133 return ERROR;
134 }
135 return len;
136 }
137
SetAudioPnpUevent(AudioEvent * audioEvent,struct AudioPnpUevent * audioPnpUevent,uint32_t h2wTypeLast)138 static void SetAudioPnpUevent(AudioEvent *audioEvent, struct AudioPnpUevent *audioPnpUevent, uint32_t h2wTypeLast)
139 {
140 switch (audioPnpUevent->switchState[0]) {
141 case REMOVE_AUDIO_DEVICE:
142 audioEvent->eventType = PNP_EVENT_DEVICE_REMOVE;
143 audioEvent->deviceType = h2wTypeLast;
144 break;
145 case ADD_DEVICE_HEADSET:
146 case ADD_DEVICE_HEADSET_WITHOUT_MIC:
147 audioEvent->eventType = PNP_EVENT_DEVICE_ADD;
148 audioEvent->deviceType = PNP_DEVICE_HEADSET;
149 break;
150 case ADD_DEVICE_ADAPTER:
151 audioEvent->eventType = PNP_EVENT_DEVICE_ADD;
152 audioEvent->deviceType = PNP_DEVICE_ADAPTER_DEVICE;
153 break;
154 default:
155 audioEvent->eventType = PNP_EVENT_DEVICE_ADD;
156 audioEvent->deviceType = PNP_DEVICE_UNKNOWN;
157 break;
158 }
159 }
160
SetAudioPnpServerEventValue(AudioEvent * audioEvent,struct AudioPnpUevent * audioPnpUevent)161 int32_t AudioSocketThread::SetAudioPnpServerEventValue(AudioEvent *audioEvent, struct AudioPnpUevent *audioPnpUevent)
162 {
163 if (strncmp(audioPnpUevent->subSystem, UEVENT_SUBSYSTEM_SWITCH, strlen(UEVENT_SUBSYSTEM_SWITCH)) == 0) {
164 static uint32_t h2wTypeLast = PNP_DEVICE_HEADSET;
165 if (strncmp(audioPnpUevent->switchName, UEVENT_SWITCH_NAME_H2W, strlen(UEVENT_SWITCH_NAME_H2W)) != 0) {
166 AUDIO_ERR_LOG("the switch name of 'h2w' not found!");
167 return ERROR;
168 }
169 SetAudioPnpUevent(audioEvent, audioPnpUevent, h2wTypeLast);
170 h2wTypeLast = audioEvent->deviceType;
171 audioEvent->name = audioPnpUevent->name;
172 audioEvent->address = audioPnpUevent->devName;
173 } else {
174 if (strncmp(audioPnpUevent->action, UEVENT_ACTION_CHANGE, strlen(UEVENT_ACTION_CHANGE)) != 0) {
175 return ERROR;
176 }
177 if (strstr(audioPnpUevent->name, UEVENT_NAME_HEADSET) == NULL) {
178 return ERROR;
179 }
180 if (strncmp(audioPnpUevent->devType, UEVENT_TYPE_EXTCON, strlen(UEVENT_TYPE_EXTCON)) != 0) {
181 return ERROR;
182 }
183 if (strstr(audioPnpUevent->state, UEVENT_STATE_ANALOG_HS0) != NULL) {
184 audioEvent->eventType = PNP_EVENT_DEVICE_REMOVE;
185 } else if (strstr(audioPnpUevent->state, UEVENT_STATE_ANALOG_HS1) != NULL) {
186 audioEvent->eventType = PNP_EVENT_DEVICE_ADD;
187 } else {
188 return ERROR;
189 }
190 audioEvent->deviceType = PNP_DEVICE_HEADSET;
191 }
192 return SUCCESS;
193 }
194
AudioAnalogHeadsetDetectDevice(struct AudioPnpUevent * audioPnpUevent)195 int32_t AudioSocketThread::AudioAnalogHeadsetDetectDevice(struct AudioPnpUevent *audioPnpUevent)
196 {
197 AudioEvent audioEvent;
198 if (audioPnpUevent == NULL) {
199 AUDIO_ERR_LOG("audioPnpUevent is null!");
200 return HDF_ERR_INVALID_PARAM;
201 }
202
203 if (SetAudioPnpServerEventValue(&audioEvent, audioPnpUevent) != SUCCESS) {
204 return ERROR;
205 }
206 AUDIO_DEBUG_LOG("audio analog [%{public}s][%{public}s]",
207 audioEvent.deviceType == PNP_DEVICE_HEADSET ? "headset" : "headphone",
208 audioEvent.eventType == PNP_EVENT_DEVICE_ADD ? "add" : "removed");
209
210 if (!IsUpdatePnpDeviceState(&audioEvent)) {
211 AUDIO_ERR_LOG("audio analog device[%{public}u] state[%{public}u] not need flush !", audioEvent.deviceType,
212 audioEvent.eventType);
213 return SUCCESS;
214 }
215 UpdatePnpDeviceState(&audioEvent);
216 return SUCCESS;
217 }
218
CheckUsbDesc(struct UsbDevice * usbDevice)219 int32_t AudioSocketThread::CheckUsbDesc(struct UsbDevice *usbDevice)
220 {
221 if (usbDevice->descLen > USB_DES_LEN_MAX) {
222 AUDIO_ERR_LOG("usbDevice->descLen is more than USB_DES_LEN_MAX");
223 return HDF_ERR_INVALID_PARAM;
224 }
225 for (size_t len = 0; len < usbDevice->descLen;) {
226 size_t descLen = usbDevice->desc[len];
227 if (descLen == 0) {
228 AUDIO_ERR_LOG("descLen is 0");
229 return HDF_ERR_INVALID_PARAM;
230 }
231
232 if (descLen < USB_IF_DESC_LEN) {
233 len += descLen;
234 continue;
235 }
236
237 int32_t descType = usbDevice->desc[len + 1];
238 if (descType != USB_AUDIO_DESC_TYPE) {
239 len += descLen;
240 continue;
241 }
242
243 /* According to the 1.0 and 2.0 usb standard protocols, the audio field corresponding to the interface
244 * description type is: offset=1 interface descriptor type is 4; offset=5 interface class,audio is 1; offset=6
245 * interface subclass,audio control is 1 */
246 int32_t usbClass = usbDevice->desc[len + USB_IF_CLASS_OFFSET];
247 int32_t subClass = usbDevice->desc[len + USB_IF_SUBCLASS_OFFSET];
248 if (usbClass == USB_AUDIO_CLASS && subClass == USB_AUDIO_SUBCLASS_CTRL) {
249 AUDIO_INFO_LOG(
250 "descType %{public}d, usbClass %{public}d, subClass %{public}d", descType, usbClass, subClass);
251 return AUDIO_DEVICE_ONLINE;
252 }
253 len += descLen;
254 }
255 return SUCCESS;
256 }
257
ReadAndScanUsbDev(const char * devPath)258 int32_t AudioSocketThread::ReadAndScanUsbDev(const char *devPath)
259 {
260 FILE *fp = NULL;
261 struct UsbDevice usbDevice;
262 size_t len;
263 errno_t error;
264 uint32_t tryTime = 0;
265 char realpathRes[PATH_MAX + 1] = {'\0'};
266
267 if (devPath == NULL) {
268 AUDIO_ERR_LOG("audio devPath null");
269 return ERROR;
270 }
271
272 while (tryTime < AUDIO_DEVICE_WAIT_TRY_TIME) {
273 if (realpath(devPath, realpathRes) != NULL || (strlen(devPath) > PATH_MAX)) {
274 AUDIO_INFO_LOG("audio try[%{public}d] realpath fail[%{public}d] realpathRes [%{public}s]",
275 tryTime, errno, realpathRes);
276 break;
277 }
278 tryTime++;
279 OsalMSleep(AUDIO_DEVICE_WAIT_ONLINE);
280 }
281
282 fp = fopen(realpathRes, "r");
283 if (fp == NULL) {
284 AUDIO_ERR_LOG("audio realpath open fail[%{public}d]", errno);
285 return ERROR;
286 }
287
288 len = fread(usbDevice.desc, 1, sizeof(usbDevice.desc) - 1, fp);
289 if (len == 0) {
290 AUDIO_ERR_LOG("audio realpath read fail");
291 fclose(fp);
292 return ERROR;
293 }
294 fclose(fp);
295
296 error = strncpy_s((char *)usbDevice.devName, sizeof(usbDevice.devName), realpathRes,
297 sizeof(usbDevice.devName) - 1);
298 if (error != EOK) {
299 AUDIO_ERR_LOG("audio realpath strncpy fail");
300 return ERROR;
301 }
302
303 usbDevice.descLen = len;
304 return CheckUsbDesc(&usbDevice);
305 }
306
FindAudioUsbDevice(const char * devName)307 bool AudioSocketThread::FindAudioUsbDevice(const char *devName)
308 {
309 if (strlen(devName) > USB_DEV_NAME_LEN_MAX - 1) {
310 AUDIO_ERR_LOG("find usb audio device name exceed max len");
311 return false;
312 }
313
314 for (uint32_t count = 0; count < AUDIO_UEVENT_USB_DEVICE_COUNT; count++) {
315 if (g_audioUsbDeviceList[count].isUsed &&
316 (strncmp((char *)g_audioUsbDeviceList[count].devName, devName, strlen(devName)) == EOK)) {
317 return true;
318 }
319 }
320 return false;
321 }
322
AddAudioUsbDevice(const char * devName)323 bool AudioSocketThread::AddAudioUsbDevice(const char *devName)
324 {
325 if (strlen(devName) > USB_DEV_NAME_LEN_MAX - 1) {
326 AUDIO_ERR_LOG("add usb audio device name exceed max len");
327 return false;
328 }
329
330 if (FindAudioUsbDevice(devName)) {
331 AUDIO_ERR_LOG("find usb audio device name[%{public}s]", devName);
332 return true;
333 }
334
335 for (uint32_t count = 0; count < AUDIO_UEVENT_USB_DEVICE_COUNT; count++) {
336 if (g_audioUsbDeviceList[count].isUsed) {
337 continue;
338 }
339 if (strncpy_s((char *)g_audioUsbDeviceList[count].devName, USB_DEV_NAME_LEN_MAX, devName, strlen(devName))
340 != EOK) {
341 AUDIO_ERR_LOG("add usb audio device name fail");
342 return false;
343 }
344 g_audioUsbDeviceList[count].isUsed = true;
345 return true;
346 }
347 AUDIO_ERR_LOG("add usb audio device name fail");
348 return false;
349 }
350
CheckAudioUsbDevice(const char * devName)351 bool AudioSocketThread::CheckAudioUsbDevice(const char *devName)
352 {
353 int32_t state = 0;
354 int32_t len;
355 char subDir[USB_DEV_NAME_LEN_MAX] = {0};
356
357 if (*devName == '\0') {
358 return false;
359 }
360 len = snprintf_s(subDir, USB_DEV_NAME_LEN_MAX, USB_DEV_NAME_LEN_MAX - 1, "/dev/" "%s", devName);
361 if (len < 0) {
362 AUDIO_ERR_LOG("audio snprintf dev dir fail");
363 return false;
364 }
365 AUDIO_INFO_LOG("CheckAudioUsbDevice: devName:%{public}s subDir:%{public}s len:%{public}d", devName, subDir, len);
366
367 state = ReadAndScanUsbDev(subDir);
368 if ((state == AUDIO_DEVICE_ONLINE) && AddAudioUsbDevice(devName)) {
369 return true;
370 }
371 return false;
372 }
373
DeleteAudioUsbDevice(const char * devName)374 bool AudioSocketThread::DeleteAudioUsbDevice(const char *devName)
375 {
376 if (strlen(devName) > USB_DEV_NAME_LEN_MAX - 1) {
377 AUDIO_ERR_LOG("delete usb audio device name exceed max len");
378 return false;
379 }
380
381 for (uint32_t count = 0; count < AUDIO_UEVENT_USB_DEVICE_COUNT; count++) {
382 if (g_audioUsbDeviceList[count].isUsed &&
383 strncmp((char *)g_audioUsbDeviceList[count].devName, devName, strlen(devName)) == EOK) {
384 g_audioUsbDeviceList[count].isUsed = false;
385 AUDIO_INFO_LOG("delete usb audio device name[%{public}s]", devName);
386 return true;
387 }
388 }
389
390 return false;
391 }
392
AudioDpDetectDevice(struct AudioPnpUevent * audioPnpUevent)393 int32_t AudioSocketThread::AudioDpDetectDevice(struct AudioPnpUevent *audioPnpUevent)
394 {
395 AudioEvent audioEvent = {0};
396 if (audioPnpUevent == NULL) {
397 return HDF_ERR_INVALID_PARAM;
398 }
399 if ((strcmp(audioPnpUevent->subSystem, "switch") != 0) ||
400 (strstr(audioPnpUevent->switchName, "hdmi_audio") == NULL) ||
401 (strcmp(audioPnpUevent->action, "change") != 0)) {
402 return HDF_ERR_INVALID_PARAM;
403 }
404
405 if (strcmp(audioPnpUevent->switchState, "1") == 0) {
406 audioEvent.eventType = PNP_EVENT_DEVICE_ADD;
407 } else if (strcmp(audioPnpUevent->switchState, "0") == 0) {
408 audioEvent.eventType = PNP_EVENT_DEVICE_REMOVE;
409 } else {
410 AUDIO_ERR_LOG("audio dp device [%{public}d]", audioEvent.eventType);
411 return ERROR;
412 }
413 audioEvent.deviceType = PNP_DEVICE_DP_DEVICE;
414
415 std::string switchNameStr = audioPnpUevent->switchName;
416
417 auto portBegin = switchNameStr.find("device_port=");
418 if (portBegin != switchNameStr.npos) {
419 audioEvent.name = switchNameStr.substr(portBegin + std::strlen("device_port="),
420 switchNameStr.length() - portBegin - std::strlen("device_port="));
421 }
422
423 auto addressBegin = switchNameStr.find("hdmi_audio");
424 auto addressEnd = switchNameStr.find_first_of("device_port", portBegin);
425 if (addressEnd != switchNameStr.npos) {
426 std::string portId = switchNameStr.substr(addressBegin + std::strlen("hdmi_audio"),
427 addressEnd - addressBegin - std::strlen("hdmi_audio")-1);
428 audioEvent.address = portId;
429 AUDIO_INFO_LOG("audio dp device portId:[%{public}s]", portId.c_str());
430 }
431
432 if (audioEvent.address.empty()) {
433 audioEvent.address = '0';
434 }
435 AUDIO_INFO_LOG("audio dp device [%{public}s]", audioEvent.eventType == PNP_EVENT_DEVICE_ADD ? "add" : "removed");
436
437 if (!IsUpdatePnpDeviceState(&audioEvent)) {
438 AUDIO_ERR_LOG("audio usb device[%{public}u] state[%{public}u] not need flush !", audioEvent.deviceType,
439 audioEvent.eventType);
440 return SUCCESS;
441 }
442 UpdatePnpDeviceState(&audioEvent);
443 return SUCCESS;
444 }
445
AudioUsbHeadsetDetectDevice(struct AudioPnpUevent * audioPnpUevent)446 int32_t AudioSocketThread::AudioUsbHeadsetDetectDevice(struct AudioPnpUevent *audioPnpUevent)
447 {
448 AudioEvent audioEvent = {0};
449
450 if (audioPnpUevent == NULL) {
451 return HDF_ERR_INVALID_PARAM;
452 }
453
454 if (audioPnpUevent->action == NULL || audioPnpUevent->devName == NULL || audioPnpUevent->subSystem == NULL ||
455 audioPnpUevent->devType == NULL) {
456 return HDF_ERR_INVALID_PARAM;
457 }
458
459 if ((strcmp(audioPnpUevent->subSystem, UEVENT_SUBSYSTEM_USB) != 0) ||
460 (strcmp(audioPnpUevent->devType, UEVENT_SUBSYSTEM_USB_DEVICE) != 0) ||
461 (strstr(audioPnpUevent->devName, BUS_USB_DIR) == NULL)) {
462 return HDF_ERR_INVALID_PARAM;
463 }
464
465 if (strcmp(audioPnpUevent->action, UEVENT_ACTION_ADD) == 0) {
466 if (!CheckAudioUsbDevice(audioPnpUevent->devName)) {
467 return HDF_ERR_INVALID_PARAM;
468 }
469 audioEvent.eventType = PNP_EVENT_DEVICE_ADD;
470 } else if (strcmp(audioPnpUevent->action, UEVENT_ACTION_REMOVE) == 0) {
471 if (!DeleteAudioUsbDevice(audioPnpUevent->devName)) {
472 return HDF_ERR_INVALID_PARAM;
473 }
474 audioEvent.eventType = PNP_EVENT_DEVICE_REMOVE;
475 } else {
476 return ERROR;
477 }
478
479 audioEvent.deviceType = PNP_DEVICE_USB_HEADSET;
480 AUDIO_DEBUG_LOG("audio usb headset [%{public}s]", audioEvent.eventType == PNP_EVENT_DEVICE_ADD ? "add" : "removed");
481
482 audioEvent.name = audioPnpUevent->name;
483 audioEvent.address = audioPnpUevent->devName;
484
485 if (!IsUpdatePnpDeviceState(&audioEvent)) {
486 AUDIO_ERR_LOG("audio usb device[%{public}u] state[%{public}u] not need flush !", audioEvent.deviceType,
487 audioEvent.eventType);
488 return SUCCESS;
489 }
490 UpdatePnpDeviceState(&audioEvent);
491 return SUCCESS;
492 }
493
AudioMicBlockDevice(struct AudioPnpUevent * audioPnpUevent)494 int32_t AudioSocketThread::AudioMicBlockDevice(struct AudioPnpUevent *audioPnpUevent)
495 {
496 if (audioPnpUevent == nullptr) {
497 AUDIO_ERR_LOG("mic blocked audioPnpUevent is null");
498 return HDF_ERR_INVALID_PARAM;
499 }
500 AudioEvent audioEvent = {0};
501 if (strncmp(audioPnpUevent->name, "mic_blocked", strlen("mic_blocked")) == 0) {
502 audioEvent.eventType = PNP_EVENT_MIC_BLOCKED;
503 } else if (strncmp(audioPnpUevent->name, "mic_un_blocked", strlen("mic_un_blocked")) == 0) {
504 audioEvent.eventType = PNP_EVENT_MIC_UNBLOCKED;
505 } else {
506 return HDF_ERR_INVALID_PARAM;
507 }
508 audioEvent.deviceType = PNP_DEVICE_MIC;
509
510 AUDIO_INFO_LOG("mic blocked uevent info recv: %{public}s", audioPnpUevent->name);
511 UpdatePnpDeviceState(&audioEvent);
512 return SUCCESS;
513 }
514
AudioPnpUeventParse(const char * msg,const ssize_t strLength)515 bool AudioSocketThread::AudioPnpUeventParse(const char *msg, const ssize_t strLength)
516 {
517 struct AudioPnpUevent audioPnpUevent = {"", "", "", "", "", "", "", "", ""};
518
519 if (strncmp(msg, "libudev", strlen("libudev")) == 0) {
520 return false;
521 }
522
523 if (strLength > UEVENT_MSG_LEN + 1) {
524 AUDIO_ERR_LOG("strLength > UEVENT_MSG_LEN + 1");
525 return false;
526 }
527 AUDIO_DEBUG_LOG("Param strLength: %{public}zu msg:[%{public}s] len:[%{public}zu]", strLength, msg, strlen(msg));
528 for (const char *msgTmp = msg; msgTmp < (msg + strLength);) {
529 if (*msgTmp == '\0') {
530 msgTmp++;
531 continue;
532 }
533 AUDIO_DEBUG_LOG("Param msgTmp:[%{public}s] len:[%{public}zu]", msgTmp, strlen(msgTmp));
534 const char *arrStrTmp[UEVENT_ARR_SIZE] = {
535 UEVENT_ACTION, UEVENT_DEV_NAME, UEVENT_NAME, UEVENT_STATE, UEVENT_DEVTYPE,
536 UEVENT_SUBSYSTEM, UEVENT_SWITCH_NAME, UEVENT_SWITCH_STATE, UEVENT_HDI_NAME
537 };
538 const char **arrVarTmp[UEVENT_ARR_SIZE] = {
539 &audioPnpUevent.action, &audioPnpUevent.devName, &audioPnpUevent.name,
540 &audioPnpUevent.state, &audioPnpUevent.devType, &audioPnpUevent.subSystem,
541 &audioPnpUevent.switchName, &audioPnpUevent.switchState, &audioPnpUevent.hidName
542 };
543 for (int count = 0; count < UEVENT_ARR_SIZE; count++) {
544 if (strncmp(msgTmp, arrStrTmp[count], strlen(arrStrTmp[count])) == 0) {
545 msgTmp += strlen(arrStrTmp[count]);
546 *arrVarTmp[count] = msgTmp;
547 break;
548 }
549 }
550 msgTmp += strlen(msgTmp) + 1;
551 }
552
553 if ((AudioAnalogHeadsetDetectDevice(&audioPnpUevent) == SUCCESS) ||
554 (AudioUsbHeadsetDetectDevice(&audioPnpUevent) == SUCCESS) ||
555 (AudioDpDetectDevice(&audioPnpUevent) == SUCCESS) ||
556 (AudioMicBlockDevice(&audioPnpUevent) == SUCCESS)) {
557 return true;
558 }
559
560 return false;
561 }
562
DetectAnalogHeadsetState(AudioEvent * audioEvent)563 int32_t AudioSocketThread::DetectAnalogHeadsetState(AudioEvent *audioEvent)
564 {
565 int8_t state = 0;
566 FILE *fp = fopen(SWITCH_STATE_PATH, "r");
567 if (fp == NULL) {
568 AUDIO_ERR_LOG("audio open switch state node fail, %{public}d", errno);
569 return HDF_ERR_INVALID_PARAM;
570 }
571
572 size_t ret = fread(&state, STATE_PATH_ITEM_SIZE, STATE_PATH_ITEM_SIZE, fp);
573 if (ret == 0) {
574 fclose(fp);
575 AUDIO_ERR_LOG("audio read switch state node fail, %{public}d", errno);
576 return ERROR;
577 }
578
579 if (state == '0') {
580 audioEvent->eventType = AUDIO_DEVICE_REMOVE;
581 audioEvent->deviceType = AUDIO_HEADSET;
582 } else {
583 audioEvent->eventType = AUDIO_DEVICE_ADD;
584 audioEvent->deviceType = AUDIO_HEADSET;
585 }
586
587 fclose(fp);
588 return SUCCESS;
589 }
590
UpdateDeviceState(AudioEvent audioEvent)591 void AudioSocketThread::UpdateDeviceState(AudioEvent audioEvent)
592 {
593 char pnpInfo[AUDIO_EVENT_INFO_LEN_MAX] = {0};
594 int32_t ret;
595 if (!IsUpdatePnpDeviceState(&audioEvent)) {
596 AUDIO_ERR_LOG("audio first pnp device[%{public}u] state[%{public}u] not need flush !", audioEvent.deviceType,
597 audioEvent.eventType);
598 return;
599 }
600 ret = snprintf_s(pnpInfo, AUDIO_EVENT_INFO_LEN_MAX, AUDIO_EVENT_INFO_LEN_MAX - 1, "EVENT_TYPE=%u;DEVICE_TYPE=%u",
601 audioEvent.eventType, audioEvent.deviceType);
602 if (ret < 0) {
603 AUDIO_ERR_LOG("snprintf_s fail!");
604 return;
605 }
606
607 UpdatePnpDeviceState(&audioEvent);
608 return;
609 }
610
IsBadName(const char * name)611 inline bool AudioSocketThread::IsBadName(const char *name)
612 {
613 if (*name == '\0') {
614 AUDIO_ERR_LOG("name is null");
615 return true;
616 }
617
618 while (*name != '\0') {
619 if (isdigit(*name++) == 0) {
620 return true;
621 }
622 }
623
624 return false;
625 }
626
ScanUsbBusSubDir(const char * subDir)627 int32_t AudioSocketThread::ScanUsbBusSubDir(const char *subDir)
628 {
629 int32_t len;
630 DIR *devDir = NULL;
631 dirent *dirEnt = NULL;
632
633 char devName[USB_DEV_NAME_LEN_MAX] = {0};
634
635 devDir = opendir(subDir);
636 if (devDir == NULL) {
637 AUDIO_ERR_LOG("open usb sub dir failed");
638 return HDF_ERR_INVALID_PARAM;
639 }
640
641 int32_t state = SUCCESS;
642 while (((dirEnt = readdir(devDir)) != NULL) && (state == SUCCESS)) {
643 if (IsBadName(dirEnt->d_name)) {
644 continue;
645 }
646
647 len = snprintf_s(devName, USB_DEV_NAME_LEN_MAX, USB_DEV_NAME_LEN_MAX - 1, "%s/%s", subDir,
648 dirEnt->d_name);
649 if (len < 0) {
650 AUDIO_ERR_LOG("audio snprintf dev dir fail");
651 state = ERROR;
652 break;
653 }
654
655 AUDIO_DEBUG_LOG("audio usb dir[%{public}s]", devName);
656 state = ReadAndScanUsbDev(devName);
657 if (state == AUDIO_DEVICE_ONLINE) {
658 char *subDevName = devName + strlen("/dev/");
659 AUDIO_ERR_LOG("audio sub dev dir=[%{public}s]", subDevName);
660 if (AddAudioUsbDevice(subDevName)) {
661 AUDIO_ERR_LOG("audio add usb audio device success");
662 break;
663 }
664 }
665 }
666
667 closedir(devDir);
668 return state;
669 }
670
DetectUsbHeadsetState(AudioEvent * audioEvent)671 int32_t AudioSocketThread::DetectUsbHeadsetState(AudioEvent *audioEvent)
672 {
673 int32_t len;
674 DIR *busDir = NULL;
675 dirent *dirEnt = NULL;
676
677 char subDir[USB_DEV_NAME_LEN_MAX] = {0};
678
679 busDir = opendir(DEV_BUS_USB_DIR);
680 if (busDir == NULL) {
681 AUDIO_ERR_LOG("open usb dir failed");
682 return HDF_ERR_INVALID_PARAM;
683 }
684
685 int32_t state = SUCCESS;
686 while (((dirEnt = readdir(busDir)) != NULL) && (state == SUCCESS)) {
687 if (IsBadName(dirEnt->d_name)) {
688 continue;
689 }
690
691 len = snprintf_s(subDir, USB_DEV_NAME_LEN_MAX, USB_DEV_NAME_LEN_MAX - 1, DEV_BUS_USB_DIR "/%s",
692 dirEnt->d_name);
693 if (len < 0) {
694 AUDIO_ERR_LOG("audio snprintf dev dir fail");
695 break;
696 }
697 state = ScanUsbBusSubDir(subDir);
698 if (state == AUDIO_DEVICE_ONLINE) {
699 audioEvent->eventType = AUDIO_DEVICE_ADD;
700 audioEvent->deviceType = AUDIO_USB_HEADSET;
701 closedir(busDir);
702 return SUCCESS;
703 }
704 }
705
706 closedir(busDir);
707 return ERROR;
708 }
709 } // namespace AudioStandard
710 } // namespace OHOS