2017-06-09 27 views
0

私は実際にUSBを接続する指紋リーダー(FPリーダー)に取り組んでいます。このFPリーダーは、stm32f4ボードにも接続します。私が正しく理解すれば、FPリーダーには実際に小さなデータベースFPテンプレートが含まれています。これらのテンプレートを変更するには、FPリーダーをUSBに接続し、Windows上でプログラムを使用して修正します。私はLinux(そして好奇心のため)に取り組んでいるので、Linux上でテンプレートを修正するためのプログラムを作ろうとしています。Linuxで特定のコマンドをscsiデバイスに送信するにはどうすればよいですか?

このFPリーダーは、CD-ROMリーダーと見なされます。私はsgパッケージの助けを借りてそれに連絡しようとしています(私はこの文書http://www.tldp.org/HOWTO/SCSI-Generic-HOWTO/に従っています)。 FPリーダーのドキュメントによると(http://www.adh-tech.com.tw/files/GT-511C3_datasheet_V1%201_20131127.pdfがあります)、このような[55 aa 0001 00000000 0001 0101]のようなバッファ(12バイト)を送信して、 "open"コマンドを実行する必要があります。ここで

は(私が読める最小限の例を作ってみました)このコマンドを作るために私のコードです:私が期待したもの

#include <errno.h> 
#include <fcntl.h> 
#include <scsi/sg.h> 
#include <stdint.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/ioctl.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <unistd.h> 

#define FP_PACKET_SZ 12 

const uint8_t fp_packet_sz = FP_PACKET_SZ; 
static unsigned char sense_buffer[32]; 

#define OPEN_CMD 

static void init_snd(uint8_t buf[fp_packet_sz]) { 
    size_t offset = 0; 
    const uint16_t deviceID = 1; 
    const uint16_t cmd = 1; 
    const uint32_t parameter = 0; 
    buf[offset++] = 0x55; 
    buf[offset++] = 0xAA; 
    memcpy(buf + offset, &deviceID, sizeof(deviceID)); 
    offset += sizeof(deviceID); 
    memcpy(buf + offset, &parameter, sizeof(parameter)); 
    offset += sizeof(parameter); 
    memcpy(buf + offset, &cmd, sizeof(cmd)); 
    offset += sizeof(cmd); 

    uint16_t checksum = 0; 
    for (unsigned int i = 0 ; i < offset ; i++) 
    checksum += buf[i]; 
    memcpy(buf + offset, &checksum, sizeof(checksum)); 

} 

int main(int argc, char *argv[]) { 
    int fd = 0, res = 0; 
    char * filename = 0; 

    sg_io_hdr_t header; 
    uint8_t snd[fp_packet_sz]; 
    uint8_t rcv[fp_packet_sz]; 
    memset (snd, 0, sizeof(snd)); 
    memset (rcv, 0, sizeof(rcv)); 

    if (argc < 2) { 
    fprintf(stderr, "argument missing\n"); 
    return EXIT_FAILURE; 
    } 
    filename = argv[1]; 
    fd = open(filename, O_RDWR); 
    if (fd < 0) { 
    fprintf(stderr, "open %s failed\n", filename); 
    return EXIT_FAILURE; 
    } 

    init_snd(snd); 
    header.interface_id = 'S'; 
    header.dxfer_direction = SG_DXFER_TO_FROM_DEV; 

    header.cmd_len = fp_packet_sz; 
    header.cmdp = snd; 

    header.mx_sb_len = sizeof (sense_buffer); 
    header.sbp = sense_buffer; 

    header.iovec_count = 0; 
    header.dxfer_len = fp_packet_sz; 
    header.dxferp = rcv; 

    header.timeout = 60000; 
    header.flags = 0; 

    if ((res = ioctl(fd, SG_IO, &header)) < 0) { 
    fprintf(stderr, "ioctl failed and return errno: %s \n", strerror(errno)); 
    exit(EXIT_FAILURE); 
    } 

    fprintf(stdout, "receive buffer:"); 
    for (int i = 0 ; i < fp_packet_sz ; i++) 
    fprintf(stdout, " %02x", rcv[i]); 
    fprintf(stdout, "\n"); 


    fprintf(stdout, "sense data:"); 
    for (int i = 0 ; i < header.sb_len_wr ; i++) 
    fprintf(stdout, " %02x", sense_buffer[i]); 
    fprintf(stdout, "\n"); 

    return EXIT_SUCCESS; 
} 

は、次の値[55 aa 00 01 00 00 00 00 00 30 01 30]を持つようにrcvました。 70 00 05 00 00 00 00 0A 00 00 00 00 20 00 00 00 00 00Illegal Requestに対応(http://blog.disksurvey.org/knowledge-base/scsi-sense/ブログによる):

はしかし、その代わりに、私は何も(または何か私は理解していない)と、以下の値を取得sense_dataを受けていません。私はまた、scsi_inquiry.cと同じスキームを使って、そのフォーラムhttp://www.linuxquestions.org/questions/programming-9/linux-scsi-passthrough-porting-windows-routine-4175528749/と同じようにしてみました。同じsense_dataが得られました。私は実際にどのようにsgドライバーの仕事を理解していないと思う。それはsense_dataまたはデバイスを与えるドライバですか?で、SGコマンドによって与えられたいくつかの追加情報

(私は唯一のFPリーダーのメモリのフォーマットに関するいくつかの情報を読み取ることができるように思える)私も/dev/sr1にいくつかのread()write()をしようが、それはうまくいきませんでした端末:

>sg_map 
/dev/sg3 /dev/sr1 

>sg_inq /dev/sg3 
invalid VPD response; probably a STANDARD INQUIRY response 
standard INQUIRY: 
    PQual=0 Device_type=5 RMB=1 LU_CONG=0 version=0x06 [SPC-4] 
    [AERC=0] [TrmTsk=0] NormACA=0 HiSUP=0 Resp_data_format=2 
    SCCS=0 ACC=0 TPGS=0 3PC=0 Protect=0 [BQue=0] 
    EncServ=0 MultiP=0 [MChngr=0] [ACKREQQ=0] Addr16=0 
    [RelAdr=0] WBus16=0 Sync=0 [Linked=0] [TranDis=0] CmdQue=0 
    length=36 (0x24) Peripheral device type: cd/dvd 
Vendor identification:   
Product identification: Fingerprint  
Product revision level: 0.01 

さらに詳しい情報が必要な場合は、その投稿に追加します。

質問の再開:どのように私は、Linux(SG)にSCSIドライバを使用することにより、指紋リーダーに特定のコマンド(バッファ)を送信することができますまたは他のプログラム?

今後のご支援ありがとうございます。

EDIT1:どのように私は、特定のコマンドを送信することができます(バッファ) へ:ここ は(GDBによって与えられた)デバイス

gdb> x /3xw snd 
0x0001aa55 0x00000000 0x01010001 
+0

あなたは整数のdeviceID、cmdおよびパラメータのメモリ内容を送信しているようです。あなたはあなたがそうするべき適切なエンディアンでこれらを送りますか?おそらくあなたはリトルエンディアンマシンにいると思われますが、例[55 aa 0001 00000000 0001 0101]はビッグエンディアンのフィールドを持っているようです。 – nos

+0

@nos私のマシンはリトルエンディアンで、指紋リーダーもリトルエンディアンです。送信するバッファを準備するのは 'init_snd'です。私が使用した例は、読みやすくするために書かれています。私は、エンディアンで本当にうまくいったことはありません。私はそれが可能かどうかを確認します。ありがとうございます。 – Missu

+0

'header.cmdp'にあるsndバッファの値を追加しました。それは同じエンディアンで別の結果を与えたコンピュータのワードサイズと同じではない可能性がありますか? – Missu

答えて

1

質問の再開に送られたSNDバッファの正確な値でありますLinux(sg)または任意の のscsiドライバを使用して指紋リーダー?

Do not。

は、残念ながら「SCSI」はしばしば「漠然とSCSIのような、しかしSCSIと厳密に準拠していない」と同義語です。 USBデバイスは、しばしば、いくつかのインターフェース(例えば、OSに有用なドライバがない場合には機能が損なわれている「漠然とSCSIでSCSIではなくSCSIではない」インターフェースと、デバイス用のドライバがある場合に使用されるネイティブ・インターフェース)を提供する。

これは、デバイス専用のUSBデバイスドライバを作成する必要が非常に高いということです。

このデバイスのデータシートを見ると、SCSIとは何の関係もないことがわかります.CDのように見えるのは、「Upgrade ISO CD Image()」だけです。 "サポートされていない"と文書化されています。

+0

ありがとうございます。実際には、私はWindows上で指紋を使用するプログラムのソースを持っており、 'direct_buffer_pass_through'のようなSCSIを使用しているため、SCSIについて語りました。私はドライバーの作り方を見ていきます。それは良い経験をするでしょう。 – Missu

関連する問題