예제 #1
0
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;
}
예제 #2
0
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;
}
예제 #3
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;
}
예제 #4
0
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;
}
예제 #5
0
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;
}
예제 #6
0
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;
}
예제 #7
0
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;
}
예제 #8
0
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;
}