ioctl Problem
-
Hi
Ich beschäftige mich gerade unter Linux in c++ mit ioctl und komme irgendwie damit nicht klar. Bzw mit dem Debuggen dieser Funktion.
OS: Xubuntu 8.10
cat /proc/scsi/sg/version
30534 3.5.34 [20061027]unsigned char dbg = 0x01; int err = ioctl(fd, SG_SET_DEBUG, &dbg); printf ("Debug Error: %d\n", err); unsigned char buff[4]; for(int i = 0; i < 4; i++) { buff[i] = 0x00; } err = ioctl(fd, SG_GET_VERSION_NUM, buff); printf ("Version Error: %d\n", err); printf ("Versionsnummer: "); for (int i = 0; i < 4; i++) { printf ("%d", buff[i]); } printf ("\n"); if (ioctl (fd, SG_IO, &sg_io)) { return -1; }
Ausgabe:[tt]
Debug Error: -1
Version Error: 0
Versionsnummer: 6311900
[/tt]ioctl (fd, SG_IO, &sg_io) liefert auch -1.
Restlichen Variablen:
fd = 3 (int)/* * O_RDWR is expected to provide for none set-root-uid * execution under Linux kernel 2.6[.8]. Under 2.4 it * falls down to O_RDONLY... */ fd = open (file, O_RDWR|O_NONBLOCK)
sg_io
// read10 command cmd[0] = 0x28; // READ 10 cmd[1] = 0x00; // DPO, FUA cmd[2] = address; cmd[3] = address; cmd[4] = address; cmd[5] = address; cmd[6] = 0x00; // Reserved, Restricted cmd[7] = SECTORS ; cmd[8] = SECTORS; cmd[9] = 0x00; // Control
Device: "/dev/cdrom3" -> USB CDRom
Das Read10 commando funktioniert (ioctl (fd, SG_IO, &sg_io) gibt nicht -1 aus)
Auch test Uinit Ready commands bzw write commands funktionieren einwandfrei.Allerdings gibt es speziell für diese Laufwerk zusätzliche Kommandos. Eines davon funktioniert aber bei 2 anderen hakts jetzt. Wenn ich die Befehle nach Spezifikation zusammenbaue und sende gibt mir ioctl (fd, SG_IO, &sg_io) immer -1 zurück. Ich weiß allerdings nicht wieso. Und da ich es auch nicht schaffe ioctl dazu zu bewegen mir mehr Informationen zurückzugeben werde ich einfach nicht schauer
Weiß zufällig wer wie ich ioctl debuggen kann oder es dazu bringe mir mehr infos zu geben?
Ich müsste wissen:
Wurde das Kommando überhaupt gesendet oder gab es vorher schon ein Problem?
Antwortet das Drive auf dieses Command mit einem Error?
Wenns die beiden nicht sind wo liegt der Fehler sonst ^^?Ich wäre auch Vorschlägen wie man die Befehle anders Senden kann nicht abgeneigt (ich muss aber auch nicht Standart Kommandos senden können). Will ja alles mal gesehen haben
MfG
-
in die errno variable schreibt ers rein
#include <error.h> ... printf(%d - %s\n", errno, strerror(errno));
MfG
-
etzt weiß ich zwar wo der Fehler liegt aber bekomm ihn ned weg
Ich habe folgenden code:
if (ioctl (fd, SG_IO, &sg_io)) { return -1; }
fd:
fd = open (file, O_RDWR|O_NONBLOCK)
SG_IO aus der sg.h
/* synchronous SCSI command ioctl, (only in version 3 interface) */ #define SG_IO 0x2285 /* similar effect as write() followed by read() */
sg_io ist ein struct
typedef struct sg_io_hdr { int interface_id; /* [i] 'S' for SCSI generic (required) */ int dxfer_direction; /* [i] data transfer direction */ unsigned char cmd_len; /* [i] SCSI command length ( <= 16 bytes) */ unsigned char mx_sb_len; /* [i] max length to write to sbp */ unsigned short int iovec_count; /* [i] 0 implies no scatter gather */ unsigned int dxfer_len; /* [i] byte count of data transfer */ void * dxferp; /* [i], [*io] points to data transfer memory or scatter gather list */ unsigned char * cmdp; /* [i], [*i] points to command to perform */ unsigned char * sbp; /* [i], [*o] points to sense_buffer memory */ unsigned int timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */ unsigned int flags; /* [i] 0 -> default, see SG_FLAG... */ int pack_id; /* [i->o] unused internally (normally) */ void * usr_ptr; /* [i->o] unused internally */ unsigned char status; /* [o] scsi status */ unsigned char masked_status;/* [o] shifted, masked scsi status */ unsigned char msg_status; /* [o] messaging level data (optional) */ unsigned char sb_len_wr; /* [o] byte count actually written to sbp */ unsigned short int host_status; /* [o] errors from host adapter */ unsigned short int driver_status;/* [o] errors from software driver */ int resid; /* [o] dxfer_len - actual_transferred */ unsigned int duration; /* [o] time taken by cmd (unit: millisec) */ unsigned int info; /* [o] auxiliary information */ } sg_io_hdr_t;
Das struct wird verteilt mit den Daten gefüllt die man braucht.
Aber zum Wichtigen. Ich baue mir dann selber MMC Kommandos zusammen die ich dann über ioctl an meinen Brenner schicke.
int err = 0; Scsi_Command cmd; cmd.associate (device); cmd[0] = 0x35; // Synchronize Cache cmd[1] = 0x00; // Immed cmd[2] = 0x00; // Logical Block Address (drive may ignore this) cmd[3] = 0x00; // Logical Block Address (drive may ignore this) cmd[4] = 0x00; // Logical Block Address (drive may ignore this) cmd[5] = 0x00; // Logical Block Address (drive may ignore this) cmd[6] = 0x00; // Reserved cmd[7] = 0x00; // Number of blocks (drive may ignore this) cmd[8] = 0x00; // Number of blocks (drive may ignore this) cmd[9] = 0x00; // Control err = cmd.transport (); // -> ioctl // err = cmd.transport (WRITE, buffer, 4); // testing return err;
Das funktioniert auch Prima.
Nur mein Brenner unterstützt auch ein paar nicht Standart MMC Kommandos. Drei davon hab ich mittlerweile programmiert. Aber es funktioniert leider nur eines. Bei den beiden Anderen liefert mir ioctl -1 als Rückgabewert und setzt die errno Variable. In errno finde ich dann ''14 - Bad address''.
Ich habe dann etwas gesucht und der Fehler deutet anscheinend darauf hin das mit Parameter 3 (sg_io) im ioctl Kommando etwas nicht stimmt.
Quelle: http://www.linuxquestions.org/questions/programming-9/ioctl-call-returns-error.-668680/Die müssen allerdings ne bessere Man Page haben als ich denn in meiner find ich gar nix zu Bad Address
http://manpages.ubuntu.com/manpages/intrepid/de/man2/ioctl.2.htmlKennt sich in der Hinsicht jemand aus oder weiß wo ich fragen könnte. Ich versteh einfach nicht wieso der Fehler auftritt. Alle Standart MMC Kommandos laufen einwandfrei und das eine spezielle auch. Nur eben die anderen 2 nicht
A ja am Brenner liegt es nicht unter Windows akzeptiert er alle Spezialkommandos (auch per ioctl Kommando gesendet).SendScsiCommand(hbd, output, prds, SCSI_PASS_THROUGH_DIRECT_ENGINE.SCSI_IOCTL_DATA_OUT, counter, mem);
Was hab ich denn da unter Linux übersehen? Was sitzt denn da noch dazwischen das ich so nen Fehler bekomme?