• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <linux/cdrom.h>
28 
29 // SCSI's overcomplicated way of requesting eject
remove_scsi(int fd)30 static void remove_scsi(int fd)
31 {
32   unsigned i;
33   sg_io_hdr_t *header = (sg_io_hdr_t *)(toybuf+64);
34   char sg_driver_cmd[][6] = {
35     { ALLOW_MEDIUM_REMOVAL, 0, 0, 0, 0, 0 },
36     { START_STOP, 0, 0, 0, 1, 0 }, //start the motor
37     { START_STOP, 0, 0, 0, 2, 0 } //eject the media
38   };
39 
40   header->interface_id = 'S';
41   header->cmd_len = 6;
42   header->mx_sb_len = 32;
43   header->dxfer_direction = SG_DXFER_NONE;
44   header->dxferp = toybuf + 32;
45   header->sbp = (void *)toybuf;
46   header->timeout = 2000;
47 
48   for (i = 0; i < ARRAY_LEN(sg_driver_cmd); i++) {
49     header->cmdp = (void *)sg_driver_cmd[i];
50     xioctl(fd, SG_IO, header);
51   }
52 
53   // force kernel to reread partition table when new disc is inserted
54   ioctl(fd, BLKRRPART);
55 }
56 
eject_main(void)57 void eject_main(void)
58 {
59   int fd = xopen(*toys.optargs ? : "/dev/cdrom", O_RDONLY | O_NONBLOCK);
60 
61   if (FLAG(s)) remove_scsi(fd);
62   else if (FLAG(T) && CDS_TRAY_OPEN == ioctl(fd, CDROM_DRIVE_STATUS, toybuf))
63     xioctl(fd, CDROMCLOSETRAY, toybuf);
64   else xioctl(fd, CDROMEJECT, toybuf);
65   if (CFG_TOYBOX_FREE) xclose(fd);
66 }
67