10f66f451Sopenharmony_ci/* eject.c - eject device.
20f66f451Sopenharmony_ci *
30f66f451Sopenharmony_ci * Copyright 2012 Harvind Singh <harvindsingh1981@gmail.com>
40f66f451Sopenharmony_ci * Copyright 2013 Kyungwan Han <asura321@gamil.com>
50f66f451Sopenharmony_ci *
60f66f451Sopenharmony_ci * No standard.
70f66f451Sopenharmony_ci
80f66f451Sopenharmony_ciUSE_EJECT(NEWTOY(eject, ">1stT[!tT]", TOYFLAG_USR|TOYFLAG_BIN))
90f66f451Sopenharmony_ci
100f66f451Sopenharmony_ciconfig EJECT
110f66f451Sopenharmony_ci  bool "eject"
120f66f451Sopenharmony_ci  default y
130f66f451Sopenharmony_ci  help
140f66f451Sopenharmony_ci    usage: eject [-stT] [DEVICE]
150f66f451Sopenharmony_ci
160f66f451Sopenharmony_ci    Eject DEVICE or default /dev/cdrom
170f66f451Sopenharmony_ci
180f66f451Sopenharmony_ci    -s	SCSI device
190f66f451Sopenharmony_ci    -t	Close tray
200f66f451Sopenharmony_ci    -T	Open/close tray (toggle)
210f66f451Sopenharmony_ci*/
220f66f451Sopenharmony_ci
230f66f451Sopenharmony_ci#define FOR_eject
240f66f451Sopenharmony_ci#include "toys.h"
250f66f451Sopenharmony_ci#include <scsi/sg.h>
260f66f451Sopenharmony_ci#include <scsi/scsi.h>
270f66f451Sopenharmony_ci#include <linux/cdrom.h>
280f66f451Sopenharmony_ci
290f66f451Sopenharmony_ci// SCSI's overcomplicated way of requesting eject
300f66f451Sopenharmony_cistatic void remove_scsi(int fd)
310f66f451Sopenharmony_ci{
320f66f451Sopenharmony_ci  unsigned i;
330f66f451Sopenharmony_ci  sg_io_hdr_t *header = (sg_io_hdr_t *)(toybuf+64);
340f66f451Sopenharmony_ci  char sg_driver_cmd[][6] = {
350f66f451Sopenharmony_ci    { ALLOW_MEDIUM_REMOVAL, 0, 0, 0, 0, 0 },
360f66f451Sopenharmony_ci    { START_STOP, 0, 0, 0, 1, 0 }, //start the motor
370f66f451Sopenharmony_ci    { START_STOP, 0, 0, 0, 2, 0 } //eject the media
380f66f451Sopenharmony_ci  };
390f66f451Sopenharmony_ci
400f66f451Sopenharmony_ci  header->interface_id = 'S';
410f66f451Sopenharmony_ci  header->cmd_len = 6;
420f66f451Sopenharmony_ci  header->mx_sb_len = 32;
430f66f451Sopenharmony_ci  header->dxfer_direction = SG_DXFER_NONE;
440f66f451Sopenharmony_ci  header->dxferp = toybuf + 32;
450f66f451Sopenharmony_ci  header->sbp = (void *)toybuf;
460f66f451Sopenharmony_ci  header->timeout = 2000;
470f66f451Sopenharmony_ci
480f66f451Sopenharmony_ci  for (i = 0; i < ARRAY_LEN(sg_driver_cmd); i++) {
490f66f451Sopenharmony_ci    header->cmdp = (void *)sg_driver_cmd[i];
500f66f451Sopenharmony_ci    xioctl(fd, SG_IO, header);
510f66f451Sopenharmony_ci  }
520f66f451Sopenharmony_ci
530f66f451Sopenharmony_ci  // force kernel to reread partition table when new disc is inserted
540f66f451Sopenharmony_ci  ioctl(fd, BLKRRPART);
550f66f451Sopenharmony_ci}
560f66f451Sopenharmony_ci
570f66f451Sopenharmony_civoid eject_main(void)
580f66f451Sopenharmony_ci{
590f66f451Sopenharmony_ci  int fd = xopen(*toys.optargs ? : "/dev/cdrom", O_RDONLY | O_NONBLOCK);
600f66f451Sopenharmony_ci
610f66f451Sopenharmony_ci  if (FLAG(s)) remove_scsi(fd);
620f66f451Sopenharmony_ci  else if (FLAG(T) && CDS_TRAY_OPEN == ioctl(fd, CDROM_DRIVE_STATUS, toybuf))
630f66f451Sopenharmony_ci    xioctl(fd, CDROMCLOSETRAY, toybuf);
640f66f451Sopenharmony_ci  else xioctl(fd, CDROMEJECT, toybuf);
650f66f451Sopenharmony_ci  if (CFG_TOYBOX_FREE) xclose(fd);
660f66f451Sopenharmony_ci}
67