星期日, 9月 25, 2016

AM335x Ethernet

AM335x 內建有 3 埠 Ethernet Switch,連接兩個 GMII 埠及 SoC Host,驅動程式使用 cpsw (CONFIG_CPSW,device tree 是 ti,cpsw)。

網路界面可使用單一 eth0,或者 eth0 加上 eth1。後者是 dual_emac 模式,可透過 device tree 設定。dual_emac 會有兩份 net_device 及 priv,有各自的 MAC address,但有許多東西是相同或共用的。

接收封包 (使用 NAPI)
  • 原本就有 sk_buff,open 時就準備好給驅動程式 DMA 使用。
  • 如果是 dual_emac 模式,會去看來自哪個 GMII port,取得精確的 net_device 及 priv
  • 取新 sk_buff 給之後封包 DMA 用。如果取不到,拋棄此封包,原本的 sk_buff 給之後封包 DMA 用。
  • 設 time stamp、protocol,netif_receive_skb() 及統計
註:
  • AM335x 不是 ARCH_DAVINCI,但用 DaVinci 的 MDIO 及 CPDMA。ti 有下列網路界面
    • CPSW (ARCH_DAVINCI or SOC_AM33XX): +DaVinci MDIO +DaVinci CPDMA +CPSW Phy sel
      • CPTS (CPSW): +PTP_1588_CLOCK
    • DaVinci EMAC (ARCH_DAVINCI or ARCH_OMAP3): +DaVinci MDIO +DaVinci CPDMA
    • TLAN (PCI or EISA)
    • CPMAC (AR7)
  • kernel source code 在 git://git.ti.com/ti-linux-kernel/ti-linux-kernel.git
參考來源
  1. http://processors.wiki.ti.com/index.php/Linux_Core_CPSW_User%27s_Guide

星期二, 9月 13, 2016

GPS

衛星導航 (satellite navigation 或 satnav) 系統
Global Navigation Satellite System (GNSS) 涵蓋全球的導航衛星系統

全球定位系統 (Global Positioning System,GPS) 原為美軍用來定位及導航,後來擴大給民間使用。因為 GPS 是最普遍的衛星定位系統,而變成通稱,還有其它系統,支援越多系統也就可以看到越多衛星。

衛星定位原理

GPS 衛星不斷往地面傳送衛星位置及時間等資訊,GPS 接收器收到後依據位置變化及訊號接收的時間差推算出跟衛星的距離。當只有一顆衛星時,只知道接收器位置是在一個球面。當有兩顆衛星時,接收器位置縮小為兩個球面相交的地方,也就是一個圓。當有三顆衛星時再縮小為兩點,其中只有一點是在地球表面,可決定出位置。實際上需要第四或更多的衛星來增進準確度,特別是高度。高樓、峽谷、密林、高壓電塔等也會干擾 GPS 信號,能看到越多的衛星也就越能增進可靠度。

衛星定位系統
  • GPS (美):21 顆運作衛星及 3 顆備份衛星在互成 30 度的 6 個軌道,在任何時間任何地點皆可同時觀測到 4 至 7 顆衛星,精確度 5M。
  • GLONASS (GLObal NAvigation Satellite System,俄):跟 GPS 類似,但每顆衛星信號頻率不同 (可防止整個系統同時被敵方干擾)、使用前蘇聯的地心座標系、莫斯科標準時間
  • BDS (中國北斗系統,發展中,計畫 2020 完成)
  • Galilen (歐,完成時間未定):24 顆運行衛星及 6 顆備份衛星組成,精確度 1M (public) 1cm (加密)
  • QZSS (Quasi-Zenith Satellite System,日本準天頂):3 顆只覆蓋東亞的輔助 GPS 衛星,增進信號的可用性、準確度和可靠度。
單靠衛星就可以完成定位,但加上其它輔助可加快定位時間、增加定位精準度。
  • A-GPS (Assisted GPS)
    • 透過網路 (線上或離線) 取得衛星位置 => 大幅減少首次定位時間
    • 由基地台計算位置 => 減低行動裝置所需計算能力
    • Wi-Fi ESSID 或基地台 Cell ID 透過網路查詢大約位置 => 加速定位時間
  • 全球衛星導航增強系統 (GNSS Augmentation System) 或 WADGPS (Wide Area Differential GPS):在地面增設固定位置的地面站,提供更精確的定位資料,讓計算出來的位置更精準。
  • 慣性導航:藉由陀螺儀、加速計、電子羅盤、氣壓計、計步器、單車轉速等資訊推算,尤其在收不到衛星或其它無線訊號時。
應用
  • 定位 (經緯度及海拔)
  • 移動軌跡:位置移動的連續定位結果。可即時或事後對應到地圖上使用。或者按照之前的儲存的路徑去行進,不需要地圖。
  • 測速:移動軌跡上每個定位點加上時間可算出速度
  • 導航:定位搭配地圖資料行進
參考來源
  1. 手機GPS登山推廣計畫
  2. 關於衛星導航系統的兩三事
  3. OpenStreetMap wiki:Accuracy of GPS data
  4. http://tech.shaolin.tw/posts/2013/07/13/wi-fi-positioning-system-spoofing-1/

星期日, 8月 28, 2016

git describe

用最近的 tag 及其間隔的送交數目來描述一個送交,格式是 <tag>-<間隔的送交數目>-g<短 HASH 碼>,後面可以選擇加是否 dirty。<短 HASH 碼> 前面的 g 代表 git,用來區別 SCM。
指令格式
git describe [--all] [--tags] [--contains] [--abbrev=<n>] [<commit-ish>...]
git describe [--all] [--tags] [--contains] [--abbrev=<n>] --dirty[=<mark>]

尋找最近的 tag,首先先看送交本身有沒有 tag,沒有則往上游找。annotated tag 比 lightweight tag 優先,新的比舊的優先。往上游找 tag 的過程中,可能會因合併的送交而有好幾個候選的 tag,最後以間隔的送交數目少的出線。

預設只找 annotated tag
--tags:也找 lightweight tag
--all:也找 refs/ 下的任何 ref,可能是已知的分支、遠端追蹤的分支、或 lightweight tag。
--contains:也找 lightweight tag,但找下游的 tag
--first-parent:只往第一上游找
--match <pattern>:只找符合 <pattern> 的 tag。(似乎 wildcard <pattern> 有些清況比對會有問題)
--exact-match:只看送交本身的 tag
--candidates=<n>:設定候選 tag 的數目,預設只考慮 10 個,設大於 10 執行會慢一些,但較精準,用 --debug 可看每個候選 tag 的結果。設為 0 相當於 --exact-match。
--debug:在 stderr 顯示對每個 tag 尋找的結果

--abbrev=<n>:設定短 HASH 碼的碼數,預設是 9。設為 0 則不加 HASH 碼。

--dirty[=<mark>]:只能用在 HEAD,增加描述 dirty 的清況,預設加 -dirty,可提供 dirty 時要加的描述,例如 M。較舊版本的 git 無此選項,可用 git status | grep 'Change.*:' 判斷。

