• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "audio_usb_linux.h"
10 #include <linux/bitops.h>
11 #include <linux/ctype.h>
12 #include <linux/init.h>
13 #include <linux/list.h>
14 #include <linux/module.h>
15 #include <linux/moduleparam.h>
16 #include <linux/mutex.h>
17 #include <linux/slab.h>
18 #include <linux/string.h>
19 #include <linux/usb.h>
20 #include <linux/usb/audio-v2.h>
21 #include <linux/usb/audio-v3.h>
22 #include <linux/usb/audio.h>
23 
24 #include "audio_driver_log.h"
25 #include "audio_usb_endpoints.h"
26 #include "audio_usb_parse_interface.h"
27 #include "audio_usb_validate_desc.h"
28 #include "devmgr_service_clnt.h"
29 #include "devsvc_manager_clnt.h"
30 #include "hdf_device_object.h"
31 #include "osal_time.h"
32 
33 #define HDF_LOG_TAG HDF_AUDIO_USB
34 
35 #define HDF_AUDIO_USB_CODEC_NAME       "hdf_audio_codec_usb_dev0"
36 #define HDF_AUDIO_USB_PNP_SRV_NAME     "audio_usb_service_0"
37 #define HDF_AUDIO_USB_DMA_NAME         "usb_dma_service_0"
38 #define WAIT_FOR_HDF_START_MILLISECOND 500
39 
40 #define USB_SHIFT_SIZE_16 16
41 
42 #define LOAD_AUDIO_USB_DRIVER_FREQUENCY 5
43 
44 #define USB_DEFAULT_SET 0
45 #define USB_DEFAULT_VAL 0
46 
47 static struct AudioUsbDriver g_hdfAudioUsbDriver;
48 
GetLinuxAudioUsb(void)49 struct AudioUsbDriver *GetLinuxAudioUsb(void)
50 {
51     return &g_hdfAudioUsbDriver;
52 }
53 
AudioUsbGetUsbId(uint32_t vendor,uint32_t product)54 uint32_t AudioUsbGetUsbId(uint32_t vendor, uint32_t product)
55 {
56     // The usb id is composed of vendor id and product id.
57     return (((vendor) << USB_SHIFT_SIZE_16) | (product));
58 }
59 
AudioUsbDriverLoad(const char * serviceName)60 static int32_t AudioUsbDriverLoad(const char *serviceName)
61 {
62     struct AudioUsbDriver *usbDriver = NULL;
63     struct DevmgrServiceClnt *hdf = NULL;
64     int32_t ret;
65 
66     if (serviceName == NULL) {
67         return HDF_ERR_INVALID_PARAM;
68     }
69 
70     usbDriver = GetLinuxAudioUsb();
71     if (usbDriver == NULL) {
72         ADM_LOG_ERR("get linux audio usb driver fail!");
73         return HDF_ERR_INVALID_OBJECT;
74     }
75 
76     hdf = DevmgrServiceClntGetInstance();
77     if ((hdf == NULL || hdf->devMgrSvcIf == NULL || hdf->devMgrSvcIf->LoadDevice == NULL)) {
78         return HDF_ERR_INVALID_OBJECT;
79     }
80 
81     ret = hdf->devMgrSvcIf->LoadDevice(hdf->devMgrSvcIf, serviceName);
82     if (ret == HDF_SUCCESS) {
83         ADM_LOG_INFO("serviceName[%s] load success", serviceName);
84         usbDriver->pnpFlag = 1;
85     } else if (ret == HDF_ERR_DEVICE_BUSY) {
86         ADM_LOG_INFO("serviceName[%s] has been loaded", serviceName);
87     } else {
88         ADM_LOG_ERR("serviceName[%s] load fail", serviceName);
89         usbDriver->pnpFlag = 0;
90         return HDF_ERR_NOT_SUPPORT;
91     }
92 
93     return HDF_SUCCESS;
94 }
95 
AudioUsbDriverInit(struct AudioUsbDriver * audioUsbDriver,struct usb_interface * usbIf,const struct usb_device_id * usbDevId)96 static int32_t AudioUsbDriverInit(
97     struct AudioUsbDriver *audioUsbDriver, struct usb_interface *usbIf, const struct usb_device_id *usbDevId)
98 {
99     struct usb_device *usbDev = interface_to_usbdev(usbIf);
100     struct usb_host_interface *alts = NULL;
101     uint32_t i, ifNum, protocol;
102     struct usb_host_interface *hostIface = NULL;
103     struct usb_interface_descriptor *altsd = NULL, *inteDesc = NULL;
104     struct uac1_ac_header_descriptor *h1 = NULL;
105 
106     alts = &usbIf->altsetting[USB_DEFAULT_SET];
107     inteDesc = AudioUsbGetIfaceDesc(alts);
108     ifNum = inteDesc->bInterfaceNumber;
109     hostIface = &usb_ifnum_to_if(usbDev, ifNum)->altsetting[USB_DEFAULT_SET];
110     altsd = AudioUsbGetIfaceDesc(hostIface);
111     protocol = altsd->bInterfaceProtocol;
112 
113     audioUsbDriver->pnpFlag = USB_DEFAULT_VAL;
114     audioUsbDriver->usbDevId = usbDevId;
115     audioUsbDriver->usbIf = usbIf;
116     audioUsbDriver->usbId =
117         AudioUsbGetUsbId(le16_to_cpu(usbDev->descriptor.idVendor), le16_to_cpu(usbDev->descriptor.idProduct));
118     audioUsbDriver->sampleRateReadError = USB_DEFAULT_VAL;
119     audioUsbDriver->ctrlIntf = alts;
120     audioUsbDriver->setup = USB_DEFAULT_VAL;
121     audioUsbDriver->dev = usbDev;
122     audioUsbDriver->ifNum = ifNum;
123     init_waitqueue_head(&audioUsbDriver->shutdownWait);
124 
125     spin_lock_init(&audioUsbDriver->lock);
126 
127     atomic_set(&audioUsbDriver->active, 1); /* avoid autopm during probing */
128     atomic_set(&audioUsbDriver->usageCount, USB_DEFAULT_VAL);
129     atomic_set(&audioUsbDriver->shutdown, USB_DEFAULT_VAL);
130 
131     DListHeadInit(&audioUsbDriver->renderUsbFormatList);
132     DListHeadInit(&audioUsbDriver->captureUsbFormatList);
133 
134     if (protocol != UAC_VERSION_1) {
135         ADM_LOG_ERR("usb version is not support");
136         return HDF_ERR_NOT_SUPPORT;
137     }
138     if (ifNum > 0) {
139         ADM_LOG_ERR("usb device is not support");
140         return HDF_ERR_NOT_SUPPORT;
141     }
142 
143     h1 = AudioUsbFindCsintDesc(alts->extra, alts->extralen, NULL, UAC_HEADER);
144     if (h1 == NULL || h1->bLength < sizeof(*h1)) {
145         ADM_LOG_ERR("cannot find UAC_HEADER\n");
146         return -EINVAL;
147     }
148 
149     for (i = 0; i < h1->bInCollection; i++) {
150         AudioUsbParseAudioInterface(audioUsbDriver, h1->baInterfaceNr[i]);
151     }
152     return HDF_SUCCESS;
153 }
154 
LinuxAudioUsbProbe(struct usb_interface * usbIf,const struct usb_device_id * usbDevId)155 static int32_t LinuxAudioUsbProbe(struct usb_interface *usbIf, const struct usb_device_id *usbDevId)
156 {
157     int32_t ret;
158     uint32_t i;
159     ADM_LOG_INFO("entry");
160 
161     (void)memset_s(&g_hdfAudioUsbDriver, sizeof(struct AudioUsbDriver), 0, sizeof(struct AudioUsbDriver));
162     ret = AudioUsbDriverInit(&g_hdfAudioUsbDriver, usbIf, usbDevId);
163     if (ret != HDF_SUCCESS) {
164         ADM_LOG_ERR("AudioUsbDriverInit is failed");
165         return HDF_FAILURE;
166     }
167 
168     for (i = 0; g_hdfAudioUsbDriver.pnpFlag != 1 && i <= LOAD_AUDIO_USB_DRIVER_FREQUENCY; i++) {
169         OsalMSleep(WAIT_FOR_HDF_START_MILLISECOND);
170         if (AudioUsbDriverLoad(HDF_AUDIO_USB_PNP_SRV_NAME) == HDF_SUCCESS &&
171             AudioUsbDriverLoad(HDF_AUDIO_USB_DMA_NAME) == HDF_SUCCESS &&
172             AudioUsbDriverLoad(HDF_AUDIO_USB_CODEC_NAME) == HDF_SUCCESS) {
173             break;
174         }
175     }
176 
177     ADM_LOG_INFO("success");
178     return HDF_SUCCESS;
179 }
180 
LinuxAudioUsbDisconnect(struct usb_interface * usbIf)181 static void LinuxAudioUsbDisconnect(struct usb_interface *usbIf)
182 {
183     struct HdfDeviceObject *usbService = NULL;
184 
185     wait_event(g_hdfAudioUsbDriver.shutdownWait, !atomic_read(&g_hdfAudioUsbDriver.usageCount));
186 
187     usbService = DevSvcManagerClntGetDeviceObject(HDF_AUDIO_USB_DMA_NAME);
188     HdfDeviceObjectRelease(usbService);
189 
190     usbService = DevSvcManagerClntGetDeviceObject(HDF_AUDIO_USB_CODEC_NAME);
191     HdfDeviceObjectRelease(usbService);
192 
193     usbService = DevSvcManagerClntGetDeviceObject(HDF_AUDIO_USB_PNP_SRV_NAME);
194     HdfDeviceObjectRelease(usbService);
195 
196     g_hdfAudioUsbDriver.pnpFlag = USB_DEFAULT_VAL; // USB_DEFAULT_VAL means disconnect
197 }
198 
199 /* Element 2 to Terminating */
200 static const struct usb_device_id g_linuxAudioUsbIds[2] = {
201     {.bInterfaceClass = USB_CLASS_AUDIO,
202      .match_flags = (USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS),
203      .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL},
204 };
205 MODULE_DEVICE_TABLE(usb, g_linuxAudioUsbIds);
206 
207 static struct usb_driver g_linuxAudioUsbDriver = {
208     .name = "hdf-audio-usb",
209     .probe = LinuxAudioUsbProbe,
210     .disconnect = LinuxAudioUsbDisconnect,
211     .id_table = g_linuxAudioUsbIds,
212     .supports_autosuspend = 1,
213 };
214 module_usb_driver(g_linuxAudioUsbDriver);
215