Revision 29c74f76

b/hw/usb-msd.c
43 43
    enum USBMSDMode mode;
44 44
    uint32_t scsi_len;
45 45
    uint8_t *scsi_buf;
46
    uint32_t usb_len;
47
    uint8_t *usb_buf;
48 46
    uint32_t data_len;
49 47
    uint32_t residue;
50 48
    uint32_t tag;
......
176 174
    .str  = desc_strings,
177 175
};
178 176

  
179
static void usb_msd_copy_data(MSDState *s)
177
static void usb_msd_copy_data(MSDState *s, USBPacket *p)
180 178
{
181 179
    uint32_t len;
182
    len = s->usb_len;
180
    len = p->iov.size - p->result;
183 181
    if (len > s->scsi_len)
184 182
        len = s->scsi_len;
185
    if (s->mode == USB_MSDM_DATAIN) {
186
        memcpy(s->usb_buf, s->scsi_buf, len);
187
    } else {
188
        memcpy(s->scsi_buf, s->usb_buf, len);
189
    }
190
    s->usb_len -= len;
183
    usb_packet_copy(p, s->scsi_buf, len);
191 184
    s->scsi_len -= len;
192
    s->usb_buf += len;
193 185
    s->scsi_buf += len;
194 186
    s->data_len -= len;
195 187
    if (s->scsi_len == 0 || s->data_len == 0) {
......
221 213
    s->scsi_len = len;
222 214
    s->scsi_buf = scsi_req_get_buf(req);
223 215
    if (p) {
224
        usb_msd_copy_data(s);
225
        if (s->packet && s->usb_len == 0) {
226
            p->result = p->iov.size;
216
        usb_msd_copy_data(s, p);
217
        p = s->packet;
218
        if (p && p->result == p->iov.size) {
227 219
            /* Set s->packet to NULL before calling usb_packet_complete
228 220
               because another request may be issued before
229 221
               usb_packet_complete returns.  */
......
250 242
            s->mode = USB_MSDM_CBW;
251 243
        } else {
252 244
            if (s->data_len) {
253
                s->data_len -= s->usb_len;
254
                if (s->mode == USB_MSDM_DATAIN) {
255
                    memset(s->usb_buf, 0, s->usb_len);
256
                }
257
                s->usb_len = 0;
245
                int len = (p->iov.size - p->result);
246
                usb_packet_skip(p, len);
247
                s->data_len -= len;
258 248
            }
259 249
            if (s->data_len == 0) {
260 250
                s->mode = USB_MSDM_CSW;
261 251
            }
262
            p->result = p->iov.size;
263 252
        }
264 253
        s->packet = NULL;
265 254
        usb_packet_complete(&s->dev, p);
......
345 334
    int ret = 0;
346 335
    struct usb_msd_cbw cbw;
347 336
    uint8_t devep = p->devep;
348
    uint8_t *data = p->iov.iov[0].iov_base;
349
    int len = p->iov.iov[0].iov_len;
350 337

  
351
    assert(p->iov.niov == 1); /* temporary */
352 338
    switch (p->pid) {
353 339
    case USB_TOKEN_OUT:
354 340
        if (devep != 2)
......
356 342

  
357 343
        switch (s->mode) {
358 344
        case USB_MSDM_CBW:
359
            if (len != 31) {
345
            if (p->iov.size != 31) {
360 346
                fprintf(stderr, "usb-msd: Bad CBW size");
361 347
                goto fail;
362 348
            }
363
            memcpy(&cbw, data, 31);
349
            usb_packet_copy(p, &cbw, 31);
364 350
            if (le32_to_cpu(cbw.sig) != 0x43425355) {
365 351
                fprintf(stderr, "usb-msd: Bad signature %08x\n",
366 352
                        le32_to_cpu(cbw.sig));
......
391 377
            if (s->mode != USB_MSDM_CSW && s->residue == 0) {
392 378
                scsi_req_continue(s->req);
393 379
            }
394
            ret = len;
380
            ret = p->result;
395 381
            break;
396 382

  
397 383
        case USB_MSDM_DATAOUT:
398
            DPRINTF("Data out %d/%d\n", len, s->data_len);
399
            if (len > s->data_len)
384
            DPRINTF("Data out %zd/%d\n", p->iov.size, s->data_len);
385
            if (p->iov.size > s->data_len) {
400 386
                goto fail;
387
            }
401 388

  
402
            s->usb_buf = data;
403
            s->usb_len = len;
404 389
            if (s->scsi_len) {
405
                usb_msd_copy_data(s);
390
                usb_msd_copy_data(s, p);
406 391
            }
407
            if (s->residue && s->usb_len) {
408
                s->data_len -= s->usb_len;
409
                if (s->data_len == 0)
410
                    s->mode = USB_MSDM_CSW;
411
                s->usb_len = 0;
392
            if (s->residue) {
393
                int len = p->iov.size - p->result;
394
                if (len) {
395
                    usb_packet_skip(p, len);
396
                    s->data_len -= len;
397
                    if (s->data_len == 0) {
398
                        s->mode = USB_MSDM_CSW;
399
                    }
400
                }
412 401
            }
413
            if (s->usb_len) {
402
            if (p->result < p->iov.size) {
414 403
                DPRINTF("Deferring packet %p\n", p);
415 404
                s->packet = p;
416 405
                ret = USB_RET_ASYNC;
417 406
            } else {
418
                ret = len;
407
                ret = p->result;
419 408
            }
420 409
            break;
421 410

  
422 411
        default:
423
            DPRINTF("Unexpected write (len %d)\n", len);
412
            DPRINTF("Unexpected write (len %zd)\n", p->iov.size);
424 413
            goto fail;
425 414
        }
426 415
        break;
......
431 420

  
432 421
        switch (s->mode) {
433 422
        case USB_MSDM_DATAOUT:
434
            if (s->data_len != 0 || len < 13)
423
            if (s->data_len != 0 || p->iov.size < 13) {
435 424
                goto fail;
425
            }
436 426
            /* Waiting for SCSI write to complete.  */
437 427
            s->packet = p;
438 428
            ret = USB_RET_ASYNC;
439 429
            break;
440 430

  
441 431
        case USB_MSDM_CSW:
442
            DPRINTF("Command status %d tag 0x%x, len %d\n",
443
                    s->result, s->tag, len);
444
            if (len < 13)
432
            DPRINTF("Command status %d tag 0x%x, len %zd\n",
433
                    s->result, s->tag, p->iov.size);
434
            if (p->iov.size < 13) {
445 435
                goto fail;
436
            }
446 437

  
447 438
            usb_msd_send_status(s, p);
448 439
            s->mode = USB_MSDM_CBW;
......
450 441
            break;
451 442

  
452 443
        case USB_MSDM_DATAIN:
453
            DPRINTF("Data in %d/%d, scsi_len %d\n", len, s->data_len, s->scsi_len);
454
            if (len > s->data_len)
455
                len = s->data_len;
456
            s->usb_buf = data;
457
            s->usb_len = len;
444
            DPRINTF("Data in %zd/%d, scsi_len %d\n",
445
                    p->iov.size, s->data_len, s->scsi_len);
458 446
            if (s->scsi_len) {
459
                usb_msd_copy_data(s);
447
                usb_msd_copy_data(s, p);
460 448
            }
461
            if (s->residue && s->usb_len) {
462
                s->data_len -= s->usb_len;
463
                memset(s->usb_buf, 0, s->usb_len);
464
                if (s->data_len == 0)
465
                    s->mode = USB_MSDM_CSW;
466
                s->usb_len = 0;
449
            if (s->residue) {
450
                int len = p->iov.size - p->result;
451
                if (len) {
452
                    usb_packet_skip(p, len);
453
                    s->data_len -= len;
454
                    if (s->data_len == 0) {
455
                        s->mode = USB_MSDM_CSW;
456
                    }
457
                }
467 458
            }
468
            if (s->usb_len) {
459
            if (p->result < p->iov.size) {
469 460
                DPRINTF("Deferring packet %p\n", p);
470 461
                s->packet = p;
471 462
                ret = USB_RET_ASYNC;
472 463
            } else {
473
                ret = len;
464
                ret = p->result;
474 465
            }
475 466
            break;
476 467

  
477 468
        default:
478
            DPRINTF("Unexpected read (len %d)\n", len);
469
            DPRINTF("Unexpected read (len %zd)\n", p->iov.size);
479 470
            goto fail;
480 471
        }
481 472
        break;

Also available in: Unified diff