Example #1
0
static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr,
			   const char *buf, size_t count)
{
	struct cardstate *cs = dev_get_drvdata(dev);
	long int value;
	char *end;

	value = simple_strtol(buf, &end, 0);
	while (*end)
		if (!isspace(*end++))
			return -EINVAL;
	if (value < 0 || value > 1)
			return -EINVAL;

	if (mutex_lock_interruptible(&cs->mutex))
		return -ERESTARTSYS;

	cs->waiting = 1;
	if (!gigaset_add_event(cs, &cs->at_state, EV_PROC_CIDMODE,
			       NULL, value, NULL)) {
		cs->waiting = 0;
		mutex_unlock(&cs->mutex);
		return -ENOMEM;
	}

	gig_dbg(DEBUG_CMD, "scheduling PROC_CIDMODE");
	gigaset_schedule_event(cs);

	wait_event(cs->waitqueue, !cs->waiting);

	mutex_unlock(&cs->mutex);

	return count;
}
Example #2
0
static int if_version(struct cardstate *cs, unsigned arg[4])
{
	static const unsigned version[4] = GIG_VERSION;
	static const unsigned compat[4] = GIG_COMPAT;
	unsigned cmd = arg[0];

	gig_dbg(DEBUG_IF, "%u: if_version (%d)", cs->minor_index, cmd);

	switch (cmd) {
	case GIGVER_DRIVER:
		memcpy(arg, version, sizeof version);
		return 0;
	case GIGVER_COMPAT:
		memcpy(arg, compat, sizeof compat);
		return 0;
	case GIGVER_FWBASE:
		cs->waiting = 1;
		if (!gigaset_add_event(cs, &cs->at_state, EV_IF_VER,
				       NULL, 0, arg)) {
			cs->waiting = 0;
			return -ENOMEM;
		}
		gigaset_schedule_event(cs);

		wait_event(cs->waitqueue, !cs->waiting);

		if (cs->cmd_result >= 0)
			return 0;

		return cs->cmd_result;
	default:
		return -EINVAL;
	}
}
Example #3
0
/**
 *	gigaset_read_int_callback
 *
 *	It is called if the data was received from the device.
 */
static void gigaset_read_int_callback(struct urb *urb, struct pt_regs *regs)
{
	struct inbuf_t *inbuf = urb->context;
	struct cardstate *cs = inbuf->cs;
	int resubmit = 0;
	int r;
	unsigned numbytes;
	unsigned char *src;
	unsigned long flags;

	if (!urb->status) {
		if (!cs->connected) {
			err("%s: disconnected", __func__); /* should never happen */
			return;
		}

		numbytes = urb->actual_length;

		if (numbytes) {
			src = inbuf->rcvbuf;
			if (unlikely(*src))
				dev_warn(cs->dev,
				    "%s: There was no leading 0, but 0x%02x!\n",
					 __func__, (unsigned) *src);
			++src; /* skip leading 0x00 */
			--numbytes;
			if (gigaset_fill_inbuf(inbuf, src, numbytes)) {
				gig_dbg(DEBUG_INTR, "%s-->BH", __func__);
				gigaset_schedule_event(inbuf->cs);
			}
		} else
			gig_dbg(DEBUG_INTR, "Received zero block length");
		resubmit = 1;
	} else {
		/* The urb might have been killed. */
		gig_dbg(DEBUG_ANY, "%s - nonzero read bulk status received: %d",
			__func__, urb->status);
		if (urb->status != -ENOENT) { /* not killed */
			if (!cs->connected) {
				err("%s: disconnected", __func__); /* should never happen */
				return;
			}
			resubmit = 1;
		}
	}

	if (resubmit) {
		spin_lock_irqsave(&cs->lock, flags);
		r = cs->connected ? usb_submit_urb(urb, SLAB_ATOMIC) : -ENODEV;
		spin_unlock_irqrestore(&cs->lock, flags);
		if (r)
			dev_err(cs->dev, "error %d when resubmitting urb.\n",
				-r);
	}
}
/*
 * Interrupt Input URB completion routine
 */
static void gigaset_read_int_callback(struct urb *urb)
{
	struct cardstate *cs = urb->context;
	struct inbuf_t *inbuf = cs->inbuf;
	int status = urb->status;
	int r;
	unsigned numbytes;
	unsigned char *src;
	unsigned long flags;

	if (!status) {
		numbytes = urb->actual_length;

		if (numbytes) {
			src = cs->hw.usb->rcvbuf;
			if (unlikely(*src))
				dev_warn(cs->dev,
				    "%s: There was no leading 0, but 0x%02x!\n",
					 __func__, (unsigned) *src);
			++src; /* skip leading 0x00 */
			--numbytes;
			if (gigaset_fill_inbuf(inbuf, src, numbytes)) {
				gig_dbg(DEBUG_INTR, "%s-->BH", __func__);
				gigaset_schedule_event(inbuf->cs);
			}
		} else
			gig_dbg(DEBUG_INTR, "Received zero block length");
	} else {
		/* The urb might have been killed. */
		gig_dbg(DEBUG_ANY, "%s - nonzero status received: %d",
			__func__, status);
		if (status == -ENOENT || status == -ESHUTDOWN)
			/* killed or endpoint shutdown: don't resubmit */
			return;
	}

	/* resubmit URB */
	spin_lock_irqsave(&cs->lock, flags);
	if (!cs->connected) {
		spin_unlock_irqrestore(&cs->lock, flags);
		pr_err("%s: disconnected\n", __func__);
		return;
	}
	r = usb_submit_urb(urb, GFP_ATOMIC);
	spin_unlock_irqrestore(&cs->lock, flags);
	if (r)
		dev_err(cs->dev, "error %d resubmitting URB\n", -r);
}
Example #5
0
static int if_lock(struct cardstate *cs, int *arg)
{
	int cmd = *arg;

	gig_dbg(DEBUG_IF, "%u: if_lock (%d)", cs->minor_index, cmd);

	if (cmd > 1)
		return -EINVAL;

	if (cmd < 0) {
		*arg = cs->mstate == MS_LOCKED;
		return 0;
	}

	if (!cmd && cs->mstate == MS_LOCKED && cs->connected) {
		cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS);
		cs->ops->baud_rate(cs, B115200);
		cs->ops->set_line_ctrl(cs, CS8);
		cs->control_state = TIOCM_DTR|TIOCM_RTS;
	}

	cs->waiting = 1;
	if (!gigaset_add_event(cs, &cs->at_state, EV_IF_LOCK,
			       NULL, cmd, NULL)) {
		cs->waiting = 0;
		return -ENOMEM;
	}

	gig_dbg(DEBUG_CMD, "scheduling IF_LOCK");
	gigaset_schedule_event(cs);

	wait_event(cs->waitqueue, !cs->waiting);

	if (cs->cmd_result >= 0) {
		*arg = cs->cmd_result;
		return 0;
	}

	return cs->cmd_result;
}