1 /* Multimedia Command (MMC) "helper" routines that don't depend
2    on anything other than headers.
3 
4   Copyright (C) 2010, 2011 Rocky Bernstein <rocky@gnu.org>
5 
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 3 of the License, or
9   (at your option) any later version.
10 
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.
15 
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/>.
18 */
19 
20 #ifdef HAVE_CONFIG_H
21 # include "config.h"
22 # define __CDIO_CONFIG_H__ 1
23 #endif
24 
25 #ifdef HAVE_STDIO_H
26 #include <stdio.h>
27 #endif
28 
29 #include <cdio/mmc.h>
30 #include "mmc_private.h"
31 
32 /** The below variables are trickery to force enum symbol values to be
33     recorded in debug symbol tables. They are used to allow one to refer
34     to the enumeration value names in the typedefs above in a debugger
35     and debugger expressions
36 */
37 cdio_mmc_feature_t           debug_cdio_mmc_feature;
38 cdio_mmc_feature_interface_t debug_cdio_mmc_feature_interface;
39 cdio_mmc_feature_profile_t   debug_cdio_mmc_feature_profile;
40 cdio_mmc_get_conf_t          debug_cdio_mmc_get_conf;
41 cdio_mmc_gpcmd_t             debug_cdio_mmc_gpcmd;
42 cdio_mmc_read_sub_state_t    debug_cdio_mmc_read_sub_state;
43 cdio_mmc_read_cd_type_t      debug_cdio_mmc_read_cd_type;
44 cdio_mmc_readtoc_t           debug_cdio_mmc_readtoc;
45 cdio_mmc_mode_page_t         debug_cdio_mmc_mode_page;
46 
47 /**
48    Maps a mmc_sense_key_t into a string name.
49  */
50 const char mmc_sense_key2str[16][40] = {
51     "No Sense",              /**< 0 No specific Sense Key info reported */
52     "Recovered Error",       /**< 1 Completed ok with recovery */
53     "Not Ready",             /**< 2 */
54     "Medium Error",          /**< 3 */
55     "Hardware Error",        /**< 4 */
56     "Illegal Request",       /**< 5 */
57     "Unit Attention",        /**< 6 */
58     "Data Protect",          /**< 7 */
59     "Blank Check",           /**< 8 */
60     "Vendor Specific",       /**< 9 */
61     "Copy aborted",          /**< A */
62     "Aborted Command",       /**< B */
63     "Obsolete",              /**< C */
64     "Unknown - 13",          /**< D */
65     "Unknown - 14",          /**< E */
66     "Unknown - 15",          /**< F */
67 };
68 
69 /**
70     The maximum value in milliseconds that we will wait on an MMC
71     command.
72 */
73 uint32_t mmc_timeout_ms = MMC_TIMEOUT_DEFAULT;
74 
75 /**
76     The maximum value in milliseconds that we will wait on an MMC read
77   command.
78 */
79 uint32_t mmc_read_timeout_ms = MMC_READ_TIMEOUT_DEFAULT;
80 
81 /*!
82   Return a string containing the name of the audio state as returned from
83   the Q_SUBCHANNEL.
84  */
85 const char *
mmc_audio_state2str(uint8_t i_audio_state)86 mmc_audio_state2str( uint8_t i_audio_state )
87 {
88     switch(i_audio_state) {
89       case CDIO_MMC_READ_SUB_ST_INVALID:
90         return "invalid";
91       case CDIO_MMC_READ_SUB_ST_PLAY:
92         return "playing";
93       case CDIO_MMC_READ_SUB_ST_PAUSED:
94         return "paused";
95       case CDIO_MMC_READ_SUB_ST_COMPLETED:
96         return "completed";
97       case CDIO_MMC_READ_SUB_ST_ERROR:
98         return "error";
99       case CDIO_MMC_READ_SUB_ST_NO_STATUS:
100         return "no status";
101       default:
102         return "unknown";
103     }
104 }
105 
106 /**
107   On input a MODE_SENSE command was issued and we have the results
108   in p. We interpret this and return a bit mask set according to the
109   capabilities.
110 */
111 void
mmc_get_drive_cap_buf(const uint8_t * p,cdio_drive_read_cap_t * p_read_cap,cdio_drive_write_cap_t * p_write_cap,cdio_drive_misc_cap_t * p_misc_cap)112 mmc_get_drive_cap_buf(const uint8_t *p,
113                       /*out*/ cdio_drive_read_cap_t  *p_read_cap,
114                       /*out*/ cdio_drive_write_cap_t *p_write_cap,
115                       /*out*/ cdio_drive_misc_cap_t  *p_misc_cap)
116 {
117   /* Reader */
118   if (p[2] & 0x01) *p_read_cap  |= CDIO_DRIVE_CAP_READ_CD_R;
119   if (p[2] & 0x02) *p_read_cap  |= CDIO_DRIVE_CAP_READ_CD_RW;
120   if (p[2] & 0x08) *p_read_cap  |= CDIO_DRIVE_CAP_READ_DVD_ROM;
121   if (p[4] & 0x01) *p_read_cap  |= CDIO_DRIVE_CAP_READ_AUDIO;
122   if (p[4] & 0x10) *p_read_cap  |= CDIO_DRIVE_CAP_READ_MODE2_FORM1;
123   if (p[4] & 0x20) *p_read_cap  |= CDIO_DRIVE_CAP_READ_MODE2_FORM2;
124   if (p[5] & 0x01) *p_read_cap  |= CDIO_DRIVE_CAP_READ_CD_DA;
125   if (p[5] & 0x10) *p_read_cap  |= CDIO_DRIVE_CAP_READ_C2_ERRS;
126   if (p[5] & 0x20) *p_read_cap  |= CDIO_DRIVE_CAP_READ_ISRC;
127   if (p[5] & 0x40) *p_read_cap  |= CDIO_DRIVE_CAP_READ_MCN;
128 
129   /* Writer */
130   if (p[3] & 0x01) *p_write_cap |= CDIO_DRIVE_CAP_WRITE_CD_R;
131   if (p[3] & 0x02) *p_write_cap |= CDIO_DRIVE_CAP_WRITE_CD_RW;
132   if (p[3] & 0x10) *p_write_cap |= CDIO_DRIVE_CAP_WRITE_DVD_R;
133   if (p[3] & 0x20) *p_write_cap |= CDIO_DRIVE_CAP_WRITE_DVD_RAM;
134   if (p[4] & 0x80) *p_misc_cap  |= CDIO_DRIVE_CAP_WRITE_BURN_PROOF;
135 
136   /* Misc */
137   if (p[4] & 0x40) *p_misc_cap  |= CDIO_DRIVE_CAP_MISC_MULTI_SESSION;
138   if (p[6] & 0x01) *p_misc_cap  |= CDIO_DRIVE_CAP_MISC_LOCK;
139   if (p[6] & 0x08) *p_misc_cap  |= CDIO_DRIVE_CAP_MISC_EJECT;
140   if (p[6] >> 5 != 0)
141     *p_misc_cap |= CDIO_DRIVE_CAP_MISC_CLOSE_TRAY;
142 }
143 
144 /**
145    Return a string containing the name of the given feature
146 */
147 const char *
mmc_feature2str(int i_feature)148 mmc_feature2str( int i_feature )
149 {
150   switch(i_feature) {
151   case CDIO_MMC_FEATURE_PROFILE_LIST:
152     return "Profile List";
153   case CDIO_MMC_FEATURE_CORE:
154     return "Core";
155   case CDIO_MMC_FEATURE_MORPHING:
156     return "Morphing" ;
157   case CDIO_MMC_FEATURE_REMOVABLE_MEDIUM:
158     return "Removable Medium";
159   case CDIO_MMC_FEATURE_WRITE_PROTECT:
160     return "Write Protect";
161   case CDIO_MMC_FEATURE_RANDOM_READABLE:
162     return "Random Readable";
163   case CDIO_MMC_FEATURE_MULTI_READ:
164     return "Multi-Read";
165   case CDIO_MMC_FEATURE_CD_READ:
166     return "CD Read";
167   case CDIO_MMC_FEATURE_DVD_READ:
168     return "DVD Read";
169   case CDIO_MMC_FEATURE_RANDOM_WRITABLE:
170     return "Random Writable";
171   case CDIO_MMC_FEATURE_INCR_WRITE:
172     return "Incremental Streaming Writable";
173   case CDIO_MMC_FEATURE_SECTOR_ERASE:
174     return "Sector Erasable";
175   case CDIO_MMC_FEATURE_FORMATABLE:
176     return "Formattable";
177   case CDIO_MMC_FEATURE_DEFECT_MGMT:
178     return "Management Ability of the Logical Unit/media system "
179       "to provide an apparently defect-free space.";
180   case CDIO_MMC_FEATURE_WRITE_ONCE:
181     return "Write Once";
182   case CDIO_MMC_FEATURE_RESTRICT_OVERW:
183     return "Restricted Overwrite";
184   case CDIO_MMC_FEATURE_CD_RW_CAV:
185     return "CD-RW CAV Write";
186   case CDIO_MMC_FEATURE_MRW:
187     return "MRW";
188   case CDIO_MMC_FEATURE_ENHANCED_DEFECT:
189     return "Enhanced Defect Reporting";
190   case CDIO_MMC_FEATURE_DVD_PRW:
191     return "DVD+RW";
192   case CDIO_MMC_FEATURE_DVD_PR:
193     return "DVD+R";
194   case CDIO_MMC_FEATURE_RIGID_RES_OVERW:
195     return "Rigid Restricted Overwrite";
196   case CDIO_MMC_FEATURE_CD_TAO:
197     return "CD Track at Once";
198   case CDIO_MMC_FEATURE_CD_SAO:
199     return "CD Mastering (Session at Once)";
200   case CDIO_MMC_FEATURE_DVD_R_RW_WRITE:
201     return "DVD-R/RW Write";
202   case CDIO_MMC_FEATURE_CD_RW_MEDIA_WRITE:
203     return "CD-RW Media Write Support";
204   case CDIO_MMC_FEATURE_DVD_PR_2_LAYER:
205     return "DVD+R Double Layer";
206   case CDIO_MMC_FEATURE_POWER_MGMT:
207     return "Initiator- and Device-directed Power Management";
208   case CDIO_MMC_FEATURE_CDDA_EXT_PLAY:
209     return "CD Audio External Play";
210   case CDIO_MMC_FEATURE_MCODE_UPGRADE:
211     return "Ability for the device to accept new microcode via the interface";
212   case CDIO_MMC_FEATURE_TIME_OUT:
213     return "Ability to respond to all commands within a specific time";
214   case CDIO_MMC_FEATURE_DVD_CSS:
215     return "Ability to perform DVD CSS/CPPM authentication via RPC";
216   case CDIO_MMC_FEATURE_RT_STREAMING:
217     return "Ability to read and write using Initiator requested performance"
218       " parameters";
219   case CDIO_MMC_FEATURE_LU_SN:
220     return "The Logical Unit Unique Identifier";
221   default:
222     {
223       static char buf[100];
224       if ( 0 != (i_feature & 0xFF00) ) {
225         snprintf( buf, sizeof(buf),
226                  "Vendor-specific code %x", i_feature );
227       } else {
228         snprintf( buf, sizeof(buf),
229                  "Unknown code %x", i_feature );
230       }
231       return buf;
232     }
233   }
234 }
235 
236 
237 /**
238  Return a string containing the name of the given feature profile.
239  */
240 const char *
mmc_feature_profile2str(int i_feature_profile)241 mmc_feature_profile2str( int i_feature_profile )
242 {
243   switch(i_feature_profile) {
244   case CDIO_MMC_FEATURE_PROF_NON_REMOVABLE:
245     return "Non-removable";
246   case CDIO_MMC_FEATURE_PROF_REMOVABLE:
247     return "disk Re-writable; with removable media";
248   case CDIO_MMC_FEATURE_PROF_MO_ERASABLE:
249     return "Erasable Magneto-Optical disk with sector erase capability";
250   case CDIO_MMC_FEATURE_PROF_MO_WRITE_ONCE:
251     return "Write Once Magneto-Optical write once";
252   case CDIO_MMC_FEATURE_PROF_AS_MO:
253     return "Advance Storage Magneto-Optical";
254   case CDIO_MMC_FEATURE_PROF_CD_ROM:
255     return "Read only Compact Disc capable";
256   case CDIO_MMC_FEATURE_PROF_CD_R:
257     return "Write once Compact Disc capable";
258   case CDIO_MMC_FEATURE_PROF_CD_RW:
259     return "CD-RW Re-writable Compact Disc capable";
260   case CDIO_MMC_FEATURE_PROF_DVD_ROM:
261     return "Read only DVD";
262   case CDIO_MMC_FEATURE_PROF_DVD_R_SEQ:
263     return "Re-recordable DVD using Sequential recording";
264   case CDIO_MMC_FEATURE_PROF_DVD_RAM:
265     return "Re-writable DVD";
266   case CDIO_MMC_FEATURE_PROF_DVD_RW_RO:
267     return "Re-recordable DVD using Restricted Overwrite";
268   case CDIO_MMC_FEATURE_PROF_DVD_RW_SEQ:
269     return "Re-recordable DVD using Sequential Recording";
270   case CDIO_MMC_FEATURE_PROF_DVD_R_DL_SEQ:
271     return "DVD-R - Double-Layer Sequential Recording";
272   case CDIO_MMC_FEATURE_PROF_DVD_R_DL_JR:
273     return "DVD-R - Double-layer Jump Recording";
274   case CDIO_MMC_FEATURE_PROF_DVD_PRW:
275     return "DVD+RW - DVD Rewritable";
276   case CDIO_MMC_FEATURE_RIGID_RES_OVERW:
277     return "Rigid Restricted Overwrite";
278   case CDIO_MMC_FEATURE_PROF_DVD_PR:
279     return "DVD+R - DVD Recordable";
280   case CDIO_MMC_FEATURE_PROF_DDCD_ROM:
281     return "Read only DDCD";
282   case CDIO_MMC_FEATURE_PROF_DDCD_R:
283     return "DDCD-R Write only DDCD";
284   case CDIO_MMC_FEATURE_PROF_DDCD_RW:
285     return "Re-Write only DDCD";
286   case CDIO_MMC_FEATURE_PROF_DVD_PRW_DL:
287     return "DVD+RW - Double Layer";
288   case CDIO_MMC_FEATURE_PROF_DVD_PR_DL:
289     return "DVD+R Double Layer - DVD Recordable Double Layer";
290   case CDIO_MMC_FEATURE_PROF_BD_ROM:
291     return "Blu Ray BD-ROM";
292   case CDIO_MMC_FEATURE_PROF_BD_SEQ:
293     return "Blu Ray BD-R sequential recording";
294   case CDIO_MMC_FEATURE_PROF_BD_R_RANDOM:
295     return "Blu Ray BD-R random recording";
296   case CDIO_MMC_FEATURE_PROF_BD_RE:
297     return "Blu Ray BD-RE";
298   case CDIO_MMC_FEATURE_PROF_HD_DVD_ROM:
299     return "HD-DVD-ROM";
300   case CDIO_MMC_FEATURE_PROF_HD_DVD_R:
301       return "HD-DVD-R";
302   case CDIO_MMC_FEATURE_PROF_HD_DVD_RAM:
303     return "HD-DVD-RAM";
304   case CDIO_MMC_FEATURE_PROF_NON_CONFORM:
305     return "The Logical Unit does not conform to any Profile";
306   default:
307     {
308       static char buf[100];
309       snprintf(buf, sizeof(buf), "Unknown Profile %x", i_feature_profile);
310       return buf;
311     }
312   }
313 }
314 
315 bool
mmc_is_disctype_bd(cdio_mmc_feature_profile_t disctype)316 mmc_is_disctype_bd (cdio_mmc_feature_profile_t disctype) {
317     switch (disctype) {
318       case CDIO_MMC_FEATURE_PROF_BD_ROM:
319       case CDIO_MMC_FEATURE_PROF_BD_SEQ:
320       case CDIO_MMC_FEATURE_PROF_BD_R_RANDOM:
321       case CDIO_MMC_FEATURE_PROF_BD_RE:
322         return true;
323       default:
324         return false;
325     }
326 }
327 
328 bool
mmc_is_disctype_cdrom(cdio_mmc_feature_profile_t disctype)329 mmc_is_disctype_cdrom (cdio_mmc_feature_profile_t disctype) {
330     switch (disctype) {
331       case CDIO_MMC_FEATURE_PROF_CD_ROM:
332       case CDIO_MMC_FEATURE_PROF_CD_R:
333       case CDIO_MMC_FEATURE_PROF_CD_RW:
334         return true;
335       default:
336         return false;
337     }
338 }
339 
340 
341 bool
mmc_is_disctype_dvd(cdio_mmc_feature_profile_t disctype)342 mmc_is_disctype_dvd (cdio_mmc_feature_profile_t disctype) {
343     switch (disctype) {
344       case CDIO_MMC_FEATURE_PROF_DVD_ROM:
345       case CDIO_MMC_FEATURE_PROF_DVD_RAM:
346       case CDIO_MMC_FEATURE_PROF_DVD_R_SEQ:
347       case CDIO_MMC_FEATURE_PROF_DVD_RW_RO:
348       case CDIO_MMC_FEATURE_PROF_DVD_RW_SEQ:
349       case CDIO_MMC_FEATURE_PROF_DVD_R_DL_SEQ:
350       case CDIO_MMC_FEATURE_PROF_DVD_R_DL_JR:
351       case CDIO_MMC_FEATURE_PROF_DVD_PRW:
352       case CDIO_MMC_FEATURE_PROF_DVD_PR:
353       case CDIO_MMC_FEATURE_PROF_DVD_PRW_DL:
354       case CDIO_MMC_FEATURE_PROF_DVD_PR_DL:
355         return true;
356       default:
357         return false;
358     }
359 }
360 
361 bool
mmc_is_disctype_hd_dvd(cdio_mmc_feature_profile_t disctype)362 mmc_is_disctype_hd_dvd (cdio_mmc_feature_profile_t disctype) {
363     switch (disctype) {
364       case CDIO_MMC_FEATURE_PROF_HD_DVD_ROM:
365       case CDIO_MMC_FEATURE_PROF_HD_DVD_R:
366       case CDIO_MMC_FEATURE_PROF_HD_DVD_RAM:
367         return true;
368       default:
369         return false;
370     }
371 }
372 
373 
374 bool
mmc_is_disctype_overwritable(cdio_mmc_feature_profile_t disctype)375 mmc_is_disctype_overwritable (cdio_mmc_feature_profile_t disctype) {
376     switch (disctype) {
377       case CDIO_MMC_FEATURE_PROF_DVD_RW_RO:
378       case CDIO_MMC_FEATURE_PROF_DVD_R_DL_JR:
379       case CDIO_MMC_FEATURE_PROF_DVD_PRW:
380       case CDIO_MMC_FEATURE_PROF_DVD_PRW_DL:
381       case CDIO_MMC_FEATURE_PROF_BD_R_RANDOM: /* pseudo-overwritable */
382       case CDIO_MMC_FEATURE_PROF_BD_RE:
383       case CDIO_MMC_FEATURE_PROF_HD_DVD_RAM:
384         return true;
385       default:
386         return false;
387     }
388 }
389 
390 
391 bool
mmc_is_disctype_rewritable(cdio_mmc_feature_profile_t disctype)392 mmc_is_disctype_rewritable (cdio_mmc_feature_profile_t disctype) {
393     /* discs that need blanking before re-use */
394     if (mmc_is_disctype_overwritable (disctype))
395         return true;
396 
397     switch (disctype) {
398       case CDIO_MMC_FEATURE_PROF_CD_RW:
399       case CDIO_MMC_FEATURE_PROF_DVD_RW_SEQ:
400       case CDIO_MMC_FEATURE_PROF_BD_SEQ:
401         return true;
402       default:
403         return false;
404     }
405 }
406 
407