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