Пример #1
0
static int recv_stream(struct kiocb *iocb, struct socket *sock,
		       struct msghdr *m, size_t buf_len, int flags)
{
	struct sock *sk = sock->sk;
	struct tipc_port *tport = tipc_sk_port(sk);
	struct sk_buff *buf;
	struct tipc_msg *msg;
	unsigned int sz;
	int sz_to_copy, target, needed;
	int sz_copied = 0;
	char __user *crs = m->msg_iov->iov_base;
	unsigned char *buf_crs;
	u32 err;
	int res = 0;

	/* Catch invalid receive attempts */

	if (m->msg_iovlen != 1)
		return -EOPNOTSUPP;   /* Don't do multiple iovec entries yet */

	if (unlikely(!buf_len))
		return -EINVAL;

	lock_sock(sk);

	if (unlikely((sock->state == SS_UNCONNECTED) ||
		     (sock->state == SS_CONNECTING))) {
		res = -ENOTCONN;
		goto exit;
	}

	target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len);

restart:

	/* Look for a message in receive queue; wait if necessary */

	while (skb_queue_empty(&sk->sk_receive_queue)) {
		if (sock->state == SS_DISCONNECTING) {
			res = -ENOTCONN;
			goto exit;
		}
		if (flags & MSG_DONTWAIT) {
			res = -EWOULDBLOCK;
			goto exit;
		}
		release_sock(sk);
		res = wait_event_interruptible(*sk_sleep(sk),
			(!skb_queue_empty(&sk->sk_receive_queue) ||
			 (sock->state == SS_DISCONNECTING)));
		lock_sock(sk);
		if (res)
			goto exit;
	}

	/* Look at first message in receive queue */

	buf = skb_peek(&sk->sk_receive_queue);
	msg = buf_msg(buf);
	sz = msg_data_sz(msg);
	err = msg_errcode(msg);

	/* Discard an empty non-errored message & try again */

	if ((!sz) && (!err)) {
		advance_rx_queue(sk);
		goto restart;
	}

	/* Optionally capture sender's address & ancillary data of first msg */

	if (sz_copied == 0) {
		set_orig_addr(m, msg);
		res = anc_data_recv(m, msg, tport);
		if (res)
			goto exit;
	}

	/* Capture message data (if valid) & compute return value (always) */

	if (!err) {
		buf_crs = (unsigned char *)(TIPC_SKB_CB(buf)->handle);
		sz = (unsigned char *)msg + msg_size(msg) - buf_crs;

		needed = (buf_len - sz_copied);
		sz_to_copy = (sz <= needed) ? sz : needed;
		if (unlikely(copy_to_user(crs, buf_crs, sz_to_copy))) {
			res = -EFAULT;
			goto exit;
		}
		sz_copied += sz_to_copy;

		if (sz_to_copy < sz) {
			if (!(flags & MSG_PEEK))
				TIPC_SKB_CB(buf)->handle = buf_crs + sz_to_copy;
			goto exit;
		}

		crs += sz_to_copy;
	} else {
		if (sz_copied != 0)
			goto exit; /* can't add error msg to valid data */

		if ((err == TIPC_CONN_SHUTDOWN) || m->msg_control)
			res = 0;
		else
			res = -ECONNRESET;
	}

	/* Consume received message (optional) */

	if (likely(!(flags & MSG_PEEK))) {
		if (unlikely(++tport->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
			tipc_acknowledge(tport->ref, tport->conn_unacked);
		advance_rx_queue(sk);
	}

	/* Loop around if more data is required */

	if ((sz_copied < buf_len) &&	/* didn't get all requested data */
	    (!skb_queue_empty(&sk->sk_receive_queue) ||
	    (sz_copied < target)) &&	/* and more is ready or required */
	    (!(flags & MSG_PEEK)) &&	/* and aren't just peeking at data */
	    (!err))			/* and haven't reached a FIN */
		goto restart;

exit:
	release_sock(sk);
	return sz_copied ? sz_copied : res;
}
Пример #2
0
static int akmd_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
		      unsigned long arg)
{
	void __user *argp = (void __user *) arg;

	char rwbuf[16];
	char databuf[RBUFF_SIZE];
	int ret = -1;
	int status;
	int value[3];
	short delay;
	short mode;
	struct akm8975_data *akm = file->private_data;
	
	FUNCDBG("called");

	switch (cmd) {
	case ECS_IOCTL_READ:
	case ECS_IOCTL_WRITE:
		if (copy_from_user(&rwbuf, argp, sizeof(rwbuf)))
			return -EFAULT;
		break;
	case ECS_IOCTL_SET_MODE:
		if (copy_from_user(&mode, argp, sizeof(mode)))
			return -EFAULT;
		break;
	case ECS_IOCTL_SET_YPR:
		if (copy_from_user(&value, argp, sizeof(value)))
			return -EFAULT;
		break;

	default:
		break;
	}

	switch (cmd) {
	case ECS_IOCTL_READ:
		if ((rwbuf[0] > AK8975_FUSE_ASAZ) || (rwbuf[1] < 1) ||
			(rwbuf[1] > 3)) {
			pr_err("AKM8975 IOCTL_READ invalid argument: %d, %d\n", 
				(int)rwbuf[0], (int)rwbuf[1]);
			return -EINVAL;
		}

		ret = akm8975_i2c_rxdata(akm, rwbuf[0], rwbuf[1], &rwbuf[2]);
		if (ret < 0)
			return ret;
		break;

	case ECS_IOCTL_WRITE:
		if (rwbuf[0] < 2)
			return -EINVAL;

		ret = akm8975_i2c_txdata(akm, rwbuf[0], rwbuf[1]);
		if (ret < 0)
			return ret;
		break;

	case ECS_IOCTL_SET_MODE:
		ret = akm8975_ecs_set_mode(akm, (char) mode);
		if (ret < 0)
			return ret;

		if (mode == AK8975_MODE_SNG_MEASURE) {
			/* wait for data to become ready */
			ret = wait_for_completion_interruptible_timeout(&akm->data_ready, 
						msecs_to_jiffies(AK8975_MAX_CONVERSION_TIMEOUT));
			if (ret < 0) {
				pr_err("AKM8975 conversion timeout happened\n");
				return -EINVAL;
			}
		}
		break;

	case ECS_IOCTL_GETDATA:
		ret = akm8975_ecs_get_data(akm, RBUFF_SIZE, databuf);
		if (ret < 0)
			return ret;

	case ECS_IOCTL_SET_YPR:
		akm8975_ecs_report_value(akm, value);
		break;

	case ECS_IOCTL_GET_OPEN_STATUS:
		wait_event_interruptible(open_wq,
					 (atomic_read(&open_flag) != 0));
		status = atomic_read(&open_flag);
		break;
	case ECS_IOCTL_GET_CLOSE_STATUS:
		wait_event_interruptible(open_wq,
					 (atomic_read(&open_flag) == 0));
		status = atomic_read(&open_flag);
		break;

	case ECS_IOCTL_GET_DELAY:
		delay = akmd_delay;
		break;

	default:
		FUNCDBG("Unknown cmd\n");
		return -ENOTTY;
	}

	switch (cmd) {
	case ECS_IOCTL_READ:
		if (copy_to_user(argp, &rwbuf[2], rwbuf[1]))
			return -EFAULT;
		break;
	case ECS_IOCTL_GETDATA:
		if (copy_to_user(argp, &databuf, RBUFF_SIZE))
			return -EFAULT;
		break;
	case ECS_IOCTL_GET_OPEN_STATUS:
	case ECS_IOCTL_GET_CLOSE_STATUS:
		if (copy_to_user(argp, &status, sizeof(status)))
			return -EFAULT;
		break;
	case ECS_IOCTL_GET_DELAY:
		if (copy_to_user(argp, &delay, sizeof(delay)))
			return -EFAULT;
		break;
	default:
		break;
	}

	return 0;
}
Пример #3
0
static ssize_t pn544_dev_read(struct file *filp, char __user *buf,
		size_t count, loff_t *offset)
{
	struct pn544_dev *pn544_dev = filp->private_data;
	char tmp[MAX_BUFFER_SIZE];
	int ret;

	if (count > MAX_BUFFER_SIZE)
		count = MAX_BUFFER_SIZE;

	pr_debug("%s : reading %zu bytes.\n", __func__, count);
#ifdef FEATURE_PN544_KERNEL_LOG
    pr_info("==> %s #1 (ven, firm, irq)=(%d, %d, %d)\n", __func__, gpio_get_value(pn544_dev->ven_gpio), gpio_get_value(pn544_dev->firm_gpio), gpio_get_value(pn544_dev->irq_gpio));
#endif

	mutex_lock(&pn544_dev->read_mutex);

	if (!gpio_get_value(pn544_dev->irq_gpio)) {
		if (filp->f_flags & O_NONBLOCK) {
			ret = -EAGAIN;
			goto fail;
		}

		pn544_dev->irq_enabled = true;

#ifdef READ_IRQ_MODIFY
		do_reading=0;
#endif

		enable_irq(pn544_dev->client->irq);
#ifdef READ_IRQ_MODIFY
		ret = wait_event_interruptible(pn544_dev->read_wq, do_reading);
#else
		ret = wait_event_interruptible(pn544_dev->read_wq,
				gpio_get_value(pn544_dev->irq_gpio));
#endif
		pn544_disable_irq(pn544_dev);

#ifdef READ_IRQ_MODIFY
		if(cancle_read == true)
		{
		    cancle_read = false;
		    ret = -1;
		    goto fail;
		}
#endif
		if (ret)
			goto fail;

	}

#ifdef FEATURE_PN544_KERNEL_LOG
    pr_info("==> %s #2 (ven, firm, irq)=(%d, %d, %d)\n", __func__, gpio_get_value(pn544_dev->ven_gpio), gpio_get_value(pn544_dev->firm_gpio), gpio_get_value(pn544_dev->irq_gpio));
#endif
	/* Read data */
	ret = i2c_master_recv(pn544_dev->client, tmp, count);
	mutex_unlock(&pn544_dev->read_mutex);

	if (ret < 0) {
		pr_err("%s: i2c_master_recv returned %d\n", __func__, ret);
		return ret;
	}
	if (ret > count) {
		pr_err("%s: received too many bytes from i2c (%d)\n",
			__func__, ret);
		return -EIO;
	}
	if (copy_to_user(buf, tmp, ret)) {
		pr_warning("%s : failed to copy to user space\n", __func__);
		return -EFAULT;
	}
	return ret;

fail:
	mutex_unlock(&pn544_dev->read_mutex);
	return ret;
}
Пример #4
0
int do_syslog(int type, char __user *buf, int len, bool from_file)
{
	unsigned i, j, limit, count;
	int do_clear = 0;
	char c;
	int error;

	error = check_syslog_permissions(type, from_file);
	if (error)
		goto out;

	error = security_syslog(type);
	if (error)
		return error;

	switch (type) {
	case SYSLOG_ACTION_CLOSE:	/* Close log */
		break;
	case SYSLOG_ACTION_OPEN:	/* Open log */
		break;
	case SYSLOG_ACTION_READ:	/* Read from log */
		error = -EINVAL;
		if (!buf || len < 0)
			goto out;
		error = 0;
		if (!len)
			goto out;
		if (!access_ok(VERIFY_WRITE, buf, len)) {
			error = -EFAULT;
			goto out;
		}
		error = wait_event_interruptible(log_wait,
							(log_start - log_end));
		if (error)
			goto out;
		i = 0;
		spin_lock_irq(&logbuf_lock);
		while (!error && (log_start != log_end) && i < len) {
			c = LOG_BUF(log_start);
			log_start++;
			spin_unlock_irq(&logbuf_lock);
			error = __put_user(c,buf);
			buf++;
			i++;
			cond_resched();
			spin_lock_irq(&logbuf_lock);
		}
		spin_unlock_irq(&logbuf_lock);
		if (!error)
			error = i;
		break;
	/* Read/clear last kernel messages */
	case SYSLOG_ACTION_READ_CLEAR:
		do_clear = 1;
		/* FALL THRU */
	/* Read last kernel messages */
	case SYSLOG_ACTION_READ_ALL:
		error = -EINVAL;
		if (!buf || len < 0)
			goto out;
		error = 0;
		if (!len)
			goto out;
		if (!access_ok(VERIFY_WRITE, buf, len)) {
			error = -EFAULT;
			goto out;
		}
		count = len;
		if (count > log_buf_len)
			count = log_buf_len;
		spin_lock_irq(&logbuf_lock);
		if (count > logged_chars)
			count = logged_chars;
		if (do_clear)
			logged_chars = 0;
		limit = log_end;
		/*
		 * __put_user() could sleep, and while we sleep
		 * printk() could overwrite the messages
		 * we try to copy to user space. Therefore
		 * the messages are copied in reverse. <manfreds>
		 */
		for (i = 0; i < count && !error; i++) {
			j = limit-1-i;
			if (j + log_buf_len < log_end)
				break;
			c = LOG_BUF(j);
			spin_unlock_irq(&logbuf_lock);
			error = __put_user(c,&buf[count-1-i]);
			cond_resched();
			spin_lock_irq(&logbuf_lock);
		}
		spin_unlock_irq(&logbuf_lock);
		if (error)
			break;
		error = i;
		if (i != count) {
			int offset = count-error;
			/* buffer overflow during copy, correct user buffer. */
			for (i = 0; i < error; i++) {
				if (__get_user(c,&buf[i+offset]) ||
				    __put_user(c,&buf[i])) {
					error = -EFAULT;
					break;
				}
				cond_resched();
			}
		}
		break;
	/* Clear ring buffer */
	case SYSLOG_ACTION_CLEAR:
		logged_chars = 0;
		break;
	/* Disable logging to console */
	case SYSLOG_ACTION_CONSOLE_OFF:
		if (saved_console_loglevel == -1)
			saved_console_loglevel = console_loglevel;
		console_loglevel = minimum_console_loglevel;
		break;
	/* Enable logging to console */
	case SYSLOG_ACTION_CONSOLE_ON:
		if (saved_console_loglevel != -1) {
			console_loglevel = saved_console_loglevel;
			saved_console_loglevel = -1;
		}
		break;
	/* Set level of messages printed to console */
	case SYSLOG_ACTION_CONSOLE_LEVEL:
		error = -EINVAL;
		if (len < 1 || len > 8)
			goto out;
		if (len < minimum_console_loglevel)
			len = minimum_console_loglevel;
		console_loglevel = len;
		/* Implicitly re-enable logging to console */
		saved_console_loglevel = -1;
		error = 0;
		break;
	/* Number of chars in the log buffer */
	case SYSLOG_ACTION_SIZE_UNREAD:
		error = log_end - log_start;
		break;
	/* Size of the log buffer */
	case SYSLOG_ACTION_SIZE_BUFFER:
		error = log_buf_len;
		break;
	default:
		error = -EINVAL;
		break;
	}
out:
	return error;
}
Пример #5
0
/*
 * This function removes the card.
 *
 * This function follows the following major steps to remove the device -
 *      - Stop data traffic
 *      - Shutdown firmware
 *      - Remove the logical interfaces
 *      - Terminate the work queue
 *      - Unregister the device
 *      - Free the adapter structure
 */
