1 /* eject.c - eject device. 2 * 3 * Copyright 2012 Harvind Singh <harvindsingh1981 (at) gmail.com> 4 * Copyright 2013 Kyungwan Han <asura321 (at) gamil.com> 5 * 6 * No standard. 7 8 USE_EJECT(NEWTOY(eject, ">1stT[!tT]", TOYFLAG_USR|TOYFLAG_BIN)) 9 10 config 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 29 static 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 */ 59 void 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