Windows虚拟UAC麦克风增加特性单元的开发调试笔记
昨晚突然接到通知,需要增加对UAC麦克风设备音量增益的控制。
我努力地回忆了去年12月份自己粗略地整理的UAC规范,发布于http://www.usbzh.com/article/forum-1.html
想着今天完成应该是美好的周五,会心满意足地完成工作,然后美美地打卡下班。可没想到就这么一个简单的东西(想着UVC的各种单元都可以轻松完成,你UAC还不手到擒来),可没想到实际在操作过程中差一点就闪了我的老腰…
在UAC的音频控制类有一个UAC 特性单元描述符,该描述符用于描述特性单元的功能,如常见的静音、音量大小等,详情见本人总结的特性单元描述符一节的bmaControls字节段描述。
该特性描述符由于是对音频特性的控制,所以在音频的拓扑结构中应位于输入终端和输出终端之间。
- 输入终端:http://www.usbzh.com/article/detail-180.html
- 特性单元:http://www.usbzh.com/article/detail-255.html
- 输出终端:http://www.usbzh.com/article/detail-237.html
增加了描述符后,再后再增加其对应的特定类请求,类似这样的代码:
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_INTERNAL_USB_SUBMIT_URB)
{
PURB Urb = (PURB)irpStack->Parameters.Others.Argument1;
if (Urb->UrbHeader.Function == URB_FUNCTION_CLASS_INTERFACE)
{
//在这里根据过滤特性单元ID进行特性类请求相关代码的实现
}
}
特定类的请求一般包括SET_CUR,GET_CUR,GET_MIN,GET_MAX,GET_RES,GET_LEN,GET_IN,GET_DEF
对特定类请求不了解的同学可以参见以下网址:
- 特定类请求概述 http://www.usbzh.com/article/detail-41.html
- SET_CUR和GET_CUR http://www.usbzh.com/article/detail-29.html
关于该特性单元的选择子由于这里只设置音量的大小,所以选择子只有VOLUME_CONTROL。
关于该选择子的解释可详见:http://www.usbzh.com/article/detail-249.html
实现以上的代码,可能只需要几分钟,如果代码正常,应该分分钟调试完成。可实际上我是调试了一个上午外加下午一个小时。现象是只要我增加了特性单元描述符,Windows设备管理器中枚举出的设备显示设备启动失败,原因是找不到对象。
很粗略的解释,我的理解应该是这个对象应该就是特性单元,但我左看右看上看下看我的拓年结构配置没有问题啊,为什么会出现这种情况了。
开始怀疑人生了…
开始怀疑自己对UAC的认识了…
喵喵喵…
气死我了…
一翻波折,终于在单步调试的时候发现UA控制单元头的长度感觉有点不对,进而最后再查原来是特性单元的描述符的长度设置错误了:
PUSB_AUDIO_CONTROL_FEATURE_DESCRIPTOR pAudioControlDesc = (PUSB_AUDIO_CONTROL_FEATURE_DESCRIPTOR)((char*)pACITDesc + pACITDesc->bLength);
pAudioControlDesc->bControlSize = 9; //本该设置的是length,怎么奈写成了bControlSize
pAudioControlDesc->bDescriptorType = 0x24;//AUDIO INTERFACE DESCRIPTOR
pAudioControlDesc->bDescriptorSubtype = 6;//Feature unit
pAudioControlDesc->bUnitID = 0x0a;
pAudioControlDesc->bSourceID = 1;
pAudioControlDesc->bControlSize = 1;
pAudioControlDesc->bmaControls[0] = 0x02;//main channel
pAudioControlDesc->bmaControls[1] = 0x00;// other channel
pAudioControlDesc->iFeature = 0;//no string
描述符的定义如下:
typedef struct _USB_AUDIO_CONTROL_FEATURE_DESCRIPTOR
{
UINT8 bLength;
UINT8 bDescriptorType;
UINT8 bDescriptorSubtype;
UINT8 bUnitID;
UINT8 bSourceID;
UINT8 bControlSize;
UINT8 bmaControls[2]; //0为主通道,后续依次为各逻辑通道
UINT8 iFeature;
}USB_AUDIO_CONTROL_FEATURE_DESCRIPTOR;