1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
4 * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app@wanadoo.fr>
6 * Libbrasero-media 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 * The Libbrasero-media authors hereby grant permission for non-GPL compatible
12 * GStreamer plugins to be used and distributed together with GStreamer
13 * and Libbrasero-media. This permission is above and beyond the permissions granted
14 * by the GPL license by which Libbrasero-media is covered. If you modify this code
15 * you may extend this exception to your version of the code, but you are not
16 * obligated to do so. If you do not wish to do so, delete this exception
17 * statement from your version.
19 * Libbrasero-media is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Library General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to:
26 * The Free Software Foundation, Inc.,
27 * 51 Franklin Street, Fifth Floor
28 * Boston, MA 02110-1301, USA.
37 #include "brasero-media-private.h"
39 #include "scsi-spc1.h"
41 #include "scsi-error.h"
42 #include "scsi-utils.h"
43 #include "scsi-base.h"
44 #include "scsi-command.h"
45 #include "scsi-opcodes.h"
46 #include "scsi-mode-pages.h"
49 * MODE SENSE command description (defined in SPC, Scsi Primary Commands)
52 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
54 struct _BraseroModeSenseCDB
{
63 uchar subpage_code
:8;
73 struct _BraseroModeSenseCDB
{
82 uchar subpage_code
:8;
92 typedef struct _BraseroModeSenseCDB BraseroModeSenseCDB
;
94 BRASERO_SCSI_COMMAND_DEFINE (BraseroModeSenseCDB
,
98 #define BRASERO_MODE_DATA(data) ((BraseroScsiModeData *) (data))
101 brasero_spc1_mode_sense_get_page (BraseroDeviceHandle
*handle
,
102 BraseroSPCPageType num
,
103 BraseroScsiModeData
**data
,
105 BraseroScsiErrCode
*error
)
110 BraseroScsiResult res
;
111 BraseroModeSenseCDB
*cdb
;
112 BraseroScsiModeData header
;
113 BraseroScsiModeData
*buffer
;
115 g_return_val_if_fail (handle
!= NULL
, BRASERO_SCSI_FAILURE
);
117 if (!data
|| !data_size
) {
118 BRASERO_SCSI_SET_ERRCODE (error
, BRASERO_SCSI_BAD_ARGUMENT
);
119 return BRASERO_SCSI_FAILURE
;
122 /* issue a first command to get the size of the page ... */
123 cdb
= brasero_scsi_command_new (&info
, handle
);
125 cdb
->page_code
= num
;
126 BRASERO_SET_16 (cdb
->alloc_len
, sizeof (header
));
127 bzero (&header
, sizeof (header
));
129 BRASERO_MEDIA_LOG ("Getting page size");
130 res
= brasero_scsi_command_issue_sync (cdb
, &header
, sizeof (header
), error
);
134 if (!header
.hdr
.len
) {
135 BRASERO_SCSI_SET_ERRCODE (error
, BRASERO_SCSI_SIZE_MISMATCH
);
136 res
= BRASERO_SCSI_FAILURE
;
140 /* Paranoïa, make sure:
141 * - the size given in header, the one of the page returned are coherent
142 * - the block descriptors are actually disabled */
143 if (BRASERO_GET_16 (header
.hdr
.bdlen
)) {
144 BRASERO_SCSI_SET_ERRCODE (error
, BRASERO_SCSI_BAD_ARGUMENT
);
145 BRASERO_MEDIA_LOG ("Block descriptors not disabled %i", BRASERO_GET_16 (header
.hdr
.bdlen
));
146 res
= BRASERO_SCSI_FAILURE
;
150 request_size
= BRASERO_GET_16 (header
.hdr
.len
) +
151 G_STRUCT_OFFSET (BraseroScsiModeHdr
, len
) +
152 sizeof (header
.hdr
.len
);
154 page_size
= header
.page
.len
+
155 G_STRUCT_OFFSET (BraseroScsiModePage
, len
) +
156 sizeof (header
.page
.len
);
158 if (request_size
!= page_size
+ sizeof (BraseroScsiModeHdr
)) {
159 BRASERO_SCSI_SET_ERRCODE (error
, BRASERO_SCSI_SIZE_MISMATCH
);
160 BRASERO_MEDIA_LOG ("Incoherent answer sizes: request %i, page %i", request_size
, page_size
);
161 res
= BRASERO_SCSI_FAILURE
;
165 /* ... allocate an appropriate buffer ... */
166 buffer
= (BraseroScsiModeData
*) g_new0 (uchar
, request_size
);
168 /* ... re-issue the command */
169 BRASERO_MEDIA_LOG("Getting page (size = %i)", request_size
);
171 BRASERO_SET_16 (cdb
->alloc_len
, request_size
);
172 res
= brasero_scsi_command_issue_sync (cdb
, buffer
, request_size
, error
);
178 /* Paranoïa, some more checks:
179 * - the size of the page returned is the one we requested
180 * - block descriptors are actually disabled
181 * - header claimed size == buffer size
182 * - header claimed size == sizeof (header) + sizeof (page) */
183 buffer_size
= BRASERO_GET_16 (buffer
->hdr
.len
) +
184 G_STRUCT_OFFSET (BraseroScsiModeHdr
, len
) +
185 sizeof (buffer
->hdr
.len
);
187 page_size
= buffer
->page
.len
+
188 G_STRUCT_OFFSET (BraseroScsiModePage
, len
) +
189 sizeof (buffer
->page
.len
);
191 if (request_size
!= buffer_size
192 || BRASERO_GET_16 (buffer
->hdr
.bdlen
)
193 || buffer_size
!= page_size
+ sizeof (BraseroScsiModeHdr
)) {
196 BRASERO_SCSI_SET_ERRCODE (error
, BRASERO_SCSI_SIZE_MISMATCH
);
197 res
= BRASERO_SCSI_FAILURE
;
202 *data_size
= request_size
;
205 brasero_scsi_command_free (cdb
);