1#!/usr/bin/perl -w
2# Eject using mode change
3# $Rev: 114 $ $Date: 2009-10-19 14:01:11 +0100 (Mon, 19 Oct 2009) $
4
5use Fcntl;
6use Config;
7use Sys::Syslog;
8
9$dev = shift @ARGV;
10$method = shift @ARGV;
11
12#
13# Use the old eject method if specified
14#
15
16if (! $method)
17{
18    # Use classic eject method
19    -x "/usr/sbin/eject" and exec "/usr/sbin/eject $dev";
20    -x "/usr/bin/eject" and exec "/usr/bin/eject $dev";
21    -x "/bin/eject" and exec "/bin/eject $dev";
22    system "eject $dev";
23    exit 0;
24}
25
26openlog( $0, "nofatal", "local0" );
27
28#
29# Some time sensitive condition exists on some versions of some distributions.
30# Have a few attempts at finding the device before sending the IOCTL command.
31# Sleep for a second after each failed attempt and give up after 5.
32#
33
34$found_dev = 0;
35for ($i=0 ; $i<5 ; $i++ )
36{
37    if (sysopen(USB, $dev, O_RDWR))
38    {
39        $found_dev = 1;
40        next;
41    }
42    else
43    {
44        sleep 1;
45    } 
46}
47
48if (! $found_dev)
49{
50    syslog( "error", "Unable to find given device: $dev\n" );
51    syslog( "error", "$!" );
52}
53else
54{
55    syslog( "info", "Found device $dev\n" );
56    
57    #struct usbdevfs_ctrltransfer {
58    #	__u8 bRequestType;
59    #	__u8 bRequest;
60    #	__u16 wValue;
61    #	__u16 wIndex;
62    #	__u16 wLength;
63    #	__u32 timeout;  /* in milliseconds */
64    #	void *data;
65    #};
66
67    #    ctrl_transfer.bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
68    #    ctrl_transfer.bRequest = 1;
69    #    ctrl_transfer.wValue = 0;
70    #    ctrl_transfer.wIndex = 2;
71
72    $buffer = pack("CCSSSLxxxxxxxx", (0x02 << 5), 0x0a, 0, 0, 0, 0);
73
74    #define USBDEVFS_CONTROL           _IOWR('U', 0, struct usbdevfs_ctrltransfer)
75    $ioctl = ($Config{longsize} == 8) ? 0xc0185500 : 0xc0105500;
76
77    ioctl(USB, $ioctl, $buffer) or syslog( "warning", "USB ioctl error $!\n" );
78    close USB
79}
80
81closelog();
82