//! This function manages the SET INTERFACE request. //! void usb_set_interface(void) { U8 u8_i; // wValue = Alternate Setting // wIndex = Interface U16 wValue = usb_format_usb_to_mcu_data(16, Usb_read_endpoint_data(EP_CONTROL, 16)); U16 wIndex = usb_format_usb_to_mcu_data(16, Usb_read_endpoint_data(EP_CONTROL, 16)); Usb_ack_setup_received_free(); // Get descriptor #if (USB_HIGH_SPEED_SUPPORT==true) if( Is_usb_full_speed_mode() ) { data_to_transfer = Usb_get_conf_desc_fs_length(); //!< sizeof(usb_conf_desc_fs); pbuffer = Usb_get_conf_desc_fs_pointer(); }else{ data_to_transfer = Usb_get_conf_desc_hs_length(); //!< sizeof(usb_conf_desc_hs); pbuffer = Usb_get_conf_desc_hs_pointer(); } #else data_to_transfer = Usb_get_conf_desc_length(); //!< sizeof(usb_conf_desc); pbuffer = Usb_get_conf_desc_pointer(); #endif //** Scan descriptor //* Find configuration selected if( usb_configuration_nb == 0 ) { // No configuration selected then no interface enable Usb_enable_stall_handshake(EP_CONTROL); Usb_ack_setup_received_free(); return; } u8_i = usb_configuration_nb; while( u8_i != 0 ) { if( CONFIGURATION_DESCRIPTOR != ((S_usb_configuration_descriptor*)pbuffer)->bDescriptorType ) { data_to_transfer -= ((S_usb_configuration_descriptor*)pbuffer)->bLength; pbuffer = (U8*)pbuffer + ((S_usb_configuration_descriptor*)pbuffer)->bLength; continue; } u8_i--; if( u8_i != 0 ) { data_to_transfer -= ((S_usb_configuration_descriptor*)pbuffer)->wTotalLength; pbuffer = (U8*)pbuffer + ((S_usb_configuration_descriptor*)pbuffer)->wTotalLength; } } // Find interface selected if( wIndex >= ((S_usb_configuration_descriptor*)pbuffer)->bNumInterfaces ) { // Interface number unknown Usb_enable_stall_handshake(EP_CONTROL); Usb_ack_setup_received_free(); return; } while( 1 ) { if( data_to_transfer <= ((S_usb_interface_descriptor*)pbuffer)->bLength ) { // Interface unknown Usb_enable_stall_handshake(EP_CONTROL); Usb_ack_setup_received_free(); return; } data_to_transfer -= ((S_usb_interface_descriptor*)pbuffer)->bLength; pbuffer = (U8*)pbuffer + ((S_usb_interface_descriptor*)pbuffer)->bLength; if( INTERFACE_DESCRIPTOR != ((S_usb_interface_descriptor*)pbuffer)->bDescriptorType ) continue; if( wIndex != ((S_usb_interface_descriptor*)pbuffer)->bInterfaceNumber ) continue; if( wValue != ((S_usb_interface_descriptor*)pbuffer)->bAlternateSetting ) continue; usb_interface_status[wIndex] = wValue; break; } //* Find endpoints of interface and reset it while( 1 ) { if( data_to_transfer <= ((S_usb_endpoint_descriptor*)pbuffer)->bLength ) break; // End of interface data_to_transfer -= ((S_usb_endpoint_descriptor*)pbuffer)->bLength; pbuffer = (U8*)pbuffer + ((S_usb_endpoint_descriptor*)pbuffer)->bLength; if( INTERFACE_DESCRIPTOR == ((S_usb_endpoint_descriptor*)pbuffer)->bDescriptorType ) break; // End of interface if( ENDPOINT_DESCRIPTOR == ((S_usb_endpoint_descriptor*)pbuffer)->bDescriptorType ) { // Reset endpoint u8_i = ((S_usb_endpoint_descriptor*)pbuffer)->bEndpointAddress & (~MSK_EP_DIR); Usb_disable_stall_handshake(u8_i); Usb_reset_endpoint(u8_i); Usb_reset_data_toggle(u8_i); } } // send a ZLP for STATUS phase Usb_ack_control_in_ready_send(); while (!Is_usb_control_in_ready()); }
//! This function manages the GET DESCRIPTOR request. The device descriptor, //! the configuration descriptor and the device qualifier are supported. All //! other descriptors must be supported by the usb_user_get_descriptor //! function. //! Only 1 configuration is supported. //! void usb_get_descriptor(void) { bool zlp; U16 wLength; U8 descriptor_type; U8 string_type; Union32 temp; #if (USB_HIGH_SPEED_SUPPORT==true) bool b_first_data = true; #endif zlp = false; /* no zero length packet */ string_type = Usb_read_endpoint_data(EP_CONTROL, 8); /* read LSB of wValue */ descriptor_type = Usb_read_endpoint_data(EP_CONTROL, 8); /* read MSB of wValue */ switch (descriptor_type) { case DEVICE_DESCRIPTOR: data_to_transfer = Usb_get_dev_desc_length(); //!< sizeof(usb_dev_desc); pbuffer = Usb_get_dev_desc_pointer(); break; #if (USB_HIGH_SPEED_SUPPORT==false) case CONFIGURATION_DESCRIPTOR: data_to_transfer = Usb_get_conf_desc_length(); //!< sizeof(usb_conf_desc); pbuffer = Usb_get_conf_desc_pointer(); break; #else case CONFIGURATION_DESCRIPTOR: if( Is_usb_full_speed_mode() ) { data_to_transfer = Usb_get_conf_desc_fs_length(); //!< sizeof(usb_conf_desc_fs); pbuffer = Usb_get_conf_desc_fs_pointer(); }else{ data_to_transfer = Usb_get_conf_desc_hs_length(); //!< sizeof(usb_conf_desc_hs); pbuffer = Usb_get_conf_desc_hs_pointer(); } break; case OTHER_SPEED_CONFIGURATION_DESCRIPTOR: if( !Is_usb_full_speed_mode() ) { data_to_transfer = Usb_get_conf_desc_fs_length(); //!< sizeof(usb_conf_desc_fs); pbuffer = Usb_get_conf_desc_fs_pointer(); }else{ data_to_transfer = Usb_get_conf_desc_hs_length(); //!< sizeof(usb_conf_desc_hs); pbuffer = Usb_get_conf_desc_hs_pointer(); } break; case DEVICE_QUALIFIER_DESCRIPTOR: data_to_transfer = Usb_get_qualifier_desc_length(); //!< sizeof(usb_qualifier_desc); pbuffer = Usb_get_qualifier_desc_pointer(); break; #endif default: if (!usb_user_get_descriptor(descriptor_type, string_type)) { Usb_enable_stall_handshake(EP_CONTROL); Usb_ack_setup_received_free(); return; } break; } temp.u32 = Usb_read_endpoint_data(EP_CONTROL, 32); //!< read wIndex and wLength with a 32-bit access //!< since this access is aligned with a 32-bit //!< boundary from the beginning of the endpoint wLength = usb_format_usb_to_mcu_data(16, temp.u16[1]); //!< ignore wIndex, keep and format wLength Usb_ack_setup_received_free(); //!< clear the setup received flag if (wLength > data_to_transfer) { zlp = !(data_to_transfer % EP_CONTROL_LENGTH); //!< zero length packet condition } else { // No need to test ZLP sending since we send the exact number of bytes as // expected by the host. data_to_transfer = wLength; //!< send only requested number of data bytes } Usb_ack_nak_out(EP_CONTROL); while (data_to_transfer && !Is_usb_nak_out(EP_CONTROL)) { while (!Is_usb_control_in_ready() && !Is_usb_nak_out(EP_CONTROL)); if (Is_usb_nak_out(EP_CONTROL)) break; // don't clear the flag now, it will be cleared after Usb_reset_endpoint_fifo_access(EP_CONTROL); #if (USB_HIGH_SPEED_SUPPORT==true) // To support other descriptors like OTHER_SPEED_CONFIGURATION_DESCRIPTOR if( b_first_data ) { b_first_data = false; if( 0!= data_to_transfer ) { usb_write_ep_txpacket(EP_CONTROL, pbuffer, 1, &pbuffer); data_to_transfer--; } if( 0!= data_to_transfer ) { usb_write_ep_txpacket(EP_CONTROL, &descriptor_type, 1, NULL); pbuffer = ((const U8*)pbuffer)+1; data_to_transfer--; } } #endif if( 0!= data_to_transfer ) { data_to_transfer = usb_write_ep_txpacket(EP_CONTROL, pbuffer, data_to_transfer, &pbuffer); } if (Is_usb_nak_out(EP_CONTROL)) break; Usb_ack_control_in_ready_send(); //!< Send data until necessary } if (zlp && !Is_usb_nak_out(EP_CONTROL)) { while (!Is_usb_control_in_ready()); Usb_ack_control_in_ready_send(); } while (!Is_usb_nak_out(EP_CONTROL)); Usb_ack_nak_out(EP_CONTROL); while (!Is_usb_control_out_received()); Usb_ack_control_out_received_free(); }
//! usb_get_descriptor. //! //! This function manages the GET DESCRIPTOR request. The device descriptor, //! the configuration descriptor and the device qualifier are supported. All //! other descriptors must be supported by the usb_user_get_descriptor //! function. //! Only 1 configuration is supported. //! //! @warning Code:xx bytes (function code length) //! //! @param none //! //! @return none //! void usb_get_descriptor(void) { U16 wLength ; U8 descriptor_type ; U8 string_type ; U8 dummy; U8 nb_byte; zlp = FALSE; /* no zero length packet */ string_type = Usb_read_byte(); /* read LSB of wValue */ descriptor_type = Usb_read_byte(); /* read MSB of wValue */ switch (descriptor_type) { case DEVICE_DESCRIPTOR: data_to_transfer = Usb_get_dev_desc_length(); //!< sizeof (usb_user_device_descriptor); pbuffer = Usb_get_dev_desc_pointer(); break; case CONFIGURATION_DESCRIPTOR: data_to_transfer = Usb_get_conf_desc_length(); //!< sizeof (usb_user_configuration_descriptor); pbuffer = Usb_get_conf_desc_pointer(); break; default: if( usb_user_get_descriptor(descriptor_type, string_type)==FALSE ) { Usb_enable_stall_handshake(); Usb_ack_receive_setup(); return; } break; } dummy = Usb_read_byte(); //!< don't care of wIndex field dummy = Usb_read_byte(); LSB(wLength) = Usb_read_byte(); //!< read wLength MSB(wLength) = Usb_read_byte(); Usb_ack_receive_setup() ; //!< clear the receive setup flag if (wLength > data_to_transfer) { if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; } else { zlp = FALSE; } //!< no need of zero length packet } else { data_to_transfer = (U8)wLength; //!< send only requested number of data } while((data_to_transfer != 0) && (!Is_usb_receive_out())) { while(!Is_usb_read_control_enabled()); nb_byte=0; while(data_to_transfer != 0) //!< Send data until necessary { if(nb_byte++==EP_CONTROL_LENGTH) //!< Check endpoint 0 size { break; } #ifndef AVRGCC Usb_write_byte(*pbuffer++); #else // AVRGCC does not support point to PGM space #warning with avrgcc assumes devices descriptors are stored in the lower 64Kbytes of on-chip flash memory Usb_write_byte(pgm_read_byte_near((unsigned int)pbuffer++)); #endif data_to_transfer --; } Usb_send_control_in(); } if(Is_usb_receive_out()) { Usb_ack_receive_out(); return; } //!< abort from Host if(zlp == TRUE) { while(!Is_usb_read_control_enabled()); Usb_send_control_in(); } while(!Is_usb_receive_out()); Usb_ack_receive_out(); }
//! usb_get_descriptor. //! //! This function manages the GET DESCRIPTOR request. The device descriptor, //! the configuration descriptor and the device qualifier are supported. All //! other descriptors must be supported by the usb_user_get_descriptor //! function. //! Only 1 configuration is supported. //! //! @warning Code:xx bytes (function code length) //! void usb_get_descriptor(void) { U8 LSBwLength, MSBwLength; U8 descriptor_type ; U8 string_type ; U8 dummy; U8 byteswereread; zlp = FALSE; /* no zero length packet */ string_type = Usb_read_byte(); /* read LSB of wValue */ descriptor_type = Usb_read_byte(); /* read MSB of wValue */ byteswereread = 0; switch (descriptor_type) { case DEVICE_DESCRIPTOR: data_to_transfer = Usb_get_dev_desc_length(); //!< sizeof (usb_user_device_descriptor); pbuffer = Usb_get_dev_desc_pointer(); break; case CONFIGURATION_DESCRIPTOR: data_to_transfer = Usb_get_conf_desc_length(string_type); //!< sizeof (usb_user_configuration_descriptor); pbuffer = Usb_get_conf_desc_pointer(string_type); break; #if 1 case STRING_DESCRIPTOR: if(string_type!=LANG_ID) { usb_get_string_descriptor(string_type); return; } #endif default: dummy = Usb_read_byte(); dummy = Usb_read_byte(); LSBwLength = Usb_read_byte(); MSBwLength = Usb_read_byte(); byteswereread=1; if( usb_user_get_descriptor(descriptor_type, string_type)==FALSE ) { Usb_enable_stall_handshake(); //TODO:is this necessary, Win7 flaky without? Usb_ack_receive_setup(); return; } break; } if (byteswereread==0) { dummy = Usb_read_byte(); //!< don't care of wIndex field dummy = Usb_read_byte(); LSBwLength = Usb_read_byte(); //!< read wLength MSBwLength = Usb_read_byte(); } Usb_ack_receive_setup() ; //!< clear the receive setup flag if ((LSBwLength > data_to_transfer) || (MSBwLength)) { if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; } else { zlp = FALSE; } //!< no need of zero length packet LSBwLength = data_to_transfer; MSBwLength = 0x00; } else { data_to_transfer = LSBwLength; //!< send only requested number of data } while((data_to_transfer != 0) && (!Is_usb_receive_out())) { U8 nb_byte = 0; if(usb_endpoint_wait_for_read_control_enabled()!=0) { Usb_enable_stall_handshake(); break; } //! Send data until necessary while(data_to_transfer != 0) { // if(Is_usb_write_enabled()) //!< Check endpoint 0 size if(nb_byte++==EP_CONTROL_LENGTH) //!< Check endpoint 0 size break; Usb_write_byte(pgm_read_byte_near((unsigned int)pbuffer++)); data_to_transfer --; } Usb_send_control_in(); } if(Is_usb_receive_out()) { //! abort from Host Usb_ack_receive_out(); return; } if(zlp == TRUE) { if(usb_endpoint_wait_for_read_control_enabled()!=0) { Usb_enable_stall_handshake(); return; } Usb_send_control_in(); } usb_endpoint_wait_for_receive_out(); Usb_ack_receive_out(); }
//! This function manages the GET DESCRIPTOR request. The device descriptor, //! the configuration descriptor and the device qualifier are supported. All //! other descriptors must be supported by the usb_user_get_descriptor //! function. //! Only 1 configuration is supported. //! void usb_get_descriptor(void) { Bool zlp; U16 wLength; U8 descriptor_type; U8 string_type; Union32 temp; zlp = FALSE; /* no zero length packet */ string_type = Usb_read_endpoint_data(EP_CONTROL, 8); /* read LSB of wValue */ descriptor_type = Usb_read_endpoint_data(EP_CONTROL, 8); /* read MSB of wValue */ switch (descriptor_type) { case DEVICE_DESCRIPTOR: data_to_transfer = Usb_get_dev_desc_length(); //!< sizeof(usb_dev_desc); pbuffer = Usb_get_dev_desc_pointer(); break; case CONFIGURATION_DESCRIPTOR: data_to_transfer = Usb_get_conf_desc_length(); //!< sizeof(usb_conf_desc); pbuffer = Usb_get_conf_desc_pointer(); break; default: if (!usb_user_get_descriptor(descriptor_type, string_type)) { Usb_enable_stall_handshake(EP_CONTROL); Usb_ack_setup_received_free(); return; } break; } temp.u32 = Usb_read_endpoint_data(EP_CONTROL, 32); //!< read wIndex and wLength with a 32-bit access //!< since this access is aligned with a 32-bit //!< boundary from the beginning of the endpoint wLength = usb_format_usb_to_mcu_data(16, temp.u16[1]); //!< ignore wIndex, keep and format wLength Usb_ack_setup_received_free(); //!< clear the setup received flag if (wLength > data_to_transfer) { zlp = !(data_to_transfer % EP_CONTROL_LENGTH); //!< zero length packet condition } else { // No need to test ZLP sending since we send the exact number of bytes as // expected by the host. data_to_transfer = (U8)wLength; //!< send only requested number of data bytes } Usb_ack_nak_out(EP_CONTROL); while (data_to_transfer && !Is_usb_nak_out(EP_CONTROL)) { while (!Is_usb_control_in_ready() && !Is_usb_nak_out(EP_CONTROL)); if (Is_usb_nak_out(EP_CONTROL)) break; // don't clear the flag now, it will be cleared after Usb_reset_endpoint_fifo_access(EP_CONTROL); data_to_transfer = usb_write_ep_txpacket(EP_CONTROL, pbuffer, data_to_transfer, &pbuffer); if (Is_usb_nak_out(EP_CONTROL)) break; else Usb_ack_control_in_ready_send(); //!< Send data until necessary } if (zlp && !Is_usb_nak_out(EP_CONTROL)) { while (!Is_usb_control_in_ready()); Usb_ack_control_in_ready_send(); } while (!Is_usb_nak_out(EP_CONTROL)); Usb_ack_nak_out(EP_CONTROL); while (!Is_usb_control_out_received()); Usb_ack_control_out_received_free(); }
//! This function manages the GET DESCRIPTOR request. The device descriptor, //! the configuration descriptor and the device qualifier are supported. All //! other descriptors must be supported by the usb_user_get_descriptor //! function. //! Only 1 configuration is supported. //! Bool usb_get_descriptor(void) { Bool zlp; U16 wLength; U8 descriptor_type ; U8 string_type; U8 dummy; U8 nb_byte; U8 byte_to_send; #if (USE_DEVICE_SN_UNIQUE==ENABLE) U16 sn_index=0; U8 initial_data_to_transfer; #endif zlp = FALSE; /* no zero length packet */ string_type = Usb_read_byte(); /* read LSB of wValue */ descriptor_type = Usb_read_byte(); /* read MSB of wValue */ switch (descriptor_type) { case DESCRIPTOR_DEVICE: data_to_transfer = Usb_get_dev_desc_length(); //!< sizeof (usb_user_device_descriptor); pbuffer = Usb_get_dev_desc_pointer(); break; case DESCRIPTOR_CONFIGURATION: data_to_transfer = Usb_get_conf_desc_length(); //!< sizeof (usb_user_configuration_descriptor); pbuffer = Usb_get_conf_desc_pointer(); break; default: if( !usb_user_get_descriptor(descriptor_type, string_type)) return FALSE; // Unknow descriptor then stall request break; } dummy = Usb_read_byte(); //!< don't care of wIndex field dummy = Usb_read_byte(); LSB(wLength) = Usb_read_byte(); //!< read wLength MSB(wLength) = Usb_read_byte(); Usb_ack_receive_setup() ; //!< clear the receive setup flag if (wLength > data_to_transfer) { if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; } else { zlp = FALSE; } //!< no need of zero length packet } else { data_to_transfer = (U8)wLength; //!< send only requested number of data } Usb_ack_nak_out(); byte_to_send=0; #if (USE_DEVICE_SN_UNIQUE==ENABLE) initial_data_to_transfer = data_to_transfer; #endif while((data_to_transfer != 0) && (!Is_usb_nak_out_sent())) { while(!Is_usb_read_control_enabled()) { if (Is_usb_nak_out_sent()) break; // don't clear the flag now, it will be cleared after } nb_byte=0; while(data_to_transfer != 0) //!< Send data until necessary { if(nb_byte++==EP_CONTROL_LENGTH) //!< Check endpoint 0 size break; #if (USE_DEVICE_SN_UNIQUE==ENABLE) if(f_get_serial_string && (data_to_transfer < (initial_data_to_transfer-1))) //if we are sending the signature characters (third byte and more...) { //(The first two bytes are the length and the descriptor) switch (byte_to_send) { case 0: Usb_write_byte(bin_to_ascii((Flash_read_sn(sn_index)>>4) & 0x0F)); //sends the fist part (MSB) of the signature hex number, converted in ascii break; case 1: Usb_write_byte(0); //then, sends a null character (Usb_unicode) break; case 2: Usb_write_byte(bin_to_ascii(Flash_read_sn(sn_index) & 0x0F)); //sends the second part (LSB) of the signature hex number, converted in ascii break; case 3: Usb_write_byte(0); //then, sends a null character (Usb_unicode) sn_index++; //increments the signature address pointer. break; } byte_to_send = (byte_to_send+1)%4; } else { Usb_write_PGM_byte(pbuffer++); //Write a flash byte to USB } #else Usb_write_PGM_byte(pbuffer++); #endif data_to_transfer --; //decrements the number of bytes to transmit. } if (Is_usb_nak_out_sent()) break; else Usb_send_control_in(); }