Re: How to handle USB_ENDPOINT_XFER_BULK in gadget API?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 28 Apr 2011 15:24:19 +0200, baseplast <baseplast@xxxxxxx> wrote:
finally did this, but after calling usb_ep_queue has an error
0xFFFFFF8D, whats may be wrong ?

Do not format it as an unsigned integer but as signed integer.  You
will then get -115.  You can use errno[1] to see what it is:

$ errno 115
115: EINPROGRESS: Operation now in progress

[1] <https://github.com/mina86/tinyapps/blob/master/errno>

=================BASED on GMIDI code ==================================
=======================================================================
static BYTE RESPONSE_ARRAY[23] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}; static int set_myDevice_config(struct myDevice_device *dev, gfp_t gfp_flags)
{
        int err = 0;
        struct usb_request *req;
        struct usb_ep *ep;
        unsigned i;

        dev->in_ep->driver_data = dev;
        dev->out_ep->driver_data = dev;

        err = usb_ep_enable(dev->out_ep, &dongle_endpoint01_descriptor);
        err = usb_ep_enable(dev->in_ep, &dongle_endpoint81_descriptor);

        // for OUT endpoint
/* allocate a bunch of read buffers and queue them all at once. */
        ep = dev->out_ep;
        for (i = 0; i < qlen && err == 0; i++) {
                req = alloc_ep_req(ep, buflen);
                if (req) {
                        req->complete = myDevice_complete;
                        err = usb_ep_queue(ep, req, GFP_ATOMIC);
                        if (err) {
DBG(dev, "OUT %s queue req: %d\n", ep->name, err);
                        }
                } else {
                        err = -ENOMEM;
                }
        }

        // for IN  endpoint
/* allocate a bunch of read buffers and queue them all at once. */
        ep = dev->in_ep;
        for (i = 0; i < qlen && err == 0; i++) {
                req = alloc_ep_req(ep, buflen);
                if (req) {
                        req->complete = myDevice_complete;
                        err = usb_ep_queue(ep, req, GFP_ATOMIC);
                       if (err) {
DBG(dev, "IN %s queue req: %d\n", ep->name, err);
                        }
                } else {
                        err = -ENOMEM;
                }
        }

This is invalid.  You cannot just queue requests on IN endpoint without
feeding the buffers with any data.  You'll basically sending garbage to
the host.

fail:
        /* caller is responsible for cleanup on error */
        return err;
}



static void myDevice_complete(struct usb_ep *ep, struct usb_request *req)
{
        struct myDevice_device *dev = ep->driver_data;
        int status = req->status;

        switch (status) {
        case 0:                         /* normal completion */
                if (ep == dev->out_ep) {
/* we received stuff. req is queued again, below */ // here is correct data passed from host to endpoint 01, working ok
                        myDevice_handle_out_data(ep, req);
printk("RECEIVE DATA length = %08X\n",req->actual);
                        req->status = 0;

                } else if (ep == dev->in_ep) {

                    printk("Sending RESPONSE DATA to host len=0x08\n");

                    req->zero   = 0x00;
                    req->actual = 0x08;
                    req->length = 0x17;
                    req->complete=myDevice_complete;
                    // copyin response buffer to transfer buffer
                    memcpy(req->buf,&RESPONSE_ARRAY[0],req->actual);

                    //sending URB request back to host
status = usb_ep_queue(dev->in_ep, req, GFP_ATOMIC); //here i have STATUS_OK, but after calling status in HCD is 0xFFFFFF8D and req->actual=0...

You've just queued request that you are processing, ie. one that is still
on the queue.

                   return;

                }
                break;

        /* this endpoint is normally active while we're configured */
        case -ECONNABORTED:             /* hardware forced ep reset */
        case -ECONNRESET:               /* request dequeued */
        case -ESHUTDOWN:                /* disconnect from host */
                VDBG(dev, "%s gone (%d), %d/%d\n", ep->name, status,
                                req->actual, req->length);
                if (ep == dev->out_ep) {
                        myDevice_handle_out_data(ep, req);
                }
                free_ep_req(ep, req);
                return;

case -EOVERFLOW: /* buffer overrun on read means that
                                         * we didn't provide a big enough
                                         * buffer.
                                         */
        default:
                DBG(dev, "%s complete --> %d, %d/%d\n", ep->name,
                                status, req->actual, req->length);
                break;
        case -EREMOTEIO:                /* short read */
                break;
        }

        status = usb_ep_queue(ep, req, GFP_ATOMIC);
        if (status) {
                ERROR(dev, "kill %s:  resubmit %d bytes --> %d\n",
                                ep->name, req->length, status);
                usb_ep_set_halt(ep);

        }
}


--
Best regards,                                         _     _
.o. | Liege of Serenely Enlightened Majesty of      o' \,=./ `o
..o | Computer Science,  Michal "mina86" Nazarewicz    (o o)
ooo +-----<email/xmpp: mnazarewicz@xxxxxxxxxx>-----ooO--(_)--Ooo--
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux