Esempio n. 1
0
/*
 * RPC done RNDIS-style.  Caller guarantees:
 * - message is properly byteswapped
 * - there's no other request pending
 * - buf can hold up to 1KB response (required by RNDIS spec)
 * On return, the first few entries are already byteswapped.
 *
 * Call context is likely probe(), before interface name is known,
 * which is why we won't try to use it in the diagnostics.
 */
int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen)
{
	struct cdc_state	*info = (void *) &dev->data;
	int			master_ifnum;
	int			retval;
	unsigned		count;
	__le32			rsp;
	u32			xid = 0, msg_len, request_id;

	/* REVISIT when this gets called from contexts other than probe() or
	 * disconnect(): either serialize, or dispatch responses on xid
	 */

	/* Issue the request; xid is unique, don't bother byteswapping it */
	if (likely(buf->msg_type != RNDIS_MSG_HALT
			&& buf->msg_type != RNDIS_MSG_RESET)) {
		xid = dev->xid++;
		if (!xid)
			xid = dev->xid++;
		buf->request_id = (__force __le32) xid;
	}
	master_ifnum = info->control->cur_altsetting->desc.bInterfaceNumber;
	retval = usb_control_msg(dev->udev,
		usb_sndctrlpipe(dev->udev, 0),
		USB_CDC_SEND_ENCAPSULATED_COMMAND,
		USB_TYPE_CLASS | USB_RECIP_INTERFACE,
		0, master_ifnum,
		buf, le32_to_cpu(buf->msg_len),
		RNDIS_CONTROL_TIMEOUT_MS);
	if (unlikely(retval < 0 || xid == 0))
		return retval;

	// FIXME Seems like some devices discard responses when
	// we time out and cancel our "get response" requests...
	// so, this is fragile.  Probably need to poll for status.

	/* ignore status endpoint, just poll the control channel;
	 * the request probably completed immediately
	 */
	rsp = buf->msg_type | RNDIS_MSG_COMPLETION;
	for (count = 0; count < 10; count++) {
		memset(buf, 0, CONTROL_BUFFER_SIZE);
		retval = usb_control_msg(dev->udev,
			usb_rcvctrlpipe(dev->udev, 0),
			USB_CDC_GET_ENCAPSULATED_RESPONSE,
			USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
			0, master_ifnum,
			buf, buflen,
			RNDIS_CONTROL_TIMEOUT_MS);
		if (likely(retval >= 8)) {
			msg_len = le32_to_cpu(buf->msg_len);
			request_id = (__force u32) buf->request_id;
			if (likely(buf->msg_type == rsp)) {
				if (likely(request_id == xid)) {
					if (unlikely(rsp == RNDIS_MSG_RESET_C))
						return 0;
					if (likely(RNDIS_STATUS_SUCCESS
							== buf->status))
						return 0;
					dev_dbg(&info->control->dev,
						"rndis reply status %08x\n",
						le32_to_cpu(buf->status));
					return -EL3RST;
				}
				dev_dbg(&info->control->dev,
					"rndis reply id %d expected %d\n",
					request_id, xid);
				/* then likely retry */
			} else switch (buf->msg_type) {
			case RNDIS_MSG_INDICATE:	/* fault/event */
				rndis_msg_indicate(dev, (void *)buf, buflen);

				break;
			case RNDIS_MSG_KEEPALIVE: {	/* ping */
				struct rndis_keepalive_c *msg = (void *)buf;

				msg->msg_type = RNDIS_MSG_KEEPALIVE_C;
				msg->msg_len = cpu_to_le32(sizeof *msg);
				msg->status = RNDIS_STATUS_SUCCESS;
				retval = usb_control_msg(dev->udev,
					usb_sndctrlpipe(dev->udev, 0),
					USB_CDC_SEND_ENCAPSULATED_COMMAND,
					USB_TYPE_CLASS | USB_RECIP_INTERFACE,
					0, master_ifnum,
					msg, sizeof *msg,
					RNDIS_CONTROL_TIMEOUT_MS);
				if (unlikely(retval < 0))
					dev_dbg(&info->control->dev,
						"rndis keepalive err %d\n",
						retval);
				}
				break;
			default:
				dev_dbg(&info->control->dev,
					"unexpected rndis msg %08x len %d\n",
					le32_to_cpu(buf->msg_type), msg_len);
			}
		} else {
			/* device probably issued a protocol stall; ignore */
			dev_dbg(&info->control->dev,
				"rndis response error, code %d\n", retval);
		}
		msleep(20);
	}
	dev_dbg(&info->control->dev, "rndis response timeout\n");
	return -ETIMEDOUT;
}
Esempio n. 2
0
/*
 * RPC done RNDIS-style.  Caller guarantees:
 * - message is properly byteswapped
 * - there's no other request pending
 * - buf can hold up to 1KB response (required by RNDIS spec)
 * On return, the first few entries are already byteswapped.
 *
 * Call context is likely probe(), before interface name is known,
 * which is why we won't try to use it in the diagnostics.
 */
int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen)
{
    struct cdc_state	*info = (void *) &dev->data;
    struct usb_cdc_notification notification;
    int			master_ifnum;
    int			retval;
    int			partial;
    unsigned		count;
    u32			xid = 0, msg_len, request_id, msg_type, rsp,
                status;

    /* REVISIT when this gets called from contexts other than probe() or
     * disconnect(): either serialize, or dispatch responses on xid
     */

    msg_type = le32_to_cpu(buf->msg_type);

    /* Issue the request; xid is unique, don't bother byteswapping it */
    if (likely(msg_type != RNDIS_MSG_HALT && msg_type != RNDIS_MSG_RESET)) {
        xid = dev->xid++;
        if (!xid)
            xid = dev->xid++;
        buf->request_id = (__force __le32) xid;
    }
    master_ifnum = info->control->cur_altsetting->desc.bInterfaceNumber;
    retval = usb_control_msg(dev->udev,
                             usb_sndctrlpipe(dev->udev, 0),
                             USB_CDC_SEND_ENCAPSULATED_COMMAND,
                             USB_TYPE_CLASS | USB_RECIP_INTERFACE,
                             0, master_ifnum,
                             buf, le32_to_cpu(buf->msg_len),
                             RNDIS_CONTROL_TIMEOUT_MS);
    if (unlikely(retval < 0 || xid == 0))
        return retval;

    /* Some devices don't respond on the control channel until
     * polled on the status channel, so do that first. */
    if (dev->driver_info->data & RNDIS_DRIVER_DATA_POLL_STATUS) {
        retval = usb_interrupt_msg(
                     dev->udev,
                     usb_rcvintpipe(dev->udev,
                                    dev->status->desc.bEndpointAddress),
                     &notification, sizeof(notification), &partial,
                     RNDIS_CONTROL_TIMEOUT_MS);
        if (unlikely(retval < 0))
            return retval;
    }

    /* Poll the control channel; the request probably completed immediately */
    rsp = le32_to_cpu(buf->msg_type) | RNDIS_MSG_COMPLETION;
    for (count = 0; count < 10; count++) {
        memset(buf, 0, CONTROL_BUFFER_SIZE);
        retval = usb_control_msg(dev->udev,
                                 usb_rcvctrlpipe(dev->udev, 0),
                                 USB_CDC_GET_ENCAPSULATED_RESPONSE,
                                 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
                                 0, master_ifnum,
                                 buf, buflen,
                                 RNDIS_CONTROL_TIMEOUT_MS);
        if (likely(retval >= 8)) {
            msg_type = le32_to_cpu(buf->msg_type);
            msg_len = le32_to_cpu(buf->msg_len);
            status = le32_to_cpu(buf->status);
            request_id = (__force u32) buf->request_id;
            if (likely(msg_type == rsp)) {
                if (likely(request_id == xid)) {
                    if (unlikely(rsp == RNDIS_MSG_RESET_C))
                        return 0;
                    if (likely(RNDIS_STATUS_SUCCESS ==
                               status))
                        return 0;
                    dev_dbg(&info->control->dev,
                            "rndis reply status %08x\n",
                            status);
                    return -EL3RST;
                }
                dev_dbg(&info->control->dev,
                        "rndis reply id %d expected %d\n",
                        request_id, xid);
                /* then likely retry */
            } else switch (msg_type) {
                case RNDIS_MSG_INDICATE: /* fault/event */
                    rndis_msg_indicate(dev, (void *)buf, buflen);
                    break;
                case RNDIS_MSG_KEEPALIVE: { /* ping */
                    struct rndis_keepalive_c *msg = (void *)buf;

                    msg->msg_type = cpu_to_le32(RNDIS_MSG_KEEPALIVE_C);
                    msg->msg_len = cpu_to_le32(sizeof *msg);
                    msg->status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
                    retval = usb_control_msg(dev->udev,
                                             usb_sndctrlpipe(dev->udev, 0),
                                             USB_CDC_SEND_ENCAPSULATED_COMMAND,
                                             USB_TYPE_CLASS | USB_RECIP_INTERFACE,
                                             0, master_ifnum,
                                             msg, sizeof *msg,
                                             RNDIS_CONTROL_TIMEOUT_MS);
                    if (unlikely(retval < 0))
                        dev_dbg(&info->control->dev,
                                "rndis keepalive err %d\n",
                                retval);
                }
                break;
                default:
                    dev_dbg(&info->control->dev,
                            "unexpected rndis msg %08x len %d\n",
                            le32_to_cpu(buf->msg_type), msg_len);
                }
        } else {
            /* device probably issued a protocol stall; ignore */
            dev_dbg(&info->control->dev,
                    "rndis response error, code %d\n", retval);
        }
        msleep(20);
    }
    dev_dbg(&info->control->dev, "rndis response timeout\n");
    return -ETIMEDOUT;
}
Esempio n. 3
0
int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf, int buflen)
{
	struct cdc_state	*info = (void *) &dev->data;
	int			master_ifnum;
	int			retval;
	unsigned		count;
	__le32			rsp;
	u32			xid = 0, msg_len, request_id;

	

	
	if (likely(buf->msg_type != RNDIS_MSG_HALT
			&& buf->msg_type != RNDIS_MSG_RESET)) {
		xid = dev->xid++;
		if (!xid)
			xid = dev->xid++;
		buf->request_id = (__force __le32) xid;
	}
	master_ifnum = info->control->cur_altsetting->desc.bInterfaceNumber;
	retval = usb_control_msg(dev->udev,
		usb_sndctrlpipe(dev->udev, 0),
		USB_CDC_SEND_ENCAPSULATED_COMMAND,
		USB_TYPE_CLASS | USB_RECIP_INTERFACE,
		0, master_ifnum,
		buf, le32_to_cpu(buf->msg_len),
		RNDIS_CONTROL_TIMEOUT_MS);
	if (unlikely(retval < 0 || xid == 0))
		return retval;

	
	
	

	
	rsp = buf->msg_type | RNDIS_MSG_COMPLETION;
	for (count = 0; count < 10; count++) {
		memset(buf, 0, CONTROL_BUFFER_SIZE);
		retval = usb_control_msg(dev->udev,
			usb_rcvctrlpipe(dev->udev, 0),
			USB_CDC_GET_ENCAPSULATED_RESPONSE,
			USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
			0, master_ifnum,
			buf, buflen,
			RNDIS_CONTROL_TIMEOUT_MS);
		if (likely(retval >= 8)) {
			msg_len = le32_to_cpu(buf->msg_len);
			request_id = (__force u32) buf->request_id;
			if (likely(buf->msg_type == rsp)) {
				if (likely(request_id == xid)) {
					if (unlikely(rsp == RNDIS_MSG_RESET_C))
						return 0;
					if (likely(RNDIS_STATUS_SUCCESS
							== buf->status))
						return 0;
					dev_dbg(&info->control->dev,
						"rndis reply status %08x\n",
						le32_to_cpu(buf->status));
					return -EL3RST;
				}
				dev_dbg(&info->control->dev,
					"rndis reply id %d expected %d\n",
					request_id, xid);
				
			} else switch (buf->msg_type) {
			case RNDIS_MSG_INDICATE:	
				rndis_msg_indicate(dev, (void *)buf, buflen);

				break;
			case RNDIS_MSG_KEEPALIVE: {	
				struct rndis_keepalive_c *msg = (void *)buf;

				msg->msg_type = RNDIS_MSG_KEEPALIVE_C;
				msg->msg_len = cpu_to_le32(sizeof *msg);
				msg->status = RNDIS_STATUS_SUCCESS;
				retval = usb_control_msg(dev->udev,
					usb_sndctrlpipe(dev->udev, 0),
					USB_CDC_SEND_ENCAPSULATED_COMMAND,
					USB_TYPE_CLASS | USB_RECIP_INTERFACE,
					0, master_ifnum,
					msg, sizeof *msg,
					RNDIS_CONTROL_TIMEOUT_MS);
				if (unlikely(retval < 0))
					dev_dbg(&info->control->dev,
						"rndis keepalive err %d\n",
						retval);
				}
				break;
			default:
				dev_dbg(&info->control->dev,
					"unexpected rndis msg %08x len %d\n",
					le32_to_cpu(buf->msg_type), msg_len);
			}
		} else {
			
			dev_dbg(&info->control->dev,
				"rndis response error, code %d\n", retval);
		}
		msleep(20);
	}
	dev_dbg(&info->control->dev, "rndis response timeout\n");
	return -ETIMEDOUT;
}