LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Distributions > Slackware
User Name
Password
Slackware This Forum is for the discussion of Slackware Linux.

Notices


Reply
  Search this Thread
Old 02-18-2013, 01:21 AM   #1
Woodsman
Senior Member
 
Registered: Oct 2005
Distribution: Slackware 14.1
Posts: 3,482

Rep: Reputation: 546Reputation: 546Reputation: 546Reputation: 546Reputation: 546Reputation: 546
Detect CD tray status


Superfluous project of the day:

I'm looking for a way to detect a CD drive tray status.

Background: I have a vintage system with a nice CD writer but the drive does not support the eject -T command. I can only use eject or eject -t. On all of my other systems I have a handy desktop shortcut with the eject -T command. I can't use that shortcut with this drive --- I need two shortcuts.

I prefer to detect the tray status with the stock Slackware tools. I've seen some possible solutions but they require lshw or hwinfo. The /usr/include/linux/cdrom.h has a CDROM_DRIVE_STATUS option, but I'm not a C coder.

All I seek is something like this:

Code:
if [ $TRAY_IS_OPEN ];
  eject -t
else
  eject
fi
Using lshw, which is not part of the stock Slackware, I can use something like this (slow --- takes a few seconds to execute):

Code:
if [ "`/usr/sbin/lshw -quiet 2>/dev/null | awk '/\*-cd/,/con/' | sed -e 's/^[ \t]*//' | grep configuration | cut -d ' ' -f3`" = "status=open" ]; then
  eject -t
else
  eject
fi
Seems if lshw can pull the information that the information exists somewhere. I've been looking into /proc, sg3_utils, and udisks, but haven't found anything. Too bad the eject command is not a little more robust.

Thanks.
 
Old 02-18-2013, 02:01 AM   #2
volkerdi
Slackware Maintainer
 
Registered: Dec 2002
Location: Minnesota
Distribution: Slackware! :-)
Posts: 2,504

Rep: Reputation: 8461Reputation: 8461Reputation: 8461Reputation: 8461Reputation: 8461Reputation: 8461Reputation: 8461Reputation: 8461Reputation: 8461Reputation: 8461Reputation: 8461
Here's a simple C program:

Code:
#include <sys/ioctl.h>
#include <fcntl.h>
#include <linux/cdrom.h>

int main(int argc,char **argv) {
    int cdrom;
    int status=1;

    if ((cdrom = open(argv[1],O_RDONLY | O_NONBLOCK)) < 0) {
        printf("Unable to open device %s",argv[1]);
        exit(1);
    }

    if (ioctl(cdrom,CDROM_DRIVE_STATUS) == CDS_TRAY_OPEN) {
        status=0;
    }

    close(cdrom);
    exit(status);
}
Compile it with gcc, call it trayopen. Then you can use it in scripts based on the exit code, like so:

./trayopen /dev/sr0 && echo tray is open || echo tray is closed
 
2 members found this post helpful.
Old 02-18-2013, 12:46 PM   #3
Woodsman
Senior Member
 
Registered: Oct 2005
Distribution: Slackware 14.1
Posts: 3,482

Original Poster
Rep: Reputation: 546Reputation: 546Reputation: 546Reputation: 546Reputation: 546Reputation: 546
Pat, that is very kind of you. Thank you!

I'm not a C coder but I can read uncomplicated C code and write a basic printf command. Because I tend to forget things as I age, here is version 0.2 with some reminders for me how to use. I added two includes to fix the compile warnings (I had to search the web to learn how to do that ).

Code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <linux/cdrom.h>

int main(int argc,char **argv) {
  int cdrom;
  int status=1;

  printf("Usage: trayopen [device]\n");
  printf("Result: Open tray exit code 0, closed tray exit code 1.\n");

  if ((cdrom = open(argv[1],O_RDONLY | O_NONBLOCK)) < 0) {
    printf("Unable to open device %s. Provide a device name (/dev/sr0, /dev/cdrom) as a parameter.\n",argv[1]);
    exit(1);
  }

  if (ioctl(cdrom,CDROM_DRIVE_STATUS) == CDS_TRAY_OPEN) {
    status=0;
  }

  close(cdrom);
  exit(status);
}
I wonder whether the eject source code could be patched with something similar to your simple program? Seems the "eject -T" parameter needs only to query the status of the device as you did and then the -T option would work on any optical disk device.
 
Old 02-18-2013, 01:56 PM   #4
volkerdi
Slackware Maintainer
 
Registered: Dec 2002
Location: Minnesota
Distribution: Slackware! :-)
Posts: 2,504

