Device-LabJack

 view release on metacpan or  search on metacpan

linux-labjack/INSTALL  view on Meta::CPAN

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
Finally, run the test application:
 
        # ./firmware-revision   or
        # ./analog-outs         or
        # ./list-all
 
HID NOTE: If the hid module is loaded (use lsmod to view the modules and
look for "hid"), the provided labjack driver will not work correctly. 
Since the Labjack is classified as a HID device, the hid driver will
claim the device. However, the hid driver does not support the "Interrupt"
out endpoint used by the Labjack and thus cannot communicate with the
Labjack.  You must remove the hid driver prior to loading the labjack
driver.  The following command, as root, should suffice:
 
        # modprobe -r hid
 
If you absolutely must have the hid device driver loaded, it is possible
to add the Labjack to the HID blacklist.  Add the Labjack USB vendor
(0x0cd5) and product (0x0001) IDs to the hid_blacklist structure in hid-core.c
in the drivers/usb directory.  An example of the line to insert into the
hid_blacklist structure would be:

linux-labjack/INSTALL  view on Meta::CPAN

120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
        % make
 
Finally, run the test application as root:
 
        # ./firmware-revision
 
HID NOTE: If the hid module is loaded (use lsmod to view the modules and
look for "hid"), the provided labjack driver will not work correctly. 
Since the Labjack is classified as a HID device, the hid driver will claim
the device.  However, the hid driver does not support the "Interrupt" out
endpoint used by the Labjack and thus cannot communicate with the Labjack. 
You must remove the hid driver prior to loading the labjack driver.  The
following command, as root, should suffice:
 
        # modprobe -r hid
 
If you absolutely must have the hid device driver loaded, it is possible to
add the Labjack to the HID blacklist.  Add the Labjack USB vendor (0x0cd5)
and product (0x0001) IDs to the hid_blacklist structure in hid-core.c in
the drivers/usb/input directory.  An example of the line to insert in the
hid_blacklist structure would be:

linux-labjack/README  view on Meta::CPAN

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
        o) Linux Labjack device drivers for the Linux Kernel v2.4 and v2.6.
        o) A port of the Windows API (based upon Eric Sorton modified ljackv112.c
        and ljackuw.c v1.18).
        o) Test application to read the firmware revision, set analog-outs, and
        list all the LabJacks connected to your system.
 
Installation instructions are provided in the INSTALL file.
 
The Labjack driver is heavily (about 95% code reuse) based upon the device driver
for the LegoUSB tower provided in leJOS.  The LegoUSB tower, the Labjack U12, and
several other devices all use Interrupt endpoints (both In and Out) to communicate
over the USB bus.  The device driver simply maps the two endpoints to the read()
and write() system calls.  At this time, there is no generic capability within the
Linux USB subsystem to support generic read/writes using Interrupt endpoints. 
Possibly, in the future, such a capability will be provided by the Linux
kernel and the device drivers will no longer be necessary.
 
The Windows API code (v1.12 and v1.18) has been modified to work under Linux.
There are some notes within the code. 
There are a few restrictions:
 
        o)At this time, there is support for up to 16 LabJacks.  They are accessed
        the same way as under the Windows API (by their local id).
        o)The state of the discretes are not persistent across applications(in the

linux-labjack/driver/linux-2.4/labjack.c  view on Meta::CPAN

93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
        int                     open_count;     /* number of times this port has been opened */
         
        char*                   read_buffer;
    int                     read_buffer_length;
 
        wait_queue_head_t       read_wait;
        wait_queue_head_t       write_wait;
 
        char*                   interrupt_in_buffer;
        struct usb_endpoint_descriptor* interrupt_in_endpoint;
        struct urb*             interrupt_in_urb;
 
        char*                   interrupt_out_buffer;
        struct usb_endpoint_descriptor* interrupt_out_endpoint;
        struct urb*             interrupt_out_urb;
         
        int                     read_timeout;
        int                     write_timeout;
};
 
