|
@@ -270,18 +270,17 @@ static int usbtmc_release(struct inode *inode, struct file *file)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data)
|
|
|
+static int usbtmc_ioctl_abort_bulk_in_tag(struct usbtmc_device_data *data,
|
|
|
+ u8 tag)
|
|
|
{
|
|
|
u8 *buffer;
|
|
|
struct device *dev;
|
|
|
int rv;
|
|
|
int n;
|
|
|
int actual;
|
|
|
- struct usb_host_interface *current_setting;
|
|
|
- int max_size;
|
|
|
|
|
|
dev = &data->intf->dev;
|
|
|
- buffer = kmalloc(USBTMC_SIZE_IOBUFFER, GFP_KERNEL);
|
|
|
+ buffer = kmalloc(USBTMC_BUFSIZE, GFP_KERNEL);
|
|
|
if (!buffer)
|
|
|
return -ENOMEM;
|
|
|
|
|
@@ -289,86 +288,87 @@ static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data)
|
|
|
usb_rcvctrlpipe(data->usb_dev, 0),
|
|
|
USBTMC_REQUEST_INITIATE_ABORT_BULK_IN,
|
|
|
USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT,
|
|
|
- data->bTag_last_read, data->bulk_in,
|
|
|
- buffer, 2, USBTMC_TIMEOUT);
|
|
|
+ tag, data->bulk_in,
|
|
|
+ buffer, 2, USB_CTRL_GET_TIMEOUT);
|
|
|
|
|
|
if (rv < 0) {
|
|
|
dev_err(dev, "usb_control_msg returned %d\n", rv);
|
|
|
goto exit;
|
|
|
}
|
|
|
|
|
|
- dev_dbg(dev, "INITIATE_ABORT_BULK_IN returned %x\n", buffer[0]);
|
|
|
+ dev_dbg(dev, "INITIATE_ABORT_BULK_IN returned %x with tag %02x\n",
|
|
|
+ buffer[0], buffer[1]);
|
|
|
|
|
|
if (buffer[0] == USBTMC_STATUS_FAILED) {
|
|
|
+ /* No transfer in progress and the Bulk-OUT FIFO is empty. */
|
|
|
rv = 0;
|
|
|
goto exit;
|
|
|
}
|
|
|
|
|
|
- if (buffer[0] != USBTMC_STATUS_SUCCESS) {
|
|
|
- dev_err(dev, "INITIATE_ABORT_BULK_IN returned %x\n",
|
|
|
- buffer[0]);
|
|
|
- rv = -EPERM;
|
|
|
+ if (buffer[0] == USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS) {
|
|
|
+ /* The device returns this status if either:
|
|
|
+ * - There is a transfer in progress, but the specified bTag
|
|
|
+ * does not match.
|
|
|
+ * - There is no transfer in progress, but the Bulk-OUT FIFO
|
|
|
+ * is not empty.
|
|
|
+ */
|
|
|
+ rv = -ENOMSG;
|
|
|
goto exit;
|
|
|
}
|
|
|
|
|
|
- max_size = 0;
|
|
|
- current_setting = data->intf->cur_altsetting;
|
|
|
- for (n = 0; n < current_setting->desc.bNumEndpoints; n++)
|
|
|
- if (current_setting->endpoint[n].desc.bEndpointAddress ==
|
|
|
- data->bulk_in)
|
|
|
- max_size = usb_endpoint_maxp(¤t_setting->endpoint[n].desc);
|
|
|
-
|
|
|
- if (max_size == 0) {
|
|
|
- dev_err(dev, "Couldn't get wMaxPacketSize\n");
|
|
|
+ if (buffer[0] != USBTMC_STATUS_SUCCESS) {
|
|
|
+ dev_err(dev, "INITIATE_ABORT_BULK_IN returned %x\n",
|
|
|
+ buffer[0]);
|
|
|
rv = -EPERM;
|
|
|
goto exit;
|
|
|
}
|
|
|
|
|
|
- dev_dbg(&data->intf->dev, "wMaxPacketSize is %d\n", max_size);
|
|
|
-
|
|
|
n = 0;
|
|
|
|
|
|
- do {
|
|
|
- dev_dbg(dev, "Reading from bulk in EP\n");
|
|
|
+usbtmc_abort_bulk_in_status:
|
|
|
+ dev_dbg(dev, "Reading from bulk in EP\n");
|
|
|
|
|
|
- rv = usb_bulk_msg(data->usb_dev,
|
|
|
- usb_rcvbulkpipe(data->usb_dev,
|
|
|
- data->bulk_in),
|
|
|
- buffer, USBTMC_SIZE_IOBUFFER,
|
|
|
- &actual, USBTMC_TIMEOUT);
|
|
|
+ /* Data must be present. So use low timeout 300 ms */
|
|
|
+ rv = usb_bulk_msg(data->usb_dev,
|
|
|
+ usb_rcvbulkpipe(data->usb_dev,
|
|
|
+ data->bulk_in),
|
|
|
+ buffer, USBTMC_BUFSIZE,
|
|
|
+ &actual, 300);
|
|
|
|
|
|
- n++;
|
|
|
+ print_hex_dump_debug("usbtmc ", DUMP_PREFIX_NONE, 16, 1,
|
|
|
+ buffer, actual, true);
|
|
|
|
|
|
- if (rv < 0) {
|
|
|
- dev_err(dev, "usb_bulk_msg returned %d\n", rv);
|
|
|
+ n++;
|
|
|
+
|
|
|
+ if (rv < 0) {
|
|
|
+ dev_err(dev, "usb_bulk_msg returned %d\n", rv);
|
|
|
+ if (rv != -ETIMEDOUT)
|
|
|
goto exit;
|
|
|
- }
|
|
|
- } while ((actual == max_size) &&
|
|
|
- (n < USBTMC_MAX_READS_TO_CLEAR_BULK_IN));
|
|
|
+ }
|
|
|
|
|
|
- if (actual == max_size) {
|
|
|
+ if (actual == USBTMC_BUFSIZE)
|
|
|
+ goto usbtmc_abort_bulk_in_status;
|
|
|
+
|
|
|
+ if (n >= USBTMC_MAX_READS_TO_CLEAR_BULK_IN) {
|
|
|
dev_err(dev, "Couldn't clear device buffer within %d cycles\n",
|
|
|
USBTMC_MAX_READS_TO_CLEAR_BULK_IN);
|
|
|
rv = -EPERM;
|
|
|
goto exit;
|
|
|
}
|
|
|
|
|
|
- n = 0;
|
|
|
-
|
|
|
-usbtmc_abort_bulk_in_status:
|
|
|
rv = usb_control_msg(data->usb_dev,
|
|
|
usb_rcvctrlpipe(data->usb_dev, 0),
|
|
|
USBTMC_REQUEST_CHECK_ABORT_BULK_IN_STATUS,
|
|
|
USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT,
|
|
|
0, data->bulk_in, buffer, 0x08,
|
|
|
- USBTMC_TIMEOUT);
|
|
|
+ USB_CTRL_GET_TIMEOUT);
|
|
|
|
|
|
if (rv < 0) {
|
|
|
dev_err(dev, "usb_control_msg returned %d\n", rv);
|
|
|
goto exit;
|
|
|
}
|
|
|
|
|
|
- dev_dbg(dev, "INITIATE_ABORT_BULK_IN returned %x\n", buffer[0]);
|
|
|
+ dev_dbg(dev, "CHECK_ABORT_BULK_IN returned %x\n", buffer[0]);
|
|
|
|
|
|
if (buffer[0] == USBTMC_STATUS_SUCCESS) {
|
|
|
rv = 0;
|
|
@@ -376,43 +376,26 @@ usbtmc_abort_bulk_in_status:
|
|
|
}
|
|
|
|
|
|
if (buffer[0] != USBTMC_STATUS_PENDING) {
|
|
|
- dev_err(dev, "INITIATE_ABORT_BULK_IN returned %x\n", buffer[0]);
|
|
|
+ dev_err(dev, "CHECK_ABORT_BULK_IN returned %x\n", buffer[0]);
|
|
|
rv = -EPERM;
|
|
|
goto exit;
|
|
|
}
|
|
|
|
|
|
- if (buffer[1] == 1)
|
|
|
- do {
|
|
|
- dev_dbg(dev, "Reading from bulk in EP\n");
|
|
|
-
|
|
|
- rv = usb_bulk_msg(data->usb_dev,
|
|
|
- usb_rcvbulkpipe(data->usb_dev,
|
|
|
- data->bulk_in),
|
|
|
- buffer, USBTMC_SIZE_IOBUFFER,
|
|
|
- &actual, USBTMC_TIMEOUT);
|
|
|
-
|
|
|
- n++;
|
|
|
-
|
|
|
- if (rv < 0) {
|
|
|
- dev_err(dev, "usb_bulk_msg returned %d\n", rv);
|
|
|
- goto exit;
|
|
|
- }
|
|
|
- } while ((actual == max_size) &&
|
|
|
- (n < USBTMC_MAX_READS_TO_CLEAR_BULK_IN));
|
|
|
-
|
|
|
- if (actual == max_size) {
|
|
|
- dev_err(dev, "Couldn't clear device buffer within %d cycles\n",
|
|
|
- USBTMC_MAX_READS_TO_CLEAR_BULK_IN);
|
|
|
- rv = -EPERM;
|
|
|
- goto exit;
|
|
|
+ if ((buffer[1] & 1) > 0) {
|
|
|
+ /* The device has 1 or more queued packets the Host can read */
|
|
|
+ goto usbtmc_abort_bulk_in_status;
|
|
|
}
|
|
|
|
|
|
- goto usbtmc_abort_bulk_in_status;
|
|
|
-
|
|
|
+ /* The Host must send CHECK_ABORT_BULK_IN_STATUS at a later time. */
|
|
|
+ rv = -EAGAIN;
|
|
|
exit:
|
|
|
kfree(buffer);
|
|
|
return rv;
|
|
|
+}
|
|
|
|
|
|
+static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data)
|
|
|
+{
|
|
|
+ return usbtmc_ioctl_abort_bulk_in_tag(data, data->bTag_last_read);
|
|
|
}
|
|
|
|
|
|
static int usbtmc_ioctl_abort_bulk_out(struct usbtmc_device_data *data)
|