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

📄 hc_simple.c

📁 isp1161a USB主控制芯片驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
            DBGVERBOSE ("sh_scan_urb_list !INT: %d fr_no: %d int: %d pint: %d\n",                    urb->start_frame, hci->frame_number, urb->interval,                    usb_pipeint (urb->pipe));            if (!sh_add_packet (hci, urb)) {                return 0;            } else {                DBGVERBOSE ("INT: start: %d fr_no: %d int: %d pint: %d\n",                        urb->start_frame, hci->frame_number,                        urb->interval, usb_pipeint (urb->pipe));                urb->start_frame = hci->frame_number;                return 0;            }        }    }    return 1;}/*************************************************************************** * Function Name : sh_shedule_trans * * This function schedule the USB transaction. * This function will process the endpoint in the following order:  * interrupt, control, and bulk.     *  * Input: hci = data structure for the host controller  *        isSOF = flag indicate if Start Of Frame has occurred  *        (ignored) * Return: 0    **************************************************************************/static int sh_schedule_trans (hci_t * hci, int isSOF){    int units_left = 1;    struct list_head *lh;    if (hci == NULL) {        DBGERR ("sh_schedule_trans: hci == NULL\n");        return 0;    }    if (hci->td_array == NULL) {        DBGERR ("sh_schedule_trans: hci->td_array == NULL\n");        return 0;    }    if (hci->td_array->len != 0) {        DBGERR ("ERROR: schedule, hci->td_array->len = 0x%x, s/b: 0\n",            hci->td_array->len);    }    /* schedule the next available interrupt transfer or the next     * stage of the interrupt transfer */    if (hci->td_array->len == 0 && !list_empty (&hci->intr_list)) {        units_left = sh_scan_urb_list (hci, &hci->intr_list);    }    /* schedule the next available control transfer or the next     * stage of the control transfer */    if (hci->td_array->len == 0 && !list_empty (&hci->ctrl_list) && units_left > 0) {        units_left = sh_scan_urb_list (hci, &hci->ctrl_list);    }    /* schedule the next available bulk transfer or the next     * stage of the bulk transfer */    if (hci->td_array->len == 0 && !list_empty (&hci->bulk_list) && units_left > 0) {        sh_scan_urb_list (hci, &hci->bulk_list);        /* be fair to each BULK URB (move list head around)          * only when the new SOF happens */        lh = hci->bulk_list.next;        list_del (&hci->bulk_list);        list_add (&hci->bulk_list, lh);    }    return 0;}/*************************************************************************** * Function Name : sh_add_packet * * This function forms the packet and transmit the packet. This function * will handle all endpoint type: isochoronus, interrupt, control, and  * bulk. *  * Input: hci = data structure for the host controller  *        urb = USB request block data structure  * * Return: 0 = unsucessful; 1 = successful    **************************************************************************/static int sh_add_packet (hci_t * hci, struct urb * urb){    __u8 *data = NULL;    int len = 0;    int toggle = 0;    int maxps = usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe));    int endpoint = usb_pipeendpoint (urb->pipe);    int address = usb_pipedevice (urb->pipe);    int slow = (((urb->pipe) >> 26) & 1);    int out = usb_pipeout (urb->pipe);    int pid = 0;    int ret;    int i = 0;    int iso = 0;    DBGFUNC ("enter sh_add_packet\n");    if (maxps == 0)        maxps = 8;    /* calculate len, toggle bit and add the transaction */    switch (usb_pipetype (urb->pipe)) {        case PIPE_ISOCHRONOUS:        pid = out ? PID_OUT : PID_IN;        iso = 1;        i = hci->frame_number - urb->start_frame;        data = urb->transfer_buffer + urb->iso_frame_desc[i].offset;        len = urb->iso_frame_desc[i].length;        break;        case PIPE_BULK:    /* BULK and BULK0 */        case PIPE_INTERRUPT:        pid = out ? PID_OUT : PID_IN;        len = urb->transfer_buffer_length - urb->actual_length;        data = urb->transfer_buffer + urb->actual_length;        toggle = usb_gettoggle (urb->dev, endpoint, out);        break;        case PIPE_CONTROL:        switch (qu_urbstate (urb)) {            case US_CTRL_SETUP:            len = 8;            pid = PID_SETUP;            data = urb->setup_packet;            toggle = 0;            break;            case US_CTRL_DATA:            if (!hci->last_packet_nak) {                /* The last packet received is not a nak:                 * reset the nak count                 */                hci->nakCnt = 0;            }            if (urb->transfer_buffer_length != 0) {                pid = out ? PID_OUT : PID_IN;                len = urb->transfer_buffer_length - urb->actual_length;                data = urb->transfer_buffer + urb->actual_length;                toggle = (urb->actual_length & maxps) ? 0 : 1;                usb_settoggle (urb->dev,                           usb_pipeendpoint (urb->pipe),                           usb_pipeout (urb->pipe), toggle);                break;            } else {                /* correct state and fall through */                qu_seturbstate (urb, US_CTRL_ACK);            }        case US_CTRL_ACK:            len = 0;            /* reply in opposite direction */            pid = !out ? PID_OUT : PID_IN;            toggle = 1;            usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe),                       usb_pipeout (urb->pipe), toggle);            break;        }    }    ret =        hc_add_trans (hci, len, data, toggle, maxps, slow, endpoint,              address, pid, iso, qu_urbstate (urb));    DBGVERBOSE ("transfer_pa: addr:%d ep:%d pid:%x tog:%x iso:%x sl:%x "            "max:%d\n len:%d ret:%d data:%p left:%d\n",            address, endpoint, pid, toggle, iso, slow,            maxps, len, ret, data, hci->hp.units_left);    if (ret >= 0) {        hci->td_array->td[hci->td_array->len].urb = urb;        hci->td_array->td[hci->td_array->len].len = ret;        hci->td_array->td[hci->td_array->len].iso_index = i;        hci->td_array->len++;        hci->active_trans = 1;        return 1;    }    return 0;}/*************************************************************************** * Function Name : sh_done_list * * This function process the packet when it has done finish transfer. *  * 1) It handles hardware error * 2) It updates the URB state * 3) If the USB transaction is complete, it start the return stack path. *  * Input: hci = data structure for the host controller  *        isExcessNak = flag tells if there excess NAK condition occurred  * * Return:  urb_state or -1 if the transaction has complete    **************************************************************************/static int sh_done_list (hci_t * hci, int *isExcessNak){    int actbytes = 0;    int active = 0;    void *data = NULL;    int cc=0,usb_error=0;    int maxps;    int toggle;    struct urb *urb;    int urb_state = 0;    int ret = 1;        /* -1 parse abbort, 1 parse ok, 0 last element */    int trans = 0;    int len;    int iso_index = 0;    int out;    int pid = 0;    int debugLen = 0;    *isExcessNak = 0;    DBGFUNC ("enter sh_done_list: td_array->len = 0x%x\n",         hci->td_array->len);    debugLen = hci->td_array->len;    if (debugLen > 1)        DBGERR ("sh_done_list: td_array->len = 0x%x > 1\n",            hci->td_array->len);    for (trans = 0; ret && trans < hci->td_array->len && trans < MAX_TRANS;         trans++) {        urb = hci->td_array->td[trans].urb;        len = hci->td_array->td[trans].len;        out = usb_pipeout (urb->pipe);        if (usb_pipeisoc (urb->pipe)) {            iso_index = hci->td_array->td[trans].iso_index;            data = urb->transfer_buffer + urb->iso_frame_desc[iso_index].offset;            toggle = 0;        } else {            data = urb->transfer_buffer + urb->actual_length;            toggle = usb_gettoggle (urb->dev,                        usb_pipeendpoint (urb->pipe),                        usb_pipeout (urb->pipe));        }        urb_state = qu_urbstate (urb);        pid = out ? PID_OUT : PID_IN;        ret = hc_parse_trans (hci, &actbytes, data, &cc, &toggle, len,                      pid, urb_state);        maxps = usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe));        if (maxps == 0)            maxps = 8;        active = (urb_state != US_CTRL_SETUP) && (actbytes && !(actbytes & (maxps - 1)));        /* If the transfer is not bulk in, then it is necessary to get all         * data specify by the urb->transfer_len.         */        if (!(usb_pipebulk (urb->pipe) && usb_pipein (urb->pipe)))            active = active && (urb->transfer_buffer_length != urb->actual_length + actbytes);        if (urb->transfer_buffer_length == urb->actual_length + actbytes)            active = 0;        /*         * Check packet status for error         */        usb_error = cc_to_error(cc);                if ( usb_error == USB_ST_CRC ||             usb_error == USB_ST_STALL ||             usb_error == USB_ST_NORESPONSE )        {            ++urb->error_count;            if ( (urb->error_count > 3) && (usb_error == USB_ST_STALL) ) {                DBGERR ("done_list: excessive error: errcount = 0x%x, cc = 0x%x\n",                    urb->error_count, cc);                urb_state = 0;                active = 0;            } else {                DBGERR ("done_list: packet err, cc = 0x%x, "                    " urb->length = 0x%x, actual_len = 0x%x,"                    " urb_state =0x%x\n",                    cc, urb->transfer_buffer_length,                    urb->actual_length, urb_state);                active = 1;            }        } else {            hci->nakCnt = 0;            hci->last_packet_nak = 0;            if (urb_state != US_CTRL_SETUP) {                /* no error */                urb->actual_length += actbytes;                usb_settoggle (urb->dev,                           usb_pipeendpoint (urb->pipe),                           usb_pipeout (urb->pipe), toggle);            }            if (usb_pipeisoc (urb->pipe)) {                urb->iso_frame_desc[iso_index].actual_length = actbytes;                urb->iso_frame_desc[iso_index].status = cc_to_error (cc);                active = (iso_index < urb->number_of_packets);            }        }        if (!active) {            if (!urb_state) {                urb->status = cc_to_error (cc);                //printk(KERN_ALERT "cc_to_error(%d)=%d\n",cc,urb->status);                if (urb->status) {                    DBGERR ("error on received packet: urb->status = 0x%x\n",                        urb->status);                }                hci->td_array->len = 0;                qu_return_urb (hci, urb, 1);                return -1;            } else {                /* We do not want to decrement the urb_state if exceeded nak,                 * because we need to finish the data stage of the control                  * packet                  */                if (!(*isExcessNak))                    urb_state--;                qu_seturbstate (urb, urb_state);            }        }    }    if (urb_state < 0)        DBGERR ("ERROR: done_list, urb_state = %d, suppose > 0\n",            urb_state);    if (debugLen != hci->td_array->len) {        DBGERR ("ERROR: done_list, debugLen!= td_array->len,"            "debugLen = 0x%x, hci->td_array->len = 0x%x\n",            debugLen, hci->td_array->len);    }    hci->td_array->len = 0;    return urb_state;}/*-------------------------------------------------------------------------*//* scan the delete list (qu_return_urb removes URB from list)  * */static void sh_del_list (hci_t * hci) {    struct list_head * lh = &hci->del_list;    struct urb * urb;    if (!list_empty (lh)) {        do {            lh = lh->next;            urb = list_entry (lh, struct urb, urb_list);            qu_return_urb (hci, urb, 0);        } while (!list_empty (lh));                wake_up (&hci->waitq);    }    return;}    

⌨️ 快捷键说明

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