int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
{
	struct mwifiex_private *priv = NULL;
	int i;

	if (down_trylock(sem))
		goto exit_sem_err;

	if (!adapter)
		goto exit_remove;

	/* We can no longer handle interrupts once we start doing the teardown
	 * below. */
	if (adapter->if_ops.disable_int)
		adapter->if_ops.disable_int(adapter);

	adapter->surprise_removed = true;

	mwifiex_terminate_workqueue(adapter);

	/* Stop data */
	for (i = 0; i < adapter->priv_num; i++) {
		priv = adapter->priv[i];
		if (priv && priv->netdev) {
			mwifiex_stop_net_dev_queue(priv->netdev, adapter);
			if (netif_carrier_ok(priv->netdev))
				netif_carrier_off(priv->netdev);
		}
	}

	mwifiex_dbg(adapter, CMD,
		    "cmd: calling mwifiex_shutdown_drv...\n");
	adapter->init_wait_q_woken = false;

	if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
		wait_event_interruptible(adapter->init_wait_q,
					 adapter->init_wait_q_woken);
	mwifiex_dbg(adapter, CMD,
		    "cmd: mwifiex_shutdown_drv done\n");
	if (atomic_read(&adapter->rx_pending) ||
	    atomic_read(&adapter->tx_pending) ||
	    atomic_read(&adapter->cmd_pending)) {
		mwifiex_dbg(adapter, ERROR,
			    "rx_pending=%d, tx_pending=%d,\t"
			    "cmd_pending=%d\n",
			    atomic_read(&adapter->rx_pending),
			    atomic_read(&adapter->tx_pending),
			    atomic_read(&adapter->cmd_pending));
	}

	for (i = 0; i < adapter->priv_num; i++) {
		priv = adapter->priv[i];

		if (!priv)
			continue;

		rtnl_lock();
		if (priv->netdev &&
		    priv->wdev.iftype != NL80211_IFTYPE_UNSPECIFIED)
			mwifiex_del_virtual_intf(adapter->wiphy, &priv->wdev);
		rtnl_unlock();
	}

	wiphy_unregister(adapter->wiphy);
	wiphy_free(adapter->wiphy);

	/* Unregister device */
	mwifiex_dbg(adapter, INFO,
		    "info: unregister device\n");
	if (adapter->if_ops.unregister_dev)
		adapter->if_ops.unregister_dev(adapter);
	/* Free adapter structure */
	mwifiex_dbg(adapter, INFO,
		    "info: free adapter\n");
	mwifiex_free_adapter(adapter);

exit_remove:
	up(sem);
exit_sem_err:
	return 0;
}
Пример #6
0
/*
 * Alon: This function should write the buffer given by the user into the file.
 *               The function assumes the given buffer is encrypted, and will therefor
 *               use the iKey to decypher each character before writing it to the file.
 *               The function returns the amount of bytes it managed to write into the
 *               file, and -1 in case of failure.
 */
ssize_t my_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos) {
        if(check_buffer_size(count) != 0)
        {
                return -EINVAL;
        }

        int minor = get_minor_from_file(filp);
        int is_this_process_reader = is_reader(filp);
        int key = ((device_private_data *)((filp)->private_data))->private_key;

        down_interruptible(&write_lock[minor]);
        down_interruptible(&index_lock[minor]);

        int maxToWrite = get_max_to_write(minor);
        if (maxToWrite == 0)
        {
                int current_num_of_readers = get_current_num_of_readers(minor);
                if(current_num_of_readers == is_this_process_reader)
                {
                        up(&index_lock[minor]);
                        up(&write_lock[minor]);
                        return 0;
                }
                //Going to sleep until a reader clears some room in the buffer
                up(&index_lock[minor]);
                int wake_up_reason = wait_event_interruptible(write_wq[minor],
                                flag_is_full[minor] == 0 || get_current_num_of_readers(minor) == is_this_process_reader);
                if(wake_up_reason != 0)
                {
                        up(&write_lock[minor]);
                        return -EINTR;
                }
                if (get_current_num_of_readers(minor) == is_this_process_reader)
                {
                        up(&write_lock[minor]);
                        return 0;
                }
                down_interruptible(&index_lock[minor]);
                maxToWrite = get_max_to_write(minor);
        }

        int numToWrite = MIN(maxToWrite,count);
        int firstPartSize = 0;
        int retval = 0;
        char* tmpBuf =(char*)kmalloc(sizeof(char)*numToWrite,GFP_KERNEL);
        if (!tmpBuf){
                up(&index_lock[minor]);
                up(&write_lock[minor]);
                return -ENOMEM;
        }
        retval = copy_from_user(tmpBuf, buf, numToWrite); //copy the data from user
        if(retval != 0){
                kfree(tmpBuf);
                up(&index_lock[minor]);
                up(&write_lock[minor]);
                return retval;
        }

        int numOfParts = ( (writing_position[minor] + numToWrite) > BUF_SIZE) ? TWO : ONE ;
        if(numOfParts == ONE )
        {
                if (minor == 1)
                {
                        encryptor(tmpBuf, &buffer[minor][writing_position[minor]], numToWrite, key, minor);
                }
                else if(minor == 0){
                        memcpy(&buffer[minor][ writing_position[minor] ], tmpBuf, numToWrite);
                }
                writing_position[minor] = (writing_position[minor] + numToWrite) % BUF_SIZE;
        }
        else
        {
                firstPartSize = BUF_SIZE - writing_position[minor];
                if (minor == 1)
                {
                        encryptor(tmpBuf, &buffer[minor][writing_position[minor]], firstPartSize, key, minor);
                        encryptor(tmpBuf + firstPartSize, &buffer[minor][0], numToWrite - firstPartSize, key, minor);
                }
                else if (minor == 0)
                {
                        memcpy(&buffer[minor][writing_position[minor]], tmpBuf, firstPartSize);
                        memcpy(&buffer[minor][0], tmpBuf + firstPartSize, numToWrite - firstPartSize);
                }
                writing_position[minor] = (numToWrite - firstPartSize);
        }

        if(( writing_position[minor] == reading_position[minor]) && numToWrite){
                flag_is_full[minor] = 1;
        }
        if (numToWrite)
        {
                flag_is_empty[minor] = 0;
                wake_up_interruptible(&read_wq[minor]);
        }
        /*
         * If we wrote something into the buffer, this makes sure to wake up
         * any writer who may be waiting for input.
         */

        kfree(tmpBuf);
        up(&index_lock[minor]);
        up(&write_lock[minor]);
        if(retval != 0){
                return retval;
        }
        return numToWrite;
}
Пример #7
0
/*
 * iowarrior_write
 */
static ssize_t iowarrior_write(struct file *file,
			       const char __user *user_buffer,
			       size_t count, loff_t *ppos)
{
	struct iowarrior *dev;
	int retval = 0;
	char *buf = NULL;	/* for IOW24 and IOW56 we need a buffer */
	struct urb *int_out_urb = NULL;

	dev = file->private_data;

	mutex_lock(&dev->mutex);
	/* verify that the device wasn't unplugged */
	if (!dev->present) {
		retval = -ENODEV;
		goto exit;
	}
	dbg("%s - minor %d, count = %zd", __func__, dev->minor, count);
	/* if count is 0 we're already done */
	if (count == 0) {
		retval = 0;
		goto exit;
	}
	/* We only accept full reports */
	if (count != dev->report_size) {
		retval = -EINVAL;
		goto exit;
	}
	switch (dev->product_id) {
	case USB_DEVICE_ID_CODEMERCS_IOW24:
	case USB_DEVICE_ID_CODEMERCS_IOWPV1:
	case USB_DEVICE_ID_CODEMERCS_IOWPV2:
	case USB_DEVICE_ID_CODEMERCS_IOW40:
		/* IOW24 and IOW40 use a synchronous call */
		buf = kmalloc(8, GFP_KERNEL);	/* 8 bytes are enough for both products */
		if (!buf) {
			retval = -ENOMEM;
			goto exit;
		}
		if (copy_from_user(buf, user_buffer, count)) {
			retval = -EFAULT;
			kfree(buf);
			goto exit;
		}
		retval = usb_set_report(dev->interface, 2, 0, buf, count);
		kfree(buf);
		goto exit;
		break;
	case USB_DEVICE_ID_CODEMERCS_IOW56:
		/* The IOW56 uses asynchronous IO and more urbs */
		if (atomic_read(&dev->write_busy) == MAX_WRITES_IN_FLIGHT) {
			/* Wait until we are below the limit for submitted urbs */
			if (file->f_flags & O_NONBLOCK) {
				retval = -EAGAIN;
				goto exit;
			} else {
				retval = wait_event_interruptible(dev->write_wait,
								  (!dev->present || (atomic_read (&dev-> write_busy) < MAX_WRITES_IN_FLIGHT)));
				if (retval) {
					/* we were interrupted by a signal */
					retval = -ERESTART;
					goto exit;
				}
				if (!dev->present) {
					/* The device was unplugged */
					retval = -ENODEV;
					goto exit;
				}
				if (!dev->opened) {
					/* We were closed while waiting for an URB */
					retval = -ENODEV;
					goto exit;
				}
			}
		}
		atomic_inc(&dev->write_busy);
		int_out_urb = usb_alloc_urb(0, GFP_KERNEL);
		if (!int_out_urb) {
			retval = -ENOMEM;
			dbg("%s Unable to allocate urb ", __func__);
			goto error_no_urb;
		}
		buf = usb_alloc_coherent(dev->udev, dev->report_size,
					 GFP_KERNEL, &int_out_urb->transfer_dma);
		if (!buf) {
			retval = -ENOMEM;
			dbg("%s Unable to allocate buffer ", __func__);
			goto error_no_buffer;
		}
		usb_fill_int_urb(int_out_urb, dev->udev,
				 usb_sndintpipe(dev->udev,
						dev->int_out_endpoint->bEndpointAddress),
				 buf, dev->report_size,
				 iowarrior_write_callback, dev,
				 dev->int_out_endpoint->bInterval);
		int_out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
		if (copy_from_user(buf, user_buffer, count)) {
			retval = -EFAULT;
			goto error;
		}
		retval = usb_submit_urb(int_out_urb, GFP_KERNEL);
		if (retval) {
			dbg("%s submit error %d for urb nr.%d", __func__,
			    retval, atomic_read(&dev->write_busy));
			goto error;
		}
		/* submit was ok */
		retval = count;
		usb_free_urb(int_out_urb);
		goto exit;
		break;
	default:
		/* what do we have here ? An unsupported Product-ID ? */
		dev_err(&dev->interface->dev, "%s - not supported for product=0x%x\n",
			__func__, dev->product_id);
		retval = -EFAULT;
		goto exit;
		break;
	}
error:
	usb_free_coherent(dev->udev, dev->report_size, buf,
			  int_out_urb->transfer_dma);
error_no_buffer:
	usb_free_urb(int_out_urb);
error_no_urb:
	atomic_dec(&dev->write_busy);
	wake_up_interruptible(&dev->write_wait);
exit:
	mutex_unlock(&dev->mutex);
	return retval;
}
Пример #8
0
/*
 * This function gets firmware and initializes it.
 *
 * The main initialization steps followed are -
 *      - Download the correct firmware to card
 *      - Issue the init commands to firmware
 */
static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
{
	int ret;
	char fmt[64];
	struct mwifiex_private *priv;
	struct mwifiex_adapter *adapter = context;
	struct mwifiex_fw_image fw;

	if (!firmware) {
		dev_err(adapter->dev,
			"Failed to get firmware %s\n", adapter->fw_name);
		goto done;
	}

	memset(&fw, 0, sizeof(struct mwifiex_fw_image));
	adapter->firmware = firmware;
	fw.fw_buf = (u8 *) adapter->firmware->data;
	fw.fw_len = adapter->firmware->size;

	if (adapter->if_ops.dnld_fw)
		ret = adapter->if_ops.dnld_fw(adapter, &fw);
	else
		ret = mwifiex_dnld_fw(adapter, &fw);
	if (ret == -1)
		goto done;

	dev_notice(adapter->dev, "WLAN FW is active\n");

	adapter->init_wait_q_woken = false;
	ret = mwifiex_init_fw(adapter);
	if (ret == -1) {
		goto done;
	} else if (!ret) {
		adapter->hw_status = MWIFIEX_HW_STATUS_READY;
		goto done;
	}
	/* Wait for mwifiex_init to complete */
	wait_event_interruptible(adapter->init_wait_q,
				 adapter->init_wait_q_woken);
	if (adapter->hw_status != MWIFIEX_HW_STATUS_READY)
		goto done;

	priv = adapter->priv[MWIFIEX_BSS_ROLE_STA];
	if (mwifiex_register_cfg80211(adapter)) {
		dev_err(adapter->dev, "cannot register with cfg80211\n");
		goto err_init_fw;
	}

	rtnl_lock();
	/* Create station interface by default */
	if (!mwifiex_add_virtual_intf(adapter->wiphy, "mlan%d",
				      NL80211_IFTYPE_STATION, NULL, NULL)) {
		dev_err(adapter->dev, "cannot create default STA interface\n");
		goto err_add_intf;
	}
	rtnl_unlock();

	mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1);
	dev_notice(adapter->dev, "driver_version = %s\n", fmt);
	goto done;

err_add_intf:
	mwifiex_del_virtual_intf(adapter->wiphy, priv->wdev);
	rtnl_unlock();
err_init_fw:
	pr_debug("info: %s: unregister device\n", __func__);
	adapter->if_ops.unregister_dev(adapter);
done:
	release_firmware(adapter->firmware);
	complete(&adapter->fw_load);
	return;
}
Пример #9
0
/*
 * This function adds the card.
 *
 * This function follows the following major steps to set up the device -
 *      - Initialize software. This includes probing the card, registering
 *        the interface operations table, and allocating/initializing the
 *        adapter structure
 *      - Set up the netlink socket
 *      - Create and start the main work queue
 *      - Register the device
 *      - Initialize firmware and hardware
 *      - Add logical interfaces
 */
int
mwifiex_add_card(void *card, struct semaphore *sem,
		 struct mwifiex_if_ops *if_ops, u8 iface_type)
{
	struct mwifiex_adapter *adapter;

	if (down_interruptible(sem))
		goto exit_sem_err;

