UAC麦克风驱动分析
2021-07-23
1288
0
UAC麦克风驱动框架:
应用层测试代码:https://blog.csdn.net/isunbin/article/details/81503152
对于 gadget uac1 驱动来说, 只需要通过ALSA 框架提供的API读写声卡设备即可。 也是就是说我们只要实现声卡的读写和配置理论上就可以访到麦克风硬件了。
具体读写API 参见 u_uac.c / u_uac.h
int gaudio_setup(struct gaudio * card);
void gaudio_cleanup(struct gaudio * the_card);
void u_audio_clear(struct gaudio * card);
size_t u_audio_playback(struct gaudio * card, void * buf, size_t count);
size_t u_audio_capture(struct gaudio * card, void * buf, size_t count);
int u_audio_get_playback_channels(struct gaudio * card);
int u_audio_get_playback_rate(struct gaudio * card);
int u_audio_get_capture_channels(struct gaudio * card);
int u_audio_get_capture_rate(struct gaudio * card);
f_uac.c 驱动加载过程
- 为f_usb_function_instance 实例申请内存并初始化实例相关参数
DECLARE_USB_FUNCTION_INIT(uac1, f_audio_alloc_inst, f_audio_alloc); static struct usb_function_instance * f_audio_alloc_inst(void) { struct f_uac1_opts * opts; opts = kzalloc(sizeof( * opts), GFP_KERNEL); if (!opts) return ERR_PTR(-ENOMEM); mutex_init( & opts - > lock); opts - > func_inst.free_func_inst = f_audio_free_inst; config_group_init_type_name( & opts - > func_inst.group, "", & f_uac1_func_type); opts - > req_capture_buf_size = UAC1_IN_EP_MAX_PACKET_SIZE; opts - > req_capture_count = UAC1_IN_REQ_COUNT; opts - > audio_capture_buf_size = UAC1_AUDIO_CAPTURE_BUF_SIZE; opts - > sample_rate = UAC1_SAMPLE_RATE; opts - > fn_play = FILE_PCM_PLAYBACK; opts - > fn_cap = FILE_PCM_CAPTURE; opts - > fn_cntl = FILE_CONTROL; return &opts - > func_inst; }
- 为 usb_function( 我们这里是usb 声卡) 申请内存 并为相关功能函数指针赋值
static struct usb_function * f_audio_alloc(struct usb_function_instance * fi) { struct f_audio * audio; struct f_uac1_opts * opts; /* allocate and initialize one new instance */ audio = kzalloc(sizeof( * audio), GFP_KERNEL); if (!audio) return ERR_PTR(-ENOMEM); audio - > card.func.name = "g_audio"; opts = container_of(fi, struct f_uac1_opts, func_inst); mutex_lock( & opts - > lock); ++opts - > refcnt; mutex_unlock( & opts - > lock); INIT_LIST_HEAD( & audio - > capture_queue); spin_lock_init( & audio - > capture_lock); audio - > card.func.bind = f_audio_bind; audio - > card.func.unbind = f_audio_unbind; audio - > card.func.get_alt = f_audio_get_alt; audio - > card.func.set_alt = f_audio_set_alt; audio - > card.func.setup = f_audio_setup; audio - > card.func.disable = f_audio_disable; audio - > card.func.free_func = f_audio_free; control_selector_init(audio); INIT_WORK( & audio - > capture_work, f_audio_capture_work); INIT_WORK( & audio - > close_work, f_audio_close_work); mutex_init( & audio - > mutex); return &audio - > card.func; }
- 设备绑定 注册设备描述符给主机
static int f_audio_bind(struct usb_configuration * c, struct usb_function * f) status = usb_assign_descriptors(f, f_audio_desc, f_audio_desc, f_audio_ss_desc, NULL);
- 主机根据上报的设备相关描述符识别我们的麦克风设备, 当我们在PC端使用麦克风的时候, 主机会主动向设备的OUT端点发送 URB 请求包.
5.此时会受到并相应主机的请求
启动读取麦克风数据任务
此时调用capture_work 实现麦克风数据读取并添加到capture_queue 队列。
当 audio->in_ep 请求完成之后我们调用f_audio_capture_ep_complete(ep, req); 将数据送给PC 主机。
HID人机交互QQ群:564808376
UAC音频QQ群:218581009
UVC相机QQ群:331552032
BOT&UASP大容量存储QQ群:258159197
STC-USB单片机QQ群:315457461
USB技术交流QQ群2:580684376
USB技术交流QQ群:952873936