xref: /third_party/toybox/toys/other/eject.c (revision 0f66f451)
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#include <linux/cdrom.h>
28
29// SCSI's overcomplicated way of requesting eject
30static 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
57void 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