	if (mwifiex_register(card, if_ops, (void **)&adapter)) {
		pr_err("%s: software init failed\n", __func__);
		goto err_init_sw;
	}

	adapter->iface_type = iface_type;

	adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
	adapter->surprise_removed = false;
	init_waitqueue_head(&adapter->init_wait_q);
	adapter->is_suspended = false;
	adapter->hs_activated = false;
	init_waitqueue_head(&adapter->hs_activate_wait_q);
	adapter->cmd_wait_q_required = false;
	init_waitqueue_head(&adapter->cmd_wait_q.wait);
	adapter->cmd_wait_q.status = 0;
	adapter->scan_wait_q_woken = false;

	adapter->workqueue = create_workqueue("MWIFIEX_WORK_QUEUE");
	if (!adapter->workqueue)
		goto err_kmalloc;

	INIT_WORK(&adapter->main_work, mwifiex_main_work_queue);

	/* Register the device. Fill up the private data structure with relevant
	   information from the card and request for the required IRQ. */
	if (adapter->if_ops.register_dev(adapter)) {
		pr_err("%s: failed to register mwifiex device\n", __func__);
		goto err_registerdev;
	}

	if (mwifiex_init_hw_fw(adapter)) {
		pr_err("%s: firmware init failed\n", __func__);
		goto err_init_fw;
	}

	up(sem);
	return 0;

err_init_fw:
	pr_debug("info: %s: unregister device\n", __func__);
	if (adapter->if_ops.unregister_dev)
		adapter->if_ops.unregister_dev(adapter);
err_registerdev:
	adapter->surprise_removed = true;
	mwifiex_terminate_workqueue(adapter);
err_kmalloc:
	if ((adapter->hw_status == MWIFIEX_HW_STATUS_FW_READY) ||
	    (adapter->hw_status == MWIFIEX_HW_STATUS_READY)) {
		pr_debug("info: %s: shutdown mwifiex\n", __func__);
		adapter->init_wait_q_woken = false;

		if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
			wait_event_interruptible(adapter->init_wait_q,
						 adapter->init_wait_q_woken);
	}

	mwifiex_free_adapter(adapter);

err_init_sw:
	up(sem);

exit_sem_err:
	return -1;
}
static ssize_t rmnet_ctl_read(struct file *file, char __user *buf, size_t count,
		loff_t *ppos)
{
	int				retval = 0;
	int				bytes_to_read;
	unsigned int			hdr_len = 0;
	struct rmnet_ctrl_dev		*dev;
	struct ctrl_pkt_list_elem	*list_elem = NULL;
	unsigned long			flags;

	dev = file->private_data;
	if (!dev)
		return -ENODEV;

	DBG("%s: Read from %s\n", __func__, dev->name);

ctrl_read:
	if (!test_bit(RMNET_CTRL_DEV_READY, &dev->status)) {
		dev_dbg(dev->devicep, "%s: Device not connected\n",
			__func__);
		return -ENETRESET;
	}
	spin_lock_irqsave(&dev->rx_lock, flags);
	if (list_empty(&dev->rx_list)) {
		spin_unlock_irqrestore(&dev->rx_lock, flags);

		retval = wait_event_interruptible(dev->read_wait_queue,
				!list_empty(&dev->rx_list) ||
				!test_bit(RMNET_CTRL_DEV_READY, &dev->status));
		if (retval < 0)
			return retval;

		goto ctrl_read;
	}

	list_elem = list_first_entry(&dev->rx_list,
				     struct ctrl_pkt_list_elem, list);
	bytes_to_read = (uint32_t)(list_elem->cpkt.data_size);
	if (bytes_to_read > count) {
		spin_unlock_irqrestore(&dev->rx_lock, flags);
		dev_err(dev->devicep, "%s: Packet size %d > buf size %d\n",
			__func__, bytes_to_read, count);
		return -ENOMEM;
	}
	spin_unlock_irqrestore(&dev->rx_lock, flags);

	if (test_bit(RMNET_CTRL_DEV_MUX_EN, &dev->status))
		hdr_len = sizeof(struct mux_hdr);

	if (copy_to_user(buf, list_elem->cpkt.data + hdr_len, bytes_to_read)) {
			dev_err(dev->devicep,
				"%s: copy_to_user failed for %s\n",
				__func__, dev->name);
		return -EFAULT;
	}
	spin_lock_irqsave(&dev->rx_lock, flags);
	list_del(&list_elem->list);
	spin_unlock_irqrestore(&dev->rx_lock, flags);

	kfree(list_elem->cpkt.data);
	kfree(list_elem);
	DBG("%s: Returning %d bytes to %s\n", __func__, bytes_to_read,
			dev->name);
	DUMP_BUFFER("Read: ", bytes_to_read, buf);

	return bytes_to_read;
}
Пример #11
0
/* transmit out IR pulses; what you get here is a batch of alternating
 * pulse/space/pulse/space lengths that we should write out completely through
 * the FIFO, blocking on a full FIFO */
static int ite_tx_ir(struct rc_dev *rcdev, int *txbuf, u32 n)
{
	unsigned long flags;
	struct ite_dev *dev = rcdev->priv;
	bool is_pulse = false;
	int remaining_us, fifo_avail, fifo_remaining, last_idx = 0;
	int max_rle_us, next_rle_us;
	int ret = n;
	u8 last_sent[ITE_TX_FIFO_LEN];
	u8 val;

	ite_dbg("%s called", __func__);

	/* clear the array just in case */
	memset(last_sent, 0, ARRAY_SIZE(last_sent));

	/* n comes in bytes; convert to ints */
	n /= sizeof(int);

	spin_lock_irqsave(&dev->lock, flags);

	/* let everybody know we're now transmitting */
	dev->transmitting = true;

	/* and set the carrier values for transmission */
	ite_set_carrier_params(dev);

	/* calculate how much time we can send in one byte */
	max_rle_us =
	    (ITE_BAUDRATE_DIVISOR * dev->params.sample_period *
	     ITE_TX_MAX_RLE) / 1000;

	/* disable the receiver */
	dev->params.disable_rx(dev);

	/* this is where we'll begin filling in the FIFO, until it's full.
	 * then we'll just activate the interrupt, wait for it to wake us up
	 * again, disable it, continue filling the FIFO... until everything
	 * has been pushed out */
	fifo_avail =
	    ITE_TX_FIFO_LEN - dev->params.get_tx_used_slots(dev);

	while (n > 0 && dev->in_use) {
		/* transmit the next sample */
		is_pulse = !is_pulse;
		remaining_us = *(txbuf++);
		n--;

		ite_dbg("%s: %ld",
				      ((is_pulse) ? "pulse" : "space"),
				      (long int)
				      remaining_us);

		/* repeat while the pulse is non-zero length */
		while (remaining_us > 0 && dev->in_use) {
			if (remaining_us > max_rle_us)
				next_rle_us = max_rle_us;

			else
				next_rle_us = remaining_us;

			remaining_us -= next_rle_us;

			/* check what's the length we have to pump out */
			val = (ITE_TX_MAX_RLE * next_rle_us) / max_rle_us;

			/* put it into the sent buffer */
			last_sent[last_idx++] = val;
			last_idx &= (ITE_TX_FIFO_LEN);

			/* encode it for 7 bits */
			val = (val - 1) & ITE_TX_RLE_MASK;

			/* take into account pulse/space prefix */
			if (is_pulse)
				val |= ITE_TX_PULSE;

			else
				val |= ITE_TX_SPACE;

			/*
			 * if we get to 0 available, read again, just in case
			 * some other slot got freed
			 */
			if (fifo_avail <= 0)
				fifo_avail = ITE_TX_FIFO_LEN - dev->params.get_tx_used_slots(dev);

			/* if it's still full */
			if (fifo_avail <= 0) {
				/* enable the tx interrupt */
				dev->params.
				enable_tx_interrupt(dev);

				/* drop the spinlock */
				spin_unlock_irqrestore(&dev->lock, flags);

				/* wait for the FIFO to empty enough */
				wait_event_interruptible(dev->tx_queue, (fifo_avail = ITE_TX_FIFO_LEN - dev->params.get_tx_used_slots(dev)) >= 8);

				/* get the spinlock again */
				spin_lock_irqsave(&dev->lock, flags);

				/* disable the tx interrupt again. */
				dev->params.
				disable_tx_interrupt(dev);
			}

			/* now send the byte through the FIFO */
			dev->params.put_tx_byte(dev, val);
			fifo_avail--;
		}
	}

	/* wait and don't return until the whole FIFO has been sent out;
	 * otherwise we could configure the RX carrier params instead of the
	 * TX ones while the transmission is still being performed! */
	fifo_remaining = dev->params.get_tx_used_slots(dev);
	remaining_us = 0;
	while (fifo_remaining > 0) {
		fifo_remaining--;
		last_idx--;
		last_idx &= (ITE_TX_FIFO_LEN - 1);
		remaining_us += last_sent[last_idx];
	}
	remaining_us = (remaining_us * max_rle_us) / (ITE_TX_MAX_RLE);

	/* drop the spinlock while we sleep */
	spin_unlock_irqrestore(&dev->lock, flags);

	/* sleep remaining_us microseconds */
	mdelay(DIV_ROUND_UP(remaining_us, 1000));

	/* reacquire the spinlock */
	spin_lock_irqsave(&dev->lock, flags);

	/* now we're not transmitting anymore */
	dev->transmitting = false;

	/* and set the carrier values for reception */
	ite_set_carrier_params(dev);

	/* reenable the receiver */
	if (dev->in_use)
		dev->params.enable_rx(dev);

	/* notify transmission end */
	wake_up_interruptible(&dev->tx_ended);

	spin_unlock_irqrestore(&dev->lock, flags);

	return ret;
}
Пример #12
0
static int recv_msg(struct kiocb *iocb, struct socket *sock,
		    struct msghdr *m, size_t buf_len, int flags)
{
	struct sock *sk = sock->sk;
	struct tipc_port *tport = tipc_sk_port(sk);
	struct sk_buff *buf;
	struct tipc_msg *msg;
	unsigned int sz;
	u32 err;
	int res;

	/* Catch invalid receive requests */

	if (m->msg_iovlen != 1)
		return -EOPNOTSUPP;   /* Don't do multiple iovec entries yet */

	if (unlikely(!buf_len))
		return -EINVAL;

	lock_sock(sk);

	if (unlikely(sock->state == SS_UNCONNECTED)) {
		res = -ENOTCONN;
		goto exit;
	}

restart:

	/* Look for a message in receive queue; wait if necessary */

	while (skb_queue_empty(&sk->sk_receive_queue)) {
		if (sock->state == SS_DISCONNECTING) {
			res = -ENOTCONN;
			goto exit;
		}
		if (flags & MSG_DONTWAIT) {
			res = -EWOULDBLOCK;
			goto exit;
		}
		release_sock(sk);
		res = wait_event_interruptible(*sk_sleep(sk),
			(!skb_queue_empty(&sk->sk_receive_queue) ||
			 (sock->state == SS_DISCONNECTING)));
		lock_sock(sk);
		if (res)
			goto exit;
	}

	/* Look at first message in receive queue */

	buf = skb_peek(&sk->sk_receive_queue);
	msg = buf_msg(buf);
	sz = msg_data_sz(msg);
	err = msg_errcode(msg);

	/* Complete connection setup for an implied connect */

	if (unlikely(sock->state == SS_CONNECTING)) {
		res = auto_connect(sock, msg);
		if (res)
			goto exit;
	}

	/* Discard an empty non-errored message & try again */

	if ((!sz) && (!err)) {
		advance_rx_queue(sk);
		goto restart;
	}

	/* Capture sender's address (optional) */

	set_orig_addr(m, msg);

	/* Capture ancillary data (optional) */

	res = anc_data_recv(m, msg, tport);
	if (res)
		goto exit;

	/* Capture message data (if valid) & compute return value (always) */

	if (!err) {
		if (unlikely(buf_len < sz)) {
			sz = buf_len;
			m->msg_flags |= MSG_TRUNC;
		}
		if (unlikely(copy_to_user(m->msg_iov->iov_base, msg_data(msg),
					  sz))) {
			res = -EFAULT;
			goto exit;
		}
		res = sz;
	} else {
		if ((sock->state == SS_READY) ||
		    ((err == TIPC_CONN_SHUTDOWN) || m->msg_control))
			res = 0;
		else
			res = -ECONNRESET;
	}

	/* Consume received message (optional) */

	if (likely(!(flags & MSG_PEEK))) {
		if ((sock->state != SS_READY) &&
		    (++tport->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
			tipc_acknowledge(tport->ref, tport->conn_unacked);
		advance_rx_queue(sk);
	}
exit:
	release_sock(sk);
	return res;
}
Пример #13
0
static int send_msg(struct kiocb *iocb, struct socket *sock,
		    struct msghdr *m, size_t total_len)
{
	struct sock *sk = sock->sk;
	struct tipc_port *tport = tipc_sk_port(sk);
	struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name;
	int needs_conn;
	int res = -EINVAL;

	if (unlikely(!dest))
		return -EDESTADDRREQ;
	if (unlikely((m->msg_namelen < sizeof(*dest)) ||
		     (dest->family != AF_TIPC)))
		return -EINVAL;

	if (iocb)
		lock_sock(sk);

	needs_conn = (sock->state != SS_READY);
	if (unlikely(needs_conn)) {
		if (sock->state == SS_LISTENING) {
			res = -EPIPE;
			goto exit;
		}
		if (sock->state != SS_UNCONNECTED) {
			res = -EISCONN;
			goto exit;
		}
		if ((tport->published) ||
		    ((sock->type == SOCK_STREAM) && (total_len != 0))) {
			res = -EOPNOTSUPP;
			goto exit;
		}
		if (dest->addrtype == TIPC_ADDR_NAME) {
			tport->conn_type = dest->addr.name.name.type;
			tport->conn_instance = dest->addr.name.name.instance;
		}

		/* Abort any pending connection attempts (very unlikely) */

		reject_rx_queue(sk);
	}

	do {
		if (dest->addrtype == TIPC_ADDR_NAME) {
			res = dest_name_check(dest, m);
			if (res)
				break;
			res = tipc_send2name(tport->ref,
					     &dest->addr.name.name,
					     dest->addr.name.domain,
					     m->msg_iovlen,
					     m->msg_iov);
		} else if (dest->addrtype == TIPC_ADDR_ID) {
			res = tipc_send2port(tport->ref,
					     &dest->addr.id,
					     m->msg_iovlen,
					     m->msg_iov);
		} else if (dest->addrtype == TIPC_ADDR_MCAST) {
			if (needs_conn) {
				res = -EOPNOTSUPP;
				break;
			}
			res = dest_name_check(dest, m);
			if (res)
				break;
			res = tipc_multicast(tport->ref,
					     &dest->addr.nameseq,
					     m->msg_iovlen,
					     m->msg_iov);
		}
		if (likely(res != -ELINKCONG)) {
			if (needs_conn && (res >= 0))
				sock->state = SS_CONNECTING;
			break;
		}
		if (m->msg_flags & MSG_DONTWAIT) {
			res = -EWOULDBLOCK;
			break;
		}
		release_sock(sk);
		res = wait_event_interruptible(*sk_sleep(sk),
					       !tport->congested);
		lock_sock(sk);
		if (res)
			break;
	} while (1);

exit:
	if (iocb)
		release_sock(sk);
	return res;
}
Пример #14
0
static int accept(struct socket *sock, struct socket *new_sock, int flags)
{
	struct sock *sk = sock->sk;
	struct sk_buff *buf;
	int res;

	lock_sock(sk);

	if (sock->state == SS_READY) {
		res = -EOPNOTSUPP;
		goto exit;
	}
	if (sock->state != SS_LISTENING) {
		res = -EINVAL;
		goto exit;
	}

	while (skb_queue_empty(&sk->sk_receive_queue)) {
		if (flags & O_NONBLOCK) {
			res = -EWOULDBLOCK;
			goto exit;
		}
		release_sock(sk);
		res = wait_event_interruptible(*sk_sleep(sk),
				(!skb_queue_empty(&sk->sk_receive_queue)));
		lock_sock(sk);
		if (res)
			goto exit;
	}

	buf = skb_peek(&sk->sk_receive_queue);

	res = tipc_create(sock_net(sock->sk), new_sock, 0, 0);
	if (!res) {
		struct sock *new_sk = new_sock->sk;
		struct tipc_sock *new_tsock = tipc_sk(new_sk);
		struct tipc_port *new_tport = new_tsock->p;
		u32 new_ref = new_tport->ref;
		struct tipc_msg *msg = buf_msg(buf);

		lock_sock(new_sk);

		/*
		 * Reject any stray messages received by new socket
		 * before the socket lock was taken (very, very unlikely)
		 */

		reject_rx_queue(new_sk);

		/* Connect new socket to it's peer */

		new_tsock->peer_name.ref = msg_origport(msg);
		new_tsock->peer_name.node = msg_orignode(msg);
		tipc_connect2port(new_ref, &new_tsock->peer_name);
		new_sock->state = SS_CONNECTED;

		tipc_set_portimportance(new_ref, msg_importance(msg));
		if (msg_named(msg)) {
			new_tport->conn_type = msg_nametype(msg);
			new_tport->conn_instance = msg_nameinst(msg);
		}

		/*
		 * Respond to 'SYN-' by discarding it & returning 'ACK'-.
		 * Respond to 'SYN+' by queuing it on new socket.
		 */

		if (!msg_data_sz(msg)) {
			struct msghdr m = {NULL,};

			advance_rx_queue(sk);
			send_packet(NULL, new_sock, &m, 0);
		} else {
			__skb_dequeue(&sk->sk_receive_queue);
			__skb_queue_head(&new_sk->sk_receive_queue, buf);
		}
		release_sock(new_sk);
	}
exit:
	release_sock(sk);
	return res;
}
Пример #15
0
static ssize_t ksb_fs_read(struct file *fp, char __user *buf,
				size_t count, loff_t *pos)
{
	int ret;
	unsigned long flags;
	struct ks_bridge *ksb = fp->private_data;
	struct data_pkt *pkt;
	size_t space, copied;

read_start:
	if (!test_bit(USB_DEV_CONNECTED, &ksb->flags))
		return -ENODEV;

	spin_lock_irqsave(&ksb->lock, flags);
	if (list_empty(&ksb->to_ks_list)) {
		spin_unlock_irqrestore(&ksb->lock, flags);
		ret = wait_event_interruptible(ksb->ks_wait_q,
				!list_empty(&ksb->to_ks_list) ||
				!test_bit(USB_DEV_CONNECTED, &ksb->flags));
		if (ret < 0)
			return ret;

		goto read_start;
	}

	space = count;
	copied = 0;
	while (!list_empty(&ksb->to_ks_list) && space) {
		size_t len;

		pkt = list_first_entry(&ksb->to_ks_list, struct data_pkt, list);
		len = min_t(size_t, space, pkt->len);
		pkt->n_read += len;
		spin_unlock_irqrestore(&ksb->lock, flags);

		ret = copy_to_user(buf + copied, pkt->buf, len);
		if (ret) {
			pr_err("copy_to_user failed err:%d\n", ret);
			ksb_free_data_pkt(pkt);
			return ret;
		}

		space -= len;
		copied += len;

		spin_lock_irqsave(&ksb->lock, flags);
		if (pkt->n_read == pkt->len) {
			/*
			 * re-init the packet and queue it
			 * for more data.
			 */
			list_del_init(&pkt->list);
			pkt->n_read = 0;
			pkt->len = MAX_DATA_PKT_SIZE;
			spin_unlock_irqrestore(&ksb->lock, flags);
			submit_one_urb(ksb, GFP_KERNEL, pkt);
			spin_lock_irqsave(&ksb->lock, flags);
		}
	}
	spin_unlock_irqrestore(&ksb->lock, flags);

	dbg_log_event(ksb, "KS_READ", copied, 0);

	pr_debug("count:%d space:%d copied:%d", count, space, copied);

	return copied;
}
Пример #16
0
/*
 * This function removes the card.
 *
 * This function follows the following major steps to remove the device -
 *      - Stop data traffic
 *      - Shutdown firmware
 *      - Remove the logical interfaces
 *      - Terminate the work queue
 *      - Unregister the device
 *      - Free the adapter structure
 */
int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
{
	struct mwifiex_private *priv = NULL;
	int i;

	if (down_interruptible(sem))
		goto exit_sem_err;

	if (!adapter)
		goto exit_remove;

	adapter->surprise_removed = true;

	/* Stop data */
	for (i = 0; i < adapter->priv_num; i++) {
		priv = adapter->priv[i];
		if (priv && priv->netdev) {
			mwifiex_stop_net_dev_queue(priv->netdev, adapter);
			if (netif_carrier_ok(priv->netdev))
				netif_carrier_off(priv->netdev);
		}
	}

	dev_dbg(adapter->dev, "cmd: calling mwifiex_shutdown_drv...\n");
	adapter->init_wait_q_woken = false;

	if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
		wait_event_interruptible(adapter->init_wait_q,
					 adapter->init_wait_q_woken);
	dev_dbg(adapter->dev, "cmd: mwifiex_shutdown_drv done\n");
	if (atomic_read(&adapter->rx_pending) ||
	    atomic_read(&adapter->tx_pending) ||
	    atomic_read(&adapter->cmd_pending)) {
		dev_err(adapter->dev, "rx_pending=%d, tx_pending=%d, "
		       "cmd_pending=%d\n",
		       atomic_read(&adapter->rx_pending),
		       atomic_read(&adapter->tx_pending),
		       atomic_read(&adapter->cmd_pending));
	}

	for (i = 0; i < adapter->priv_num; i++) {
		priv = adapter->priv[i];

		if (!priv)
			continue;

		rtnl_lock();
		if (priv->wdev && priv->netdev)
			mwifiex_del_virtual_intf(adapter->wiphy, priv->wdev);
		rtnl_unlock();
	}

	priv = adapter->priv[0];
	if (!priv || !priv->wdev)
		goto exit_remove;

	wiphy_unregister(priv->wdev->wiphy);
	wiphy_free(priv->wdev->wiphy);

	for (i = 0; i < adapter->priv_num; i++) {
		priv = adapter->priv[i];
		if (priv)
			kfree(priv->wdev);
	}

	mwifiex_terminate_workqueue(adapter);

	/* Unregister device */
	dev_dbg(adapter->dev, "info: unregister device\n");
	if (adapter->if_ops.unregister_dev)
		adapter->if_ops.unregister_dev(adapter);
	/* Free adapter structure */
	dev_dbg(adapter->dev, "info: free adapter\n");
	mwifiex_free_adapter(adapter);

exit_remove:
	up(sem);
exit_sem_err:
	return 0;
}
Пример #17
0
/*
 * Alon: this function should simply read the data on the given file,
 *               copy it, and return it to the user as it is (encrypted or not).
 *               The function's return value is the total amount of bytes read from the
 *               file, or -1 if the function failed.
 */
ssize_t my_read(struct file *filp, char *buf, size_t count, loff_t *f_pos) {
        if (check_buffer_size(count) != 0)
        {
                return -EINVAL;
        }

        int minor = get_minor_from_file(filp);
        int is_this_process_writer = is_writer(filp);
        int key = ((device_private_data *)((filp)->private_data))->private_key;

        down_interruptible(&read_lock[minor]);
        down_interruptible(&index_lock[minor]);

        int maxToRead = get_max_to_read(minor);
        if (maxToRead == 0)
        {
                int current_num_of_writers = get_current_num_of_writers(minor);
                if(current_num_of_writers == is_this_process_writer)
                {
                        up(&index_lock[minor]);
                        up(&read_lock[minor]);
                        return 0;
                }
                //Going to sleep until something is written into the buffer
                up(&index_lock[minor]);
                int wake_up_reason = wait_event_interruptible(read_wq[minor],
                                flag_is_empty[minor] == 0 || get_current_num_of_writers(minor) == is_this_process_writer);
                if(wake_up_reason != 0)
                {
                        up(&read_lock[minor]);
                        return -EINTR;
                }
                if (get_current_num_of_writers(minor) == is_this_process_writer)
                {
                        up(&read_lock[minor]);
                        return 0;
                }
                down_interruptible(&index_lock[minor]);
                maxToRead = get_max_to_read(minor);
        }

        int numToRead = MIN(maxToRead,count);
        int firstPartSize = 0;
        int retval = 0;
        char* tmpBuf =(char*)kmalloc(sizeof(char)*numToRead,GFP_KERNEL);
        if (!tmpBuf){
                up(&index_lock[minor]);
                up(&read_lock[minor]);
                return -ENOMEM;
        }
        int numOfParts = ( (reading_position[minor] + numToRead) > BUF_SIZE) ? TWO : ONE ;
        char* source = tmpBuf;
        if(numOfParts == ONE )
        {
                if (minor == 0)
                {
                        encryptor(&buffer[minor][reading_position[minor]], tmpBuf, numToRead, key, minor);
                }
                else if(minor == 1){            // encryptor
                        source = &buffer[minor][ reading_position[minor] ];
                }
                retval = copy_to_user(buf, source, numToRead) ? -EFAULT : 0;
                reading_position[minor] = (reading_position[minor] + numToRead) % BUF_SIZE;
        }
        else
        {
                firstPartSize = BUF_SIZE - reading_position[minor];
                if (minor == 0)
                {
                        encryptor(&buffer[minor][ reading_position[minor] ], tmpBuf, firstPartSize, key, minor);
                        encryptor(&buffer[minor][0],tmpBuf+firstPartSize , numToRead - firstPartSize, key, minor);
                }
                else if (minor == 1)
                {
                        memcpy(tmpBuf, &buffer[minor][ reading_position[minor] ], firstPartSize);
                        memcpy(tmpBuf+firstPartSize, &buffer[minor][0], numToRead - firstPartSize);
                }
                retval = copy_to_user(buf, tmpBuf, numToRead);
                reading_position[minor] = numToRead - firstPartSize;
        }
        kfree(tmpBuf);
        if(retval != 0){
                up(&index_lock[minor]);
                up(&read_lock[minor]);
                return retval;
        }
        if((writing_position[minor] == reading_position[minor]) && numToRead){
                flag_is_empty[minor] = 1;
        }
        if(numToRead != 0){                             // if we have read SOMETHING, the buffer is not full anymore
                flag_is_full[minor] = 0;
                wake_up_interruptible(&write_wq[minor]);        //Notifies any waiting writers that there is now room within the buffer
        }

        up(&index_lock[minor]);
        up(&read_lock[minor]);
        return numToRead;
}
Пример #18
0
/*
 * osprd_ioctl(inode, filp, cmd, arg)
 *   Called to perform an ioctl on the named file.
 */
int osprd_ioctl(struct inode *inode, struct file *filp,
		unsigned int cmd, unsigned long arg)
{
	osprd_info_t *d = file2osprd(filp);	// device info
		
	pid_t pid;
	node_t check;
	int wait, i;
	unsigned ticket;


	// is file open for writing?
	int filp_writable = (filp->f_mode & FMODE_WRITE) != 0;

	if (cmd == OSPRDIOCACQUIRE) {

		// The process id trying to get this lock is the unique identifier
		// in our list
		pid = current->pid;

		// Check if this pid has already tried to get a lock on this device
		check = check_in_list(d->lock_list, pid);
		if (check) {
			return -EDEADLK;
		}

		/*
		This whole section is to prevent deadlock. The global lock is 
		necessary to avoid raceconditions, like processes getting inserted
		into the list after we've already checked it. This is a huge 
		unfortunate bottleneck. I does prevent deadlock, however.
		*/
		osp_spin_lock(&g_mutex);
		for (i = 0; i < NOSPRD; i++) {
			if(d == &osprds[i]) {  //Checks if this our own device
				continue;
			}
			else {
				node_t traversal = d->lock_list; //Traversal set to beginning of our lock linked list
				node_t start; // The starting position of our pid in the other list
				check = NULL;

				start = check_in_list(osprds[i].lock_list, pid);
				// We only care if our is also has another lock in this node
				if(start == NULL)
					continue;

				while(traversal != NULL) {
					// Only care about stuff after our pid
					check = check_in_list(start, traversal->pid);

					// We must make sure that our pid does not hold
					//  a lock that would block anything in another queue
					if(check != NULL) {
						osp_spin_unlock(&g_mutex);
						return -EDEADLK;
					}
					traversal = traversal->next;   
				}
			}
		}

		// It doesn't cause deadlock, so me must insert it into the list so
		// that others can check if this process will cause deadlock
		insert_node (&d->lock_list, pid, d->read_locks, d->write_locks);
		
		osp_spin_unlock(&g_mutex);

		// EXERCISE: Lock the ramdisk.
		//
		// If *filp is open for writing (filp_writable), then attempt
		// to write-lock the ramdisk; otherwise attempt to read-lock
		// the ramdisk.
		//
                // This lock request must block using 'd->blockq' until:
		// 1) no other process holds a write lock;
		// 2) either the request is for a read lock, or no other process
		//    holds a read lock; and
		// 3) lock requests should be serviced in order, so no process
		//    that blocked earlier is still blocked waiting for the
		//    lock.
		//
		// If a process acquires a lock, mark this fact by setting
		// 'filp->f_flags |= F_OSPRD_LOCKED'.  You also need to
		// keep track of how many read and write locks are held:
		// change the 'osprd_info_t' structure to do this.
		//
		// Also wake up processes waiting on 'd->blockq' as needed.
		//
		// If the lock request would cause a deadlock, return -EDEADLK.
		// If the lock request blocks and is awoken by a signal, then
		// return -ERESTARTSYS.
		// Otherwise, if we can grant the lock request, return 0.

		// 'd->ticket_head' and 'd->ticket_tail' should help you
		// service lock requests in order.  These implement a ticket
		// order: 'ticket_tail' is the next ticket, and 'ticket_head'
		// is the ticket currently being served.  You should set a local
		// variable to 'd->ticket_head' and increment 'd->ticket_head'.
		// Then, block at least until 'd->ticket_tail == local_ticket'.
		// (Some of these operations are in a critical section and must
		// be protected by a spinlock; which ones?)

		if (filp_writable) {
			
			// Get the next ticket
			osp_spin_lock(&d->mutex);
			ticket = d->ticket_tail;
			d->ticket_tail++;
			osp_spin_unlock(&d->mutex);

			// Wait for the ticket to become the current job
			wait = 
				wait_event_interruptible(
					d->blockq, 
					(ticket == d->ticket_head
						&& d->read_locks == 0
						&& d->write_locks == 0)
			
				);

			// Interupt handling
			if (wait != 0) {
				// Wait until we have the ticket
				// If we increment too early, another process could wait 
				//  forever
				while(ticket != d->ticket_head) {
					yield();
					continue;
				}

				osp_spin_lock(&d->mutex);
				d->ticket_head++;
				osp_spin_unlock(&d->mutex);
				
				return wait;
			}

			// Give the lock for this job
			osp_spin_lock(&d->mutex);
			d->write_locks++;
			filp->f_flags |= F_OSPRD_LOCKED;
			osp_spin_unlock(&d->mutex);
		}
		else { // Read only

			// Get the next ticket
			osp_spin_lock(&d->mutex);
			ticket = d->ticket_tail;
			d->ticket_tail++;
			osp_spin_unlock(&d->mutex);

			// Wait for the ticket to become the current job
			wait = 
				wait_event_interruptible(
					d->blockq, 
					// We don't need to check for other read tasks, take note
					(ticket == d->ticket_head && 
						d->write_locks == 0)
				);

			// Interrupt handling
			if (wait != 0) {
				// Wait until we have the ticket
				// If we increment too early, another process could wait 
				//  forever
				while(ticket != d->ticket_head) {
					yield();
					continue;
				}
				
				osp_spin_lock(&d->mutex);
				d->ticket_head++;
				osp_spin_unlock(&d->mutex);
				
				wake_up_all(&d->blockq);

				return wait;
			}

			// Give the lock to the current job
			osp_spin_lock(&d->mutex);
			d->read_locks++;
			filp->f_flags |= F_OSPRD_LOCKED;
			osp_spin_unlock(&d->mutex);

			// Since the next task might be a read task, we wake everyone
			wake_up_all(&d->blockq);
		}


		return 0;
		/*
		*/

	} else if (cmd == OSPRDIOCTRYACQUIRE) {

		// EXERCISE: ATTEMPT to lock the ramdisk.
		//
		// This is just like OSPRDIOCACQUIRE, except it should never
		// block.  If OSPRDIOCACQUIRE would block or return deadlock,
		// OSPRDIOCTRYACQUIRE should return -EBUSY.
		// Otherwise, if we can grant the lock request, return 0.

		if (filp_writable) {
			
			// Get the next ticket
			osp_spin_lock(&d->mutex);
			ticket = d->ticket_tail;
			d->ticket_tail++;
			osp_spin_unlock(&d->mutex);

			// Check if we can get the ticket
			if (ticket == d->ticket_head &&
						d->read_locks == 0 &&
						d->write_locks == 0) {
				osp_spin_lock(&d->mutex);
				d->write_locks++;
				filp->f_flags |= F_OSPRD_LOCKED;
				osp_spin_unlock(&d->mutex);
			}
			else {
				// Clean up the tickets, make sure they are back to
				// where they should be
				osp_spin_lock(&d->mutex);
				d->ticket_head++;
				osp_spin_unlock(&d->mutex);
				
				return -EBUSY;
			}
		}
		else { // Read only

			// Get the next ticket
			osp_spin_lock(&d->mutex);
			ticket = d->ticket_tail;
			d->ticket_tail++;
			osp_spin_unlock(&d->mutex);

			// Check if we can get the ticket
			if (ticket == d->ticket_head && 
						d->write_locks == 0) {
				osp_spin_lock(&d->mutex);
				d->read_locks++;
				filp->f_flags |= F_OSPRD_LOCKED;
				osp_spin_unlock(&d->mutex);

				// Wake up everyone for the same reasons
				wake_up_all(&d->blockq);
			}
			else {
				// Clean up the tickets, make sure they are back to
				// where they should be
				osp_spin_lock(&d->mutex);
				d->ticket_head++;
				osp_spin_unlock(&d->mutex);
				
				return -EBUSY;
			}
		}
		// Success
		return 0;

	} else if (cmd == OSPRDIOCRELEASE) {

		// EXERCISE: Unlock the ramdisk.
		//
		// If the file hasn't locked the ramdisk, return -EINVAL.
		// Otherwise, clear the lock from filp->f_flags, wake up
		// the wait queue, perform any additional accounting steps
		// you need, and return 0.

		// Your code here (instead of the next line).
		// Check to make sure has lock
		if (!(filp->f_flags & F_OSPRD_LOCKED)) {
			return -EINVAL;
		}

		// Clear the locked flag
		filp->f_flags &= ~(F_OSPRD_LOCKED);

		// Increment the current job and increment the number of finished
		// writing/reading tasks
		if(filp_writable) {
			osp_spin_lock(&d->mutex);
			d->ticket_head++;
			d->write_locks--;
			osp_spin_unlock(&d->mutex);
		}
		else {
			osp_spin_lock(&d->mutex);
			d->ticket_head++;
			d->read_locks--;
			osp_spin_unlock(&d->mutex);
		}

		// We're finished, notify everyone
		wake_up_all(&d->blockq);

		return 0;

	} else
		return -ENOTTY; /* unknown command */
}
Пример #19
0
ssize_t ar6000_htc_raw_write(AR_SOFTC_T *ar, HTC_RAW_STREAM_ID StreamID,
                     char __user *buffer, size_t length)
{
    int writePtr;
    raw_htc_buffer *free;

    if (arRawStream2EndpointID(ar,StreamID) == 0) {
        AR_DEBUG_PRINTF("StreamID(%d) not connected! \n", StreamID);
        return -EFAULT;
    }

    if (down_interruptible(&ar->raw_htc_write_sem[StreamID])) {
        return -ERESTARTSYS;
    }

    /* Search for a free buffer */
    free = get_free_buffer(ar,StreamID);

    /* Check if there is space to write else wait */
    while (!ar->write_buffer_available[StreamID]) {
        up(&ar->raw_htc_write_sem[StreamID]);

        /* Wait for buffer to become free */
        AR_DEBUG2_PRINTF("Sleeping StreamID(%d) write process\n", StreamID);
        if (wait_event_interruptible(ar->raw_htc_write_queue[StreamID],
                                     ar->write_buffer_available[StreamID]))
        {
            return -EINTR;
        }
        if (down_interruptible(&ar->raw_htc_write_sem[StreamID])) {
            return -ERESTARTSYS;
        }
        free = get_free_buffer(ar,StreamID);
    }

    /* Send the data */
    writePtr = HTC_HEADER_LEN;
    if (length > (AR6000_BUFFER_SIZE - HTC_HEADER_LEN)) {
        length = AR6000_BUFFER_SIZE - HTC_HEADER_LEN;
    }

    if (copy_from_user(&free->data[writePtr], buffer, length)) {
        up(&ar->raw_htc_read_sem[StreamID]);
        return -EFAULT;
    }

    free->length = length;

    SET_HTC_PACKET_INFO_TX(&free->HTCPacket,
                           free,
                           &free->data[writePtr],
                           length,
                           arRawStream2EndpointID(ar,StreamID),
                           AR6K_DATA_PKT_TAG);

    HTCSendPkt(ar->arHtcTarget,&free->HTCPacket);

    ar->write_buffer_available[StreamID] = FALSE;
    up(&ar->raw_htc_write_sem[StreamID]);

    return length;
}
Пример #20
0
static ssize_t wdm_write
(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
{
	u8 *buf;
	int rv = -EMSGSIZE, r, we;
	struct wdm_device *desc = file->private_data;
	struct usb_ctrlrequest *req;

	if (count > desc->wMaxCommand)
		count = desc->wMaxCommand;

	spin_lock_irq(&desc->iuspin);
	we = desc->werr;
	desc->werr = 0;
	spin_unlock_irq(&desc->iuspin);
	if (we < 0)
		return -EIO;

	buf = kmalloc(count, GFP_KERNEL);
	if (!buf) {
		rv = -ENOMEM;
		goto outnl;
	}

	r = copy_from_user(buf, buffer, count);
	if (r > 0) {
		kfree(buf);
		rv = -EFAULT;
		goto outnl;
	}

	/* concurrent writes and disconnect */
	r = mutex_lock_interruptible(&desc->wlock);
	rv = -ERESTARTSYS;
	if (r) {
		kfree(buf);
		goto outnl;
	}

	if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
		kfree(buf);
		rv = -ENODEV;
		goto outnp;
	}

	r = usb_autopm_get_interface(desc->intf);
	if (r < 0) {
		kfree(buf);
		goto outnp;
	}

	if (!(file->f_flags & O_NONBLOCK))
		r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE,
								&desc->flags));
	else
		if (test_bit(WDM_IN_USE, &desc->flags))
			r = -EAGAIN;
	if (r < 0) {
		kfree(buf);
		goto out;
	}

