コード例 #1
0
int ctrl_bridge_resume(unsigned int id)
{
	struct ctrl_bridge	*dev;
	struct urb		*urb;

	if (id >= MAX_BRIDGE_DEVICES)
		return -EINVAL;

	dev = __dev[id];
	if (!dev)
		return -ENODEV;

	if (!test_and_clear_bit(SUSPENDED, &dev->flags))
		return 0;

	/* submit pending write requests */
	while ((urb = usb_get_from_anchor(&dev->tx_deferred))) {
		int ret;
		usb_anchor_urb(urb, &dev->tx_submitted);
		ret = usb_submit_urb(urb, GFP_ATOMIC);
		if (ret < 0) {
			usb_unanchor_urb(urb);
			kfree(urb->setup_packet);
			kfree(urb->transfer_buffer);
			usb_free_urb(urb);
			usb_autopm_put_interface_async(dev->intf);
		}
	}

	return ctrl_bridge_start_read(dev);
}
コード例 #2
0
int ctrl_bridge_resume(unsigned int id)
{
	struct ctrl_bridge	*dev;
	struct urb		*urb;

	if (id >= MAX_BRIDGE_DEVICES)
		return -EINVAL;

	dev = __dev[id];
	if (!dev)
		return -ENODEV;

	if (!test_and_clear_bit(SUSPENDED, &dev->flags))
		return 0;

	/* submit pending write requests */
	while ((urb = usb_get_from_anchor(&dev->tx_deferred))) {
		int ret;
		usb_anchor_urb(urb, &dev->tx_submitted);
		ret = usb_submit_urb(urb, GFP_ATOMIC);
		if (ret < 0) {
			usb_unanchor_urb(urb);
			kfree(urb->setup_packet);
			kfree(urb->transfer_buffer);
			usb_free_urb(urb);
			usb_autopm_put_interface_async(dev->intf);
		}
	}

	/* if the bridge is open, resume reading */
#ifndef CONFIG_MDM_HSIC_PM
	if (dev->brdg)
		return ctrl_bridge_start_read(dev);
#else
	/* if the bridge is open or not, resume to consume mdm request
	 * because this link is not dead, it's alive
	 */
	return ctrl_bridge_start_read(dev);
#endif
	return 0;
}
コード例 #3
0
static void resp_avail_cb(struct urb *urb)
{
	struct ctrl_bridge	*dev = urb->context;
	int			resubmit_urb = 1;
	struct bridge		*brdg = dev->brdg;
	unsigned long		flags;

	/*usb device disconnect*/
	if (urb->dev->state == USB_STATE_NOTATTACHED)
		return;

	switch (urb->status) {
	case 0:
		/*success*/
		dev->get_encap_res++;
		if (brdg && brdg->ops.send_pkt)
			brdg->ops.send_pkt(brdg->ctx, urb->transfer_buffer,
				urb->actual_length);
		break;

	/*do not resubmit*/
	case -ESHUTDOWN:
	case -ENOENT:
	case -ECONNRESET:
		/* unplug */
	case -EPROTO:
		/*babble error*/
		resubmit_urb = 0;
	/*resubmit*/
	case -EOVERFLOW:
	default:
		dev_dbg(&dev->intf->dev, "%s: non zero urb status = %d\n",
			__func__, urb->status);
	}

	if (resubmit_urb) {
		/*re- submit int urb to check response available*/
		ctrl_bridge_start_read(dev, GFP_ATOMIC);
	} else {
		spin_lock_irqsave(&dev->lock, flags);
		dev->rx_state = RX_IDLE;
		spin_unlock_irqrestore(&dev->lock, flags);
	}

	usb_autopm_put_interface_async(dev->intf);
}
int ctrl_bridge_resume(unsigned int id)
{
    struct ctrl_bridge	*dev;
    struct urb		*urb;
    unsigned long		flags;
    int			ret;

    if (id >= MAX_BRIDGE_DEVICES)
        return -EINVAL;

    dev = __dev[id];
    if (!dev)
        return -ENODEV;
    if (!dev->int_pipe)
        return 0;
    if (!test_bit(SUSPENDED, &dev->flags))
        return 0;

    spin_lock_irqsave(&dev->lock, flags);
    /* submit pending write requests */
    while ((urb = usb_get_from_anchor(&dev->tx_deferred))) {
        spin_unlock_irqrestore(&dev->lock, flags);
        /*
         * usb_get_from_anchor() does not drop the
         * ref count incremented by the usb_anchro_urb()
         * called in Tx submission path. Let us do it.
         */
        usb_put_urb(urb);
        usb_anchor_urb(urb, &dev->tx_submitted);
        ret = usb_submit_urb(urb, GFP_ATOMIC);
        if (ret < 0) {
            usb_unanchor_urb(urb);
            kfree(urb->setup_packet);
            kfree(urb->transfer_buffer);
            usb_free_urb(urb);
            usb_autopm_put_interface_async(dev->intf);
        }
        spin_lock_irqsave(&dev->lock, flags);
    }
    clear_bit(SUSPENDED, &dev->flags);
    spin_unlock_irqrestore(&dev->lock, flags);

    return ctrl_bridge_start_read(dev, GFP_KERNEL);
}
int ctrl_bridge_suspend(unsigned int id)
{
    struct ctrl_bridge	*dev;
    unsigned long		flags;

    if (id >= MAX_BRIDGE_DEVICES)
        return -EINVAL;

    dev = __dev[id];
    if (!dev)
        return -ENODEV;
    if (!dev->int_pipe)
        return 0;

    spin_lock_irqsave(&dev->lock, flags);
    if (!usb_anchor_empty(&dev->tx_submitted) || dev->rx_state == RX_BUSY) {
        spin_unlock_irqrestore(&dev->lock, flags);
        return -EBUSY;
    }
    spin_unlock_irqrestore(&dev->lock, flags);

    usb_kill_urb(dev->inturb);

    spin_lock_irqsave(&dev->lock, flags);
    if (dev->rx_state != RX_IDLE) {
        spin_unlock_irqrestore(&dev->lock, flags);
        return -EBUSY;
    }
    if (!usb_anchor_empty(&dev->tx_submitted)) {
        spin_unlock_irqrestore(&dev->lock, flags);
        ctrl_bridge_start_read(dev, GFP_KERNEL);
        return -EBUSY;
    }
    set_bit(SUSPENDED, &dev->flags);
    spin_unlock_irqrestore(&dev->lock, flags);

    return 0;
}
コード例 #6
0
int ctrl_bridge_open(struct bridge *brdg)
{
	struct ctrl_bridge	*dev;
	int			ret;

	if (!brdg) {
		err("bridge is null\n");
		return -EINVAL;
	}

	if (brdg->ch_id >= MAX_BRIDGE_DEVICES)
		return -EINVAL;

	dev = __dev[brdg->ch_id];
	if (!dev) {
		err("dev is null\n");
		return -ENODEV;
	}

	dev->brdg = brdg;
	dev->snd_encap_cmd = 0;
	dev->get_encap_res = 0;
	dev->resp_avail = 0;
	dev->set_ctrl_line_sts = 0;
	dev->notify_ser_state = 0;

	ret = usb_autopm_get_interface(dev->intf);
	if (ret < 0) {
		dev_err(&dev->udev->dev, "%s autopm_get fail: %d\n",
			__func__, ret);
		return ret;
	}

	ret = ctrl_bridge_start_read(dev);
	usb_autopm_put_interface(dev->intf);
	return ret;
}
コード例 #7
0
int
ctrl_bridge_probe(struct usb_interface *ifc, struct usb_host_endpoint *int_in,
		int id)
{
	struct ctrl_bridge		*dev;
	struct usb_device		*udev;
	struct usb_endpoint_descriptor	*ep;
	u16				wMaxPacketSize;
	int				retval = 0;
	int				interval;

	udev = interface_to_usbdev(ifc);

	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
	if (!dev) {
		dev_err(&ifc->dev, "%s: unable to allocate dev\n",
			__func__);
		return -ENOMEM;
	}
	dev->pdev = platform_device_alloc(ctrl_bridge_names[id], id);
	if (!dev->pdev) {
		dev_err(&ifc->dev, "%s: unable to allocate platform device\n",
			__func__);
		retval = -ENOMEM;
		goto nomem;
	}

	dev->udev = udev;
	dev->int_pipe = usb_rcvintpipe(udev,
		int_in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
	dev->intf = ifc;

	init_usb_anchor(&dev->tx_submitted);
	init_usb_anchor(&dev->tx_deferred);

	/*use max pkt size from ep desc*/
	ep = &dev->intf->cur_altsetting->endpoint[0].desc;

	dev->inturb = usb_alloc_urb(0, GFP_KERNEL);
	if (!dev->inturb) {
		dev_err(&ifc->dev, "%s: error allocating int urb\n", __func__);
		retval = -ENOMEM;
		goto pdev_del;
	}

	wMaxPacketSize = le16_to_cpu(ep->wMaxPacketSize);

	dev->intbuf = kmalloc(wMaxPacketSize, GFP_KERNEL);
	if (!dev->intbuf) {
		dev_err(&ifc->dev, "%s: error allocating int buffer\n",
			__func__);
		retval = -ENOMEM;
		goto free_inturb;
	}

	interval =
		(udev->speed == USB_SPEED_HIGH) ? HS_INTERVAL : FS_LS_INTERVAL;

	usb_fill_int_urb(dev->inturb, udev, dev->int_pipe,
				dev->intbuf, wMaxPacketSize,
				notification_available_cb, dev, interval);

	dev->readurb = usb_alloc_urb(0, GFP_KERNEL);
	if (!dev->readurb) {
		dev_err(&ifc->dev, "%s: error allocating read urb\n",
			__func__);
		retval = -ENOMEM;
		goto free_intbuf;
	}

	dev->readbuf = kmalloc(DEFAULT_READ_URB_LENGTH, GFP_KERNEL);
	if (!dev->readbuf) {
		dev_err(&ifc->dev, "%s: error allocating read buffer\n",
			__func__);
		retval = -ENOMEM;
		goto free_rurb;
	}

	dev->in_ctlreq = kmalloc(sizeof(*dev->in_ctlreq), GFP_KERNEL);
	if (!dev->in_ctlreq) {
		dev_err(&ifc->dev, "%s:error allocating setup packet buffer\n",
			__func__);
		retval = -ENOMEM;
		goto free_rbuf;
	}

	dev->in_ctlreq->bRequestType =
			(USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE);
	dev->in_ctlreq->bRequest  = USB_CDC_GET_ENCAPSULATED_RESPONSE;
	dev->in_ctlreq->wValue = 0;
	dev->in_ctlreq->wIndex =
		dev->intf->cur_altsetting->desc.bInterfaceNumber;
	dev->in_ctlreq->wLength = cpu_to_le16(DEFAULT_READ_URB_LENGTH);

	__dev[id] = dev;

	platform_device_add(dev->pdev);

	ch_id++;

	return ctrl_bridge_start_read(dev);

free_rbuf:
	kfree(dev->readbuf);
free_rurb:
	usb_free_urb(dev->readurb);
free_intbuf:
	kfree(dev->intbuf);
free_inturb:
	usb_free_urb(dev->inturb);
pdev_del:
	platform_device_unregister(dev->pdev);
nomem:
	kfree(dev);

	return retval;
}
コード例 #8
0
static void notification_available_cb(struct urb *urb)
{
	int				status;
	struct usb_cdc_notification	*ctrl;
	struct ctrl_bridge		*dev = urb->context;
	struct bridge			*brdg = dev->brdg;
	unsigned int			ctrl_bits;
	unsigned char			*data;
	unsigned long			flags;

	/*usb device disconnect*/
	if (urb->dev->state == USB_STATE_NOTATTACHED)
		return;

	spin_lock_irqsave(&dev->lock, flags);
	dev->rx_state = RX_IDLE;
	spin_unlock_irqrestore(&dev->lock, flags);

	switch (urb->status) {
	case 0:
		/*success*/
		break;
	case -ESHUTDOWN:
	case -ENOENT:
	case -ECONNRESET:
	case -EPROTO:
		 /* unplug */
		 return;
	case -EPIPE:
		dev_err(&dev->intf->dev,
			"%s: stall on int endpoint\n", __func__);
		/* TBD : halt to be cleared in work */
	case -EOVERFLOW:
	default:
		pr_debug_ratelimited("%s: non zero urb status = %d\n",
					__func__, urb->status);
		goto resubmit_int_urb;
	}

	ctrl = (struct usb_cdc_notification *)urb->transfer_buffer;
	data = (unsigned char *)(ctrl + 1);

	switch (ctrl->bNotificationType) {
	case USB_CDC_NOTIFY_RESPONSE_AVAILABLE:
		spin_lock_irqsave(&dev->lock, flags);
		dev->rx_state = RX_BUSY;
		spin_unlock_irqrestore(&dev->lock, flags);
		dev->resp_avail++;
		usb_autopm_get_interface_no_resume(dev->intf);
		usb_fill_control_urb(dev->readurb, dev->udev,
					usb_rcvctrlpipe(dev->udev, 0),
					(unsigned char *)dev->in_ctlreq,
					dev->readbuf,
					DEFAULT_READ_URB_LENGTH,
					resp_avail_cb, dev);

		status = usb_submit_urb(dev->readurb, GFP_ATOMIC);
		if (status) {
			dev_err(&dev->intf->dev,
				"%s: Error submitting Read URB %d\n",
				__func__, status);
			usb_autopm_put_interface_async(dev->intf);
			goto resubmit_int_urb;
		}
		return;
	case USB_CDC_NOTIFY_NETWORK_CONNECTION:
		dev_dbg(&dev->intf->dev, "%s network\n", ctrl->wValue ?
					"connected to" : "disconnected from");
		break;
	case USB_CDC_NOTIFY_SERIAL_STATE:
		dev->notify_ser_state++;
		ctrl_bits = get_unaligned_le16(data);
		dev_dbg(&dev->intf->dev, "serial state: %d\n", ctrl_bits);
		dev->cbits_tohost = ctrl_bits;
		if (brdg && brdg->ops.send_cbits)
			brdg->ops.send_cbits(brdg->ctx, ctrl_bits);
		break;
	default:
		dev_err(&dev->intf->dev, "%s: unknown notification %d received:"
			"index %d len %d data0 %d data1 %d",
			__func__, ctrl->bNotificationType, ctrl->wIndex,
			ctrl->wLength, data[0], data[1]);
	}

resubmit_int_urb:
	ctrl_bridge_start_read(dev, GFP_ATOMIC);
}
int
ctrl_bridge_probe(struct usb_interface *ifc, struct usb_host_endpoint *int_in,
                  char *name, int id)
{
    struct ctrl_bridge		*dev;
    struct usb_device		*udev;
    struct usb_endpoint_descriptor	*ep;
    u16				wMaxPacketSize;
    int				retval = 0;
    int				interval;

    udev = interface_to_usbdev(ifc);

    dev = __dev[id];
    if (!dev) {
        pr_err("%s:device not found\n", __func__);
        return -ENODEV;
    }
    if (!int_in)
        return 0;
    dev->name = name;

    dev->pdev = platform_device_alloc(name, -1);
    if (!dev->pdev) {
        retval = -ENOMEM;
        dev_err(&ifc->dev, "%s: unable to allocate platform device\n",
                __func__);
        goto free_name;
    }

    dev->flags = 0;
    dev->udev = udev;
    dev->int_pipe = usb_rcvintpipe(udev,
                                   int_in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
    dev->intf = ifc;

    /*use max pkt size from ep desc*/
    ep = &dev->intf->cur_altsetting->endpoint[0].desc;

    dev->inturb = usb_alloc_urb(0, GFP_KERNEL);
    if (!dev->inturb) {
        dev_err(&ifc->dev, "%s: error allocating int urb\n", __func__);
        retval = -ENOMEM;
        goto pdev_put;
    }

    wMaxPacketSize = le16_to_cpu(ep->wMaxPacketSize);

    dev->intbuf = kmalloc(wMaxPacketSize, GFP_KERNEL);
    if (!dev->intbuf) {
        dev_err(&ifc->dev, "%s: error allocating int buffer\n",
                __func__);
        retval = -ENOMEM;
        goto free_inturb;
    }

    interval = int_in->desc.bInterval;

    usb_fill_int_urb(dev->inturb, udev, dev->int_pipe,
                     dev->intbuf, wMaxPacketSize,
                     notification_available_cb, dev, interval);

    dev->readurb = usb_alloc_urb(0, GFP_KERNEL);
    if (!dev->readurb) {
        dev_err(&ifc->dev, "%s: error allocating read urb\n",
                __func__);
        retval = -ENOMEM;
        goto free_intbuf;
    }

    dev->readbuf = kmalloc(DEFAULT_READ_URB_LENGTH, GFP_KERNEL);
    if (!dev->readbuf) {
        dev_err(&ifc->dev, "%s: error allocating read buffer\n",
                __func__);
        retval = -ENOMEM;
        goto free_rurb;
    }

    dev->in_ctlreq = kmalloc(sizeof(*dev->in_ctlreq), GFP_KERNEL);
    if (!dev->in_ctlreq) {
        dev_err(&ifc->dev, "%s:error allocating setup packet buffer\n",
                __func__);
        retval = -ENOMEM;
        goto free_rbuf;
    }

    dev->in_ctlreq->bRequestType =
        (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE);
    dev->in_ctlreq->bRequest  = USB_CDC_GET_ENCAPSULATED_RESPONSE;
    dev->in_ctlreq->wValue = 0;
    dev->in_ctlreq->wIndex =
        dev->intf->cur_altsetting->desc.bInterfaceNumber;
    dev->in_ctlreq->wLength = cpu_to_le16(DEFAULT_READ_URB_LENGTH);

    retval = platform_device_add(dev->pdev);
    if (retval) {
        dev_err(&ifc->dev, "%s:fail to add pdev\n", __func__);
        goto free_ctrlreq;
    }

    retval = ctrl_bridge_start_read(dev, GFP_KERNEL);
    if (retval) {
        dev_err(&ifc->dev, "%s:fail to start reading\n", __func__);
        goto pdev_del;
    }

    return 0;

pdev_del:
    platform_device_del(dev->pdev);
free_ctrlreq:
    kfree(dev->in_ctlreq);
free_rbuf:
    kfree(dev->readbuf);
free_rurb:
    usb_free_urb(dev->readurb);
free_intbuf:
    kfree(dev->intbuf);
free_inturb:
    usb_free_urb(dev->inturb);
pdev_put:
    platform_device_put(dev->pdev);
free_name:
    dev->name = "none";

    return retval;
}