3. 物理プロトコル

Takami Torao #Garmin #GPS
  • このエントリーをはてなブックマークに追加

3.1 Serial Protocol

The Serial Protocol is based on RS-232. The voltage characteristics are compatible with most hosts; however, the device transmits positive voltages only, whereas the RS-232 standard requires both positive and negative voltages. Also, the voltage swing between mark and space may not be large enough to meet the strict requirements of the RS-232 standard. Still, the device voltage characteristics are compatible with most hosts as long as the interface cable is wired correctly.

The other electrical characteristics are full duplex, serial data, 9600 baud, 8 data bits, no parity bits, and 1 stop bit.

The mechanical characteristics vary among devices; most devices have custom-designed interface connectors in order to meet Garmin packaging requirements. The electrical and mechanical connections to standard DB-9 or DB-25 connectors can be accomplished with special cables that are available from Garmin.

3.1.1 Serial Packet Format

All data is transferred in byte-oriented packets. A packet contains a three-byte header (DLE, ID, and Size), followed by a variable number of data bytes, followed by a three-byte trailer (Checksum, DLE, and ETX). The following table shows the format of a packet:

Table 2 – Serial Packet Format
Byte Number Byte Description Notes
0 Data Link Escape ASCII DLE character (16 decimal)
1 Packet ID identifies the type of packet
2 Size of Packet Data number of bytes of packet data (bytes 3 to n-4)
3 to n-4 Packet Data 0 to 255 bytes
n-3 Checksum 2's complement of the sum of all bytes from byte 1 to byte n-4
n-2 Data Link Escape ASCII DLE character (16 decimal)
n-1 End of Text ASCII ETX character (3 decimal)

3.1.2 DLE Stuffing

If any byte in the Size, Packet Data, or Checksum fields is equal to DLE, then a second DLE is inserted immediately following the byte. This extra DLE is not included in the size or checksum calculation. This procedure allows the DLE character to be used to delimit the boundaries of a packet.

3.1.3 ACK/NAK Handshaking

Unless otherwise noted in this document, a device that receives a data packet must send an ACK or NAK packet to the transmitting device to indicate whether or not the data packet was successfully received. Normally, the transmitting device does not send any additional packets until an ACK or NAK is received (this is sometimes referred to as a “stop and wait” protocol).

The ACK packet has a Packet ID equal to 6 decimal (the ASCII ACK character), while the NAK packet has a Packet ID equal to 21 decimal (the ASCII NAK character). Both ACK and NAK packets contain an 8-bit integer in their packet data to indicate the Packet ID of the acknowledged packet. Note: some devices will report a Packet Data Size of two bytes for ACK and NAK packets; however, only the first byte should be considered. Note: Some devices may work sporadically if only one byte ACK/NAK packets are sent. The host should send two byte ACK/NAK packets to ensure consistency.

If an ACK packet is received, the data packet was received correctly and communication may continue. If a NAK packet is received, the data packet was not received correctly and should be sent again. NAKs are used only to indicate errors in the communications link, not errors in any higher-layer protocol. For example, consider the following higherlayer protocol error: a Pid_Wpt_Data packet was expected by the device, but a valid Pid_Xfer_Cmplt packet was received instead. This higher-layer protocol error does not cause the device to generate a NAK.

Some devices may send NAK packets during communication timeout conditions. For example, when the device is waiting for a packet in the middle of a protocol sequence, it will periodically send NAK packets (typically every 2-5 seconds) if no data is received from the host. The purpose of this NAK Packet is to guard against a deadlock condition in which the host is waiting for an ACK or NAK in response to a data packet that was never received by the device (perhaps due to cable disconnection during the middle of a protocol sequence). Not all devices provide NAKs during timeout conditions, so the host should not rely on this behavior. It is recommended that the host implement its own timeout and retransmission strategy to guard against deadlock. For example, if the host does not receive an ACK within a reasonable amount of time, it could warn the user and give the option of aborting or re-initiating the transfer.

3.1.4 Serial Protocol Packet IDs

The Serial Protocol Packet ID values are defined using the enumerations shown below:

enum
{
    Pid_Ack_Byte = 6,
    Pid_Nak_Byte = 21
};

Additional Packet IDs are defined by other Link protocols (see below); however, the values of ASCII DLE (16 decimal) and ASCII ETX (3 decimal) are reserved and will never be used as Packet IDs in any Link protocol. This allows more efficient detection of packet boundaries in the link-layer software implementation.

3.2 USB プロトコル

このプロトコルは USB 上でのリンク及びアプリケーション層プロトコルを使用するための機構を提供します。

3.2.1 USB プロトコルの詳細

Microsoft Windows アプリケーション開発者は USB プロトコルを使用するにあたってこの章での概念を熟知する必要はありません。

ホストは常にバルク OUT パイプを使用してデバイスへ転送を行います。

デバイスは割り込み IN パイプまたはバルク IN パイプのどちらかを選択してホストへ転送することが出来ます。デバイスは特定のパイプでアプリケーションプロトコルを開始したら同じパイプ上でプロトコルを完了します。いくつかのデバイスは割り込み IN パイプのみでホストへデータを転送するかもしれません。

ホストはデータに対して絶えず割り込みパイプをチェックしなければいけません。ホストはデバイスからのデータ有効パケットを受信した時のみバルクパイプを読み込みます (下記 3.2.3.2章参照)。ホストはバルクパイプの読み込みを開始したら長さ 0 の転送を受信するまでパケットを読み込み続けるべきです (例: Garmin でないパケットに対する USB 転送への対処)。