/* Note that no locking is needed:
 * read_buffer is arbitrated by read_buffer_length == 0
 * interrupt_out_buffer is arbitrated by interrupt_out_urb->status == -EINPROGRESS
 * interrupt_in_buffer belongs to urb alone and is overwritten on overflow

linux-labjack/driver/linux-2.4/labjack.c  view on Meta::CPAN

238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
       if (dev->open_count > 1) {
               retval = -EBUSY;
               goto error;
       }
       file->private_data = dev;
        
       dev->read_buffer_length = 0;
       FILL_INT_URB(
               dev->interrupt_in_urb,
               dev->udev,
               usb_rcvintpipe(dev->udev, dev->interrupt_in_endpoint->bEndpointAddress),
               dev->interrupt_in_buffer,
               dev->interrupt_in_endpoint->wMaxPacketSize,
               labjack_interrupt_in_callback,
               dev,
               dev->interrupt_in_endpoint->bInterval);
       retval = usb_submit_urb (dev->interrupt_in_urb);
       if (retval != 0) {
               err("Couldn't submit interrupt_in_urb");
               goto error;
       }
 
       goto unlock_exit;
 
error:
       labjack_release_internal (dev);

linux-labjack/driver/linux-2.4/labjack.c  view on Meta::CPAN

504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
                retval = -ETIMEDOUT;
                goto exit;
        }
 
        dbg(4," %s : in progress, count = %d", __func__, count);
 
} else {
                dbg(4," %s : sending, count = %d", __func__, count);
 
        /* write the data into interrupt_out_buffer from userspace */
        buffer_size = dev->interrupt_out_endpoint->wMaxPacketSize;
        bytes_to_write = count > buffer_size ? buffer_size : count;
        dbg(4," %s : buffer_size = %d, count = %d, bytes_to_write = %d", __func__, buffer_size, count, bytes_to_write);
 
        if (copy_from_user (dev->interrupt_out_buffer, buffer, bytes_to_write) != 0) {
                retval = -EFAULT;
                goto exit;
        }
 
        /* send off the urb */
        FILL_INT_URB(
                dev->interrupt_out_urb,
                dev->udev,
                usb_sndintpipe(dev->udev, dev->interrupt_out_endpoint->bEndpointAddress),
                dev->interrupt_out_buffer,
                bytes_to_write,
                labjack_interrupt_out_callback,
                dev,
                0);
 
        dev->interrupt_out_urb->actual_length = bytes_to_write;
        retval = usb_submit_urb (dev->interrupt_out_urb);
 
        if (retval != 0) {

linux-labjack/driver/linux-2.4/labjack.c  view on Meta::CPAN

642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
        if ((urb->status != -ENOENT) && (urb->status != -ECONNRESET)) {
                dbg(1," %s : nonzero status received: %d", __func__, urb->status);
        }
        goto exit;
}
 
down (&dev->sem);
 
if (urb->actual_length > 0) {
        if (dev->read_buffer_length <
            (4 * dev->interrupt_in_endpoint->wMaxPacketSize) - (urb->actual_length)) {
                memcpy (dev->read_buffer+dev->read_buffer_length, dev->interrupt_in_buffer, urb->actual_length);
                dev->read_buffer_length += urb->actual_length;
                wake_up_interruptible (&dev->read_wait);
        } else {
                dbg(1," %s : read_buffer overflow", __func__);
        }
}
 
up (&dev->sem);

linux-labjack/driver/linux-2.4/labjack.c  view on Meta::CPAN

688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
        dbg(4," %s : leave, status %d", __func__, urb->status);
}
 
 
static void * labjack_probe (struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id)
{
        struct labjack_usb *dev = NULL;
        int minor;
        struct usb_interface* interface;
        struct usb_interface_descriptor *iface_desc;
    struct usb_endpoint_descriptor* endpoint;
        int i;
        char name[32];
    void *retval = NULL;
 
        dbg(2," %s : enter", __func__);
 
        if (udev == NULL) {
                info ("udev is NULL.");
        }
        

linux-labjack/driver/linux-2.4/labjack.c  view on Meta::CPAN

737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
dev->minor = minor;
dev->open_count = 0;
 
dev->read_buffer = NULL;
dev->read_buffer_length = 0;
 
init_waitqueue_head (&dev->read_wait);
init_waitqueue_head (&dev->write_wait);
 
dev->interrupt_in_buffer = NULL;
dev->interrupt_in_endpoint = NULL;
dev->interrupt_in_urb = NULL;
 
dev->interrupt_out_buffer = NULL;
dev->interrupt_out_endpoint = NULL;
dev->interrupt_out_urb = NULL;
 
/*
 * It seems slightly dubious to set up endpoints here, as we may
 * change the configuration before calling open.  But the endpoints
 * should be the same in all configurations.
 */
interface = &dev->udev->actconfig->interface[0];
iface_desc = &interface->altsetting[0];
 
for (i = 0; i < iface_desc->bNumEndpoints; ++i) {
        endpoint = &iface_desc->endpoint[i];
 
        if (((endpoint->bEndpointAddress & USB_DIR_MASK) == USB_DIR_IN) &&
            ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
                /* we found an interrupt in endpoint */
                dev->interrupt_in_endpoint = endpoint;
        }
         
        if (((endpoint->bEndpointAddress & USB_DIR_MASK) == USB_DIR_OUT) &&
            ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
                /* we found an interrupt out endpoint */
                dev->interrupt_out_endpoint = endpoint;
        }
}
if(dev->interrupt_in_endpoint == NULL) {
        err("interrupt in endpoint not found");
        retval = NULL;
        goto unlock_exit;
}
if (dev->interrupt_out_endpoint == NULL) {
        err("interrupt out endpoint not found");
        retval = NULL;
        goto unlock_exit;
}
 
dev->read_buffer = kmalloc ((4*dev->interrupt_in_endpoint->wMaxPacketSize), GFP_KERNEL);
if (!dev->read_buffer) {
        err("Couldn't allocate read_buffer");
        retval = NULL;
        goto unlock_exit;
}
dev->interrupt_in_buffer = kmalloc (dev->interrupt_in_endpoint->wMaxPacketSize, GFP_KERNEL);
if (!dev->interrupt_in_buffer) {
        err("Couldn't allocate interrupt_in_buffer");
        retval = NULL;
        goto unlock_exit;
}
dev->interrupt_in_urb = usb_alloc_urb(0);
if (!dev->interrupt_in_urb) {
        err("Couldn't allocate interrupt_in_urb");
        retval = NULL;
        goto unlock_exit;
}
dev->interrupt_out_buffer = kmalloc (dev->interrupt_out_endpoint->wMaxPacketSize, GFP_KERNEL);
if (!dev->interrupt_out_buffer) {
        err("Couldn't allocate interrupt_out_buffer");
        retval = NULL;
        goto unlock_exit;
}
dev->interrupt_out_urb = usb_alloc_urb(0);
if (!dev->interrupt_out_urb) {
        err("Couldn't allocate interrupt_out_urb");
        retval = NULL;
        goto unlock_exit;

linux-labjack/driver/linux-2.6/labjack.c  view on Meta::CPAN

113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
        size_t                  read_buffer_length; /* this much came in */
        size_t                  read_packet_length; /* this much will be returned on read */
        spinlock_t              read_buffer_lock;
        int                     packet_timeout_jiffies;
        unsigned long           read_last_arrival;
 
        wait_queue_head_t       read_wait;
        wait_queue_head_t       write_wait;
 
        char*                   interrupt_in_buffer;
        struct usb_endpoint_descriptor* interrupt_in_endpoint;
        struct urb*             interrupt_in_urb;
        int                     interrupt_in_interval;
        int                     interrupt_in_running;
        int                     interrupt_in_done;
 
        char*                   interrupt_out_buffer;
        struct usb_endpoint_descriptor* interrupt_out_endpoint;
        struct urb*             interrupt_out_urb;
        int                     interrupt_out_interval;
        int                     interrupt_out_busy;
 
};
 
static ssize_t labjack_read(struct file *file, char *buffer, size_t count, loff_t *ppos);
static ssize_t labjack_read_feature(struct file *file, char *buffer, size_t count, loff_t *ppos);
static ssize_t labjack_write(struct file *file, const char *buffer, size_t count, loff_t *ppos);
static int labjack_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);

linux-labjack/driver/linux-2.6/labjack.c  view on Meta::CPAN

256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
        goto unlock_exit;
}
 
dev->open_count = 1;
 
dev->read_buffer_length = 0;
 
dev->read_packet_length = 0;
usb_fill_int_urb (dev->interrupt_in_urb,
        dev->udev,
        usb_rcvintpipe(dev->udev, dev->interrupt_in_endpoint->bEndpointAddress),
        dev->interrupt_in_buffer,
        dev->interrupt_in_endpoint->wMaxPacketSize,
        labjack_interrupt_in_callback,
        dev,
        dev->interrupt_in_interval);
 
        dev->interrupt_in_running = 1;
        dev->interrupt_in_done = 0;
        mb();
 
retval = usb_submit_urb (dev->interrupt_in_urb, GFP_KERNEL);
if (retval) {

linux-labjack/driver/linux-2.6/labjack.c  view on Meta::CPAN

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
bytes_to_write = min(count, write_buffer_size);
dbg(4, "%s: count = %Zd, bytes_to_write = %Zd", __FUNCTION__, count, bytes_to_write);
 
if (copy_from_user (dev->interrupt_out_buffer, buffer, bytes_to_write)) {
        retval = -EFAULT;
        goto unlock_exit;
}
 
usb_fill_int_urb(dev->interrupt_out_urb, dev->udev,
    usb_sndintpipe(dev->udev, dev->interrupt_out_endpoint->bEndpointAddress),
    dev->interrupt_out_buffer,
    bytes_to_write,
    labjack_interrupt_out_callback,
    dev,
    dev->interrupt_out_interval);
 
dev->interrupt_out_busy = 1;
wmb();
 
retval = usb_submit_urb (dev->interrupt_out_urb, GFP_KERNEL);

linux-labjack/driver/linux-2.6/labjack.c  view on Meta::CPAN

717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
        usb_labjack_debug_data(5,__FUNCTION__, urb->actual_length, urb->transfer_buffer);
        dbg(4," %s : leave, status %d", __FUNCTION__, urb->status);
}
 
 
static int labjack_probe (struct usb_interface *interface, const struct usb_device_id *id)
{
        struct usb_device *udev = interface_to_usbdev(interface);
        struct labjack_usb *dev = NULL;
        struct usb_host_interface *iface_desc;
        struct usb_endpoint_descriptor* endpoint;
        int i;
        int retval = -ENOMEM;
 
        dbg(2," %s : enter", __FUNCTION__);
 
        if (udev == NULL) {
                info ("udev is NULL.");
        }
         
        if ((udev->descriptor.idVendor != LABJACK_USB_VENDOR_ID) ||

linux-labjack/driver/linux-2.6/labjack.c  view on Meta::CPAN

754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
dev->read_buffer_length = 0;
dev->read_packet_length = 0;
spin_lock_init (&dev->read_buffer_lock);
dev->packet_timeout_jiffies = packet_timeout * HZ / 1000;
dev->read_last_arrival = jiffies;
 
init_waitqueue_head (&dev->read_wait);
init_waitqueue_head (&dev->write_wait);
 
dev->interrupt_in_buffer = NULL;
dev->interrupt_in_endpoint = NULL;
dev->interrupt_in_urb = NULL;
dev->interrupt_in_running = 0;
dev->interrupt_in_done = 0;
 
dev->interrupt_out_buffer = NULL;
dev->interrupt_out_endpoint = NULL;
dev->interrupt_out_urb = NULL;
dev->interrupt_out_busy = 0;
 
iface_desc = &interface->altsetting[0];
 
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
        endpoint = &iface_desc->endpoint[i].desc;
 
        if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) &&
            ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
                dev->interrupt_in_endpoint = endpoint;
        }
         
        if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) &&
            ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
                dev->interrupt_out_endpoint = endpoint;
        }
}       
 
if(dev->interrupt_in_endpoint == NULL) {
        err("interrupt in endpoint not found");
        goto error;
}
if (dev->interrupt_out_endpoint == NULL) {
        err("interrupt out endpoint not found");
        goto error; 
}
 
dev->read_buffer = kmalloc (read_buffer_size, GFP_KERNEL);
if (!dev->read_buffer) {
        err("Couldn't allocate read_buffer");
        goto error;
}
dev->interrupt_in_buffer = kmalloc (dev->interrupt_in_endpoint->wMaxPacketSize, GFP_KERNEL);
if (!dev->interrupt_in_buffer) {
        err("Couldn't allocate interrupt_in_buffer");
        goto error;
}
dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!dev->interrupt_in_urb) {
        err("Couldn't allocate interrupt_in_urb");
        goto error;   
}
dev->interrupt_out_buffer = kmalloc (write_buffer_size, GFP_KERNEL);
if (!dev->interrupt_out_buffer) {
        err("Couldn't allocate interrupt_out_buffer");
        goto error;
}
dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!dev->interrupt_out_urb) {
        err("Couldn't allocate interrupt_out_urb");
        goto error;
}               
dev->interrupt_in_interval = interrupt_in_interval ? interrupt_in_interval : dev->interrupt_in_endpoint->bInterval;
dev->interrupt_out_interval = interrupt_out_interval ? interrupt_out_interval : dev->interrupt_out_endpoint->bInterval;
 
usb_set_intfdata (interface, dev);
 
retval = usb_register_dev (interface, &labjack_class);
 
if (retval) {
        err ("Not able to get a minor for this device.");
        usb_set_intfdata (interface, NULL);
        goto error;
}

linux-labjack/liblabjack/ljackul.c  view on Meta::CPAN

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// ReadLabJack
// CloseAll
//
// The LabJack U12 is an HID V1.1 device.  Input and Output reports
// are both 8 bytes (although Windows throws on an extra byte
// at the beginning).  Feature reports are used to transfer stream
// and burst data from the LabJack to the PC, and are 16*8 or 128
// bytes (plus the extra Windows byte at the beginning).
//
// The first time after enumeration that the LabJack is supposed to
// write 8 bytes to the interrupt IN endpoint, the write does not
// happen.  Windows reads nothing. This initial non-response provides
// a good test of the thread timeout we use in our Windows HID
// read function.  You will probably see this behavior on other
// operating systems.
//
//----------------------------------------------------------------------
//
// Changes
//
// (08/18/2005) Fixed problem in OpenLabJack when *idnum is 0.  Updated



( run in 0.286 second using v1.01-cache-2.11-cpan-e5176c747c2 )