multiplexer protocol研究笔记
multiplexer protocol研究筆記
?
轉載時請注明出處和作者聯系方式:http://blog.csdn.net/absurd
作者聯系方式:Li XianJing <xianjimli at hotmail dot com>
更新時間:2006-12-19
?
multiplexer protocol是GSM中比較重要的協議,在GSM 07.10中對該協議做了詳細的描述。說它重要是因為它是銜接手機(TE)和模組(MS)之間的紐帶,TE和MS通信,一般是通過一個串口進行,問題在于串口只有一個,而通信的數據類型卻有很多種。比如AT Command、voice、 fax、 data、 SMS、CBS、 phonebook、電量狀態、GPRS和USSD 等等。如果傳輸時一個一個來,每種類型的數據都以獨占的方式傳輸(比如在使用GPRS上網時,就不能接收/發送短信),雖然技術上可行,但是對用戶來說不太友好。
?
multiplexer protocol就是用來解決這個問題的:讓不同類型的數據在一個串口上傳輸,而不至于發生紊亂。想想我們的網卡,通常也只有一個,但可以用它來傳輸任何數據類型,可以用HTTP協議瀏覽網頁,用FTP協議下載/上傳文件,用即時通信協議聊天,這些事情同時進行,而不會發生任何干擾,這一切都是由TCP/IP這一系列的協議來保證的。
?
multiplexer protocol采用的方法是把一個串口模擬成多個串口,對上層應用程序來說,每一個虛擬的串口和普通串口幾乎沒有差別,只是每個虛擬串口都只能傳輸特定類型的數據。下面moto的定義:
| VOICE_CALL | "/dev/mux0" |
| SMS_MO | "/dev/mux1" |
| SMS_MT | "/dev/mux2" |
| PHONEBOOK | "/dev/mux3" |
| MISC | "/dev/mux4" |
| CSD | "/dev/mux5" |
| GPRS1 | "/dev/mux6" |
| GPRS2 | "/dev/mux7" |
| CSD | "/dev/mux8" |
| GPRS1 | "/dev/mux9" |
| GPRS2 | "/dev/mux10" |
| LOGGER_CMD | "/dev/mux11" |
| LOGGER_DATA | "/dev/mux12" |
| TEST_CMD | "/dev/mux13" |
| AGPS | "/dev/mux14" |
| NET_MONITOR | "/dev/mux15" |
?
多個虛擬串口上的數據最終要在一個串口上傳輸,所以需要用一個標識來區分它們,這就是Data Link Connection Identifier (DLCI)。其中DLC0比較特殊,它用于在MS和TE之間傳遞管理和控制數據包。比如建立其它DLCI、參數協商和退出multiplexer狀態等等。
?
multiplexer protocol的協議棧如下:
l?????????最上層是應用層,應用層協議與具體應用有關,比如傳遞AT Command、Voice和GPRS數據,不同應用的協議是不一樣的。
l?????????最下層是物理層,即串口協議,描述了諸如起始位,校驗方式和速率等等。
l?????????Multiplexer Layers: 傳遞字節流數據。
l?????????Convergence Layers: 傳遞結構化數據。
?
具體如下圖所示:
?
multiplexer protocol有三種工作模式:基本模式、不帶錯誤恢復的高級模式和帶錯誤恢復的高級模式。
?
multiplexer protocol定義了下面這些類型服務:
l?????????Start up services 進入multiplexer模式。
l?????????DLC establishment services 建立DLC連接,每個連接對應一個虛擬串口。
l?????????Data services 傳輸數據。
l?????????Power Control services 電源管理,進入睡眠和喚醒。
l?????????DLC Release services 斷開DLC連接。
l?????????Close down services退出multiplexer模式。
l?????????Control Services 控制服務,主要用于設置一些參數,比如超時時間,重傳次數和速率等等。
?
基本協議數據單元(PDU)格式如下:
| Flag | Address | Control | Length Indicator | Information | FCS | Flag |
| 1?octet | 1?octet | 1 octet | 1or2 octets | Unspecified length but integral number of octets | 1?octet | 1?octet |
前后的flag用來標識幀的起始和結束。
Address主要是DLCI,同時還一個c/r用來標識是命令還是命令的回應。
Length是數據的長度。
Information是實際傳輸的數據。
FCS是校驗和,不同類型的幀的FCS計算方法不一樣。
control是用來描述數據包類型的。其描述如下:
| Frame Type | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Notes |
| SABM (Set Asynchronous Balanced Mode) | 1 | 1 | 1 | 1 | P/F | 1 | 0 | 0 | ? |
| UA (Unnumbered Acknowledgement) | 1 | 1 | 0 | 0 | P/F | 1 | 1 | 0 | ? |
| DM (Disconnected Mode) | 1 | 1 | 1 | 1 | P/F | 0 | 0 | 0 | ? |
| DISC (Disconnect) | 1 | 1 | 0 | 0 | P/F | 0 | 1 | 0 | ? |
| UIH (Unnumbered Information with Header check) | 1 | 1 | 1 | 1 | P/F | 1 | 1 | 1 | ? |
| UI (Unnumbered Information) | 1 | 1 | 0 | 0 | P/F | 0 | 0 | 0 | Optional |
?
上述的PDU(short address/short length)在程序中表示如下:
| typedef?struct{ ??__u8?ea:1; ??__u8?cr:1; ??__u8?d:1; ??__u8?server_chn:5; }?__attribute__((packed)) address_field; ? typedef?struct{ ??__u8??ea:1; ??__u8??len:7; }?__attribute__((packed)) short_length; ? typedef?struct{ ??address_field?addr; ??__u8?control; ??short_length?length; }?__attribute__((packed)) short_frame_head; ? typedef?struct{ ??short_frame_head?h; ??__u8?data[0]; }?__attribute__((packed)) short_frame; ? |
?
在linux下虛擬串口,主要是實現一個tty_driver,和其它驅動程序一樣,要實現諸如打開、關閉、讀、寫、控制等函數。下面我們看看數據的發送過程,也就是write函數的實現。
?
| 函數原型: static?int?mux_write(struct?tty_struct *?tty,?int?from_user, ???????????const?unsigned?char?*buf,?int?count) ? 檢查狀態: ??dlci = tty2dlci[line]; ??if( ts0710->dlci[0].state?== FLOW_STOPPED ){ ????TS0710_DEBUG("Flow stopped on all channels, returning zero /dev/mux%d/n", line); ????return?0; ??}?else?if( ts0710->dlci[dlci].state?== FLOW_STOPPED ){ ????TS0710_DEBUG("Flow stopped, returning zero /dev/mux%d/n", line); ????return?0; ??}?else?if( ts0710->dlci[dlci].state?== CONNECTED ){ ? 準備數據包: ????send_info->frame?= d_buf; ????queue_uih(send_info, c + 1, ts0710, dlci); ? 發送數據包: ?????????mux_sched_send ? static?void?queue_uih(mux_send_struct *send_info, __u16?len, ts0710_con *ts0710, __u8 dlci) { ??__u32?size; ? ???長數據包: ??if?(len?> SHORT_PAYLOAD_SIZE) { ????long_frame *l_pkt; ? ????size?=?sizeof(long_frame) +?len?+ FCS_SIZE; ????l_pkt?= (long_frame *) (send_info->frame?-?sizeof(long_frame)); ????set_uih_hdr((void*)l_pkt, dlci,?len, ts0710->initiator); ????l_pkt->data[len] = crc_calc((__u8*)?l_pkt, LONG_CRC_CHECK); ????send_info->frame?= ( (__u8*)l_pkt?) - 1; ??}?else?{ ???短數據包: ????short_frame *s_pkt; ? ????size?=?sizeof(short_frame) +?len?+ FCS_SIZE; ????s_pkt?= (short_frame *) (send_info->frame?-?sizeof(short_frame)); ????set_uih_hdr((void?*)s_pkt, dlci,?len, ts0710->initiator); ????s_pkt->data[len] = crc_calc((__u8*)?s_pkt, SHORT_CRC_CHECK); ????send_info->frame?= ( (__u8*)s_pkt?) - 1; ??} ??send_info->length?=?size; } ? static?void?set_uih_hdr(short_frame *uih_pkt, __u8 dlci, __u32?len, __u8 cr) { ??uih_pkt->h.addr.ea = 1; ??uih_pkt->h.addr.cr = cr; ??uih_pkt->h.addr.d = dlci & 0x1; ??uih_pkt->h.addr.server_chn = dlci >> 1; ??uih_pkt->h.control = CLR_PF(UIH);?/*奇怪:為什么不是SET_PF?*/ ? ??if?(len?> SHORT_PAYLOAD_SIZE) { ????SET_LONG_LENGTH( ((long_frame*) uih_pkt)->h.length,?len?); ??}?else?{ ????uih_pkt->h.length.ea = 1; ????uih_pkt->h.length.len?=?len; ??} } |
?
Multiplexer是一個對稱的協議,也就是說協議連接的雙方是對等的,誰都可以發起請求,設置控制參數,或者斷開連接(不過要注意應用層協議是非對等的)。
?
在GSM協議方面我完全是外行,花了兩天時間,Multiplexer協議的基本原理差不多清楚了,但仍然有些細節不太明白,以后用的時候再說吧。歡迎大家和我交流。
?
注:
以上引用的代碼源于Motorola的Multiplexer實現,版權歸Motorola所有。
以上引用的數據源于GSM 07.10 version 7.1.0 Release 1998
?
~~end~~
總結
以上是生活随笔為你收集整理的multiplexer protocol研究笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 五子棋GUI_C++
- 下一篇: 数据分享|1961-2017年中国0.2