bhoar Posted June 28, 2006 Posted June 28, 2006 (edited) [sOLVED - see 8th post]The idea here is to send a special SCSI command to the drive directly, and have it report back whether or not the tray/door is open or closed. This would improves upon the standard methods that cannot seem to differentiate between an empty but closed tray and an open tray.I need this specifically because a.) I don't want to interrupt what the drive is doing with another application and b.) I need to make sure all drive trays are closed before moving the robot arm in the space that open trays occupy.The code below is based primarily on VB and C++ examples found on microsoft's development site and other dev forums, using DeviceIoControl to perform a IOCTL_SCSI_PASS_THROUGH transaction containing the CDB 0xBD which requests "Mechanism Status".This is what I see as a result of the DeviceIoControl call:1) The DLLCall does not return an error via $ret[0] or @error, so the general calling dllcall convention seems to be OK.2) Apparently, the DeviceIoControl does not return a non-null value via $returnvalue, so I take it that worked OK.3) However, all of the values in the structure I passed seem to be unchanged, which means the call didn't do anything. I don't know if a SCSI command was issued at all.I'm clearly missing something in the preparation/population of the data structures, access control or with the DeviceIoControl request, but I am currently at a loss as to why all the data comes back from the call unchanged. I've tried several CDB sizes (8,10,12,16).Anyone want a challenge? [this is my continuation of an ancient discussion here: http://www.autoitscript.com/forum/index.php?showtopic=25089 ]EDIT: attachment removed. See eight post for final version.-brendan Edited June 30, 2006 by bhoar
bhoar Posted June 29, 2006 Author Posted June 29, 2006 (edited) Oh scrap that, still buggy. But at least the SCSI call is executing. (removed attachment) -brendan Edited June 29, 2006 by bhoar
bhoar Posted June 29, 2006 Author Posted June 29, 2006 (edited) Ok, here's the final one. It finally works....got bit by AND vs. BITAND. Little bit of humor there. Oof. Was that a TOS violation? Thanks to Robert Nelson for assistance. -brendan Edited June 29, 2006 by bhoar
SandelPerieanu Posted June 29, 2006 Posted June 29, 2006 (edited) DON'T WORK FOR ME (I HAVE ATAPI DVD-RW) LOCK/UNLOCK WORK, BUT I DON'T KNOW CHECK THIS. MsgBox(4096, LockDevice("E:", 1), "Try yo CD") MsgBox(4096, LockDevice("E:", 0), "All Better") Func LockDevice($szdrivewithcolon, $block) Local Const $invalid_handle_value = -1 Local Const $open_existing = 3 Local Const $file_attribute_normal = 128 Local Const $file_share_write = 2 Local Const $file_share_read = 1 Local Const $generic_read = 2147483648 Local Const $ioctl_storage_media_removal = 2967556 $block = Not (Not $block) $szdrivewithcolon = StringReplace($szdrivewithcolon, "", "") If StringLen($szdrivewithcolon) <> 2 Then Return -1 $szdrivewithcolon = "\\.\"& $szdrivewithcolon $hdrive = DllCall("kernel32.dll", "int", "CreateFile", "str", $szdrivewithcolon, _ "int", $generic_read, "int", BitOR($file_share_read, $file_share_write), "ptr", 0, "int", $open_existing, _ "int", $file_attribute_normal, "ptr", 0) If $hdrive[0] = $invalid_handle_value Then Return -2 $bool = DLLStructCreate ("byte") DLLStructSetData ($bool, 1, $block) $lockmediarslt = DllCall("kernel32.dll", "int", "DeviceIoControl", "int", $hdrive[0], _ "int", $ioctl_storage_media_removal, "ptr", DllStructGetPtr ($bool), "int", 1, _ "int", 0, "int", 0, "int_ptr", 0, "ptr", 0) DllCall("kernel32.dll", "int", "CloseHandle", "int", $hdrive[0]) $bool = 0 Return $lockmediarslt[0] EndFunc ;==>LockDevice Edited September 21, 2006 by psandu.ro
bhoar Posted June 29, 2006 Author Posted June 29, 2006 DON'T WORK FOR ME (I HAVE ATAPI DVD-RW) Try this change: replace: DllStructSetData($sptwb, 6, $CDBSIZE);Length of CDB to be set before making call - or always 12? with: DllStructSetData($sptwb, 6, 12);Length of real CDB to be set before making call - or always 12? -brendan
bhoar Posted June 29, 2006 Author Posted June 29, 2006 (edited) Updated code with above change and to be better organized. -brendan Edited June 29, 2006 by bhoar
bhoar Posted June 29, 2006 Author Posted June 29, 2006 Very strange problem, but it's definitely tracking the tray status On my win2000 system with a USB DVD-RW, this works: $second_byte = DllStructGetData($sptwb, 16, 2) ;should be the second byte ;now we need the bit here 00010000 $traystatus = BitAND($second_byte, 0x10) That is, I have to change to change the byte I'm grabbing the flag from. Something odd is going on. Gotta figure out if it's me or if it's windows. Probably me. -brendan
bhoar Posted June 29, 2006 Author Posted June 29, 2006 Fixed: I stupidly changed the buffer size of the sense response to an odd number.Tested this against several drives both USB and IDE/ATAPI on 2K and XP. It uses SPTI, not ASPI, so it will not work on 95/98/ME.This should be the final version of this example.Sorry for all the posts pushing this thread to the top. Maybe someone will find the SCSI stuff useful someday.-brendancdtray_routines.au3
SandelPerieanu Posted June 30, 2006 Posted June 30, 2006 sorry.don't work! $second_byte = DllStructGetData($sptwb, 16, 2) ;should be the second byte ;now we need the bit here 00010000$second_byte=0 everytimei try $second_byte = DllStructGetData($sptwb, 16, 1) and nothing.
SandelPerieanu Posted June 30, 2006 Posted June 30, 2006 i reinstall autoit and work! sorry and thanks. the questions is how now: how i check if cd-tray is blocked or not?
bhoar Posted June 30, 2006 Author Posted June 30, 2006 i reinstall autoit and work!sorry and thanks.the questions is how now: how i check if cd-tray is blocked or not?Blocked...or Locked?-brendan
bhoar Posted June 30, 2006 Author Posted June 30, 2006 (edited) I don't see a scsi command that will tell me whether or not a drive is locked or unlocked. However, we can tell it to lock/unlock.So... I did update the routines so that, in addition to reporting on the current tray status, you can also lock/unlock the trays and load/unload (=mount/eject) the trays as well. Yes, CDTray can do that last one, I know. See attached.-brendancdtray_routines.au3 Edited June 30, 2006 by bhoar
SandelPerieanu Posted July 5, 2006 Posted July 5, 2006 work on Combo Drive but on CD-RW don't work for me. It's always closed.
bhoar Posted July 6, 2006 Author Posted July 6, 2006 If you uncomment-out (comment-in? heh.) the debugging code, you should be able to record if the response from the drive is the same in both situations. Older drives had their firmware written before the MMC-3 standard (or perhaps MMC-2) added the tray flag to the mechanism status response. I should really be writing results to file, though. More updates later. -brendan
jzn2 Posted September 20, 2006 Posted September 20, 2006 I tried both posts 8 and 12 but they say the same thing... an error message about line 76 or 72 $cdb = DllStructCreate($CDB_STRUCT) $cdb = ^ ERROR Error: Unknown function name a little help would be appreciative
bhoar Posted October 6, 2006 Author Posted October 6, 2006 IIRC, you need to be using the beta (or at least what was beta at the time I wrote the script). -brendan
bhoar Posted May 11, 2007 Author Posted May 11, 2007 There's a fix for the drive handle not being closed in this thread:http://www.autoitscript.com/forum/index.ph...9368&hl=cdb-brendan
Lakes Posted May 11, 2007 Posted May 11, 2007 Is this just for SCSI drives? I was looking for something to Lock/Unlock my IDE DVD/CD drive. 2015 - Still no flying cars, instead blankets with sleeves.
bhoar Posted May 12, 2007 Author Posted May 12, 2007 Is this just for SCSI drives?I was looking for something to Lock/Unlock my IDE DVD/CD drive.It works for all optical drives (SCSI, IDE/ATA/PATA, SATA, Firewire, USB) that I have tested, though success via USB may be limited by the bridge chipset in use at the time.Here's a snippet you could combine with the above approach for locking/unlocking the drive:CODEFunc PopulateCDB_LockTray(ByRef $cdb) $fname = "PopulateCDB_LockTray" $CDBCOMMAND = 0x1E ;Prevent/Allow Medium Removal DllStructSetData($cdb, 1, $CDBCOMMAND, 1) DllStructSetData($cdb, 1, 0x00, 2) DllStructSetData($cdb, 1, 0x00, 3) DllStructSetData($cdb, 1, 0x00, 4) DllStructSetData($cdb, 1, 0x01, 5); Lock = Set bit 0 to 1 DllStructSetData($cdb, 1, 0x00, 6) DllStructSetData($cdb, 1, 0x00, 7) DllStructSetData($cdb, 1, 0x00, 8) DllStructSetData($cdb, 1, 0x00, 9) DllStructSetData($cdb, 1, 0x00, 10) DllStructSetData($cdb, 1, 0x00, 11) DllStructSetData($cdb, 1, 0x00, 12) ;The next four are not used for ATAPI compatibility, but should be set to zero anyway. DllStructSetData($cdb, 1, 0x00, 13) DllStructSetData($cdb, 1, 0x00, 14) DllStructSetData($cdb, 1, 0x00, 15) DllStructSetData($cdb, 1, 0x00, 16)EndFunc ;==>PopulateCDB_LockTrayFunc PopulateCDB_UnLockTray(ByRef $cdb) $fname = "PopulateCDB_UnLockTray" $CDBCOMMAND = 0x1E ;Prevent/Allow Medium Removal DllStructSetData($cdb, 1, $CDBCOMMAND, 1) DllStructSetData($cdb, 1, 0x00, 2) DllStructSetData($cdb, 1, 0x00, 3) DllStructSetData($cdb, 1, 0x00, 4) DllStructSetData($cdb, 1, 0x00, 5); Unlock = Set bit 0 to 0 DllStructSetData($cdb, 1, 0x00, 6) DllStructSetData($cdb, 1, 0x00, 7) DllStructSetData($cdb, 1, 0x00, 8) DllStructSetData($cdb, 1, 0x00, 9) DllStructSetData($cdb, 1, 0x00, 10) DllStructSetData($cdb, 1, 0x00, 11) DllStructSetData($cdb, 1, 0x00, 12) ;The next four are not used for ATAPI compatibility, but should be set to zero anyway. DllStructSetData($cdb, 1, 0x00, 13) DllStructSetData($cdb, 1, 0x00, 14) DllStructSetData($cdb, 1, 0x00, 15) DllStructSetData($cdb, 1, 0x00, 16)EndFunc ;==>PopulateCDB_UnLockTray
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now