📄 sl11.c
字号:
} if (((status & EPN_PSTS_SEQUENCE) && ep_sequence[ep]) || (!(status & EPN_PSTS_SEQUENCE) && !ep_sequence[ep])) { ep_sequence[ep] = (~ep_sequence[ep]) & 0x1; } else { // sequence error printk (KERN_DEBUG "sl11_out[%d]: SEQ\n", cep); error = 1; } if (endpoint->rcv_urb && len) { sl11read_buffer (adr, endpoint->rcv_urb->buffer + endpoint->rcv_urb->actual_length, len); } // re-arm sl11write_epn (cep, EPN_Status, 0); sl11write_epn (cep, EPN_Counter, 0); sl11write_epn (cep, EPN_XferLen, endpoint->rcv_packetSize); //sl11_dump_epn(ep, "\n"); sl11write_epn (cep, EPN_Control, ctl | EPN_CTRL_ARM); if (endpoint->endpoint_address) { //printk(KERN_DEBUG"sl11_out: receive len: %d\n", len); usbd_rcv_complete_irq (endpoint, len, 0); } else { printk (KERN_DEBUG "sl11_out: cannot receive no endpoint address len: %d\n", len); } }}/* ********************************************************************************************* *//** * sl11_start - start transmit * @ep: */static void __inline__ sl11_start (unsigned int ep, struct usb_endpoint_instance *endpoint, int restart){ //printk(KERN_DEBUG"sl11_start: tx_urb: %p sent: %d\n", endpoint->tx_urb, endpoint->sent); if (endpoint->tx_urb) { struct urb *urb = endpoint->tx_urb; //printk(KERN_DEBUG"sl11_start: length: %d\n", endpoint->tx_urb->actual_length); if ((urb->actual_length - endpoint->sent) > 0) { endpoint->last = MIN (urb->actual_length - endpoint->sent, endpoint->tx_packetSize); sl11send_data (ep, urb->buffer + endpoint->sent, endpoint->last); } else { // XXX ZLP endpoint->last = 0; sl11send_data (ep, urb->buffer + endpoint->sent, 0); } }}/** * sl11_in - process tx interrupt * @ep: * @endpoint: * * Determine status of last data sent, queue new data. */static __inline__ void sl11_in (unsigned int ep, struct usb_endpoint_instance *endpoint){ int restart = 0; unsigned char status; restart = 0; //printk(KERN_DEBUG"in[%d]: seq: %d next: %d\n", ep, ep_sequence[ep], ep_next[ep]); // check packet status bits for errors status = sl11read_epn (ep, EPN_Status); if (status & (EPN_PSTS_ERROR | EPN_PSTS_TIMEOUT | EPN_PSTS_SETUP | EPN_PSTS_OVERFLOW)) { printk (KERN_DEBUG "sl11_in[%d]: ERROR status: %0x\n", ep, status); restart = 1; } else { // flip sequence ep_sequence[ep] = (~ep_sequence[ep]) & 0x1; } usbd_tx_complete_irq (endpoint, restart); sl11_start (ep, endpoint, restart);}/* ********************************************************************************************* */static void sl11_ep0_setaddress (struct usb_endpoint_instance *endpoint){ //printk(KERN_DEBUG"sl11_ep0: finished set address: %d\n", usb_address); sl11write_byte (USBAdd, usb_address); udc_addressed = usb_address; usb_address = 0; // send ack sl11write_epn (0, EPN_XferLen, endpoint->rcv_packetSize); sl11write_epn (0, EPN_Control, EPN_CTRL_ENABLE | EPN_CTRL_ARM); printk ("\n"); sl11_dump_epn (0, "\n");}static void sl11_ep0_ending (struct usb_endpoint_instance *endpoint){ //ep_sequence[0] = ~ep_sequence[0]; if (endpoint->tx_urb) { //printk(KERN_DEBUG"sl11_ep0: continue IN actual: %d sent: %d last: %d seq: %d\n", // endpoint->tx_urb->actual_length, endpoint->sent, endpoint->last, ep_sequence[0]); sl11_in (0, endpoint); } if (endpoint->tx_urb) { //printk(KERN_DEBUG"sl11_ep0: still sending\n"); return; } //printk(KERN_DEBUG"sl11_ep0: finished sending\n"); // send ack sl11write_epn (0, EPN_XferLen, endpoint->rcv_packetSize); sl11write_epn (0, EPN_Control, EPN_CTRL_ENABLE | EPN_CTRL_ARM);}static void sl11_ep0_receiving (struct usb_endpoint_instance *endpoint){ // XXX check sequence //ep_sequence[ep] = ~ep_sequence[ep]; // are we trying to read data? if (endpoint->rcv_urb) { // ok, handle incoming data sl11_out (0, endpoint); // more to send? if (endpoint->rcv_urb) { return; } // send ack sl11write_epn (0, EPN_XferLen, 0); sl11write_epn (0, EPN_Control, EPN_CTRL_ENABLE | EPN_CTRL_ARM); return; } //printk(KERN_DEBUG"sl11_ep0: received ACK\n"); sl11write_epn (0, EPN_XferLen, endpoint->rcv_packetSize); sl11write_epn (0, EPN_Control, EPN_CTRL_ENABLE | EPN_CTRL_ARM); // stall if we where not waiting for data //udc_stall_ep(0);}/** * sl11_ep0 - process an endpoint 0 interrupt * * Read and process a setup packet */static void sl11_ep0 (struct usb_endpoint_instance *endpoint){ unsigned char control; unsigned char status; unsigned char *cp; //sl11_dump_epn(0, "\n"); // delayed set address, cannot set until we have received IN if (usb_address) { sl11_ep0_setaddress (endpoint); return; } // are we sending a reply control = sl11read_epn (0, EPN_Control); if (control & EPN_CTRL_DIRECTION_IN) { sl11_ep0_ending (endpoint); return; } status = sl11read_epn (0, EPN_Status); // is the host sending data? if (!(status & EPN_PSTS_SETUP)) { sl11_ep0_receiving (endpoint); return; } // check if host changed it's mind if (endpoint->tx_urb) { endpoint->tx_urb = NULL; endpoint->last = endpoint->sent = 0; printk (KERN_DEBUG "sl11_ep0: host cancelled tx\n"); } if (endpoint->rcv_urb) { endpoint->rcv_urb = NULL; ep0_urb->actual_length = 0; printk (KERN_DEBUG "sl11_ep0: host cancelled rcv\n"); } // read setup packet //len = sl11read_epn(0, EPN_XferLen); //printk(KERN_DEBUG"sl11_ep0: reading setup\n"); sl11read_buffer (ep_address[0], (unsigned char *) &ep0_urb->device_request, 8); //sl11_dump(0, 255); cp = (unsigned char *) &ep0_urb->device_request; //printk(KERN_DEBUG"setup: %02x %02x %02x %02x %02x %02x %02x %02x\n", // cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); // process setup packet if (usbd_recv_setup (ep0_urb)) { printk (KERN_DEBUG "sl11_ep0: setup failed\n"); //sl11write_epn(0, ) //udc_stall_ep(0); return; } //sl11write_epn(0, EPN_XferLen, 0); //sl11write_epn(0, EPN_Control, EPN_CTRL_SEQUENCE | EPN_CTRL_DIRECTION_IN | EPN_CTRL_ENABLE | EPN_CTRL_ARM); //return; // XXX // check data direction if ((ep0_urb->device_request.bmRequestType & USB_REQ_DIRECTION_MASK) == USB_REQ_HOST2DEVICE) { // should we setup to receive data if (le16_to_cpu (ep0_urb->device_request.wLength)) { //printk(KERN_DEBUG"sl11_ep0: read data %d\n",le16_to_cpu(ep0_urb->device_request.wLength)); endpoint->rcv_urb = ep0_urb; endpoint->rcv_urb->actual_length = 0; sl11_out (0, endpoint); return; } //printk(KERN_DEBUG"sl11_ep0: send ack %d\n",le16_to_cpu(ep0_urb->device_request.wLength)); // should be finished, send ack sl11write_epn (0, EPN_XferLen, 0); sl11write_epn (0, EPN_Control, EPN_CTRL_SEQUENCE | EPN_CTRL_DIRECTION_IN | EPN_CTRL_ENABLE | EPN_CTRL_ARM); return; } // we should be sending data back //printk(KERN_DEBUG"sl11_ep0: send data: %d\n", le16_to_cpu(ep0_urb->device_request.wLength)); // verify that we have non-zero request length if (!le16_to_cpu (ep0_urb->device_request.wLength)) { udc_stall_ep (0); return; } // verify that we have non-zero length response if (!ep0_urb->actual_length) { udc_stall_ep (0); return; } // start sending //printk(KERN_DEBUG"sl11_ep0: start sending\n"); endpoint->tx_urb = ep0_urb; endpoint->sent = 0; endpoint->last = 0; ep_sequence[0] = 1; sl11_start (0, endpoint, 0);}/* ********************************************************************************************* *//** * sl11_int_hndlr - interrupt handler * */static void sl11_int_hndlr (int irq, void *dev_id, struct pt_regs *regs){ int i; unsigned char status; int ep; udc_interrupts++; // loop while interrupt status register is non-zero for (i = 0; (i < 10) && (status = sl11read_byte (IntStatus)); i++) { //if ((status & ~INT_SOF_RECEIVED)) { // printk(KERN_DEBUG"[%d] %02x\n", udc_interrupts, status); //} // Common interrupts - Endpoint done for (ep = 1; ep < UDC_MAX_ENDPOINTS; ep++) { struct usb_endpoint_instance *endpoint; if ((status & ep_int_mask[ep]) && (endpoint = ep_endpoints[ep])) { // transmit on other than endpoint zero if (endpoint->endpoint_address & IN) { endpoint->tx_interrupts++; sl11_in (ep, endpoint); } // receive on other than endpoint zero else { endpoint->rcv_interrupts++; sl11_out (ep, endpoint); } } } // uncommon interrupts if (status & (INT_USB_RESET | INT_EP0_DONE | INT_DMA_DONE | INT_SOF_RECEIVED)) { // Reset if (status & INT_USB_RESET) { printk (KERN_DEBUG "sl11_int_hndlr: RESET: %02x\n", status); udc_suspended = 0; usbd_device_event (udc_device, DEVICE_RESET, 0); } // endpoint zero if ((status & INT_EP0_DONE)) { struct usb_endpoint_instance *endpoint; endpoint = ep_endpoints[0]; endpoint->ep0_interrupts++; sl11_ep0 (endpoint); } // DMA done if (status & INT_DMA_DONE) { printk (KERN_DEBUG "sl11_int_hndlr: DMA: %02x\n", status); } // SOF frame if (status & INT_SOF_RECEIVED) { udc_saw_sof = 1; if (udc_suspended) { udc_suspended = 0; usbd_device_event (udc_device, DEVICE_BUS_ACTIVITY, 0); printk (KERN_DEBUG "sl11_tick: RESUMED\n"); } } } // clear all available status bits sl11write_byte (IntStatus, status); }}/* ********************************************************************************************* *//** * sl11_tick - clock timer task * @data: * * Run from global clock tick to check if we are suspended. */static void sl11_tick (void *data){ udc_ticks++; // is driver active if (data) { // if not suspended check if we should suspend if (udc_addressed && !udc_suspended) { int saw_sof = *((int *) data); if (!saw_sof) { // XXX // usbd_device_event (udc_device, DEVICE_BUS_INACTIVE, 0); udc_suspended = 1; printk (KERN_DEBUG "sl11_tick: SUSPENDED\n"); } *(int *) data = 0; } // re-queue task queue_task (&sl11_tq, &tq_timer); } else { printk (KERN_DEBUG "sl11_tick: not restarting\n"); }}/* ********************************************************************************************* *//* * Start of public functions. *//** * udc_start_in_irq - start transmit * @eendpoint: endpoint instance * * Called by bus interface driver to see if we need to start a data transmission. */void udc_start_in_irq (struct usb_endpoint_instance *endpoint){ sl11_start (endpoint->endpoint_address & 0xf, endpoint, 0);}/** * udc_stall_ep - stall endpoint * @ep: physical endpoint * * Stall the endpoint. */void udc_stall_ep (unsigned int ep){ unsigned char status; if (ep < UDC_MAX_ENDPOINTS) { status = sl11read_epn (ep, EPN_Control); sl11write_epn (ep, EPN_Control, status | EPN_CTRL_SENDSTALL); udelay (10); // XXX sl11write_epn (ep, EPN_Control, status); }}/** * udc_reset_ep - reset endpoint * @ep: physical endpoint * reset the endpoint. * * returns : 0 if ok, -1 otherwise */void udc_reset_ep (unsigned int ep){ if (ep < UDC_MAX_ENDPOINTS) { ep_sequence[ep] = 0; } printk (KERN_DEBUG "udc_reset_ep[%d]:\n", ep); if (!ep) { if (udc_addressed) { printk (KERN_DEBUG "udc_reset_ep[%d]: reseting address\n", ep); usb_address = 0; udc_addressed = 0; sl11write_byte (USBAdd, 0); // reset UDC sl11write_byte (CtrlReg, CTRL_USB_RESET); udelay (100); // XXX may not be needed sl11write_byte (CtrlReg, 0); // enable UDC sl11write_byte (CtrlReg, CTRL_USB_ENABLE); } // arm EP0 sl11write_epn (0, EPN_Control, EPN_CTRL_ARM | EPN_CTRL_ENABLE | EPN_CTRL_DIRECTION_OUT); sl11_dump_epn (ep + 0, " "); sl11_dump_epn (ep + 4, "\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -