一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

深入淺出解析低功耗藍(lán)牙協(xié)議棧

jf_14701710 ? 來(lái)源:jf_14701710 ? 作者:jf_14701710 ? 2025-04-09 14:49 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

Bluetooth LE協(xié)議棧為什么要分層?怎么理解Bluetooth LE“連接”?如果Bluetooth LE協(xié)議只有ATT層沒有GATT層會(huì)發(fā)生什么?

一、協(xié)議??蚣?/p>

一般而言,我們把某個(gè)協(xié)議的實(shí)現(xiàn)代碼稱為協(xié)議棧(protocol stack),Bluetooth LE協(xié)議棧就是實(shí)現(xiàn)低功耗藍(lán)牙協(xié)議的代碼,理解和掌握Bluetooth LE協(xié)議是實(shí)現(xiàn)Bluetooth LE協(xié)議棧的前提。在深入Bluetooth LE協(xié)議棧各個(gè)組成部分之前,我們先看一下Bluetooth LE協(xié)議棧整體架構(gòu)。

wKgZPGf2GIyAPI_pAADGpv58Kys92.jpeg

如上圖所述,要實(shí)現(xiàn)一個(gè)Bluetooth LE應(yīng)用,首先需要一個(gè)支持Bluetooth LE射頻的芯片,然后還需要提供一個(gè)與此芯片配套的Bluetooth LE協(xié)議棧,最后在協(xié)議棧上開發(fā)自己的應(yīng)用。可以看出Bluetooth LE協(xié)議棧是連接芯片和應(yīng)用的橋梁,是實(shí)現(xiàn)整個(gè)Bluetooth LE應(yīng)用的關(guān)鍵。那Bluetooth LE協(xié)議棧具體包含哪些功能呢?簡(jiǎn)單來(lái)說(shuō),Bluetooth LE協(xié)議棧主要用來(lái)對(duì)你的應(yīng)用數(shù)據(jù)進(jìn)行層層封包,以生成一個(gè)滿足Bluetooth LE協(xié)議的空中數(shù)據(jù)包,也就是說(shuō),把應(yīng)用數(shù)據(jù)包裹在一系列的幀頭(header)和幀尾(tail)中。具體來(lái)說(shuō),Bluetooth LE協(xié)議棧主要由如下幾部分組成:

PHY層(Physical layer物理層)。PHY層用來(lái)指定Bluetooth LE所用的無(wú)線頻段,調(diào)制解調(diào)方式和方法等。PHY層做得好不好,直接決定整個(gè)Bluetooth LE芯片的功耗,靈敏度以及selectivity等射頻指標(biāo)。

LL層(Link Layer鏈路層)。LL層是整個(gè)Bluetooth LE協(xié)議棧的核心,也是Bluetooth LE協(xié)議棧的難點(diǎn)和重點(diǎn)。像Nordic的Bluetooth LE協(xié)議棧能同時(shí)支持20個(gè)link(連接),就是LL層的功勞。LL層要做的事情非常多,比如具體選擇哪個(gè)射頻通道進(jìn)行通信,怎么識(shí)別空中數(shù)據(jù)包,具體在哪個(gè)時(shí)間點(diǎn)把數(shù)據(jù)包發(fā)送出去,怎么保證數(shù)據(jù)的完整性,ACK如何接收,如何進(jìn)行重傳,以及如何對(duì)鏈路進(jìn)行管理和控制等等。LL層只負(fù)責(zé)把數(shù)據(jù)發(fā)出去或者收回來(lái),對(duì)數(shù)據(jù)進(jìn)行怎樣的解析則交給上面的GAP或者GATT。

HCI(Host controller interface)。HCI是可選的(具體請(qǐng)參考文章: 三種藍(lán)牙架構(gòu)實(shí)現(xiàn)方案(藍(lán)牙協(xié)議棧方案)),HCI主要用于2顆芯片實(shí)現(xiàn)Bluetooth LE協(xié)議棧的場(chǎng)合,用來(lái)規(guī)范兩者之間的通信協(xié)議和通信命令等。

GAP層(Generic access profile)。GAP是對(duì)LL層payload(有效數(shù)據(jù)包)如何進(jìn)行解析的兩種方式中的一種,而且是最簡(jiǎn)單的那一種。GAP簡(jiǎn)單的對(duì)LL payload進(jìn)行一些規(guī)范和定義,因此GAP能實(shí)現(xiàn)的功能極其有限。GAP目前主要用來(lái)進(jìn)行廣播,掃描和發(fā)起連接等。

L2CAP層(Logic link control and adaptation protocol)。L2CAP對(duì)LL進(jìn)行了一次簡(jiǎn)單封裝,LL只關(guān)心傳輸?shù)臄?shù)據(jù)本身,L2CAP就要區(qū)分是加密通道還是普通通道,同時(shí)還要對(duì)連接間隔進(jìn)行管理。

SMP(Secure manager protocol)。SMP用來(lái)管理Bluetooth LE連接的加密和安全的,如何保證連接的安全性,同時(shí)不影響用戶的體驗(yàn),這些都是SMP要考慮的工作。

ATT(Attribute protocol)。簡(jiǎn)單來(lái)說(shuō),ATT層用來(lái)定義用戶命令及命令操作的數(shù)據(jù),比如讀取某個(gè)數(shù)據(jù)或者寫某個(gè)數(shù)據(jù)。Bluetooth LE協(xié)議棧中,開發(fā)者接觸最多的就是ATT。Bluetooth LE引入了attribute概念,用來(lái)描述一條一條的數(shù)據(jù)。Attribute除了定義數(shù)據(jù),同時(shí)定義該數(shù)據(jù)可以使用的ATT命令,因此這一層被稱為ATT層。

GATT(Generic attribute profile )。GATT用來(lái)規(guī)范attribute中的數(shù)據(jù)內(nèi)容,并運(yùn)用group(分組)的概念對(duì)attribute進(jìn)行分類管理。沒有GATT,Bluetooth LE協(xié)議棧也能跑,但互聯(lián)互通就會(huì)出問題,也正是因?yàn)橛辛薌ATT和各種各樣的應(yīng)用profile,Bluetooth LE擺脫了ZigBee等無(wú)線協(xié)議的兼容性困境,成了出貨量最大的2.4G無(wú)線通信產(chǎn)品。

我相信很多人看了上面的介紹,還是不懂Bluetooth LE協(xié)議棧的工作原理,以及每一層具體干什么的,為什么要這么分層。下面我以如何發(fā)送一個(gè)數(shù)據(jù)包為例來(lái)講解Bluetooth LE協(xié)議棧各層是如何緊密配合,以完成發(fā)送任務(wù)的。

二、如何通過無(wú)線發(fā)送一個(gè)數(shù)據(jù)包

假設(shè)有設(shè)備A和設(shè)備B,設(shè)備A要把自己目前的電量狀態(tài)83%(十六進(jìn)制表示為0x53)發(fā)給設(shè)備B,該怎么做呢?作為一個(gè)開發(fā)者,他希望越簡(jiǎn)單越好,對(duì)他而言,他希望調(diào)用一個(gè)簡(jiǎn)單的API就能完成這件事,比如send(0x53),實(shí)際上我們的Bluetooth LE協(xié)議棧就是這樣設(shè)計(jì)的,開發(fā)者只需調(diào)用send(0x53)就可以把數(shù)據(jù)發(fā)送出去了,其余的事情Bluetooth LE協(xié)議棧幫你搞定。很多人會(huì)想,Bluetooth LE協(xié)議棧是不是直接在物理層就把0x53發(fā)出去,就如下圖所示:

wKgZO2f2GIyAIzxkAAARxQFP1Lc80.jpeg

這種方式初看起來(lái)挺美的,但由于很多細(xì)節(jié)沒有考慮到,實(shí)際是不可行的。首先,它沒有考慮用哪一個(gè)射頻信道來(lái)進(jìn)行傳輸,在不更改API的情況下,我們只能對(duì)協(xié)議棧進(jìn)行分層,為此引入LL層,開發(fā)者還是調(diào)用send(0x53),send(0x53)再調(diào)用send_LL(0x53,2402M)(注:2402M為信道頻率)。

這里還有一個(gè)問題,設(shè)備B怎么知道這個(gè)數(shù)據(jù)包是發(fā)給自己的還是其他人的,為此Bluetooth LE引入access address概念,用來(lái)指明接收者身份,其中,0x8E89BED6這個(gè)access address比較特殊,它表示要發(fā)給周邊所有設(shè)備,即廣播。如果你要一對(duì)一的進(jìn)行通信(Bluetooth LE協(xié)議將其稱為連接),即設(shè)備A的數(shù)據(jù)包只能設(shè)備B接收,同樣設(shè)備B的數(shù)據(jù)包只能設(shè)備A接收,那么就必須生成一個(gè)獨(dú)特的隨機(jī)access address以標(biāo)識(shí)設(shè)備A和設(shè)備B兩者之間的連接。

廣播方式

我們先來(lái)看一下簡(jiǎn)單的廣播情況,這種情況下,我們把設(shè)備A叫advertiser(廣播者),設(shè)備B叫scanner或者observer(掃描者)。廣播狀態(tài)下設(shè)備A的LL層API將變成send_LL(0x53,2402M, 0x8E89BED6)。由于設(shè)備B可以同時(shí)接收到很多設(shè)備的廣播,因此數(shù)據(jù)包還必須包含設(shè)備A的device address(0xE1022AAB753B)以確認(rèn)該廣播包來(lái)自設(shè)備A,為此send_LL參數(shù)需要變成(0x53,2402M, 0x8E89BED6, 0xE1022AAB753B)。LL層還要檢查數(shù)據(jù)的完整性,即數(shù)據(jù)在傳輸過程中有沒有發(fā)生竄改,為此引入CRC24對(duì)數(shù)據(jù)包進(jìn)行檢驗(yàn) (假設(shè)為0xB2C78E) 。同時(shí)為了調(diào)制解調(diào)電路工作更高效,每一個(gè)數(shù)據(jù)包的最前面會(huì)加上1個(gè)字節(jié)的preamble(前導(dǎo)幀),preamble一般為0x55或者0xAA。這樣,整個(gè)空中包就變成(注:空中包用小端模式表示?。?/p>

wKgZPGf2GI2AO9KSAAAugD6FXvs93.jpeg

上面這個(gè)數(shù)據(jù)包還有如下問題:

沒有對(duì)數(shù)據(jù)包進(jìn)行分類組織,設(shè)備B無(wú)法找到自己想要的數(shù)據(jù)0x53。為此我們需要在access address之后加入兩個(gè)字段:LL header和長(zhǎng)度字節(jié)。LL header用來(lái)表示數(shù)據(jù)包的LL類型,長(zhǎng)度字節(jié)用來(lái)指明payload的長(zhǎng)度

設(shè)備B什么時(shí)候開啟射頻窗口以接收空中數(shù)據(jù)包?如上圖case1所示,當(dāng)設(shè)備A的數(shù)據(jù)包在空中傳輸?shù)臅r(shí)候,設(shè)備B把接收窗口關(guān)閉,此時(shí)通信將失??;同樣對(duì)case2來(lái)說(shuō),當(dāng)設(shè)備A沒有在空中發(fā)送數(shù)據(jù)包時(shí),設(shè)備B把接收窗口打開,此時(shí)通信也將失敗。只有case3的情況,通信才能成功,即設(shè)備A的數(shù)據(jù)包在空中傳輸時(shí),設(shè)備B正好打開射頻接收窗口,此時(shí)通信才能成功,換句話說(shuō),LL層還必須定義通信時(shí)序。

當(dāng)設(shè)備B拿到數(shù)據(jù)0x53后,該如何解析這個(gè)數(shù)據(jù)呢?它到底表示濕度還是電量,還是別的意思?這個(gè)就是GAP層要做的工作,GAP層引入了LTV(Length-Type-Value)結(jié)構(gòu)來(lái)定義數(shù)據(jù),比如020105,02-長(zhǎng)度,01-類型(強(qiáng)制字段,表示廣播flag,廣播包必須包含該字段),05-值。由于廣播包最大只能為31個(gè)字節(jié),它能定義的數(shù)據(jù)類型極其有限,像這里說(shuō)的電量,GAP就沒有定義,因此要通過廣播方式把電量數(shù)據(jù)發(fā)出去,只能使用供應(yīng)商自定義數(shù)據(jù)類型0xFF,即04FF590053,其中04表示長(zhǎng)度,F(xiàn)F表示數(shù)據(jù)類型(自定義數(shù)據(jù)),0x0059是供應(yīng)商ID(自定義數(shù)據(jù)中的強(qiáng)制字段),0x53就是我們的數(shù)據(jù)(設(shè)備雙方約定0x53就是表示電量,而不是其他意思)。

最終空中傳輸?shù)臄?shù)據(jù)包將變成:

AAD6BE898E600E3B75AB2A02E102010504FF5900538EC7B2

AA – 前導(dǎo)幀(preamble)

D6BE898E – 訪問地址(access address)

60 – LL幀頭字段(LL header)

0E – 有效數(shù)據(jù)包長(zhǎng)度(payload length)

3B75AB2A02E1 – 廣播者設(shè)備地址(advertiser address)

02010504FF590053 – 廣播數(shù)據(jù)

8EC7B2 – CRC24值

wKgZO2f2GI6ABgmfAAAfugdTqYg14.jpeg

有了PHY,LL和GAP,就可以發(fā)送廣播包了,但廣播包攜帶的信息極其有限,而且還有如下幾大限制:

無(wú)法進(jìn)行一對(duì)一雙向通信 (廣播是一對(duì)多通信,而且是單方向的通信)

由于不支持組包和拆包,因此無(wú)法傳輸大數(shù)據(jù)

通信不可靠及效率低下。廣播信道不能太多,否則將導(dǎo)致掃描端效率低下。為此,Bluetooth LE只使用37(2402MHz) /38(2426MHz) /39(2480MHz)三個(gè)信道進(jìn)行廣播和掃描,因此廣播不支持跳頻。由于廣播是一對(duì)多的,所以廣播也無(wú)法支持ACK。這些都使廣播通信變得不可靠。

掃描端功耗高。由于掃描端不知道設(shè)備端何時(shí)廣播,也不知道設(shè)備端選用哪個(gè)頻道進(jìn)行廣播,掃描端只能拉長(zhǎng)掃描窗口時(shí)間,并同時(shí)對(duì)37/38/39三個(gè)通道進(jìn)行掃描,這樣功耗就會(huì)比較高。

而連接則可以很好解決上述問題,下面我們就來(lái)看看連接是如何將0x53發(fā)送出去的。

連接方式

到底什么叫連接(connection)?像有線UART,很容易理解,就是用線(Rx和Tx等)把設(shè)備A和設(shè)備B相連,即為連接。用“線”把兩個(gè)設(shè)備相連,實(shí)際是讓2個(gè)設(shè)備有共同的通信媒介,并讓兩者時(shí)鐘同步起來(lái)。

藍(lán)牙連接何嘗不是這個(gè)道理,所謂設(shè)備A和設(shè)備B建立藍(lán)牙連接,就是指設(shè)備A和設(shè)備B兩者一對(duì)一“同步”成功,其具體包含以下幾方面:

設(shè)備A和設(shè)備B對(duì)接下來(lái)要使用的物理信道達(dá)成一致

設(shè)備A和設(shè)備B雙方建立一個(gè)共同的時(shí)間錨點(diǎn),也就是說(shuō),把雙方的時(shí)間原點(diǎn)變成同一個(gè)點(diǎn)

設(shè)備A和設(shè)備B兩者時(shí)鐘同步成功,即雙方都知道對(duì)方什么時(shí)候發(fā)送數(shù)據(jù)包什么時(shí)候接收數(shù)據(jù)包

