Device-LabJack

 view release on metacpan or  search on metacpan

linux-labjack/INSTALL  view on Meta::CPAN

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

	% 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

	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


	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

        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

				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

                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

	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

	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

        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

                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

    
	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

	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

        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

// 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 1.465 second using v1.01-cache-2.11-cpan-e5176c747c2 )