3.2.2 USB パケットフォーマット

このプロトコルを使用した全てのパケット転送は以下のフォーマットをとります:

Table 3 – USB Packet Format
バイト数 バイト説明 補足
0 パケット型 USB プロトコル層 = 0, アプリケーション層 = 20
1-3 予約 0 に設定されなければならない
4-5 パケット ID
6-7 予約 0 に設定されなければならない
8-11 データサイズ
12+ データ

3.2.3 USB プロトコル層パケット ID

USB プロトコルパケット ID の値は以下の列挙で定義されます:

enum
{
    Pid_Data_Available = 2,
    Pid_Start_Session = 5,
    Pid_Session_Started = 6
};

3.2.3.1 データ有効パケット

データ有効パケット (Data Available Packet) はホストからのデータ読み込みが可能になった事を表します。ホストは無データ転送 (長さ0) を受け取るまでデータを読み込むべきです。このパケットに結び付けられたデータはありません。

Table 4 – Data Available Packet
N 方向 パケット ID パケットデータ型
0 デバイス → ホスト Pid_Data_Available n/a

3.2.3.2 セッション開始要求パケット

セッション開始要求パケット (Start Session Packet) は USB 上でパケットの転送を開始するためにホストによって送信されなければならない。またこれは USB 上で連続的に送られるパケットを意図的に停止し、再開する時には必ず送られなければならない。このパケットに結び付けられたデータはありません。

Table 5 – Start Session Packet
N 方向 パケット ID パケットデータ型
0 ホスト → デバイス Pid_Start_Session n/a

3.2.3.3 セッション開始完了パケット

セッション開始完了パケット (Session Started Packet) はデバイスに対する転送の送受信が行える事を示します。ホストはこのパケットを受信する前に受け取った全てのパケットを無視すべきです。このデータに付随するデータはデバイスのユニット ID です。

Table 6 – Session Started Packet
N 方向 パケット ID パケットデータ型
0 デバイス → ホスト Pid_Session_Started uint32

3.2.4 Garmin USB ドライバ (Microsoft Windows)

この章では Microsoft Windows OS 上での Garmin 純正 USB ドライバの使用に関連した情報を提供します。このドライバは Windows 98, Me, 2000, XP 互換です。Windows Platform SDK と Driver Development Kit に対するプログラミングに熟知している読者を対象とします。

アプリケーションは Win32 WriteFile 関数を使用してデバイスへパケットを送信します。もしパケットサイズが正確に USB パケットサイズの倍数であれば WriteFile への更なる呼び出しはデータを渡さないようにすべきです (If the packet size is an exact multiple of the USB packet size, an additional call to WriteFile should be made passing in no data)。

アプリケーションは絶えず Win32 DeviceIoControl 関数を呼び出す事でデバイスからの非同期パケットを受信します。アプリケーションがデータ有効パケットを受信した場合、Win32 ReadFile 関数を使用してパケットを読み込みます。アプリケーションは DeviceIoControl または ReadFile を使用してプロトコルに対するパケットを受信し始めたら、そのプロトコル上でのそれ以降の全てのパケットは同じ関数を使用して受信できます。

3.2.4.1 デバイスインターフェース GUID

// {2C9C45C2-8E7D-4C08-A12D-816BBAE722C0}
DEFINE_GUID(GUID_DEVINTERFACE_GRMNUSB, 0x2c9c45c2L, 0x8e7d, 0x4c08, 0xa1, 0x2d, 0x81,
0x6b, 0xba, 0xe7, 0x22, 0xc0);

3.2.4.2 定数

#define API_VERSION 1
#define MAX_BUFFER_SIZE 4096
#define ASYNC_DATA_SIZE 64

3.2.4.3 ReadFile, WriteFile 関数

ReadFile, WriteFile に対して呼び出し側から渡されるバッファは MAX_BUFFER_SIZE より大きくなければならない。データが MAX_BUFFER_SIZE を超えるなら複数回の呼び出しを行います。

3.2.4.4 IOCTL

以下の定数は DeviceIoControl 関数と共に使用されることを意図しています。下記の IOCTL それぞれが返す値は出力バッファに書き込んだバイト数です。

#define IOCTL_API_VERSION CTL_CODE( FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED,
FILE_ANY_ACCESS )

出力バッファは 4 バイトの API バージョンを受け取ります。

#define IOCTL_ASYNC_IN CTL_CODE( FILE_DEVICE_UNKNOWN, 0x850, METHOD_BUFFERED,
FILE_ANY_ACCESS )

出力バッファはデバイスから非同期データを受信します。サイズは ASYNC_DATA_SIZE と等しいかそれより小さい値です。呼び出し側はこの IOCTL でドライバを絶えず呼び出す必要があります。ドライバはサイズ制限のされた非同期データを保存します。

#define IOCTL_USB_PACKET_SIZE CTL_CODE( FILE_DEVICE_UNKNOWN, 0x851, METHOD_BUFFERED,
FILE_ANY_ACCESS )

出力バッファは 4 バイトの USB パケットサイズを受信します。デバイスに送信されるデータ量が USB パケットサイズの整数倍 (integral multiple) の場合、呼び出し側は長さ 0 の転送を送る責任があります。