1 /* eject.c - eject device.
2  *
3  * Copyright 2012 Harvind Singh <harvindsingh1981@gmail.com>
4  * Copyright 2013 Kyungwan Han <asura321@gamil.com>
5  *
6  * No standard.
7 
8 USE_EJECT(NEWTOY(eject, ">1stT[!tT]", TOYFLAG_USR|TOYFLAG_BIN))
9 
10 config EJECT
11   bool "eject"
12   default y
13   help
14     usage: eject [-stT] [DEVICE]
15 
16     Eject DEVICE or default /dev/cdrom
17 
18     -s	SCSI device
19     -t	Close tray
20     -T	Open/close tray (toggle).
21 */
22 
23 #define FOR_eject
24 #include "toys.h"
25 #include <scsi/sg.h>
26 #include <scsi/scsi.h>
27 
28 // The SCSI way of requesting eject
remove_scsi(int fd)29 static void remove_scsi(int fd)
30 {
31   unsigned i;
32   sg_io_hdr_t *header = (sg_io_hdr_t *)(toybuf+64);
33   char sg_driver_cmd[3][6] = {
34     { ALLOW_MEDIUM_REMOVAL, 0, 0, 0, 0, 0 },
35     { START_STOP, 0, 0, 0, 1, 0 }, //start the motor
36     { START_STOP, 0, 0, 0, 2, 0 } //eject the media
37   };
38 
39   header->interface_id = 'S';
40   header->cmd_len = 6;
41   header->mx_sb_len = 32;
42   header->dxfer_direction = SG_DXFER_NONE;
43   header->dxferp = toybuf + 32;
44   header->sbp = (void *)toybuf;
45   header->timeout = 2000;
46 
47   for (i = 0; i < 3; i++) {
48     header->cmdp = (void *)sg_driver_cmd[i];
49     xioctl(fd, SG_IO, (void *)header);
50   }
51 
52   // force kernel to reread partition table when new disc is inserted
53   ioctl(fd, BLKRRPART);
54 }
55 
56 /*
57  * eject main function.
58  */
eject_main(void)59 void eject_main(void)
60 {
61   int fd, out = 0;
62   char *device_name = "/dev/cdrom";
63 
64   if (*toys.optargs) device_name = *toys.optargs;
65 
66   fd = xopen(device_name, O_RDONLY | O_NONBLOCK);
67   if (!toys.optflags) xioctl(fd, 0x5309, &out);		// CDROM_EJECT
68   else if (toys.optflags & FLAG_s) remove_scsi(fd);
69   else {
70     if ((toys.optflags & FLAG_T) || (toys.optflags & FLAG_t)) {
71       int rc = ioctl(fd, 0x5326, &out);			// CDROM_DRIVE_STATUS
72       if ((toys.optflags & FLAG_t) || rc == 2)		// CDS_TRAY_OPEN
73         xioctl(fd, 0x5319, &out);			// CDROM_CLOSE_TRAY
74       else xioctl(fd, 0x5309, &out);			// CDROM_EJECT
75     }
76   }
77   if (CFG_TOYBOX_FREE) xclose(fd);
78 }
79