static void udd_ctrl_setup_received(void) { irqflags_t flags; uint8_t i; if (UDD_EPCTRL_SETUP != udd_ep_control_state) { // May be a hidden DATA or ZLP phase or protocol abort udd_ctrl_endofrequest(); // Reinitializes control endpoint management udd_ctrl_init(); } // Fill setup request structure if (8 != udd_byte_count(0)) { udd_ctrl_stall_data(); udd_ack_setup_received(0); return; // Error data number doesn't correspond to SETUP packet } uint8_t *ptr = (uint8_t *) & udd_get_endpoint_fifo_access(0,8); for (i = 0; i < 8; i++) { ((uint8_t*) &udd_g_ctrlreq.req)[i] = *ptr++; } // Manage LSB/MSB to fit with CPU usage udd_g_ctrlreq.req.wValue = le16_to_cpu(udd_g_ctrlreq.req.wValue); udd_g_ctrlreq.req.wIndex = le16_to_cpu(udd_g_ctrlreq.req.wIndex); udd_g_ctrlreq.req.wLength = le16_to_cpu(udd_g_ctrlreq.req.wLength); // Decode setup request if (udc_process_setup() == false) { // Setup request unknown then stall it udd_ctrl_stall_data(); udd_ack_setup_received(0); return; } udd_ack_setup_received(0); if (Udd_setup_is_in()) { // IN data phase requested udd_ctrl_prev_payload_buf_cnt = 0; udd_ctrl_payload_buf_cnt = 0; udd_ep_control_state = UDD_EPCTRL_DATA_IN; udd_ctrl_in_sent(); // Send first data transfer } else { if (0 == udd_g_ctrlreq.req.wLength) { // No data phase requested // Send IN ZLP to ACK setup request udd_ctrl_send_zlp_in(); return; } // OUT data phase requested udd_ctrl_prev_payload_buf_cnt = 0; udd_ctrl_payload_buf_cnt = 0; udd_ep_control_state = UDD_EPCTRL_DATA_OUT; // To detect a protocol error, enable NAK interrupt on data IN phase udd_ack_nak_in(0); flags = cpu_irq_save(); udd_enable_nak_in_interrupt(0); cpu_irq_restore(flags); } }
static void udd_ctrl_setup_received(void) { uint8_t i; if (UDD_EPCTRL_SETUP != udd_ep_control_state) { // May be a hidden DATA or ZLP phase // or protocol abort udd_ctrl_endofrequest(); // Reinitializes control endpoint management udd_ctrl_init(); } // Fill setup request structure if (8 != udd_byte_count(0)) { udd_ack_setup_received(0); udd_ctrl_stall_data(); return; // Error data number doesn't correspond to SETUP packet } for (i = 0; i < 8; i++) { ((uint8_t *) & udd_g_ctrlreq.req)[i] = udd_endpoint_fifo_read(0); } // Manage LSB/MSB to fit with CPU usage udd_g_ctrlreq.req.wValue = le16_to_cpu(udd_g_ctrlreq.req.wValue); udd_g_ctrlreq.req.wIndex = le16_to_cpu(udd_g_ctrlreq.req.wIndex); udd_g_ctrlreq.req.wLength = le16_to_cpu(udd_g_ctrlreq.req.wLength); // Decode setup request if (udc_process_setup() == false) { // Setup request unknown then stall it udd_ack_setup_received(0); udd_ctrl_stall_data(); return; } if (Udd_setup_is_in()) { // Set DIR udd_set_endpoint_direction_in(0); udd_ack_setup_received(0); // IN data phase requested udd_ctrl_prev_payload_nb_trans = 0; udd_ctrl_payload_nb_trans = 0; udd_ep_control_state = UDD_EPCTRL_DATA_IN; udd_ctrl_in_sent(); // Send first data transfer } else { udd_ack_setup_received(0); if (0 == udd_g_ctrlreq.req.wLength) { // No data phase requested // Send IN ZLP to ACK setup request udd_ctrl_send_zlp_in(); return; } // OUT data phase requested udd_ctrl_prev_payload_nb_trans = 0; udd_ctrl_payload_nb_trans = 0; udd_ep_control_state = UDD_EPCTRL_DATA_OUT; } }
//! \brief Waits a SETUP packet and load data in main_setup_packet[] static void main_usb_wait_setup_packet(void) { while (!Is_udd_setup_received(0)); // SETUP packet received Assert(8 == udd_byte_count(0)); uint8_t *ptr = (uint8_t *) & udd_get_endpoint_fifo_access(0,8); for (uint8_t i = 0; i < 8; i++) { ((uint8_t*) &main_setup_packet)[i] = *ptr++; } udd_ack_setup_received(0); }
/** * \brief Sends a DATA OUT packets on control endpoint * * \param payload Data buffer to send * \param size Size of buffer */ static void main_usb_wait_out(uint8_t *payload, uint8_t size) { uint8_t nb_data; do { while (!Is_udd_out_received(0)); // Read data received during OUT phase nb_data = udd_byte_count(0); uint8_t *ptr_src = (uint8_t *) & udd_get_endpoint_fifo_access(0, 8); for (uint8_t i = 0; (i < nb_data) && size; i++) { *payload++ = *ptr_src++; size--; } // Send IN ZLP to ACK setup request udd_ack_out_received(0); } while(size); }
static void udd_ep_out_received(udd_ep_id_t ep) { udd_ep_job_t *ptr_job = &udd_ep_job[ep - 1]; uint32_t nb_data = 0, i; uint32_t nb_remain = ptr_job->buf_size - ptr_job->buf_cnt; uint32_t pkt_size = ptr_job->size; uint8_t *ptr_dst = &ptr_job->buf[ptr_job->buf_cnt]; bool b_full = false, b_short; // Read byte count nb_data = udd_byte_count(ep); b_short = (nb_data < pkt_size); // Copy data if there is if (nb_data > 0) { if (nb_data >= nb_remain) { nb_data = nb_remain; b_full = true; } // Modify job information ptr_job->buf_cnt += nb_data; // Copy FIFO (DPRAM) to buffer for (i = 0; i < nb_data; i++) { *ptr_dst++ = udd_endpoint_fifo_read(ep); } } // Clear FIFO Status udd_ep_ack_out_received(ep); // Finish job on error or short packet if ((b_full || b_short) && !Is_udd_endpoint_stall_requested(ep)) { udd_disable_endpoint_interrupt(ep); ptr_job->buf_size = ptr_job->buf_cnt; // buf_size is passed to callback as XFR count udd_ep_finish_job(ptr_job, UDD_EP_TRANSFER_OK, ep); } }
static void udd_ctrl_out_received(void) { irqflags_t flags; uint8_t i; uint16_t nb_data; if (UDD_EPCTRL_DATA_OUT != udd_ep_control_state) { if ((UDD_EPCTRL_DATA_IN == udd_ep_control_state) || (UDD_EPCTRL_HANDSHAKE_WAIT_OUT_ZLP == udd_ep_control_state)) { // End of SETUP request: // - Data IN Phase aborted, // - or last Data IN Phase hidden by ZLP OUT sending quickly, // - or ZLP OUT received normally. udd_ctrl_endofrequest(); } else { // Protocol error during SETUP request udd_ctrl_stall_data(); } // Reinitializes control endpoint management udd_ctrl_init(); return; } // Read data received during OUT phase nb_data = udd_byte_count(0); if (udd_g_ctrlreq.payload_size < (udd_ctrl_payload_nb_trans + nb_data)) { // Payload buffer too small nb_data = udd_g_ctrlreq.payload_size - udd_ctrl_payload_nb_trans; } uint8_t *ptr_src = (uint8_t *) & udd_get_endpoint_fifo_access(0, 8); uint8_t *ptr_dest = udd_g_ctrlreq.payload + udd_ctrl_payload_nb_trans; for (i = 0; i < nb_data; i++) { *ptr_dest++ = *ptr_src++; } udd_ctrl_payload_nb_trans += nb_data; if ((USB_DEVICE_EP_CTRL_SIZE != nb_data) || (udd_g_ctrlreq.req.wLength <= (udd_ctrl_prev_payload_nb_trans + udd_ctrl_payload_nb_trans))) { // End of reception because it is a short packet // Before send ZLP, call intermediate callback // in case of data receive generate a stall udd_g_ctrlreq.payload_size = udd_ctrl_payload_nb_trans; if (NULL != udd_g_ctrlreq.over_under_run) { if (!udd_g_ctrlreq.over_under_run()) { // Stall ZLP udd_ctrl_stall_data(); // Ack reception of OUT to replace NAK by a STALL udd_ack_out_received(0); return; } } // Send IN ZLP to ACK setup request udd_ack_out_received(0); udd_ctrl_send_zlp_in(); return; } if (udd_g_ctrlreq.payload_size == udd_ctrl_payload_nb_trans) { // Overrun then request a new payload buffer if (!udd_g_ctrlreq.over_under_run) { // No callback available to request a new payload buffer udd_ctrl_stall_data(); // Ack reception of OUT to replace NAK by a STALL udd_ack_out_received(0); return; } if (!udd_g_ctrlreq.over_under_run()) { // No new payload buffer delivered udd_ctrl_stall_data(); // Ack reception of OUT to replace NAK by a STALL udd_ack_out_received(0); return; } // New payload buffer available // Update number of total data received udd_ctrl_prev_payload_nb_trans += udd_ctrl_payload_nb_trans; // Reinit reception on payload buffer udd_ctrl_payload_nb_trans = 0; } // Free buffer of control endpoint to authorize next reception udd_ack_out_received(0); // To detect a protocol error, enable nak interrupt on data IN phase udd_ack_nak_in(0); flags = cpu_irq_save(); udd_enable_nak_in_interrupt(0); cpu_irq_restore(flags); }