aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/class
diff options
context:
space:
mode:
authorAlexandre Peixoto Ferreira <alexandref75@gmail.com>2013-04-30 01:51:53 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-05-16 20:50:51 -0400
commitd2ddce37a7f5992e256ba0d893f3ad5e2af96b21 (patch)
tree3ad4f2285fc2c7666a8c5b68fa48648572cd1ea6 /drivers/usb/class
parentc2e314835af0e09652ef4571eb5e481757ebb90f (diff)
USB: usbtmc: usbtmc_read sends multiple TMC header based on rigol_quirk
These patches implement a modification of the USBTMC protocol to allow operation with Rigol equipment. The usbtmc_read function is modified so if the quirk is active, the TMC header is sent with the size of the data as the whole size of the request. If the quirk is inactive, the TMC request is sent once per bulk transfer and with size limited to the bulk transfer size. In the case of the quirk, only the first response contains the TMC header and the others are just data. Signed-off-by: Alexandre Peixoto Ferreira <alexandref75@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/class')
-rw-r--r--drivers/usb/class/usbtmc.c152
1 files changed, 114 insertions, 38 deletions
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index fd2f90d21d95..8ebd06bf4865 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -455,21 +455,39 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf,
455 goto exit; 455 goto exit;
456 } 456 }
457 457
458 if (data->rigol_quirk) {
459 dev_dbg(dev, "usb_bulk_msg_in: count(%zu)\n", count);
460
461 retval = send_request_dev_dep_msg_in(data, count);
462
463 if (retval < 0) {
464 if (data->auto_abort)
465 usbtmc_ioctl_abort_bulk_out(data);
466 goto exit;
467 }
468 }
469
470 /* Loop until we have fetched everything we requested */
458 remaining = count; 471 remaining = count;
472 this_part = remaining;
459 done = 0; 473 done = 0;
460 474
461 while (remaining > 0) { 475 while (remaining > 0) {
462 if (remaining > USBTMC_SIZE_IOBUFFER - 12 - 3) 476 if (!(data->rigol_quirk)) {
463 this_part = USBTMC_SIZE_IOBUFFER - 12 - 3; 477 dev_dbg(dev, "usb_bulk_msg_in: remaining(%zu), count(%zu)\n", remaining, count);
464 else 478
465 this_part = remaining; 479 if (remaining > USBTMC_SIZE_IOBUFFER - USBTMC_HEADER_SIZE - 3)
480 this_part = USBTMC_SIZE_IOBUFFER - USBTMC_HEADER_SIZE - 3;
481 else
482 this_part = remaining;
466 483
467 retval = send_request_dev_dep_msg_in(data, this_part); 484 retval = send_request_dev_dep_msg_in(data, this_part);
468 if (retval < 0) { 485 if (retval < 0) {
469 dev_err(dev, "usb_bulk_msg returned %d\n", retval); 486 dev_err(dev, "usb_bulk_msg returned %d\n", retval);
470 if (data->auto_abort) 487 if (data->auto_abort)
471 usbtmc_ioctl_abort_bulk_out(data); 488 usbtmc_ioctl_abort_bulk_out(data);
472 goto exit; 489 goto exit;
490 }
473 } 491 }
474 492
475 /* Send bulk URB */ 493 /* Send bulk URB */
@@ -479,51 +497,109 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf,
479 buffer, USBTMC_SIZE_IOBUFFER, &actual, 497 buffer, USBTMC_SIZE_IOBUFFER, &actual,
480 USBTMC_TIMEOUT); 498 USBTMC_TIMEOUT);
481 499
500 dev_dbg(dev, "usb_bulk_msg: retval(%u), done(%zu), remaining(%zu), actual(%d)\n", retval, done, remaining, actual);
501
482 /* Store bTag (in case we need to abort) */ 502 /* Store bTag (in case we need to abort) */
483 data->bTag_last_read = data->bTag; 503 data->bTag_last_read = data->bTag;
484 504
485 if (retval < 0) { 505 if (retval < 0) {
486 dev_err(dev, "Unable to read data, error %d\n", retval); 506 dev_dbg(dev, "Unable to read data, error %d\n", retval);
487 if (data->auto_abort) 507 if (data->auto_abort)
488 usbtmc_ioctl_abort_bulk_in(data); 508 usbtmc_ioctl_abort_bulk_in(data);
489 goto exit; 509 goto exit;
490 } 510 }
491 511
492 /* How many characters did the instrument send? */ 512 /* Parse header in first packet */
493 n_characters = buffer[4] + 513 if ((done == 0) || (!(data->rigol_quirk))) {
494 (buffer[5] << 8) + 514 /* Sanity checks for the header */
495 (buffer[6] << 16) + 515 if (actual < USBTMC_HEADER_SIZE) {
496 (buffer[7] << 24); 516 dev_err(dev, "Device sent too small first packet: %u < %u\n", actual, USBTMC_HEADER_SIZE);
517 if (data->auto_abort)
518 usbtmc_ioctl_abort_bulk_in(data);
519 goto exit;
520 }
497 521
498 /* Ensure the instrument doesn't lie about it */ 522 if (buffer[0] != 2) {
499 if(n_characters > actual - 12) { 523 dev_err(dev, "Device sent reply with wrong MsgID: %u != 2\n", buffer[0]);
500 dev_err(dev, "Device lies about message size: %u > %d\n", n_characters, actual - 12); 524 if (data->auto_abort)
501 n_characters = actual - 12; 525 usbtmc_ioctl_abort_bulk_in(data);
502 } 526 goto exit;
527 }
503 528
504 /* Ensure the instrument doesn't send more back than requested */ 529 if (buffer[1] != data->bTag_last_write) {
505 if(n_characters > this_part) { 530 dev_err(dev, "Device sent reply with wrong bTag: %u != %u\n", buffer[1], data->bTag_last_write);
506 dev_err(dev, "Device returns more than requested: %zu > %zu\n", done + n_characters, done + this_part); 531 if (data->auto_abort)
507 n_characters = this_part; 532 usbtmc_ioctl_abort_bulk_in(data);
508 } 533 goto exit;
534 }
509 535
510 /* Bound amount of data received by amount of data requested */ 536 /* How many characters did the instrument send? */
511 if (n_characters > this_part) 537 n_characters = buffer[4] +
512 n_characters = this_part; 538 (buffer[5] << 8) +
539 (buffer[6] << 16) +
540 (buffer[7] << 24);
513 541
514 /* Copy buffer to user space */ 542 if (n_characters > this_part) {
515 if (copy_to_user(buf + done, &buffer[12], n_characters)) { 543 dev_err(dev, "Device wants to return more data than requested: %u > %zu\n", n_characters, count);
516 /* There must have been an addressing problem */ 544 if (data->auto_abort)
517 retval = -EFAULT; 545 usbtmc_ioctl_abort_bulk_in(data);
518 goto exit; 546 goto exit;
547 }
548
549 /* Remove the USBTMC header */
550 actual -= USBTMC_HEADER_SIZE;
551
552 /* Check if the message is smaller than requested */
553 if (data->rigol_quirk) {
554 if (remaining > n_characters)
555 remaining = n_characters;
556 /* Remove padding if it exists */
557 if (actual > remaining)
558 actual = remaining;
559 }
560 else {
561 if (this_part > n_characters)
562 this_part = n_characters;
563 /* Remove padding if it exists */
564 if (actual > this_part)
565 actual = this_part;
566 }
567
568 dev_dbg(dev, "Bulk-IN header: N_characters(%u), bTransAttr(%u)\n", n_characters, buffer[8]);
569
570 remaining -= actual;
571
572 /* Terminate if end-of-message bit received from device */
573 if ((buffer[8] & 0x01) && (actual >= n_characters))
574 remaining = 0;
575
576 dev_dbg(dev, "Bulk-IN header: remaining(%zu), buf(%p), buffer(%p) done(%zu)\n", remaining,buf,buffer,done);
577
578
579 /* Copy buffer to user space */
580 if (copy_to_user(buf + done, &buffer[USBTMC_HEADER_SIZE], actual)) {
581 /* There must have been an addressing problem */
582 retval = -EFAULT;
583 goto exit;
584 }
585 done += actual;
519 } 586 }
587 else {
588 if (actual > remaining)
589 actual = remaining;
520 590
521 done += n_characters; 591 remaining -= actual;
522 /* Terminate if end-of-message bit received from device */ 592
523 if ((buffer[8] & 0x01) && (actual >= n_characters + 12)) 593 dev_dbg(dev, "Bulk-IN header cont: actual(%u), done(%zu), remaining(%zu), buf(%p), buffer(%p)\n", actual, done, remaining,buf,buffer);
524 remaining = 0; 594
525 else 595 /* Copy buffer to user space */
526 remaining -= n_characters; 596 if (copy_to_user(buf + done, buffer, actual)) {
597 /* There must have been an addressing problem */
598 retval = -EFAULT;
599 goto exit;
600 }
601 done += actual;
602 }
527 } 603 }
528 604
529 /* Update file position value */ 605 /* Update file position value */