1
1
/* SCSI commands to USB Mass storage devices port library for Linux
3
* Copyright (c) 2010 Hans de Goede <hdegoede@redhat.com>
3
* Copyright (c) 2010-2012 Hans de Goede <hdegoede@redhat.com>
5
5
* This program is free software; you can redistribute it and/or modify
6
6
* it under the terms of the GNU Lesser General Public License as published by
16
16
* along with this program; if not, write to the Free Software
17
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
#define _BSD_SOURCE /* for flock */
19
22
#include "config.h"
20
23
#include <gphoto2/gphoto2-port-library.h>
23
27
#include <stdlib.h>
24
28
#include <unistd.h>
83
gp_port_usbscsi_lock (GPPort *port, const char *path)
87
gp_port_usbscsi_lock (GPPort *port)
88
90
gp_log (GP_LOG_DEBUG, "gphoto2-port-usbscsi",
89
"Trying to lock '%s'...", path);
91
"Trying to lock '%s'...", port->settings.usbscsi.path);
91
pid = dev_lock (path);
95
gp_port_set_error (port, _("Device '%s' is "
96
"locked by pid %d"), path, pid);
98
gp_port_set_error (port, _("Device '%s' could "
99
"not be locked (dev_lock returned "
93
if (flock(port->pl->fd, LOCK_EX | LOCK_NB) != 0) {
96
gp_port_set_error (port,
97
_("Device '%s' is locked by another app."),
98
port->settings.usbscsi.path);
99
return GP_ERROR_IO_LOCK;
101
gp_port_set_error (port,
102
_("Failed to lock '%s' (%m)."),
103
port->settings.usbscsi.path);
102
return GP_ERROR_IO_LOCK;
106
# warning No locking library found.
107
# warning You will run into problems if you use
108
# warning gphoto2 with a usbscsi picframe in
109
# warning combination with Konqueror (KDE) or Nautilus (GNOME).
110
# warning This will *not* concern USB cameras.
108
gp_log (GP_LOG_DEBUG, "gphoto2-port-usbscsi",
109
"Locking '%s' not possible, flock not availbale.", port->settings.usbscsi.path);
118
gp_port_usbscsi_unlock (GPPort *port, const char *path)
115
gp_port_usbscsi_unlock (GPPort *port)
123
pid = dev_unlock (path, 0);
127
gp_port_set_error (port, _("Device '%s' could "
128
"not be unlocked as it is locked by "
129
"pid %d."), path, pid);
131
gp_port_set_error (port, _("Device '%s' could "
132
"not be unlocked (dev_unlock "
133
"returned %d)"), path, pid);
135
return GP_ERROR_IO_LOCK;
118
if (flock(port->pl->fd, LOCK_UN) != 0) {
119
gp_port_set_error (port, _("Failed to unlock '%s' (%m)."),
120
port->settings.usbscsi.path);
137
#endif /* !HAVE_LOCKDEV */
222
207
while ((dirent = readdir (dir))) {
223
209
if (gp_port_usbscsi_get_usb_id (dirent->d_name,
224
210
&vendor_id, &product_id) != GP_OK)
225
211
continue; /* Not a usb device */
227
info.type = GP_PORT_USB_SCSI;
228
snprintf (info.path, sizeof (info.path),
213
gp_port_info_new (&info);
214
gp_port_info_set_type (info, GP_PORT_USB_SCSI);
215
snprintf (path, sizeof (path),
229
216
"usbscsi:/dev/%s",
231
snprintf (info.name, sizeof (info.name),
232
_("USB Mass Storage raw SCSI"));
218
gp_port_info_set_path (info, path);
219
gp_port_info_set_name (info, _("USB Mass Storage raw SCSI"));
233
220
CHECK (gp_port_info_list_append (list, info))
269
256
const int max_tries = 5;
270
257
const char *path = port->settings.usbscsi.path;
272
result = gp_port_usbscsi_lock (port, path);
273
if (result != GP_OK) {
274
for (i = 0; i < max_tries; i++) {
275
result = gp_port_usbscsi_lock (port, path);
278
gp_log (GP_LOG_DEBUG, "gphoto2-port-usbscsi",
279
"Failed to get a lock, trying again...");
284
259
port->pl->fd = open (path, O_RDWR);
285
260
if (port->pl->fd == -1) {
286
gp_port_usbscsi_unlock (port, path);
287
261
gp_port_set_error (port, _("Failed to open '%s' (%m)."), path);
288
262
return GP_ERROR_IO;
265
result = gp_port_usbscsi_lock (port);
266
for (i = 0; i < max_tries && result == GP_ERROR_IO_LOCK; i++) {
267
gp_log (GP_LOG_DEBUG, "gphoto2-port-usbscsi",
268
"Failed to get a lock, trying again...");
270
result = gp_port_usbscsi_lock (port);
272
if (result != GP_OK) {
273
close (port->pl->fd);
295
280
gp_port_usbscsi_close (GPPort *port)
297
284
if (!port || port->pl->fd == -1)
287
result = gp_port_usbscsi_unlock (port);
300
289
if (close (port->pl->fd) == -1) {
301
290
gp_port_set_error (port, _("Could not close "
302
291
"'%s' (%m)."), port->settings.usbscsi.path);
338
324
io_hdr.mx_sb_len = sense_size;
339
325
io_hdr.dxferp = (unsigned char *)data;
340
326
io_hdr.dxfer_len = data_size;
341
io_hdr.timeout = 500;
327
/*io_hdr.timeout = 1500;*/
328
io_hdr.timeout = port->timeout;
329
gp_log (GP_LOG_DEBUG, "port/usbscsi", "setting scsi command timeout to %d", port->timeout);
330
if (io_hdr.timeout < 1500)
331
io_hdr.timeout = 1500;
343
333
if (ioctl (port->pl->fd, SG_IO, &io_hdr) < 0)
346
336
"'%s' (%m)."), port->settings.usbscsi.path);
347
337
return GP_ERROR_IO;
349
/* https://secure.wikimedia.org/wikipedia/en/wiki/Key_Code_Qualifier */
351
gp_log(GP_LOG_DEBUG,"send_scsi_cmd","Request Sense reports:");
352
if ((sense[0]&0x7f)!=0x70) {
353
gp_log(GP_LOG_DEBUG,"send_scsi_cmd","\tInvalid header.");
356
gp_log(GP_LOG_DEBUG,"send_scsi_cmd","\tCurrent command read filemark: %s",(sense[2]&0x80)?"yes":"no");
357
gp_log(GP_LOG_DEBUG,"send_scsi_cmd","\tEarly warning passed: %s",(sense[2]&0x40)?"yes":"no");
358
gp_log(GP_LOG_DEBUG,"send_scsi_cmd","\tIncorrect blocklengt: %s",(sense[2]&0x20)?"yes":"no");
359
gp_log(GP_LOG_DEBUG,"send_scsi_cmd","\tSense Key: %d",sense[2]&0xf);
361
gp_log(GP_LOG_DEBUG,"send_scsi_cmd","\tResidual Length: %d",sense[3]*0x1000000+sense[4]*0x10000+sense[5]*0x100+sense[6]);
362
gp_log(GP_LOG_DEBUG,"send_scsi_cmd","\tAdditional Sense Length: %d",sense[7]);
363
gp_log(GP_LOG_DEBUG,"send_scsi_cmd","\tAdditional Sense Code: %d",sense[12]);
364
gp_log(GP_LOG_DEBUG,"send_scsi_cmd","\tAdditional Sense Code Qualifier: %d",sense[13]);
365
if (sense[15]&0x80) {
366
gp_log(GP_LOG_DEBUG,"send_scsi_cmd","\tIllegal Param is in %s",(sense[15]&0x40)?"the CDB":"the Data Out Phase");
368
gp_log(GP_LOG_DEBUG,"send_scsi_cmd","Pointer at %d, bit %d",sense[16]*256+sense[17],sense[15]&0x7);
374
341
return GP_ERROR_NOT_SUPPORTED;