blob: 529295a17579ed25a15b76512499aa0e2735a014 [file] [log] [blame]
Greg Kroah-Hartman5fd54ac2017-11-03 11:28:30 +01001// SPDX-License-Identifier: GPL-2.0+
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07002/**
André Goddard Rosaaf901ca2009-11-14 13:09:05 -02003 * drivers/usb/class/usbtmc.c - USB Test & Measurement class driver
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07004 *
5 * Copyright (C) 2007 Stefan Kopp, Gechingen, Germany
6 * Copyright (C) 2008 Novell, Inc.
7 * Copyright (C) 2008 Greg Kroah-Hartman <gregkh@suse.de>
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07008 */
9
Andy Shevchenkof4d844c2013-07-15 11:59:42 +030010#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -070012#include <linux/module.h>
Ilpo Järvinen857cc4d2008-10-30 13:56:47 +020013#include <linux/kernel.h>
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -070014#include <linux/fs.h>
15#include <linux/uaccess.h>
16#include <linux/kref.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090017#include <linux/slab.h>
Dave Penklereb6b92e2016-01-27 19:19:14 +010018#include <linux/poll.h>
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -070019#include <linux/mutex.h>
20#include <linux/usb.h>
21#include <linux/usb/tmc.h>
22
23
Alexandre Peixoto Ferreira8402db52013-04-30 00:51:50 -050024#define USBTMC_HEADER_SIZE 12
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -070025#define USBTMC_MINOR_BASE 176
26
27/*
28 * Size of driver internal IO buffer. Must be multiple of 4 and at least as
29 * large as wMaxPacketSize (which is usually 512 bytes).
30 */
31#define USBTMC_SIZE_IOBUFFER 2048
32
33/* Default USB timeout (in milliseconds) */
Gergely Imreh35f76e892009-09-15 16:03:31 +080034#define USBTMC_TIMEOUT 5000
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -070035
36/*
37 * Maximum number of read cycles to empty bulk in endpoint during CLEAR and
38 * ABORT_BULK_IN requests. Ends the loop if (for whatever reason) a short
39 * packet is never read.
40 */
41#define USBTMC_MAX_READS_TO_CLEAR_BULK_IN 100
42
Németh Márton6ef48522010-01-10 15:33:45 +010043static const struct usb_device_id usbtmc_devices[] = {
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -070044 { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 0), },
Greg Kroah-Hartman228dd052009-03-11 13:51:42 -070045 { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 1), },
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -070046 { 0, } /* terminating entry */
47};
Greg Kroah-Hartman5413aa42008-12-03 16:33:09 -080048MODULE_DEVICE_TABLE(usb, usbtmc_devices);
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -070049
50/*
51 * This structure is the capabilities for the device
Gergely Imrehd0a38362009-09-07 10:47:01 +080052 * See section 4.2.1.8 of the USBTMC specification,
53 * and section 4.2.2 of the USBTMC usb488 subclass
54 * specification for details.
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -070055 */
56struct usbtmc_dev_capabilities {
57 __u8 interface_capabilities;
58 __u8 device_capabilities;
59 __u8 usb488_interface_capabilities;
60 __u8 usb488_device_capabilities;
61};
62
63/* This structure holds private data for each USBTMC device. One copy is
64 * allocated for each USBTMC device in the driver's probe function.
65 */
66struct usbtmc_device_data {
67 const struct usb_device_id *id;
68 struct usb_device *usb_dev;
69 struct usb_interface *intf;
70
71 unsigned int bulk_in;
72 unsigned int bulk_out;
73
74 u8 bTag;
75 u8 bTag_last_write; /* needed for abort */
76 u8 bTag_last_read; /* needed for abort */
77
Dave Penklerdbf3e7f2016-01-27 19:09:24 +010078 /* data for interrupt in endpoint handling */
79 u8 bNotify1;
80 u8 bNotify2;
81 u16 ifnum;
82 u8 iin_bTag;
83 u8 *iin_buffer;
84 atomic_t iin_data_valid;
85 unsigned int iin_ep;
86 int iin_ep_present;
87 int iin_interval;
88 struct urb *iin_urb;
89 u16 iin_wMaxPacketSize;
Dave Penkler82ed3382016-01-27 19:15:15 +010090 atomic_t srq_asserted;
Dave Penklerdbf3e7f2016-01-27 19:09:24 +010091
Dave Penkler29779d892016-01-27 19:22:28 +010092 /* coalesced usb488_caps from usbtmc_dev_capabilities */
93 __u8 usb488_caps;
94
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -070095 /* attributes from the USB TMC spec for this device */
96 u8 TermChar;
97 bool TermCharEnabled;
98 bool auto_abort;
99
Oliver Neukum86286882009-07-02 11:36:30 +0200100 bool zombie; /* fd of disconnected device */
101
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700102 struct usbtmc_dev_capabilities capabilities;
103 struct kref kref;
104 struct mutex io_mutex; /* only one i/o function running at a time */
Dave Penklerdbf3e7f2016-01-27 19:09:24 +0100105 wait_queue_head_t waitq;
Dave Penkler82ed3382016-01-27 19:15:15 +0100106 struct fasync_struct *fasync;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700107};
108#define to_usbtmc_data(d) container_of(d, struct usbtmc_device_data, kref)
109
110/* Forward declarations */
111static struct usb_driver usbtmc_driver;
112
113static void usbtmc_delete(struct kref *kref)
114{
115 struct usbtmc_device_data *data = to_usbtmc_data(kref);
116
117 usb_put_dev(data->usb_dev);
Greg Kroah-Hartmanab21b632016-09-28 11:48:44 +0200118 kfree(data);
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700119}
120
121static int usbtmc_open(struct inode *inode, struct file *filp)
122{
123 struct usb_interface *intf;
124 struct usbtmc_device_data *data;
Greg Kroah-Hartman5b109162009-03-10 20:42:55 -0700125 int retval = 0;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700126
127 intf = usb_find_interface(&usbtmc_driver, iminor(inode));
128 if (!intf) {
Andy Shevchenkof4d844c2013-07-15 11:59:42 +0300129 pr_err("can not find device for minor %d", iminor(inode));
130 return -ENODEV;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700131 }
132
133 data = usb_get_intfdata(intf);
Dave Penkler88aecde2016-09-28 20:06:01 +0200134 /* Protect reference to data from file structure until release */
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700135 kref_get(&data->kref);
136
137 /* Store pointer in file structure's private data field */
138 filp->private_data = data;
139
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700140 return retval;
141}
142
143static int usbtmc_release(struct inode *inode, struct file *file)
144{
145 struct usbtmc_device_data *data = file->private_data;
146
147 kref_put(&data->kref, usbtmc_delete);
148 return 0;
149}
150
151static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data)
152{
Chris Malleyb361a6e2008-10-25 22:07:32 +0100153 u8 *buffer;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700154 struct device *dev;
155 int rv;
156 int n;
157 int actual;
158 struct usb_host_interface *current_setting;
159 int max_size;
160
161 dev = &data->intf->dev;
162 buffer = kmalloc(USBTMC_SIZE_IOBUFFER, GFP_KERNEL);
163 if (!buffer)
164 return -ENOMEM;
165
166 rv = usb_control_msg(data->usb_dev,
167 usb_rcvctrlpipe(data->usb_dev, 0),
168 USBTMC_REQUEST_INITIATE_ABORT_BULK_IN,
169 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT,
170 data->bTag_last_read, data->bulk_in,
171 buffer, 2, USBTMC_TIMEOUT);
172
173 if (rv < 0) {
174 dev_err(dev, "usb_control_msg returned %d\n", rv);
175 goto exit;
176 }
177
178 dev_dbg(dev, "INITIATE_ABORT_BULK_IN returned %x\n", buffer[0]);
179
180 if (buffer[0] == USBTMC_STATUS_FAILED) {
181 rv = 0;
182 goto exit;
183 }
184
185 if (buffer[0] != USBTMC_STATUS_SUCCESS) {
186 dev_err(dev, "INITIATE_ABORT_BULK_IN returned %x\n",
187 buffer[0]);
188 rv = -EPERM;
189 goto exit;
190 }
191
192 max_size = 0;
193 current_setting = data->intf->cur_altsetting;
194 for (n = 0; n < current_setting->desc.bNumEndpoints; n++)
195 if (current_setting->endpoint[n].desc.bEndpointAddress ==
196 data->bulk_in)
Kuninori Morimoto29cc8892011-08-23 03:12:03 -0700197 max_size = usb_endpoint_maxp(&current_setting->endpoint[n].desc);
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700198
199 if (max_size == 0) {
200 dev_err(dev, "Couldn't get wMaxPacketSize\n");
201 rv = -EPERM;
202 goto exit;
203 }
204
205 dev_dbg(&data->intf->dev, "wMaxPacketSize is %d\n", max_size);
206
207 n = 0;
208
209 do {
210 dev_dbg(dev, "Reading from bulk in EP\n");
211
212 rv = usb_bulk_msg(data->usb_dev,
213 usb_rcvbulkpipe(data->usb_dev,
214 data->bulk_in),
215 buffer, USBTMC_SIZE_IOBUFFER,
216 &actual, USBTMC_TIMEOUT);
217
218 n++;
219
220 if (rv < 0) {
221 dev_err(dev, "usb_bulk_msg returned %d\n", rv);
222 goto exit;
223 }
224 } while ((actual == max_size) &&
225 (n < USBTMC_MAX_READS_TO_CLEAR_BULK_IN));
226
227 if (actual == max_size) {
228 dev_err(dev, "Couldn't clear device buffer within %d cycles\n",
229 USBTMC_MAX_READS_TO_CLEAR_BULK_IN);
230 rv = -EPERM;
231 goto exit;
232 }
233
234 n = 0;
235
236usbtmc_abort_bulk_in_status:
237 rv = usb_control_msg(data->usb_dev,
238 usb_rcvctrlpipe(data->usb_dev, 0),
239 USBTMC_REQUEST_CHECK_ABORT_BULK_IN_STATUS,
240 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT,
241 0, data->bulk_in, buffer, 0x08,
242 USBTMC_TIMEOUT);
243
244 if (rv < 0) {
245 dev_err(dev, "usb_control_msg returned %d\n", rv);
246 goto exit;
247 }
248
249 dev_dbg(dev, "INITIATE_ABORT_BULK_IN returned %x\n", buffer[0]);
250
251 if (buffer[0] == USBTMC_STATUS_SUCCESS) {
252 rv = 0;
253 goto exit;
254 }
255
256 if (buffer[0] != USBTMC_STATUS_PENDING) {
257 dev_err(dev, "INITIATE_ABORT_BULK_IN returned %x\n", buffer[0]);
258 rv = -EPERM;
259 goto exit;
260 }
261
262 if (buffer[1] == 1)
263 do {
264 dev_dbg(dev, "Reading from bulk in EP\n");
265
266 rv = usb_bulk_msg(data->usb_dev,
267 usb_rcvbulkpipe(data->usb_dev,
268 data->bulk_in),
269 buffer, USBTMC_SIZE_IOBUFFER,
270 &actual, USBTMC_TIMEOUT);
271
272 n++;
273
274 if (rv < 0) {
275 dev_err(dev, "usb_bulk_msg returned %d\n", rv);
276 goto exit;
277 }
Maxim Nikulin4f1a7a32011-07-09 23:44:44 +0700278 } while ((actual == max_size) &&
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700279 (n < USBTMC_MAX_READS_TO_CLEAR_BULK_IN));
280
281 if (actual == max_size) {
282 dev_err(dev, "Couldn't clear device buffer within %d cycles\n",
283 USBTMC_MAX_READS_TO_CLEAR_BULK_IN);
284 rv = -EPERM;
285 goto exit;
286 }
287
288 goto usbtmc_abort_bulk_in_status;
289
290exit:
291 kfree(buffer);
292 return rv;
293
294}
295
296static int usbtmc_ioctl_abort_bulk_out(struct usbtmc_device_data *data)
297{
298 struct device *dev;
299 u8 *buffer;
300 int rv;
301 int n;
302
303 dev = &data->intf->dev;
304
305 buffer = kmalloc(8, GFP_KERNEL);
306 if (!buffer)
307 return -ENOMEM;
308
309 rv = usb_control_msg(data->usb_dev,
310 usb_rcvctrlpipe(data->usb_dev, 0),
311 USBTMC_REQUEST_INITIATE_ABORT_BULK_OUT,
312 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT,
313 data->bTag_last_write, data->bulk_out,
314 buffer, 2, USBTMC_TIMEOUT);
315
316 if (rv < 0) {
317 dev_err(dev, "usb_control_msg returned %d\n", rv);
318 goto exit;
319 }
320
321 dev_dbg(dev, "INITIATE_ABORT_BULK_OUT returned %x\n", buffer[0]);
322
323 if (buffer[0] != USBTMC_STATUS_SUCCESS) {
324 dev_err(dev, "INITIATE_ABORT_BULK_OUT returned %x\n",
325 buffer[0]);
326 rv = -EPERM;
327 goto exit;
328 }
329
330 n = 0;
331
332usbtmc_abort_bulk_out_check_status:
333 rv = usb_control_msg(data->usb_dev,
334 usb_rcvctrlpipe(data->usb_dev, 0),
335 USBTMC_REQUEST_CHECK_ABORT_BULK_OUT_STATUS,
336 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT,
337 0, data->bulk_out, buffer, 0x08,
338 USBTMC_TIMEOUT);
339 n++;
340 if (rv < 0) {
341 dev_err(dev, "usb_control_msg returned %d\n", rv);
342 goto exit;
343 }
344
345 dev_dbg(dev, "CHECK_ABORT_BULK_OUT returned %x\n", buffer[0]);
346
347 if (buffer[0] == USBTMC_STATUS_SUCCESS)
348 goto usbtmc_abort_bulk_out_clear_halt;
349
350 if ((buffer[0] == USBTMC_STATUS_PENDING) &&
351 (n < USBTMC_MAX_READS_TO_CLEAR_BULK_IN))
352 goto usbtmc_abort_bulk_out_check_status;
353
354 rv = -EPERM;
355 goto exit;
356
357usbtmc_abort_bulk_out_clear_halt:
Sarah Sharp3342ecd2009-12-03 11:35:59 -0800358 rv = usb_clear_halt(data->usb_dev,
359 usb_sndbulkpipe(data->usb_dev, data->bulk_out));
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700360
361 if (rv < 0) {
362 dev_err(dev, "usb_control_msg returned %d\n", rv);
363 goto exit;
364 }
365 rv = 0;
366
367exit:
368 kfree(buffer);
369 return rv;
370}
371
Dave Penklerdbf3e7f2016-01-27 19:09:24 +0100372static int usbtmc488_ioctl_read_stb(struct usbtmc_device_data *data,
373 void __user *arg)
374{
375 struct device *dev = &data->intf->dev;
376 u8 *buffer;
377 u8 tag;
378 __u8 stb;
379 int rv;
380
381 dev_dbg(dev, "Enter ioctl_read_stb iin_ep_present: %d\n",
382 data->iin_ep_present);
383
384 buffer = kmalloc(8, GFP_KERNEL);
385 if (!buffer)
386 return -ENOMEM;
387
388 atomic_set(&data->iin_data_valid, 0);
389
Dave Penkler82ed3382016-01-27 19:15:15 +0100390 /* must issue read_stb before using poll or select */
391 atomic_set(&data->srq_asserted, 0);
392
Dave Penklerdbf3e7f2016-01-27 19:09:24 +0100393 rv = usb_control_msg(data->usb_dev,
394 usb_rcvctrlpipe(data->usb_dev, 0),
395 USBTMC488_REQUEST_READ_STATUS_BYTE,
396 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
397 data->iin_bTag,
398 data->ifnum,
399 buffer, 0x03, USBTMC_TIMEOUT);
400 if (rv < 0) {
401 dev_err(dev, "stb usb_control_msg returned %d\n", rv);
402 goto exit;
403 }
404
405 if (buffer[0] != USBTMC_STATUS_SUCCESS) {
406 dev_err(dev, "control status returned %x\n", buffer[0]);
407 rv = -EIO;
408 goto exit;
409 }
410
411 if (data->iin_ep_present) {
412 rv = wait_event_interruptible_timeout(
413 data->waitq,
414 atomic_read(&data->iin_data_valid) != 0,
415 USBTMC_TIMEOUT);
416 if (rv < 0) {
417 dev_dbg(dev, "wait interrupted %d\n", rv);
418 goto exit;
419 }
420
421 if (rv == 0) {
422 dev_dbg(dev, "wait timed out\n");
423 rv = -ETIME;
424 goto exit;
425 }
426
427 tag = data->bNotify1 & 0x7f;
428 if (tag != data->iin_bTag) {
429 dev_err(dev, "expected bTag %x got %x\n",
430 data->iin_bTag, tag);
431 }
432
433 stb = data->bNotify2;
434 } else {
435 stb = buffer[2];
436 }
437
438 rv = copy_to_user(arg, &stb, sizeof(stb));
439 if (rv)
440 rv = -EFAULT;
441
442 exit:
443 /* bump interrupt bTag */
444 data->iin_bTag += 1;
445 if (data->iin_bTag > 127)
446 /* 1 is for SRQ see USBTMC-USB488 subclass spec section 4.3.1 */
447 data->iin_bTag = 2;
448
449 kfree(buffer);
450 return rv;
451}
452
Dave Penkler379d3d32016-01-27 19:25:24 +0100453static int usbtmc488_ioctl_simple(struct usbtmc_device_data *data,
454 void __user *arg, unsigned int cmd)
455{
456 struct device *dev = &data->intf->dev;
457 __u8 val;
458 u8 *buffer;
459 u16 wValue;
460 int rv;
461
462 if (!(data->usb488_caps & USBTMC488_CAPABILITY_SIMPLE))
463 return -EINVAL;
464
465 buffer = kmalloc(8, GFP_KERNEL);
466 if (!buffer)
467 return -ENOMEM;
468
469 if (cmd == USBTMC488_REQUEST_REN_CONTROL) {
470 rv = copy_from_user(&val, arg, sizeof(val));
471 if (rv) {
472 rv = -EFAULT;
473 goto exit;
474 }
475 wValue = val ? 1 : 0;
476 } else {
477 wValue = 0;
478 }
479
480 rv = usb_control_msg(data->usb_dev,
481 usb_rcvctrlpipe(data->usb_dev, 0),
482 cmd,
483 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
484 wValue,
485 data->ifnum,
486 buffer, 0x01, USBTMC_TIMEOUT);
487 if (rv < 0) {
488 dev_err(dev, "simple usb_control_msg failed %d\n", rv);
489 goto exit;
490 } else if (rv != 1) {
491 dev_warn(dev, "simple usb_control_msg returned %d\n", rv);
492 rv = -EIO;
493 goto exit;
494 }
495
496 if (buffer[0] != USBTMC_STATUS_SUCCESS) {
497 dev_err(dev, "simple control status returned %x\n", buffer[0]);
498 rv = -EIO;
499 goto exit;
500 }
501 rv = 0;
502
503 exit:
504 kfree(buffer);
505 return rv;
506}
507
Alexandre Peixoto Ferreira88d9b2b2013-04-30 00:51:51 -0500508/*
Dave Penkler88aecde2016-09-28 20:06:01 +0200509 * Sends a REQUEST_DEV_DEP_MSG_IN message on the Bulk-OUT endpoint.
Alexandre Peixoto Ferreira88d9b2b2013-04-30 00:51:51 -0500510 * @transfer_size: number of bytes to request from the device.
511 *
512 * See the USBTMC specification, Table 4.
513 *
514 * Also updates bTag_last_write.
515 */
516static int send_request_dev_dep_msg_in(struct usbtmc_device_data *data, size_t transfer_size)
517{
518 int retval;
Oliver Neukumd846b762014-05-19 13:54:57 +0200519 u8 *buffer;
Alexandre Peixoto Ferreira88d9b2b2013-04-30 00:51:51 -0500520 int actual;
521
Oliver Neukumd846b762014-05-19 13:54:57 +0200522 buffer = kmalloc(USBTMC_HEADER_SIZE, GFP_KERNEL);
523 if (!buffer)
524 return -ENOMEM;
Alexandre Peixoto Ferreira88d9b2b2013-04-30 00:51:51 -0500525 /* Setup IO buffer for REQUEST_DEV_DEP_MSG_IN message
526 * Refer to class specs for details
527 */
528 buffer[0] = 2;
529 buffer[1] = data->bTag;
Andy Shevchenkobbf49762013-07-15 11:59:43 +0300530 buffer[2] = ~data->bTag;
Alexandre Peixoto Ferreira88d9b2b2013-04-30 00:51:51 -0500531 buffer[3] = 0; /* Reserved */
Andy Shevchenkobbf49762013-07-15 11:59:43 +0300532 buffer[4] = transfer_size >> 0;
533 buffer[5] = transfer_size >> 8;
534 buffer[6] = transfer_size >> 16;
535 buffer[7] = transfer_size >> 24;
Alexandre Peixoto Ferreira88d9b2b2013-04-30 00:51:51 -0500536 buffer[8] = data->TermCharEnabled * 2;
537 /* Use term character? */
538 buffer[9] = data->TermChar;
539 buffer[10] = 0; /* Reserved */
540 buffer[11] = 0; /* Reserved */
541
542 /* Send bulk URB */
543 retval = usb_bulk_msg(data->usb_dev,
544 usb_sndbulkpipe(data->usb_dev,
545 data->bulk_out),
546 buffer, USBTMC_HEADER_SIZE, &actual, USBTMC_TIMEOUT);
547
548 /* Store bTag (in case we need to abort) */
549 data->bTag_last_write = data->bTag;
550
551 /* Increment bTag -- and increment again if zero */
552 data->bTag++;
553 if (!data->bTag)
Andy Shevchenkobbf49762013-07-15 11:59:43 +0300554 data->bTag++;
Alexandre Peixoto Ferreira88d9b2b2013-04-30 00:51:51 -0500555
Oliver Neukumd846b762014-05-19 13:54:57 +0200556 kfree(buffer);
Alexandre Peixoto Ferreira88d9b2b2013-04-30 00:51:51 -0500557 if (retval < 0) {
558 dev_err(&data->intf->dev, "usb_bulk_msg in send_request_dev_dep_msg_in() returned %d\n", retval);
559 return retval;
560 }
561
562 return 0;
563}
564
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700565static ssize_t usbtmc_read(struct file *filp, char __user *buf,
566 size_t count, loff_t *f_pos)
567{
568 struct usbtmc_device_data *data;
569 struct device *dev;
Guus Sliepen665d7662009-07-22 17:39:42 +0200570 u32 n_characters;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700571 u8 *buffer;
572 int actual;
Guus Sliepen665d7662009-07-22 17:39:42 +0200573 size_t done;
574 size_t remaining;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700575 int retval;
Guus Sliepen665d7662009-07-22 17:39:42 +0200576 size_t this_part;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700577
578 /* Get pointer to private data structure */
579 data = filp->private_data;
580 dev = &data->intf->dev;
581
582 buffer = kmalloc(USBTMC_SIZE_IOBUFFER, GFP_KERNEL);
583 if (!buffer)
584 return -ENOMEM;
585
586 mutex_lock(&data->io_mutex);
Oliver Neukum86286882009-07-02 11:36:30 +0200587 if (data->zombie) {
588 retval = -ENODEV;
589 goto exit;
590 }
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700591
Guido Kienerbaf12d62018-05-17 19:03:25 +0200592 dev_dbg(dev, "usb_bulk_msg_in: count(%zu)\n", count);
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700593
Guido Kienerbaf12d62018-05-17 19:03:25 +0200594 retval = send_request_dev_dep_msg_in(data, count);
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700595
Guido Kienerbaf12d62018-05-17 19:03:25 +0200596 if (retval < 0) {
597 if (data->auto_abort)
598 usbtmc_ioctl_abort_bulk_out(data);
599 goto exit;
Alexandre Peixoto Ferreirad2ddce32013-04-30 00:51:53 -0500600 }
601
602 /* Loop until we have fetched everything we requested */
603 remaining = count;
604 this_part = remaining;
605 done = 0;
606
607 while (remaining > 0) {
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700608 /* Send bulk URB */
609 retval = usb_bulk_msg(data->usb_dev,
610 usb_rcvbulkpipe(data->usb_dev,
611 data->bulk_in),
612 buffer, USBTMC_SIZE_IOBUFFER, &actual,
613 USBTMC_TIMEOUT);
614
Alexandre Peixoto Ferreirad2ddce32013-04-30 00:51:53 -0500615 dev_dbg(dev, "usb_bulk_msg: retval(%u), done(%zu), remaining(%zu), actual(%d)\n", retval, done, remaining, actual);
616
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700617 /* Store bTag (in case we need to abort) */
618 data->bTag_last_read = data->bTag;
619
620 if (retval < 0) {
Alexandre Peixoto Ferreirad2ddce32013-04-30 00:51:53 -0500621 dev_dbg(dev, "Unable to read data, error %d\n", retval);
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700622 if (data->auto_abort)
623 usbtmc_ioctl_abort_bulk_in(data);
624 goto exit;
625 }
626
Alexandre Peixoto Ferreirad2ddce32013-04-30 00:51:53 -0500627 /* Parse header in first packet */
Guido Kienerbaf12d62018-05-17 19:03:25 +0200628 if (done == 0) {
Alexandre Peixoto Ferreirad2ddce32013-04-30 00:51:53 -0500629 /* Sanity checks for the header */
630 if (actual < USBTMC_HEADER_SIZE) {
631 dev_err(dev, "Device sent too small first packet: %u < %u\n", actual, USBTMC_HEADER_SIZE);
632 if (data->auto_abort)
633 usbtmc_ioctl_abort_bulk_in(data);
634 goto exit;
635 }
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700636
Alexandre Peixoto Ferreirad2ddce32013-04-30 00:51:53 -0500637 if (buffer[0] != 2) {
638 dev_err(dev, "Device sent reply with wrong MsgID: %u != 2\n", buffer[0]);
639 if (data->auto_abort)
640 usbtmc_ioctl_abort_bulk_in(data);
641 goto exit;
642 }
643
644 if (buffer[1] != data->bTag_last_write) {
645 dev_err(dev, "Device sent reply with wrong bTag: %u != %u\n", buffer[1], data->bTag_last_write);
646 if (data->auto_abort)
647 usbtmc_ioctl_abort_bulk_in(data);
648 goto exit;
649 }
650
651 /* How many characters did the instrument send? */
652 n_characters = buffer[4] +
653 (buffer[5] << 8) +
654 (buffer[6] << 16) +
655 (buffer[7] << 24);
656
657 if (n_characters > this_part) {
658 dev_err(dev, "Device wants to return more data than requested: %u > %zu\n", n_characters, count);
659 if (data->auto_abort)
660 usbtmc_ioctl_abort_bulk_in(data);
661 goto exit;
662 }
663
664 /* Remove the USBTMC header */
665 actual -= USBTMC_HEADER_SIZE;
666
667 /* Check if the message is smaller than requested */
Guido Kienerbaf12d62018-05-17 19:03:25 +0200668 if (remaining > n_characters)
669 remaining = n_characters;
670 /* Remove padding if it exists */
671 if (actual > remaining)
672 actual = remaining;
Alexandre Peixoto Ferreirad2ddce32013-04-30 00:51:53 -0500673
674 dev_dbg(dev, "Bulk-IN header: N_characters(%u), bTransAttr(%u)\n", n_characters, buffer[8]);
675
676 remaining -= actual;
677
678 /* Terminate if end-of-message bit received from device */
Andy Shevchenkobbf49762013-07-15 11:59:43 +0300679 if ((buffer[8] & 0x01) && (actual >= n_characters))
Alexandre Peixoto Ferreirad2ddce32013-04-30 00:51:53 -0500680 remaining = 0;
681
682 dev_dbg(dev, "Bulk-IN header: remaining(%zu), buf(%p), buffer(%p) done(%zu)\n", remaining,buf,buffer,done);
683
684
685 /* Copy buffer to user space */
686 if (copy_to_user(buf + done, &buffer[USBTMC_HEADER_SIZE], actual)) {
687 /* There must have been an addressing problem */
688 retval = -EFAULT;
689 goto exit;
690 }
691 done += actual;
Guus Sliepen665d7662009-07-22 17:39:42 +0200692 }
Alexandre Peixoto Ferreirad2ddce32013-04-30 00:51:53 -0500693 else {
Andy Shevchenko92f78dd2013-07-15 11:59:40 +0300694 if (actual > remaining)
Alexandre Peixoto Ferreirad2ddce32013-04-30 00:51:53 -0500695 actual = remaining;
Guus Sliepen665d7662009-07-22 17:39:42 +0200696
Alexandre Peixoto Ferreirad2ddce32013-04-30 00:51:53 -0500697 remaining -= actual;
698
699 dev_dbg(dev, "Bulk-IN header cont: actual(%u), done(%zu), remaining(%zu), buf(%p), buffer(%p)\n", actual, done, remaining,buf,buffer);
700
701 /* Copy buffer to user space */
702 if (copy_to_user(buf + done, buffer, actual)) {
703 /* There must have been an addressing problem */
704 retval = -EFAULT;
705 goto exit;
706 }
707 done += actual;
Guus Sliepen665d7662009-07-22 17:39:42 +0200708 }
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700709 }
710
711 /* Update file position value */
712 *f_pos = *f_pos + done;
713 retval = done;
714
715exit:
716 mutex_unlock(&data->io_mutex);
717 kfree(buffer);
718 return retval;
719}
720
721static ssize_t usbtmc_write(struct file *filp, const char __user *buf,
722 size_t count, loff_t *f_pos)
723{
724 struct usbtmc_device_data *data;
725 u8 *buffer;
726 int retval;
727 int actual;
728 unsigned long int n_bytes;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700729 int remaining;
730 int done;
731 int this_part;
732
733 data = filp->private_data;
734
735 buffer = kmalloc(USBTMC_SIZE_IOBUFFER, GFP_KERNEL);
736 if (!buffer)
737 return -ENOMEM;
738
739 mutex_lock(&data->io_mutex);
Oliver Neukum86286882009-07-02 11:36:30 +0200740 if (data->zombie) {
741 retval = -ENODEV;
742 goto exit;
743 }
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700744
745 remaining = count;
746 done = 0;
747
748 while (remaining > 0) {
Alexandre Peixoto Ferreira50c9ba32013-04-30 00:51:54 -0500749 if (remaining > USBTMC_SIZE_IOBUFFER - USBTMC_HEADER_SIZE) {
750 this_part = USBTMC_SIZE_IOBUFFER - USBTMC_HEADER_SIZE;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700751 buffer[8] = 0;
752 } else {
753 this_part = remaining;
754 buffer[8] = 1;
755 }
756
757 /* Setup IO buffer for DEV_DEP_MSG_OUT message */
758 buffer[0] = 1;
759 buffer[1] = data->bTag;
Andy Shevchenkobbf49762013-07-15 11:59:43 +0300760 buffer[2] = ~data->bTag;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700761 buffer[3] = 0; /* Reserved */
Andy Shevchenkobbf49762013-07-15 11:59:43 +0300762 buffer[4] = this_part >> 0;
763 buffer[5] = this_part >> 8;
764 buffer[6] = this_part >> 16;
765 buffer[7] = this_part >> 24;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700766 /* buffer[8] is set above... */
767 buffer[9] = 0; /* Reserved */
768 buffer[10] = 0; /* Reserved */
769 buffer[11] = 0; /* Reserved */
770
Alexandre Peixoto Ferreira50c9ba32013-04-30 00:51:54 -0500771 if (copy_from_user(&buffer[USBTMC_HEADER_SIZE], buf + done, this_part)) {
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700772 retval = -EFAULT;
773 goto exit;
774 }
775
Alexandre Peixoto Ferreira50c9ba32013-04-30 00:51:54 -0500776 n_bytes = roundup(USBTMC_HEADER_SIZE + this_part, 4);
777 memset(buffer + USBTMC_HEADER_SIZE + this_part, 0, n_bytes - (USBTMC_HEADER_SIZE + this_part));
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700778
Andre Hermsec412b92009-11-19 18:14:49 +0100779 do {
780 retval = usb_bulk_msg(data->usb_dev,
781 usb_sndbulkpipe(data->usb_dev,
782 data->bulk_out),
783 buffer, n_bytes,
784 &actual, USBTMC_TIMEOUT);
785 if (retval != 0)
786 break;
787 n_bytes -= actual;
788 } while (n_bytes);
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700789
790 data->bTag_last_write = data->bTag;
791 data->bTag++;
792
793 if (!data->bTag)
794 data->bTag++;
795
796 if (retval < 0) {
797 dev_err(&data->intf->dev,
798 "Unable to send data, error %d\n", retval);
799 if (data->auto_abort)
800 usbtmc_ioctl_abort_bulk_out(data);
801 goto exit;
802 }
803
804 remaining -= this_part;
805 done += this_part;
806 }
807
808 retval = count;
809exit:
810 mutex_unlock(&data->io_mutex);
811 kfree(buffer);
812 return retval;
813}
814
815static int usbtmc_ioctl_clear(struct usbtmc_device_data *data)
816{
817 struct usb_host_interface *current_setting;
818 struct usb_endpoint_descriptor *desc;
819 struct device *dev;
820 u8 *buffer;
821 int rv;
822 int n;
Rickard Strandqvistab53eb92014-06-01 15:43:19 +0200823 int actual = 0;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700824 int max_size;
825
826 dev = &data->intf->dev;
827
828 dev_dbg(dev, "Sending INITIATE_CLEAR request\n");
829
830 buffer = kmalloc(USBTMC_SIZE_IOBUFFER, GFP_KERNEL);
831 if (!buffer)
832 return -ENOMEM;
833
834 rv = usb_control_msg(data->usb_dev,
835 usb_rcvctrlpipe(data->usb_dev, 0),
836 USBTMC_REQUEST_INITIATE_CLEAR,
837 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
838 0, 0, buffer, 1, USBTMC_TIMEOUT);
839 if (rv < 0) {
840 dev_err(dev, "usb_control_msg returned %d\n", rv);
841 goto exit;
842 }
843
844 dev_dbg(dev, "INITIATE_CLEAR returned %x\n", buffer[0]);
845
846 if (buffer[0] != USBTMC_STATUS_SUCCESS) {
847 dev_err(dev, "INITIATE_CLEAR returned %x\n", buffer[0]);
848 rv = -EPERM;
849 goto exit;
850 }
851
852 max_size = 0;
853 current_setting = data->intf->cur_altsetting;
854 for (n = 0; n < current_setting->desc.bNumEndpoints; n++) {
855 desc = &current_setting->endpoint[n].desc;
856 if (desc->bEndpointAddress == data->bulk_in)
Kuninori Morimoto29cc8892011-08-23 03:12:03 -0700857 max_size = usb_endpoint_maxp(desc);
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700858 }
859
860 if (max_size == 0) {
861 dev_err(dev, "Couldn't get wMaxPacketSize\n");
862 rv = -EPERM;
863 goto exit;
864 }
865
866 dev_dbg(dev, "wMaxPacketSize is %d\n", max_size);
867
868 n = 0;
869
870usbtmc_clear_check_status:
871
872 dev_dbg(dev, "Sending CHECK_CLEAR_STATUS request\n");
873
874 rv = usb_control_msg(data->usb_dev,
875 usb_rcvctrlpipe(data->usb_dev, 0),
876 USBTMC_REQUEST_CHECK_CLEAR_STATUS,
877 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
878 0, 0, buffer, 2, USBTMC_TIMEOUT);
879 if (rv < 0) {
880 dev_err(dev, "usb_control_msg returned %d\n", rv);
881 goto exit;
882 }
883
884 dev_dbg(dev, "CHECK_CLEAR_STATUS returned %x\n", buffer[0]);
885
886 if (buffer[0] == USBTMC_STATUS_SUCCESS)
887 goto usbtmc_clear_bulk_out_halt;
888
889 if (buffer[0] != USBTMC_STATUS_PENDING) {
890 dev_err(dev, "CHECK_CLEAR_STATUS returned %x\n", buffer[0]);
891 rv = -EPERM;
892 goto exit;
893 }
894
895 if (buffer[1] == 1)
896 do {
897 dev_dbg(dev, "Reading from bulk in EP\n");
898
899 rv = usb_bulk_msg(data->usb_dev,
900 usb_rcvbulkpipe(data->usb_dev,
901 data->bulk_in),
902 buffer, USBTMC_SIZE_IOBUFFER,
903 &actual, USBTMC_TIMEOUT);
904 n++;
905
906 if (rv < 0) {
907 dev_err(dev, "usb_control_msg returned %d\n",
908 rv);
909 goto exit;
910 }
911 } while ((actual == max_size) &&
912 (n < USBTMC_MAX_READS_TO_CLEAR_BULK_IN));
913
914 if (actual == max_size) {
915 dev_err(dev, "Couldn't clear device buffer within %d cycles\n",
916 USBTMC_MAX_READS_TO_CLEAR_BULK_IN);
917 rv = -EPERM;
918 goto exit;
919 }
920
921 goto usbtmc_clear_check_status;
922
923usbtmc_clear_bulk_out_halt:
924
Sarah Sharp3342ecd2009-12-03 11:35:59 -0800925 rv = usb_clear_halt(data->usb_dev,
926 usb_sndbulkpipe(data->usb_dev, data->bulk_out));
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700927 if (rv < 0) {
928 dev_err(dev, "usb_control_msg returned %d\n", rv);
929 goto exit;
930 }
931 rv = 0;
932
933exit:
934 kfree(buffer);
935 return rv;
936}
937
938static int usbtmc_ioctl_clear_out_halt(struct usbtmc_device_data *data)
939{
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700940 int rv;
941
Sarah Sharp3342ecd2009-12-03 11:35:59 -0800942 rv = usb_clear_halt(data->usb_dev,
943 usb_sndbulkpipe(data->usb_dev, data->bulk_out));
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700944
945 if (rv < 0) {
946 dev_err(&data->usb_dev->dev, "usb_control_msg returned %d\n",
947 rv);
Ming Leiac9e59c2013-04-18 12:17:38 +0800948 return rv;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700949 }
Ming Leiac9e59c2013-04-18 12:17:38 +0800950 return 0;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700951}
952
953static int usbtmc_ioctl_clear_in_halt(struct usbtmc_device_data *data)
954{
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700955 int rv;
956
Sarah Sharp3342ecd2009-12-03 11:35:59 -0800957 rv = usb_clear_halt(data->usb_dev,
958 usb_rcvbulkpipe(data->usb_dev, data->bulk_in));
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700959
960 if (rv < 0) {
961 dev_err(&data->usb_dev->dev, "usb_control_msg returned %d\n",
962 rv);
Ming Leiac9e59c2013-04-18 12:17:38 +0800963 return rv;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700964 }
Ming Leiac9e59c2013-04-18 12:17:38 +0800965 return 0;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700966}
967
968static int get_capabilities(struct usbtmc_device_data *data)
969{
970 struct device *dev = &data->usb_dev->dev;
971 char *buffer;
Oliver Neukumca157c42009-07-02 16:41:39 +0200972 int rv = 0;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700973
974 buffer = kmalloc(0x18, GFP_KERNEL);
975 if (!buffer)
976 return -ENOMEM;
977
978 rv = usb_control_msg(data->usb_dev, usb_rcvctrlpipe(data->usb_dev, 0),
979 USBTMC_REQUEST_GET_CAPABILITIES,
980 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
981 0, 0, buffer, 0x18, USBTMC_TIMEOUT);
982 if (rv < 0) {
983 dev_err(dev, "usb_control_msg returned %d\n", rv);
Oliver Neukumca157c42009-07-02 16:41:39 +0200984 goto err_out;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700985 }
986
987 dev_dbg(dev, "GET_CAPABILITIES returned %x\n", buffer[0]);
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700988 if (buffer[0] != USBTMC_STATUS_SUCCESS) {
989 dev_err(dev, "GET_CAPABILITIES returned %x\n", buffer[0]);
Oliver Neukumca157c42009-07-02 16:41:39 +0200990 rv = -EPERM;
991 goto err_out;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700992 }
Gergely Imrehd0a38362009-09-07 10:47:01 +0800993 dev_dbg(dev, "Interface capabilities are %x\n", buffer[4]);
994 dev_dbg(dev, "Device capabilities are %x\n", buffer[5]);
995 dev_dbg(dev, "USB488 interface capabilities are %x\n", buffer[14]);
996 dev_dbg(dev, "USB488 device capabilities are %x\n", buffer[15]);
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -0700997
998 data->capabilities.interface_capabilities = buffer[4];
999 data->capabilities.device_capabilities = buffer[5];
1000 data->capabilities.usb488_interface_capabilities = buffer[14];
1001 data->capabilities.usb488_device_capabilities = buffer[15];
Dave Penkler29779d892016-01-27 19:22:28 +01001002 data->usb488_caps = (buffer[14] & 0x07) | ((buffer[15] & 0x0f) << 4);
Gergely Imrehd0a38362009-09-07 10:47:01 +08001003 rv = 0;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001004
Oliver Neukumca157c42009-07-02 16:41:39 +02001005err_out:
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001006 kfree(buffer);
Oliver Neukumca157c42009-07-02 16:41:39 +02001007 return rv;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001008}
1009
1010#define capability_attribute(name) \
Greg Kroah-Hartman2a6eb8a2013-08-23 16:09:33 -07001011static ssize_t name##_show(struct device *dev, \
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001012 struct device_attribute *attr, char *buf) \
1013{ \
1014 struct usb_interface *intf = to_usb_interface(dev); \
1015 struct usbtmc_device_data *data = usb_get_intfdata(intf); \
1016 \
1017 return sprintf(buf, "%d\n", data->capabilities.name); \
1018} \
Greg Kroah-Hartman2a6eb8a2013-08-23 16:09:33 -07001019static DEVICE_ATTR_RO(name)
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001020
1021capability_attribute(interface_capabilities);
1022capability_attribute(device_capabilities);
1023capability_attribute(usb488_interface_capabilities);
1024capability_attribute(usb488_device_capabilities);
1025
1026static struct attribute *capability_attrs[] = {
1027 &dev_attr_interface_capabilities.attr,
1028 &dev_attr_device_capabilities.attr,
1029 &dev_attr_usb488_interface_capabilities.attr,
1030 &dev_attr_usb488_device_capabilities.attr,
1031 NULL,
1032};
1033
Arvind Yadava70df962017-08-04 17:36:40 +05301034static const struct attribute_group capability_attr_grp = {
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001035 .attrs = capability_attrs,
1036};
1037
Greg Kroah-Hartman2a6eb8a2013-08-23 16:09:33 -07001038static ssize_t TermChar_show(struct device *dev,
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001039 struct device_attribute *attr, char *buf)
1040{
1041 struct usb_interface *intf = to_usb_interface(dev);
1042 struct usbtmc_device_data *data = usb_get_intfdata(intf);
1043
1044 return sprintf(buf, "%c\n", data->TermChar);
1045}
1046
Greg Kroah-Hartman2a6eb8a2013-08-23 16:09:33 -07001047static ssize_t TermChar_store(struct device *dev,
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001048 struct device_attribute *attr,
1049 const char *buf, size_t count)
1050{
1051 struct usb_interface *intf = to_usb_interface(dev);
1052 struct usbtmc_device_data *data = usb_get_intfdata(intf);
1053
1054 if (count < 1)
1055 return -EINVAL;
1056 data->TermChar = buf[0];
1057 return count;
1058}
Greg Kroah-Hartman2a6eb8a2013-08-23 16:09:33 -07001059static DEVICE_ATTR_RW(TermChar);
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001060
1061#define data_attribute(name) \
Greg Kroah-Hartman2a6eb8a2013-08-23 16:09:33 -07001062static ssize_t name##_show(struct device *dev, \
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001063 struct device_attribute *attr, char *buf) \
1064{ \
1065 struct usb_interface *intf = to_usb_interface(dev); \
1066 struct usbtmc_device_data *data = usb_get_intfdata(intf); \
1067 \
1068 return sprintf(buf, "%d\n", data->name); \
1069} \
Greg Kroah-Hartman2a6eb8a2013-08-23 16:09:33 -07001070static ssize_t name##_store(struct device *dev, \
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001071 struct device_attribute *attr, \
1072 const char *buf, size_t count) \
1073{ \
1074 struct usb_interface *intf = to_usb_interface(dev); \
1075 struct usbtmc_device_data *data = usb_get_intfdata(intf); \
1076 ssize_t result; \
1077 unsigned val; \
1078 \
1079 result = sscanf(buf, "%u\n", &val); \
1080 if (result != 1) \
1081 result = -EINVAL; \
1082 data->name = val; \
1083 if (result < 0) \
1084 return result; \
1085 else \
1086 return count; \
1087} \
Greg Kroah-Hartman2a6eb8a2013-08-23 16:09:33 -07001088static DEVICE_ATTR_RW(name)
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001089
1090data_attribute(TermCharEnabled);
1091data_attribute(auto_abort);
1092
1093static struct attribute *data_attrs[] = {
1094 &dev_attr_TermChar.attr,
1095 &dev_attr_TermCharEnabled.attr,
1096 &dev_attr_auto_abort.attr,
1097 NULL,
1098};
1099
Arvind Yadava70df962017-08-04 17:36:40 +05301100static const struct attribute_group data_attr_grp = {
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001101 .attrs = data_attrs,
1102};
1103
1104static int usbtmc_ioctl_indicator_pulse(struct usbtmc_device_data *data)
1105{
1106 struct device *dev;
1107 u8 *buffer;
1108 int rv;
1109
1110 dev = &data->intf->dev;
1111
1112 buffer = kmalloc(2, GFP_KERNEL);
1113 if (!buffer)
1114 return -ENOMEM;
1115
1116 rv = usb_control_msg(data->usb_dev,
1117 usb_rcvctrlpipe(data->usb_dev, 0),
1118 USBTMC_REQUEST_INDICATOR_PULSE,
1119 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
1120 0, 0, buffer, 0x01, USBTMC_TIMEOUT);
1121
1122 if (rv < 0) {
1123 dev_err(dev, "usb_control_msg returned %d\n", rv);
1124 goto exit;
1125 }
1126
1127 dev_dbg(dev, "INDICATOR_PULSE returned %x\n", buffer[0]);
1128
1129 if (buffer[0] != USBTMC_STATUS_SUCCESS) {
1130 dev_err(dev, "INDICATOR_PULSE returned %x\n", buffer[0]);
1131 rv = -EPERM;
1132 goto exit;
1133 }
1134 rv = 0;
1135
1136exit:
1137 kfree(buffer);
1138 return rv;
1139}
1140
1141static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1142{
1143 struct usbtmc_device_data *data;
1144 int retval = -EBADRQC;
1145
1146 data = file->private_data;
1147 mutex_lock(&data->io_mutex);
Oliver Neukum86286882009-07-02 11:36:30 +02001148 if (data->zombie) {
1149 retval = -ENODEV;
1150 goto skip_io_on_zombie;
1151 }
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001152
1153 switch (cmd) {
1154 case USBTMC_IOCTL_CLEAR_OUT_HALT:
1155 retval = usbtmc_ioctl_clear_out_halt(data);
Greg Kroah-Hartmana92b63e2009-06-15 13:13:05 -07001156 break;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001157
1158 case USBTMC_IOCTL_CLEAR_IN_HALT:
1159 retval = usbtmc_ioctl_clear_in_halt(data);
Greg Kroah-Hartmana92b63e2009-06-15 13:13:05 -07001160 break;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001161
1162 case USBTMC_IOCTL_INDICATOR_PULSE:
1163 retval = usbtmc_ioctl_indicator_pulse(data);
Greg Kroah-Hartmana92b63e2009-06-15 13:13:05 -07001164 break;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001165
1166 case USBTMC_IOCTL_CLEAR:
1167 retval = usbtmc_ioctl_clear(data);
Greg Kroah-Hartmana92b63e2009-06-15 13:13:05 -07001168 break;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001169
1170 case USBTMC_IOCTL_ABORT_BULK_OUT:
1171 retval = usbtmc_ioctl_abort_bulk_out(data);
Greg Kroah-Hartmana92b63e2009-06-15 13:13:05 -07001172 break;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001173
1174 case USBTMC_IOCTL_ABORT_BULK_IN:
1175 retval = usbtmc_ioctl_abort_bulk_in(data);
Greg Kroah-Hartmana92b63e2009-06-15 13:13:05 -07001176 break;
Dave Penklerdbf3e7f2016-01-27 19:09:24 +01001177
Dave Penkler29779d892016-01-27 19:22:28 +01001178 case USBTMC488_IOCTL_GET_CAPS:
1179 retval = copy_to_user((void __user *)arg,
1180 &data->usb488_caps,
1181 sizeof(data->usb488_caps));
1182 if (retval)
1183 retval = -EFAULT;
1184 break;
1185
Dave Penklerdbf3e7f2016-01-27 19:09:24 +01001186 case USBTMC488_IOCTL_READ_STB:
1187 retval = usbtmc488_ioctl_read_stb(data, (void __user *)arg);
1188 break;
Dave Penkler379d3d32016-01-27 19:25:24 +01001189
1190 case USBTMC488_IOCTL_REN_CONTROL:
1191 retval = usbtmc488_ioctl_simple(data, (void __user *)arg,
1192 USBTMC488_REQUEST_REN_CONTROL);
1193 break;
1194
1195 case USBTMC488_IOCTL_GOTO_LOCAL:
1196 retval = usbtmc488_ioctl_simple(data, (void __user *)arg,
1197 USBTMC488_REQUEST_GOTO_LOCAL);
1198 break;
1199
1200 case USBTMC488_IOCTL_LOCAL_LOCKOUT:
1201 retval = usbtmc488_ioctl_simple(data, (void __user *)arg,
1202 USBTMC488_REQUEST_LOCAL_LOCKOUT);
1203 break;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001204 }
1205
Oliver Neukum86286882009-07-02 11:36:30 +02001206skip_io_on_zombie:
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001207 mutex_unlock(&data->io_mutex);
1208 return retval;
1209}
1210
Dave Penkler82ed3382016-01-27 19:15:15 +01001211static int usbtmc_fasync(int fd, struct file *file, int on)
1212{
1213 struct usbtmc_device_data *data = file->private_data;
1214
1215 return fasync_helper(fd, file, on, &data->fasync);
1216}
1217
Al Viroafc9a422017-07-03 06:39:46 -04001218static __poll_t usbtmc_poll(struct file *file, poll_table *wait)
Dave Penklereb6b92e2016-01-27 19:19:14 +01001219{
1220 struct usbtmc_device_data *data = file->private_data;
Al Viroafc9a422017-07-03 06:39:46 -04001221 __poll_t mask;
Dave Penklereb6b92e2016-01-27 19:19:14 +01001222
1223 mutex_lock(&data->io_mutex);
1224
1225 if (data->zombie) {
Linus Torvaldsa9a08842018-02-11 14:34:03 -08001226 mask = EPOLLHUP | EPOLLERR;
Dave Penklereb6b92e2016-01-27 19:19:14 +01001227 goto no_poll;
1228 }
1229
1230 poll_wait(file, &data->waitq, wait);
1231
Linus Torvaldsa9a08842018-02-11 14:34:03 -08001232 mask = (atomic_read(&data->srq_asserted)) ? EPOLLIN | EPOLLRDNORM : 0;
Dave Penklereb6b92e2016-01-27 19:19:14 +01001233
1234no_poll:
1235 mutex_unlock(&data->io_mutex);
1236 return mask;
1237}
1238
Alexey Dobriyan828c0952009-10-01 15:43:56 -07001239static const struct file_operations fops = {
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001240 .owner = THIS_MODULE,
1241 .read = usbtmc_read,
1242 .write = usbtmc_write,
1243 .open = usbtmc_open,
1244 .release = usbtmc_release,
1245 .unlocked_ioctl = usbtmc_ioctl,
Dave Penkler82ed3382016-01-27 19:15:15 +01001246 .fasync = usbtmc_fasync,
Dave Penklereb6b92e2016-01-27 19:19:14 +01001247 .poll = usbtmc_poll,
Arnd Bergmann6038f372010-08-15 18:52:59 +02001248 .llseek = default_llseek,
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001249};
1250
1251static struct usb_class_driver usbtmc_class = {
1252 .name = "usbtmc%d",
1253 .fops = &fops,
1254 .minor_base = USBTMC_MINOR_BASE,
1255};
1256
Dave Penklerdbf3e7f2016-01-27 19:09:24 +01001257static void usbtmc_interrupt(struct urb *urb)
1258{
1259 struct usbtmc_device_data *data = urb->context;
1260 struct device *dev = &data->intf->dev;
1261 int status = urb->status;
1262 int rv;
1263
1264 dev_dbg(&data->intf->dev, "int status: %d len %d\n",
1265 status, urb->actual_length);
1266
1267 switch (status) {
1268 case 0: /* SUCCESS */
1269 /* check for valid STB notification */
1270 if (data->iin_buffer[0] > 0x81) {
1271 data->bNotify1 = data->iin_buffer[0];
1272 data->bNotify2 = data->iin_buffer[1];
1273 atomic_set(&data->iin_data_valid, 1);
1274 wake_up_interruptible(&data->waitq);
1275 goto exit;
1276 }
Dave Penkler82ed3382016-01-27 19:15:15 +01001277 /* check for SRQ notification */
1278 if (data->iin_buffer[0] == 0x81) {
1279 if (data->fasync)
1280 kill_fasync(&data->fasync,
1281 SIGIO, POLL_IN);
1282
1283 atomic_set(&data->srq_asserted, 1);
1284 wake_up_interruptible(&data->waitq);
1285 goto exit;
1286 }
Dave Penklerdbf3e7f2016-01-27 19:09:24 +01001287 dev_warn(dev, "invalid notification: %x\n", data->iin_buffer[0]);
1288 break;
1289 case -EOVERFLOW:
1290 dev_err(dev, "overflow with length %d, actual length is %d\n",
1291 data->iin_wMaxPacketSize, urb->actual_length);
Gustavo A. R. Silvae4c65942017-10-24 21:53:09 -05001292 /* fall through */
Dave Penklerdbf3e7f2016-01-27 19:09:24 +01001293 case -ECONNRESET:
1294 case -ENOENT:
1295 case -ESHUTDOWN:
1296 case -EILSEQ:
1297 case -ETIME:
1298 /* urb terminated, clean up */
1299 dev_dbg(dev, "urb terminated, status: %d\n", status);
1300 return;
1301 default:
1302 dev_err(dev, "unknown status received: %d\n", status);
1303 }
1304exit:
1305 rv = usb_submit_urb(urb, GFP_ATOMIC);
1306 if (rv)
1307 dev_err(dev, "usb_submit_urb failed: %d\n", rv);
1308}
1309
1310static void usbtmc_free_int(struct usbtmc_device_data *data)
1311{
1312 if (!data->iin_ep_present || !data->iin_urb)
1313 return;
1314 usb_kill_urb(data->iin_urb);
1315 kfree(data->iin_buffer);
1316 usb_free_urb(data->iin_urb);
1317 kref_put(&data->kref, usbtmc_delete);
1318}
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001319
1320static int usbtmc_probe(struct usb_interface *intf,
1321 const struct usb_device_id *id)
1322{
1323 struct usbtmc_device_data *data;
1324 struct usb_host_interface *iface_desc;
Johan Hovold041370c2017-03-28 10:33:16 +02001325 struct usb_endpoint_descriptor *bulk_in, *bulk_out, *int_in;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001326 int retcode;
1327
1328 dev_dbg(&intf->dev, "%s called\n", __func__);
1329
Johan Hovold687e0682017-03-14 17:55:45 +01001330 data = kzalloc(sizeof(*data), GFP_KERNEL);
Peter Chenb8f28542014-10-14 15:55:56 +08001331 if (!data)
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001332 return -ENOMEM;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001333
1334 data->intf = intf;
1335 data->id = id;
1336 data->usb_dev = usb_get_dev(interface_to_usbdev(intf));
1337 usb_set_intfdata(intf, data);
1338 kref_init(&data->kref);
1339 mutex_init(&data->io_mutex);
Dave Penklerdbf3e7f2016-01-27 19:09:24 +01001340 init_waitqueue_head(&data->waitq);
1341 atomic_set(&data->iin_data_valid, 0);
Dave Penkler82ed3382016-01-27 19:15:15 +01001342 atomic_set(&data->srq_asserted, 0);
Oliver Neukum86286882009-07-02 11:36:30 +02001343 data->zombie = 0;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001344
1345 /* Initialize USBTMC bTag and other fields */
1346 data->bTag = 1;
1347 data->TermCharEnabled = 0;
1348 data->TermChar = '\n';
Dave Penklerdbf3e7f2016-01-27 19:09:24 +01001349 /* 2 <= bTag <= 127 USBTMC-USB488 subclass specification 4.3.1 */
1350 data->iin_bTag = 2;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001351
1352 /* USBTMC devices have only one setting, so use that */
1353 iface_desc = data->intf->cur_altsetting;
Dave Penklerdbf3e7f2016-01-27 19:09:24 +01001354 data->ifnum = iface_desc->desc.bInterfaceNumber;
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001355
Johan Hovold041370c2017-03-28 10:33:16 +02001356 /* Find bulk endpoints */
1357 retcode = usb_find_common_endpoints(iface_desc,
1358 &bulk_in, &bulk_out, NULL, NULL);
1359 if (retcode) {
Johan Hovold687e0682017-03-14 17:55:45 +01001360 dev_err(&intf->dev, "bulk endpoints not found\n");
Johan Hovold687e0682017-03-14 17:55:45 +01001361 goto err_put;
1362 }
1363
Johan Hovold041370c2017-03-28 10:33:16 +02001364 data->bulk_in = bulk_in->bEndpointAddress;
1365 dev_dbg(&intf->dev, "Found bulk in endpoint at %u\n", data->bulk_in);
Dave Penklerdbf3e7f2016-01-27 19:09:24 +01001366
Johan Hovold041370c2017-03-28 10:33:16 +02001367 data->bulk_out = bulk_out->bEndpointAddress;
1368 dev_dbg(&intf->dev, "Found Bulk out endpoint at %u\n", data->bulk_out);
1369
1370 /* Find int endpoint */
1371 retcode = usb_find_int_in_endpoint(iface_desc, &int_in);
1372 if (!retcode) {
1373 data->iin_ep_present = 1;
1374 data->iin_ep = int_in->bEndpointAddress;
1375 data->iin_wMaxPacketSize = usb_endpoint_maxp(int_in);
1376 data->iin_interval = int_in->bInterval;
1377 dev_dbg(&intf->dev, "Found Int in endpoint at %u\n",
Dave Penklerdbf3e7f2016-01-27 19:09:24 +01001378 data->iin_ep);
Dave Penklerdbf3e7f2016-01-27 19:09:24 +01001379 }
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001380
1381 retcode = get_capabilities(data);
1382 if (retcode)
1383 dev_err(&intf->dev, "can't read capabilities\n");
1384 else
1385 retcode = sysfs_create_group(&intf->dev.kobj,
1386 &capability_attr_grp);
1387
Dave Penklerdbf3e7f2016-01-27 19:09:24 +01001388 if (data->iin_ep_present) {
1389 /* allocate int urb */
1390 data->iin_urb = usb_alloc_urb(0, GFP_KERNEL);
Johan Hovold2e47c532017-03-14 17:55:46 +01001391 if (!data->iin_urb) {
1392 retcode = -ENOMEM;
Dave Penklerdbf3e7f2016-01-27 19:09:24 +01001393 goto error_register;
Johan Hovold2e47c532017-03-14 17:55:46 +01001394 }
Dave Penklerdbf3e7f2016-01-27 19:09:24 +01001395
Dave Penkler88aecde2016-09-28 20:06:01 +02001396 /* Protect interrupt in endpoint data until iin_urb is freed */
Dave Penklerdbf3e7f2016-01-27 19:09:24 +01001397 kref_get(&data->kref);
1398
1399 /* allocate buffer for interrupt in */
1400 data->iin_buffer = kmalloc(data->iin_wMaxPacketSize,
1401 GFP_KERNEL);
Johan Hovold2e47c532017-03-14 17:55:46 +01001402 if (!data->iin_buffer) {
1403 retcode = -ENOMEM;
Dave Penklerdbf3e7f2016-01-27 19:09:24 +01001404 goto error_register;
Johan Hovold2e47c532017-03-14 17:55:46 +01001405 }
Dave Penklerdbf3e7f2016-01-27 19:09:24 +01001406
1407 /* fill interrupt urb */
1408 usb_fill_int_urb(data->iin_urb, data->usb_dev,
1409 usb_rcvintpipe(data->usb_dev, data->iin_ep),
1410 data->iin_buffer, data->iin_wMaxPacketSize,
1411 usbtmc_interrupt,
1412 data, data->iin_interval);
1413
1414 retcode = usb_submit_urb(data->iin_urb, GFP_KERNEL);
1415 if (retcode) {
1416 dev_err(&intf->dev, "Failed to submit iin_urb\n");
1417 goto error_register;
1418 }
1419 }
1420
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001421 retcode = sysfs_create_group(&intf->dev.kobj, &data_attr_grp);
1422
1423 retcode = usb_register_dev(intf, &usbtmc_class);
1424 if (retcode) {
1425 dev_err(&intf->dev, "Not able to get a minor"
1426 " (base %u, slice default): %d\n", USBTMC_MINOR_BASE,
1427 retcode);
1428 goto error_register;
1429 }
1430 dev_dbg(&intf->dev, "Using minor number %d\n", intf->minor);
1431
1432 return 0;
1433
1434error_register:
1435 sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp);
1436 sysfs_remove_group(&intf->dev.kobj, &data_attr_grp);
Dave Penklerdbf3e7f2016-01-27 19:09:24 +01001437 usbtmc_free_int(data);
Johan Hovold687e0682017-03-14 17:55:45 +01001438err_put:
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001439 kref_put(&data->kref, usbtmc_delete);
1440 return retcode;
1441}
1442
1443static void usbtmc_disconnect(struct usb_interface *intf)
1444{
1445 struct usbtmc_device_data *data;
1446
1447 dev_dbg(&intf->dev, "usbtmc_disconnect called\n");
1448
1449 data = usb_get_intfdata(intf);
1450 usb_deregister_dev(intf, &usbtmc_class);
1451 sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp);
1452 sysfs_remove_group(&intf->dev.kobj, &data_attr_grp);
Oliver Neukum86286882009-07-02 11:36:30 +02001453 mutex_lock(&data->io_mutex);
1454 data->zombie = 1;
Dave Penklerf9cfabc2016-02-18 10:03:00 +01001455 wake_up_all(&data->waitq);
Oliver Neukum86286882009-07-02 11:36:30 +02001456 mutex_unlock(&data->io_mutex);
Dave Penklerf9cfabc2016-02-18 10:03:00 +01001457 usbtmc_free_int(data);
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001458 kref_put(&data->kref, usbtmc_delete);
1459}
1460
Oliver Neukumdca8cd02009-09-24 00:33:45 +02001461static int usbtmc_suspend(struct usb_interface *intf, pm_message_t message)
Oliver Neukuma4708102009-07-02 11:44:33 +02001462{
1463 /* this driver does not have pending URBs */
1464 return 0;
1465}
1466
Oliver Neukumdca8cd02009-09-24 00:33:45 +02001467static int usbtmc_resume(struct usb_interface *intf)
Oliver Neukuma4708102009-07-02 11:44:33 +02001468{
1469 return 0;
1470}
1471
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001472static struct usb_driver usbtmc_driver = {
1473 .name = "usbtmc",
1474 .id_table = usbtmc_devices,
1475 .probe = usbtmc_probe,
Oliver Neukuma4708102009-07-02 11:44:33 +02001476 .disconnect = usbtmc_disconnect,
1477 .suspend = usbtmc_suspend,
1478 .resume = usbtmc_resume,
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001479};
1480
Greg Kroah-Hartman65db4302011-11-18 09:34:02 -08001481module_usb_driver(usbtmc_driver);
Greg Kroah-Hartman5b775f62008-08-26 16:22:06 -07001482
1483MODULE_LICENSE("GPL");