連接成功后,設(shè)備A和設(shè)備B通信流程如下所示:

wKgZPGf2GI6AA3LwAAArnOKLgk433.jpeg

如上圖所示,一旦設(shè)備A和設(shè)備B連接成功(此種情況下,我們把設(shè)備A稱為Master或者Central,把設(shè)備B稱為Slave或者Peripheral),設(shè)備A將周期性以CI(connection interval)為間隔向設(shè)備B發(fā)送數(shù)據(jù)包,而設(shè)備B也周期性地以CI為間隔打開射頻接收窗口以接收設(shè)備A的數(shù)據(jù)包。同時(shí)按照藍(lán)牙spec要求,設(shè)備B收到設(shè)備A數(shù)據(jù)包150us后,設(shè)備B切換到發(fā)送狀態(tài),把自己的數(shù)據(jù)發(fā)給設(shè)備A;設(shè)備A則切換到接收狀態(tài),接收設(shè)備B發(fā)過來(lái)的數(shù)據(jù)。由此可見,連接狀態(tài)下,設(shè)備A和設(shè)備B的射頻發(fā)送和接收窗口都是周期性地有計(jì)劃地開和關(guān),而且開的時(shí)間非常短,從而大大降低系統(tǒng)功耗并大大提高系統(tǒng)效率。

現(xiàn)在我們看看連接狀態(tài)下是如何把數(shù)據(jù)0x53發(fā)送出去的,從中大家可以體會(huì)到藍(lán)牙協(xié)議棧分層的妙處。

對(duì)開發(fā)者來(lái)說(shuō),很簡(jiǎn)單,他只需要調(diào)用send(0x53)

GATT層定義數(shù)據(jù)的類型和分組,方便起見,我們用0x0013表示電量這種數(shù)據(jù)類型,這樣GATT層把數(shù)據(jù)打包成130053(小端模式!)

ATT層用來(lái)選擇具體的通信命令,比如讀/寫/notify/indicate等,這里選擇notify命令0x1B,這樣數(shù)據(jù)包變成了:1B130053

L2CAP用來(lái)指定connection interval(連接間隔),比如每10ms同步一次(CI不體現(xiàn)在數(shù)據(jù)包中),同時(shí)指定邏輯通道編號(hào)0004(表示ATT命令),最后把ATT數(shù)據(jù)長(zhǎng)度0x0004加在包頭,這樣數(shù)據(jù)就變?yōu)椋?40004001B130053

LL層要做的工作很多,首先LL層需要指定用哪個(gè)物理信道進(jìn)行傳輸(物理信道不體現(xiàn)在數(shù)據(jù)包中),然后再給此連接分配一個(gè)Access address(0x50655DAB)以標(biāo)識(shí)此連接只為設(shè)備A和設(shè)備B直連服務(wù),然后加上LL header和payload length字段,LL header標(biāo)識(shí)此packet為數(shù)據(jù)packet,而不是control packet等,payload length為整個(gè)L2CAP字段的長(zhǎng)度,最后加上CRC24字段,以保證整個(gè)packet的數(shù)據(jù)完整性,所以數(shù)據(jù)包最后變成:

AAAB5D65501E08040004001B130053D550F6

AA – 前導(dǎo)幀(preamble)

0x50655DAB – 訪問地址(access address)

1E – LL幀頭字段(LL header)

08 – 有效數(shù)據(jù)包長(zhǎng)度(payload length)

04000400 – ATT數(shù)據(jù)長(zhǎng)度,以及L2CAP通道編號(hào)

1B – notify command

0x0013 – 電量數(shù)據(jù)handle

0x53 – 真正要發(fā)送的電量數(shù)據(jù)

0xF650D5 – CRC24值

雖然開發(fā)者只調(diào)用了 send(0x53),但由于低功耗藍(lán)牙協(xié)議棧層層打包,最后空中實(shí)際傳輸?shù)臄?shù)據(jù)將變成下圖所示的模樣,這就既滿足了低功耗藍(lán)牙通信的需求,又讓用戶API變得簡(jiǎn)單,可謂一箭雙雕!

