~ubuntu-branches/ubuntu/utopic/libgphoto2/utopic-proposed

« back to all changes in this revision

Viewing changes to camlibs/sierra/sierra-usbwrap.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt
  • Date: 2014-04-28 13:50:11 UTC
  • mfrom: (1.4.6) (2.1.24 sid)
  • Revision ID: package-import@ubuntu.com-20140428135011-undw190zxp0sezkv
Tags: 2.5.4-1ubuntu1
* Merge with Debian unstable. Remaining Ubuntu changes:
  - Re-introduce building with dh-autoreconf instead of just autotools_dev
    to use latest libtool. Fixes ppc64el build failure.
  - Stop installing the udev rules; it's redundant with the (much more
    efficient) hwdb file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* sierra_usbwrap.c
2
2
 *
3
 
 * Copyright � 2002 Lutz M�ller <lutz@users.sourceforge.net>
 
3
 * Copyright 2002 Lutz M�ller <lutz@users.sourceforge.net>
 
4
 * Copyright 2012-2013 Marcus Meissner <marcus@jet.franken.de>
4
5
 *
5
6
 * This library is free software; you can redistribute it and/or
6
7
 * modify it under the terms of the GNU Lesser General Public
123
124
#define UW_PACKET_DATA ((uw4c_t){ 0x02, 0x00, 0xff, 0x9f })
124
125
#define UW_PACKET_STAT ((uw4c_t){ 0x03, 0x00, 0xff, 0x9f })
125
126
 
 
127
#define UW_MAGIC_OUT ((uw4c_t){ 'U','S','B','C' })
 
128
#define UW_MAGIC_IN  ((uw4c_t){ 'U','S','B','S' })
 
129
 
126
130
#pragma pack(1)
 
131
/* This is linux/include/linux/usb/storage.h, struct bulk_cb_wrap
 
132
 * 31 byte length */
 
133
typedef struct
 
134
{
 
135
      uw4c_t magic;             /* The letters U S B C for packets sent to camera */
 
136
      uw32_t tag;               /* The SCSI command tag */
 
137
      uw32_t rw_length;         /* Length of data to be read or written next */
 
138
      unsigned char flags;      /* in / out flag mostly */
 
139
      unsigned char lun;        /* 0 here */
 
140
      unsigned char length;     /* of the CDB... but 0x0c is used here in the traces */
 
141
      unsigned char cdb[16];    
 
142
} uw_header_t;
 
143
 
 
144
/*
 
145
 * This is the end response block from the camera looks like this:
 
146
 *
 
147
 * This is the generic bulk style USB Storage response block.
 
148
 *
 
149
 * linux/include/linux/usb/storage.h, struct bulk_cs_wrap */
 
150
typedef struct
 
151
{
 
152
      uw4c_t magic;     /* The letters U S B S for packets from camera */
 
153
      uw32_t tag;       /* A copy of whatever value the host made up */
 
154
      uw32_t residue;   /* residual read? */
 
155
      char   status;    /* status byte */
 
156
} uw_response_t;
 
157
 
127
158
/*
128
159
 * Data packet sent along with a UW_REQUEST_RDY:
129
160
 */
165
196
      uw32_t size;             /* The size of data waiting to be sent by camera */
166
197
} uw_size_t;
167
198
 
168
 
/*
169
 
 * The end of the response from the camera looks like this:
170
 
 */
171
 
typedef struct
172
 
{
173
 
      uw4c_t magic;    /* The letters U S B S for packets from camera */
174
 
      uw32_t sessionid;        /* A copy of whatever value the host made up */
175
 
      char   zero[5];  /* 00 00 00 00 00 */
176
 
} uw_response_t;
177
 
 
178
199
typedef struct
179
200
{
180
201
      unsigned char cmd;
184
205
} uw_scsicmd_t;
185
206
#pragma pack()
186
207
 
 
208
static int ums_tag = 0x42424242;
 
209
 
 
210
static int
 
