diff options
Diffstat (limited to 'drivers/staging/rspiusb/rspiusb.c')
-rw-r--r-- | drivers/staging/rspiusb/rspiusb.c | 929 |
1 files changed, 0 insertions, 929 deletions
diff --git a/drivers/staging/rspiusb/rspiusb.c b/drivers/staging/rspiusb/rspiusb.c deleted file mode 100644 index 0495fbf..0000000 --- a/drivers/staging/rspiusb/rspiusb.c +++ /dev/null @@ -1,929 +0,0 @@ -/* - * rspiusb.c - * - * Copyright (C) 2005, 2006 Princeton Instruments - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/vmalloc.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/smp_lock.h> -#include <linux/completion.h> -#include <linux/scatterlist.h> -#include <linux/usb.h> -#include <linux/mm.h> -#include <linux/pagemap.h> -#include <linux/ioctl.h> -#include "rspiusb.h" - -#ifdef CONFIG_USB_DEBUG -static int debug = 1; -#else -static int debug; -#endif -/* Use our own dbg macro */ -#undef dbg -#define dbg(format, arg...) \ - do { \ - if (debug) \ - printk(KERN_DEBUG __FILE__ ": " format "\n" , ##arg); \ - } while (0) - -/* Version Information */ -#define DRIVER_VERSION "V1.0.1" -#define DRIVER_AUTHOR "Princeton Instruments" -#define DRIVER_DESC "PI USB2.0 Device Driver for Linux" - -/* Define these values to match your devices */ -#define VENDOR_ID 0x0BD7 -#define ST133_PID 0xA010 -#define PIXIS_PID 0xA026 - -/* Get a minor range for your devices from the usb maintainer */ -#ifdef CONFIG_USB_DYNAMIC_MINORS -#define PIUSB_MINOR_BASE 0 -#else -#define PIUSB_MINOR_BASE 192 -#endif - -/* prevent races between open() and disconnect() */ -static DECLARE_MUTEX(disconnect_sem); - -/* Structure to hold all of our device specific stuff */ -struct device_extension { - struct usb_device *udev; /* save off the usb device pointer */ - struct usb_interface *interface; /* the interface for this device */ - unsigned char minor; /* the starting minor number - * for this device - */ - size_t bulk_in_size_returned; - int bulk_in_byte_trk; - struct urb ***PixelUrb; - int frameIdx; - int urbIdx; - unsigned int *maplist_numPagesMapped; - int open; /* if the port is open or not */ - int present; /* if the device is not disconnected */ - int userBufMapped; /* has the user buffer been mapped ? */ - struct scatterlist **sgl; /* scatter-gather list for user buffer */ - unsigned int *sgEntries; - struct kref kref; - int gotPixelData; - int pendingWrite; - char **pendedPixelUrbs; - int iama; /* PIXIS or ST133 */ - int num_frames; /* the number of frames that will fit - * in the user buffer - */ - int active_frame; - unsigned long frameSize; - struct semaphore sem; - unsigned int hEP[8]; /* FX2 specific endpoints */ -}; - -#define to_pi_dev(d) container_of(d, struct device_extension, kref) - -/* Prototypes */ -static int MapUserBuffer(struct ioctl_struct *, struct device_extension *); -static int UnMapUserBuffer(struct device_extension *); -static int piusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg); -static int piusb_output(struct ioctl_struct *, unsigned char *, int, - struct device_extension *); -static struct usb_driver piusb_driver; - -/* table of devices that work with this driver */ -static struct usb_device_id pi_device_table[] = { - {USB_DEVICE(VENDOR_ID, ST133_PID)}, - {USB_DEVICE(VENDOR_ID, PIXIS_PID)}, - {0, } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, pi_device_table); - -static int lastErr; -static int errCnt; - -static void piusb_delete(struct kref *kref) -{ - struct device_extension *pdx = to_pi_dev(kref); - - dev_dbg(&pdx->udev->dev, "%s\n", __func__); - usb_put_dev(pdx->udev); - kfree(pdx); -} - -static int piusb_open(struct inode *inode, struct file *file) -{ - struct device_extension *pdx = NULL; - struct usb_interface *interface; - int subminor; - int retval = 0; - - dbg("Piusb_Open()"); - subminor = iminor(inode); - interface = usb_find_interface(&piusb_driver, subminor); - if (!interface) { - printk(KERN_ERR "%s - error, can't find device for minor %d\n", - __func__, subminor); - retval = -ENODEV; - goto exit_no_device; - } - - pdx = usb_get_intfdata(interface); - if (!pdx) { - retval = -ENODEV; - goto exit_no_device; - } - dbg("Alternate Setting = %d", interface->num_altsetting); - - pdx->bulk_in_size_returned = 0; - pdx->bulk_in_byte_trk = 0; - pdx->PixelUrb = NULL; - pdx->frameIdx = 0; - pdx->urbIdx = 0; - pdx->maplist_numPagesMapped = NULL; - pdx->userBufMapped = 0; - pdx->sgl = NULL; - pdx->sgEntries = NULL; - pdx->gotPixelData = 0; - pdx->pendingWrite = 0; - pdx->pendedPixelUrbs = NULL; - pdx->num_frames = 0; - pdx->active_frame = 0; - pdx->frameSize = 0; - - /* increment our usage count for the device */ - kref_get(&pdx->kref); - - /* save our object in the file's private structure */ - file->private_data = pdx; - -exit_no_device: - return retval; -} - -static int piusb_release(struct inode *inode, struct file *file) -{ - struct device_extension *pdx; - int retval = 0; - - dbg("Piusb_Release()"); - pdx = (struct device_extension *)file->private_data; - if (pdx == NULL) { - dbg("%s - object is NULL", __func__); - retval = -ENODEV; - goto object_null; - } - /* decrement the count on our device */ - kref_put(&pdx->kref, piusb_delete); - -object_null: - return retval; -} - -static int pixis_io(struct ioctl_struct *ctrl, struct device_extension *pdx, - struct ioctl_struct *arg) -{ - unsigned int numToRead = 0; - unsigned int totalRead = 0; - unsigned char *uBuf; - int numbytes; - int i; - - uBuf = kmalloc(ctrl->numbytes, GFP_KERNEL); - if (!uBuf) { - dbg("Alloc for uBuf failed"); - return 0; - } - numbytes = (int) ctrl->numbytes; - numToRead = (unsigned int) ctrl->numbytes; - dbg("numbytes to read = %d", numbytes); - dbg("endpoint # %d", ctrl->endpoint); - - if (copy_from_user(uBuf, ctrl->pData, numbytes)) { - dbg("copying ctrl->pData to dummyBuf failed"); - return -EFAULT; - } - - do { - i = usb_bulk_msg(pdx->udev, pdx->hEP[ctrl->endpoint], - (uBuf + totalRead), - /* EP0 can only handle 64 bytes at a time */ - (numToRead > 64) ? 64 : numToRead, - &numbytes, HZ * 10); - if (i) { - dbg("CMD = %s, Address = 0x%02X", - ((uBuf[3] == 0x02) ? "WRITE" : "READ"), - uBuf[1]); - dbg("Number of bytes Attempted to read = %d", - (int)ctrl->numbytes); - dbg("Blocking ReadI/O Failed with status %d", i); - kfree(uBuf); - return -1; - } - dbg("Pixis EP0 Read %d bytes", numbytes); - totalRead += numbytes; - numToRead -= numbytes; - } while (numToRead); - - memcpy(ctrl->pData, uBuf, totalRead); - dbg("Total Bytes Read from PIXIS EP0 = %d", totalRead); - ctrl->numbytes = totalRead; - - if (copy_to_user(arg, ctrl, sizeof(struct ioctl_struct))) - dbg("copy_to_user failed in IORB"); - - kfree(uBuf); - return ctrl->numbytes; -} - -static int pixel_data(struct ioctl_struct *ctrl, struct device_extension *pdx) -{ - int i; - - if (!pdx->gotPixelData) - return 0; - - pdx->gotPixelData = 0; - ctrl->numbytes = pdx->bulk_in_size_returned; - pdx->bulk_in_size_returned -= pdx->frameSize; - - for (i = 0; i < pdx->maplist_numPagesMapped[pdx->active_frame]; i++) - SetPageDirty(sg_page(&pdx->sgl[pdx->active_frame][i])); - - pdx->active_frame = ((pdx->active_frame + 1) % pdx->num_frames); - - return ctrl->numbytes; -} - -/** - * piusb_ioctl - */ -static int piusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct device_extension *pdx; - char dummyCtlBuf[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - unsigned long devRB = 0; - int err = 0; - int retval = 0; - struct ioctl_struct ctrl; - unsigned short controlData = 0; - - pdx = (struct device_extension *)file->private_data; - /* verify that the device wasn't unplugged */ - if (!pdx->present) { - dbg("No Device Present\n"); - return -ENODEV; - } - /* fill in your device specific stuff here */ - if (_IOC_DIR(cmd) & _IOC_READ) - err = !access_ok(VERIFY_WRITE, (void __user *)arg, - _IOC_SIZE(cmd)); - else if (_IOC_DIR(cmd) & _IOC_WRITE) - err = !access_ok(VERIFY_READ, (void __user *)arg, - _IOC_SIZE(cmd)); - if (err) { - dev_err(&pdx->udev->dev, "return with error = %d\n", err); - return -EFAULT; - } - switch (cmd) { - case PIUSB_GETVNDCMD: - if (__copy_from_user - (&ctrl, (void __user *)arg, sizeof(struct ioctl_struct))) { - dev_err(&pdx->udev->dev, "copy_from_user failed\n"); - return -EFAULT; - } - dbg("%s %x\n", "Get Vendor Command = ", ctrl.cmd); - retval = - usb_control_msg(pdx->udev, usb_rcvctrlpipe(pdx->udev, 0), - ctrl.cmd, USB_DIR_IN, 0, 0, &devRB, - ctrl.numbytes, HZ * 10); - if (ctrl.cmd == 0xF1) { - dbg("FW Version returned from HW = %ld.%ld", - (devRB >> 8), (devRB & 0xFF)); - } - if (retval >= 0) - retval = (int)devRB; - return retval; - - case PIUSB_SETVNDCMD: - if (__copy_from_user - (&ctrl, (void __user *)arg, sizeof(struct ioctl_struct))) { - dev_err(&pdx->udev->dev, "copy_from_user failed\n"); - return -EFAULT; - } - /* dbg( "%s %x", "Set Vendor Command = ",ctrl.cmd ); */ - controlData = ctrl.pData[0]; - controlData |= (ctrl.pData[1] << 8); - /* dbg( "%s %d", "Vendor Data =",controlData ); */ - retval = usb_control_msg(pdx->udev, - usb_sndctrlpipe(pdx->udev, 0), - ctrl.cmd, - (USB_DIR_OUT | USB_TYPE_VENDOR - /* | USB_RECIP_ENDPOINT */), - controlData, 0, - &dummyCtlBuf, ctrl.numbytes, HZ * 10); - return retval; - - case PIUSB_ISHIGHSPEED: - return ((pdx->udev->speed == USB_SPEED_HIGH) ? 1 : 0); - - case PIUSB_WRITEPIPE: - if (__copy_from_user(&ctrl, (void __user *)arg, _IOC_SIZE(cmd))) { - dev_err(&pdx->udev->dev, - "copy_from_user WRITE_DUMMY failed\n"); - return -EFAULT; - } - if (!access_ok(VERIFY_READ, ctrl.pData, ctrl.numbytes)) { - dbg("can't access pData"); - return 0; - } - piusb_output(&ctrl, ctrl.pData /* uBuf */, ctrl.numbytes, pdx); - return ctrl.numbytes; - - case PIUSB_USERBUFFER: - if (__copy_from_user - (&ctrl, (void __user *)arg, sizeof(struct ioctl_struct))) { - dev_err(&pdx->udev->dev, "copy_from_user failed\n"); - return -EFAULT; - } - return MapUserBuffer((struct ioctl_struct *) &ctrl, pdx); - - case PIUSB_UNMAP_USERBUFFER: - retval = UnMapUserBuffer(pdx); - return retval; - - case PIUSB_READPIPE: - if (__copy_from_user(&ctrl, (void __user *)arg, - sizeof(struct ioctl_struct))) { - dev_err(&pdx->udev->dev, "copy_from_user failed\n"); - return -EFAULT; - } - if (((0 == ctrl.endpoint) && (PIXIS_PID == pdx->iama)) || - (1 == ctrl.endpoint) || /* ST133IO */ - (4 == ctrl.endpoint)) /* PIXIS IO */ - return pixis_io(&ctrl, pdx, - (struct ioctl_struct *)arg); - else if ((0 == ctrl.endpoint) || /* ST133 Pixel Data */ - (2 == ctrl.endpoint) || /* PIXIS Ping */ - (3 == ctrl.endpoint)) /* PIXIS Pong */ - return pixel_data(&ctrl, pdx); - - break; - - case PIUSB_WHATCAMERA: - return pdx->iama; - - case PIUSB_SETFRAMESIZE: - dbg("PIUSB_SETFRAMESIZE"); - if (__copy_from_user - (&ctrl, (void __user *)arg, sizeof(struct ioctl_struct))) { - dev_err(&pdx->udev->dev, "copy_from_user failed\n"); - return -EFAULT; - } - pdx->frameSize = ctrl.numbytes; - pdx->num_frames = ctrl.numFrames; - if (!pdx->sgl) - pdx->sgl = - kmalloc(sizeof(struct scatterlist *) * - pdx->num_frames, GFP_KERNEL); - if (!pdx->sgEntries) - pdx->sgEntries = - kmalloc(sizeof(unsigned int) * pdx->num_frames, - GFP_KERNEL); - if (!pdx->PixelUrb) - pdx->PixelUrb = - kmalloc(sizeof(struct urb **) * pdx->num_frames, - GFP_KERNEL); - if (!pdx->maplist_numPagesMapped) - pdx->maplist_numPagesMapped = - vmalloc(sizeof(unsigned int) * pdx->num_frames); - if (!pdx->pendedPixelUrbs) - pdx->pendedPixelUrbs = - kmalloc(sizeof(char *) * pdx->num_frames, - GFP_KERNEL); - return 0; - - default: - dbg("%s\n", "No IOCTL found"); - break; - - } - /* return that we did not understand this ioctl call */ - dbg("Returning -ENOTTY"); - return -ENOTTY; -} - -static void piusb_write_bulk_callback(struct urb *urb) -{ - struct device_extension *pdx = urb->context; - int status = urb->status; - - /* sync/async unlink faults aren't errors */ - if (status && !(status == -ENOENT || status == -ECONNRESET)) - dev_dbg(&urb->dev->dev, - "%s - nonzero write bulk status received: %d", - __func__, status); - - pdx->pendingWrite = 0; - kfree(urb->transfer_buffer); -} - -int piusb_output(struct ioctl_struct *io, unsigned char *uBuf, int len, - struct device_extension *pdx) -{ - struct urb *urb = NULL; - int err = 0; - unsigned char *kbuf = NULL; - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (urb != NULL) { - kbuf = kmalloc(len, GFP_KERNEL); - if (!kbuf) { - dev_err(&pdx->udev->dev, "buffer_alloc failed\n"); - return -ENOMEM; - } - if(__copy_from_user(kbuf, uBuf, len)) { - dev_err(&pdx->udev->dev, "__copy_from_user failed\n"); - return -EFAULT; - } - usb_fill_bulk_urb(urb, pdx->udev, pdx->hEP[io->endpoint], kbuf, - len, piusb_write_bulk_callback, pdx); - err = usb_submit_urb(urb, GFP_KERNEL); - if (err) { - dev_err(&pdx->udev->dev, - "WRITE ERROR:submit urb error = %d\n", err); - } - pdx->pendingWrite = 1; - usb_free_urb(urb); - } - return -EINPROGRESS; -} - -static int UnMapUserBuffer(struct device_extension *pdx) -{ - int i = 0; - int k = 0; - unsigned int epAddr; - - for (k = 0; k < pdx->num_frames; k++) { - dbg("Killing Urbs for Frame %d", k); - for (i = 0; i < pdx->sgEntries[k]; i++) { - usb_kill_urb(pdx->PixelUrb[k][i]); - usb_free_urb(pdx->PixelUrb[k][i]); - pdx->pendedPixelUrbs[k][i] = 0; - } - dbg("Urb error count = %d", errCnt); - errCnt = 0; - dbg("Urbs free'd and Killed for Frame %d", k); - } - - for (k = 0; k < pdx->num_frames; k++) { - if (pdx->iama == PIXIS_PID) - /* which EP should we map this frame to ? */ - /* PONG, odd frames: hEP[3] */ - /* PING, even frames and zero hEP[2] */ - epAddr = (k % 2) ? pdx->hEP[3] : pdx->hEP[2]; - else - /* ST133 only has 1 endpoint for Pixel data transfer */ - epAddr = pdx->hEP[0]; - - usb_buffer_unmap_sg(pdx->udev, epAddr, pdx->sgl[k], - pdx->maplist_numPagesMapped[k]); - for (i = 0; i < pdx->maplist_numPagesMapped[k]; i++) - page_cache_release(sg_page(&pdx->sgl[k][i])); - kfree(pdx->sgl[k]); - kfree(pdx->PixelUrb[k]); - kfree(pdx->pendedPixelUrbs[k]); - pdx->sgl[k] = NULL; - pdx->PixelUrb[k] = NULL; - pdx->pendedPixelUrbs[k] = NULL; - } - - kfree(pdx->sgEntries); - vfree(pdx->maplist_numPagesMapped); - pdx->sgEntries = NULL; - pdx->maplist_numPagesMapped = NULL; - kfree(pdx->sgl); - kfree(pdx->pendedPixelUrbs); - kfree(pdx->PixelUrb); - pdx->sgl = NULL; - pdx->pendedPixelUrbs = NULL; - pdx->PixelUrb = NULL; - - return 0; -} - -static void piusb_readPIXEL_callback(struct urb *urb) -{ - int i = 0; - struct device_extension *pdx = urb->context; - int status = urb->status; - - if (status && !(status == -ENOENT || status == -ECONNRESET)) { - dbg("%s - nonzero read bulk status received: %d", __func__, - status); - dbg("Error in read EP2 callback"); - dbg("FrameIndex = %d", pdx->frameIdx); - dbg("Bytes received before problem occurred = %d", - pdx->bulk_in_byte_trk); - dbg("Urb Idx = %d", pdx->urbIdx); - pdx->pendedPixelUrbs[pdx->frameIdx][pdx->urbIdx] = 0; - } else { - pdx->bulk_in_byte_trk += urb->actual_length; - i = usb_submit_urb(urb, GFP_ATOMIC); /* resubmit the URB */ - if (i) { - errCnt++; - if (i != lastErr) { - dbg("submit urb in callback failed " - "with error code %d", i); - lastErr = i; - } - } else { - pdx->urbIdx++; /* point to next URB when we callback */ - if (pdx->bulk_in_byte_trk >= pdx->frameSize) { - pdx->bulk_in_size_returned = - pdx->bulk_in_byte_trk; - pdx->bulk_in_byte_trk = 0; - pdx->gotPixelData = 1; - pdx->frameIdx = - ((pdx->frameIdx + - 1) % pdx->num_frames); - pdx->urbIdx = 0; - } - } - } -} - -/* MapUserBuffer( - inputs: - struct ioctl_struct *io - structure containing user address, - frame #, and size - struct device_extension *pdx - the PIUSB device extension - - returns: - int - status of the task - - Notes: - MapUserBuffer maps a buffer passed down through an ioctl. - The user buffer is Page Aligned by the app and then passed down. - The function get_free_pages(...) does the actual mapping of the buffer - from user space to kernel space. - From there a scatterlist is created from all the pages. - The next function called is to usb_buffer_map_sg which allocated - DMA addresses for each page, even coalescing them if possible. - The DMA address is placed in the scatterlist structure. - The function returns the number of DMA addresses. - This may or may not be equal to the number of pages that - the user buffer uses. - We then build an URB for each DMA address and then submit them. -*/ - -/* -int MapUserBuffer(unsigned long uaddr, unsigned long numbytes, - unsigned long frameInfo, struct device_extension *pdx) -*/ -static int MapUserBuffer(struct ioctl_struct *io, struct device_extension *pdx) -{ - unsigned long uaddr; - unsigned long numbytes; - int frameInfo; /* which frame we're mapping */ - unsigned int epAddr = 0; - unsigned long count = 0; - int i = 0; - int k = 0; - int err = 0; - int ret; - struct page **maplist_p; - int numPagesRequired; - - frameInfo = io->numFrames; - uaddr = (unsigned long)io->pData; - numbytes = io->numbytes; - - if (pdx->iama == PIXIS_PID) { - /* which EP should we map this frame to ? */ - /* PONG, odd frames: hEP[3] */ - /* PING, even frames and zero hEP[2] */ - epAddr = (frameInfo % 2) ? pdx->hEP[3] : pdx->hEP[2]; - dbg("Pixis Frame #%d: EP=%d", frameInfo, - (epAddr == pdx->hEP[2]) ? 2 : 4); - } else { /* ST133 only has 1 endpoint for Pixel data transfer */ - epAddr = pdx->hEP[0]; - dbg("ST133 Frame #%d: EP=2", frameInfo); - } - count = numbytes; - dbg("UserAddress = 0x%08lX", uaddr); - dbg("numbytes = %d", (int)numbytes); - - /* number of pages to map the entire user space DMA buffer */ - numPagesRequired = - ((uaddr & ~PAGE_MASK) + count + ~PAGE_MASK) >> PAGE_SHIFT; - dbg("Number of pages needed = %d", numPagesRequired); - maplist_p = vmalloc(numPagesRequired * sizeof(struct page *)); - if (!maplist_p) { - dbg("Can't Allocate Memory for maplist_p"); - return -ENOMEM; - } - - /* map the user buffer to kernel memory */ - down_write(¤t->mm->mmap_sem); - pdx->maplist_numPagesMapped[frameInfo] = get_user_pages(current, - current->mm, (uaddr & PAGE_MASK), numPagesRequired, - WRITE, 0 /* Don't Force*/, maplist_p, NULL); - up_write(¤t->mm->mmap_sem); - dbg("Number of pages mapped = %d", - pdx->maplist_numPagesMapped[frameInfo]); - - for (i = 0; i < pdx->maplist_numPagesMapped[frameInfo]; i++) - flush_dcache_page(maplist_p[i]); - if (!pdx->maplist_numPagesMapped[frameInfo]) { - dbg("get_user_pages() failed"); - vfree(maplist_p); - return -ENOMEM; - } - - /* need to create a scatterlist that spans each frame - * that can fit into the mapped buffer - */ - pdx->sgl[frameInfo] = - kmalloc((pdx->maplist_numPagesMapped[frameInfo] * - sizeof(struct scatterlist)), GFP_ATOMIC); - if (!pdx->sgl[frameInfo]) { - vfree(maplist_p); - dbg("can't allocate mem for sgl"); - return -ENOMEM; - } - sg_assign_page(&pdx->sgl[frameInfo][0], maplist_p[0]); - pdx->sgl[frameInfo][0].offset = uaddr & ~PAGE_MASK; - if (pdx->maplist_numPagesMapped[frameInfo] > 1) { - pdx->sgl[frameInfo][0].length = - PAGE_SIZE - pdx->sgl[frameInfo][0].offset; - count -= pdx->sgl[frameInfo][0].length; - for (k = 1; k < pdx->maplist_numPagesMapped[frameInfo]; k++) { - pdx->sgl[frameInfo][k].offset = 0; - sg_assign_page(&pdx->sgl[frameInfo][k], maplist_p[k]); - pdx->sgl[frameInfo][k].length = - (count < PAGE_SIZE) ? count : PAGE_SIZE; - count -= PAGE_SIZE; /* example had PAGE_SIZE here */ - } - } else { - pdx->sgl[frameInfo][0].length = count; - } - ret = usb_buffer_map_sg(pdx->udev, epAddr, pdx->sgl[frameInfo], - pdx->maplist_numPagesMapped[frameInfo]); - if (ret < 0) { - vfree(maplist_p); - dbg("usb_buffer_map_sg() failed"); - return -EINVAL; - } - - pdx->sgEntries[frameInfo] = ret; - - dbg("number of sgEntries = %d", pdx->sgEntries[frameInfo]); - pdx->userBufMapped = 1; - vfree(maplist_p); - - /* Create and Send the URB's for each s/g entry */ - pdx->PixelUrb[frameInfo] = - kmalloc(pdx->sgEntries[frameInfo] * sizeof(struct urb *), - GFP_KERNEL); - if (!pdx->PixelUrb[frameInfo]) { - dbg("Can't Allocate Memory for Urb"); - return -ENOMEM; - } - for (i = 0; i < pdx->sgEntries[frameInfo]; i++) { - /* 0 iso packets because we're using BULK transfers */ - pdx->PixelUrb[frameInfo][i] = usb_alloc_urb(0, GFP_KERNEL); - usb_fill_bulk_urb(pdx->PixelUrb[frameInfo][i], - pdx->udev, - epAddr, - NULL, // non-DMA HC? buy a better hardware - sg_dma_len(&pdx->sgl[frameInfo][i]), - piusb_readPIXEL_callback, (void *)pdx); - pdx->PixelUrb[frameInfo][i]->transfer_dma = - sg_dma_address(&pdx->sgl[frameInfo][i]); - pdx->PixelUrb[frameInfo][i]->transfer_flags = - URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT; - } - /* only interrupt when last URB completes */ - pdx->PixelUrb[frameInfo][--i]->transfer_flags &= ~URB_NO_INTERRUPT; - pdx->pendedPixelUrbs[frameInfo] = - kmalloc((pdx->sgEntries[frameInfo] * sizeof(char)), GFP_KERNEL); - if (!pdx->pendedPixelUrbs[frameInfo]) - dbg("Can't allocate Memory for pendedPixelUrbs"); - for (i = 0; i < pdx->sgEntries[frameInfo]; i++) { - err = usb_submit_urb(pdx->PixelUrb[frameInfo][i], GFP_ATOMIC); - if (err) { - dbg("%s %d\n", "submit urb error =", err); - pdx->pendedPixelUrbs[frameInfo][i] = 0; - return err; - } - pdx->pendedPixelUrbs[frameInfo][i] = 1; - } - return 0; -} - -static const struct file_operations piusb_fops = { - .owner = THIS_MODULE, - .ioctl = piusb_ioctl, - .open = piusb_open, - .release = piusb_release, -}; - -static struct usb_class_driver piusb_class = { - .name = "usb/rspiusb%d", - .fops = &piusb_fops, - .minor_base = PIUSB_MINOR_BASE, -}; - -/** - * piusb_probe - * - * Called by the usb core when a new device is connected that it thinks - * this driver might be interested in. - */ -static int piusb_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct device_extension *pdx = NULL; - struct usb_host_interface *iface_desc; - struct usb_endpoint_descriptor *endpoint; - int i; - int retval = -ENOMEM; - - dev_dbg(&interface->dev, "%s - Looking for PI USB Hardware", __func__); - - pdx = kzalloc(sizeof(struct device_extension), GFP_KERNEL); - if (pdx == NULL) { - dev_err(&interface->dev, "Out of memory\n"); - goto error; - } - kref_init(&pdx->kref); - pdx->udev = usb_get_dev(interface_to_usbdev(interface)); - pdx->interface = interface; - iface_desc = interface->cur_altsetting; - - /* See if the device offered us matches what we can accept */ - if ((pdx->udev->descriptor.idVendor != VENDOR_ID) - || ((pdx->udev->descriptor.idProduct != PIXIS_PID) - && (pdx->udev->descriptor.idProduct != ST133_PID))) - return -ENODEV; - - pdx->iama = pdx->udev->descriptor.idProduct; - - if (debug) { - if (pdx->udev->descriptor.idProduct == PIXIS_PID) - dbg("PIUSB:Pixis Camera Found"); - else - dbg("PIUSB:ST133 USB Controller Found"); - if (pdx->udev->speed == USB_SPEED_HIGH) - dbg("Highspeed(USB2.0) Device Attached"); - else - dbg("Lowspeed (USB1.1) Device Attached"); - - dbg("NumEndpoints in Configuration: %d", - iface_desc->desc.bNumEndpoints); - } - for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { - endpoint = &iface_desc->endpoint[i].desc; - if (debug) { - dbg("Endpoint[%d]->bDescriptorType = %d", i, - endpoint->bDescriptorType); - dbg("Endpoint[%d]->bEndpointAddress = 0x%02X", i, - endpoint->bEndpointAddress); - dbg("Endpoint[%d]->bbmAttributes = %d", i, - endpoint->bmAttributes); - dbg("Endpoint[%d]->MaxPacketSize = %d\n", i, - endpoint->wMaxPacketSize); - } - if (usb_endpoint_xfer_bulk(endpoint)) { - if (usb_endpoint_dir_in(endpoint)) - pdx->hEP[i] = - usb_rcvbulkpipe(pdx->udev, - endpoint->bEndpointAddress); - else - pdx->hEP[i] = - usb_sndbulkpipe(pdx->udev, - endpoint->bEndpointAddress); - } - } - usb_set_intfdata(interface, pdx); - retval = usb_register_dev(interface, &piusb_class); - if (retval) { - err("Not able to get a minor for this device."); - usb_set_intfdata(interface, NULL); - goto error; - } - pdx->present = 1; - - /* we can register the device now, as it is ready */ - pdx->minor = interface->minor; - /* let the user know what node this device is now attached to */ - dbg("PI USB2.0 device now attached to piusb-%d", pdx->minor); - return 0; - -error: - if (pdx) - kref_put(&pdx->kref, piusb_delete); - return retval; -} - -/** - * piusb_disconnect - * - * Called by the usb core when the device is removed from the system. - * - * This routine guarantees that the driver will not submit any more urbs - * by clearing pdx->udev. It is also supposed to terminate any currently - * active urbs. Unfortunately, usb_bulk_msg(), used in piusb_read(), does - * not provide any way to do this. But at least we can cancel an active - * write. - */ -static void piusb_disconnect(struct usb_interface *interface) -{ - struct device_extension *pdx; - int minor = interface->minor; - - lock_kernel(); - - pdx = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - - /* give back our minor */ - usb_deregister_dev(interface, &piusb_class); - - unlock_kernel(); - - /* prevent device read, write and ioctl */ - pdx->present = 0; - kref_put(&pdx->kref, piusb_delete); - dbg("PI USB2.0 device #%d now disconnected\n", minor); -} - -static struct usb_driver piusb_driver = { - .name = "sub", - .probe = piusb_probe, - .disconnect = piusb_disconnect, - .id_table = pi_device_table, -}; - -/** - * piusb_init - */ -static int __init piusb_init(void) -{ - int result; - - lastErr = 0; - errCnt = 0; - - /* register this driver with the USB subsystem */ - result = usb_register(&piusb_driver); - if (result) - printk(KERN_ERR KBUILD_MODNAME - ": usb_register failed. Error number %d\n", - result); - else - printk(KERN_INFO KBUILD_MODNAME ":%s: %s\n", DRIVER_DESC, - DRIVER_VERSION); - return result; -} - -/** - * piusb_exit - */ -static void __exit piusb_exit(void) -{ - /* deregister this driver with the USB subsystem */ - usb_deregister(&piusb_driver); -} - -module_init(piusb_init); -module_exit(piusb_exit); - -/* Module parameters */ -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "Debug enabled or not"); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL v2"); |