• Home
  • Raw
  • Download

Lines Matching +full:micro +full:- +full:usb

1 // SPDX-License-Identifier: GPL-2.0+
3 * Generic USB driver for report based interrupt in/out devices
4 * like LD Didactic's USB devices. LD Didactic's USB devices are
11 * Devices based on the book USB COMPLETE by Jan Axelson may need
14 * Copyright (C) 2005 Michael Hund <mhund@ld-didactic.de>
16 * Derived from Lego USB Tower driver
18 * 2001-2004 Juergen Stuber <starblue@users.sourceforge.net>
29 #include <linux/usb.h>
33 #define USB_VENDOR_ID_LD 0x0f11 /* USB Vendor ID of LD Didactic GmbH */
34 #define USB_DEVICE_ID_LD_CASSY 0x1000 /* USB Product ID of CASSY-S modules with 8 bytes endpoint s…
35 #define USB_DEVICE_ID_LD_CASSY2 0x1001 /* USB Product ID of CASSY-S modules with 64 bytes endpoint…
36 #define USB_DEVICE_ID_LD_POCKETCASSY 0x1010 /* USB Product ID of Pocket-CASSY */
37 #define USB_DEVICE_ID_LD_POCKETCASSY2 0x1011 /* USB Product ID of Pocket-CASSY 2 (reserved) */
38 #define USB_DEVICE_ID_LD_MOBILECASSY 0x1020 /* USB Product ID of Mobile-CASSY */
39 #define USB_DEVICE_ID_LD_MOBILECASSY2 0x1021 /* USB Product ID of Mobile-CASSY 2 (reserved) */
40 #define USB_DEVICE_ID_LD_MICROCASSYVOLTAGE 0x1031 /* USB Product ID of Micro-CASSY Voltage */
41 #define USB_DEVICE_ID_LD_MICROCASSYCURRENT 0x1032 /* USB Product ID of Micro-CASSY Current */
42 #define USB_DEVICE_ID_LD_MICROCASSYTIME 0x1033 /* USB Product ID of Micro-CASSY Time (reserved) */
43 #define USB_DEVICE_ID_LD_MICROCASSYTEMPERATURE 0x1035 /* USB Product ID of Micro-CASSY Temperature …
44 #define USB_DEVICE_ID_LD_MICROCASSYPH 0x1038 /* USB Product ID of Micro-CASSY pH */
45 #define USB_DEVICE_ID_LD_POWERANALYSERCASSY 0x1040 /* USB Product ID of Power Analyser CASSY */
46 #define USB_DEVICE_ID_LD_CONVERTERCONTROLLERCASSY 0x1042 /* USB Product ID of Converter Controller …
47 #define USB_DEVICE_ID_LD_MACHINETESTCASSY 0x1043 /* USB Product ID of Machine Test CASSY */
48 #define USB_DEVICE_ID_LD_JWM 0x1080 /* USB Product ID of Joule and Wattmeter */
49 #define USB_DEVICE_ID_LD_DMMP 0x1081 /* USB Product ID of Digital Multimeter P (reserved) */
50 #define USB_DEVICE_ID_LD_UMIP 0x1090 /* USB Product ID of UMI P */
51 #define USB_DEVICE_ID_LD_UMIC 0x10A0 /* USB Product ID of UMI C */
52 #define USB_DEVICE_ID_LD_UMIB 0x10B0 /* USB Product ID of UMI B */
53 #define USB_DEVICE_ID_LD_XRAY 0x1100 /* USB Product ID of X-Ray Apparatus 55481 */
54 #define USB_DEVICE_ID_LD_XRAY2 0x1101 /* USB Product ID of X-Ray Apparatus 554800 */
55 #define USB_DEVICE_ID_LD_XRAYCT 0x1110 /* USB Product ID of X-Ray Apparatus CT 554821*/
56 #define USB_DEVICE_ID_LD_VIDEOCOM 0x1200 /* USB Product ID of VideoCom */
57 #define USB_DEVICE_ID_LD_MOTOR 0x1210 /* USB Product ID of Motor (reserved) */
58 #define USB_DEVICE_ID_LD_COM3LAB 0x2000 /* USB Product ID of COM3LAB */
59 #define USB_DEVICE_ID_LD_TELEPORT 0x2010 /* USB Product ID of Terminal Adapter */
60 #define USB_DEVICE_ID_LD_NETWORKANALYSER 0x2020 /* USB Product ID of Network Analyser */
61 #define USB_DEVICE_ID_LD_POWERCONTROL 0x2030 /* USB Product ID of Converter Control Unit */
62 #define USB_DEVICE_ID_LD_MACHINETEST 0x2040 /* USB Product ID of Machine Test System */
63 #define USB_DEVICE_ID_LD_MOSTANALYSER 0x2050 /* USB Product ID of MOST Protocol Analyser */
64 #define USB_DEVICE_ID_LD_MOSTANALYSER2 0x2051 /* USB Product ID of MOST Protocol Analyser 2 */
65 #define USB_DEVICE_ID_LD_ABSESP 0x2060 /* USB Product ID of ABS ESP */
66 #define USB_DEVICE_ID_LD_AUTODATABUS 0x2070 /* USB Product ID of Automotive Data Buses */
67 #define USB_DEVICE_ID_LD_MCT 0x2080 /* USB Product ID of Microcontroller technique */
68 #define USB_DEVICE_ID_LD_HYBRID 0x2090 /* USB Product ID of Automotive Hybrid */
69 #define USB_DEVICE_ID_LD_HEATCONTROL 0x20A0 /* USB Product ID of Heat control */
116 MODULE_DEVICE_TABLE(usb, ld_usb_table);
117 MODULE_AUTHOR("Michael Hund <mhund@ld-didactic.de>");
118 MODULE_DESCRIPTION("LD USB Driver");
120 MODULE_SUPPORTED_DEVICE("LD USB Devices");
135 /* As of kernel version 2.6.4 ehci-hcd uses an
155 struct usb_interface *intf; /* save off the usb interface pointer */
194 if (dev->interrupt_in_running) { in ld_usb_abort_transfers()
195 dev->interrupt_in_running = 0; in ld_usb_abort_transfers()
196 usb_kill_urb(dev->interrupt_in_urb); in ld_usb_abort_transfers()
198 if (dev->interrupt_out_busy) in ld_usb_abort_transfers()
199 usb_kill_urb(dev->interrupt_out_urb); in ld_usb_abort_transfers()
208 usb_free_urb(dev->interrupt_in_urb); in ld_usb_delete()
209 usb_free_urb(dev->interrupt_out_urb); in ld_usb_delete()
210 kfree(dev->ring_buffer); in ld_usb_delete()
211 kfree(dev->interrupt_in_buffer); in ld_usb_delete()
212 kfree(dev->interrupt_out_buffer); in ld_usb_delete()
221 struct ld_usb *dev = urb->context; in ld_usb_interrupt_in_callback()
224 int status = urb->status; in ld_usb_interrupt_in_callback()
229 if (status == -ENOENT || in ld_usb_interrupt_in_callback()
230 status == -ECONNRESET || in ld_usb_interrupt_in_callback()
231 status == -ESHUTDOWN) { in ld_usb_interrupt_in_callback()
234 dev_dbg(&dev->intf->dev, in ld_usb_interrupt_in_callback()
237 spin_lock_irqsave(&dev->rbsl, flags); in ld_usb_interrupt_in_callback()
242 spin_lock_irqsave(&dev->rbsl, flags); in ld_usb_interrupt_in_callback()
243 if (urb->actual_length > 0) { in ld_usb_interrupt_in_callback()
244 next_ring_head = (dev->ring_head+1) % ring_buffer_size; in ld_usb_interrupt_in_callback()
245 if (next_ring_head != dev->ring_tail) { in ld_usb_interrupt_in_callback()
246 …actual_buffer = (size_t *)(dev->ring_buffer + dev->ring_head * (sizeof(size_t)+dev->interrupt_in_e… in ld_usb_interrupt_in_callback()
247 /* actual_buffer gets urb->actual_length + interrupt_in_buffer */ in ld_usb_interrupt_in_callback()
248 *actual_buffer = urb->actual_length; in ld_usb_interrupt_in_callback()
249 memcpy(actual_buffer+1, dev->interrupt_in_buffer, urb->actual_length); in ld_usb_interrupt_in_callback()
250 dev->ring_head = next_ring_head; in ld_usb_interrupt_in_callback()
251 dev_dbg(&dev->intf->dev, "%s: received %d bytes\n", in ld_usb_interrupt_in_callback()
252 __func__, urb->actual_length); in ld_usb_interrupt_in_callback()
254 dev_warn(&dev->intf->dev, in ld_usb_interrupt_in_callback()
256 urb->actual_length); in ld_usb_interrupt_in_callback()
257 dev->buffer_overflow = 1; in ld_usb_interrupt_in_callback()
263 if (dev->interrupt_in_running && !dev->buffer_overflow) { in ld_usb_interrupt_in_callback()
264 retval = usb_submit_urb(dev->interrupt_in_urb, GFP_ATOMIC); in ld_usb_interrupt_in_callback()
266 dev_err(&dev->intf->dev, in ld_usb_interrupt_in_callback()
268 dev->buffer_overflow = 1; in ld_usb_interrupt_in_callback()
271 spin_unlock_irqrestore(&dev->rbsl, flags); in ld_usb_interrupt_in_callback()
273 dev->interrupt_in_done = 1; in ld_usb_interrupt_in_callback()
274 wake_up_interruptible(&dev->read_wait); in ld_usb_interrupt_in_callback()
282 struct ld_usb *dev = urb->context; in ld_usb_interrupt_out_callback()
283 int status = urb->status; in ld_usb_interrupt_out_callback()
286 if (status && !(status == -ENOENT || in ld_usb_interrupt_out_callback()
287 status == -ECONNRESET || in ld_usb_interrupt_out_callback()
288 status == -ESHUTDOWN)) in ld_usb_interrupt_out_callback()
289 dev_dbg(&dev->intf->dev, in ld_usb_interrupt_out_callback()
290 "%s - nonzero write interrupt status received: %d\n", in ld_usb_interrupt_out_callback()
293 dev->interrupt_out_busy = 0; in ld_usb_interrupt_out_callback()
294 wake_up_interruptible(&dev->write_wait); in ld_usb_interrupt_out_callback()
313 printk(KERN_ERR "%s - error, can't find device for minor %d\n", in ld_usb_open()
315 return -ENODEV; in ld_usb_open()
321 return -ENODEV; in ld_usb_open()
324 if (mutex_lock_interruptible(&dev->mutex)) in ld_usb_open()
325 return -ERESTARTSYS; in ld_usb_open()
328 if (dev->open_count) { in ld_usb_open()
329 retval = -EBUSY; in ld_usb_open()
332 dev->open_count = 1; in ld_usb_open()
335 dev->ring_head = 0; in ld_usb_open()
336 dev->ring_tail = 0; in ld_usb_open()
337 dev->buffer_overflow = 0; in ld_usb_open()
338 usb_fill_int_urb(dev->interrupt_in_urb, in ld_usb_open()
341 dev->interrupt_in_endpoint->bEndpointAddress), in ld_usb_open()
342 dev->interrupt_in_buffer, in ld_usb_open()
343 dev->interrupt_in_endpoint_size, in ld_usb_open()
346 dev->interrupt_in_interval); in ld_usb_open()
348 dev->interrupt_in_running = 1; in ld_usb_open()
349 dev->interrupt_in_done = 0; in ld_usb_open()
351 retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL); in ld_usb_open()
353 dev_err(&interface->dev, "Couldn't submit interrupt_in_urb %d\n", retval); in ld_usb_open()
354 dev->interrupt_in_running = 0; in ld_usb_open()
355 dev->open_count = 0; in ld_usb_open()
360 file->private_data = dev; in ld_usb_open()
363 mutex_unlock(&dev->mutex); in ld_usb_open()
376 dev = file->private_data; in ld_usb_release()
379 retval = -ENODEV; in ld_usb_release()
383 mutex_lock(&dev->mutex); in ld_usb_release()
385 if (dev->open_count != 1) { in ld_usb_release()
386 retval = -ENODEV; in ld_usb_release()
389 if (dev->disconnected) { in ld_usb_release()
391 mutex_unlock(&dev->mutex); in ld_usb_release()
398 if (dev->interrupt_out_busy) in ld_usb_release()
399 wait_event_interruptible_timeout(dev->write_wait, !dev->interrupt_out_busy, 2 * HZ); in ld_usb_release()
401 dev->open_count = 0; in ld_usb_release()
404 mutex_unlock(&dev->mutex); in ld_usb_release()
418 dev = file->private_data; in ld_usb_poll()
420 if (dev->disconnected) in ld_usb_poll()
423 poll_wait(file, &dev->read_wait, wait); in ld_usb_poll()
424 poll_wait(file, &dev->write_wait, wait); in ld_usb_poll()
426 if (dev->ring_head != dev->ring_tail) in ld_usb_poll()
428 if (!dev->interrupt_out_busy) in ld_usb_poll()
446 dev = file->private_data; in ld_usb_read()
453 if (mutex_lock_interruptible(&dev->mutex)) { in ld_usb_read()
454 retval = -ERESTARTSYS; in ld_usb_read()
459 if (dev->disconnected) { in ld_usb_read()
460 retval = -ENODEV; in ld_usb_read()
466 spin_lock_irq(&dev->rbsl); in ld_usb_read()
467 while (dev->ring_head == dev->ring_tail) { in ld_usb_read()
468 dev->interrupt_in_done = 0; in ld_usb_read()
469 spin_unlock_irq(&dev->rbsl); in ld_usb_read()
470 if (file->f_flags & O_NONBLOCK) { in ld_usb_read()
471 retval = -EAGAIN; in ld_usb_read()
474 retval = wait_event_interruptible(dev->read_wait, dev->interrupt_in_done); in ld_usb_read()
478 spin_lock_irq(&dev->rbsl); in ld_usb_read()
480 spin_unlock_irq(&dev->rbsl); in ld_usb_read()
483 …actual_buffer = (size_t *)(dev->ring_buffer + dev->ring_tail * (sizeof(size_t)+dev->interrupt_in_e… in ld_usb_read()
484 if (*actual_buffer > dev->interrupt_in_endpoint_size) { in ld_usb_read()
485 retval = -EIO; in ld_usb_read()
490 dev_warn(&dev->intf->dev, "Read buffer overflow, %zu bytes dropped\n", in ld_usb_read()
491 *actual_buffer-bytes_to_read); in ld_usb_read()
495 retval = -EFAULT; in ld_usb_read()
500 spin_lock_irq(&dev->rbsl); in ld_usb_read()
501 dev->ring_tail = (dev->ring_tail + 1) % ring_buffer_size; in ld_usb_read()
503 if (dev->buffer_overflow) { in ld_usb_read()
504 dev->buffer_overflow = 0; in ld_usb_read()
505 spin_unlock_irq(&dev->rbsl); in ld_usb_read()
506 rv = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL); in ld_usb_read()
508 dev->buffer_overflow = 1; in ld_usb_read()
510 spin_unlock_irq(&dev->rbsl); in ld_usb_read()
515 mutex_unlock(&dev->mutex); in ld_usb_read()
531 dev = file->private_data; in ld_usb_write()
538 if (mutex_lock_interruptible(&dev->mutex)) { in ld_usb_write()
539 retval = -ERESTARTSYS; in ld_usb_write()
544 if (dev->disconnected) { in ld_usb_write()
545 retval = -ENODEV; in ld_usb_write()
551 if (dev->interrupt_out_busy) { in ld_usb_write()
552 if (file->f_flags & O_NONBLOCK) { in ld_usb_write()
553 retval = -EAGAIN; in ld_usb_write()
556 retval = wait_event_interruptible(dev->write_wait, !dev->interrupt_out_busy); in ld_usb_write()
563 bytes_to_write = min(count, write_buffer_size*dev->interrupt_out_endpoint_size); in ld_usb_write()
565 dev_warn(&dev->intf->dev, "Write buffer overflow, %zu bytes dropped\n", in ld_usb_write()
566 count - bytes_to_write); in ld_usb_write()
567 dev_dbg(&dev->intf->dev, "%s: count = %zu, bytes_to_write = %zu\n", in ld_usb_write()
570 if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) { in ld_usb_write()
571 retval = -EFAULT; in ld_usb_write()
575 if (dev->interrupt_out_endpoint == NULL) { in ld_usb_write()
577 retval = usb_control_msg(interface_to_usbdev(dev->intf), in ld_usb_write()
578 usb_sndctrlpipe(interface_to_usbdev(dev->intf), 0), in ld_usb_write()
582 dev->interrupt_out_buffer, in ld_usb_write()
586 dev_err(&dev->intf->dev, in ld_usb_write()
593 usb_fill_int_urb(dev->interrupt_out_urb, in ld_usb_write()
594 interface_to_usbdev(dev->intf), in ld_usb_write()
595 usb_sndintpipe(interface_to_usbdev(dev->intf), in ld_usb_write()
596 dev->interrupt_out_endpoint->bEndpointAddress), in ld_usb_write()
597 dev->interrupt_out_buffer, in ld_usb_write()
601 dev->interrupt_out_interval); in ld_usb_write()
603 dev->interrupt_out_busy = 1; in ld_usb_write()
606 retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL); in ld_usb_write()
608 dev->interrupt_out_busy = 0; in ld_usb_write()
609 dev_err(&dev->intf->dev, in ld_usb_write()
617 mutex_unlock(&dev->mutex); in ld_usb_write()
635 * usb class driver info in order to get a minor number from the usb core,
647 * Called by the usb core when a new device is connected that it thinks
656 int retval = -ENOMEM; in ld_usb_probe()
664 mutex_init(&dev->mutex); in ld_usb_probe()
665 spin_lock_init(&dev->rbsl); in ld_usb_probe()
666 dev->intf = intf; in ld_usb_probe()
667 init_waitqueue_head(&dev->read_wait); in ld_usb_probe()
668 init_waitqueue_head(&dev->write_wait); in ld_usb_probe()
671 if ((le16_to_cpu(udev->descriptor.idVendor) == USB_VENDOR_ID_LD) && in ld_usb_probe()
672 ((le16_to_cpu(udev->descriptor.idProduct) == USB_DEVICE_ID_LD_CASSY) || in ld_usb_probe()
673 (le16_to_cpu(udev->descriptor.idProduct) == USB_DEVICE_ID_LD_COM3LAB)) && in ld_usb_probe()
674 (le16_to_cpu(udev->descriptor.bcdDevice) <= 0x103)) { in ld_usb_probe()
683 iface_desc = intf->cur_altsetting; in ld_usb_probe()
686 &dev->interrupt_in_endpoint); in ld_usb_probe()
688 dev_err(&intf->dev, "Interrupt in endpoint not found\n"); in ld_usb_probe()
694 &dev->interrupt_out_endpoint); in ld_usb_probe()
696 dev_warn(&intf->dev, "Interrupt out endpoint not found (using control endpoint instead)\n"); in ld_usb_probe()
698 dev->interrupt_in_endpoint_size = usb_endpoint_maxp(dev->interrupt_in_endpoint); in ld_usb_probe()
699 dev->ring_buffer = kcalloc(ring_buffer_size, in ld_usb_probe()
700 sizeof(size_t) + dev->interrupt_in_endpoint_size, in ld_usb_probe()
702 if (!dev->ring_buffer) in ld_usb_probe()
704 dev->interrupt_in_buffer = kmalloc(dev->interrupt_in_endpoint_size, GFP_KERNEL); in ld_usb_probe()
705 if (!dev->interrupt_in_buffer) in ld_usb_probe()
707 dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL); in ld_usb_probe()
708 if (!dev->interrupt_in_urb) in ld_usb_probe()
710 …dev->interrupt_out_endpoint_size = dev->interrupt_out_endpoint ? usb_endpoint_maxp(dev->interrupt_… in ld_usb_probe()
711 udev->descriptor.bMaxPacketSize0; in ld_usb_probe()
712 dev->interrupt_out_buffer = in ld_usb_probe()
714 dev->interrupt_out_endpoint_size, GFP_KERNEL); in ld_usb_probe()
715 if (!dev->interrupt_out_buffer) in ld_usb_probe()
717 dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL); in ld_usb_probe()
718 if (!dev->interrupt_out_urb) in ld_usb_probe()
720 …ev->interrupt_in_interval = min_interrupt_in_interval > dev->interrupt_in_endpoint->bInterval ? mi… in ld_usb_probe()
721 if (dev->interrupt_out_endpoint) in ld_usb_probe()
722->interrupt_out_interval = min_interrupt_out_interval > dev->interrupt_out_endpoint->bInterval ? m… in ld_usb_probe()
730 dev_err(&intf->dev, "Not able to get a minor for this device.\n"); in ld_usb_probe()
736 dev_info(&intf->dev, "LD USB Device #%d now attached to major %d minor %d\n", in ld_usb_probe()
737 (intf->minor - USB_LD_MINOR_BASE), USB_MAJOR, intf->minor); in ld_usb_probe()
751 * Called by the usb core when the device is removed from the system.
761 minor = intf->minor; in ld_usb_disconnect()
766 usb_poison_urb(dev->interrupt_in_urb); in ld_usb_disconnect()
767 usb_poison_urb(dev->interrupt_out_urb); in ld_usb_disconnect()
769 mutex_lock(&dev->mutex); in ld_usb_disconnect()
772 if (!dev->open_count) { in ld_usb_disconnect()
773 mutex_unlock(&dev->mutex); in ld_usb_disconnect()
776 dev->disconnected = 1; in ld_usb_disconnect()
778 wake_up_interruptible_all(&dev->read_wait); in ld_usb_disconnect()
779 wake_up_interruptible_all(&dev->write_wait); in ld_usb_disconnect()
780 mutex_unlock(&dev->mutex); in ld_usb_disconnect()
783 dev_info(&intf->dev, "LD USB Device #%d now disconnected\n", in ld_usb_disconnect()
784 (minor - USB_LD_MINOR_BASE)); in ld_usb_disconnect()
787 /* usb specific object needed to register this driver with the usb subsystem */