void udd_ep_free(udd_ep_id_t ep) { UDD_EP_t *ep_ctrl; Assert(udd_ep_is_valid(ep)); udd_ep_abort(ep); ep_ctrl = udd_ep_get_ctrl(ep); udd_endpoint_disable(ep_ctrl); }
bool udd_ep_run(udd_ep_id_t ep, bool b_shortpacket, uint8_t * buf, iram_size_t buf_size, udd_callback_trans_t callback) { udd_ep_job_t *ptr_job; irqflags_t flags; UDD_EP_t *ep_ctrl; Assert(udd_ep_is_valid(ep)); // Get control & job about this endpoint ptr_job = udd_ep_get_job(ep); ep_ctrl = udd_ep_get_ctrl(ep); if (!udd_endpoint_is_enable(ep_ctrl)) { return false; // Endpoint not allocated } if (udd_endpoint_get_type(ep_ctrl)!=USB_EP_TYPE_ISOCHRONOUS_gc && udd_endpoint_is_stall(ep_ctrl)) { return false; // Endpoint is halted } flags = cpu_irq_save(); if (ptr_job->busy == true) { cpu_irq_restore(flags); return false; // Job already on going } ptr_job->busy = true; cpu_irq_restore(flags); // Update Job information ptr_job->buf = buf; ptr_job->buf_size = buf_size; ptr_job->nb_trans = 0; ptr_job->call_trans = callback; // Need to enable shortpacket to send a ZLP (buf_size==0) ptr_job->b_shortpacket = b_shortpacket || (buf_size==0); ptr_job->b_use_out_cache_buffer = false; // Initialize value to simulate a empty transfer if (USB_EP_DIR_IN == (ep & USB_EP_DIR_IN)) { udd_endpoint_in_reset_nb_sent(ep_ctrl); } else { if ((USB_EP_TYPE_ISOCHRONOUS_gc == udd_endpoint_get_type(ep_ctrl)) && (0 != (buf_size % udd_ep_get_size(ep_ctrl)))) { // The user must use a buffer size modulo endpoint size ptr_job->busy = false; return false; } udd_endpoint_out_reset_nb_received(ep_ctrl); udd_endpoint_out_set_nbbyte(ep_ctrl, 0); } // Request next transfer udd_ep_trans_complet(ep); return true; }
bool udd_ep_set_halt(udd_ep_id_t ep) { UDD_EP_t *ep_ctrl; Assert(udd_ep_is_valid(ep)); ep_ctrl = udd_ep_get_ctrl(ep); udd_endpoint_enable_stall(ep_ctrl); udd_ep_abort(ep); return true; }
bool udd_ep_clear_halt(udd_ep_id_t ep) { udd_ep_job_t *ptr_job; UDD_EP_t *ep_ctrl; Assert(udd_ep_is_valid(ep)); ep_ctrl = udd_ep_get_ctrl(ep); if (!udd_endpoint_is_stall(ep_ctrl)) { return true; // No stall on going } udd_endpoint_disable_stall(ep_ctrl); // If a job is register on clear halt action // then execute callback ptr_job = udd_ep_get_job(ep); if (ptr_job->busy == true) { ptr_job->busy = false; ptr_job->call_nohalt(); } return true; }
bool udd_ep_alloc(udd_ep_id_t ep, uint8_t bmAttributes, uint16_t MaxEndpointSize) { UDD_EP_t *ep_ctrl; Assert(udd_ep_is_valid(ep)); ep_ctrl = udd_ep_get_ctrl(ep); if (udd_endpoint_is_enable(ep_ctrl)) { return false; // Already allocated } udd_ep_init(ep, bmAttributes, MaxEndpointSize); // Do not use multipacket mode with isochronous 1023 bytes endpoint if (udd_endpoint_get_type(ep_ctrl)==USB_EP_TYPE_ISOCHRONOUS_gc && (udd_endpoint_get_size_field(ep_ctrl) ==USB_EP_BUFSIZE_1023_gc)) { return true; } udd_endpoint_set_multipacket(ep_ctrl); return true; }
bool udd_ep_wait_stall_clear(udd_ep_id_t ep, udd_callback_halt_cleared_t callback) { udd_ep_job_t *ptr_job; UDD_EP_t *ep_ctrl; Assert(udd_ep_is_valid(ep)); ep_ctrl = udd_ep_get_ctrl(ep); ptr_job = udd_ep_get_job(ep); if (udd_endpoint_is_stall(ep_ctrl)) { // Wait clear halt endpoint if (ptr_job->busy == true) { return false; // Job already on going } ptr_job->busy = true; ptr_job->call_nohalt = callback; } else { // endpoint not halted then call directly callback callback(); } return true; }
void udd_ep_abort(udd_ep_id_t ep) { UDD_EP_t *ep_ctrl; udd_ep_job_t *ptr_job; Assert(udd_ep_is_valid(ep)); ep_ctrl = udd_ep_get_ctrl(ep); ptr_job = udd_ep_get_job(ep); // Stop transfer udd_endpoint_set_NACK0(ep_ctrl); if (ptr_job->busy == false) { return; // No job on going } ptr_job->busy = false; if (NULL != ptr_job->call_trans) { ptr_job->call_trans(UDD_EP_TRANSFER_ABORT, (ep & USB_EP_DIR_IN) ? udd_endpoint_in_nb_sent(ep_ctrl) : udd_endpoint_out_nb_receiv(ep_ctrl), ep); } }