Merge branch 'master' into 'master'
[brasero.git] / libbrasero-media / scsi-sg.c
blob8e88e1a2a888c2356f0963519afe9782a278e5c8
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3 * Libbrasero-media
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.
31 #ifdef HAVE_CONFIG_H
32 # include <config.h>
33 #endif
35 #include <errno.h>
36 #include <unistd.h>
37 #include <stdlib.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <fcntl.h>
41 #include <string.h>
42 #include <sys/ioctl.h>
44 #include <scsi/scsi.h>
45 #include <scsi/sg.h>
47 #include "brasero-media-private.h"
49 #include "scsi-command.h"
50 #include "scsi-utils.h"
51 #include "scsi-error.h"
52 #include "scsi-sense-data.h"
54 struct _BraseroDeviceHandle {
55 int fd;
58 struct _BraseroScsiCmd {
59 uchar cmd [BRASERO_SCSI_CMD_MAX_LEN];
60 BraseroDeviceHandle *handle;
62 const BraseroScsiCmdInfo *info;
64 typedef struct _BraseroScsiCmd BraseroScsiCmd;
66 #define BRASERO_SCSI_CMD_OPCODE_OFF 0
67 #define BRASERO_SCSI_CMD_SET_OPCODE(command) (command->cmd [BRASERO_SCSI_CMD_OPCODE_OFF] = command->info->opcode)
69 #define OPEN_FLAGS O_RDWR /*|O_EXCL */|O_NONBLOCK
71 /**
72 * This is to send a command
75 static void
76 brasero_sg_command_setup (struct sg_io_hdr *transport,
77 uchar *sense_data,
78 BraseroScsiCmd *cmd,
79 uchar *buffer,
80 int size)
82 memset (sense_data, 0, BRASERO_SENSE_DATA_SIZE);
83 memset (transport, 0, sizeof (struct sg_io_hdr));
85 transport->interface_id = 'S'; /* mandatory */
86 // transport->flags = SG_FLAG_LUN_INHIBIT|SG_FLAG_DIRECT_IO;
87 transport->cmdp = cmd->cmd;
88 transport->cmd_len = cmd->info->size;
89 transport->dxferp = buffer;
90 transport->dxfer_len = size;
92 /* where to output the scsi sense buffer */
93 transport->sbp = sense_data;
94 transport->mx_sb_len = BRASERO_SENSE_DATA_SIZE;
96 if (cmd->info->direction & BRASERO_SCSI_READ)
97 transport->dxfer_direction = SG_DXFER_FROM_DEV;
98 else if (cmd->info->direction & BRASERO_SCSI_WRITE)
99 transport->dxfer_direction = SG_DXFER_TO_DEV;
102 BraseroScsiResult
103 brasero_scsi_command_issue_sync (gpointer command,
104 gpointer buffer,
105 int size,
106 BraseroScsiErrCode *error)
108 uchar sense_buffer [BRASERO_SENSE_DATA_SIZE];
109 struct sg_io_hdr transport;
110 BraseroScsiResult res;
111 BraseroScsiCmd *cmd;
113 g_return_val_if_fail (command != NULL, BRASERO_SCSI_FAILURE);
115 cmd = command;
116 brasero_sg_command_setup (&transport,
117 sense_buffer,
118 cmd,
119 buffer,
120 size);
122 /* NOTE on SG_IO: only for TEST UNIT READY, REQUEST/MODE SENSE, INQUIRY,
123 * READ CAPACITY, READ BUFFER, READ and LOG SENSE are allowed with it */
124 res = ioctl (cmd->handle->fd, SG_IO, &transport);
125 if (res) {
126 BRASERO_SCSI_SET_ERRCODE (error, BRASERO_SCSI_ERRNO);
127 return BRASERO_SCSI_FAILURE;
130 if ((transport.info & SG_INFO_OK_MASK) == SG_INFO_OK)
131 return BRASERO_SCSI_OK;
133 if ((transport.masked_status & CHECK_CONDITION) && transport.sb_len_wr)
134 return brasero_sense_data_process (sense_buffer, error);
136 return BRASERO_SCSI_FAILURE;
139 gpointer
140 brasero_scsi_command_new (const BraseroScsiCmdInfo *info,
141 BraseroDeviceHandle *handle)
143 BraseroScsiCmd *cmd;
145 g_return_val_if_fail (handle != NULL, NULL);
147 /* make sure we can set the flags of the descriptor */
149 /* allocate the command */
150 cmd = g_new0 (BraseroScsiCmd, 1);
151 cmd->info = info;
152 cmd->handle = handle;
154 BRASERO_SCSI_CMD_SET_OPCODE (cmd);
155 return cmd;
158 BraseroScsiResult
159 brasero_scsi_command_free (gpointer cmd)
161 g_free (cmd);
162 return BRASERO_SCSI_OK;
166 * This is to open a device
169 BraseroDeviceHandle *
170 brasero_device_handle_open (const gchar *path,
171 gboolean exclusive,
172 BraseroScsiErrCode *code)
174 int fd;
175 int flags = OPEN_FLAGS;
176 BraseroDeviceHandle *handle;
178 if (exclusive)
179 flags |= O_EXCL;
181 BRASERO_MEDIA_LOG ("Getting handle");
182 fd = open (path, flags);
183 if (fd < 0) {
184 BRASERO_MEDIA_LOG ("No handle: %s", strerror (errno));
185 if (code) {
186 if (errno == EAGAIN
187 || errno == EWOULDBLOCK
188 || errno == EBUSY)
189 *code = BRASERO_SCSI_NOT_READY;
190 else
191 *code = BRASERO_SCSI_ERRNO;
194 return NULL;
197 handle = g_new (BraseroDeviceHandle, 1);
198 handle->fd = fd;
200 BRASERO_MEDIA_LOG ("Handle ready");
201 return handle;
204 void
205 brasero_device_handle_close (BraseroDeviceHandle *handle)
207 close (handle->fd);
208 g_free (handle);
211 char *
212 brasero_device_get_bus_target_lun (const gchar *device)
214 return strdup (device);