diff options
Diffstat (limited to 'toys/other/eject.c')
-rw-r--r-- | toys/other/eject.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/toys/other/eject.c b/toys/other/eject.c new file mode 100644 index 00000000..279f7a31 --- /dev/null +++ b/toys/other/eject.c @@ -0,0 +1,89 @@ +/* eject.c - eject device. + * + * Copyright 2012 Harvind Singh <harvindsingh1981@gmail.com> + * Copyright 2013 Kyungwan Han <asura321@gamil.com> + * Not in SUSv4. + +USE_EJECT(NEWTOY(eject, ">1stT[!tT]", TOYFLAG_USR|TOYFLAG_BIN)) + +config EJECT + bool "eject" + default y + help + usage: eject [-s] [-t] [-T] [...] + + Eject DEVICE or default /dev/cdrom + + -s SCSI device + -t Close tray + -T Open/close tray (toggle). +*/ + +#define FOR_eject +#include "toys.h" +#include <scsi/sg.h> +#include <scsi/scsi.h> + +#define CDROM_DRIVE_STATUS 0x5326 //Get tray position, etc. +#define CDROM_CLOSE_TRAY 0x5319 //Pendant of CDROM_EJECT. +#define CDROM_EJECT 0x5309 //Ejects the cdrom media. +#define DRIVE_NOT_READY 3 //Drive is busy. + +/* + * Remove SCSI Device. + */ +static void remove_scsi(int dscptr) +{ + char sg_driver_cmd[3][6] = { + { ALLOW_MEDIUM_REMOVAL, 0, 0, 0, 0, 0 }, //allow medium removal + { START_STOP, 0, 0, 0, 1, 0 }, //start the motor + { START_STOP, 0, 0, 0, 2, 0 } //eject the media + }; + + unsigned i; + unsigned char buffer1[32],buffer2[2]; + sg_io_hdr_t in_out_header; + + if ((ioctl(dscptr, SG_GET_VERSION_NUM, &i) < 0) || (i < 30000)) + error_exit("not a sg device or old sg driver"); + + memset(&in_out_header, 0, sizeof(sg_io_hdr_t)); + in_out_header.interface_id = 'S'; + in_out_header.cmd_len = 6; + in_out_header.mx_sb_len = sizeof(buffer1); + in_out_header.dxfer_direction = SG_DXFER_NONE; + in_out_header.dxferp = buffer2; + in_out_header.sbp = buffer1; + in_out_header.timeout = 2000; + + for (i = 0; i < 3; i++) { + in_out_header.cmdp = (void *)sg_driver_cmd[i]; + xioctl(dscptr, SG_IO, (void *)&in_out_header); + } + /* force kernel to reread partition table when new disc is inserted */ + ioctl(dscptr, BLKRRPART); +} + +/* + * eject main function. + */ +void eject_main(void) +{ + int fd, out = 0, rc = 0; + char *device_name; + if (!toys.optc) device_name = "/dev/cdrom"; + else device_name = toys.optargs[0]; + + fd = xopen(device_name, O_RDONLY | O_NONBLOCK); + if (!toys.optflags) xioctl(fd, CDROM_EJECT, &out); + else if (toys.optflags & FLAG_s) remove_scsi(fd); + else { + if (toys.optflags & FLAG_T || toys.optflags & FLAG_t) { + rc = ioctl(fd, CDROM_DRIVE_STATUS, &out); + if (toys.optflags & FLAG_t || rc == 2) //CDS_TRAY_OPEN = 2 + xioctl(fd, CDROM_CLOSE_TRAY, &out); + else xioctl(fd, CDROM_EJECT, &out); + } + } + xclose(fd); +} |