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