2013-02-10 2 views
2

Использование Windows я могу легко общаться с моим устройством USB, используя следующий упрощенный код:ioctrl с помощью пропуска через SCSI

DWORD dwJunk; // discard results from DeviceIOControl() 
int iReply; 
char cBuffer[100]; 
// cBuffer is initialized here. 
HANDLE hDevice; // handle to the drive to be examined 
CString sDrive = _T(\\\\.\\H:); // drive H: for this test 
hDevice = CreateFile(sDrive,   // drive to open 
    GENERIC_READ | GENERIC_WRITE,  // read and write access to the drive 
    FILE_SHARE_READ | FILE_SHARE_WRITE, // share mode   
    NULL,        // default security attributes 
    OPEN_EXISTING,      // disposition 
    0,         // file attributes 
    NULL);        // do not copy file attributes 

iReply = DeviceIoControl(hDevice, IOCTL_SCSI_PASS_THROUGH_DIRECT, &cBuffer, sizeof(cBuffer), &cBuffer, sizeof(cBuffer), &dwJunk, (LPOVERLAPPED)NULL); 

Я пытаюсь сделать то же самое в Linux, но не смогли выяснить ioctrl(), или лучше разместить структуру. Фрагмент кода будет оценен по достоинству. Благодарю.

ответ

0

Смотрите здесь:

#include <sys/ioctl.h> 

int ioctl(int d, int request, ...); 

Параметры:

  1. FileDescriptor (! Должны быть открыты)
  2. Код запроса номер (зависит от устройства)
  3. Нетипизированные указатель памяти (переход/исходящие от драйвера)

Пример

#include <stdio.h> 
#include <fcntl.h> 
#include <errno.h> 
#include <sys/ioctl.h> 
#include <linux/usbdevice_fs.h> 

void main(int argc, char **argv) 
{ 
    const char *filename; 
    int fd; 

    filename = argv[1]; 

    fd = open(filename, O_WRONLY); 
    ioctl(fd, USBDEVFS_RESET, 0); 

    close(fd); 

    return; 
} 

Документация:


Редактировать

#define BUFF_SIZE 100 // - Buffersize 

#define DEF_TIMEOUT 5000 // 5 seconds 
char cDiskName[] = "/dev/sg3"; 
int fd = open(cDiskName, O_RDWR); 
if (fd < 0) 
{ 
    printf("Open error: %s, errno=%d (%s)\n", cDiskName, errno, strerror(errno)); 
    return 1; 
} 

unsigned char turCmbBlk[] = {0x00, 0, 0, 0, 0, 0}; 
struct sg_io_hdr *p = (struct sg_io_hdr *) malloc(sizeof(struct sg_io_hdr)); // - dynamic memory allocation - free() required somewhere 

unsigned char cIOBuffer[BUFF_SIZE]; 
unsigned char replyBuffer[BUFF_SIZE]; // - dxfer buffer 

// buffer initialization code omitted 

memset(p, 0, sizeof(struct sg_io_hdr)); 
p->interface_id = 'S'; 
p->cmd_len = sizeof(turCmbBlk); 
p->mx_sb_len = BUFF_SIZE; 
p->dxfer_direction = SG_DXFER_NONE; 
p->cmdp = turCmbBlk; 
p->sbp = cIOBuffer; 
p->timeout = DEF_TIMEOUT; 
p->flags = SG_FLAG_DIRECT_IO; // - Does this help? 
p->dxferp = replyBuffer; // - Set dxferp buffer - (A) 
p->dxfer_len = BUFF_SIZE; // - buffersize 

if (ioctl(fd, SG_IO, p) < 0) 
{ 
    printf("ioctl error: errno=%d (%s)\n", errno, strerror(errno)); 
} 

// Code returned here without any errors but cIOBuffer remains unchanged. 

Примечание (A): Пожалуйста, попробуйте установить входной/выходной буфер вы работаете здесь.

Документация:

+2

Благодарим вас за то, что нашли время, чтобы опубликовать ссылки. Ваши параметры будут именно то, что я ищу, но я считаю, что волшебным словом является код запроса для эквивалента Windows «IOCTL_SCSI_PASS_THROUGH_DIRECT». Я уже занимаюсь поиском и отключением на протяжении более 2 недель, но не нашел кода, который работает в Linux. В Windows код работает со стандартными драйверами, поэтому я не верю, что код запроса зависит от устройства. Все, что я хочу сделать, это отправить буфер на USB-устройство. Затем устройство USB обновит буфер. – MaxiFlash

+3

Действительно ли 'SG_IO' вам нужно? * «SG_IO ioctl позволяет пользовательским приложениям отправлять команды SCSI на устройство». * [См. Здесь] (http://sg.danny.cz/sg/sg_io.html) – ollo

+2

Я только что посмотрел SG_IO, и это звучит за исключением того, что ему нужно правильно заполнить sg_io_hdr_t - и это выглядит сложнее, особенно в том, что ему нужна команда SCSI, которой у меня нет. Все, что я хочу сделать, - прозрачно отправить 100-байтовый буфер на USB-устройство. В Windows это так просто, я просто поставлю буфер и размер буфера. Неужели что-то вроде этого должно существовать в Linux? [EDIT] Я только что посмотрел на вашу последнюю ссылку, и это может быть то, что я хочу. Мне придется подождать до завтра, чтобы попробовать. Я отвечу завтра. – MaxiFlash

1

К сожалению, код я изменил с помощью ссылки не дали никаких результатов. Вот раздел, который я использовал.ioctl() возвращается без ошибок:

#define DEF_TIMEOUT 5000 // 5 seconds 
char cDiskName[] = "/dev/sg3"; 
int fd = open(cDiskName, O_RDWR); 
if (fd < 0) 
{ 
    printf("Open error: %s, errno=%d (%s)\n", cDiskName, errno, strerror(errno)); 
    return 1; 
} 

unsigned char turCmbBlk[] = {0x00, 0, 0, 0, 0, 0}; 
struct sg_io_hdr io_hdr; 

unsigned char cIOBuffer[100]; 

// buffer initialization code omitted 

memset(&io_hdr, 0, sizeof(struct sg_io_hdr)); 
io_hdr.interface_id = 'S'; 
io_hdr.cmd_len = sizeof(turCmbBlk); 
io_hdr.mx_sb_len = sizeof(cIOBuffer); 
io_hdr.dxfer_direction = SG_DXFER_NONE; 
io_hdr.cmdp = turCmbBlk; 
io_hdr.sbp = cIOBuffer; 
io_hdr.timeout = DEF_TIMEOUT; 
if (ioctl(fd, SG_IO, &io_hdr) < 0) 
{ 
    printf("ioctl error: errno=%d (%s)\n", errno, strerror(errno)); 
} 

// Code returned here without any errors but cIOBuffer remains unchanged. 

Возможно, для вызова нужен другой код запроса?

+1

Пожалуйста, замените 'io_hdr.dxfer_direction = SG_DXFER_NONE' (= * отсутствие передачи данных *) с' io_hdr.dxfer_direction = SG_DXFER_TO_FROM_DEV' (= * передача в обоих направлениях *). – ollo

+0

Спасибо за подшипник со мной. Я попытался использовать SG_DXFER_TO_FROM_DEV вместо SG_DXFER_NONE, но мой буфер по-прежнему не изменился. – MaxiFlash

+0

Пожалуйста, взгляните на мои изменения (* edit * моего ответа). мои изменения отмечены комментариями '// -'. Изменения: a.) Динамическая память, b.) Установленные флаги, c.) Использование dxferp. – ollo

Смежные вопросы