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
8USE_EJECT(NEWTOY(eject, ">1stT[!tT]", TOYFLAG_USR|TOYFLAG_BIN))
9
10config 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
29static 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 */
59void 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