static void udd_ctrl_setup_received(void) { irqflags_t flags; 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_udesc_get_buf0_ctn(0)) { udd_ctrl_stall_data(); udd_ack_setup_received(0); return; // Error data number doesn't correspond to SETUP packet } memcpy((uint8_t *) & udd_g_ctrlreq.req, udd_ctrl_buffer, 8); // 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_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 { 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; // 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; } }
static void udd_ctrl_setup_received(void) { if (UDD_EPCTRL_SETUP != udd_ep_control_state) { if ((UDD_EPCTRL_HANDSHAKE_WAIT_IN_ZLP == udd_ep_control_state) || (UDD_EPCTRL_HANDSHAKE_WAIT_OUT_ZLP == udd_ep_control_state)) { // Accept that ZLP event can be hidden by setup packet event // in case of setup packet sending quickly after a ZLP udd_ctrl_endofrequest(); } // Reinitializes control endpoint management udd_ctrl_init(); } // Fill setup request structure if (8 != udd_control_out_get_bytecnt()) return; // Error data number don't correspond to SETUP packet memcpy((uint8_t *) & udd_g_ctrlreq.req, udd_ctrl_buffer, 8); // To detect a protocol error on setup, enable nak interrupt on IN/OUT of control endpoint udd_enable_overflow_interrupt(); udd_enable_underflow_interrupt(); // Decode setup request if (udc_process_setup() == false) { // Setup request unknown then stall it udd_ctrl_stall_data(); return; } if (Udd_setup_is_in()) { 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 { 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; // Clear packet to receive first packet udd_control_out_clear_NACK0(); udd_control_out_ack_tc(); } }
static void udd_ctrl_underflow(void) { if (Is_udd_out_received(0)) return; // underflow ignored if OUT data is received if (UDD_EPCTRL_DATA_OUT == udd_ep_control_state) { // Host want to stop OUT transaction // then stop to wait OUT data phase and wait IN ZLP handshake udd_ctrl_send_zlp_in(); } else if (UDD_EPCTRL_HANDSHAKE_WAIT_OUT_ZLP == udd_ep_control_state) { // A OUT handshake is waiting by device, // but host want extra IN data then stall extra IN data udd_enable_stall_handshake(0); } }
static void udd_ctrl_underflow(void) { if (udd_is_tc_event() || udd_ctrl_interrupt_tc_setup()) { return; // underflow ignored if a transfer complete has been no processed } if (UDD_EPCTRL_DATA_OUT == udd_ep_control_state) { // Host want to stop OUT transaction // then stop to wait OUT data phase and wait IN ZLP handshake udd_ctrl_send_zlp_in(); } else if (UDD_EPCTRL_HANDSHAKE_WAIT_OUT_ZLP == udd_ep_control_state) { // A OUT handshake is waiting by device, // but host want extra IN data then stall extra IN data and following status stage udd_control_in_enable_stall(); udd_control_out_enable_stall(); } }
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); }
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 } uint32_t *ptr = (uint32_t *) & udd_get_endpoint_fifo_access(0, 32); for (i = 0; i < 8 / 4; i++) { ((uint32_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 unknow then stall it udd_ctrl_stall_data(); udd_ack_setup_received(0); return; } udd_ack_setup_received(0); if (Udd_setup_is_in()) { // Compute if an IN ZLP must be send after IN data udd_ctrl_payload_need_in_zlp = ((udd_g_ctrlreq.payload_size % USB_DEVICE_EP_CTRL_SIZE) == 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 { 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; // 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_out_received(void) { uint16_t nb_data; if (UDD_EPCTRL_HANDSHAKE_WAIT_OUT_ZLP == udd_ep_control_state) { // Valid end of setup request udd_ctrl_endofrequest(); // Reinitializes control endpoint management udd_ctrl_init(); return; } Assert(udd_ep_control_state == UDD_EPCTRL_DATA_OUT); // Read data received during OUT phase nb_data = udd_control_out_get_bytecnt(); if (udd_g_ctrlreq.payload_size < (udd_ctrl_payload_nb_trans + nb_data)) { // Payload buffer too small, ignore data remaining nb_data = udd_g_ctrlreq.payload_size - udd_ctrl_payload_nb_trans; } memcpy((uint8_t *) (udd_g_ctrlreq.payload + udd_ctrl_payload_nb_trans), udd_ctrl_buffer, nb_data); 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 // or all data are transfered // 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(); return; } } // Send IN ZLP to ACK setup request 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(); return; } if (!udd_g_ctrlreq.over_under_run()) { // No new payload buffer delivered udd_ctrl_stall_data(); 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 OUT control endpoint to authorize next reception udd_control_out_clear_NACK0(); }