	req = desc->orq;
	usb_fill_control_urb(
		desc->command,
		interface_to_usbdev(desc->intf),
		/* using common endpoint 0 */
		usb_sndctrlpipe(interface_to_usbdev(desc->intf), 0),
		(unsigned char *)req,
		buf,
		count,
		wdm_out_callback,
		desc
	);

	req->bRequestType = (USB_DIR_OUT | USB_TYPE_CLASS |
			     USB_RECIP_INTERFACE);
	req->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND;
	req->wValue = 0;
	req->wIndex = desc->inum;
	req->wLength = cpu_to_le16(count);
	set_bit(WDM_IN_USE, &desc->flags);
	desc->outbuf = buf;

	rv = usb_submit_urb(desc->command, GFP_KERNEL);
	if (rv < 0) {
		kfree(buf);
		desc->outbuf = NULL;
		clear_bit(WDM_IN_USE, &desc->flags);
		dev_err(&desc->intf->dev, "Tx URB error: %d\n", rv);
	} else {
		dev_dbg(&desc->intf->dev, "Tx URB has been submitted index=%d",
			req->wIndex);
	}
out:
	usb_autopm_put_interface(desc->intf);
outnp:
	mutex_unlock(&desc->wlock);
outnl:
	return rv < 0 ? rv : count;
}
Пример #21
0
static int touch_event_handler(void *unused) {
    struct sched_param param = { .sched_priority = RTPM_PRIO_TPD }; 
    static int x1, y1, raw_x1, raw_y1;
    int temp_x1, temp_y1, temp_raw_x1, temp_raw_y1, temp_touch_dir, temp_contact_id;
    int report_id, touch_valid, contact_id, touch_dir, touch_need_sync;
    char buffer[10];
    int ret = -1;
    
    sched_setscheduler(current, SCHED_RR, &param); 
    do {
        set_current_state(TASK_INTERRUPTIBLE);
        while (tpd_halt) {tpd_flag = 0; msleep(20);}
        wait_event_interruptible(waiter, tpd_flag != 0);
        tpd_flag = 0;
        TPD_DEBUG_SET_TIME;
        set_current_state(TASK_RUNNING); 
        TPD_DEBUG("[mtk-tpd] touch interrupt\n");
        touch_need_sync = 0;
        temp_x1 = 0xFFFFFFFF;
        temp_y1 = 0xFFFFFFFF;
        temp_raw_x1 = 0xFFFFFFFF;
        temp_raw_y1 = 0xFFFFFFFF;
        temp_touch_dir = 0xFFFFFFFF;
        temp_contact_id = 0xFFFFFFFF;
        do
        {
            i2c_client->addr = i2c_client->addr & I2C_MASK_FLAG | I2C_DMA_FLAG | I2C_ENEXT_FLAG;
            ret = tpd_i2c_read(i2c_client, buffer, 10);
            if (ret != sizeof(buffer))
            {
                TPD_DEBUG("[mtk-tpd] i2c read communcate error: 0x%x\n", ret);
                continue;
            }
            i2c_client->addr = i2c_client->addr & I2C_MASK_FLAG;
            report_id = buffer[0];
            if (0x4 == report_id)
            {
            	touch_valid = buffer[1]>>7;
            	if (touch_valid)
            	{
            	    contact_id = (buffer[1]&0x7C)>>2;
            	    touch_dir = buffer[1]&0x1;
            	    raw_x1 = x1 = ((buffer[3] << 8) | buffer[2]);
                    raw_y1 = y1 = ((buffer[5] << 8) | buffer[4]);
                    TPD_DEBUG("[mtk-tpd]:id:%d, raw_x1:%d, raw_y1:%d\n", contact_id, raw_x1, raw_y1);
                    tpd_calibrate(&x1, &y1);
                    
                    if (((temp_x1 != x1) || (temp_y1 != y1) || (temp_contact_id != contact_id))
                        && (0xFFFFFFFF != temp_x1) && (0xFFFFFFFF != temp_y1))
                    {
                    	touch_need_sync = 1;
                        if (temp_touch_dir)
                        {
                    	    tpd_down(temp_raw_y1, temp_raw_x1, temp_y1, temp_x1, 1);
                        }
                        else
                        {
                    	    tpd_up(temp_raw_y1, temp_raw_x1, temp_y1, temp_x1, 0);
                        }
                    }
                    temp_x1 = x1;
                    temp_y1 = y1;
                    temp_raw_x1 = raw_x1;
                    temp_raw_y1 = raw_y1;
                    temp_touch_dir = touch_dir;
                    temp_contact_id = contact_id;
            	}
            	else
            	{
            	    TPD_DEBUG("[mtk-tpd]:Touch Invalid\n");
            	}
            }
            else
            {
                TPD_DEBUG("[mtk-tpd]:Invalid report ID:%d\n", buffer);
            }
        }while(!mt_get_gpio_in(GPIO_CTP_EINT_PIN));
Пример #22
0
static ssize_t wdm_read
(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
	int rv, cntr;
	int i = 0;
	struct wdm_device *desc = file->private_data;


	rv = mutex_lock_interruptible(&desc->rlock); /*concurrent reads */
	if (rv < 0)
		return -ERESTARTSYS;

	cntr = ACCESS_ONCE(desc->length);
	if (cntr == 0) {
		desc->read = 0;
retry:
		if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
			rv = -ENODEV;
			goto err;
		}
		if (test_bit(WDM_OVERFLOW, &desc->flags)) {
			clear_bit(WDM_OVERFLOW, &desc->flags);
			rv = -ENOBUFS;
			goto err;
		}
		i++;
		if (file->f_flags & O_NONBLOCK) {
			if (!test_bit(WDM_READ, &desc->flags)) {
				rv = cntr ? cntr : -EAGAIN;
				goto err;
			}
			rv = 0;
		} else {
			rv = wait_event_interruptible(desc->wait,
				test_bit(WDM_READ, &desc->flags));
		}

		/* may have happened while we slept */
		if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
			rv = -ENODEV;
			goto err;
		}
		usb_mark_last_busy(interface_to_usbdev(desc->intf));
		if (rv < 0) {
			rv = -ERESTARTSYS;
			goto err;
		}

		spin_lock_irq(&desc->iuspin);

		if (desc->rerr) { /* read completed, error happened */
			desc->rerr = 0;
			spin_unlock_irq(&desc->iuspin);
			rv = -EIO;
			goto err;
		}
		/*
		 * recheck whether we've lost the race
		 * against the completion handler
		 */
		if (!test_bit(WDM_READ, &desc->flags)) { /* lost race */
			spin_unlock_irq(&desc->iuspin);
			goto retry;
		}

		if (!desc->reslength) { /* zero length read */
			dev_dbg(&desc->intf->dev, "%s: zero length - clearing WDM_READ\n", __func__);
			clear_bit(WDM_READ, &desc->flags);
			spin_unlock_irq(&desc->iuspin);
			goto retry;
		}
		cntr = desc->length;
		spin_unlock_irq(&desc->iuspin);
	}

	if (cntr > count)
		cntr = count;
	rv = copy_to_user(buffer, desc->ubuf, cntr);
	if (rv > 0) {
		rv = -EFAULT;
		goto err;
	}

	spin_lock_irq(&desc->iuspin);

	for (i = 0; i < desc->length - cntr; i++)
		desc->ubuf[i] = desc->ubuf[i + cntr];

	desc->length -= cntr;
	/* in case we had outstanding data */
	if (!desc->length)
		clear_bit(WDM_READ, &desc->flags);

	spin_unlock_irq(&desc->iuspin);

	rv = cntr;

err:
	mutex_unlock(&desc->rlock);
	return rv;
}
Пример #23
0
/*
 * This function adds the card.
 *
 * This function follows the following major steps to set up the device -
 *      - Initialize software. This includes probing the card, registering
 *        the interface operations table, and allocating/initializing the
 *        adapter structure
 *      - Set up the netlink socket
 *      - Create and start the main work queue
 *      - Register the device
 *      - Initialize firmware and hardware
 *      - Add logical interfaces
 */
