1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2019-09-07 flybreak the first version
9 */
10
11 #include <rthw.h>
12 #include <rtdevice.h>
13 #include "drivers/usb_device.h"
14
15 #include "uaudioreg.h"
16
17 #define DBG_TAG "usbd.audio.mic"
18 #define DBG_LVL DBG_INFO
19 #include <rtdbg.h>
20
21 #define RECORD_SAMPLERATE 16000
22 #define RECORD_CHANNEL 1
23 #define RESOLUTION_BITS 16
24
25 #define RESOLUTION_BYTE (RESOLUTION_BITS / 8)
26 #define RECORD_PER_MS_SZ ((RECORD_SAMPLERATE * RECORD_CHANNEL * RESOLUTION_BYTE) / 1000)
27 #define RECORD_BUFFER_SZ (RECORD_PER_MS_SZ * 20) /* 20ms */
28
29 #if defined(RT_USBD_MIC_DEVICE_NAME)
30 #define MIC_DEVICE_NAME RT_USBD_MIC_DEVICE_NAME
31 #else
32 #define MIC_DEVICE_NAME "mic0"
33 #endif
34
35 #define EVENT_RECORD_START (1 << 0)
36 #define EVENT_RECORD_STOP (1 << 1)
37 #define EVENT_RECORD_DATA (1 << 2)
38
39 #define MIC_INTF_STR_INDEX 8
40 /*
41 * uac mic descriptor define
42 */
43
44 #define UAC_CS_INTERFACE 0x24
45 #define UAC_CS_ENDPOINT 0x25
46
47 #define UAC_MAX_PACKET_SIZE 64
48 #define UAC_EP_MAX_PACKET_SIZE 32
49 #define UAC_CHANNEL_NUM RECORD_CHANNEL
50
51 struct uac_ac_descriptor
52 {
53 #ifdef RT_USB_DEVICE_COMPOSITE
54 struct uiad_descriptor iad_desc;
55 #endif
56 struct uinterface_descriptor intf_desc;
57 struct usb_audio_control_descriptor hdr_desc;
58 struct usb_audio_input_terminal it_desc;
59 struct usb_audio_output_terminal ot_desc;
60 #if UAC_USE_FEATURE_UNIT
61 struct usb_audio_feature_unit feature_unit_desc;
62 #endif
63 };
64
65 struct uac_as_descriptor
66 {
67 struct uinterface_descriptor intf_desc;
68 struct usb_audio_streaming_interface_descriptor hdr_desc;
69 struct usb_audio_streaming_type1_descriptor format_type_desc;
70 struct uendpoint_descriptor ep_desc;
71 struct usb_audio_streaming_endpoint_descriptor as_ep_desc;
72 };
73
74 /*
75 * uac mic device type
76 */
77
78 struct uac_audio_mic
79 {
80 rt_device_t dev;
81 rt_event_t event;
82 rt_uint8_t open_count;
83
84 rt_uint8_t *buffer;
85 rt_uint32_t buffer_index;
86
87 uep_t ep;
88 };
89 static struct uac_audio_mic mic;
90
91 rt_align(4)
92 static struct udevice_descriptor dev_desc =
93 {
94 USB_DESC_LENGTH_DEVICE, //bLength;
95 USB_DESC_TYPE_DEVICE, //type;
96 USB_BCD_VERSION, //bcdUSB;
97 USB_CLASS_DEVICE, //bDeviceClass;
98 0x00, //bDeviceSubClass;
99 0x00, //bDeviceProtocol;
100 UAC_MAX_PACKET_SIZE, //bMaxPacketSize0;
101 _VENDOR_ID, //idVendor;
102 _PRODUCT_ID, //idProduct;
103 USB_BCD_DEVICE, //bcdDevice;
104 USB_STRING_MANU_INDEX, //iManufacturer;
105 USB_STRING_PRODUCT_INDEX, //iProduct;
106 USB_STRING_SERIAL_INDEX, //iSerialNumber;Unused.
107 USB_DYNAMIC, //bNumConfigurations;
108 };
109
110 //FS and HS needed
111 rt_align(4)
112 static struct usb_qualifier_descriptor dev_qualifier =
113 {
114 sizeof(dev_qualifier), //bLength
115 USB_DESC_TYPE_DEVICEQUALIFIER, //bDescriptorType
116 0x0200, //bcdUSB
117 USB_CLASS_AUDIO, //bDeviceClass
118 0x00, //bDeviceSubClass
119 0x00, //bDeviceProtocol
120 64, //bMaxPacketSize0
121 0x01, //bNumConfigurations
122 0,
123 };
124
125 rt_align(4)
126 const static char *_ustring[] =
127 {
128 "Language",
129 "RT-Thread Team.",
130 "RT-Thread Audio Microphone",
131 "32021919830108",
132 "Configuration",
133 "Interface",
134 };
135
136 rt_align(4)
137 static struct uac_ac_descriptor ac_desc =
138 {
139 #ifdef RT_USB_DEVICE_COMPOSITE
140 /* Interface Association Descriptor */
141 {
142 USB_DESC_LENGTH_IAD,
143 USB_DESC_TYPE_IAD,
144 USB_DYNAMIC,
145 0x02,
146 USB_CLASS_AUDIO,
147 USB_SUBCLASS_AUDIOSTREAMING,
148 0x00,
149 0x00,
150 },
151 #endif
152 /* Interface Descriptor */
153 {
154 USB_DESC_LENGTH_INTERFACE,
155 USB_DESC_TYPE_INTERFACE,
156 USB_DYNAMIC,
157 0x00,
158 0x00,
159 USB_CLASS_AUDIO,
160 USB_SUBCLASS_AUDIOCONTROL,
161 0x00,
162 #ifdef RT_USB_DEVICE_COMPOSITE
163 MIC_INTF_STR_INDEX,
164 #else
165 0x00,
166 #endif
167 },
168 /* Header Descriptor */
169 {
170 sizeof(struct usb_audio_control_descriptor),
171 UAC_CS_INTERFACE,
172 UDESCSUB_AC_HEADER,
173 0x0100, /* Version: 1.00 */
174 0x001E, /* Total length: 30 */
175 0x01, /* Total number of interfaces: 1 */
176 {0x01}, /* Interface number: 1 */
177 },
178 /* Input Terminal Descriptor */
179 {
180 sizeof(struct usb_audio_input_terminal),
181 UAC_CS_INTERFACE,
182 UDESCSUB_AC_INPUT,
183 0x01, /* Terminal ID: 1 */
184 0x0201, /* Terminal Type: Microphone (0x0201) */
185 0x00, /* Assoc Terminal: 0 */
186 0x01, /* Number Channels: 1 */
187 0x0000, /* Channel Config: 0x0000 */
188 0x00, /* Channel Names: 0 */
189 0x00, /* Terminal: 0 */
190 },
191 /* Output Terminal Descriptor */
192 {
193 sizeof(struct usb_audio_output_terminal),
194 UAC_CS_INTERFACE,
195 UDESCSUB_AC_OUTPUT,
196 0x02, /* Terminal ID: 2 */
197 0x0101, /* Terminal Type: USB Streaming (0x0101) */
198 0x00, /* Assoc Terminal: 0 */
199 0x01, /* Source ID: 1 */
200 0x00, /* Terminal: 0 */
201 },
202 #if UAC_USE_FEATURE_UNIT
203 /* Feature unit Descriptor */
204 {
205 sizeof(struct usb_audio_feature_unit),
206 UAC_CS_INTERFACE,
207 UDESCSUB_AC_FEATURE,
208 0x02,
209 0x01,
210 0x01,
211 0x00,
212 0x01,
213 },
214 #endif
215 };
216
217 rt_align(4)
218 static struct uinterface_descriptor as_desc0 =
219 {
220 USB_DESC_LENGTH_INTERFACE,
221 USB_DESC_TYPE_INTERFACE,
222 USB_DYNAMIC,
223 0x00,
224 0x00,
225 USB_CLASS_AUDIO,
226 USB_SUBCLASS_AUDIOSTREAMING,
227 0x00,
228 0x00,
229 };
230
231 rt_align(4)
232 static struct uac_as_descriptor as_desc =
233 {
234 /* Interface Descriptor */
235 {
236 USB_DESC_LENGTH_INTERFACE,
237 USB_DESC_TYPE_INTERFACE,
238 USB_DYNAMIC,
239 0x01,
240 0x01,
241 USB_CLASS_AUDIO,
242 USB_SUBCLASS_AUDIOSTREAMING,
243 0x00,
244 0x00,
245 },
246 /* General AS Descriptor */
247 {
248 sizeof(struct usb_audio_streaming_interface_descriptor),
249 UAC_CS_INTERFACE,
250 AS_GENERAL,
251 0x02, /* Terminal ID: 2 */
252 0x01, /* Interface delay in frames: 1 */
253 UA_FMT_PCM,
254 },
255 /* Format type i Descriptor */
256 {
257 sizeof(struct usb_audio_streaming_type1_descriptor),
258 UAC_CS_INTERFACE,
259 FORMAT_TYPE,
260 FORMAT_TYPE_I,
261 UAC_CHANNEL_NUM,
262 2, /* Subframe Size: 2 */
263 RESOLUTION_BITS,
264 0x01, /* Samples Frequence Type: 1 */
265 {0}, /* Samples Frequence */
266 },
267 /* Endpoint Descriptor */
268 {
269 USB_DESC_LENGTH_ENDPOINT,
270 USB_DESC_TYPE_ENDPOINT,
271 USB_DYNAMIC | USB_DIR_IN,
272 USB_EP_ATTR_ISOC,
273 UAC_EP_MAX_PACKET_SIZE,
274 0x01,
275 },
276 /* AS Endpoint Descriptor */
277 {
278 sizeof(struct usb_audio_streaming_endpoint_descriptor),
279 UAC_CS_ENDPOINT,
280 AS_GENERAL,
281 },
282 };
283
mic_entry(void * parameter)284 void mic_entry(void *parameter)
285 {
286 struct rt_audio_caps caps = {0};
287 rt_uint32_t e, index;
288
289 mic.buffer = rt_malloc(RECORD_BUFFER_SZ);
290 if (mic.buffer == RT_NULL)
291 {
292 LOG_E("malloc failed");
293 goto __exit;
294 }
295
296 mic.dev = rt_device_find(MIC_DEVICE_NAME);
297 if (mic.dev == RT_NULL)
298 {
299 LOG_E("can't find device:%s", MIC_DEVICE_NAME);
300 goto __exit;
301 }
302
303 while (1)
304 {
305 if (rt_event_recv(mic.event, EVENT_RECORD_START | EVENT_RECORD_STOP,
306 RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
307 1000, &e) != RT_EOK)
308 {
309 continue;
310 }
311 if (mic.open_count == 0)
312 {
313 continue;
314 }
315 LOG_D("record start");
316
317 rt_device_open(mic.dev, RT_DEVICE_OFLAG_RDONLY);
318
319 caps.main_type = AUDIO_TYPE_INPUT;
320 caps.sub_type = AUDIO_DSP_PARAM;
321 caps.udata.config.samplerate = RECORD_SAMPLERATE;
322 caps.udata.config.channels = RECORD_CHANNEL;
323 caps.udata.config.samplebits = RESOLUTION_BITS;
324 rt_device_control(mic.dev, AUDIO_CTL_CONFIGURE, &caps);
325
326 while (1)
327 {
328 if (rt_event_recv(mic.event, EVENT_RECORD_DATA | EVENT_RECORD_STOP,
329 RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
330 1000, &e) != RT_EOK)
331 {
332 if (mic.open_count > 0)
333 continue;
334 else
335 break;
336 }
337 if (e & EVENT_RECORD_DATA)
338 {
339 index = (mic.buffer_index >= RECORD_BUFFER_SZ / 2) ? 0 : (RECORD_BUFFER_SZ / 2);
340 rt_device_read(mic.dev, 0, mic.buffer + index, RECORD_BUFFER_SZ / 2);
341 }
342 else if (e & EVENT_RECORD_STOP)
343 {
344 break;
345 }
346 }
347 LOG_D("record stop");
348 rt_device_close(mic.dev);
349 }
350
351 __exit:
352 if (mic.buffer)
353 rt_free(mic.buffer);
354 }
355
_record_start(ufunction_t func)356 static rt_err_t _record_start(ufunction_t func)
357 {
358 mic.ep->request.buffer = RT_NULL;
359 mic.ep->request.size = UAC_EP_MAX_PACKET_SIZE;
360 mic.ep->request.req_type = UIO_REQUEST_WRITE;
361 rt_usbd_io_request(func->device, mic.ep, &mic.ep->request);
362
363 mic.open_count ++;
364 rt_event_send(mic.event, EVENT_RECORD_START);
365 return 0;
366 }
367
_record_stop(ufunction_t func)368 static rt_err_t _record_stop(ufunction_t func)
369 {
370 mic.open_count --;
371 rt_event_send(mic.event, EVENT_RECORD_STOP);
372 return 0;
373 }
374
_ep_data_in_handler(ufunction_t func,rt_size_t size)375 static rt_err_t _ep_data_in_handler(ufunction_t func, rt_size_t size)
376 {
377 RT_ASSERT(func != RT_NULL);
378 LOG_D("_ep_data_in_handler");
379
380 mic.ep->request.buffer = mic.buffer + mic.buffer_index;
381 mic.ep->request.size = UAC_EP_MAX_PACKET_SIZE;
382 mic.ep->request.req_type = UIO_REQUEST_WRITE;
383 rt_usbd_io_request(func->device, mic.ep, &mic.ep->request);
384
385 mic.buffer_index += UAC_EP_MAX_PACKET_SIZE;
386 if (mic.buffer_index >= RECORD_BUFFER_SZ)
387 {
388 mic.buffer_index = 0;
389 rt_event_send(mic.event, EVENT_RECORD_DATA);
390 }
391 else if (mic.buffer_index == RECORD_BUFFER_SZ / 2)
392 {
393 rt_event_send(mic.event, EVENT_RECORD_DATA);
394 }
395
396 return RT_EOK;
397 }
398
_interface_as_handler(ufunction_t func,ureq_t setup)399 static rt_err_t _interface_as_handler(ufunction_t func, ureq_t setup)
400 {
401 RT_ASSERT(func != RT_NULL);
402 RT_ASSERT(func->device != RT_NULL);
403 RT_ASSERT(setup != RT_NULL);
404
405 LOG_D("_interface_as_handler");
406
407 if ((setup->request_type & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_STANDARD)
408 {
409 switch (setup->bRequest)
410 {
411 case USB_REQ_GET_INTERFACE:
412 break;
413 case USB_REQ_SET_INTERFACE:
414 LOG_D("set interface handler");
415 if (setup->wValue == 1)
416 {
417 _record_start(func);
418 }
419 else if (setup->wValue == 0)
420 {
421 _record_stop(func);
422 }
423 break;
424 default:
425 LOG_D("unknown uac request 0x%x", setup->bRequest);
426 return -RT_ERROR;
427 }
428 }
429
430 return RT_EOK;
431 }
432
_function_enable(ufunction_t func)433 static rt_err_t _function_enable(ufunction_t func)
434 {
435 RT_ASSERT(func != RT_NULL);
436
437 LOG_D("uac function enable");
438
439 return RT_EOK;
440 }
441
_function_disable(ufunction_t func)442 static rt_err_t _function_disable(ufunction_t func)
443 {
444 RT_ASSERT(func != RT_NULL);
445
446 LOG_D("uac function disable");
447 _record_stop(func);
448 return RT_EOK;
449 }
450
451 static struct ufunction_ops ops =
452 {
453 _function_enable,
454 _function_disable,
455 RT_NULL,
456 };
457 /**
458 * This function will configure uac descriptor.
459 *
460 * @param comm the communication interface number.
461 * @param data the data interface number.
462 *
463 * @return RT_EOK on successful.
464 */
_uac_descriptor_config(struct uac_ac_descriptor * ac,rt_uint8_t cintf_nr,struct uac_as_descriptor * as,rt_uint8_t sintf_nr)465 static rt_err_t _uac_descriptor_config(struct uac_ac_descriptor *ac,
466 rt_uint8_t cintf_nr, struct uac_as_descriptor *as, rt_uint8_t sintf_nr)
467 {
468 ac->hdr_desc.baInterfaceNr[0] = sintf_nr;
469 #ifdef RT_USB_DEVICE_COMPOSITE
470 ac->iad_desc.bFirstInterface = cintf_nr;
471 #endif
472
473 return RT_EOK;
474 }
475
_uac_samplerate_config(struct uac_as_descriptor * as,rt_uint32_t samplerate)476 static rt_err_t _uac_samplerate_config(struct uac_as_descriptor *as, rt_uint32_t samplerate)
477 {
478 as->format_type_desc.tSamFreq[0 * 3 + 2] = samplerate >> 16 & 0xff;
479 as->format_type_desc.tSamFreq[0 * 3 + 1] = samplerate >> 8 & 0xff;
480 as->format_type_desc.tSamFreq[0 * 3 + 0] = samplerate & 0xff;
481 return RT_EOK;
482 }
483
484 /**
485 * This function will create a uac function instance.
486 *
487 * @param device the usb device object.
488 *
489 * @return RT_EOK on successful.
490 */
rt_usbd_function_uac_mic_create(udevice_t device)491 ufunction_t rt_usbd_function_uac_mic_create(udevice_t device)
492 {
493 ufunction_t func;
494 uintf_t intf_ac, intf_as;
495 ualtsetting_t setting_as0;
496 ualtsetting_t setting_ac, setting_as;
497 struct uac_as_descriptor *as_desc_t;
498
499 /* parameter check */
500 RT_ASSERT(device != RT_NULL);
501
502 #ifdef RT_USB_DEVICE_COMPOSITE
503 rt_usbd_device_set_interface_string(device, MIC_INTF_STR_INDEX, _ustring[2]);
504 #else
505 /* set usb device string description */
506 rt_usbd_device_set_string(device, _ustring);
507 #endif
508 /* create a uac function */
509 func = rt_usbd_function_new(device, &dev_desc, &ops);
510 //not support HS
511 //rt_usbd_device_set_qualifier(device, &dev_qualifier);
512
513 /* create interface */
514 intf_ac = rt_usbd_interface_new(device, RT_NULL);
515 intf_as = rt_usbd_interface_new(device, _interface_as_handler);
516
517 /* create alternate setting */
518 setting_ac = rt_usbd_altsetting_new(sizeof(struct uac_ac_descriptor));
519 setting_as0 = rt_usbd_altsetting_new(sizeof(struct uinterface_descriptor));
520 setting_as = rt_usbd_altsetting_new(sizeof(struct uac_as_descriptor));
521 /* config desc in alternate setting */
522 rt_usbd_altsetting_config_descriptor(setting_ac, &ac_desc,
523 (rt_off_t) & ((struct uac_ac_descriptor *)0)->intf_desc);
524 rt_usbd_altsetting_config_descriptor(setting_as0, &as_desc0, 0);
525 rt_usbd_altsetting_config_descriptor(setting_as, &as_desc,
526 (rt_off_t) & ((struct uac_as_descriptor *)0)->intf_desc);
527 /* configure the uac interface descriptor */
528 _uac_descriptor_config(setting_ac->desc, intf_ac->intf_num, setting_as->desc, intf_as->intf_num);
529 _uac_samplerate_config(setting_as->desc, RECORD_SAMPLERATE);
530
531 /* create endpoint */
532 as_desc_t = (struct uac_as_descriptor *)setting_as->desc;
533 mic.ep = rt_usbd_endpoint_new(&as_desc_t->ep_desc, _ep_data_in_handler);
534
535 /* add the endpoint to the alternate setting */
536 rt_usbd_altsetting_add_endpoint(setting_as, mic.ep);
537
538 /* add the alternate setting to the interface, then set default setting of the interface */
539 rt_usbd_interface_add_altsetting(intf_ac, setting_ac);
540 rt_usbd_set_altsetting(intf_ac, 0);
541 rt_usbd_interface_add_altsetting(intf_as, setting_as0);
542 rt_usbd_interface_add_altsetting(intf_as, setting_as);
543 rt_usbd_set_altsetting(intf_as, 0);
544
545 /* add the interface to the uac function */
546 rt_usbd_function_add_interface(func, intf_ac);
547 rt_usbd_function_add_interface(func, intf_as);
548
549 return func;
550 }
551
audio_mic_init(void)552 int audio_mic_init(void)
553 {
554 rt_thread_t mic_tid;
555 mic.event = rt_event_create("mic_event", RT_IPC_FLAG_FIFO);
556
557 mic_tid = rt_thread_create("mic_thread",
558 mic_entry, RT_NULL,
559 1024,
560 5, 10);
561
562 if (mic_tid != RT_NULL)
563 rt_thread_startup(mic_tid);
564 return RT_EOK;
565 }
566 INIT_COMPONENT_EXPORT(audio_mic_init);
567
568 /*
569 * register uac class
570 */
571 struct udclass uac_class =
572 {
573 .rt_usbd_function_create = rt_usbd_function_uac_mic_create
574 };
575
rt_usbd_uac_mic_class_register(void)576 int rt_usbd_uac_mic_class_register(void)
577 {
578 rt_usbd_class_register(&uac_class);
579 return 0;
580 }
581 INIT_PREV_EXPORT(rt_usbd_uac_mic_class_register);
582