211
scsi_wrap_cmd(
 
212
        GPPort *dev, int todev,
 
213
        char *cmd, unsigned int cmdlen,
 
214
        char *sense, unsigned int senselen,
 
215
        char *data, unsigned int size
 
216
) {
 
217
        GPPortInfo      info;
 
218
        GPPortType      type;
 
219
        uw_header_t     hdr;
 
220
        uw_response_t   rsp;
 
221
        int             ret;
 
222
 
 
223
        ret = gp_port_get_info (dev, &info);
 
224
        if (ret != GP_OK) return ret;
 
225
 
 
226
        ret = gp_port_info_get_type (info, &type);
 
227
        if (ret != GP_OK) return ret;
 
228
 
 
229
        if (type == GP_PORT_USB_SCSI)
 
230
                /* just send it to the generic SCSI stack */
 
231
                return gp_port_send_scsi_cmd (
 
232
                        dev, todev,
 
233
                        cmd, cmdlen,
 
234
                        sense, senselen,
 
235
                        data, size
 
236
                );
 
237
 
 
238
        /* Assuming plain USB, emulating SCSI ... */
 
239
 
 
240
        memset(&hdr, 0, sizeof(hdr));
 
241
        hdr.magic       = UW_MAGIC_OUT;
 
242
        hdr.tag         = uw_value(ums_tag);
 
243
        ums_tag++;
 
244
        hdr.rw_length   = uw_value(size);
 
245
        hdr.length      = 12; /* seems to be always 12, even as we send 16 byte CDBs */
 
246
        hdr.flags       = todev?0:(1<<7);
 
247
        hdr.lun         = 0;
 
248
 
 
249
        memcpy(hdr.cdb, cmd, cmdlen);
 
250
 
 
251
        /* WRITE scsi header / cdb */
 
252
        if ((ret=gp_port_write(dev, (char*)&hdr, sizeof(hdr))) < GP_OK) {
 
253
                GP_DEBUG( "scsi_wrap_cmd *** FAILED to write scsi cmd" );
 
254
                return GP_ERROR_IO;
 
255
        }
 
256
        /* WRITE / READ data blob */
 
257
        if (todev) {
 
258
                if ((ret=gp_port_write(dev, (char*)data, size)) < GP_OK) {
 
259
                        GP_DEBUG( "scsi_wrap_cmd *** FAILED to write scsi data" );
 
260
                        return GP_ERROR_IO;
 
261
                }
 
262
        } else {
 
263
                if ((ret=gp_port_read(dev, (char*)data, size)) < GP_OK) {
 
264
                        GP_DEBUG( "scsi_wrap_cmd *** FAILED to read scsi data" );
 
265
                        return GP_ERROR_IO;
 
266
                }
 
267
        }
 
268
 
 
269
        /* READ RESPONSE */
 
270
        memset(&rsp, 0, sizeof(rsp));
 
271
 
 
272
        GP_DEBUG( "usb_wrap_OK" );
 
273
        if ((ret = gp_port_read(dev, (char*)&rsp, sizeof(rsp))) != sizeof(rsp)) {
 
274
                gp_log (GP_LOG_DEBUG, GP_MODULE, "scsi_wrap_cmd *** FAILED (%d vs %d bytes)", (int)sizeof(rsp), ret );
 
275
                if (ret < GP_OK)
 
276
                        return ret;
 
277
                return GP_ERROR;
 
278
        }
 
279
        if (    !UW_EQUAL(rsp.magic, UW_MAGIC_IN) ||
 
280
                !UW_EQUAL(rsp.tag, hdr.tag))
 
281
        {
 
282
                GP_DEBUG( "scsi_wrap_cmd wrong session *** FAILED" );
 
283
                return GP_ERROR;
 
284
        }
 
285
        /*
 
286
         * 32bit residual length (0) and 8 bit status (0) are good.
 
287
         */
 
288
        if (    rsp.residue.c1 != 0 ||
 
289
                rsp.residue.c2 != 0 ||
 
290
                rsp.residue.c3 != 0 ||
 
291
                rsp.residue.c4 != 0 ||
 
292
                rsp.status != 0) {
 
293
                GP_DEBUG( "Error: scsi_wrap_cmd - residual non-0 or status %x", rsp.status);
 
294
                return GP_ERROR;
 
295
        }
 
296
        return GP_OK;
 
297
}
 
298
 
 
299
#define gp_port_send_scsi_cmd scsi_wrap_cmd
 
300
 
187
301
static int
188
302
usb_wrap_RDY(gp_port* dev, unsigned int type)
189
303
{