⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbhost.c

📁 printer usb
💻 C
📖 第 1 页 / 共 5 页
字号:
    volatile Uint32 inx;
    volatile Uint32 outx;
    volatile Uint32 tick;
    volatile Boolean sleeping;
    volatile Boolean DeviceReady;
} HOST_STATE_STRUCT;

typedef struct {
    Boolean needClass;
    int Config;
    int iface;
    int ifaceAlt;
    int MaxLUN;
    int ep_in;
    int ep_in_pksize;
    int ep_out;
    int ep_out_pksize;
    int ep_intr;
    int ep_intr_pksize;
    int ep_intr_pollms;
} USB_CLASS;

/* For now, leave this public for doing a post-mortum */
HOST_STATE_STRUCT usb_host;
Boolean USBCancelHost = FALSE;

static DEVICE_DESC DeviceDesc;
static CONFIG_DESC ConfigDesc;
static INTERFACE_DESC InterfaceDesc;
static ENDPOINT_DESC EndpointDesc;

/* Prototypes */
static void USBH_isr(int arg);
static void process_token_done_ISR(Uint32 rstatus);
static void ProcessIN_ISR(Uint32 rstatus);
static void ProcessOUT_ISR(Uint32 rstatus);
static void Start_USB_Host_Task(Uint8 code, Uint32 rstatus);
static void USBH_hisr(void);
static Sint32 USB_Host_Task(void *arg);
static Boolean USB_enumerate(void);
static void USB_UnsupportedDevice(void);
static Boolean USB_GetConfiguration(void);
static void reset_the_device(void);
static Uint8 USB_Request(Uint32 *rstatus);
static int USB_GetDescriptor(Uint8 type, Uint8 index, void *desc, Uint16 length);
static Boolean USB_device_request(Uint8 *setup);
static Boolean USB_DoConfiguration(USB_CLASS *class);
static PTPIO_RETN doPTP_USB_ReadInterrupt(Uint8 *Input, Uint32 Size,
                                          Uint32 *retCount);
static Boolean PollInterruptEndpoint(void);

#define MAX_INT_PACKETS 5

static Uint8 intbuff[64];
static Sint32 intcount = -1;

#if USBH_VERBOSE
static int USB_GetString(Uint8 index, Uint16 lang_id);
static void USB_PrintString(Uint8 index, Uint16 lang_id);
#endif

/*  NUCLEUS O/S and ts task related declarations */
#define HISR_STACKSIZE  400

#ifndef USBHTASK_STACKSIZE
#define USBHTASK_STACKSIZE 5000
#endif

#ifndef USBHTASK_PRIORITY
#define USBHTASK_PRIORITY 45
#endif

/* hISR (High Interrupt Service Routine) declaration */
static NU_HISR usbh_hisr;
static Uint32 pHISRStack[HISR_STACKSIZE/4];

/* ts: task and semaphore */
static void *TaskUSBH_data;
static tsTaskID TaskUSBH_ID;
static int TaskUSBH_arg;
static Uint32 TaskUSBH_stack[USBHTASK_STACKSIZE/4];

static tsSemaphore USBHSemaphore;

#ifdef MSCLASS_HOST_PASSTHROUGH
/*
 * This semaphore is only required for passthrough mode to protect the
 * the USB host routines from being reentered by the USB_task in usbch9.c
 * which calls the MSCLASS_HOST_PASSTHROUGH camera I/O routines via
 * USBMassStorage() and USB_Host_Task() in this module.
 */
static tsSemaphore BLOCKsemaphore;
#define PASSTHROUGH_BLOCK TaskSemWait(BLOCKsemaphore);
#define PASSTHROUGH_UNBLOCK TaskSemSignal(BLOCKsemaphore);
#else
#define PASSTHROUGH_BLOCK
#define PASSTHROUGH_UNBLOCK
#endif

static USB_CLASS MassStorage;
static USB_CLASS StillImage;

/***********************************************************************/
/*  Function Name  : USBH_isr                                          */
/*  Returned Value : None                                              */
/*                                                                     */
/*  Service all the interrupts in the VUSB1.1 host hardware            */
/***********************************************************************/
static void USBH_isr(int arg)
{
    /* Mask off USB interrupts because we're moving to HISR */
    *(unsigned long *)EXMSK1A &= ~(1 << USB1_INTERRUPT_BIT);

    NU_Activate_HISR(&usbh_hisr);

    /* Clear bit in exception register. */
    *(Uint32 *)EXCLRA = (1 << USB1_INTERRUPT_BIT);
}