int
mwifiex_add_card(void *card, struct semaphore *sem,
		 struct mwifiex_if_ops *if_ops, u8 iface_type)
{
	struct mwifiex_adapter *adapter;

	if (down_interruptible(sem))
		goto exit_sem_err;

	if (mwifiex_register(card, if_ops, (void **)&adapter)) {
		pr_err("%s: software init failed\n", __func__);
		goto err_init_sw;
	}

	adapter->iface_type = iface_type;
	adapter->card_sem = sem;

	adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
	adapter->surprise_removed = false;
	init_waitqueue_head(&adapter->init_wait_q);
	adapter->is_suspended = false;
	adapter->hs_activated = false;
	init_waitqueue_head(&adapter->hs_activate_wait_q);
	init_waitqueue_head(&adapter->cmd_wait_q.wait);
	adapter->cmd_wait_q.status = 0;
	adapter->scan_wait_q_woken = false;

	if ((num_possible_cpus() > 1) || adapter->iface_type == MWIFIEX_USB) {
		adapter->rx_work_enabled = true;
		pr_notice("rx work enabled, cpus %d\n", num_possible_cpus());
	}

	adapter->workqueue =
		alloc_workqueue("MWIFIEX_WORK_QUEUE",
				WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
	if (!adapter->workqueue)
		goto err_kmalloc;

	INIT_WORK(&adapter->main_work, mwifiex_main_work_queue);

	if (adapter->rx_work_enabled) {
		adapter->rx_workqueue = alloc_workqueue("MWIFIEX_RX_WORK_QUEUE",
							WQ_HIGHPRI |
							WQ_MEM_RECLAIM |
							WQ_UNBOUND, 1);
		if (!adapter->rx_workqueue)
			goto err_kmalloc;

		INIT_WORK(&adapter->rx_work, mwifiex_rx_work_queue);
	}

	/* Register the device. Fill up the private data structure with relevant
	   information from the card. */
	if (adapter->if_ops.register_dev(adapter)) {
		pr_err("%s: failed to register mwifiex device\n", __func__);
		goto err_registerdev;
	}

	if (mwifiex_init_hw_fw(adapter)) {
		pr_err("%s: firmware init failed\n", __func__);
		goto err_init_fw;
	}

	return 0;

err_init_fw:
	pr_debug("info: %s: unregister device\n", __func__);
	if (adapter->if_ops.unregister_dev)
		adapter->if_ops.unregister_dev(adapter);
	if (adapter->hw_status == MWIFIEX_HW_STATUS_READY) {
		pr_debug("info: %s: shutdown mwifiex\n", __func__);
		adapter->init_wait_q_woken = false;

		if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
			wait_event_interruptible(adapter->init_wait_q,
						 adapter->init_wait_q_woken);
	}
err_registerdev:
	adapter->surprise_removed = true;
	mwifiex_terminate_workqueue(adapter);
err_kmalloc:
	mwifiex_free_adapter(adapter);

err_init_sw:
	up(sem);

exit_sem_err:
	return -1;
}
Пример #24
0
int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
		enum autofs_notify notify)
{
	struct autofs_info *ino;
	struct autofs_wait_queue *wq;
	char *name;
	unsigned int len = 0;
	unsigned int hash = 0;
	int status, type;

	/* In catatonic mode, we don't wait for nobody */
	if (sbi->catatonic)
		return -ENOENT;
	
	name = kmalloc(NAME_MAX + 1, GFP_KERNEL);
	if (!name)
		return -ENOMEM;

	/* If this is a direct mount request create a dummy name */
	if (IS_ROOT(tx_cache_get_dentry(dentry)) && (sbi->type & AUTOFS_TYPE_DIRECT))
		len = sprintf(name, "%p", dentry);
	else {
		len = autofs4_getpath(sbi, dentry, &name);
		if (!len) {
			kfree(name);
			return -ENOENT;
		}
	}
	hash = full_name_hash(name, len);

	if (mutex_lock_interruptible(&sbi->wq_mutex)) {
		kfree(name);
		return -EINTR;
	}

	wq = autofs4_find_wait(sbi, name, hash, len);
	ino = autofs4_dentry_ino(dentry);
	if (!wq && ino && notify == NFY_NONE) {
		/*
		 * Either we've betean the pending expire to post it's
		 * wait or it finished while we waited on the mutex.
		 * So we need to wait till either, the wait appears
		 * or the expire finishes.
		 */

		while (ino->flags & AUTOFS_INF_EXPIRING) {
			mutex_unlock(&sbi->wq_mutex);
			schedule_timeout_interruptible(HZ/10);
			if (mutex_lock_interruptible(&sbi->wq_mutex)) {
				kfree(name);
				return -EINTR;
			}
			wq = autofs4_find_wait(sbi, name, hash, len);
			if (wq)
				break;
		}

		/*
		 * Not ideal but the status has already gone. Of the two
		 * cases where we wait on NFY_NONE neither depend on the
		 * return status of the wait.
		 */
		if (!wq) {
			kfree(name);
			mutex_unlock(&sbi->wq_mutex);
			return 0;
		}
	}

	if (!wq) {
		/* Create a new wait queue */
		wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL);
		if (!wq) {
			kfree(name);
			mutex_unlock(&sbi->wq_mutex);
			return -ENOMEM;
		}

		wq->wait_queue_token = autofs4_next_wait_queue;
		if (++autofs4_next_wait_queue == 0)
			autofs4_next_wait_queue = 1;
		wq->next = sbi->queues;
		sbi->queues = wq;
		init_waitqueue_head(&wq->queue);
		wq->hash = hash;
		wq->name = name;
		wq->len = len;
		wq->dev = autofs4_get_dev(sbi);
		wq->ino = autofs4_get_ino(sbi);
		wq->uid = current->uid;
		wq->gid = current->gid;
		wq->pid = current->pid;
		wq->tgid = current->tgid;
		wq->status = -EINTR; /* Status return if interrupted */
		atomic_set(&wq->wait_ctr, 2);
		mutex_unlock(&sbi->wq_mutex);

		if (sbi->version < 5) {
			if (notify == NFY_MOUNT)
				type = autofs_ptype_missing;
			else
				type = autofs_ptype_expire_multi;
		} else {
			if (notify == NFY_MOUNT)
				type = (sbi->type & AUTOFS_TYPE_DIRECT) ?
					autofs_ptype_missing_direct :
					 autofs_ptype_missing_indirect;
			else
				type = (sbi->type & AUTOFS_TYPE_DIRECT) ?
					autofs_ptype_expire_direct :
					autofs_ptype_expire_indirect;
		}

		DPRINTK("new wait id = 0x%08lx, name = %.*s, nfy=%d\n",
			(unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);

		/* autofs4_notify_daemon() may block */
		autofs4_notify_daemon(sbi, wq, type);
	} else {
		atomic_inc(&wq->wait_ctr);
		mutex_unlock(&sbi->wq_mutex);
		kfree(name);
		DPRINTK("existing wait id = 0x%08lx, name = %.*s, nfy=%d",
			(unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);
	}

	/* wq->name is NULL if and only if the lock is already released */

	if (sbi->catatonic) {
		/* We might have slept, so check again for catatonic mode */
		wq->status = -ENOENT;
		kfree(wq->name);
		wq->name = NULL;
	}

	if (wq->name) {
		/* Block all but "shutdown" signals while waiting */
		sigset_t oldset;
		unsigned long irqflags;

		spin_lock_irqsave(&current->sighand->siglock, irqflags);
		oldset = current->blocked;
		siginitsetinv(&current->blocked, SHUTDOWN_SIGS & ~oldset.sig[0]);
		recalc_sigpending();
		spin_unlock_irqrestore(&current->sighand->siglock, irqflags);

		wait_event_interruptible(wq->queue, wq->name == NULL);

		spin_lock_irqsave(&current->sighand->siglock, irqflags);
		current->blocked = oldset;
		recalc_sigpending();
		spin_unlock_irqrestore(&current->sighand->siglock, irqflags);
	} else {
		DPRINTK("skipped sleeping");
	}

	status = wq->status;

	/* Are we the last process to need status? */
	if (atomic_dec_and_test(&wq->wait_ctr))
		kfree(wq);

	return status;
}
Пример #25
0
/*
 * This function gets firmware and initializes it.
 *
 * The main initialization steps followed are -
 *      - Download the correct firmware to card
 *      - Issue the init commands to firmware
 */
static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
{
	int ret;
	char fmt[64];
	struct mwifiex_private *priv;
	struct mwifiex_adapter *adapter = context;
	struct mwifiex_fw_image fw;
	struct semaphore *sem = adapter->card_sem;
	bool init_failed = false;
	struct wireless_dev *wdev;

	if (!firmware) {
		mwifiex_dbg(adapter, ERROR,
			    "Failed to get firmware %s\n", adapter->fw_name);
		goto err_dnld_fw;
	}

	memset(&fw, 0, sizeof(struct mwifiex_fw_image));
	adapter->firmware = firmware;
	fw.fw_buf = (u8 *) adapter->firmware->data;
	fw.fw_len = adapter->firmware->size;

	if (adapter->if_ops.dnld_fw) {
		ret = adapter->if_ops.dnld_fw(adapter, &fw);
	} else {
		ret = mwifiex_dnld_fw(adapter, &fw);
	}

	if (ret == -1)
		goto err_dnld_fw;

	mwifiex_dbg(adapter, MSG, "WLAN FW is active\n");

	if (cal_data_cfg) {
		if ((request_firmware(&adapter->cal_data, cal_data_cfg,
				      adapter->dev)) < 0)
			mwifiex_dbg(adapter, ERROR,
				    "Cal data request_firmware() failed\n");
	}

	/* enable host interrupt after fw dnld is successful */
	if (adapter->if_ops.enable_int) {
		if (adapter->if_ops.enable_int(adapter))
			goto err_dnld_fw;
	}

	adapter->init_wait_q_woken = false;
	ret = mwifiex_init_fw(adapter);
	if (ret == -1) {
		goto err_init_fw;
	} else if (!ret) {
		adapter->hw_status = MWIFIEX_HW_STATUS_READY;
		goto done;
	}
	/* Wait for mwifiex_init to complete */
	wait_event_interruptible(adapter->init_wait_q,
				 adapter->init_wait_q_woken);
	if (adapter->hw_status != MWIFIEX_HW_STATUS_READY)
		goto err_init_fw;

	priv = adapter->priv[MWIFIEX_BSS_ROLE_STA];
	if (mwifiex_register_cfg80211(adapter)) {
		mwifiex_dbg(adapter, ERROR,
			    "cannot register with cfg80211\n");
		goto err_init_fw;
	}

	if (mwifiex_init_channel_scan_gap(adapter)) {
		mwifiex_dbg(adapter, ERROR,
			    "could not init channel stats table\n");
		goto err_init_fw;
	}

	if (driver_mode) {
		driver_mode &= MWIFIEX_DRIVER_MODE_BITMASK;
		driver_mode |= MWIFIEX_DRIVER_MODE_STA;
	}

	rtnl_lock();
	/* Create station interface by default */
	wdev = mwifiex_add_virtual_intf(adapter->wiphy, "mlan%d", NET_NAME_ENUM,
					NL80211_IFTYPE_STATION, NULL, NULL);
	if (IS_ERR(wdev)) {
		mwifiex_dbg(adapter, ERROR,
			    "cannot create default STA interface\n");
		rtnl_unlock();
		goto err_add_intf;
	}

	if (driver_mode & MWIFIEX_DRIVER_MODE_UAP) {
		wdev = mwifiex_add_virtual_intf(adapter->wiphy, "uap%d", NET_NAME_ENUM,
						NL80211_IFTYPE_AP, NULL, NULL);
		if (IS_ERR(wdev)) {
			mwifiex_dbg(adapter, ERROR,
				    "cannot create AP interface\n");
			rtnl_unlock();
			goto err_add_intf;
		}
	}

	if (driver_mode & MWIFIEX_DRIVER_MODE_P2P) {
		wdev = mwifiex_add_virtual_intf(adapter->wiphy, "p2p%d", NET_NAME_ENUM,
						NL80211_IFTYPE_P2P_CLIENT, NULL,
						NULL);
		if (IS_ERR(wdev)) {
			mwifiex_dbg(adapter, ERROR,
				    "cannot create p2p client interface\n");
			rtnl_unlock();
			goto err_add_intf;
		}
	}
	rtnl_unlock();

	mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1);
	mwifiex_dbg(adapter, MSG, "driver_version = %s\n", fmt);
	goto done;

err_add_intf:
	wiphy_unregister(adapter->wiphy);
	wiphy_free(adapter->wiphy);
err_init_fw:
	if (adapter->if_ops.disable_int)
		adapter->if_ops.disable_int(adapter);
err_dnld_fw:
	mwifiex_dbg(adapter, ERROR,
		    "info: %s: unregister device\n", __func__);
	if (adapter->if_ops.unregister_dev)
		adapter->if_ops.unregister_dev(adapter);

	if (adapter->hw_status == MWIFIEX_HW_STATUS_READY) {
		pr_debug("info: %s: shutdown mwifiex\n", __func__);
		adapter->init_wait_q_woken = false;

		if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
			wait_event_interruptible(adapter->init_wait_q,
						 adapter->init_wait_q_woken);
	}
	adapter->surprise_removed = true;
	mwifiex_terminate_workqueue(adapter);
	init_failed = true;
done:
	if (adapter->cal_data) {
		release_firmware(adapter->cal_data);
		adapter->cal_data = NULL;
	}
	if (adapter->firmware) {
		release_firmware(adapter->firmware);
		adapter->firmware = NULL;
	}
	if (init_failed)
		mwifiex_free_adapter(adapter);
	up(sem);
	return;
}
Пример #26
0
/*
 * Commands to do_syslog:
 *
 * 	0 -- Close the log.  Currently a NOP.
 * 	1 -- Open the log. Currently a NOP.
 * 	2 -- Read from the log.
 * 	3 -- Read all messages remaining in the ring buffer.
 * 	4 -- Read and clear all messages remaining in the ring buffer
 * 	5 -- Clear ring buffer.
 * 	6 -- Disable printk's to console
 * 	7 -- Enable printk's to console
 *	8 -- Set level of messages printed to console
 *	9 -- Return number of unread characters in the log buffer
 *     10 -- Return size of the log buffer
 */
int do_syslog(int type, char __user *buf, int len)
{
	unsigned i, j, limit, count;
	int do_clear = 0;
	char c;
	int error = 0;

	error = security_syslog(type);
	if (error)
		return error;

	switch (type) {
	case 0:		/* Close log */
		break;
	case 1:		/* Open log */
		break;
	case 2:		/* Read from log */
		error = -EINVAL;
		if (!buf || len < 0)
			goto out;
		error = 0;
		if (!len)
			goto out;
		if (!access_ok(VERIFY_WRITE, buf, len)) {
			error = -EFAULT;
			goto out;
		}
		error = wait_event_interruptible(log_wait,
							(log_start - log_end));
		if (error)
			goto out;
		i = 0;
		spin_lock_irq(&logbuf_lock);
		while (!error && (log_start != log_end) && i < len) {
			c = LOG_BUF(log_start);
			log_start++;
			spin_unlock_irq(&logbuf_lock);
			error = __put_user(c,buf);
			buf++;
			i++;
			cond_resched();
			spin_lock_irq(&logbuf_lock);
		}
		spin_unlock_irq(&logbuf_lock);
		if (!error)
			error = i;
		break;
	case 4:		/* Read/clear last kernel messages */
		do_clear = 1;
		/* FALL THRU */
	case 3:		/* Read last kernel messages */
		error = -EINVAL;
		if (!buf || len < 0)
			goto out;
		error = 0;
		if (!len)
			goto out;
		if (!access_ok(VERIFY_WRITE, buf, len)) {
			error = -EFAULT;
			goto out;
		}
		count = len;
		if (count > log_buf_len)
			count = log_buf_len;
		spin_lock_irq(&logbuf_lock);
		if (count > logged_chars)
			count = logged_chars;
		if (do_clear)
			logged_chars = 0;
		limit = log_end;
		/*
		 * __put_user() could sleep, and while we sleep
		 * printk() could overwrite the messages
		 * we try to copy to user space. Therefore
		 * the messages are copied in reverse. <manfreds>
		 */
		for (i = 0; i < count && !error; i++) {
			j = limit-1-i;
			if (j + log_buf_len < log_end)
				break;
			c = LOG_BUF(j);
			spin_unlock_irq(&logbuf_lock);
			error = __put_user(c,&buf[count-1-i]);
			cond_resched();
			spin_lock_irq(&logbuf_lock);
		}
		spin_unlock_irq(&logbuf_lock);
		if (error)
			break;
		error = i;
		if (i != count) {
			int offset = count-error;
			/* buffer overflow during copy, correct user buffer. */
			for (i = 0; i < error; i++) {
				if (__get_user(c,&buf[i+offset]) ||
				    __put_user(c,&buf[i])) {
					error = -EFAULT;
					break;
				}
				cond_resched();
			}
		}
		break;
	case 5:		/* Clear ring buffer */
		logged_chars = 0;
		break;
	case 6:		/* Disable logging to console */
		console_loglevel = minimum_console_loglevel;
		break;
	case 7:		/* Enable logging to console */
		console_loglevel = default_console_loglevel;
		break;
	case 8:		/* Set level of messages printed to console */
		error = -EINVAL;
		if (len < 1 || len > 8)
			goto out;
		if (len < minimum_console_loglevel)
			len = minimum_console_loglevel;
		console_loglevel = len;
		error = 0;
		break;
	case 9:		/* Number of chars in the log buffer */
		error = log_end - log_start;
		break;
	case 10:	/* Size of the log buffer */
		error = log_buf_len;
		break;
	default:
		error = -EINVAL;
		break;
	}
out:
	return error;
}
Пример #27
0
//      read
//
//	wait until the teensy returns data
//
ssize_t
vote_read (struct file *file, char __user *buf, size_t count, loff_t *pos)
{
    struct usb_vote *vote_dev = file->private_data;
    int rc = 0;
    struct urb *vote_urb;	// usb request
    int wqrc = 0;		// return from wait queue
    int bytes_notcopied = 0;
    int copycount = 0;
    int actual_count;
    char *usbbuf;
    char vote_from_teensy;	// single character vote from teensy

    printk(KERN_NOTICE "In %s\n", __FUNCTION__);

    if (!access_ok(VERIFY_WRITE, buf, count))
        return -EINVAL;

    vote_urb = usb_alloc_urb(0, GFP_KERNEL);
    if (!vote_urb) return -ENOMEM;

    usbbuf = usb_buffer_alloc(
	vote_dev->udev,
	64,
	GFP_KERNEL,
	&vote_urb->transfer_dma
    );
    if (!usbbuf) {
	printk (KERN_NOTICE "%s: usb_buffer_alloc failed\n", __FUNCTION__);
	usb_buffer_free(
	    vote_dev->udev,
	    vote_urb->transfer_buffer_length,
	    vote_urb->transfer_buffer,
	    vote_urb->transfer_dma
	);
	return -ENOMEM;
    }

    usb_fill_int_urb(
	vote_urb,
	vote_dev->udev,
	usb_rcvintpipe(vote_dev->udev, vote_dev->intr_in_endpointAddr),
	usbbuf,
	64,
	(usb_complete_t) vote_read_intr_callback,
	vote_dev,
	250
    );

    vote_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

    // vote_dev->data_from_teensy = false;
    data_from_teensy = false;


    if ((rc = usb_submit_urb(vote_urb, GFP_KERNEL))) {
	err("%s - failed submitting write urb, error %d", __FUNCTION__, rc);
    }

    //
    // Wait until teensy returns data
    //		We will be awoken by our callback function,
    //		vote_read_intr_callback().
    //
    printk(KERN_DEBUG "%s: process %i (%s) going to sleep\n",
		      __FUNCTION__, current->pid, current->comm);

    wqrc = wait_event_interruptible(
	// vote_dev->wait4voter,
	// vote_dev->data_from_teensy == true
	wait4voter,
	data_from_teensy == true
    );

    if (wqrc ==  -ERESTARTSYS) {
	// Got a signal
	usb_buffer_free(
	    vote_urb->dev,
	    vote_urb->transfer_buffer_length,
	    vote_urb->transfer_buffer,
	    vote_urb->transfer_dma
	);

	printk(KERN_DEBUG "%s got signal while waiting: %i (%s):\n",
    		      __FUNCTION__, current->pid, current->comm);

	// What needs to be deallocated here??? kgb

	return -EINTR;
    }

    printk(KERN_DEBUG "%s awoken %i (%s):\n",
    		      __FUNCTION__, current->pid, current->comm);

    // the actual amount of data from the URB
    actual_count = vote_urb->actual_length;

    printk(KERN_NOTICE "%s: Actual Count in the URB = %d\n",
           __FUNCTION__, actual_count);

    // We are expecting exactly 1 byte from the teensy.
    if (actual_count == 1) {
	vote_from_teensy = ((char *) vote_urb->transfer_buffer)[0];
	// Set the vote in vote_dev->votecast
	// to reflect the voter's choice.
	// This is for viewing in sysfs.
	vote_dev->votecast = vote_from_teensy;
    }

    // actual_count is 64 bytes -- not the amount of data sent from teensy
    // kgb: Since we know its just one byte
    vote_from_teensy = ((char *) vote_urb->transfer_buffer)[0];
    vote_dev->votecast = vote_from_teensy;

    printk(KERN_NOTICE "%s: Vote from teensy. [%c]\n",
           __FUNCTION__, vote_dev->votecast);

    if(count <= actual_count)
        copycount = count;
    else
        copycount = actual_count;

    bytes_notcopied = copy_to_user(
	buf,
	(char *) vote_urb->transfer_buffer,
	copycount
    );

    if (bytes_notcopied != 0) {
	printk(KERN_NOTICE "%s: copy_to_user failed. \n", __FUNCTION__);
    }

    printk(KERN_NOTICE "%s: after copy_to_user. bytes_not_copied=%d \n",
           __FUNCTION__, bytes_notcopied);

    printk(KERN_NOTICE "%s: after copy_to_user. %c\n",
           __FUNCTION__, ((char *) vote_urb->transfer_buffer)[0]);

    // dealloc the URB
    usb_buffer_free(
        vote_urb->dev,
        vote_urb->transfer_buffer_length,
        vote_urb->transfer_buffer,
        vote_urb->transfer_dma
    );


    // return the number of bytes read
    return copycount;

} // vote_read()
static int touch_event_handler(void *unused) {
    struct sched_param param = { .sched_priority = RTPM_PRIO_TPD };
    int x1=0, y1=0, x2=0, y2=0, x3=0, y3=0, x4=0, y4=0, p1=0, p2=0, p3=0, p4=0, id1=0xf, id2=0xf, id3=0xf, id4 = 0xf, pre_id1 = 0xf, pre_id2 = 0xf, pre_id3 = 0xf, pre_id4 = 0xf, pre_tt_mode = 0, finger_num = 0, pre_num = 0;
    int raw_x1=0, raw_y1=0, raw_x2=0, raw_y2=0, raw_x3=0, raw_y3=0, raw_x4=0, raw_y4=0;
    static char toggle;
    static char buffer[32];//[16];
//    int pending = 0;
    u32 temp;
    sched_setscheduler(current, SCHED_RR, &param);
    g_temptimerdiff=get_jiffies_64();//jiffies;
    do {
        if(tpd_debuglog==1) {
            TPD_DMESG("[mtk-tpd] %s\n", __FUNCTION__);
        }
        set_current_state(TASK_INTERRUPTIBLE);
        if(tpd_debuglog==1)
            TPD_DMESG("[mtk-tpd], %s, tpd_halt=%d\n", __FUNCTION__, tpd_halt);
        while (tpd_halt) {
            tpd_flag = 0;
            msleep(20);
        }
#ifndef POLL_MODE
        wait_event_interruptible(waiter, tpd_flag != 0);
        tpd_flag = 0;
#endif
        TPD_DEBUG_SET_TIME;
        set_current_state(TASK_RUNNING);
        //	#ifndef CY8CTMA300_CHARGE
#if 0
        temp =  *(volatile u32 *)CHR_CON0;
        temp &= (1<<13);
        if(temp!=0)
        {
            if(tpd_debuglog==1)
                TPD_DMESG("[mtk-tpd], write 0x01 to 0x1D register!!\n");
            buffer[0] = 0x01;
            buffer[0] = 0x01;
            i2c_smbus_write_i2c_block_data(i2c_client, 0x1D, 1, &(buffer[0]));
        }
        else
        {
            if(tpd_debuglog==1)
                TPD_DMESG("[mtk-tpd], write 0x00 to 0x1D register!!\n");
            buffer[0] = 0x00;
            i2c_smbus_write_i2c_block_data(i2c_client, 0x1D, 1, &(buffer[0]));
        }
#endif
#ifndef TPD_NO_GPIO 	    // for mt6575T fpga early porting    
        if (tpd_show_version) {
            tpd_show_version = 0;

            mt_set_gpio_mode(GPIO1, 0x00);
            mt_set_gpio_dir(GPIO1, GPIO_DIR_OUT);
            mt_set_gpio_pull_enable(GPIO1, GPIO_PULL_ENABLE);
            mt_set_gpio_pull_select(GPIO1, GPIO_PULL_UP);

            mt_set_gpio_out(GPIO1, GPIO_OUT_ZERO);
            msleep(100);

            buffer[0] = 0x01; // reset touch panel mode
            i2c_smbus_write_i2c_block_data(i2c_client, 0x00, 1, &(buffer[0]));
            msleep(200);

            buffer[0] = 0x10; // swith to system information mode
            i2c_smbus_write_i2c_block_data(i2c_client, 0x00, 1, &(buffer[0]));
            msleep(200);

            i2c_smbus_read_i2c_block_data(i2c_client, 0x00, 8, &(buffer[0x0]));
            i2c_smbus_read_i2c_block_data(i2c_client, 0x08, 8, &(buffer[0x8]));
            i2c_smbus_read_i2c_block_data(i2c_client, 0x10, 8, &(buffer[0x10]));
            i2c_smbus_read_i2c_block_data(i2c_client, 0x18, 8, &(buffer[0x18]));
            printk("[mtk-tpd] Cypress Touch Panel ID %x.%x\n", buffer[0x07], buffer[0x08]);
            printk("[mtk-tpd] Cypress Touch Panel Firmware Version %x.%x\n", buffer[0x15], buffer[0x16]);
            buffer[0] = 0x04; // switch to operation mode
            i2c_smbus_write_i2c_block_data(i2c_client, 0x00, 1, &(buffer[0]));
            msleep(200);

            mt_set_gpio_out(GPIO1, GPIO_OUT_ONE);
            mt_set_gpio_mode(GPIO1, 0x01);
            mt_set_gpio_pull_enable(GPIO1, GPIO_PULL_ENABLE);
            mt_set_gpio_pull_select(GPIO1, GPIO_PULL_UP);
            continue;
        }
#endif
        i2c_smbus_read_i2c_block_data(i2c_client, 0x00, 8, &(buffer[0]));
        i2c_smbus_read_i2c_block_data(i2c_client, 0x08, 8, &(buffer[8]));
        i2c_smbus_read_i2c_block_data(i2c_client, 0x10, 8, &(buffer[16]));
        i2c_smbus_read_i2c_block_data(i2c_client, 0x18, 8, &(buffer[24]));
        if(tpd_debuglog==1)
        {
            TPD_DMESG("[mtk-tpd]HST_MODE  : %x\n", buffer[0]);
            TPD_DMESG("[mtk-tpd]TT_MODE   : %x\n", buffer[1]);
            TPD_DMESG("[mtk-tpd]TT_STAT   : %x\n", buffer[2]);
            // TPD_DEBUG("[mtk-tpd]TOUCH_ID  : %x\n", buffer[8]);
            TPD_DMESG("[mtk-tpd]TOUCH_12ID  : %x\n", buffer[8]);
            TPD_DMESG("[mtk-tpd]TOUCH_34ID  : %x\n", buffer[21]);
        }

        finger_num = buffer[2] & 0x0f;

        if (finger_num == 0 && pre_num ==0) {
            msleep(10);
            tpd_flag = 0;
            pre_tt_mode = buffer[1];
            continue;
        }

        if (pre_tt_mode == buffer[1]) {
            msleep(5);
            tpd_flag = 0;
            pre_tt_mode = buffer[1];
            continue;
        }

        if (buffer[1] & 0x20) {
            TPD_DEBUG("buffer not ready\n");
            tpd_flag = 0;
            pre_tt_mode = buffer[1];
            continue; // buffer is not ready for use
        }

        id1 = (buffer[8] & 0xf0) >> 4;
        id2 = (buffer[8] & 0x0f);
        id3 = (buffer[21] & 0xf0) >> 4;
        id4 = (buffer[21] & 0x0f);

//        if (id1 != 0xf) {
        if(finger_num>=1) {
            x1 = (((int)buffer[3]) << 8) + buffer[4];
            y1 = (((int)buffer[5]) << 8) + buffer[6];
            if(x1>2048 || y1>2048) {
                tpd_flag = 0;
                pre_tt_mode = buffer[1];
                continue;
            }
            p1 = buffer[7];
            raw_x1 = x1;
            raw_y1 = y1;
            tpd_calibrate(&x1, &y1);
            tpd_down(raw_x1, raw_y1, x1, y1, p1);
            if(counter_pointer==0)
                g_temptimerdiff=get_jiffies_64();//jiffies;
            if(x_min==0&&y_min==0&&x_max==0&&y_max==0) {
                x_min = x1;
                y_min = y1;
                x_max = x1;
                y_max = y1;
            }
            if(x1<x_min)
                x_min = x1;
            if(x1>x_max)
                x_max = x1;
            if(y1<y_min)
                y_min = y1;
            if(y1>y_max)
                y_max = y1;
            counter_pointer++;
            if (time_after(jiffies, g_temptimerdiff + 100)) {	//1s
                TPD_DMESG("[mtk-tpd], x_min=%d, y_min=%d, x_max=%d, y_max=%d, counter_pointer=%d!!\n", x_min, y_min, x_max, y_max, counter_pointer);
                x_min=0;
                y_min=0;
                x_max=0;
                y_max=0;
                counter_pointer=0;
            }
        }

//        if (id2 != 0xf || finger_num==2) {
        if(finger_num>=2) {
            x2 = (((int)buffer[9]) << 8) + buffer[10];
            y2 = (((int)buffer[11]) << 8) + buffer[12];
            p2 = buffer[13];
            raw_x2 = x2;
            raw_y2 = y2;
            tpd_calibrate(&x2, &y2);
            tpd_down(raw_x2, raw_y2, x2, y2, p2);
        }
//	if(id3 != 0xf || finger_num==3) {
        if(finger_num>=3) {
            x3 = (((int)buffer[16]) << 8) + buffer[17];
            y3= (((int)buffer[18]) << 8) + buffer[19];
            p3= buffer[20];
            raw_x3 = x3;
            raw_y3 = y3;
            tpd_calibrate(&x3, &y3);
            tpd_down(raw_x3, raw_y3, x3, y3, p3);
        }

//	if(id4 != 0xf || finger_num==4) {
        if(finger_num>=4) {
            x4 = (((int)buffer[22]) << 8) + buffer[23];
            y4= (((int)buffer[24]) << 8) + buffer[25];
            p4= buffer[26];
            raw_x4 = x4;
            raw_y4 = y4;
            tpd_calibrate(&x4, &y4);
            tpd_down(raw_x4, raw_y4, x4, y4, p4);
        }

        if(pre_num>=1 && pre_id1==0xf) {
            if(finger_num>=1 && id1==0xf) {
                if(tpd_debuglog==1)
                    TPD_DMESG("finger1 is still down!\n");
            } else {
                if(tpd_debuglog==1)
                    TPD_DMESG("finger1 is up!!\n");
                tpd_up(raw_x1, raw_y1, x1, y1, p1);
            }

        } else if(pre_num>=1 && pre_id1 !=0xf) {
            if(id1==pre_id1) {
                if(tpd_debuglog==1)
                    TPD_DMESG("finger1 is still down!!\n");
            } else {
                if(tpd_debuglog==1)
                    TPD_DMESG("finger1 is up!\n");
                tpd_up(raw_x1, raw_y1, x1, y1, p1);
            }
        }

        if(pre_num>=2 && pre_id2==0xf) {
            if((finger_num>=2 && id2==0xf) || (finger_num==1 && id1==0xf)) {
                if(tpd_debuglog==1)
                    TPD_DMESG("finger2 is still down!\n");
            } else {
                if(tpd_debuglog==1)
                    TPD_DMESG("finger2 is up!!\n");
                tpd_up(raw_x2, raw_y2, x2, y2, p2);
            }

        } else if(pre_num>=2 && pre_id2 !=0xf) {
            if(id2==pre_id2 || id1==pre_id2) {
                if(tpd_debuglog==1)
                    TPD_DMESG("finger2 is still down!!\n");
            } else {
                if(tpd_debuglog==1)
                    TPD_DMESG("finger2 is up!\n");
                tpd_up(raw_x2, raw_y2, x2, y2, p2);
            }
        }


        if(pre_num>=3 && pre_id3==0xf) {
            if((finger_num>=3 && id3==0xf) || (finger_num==2 && id2==0xf) || (finger_num==1 && id1==0xf)) {
                if(tpd_debuglog==1)
                    TPD_DMESG("finger3 is still down!\n");
            } else {
                if(tpd_debuglog==1)
                    TPD_DMESG("finger3 is up!!\n");
                tpd_up(raw_x3, raw_y3, x3, y3, p3);
            }

        } else if(pre_num>=3 && pre_id3 !=0xf) {
            if(id3==pre_id3 || id2==pre_id3 || id1==pre_id3) {
                if(tpd_debuglog==1)
                    TPD_DMESG("finger3 is still down!!\n");
            } else {
                if(tpd_debuglog==1)
                    TPD_DMESG("finger3 is up!\n");
                tpd_up(raw_x3, raw_y3, x3, y3, p3);
            }
        }

        if(pre_num==4 && pre_id4==0xf) {
            if((finger_num>=4 && id4==0xf) || (finger_num==3 && id3==0xf) || (finger_num==2 && id2==0xf) || (finger_num==1 && id1==0xf)) {
                if(tpd_debuglog==1)
                    TPD_DMESG("finger4 is still down!\n");
            } else {
                if(tpd_debuglog==1)
                    TPD_DMESG("finger4 is up!!\n");
                tpd_up(raw_x4, raw_y4, x4, y4, p4);
            }

        } else if(pre_num==4 && pre_id4 !=0xf) {
            if(id4==pre_id4 || id3==pre_id4 || id2==pre_id4 || id1==pre_id4) {
                if(tpd_debuglog==1)
                    TPD_DMESG("finger4 is still down!!\n");
            } else {
                if(tpd_debuglog==1)
                    TPD_DMESG("finger4 is up!\n");
                tpd_up(raw_x4, raw_y4, x4, y4, p4);
            }
        }
        if(tpd_debuglog==1)
            TPD_DMESG("pre_id1=%d, pre_id2=%d, pre_id3=%d, pre_id4=%d, id1=%d, id2=%d, id3=%d, id4=%d\n", pre_id1, pre_id2, pre_id3, pre_id4, id1, id2, id3, id4);
        pre_id1 = id1;
        pre_id2 = id2;
        pre_id3 = id3;
        pre_id4 = id4;
        pre_tt_mode = buffer[1];
        pre_num = finger_num;

        if(tpd && tpd->dev && tpd_register_flag==1) {
            input_sync(tpd->dev);
        }

        i2c_smbus_read_i2c_block_data(i2c_client, 0x00, 1, &toggle);
        if((toggle & 0x80) == 0)
            toggle = toggle | 0x80;
        else
            toggle = toggle & (~0x80);
        i2c_smbus_write_i2c_block_data(i2c_client, 0x00, 1, &toggle); // switch the read toggle bit to do next sampling
        tpd_flag = 0;
#ifndef POLL_MODE
    } while (!kthread_should_stop());
#else
    }
Пример #29
0
static ssize_t evtchn_read(struct file *file, char __user *buf,
			   size_t count, loff_t *ppos)
{
	int rc;
	unsigned int c, p, bytes1 = 0, bytes2 = 0;
	struct per_user_data *u = file->private_data;

	/* Whole number of ports. */
	count &= ~(sizeof(evtchn_port_t)-1);

	if (count == 0)
		return 0;

	if (count > PAGE_SIZE)
		count = PAGE_SIZE;

	for (;;) {
		mutex_lock(&u->ring_cons_mutex);

		rc = -EFBIG;
		if (u->ring_overflow)
			goto unlock_out;

		c = u->ring_cons;
		p = u->ring_prod;
		if (c != p)
			break;

		mutex_unlock(&u->ring_cons_mutex);

		if (file->f_flags & O_NONBLOCK)
			return -EAGAIN;

		rc = wait_event_interruptible(u->evtchn_wait,
					      u->ring_cons != u->ring_prod);
		if (rc)
			return rc;
	}

	/* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */
	if (((c ^ p) & EVTCHN_RING_SIZE) != 0) {
		bytes1 = (EVTCHN_RING_SIZE - EVTCHN_RING_MASK(c)) *
			sizeof(evtchn_port_t);
		bytes2 = EVTCHN_RING_MASK(p) * sizeof(evtchn_port_t);
	} else {
		bytes1 = (p - c) * sizeof(evtchn_port_t);
		bytes2 = 0;
	}

	/* Truncate chunks according to caller's maximum byte count. */
	if (bytes1 > count) {
		bytes1 = count;
		bytes2 = 0;
	} else if ((bytes1 + bytes2) > count) {
		bytes2 = count - bytes1;
	}

	rc = -EFAULT;
	rmb(); /* Ensure that we see the port before we copy it. */
	if (copy_to_user(buf, &u->ring[EVTCHN_RING_MASK(c)], bytes1) ||
	    ((bytes2 != 0) &&
	     copy_to_user(&buf[bytes1], &u->ring[0], bytes2)))
		goto unlock_out;

	u->ring_cons += (bytes1 + bytes2) / sizeof(evtchn_port_t);
	rc = bytes1 + bytes2;

 unlock_out:
	mutex_unlock(&u->ring_cons_mutex);
	return rc;
}
Пример #30
0
static ssize_t plx_drv_read(struct file *file, char __user *data,
			      size_t len, loff_t *ppos)
{


 int err;
 ssize_t retval = 0;

driver_t *dev = file->private_data;



 PDEBUG(("function: %s, file: %s line: %d invoked, dev %lx\n", __FUNCTION__, __FILE__, __LINE__, (unsigned long)dev)); 


   if(down_interruptible(&dev->read_semph))
	return -ERESTARTSYS;

   dev->cntr_read++;
/* Wait for interrupt handler to signal that it's OK to read */

  while (dev->rp == dev->wp) { /* nothing to read */

    PDEBUG(("function: %s, line: %d, wp and rp eq:%d\n", __FUNCTION__, __LINE__, dev->wp)); 
    up(&dev->read_semph); /* release the lock */
    if (file->f_flags & O_NONBLOCK)
      return -EAGAIN;
    PDEBUG(("\"%s\" reading: going to sleep\n", current->comm));
    if (wait_event_interruptible(dev->read_queue, (dev->rp != dev->wp)))
      return -ERESTARTSYS; /* signal: tell the fs layer to handle it */
    /* otherwise loop, but first reacquire the lock */
    if (down_interruptible(&dev->read_semph))
     return -ERESTARTSYS;

  }


/* Copy to user space */

PDEBUG(("function: %s, line: %d, data: %x, frame addr: %lx , len: %lx, rp%d\n", __FUNCTION__, __LINE__, (unsigned int)data, (unsigned long)dev->frames[dev->rp],(unsigned long)len, dev->rp)); 
  err = copy_to_user(data, (void *) dev->frames[dev->rp],len);
    if (err) {
      ERROR(("function: %s, line: %d, couldn't copy to user\n", __FUNCTION__, __LINE__)); 
      retval = -EFAULT;
      goto out;
    }

   dev->cntr_2_user_space++;

  /* This should never occur! */
    if (dev->rp == dev->ip) {
     ERROR(("function: %s, line: %d, ERROR rp reached ip :%d\n", __FUNCTION__, __LINE__, dev->rp)); 
     dev->cntr_circ_empty_rp++;
     return -EFAULT;
    }

    /* Increment read pointer and check for wrap */
    dev->rp++;
        if (dev->rp == NO_OF_BUFFERS)
                dev->rp = 0;

    PDEBUG(("function: %s, after copy_to_user read time:%d\n", __FUNCTION__, plx_diff_since_read(dev))); 
 
 
    /* Nonnegative value represents successfully read bytes */
    retval = len;




out:

/* Unlock .. */
up(&dev->read_semph);


 return retval;
}