Rep: Reputation: 8461Reputation: 8461Reputation: 8461Reputation: 8461Reputation: 8461Reputation: 8461Reputation: 8461Reputation: 8461Reputation: 8461Reputation: 8461Reputation: 8461
Quote:
Originally Posted by Woodsman View Post
I wonder whether the eject source code could be patched with something similar to your simple program? Seems the "eject -T" parameter needs only to query the status of the device as you did and then the -T option would work on any optical disk device.
Could the solution be as simple as something like "eject -T -s /dev/sr0"?

Long shot, but it's worth a try.
 
1 members found this post helpful.
Old 02-18-2013, 02:37 PM   #5
GazL
LQ Veteran
 
Registered: May 2008
Posts: 6,897

Rep: Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019
LOL. Out of curiosity I just looked at the code that does the toggle in eject, and it basically does this:
  1. gets time of day
  2. opens tray
  3. gets time of day
  4. compare times
  5. if it opened very quickly then it must have already been open so close tray.




Anyway, try this patch. It replaces the eject_for_mac.patch file in the slackbuild. (Needs to be applied with -p1 not -p4).
Works on my box, but no idea how it will behave on other people's machines

Last edited by GazL; 02-19-2013 at 05:40 AM.
 
Old 02-18-2013, 03:57 PM   #6
Woodsman
Senior Member
 
Registered: Oct 2005
Distribution: Slackware 14.1
Posts: 3,482

Original Poster
Rep: Reputation: 546Reputation: 546Reputation: 546Reputation: 546Reputation: 546Reputation: 546
Quote:
Could the solution be as simple as something like "eject -T -s /dev/sr0"?
Nope. Been there done that.

Quote:
LOL. Out of curiosity I just looked at the code that does the toggle in eject, and it basically does this:
Last night I looked at the eject.c sources. I am not a C coder but I saw the same thing. Because I'm not a C coder I presumed I was not seeing something obvious. Nice to see that I was not far off base.

Quote:
Anyway, try this patch.
I'll give that a whirl and report later.
 
Old 02-18-2013, 04:29 PM   #7
Woodsman
Senior Member
 
Registered: Oct 2005
Distribution: Slackware 14.1
Posts: 3,482

Original Poster
Rep: Reputation: 546Reputation: 546Reputation: 546Reputation: 546Reputation: 546Reputation: 546
My report:

I tested on 4 systems here.

On two modern systems, eject -T works with the stock Slackware eject and the newly patched eject.

On a PI system with a Creative Labs (MATSHITA CR-585 ZU17) 24x CD-ROM, the stock eject -T works to open and close the drive, but the new patched version does not. With the new patch eject -T opens the tray but will not close. Further, the C code Pat provided does not correctly reflect the tray status on this machine. That is, the trayopen command reports the tray is closed when the tray is open.

On a PII system, the original problem system that started this thread, the stock Slackware eject -T does not close the tray. The newly patched version works both to open and close. That system has a HP CD-Writer+ 9300 1.0c 10x/4x/32x CD Recorder.

So with the stock eject the PI system works correctly with eject -T but not with the PII system. The newly patched eject works with the PII system but not the PI.

Seems some combination of the new patch and the "mac" patch are needed.
 
Old 02-18-2013, 04:37 PM   #8
GazL
LQ Veteran
 
Registered: May 2008
Posts: 6,897

Rep: Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019
Pat's code above doesn't check for errors from the ioctl so if you get a 1 you don't know whether it's because the call failed or the drive is closed. If you run strace eject -T /dev/sr0 you'll see the results of the ioctls at the end of the output. You can also use strace on pats trayopen command.

What kernels are your older boxes using?

The patch I provided includes the change that the mac patch was making previously, so I don't think that matters.


Perhaps the answer is to include the time based operation as a fallback if CDROM_DRIVE_STATUS doesn't work. Maybe that would sort out your P1 machine.
If you could show me the last bit of the strace on the one that doesn't work I'll see what I can do.

Last edited by GazL; 02-18-2013 at 04:46 PM.
 
Old 02-18-2013, 05:58 PM   #9
GazL
LQ Veteran
 
Registered: May 2008
Posts: 6,897

Rep: Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019
Ok, I took a guess that the MATSHITA drive was returning CDS_NO_INFO for the CDROM_DRIVE_STATUS query.

Here's an updated patch if you want to try it.

Last edited by GazL; 02-19-2013 at 05:40 AM.
 
Old 02-18-2013, 06:01 PM   #10
Woodsman
Senior Member
 
Registered: Oct 2005
Distribution: Slackware 14.1
Posts: 3,482

Original Poster
Rep: Reputation: 546Reputation: 546Reputation: 546Reputation: 546Reputation: 546Reputation: 546
Quote:
What kernels are your older boxes using?
I'm using the stock 3.2.29 non-smp kernels with Slackware 14.