static void USBH_hisr(void)
{
    Uint8 istatus, status, error;
    Uint32 rstatus;

    /* While any of the enabled interrupts are asserted... */
    istatus = *regINT_STAT & *regINT_ENB;
    while (istatus) {
        error = *regERR_STAT;
        status = *regSTATUS;

#ifdef DEBUG
        if (status & 0xf0)
            status |= 1;
        else if (usb_host.cur_pipe)
            status |= usb_host.cur_pipe->EP << 4;
#endif
        rstatus = ((Uint32)istatus << 16) | ((Uint32)error << 8) | status;

        /* Clear error bits */
        *regERR_STAT = error & *regERR_ENB;

        /* Previous token transmission should already be done */
        if (*regCTL & CTRL_TOKEN_BUSY) {
            usb_host.state = NO_REQUEST;
            usb_host.reset_required = TRUE;
            usb_host.DeviceReady = FALSE;
            Start_USB_Host_Task(USBH_ERROR, rstatus);

            /* Clear all enabled interrupts */
            *regINT_STAT = istatus;

            /* Check for another interrupt pending */
            istatus = *regINT_STAT & *regINT_ENB;


            /* Clear bit in exception register. */
            *(unsigned long *)EXMSK1A |= (1 << USB1_INTERRUPT_BIT);
            *(Uint32 *)EXCLRA = (1 << USB1_INTERRUPT_BIT);
            return;
        }

        /* Check if STALL interrupt */
        if (istatus & INTR_STALL) {
            /* A bad-CRC16 error is OK with STALL, clear error */
            if (error & VUSB_ERR_STAT_CRC16) {
                error ^= VUSB_ERR_STAT_CRC16;
                if (!error) {
                    istatus     ^= VUSB_INT_STAT_ERROR;
                    *regINT_STAT = VUSB_INT_STAT_ERROR;
                }
            }
            rstatus = ((Uint32)istatus << 16) | ((Uint32)error << 8) | status;
            Start_USB_Host_Task(USBH_STALL, rstatus);
        }

        /*
         * Check if interrupt due to error (but not RESET or ATTACH or
         * EOF error) Note: EOF error is caused by SOF_THRESHOLD being
         * too small and shouldn't happen in a shipping product.
         */
        if ((error & ~2) && !(istatus & (INTR_USB_RST | INTR_ATTACH))) {
            if (!(error & 0x60) && usb_host.cur_pipe) {
                volatile PIPE_STRUCT *pipe;
                BDT_STRUCT *bdt;

                /* Get the current pipe and BDT and resend the last token */
                pipe = usb_host.cur_pipe;
                bdt = (BDT_STRUCT *)((Uint32)pipe->bdt ^ BDT_ODD_EVEN_BIT);
                pipe->bdt = bdt;

                if ((Uint32)bdt & BDT_OUT_BIT)
                    usb_host.even_odd_OUT ^= BDT_ODD_EVEN_BIT;
                else
                    usb_host.even_odd_IN ^= BDT_ODD_EVEN_BIT;

                bdt->PID   = usb_host.nxt_bdt.PID;
                bdt->BC    = usb_host.nxt_bdt.BC;
                bdt->ADDRL = usb_host.nxt_bdt.ADDRL;
                bdt->ADDRH = usb_host.nxt_bdt.ADDRH;

                *regEP0CTL = pipe->type;
                *regADDR = usb_host.USB_addr;
                *regTOKEN = pipe->pid_ep;
            }
            else {
                /*
                 * Force hardware reset if error is DMA or OWN error
                 * or no pipe
                 */
                Start_USB_Host_Task(USBH_ERROR, rstatus);

                /* Clear all enabled interrupts */
                *regINT_STAT = istatus;

                /* Check for another interrupt pending */
                istatus = *regINT_STAT & *regINT_ENB;

                /* Clear bit in exception register. */
                *(Uint32 *)EXCLRA = (1 << USB1_INTERRUPT_BIT);
                return;
            }
        }

        /* Check if RESET interrupt */
        else if (istatus & INTR_USB_RST) {
            *regCTL = 0;

            /* Let polling routine know that device went bye-bye */
            usb_host.DeviceReady = FALSE;
            Start_USB_Host_Task(USBH_RESET, rstatus);
        }

        /* Check if ATTACH interrupt */
        else if (istatus & INTR_ATTACH)
            Start_USB_Host_Task(USBH_ATTACH, rstatus);

        else {
            /* Check if token-done interrupt */
            if (usb_host.cur_pipe && (istatus & INTR_TOK_DNE))
                process_token_done_ISR(rstatus);

#if 0
            /* Check if Start of Frame interrupt */
            else if (istatus & INTR_SOF_TOK) {
                /*
                 * Update the current interval on the interrupt pipes if
                 * we supported interrupt pipes
                 */
            }
#endif
            else {
                DEBUG_LOG(USBH_INTR, rstatus);
            }
        }

        /* Clear all enabled interrupts */
        *regINT_STAT = istatus;

        /* Check for another interrupt pending */
        istatus = *regINT_STAT & *regINT_ENB;
    }

    /* Clear bit in exception register. */
    *(unsigned long *)EXMSK1A |= (1 << USB1_INTERRUPT_BIT);
    *(Uint32 *)EXCLRA = (1 << USB1_INTERRUPT_BIT);
}

