static int ss801u_flush(struct file *file, fl_owner_t id) { usb_ss801u *dev; int res; printk(KERN_INFO "Patrick-> ss801u_flush start\n"); dev = (usb_ss801u *)file->private_data; if (dev == NULL) return -ENODEV; /* wait for io to stop */ mutex_lock(&dev->io_mutex); /* ss801u_draw_down(dev); */ /* read out errors, leave subsequent opens a clean slate */ spin_lock_irq(&dev->err_lock); res = dev->errors ? (dev->errors == -EPIPE ? -EPIPE : -EIO) : 0; dev->errors = 0; spin_unlock_irq(&dev->err_lock); mutex_unlock(&dev->io_mutex); EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "=flush= res %d", res); printk(KERN_INFO "Patrick-> ss801u_flush finish\n"); return res; }
static int ss801u_release(struct inode *inode, struct file *file) { usb_ss801u *dev; printk(KERN_INFO "Patrick-> ss801u_release start\n"); dev = (usb_ss801u *)file->private_data; if (dev == NULL) return -ENODEV; /* allow the device to be autosuspended */ mutex_lock(&dev->io_mutex); /* usb_autopm_put_interface(dev->interface); */ if (!--dev->open_count && dev->interface) { /* usb_autopm_disable(dev->interface); */ /* usb_autopm_put_interface(dev->interface); */ ss801u_fasync(-1, file, 0); } mutex_unlock(&dev->io_mutex); /* decrement the count on our device */ kref_put(&dev->kref, ss801u_delete); EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "=RELEEASE=\r\n"); printk(KERN_INFO "Patrick-> ss801u_release finish\n"); return 0; }
static int ss801u_fasync(int fd, struct file *filp, int mode) { usb_ss801u *dev = (usb_ss801u *)filp->private_data; int iret = 0; printk(KERN_INFO "Patrick-> ss801u_fasync start\n"); /* sprintf(g_dbgbuf, "=fasync=\r\n"); */ /* ----- release async signal pipe */ if (-1 == fd && 0 == mode) { EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "\r\n=FASYNC= relase \r\n"); iret = fasync_helper(fd, filp, mode, &dev->async_suspend); iret = fasync_helper(fd, filp, mode, &dev->async_resume); iret = fasync_helper(fd, filp, mode, &dev->async_disconnect); dev->async_suspend = dev->async_resume = dev->async_disconnect = NULL; } else if (0 != mode) { /* ----- create async signal pipe */ EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "\r\n=FASYNC= type ? %d \r\n", dev->sig_type); switch (dev->sig_type) { case SIG_SUSPEND: if (!dev->async_suspend) { iret = fasync_helper(fd, filp, mode, &dev->async_suspend); dev->sig_type = SIG_UNKNOW; } break; case SIG_RESUME: if (!dev->async_resume) { iret = fasync_helper(fd, filp, mode, &dev->async_resume); dev->sig_type = SIG_UNKNOW; } break; case SIG_DISCONNECT: if (!dev->async_disconnect) { iret = fasync_helper(fd, filp, mode, &dev->async_disconnect); dev->sig_type = SIG_UNKNOW; } break; case SIG_UNKNOW: default: EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "=FASYNC= type unknow \r\n"); break; } } printk(KERN_INFO "Patrick-> ss801u_fasync finish\n"); return iret; }
int Egis_Reset_device(usb_ss801u *dev) { int lock, ret; EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "\r\n=RESET_DEVICE=\r\n"); lock = usb_lock_device_for_reset(dev->udev, dev->interface); if (lock < 0) { EgisMsg(dev->bPrintDbgMsg, KERN_ERR, "=RESET_DEVICE= locking device failed: %d\r\n", lock); return lock; } ret = usb_reset_device(dev->udev); if (ret < 0) EgisMsg(dev->bPrintDbgMsg, KERN_ERR, "=RESET_DEVICE= reset device failed: %d\r\n", ret); if (lock) usb_unlock_device(dev->udev); EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "\r\n=RESET_DEVICE= Finish\r\n"); return ret; }
static ssize_t ss801u_read(struct file *file, char *buffer, size_t count, loff_t *ppos) { usb_ss801u *dev; int retval = 0; int bytes_read; char *kbuf; printk(KERN_INFO "Patrick-> ss801u_read start\n"); dev = (usb_ss801u *)file->private_data; mutex_lock(&dev->io_mutex); /*----- To NOT go to suspend ----- */ usb_autopm_get_interface(dev->interface); if (!dev->interface) { /* disconnect() was called */ retval = -ENODEV; goto exit; } /* --------------- CASE1 : only return driver version ----------------------- */ /* -------------------------------------------------------------------------- */ if (dev->bReadTwice) { dev->bReadTwice = false; goto exit; } kbuf = kzalloc(count, GFP_KERNEL); if (!kbuf) goto exit; sprintf(kbuf, "%s v%s\r\n", NAME_EGISDRIVER, dev->version.vstring); bytes_read = strlen(kbuf); if (copy_to_user(buffer, kbuf, bytes_read)) { retval = 0; } else { retval = count; ppos += bytes_read; dev->bReadTwice = true; } kfree(kbuf); /*/ //----------------------- CASE2 : bulk read --------------------------------// //----------------------- ---------------------------------------------------// //----- do a blocking bulk read to get data from the device -----/ retval = usb_bulk_msg( dev->udev, usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr), dev->bulk_in_buffer, min(dev->bulk_in_size, count), &bytes_read, 10000 ); //----- if the read was successful, copy the data to userspace -----// if (!retval) { if (copy_to_user(buffer, dev->bulk_in_buffer , bytes_read)) retval = -EFAULT; else retval = bytes_read; } else { Egis_Reset_device(dev); EgisMsg(dev->bPrintDbgMsg, KERN_ERR, "=READ= fail %d\r\n", retval); } //*/ exit: /* ----- Auto suspend ----- */ usb_autopm_put_interface(dev->interface); mutex_unlock(&dev->io_mutex); EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "READ bytes %d\r\n", retval); printk(KERN_INFO "Patrick-> ss801u_read finish\n"); return retval; }
static int ss801u_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { usb_ss801u *dev; int argerr = 0; int retval = 0; u32 tmp; unsigned n_ioc = 0; struct spi_ioc_transfer *ioc = NULL; printk(KERN_INFO "Patrick-> ss801u_ioctl start\n"); dev = (usb_ss801u *)file->private_data; pr_debug("ioctl Start!!\n"); /* ================================ Check input cmd and arg ======================================== */ /* ================================================================================================= */ /* ---- Check control code ---- */ if (EGIS_IOCTL_MAXNR <= _IOC_NR(cmd)) return -ENOTTY; /* ================================== Switch control code ========================================== */ /* ================================================================================================= */ mutex_lock(&dev->io_mutex); if (!dev->interface) { /* disconnect() was called */ retval = -ENODEV; goto exit; } /* ----- Avoid suspend ----- */ usb_autopm_get_interface(dev->interface); /* ---- Check argument buffer ---- */ if (_IOC_READ & _IOC_DIR(cmd)) { /* access_ok : 1 means success */ /* VERIFY_WRITE : A buffer that SDK reads means drivers should write it. */ argerr = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)); } if (_IOC_WRITE & _IOC_DIR(cmd)) argerr = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)); if (argerr) return -EINVAL; if (SPI_IOC_MAGIC == _IOC_TYPE(cmd)) { tmp = _IOC_SIZE(cmd); if ((tmp % sizeof(struct spi_ioc_transfer)) != 0) { retval = -EINVAL; goto done; } n_ioc = tmp / sizeof(struct spi_ioc_transfer); pr_debug("%s->%s: Got %d spi_ioc_transfer Packages\n", __FILE__, __func__, n_ioc); if (n_ioc == 0) goto done; /* copy into scratch area */ ioc = kmalloc(tmp, GFP_KERNEL); if (!ioc) { retval = -ENOMEM; goto done; } if (__copy_from_user(ioc, (void __user *)arg, tmp)) { kfree(ioc); retval = -EFAULT; goto done; } switch (ioc->opcode) { case JADE_REGISTER_MASSREAD: printk(KERN_INFO "Patrick-> JADE_REGISTER_MASSREAD start\n"); if (ioc->rx_buf) { if (!access_ok(VERIFY_WRITE, (u8 __user *) (uintptr_t) ioc->rx_buf, ioc->len)) { pr_debug("!access_ok on JADE_REGISTER_MASSREAD!!"); retval = -EACCES; goto done; } } retval = ES603_IO_Bulk_Read(dev, ioc, n_ioc); printk(KERN_INFO "Patrick-> JADE_REGISTER_MASSREAD finish\n"); break; case JADE_REGISTER_MASSWRITE: printk(KERN_INFO "Patrick-> JADE_REGISTER_MASSWRITE start\n"); retval = ES603_IO_Bulk_Write(dev, ioc, n_ioc); printk(KERN_INFO "Patrick-> JADE_REGISTER_MASSWRITE finish\n"); break; case JADE_GET_ONE_IMG: printk(KERN_INFO "Patrick-> JADE_GET_ONE_IMG start\n"); retval = es603_io_bulk_get_image(dev, ioc, n_ioc); printk(KERN_INFO "Patrick-> JADE_GET_ONE_IMG finish\n"); break; case JADE_GET_FULL_IMAGE2: printk(KERN_INFO "Patrick-> JADE_GET_FULL_IMAGE2 start\n"); retval = es603_io_bulk_get_full_image(dev, ioc, n_ioc); printk(KERN_INFO "Patrick-> JADE_GET_FULL_IMAGE2 finish\n"); break; default: retval = -EFAULT; } done: kfree(ioc); } else if (EGIS_IOCTL_MAGIC == _IOC_TYPE(cmd)) { switch (cmd) { /* -------------------- ss801u SCSI CMD XFER ---------------------- */ /* ---------------------------------------------------------------- */ case EGIS_IOCTL_SCSI_READ: { retval = Egis_IO_SCSI_Read(dev, arg); break; } case EGIS_IOCTL_SCSI_WRITE: { retval = Egis_IO_SCSI_Write(dev, arg); break; } case EGIS_IOCTL_SET_NORMALMODE_REG: { EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "=ioctl=EGIS_IOCTL_SET_NORMALMODE_REG "); if (copy_from_user((void *)&dev->normalCBW, (void *)arg, CBW_SIZE)) { EgisMsg(dev->bPrintDbgMsg, KERN_ERR, "=ioctl=EGIS_IOCTL_SET_NORMALMODE_REG copy from user fail\r\n"); retval = -EFAULT; break; } break; } case EGIS_IOCTL_SET_CONTACTMODE_REG: { EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "=ioctl=EGIS_IOCTL_SET_CONTACTMODE_REG "); if (copy_from_user(&dev->contactCBW, (void *)arg, CBW_SIZE)) { EgisMsg(dev->bPrintDbgMsg, KERN_ERR, "=ioctl=EGIS_IOCTL_SET_CONTACTMODE_REG copy from user fail\r\n"); retval = -EFAULT; break; } break; } /* -------------------- JADE USB BASIC XFER ----------------------- */ /* ---------------------------------------------------------------- */ case EGIS_IOCTL_BULK_READ: { retval = Egis_IO_Bulk_Read(dev, arg); break; } case EGIS_IOCTL_BULK_WRITE: { retval = Egis_IO_Bulk_Write(dev, arg); break; } case EGIS_IOCTL_CTRLXFER_READ: { retval = Egis_IO_CtrlXfer(dev, arg, Ctrl_IN); break; } case EGIS_IOCTL_CTRLXFER_WRITE: { retval = Egis_IO_CtrlXfer(dev, arg, Ctrl_OUT); break; } /*---------------------- Helper function ------------------------- */ /*---------------------------------------------------------------- */ case EGIS_IOCTL_ENTER_SUSPEND: dev->udev->autosuspend_delay = 0; break; case EGIS_IOCTL_RESET_DEVICE: retval = Egis_IO_Reset_Device(dev); break; case EGIS_IOCTL_CREATE_SIGNAL: dev->sig_type = arg; break; /* -------------------- Alternative Setting ----------------------- */ /* ---------------------------------------------------------------- */ case EGIS_IOCTL_SET_AUTOSUSPEND_TIME: dev->idle_delay_time = arg; dev->udev->autosuspend_delay = dev->idle_delay_time*HZ; EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "=ioctl= idle-delay time %d \r\n", dev->idle_delay_time); break; /* ------------------------- Information -------------------------- */ /* ---------------------------------------------------------------- */ case EGIS_IOCTL_GET_VERSION: EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "=ioctl= EGIS_IOCTL_GET_VERSION %s\r\n", dev->version.vstring); if (copy_to_user((void *)arg, &dev->version, sizeof(FPDriver_Version))) { EgisMsg(dev->bPrintDbgMsg, KERN_ERR, "=ioctl= EGIS_IOCTL_GET_VERSION copy to user fail\r\n"); retval = -EFAULT; break; } break; /* ------------------------ Debug usage --------------------------- */ /* ---------------------------------------------------------------- */ case EGIS_IOCTL_ENABLE_DBG_MSG: dev->bPrintDbgMsg = arg; break; /* ------------------------ FOR TEST ------------------------------ */ /* ---------------------------------------------------------------- */ case EGIS_IOCTL_TS_SIGNAL: if (dev->async_resume) { EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "=ioctl= kill_fasync resume!!\r\n"); kill_fasync(&dev->async_resume, SIGIO, POLL_IN); } if (dev->async_suspend) { EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "=ioctl= kill_fasync suspend !!\r\n"); kill_fasync(&dev->async_suspend, SIGIO, POLL_IN); } break; case EGIS_IOCTL_TS_SWITCH_AUTOSUSPEND: arg ? usb_enable_autosuspend(dev->udev):usb_disable_autosuspend(dev->udev); break; case EGIS_IOCTL_TS_SWITCH_RMWAKEUP: dev->udev->do_remote_wakeup = arg; EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "=ioctl= do_remote_wakeup %d \r\n", dev->udev->do_remote_wakeup); break; default : retval = -ENOTTY; break; } } else { retval = -ENOTTY; } exit: /* ----- Auto suspend ----- */ usb_autopm_put_interface(dev->interface); mutex_unlock(&dev->io_mutex); printk(KERN_INFO "Patrick-> ss801u_ioctl finish\n"); return retval; }
int Egis_BulkXfer( usb_ss801u *dev, trans_dir dir, void* Data, int DataSize, int* pActualSize, int Timeout ) { int retval = -1; int iActualRWSize; bool bRestore=false; //Wayne for test // dev->bPrintDbgMsg = true; // pr_debug("%s:%d bulk In endpoint = %d Out endpoint = %d\n", __FUNCTION__, __LINE__, dev->bulk_in_endpointAddr, dev->bulk_out_endpointAddr); if (!dev->udev) { pr_debug("dev->udev = NULL\n"); } else { pr_debug("dev->udev->state = %d dev->udev->speed = %d\n", dev->udev->state, dev->udev->speed); } // for (i = 0; i < DataSize; i++) // { // pr_debug("%2x ", (u8)Data[i]); // } // pr_debug("\n"); mutex_lock(&dev->Bulk_Mutex); //----- if EPROTO happens, we will call clear feature and re-send again do{ EgisMsg(dev->bPrintDbgMsg, KERN_ERR,"Do usb_bulk_msg\n"); retval = usb_bulk_msg( dev->udev, (dir_in == dir) ? usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr) : usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), Data, DataSize, &iActualRWSize, Timeout ); // show data // EgisMsg(dev->bPrintDbgMsg, KERN_ERR,"following are data block of bulk transfer:\r\n"); // int iLoopIndex = 0; // unsigned char *pData = Data; // for(iLoopIndex = 0; iLoopIndex<DataSize; iLoopIndex++) // { // EgisMsg(dev->bPrintDbgMsg, KERN_ERR,"%2x", pData[iLoopIndex]); // } // EgisMsg(dev->bPrintDbgMsg, KERN_ERR,"\r\ndata block finish\r\n"); if(EGIS_FAIL(retval)){ //----- if error == EPROTO && not be restored --> clear halt if(EOVERFLOW == retval) { EgisMsg(dev->bPrintDbgMsg, KERN_ERR,"=Egis_BulkXfer= bulk transfer error, EOVERFLOW, data size = %d" , DataSize); } if(EPROTO == retval && !bRestore){ EgisMsg(dev->bPrintDbgMsg, KERN_ERR, "=Egis_BulkXfer= bulk xfer fail clear feature\r\n"); retval = usb_clear_halt(dev->udev, (dir_in == dir) ? usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr) : usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr) ); bRestore = true; } //----- this if include "else" above and check clear halt fail if(EGIS_FAIL(retval)){ EgisMsg(dev->bPrintDbgMsg, KERN_ERR, "=Egis_BulkXfer= bulk xfer fail %d\r\n", retval); break; } } else{ //----- if xfer is success, set bRestore=false to leave while loop bRestore = false; } }while(EGIS_SUCCESS(retval) && bRestore); memcpy(pActualSize, &iActualRWSize, sizeof(int)); EgisMsg(dev->bPrintDbgMsg, KERN_ERR, "=Egis_BulkXfer= bulk xfer actual data size: %d\r\n", iActualRWSize); mutex_unlock(&dev->Bulk_Mutex); //----- If xfer fails, reset device. if(EGIS_FAIL(retval)){ Egis_Reset_device(dev); } //Wayne for test dev->bPrintDbgMsg = false; return retval; }
int Egis_SndSCSICmd(usb_ss801u *dev, // device infomation PCBW_Form CBW, // CBW char* data, size_t datasize, trans_dir dir, // data infomation unsigned char* CSW, // CSW unsigned long timeout ) { int retval=0; int bytes_read; unsigned char tmpCSW[CSW_SIZE]; EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "=Egis_sndSCSIcmd= Start\r\n"); mutex_lock(&dev->SCSI_mutex); //================================== CBW =========================================// //================================================================================// EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "=Egis_sndSCSIcmd= send CBW using bulk transfer\r\n"); retval = Egis_BulkXfer( dev, dir_out, CBW, CBW_SIZE, &bytes_read, timeout ); if(EGIS_FAIL(retval)){ EgisMsg(dev->bPrintDbgMsg, KERN_ERR, "=Egis_sndSCSIcmd= snd CBW fail %d\r\n", retval); goto SCSI_EXIT; } //================================== DATA ========================================// //================================================================================// EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "=Egis_sndSCSIcmd= send or get data block using bulk transfer, data size is:%u\r\n", datasize); if(0 < datasize){ retval = Egis_BulkXfer( dev, dir, data, datasize, &bytes_read, timeout ); /*EgisMsg(dev->bPrintDbgMsg, KERN_ERR,"following are data block:\r\n"); int iLoopIndex = 0; for(iLoopIndex = 0; iLoopIndex<datasize; iLoopIndex++) { EgisMsg(dev->bPrintDbgMsg, KERN_ERR,"%d", data[iLoopIndex]); } EgisMsg(dev->bPrintDbgMsg, KERN_ERR,"\r\ndata block finish\r\n");*/ if(EGIS_FAIL(retval)){ EgisMsg(dev->bPrintDbgMsg, KERN_ERR, "=Egis_sndSCSIcmd= data xfer fail %d\r\n", retval); goto SCSI_EXIT; } } else { EgisMsg(dev->bPrintDbgMsg, KERN_ERR,"=Egis_sndSCSIcmd= data size <= 0\r\n"); } //================================== CSW =========================================// //================================================================================// EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "=Egis_sndSCSIcmd= read CSW using bulk transfer\r\n"); retval = Egis_BulkXfer( dev, dir_in, tmpCSW, CSW_SIZE, &bytes_read, timeout ); if(EGIS_FAIL(retval)){ EgisMsg(dev->bPrintDbgMsg, KERN_ERR, "=Egis_sndSCSIcmd= rcv CSW fail %d\r\n", retval); goto SCSI_EXIT; } else{ if(CSW){ memcpy(CSW, tmpCSW, CSW_SIZE); } } SCSI_EXIT: mutex_unlock(&dev->SCSI_mutex); EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "=Egis_sndSCSIcmd= END\r\n"); return retval; }