/** * 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 i = 0; int err = 0; int retval = 0; struct ioctl_struct ctrl; unsigned char *uBuf; int numbytes = 0; 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))) info("copy_from_user failed\n"); 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)); } return devRB; case PIUSB_SETVNDCMD: if (copy_from_user (&ctrl, (void __user *)arg, sizeof(struct ioctl_struct))) info("copy_from_user failed\n"); // 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; break; case PIUSB_ISHIGHSPEED: return ((pdx->udev->speed == USB_SPEED_HIGH) ? 1 : 0); break; case PIUSB_WRITEPIPE: if (copy_from_user(&ctrl, (void __user *)arg, _IOC_SIZE(cmd))) info("copy_from_user WRITE_DUMMY failed\n"); 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; break; case PIUSB_USERBUFFER: if (copy_from_user (&ctrl, (void __user *)arg, sizeof(struct ioctl_struct))) info("copy_from_user failed\n"); return MapUserBuffer((struct ioctl_struct *) & ctrl, pdx); break; case PIUSB_UNMAP_USERBUFFER: UnMapUserBuffer(pdx); return 0; break; case PIUSB_READPIPE: if (copy_from_user (&ctrl, (void __user *)arg, sizeof(struct ioctl_struct))) info("copy_from_user failed\n"); switch (ctrl.endpoint) { case 0: //ST133 Pixel Data or PIXIS IO if (pdx->iama == PIXIS_PID) { unsigned int numToRead = 0; unsigned int totalRead = 0; uBuf = kmalloc(ctrl.numbytes, GFP_KERNEL); if (!uBuf) { dbg("Alloc for uBuf failed"); return 0; } numbytes = ctrl.numbytes; numToRead = 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"); do { i = usb_bulk_msg(pdx->udev, pdx->hEP[ctrl.endpoint], (uBuf + totalRead), (numToRead > 64) ? 64 : numToRead, &numbytes, HZ * 10); //EP0 can only handle 64 bytes at a time 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; } else { 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 ((struct ioctl_struct *) arg, &ctrl, sizeof(struct ioctl_struct))) dbg("copy_to_user failed in IORB"); kfree(uBuf); return ctrl.numbytes; } else //ST133 Pixel Data { if (!pdx->gotPixelData) return 0; else { 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(pdx->sgl[pdx->active_frame][i].page_link); pdx->active_frame = ((pdx->active_frame + 1) % pdx->num_frames); return ctrl.numbytes; } } break; case 1: //ST133IO case 4: //PIXIS IO uBuf = kmalloc(ctrl.numbytes, GFP_KERNEL); if (!uBuf) { dbg("Alloc for uBuf failed"); return 0; } numbytes = ctrl.numbytes; // dbg( "numbytes to read = %d", numbytes ); if (copy_from_user(uBuf, ctrl.pData, numbytes)) dbg("copying ctrl.pData to dummyBuf failed"); i = usb_bulk_msg(pdx->udev, pdx->hEP[ctrl.endpoint], uBuf, numbytes, &numbytes, HZ * 10); if (i) { dbg("Blocking ReadI/O Failed with status %d", i); kfree(uBuf); return -1; } else { ctrl.numbytes = numbytes; memcpy(ctrl.pData, uBuf, numbytes); if (copy_to_user ((struct ioctl_struct *) arg, &ctrl, sizeof(struct ioctl_struct))) dbg("copy_to_user failed in IORB"); kfree(uBuf); return ctrl.numbytes; } break; case 2: //PIXIS Ping case 3: //PIXIS Pong if (!pdx->gotPixelData) return 0; else { 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(pdx->sgl[pdx->active_frame][i].page_link); pdx->active_frame = ((pdx->active_frame + 1) % pdx->num_frames); return ctrl.numbytes; } break; } 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))) info("copy_from_user failed\n"); 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; }
/** * 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; }