Quote:
Maybe that would sort out your P1 machine. If you could show me the last bit of the strace on the one that doesn't work I'll see what I can do.
At this point I'm interested in a patch that Pat can merge to help everybody.

That said, attached are the last few lines from 8 straces.

======================================================
PI, stock Slackware (eject -T works to open and close)
======================================================

Tray is closed, attempt to open:
================================
stat64("/dev/sr0", {st_mode=S_IFBLK|0660, st_rdev=makedev(11, 0), ...}) = 0
open("/dev/sr0", O_RDONLY|O_NONBLOCK) = 3
gettimeofday({1361231138, 960547}, NULL) = 0
ioctl(3, CDROMEJECT, 0) = 0
gettimeofday({1361231140, 894047}, NULL) = 0
exit_group(0) = ?

Tray is open, attempt to close:
===============================
stat64("/dev/sr0", {st_mode=S_IFBLK|0660, st_rdev=makedev(11, 0), ...}) = 0
open("/dev/sr0", O_RDONLY|O_NONBLOCK) = 3
gettimeofday({1361231159, 60890}, NULL) = 0
ioctl(3, CDROMEJECT, 0) = 0
gettimeofday({1361231159, 194454}, NULL) = 0
ioctl(3, CDROMCLOSETRAY, 0) = 0
exit_group(0) = ?

=====================================================
PI, newly patched (eject -T opens but fails to close)
=====================================================

Tray is closed, attempt to open:
================================
stat64("/dev/sr0", {st_mode=S_IFBLK|0660, st_rdev=makedev(11, 0), ...}) = 0
open("/dev/sr0", O_RDONLY|O_NONBLOCK) = 3
ioctl(3, CDROM_DRIVE_STATUS, 0x804b82c) = 1
ioctl(3, CDROMEJECT, 0) = 0
exit_group(0) = ?

Tray is open, attempt to close FAILS:
=====================================
stat64("/dev/sr0", {st_mode=S_IFBLK|0660, st_rdev=makedev(11, 0), ...}) = 0
open("/dev/sr0", O_RDONLY|O_NONBLOCK) = 3
ioctl(3, CDROM_DRIVE_STATUS, 0x804b82c) = 1
ioctl(3, CDROMEJECT, 0) = 0
exit_group(0) = ?


========================================================
PII, stock Slackware (eject -T opens but fails to close)
========================================================

Tray is closed, attempt to open:
================================
stat64("/dev/sr0", {st_mode=S_IFBLK|0660, st_rdev=makedev(11, 0), ...}) = 0
open("/dev/sr0", O_RDONLY|O_NONBLOCK) = 3
gettimeofday({1361231700, 129791}, NULL) = 0
ioctl(3, CDROMEJECT, 0) = 0
gettimeofday({1361231702, 429991}, NULL) = 0
exit_group(0) = ?

Tray is open, attempt to close FAILS:
=====================================
stat64("/dev/sr0", {st_mode=S_IFBLK|0660, st_rdev=makedev(11, 0), ...}) = 0
open("/dev/sr0", O_RDONLY|O_NONBLOCK) = 3
gettimeofday({1361231750, 488658}, NULL) = 0
ioctl(3, CDROMEJECT, 0) = 0
gettimeofday({1361231751, 180760}, NULL) = 0
exit_group(0) = ?

=====================================================
PII, newly patched (eject -T works to open and close)
=====================================================

Tray is closed, attempt to open:
================================
stat64("/dev/sr0", {st_mode=S_IFBLK|0660, st_rdev=makedev(11, 0), ...}) = 0
open("/dev/sr0", O_RDONLY|O_NONBLOCK) = 3
ioctl(3, CDROM_DRIVE_STATUS, 0x804b82c) = 1
ioctl(3, CDROMEJECT, 0) = 0
exit_group(0) = ?

Tray is open, attempt to close:
===============================
stat64("/dev/sr0", {st_mode=S_IFBLK|0660, st_rdev=makedev(11, 0), ...}) = 0
open("/dev/sr0", O_RDONLY|O_NONBLOCK) = 3
ioctl(3, CDROM_DRIVE_STATUS, 0x804b82c) = 2
ioctl(3, CDROMCLOSETRAY, 0x804b82c) = 0
exit_group(0) = ?
 
1 members found this post helpful.
Old 02-18-2013, 06:02 PM   #11
Woodsman
Senior Member
 
Registered: Oct 2005
Distribution: Slackware 14.1
Posts: 3,482

Original Poster
Rep: Reputation: 546Reputation: 546Reputation: 546Reputation: 546Reputation: 546Reputation: 546
Quote:
Here's an updated patch if you want to try it.
Oops! Are posts crossed paths.