/***********************************************************************/
static void process_token_done_ISR(Uint32 rstatus)
{
    Uint8 status;
    volatile PIPE_STRUCT *pipe;
    BDT_STRUCT *bdt;

    /* Get the current pipe and BDT */
    pipe = usb_host.cur_pipe;

    /* Get the status from BDT */
    status = pipe->bdt->PID & BDT_PID_MASKS;
    if (!status || (status == BDT_NAK_PID)) {
        if (pipe->pipe_type == PIPE_INT) {
            /* Interrupt pipe NAKed - nothing there so let task know */
            Start_USB_Host_Task(USBH_INTNAK, rstatus);
        }
        else {
            /* Warning: NAKs can overflow debug log buffer */
            /* DEBUG_LOG(USBH_NAK, rstatus); */

            /*
             * If a protocol error occurred, host may get NAK'ed forever.
             * This timer will force an NAK condition and allow connection
             * with camera to be reset and re-enumerated. However, the camera
             * may legitimately NAK a bunch of times, so we break out every
             * once in a while to intersperse interrupt-endpoint polling,
             * as required by certain PictBridge cameras, e.g., Fugi.
             */
            if (BIOSTimerMS() - pipe->NAKstart > pipe->NAKtime) {
                Start_USB_Host_Task(USBH_INTNAK, rstatus);
                pipe->NAKstart = BIOSTimerMS();
                return;
            }

            /* Got an error or a NAK... resend the last token */
            bdt = (BDT_STRUCT *)((Uint32)pipe->bdt ^ BDT_ODD_EVEN_BIT);
            pipe->bdt = bdt;

            if ((Uint32)bdt & BDT_OUT_BIT)
                usb_host.even_odd_OUT ^= BDT_ODD_EVEN_BIT;
            else
                usb_host.even_odd_IN ^= BDT_ODD_EVEN_BIT;

            bdt->PID   = usb_host.nxt_bdt.PID;
            bdt->BC    = usb_host.nxt_bdt.BC;
            bdt->ADDRL = usb_host.nxt_bdt.ADDRL;
            bdt->ADDRH = usb_host.nxt_bdt.ADDRH;

            *regEP0CTL = pipe->type;
            *regADDR = usb_host.USB_addr;
            *regTOKEN = pipe->pid_ep;
        }
        return;
    }
    pipe->NAKstart = BIOSTimerMS();

    if (usb_host.state == CNTRL_SETUP) {
        if (pipe[0].setup_bf[0] & USB_SETUP_DEV2HOST) {
            //DEBUG_LOG(USBH_IN, rstatus);

            usb_host.state = PROCESS_IN;
            pipe[0].pid_ep = VUSB_TOKEN_IN;

            bdt = (BDT_STRUCT *)(USB_BDT_PAGE | usb_host.even_odd_IN);
            pipe->bdt = bdt;
            usb_host.even_odd_IN ^= BDT_ODD_EVEN_BIT;

            usb_host.nxt_bdt.PID   = BDT_PID_OWN | pipe[0].DATAx;
            usb_host.nxt_bdt.BC    = pipe->pksize;
            usb_host.nxt_bdt.ADDRL = (Uint32)pipe[0].pipe_bf;
            usb_host.nxt_bdt.ADDRH = (Uint32)pipe[0].pipe_bf >> 8;

            bdt->BC    = usb_host.nxt_bdt.BC;
            bdt->ADDRL = usb_host.nxt_bdt.ADDRL;
            bdt->ADDRH = usb_host.nxt_bdt.ADDRH;
            bdt->PID   = usb_host.nxt_bdt.PID;

            *regEP0CTL = pipe[0].type;
            *regADDR = usb_host.USB_addr;
            *regTOKEN = pipe[0].pid_ep;
            return;
        }
        else {
            usb_host.state = PROCESS_OUT;
            pipe[0].pid_ep = VUSB_TOKEN_OUT;
            ProcessOUT_ISR(rstatus);
        }
    }

    else if (usb_host.state == PROCESS_IN)
        ProcessIN_ISR(rstatus);

    else if (usb_host.state == PROCESS_OUT)
        ProcessOUT_ISR(rstatus);

    else if (usb_host.state == PROCESS_NUL) {
        /* Toggle on success after sending null OUT packet */
        pipe->DATAx ^= BDT_PID_DATA01;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -