2017-11-21 6 views
1

Nikon LS-9000 ED 스캐너가 Linux SANE에서 지원되지 않으며 Linux Firewire 커널 API libraw1394으로 내 드라이버를 만들기로 결정했습니다.libraw1394로 메모리 액세스

스캐너 용 Library Programs and Command API Specifications은 최근 Nikon에서 출시되었습니다. 스캐너는 Serial Bus Protocol 2 (SBP-2) 및 IEEE Std 1394-1995 표준을 사용합니다.

libraw1394를 사용하여 간단한 테스트 프로그램을 만들었으며 에 대해 대부분 레지스터를 읽을 수 없다는 것을 알게되었습니다.

// gcc -Wall -o read read.c -l raw1394 
#include <stdio.h> 
#include <libraw1394/csr.h> 
#include <libraw1394/raw1394.h> 


int main() 
{ 

    raw1394handle_t handle; 

    handle = raw1394_new_handle_on_port(0); 

    printf("node: %X\n", raw1394_get_local_id(handle)); 


    quadlet_t read; 

    for (int i = 0; i <= 1048576; i++) // 0 to 0x100000 
    { 
     int result = raw1394_read(handle, 
            raw1394_get_local_id(handle), 
            CSR_REGISTER_BASE + (i*4), 
            sizeof(quadlet_t), 
            &read); 

     if (result == 0) 
      printf("%X\n", i*4);    
    } 

    raw1394_destroy_handle(handle); 

} 

출력을 (축약 된 형태로)이었다 : 읽기 테스트 프로그램은 다음과 같이이었다이 오프셋은 모든 중요한 MANAGEMENT_AGENT 레지스터를 포함하지 않는

$ sudo ./read 
node: FFC1 
0 
4 
8 
18 
1C 
200 
204 
210 
218 
21C 
220 
224 
228 
230 
234 
400 - 7FC 
1000 - 13FC 

하는 니콘 LS9000에 대한 ED는 0x30000입니다. 나는 을 기입 할 수 없었다.도이 기록에 기입한다.

커널에 일종의 메모리 액세스 제한이 있어야합니다. 예를 들어 Query Login ORB와 같이 MANAGEMENT_AGENT 레지스터에 명령을 기록하려면 어떻게해야합니까?

스캐너가 연결되기 전에

: 스캐너가 연결된 후

$ lsmod | grep firewire 
firewire_ohci   40960 0 
firewire_core   65536 1 firewire_ohci 
crc_itu_t    16384 1 firewire_core 

$ dmesg | grep firewire 
[ 0.776039] firewire_ohci 0000:03:00.0: added OHCI v1.10 device as card 0, 4 IR + 8 IT contexts, quirks 0x2 
[ 1.276095] firewire_core 0000:03:00.0: created device fw0: GUID 000000000000017e, S400 

:

$ lsmod | grep firewire 
firewire_sbp2   24576 0 
firewire_ohci   40960 0 
firewire_core   65536 2 firewire_ohci,firewire_sbp2 
crc_itu_t    16384 1 firewire_core 

$ dmesg | grep firewire 
[ 0.776039] firewire_ohci 0000:03:00.0: added OHCI v1.10 device as card 0, 4 IR + 8 IT contexts, quirks 0x2 
[ 1.276095] firewire_core 0000:03:00.0: created device fw0: GUID 000000000000017e, S400 
[ 3289.660782] firewire_core 0000:03:00.0: rediscovered device fw0 
[ 3292.688185] firewire_core 0000:03:00.0: created device fw1: GUID 0090b54003ffffff, S400 
[ 3292.688190] firewire_core 0000:03:00.0: phy config: new root=ffc0, gap_count=5 
[ 3292.922459] firewire_sbp2 fw1.0: logged in to LUN 0000 (0 retries) 

그것은 로그인을하지 분명히 스캐너가 연결되어있을 때 시작 firewire_sbp2 커널 모듈을 보인다. firewire_sbp2의 기능을 응용 프로그램에서 사용할 수 있습니까?

