USBカメラのハードウェアモデルと記述UVCカメラの前分析、内部が略VCインタフェースとVSのインターフェースに分け、VC内部インタフェースが「制御」に多くのユニットと端子を有するカメラ、例えば、我々はできますホワイトバランス、露出等の設定処理ユニット。インタフェースVSのために、含むVS標準インターフェースは、しばしば、それらが同一のエンドポイントアドレスであってもよいが、各セットは、リアルタイムトランスポートエンドポイントが含まれ、多くの設定が含まれ、それらは異なる最大送信パケットサイズ、インタフェースVS特定のクラスを持っています複数のフォーマット、複数のフォーマットのフレームを含む各々は、フォーマットYUYV MJPGは、フレーム480は、解像度640 * 320 480の様々な等である、などを意味します。これらの情報は、記述子を分析することによって得られます。
VideoStreaming要求
参考UVC 1.5クラス仕様4.3
我々は、伝送および通信VS、プローブを制御すると、図を参照して、要求フォーマットを提供コミット必要とします。
bmRequestTypeの要求タイプ、参照標準USBプロトコル
一覧bRequestサブクラス8-Aは、表に定義され
、CS、制御セレクタは、表A-16に定義され、例えば、プローブまたはコミット
wIndexが上位バイトがゼロである、低バイトインタフェース番号
wLengthのとデータは、標準のUSBプロトコル、データ長およびデータのような
、以下に示すようにパラメータ設定手順を交渉するホストとUSBデバイスを必要とする、ネゴシエーションプロセスは、実質的に:
USBデバイスに送信される最初の所望の設定をホスト(プローブ)
デバイスは、所望の設定は、独自の能力の範囲内で変更することができるホストする、ホストに戻る(PROBE)
ホスト(COMMIT)提出をコミットし、実行可能な設定と考え
Setインタフェースが現在設定されています1セット
あなたが交渉するどのようなデータ?これらのデータは、場所を定義しますか?フレームフレームのフレーム周波数、最初の送信パケットサイズ、等が含ま使用リファレンス表4-75、。
参照コード:
静的INT myuvc_try_streaming_params(構造体myuvc_streaming_control * CTRL)
{
__u8 *データ。
__u16サイズ;
int型のRET;
__u8タイプ= USB_TYPE_CLASS | USB_RECIP_INTERFACE;
unsigned int型のパイプ。
memsetの(Ctrlを押しながら、0、sizeof演算子* CTRL)。
CTRL-> bmHint = 1。/ * dwFrameInterval * /
CTRL-> bFormatIndex = 1。
CTRL-> bFrameIndex = 1。
CTRL-> dwFrameInterval = 333333;
CTRL-> dwClockFrequency = 48000000;
CTRL-> wCompQuality = 61。
サイズ= 34。
データ= kzalloc(サイズ、GFP_KERNEL)。
(データ== NULL)の場合
、戻り-ENOMEM。
*(__ le16の*)&データ[0] = cpu_to_le16(CTRL-> bmHint)。
データ[2] = CTRL-> bFormatIndex。
データ[3] = CTRL-> bFrameIndex。
*(__ le32の*)&データ[4] = cpu_to_le32(CTRL-> dwFrameInterval)。
*(__ le16の*)&データ[8] = cpu_to_le16(CTRL-> wKeyFrameRate)。
*(__ le16の*)&データ[10] = cpu_to_le16(CTRL-> wPFrameRate)。
*(__ le16の*)&データ[12] = cpu_to_le16(CTRL-> wCompQuality)。
*(__ le16の*)&データ[14] = cpu_to_le16(CTRL-> wCompWindowSize)。
*(__ le16の*)&データ[16] = cpu_to_le16(CTRL-> wDelay)。
put_unaligned_le32(CTRL-> dwMaxVideoFrameSize、&データ[18])。
put_unaligned_le32(CTRL-> dwMaxPayloadTransferSize、&データ[22])。
IF(サイズ== 34){
put_unaligned_le32(CTRL-> dwClockFrequency、&データ[26])。
データ[30] = CTRL-> bmFramingInfo。
データ[31] = CTRL-> bPreferedVersion。
データ[32] = CTRL-> bMinVersion。
データ[33] = CTRL-> bMaxVersion。
}
パイプ= usb_sndctrlpipe(myuvc_udev、0);
タイプ| = USB_DIR_OUT。
RET = usb_control_msg(myuvc_udev、パイプ、0x01の、タイプ、0x01の<< 8、
0 << 8 | myuvc_streaming_intf、データ、サイズ、5000)。
kfree(日付);
リターン(右<0)?右:0;
}
静的INT myuvc_get_streaming_params(構造体myuvc_streaming_control * CTRL)
{
__u8 *データ。
__u16サイズ;
int型のRET;
__u8タイプ= USB_TYPE_CLASS | USB_RECIP_INTERFACE;
unsigned int型のパイプ。
サイズ= 34。
データ= kmallocの(サイズ、GFP_KERNEL)。
(データ== NULL)の場合
、戻り-ENOMEM。
パイプ= usb_rcvctrlpipe(myuvc_udev、0);
タイプ| = USB_DIR_IN。
RET = usb_control_msg(myuvc_udev、パイプ、0x81と、タイプ、0x01の<< 8、
0 << 8 | myuvc_streaming_intf、データ、サイズ、5000)。
(RET <0)場合
後藤行います。
CTRL-> bmHint = le16_to_cpup((__ le16の*)&データ[0])。
CTRL-> bFormatIndex =データ[2]。
CTRL-> bFrameIndex =データ[3]。
CTRL-> dwFrameInterval = le32_to_cpup((__ le32の*)&データ[4])。
CTRL-> wKeyFrameRate = le16_to_cpup((__ le16の*)&データ[8])。
CTRL-> wPFrameRate = le16_to_cpup((__ le16 *)&データ[10])。
CTRL-> wCompQuality = le16_to_cpup((__ le16 *)&データ[12])。
CTRL-> wCompWindowSize = le16_to_cpup((__ le16 *)&データ[14])。
CTRL-> wDelay = le16_to_cpup((__ le16 *)&データ[16])。
CTRL-> dwMaxVideoFrameSize = get_unaligned_le32(&データ[18])。
CTRL-> dwMaxPayloadTransferSize = get_unaligned_le32(&データ[22])。
(サイズ== 34){もし
CTRL-> dwClockFrequency = get_unaligned_le32(&データ[26])。
CTRL-> bmFramingInfo =データ[30]。
CTRL-> bPreferedVersion =データ[31]。
CTRL-> bMinVersion =データ[32]。
CTRL-> bMaxVersion =データ[33]。
}他{
// CTRL-> dwClockFrequency =ビデオ- > DEV-> clock_frequency。
CTRL-> bmFramingInfo = 0;
CTRL-> bPreferedVersion = 0;
CTRL-> bMinVersion = 0;
CTRL-> bMaxVersion = 0;
}
行わ:
kfree(データ);
リターン(右<0)?右:0;
}
静的INT myuvc_set_streaming_params(構造体myuvc_streaming_control * CTRL)
{
__u8 *データ。
__u16サイズ;
int型のRET;
__u8タイプ= USB_TYPE_CLASS | USB_RECIP_INTERFACE;
unsigned int型のパイプ。
サイズ= 34。
データ= kzalloc(サイズ、GFP_KERNEL)。
(データ== NULL)の場合
、戻り-ENOMEM。
*(__ le16の*)&データ[0] = cpu_to_le16(CTRL-> bmHint)。
データ[2] = CTRL-> bFormatIndex。
データ[3] = CTRL-> bFrameIndex。
*(__ le32の*)&データ[4] = cpu_to_le32(CTRL-> dwFrameInterval)。
*(__ le16の*)&データ[8] = cpu_to_le16(CTRL-> wKeyFrameRate)。
*(__ le16の*)&データ[10] = cpu_to_le16(CTRL-> wPFrameRate)。
*(__ le16の*)&データ[12] = cpu_to_le16(CTRL-> wCompQuality)。
*(__ le16の*)&データ[14] = cpu_to_le16(CTRL-> wCompWindowSize)。
*(__ le16の*)&データ[16] = cpu_to_le16(CTRL-> wDelay)。
put_unaligned_le32(CTRL-> dwMaxVideoFrameSize、&データ[18])。
put_unaligned_le32(CTRL-> dwMaxPayloadTransferSize、&データ[22])。
IF(サイズ== 34){
put_unaligned_le32(CTRL-> dwClockFrequency、&データ[26])。
データ[30] = CTRL-> bmFramingInfo。
データ[31] = CTRL-> bPreferedVersion。
データ[32] = CTRL-> bMinVersion。
データ[33] = CTRL-> bMaxVersion。
}
パイプ= usb_sndctrlpipe(myuvc_udev、0);
タイプ| = USB_DIR_OUT。
RET = usb_control_msg(myuvc_udev、パイプ、0x01の、タイプ、0x02の<< 8、
0 << 8 | myuvc_streaming_intf、データ、サイズ、5000)。
kfree(日付);
リターン(右<0)?右:0;
}
VideoControlは要求
ここでは、処理ユニット制御におけるVCのインターフェイスは、例えば、明るさを要求分析:
静的ボイドmyuvc_set_le_value(__ S32値、__u8 *データ)
{
int型ビット= 16。
= 0のオフセットint型。
__u8マスク。
データは+ = / 8オフセット。
オフセット&= 7。
以下のために(;ビット> 0;データ++){
マスク=((1LL <<ビット) - 1)<<オフセット。
*データ=(*データ&〜マスク)| ((値<<オフセット)&マスク);
値は>> =オフセット?オフセット:8;
ビット- = 8 -オフセット。
= 0をオフセット。
}
}
静的__s32のmyuvc_get_le_value(CONST __u8 *データ)
{
int型ビット= 16。
= 0のオフセットint型。
__s32値= 0。
__u8マスク。
データは+ = / 8オフセット。
オフセット&= 7。
((1LL <<ビット) - 1)=マスク<<オフセット。
用(;ビット> 0;データ++){
__u8バイト= *データ&マスク。
値| => 0のオフセット?(バイト>>オフセット):(バイト<<(-offset));
ビット- = 8 - (オフセット> 0をオフセット:0?)。
オフセット- = 8。
=(1 <<ビット)をマスク- 1。
}
/ *符号拡張値を必要に応じて。* /
値| = - (値&(1 <<(15 - 1)))。
値を返します。
}
/ *参考:uvc_query_v4l2_ctrl * /
int型myuvc_vidioc_queryctrl(構造体ファイル*ファイル、void *型FH、
構造体v4l2_queryctrl * CTRL)
{
__u8タイプ= USB_TYPE_CLASS | USB_RECIP_INTERFACE;
unsigned int型のパイプ。
int型のRET;
U8データ[2]。
(!CTRL-> ID = V4L2_CID_BRIGHTNESS)の場合
-EINVALを返します。
memsetの(Ctrlを押しながら、0、sizeof演算子* CTRL)。
CTRL-> ID = V4L2_CID_BRIGHTNESS。
CTRL-> = V4L2_CTRL_TYPE_INTEGERを入力します。
strcpyの(CTRL->名、 "MyUVC_BRIGHTNESS");
CTRL->フラグ= 0;
パイプ= usb_rcvctrlpipe(udevの、0);
タイプ| = USB_DIR_IN。
/ *これらの値は、USBを開始することが決定されている* /
RET = usb_control_msg(udevに、パイプ、GET_MIN、タイプ、PU_BRIGHTNESS_CONTROL << 8、。
ProcessingUnitID 8 << | myuvc_control_intf、データ、2、5000);
IF(!RET = 2)
に戻ります- EIO;
はCtrl->最小= myuvc_get_le_value(データ); / * *注符合/
RET = usb_control_msg(udevの、パイプ、GET_MAX、タイプ、PU_BRIGHTNESS_CONTROL << 8、
ProcessingUnitID << 8 | myuvc_control_intf、データ、2、5000)。
(RET = 2!)であれば
-EIOを返します。
CTRL->最大= myuvc_get_le_value(データ)。/ *注符号の有無* /
RET = usb_control_msg(udevの、パイプ、GET_RES、タイプ、PU_BRIGHTNESS_CONTROL << 8、
ProcessingUnitID << 8 | myuvc_control_intf、データ、2、5000)。
(RET = 2!)であれば
-EIOを返します。
CTRL->ステップ= myuvc_get_le_value(データ)。/ *注符号の有無* /
RET = usb_control_msg(udevの、パイプ、GET_DEF、タイプ、PU_BRIGHTNESS_CONTROL << 8、
ProcessingUnitID << 8 | myuvc_control_intf、データ、2、5000)。
(RET = 2!)であれば
-EIOを返します。
CTRL-> DEFAULT_VALUE = myuvc_get_le_value(データ)。/ *注符号の有無* /
printk( "明るさ:最小=%D、最大=%D、ステップ=%D、デフォルト=%d個の\ n"、CTRL->最小、CTRL->最大、CTRL->ステップ、CTRL-> DEFAULT_VALUE)。
0を返します。
}
/ *参考:uvc_ctrl_get * /
int型myuvc_vidioc_g_ctrl(構造体ファイル*ファイル、void *型FH、
構造体v4l2_control * CTRL)
{
__u8タイプ= USB_TYPE_CLASS | USB_RECIP_INTERFACE;
unsigned int型のパイプ。
int型のRET;
U8データ[2]。
(!CTRL-> ID = V4L2_CID_BRIGHTNESS)の場合
-EINVALを返します。
パイプ= usb_rcvctrlpipe(udevの、0);
タイプ| = USB_DIR_IN。
RET = usb_control_msg(udevの、パイプ、GET_CUR、タイプ、PU_BRIGHTNESS_CONTROL << 8、
ProcessingUnitID << 8 | myuvc_control_intf、データ、2、5000)。
(RET = 2!)であれば
-EIOを返します。
CTRL->値= myuvc_get_le_value(データ)。/ *注符号の有無* /
0を返します。
}
/ *参考:uvc_ctrl_set / uvc_ctrl_commit * /
int型myuvc_vidioc_s_ctrl(構造体ファイル*ファイル、void *型FH、
構造体v4l2_control * CTRL)
{
__u8タイプ= USB_TYPE_CLASS | USB_RECIP_INTERFACE;
unsigned int型のパイプ。
int型のRET;
U8データ[2]。
(!CTRL-> ID = V4L2_CID_BRIGHTNESS)の場合
-EINVALを返します。
myuvc_set_le_value(CTRL->値、データ)。
パイプ= usb_sndctrlpipe(udevの、0);
タイプ| = USB_DIR_OUT。
RET = usb_control_msg(udevの、パイプ、SET_CUR、タイプ、PU_BRIGHTNESS_CONTROL << 8、
ProcessingUnitID << 8 | myuvc_control_intf、データ、2、5000)。
(RET = 2!)であれば
-EIOを返します。
0リターン;
}
データ取得
データ取得、我々はVS標準リアルタイムデータ収集、分配、集合、その後URBに設けられた通信インターフェースを終了する必要があります。
私のトランスミッション撮像初めて例えば640×320解像度の画像は、各画素16ビットなので、画像空間640×320×2バイト、3060バイト。バッファ32 URB UVC規格の最大数を制限するカメラドライバでなお、ので、データはURB 3060 * 32のように実施することができる、複数の画像データは、URBを送信する必要がある、計算されました。そのため、ユーザ空間バッファは、それは二つの画像内の1つのURBデータへの画像データのコピー中に含めることができる、あなたは、画像データの損失につながること、画像データの第2フレームが破棄される前に処理置く必要はありません。
静的INT myuvc_alloc_init_urbs(ボイド)
{
U16のPSIZE。
U32サイズ;
int型npackets;
int型I、J。
構造体URB * URB。
//構造体URB * URB。
PSIZE = 3060;バイトの/ *最大数は、トランスポートエンドポイント* /へリアルタイムに送信することができる
最大データ* /の/ *長さ;サイズ= 614400
npackets = DIV_ROUND_UP(サイズ、PSIZE);
IF(npackets> 32)
npackets = 32;
myprintk( "D npackets PSIZE%D%\ N-"、PSIZE、npackets);
サイズ= PSIZE * npackets;
のための(I = 0;私は<5; Iは++){
/ * * 1分配usb_buffers /
urb_buffer [I] = usb_alloc_coherent(
myuvc_udev、サイズ、
GFP_KERNEL | __GFP_NOWARN、&urb_dma [I])。
/ * 2分配URB * /
myurb [I] = usb_alloc_urb(npackets、GFP_KERNEL)。
もし(urb_buffer [I] || myurb [i]が!!)
{
// myuvc_uninit_urbs();
myprintk( "ALLOCバッファ又はURBがn \失敗")。
-ENOMEMを返します。
}
}
/ * 3设置URB * /
用(i = 0; iは5 '; ++ I){
URB = myurb [I]。
urb-> DEV = myuvc_udev。
urb->コンテキスト= NULL;
urb->パイプ= usb_rcvisocpipe(myuvc_udev、0x81と)。
urb-> transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
urb->間隔= 1。
urb-> transfer_buffer = urb_buffer [I]。
urb-> transfer_dma = urb_dma [I]。
urb->完全= myuvc_video_complete。
urb-> number_of_packets = npackets。
urb-> transfer_buffer_length =サイズ;
(; J、J = 0 <npackets; ++ J){
urb-> iso_frame_desc [J] .offset = J *のPSIZE。
urb-> iso_frame_desc [J] .LENGTH = PSIZE。
}
}
0を返します。
}
静的ボイドmyuvc_video_complete(構造体URB * URB)
{
U8 * SRC。
// U8 * DEST。
int型のRET、I。
int型のlen;
int型のmaxlen;
// int型nバイト。
//構造体myuvc_buffer * BUF。
myprintk( "ビデオ完全な\ nを");
スイッチ(urb->ステータス){
ケース0:
ブレーク。
デフォルト:
myprintk( "ビデオでの非ゼロのステータス(%d)は、"
。完了ハンドラ"\ n"は、urb->状態)。
返します。
}
{(; I <urb-> number_of_packets ++ I I = 0)のための
IF(urb-> iso_frame_desc [I] .status <0){
myprintk( "USBアイソクロナスフレームが"
。 "(%D)\ n"を失いました、urb-> iso_frame_desc [I] .status)。
持続する;
}
SRC = urb-> transfer_buffer + urb-> iso_frame_desc [I] .offset。
// DEST = myuvc_queue.mem + buf-> buf.m.offset + buf-> buf.bytesused。
urb- = LEN> iso_frame_desc [I] .actual_length;
myprintk( "LEN%D \ N-"、urb-> iso_frame_desc [I]は.actual_length);
/ * * /データが有効であるかどうかを判断する
/ * URBデータの意味:
* DATA [ 0]:ヘッダ長
*データ[1]:エラーステータス
* /
IF(SRC || SRC [0] <2 || LEN <2 [0]> LEN)
続けます。
/ *エラービット(「エラーフレーム」)でマークされたペイロードをスキップします。* /
IF(SRC [1]&UVC_STREAM_ERR){
myprintk( ")ペイロード(エラービットセットを削除する\ n");
持続する;
}
/ *ヘッド後のデータ長が除去された* /
LEN - SRC = [0]。
/ *バッファも格納することができる数のデータ* /
// MAXLEN = BUF - > buf.lengthする- BUF - > buf.bytesused;
// nバイト=分(LEN、MAXLEN)を、
/ *コピーデータ* /
//のmemcpy(DEST、SRC SRC + [0]、nバイト);
//buf->buf.bytesused + = nバイト。
/ * / 1フレームの全てのデータが受信されたか否かが判断される
{IF(LEN> MAXLEN)
- >状態= VIDEOBUF_DONE // BUF;
}
/ *マークEOFマーカーが設定されている場合に行われるよう、バッファ。* /
(SRC [1]&UVC_STREAM_EOF){もし
myprintk( "フレーム完全(EOF見出さ)\ n");
IF(LEN == 0)
myprintk( "空のペイロードにおけるEOF \ n");
// buf->状態= VIDEOBUF_DONE。
}
}
/ *再提出のURB * /
IF((RET = usb_submit_urb(URB、GFP_ATOMIC))<0){
myprintk( "ビデオURBを再送信に失敗しました(%D)\ n"は、RET)。
}
}
---------------------