我实际上正在使用插入USB的指纹识别器(FP阅读器)。这个FP阅读器也插在stm32f4板上。如果我理解正确,FP阅读器包含一个非常小的数据库FP模板。要修改这些模板,我们将FP读取器插入USB并使用Windows上的程序对其进行修改。由于我在Linux(以及好奇心)工作,我试图制作一个允许我们在Linux上修改模板的程序。
此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找到它)我应该发送一个缓冲区(12字节),如[55 aa 0001 00000000 0001 0101],以使"打开&#34 ;命令。
这是我的代码来制作这个命令(我试图做一个可读的最小例子):
#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, ¶meter, 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;
}
我期望rcv
具有以下值[55 aa 00 01 00 00 00 00 00 30 01 30]
。
但相反,我没有收到任何内容(或我不理解的内容),sense_data
获得以下价值:70 00 05 00 00 00 00 0A 00 00 00 00 20 00 00 00 00 00
,对应Illegal Request
(根据{ {3}}博客)。我也尝试使用与scsi_inquiry.c
相同的方案,如该论坛http://blog.disksurvey.org/knowledge-base/scsi-sense/中所述,我得到相同的sense_data
。我想我真的不明白sg驱动程序是如何工作的。这是给sense_data
或设备的驱动程序吗?我还尝试在read()
上制作一些write()
和/dev/sr1
,但它没有用(似乎我只能阅读有关FP阅读器内存格式的一些信息) )
终端中sg命令给出的一些附加信息:
>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: 这是发送到设备的snd缓冲区的确切值(由gdb给出)
gdb> x /3xw snd
0x0001aa55 0x00000000 0x01010001
答案 0 :(得分:1)
问题的简历:我如何发送特定命令(缓冲区) 通过在Linux(sg)或任何中使用scsi驱动程序到指纹识别器 其他节目?
唐&#39;吨
不幸的是&#34; SCSI&#34;通常是&#34;与SCSI很相似的同义词,但不严格遵守SCSI&#34 ;; USB设备通常提供多个接口(例如,模糊地类似于SCSI而不是SCSI&#34;具有残缺功能的接口,用于当操作系统没有有用的驱动程序时,以及本地接口,以及当设备有驱动程序时使用。)
这意味着您极有可能需要专门为该设备编写USB设备驱动程序。
请注意,如果您查看此设备的数据表,您会发现没有任何命令与SCSI有任何关系,而且唯一看起来像CD的是&#34 ;升级ISO CD Image()&#34;记录为&#34;不支持&#34;。
的功能