SCSI Write 명령어 질문입니다
글쓴이: ctvctv / 작성시간: 월, 2015/08/31 - 11:18오전
USB 드라이버 공부중입니다.
"윈도우USB 디바이스드라이버" 라는 책에 나온 USB저장장치 예제인데,
예제에는 SCSI Read 밖에 안나와 있어서, 제가 write 커맨드 추가해보려는데 잘 안되네요.
정확히 말씀드리면 Read는 잘 되는데 (책에 나와있는 예제 그대로), Write 가 안됩니다.
Read, Write 코드 모두 어플리케이션 소스에서 추가하는 방식입니다.
*buffer_data= "abcdef" 이런 식으로 write 할 데이터 버퍼에 저장했는데,
혹시 다른 형식으로 적어줘야 하나요? (배열이라던지..)
인터넷 찾아봐도 딱히 예제소스도 안보이고 답답하네요.
아래 소스는 Write, Read 부분이고, 전체 어플소스는 첨부파일에 있습니다!
IssueSCSICommand 함수를 사용해서 Read, Write 하는 방식입니다.
BOOL IssueSCSICommand( HANDLE vistaSample3, // 드라이버 핸들 PUCHAR Packet, // 명령어패킷이 들어있는 버퍼의 주소 UCHAR PacketLength, // 명령어 패킷의 길이 PVOID Buffer, // 읽기, 쓰기 데이터의 버퍼 ULONG TransferLength, // 송신할 데이터의 바이트 수 PULONG CompleteLength, // 실제로 통신한 데이터의 크기 BOOL isRead // 입력 TRUE, 출력 Flas ) { BOOL success; // SCSI/ATAPI 명령어 패킷을 발행한다. success = SendScsiCommandPacket( vistaSample3, Packet, PacketLength, TransferLength, isRead); if (success == FALSE) goto IssueSCSI_error; // 필요하면 데이터를 전송한다. if (TransferLength > 0) { if (isRead) success = ReadFile(vistaSample3, Buffer,TransferLength,CompleteLength,NULL); else success = WriteFile(vistaSample3, Buffer,TransferLength,CompleteLength,NULL); if (success == FALSE) goto IssueSCSI_error; } // 마지막에 상태를 얻는다. success = ReadCompleteStatus(vistaSample3); return success; IssueSCSI_error: // 일단 리셋한다. ResetPipe(vistaSample3); // 벌크-온리 디바이스의 경우 반드시 CSW를 얻고 종료해야 한다. // (CB/CBI 프로토콜의 경우 ReadCompleteStatus 함수에서는 아무것도 하지 않는다.) ReadCompleteStatus(vistaSample3); return FALSE; } BOOL Write10( HANDLE vistaSample3, ULONG Addr, //블록주소 USHORT Blocks, //쓸 블록수 PVOID Buffer, //데이터 저장할 버퍼 PCAPACITY Capacity //마디어 용량에 대한 정보 ) { UCHAR scsi[10]; DWORD nBytes; ULONG length; BOOL success; Blocks = 3; // ATAPI 명령어 패킷 (Write10)을 작성한다. memset(scsi,0,10); scsi[0] = 0x2A; // OP Code scsi[2] = (UCHAR)(Addr >> 24); // 엔디언 변환, lba scsi[3] = (UCHAR)(Addr >> 16); // lba scsi[4] = (UCHAR)(Addr >> 8); // lba scsi[5] = (UCHAR)Addr; // Lba scsi[7] = (UCHAR)(Blocks >> 8); // 엔디언 변환 scsi[8] = (UCHAR)Blocks; // 전송할 바이트 수를 계산한다. length = (ULONG)Blocks * Capacity->BlockLength; // SCSI 명령어를 발행한다. success = IssueSCSICommand( vistaSample3, scsi, // SCSI 명령어 패킷 10, // SCSI 명령어 패킷의 크기 Buffer, // 데이터 버퍼 length, // 데이터 버퍼의 크기 &nBytes, // 전송 완료 크기 TRUE); // 디바이스로부터의 데이터 입력 if (success == FALSE) printf("Write10 Error \n"); return success; } VOID MediaWrite(HANDLE vistaSample3,PCAPACITY Capacity) { ULONG address; ULONG blocks; PVOID buffer; BOOL success; char *buffer_data= "abcdef"; // 읽을 블록 번호와 블록 수를 입력 받는다. printf("Please output start address and write blocks .\n"); printf("쓰기 시작할 블록 번호:"); scanf("%d",&address); printf("쓸 블록 갯수 :"); scanf("%d",&blocks); // 입력받은 값을 체크한다. if (address >= Capacity->NumBlocks || blocks >= Capacity->NumBlocks) { printf("Input Parameter Error \n"); return; } // 데이터 버퍼를 할당한다. buffer = calloc(blocks * Capacity->BlockLength,1); if (!buffer) { printf("Memory Allocate Error \n"); return; } memcpy (buffer, buffer_data, 80); //버퍼에 값 복사 puts(buffer); puts(buffer_data); // Write10 명령어를 발행한다. success = Write10( vistaSample3, address, (USHORT)blocks, buffer, Capacity); free(buffer); } BOOL Read10( HANDLE vistaSample3, //드라이버 핸들 ULONG Addr, // 블록주소 USHORT Blocks, //읽을 블록수 PVOID Buffer, //데이터 저장할 버퍼 PCAPACITY Capacity //마디어 용량에 대한 정보 ) { UCHAR scsi[10]; DWORD nBytes; ULONG length; BOOL success; // ATAPI 명령어 패킷 (Read10)을 작성한다. memset(scsi,0,10); scsi[0] = 0x28; // 명령어 // lun, reaerved scsi[2] = (UCHAR)(Addr >> 24); // 엔디언 변환, lba scsi[3] = (UCHAR)(Addr >> 16); // lba scsi[4] = (UCHAR)(Addr >> 8); // lba scsi[5] = (UCHAR)Addr; // lba // reserved scsi[7] = (UCHAR)(Blocks >> 8); // 엔디언 변환, transfer length scsi[8] = (UCHAR)Blocks; // transfer length // reserved/flag/link // 전송할 바이트 수를 계산한다. length = (ULONG)Blocks * Capacity->BlockLength; // SCSI 명령어를 발행한다. success = IssueSCSICommand( vistaSample3, scsi, // SCSI 명령어 패킷 10, // SCSI 명령어 패킷의 크기 Buffer, // 데이터 버퍼 length, // 데이터 버퍼의 크기 &nBytes, // 전송 완료 크기 TRUE); // 디바이스로부터의 데이터 입력 if (success == FALSE) printf("Read10 Error \n"); return success; } VOID MediaRead(HANDLE vistaSample3,PCAPACITY Capacity) { ULONG address; ULONG blocks; PVOID buffer; BOOL success; // 읽을 블록 번호와 블록 수를 입력 받는다. printf("Please input start address and read blocks .\n"); printf("읽기 시작할 블록 번호:"); scanf("%d",&address); printf("읽을 블록 수 :"); scanf("%d",&blocks); //입력받은 값을 체크한다. if (address >= Capacity->NumBlocks || blocks >= Capacity->NumBlocks) { printf("Input Parameter Error \n"); return; } // 데이터 버퍼를 할당한다. buffer = calloc(blocks * Capacity->BlockLength,1); if (!buffer) { printf("Memory Allocate Error \n"); return; } // Read10 명령어를 발행한다. success = Read10( vistaSample3, address, (USHORT)blocks, buffer, Capacity); // 성공했다면 파일을 생성하고 블록 데이터를 쓴다. if (success == TRUE) { DWORD completeBytes; HANDLE file_handle; file_handle = CreateFile(READ_FILE_NAME, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (file_handle != INVALID_HANDLE_VALUE) { WriteFile(file_handle, buffer, (DWORD)blocks * Capacity->BlockLength, &completeBytes, NULL); CloseHandle(file_handle); } else printf("File open error\n"); } free(buffer); }
File attachments:
첨부 | 파일 크기 |
---|---|
![]() | 17.36 KB |
Forums:
아..IssueSCSICommand 쪽에 if 조건을
아..IssueSCSICommand 쪽에 if 조건을 못봤었네요.
Write10 함수 마지막에서 isRead값 TRUE 값을 0 으로 수정하니 잘 되네요 ㅠㅠ
글 삭제가 안돼서 댓글 달아놓습니다;;
댓글 달기