wKgZO2f2GI-AaEHFAAAgJ0OOSvk62.jpeg

上面只是對(duì)Bluetooth LE協(xié)議棧實(shí)現(xiàn)原理做了一個(gè)簡(jiǎn)單概述,即便如此,由于都是關(guān)于Bluetooth LE協(xié)議棧底層的東西,很多開發(fā)者還是會(huì)覺得比較枯燥和晦澀,而且對(duì)很多開發(fā)者來(lái)說(shuō),他們也不關(guān)心Bluetooth LE協(xié)議棧是如何實(shí)現(xiàn)的,他們更關(guān)心的是Bluetooth LE協(xié)議棧的使用,即怎么開發(fā)一個(gè)Bluetooth LE應(yīng)用。Bluetooth LE應(yīng)用是實(shí)打?qū)嵉臇|西,不能像上面講述協(xié)議棧一樣泛泛而談,必須結(jié)合具體的藍(lán)牙芯片和藍(lán)牙協(xié)議棧來(lái)講解,為此后面將以Nordic芯片及協(xié)議棧作為范例,來(lái)具體講解如何開發(fā)Bluetooth LE應(yīng)用,以及如何通過代碼去理解Bluetooth LE協(xié)議中定義的一些概念和術(shù)語(yǔ)。

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 協(xié)議棧
    +關(guān)注

    關(guān)注

    2

    文章

    145

    瀏覽量

    34104
  • 低功耗藍(lán)牙
    +關(guān)注

    關(guān)注

    1

    文章

    246

    瀏覽量

    21952
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    深入淺出AVR(傻孩子)

    本帖最后由 eehome 于 2013-1-5 09:56 編輯 深入淺出AVR(傻孩子)
    發(fā)表于 06-29 15:43

    深入淺出AVR

    深入淺出AVR,一本書。
    發(fā)表于 07-15 12:02

    深入淺出玩轉(zhuǎn)FPGA

    深入淺出玩轉(zhuǎn)FPGA
    發(fā)表于 07-21 09:21

    深入淺出ARM7

    深入淺出ARM7
    發(fā)表于 08-18 10:12

    HDMI技術(shù)深入淺出

    HDMI技術(shù)深入淺出
    發(fā)表于 08-19 10:52

    深入淺出Android

    深入淺出Android
    發(fā)表于 08-20 10:14

    深入淺出Android

    深入淺出Android
    發(fā)表于 04-26 10:48

    深入淺出安防視頻監(jiān)控系統(tǒng)

    深入淺出安防視頻監(jiān)控系統(tǒng)深入淺出安防視頻監(jiān)控系統(tǒng)
    發(fā)表于 05-22 19:28

    深入淺出AVR

    深入淺出AVR
    發(fā)表于 08-23 10:10

    深入淺出數(shù)據(jù)分析

    深入淺出數(shù)據(jù)分析,有需要的朋友下來(lái)看看。
    發(fā)表于 01-15 14:22 ?0次下載

    深入淺出談多層面板布線技巧

    深入淺出談多層面板布線技巧
    發(fā)表于 12-13 22:20 ?0次下載

    深入淺出Android—Android開發(fā)經(jīng)典教材

    深入淺出Android—Android開發(fā)經(jīng)典教材
    發(fā)表于 10-24 08:52 ?15次下載
    <b class='flag-5'>深入淺出</b>Android—Android開發(fā)經(jīng)典教材

    深入淺出數(shù)字信號(hào)處理

    深入淺出數(shù)字信號(hào)處理
    發(fā)表于 12-07 20:14 ?638次閱讀

    深入淺出學(xué)習(xí)250個(gè)通信原理資源下載

    深入淺出學(xué)習(xí)250個(gè)通信原理資源下載
    發(fā)表于 04-12 09:16 ?30次下載

    深入淺出學(xué)習(xí)低功耗藍(lán)牙協(xié)議

    深入淺出學(xué)習(xí)低功耗藍(lán)牙協(xié)議
    發(fā)表于 06-23 10:35 ?60次下載