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