I'll test right away.
 
Old 02-18-2013, 06:08 PM   #12
Woodsman
Senior Member
 
Registered: Oct 2005
Distribution: Slackware 14.1
Posts: 3,482

Original Poster
Rep: Reputation: 546Reputation: 546Reputation: 546Reputation: 546Reputation: 546Reputation: 546
Same results. The PI works with the stock eject -T but with the new second patch only opens. The PII opens with the stock eject but will not close. With the new second patch the tray opens and closes.

====================================================
PI, second patch (eject -T opens but fails to close)
====================================================

Tray is closed, attempt to open:
================================
stat64("/dev/sr0", {st_mode=S_IFBLK|0660, st_rdev=makedev(11, 0), ...}) = 0
open("/dev/sr0", O_RDONLY|O_NONBLOCK) = 3
ioctl(3, CDROM_DRIVE_STATUS, 0) = 1
ioctl(3, CDROMEJECT, 0) = 0
exit_group(0) = ?

Tray is open, attempt to close FAILS:
=====================================
stat64("/dev/sr0", {st_mode=S_IFBLK|0660, st_rdev=makedev(11, 0), ...}) = 0
open("/dev/sr0", O_RDONLY|O_NONBLOCK) = 3
ioctl(3, CDROM_DRIVE_STATUS, 0) = 1
ioctl(3, CDROMEJECT, 0) = 0
exit_group(0) = ?
 
Old 02-18-2013, 06:20 PM   #13
GazL
LQ Veteran
 
Registered: May 2008
Posts: 6,897

Rep: Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019
Code:
=====================================================
 PI, newly patched (eject -T opens but fails to close)
 =====================================================

 Tray is open, attempt to close FAILS:
 =====================================
 stat64("/dev/sr0", {st_mode=S_IFBLK|0660, st_rdev=makedev(11, 0), ...}) = 0
 open("/dev/sr0", O_RDONLY|O_NONBLOCK) = 3
 ioctl(3, CDROM_DRIVE_STATUS, 0x804b82c) = 1
 ioctl(3, CDROMEJECT, 0) = 0
 exit_group(0) = ?
Ahh, that's the problem there. I don't think my v2 will help (unless the ', 0') I added to the ioctl call helps ( edit: which I see it didn't ).
Your MATSHITSA drive is returning CDS_NO_DISC to CDROM_DRIVE_STATUS whether the drive is open or closed.

Damn! Off-hand, I don't see any way around that.

Last edited by GazL; 02-18-2013 at 06:24 PM.
 
Old 02-18-2013, 07:07 PM   #14
GazL
LQ Veteran
 
Registered: May 2008
Posts: 6,897

Rep: Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019
The problem with your PII and the stock eject seems to be that its responding too slowly to the first CDROMEJECT of an already open drive to meet the conditions
in the TRAY_WAS_ALREADY_OPEN_USECS check and thus never trying to close it. You could try increasing that time limit, but the danger is that if you set it too high it may trigger a close instead of an open for some drives when you're trying to open them.

I've attached a v3 of the patch, Basically it'll check for CDS_TRAY_OPEN first, and then fall back to the old mechanism for everything else.

Anyway, here it is for what it is worth. I don't think I'd suggest it for inclusion in stock slackware though. It might sort your specific problems out, but IMO it's only half a solution and version 2 or even the version 1 of my patch are more correct (but unfortunately won't work with your aptly named MATSHITA drive which doesn't provide accurate status.

Last edited by GazL; 02-19-2013 at 05:40 AM.
 
Old 02-18-2013, 07:42 PM   #15
Woodsman
Senior Member
 
Registered: Oct 2005
Distribution: Slackware 14.1
Posts: 3,482

Original Poster
Rep: Reputation: 546Reputation: 546Reputation: 546Reputation: 546Reputation: 546Reputation: 546
Quote:
Anyway, here it is for what it is worth.
Revision 3 works on all systems here. Good job!

Quote:
I don't think I'd suggest it for inclusion in stock slackware though.
Perhaps if other people with quirky optical drives find the patch useful that might provide some motivation.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] How to detect eth0 status? kakaburra Slackware 10 08-30-2009 02:28 AM
Cdrom tray status freeindy Linux - Hardware 4 09-30-2008 01:30 PM
How can a process detect the status of a signal bluehive Linux - Newbie 5 01-22-2008 12:23 PM
how to auto detect the status of sendmail!!!!!!!!!! dhanju Linux - Networking 5 10-22-2005 06:35 AM
Detect CD tray load mattkat Linux - Hardware 1 05-31-2004 06:00 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Distributions > Slackware

All times are GMT -5. The time now is 09:31 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration