Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there any way to enable/disable UAC1 when headset plugin/plugout? #5

Open
ranbochen opened this issue Oct 9, 2019 · 6 comments
Open

Comments

@ranbochen
Copy link

我在DIY一个USB手机底座,底座上有3.5寸耳机转接插口
底座USB上用UAC1获取手机音频,现在可以用耳机听音乐了
但是手机插上底座后,如果不插耳机,声音也是传给USB底座了,没法从手机中直接播放
有没有办法做到插上耳机后才让手机把音频数据传过来?
也就是插上耳机的时候,底座播放;没插耳机的时候就禁用UAC手机自己播放音频?
目前想到断开USB重连,重新发一个新的Descriptor可以实现,但这样断开重连会打乱其他interface的数据传输。不知道UAC层面是否有方法实现这个功能?

@dragonman225
Copy link
Owner

單純用 UAC 可能沒辦法實現,據我所知 UAC 的控制請求都是 host to device 的。如果要確認可以詳讀規格書 https://www.usb.org/sites/default/files/audio10.pdf 第五章 Requests。

我有兩個想法:

  1. 用 HID 可以實現 device to host 的命令,但前提是 HID 要支援「禁用 UAC」或類似的命令(參考 USB Audio 2.0: Device to host volume control 的思路)
  2. 不插耳機時,停止 USB 的運作,比如使用 USBD_Stop。插上耳機時,重新初始化 USB。思路是停止 USB 後,列舉無法完成,host 自然不會傳資料。

@ranbochen
Copy link
Author

AudioControl interface可以定义一个interrupt endpoint通知host状态有改变,可以实现device端主动更换input(muc换line-in等),主动更改音量/静音等。通知后host会主动来获取。但是感觉他没有来获取interface的alt-setting(0xA GET-INTERFACE),不然可以主动切换到zero-bandwidth实现?

目前就是按照你说的第二种方式在做。体验不是很好,我有用其他EP传输数据,插拔耳机会导致数据会断开。

@ranbochen
Copy link
Author

UAC1.0 DOC 3.7.2 AudioStreaming Interface

In addition, the concepts of dynamic interfaces as described in the Universal Serial Bus Class
Specification can be used to notify the Host software that changes have occurred on the external
connection. This is analogous to switching alternate settings on an AudioStreaming interface with USB
endpoints, except that the switch is now device-initiated instead of Host-initiated.
As an example, consider an S/PDIF connection to an audio function. If nothing is connected to this
external S/PDIF interface, the AudioStreaming interface is idle and reports itself as being dynamic and
non-configured (bInterfaceClass=0x00). If the user connects a standard IEC958 signal to the audio
function, the S/PDIF receiver inside the audio function detects this and notifies the Host that the
AudioStreaming interface has switched to its IEC958 mode (alternate setting x).

不知道这个“dynamic interfaces” 和 “bInterfaceClass=0x00”怎么实现,我查了很多文档,都没有找到相关资料,你有什么印象或者资料能分享一下吗?能否用来实现动态切换UAC呢?

@dragonman225
Copy link
Owner

翻了下文檔,有個想法,但不知道正不正確。

UAC1.0 DOC 3.7.1.2 Status Interrupt Endpoint

A USB AudioControl interface can support an optional interrupt endpoint to inform the Host about the status of the different addressable Entities (Terminals, Units, interfaces and endpoints) inside the audio function.

Bit D6 of the bStatusType field indicates a change in memory contents on one of the addressable Entities inside the audio function. This bit is cleared by a Get Memory request[1] on the appropriate Entity.

[1] 5.2.4.1.2 Get Memory Request

整個串起來可能是:
在 AudioControl 開一個 interrupt endpoint。
當耳機插入或拔出時,device 發 interrupt 告訴 host AudioStreaming interface 改變了(插入時從只有 alt setting 0 變成有多個 alt settings,拔出時則相反),host 收到 interrupt 後會發 Get Memory Request 取得新的 alt setting 列表,然後再發 Set Interface 來指定 alt setting。

也許這就是所謂的 dynamic interfaces ?

@dragonman225
Copy link
Owner

這裡有類似的問題:[alsa-devel] Audio usb switch to alternate setting 0

@ranbochen
Copy link
Author

翻了下文檔,有個想法,但不知道正不正確。

UAC1.0 DOC 3.7.1.2 Status Interrupt Endpoint

A USB AudioControl interface can support an optional interrupt endpoint to inform the Host about the status of the different addressable Entities (Terminals, Units, interfaces and endpoints) inside the audio function.

Bit D6 of the bStatusType field indicates a change in memory contents on one of the addressable Entities inside the audio function. This bit is cleared by a Get Memory request[1] on the appropriate Entity.

[1] 5.2.4.1.2 Get Memory Request

整個串起來可能是:
在 AudioControl 開一個 interrupt endpoint。
當耳機插入或拔出時,device 發 interrupt 告訴 host AudioStreaming interface 改變了(插入時從只有 alt setting 0 變成有多個 alt settings,拔出時則相反),host 收到 interrupt 後會發 Get Memory Request 取得新的 alt setting 列表,然後再發 Set Interface 來指定 alt setting。

也許這就是所謂的 dynamic interfaces ?

看他文档感觉就是应该这么做,
现在就是不知道通过什么方式,把新的config descriptor信息传给host(我目前测试interrupt报告有更改之后,host没有发送GET-DESC等标准请求来获取新的descriptor。由于stm32的库功能不全,也可能是我测试过程中有错误逻辑)
我会继续做测试

目前我还有另外一个想法,还没做测试,如下:
. 在Audio Stream中加入一个 selecter 单元,将mic和usb(手机)都作为speaker的输入源
. 插上耳机之后,将speaker-stream输入源通过selector设置为USB(手机);拔出之后设置为mic
. 通过interrupt通知手机,stream 有改变
这样手机就知道他的USB输出被悬空了,没法通过USB播放,只能自己播放了?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants