Example #1
0
void usb_handle_irq(void) {
	unsigned n;

	USB_IRQ_COUNT++;

//	P("usb %x\n", USB_IRQ_COUNT);

	n = readl(USB_INT_STATUS);
	//writel(n & (USB_INT_EP0 | USB_INT_EP1), USB_INT_CLEAR);
	writel(n, USB_INT_CLEAR);
	if (n & USB_INT_FRAME)
		msec_counter++;
	if (n & USB_INT_EP0)
		usb_ep0_rx();
	if (n & USB_INT_EP1)
		usb_ep0_tx();

	/* ignore masked interrupts */
	n &= readl(USB_INT_ENABLE);

	if (n & ~(USB_INT_FRAME)) {
//		P("usb n 0x%x\n", n);
	}

	if ((n & USB_INT_EP2) && usb_ep1_rx_full_cb)
		usb_ep1_rx_full_cb();
	if ((n & USB_INT_EP3) && usb_ep1_tx_empty_cb)
		usb_ep1_tx_empty_cb();
#if CONFIG_USB_2ND_IFC
	if ((n & USB_INT_EP4) && usb_ep2_rx_full_cb)
		usb_ep2_rx_full_cb();
	if ((n & USB_INT_EP5) && usb_ep2_tx_empty_cb)
		usb_ep2_tx_empty_cb();
#endif
}
Example #2
0
/* Windows 7 fails to configure device unless this is implemented */
static int
cdc_handle_control(struct usb_ctrl_req_t *req, void *data)
{
    struct cdc_ctx *ctx = data;
    switch ((enum cdc_ctrl_req_code)req->bRequest) {
    case USB_CTRL_REQ_CDC_SET_LINE_CODING: {
        if (req->wLength != sizeof(struct cdc_line_coding)) {
            usb_handle_control_status(1);
        } else {
            usb_ep0_rx(&ctx->line_coding, req->wLength, cdc_handle_control_set_line_coding, ctx);
            return 1;
        }
        break;
    }
    case USB_CTRL_REQ_CDC_GET_LINE_CODING: {
        usb_ep0_tx_cp(&ctx->line_coding, sizeof(struct cdc_line_coding), req->wLength, NULL, NULL);
        usb_handle_control_status(0);
        break;
    }
    case USB_CTRL_REQ_CDC_SET_CTRL_LINE_STATE: {
        /*
         * We should remain inactive unless there is a terminal on the other end of the link,
         * indicated by the first two bits of wValue
         */
        ctx->control_lines = req->wValue;
        usb_handle_control_status(0);
        break;
    }
    default:
        return 0;
    }
    return 0;
}
Example #3
0
int
dfu_handle_control(struct usb_ctrl_req_t *req, void *data)
{
        struct dfu_ctx *ctx = data;
        int fail = 1;

        /* XXX check for std vs class request */
        switch ((uint8_t)req->bRequest) {
        case USB_CTRL_REQ_SET_INTERFACE:
                if (req->wValue >= ctx->dfuf->segment_count)
                        goto out;
                ctx->segment = req->wValue;
                ctx->state = DFU_STATE_dfuIDLE;
                break;

        case USB_CTRL_REQ_GET_INTERFACE:
                usb_ep0_tx_cp(&ctx->segment, 1, req->wLength, NULL, NULL);
                break;

        case USB_CTRL_REQ_DFU_DNLOAD: {
                void *buf;

                switch (ctx->state) {
                case DFU_STATE_dfuIDLE:
                        ctx->off = 0;
                        break;
                case DFU_STATE_dfuDNLOAD_IDLE:
                        break;
                default:
                        goto err;
                }

                /**
                 * XXX we are not allowed to STALL here, and we need to eat all transferred data.
                 * better not allow setup_write to break the protocol.
                 */
                ctx->status = ctx->dfuf->segment[ctx->segment].setup_write(ctx, ctx->off, req->wLength, &buf);
                if (ctx->status != DFU_STATUS_OK) {
                        ctx->state = DFU_STATE_dfuERROR;
                        goto err_have_status;
                }

                if (req->wLength > 0) {
                        ctx->state = DFU_STATE_dfuDNLOAD_SYNC;
                        usb_ep0_rx(buf, req->wLength, dfu_dnload_complete, ctx);
                } else {
                        ctx->state = DFU_STATE_dfuMANIFEST_SYNC;
                        dfu_dnload_complete(NULL, 0, ctx);
                }
                goto out_no_status;
        }
        case USB_CTRL_REQ_DFU_GETSTATUS: {
                struct dfu_status_t st;

                st.bState = ctx->state;
                st.bStatus = ctx->status;
                st.bwPollTimeout = 1; /* XXX allow setting in desc? */
                /**
                 * If we're in DFU_STATE_dfuMANIFEST, we just finished
                 * the download, and we're just about to send our last
                 * status report.  Once the report has been sent, go
                 * and reset the system to put the new firmware into
                 * effect.
                 */
                usb_ep0_tx_cp(&st, sizeof(st), req->wLength, NULL, NULL);
                break;
        }
        case USB_CTRL_REQ_DFU_CLRSTATUS:
                if (ctx->state != DFU_STATE_dfuERROR)
                        goto err;
                ctx->state = DFU_STATE_dfuIDLE;
                ctx->status = DFU_STATUS_OK;
                break;
        case USB_CTRL_REQ_DFU_GETSTATE: {
                uint8_t st = ctx->state;
                usb_ep0_tx_cp(&st, sizeof(st), req->wLength, NULL, NULL);
                break;
        }
        case USB_CTRL_REQ_DFU_ABORT:
                switch (ctx->state) {
                case DFU_STATE_dfuIDLE:
                case DFU_STATE_dfuDNLOAD_IDLE:
                /* case DFU_STATE_dfuUPLOAD_IDLE: */
                        ctx->state = DFU_STATE_dfuIDLE;
                        break;
                default:
                        goto err;
                }
                break;
        /* case USB_CTRL_REQ_DFU_UPLOAD: */
        default:
                return (0);
        }

        fail = 0;
        goto out;

err:
        ctx->status = DFU_STATUS_errSTALLEDPKT;
err_have_status:
        ctx->state = DFU_STATE_dfuERROR;
out:
        usb_handle_control_status(fail);
out_no_status:
        return (1);
}
Example #4
0
/*
 * Handle class (HID) specific calls.
 *
 * see hid_handle_control()
 */
static int
hid_handle_control_class(struct usb_ctrl_req_t *req, struct hid_ctx *ctx)
{
    size_t len = 0;

    /* XXX maintain state for all report descriptors */

    switch ((enum hid_ctrl_req_code)req->bRequest) {
    case USB_CTRL_REQ_HID_GET_REPORT: {
        enum hid_report_type report_type = req->wValue >> 8;
        uint8_t report_id = req->wValue & 0xff;
        int ret = -1;

        ctx->get_report_outstanding_length = req->wLength;
        if (ctx->hidf->get_report)
            ret = ctx->hidf->get_report(ctx, report_type, report_id);
        if (ret <= 0) {
            ctx->get_report_outstanding_length = 0;
            usb_handle_control_status(1);
        }
        return (1);
    }

    case USB_CTRL_REQ_HID_SET_REPORT: {
        int ret = -1;
        void *buf = NULL;
        ctx->set_report_length = req->wLength;
        ctx->set_report_type = req->wValue >> 8;
        ctx->set_report_id = req->wValue & 0xff;

        if (ctx->hidf->set_report)
            ret = ctx->hidf->set_report(ctx->set_report_type, ctx->set_report_id, &buf, ctx->set_report_length);
        if (ret > 0)
            usb_ep0_rx(buf, ctx->set_report_length, hid_set_report_done, ctx);
        else
            usb_handle_control_status(1);
        return (1);
    }

    case USB_CTRL_REQ_HID_GET_IDLE:
        /* XXX implement */
        usb_ep0_tx_cp(&len, 1, req->wLength, NULL, NULL);
        usb_handle_control_status(0);
        return (1);

    case USB_CTRL_REQ_HID_SET_IDLE:
        /* XXX implement */
        usb_handle_control_status(0);
        return (1);

    case USB_CTRL_REQ_HID_GET_PROTOCOL:
        /* XXX implement */
        /* usb_ep0_tx_cp(&len, 1, req->wLength, NULL, NULL); */
        /* usb_handle_control_status(0); */
        return (0);

    case USB_CTRL_REQ_HID_SET_PROTOCOL:
        /* XXX implement */
        usb_handle_control_status(0);
        return (1);

    default:
        return (0);
    }
}