--long:送交本身有 tag 時預設不顯示間隔的送交數目及短 HASH 碼,加 --long 參數總是顯示這些部份。
--always:當找不到任何 tag 時,顯示短 HASH 碼

參考來源:git help describe

git tag

git 的標籤 (tag) 有 annotated tag 及 lightweight tag 兩種,以有沒有註釋區別。後者沒有註釋、只是代表某個送交不好記憶的 HASH 碼,比較偏向私人或暫時使用。前者有註釋,比較偏向釋出版本用,除了註釋外,還包含日期、貼標籤者的資訊 (名子及 e-mail),可以選擇加上 GnuPG 簽名。

新增 tag

指令格式:git tag [-a | -s | -u <keyid>] [-f] [-m <msg> | -F <file>] <tagname> [<commit> | <object>]

沒加特別的參數則是新增名為 <tagname> 的 lightweight tag 到目前送交,可用 <commit> 或 <object> 指定 tag 是要加到哪個送交。

加參數 -a、-s、或 -u <keyid> 的話都是用來新增 annotated tag,這三者不同在於 -a 沒有簽名,-s 是用目前使用者的簽名,-u <keyid> 是用 <keyid> 的簽名。annotated tag 需要加訊息,會跳出編輯器輸入,或用 -m <msg> 透過指令行加訊息,或用 -F <file> 自檔案取得訊息。由於 annotated tag 才能加訊息,沒有 -a、-s、或 -u <keyid>,但有 -m <msg> 或 -F <file> 也是新增 annotated tag,隱含 -a 新增沒簽名的 annotated tag。

-f 或 --force 是強制取代已存在相同名子的 tag
--cleanup

列表

指令格式:git tag 或 git tag [-n[<num>]] -l [--contains <commit>] [--points-at <object>] [--column[=<options>] | --no-column] [--create-reflog] [--sort=<key>] [--format=<format>] [--[no-]merged [<commit>]] [<pattern>...]

(沒有 <tagname> 或含有參數 -l 或 --list)

-n[<num>]:加顯示 tag 的訊息,預設只顯示一行,可指定顯示幾行。
--contains <commit>:只顯示包含特定送交的 tag
--points-at <object>:只顯示特定送交的 tag
--column[=<options>]:column 顯示
--no-column
--create-reflog
--sort=<key>:排序
--format=<format>:顯示格式
--[no-]merged [<commit>]:只列特定送交可到達與否 (待深入了解)
<pattern>:只顯示樣式比對符合的

刪除

(含有參數-d 或 --delete)

簽名校驗

(含有參數 -v 或 --verify)

tag 修改

以修改 annotated tag 為例:
git tag <tagname> <tagname> -a -f
自動跳出編輯器修改之前的註釋
git show <tagname>
可看到除了原本的註釋,另外有多一筆註釋。如果要覆蓋原本的註釋則用
git tag <tagname> <tagname>^{} -a -f
送交修改的 tag
git push <tagname> -f

在別的 git clone 執行 git pull 並不會更新註釋內容,除非知道哪個 tag 有修改,移除它,再 pull
git tag -d <tagname>
git pull

參考及延伸閱讀

星期日, 7月 24, 2016

scanf()

輸入格式轉換,存到記憶體

#include <stdio.h>

int scanf(const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
int sscanf(const char *str, const char *format, ...);

#include <stdarg.h>

int vscanf(const char *format, va_list ap);
int vsscanf(const char *str, const char *format, va_list ap);
int vfscanf(FILE *stream, const char *format, va_list ap);

format 是一個字串,描述如何處理輸入字元。如果沒有輸入、或比對失敗,就停止,回傳轉換成功的次數。format 內容可以是:
  • 空白字元集,包括 space、tab、newline 等,比對 0 個以上的空白字元集。
  • % 開頭的轉換規範。
  • 其它一般字元
每個轉換規範以 '%' 或 %n$ 開始,後者指定用第幾個變數存。接著:
  • (optional) '*':依照轉換定義讀取,但不儲存,不計成功轉換次數。
  • (optional) 'm':用在字串轉換 (%s, %c, %[),自動配置足夠的記憶體放字串,之後需要 free()。
  • (optional) 十位數字說明最大 field width,不含字串結尾 0。
  • (optional) 改變存成的資料型態
    • h:存成 short int 或 unsigned short int
    • hh:存成 signed char 或 unsigned char
    • j:存成 intmax_t 或 uintmax_t
    • l:整數存成 long 或 unsigned long,浮點存成 double
    • ll:跟 L 一樣,用在 %c 或 %s 表示寬字元。
    • L:整數存成 long long,浮點存成 long double
    • t:存成 ptrdiff_t
    • z:存成 size_t
  • 轉換定義
    • %:比對 %
    • d:比對十進位整數,可以是有號,結果存到 int
    • i:比對對整數,可以是有號,可以是 0x 或 0X 開始的十六進位數字、0 開頭的八進位數字、不然則是十進位。結果存到 int。
    • o:比對無號八進位整數,結果存到 unsigned int。
    • u:比對無號十進位整數,結果存到 unsigned int。
    • x, X:比對無號十六進位整數,結果存到 unsigned int。
    • f, e, g, E, a:有號浮點數字,結果存到 float。
    • s:不含 white-space 的字串,存到字串。
    • c:數個字元,存到 char 陣列。
    • [字元集]:比對字元集存到字串。字元集不能是空的,不省略開頭的 white space。排除這些字元集的話,字元集以 ^ 開始。如果字元集要包含 ],可放在第一個字元。兩字元間可夾 - 表示範圍。例如 [^]0-9-] 表示任何字元不含 ]、0 到 9、-。
    • p:比對指標值存到 void 指標。
    • n:計數字元數目存到 int。可能不計成功的轉換次數。

問題:可以忽略開頭字元嗎?

參考:printf

SIP REGISTER

SIP 註冊 [RFC3261 §10]

SIP 用戶在其網域 (domain) 中有個帳號,稱為 address-of-record,簡單來說就是「user@domain」,但其對應的實際位址 (binding) 是可以變動的,可透過 SIP REGISTER 登記目前的位址。registrar 專指接受並回覆 SIP REGISTER 請求的 UAS,在其管理的網域維護對應表,讓其它用戶要建立通話時可透過 proxy server 或 redirect server 查詢。
                                              bob
                                            +----+
                                            | UA |
                                            |    |
                                            +----+
                                               |
                                               |3)INVITE
                                               |   carol@chicago.com
      chicago.com        +--------+            V
      +---------+ 2)Store|Location|4)Query +-----+
      |Registrar|=======>| Service|<=======|Proxy|sip.chicago.com
      +---------+        +--------+=======>+-----+
            A                      5)Resp      |
            |                                  |
            |                                  |
  1)REGISTER|                                  |
            |                                  |
         +----+                                |
         | UA |<-------------------------------+
cube2214a|    |                            6)INVITE
         +----+                    carol@cube2214a.chicago.com
          carol

SIP REGISTER 可進行的動作包括建立 (create)、新增 (add)、更新效期 (refresh)、詢問 (query)、移除 (delete)、及修改 (modify)。每個用戶可有多個位址,可能是多個 UAC 註冊的不同位址,或者是不同情況使用的位址。每個位址都有效期限,到期前需要更新效期才能持續使用。效期設為 0 將位址移除,之後可再新增來達到修改的目的。

header 欄位
  • Request-URI (必要):domain,例如 "sip:chicago.com",不能有 "userinfo" 及 "@"。
  • To (必要):要建立、詢問、或修改的 address-of-record,包含有 user name。
  • From (必要):負責註冊者的 address-of-record,通常跟 To: 一致,或者由第三方註冊。
  • Call-ID 及 CSeq (必要):對特定 registrar,UAC 每次開機後應該使用相同的 Call-ID,搭配 CSeq 每次請求加一,依此 registrar 可以偵測出沒按照順序到達的 REGISTER 請求。(反之,如果 Call-ID 不同便無法偵測順序是否正確)
  • Contact (may): 要登記連結的位址 (address bindings),可有多個,可以是 sip:、tel:、mailto: 等。可加 q 參數作為偏好使用。沒此項欄位時用來詢問。
  • Contact 各自的 expires 參數、或 Expires (may):到期秒數,註冊時可建議,但最終由 registar 決定。大於 232-1 (4294967295 秒或 136 年) 可視為 232-1,Malformed 值應該視為 3600。0 表示移除,此時 Contact 可用 * 移除所有位址連結。
  • Route (may)
  • Record-Route (有可能會有,但忽略):因為不會建立 dialog,所以沒效用。
  • Contact 的 action 參數:來自 RFC 2543,deprecated,不該使用。
registrar response:
  • 2xx 的 Contact 會列出所有的 binding。註冊成功的 UA 找出自己那一項,根據其 expires 參數或 Expires 欄位值計算並更新有效期限。
  • Date: 用來設定時間。
  • 423 (Interval Too Brief) 的 Min-Expires:可使用等於或大於 Min-Expires 的 expires 值重新嘗試註冊。
  • 501 Not Implemented:不支援單純詢問。
  • 不能產生 6xx,不能有 Record-Route。
動作ContactExpire
建立特定位址建議值
新增特定位址建議值
更新效期特定位址建議值
詢問不需要
移除特定位址,或 * 表全部。0
修改特定位址建議值
registrar 位址除了使用設定外,也可以用 domain 位址 DNS 取得,或 well-known "all SIP servers" 的 multicast 位址 "sip.mcast.net" (IPv4 是 224.0.1.75,IPv6 ?)。但使用 multicast 只是讓 registrar 知道位置,不會有回應 (為什麼?)。

參考

  • From TS 24.229:Unless either the user or the application within the UE has determined that a continued registration is not required the UE shall reregister an already registered public user identity either 600 seconds before the expiration time if the previous registration was for greater than 1200 seconds, or when half of the time has expired if the previous registration was for 1200 seconds or less, or when the UE intends to update its capabilities according to RFC 3840 [62] or when the UE needs to modify the ICSI values that the UE intends to use in a g.3gpp.icsi-ref media feature tag or IARI values that the UE intends to use in the g.3gpp.iari-ref media feature tag.
  • M. Schooler, "A multicast user directory service for synchronous rendezvous," Master's Thesis CS-TR-96-18, Department of Computer Science, California Institute of Technology, Pasadena, California, Aug. 1996.

星期二, 2月 23, 2016

手機螢幕擷取

Zenfone 2 螢幕擷取方式
  1. 同時按電源及音量小聲鍵
  2. 快速設定小工具可以選四種,其中一個可設為螢幕截圖
  3. ASUS 個人化設定可將長按最近使用的應用程式鍵設為螢幕截圖
參考來源:http://www.androidcentral.com/how-take-screenshot-asus-zenfone-2

星期日, 2月 14, 2016

GCC 使用 MIPS DSP ASE

MIPS DSP ASE