답변

0

SBP2은 FireWire를 통해 SCSI 명령을 전송하는 프로토콜입니다.

Linux에서는 SCSI Generic driver (sg)을 사용하여 SCSI 명령을 이러한 장치에 보낼 수 있습니다.

+0

이 정보를 제공해 주셔서 감사합니다. 나는이 드라이버를 조심스럽게보고 몇 주 후에 다시보고 할 것입니다. – Rhett

0

나는 나의 목적을 위해 SCSI Generic 드라이버를 사용할 수있어서 기쁩니다.

다음은 Nikon LS-9000 ED 스캐너의 필름 트레이를 꺼내기위한 맞춤형 프로그램입니다.

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

/* A program to eject the tray of a Nikon LS-9000 ED scanner 
* using the Linux SCSI generic (sg) driver. 
* 
* Based on the example by D. Gilbert at 
* http://tldp.org/HOWTO/SCSI-Generic-HOWTO/pexample.html 
*/ 



#define OPCODE_EXECUTE 0xC1 
#define OPCODE_SET  0xE0     

#define CMD_EXECUTE_LEN 6 
#define CMD_SET_LEN  10 

#define EJECT_TRAY  0xD0  


#define PARAM_LEN  0xD 



int main(int argc, char * argv[]) 
{ 

    int sg_device; 

    unsigned char setCmdBlk[CMD_SET_LEN] = 
     {OPCODE_SET, 0, EJECT_TRAY, 0, 0, 0, 0, 0, PARAM_LEN, 0}; 

    unsigned char exeCmdBlk[CMD_EXECUTE_LEN] = 
     {OPCODE_EXECUTE, 0, 0, 0, 0, 0}; 

    unsigned char sense_buffer[32]; 
    sg_io_hdr_t io_hdr; 


    if (argc != 2) 
    { 
     printf("Usage: 'eject /dev/sg<device number>'\n"); 
     return 1; 
    } 

    if ((sg_device = open(argv[1], O_RDWR)) < 0) 
    { 
     perror("Error opening device"); 
     return 1; 
    } 


    memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); 
    io_hdr.interface_id = 'S'; 
    io_hdr.cmd_len = sizeof(setCmdBlk); 
    io_hdr.mx_sb_len = sizeof(sense_buffer); 
    io_hdr.dxfer_direction = SG_DXFER_NONE; 
    io_hdr.dxfer_len = 0; 
    io_hdr.dxferp = NULL; 
    io_hdr.cmdp = setCmdBlk; 
    io_hdr.sbp = sense_buffer; 
    io_hdr.timeout = 20000; 

    if (ioctl(sg_device, SG_IO, &io_hdr) < 0) 
    { 
     perror("SET PARAM ioctl error"); 
     return 1; 
    } 


    io_hdr.cmd_len = sizeof(exeCmdBlk); 
    io_hdr.cmdp = exeCmdBlk; 

    if (ioctl(sg_device, SG_IO, &io_hdr) < 0) 
    { 
     perror("EXECUTE ioctl error"); 
     return 1; 
    } 


    close(sg_device); 
    return 0; 

} 

은 그와의 통신 및 리눅스에서 내 니콘 스캐너의 사용 지금은 원칙적으로 해결되어야한다 가정.

분명히 실제로 스캔을 생성하고 스캐너를 제어하는 ​​모든 설정을 구현해야하는 많은 작업이 남아 있습니다. 필자는 함수 라이브러리와 데스크탑 응용 프로그램을 만들 계획입니다. 목표는 광범위하게 Nikon Scan 4.0.3과 유사한 인터페이스를 만드는 것입니다.

도움 주셔서 감사합니다.

+0

위의 코드가 일관되게 작동하려면 (이제는 이해 했으므로) SET PARAM ioctl과 EXECUTE ioctl 사이에 TEST UNIT READY ioctl을 추가해야합니다. – Rhett