USBを使用するデバイスの内部には、USBデバイス・コントローラと呼ばれるLSIが内蔵されています。USBデバイス・コントローラは、USBバスを構成する信号線(VBUS, D+, D-, GND)に接続され、CPUからの指示に従ってデータを送受信したり、USBバス上で発生したイベントをCPUに知らせたりします。
USBデバイス・コントローラは、USB規格の物理層を担当するトランシーバ/レシーバ、論理層を担当するプロトコルエンジン、CPUとの間でデータをやり取りするためのFIFO、各種の制御レジスタなどから構成されています。
USBデバイス・コントローラは独立したLSIチップになっている場合もあり、またIPコアとしてCPUと同じチップ内に内蔵されていることもあります。USBデバイス・コントローラを供給しているメーカーは多数あり、種類もさまざまです。以下では一般的な例を説明します。
USBデバイスがUSBホストに接続されると、VBUSラインに5Vの電圧が発生します。また、USB接続直後や、通信エラーが発生した場合などに、USBホストはバスリセットと呼ばれる信号を出して、USBバスの接続状態をリセットします。コントローラは、USBバス上で発生したこれらのイベントを検知し、CPUに割り込みを発生させます。
USBホストとデバイスを結ぶUSBポートやケーブルは物理的には1本ですが、論理的には複数の通信チャネルを持つことができます。通信チャネルの端点をエンドポイントと呼びます。CPUは、USB通信を開始する前に、デバイスが持つエンドポイントの数と、それぞれのエンドポイントの転送方式、転送方向を決め、コントローラに設定しておきます。実際に通信が始まると、コントローラはUSBバス上を流れるパケットを識別して、それぞれのエンドポイントに振り分けます。
ホストからデータが送られてくると、コントローラはパケットを解析し、指定されたエンドポイントのFIFOにデータを格納します。データを受信し終わると、コントローラはCPUに割り込みをかけ、CPUがFIFO内のデータを取り出すのを待ちます。FIFOに空きがないのにホストから新たなパケットが送られてきた場合、コントローラはNAK応答を返して、パケットを後で再送するように要求します。
CPUからホストに送りたいデータがあるときは、送信用エンドポイントのFIFOにデータを格納します。コントローラは、ホストから要求があったときに、このデータを元にパケットを作成して、USBバス上に送出します。
デバイスがデータを送信するとき、CPUはメインメモリ上にあるデータを送信エンドポイントのFIFOにコピーしなければなりません。またデータを受信するときは、受信エンドポイントのFIFOにあるデータをメインメモリにコピーしなければなりません。送受信データの量が多いときは、コピーを行うだけで多くのCPUサイクルを消費してしまいます。
このような場合はDMA(Direct Memory Access)を利用します。DMAでは、あらかじめメインメモリ側のバッファのアドレスと、USBコントローラ側のFIFOの番号とを指定しておけば、DMAコントローラが自動的にデータのコピーを行ってくれます。CPUはこの間に別の処理を行うことができます。