gcc 編譯選項
  • 加「-mdsp」(24KE, 34K) 或「-mdsp2」(74K, M14KE),不然會有「undefined reference to `__ssaddhq3'」之類的錯誤
  • 加「-mips32r2」可使用 INS 指令,存取 SIMD 變數的單元有較好的效能
  • M14KE 的 DSP instructions 可組譯成 microMIPS opcode (加「-mmicromips」)
C 定義
  • __mips_dsp 或 __mips_dsp_rev=1
  • __mips_dspr2 或 __mips_dsp_rev=2
  • __MIPSEL__
Data types 及變數初始化
  • typedef short q15;
    q15 a = 0.1234 * 32768.0;
  • typedef int q31;
    q31 b = 0.2468 * 2147483648.0;
  • typedef long long a64;
  • typedef signed char v4i8 __attribute__ ((vector_size(4)));
    v4i8 a = {1, 2, 3, 4};
    v4i8 b;
    b = (v4i8) {5, 6, 7, 8};
  • typedef short v2q15 __attribute__ ((vector_size(4)));
    v2q15 a = {0x0fcb, 0x3a75};
    v2q15 b;
    b = (v2q15) {0.1234 * 32768.0, 0.4567 * 32768.0};
  • endian 問題,詳見 MD00485 2.4 2.5
C 運算子
  • fractional data 的 +, - 跟 integer data 一樣 (addu, subu),但 * (乘法) 後需要位移來對齊小數點
  • SIMD 變數可以使用 +, -, *, /, unary minus, ^, |, &, ~ 作運算,但只有 +, - 有指令 (addu.qb, subu.qb, addq.ph, subq.ph),其它 GCC 則 synthesizes 一系列指令。
暫存器多三組 HI-LO (共四組) 及 DSPControl
DSP Control Register
  • 有 6 欄位:
    namebitsmask說明
    CCOND 27:2416condition code
    OUFLAG 23:168overflow/underflow。只能用 wrdsp 清掉
    16:HI-LO 0
    17:HI-LO 1
    18:HI-LO 2
    19:HI-LO 3
    20:
    21:
    22:
    23:
    EFI 1432extract fail indicator
    C134carry bit,用在 addsc, addwc
    SCOUNT 12:72size count
    POS5:01position bits
  • 專用來存取的指令:rddsp/wrdsp
  • SCOUNT 及 POS 視為全域變數,會改變它們的指令或函數不會優化掉,包括 wrdsp, extpdp, extpdpv、及 mthlip。
  • For correctness, programmers must assume that a function call clobbers all fields of the DSP control register. That is, programmers cannot depend on the values in CCOND, OUFLAG, EFI or C across a function-call boundary. They must re-initialize the values of CCOND, OUFLAG, EFI or C before using them.
比較:使用內建函數 (Intrinsic) 及組合語言巨集 (macro)
內建函數已對 pipeline 延遲做最佳化,而 macro 沒有,而造成 code scheduling 較差、及增加 stall。

C 內建函數 (Intrinsics)
  • Q31
    • q31 __builtin_mips_addq_s_w (q31, q31);
      q31 __builtin_mips_subq_s_w (q31, q31);
    • q31 __builtin_mips_absq_s_w (q31);
    • q31 __builtin_mips_shll_s_w (q31, imm0_31);
      q31 __builtin_mips_shll_s_w (q31, i32);
    • q31 __builtin_mips_shra_r_w (q31, imm0_31);
      q31 __builtin_mips_shra_r_w (q31, i32);
    • a64 __builtin_mips_dpaq_sa_l_w (a64, q31, q31); // Q63 + Q31 * Q31 => Q63
      a64 __builtin_mips_dpsq_sa_l_w (a64, q31, q31); // Q63 - Q31 * Q31
    • q31 __builtin_mips_mulq_rs_w (q31, q31); // DSPR2
    • q31 __builtin_mips_mulq_s_w (q31, q31); // DSPR2
    • q31 __builtin_mips_addqh_w (q31, q31); // DSPR2
      q31 __builtin_mips_addqh_r_w (q31, q31); // DSPR2
    • q31 __builtin_mips_subqh_w (q31, q31); // DSPR2
      q31 __builtin_mips_subqh_r_w (q31, q31); // DSPR2
  • Q15
    • v2q15 __builtin_mips_addq_ph (v2q15, v2q15);
      v2q15 __builtin_mips_addq_s_ph (v2q15, v2q15);
      v2q15 __builtin_mips_subq_ph (v2q15, v2q15);
      v2q15 __builtin_mips_subq_s_ph (v2q15, v2q15);
    • v2q15 __builtin_mips_absq_s_ph (v2q15);
    • v2q15 __builtin_mips_shll_ph (v2q15, imm0_15);
      v2q15 __builtin_mips_shll_ph (v2q15, i32);
      v2q15 __builtin_mips_shll_s_ph (v2q15, imm0_15);
      v2q15 __builtin_mips_shll_s_ph (v2q15, i32);
    • v2q15 __builtin_mips_shra_ph (v2q15, imm0_15);
      v2q15 __builtin_mips_shra_ph (v2q15, i32);
      v2q15 __builtin_mips_shra_r_ph (v2q15, imm0_15);
      v2q15 __builtin_mips_shra_r_ph (v2q15, i32);
    • v2q15 __builtin_mips_mulq_rs_ph (v2q15, v2q15); // Q15 * Q15 => Q15
    • a64 __builtin_mips_dpaq_s_w_ph (a64, v2q15, v2q15); // 累加兩個乘積
      a64 __builtin_mips_dpsq_s_w_ph (a64, v2q15, v2q15); // 累減兩個乘積
    • a64 __builtin_mips_mulsaq_s_w_ph (a64, v2q15, v2q15); // 累加第一個乘積,減第二個乘積,跟 endian 有關
    • a64 __builtin_mips_maq_s_w_phl (a64, v2q15, v2q15); // 只累加其中一個乘積
      a64 __builtin_mips_maq_s_w_phr (a64, v2q15, v2q15);
      a64 __builtin_mips_maq_sa_w_phl (a64, v2q15, v2q15);
      a64 __builtin_mips_maq_sa_w_phr (a64, v2q15, v2q15);
    • q31 __builtin_mips_muleq_s_w_phl (v2q15, v2q15); // Q15 * Q15 => Q31,只相乘一組
      q31 __builtin_mips_muleq_s_w_phr (v2q15, v2q15);
    • Replicate a Fixed Half-word into Elements
      v2q15 __builtin_mips_repl_ph (imm_n512_511);
      v2q15 __builtin_mips_repl_ph (i32);
    • void __builtin_mips_cmp_eq_ph (v2q15, v2q15);
      void __builtin_mips_cmp_lt_ph (v2q15, v2q15);
      void __builtin_mips_cmp_le_ph (v2q15, v2q15);
    • v2q15 __builtin_mips_pick_ph (v2q15, v2q15);
    • v2q15 __builtin_mips_packrl_ph (v2q15, v2q15);
    • v2q15 __builtin_mips_mulq_s_ph (v2q15, v2q15); // DSPR2
    • v2q15 __builtin_mips_addqh_ph (v2q15, v2q15); // DSPR2
      v2q15 __builtin_mips_addqh_r_ph (v2q15, v2q15); // DSPR2
    • v2q15 __builtin_mips_subqh_ph (v2q15, v2q15); // DSPR2
      v2q15 __builtin_mips_subqh_r_ph (v2q15, v2q15); // DSPR2
    • a64 __builtin_mips_dpaqx_s_w_ph (a64, v2q15, v2q15); // DSPR2
      a64 __builtin_mips_dpaqx_sa_w_ph (a64, v2q15, v2q15); // DSPR2
      a64 __builtin_mips_dpsqx_s_w_ph (a64, v2q15, v2q15); // DSPR2
      a64 __builtin_mips_dpsqx_sa_w_ph (a64, v2q15, v2q15); // DSPR2
  • 8-bit
    • v4i8 __builtin_mips_addu_qb (v4i8, v4i8);
      v4i8 __builtin_mips_addu_s_qb (v4i8, v4i8);
      v4i8 __builtin_mips_subu_qb (v4i8, v4i8);
      v4i8 __builtin_mips_subu_s_qb (v4i8, v4i8);
    • i32 __builtin_mips_raddu_w_qb (v4i8);
    • v4i8 __builtin_mips_shll_qb (v4i8, imm0_7);
      v4i8 __builtin_mips_shll_qb (v4i8, i32);
      v4i8 __builtin_mips_shrl_qb (v4i8, imm0_7);
      v4i8 __builtin_mips_shrl_qb (v4i8, i32);
    • a64 __builtin_mips_dpau_h_qbl (a64, v4i8, v4i8);
      a64 __builtin_mips_dpau_h_qbr (a64, v4i8, v4i8);
      a64 __builtin_mips_dpsu_h_qbl (a64, v4i8, v4i8);
      a64 __builtin_mips_dpsu_h_qbr (a64, v4i8, v4i8);
    • v4i8 __builtin_mips_repl_qb (imm0_255);
      v4i8 __builtin_mips_repl_qb (i32);
    • void __builtin_mips_cmpu_eq_qb (v4i8, v4i8);
      void __builtin_mips_cmpu_lt_qb (v4i8, v4i8);
      void __builtin_mips_cmpu_le_qb (v4i8, v4i8);
      i32 __builtin_mips_cmpgu_eq_qb (v4i8, v4i8);
      i32 __builtin_mips_cmpgu_lt_qb (v4i8, v4i8);
      i32 __builtin_mips_cmpgu_le_qb (v4i8, v4i8);
      i32 __builtin_mips_cmpgdu_eq_qb (v4i8, v4i8); // DSPR2
      i32 __builtin_mips_cmpgdu_lt_qb (v4i8, v4i8); // DSPR2
      i32 __builtin_mips_cmpgdu_le_qb (v4i8, v4i8); // DSPR2
    • v4i8 __builtin_mips_pick_qb (v4i8, v4i8);
    • v4i8 __builtin_mips_absq_s_qb (v4i8); // DSPR2
    • v4i8 __builtin_mips_adduh_qb (v4i8, v4i8); // DSPR2
      v4i8 __builtin_mips_adduh_r_qb (v4i8, v4i8); // DSPR2
    • v4i8 __builtin_mips_shra_qb (v4i8, imm0_7); // DSPR2
      v4i8 __builtin_mips_shra_r_qb (v4i8, imm0_7); // DSPR2
      v4i8 __builtin_mips_shra_qb (v4i8, i32); // DSPR2
      v4i8 __builtin_mips_shra_r_qb (v4i8, i32); // DSPR2
    • v4i8 __builtin_mips_subuh_qb (v4i8, v4i8); // DSPR2
      v4i8 __builtin_mips_subuh_r_qb (v4i8, v4i8); // DSPR2
  • a64
    • i32 __builtin_mips_extr_w (a64, imm0_31);
      i32 __builtin_mips_extr_w (a64, i32);
      i32 __builtin_mips_extr_r_w (a64, imm0_31);
      i32 __builtin_mips_extr_r_w (a64, i32);
      i32 __builtin_mips_extr_rs_w (a64, imm0_31);
      i32 __builtin_mips_extr_rs_w (a64, i32);
    • i32 __builtin_mips_extr_s_h (a64, imm0_31);
      i32 __builtin_mips_extr_s_h (a64, i32);
    • i32 __builtin_mips_extp (a64, imm0_31);
      i32 __builtin_mips_extp (a64, i32);
    • i32 __builtin_mips_extpdp (a64, imm0_31);
      i32 __builtin_mips_extpdp (a64, i32);
    • a64 __builtin_mips_shilo (a64, imm_n32_31);
      a64 __builtin_mips_shilo (a64, i32);
    • a64 __builtin_mips_mthlip (a64, i32);
  • Precision Reduce/Expand
    • v4i8 __builtin_mips_precrq_qb_ph (v2q15, v2q15);
    • v4i8 __builtin_mips_precrqu_s_qb_ph (v2q15, v2q15);
    • v2q15 __builtin_mips_precequ_ph_qbl (v4i8);
      v2q15 __builtin_mips_precequ_ph_qbr (v4i8);
      v2q15 __builtin_mips_precequ_ph_qbla (v4i8);
      v2q15 __builtin_mips_precequ_ph_qbra (v4i8);
    • v2q15 __builtin_mips_preceu_ph_qbl (v4i8);
      v2q15 __builtin_mips_preceu_ph_qbr (v4i8);
      v2q15 __builtin_mips_preceu_ph_qbla (v4i8);
      v2q15 __builtin_mips_preceu_ph_qbra (v4i8);
    • v4i8 __builtin_mips_precr_qb_ph (v2i16, v2i16); // DSPR2
    • v2q15 __builtin_mips_precrq_ph_w (q31, q31);
    • v2q15 __builtin_mips_precrq_rs_ph_w (q31, q31);
    • q31 __builtin_mips_preceq_w_phl (v2q15);
      q31 __builtin_mips_preceq_w_phr (v2q15);
  • Int8 * Q15 => Q15
    • v2q15 __builtin_mips_muleu_s_ph_qbl (v4i8, v2q15);
      v2q15 __builtin_mips_muleu_s_ph_qbr (v4i8, v2q15);
  • Add and Set Carry/Add with Carry
    i32 __builtin_mips_addsc (i32, i32);
    i32 __builtin_mips_addwc (i32, i32);
  • Modular Subtraction on an Index Value
    i32 __builtin_mips_modsub (i32, i32);
  • Bit Reverse a Half-word
    i32 __builtin_mips_bitrev (i32);
  • Insert Bit Field Variable
    i32 __builtin_mips_insv (i32, i32);
  • Load Unsigned Byte/Halfword/Word Indexed
    i32 __builtin_mips_lbux (void *, i32);
    i32 __builtin_mips_lhx (void *, i32);
    i32 __builtin_mips_lwx (void *, i32);
  • Signed Multiply and Add
    a64 __builtin_mips_madd (a64, i32, i32);
  • Unsigned Mulitply and Add
    a64 __builtin_mips_maddu (a64, ui32, ui32);
  • Signed Multiply and Subtract
    a64 __builtin_mips_msub (a64, i32, i32);
  • Unsigned Multiply and Subtract
    a64 __builtin_mips_msubu (a64, ui32, ui32);
  • Signed Multiply
    a64 __builtin_mips_mult (i32, i32);
  • Unsigned Multiply
    a64 __builtin_mips_multu (ui32, ui32);
  • Left Shift and Append Bits (DSPR2)
    i32 __builtin_mips_append (i32, i32, imm0_31); // DSPR2
  • Byte Align Contents from Two Registers (DSPR2)
    i32 __builtin_mips_balign (i32, i32, imm0_3); // DSPR2
  • Right Shift and Prepend Bits (DSPR2)
    i32 __builtin_mips_prepend (i32, i32, imm0_31); // DSPR2
  • 3.9, 3.10
其它方式:
  • 全組合語言,或夾雜在 C 裡面
  • 使用 Fixed-point data types (_Frac) 搭配 C 運算子
參考資料:
  1. MD00485 -- 主要參考來源
  2. MD00086 The MIPS32® Instruction Set
  3. MD00374 The MIPS® DSP Application-Specific Extension to the MIPS32® Architecture
  4. GCC: Using Vector Instructions through Built-in Functions
相關文章:
  1. GCC Inline Assembly

星期四, 2月 04, 2016

Linux 書

Linux Kernel
參考來源
  1. Rex 的 Linux 系統軟體開發書籍推薦與 TLPI
延伸閱讀

malloc(), calloc(), realloc() 和 alloca()

可以從兩個所在動態取得記憶體,一般 malloc() 是從 heap,另一款是從 stack。

從 stack 動態配置記憶體,函數結束自動釋出。只是調整 stack 指標,效率足好。

#include <alloca.h>

void *alloca(size_t size);
  • 可簡化 longjmp() 或 siglongjmp() 的記憶體釋放,不鼓勵用在其它地方 (為什麼???)
  • 不能直接用在函數參數內,配置的記憶體夾在函數參數間可能會有問題。
  • stack overflow 時不會傳回 NULL,SIGSEGV

從 heap 動態配置記憶體

#include <stdlib.h>

// 取得 size 大小位元組、未初始化的記憶體空間。
void *malloc(size_t size);

// 從 heap 動態配置的記憶體,都需要用 free() 歸還,或者在程式結束時自動消失。
// 重複釋出可能發生不可預期的結果ptr 可以是 NULL,不進行任何動作。
void free(void *ptr);

// 基於 malloc(),取得 nmemb * size 大小的記憶體空間,並清為 0。
void *calloc(size_t nmemb, size_t size);


// 記憶體空間重新配置為 size 大小,重複部份會相同。
// 加大配置的空間時,位置可能變或不變。位置改變時會複製重複的部份,效能會較差。
void *realloc(void *ptr, size_t size);

其它使用 malloc() 的函式:strdup() 等。

malloc() 細節

heap 一般放在 Uninitialize data (bss) 後面生向高位址,另一端是 stack 生向 heap。

典型 x86-32 Linux layout

Kernel
0xC000 0000
argv, environment

Stack
Top of stack →

(unallocated memory)

Program break →
Heap

Uninitialized data (bss)

Initialized data

Text (program code)
0x0804 8000

0x0000 0000

heap 跟 stack 中間是實際沒用到的記憶體。heap 的盡頭就是 program break,不夠用時會用 sbrk() 調整 program break 來加大 heap,但通常不會縮減 heap。sbrk(0) 傳回目前 program break 位置。

藏在每一個 malloc() 的記憶體前面,會紀錄這段記憶體的大小。當 free() 時,利用記憶體空間形成 doubly link list 歸還回到 free 列表,並嘗試合併相鄰的記憶體區塊。

配置的記憶體區塊 (前置區塊大小)
size可使用的部份

已釋出可使用的列表 (利用可使用的部份存放 link list 指標)
sizeprevnext剩下可使用的部份

每次 malloc() 會先從 free 列表取得記憶體,例如用 first-fit 或 best-fit 等演算法,如取不到則嘗試加大 heap。

當配置的記憶體區塊大於 MMAP_THRESHOLD,glibc 改用系統呼叫 mmap() 配置,在 Linux 4.7 之後會受到 RLIMIT_DATA 限制。MMAP_THRESHOLD 預設 128 kB,可透過 mallopt() 調整。

在 multithread 應用,內部使用 mutex 保護相關資料結構,glibc 並建立額外的 memory allocation arenas。每個 arena 是內部用 brk() 或 mmap() 配置的大記憶體空間。

每個 process 有自己的虛擬記憶體,虛擬記憶體中實際有使用的區塊才會對應到實體記憶體。malloc() 不保證可以取得實體記憶體,萬一沒有實體記憶體體了,有些 process 會被 OOM killer 結束掉 (見 proc 檔案系統 /proc/sys/vm/overcommit_memory 和 /proc/sys/vm/oom_adj 的說明,以及 Linux kernel 的 Documentation/vm/overcommit-accounting)。

malloc() 除錯

mtrace()、muntrace()
mcheck()、mprobe()
malloc() 除錯函式庫:Electric Fence (http://www.perens.com/FreeSoftware/)、dmalloc (http://dmalloc.com/)、Valgrind (http://valgrind.org/)、Insure++ (http://www.parasoft.com/)。
mallopt()、mallinfo()

參考

  1. TLPI §7
  2. man alloca 
  3. malloc() man-page
  • asprintf()
  • mmap()
  • memalign()、posix_memalign()
  • malloc_trim()

Linux CPU 排程

Linux 程式執行以 thread 為單位,決定誰取得 CPU 使用權稱排程。Thread 在 userspace 是 preemptible 的 (非 cooperative multitasking),任何時間點 kernel tick 都有可能會中斷程式並切換到其它 thread,一個無限迴圈並不會卡住整個系統。至於透過 syscall 進入 kernel 的階段,是否 preemptible 由 kernel 設定 CONFIG_PREEMPT 決定。在 non-preemptive kernel,無限迴圈是會卡住整個系統。

註:preempty 是一種插隊的行為,像救護車,可翻作...。

由於 thread 是 preemptive 的,同一 process 內不同 thread 共用的資料,可能修改到一半有其它 thread 存取而造成錯誤 (修改被覆蓋、資料結構破壞等),所以需要 mutex 保護。函式可能重複呼叫,要看是否可以 reentry

每個 thread 有各自的 policy 及 priority 來決定排程,都會 preemptive 執行 priority 值最大的,相同 priority 的再由 policy 安排如何執行。thread 建立時會繼承 policy 及 priority。

等級policypriority說明
一般SCHED_OTHER
(預設)
0參考 nice 值動態調整 CPU 時間的使用比例,讓每個 thread 輪流、不用等候太久都能分配到 CPU 時間,滿足互動式多工系統。
SCHED_BATCH2.6.16+。類似 SCHED_OTHER,但排程會減少喚醒次數來減少 thread 切換,一般用在非互動式的程式。
SCHED_IDLE2.6.23+。以最低優先權執行。
(soft) real timeSCHED_FIFO1~99一開始先插隊執行,之後次序照先後排隊。每次執行直到等待 IO 或讓出。
SCHED_RR同 SCHED_FIFO,但每次執行有 time slice 時間限制。
SCHED_DEADLINELinux 3.14+

nice 值 (在 POSIX 是 process 層級的屬性,但目前 Linux/NPTL 實作是 thread 層級的屬性。)

  • 範圍 -20 ~ 19,預設 0,值越大越「好心」,排程分配的份量越少。對應到 kernel 內部表示的範圍是 40 ~ 1,相當於 20 - nice 值。不同 kernel 版本排程演算法有所不同。
  • 可以提高自己的 nice 值,只有 privileged thread 才能降低或設為負值 (chap35.3.2)。自從 Linux 2.6.12,process 有適當的 RLIMIT_NICE 軟性限制 (見 getrlimit()) 可以降低 nice 值。
  • round-robin timing-sharing 的 CPU 時間分配,滿足互動式多工系統需要的 Fairness (公平) 和 Responsive (不用等太久),按順序都會分配到 (不會餓死) time slice 或 quantum 的時間,除非自願放棄 (休息或等候) 才會縮短。
  • 會繼承
  • Linux 2.6.38 新增 "autogroup" 功能代表 nice 值在許多 circumstances 不再有其傳統效果。
  • getpriority(which, who):取得 which 中 who 裡 nice 值最小的。
    • which 可以是 PRIO_PROCESS (指 thread)、PRIO_PGRP、或 PRIO_USER,決定 who 是 process ID、process group ID、或 user ID。who 為 0 表示本身所屬 process、process group、或 user。
    • 由於 -1 可能是有效的值或錯誤,需先設 errno 為 0,如果回傳值是 -1 時,需檢查 errno 判別。
  • setpriority(which, who, value):
    • 有 CAP_SYS_NICE 權限可設其它 thread nice 值
    • 沒權限只能增加符合 real 或 effective user ID 的 thread。Kernel v2.6.12+ 的 RLIMI_NICE 限定可設定的範圍。
  • nice(incr)
  • 指令 nice
  • 指令 renice
POSIX realtime scheduling API 決定排程 policy 和 priority => 更緊密控制 CPU 時間
CPU affinity mask => 在多處理器系統決定可使用哪些處理器。
註:sched_get_priority_min(policy) 及 sched_get_priority_max(policy) 取得特定 policy 的 priority 範圍。
註:sched_setscheduler() 設定 pid 或自己的 policy 及 priority,而sched_setparam() 只設定 priority。sched_getscheduler()、sched_getparam() 分別取得 policy 和 prioity。在 2.6.12 以前, CAP_SYS_NICE 的 process 才能設定 policy 和 priority。另外,SCHED_OTHER process 的 real/effective user ID 和我的effective user ID 相同的,也可以設定。2.6.12 之後新增 RLIMIT_RTPRIO...。
s
避免 realtime process locking up 整個系統
  • 用 setrlimit() 設定適合的 low soft CPU time resource limit (RLIMIT_CPU, described in Section 36.3),如果 consumes too much CPU time 會送 SIGXCPU signal,預設 kill the process。
  • 用 alarm() 設定 alarm timer,如果執行超過時間會 killed by a SIGALRM signal。
  • 建立 watchdog process 執行在較高 realtime priority,無限迴圈 sleep 一段時間檢查其它 process 狀態,可順便量測 CPU time (Section 23.5.3 的 clock_getcpuclockid()) 和檢查 policy 和 priority,可降低 priority 或送 signal 停止會結束它。
  • 2.6.25 開始提供 RLIMIT_RTTIME 限制一次持續 CPU time 用量,送 signal SIGXCPU。細節見 Documentation/ scheduler/sched-rt-group.txt。
SCHED_RESET_ON_FORK
sched_yield()
註:sched_rr_get_interval() 取得 SCHED_RR 每次執行時間。
註:2.6.25+ /proc/sys/kernel/sched_rt_period_us/proc/sys/kernel/sched_rt_runtime_u

參考來源:
  1. man sched
  2. :《The Linux Programming Interface》chap. 35
  3. http://fcamel-life.blogspot.tw/2012/02/linux-process-priorities-and-scheduling.html (整理得不錯)
  4. http://stackoverflow.com/questions/10287561/sched-fifo-thread-is-preempted-by-sched-other-thread-in-linux
  5. man setpriority 
20200713 最後更新

星期日, 1月 31, 2016

LAPD

ISDN 的 datalink 層是 Q.921,也就是 LAPD (Link Access Procedure on the D-channel),是 HDLC 的 close cousin。

在 frame 之間及閒置時送 Flag (0x7E, 01111110b),而原本 0x7E 的資料為避免和 Flag 混淆,使用了 bit stuffing 機制,也就是資料在傳送端會每遇到 5 個連續 1 會插入一個 0,接收端再移除。如果出現連續 7 個以上的 1,則視為 abort 而忽略收到的資料。

LAPD 格式
AddressControlInformationFCS
21~20~2

LAPD 運作在 Asynchronous Balanced Mode (ABM),也就是兩端是對等的、沒有主從之分,雙向各自獨立運作。2-byte FCS 檢查資料有沒有錯誤,通常用硬體計算,以下說明省略。重送時,每個 octet 的 bit 1 先送。

Address:2-byte
87654321octet
SAPIC/REA
0
1
TEIEA
1
2
  • EA:Address field extension bit,0 表示有下個 byte、1 則沒有。由於固定 2-byte,所以第一個 EA 為 0,第二個 EA 為 1。
  • C/R:0 表示用戶端是發出的指令及網路端的回覆,1 則表示網路端發出的指令及用戶端的回覆。
  • SAPI:Service Access Point Identifier
    • 0:上層是 Q.931 呼叫控制 (GR303 TMC call proc)
    • 1:I.451 封包模式的呼叫控制 (GR303 EOC, TMC switching)
    • 12:teleaction
    • 16:X.25 level 3 封包
    • 63:自己本身 Layer 2 管理
  • TEI:Terminal End Indentifier,在 SAPI = 0 時
    • 0~63:用於非自動指定 TEI 的設備,PRI 使用 0
    • 64~126:用於自動指定 TEI 的設備
    • 127:廣播給所有 Terminal Endpoints
PRI 和點對點 BRI 使用 SAPI 0 TEI 0,點對多點 BRI 使用 SAPI 63 TEI 127。

Control 欄位包括 Q.921 的 frame type、序號等。
Control87654321octet
I FrameN(S)01Information Frame:連線狀態正常及序號正確後往上層丟
N(R)P2

S Frame0000SS011Supervisory Frame:datalink 本身 supervisory 用,看 SS 2-bit
N(R)P/F2

U FrameMMMP/FMM111Unnumbered Frame:Unnumbered 就是沒序號,看 MMM 及 MM 共 5-bit

P/F 在 command 是 poll,在 response 是 final。

IN(S)0I-Frame,有 Information 欄位
S00000001RR (Receive Ready):I Frame 的 acknowledgement,可以再收。
00000101RNR:Indicates a state of temporary occupation of station (e.g., window full)
00001001REJ:重傳給定的序號之後
U000x0011UI (Unnumbered Information),有 Information 欄位 => Q.931。P/F = 0 [Q.921 5.1.1]
010P0011DISC (Disconnect command)
011F0011UA (Unnumbered Acknowledgement response)
100Fx0111FRMR (Framer reject response)
000F1111DM (Disconnected Mode response)
101P/F1111XID (eXchange IDentification):不支援?
011P1111SABME (Set Asynchronous Balanced Mode Extended):command。在連線初始化時決定 window 大小,最大是 128,也就是可以有 128 個 frame 未完成 ACK。由 Address 的 C/R 可看出遠端是 Network 端還是 User 端


window size:modulo 8 待 acknowledge 的 outstanding frames
extended window size:modulo 128,使用不同的 link initialization frame type,frame type 名稱再加上 E,例如 SABM 變成 SABME。

範例:02 01 7f
  • 02 01 (Address):C/R = 1 = network command 或 user response,SAPI = 0 = Q.931,TEI = 0 = PRI or PTP
  • 7F (Control):U frame SABME,P/F = 1
範例:02 01 01 03:RR for Q.931

範例:FC FF 03 0F 5D 72 01 FF F7 6E:TEI Request
  • FC FF (Address):C/R = 0 = user command 或 network response,SAPI = 63 = Layer 2 Management,TEI = 127 = Broadcast connection for all TEs
  • 03 (Control):UI,P/F = 0
  • 0F (Management entity identifier):固定為 0x0F。
  • 5D 72 (Ri):Request number,一個亂數
  • 01 (message type = REQUEST):請求 64 ~ 126 的 TEI,成功的話回覆 2 = ASSIGNED,失敗的話回覆 3 = DENIED。另外還有 4 = CHECK_REQUEST、5 = CHECK_RESPONSE、6 = REMOVE、7 = VERIFY。
  • FF (Ai 及 E-bit):bit 1 為 E-bit,Ai 欄位的 externsion。剩下 7-bit 為 Ai = Action Indicator = 127 = 任何 TEI。
  • F7 6E (FCS)

沒其他訊息時,每 10 秒送 RR 等回應。沒回應,每秒重送最多共四次,之後改送 SABME,也是每秒重送,直到收到 UA。

MDL-ERROR() 錯誤表

Error CodeError ConditionActionError Type
ASupervisory (F=1)Error LogReceipt of unsolicited response
BDM (F=1)Error LogReceipt of unsolicited response
CUA (F=1)TEI removal procedure or 
TEI check procedure, then if TEI:

free: remove TEI
single: no action
multiple: TEI removal procedure

Receipt of unsolicited response
DUA (F=0)TEI removal procedure or 
TEI check procedure, then if TEI:

free: remove TEI
single: no action
multiple: TEI removal procedure

Receipt of unsolicited response
EDM (F=0)Error LogReceipt of unsolicited response
FSABMEError LogPeer initiated re-establish.
GSABMETEI check procedure, then if TEI:

free: remove TEI
single: no action
multiple: TEI removal procedure

Unsuccessful retransmission (N200 times)
HDISCTEI check procedure, then if TEI:

free: remove TEI
single: no action
multiple: TEI removal procedure

Unsuccessful retransmission (N200 times)
IStatus EnquiryError LogUnsuccessful retransmission (N200 times)
JN(R) errorError LogOther
KReceipt of FRMRError LogOther
LReceipt of frame with undefined control fieldError LogOther
MReceipt of I field not permittedError LogOther
NReceipt of frame with wrong sizeError LogOther
ON201 errorError LogOther

參考

  1. Q.921 ISDN user-network interface – Data link layer specification
  2. http://www.freesoft.org/CIE/Topics/125.htm
  • ISDN Q.921-User Adaptation (IUA):透過 IP 傳送 ISDN Q.921 訊息

台灣電信網路編碼計畫

電信網路編碼計畫 (Numbering Plan)

0[01][1-9].國際冠碼 + 國碼 + 區域號碼 + 客戶電話號碼
0[1-8]0X.智慧虛擬碼撥接服務
0[2-8][2-9]XXXXXXX.長途電話
09[0-8]XXXXXXX行動通訊服務
1[0-7]X服務電話
18XXX.撥號選接服務網路識別碼
19XX非營利服務電話
[2-9]X.市話服務 (局碼 + )
X 代表 0 ~ 9

參考來源:
  1. 電信網路編碼計畫
  2. https://en.wikipedia.org/wiki/Telephone_numbers_in_Taiwan
  3. 中華民國長途電話區號表

Q.931 訊息格式

Q.931 格式的基本欄位包括 Protocol Discriminator、Call Reference、及 Message Type,之後的欄位依據 Message Type 的需要而加,稱為 Information Element (IE)。

87654321Octet
Protocol Discriminator1
Call Reference2~
0Message Type
Information Elements as required

Protocol Discriminator 辨別是什麼協定,Q.931 用的值是 0x08,不過還有其它協定:
  • 0x08:Q.931
  • 0x4F:GR303
  • 0x03 或 0x43:維護用
Call Reference 是用在 user-network 界面的通話參考編號,用戶 (user) 端和網路 (network) 端各自獨立編號,由通話建立端決定。

87654321Octet
0000 Call Reference Length1
Flag
2
Call Referenceetc.
  • Call Reference Length:Call Reference 的長度,可能 0 ~ 3
  • Flag:此 call 建立端設為 0,受話端使用時設為 1

Message Type
  • 0000000
  • 00-----:建立通話
    • 0x01 ALERTING
    • 0x02 CALL PROCEEDING
    • 0x07 CONNECT
    • 0x0F CONNECT ACKNOWLEDGE
    • 0x03 PROGRESS
    • 0x05 SETUP:建立通話
    • 0x0D SETUP ACKNOWLEDGE
  • 01-----:通話中
    • 0x26 RESUME
    • 0x2E RESUME ACKNOWLEDGE
    • 0x22 RESUME REJECT
    • 0x25 SUSPEND
    • 0x2D SUSPEND ACKNOWLEDGE
    • 0x21 SUSPEND REJECT
    • 0x20 USER INFORMATION
  • 10-----:掛斷通話
    • 0x45 DISCONNECT
    • 0x4E RELEASE
    • 0x5A RELEASE COMPLETE
    • 0x46 RESTART
    • 0x4E RESTART ACKNOWLEDGE
  • 11-----:其它
    • 0x60 SEGMENT
    • 0x79 CONGESTION CONTROL
    • 0x7B INFORMATION:提供額外資訊,如 overlap sending。
    • 0x6E NOTIFY
    • 0x7D STATUS
    • 0x75 STATUS ENQUIRY
Information Element (IE) 都會有 IE identifier 辨別哪種 IE,有三種格式,前兩種為單一 byte,bit 8 為 1。第三種可變長度,有長度欄位決定內容長度。
type87654321Octet
a1Information element identifierContents of Information element1

b1Information element identifier1

c0Information element identifier1
Length of contents of information element2
Contents of information element3~

IE identifier

10100001Sending complete
0000
1000Cause
00011000Channel Identification:可重複
01110000Called party number
參考
  1. Q.931
  2. LAPD
  3. Q.931 over IP
  4. Q-Interface Signaling (QSIG)
    • 同樣基於 Q.921/Q.931 的一種 D-channel voice signaling 變形,作為 PBX 間溝通用的標準協定,用來建立通話和管理 PBX 間的 QSIG supplementary service,如 Multiple Subscriber Number、Call Waiting、Calling-Line Identification Presentation (CLIP)、Calling-Line Identification Restriction (CLIR)、Connected-Line Identification Presentation (COLP)、Connected-Line Identification Restriction (COLR)、Malicious Call Identification、Call Hold、Advice of Charge、Three-Way Conference、Call Diversion、CFU Supplementary Service、Path Replacement (ANF-PR)、Call Transfer by Join (SS-CT)、Call Completion to Busy Subscriber (CCBS)、和 Explicit Call Transfer。
    • 呼叫來自 private integrated services network exchange (PINX) 再繞到其它 PINX 設備。
    • Tunneling over H.323:H.323 基於 Q.931,旗下包含基本的 H.225.0 和 H.245,和 supplementary services H.450.1。H.323 Annex-M1 有規範 Tunneling QSIG over H.323,但 Cisco 使用 ISDN Generic Transparency Descriptor (GTD) 在對應的 H.225 訊息不變地傳送 QSIG 訊息。沒對應的,則 tunneled 在 H.225.0 FACILITY 訊息。
    • Tunneling over SIP:在 SIP 指示「Content-Type: application/QSIG」、「Content-Disposition: signal; handling=optional」放在 MIME 信體。非 QSIG 的 Q.931 訊息用「Content-Type: application/x-q931」。
    • https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/voice/cube_sip/configuration/15-mt/cube-sip-15-mt-book/voi-sip-trans-tun.pdf
    • https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/voice/sip/configuration/15-mt/sip-config-15-mt-book/voi-sip-tdm.pdf
  • Calling-Line Identification Presentation (CLIP):來電時提供主叫號碼給被叫。
  • Calling-Line Identification Restriction (CLIR):主叫限制提供主叫號碼給被叫。Calling-Line Identification Restriction Ignore:忽略主叫限制提供主叫號碼給被叫,例如撥緊急電話,即使主叫限制提供主叫號碼還是會提供。
  • Connected-Line Identification Presentation (COLP):接通時提供真正的被叫號碼給主叫。
  • Connected-Line Identification Restriction (COLR):被叫限制接通時提供真正的被叫號碼給主叫。
  • http://shannon.cm.nctu.edu.tw/netexp/isdn03.pdf 整體數位服務網路簡介