static int usbhsg_try_run_receive_packet(struct usbhsg_uep *uep, struct usbhsg_request *ureq) { struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); struct usb_request *req = &ureq->req; struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); struct device *dev = usbhsg_gpriv_to_dev(gpriv); void *buf; int maxp; int remainder, recv; int is_done = 0; /* ********* assume under spin lock ********* */ maxp = usbhs_pipe_get_maxpacket(pipe); buf = req->buf + req->actual; remainder = req->length - req->actual; recv = usbhs_fifo_read(pipe, buf, remainder); /* * recv < 0 : pipe busy * recv >= 0 : receive data * * recv <= max_packet */ if (recv < 0) return -EBUSY; /* update parameters */ req->actual += recv; if ((recv == remainder) || /* receive all data */ (recv < maxp)) /* short packet */ is_done = 1; dev_dbg(dev, " recv %d (%d/ %d/ %d/ %d)\n", usbhs_pipe_number(pipe), remainder, recv, is_done, req->zero); /* read all data ? */ if (is_done) { int disable = 0; uep->handler->irq_mask(uep, disable); usbhs_fifo_disable(pipe); usbhsg_queue_pop(uep, ureq, 0); } return 0; }
void usbhs_pipe_set_trans_count_if_bulk(struct usbhs_pipe *pipe, int len) { if (!usbhs_pipe_type_is(pipe, USB_ENDPOINT_XFER_BULK)) return; /* * clear and disable transfer counter for IN/OUT pipe */ usbhsp_pipe_tre_set(pipe, TRCLR | TRENB, TRCLR); /* * Only IN direction bulk pipe can use transfer count. * Without using this function, * received data will break if it was large data size. * see PIPEnTRN/PIPEnTRE for detail */ if (usbhs_pipe_is_dir_in(pipe)) { int maxp = usbhs_pipe_get_maxpacket(pipe); usbhsp_pipe_trn_set(pipe, 0xffff, DIV_ROUND_UP(len, maxp)); usbhsp_pipe_tre_set(pipe, TRENB, TRENB); /* enable */ } }
static int usbhsg_try_run_send_packet(struct usbhsg_uep *uep, struct usbhsg_request *ureq) { struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); struct usb_request *req = &ureq->req; struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep); struct device *dev = usbhsg_gpriv_to_dev(gpriv); void *buf; int remainder, send; int is_done = 0; int enable; int maxp; /* ********* assume under spin lock ********* */ maxp = usbhs_pipe_get_maxpacket(pipe); buf = req->buf + req->actual; remainder = req->length - req->actual; send = usbhs_fifo_write(pipe, buf, remainder); /* * send < 0 : pipe busy * send = 0 : send zero packet * send > 0 : send data * * send <= max_packet */ if (send > 0) req->actual += send; /* send all packet ? */ if (send < remainder) is_done = 0; /* there are remainder data */ else if (send < maxp) is_done = 1; /* short packet */ else is_done = !req->zero; /* send zero packet ? */ dev_dbg(dev, " send %d (%d/ %d/ %d/ %d)\n", usbhs_pipe_number(pipe), remainder, send, is_done, req->zero); /* * enable interrupt and send again in irq handler * if it still have remainder data which should be sent. */ enable = !is_done; uep->handler->irq_mask(uep, enable); /* * usbhs_fifo_enable execute * - after callback_update, * - before queue_pop / stage_end */ usbhs_fifo_enable(pipe); /* * all data were sent ? */ if (is_done) { /* it care below call in "function mode" */ if (usbhsg_is_dcp(uep)) usbhs_dcp_control_transfer_done(pipe); usbhsg_queue_pop(uep, ureq, 0); } return 0; }