Jump to content

Recommended Posts

Posted (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? :D

[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 by bhoar
Posted (edited)

Oh scrap that, still buggy. But at least the SCSI call is executing.

(removed attachment)

-brendan

Edited by bhoar
Posted (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? :D

Thanks to Robert Nelson for assistance.

-brendan

Edited by bhoar
Posted (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 by psandu.ro
Posted

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

Posted (edited)

Updated code with above change and to be better organized.

-brendan

Edited by bhoar
Posted

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. :D

-brendan

Posted

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.

-brendan

cdtray_routines.au3

Posted

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 everytime

i try $second_byte = DllStructGetData($sptwb, 16, 1) and nothing.

Posted

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

Posted (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. :D

See attached.

-brendan

cdtray_routines.au3

Edited by bhoar
Posted

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

  • 2 months later...
Posted

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

  • 3 weeks later...
  • 7 months later...
Posted

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.

Posted

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:

CODE
Func 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_LockTray

Func 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

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...