2 * cdrom_id - optical drive and media information prober
4 * Copyright (C) 2008-2010 Kay Sievers <kay@vrfy.org>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include <linux/cdrom.h>
30 #include <sys/ioctl.h>
33 #include <sys/types.h>
37 #include "libudev-private.h"
39 #include "random-util.h"
42 static unsigned int cd_cd_rom
;
43 static unsigned int cd_cd_r
;
44 static unsigned int cd_cd_rw
;
45 static unsigned int cd_dvd_rom
;
46 static unsigned int cd_dvd_r
;
47 static unsigned int cd_dvd_rw
;
48 static unsigned int cd_dvd_ram
;
49 static unsigned int cd_dvd_plus_r
;
50 static unsigned int cd_dvd_plus_rw
;
51 static unsigned int cd_dvd_plus_r_dl
;
52 static unsigned int cd_dvd_plus_rw_dl
;
53 static unsigned int cd_bd
;
54 static unsigned int cd_bd_r
;
55 static unsigned int cd_bd_re
;
56 static unsigned int cd_hddvd
;
57 static unsigned int cd_hddvd_r
;
58 static unsigned int cd_hddvd_rw
;
59 static unsigned int cd_mo
;
60 static unsigned int cd_mrw
;
61 static unsigned int cd_mrw_w
;
64 static unsigned int cd_media
;
65 static unsigned int cd_media_cd_rom
;
66 static unsigned int cd_media_cd_r
;
67 static unsigned int cd_media_cd_rw
;
68 static unsigned int cd_media_dvd_rom
;
69 static unsigned int cd_media_dvd_r
;
70 static unsigned int cd_media_dvd_rw
;
71 static unsigned int cd_media_dvd_rw_ro
; /* restricted overwrite mode */
72 static unsigned int cd_media_dvd_rw_seq
; /* sequential mode */
73 static unsigned int cd_media_dvd_ram
;
74 static unsigned int cd_media_dvd_plus_r
;
75 static unsigned int cd_media_dvd_plus_rw
;
76 static unsigned int cd_media_dvd_plus_r_dl
;
77 static unsigned int cd_media_dvd_plus_rw_dl
;
78 static unsigned int cd_media_bd
;
79 static unsigned int cd_media_bd_r
;
80 static unsigned int cd_media_bd_re
;
81 static unsigned int cd_media_hddvd
;
82 static unsigned int cd_media_hddvd_r
;
83 static unsigned int cd_media_hddvd_rw
;
84 static unsigned int cd_media_mo
;
85 static unsigned int cd_media_mrw
;
86 static unsigned int cd_media_mrw_w
;
88 static const char *cd_media_state
= NULL
;
89 static unsigned int cd_media_session_next
;
90 static unsigned int cd_media_session_count
;
91 static unsigned int cd_media_track_count
;
92 static unsigned int cd_media_track_count_data
;
93 static unsigned int cd_media_track_count_audio
;
94 static unsigned long long int cd_media_session_last_offset
;
96 #define ERRCODE(s) ((((s)[2] & 0x0F) << 16) | ((s)[12] << 8) | ((s)[13]))
97 #define SK(errcode) (((errcode) >> 16) & 0xF)
98 #define ASC(errcode) (((errcode) >> 8) & 0xFF)
99 #define ASCQ(errcode) ((errcode) & 0xFF)
101 static bool is_mounted(const char *device
)
106 bool mounted
= false;
108 if (stat(device
, &statbuf
) < 0)
111 fp
= fopen("/proc/self/mountinfo", "re");
114 while (fscanf(fp
, "%*s %*s %i:%i %*[^\n]", &maj
, &min
) == 2) {
115 if (makedev(maj
, min
) == statbuf
.st_rdev
) {
124 static void info_scsi_cmd_err(struct udev
*udev
, const char *cmd
, int err
)
127 log_debug("%s failed", cmd
);
130 log_debug("%s failed with SK=%Xh/ASC=%02Xh/ACQ=%02Xh", cmd
, SK(err
), ASC(err
), ASCQ(err
));
134 struct cdrom_generic_command cgc
;
136 struct request_sense s
;
139 struct sg_io_hdr sg_io
;
142 static void scsi_cmd_init(struct udev
*udev
, struct scsi_cmd
*cmd
)
144 memzero(cmd
, sizeof(struct scsi_cmd
));
146 cmd
->cgc
.sense
= &cmd
->_sense
.s
;
147 cmd
->sg_io
.interface_id
= 'S';
148 cmd
->sg_io
.mx_sb_len
= sizeof(cmd
->_sense
);
149 cmd
->sg_io
.cmdp
= cmd
->cgc
.cmd
;
150 cmd
->sg_io
.sbp
= cmd
->_sense
.u
;
151 cmd
->sg_io
.flags
= SG_FLAG_LUN_INHIBIT
| SG_FLAG_DIRECT_IO
;
154 static void scsi_cmd_set(struct udev
*udev
, struct scsi_cmd
*cmd
, size_t i
, unsigned char arg
)
156 cmd
->sg_io
.cmd_len
= i
+ 1;
157 cmd
->cgc
.cmd
[i
] = arg
;
160 #define CHECK_CONDITION 0x01
162 static int scsi_cmd_run(struct udev
*udev
, struct scsi_cmd
*cmd
, int fd
, unsigned char *buf
, size_t bufsize
)
167 cmd
->sg_io
.dxferp
= buf
;
168 cmd
->sg_io
.dxfer_len
= bufsize
;
169 cmd
->sg_io
.dxfer_direction
= SG_DXFER_FROM_DEV
;
171 cmd
->sg_io
.dxfer_direction
= SG_DXFER_NONE
;
173 if (ioctl(fd
, SG_IO
, &cmd
->sg_io
))
176 if ((cmd
->sg_io
.info
& SG_INFO_OK_MASK
) != SG_INFO_OK
) {
179 if (cmd
->sg_io
.masked_status
& CHECK_CONDITION
) {
180 ret
= ERRCODE(cmd
->_sense
.u
);
188 static int media_lock(struct udev
*udev
, int fd
, bool lock
)
192 /* disable the kernel's lock logic */
193 err
= ioctl(fd
, CDROM_CLEAR_OPTIONS
, CDO_LOCK
);
195 log_debug("CDROM_CLEAR_OPTIONS, CDO_LOCK failed");
197 err
= ioctl(fd
, CDROM_LOCKDOOR
, lock
? 1 : 0);
199 log_debug("CDROM_LOCKDOOR failed");
204 static int media_eject(struct udev
*udev
, int fd
)
209 scsi_cmd_init(udev
, &sc
);
210 scsi_cmd_set(udev
, &sc
, 0, 0x1b);
211 scsi_cmd_set(udev
, &sc
, 4, 0x02);
212 scsi_cmd_set(udev
, &sc
, 5, 0);
213 err
= scsi_cmd_run(udev
, &sc
, fd
, NULL
, 0);
215 info_scsi_cmd_err(udev
, "START_STOP_UNIT", err
);
221 static int cd_capability_compat(struct udev
*udev
, int fd
)
225 capability
= ioctl(fd
, CDROM_GET_CAPABILITY
, NULL
);
226 if (capability
< 0) {
227 log_debug("CDROM_GET_CAPABILITY failed");
231 if (capability
& CDC_CD_R
)
233 if (capability
& CDC_CD_RW
)
235 if (capability
& CDC_DVD
)
237 if (capability
& CDC_DVD_R
)
239 if (capability
& CDC_DVD_RAM
)
241 if (capability
& CDC_MRW
)
243 if (capability
& CDC_MRW_W
)
248 static int cd_media_compat(struct udev
*udev
, int fd
)
250 if (ioctl(fd
, CDROM_DRIVE_STATUS
, CDSL_CURRENT
) != CDS_DISC_OK
) {
251 log_debug("CDROM_DRIVE_STATUS != CDS_DISC_OK");
258 static int cd_inquiry(struct udev
*udev
, int fd
)
261 unsigned char inq
[128];
264 scsi_cmd_init(udev
, &sc
);
265 scsi_cmd_set(udev
, &sc
, 0, 0x12);
266 scsi_cmd_set(udev
, &sc
, 4, 36);
267 scsi_cmd_set(udev
, &sc
, 5, 0);
268 err
= scsi_cmd_run(udev
, &sc
, fd
, inq
, 36);
270 info_scsi_cmd_err(udev
, "INQUIRY", err
);
274 if ((inq
[0] & 0x1F) != 5) {
275 log_debug("not an MMC unit");
279 log_debug("INQUIRY: [%.8s][%.16s][%.4s]", inq
+ 8, inq
+ 16, inq
+ 32);
283 static void feature_profile_media(struct udev
*udev
, int cur_profile
)
285 switch (cur_profile
) {
289 log_debug("profile 0x%02x ", cur_profile
);
294 log_debug("profile 0x%02x media_cd_rom", cur_profile
);
299 log_debug("profile 0x%02x media_cd_r", cur_profile
);
304 log_debug("profile 0x%02x media_cd_rw", cur_profile
);
309 log_debug("profile 0x%02x media_dvd_ro", cur_profile
);
311 cd_media_dvd_rom
= 1;
314 log_debug("profile 0x%02x media_dvd_r", cur_profile
);
319 log_debug("profile 0x%02x media_dvd_ram", cur_profile
);
321 cd_media_dvd_ram
= 1;
324 log_debug("profile 0x%02x media_dvd_rw_ro", cur_profile
);
327 cd_media_dvd_rw_ro
= 1;
330 log_debug("profile 0x%02x media_dvd_rw_seq", cur_profile
);
333 cd_media_dvd_rw_seq
= 1;
336 log_debug("profile 0x%02x media_dvd_plus_r", cur_profile
);
338 cd_media_dvd_plus_r
= 1;
341 log_debug("profile 0x%02x media_dvd_plus_rw", cur_profile
);
343 cd_media_dvd_plus_rw
= 1;
346 log_debug("profile 0x%02x media_dvd_plus_rw_dl", cur_profile
);
348 cd_media_dvd_plus_rw_dl
= 1;
351 log_debug("profile 0x%02x media_dvd_plus_r_dl", cur_profile
);
353 cd_media_dvd_plus_r_dl
= 1;
356 log_debug("profile 0x%02x media_bd", cur_profile
);
362 log_debug("profile 0x%02x media_bd_r", cur_profile
);
367 log_debug("profile 0x%02x media_bd_re", cur_profile
);
372 log_debug("profile 0x%02x media_hddvd", cur_profile
);
377 log_debug("profile 0x%02x media_hddvd_r", cur_profile
);
379 cd_media_hddvd_r
= 1;
382 log_debug("profile 0x%02x media_hddvd_rw", cur_profile
);
384 cd_media_hddvd_rw
= 1;
387 log_debug("profile 0x%02x <ignored>", cur_profile
);
392 static int feature_profiles(struct udev
*udev
, const unsigned char *profiles
, size_t size
)
396 for (i
= 0; i
+4 <= size
; i
+= 4) {
399 profile
= profiles
[i
] << 8 | profiles
[i
+1];
404 log_debug("profile 0x%02x mo", profile
);
408 log_debug("profile 0x%02x cd_rom", profile
);
412 log_debug("profile 0x%02x cd_r", profile
);
416 log_debug("profile 0x%02x cd_rw", profile
);
420 log_debug("profile 0x%02x dvd_rom", profile
);
424 log_debug("profile 0x%02x dvd_ram", profile
);
429 log_debug("profile 0x%02x dvd_rw", profile
);
433 log_debug("profile 0x%02x dvd_plus_r", profile
);
437 log_debug("profile 0x%02x dvd_plus_rw", profile
);
441 log_debug("profile 0x%02x dvd_plus_rw_dl", profile
);
442 cd_dvd_plus_rw_dl
= 1;
445 log_debug("profile 0x%02x dvd_plus_r_dl", profile
);
446 cd_dvd_plus_r_dl
= 1;
450 log_debug("profile 0x%02x bd", profile
);
455 log_debug("profile 0x%02x bd_r", profile
);
459 log_debug("profile 0x%02x bd_re", profile
);
463 log_debug("profile 0x%02x hddvd", profile
);
467 log_debug("profile 0x%02x hddvd_r", profile
);
471 log_debug("profile 0x%02x hddvd_rw", profile
);
474 log_debug("profile 0x%02x <ignored>", profile
);
481 /* returns 0 if media was detected */
482 static int cd_profiles_old_mmc(struct udev
*udev
, int fd
)
487 unsigned char header
[32];
489 scsi_cmd_init(udev
, &sc
);
490 scsi_cmd_set(udev
, &sc
, 0, 0x51);
491 scsi_cmd_set(udev
, &sc
, 8, sizeof(header
));
492 scsi_cmd_set(udev
, &sc
, 9, 0);
493 err
= scsi_cmd_run(udev
, &sc
, fd
, header
, sizeof(header
));
495 info_scsi_cmd_err(udev
, "READ DISC INFORMATION", err
);
497 log_debug("no current profile, but disc is present; assuming CD-ROM");
499 cd_media_track_count
= 1;
500 cd_media_track_count_data
= 1;
503 log_debug("no current profile, assuming no media");
510 if (header
[2] & 16) {
512 log_debug("profile 0x0a media_cd_rw");
513 } else if ((header
[2] & 3) < 2 && cd_cd_r
) {
515 log_debug("profile 0x09 media_cd_r");
518 log_debug("profile 0x08 media_cd_rom");
523 /* returns 0 if media was detected */
524 static int cd_profiles(struct udev
*udev
, int fd
)
527 unsigned char features
[65530];
528 unsigned int cur_profile
= 0;
536 /* First query the current profile */
537 scsi_cmd_init(udev
, &sc
);
538 scsi_cmd_set(udev
, &sc
, 0, 0x46);
539 scsi_cmd_set(udev
, &sc
, 8, 8);
540 scsi_cmd_set(udev
, &sc
, 9, 0);
541 err
= scsi_cmd_run(udev
, &sc
, fd
, features
, 8);
543 info_scsi_cmd_err(udev
, "GET CONFIGURATION", err
);
544 /* handle pre-MMC2 drives which do not support GET CONFIGURATION */
545 if (SK(err
) == 0x5 && (ASC(err
) == 0x20 || ASC(err
) == 0x24)) {
546 log_debug("drive is pre-MMC2 and does not support 46h get configuration command");
547 log_debug("trying to work around the problem");
548 ret
= cd_profiles_old_mmc(udev
, fd
);
553 cur_profile
= features
[6] << 8 | features
[7];
554 if (cur_profile
> 0) {
555 log_debug("current profile 0x%02x", cur_profile
);
556 feature_profile_media (udev
, cur_profile
);
557 ret
= 0; /* we have media */
559 log_debug("no current profile, assuming no media");
562 len
= features
[0] << 24 | features
[1] << 16 | features
[2] << 8 | features
[3];
563 log_debug("GET CONFIGURATION: size of features buffer 0x%04x", len
);
565 if (len
> sizeof(features
)) {
566 log_debug("can not get features in a single query, truncating");
567 len
= sizeof(features
);
569 len
= sizeof(features
);
571 /* Now get the full feature buffer */
572 scsi_cmd_init(udev
, &sc
);
573 scsi_cmd_set(udev
, &sc
, 0, 0x46);
574 scsi_cmd_set(udev
, &sc
, 7, ( len
>> 8 ) & 0xff);
575 scsi_cmd_set(udev
, &sc
, 8, len
& 0xff);
576 scsi_cmd_set(udev
, &sc
, 9, 0);
577 err
= scsi_cmd_run(udev
, &sc
, fd
, features
, len
);
579 info_scsi_cmd_err(udev
, "GET CONFIGURATION", err
);
583 /* parse the length once more, in case the drive decided to have other features suddenly :) */
584 len
= features
[0] << 24 | features
[1] << 16 | features
[2] << 8 | features
[3];
585 log_debug("GET CONFIGURATION: size of features buffer 0x%04x", len
);
587 if (len
> sizeof(features
)) {
588 log_debug("can not get features in a single query, truncating");
589 len
= sizeof(features
);
592 /* device features */
593 for (i
= 8; i
+4 < len
; i
+= (4 + features
[i
+3])) {
594 unsigned int feature
;
596 feature
= features
[i
] << 8 | features
[i
+1];
600 log_debug("GET CONFIGURATION: feature 'profiles', with %i entries", features
[i
+3] / 4);
601 feature_profiles(udev
, &features
[i
]+4, MIN(features
[i
+3], len
- i
- 4));
604 log_debug("GET CONFIGURATION: feature 0x%04x <ignored>, with 0x%02x bytes", feature
, features
[i
+3]);
612 static int cd_media_info(struct udev
*udev
, int fd
)
615 unsigned char header
[32];
616 static const char *media_status
[] = {
624 scsi_cmd_init(udev
, &sc
);
625 scsi_cmd_set(udev
, &sc
, 0, 0x51);
626 scsi_cmd_set(udev
, &sc
, 8, sizeof(header
) & 0xff);
627 scsi_cmd_set(udev
, &sc
, 9, 0);
628 err
= scsi_cmd_run(udev
, &sc
, fd
, header
, sizeof(header
));
630 info_scsi_cmd_err(udev
, "READ DISC INFORMATION", err
);
635 log_debug("disk type %02x", header
[8]);
636 log_debug("hardware reported media status: %s", media_status
[header
[2] & 3]);
638 /* exclude plain CDROM, some fake cdroms return 0 for "blank" media here */
639 if (!cd_media_cd_rom
)
640 cd_media_state
= media_status
[header
[2] & 3];
642 /* fresh DVD-RW in restricted overwite mode reports itself as
643 * "appendable"; change it to "blank" to make it consistent with what
644 * gets reported after blanking, and what userspace expects */
645 if (cd_media_dvd_rw_ro
&& (header
[2] & 3) == 1)
646 cd_media_state
= media_status
[0];
648 /* DVD+RW discs (and DVD-RW in restricted mode) once formatted are
649 * always "complete", DVD-RAM are "other" or "complete" if the disc is
650 * write protected; we need to check the contents if it is blank */
651 if ((cd_media_dvd_rw_ro
|| cd_media_dvd_plus_rw
|| cd_media_dvd_plus_rw_dl
|| cd_media_dvd_ram
) && (header
[2] & 3) > 1) {
652 unsigned char buffer
[32 * 2048];
656 if (cd_media_dvd_ram
) {
657 /* a write protected dvd-ram may report "complete" status */
659 unsigned char dvdstruct
[8];
660 unsigned char format
[12];
662 scsi_cmd_init(udev
, &sc
);
663 scsi_cmd_set(udev
, &sc
, 0, 0xAD);
664 scsi_cmd_set(udev
, &sc
, 7, 0xC0);
665 scsi_cmd_set(udev
, &sc
, 9, sizeof(dvdstruct
));
666 scsi_cmd_set(udev
, &sc
, 11, 0);
667 err
= scsi_cmd_run(udev
, &sc
, fd
, dvdstruct
, sizeof(dvdstruct
));
669 info_scsi_cmd_err(udev
, "READ DVD STRUCTURE", err
);
672 if (dvdstruct
[4] & 0x02) {
673 cd_media_state
= media_status
[2];
674 log_debug("write-protected DVD-RAM media inserted");
678 /* let's make sure we don't try to read unformatted media */
679 scsi_cmd_init(udev
, &sc
);
680 scsi_cmd_set(udev
, &sc
, 0, 0x23);
681 scsi_cmd_set(udev
, &sc
, 8, sizeof(format
));
682 scsi_cmd_set(udev
, &sc
, 9, 0);
683 err
= scsi_cmd_run(udev
, &sc
, fd
, format
, sizeof(format
));
685 info_scsi_cmd_err(udev
, "READ DVD FORMAT CAPACITIES", err
);
690 if (len
& 7 || len
< 16) {
691 log_debug("invalid format capacities length");
695 switch(format
[8] & 3) {
697 log_debug("unformatted DVD-RAM media inserted");
698 /* This means that last format was interrupted
699 * or failed, blank dvd-ram discs are factory
700 * formatted. Take no action here as it takes
701 * quite a while to reformat a dvd-ram and it's
702 * not automatically started */
706 log_debug("formatted DVD-RAM media inserted");
710 cd_media
= 0; //return no media
711 log_debug("format capacities returned no media");
716 /* Take a closer look at formatted media (unformatted DVD+RW
717 * has "blank" status", DVD-RAM was examined earlier) and check
718 * for ISO and UDF PVDs or a fs superblock presence and do it
719 * in one ioctl (we need just sectors 0 and 16) */
720 scsi_cmd_init(udev
, &sc
);
721 scsi_cmd_set(udev
, &sc
, 0, 0x28);
722 scsi_cmd_set(udev
, &sc
, 5, 0);
723 scsi_cmd_set(udev
, &sc
, 8, 32);
724 scsi_cmd_set(udev
, &sc
, 9, 0);
725 err
= scsi_cmd_run(udev
, &sc
, fd
, buffer
, sizeof(buffer
));
728 info_scsi_cmd_err(udev
, "READ FIRST 32 BLOCKS", err
);
732 /* if any non-zero data is found in sector 16 (iso and udf) or
733 * eventually 0 (fat32 boot sector, ext2 superblock, etc), disc
734 * is assumed non-blank */
736 for (offset
= 32768; offset
< (32768 + 2048); offset
++) {
737 if (buffer
[offset
]) {
738 log_debug("data in block 16, assuming complete");
743 for (offset
= 0; offset
< 2048; offset
++) {
744 if (buffer
[offset
]) {
745 log_debug("data in block 0, assuming complete");
750 cd_media_state
= media_status
[0];
751 log_debug("no data in blocks 0 or 16, assuming blank");
755 /* "other" is e. g. DVD-RAM, can't append sessions there; DVDs in
756 * restricted overwrite mode can never append, only in sequential mode */
757 if ((header
[2] & 3) < 2 && !cd_media_dvd_rw_ro
)
758 cd_media_session_next
= header
[10] << 8 | header
[5];
759 cd_media_session_count
= header
[9] << 8 | header
[4];
760 cd_media_track_count
= header
[11] << 8 | header
[6];
765 static int cd_media_toc(struct udev
*udev
, int fd
)
768 unsigned char header
[12];
769 unsigned char toc
[65536];
770 unsigned int len
, i
, num_tracks
;
774 scsi_cmd_init(udev
, &sc
);
775 scsi_cmd_set(udev
, &sc
, 0, 0x43);
776 scsi_cmd_set(udev
, &sc
, 6, 1);
777 scsi_cmd_set(udev
, &sc
, 8, sizeof(header
) & 0xff);
778 scsi_cmd_set(udev
, &sc
, 9, 0);
779 err
= scsi_cmd_run(udev
, &sc
, fd
, header
, sizeof(header
));
781 info_scsi_cmd_err(udev
, "READ TOC", err
);
785 len
= (header
[0] << 8 | header
[1]) + 2;
786 log_debug("READ TOC: len: %d, start track: %d, end track: %d", len
, header
[2], header
[3]);
787 if (len
> sizeof(toc
))
791 /* 2: first track, 3: last track */
792 num_tracks
= header
[3] - header
[2] + 1;
794 /* empty media has no tracks */
798 scsi_cmd_init(udev
, &sc
);
799 scsi_cmd_set(udev
, &sc
, 0, 0x43);
800 scsi_cmd_set(udev
, &sc
, 6, header
[2]); /* First Track/Session Number */
801 scsi_cmd_set(udev
, &sc
, 7, (len
>> 8) & 0xff);
802 scsi_cmd_set(udev
, &sc
, 8, len
& 0xff);
803 scsi_cmd_set(udev
, &sc
, 9, 0);
804 err
= scsi_cmd_run(udev
, &sc
, fd
, toc
, len
);
806 info_scsi_cmd_err(udev
, "READ TOC (tracks)", err
);
810 /* Take care to not iterate beyond the last valid track as specified in
811 * the TOC, but also avoid going beyond the TOC length, just in case
812 * the last track number is invalidly large */
813 for (p
= toc
+4, i
= 4; i
< len
-8 && num_tracks
> 0; i
+= 8, p
+= 8, --num_tracks
) {
815 unsigned int is_data_track
;
817 is_data_track
= (p
[1] & 0x04) != 0;
819 block
= p
[4] << 24 | p
[5] << 16 | p
[6] << 8 | p
[7];
820 log_debug("track=%u info=0x%x(%s) start_block=%u",
821 p
[2], p
[1] & 0x0f, is_data_track
? "data":"audio", block
);
824 cd_media_track_count_data
++;
826 cd_media_track_count_audio
++;
829 scsi_cmd_init(udev
, &sc
);
830 scsi_cmd_set(udev
, &sc
, 0, 0x43);
831 scsi_cmd_set(udev
, &sc
, 2, 1); /* Session Info */
832 scsi_cmd_set(udev
, &sc
, 8, sizeof(header
));
833 scsi_cmd_set(udev
, &sc
, 9, 0);
834 err
= scsi_cmd_run(udev
, &sc
, fd
, header
, sizeof(header
));
836 info_scsi_cmd_err(udev
, "READ TOC (multi session)", err
);
839 len
= header
[4+4] << 24 | header
[4+5] << 16 | header
[4+6] << 8 | header
[4+7];
840 log_debug("last track %u starts at block %u", header
[4+2], len
);
841 cd_media_session_last_offset
= (unsigned long long int)len
* 2048;
845 int main(int argc
, char *argv
[])
848 static const struct option options
[] = {
849 { "lock-media", no_argument
, NULL
, 'l' },
850 { "unlock-media", no_argument
, NULL
, 'u' },
851 { "eject-media", no_argument
, NULL
, 'e' },
852 { "debug", no_argument
, NULL
, 'd' },
853 { "help", no_argument
, NULL
, 'h' },
859 const char *node
= NULL
;
864 log_parse_environment();
874 option
= getopt_long(argc
, argv
, "deluh", options
, NULL
);
889 log_set_target(LOG_TARGET_CONSOLE
);
890 log_set_max_level(LOG_DEBUG
);
894 printf("Usage: cdrom_id [options] <device>\n"
895 " -l,--lock-media lock the media (to enable eject request events)\n"
896 " -u,--unlock-media unlock the media\n"
897 " -e,--eject-media eject the media\n"
898 " -d,--debug debug to stderr\n"
899 " -h,--help print this help text\n\n");
909 log_error("no device");
910 fprintf(stderr
, "no device\n");
916 for (cnt
= 20; cnt
> 0; cnt
--) {
917 struct timespec duration
;
919 fd
= open(node
, O_RDONLY
|O_NONBLOCK
|O_CLOEXEC
|(is_mounted(node
) ? 0 : O_EXCL
));
920 if (fd
>= 0 || errno
!= EBUSY
)
923 duration
.tv_nsec
= (100 * 1000 * 1000) + (rand() % 100 * 1000 * 1000);
924 nanosleep(&duration
, NULL
);
927 log_debug("unable to open '%s'", node
);
928 fprintf(stderr
, "unable to open '%s'\n", node
);
932 log_debug("probing: '%s'", node
);
934 /* same data as original cdrom_id */
935 if (cd_capability_compat(udev
, fd
) < 0) {
940 /* check for media - don't bail if there's no media as we still need to
941 * to read profiles */
942 cd_media_compat(udev
, fd
);
944 /* check if drive talks MMC */
945 if (cd_inquiry(udev
, fd
) < 0)
948 /* read drive and possibly current profile */
949 if (cd_profiles(udev
, fd
) != 0)
952 /* at this point we are guaranteed to have media in the drive - find out more about it */
954 /* get session/track info */
955 cd_media_toc(udev
, fd
);
957 /* get writable media state */
958 cd_media_info(udev
, fd
);
961 /* lock the media, so we enable eject button events */
962 if (lock
&& cd_media
) {
963 log_debug("PREVENT_ALLOW_MEDIUM_REMOVAL (lock)");
964 media_lock(udev
, fd
, true);
967 if (unlock
&& cd_media
) {
968 log_debug("PREVENT_ALLOW_MEDIUM_REMOVAL (unlock)");
969 media_lock(udev
, fd
, false);
973 log_debug("PREVENT_ALLOW_MEDIUM_REMOVAL (unlock)");
974 media_lock(udev
, fd
, false);
975 log_debug("START_STOP_UNIT (eject)");
976 media_eject(udev
, fd
);
979 printf("ID_CDROM=1\n");
981 printf("ID_CDROM_CD=1\n");
983 printf("ID_CDROM_CD_R=1\n");
985 printf("ID_CDROM_CD_RW=1\n");
987 printf("ID_CDROM_DVD=1\n");
989 printf("ID_CDROM_DVD_R=1\n");
991 printf("ID_CDROM_DVD_RW=1\n");
993 printf("ID_CDROM_DVD_RAM=1\n");
995 printf("ID_CDROM_DVD_PLUS_R=1\n");
997 printf("ID_CDROM_DVD_PLUS_RW=1\n");
998 if (cd_dvd_plus_r_dl
)
999 printf("ID_CDROM_DVD_PLUS_R_DL=1\n");
1000 if (cd_dvd_plus_rw_dl
)
1001 printf("ID_CDROM_DVD_PLUS_RW_DL=1\n");
1003 printf("ID_CDROM_BD=1\n");
1005 printf("ID_CDROM_BD_R=1\n");
1007 printf("ID_CDROM_BD_RE=1\n");
1009 printf("ID_CDROM_HDDVD=1\n");
1011 printf("ID_CDROM_HDDVD_R=1\n");
1013 printf("ID_CDROM_HDDVD_RW=1\n");
1015 printf("ID_CDROM_MO=1\n");
1017 printf("ID_CDROM_MRW=1\n");
1019 printf("ID_CDROM_MRW_W=1\n");
1022 printf("ID_CDROM_MEDIA=1\n");
1024 printf("ID_CDROM_MEDIA_MO=1\n");
1026 printf("ID_CDROM_MEDIA_MRW=1\n");
1028 printf("ID_CDROM_MEDIA_MRW_W=1\n");
1029 if (cd_media_cd_rom
)
1030 printf("ID_CDROM_MEDIA_CD=1\n");
1032 printf("ID_CDROM_MEDIA_CD_R=1\n");
1034 printf("ID_CDROM_MEDIA_CD_RW=1\n");
1035 if (cd_media_dvd_rom
)
1036 printf("ID_CDROM_MEDIA_DVD=1\n");
1038 printf("ID_CDROM_MEDIA_DVD_R=1\n");
1039 if (cd_media_dvd_ram
)
1040 printf("ID_CDROM_MEDIA_DVD_RAM=1\n");
1041 if (cd_media_dvd_rw
)
1042 printf("ID_CDROM_MEDIA_DVD_RW=1\n");
1043 if (cd_media_dvd_plus_r
)
1044 printf("ID_CDROM_MEDIA_DVD_PLUS_R=1\n");
1045 if (cd_media_dvd_plus_rw
)
1046 printf("ID_CDROM_MEDIA_DVD_PLUS_RW=1\n");
1047 if (cd_media_dvd_plus_rw_dl
)
1048 printf("ID_CDROM_MEDIA_DVD_PLUS_RW_DL=1\n");
1049 if (cd_media_dvd_plus_r_dl
)
1050 printf("ID_CDROM_MEDIA_DVD_PLUS_R_DL=1\n");
1052 printf("ID_CDROM_MEDIA_BD=1\n");
1054 printf("ID_CDROM_MEDIA_BD_R=1\n");
1056 printf("ID_CDROM_MEDIA_BD_RE=1\n");
1058 printf("ID_CDROM_MEDIA_HDDVD=1\n");
1059 if (cd_media_hddvd_r
)
1060 printf("ID_CDROM_MEDIA_HDDVD_R=1\n");
1061 if (cd_media_hddvd_rw
)
1062 printf("ID_CDROM_MEDIA_HDDVD_RW=1\n");
1064 if (cd_media_state
!= NULL
)
1065 printf("ID_CDROM_MEDIA_STATE=%s\n", cd_media_state
);
1066 if (cd_media_session_next
> 0)
1067 printf("ID_CDROM_MEDIA_SESSION_NEXT=%u\n", cd_media_session_next
);
1068 if (cd_media_session_count
> 0)
1069 printf("ID_CDROM_MEDIA_SESSION_COUNT=%u\n", cd_media_session_count
);
1070 if (cd_media_session_count
> 1 && cd_media_session_last_offset
> 0)
1071 printf("ID_CDROM_MEDIA_SESSION_LAST_OFFSET=%llu\n", cd_media_session_last_offset
);
1072 if (cd_media_track_count
> 0)
1073 printf("ID_CDROM_MEDIA_TRACK_COUNT=%u\n", cd_media_track_count
);
1074 if (cd_media_track_count_audio
> 0)
1075 printf("ID_CDROM_MEDIA_TRACK_COUNT_AUDIO=%u\n", cd_media_track_count_audio
);
1076 if (cd_media_track_count_data
> 0)
1077 printf("ID_CDROM_MEDIA_TRACK_COUNT_DATA=%u\n", cd_media_track_count_data
);